2 Commits

Author SHA1 Message Date
JR-Morgan a8a32faa4c Merge branch 'main' of https://github.com/specklesystems/speckle-unreal 2022-05-25 19:18:03 +01:00
JR-Morgan 0f09aaf285 Sending Experimentation 2022-05-25 19:06:07 +01:00
25 changed files with 625 additions and 124 deletions
Binary file not shown.
@@ -1,22 +1,33 @@
#include "API/Operations/SendOperation.h"
#include "Mixpanel.h"
#include "Transports/Transport.h"
// USendOperation* USendOperation::SendOperation(UObject* WorldContextObject, UBase* Base, TScriptArray<TScriptInterface<ITransport>> Transports)
// {
// USendOperation* Node = NewObject<USendOperation>();
// Node->Base = Base;
// Node->Transports = Transports;
//
// Node->RegisterWithGameInstance(WorldContextObject);
// return Node;
// }
//
// void USendOperation::Activate()
// {
// check(Transports.Num() > 0);
//
// //TODO implement
// unimplemented();
//
// }
USendOperation* USendOperation::SendOperation(UObject* WorldContextObject, UBase* Base, TArray<TScriptInterface<ITransport>> Transports)
{
USendOperation* Node = NewObject<USendOperation>();
Node->Base = Base;
Node->Transports = Transports;
Node->RegisterWithGameInstance(WorldContextObject);
return Node;
}
void USendOperation::Activate()
{
FAnalytics::TrackEvent("unknown", "unknown", "NodeRun", TMap<FString, FString> { {"name", StaticClass()->GetName() }});
Send();
}
void USendOperation::Send()
{
check(Transports.Num() > 0);
for (const auto t : Transports)
{
//TODO
//ITransport::
}
}
@@ -64,3 +64,18 @@ UBase* USpeckleSerializer::DeserializeBaseById(const FString& ObjectId,
auto Obj = ReadTransport->GetSpeckleObject(ObjectId);
return DeserializeBase(Obj, ReadTransport);
}
UBase* TrySetProperties(const TSubclassOf<UBase> BaseType, const FString& SerialisedObject, TScriptInterface<ITransport> Transport)
{
UBase* Base = NewObject<UBase>(GetTransientPackage(), BaseType);
TSharedRef<FJsonStringReader> Reader = FJsonStringReader::Create(SerialisedObject);
for(auto foo : Reader.)
{
}
return Base;
}
@@ -34,11 +34,10 @@ void UAggregateConverter::PostEditChangeProperty(FPropertyChangedEvent& Property
}
#endif
UBase* UAggregateConverter::ConvertToSpeckle_Implementation(const UObject* Object)
void UAggregateConverter::ConvertToSpeckle_Implementation(const UObject* Object, UBase* SpeckleObject)
{
//TODO implement ToSpeckle
unimplemented();
return nullptr;
}
@@ -80,6 +79,7 @@ bool UAggregateConverter::CanConvertToNative_Implementation(TSubclassOf<UBase> B
return GetConverter(BaseType).GetInterface() != nullptr;
}
TScriptInterface<ISpeckleConverter> UAggregateConverter::GetConverter(const TSubclassOf<UBase> BaseType)
{
// Check if this SpeckleType has a known converter.
@@ -366,7 +366,7 @@ void UStaticMeshConverter::GenerateMeshParams(UStaticMesh::FBuildMeshDescription
}
UBase* UStaticMeshConverter::ConvertToSpeckle_Implementation(const UObject* Object)
void UStaticMeshConverter::ConvertToSpeckle_Implementation(const UObject* Object, UBase* SpeckleObject)
{
const UStaticMeshComponent* M = Cast<UStaticMeshComponent>(Object);
@@ -378,15 +378,68 @@ UBase* UStaticMeshConverter::ConvertToSpeckle_Implementation(const UObject* Obje
M = A->FindComponentByClass<UStaticMeshComponent>();
}
}
if(M == nullptr) return nullptr;
if(M == nullptr) return;
//SpeckleObject->DynamicProperties.Add(TEXT("@displayValue"), MeshToSpeckle(M));
return MeshToSpeckle(M);
}
UBase* UStaticMeshConverter::MeshToSpeckle(const UStaticMeshComponent* Object)
TArray<UMesh*> UStaticMeshConverter::MeshToSpeckle(const UStaticMeshComponent* MeshComponent)
{
return nullptr; //TODO implement ToSpeckle function
UStaticMeshDescription* StaticMeshDescription = NewObject<UStaticMeshDescription>(GetTransientPackage(), NAME_None, RF_Transient);
const FMeshDescription* MeshDescription = MeshComponent->GetStaticMesh()->GetMeshDescription(0);;
StaticMeshDescription->SetMeshDescription(*MeshDescription);
StaticMeshDescription->RegisterAttributes();
const FVertexArray& nVertices = StaticMeshDescription->Vertices();
TArray<FVector> sVertices;
sVertices.Reserve(nVertices.Num()); // * 3));
TMap<FVertexID, int32> VertexIdToIndex;
VertexIdToIndex.Reserve(nVertices.Num() * 3);
int32 i = 0;
for (const FVertexID& VertexId : nVertices.GetElementIDs())
{
const FVector Vert = StaticMeshDescription->GetVertexPosition(VertexId);
sVertices.Add(Vert);
VertexIdToIndex.Add(VertexId, i);
i++;
}
FTriangleArray& nTriangles = StaticMeshDescription->Triangles();
TArray<int32> sFaces;
sFaces.Reserve(nTriangles.Num());
for (const FTriangleID& TriangleId : nTriangles.GetElementIDs())
{
TArray<FVertexID> Tri;
StaticMeshDescription->GetTriangleVertices(TriangleId, Tri);
sFaces.Add(3);
sFaces.Add(VertexIdToIndex[Tri[0]]);
sFaces.Add(VertexIdToIndex[Tri[1]]);
sFaces.Add(VertexIdToIndex[Tri[2]]);
}
//TODO colors
//TODO tex-coords
//TODO split mesh by material
UMesh* Mesh = NewObject<UMesh>(GetTransientPackage(), NAME_None, RF_Transient);
Mesh->Vertices = sVertices;
Mesh->Faces = sFaces;
//Mesh->Colors = sColors;
//Mesh->TextureCoordinates = sTexCoords;
Mesh->Units = "cm";
return TArray<UMesh*>{Mesh};
}
@@ -176,4 +176,4 @@ void USpeckleConverterComponent::FinishConversion()
SpeckleConverter->FinishConversion_Internal();
}
#undef LOCTEXT_NAMESPACE
#undef LOCTEXT_NAMESPACE
@@ -0,0 +1,60 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "Conversion/SpeckleConverter.h"
#include "Conversion/SpeckleConverterComponent.h"
#include "Conversion/Converters/AggregateConverter.h"
#define LOCTEXT_NAMESPACE "FSpeckleUnrealModule"
UBase* USpeckleConverterComponent::RecursivelyConvertToSpeckle(const TArray<AActor*>& RootActors, FActorPredicate& Predicate)
{
TArray<UBase*> ConvertedRootActors;
for(const AActor* RootActor : RootActors)
{
RecurseTreeToSpeckle(RootActor, Predicate, ConvertedRootActors);
}
UBase* Wrapper = NewObject<UBase>(GetTransientPackage(), NAME_None, RF_Transient);
//Converted->DynamicProperties["objects"] = ConvertedRootActors; //TODO set children
return Wrapper;
}
void USpeckleConverterComponent::RecurseTreeToSpeckle(const AActor* RootActor, FActorPredicate& Predicate, TArray<UBase*>& OutConverted)
{
// Convert children first
TArray<UBase*> ConvertedChildren;
ConvertedChildren.Reserve(RootActor->Children.Num());
for (const AActor* Child : RootActor->Children)
{
RecurseTreeToSpeckle(Child, Predicate, ConvertedChildren);
}
bool ShouldConvert;
Predicate.Execute(RootActor, ShouldConvert);
if(ISpeckleConverter::Execute_CanConvertToSpeckle(SpeckleConverter, RootActor) && ShouldConvert)
{
// Convert and output
UBase* Converted = NewObject<UBase>(GetTransientPackage(), NAME_None, RF_Transient);
//Converted->DynamicProperties["name"] = RootActor->GetName(),
//["transform"] = TransformToSpeckle(go.Transform), //TODO set common props
//Converted->DynamicProperties["tag"] = go.tag,
//Converted->DynamicProperties["layer"] = go.layer,
//Converted->DynamicProperties["isStatic"] = go.isStatic,
ISpeckleConverter::Execute_ConvertToSpeckle(SpeckleConverter, RootActor, Converted);
//Converted->DynamicProperties["objects"] = ConvertedChildren; //TODO set children
OutConverted.Add(Converted);
}
else
{
// Skip this object, and output any children
OutConverted.Append(ConvertedChildren);
}
}
#undef LOCTEXT_NAMESPACE
@@ -0,0 +1,80 @@
// Copyright AEC Systems Ltd
#include "Objects/DynamicBase.h"
#include "Misc/Variant.h"
template <typename T>
bool UDynamicBase::TryGetDynamicProperty(const FString& Key, T& OutValue) const
{
const auto Wrapper = DynamicProperties.FindRef(Key);
if(Wrapper.IsValid()) return false;
if(Wrapper->GetType() != TVariantTraits<T>::GetType()) return false;
OutValue = Wrapper->GetValue<T>();
return true;
}
template <typename T>
void UDynamicBase::SetDynamicProperty(const FString& Key, T Value)
{
DynamicProperties.Add(Key, MakeShareable(new FVariant(Value)));
}
int32 UDynamicBase::RemoveDynamicProperty(const FString& Key)
{
return DynamicProperties.Remove(Key);
}
//-------------------
bool UDynamicBase::TryGetDynamicStringProperty(const FString& Key, FString& OutValue) const
{
return TryGetDynamicProperty(Key, OutValue);
}
bool UDynamicBase::TryGetDynamicIntProperty(const FString& Key, int32& OutValue) const
{
return TryGetDynamicProperty(Key, OutValue);
}
bool UDynamicBase::TryGetDynamicFloatProperty(const FString& Key, float& OutValue) const
{
return TryGetDynamicProperty(Key, OutValue);
}
bool UDynamicBase::TryGetDynamicBoolProperty(const FString& Key, bool& OutValue) const
{
return TryGetDynamicProperty(Key, OutValue);
}
bool UDynamicBase::TryGetDynamicBaseProperty(const FString& Key, UBase*& OutValue) const
{
return TryGetDynamicProperty(Key, OutValue);
}
void UDynamicBase::SetDynamicStringProperty(const FString& Key, FString& OutValue)
{
SetDynamicProperty(Key, OutValue);
}
void UDynamicBase::SetDynamicIntProperty(const FString& Key, int32& OutValue)
{
SetDynamicProperty(Key, OutValue);
}
void UDynamicBase::SetDynamicFloatProperty(const FString& Key, float& OutValue)
{
SetDynamicProperty(Key, OutValue);
}
void UDynamicBase::SetDynamicBoolProperty(const FString& Key, bool& OutValue)
{
SetDynamicProperty(Key, OutValue);
}
void UDynamicBase::SetDynamicBaseProperty(const FString& Key, UBase*& OutValue)
{
SetDynamicProperty(Key, OutValue);
}
@@ -105,6 +105,64 @@ bool UMesh::Parse(const TSharedPtr<FJsonObject> Obj, const TScriptInterface<ITra
return Vertices.Num() > 0 && Faces.Num() > 0;
}
void UMesh::ToJson(TJsonWriter<TCHAR, TCondensedJsonPrintPolicy<TCHAR>> Writer)
{
Super::ToJson(Writer);
// Serialize Transform
// TODO todo transform
// Serialize Vertices
{
TArray<double> FlattenedVertices;
FlattenedVertices.Reserve(Vertices.Num() * 3);
for(size_t i = 0, j = 0; i < Vertices.Num(); i++)
{
const FVector& v = Vertices[i];
FlattenedVertices[j++] = v.X;
FlattenedVertices[j++] = -v.Y;
FlattenedVertices[j++] = v.Z;
}
Writer.WriteValue(TEXT("vertices"), FlattenedVertices);
}
// Serialize Faces
Writer.WriteValue(TEXT("faces"), Faces);
//Parse TextureCoords
{
TArray<double> FlattenedTexCoords;
FlattenedTexCoords.Reserve(TextureCoordinates.Num() * 2);
for(size_t i = 0, j = 0; i < TextureCoordinates.Num(); i++)
{
const FVector2D& c = TextureCoordinates[i];
FlattenedTexCoords[j++] = c.X;
FlattenedTexCoords[j++] = -c.Y;
}
Writer.WriteValue(TEXT("textureCoordinates"), FlattenedTexCoords);
}
//Parse VertexColors
{
TArray<int32> ArgbColors;
ArgbColors.Reserve(VertexColors.Num());
for(size_t i = 0; i < VertexColors.Num(); i++)
{
ArgbColors[i] = VertexColors[i].ToPackedARGB();
}
Writer.WriteValue(TEXT("colors"), ArgbColors);
}
// Parse Optional RenderMaterial
//if (RenderMaterial != nullptr)
{
//TODO renderMaterial
}
}
/**
* If not already so, this method will align vertices
@@ -0,0 +1,79 @@
#include "FBatchSender.h"
FBatchSender::FBatchSender(FString& ServerUrl, FString& StreamId, FString& AuthToken, int32 MaxBatchSizeMb,
int32 MaxBufferLength, int32 ThreadCount)
: ServerUrl(ServerUrl)
, StreamId(StreamId)
, AuthToken(AuthToken)
, MaxBatchSizeMb(MaxBatchSizeMb)
, MaxBufferLength(MaxBufferLength)
, ThreadCount(ThreadCount)
{
SendingThread = FRunnableThread::Create(this, TEXT("Speckle Transport Send Thread"), 0);
ensure(SendingThread != nullptr);
}
FBatchSender::~FBatchSender()
{
if (SendingThread)
{
SendingThread->Kill();
delete SendingThread;
SendingThread = nullptr;
}
}
uint32 FBatchSender::Run()
{
while(true)
{
if(!ShouldSendThreadRun) return 0;
TArray<TTuple<FString, FString>> Buffer;
FScopeLock Lock(&Lock_SendBuffer);
if(SendBuffer.Num() > 0)
{
Buffer.Append(SendBuffer);
SendBuffer.Empty();
}
else
{
IsWriteComplete = true;
}
if(Buffer.Num() <= 0)
{
FPlatformProcess::Sleep(0.1);
continue;
}
TArray<FString> ObjectIds;
ObjectIds.Reserve(Buffer.Num());
for(const auto& Item: Buffer)
{
ObjectIds.Add(Item.Key);
}
//TODO only send objects that aren't already on the server.
//TMap<FString, bool> HasObjects = API.HasObjects(StreamId, ObjectIds);
//TODO api upload
//API.UploadObjects(StreamId, Buffer);
}
}
void FBatchSender::Stop()
{
ShouldSendThreadRun = false;
}
void FBatchSender::EnqueueSend(const FString& Id, const FString& Object)
{
FScopeLock Lock(&Lock_SendBuffer);
SendBuffer.Emplace(Id, Object);
IsWriteComplete = false;
}
@@ -0,0 +1,40 @@
#pragma once
/**
*
*/
class SPECKLEUNREAL_API FBatchSender : public FRunnable
{
protected:
FString ServerUrl;
FString StreamId;
FString AuthToken;
int32 MaxBatchSizeMb;
int32 MaxBufferLength;
int32 ThreadCount;
bool ShouldSendThreadRun = false;
bool IsWriteComplete = false;
FRunnableThread* SendingThread;
FCriticalSection Lock_SendBuffer;
TArray<TTuple<const FString, const FString>> SendBuffer;
public:
FBatchSender(FString& ServerUrl, FString& StreamId, FString& AuthToken, int32 MaxBatchSizeMb=1, int32 MaxBufferLength = 10, int32 ThreadCount = 4);
virtual ~FBatchSender() override;
virtual uint32 Run() override;
virtual void Stop() override;
virtual void EnqueueSend(const FString& Id, const FString& Object);
virtual void Flush();
protected:
virtual void SendingThreadMain();
};
@@ -8,7 +8,6 @@ bool UMemoryTransport::HasObject(const FString& ObjectId) const
return SpeckleObjects.Contains(ObjectId);
}
TSharedPtr<FJsonObject> UMemoryTransport::GetSpeckleObject(const FString& ObjectId) const
{
return SpeckleObjects.FindRef(ObjectId);
@@ -3,6 +3,7 @@
#include "Transports/ServerTransport.h"
#include "FBatchSender.h"
#include "LogSpeckle.h"
#include "HttpModule.h"
#include "JsonObjectConverter.h"
@@ -12,20 +13,39 @@
#include "Policies/CondensedJsonPrintPolicy.h"
TSharedPtr<FJsonObject> UServerTransport::GetSpeckleObject(const FString& ObjectId) const
{
unimplemented();
return nullptr;
}
void UServerTransport::SaveObject(const FString& ObjectId, const TSharedPtr<FJsonObject> SerializedObject)
void UServerTransport::SaveObject(const FString& ObjectId, const TSharedPtr<FJsonObject> Object)
{
unimplemented(); //TODO implement
FString SerializedObject;
{
auto Writer = TJsonWriterFactory<TCHAR, TCondensedJsonPrintPolicy<TCHAR>>::Create(&SerializedObject);
FJsonSerializerWriter<TCHAR, TCondensedJsonPrintPolicy<TCHAR>> SerializerWriter(Writer);
FJsonSerializer::Serialize(Object.ToSharedRef(), Writer);
}
BatchSender.EnqueueSend(ObjectId, SerializedObject);
}
void UServerTransport::BeginWrite()
{
}
void UServerTransport::EndWrite()
{
BatchSender.Flush();
}
bool UServerTransport::HasObject(const FString& ObjectId) const
{
unimplemented(); //TODO implement
unimplemented();
return false;
}
@@ -1,47 +1,48 @@
// // Copyright 2022 AEC Systems, Licensed under the Apache License, Version 2.0
//
// #pragma once
//
// #include "CoreMinimal.h"
// #include "Kismet/BlueprintAsyncActionBase.h"
//
// #include "SendOperation.generated.h"
//
//
// class ITransport;
// class UBase;
//
// DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FSendOperationHandler, const FString&, Id, const FString&, ErrorMessage);
//
// /**
// *
// */
// UCLASS()
// class SPECKLEUNREAL_API USendOperation : public UBlueprintAsyncActionBase
// {
// GENERATED_BODY()
//
// public:
//
// UPROPERTY(BlueprintAssignable)
// FSendOperationHandler OnSendSuccessfully;
//
//
// UPROPERTY(BlueprintAssignable)
// FSendOperationHandler OnErrorAction;
//
//
// UFUNCTION(BlueprintCallable, Category = "Speckle|Operations", meta = (WorldContext = "WorldContextObject"))
// static USendOperation* SendOperation(UObject* WorldContextObject, UBase* Base, TArray<TScriptInterface<ITransport>> Transports);
//
// virtual void Activate() override;
//
// protected:
//
//
// TWeakObjectPtr<UBase> Base;
//
// TScriptArray<TScriptInterface<ITransport>> Transports;
//
//
// };
// Copyright 2022 AEC Systems, Licensed under the Apache License, Version 2.0
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintAsyncActionBase.h"
#include "SendOperation.generated.h"
class ITransport;
class UBase;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FSendOperationHandler, const FString&, Id, const FString&, ErrorMessage);
/**
*
*/
UCLASS()
class SPECKLEUNREAL_API USendOperation : public UBlueprintAsyncActionBase
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintAssignable)
FSendOperationHandler OnSendSuccessfully;
UPROPERTY(BlueprintAssignable)
FSendOperationHandler OnErrorAction;
UFUNCTION(BlueprintCallable, Category = "Speckle|Operations", meta = (WorldContext = "WorldContextObject"))
static USendOperation* SendOperation(UObject* WorldContextObject, UBase* Base, TArray<TScriptInterface<ITransport>> Transports);
virtual void Activate() override;
void Send();
protected:
TWeakObjectPtr<UBase> Base;
TArray<TScriptInterface<ITransport>> Transports;
};
@@ -36,7 +36,7 @@ public:
virtual bool CanConvertToNative_Implementation(TSubclassOf<UBase> BaseType) override;
virtual UBase* ConvertToSpeckle_Implementation(const UObject* Object) override;
virtual void ConvertToSpeckle_Implementation(const UObject* Object, UBase* SpeckleObject) override;
UFUNCTION(BlueprintCallable, Category="Speckle|Conversion")
@@ -76,7 +76,7 @@ public:
UStaticMeshConverter();
virtual UObject* ConvertToNative_Implementation(const UBase* SpeckleBase, UWorld* World, TScriptInterface<ISpeckleConverter>& AvailableConverters) override;
virtual UBase* ConvertToSpeckle_Implementation(const UObject* Object) override;
virtual void ConvertToSpeckle_Implementation(const UObject* Object, UBase* SpeckleObject) override;
virtual void FinishConversion_Implementation() override;
// Converts a multiple Speckle Meshes to a native actor of type MeshActorType
@@ -91,7 +91,7 @@ public:
FActorSpawnParameters());
UFUNCTION(BlueprintCallable, Category="ToSpeckle")
virtual UBase* MeshToSpeckle(const UStaticMeshComponent* Object);
virtual TArray<UMesh*> MeshToSpeckle(const UStaticMeshComponent* Object);
protected:
@@ -34,13 +34,22 @@ public:
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category="ToNative")
UObject* ConvertToNative(const UBase* SpeckleBase, UWorld* World, UPARAM(ref) TScriptInterface<ISpeckleConverter>& AvailableConverters);
/// Tries to convert a given Actor or Component into a Speckle Base
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category="ToSpeckle")
UBase* ConvertToSpeckle(const UObject* Object);
/// Clean up any cached assets that now may be unused
/// Clean up cached resources, and finish any pending build tasks to complete ToNative conversion.
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category="ToNative")
void FinishConversion();
/// Will return true if this converter can convert a given
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category="ToSpeckle")
void CanConvertToSpeckle(const AActor* Actor);
/// Tries to convert a given Actor or Component into a Speckle Base
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category="ToSpeckle")
void ConvertToSpeckle(const UObject* Object, UBase* SpeckleObject);
};
@@ -7,6 +7,7 @@
#include "SpeckleConverterComponent.generated.h"
DECLARE_DYNAMIC_DELEGATE_TwoParams(FActorPredicate, const AActor*, Actor, bool&, OutShouldConvert);
class ITransport;
class ISpeckleConverter;
@@ -32,16 +33,25 @@ public:
USpeckleConverterComponent();
// Converts the given Base and all children into native actors.
UFUNCTION(BlueprintCallable, Category="Speckle|Conversion")
UFUNCTION(BlueprintCallable, Category="Speckle|Conversion|ToNative")
UPARAM(DisplayName = "RootActor") AActor* RecursivelyConvertToNative(AActor* AOwner, const UBase* Base, const TScriptInterface<ITransport>& LocalTransport, bool DisplayProgressBar, TArray<AActor*>& OutActors);
UFUNCTION(BlueprintCallable, Category="Speckle|Conversion")
UFUNCTION(BlueprintCallable, Category="Speckle|Conversion|ToNative")
virtual void FinishConversion();
// Converts the given Base and all children into native actors.
UFUNCTION(BlueprintCallable, Category="Speckle|Conversion|ToSpeckle")
virtual UBase* RecursivelyConvertToSpeckle(const TArray<AActor*>& RootActors, FActorPredicate& Predicate);
UFUNCTION(BlueprintCallable, Category="Speckle|Conversion|ToSpeckle")
virtual void RecurseTreeToSpeckle(const AActor* RootActor, FActorPredicate& Predicate, TArray<UBase*>& OutConverted);
protected:
virtual AActor* RecursivelyConvertToNative_Internal(AActor* AOwner, const UBase* Base, const TScriptInterface<ITransport>& LocalTransport, FSlowTask* Task, TArray<AActor*>& OutActors);
virtual void ConvertChild(const TSharedPtr<FJsonValue> Object, AActor* AOwner, const TScriptInterface<ITransport>& LocalTransport, FSlowTask* Task, TArray<AActor*>& OutActors);
+16 -31
View File
@@ -3,6 +3,7 @@
#pragma once
#include "CoreMinimal.h"
#include "DynamicBase.h"
#include "Dom/JsonObject.h"
#include "Base.generated.h"
@@ -14,7 +15,7 @@ class ASpeckleUnrealManager;
* Base type that all Object Models inherit from
*/
UCLASS(BlueprintType, meta=(ScriptName="Base (Speckle.Objects)"))
class SPECKLEUNREAL_API UBase : public UObject
class SPECKLEUNREAL_API UBase : public UDynamicBase
{
public:
@@ -33,8 +34,6 @@ public:
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Speckle|Objects")
FString Id;
TMap<FString, TSharedPtr<FJsonValue>> DynamicProperties; //TODO this won't be serialised!
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Speckle|Objects")
FString Units;
@@ -44,7 +43,12 @@ public:
virtual bool Parse(const TSharedPtr<FJsonObject> Obj, const TScriptInterface<ITransport> ReadTransport)
{
bool IsValid = false;
DynamicProperties = Obj->Values;
DynamicProperties.Reserve(Obj->Values.Num());
for(const auto kvp : Obj->Values)
{
SetDynamicProperty(kvp.Key, kvp.Value->Type);
}
if(Obj->TryGetStringField("id", Id))
{
IsValid = true;
@@ -57,37 +61,18 @@ public:
return IsValid;
}
protected:
UFUNCTION(BlueprintCallable, Category="Speckle|Objects")
int32 RemoveDynamicProperty(UPARAM(ref) const FString& Key)
virtual void ToJson(TJsonWriter<TCHAR, TCondensedJsonPrintPolicy<TCHAR>> Writer)
{
return DynamicProperties.Remove(Key);
}
Writer.WriteValue(TEXT("units"), Units);
Writer.WriteValue(TEXT("speckle_type"), SpeckleType);
public:
UFUNCTION(BlueprintCallable, Category="Speckle|Objects")
bool TryGetDynamicString(UPARAM(ref) const FString& Key, FString& OutString) const
{
const TSharedPtr<FJsonValue> Value = DynamicProperties.FindRef(Key);
if(Value == nullptr) return false;
return Value->TryGetString(OutString);
for(const auto& p : DynamicProperties)
{
//Writer.WriteValue(p.Key, p.Value.mmmmmm));
}
}
UFUNCTION(BlueprintCallable, Category="Speckle|Objects")
bool TryGetDynamicNumber(UPARAM(ref) const FString& Key, float& OutNumber) const
{
const TSharedPtr<FJsonValue> Value = DynamicProperties.FindRef(Key);
if(Value == nullptr) return false;
return Value->TryGetNumber(OutNumber);
}
UFUNCTION(BlueprintCallable, Category="Speckle|Objects")
bool TryGetDynamicBool(UPARAM(ref) const FString& Key, bool& OutBool) const
{
const TSharedPtr<FJsonValue> Value = DynamicProperties.FindRef(Key);
if(Value == nullptr) return false;
return Value->TryGetBool(OutBool);
}
};
@@ -0,0 +1,66 @@
// Copyright AEC Systems Ltd
#pragma once
#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "DynamicBase.generated.h"
class UBase;
/**
*
*/
UCLASS(Abstract)
class SPECKLEUNREAL_API UDynamicBase : public UObject
{
GENERATED_BODY()
protected:
TMap<FString, TSharedPtr<FVariant>> DynamicProperties;
public:
template <typename T>
bool TryGetDynamicProperty(const FString& Key, T& OutValue) const;
UFUNCTION(BlueprintCallable, Category="Speckle|Objects")
bool TryGetDynamicStringProperty(UPARAM(ref) const FString& Key, FString& OutValue) const;
UFUNCTION(BlueprintCallable, Category="Speckle|Objects")
bool TryGetDynamicIntProperty(UPARAM(ref) const FString& Key, int32& OutValue) const;
UFUNCTION(BlueprintCallable, Category="Speckle|Objects")
bool TryGetDynamicFloatProperty(UPARAM(ref) const FString& Key, float& OutValue) const;
UFUNCTION(BlueprintCallable, Category="Speckle|Objects")
bool TryGetDynamicBoolProperty(UPARAM(ref) const FString& Key, bool& OutValue) const;
UFUNCTION(BlueprintCallable, Category="Speckle|Objects")
bool TryGetDynamicBaseProperty(UPARAM(ref) const FString& Key, UBase*& OutValue) const;
template <typename T>
void SetDynamicProperty(const FString& Key, T Value);
UFUNCTION(BlueprintCallable, Category="Speckle|Objects")
void SetDynamicStringProperty(UPARAM(ref) const FString& Key, FString& OutValue);
UFUNCTION(BlueprintCallable, Category="Speckle|Objects")
void SetDynamicIntProperty(UPARAM(ref) const FString& Key, int32& OutValue);
UFUNCTION(BlueprintCallable, Category="Speckle|Objects")
void SetDynamicFloatProperty(UPARAM(ref) const FString& Key, float& OutValue);
UFUNCTION(BlueprintCallable, Category="Speckle|Objects")
void SetDynamicBoolProperty(UPARAM(ref) const FString& Key, bool& OutValue);
UFUNCTION(BlueprintCallable, Category="Speckle|Objects")
void SetDynamicBaseProperty(UPARAM(ref) const FString& Key, UBase*& OutValue);
UFUNCTION(BlueprintCallable, Category="Speckle|Objects")
int32 RemoveDynamicProperty(UPARAM(ref) const FString& Key);
};
@@ -41,6 +41,8 @@ public:
virtual bool Parse(const TSharedPtr<FJsonObject> Obj, const TScriptInterface<ITransport> ReadTransport) override;
virtual void ToJson(TJsonWriter<TCHAR, TCondensedJsonPrintPolicy<TCHAR>> Writer) override;
protected:
virtual void AlignVerticesWithTexCoordsByIndex();
};
@@ -44,6 +44,6 @@ public:
UFUNCTION(BlueprintPure, Category="Speckle/ObjectUtils")
static FTransform CreateTransform(UPARAM(ref) const FMatrix& TransformMatrix);
UFUNCTION(BlueprintCallable, Category="Speckle/ObjectUtils")
UFUNCTION(BlueprintCallable, meta = (DeterminesOutputType = "Class"), Category="Speckle/ObjectUtils")
static AActor* SpawnActorInWorld(const TSubclassOf<AActor> Class, UWorld* World, UPARAM(ref) const FTransform& Transform);
};
@@ -20,7 +20,7 @@ class SPECKLEUNREAL_API UMemoryTransport : public UObject, public ITransport
public:
virtual TSharedPtr<FJsonObject> GetSpeckleObject(const FString& ObjectId) const override;
virtual void SaveObject(const FString& ObjectId, const TSharedPtr<FJsonObject> SerializedObject) override;
virtual void SaveObject(const FString& ObjectId, const FString& SerializedObject) override;
virtual bool HasObject(const FString& ObjectId) const override;
virtual void CopyObjectAndChildren(const FString& ObjectId, TScriptInterface<ITransport> TargetTransport, const FTransportCopyObjectCompleteDelegate& OnCompleteAction, const FTransportErrorDelegate& OnErrorAction) override { unimplemented(); }
@@ -7,7 +7,7 @@
#include "ServerTransport.generated.h"
class FBatchSender;
class FHttpModule;
// Data for graphQL request for object ids.
@@ -47,6 +47,8 @@ protected:
public:
virtual ~UServerTransport() override;
UFUNCTION(BlueprintPure, Category = "Speckle|Transports")
static UServerTransport* CreateServerTransport(UPARAM(ref) FString& _ServerUrl, UPARAM(ref) FString& _StreamId, UPARAM(ref) FString& _AuthToken)
{
@@ -58,7 +60,10 @@ public:
}
virtual TSharedPtr<FJsonObject> GetSpeckleObject(const FString& ObjectId) const override;
virtual void SaveObject(const FString& ObjectId, const TSharedPtr<FJsonObject> SerializedObject) override;
virtual void BeginWrite() override;
virtual void EndWrite() override;
virtual bool HasObject(const FString& ObjectId) const override;
@@ -88,6 +93,11 @@ protected:
static bool LoadJson(const FString& ObjectJson, TSharedPtr<FJsonObject>& OutJsonObject);
static int32 SplitLines(const FString& Content, TArray<FString>& OutLines);
FBatchSender BatchSender;
// FCriticalSection Lock_SendBuffer;
// TArray<TTuple<const FString, const FString>> SendBuffer;
// FRunnableThread* SendingThread;
};
@@ -28,13 +28,16 @@ class SPECKLEUNREAL_API ITransport
GENERATED_BODY()
public:
virtual void SaveObject(const FString& ObjectId, const TSharedPtr<FJsonObject> SerializedObject) = 0;
//TODO consider changing SerializedObject to FString&
virtual void SaveObject(const FString& ObjectId, const TSharedPtr<FJsonObject> SerializedObject) = 0;
//virtual void SaveObjectFromTransport(FString& ObjectID, TScriptInterface<ITransport> SourceTransport) = 0;
virtual TSharedPtr<FJsonObject> GetSpeckleObject(const FString& ObjectId) const = 0;
virtual bool HasObject(const FString& ObjectId) const;
virtual bool HasObject(const FString& ObjectId) const = 0;
virtual void BeginWrite();
virtual void EndWrite();
virtual void CopyObjectAndChildren(const FString& ObjectId,
TScriptInterface<ITransport> TargetTransport,