27 Commits

Author SHA1 Message Date
Jedd Morgan 23a5185d04 Merge pull request #13 from PanMig/SeparateModules
Separate modules for editor and runtime modes
2021-09-07 12:29:18 +01:00
Panagiotis Migkotzidis 1aa0b90592 fetch commits from selected branch through rest 2021-08-30 14:31:33 +03:00
Panagiotis Migkotzidis 0b218b1364 remove dependency of runtime rest calls 2021-08-30 10:29:09 +03:00
Panagiotis Migkotzidis df060666af added fetching list of streams 2021-08-27 14:43:14 +03:00
Panagiotis Migkotzidis 879d794b44 crop label 2021-08-23 16:37:07 +03:00
Panagiotis Migkotzidis 85f1de1492 add styleSet and icon to toolbar 2021-08-23 16:31:26 +03:00
Panagiotis Migkotzidis d49f142c03 null check for editor widget 2021-07-30 13:14:31 +03:00
Panagiotis Migkotzidis 9d82e8ed53 added runtime example map 2021-07-30 11:36:33 +03:00
Panagiotis Migkotzidis 7b353f0c46 stabilized runtime scene example 2021-07-29 13:19:09 +03:00
Panagiotis Migkotzidis c0c9e31046 added delegates for fetching actions 2021-07-28 18:01:53 +03:00
Panagiotis Migkotzidis 9c458d4629 show commits based on branch 2021-07-20 19:43:26 +03:00
Panagiotis Migkotzidis af5d7a9d8d separate modules stable 2021-07-16 14:46:14 +03:00
Panagiotis Migkotzidis 354b0bb7e8 Editor module functionality implemented 2021-07-14 19:17:30 +03:00
Panagiotis Migkotzidis e6d0a25008 stable separation of modules 2021-07-14 11:53:54 +03:00
Panagiotis Migkotzidis f4f58eaeac Delete NewEditorUtilityWidgetBlueprint.uasset 2021-07-14 11:10:57 +03:00
Panagiotis Migkotzidis eae2f7ff9b EWBP missing class 2021-07-14 10:48:46 +03:00
Panagiotis Migkotzidis 461d00073e create separate editor module 2021-07-13 14:23:53 +03:00
Panagiotis Migkotzidis 8c8259fbef Update SpeckleUnrealProject.sln 2021-07-13 13:38:49 +03:00
Panagiotis Migkotzidis c068fe0e60 Minor refactorings in speckle panel 2021-07-05 07:47:49 +03:00
Panagiotis Migkotzidis f50ddb3f7c fix regression issue with speckleManager 2021-06-23 19:07:01 +03:00
Cristian Balas 811bd59452 Merge pull request #2 from PanMig/CommitsList
Commits list
2021-06-08 15:25:18 +03:00
Panagiotis Migkotzidis cc882f5d4a Update BP_SpeckleManager.uasset 2021-06-06 18:46:26 +03:00
Panagiotis Migkotzidis e90b9bf164 added new action icons 2021-06-06 14:14:37 +03:00
Panagiotis Migkotzidis 56cd404cb0 new icons added 2021-06-05 23:56:06 +03:00
Panagiotis Migkotzidis b9da851d4c speckle editor window
- added new speckle dedicated editor window
- fetch and view commits
- work simultaneously with many streams and servers
2021-06-05 22:50:54 +03:00
Panagiotis Migkotzidis c4cfe34e6f speckle widget blueprint 2021-05-20 12:13:32 +03:00
Panagiotis Migkotzidis 0ad15c17f4 added utility blueprint 2021-05-19 02:22:39 +03:00
45 changed files with 1404 additions and 78 deletions
+9 -2
View File
@@ -1,6 +1,9 @@
# Prerequisites
*.d
.idea/
.vs/
# Compiled Object files
*.slo
*.lo
@@ -31,11 +34,15 @@
*.out
*.app
*.umap
# UE file types
*.uasset filter=lfs diff=lfs merge=lfs -text
*.umap filter=lfs diff=lfs merge=lfs -text
SpeckleUnrealProject/Binaries/
SpeckleUnrealProject/Intermediate/
SpeckleUnrealProject/Plugins/SpeckleUnreal/Binaries/
SpeckleUnrealProject/Plugins/SpeckleUnreal/Intermediate/
SpeckleUnrealProject/Saved/
SpeckleUnrealProject/.vs/
.idea/
.vs/
SpeckleUnrealProject/SpeckleUnrealProject.sln.DotSettings.user
@@ -14,3 +14,6 @@ AppliedDefaultGraphicsPerformance=Maximum
[/Script/IOSRuntimeSettings.IOSRuntimeSettings]
RemoteServerName=
[/Script/EngineSettings.GameMapsSettings]
GameDefaultMap=/Game/SpeckleScene.SpeckleScene
@@ -1,3 +1,70 @@
[/Script/EngineSettings.GeneralProjectSettings]
ProjectID=F126DB004A50E31B2A69D284041A10E1
[/Script/UnrealEd.ProjectPackagingSettings]
Build=IfProjectHasCode
BuildConfiguration=PPBC_Development
BuildTarget=
StagingDirectory=(Path="C:/Users/migkotzidis_local/Desktop/SpeckleBuild")
FullRebuild=False
ForDistribution=False
IncludeDebugFiles=False
BlueprintNativizationMethod=Disabled
bIncludeNativizedAssetsInProjectGeneration=False
bExcludeMonolithicEngineHeadersInNativizedCode=False
UsePakFile=True
bUseIoStore=False
bGenerateChunks=False
bGenerateNoChunks=False
bChunkHardReferencesOnly=False
bForceOneChunkPerFile=False
MaxChunkSize=0
bBuildHttpChunkInstallData=False
HttpChunkInstallDataDirectory=(Path="")
PakFileCompressionFormats=
PakFileAdditionalCompressionOptions=
HttpChunkInstallDataVersion=
IncludePrerequisites=True
IncludeAppLocalPrerequisites=False
bShareMaterialShaderCode=True
bDeterministicShaderCodeOrder=False
bSharedMaterialNativeLibraries=True
ApplocalPrerequisitesDirectory=(Path="")
IncludeCrashReporter=False
InternationalizationPreset=English
-CulturesToStage=en
+CulturesToStage=en
LocalizationTargetCatchAllChunkId=0
bCookAll=False
bCookMapsOnly=False
bCompressed=False
bSkipEditorContent=False
bSkipMovies=False
-IniKeyBlacklist=KeyStorePassword
-IniKeyBlacklist=KeyPassword
-IniKeyBlacklist=rsa.privateexp
-IniKeyBlacklist=rsa.modulus
-IniKeyBlacklist=rsa.publicexp
-IniKeyBlacklist=aes.key
-IniKeyBlacklist=SigningPublicExponent
-IniKeyBlacklist=SigningModulus
-IniKeyBlacklist=SigningPrivateExponent
-IniKeyBlacklist=EncryptionKey
-IniKeyBlacklist=IniKeyBlacklist
-IniKeyBlacklist=IniSectionBlacklist
+IniKeyBlacklist=KeyStorePassword
+IniKeyBlacklist=KeyPassword
+IniKeyBlacklist=rsa.privateexp
+IniKeyBlacklist=rsa.modulus
+IniKeyBlacklist=rsa.publicexp
+IniKeyBlacklist=aes.key
+IniKeyBlacklist=SigningPublicExponent
+IniKeyBlacklist=SigningModulus
+IniKeyBlacklist=SigningPrivateExponent
+IniKeyBlacklist=EncryptionKey
+IniKeyBlacklist=IniKeyBlacklist
+IniKeyBlacklist=IniSectionBlacklist
+MapsToCook=(FilePath="/Game/SpeckleScene")
Binary file not shown.

After

Width:  |  Height:  |  Size: 852 B

@@ -0,0 +1,6 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "ISpeckleReceiver.h"
// Add default functionality here for any IISpeckleReceiver functions that are not pure virtual.
@@ -0,0 +1,116 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "SpeckleRESTHandlerComponent.h"
// Sets default values for this component's properties
USpeckleRESTHandlerComponent::USpeckleRESTHandlerComponent()
{
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
// off to improve performance if you don't need them.
PrimaryComponentTick.bCanEverTick = false;
// ...
}
// Called when the game starts
void USpeckleRESTHandlerComponent::BeginPlay()
{
Super::BeginPlay();
// cache speckleManager for runtime purposes
SpeckleManager = Cast<ASpeckleUnrealManager>(GetOwner());
}
void USpeckleRESTHandlerComponent::ImportSpeckleObject(int CurrIndex)
{
#if WITH_EDITOR
SpeckleManager = Cast<ASpeckleUnrealManager>(GetOwner());
#endif
if(SpeckleManager)
{
auto Commits = SpeckleManager->ArrayOfCommits;
// check if within bounds and import
if(Commits.Num() > 0 && (CurrIndex <= Commits.Num() && CurrIndex >= 0))
{
const auto InputObjectRefID = Commits[CurrIndex].ReferenceObjectID;
SpeckleManager->ObjectID = InputObjectRefID;
SpeckleManager->ImportSpeckleObject();
return;
}
UE_LOG(LogTemp, Warning, TEXT("[SPECKLE LOG]: Speckle unreal commits array index out of bounds"));
}
}
void USpeckleRESTHandlerComponent::FetchListOfCommits(const FString& BranchName)
{
#if WITH_EDITOR
SpeckleManager = Cast<ASpeckleUnrealManager>(GetOwner());
#endif
if(SpeckleManager)
{
//FString PostPayload = "{\"query\": \"query{stream (id: \\\"" + SpeckleManager->StreamID + "\\\"){id name commits {totalCount cursor items {id referencedObject authorName message branchName} } }}\"}";
FString PostPayload = "{\"query\": \"query{stream (id: \\\"" + SpeckleManager->StreamID + "\\\"){branch(name: \\\"" + BranchName + "\\\"){commits{items {id referencedObject authorName message branchName} } }}}\"}";
TFunction<void(FHttpRequestPtr, FHttpResponsePtr , bool)> HandleResponse = [this](FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
{ SpeckleManager->OnCommitsItemsResponseReceived(Request, Response, bWasSuccessful); };
SpeckleManager->FetchStreamItems(PostPayload, HandleResponse);
}
}
void USpeckleRESTHandlerComponent::FetchListOfStreams()
{
#if WITH_EDITOR
SpeckleManager = Cast<ASpeckleUnrealManager>(GetOwner());
#endif
if(SpeckleManager)
{
FString PostPayload = "{\"query\": \"query{user {streams(limit:20) {totalCount items {id name description}}}}\"}";
TFunction<void(FHttpRequestPtr, FHttpResponsePtr , bool)> HandleResponse = [this](FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
{ SpeckleManager->OnStreamItemsResponseReceived(Request, Response, bWasSuccessful); };
SpeckleManager->FetchStreamItems(PostPayload, HandleResponse);
}
}
void USpeckleRESTHandlerComponent::FetchListOfBranches()
{
#if WITH_EDITOR
SpeckleManager = Cast<ASpeckleUnrealManager>(GetOwner());
#endif
if(SpeckleManager)
{
FString PostPayload = "{\"query\": \"query{\\n stream (id: \\\"" + SpeckleManager->StreamID + "\\\"){\\n id\\n name\\n branches{\\n totalCount\\n cursor\\n items{\\n id\\n name\\n description\\n}\\n }\\n }\\n}\"}";
TFunction<void(FHttpRequestPtr, FHttpResponsePtr , bool)> HandleResponse = [this](FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
{ SpeckleManager->OnBranchesItemsResponseReceived(Request, Response, bWasSuccessful); };
SpeckleManager->FetchStreamItems(PostPayload, HandleResponse);
}
}
void USpeckleRESTHandlerComponent::FetchGlobals()
{
#if WITH_EDITOR
SpeckleManager = Cast<ASpeckleUnrealManager>(GetOwner());
#endif
if(SpeckleManager)
{
FString PostPayload = "{\"query\": \"query{stream (id: \\\"" + SpeckleManager->StreamID + "\\\"){branch(name: \\\"" + "globals" + "\\\"){commits{totalCount items{referencedObject}}}}}\"}";
TFunction<void(FHttpRequestPtr, FHttpResponsePtr , bool)> HandleResponse = [this](FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
{ SpeckleManager->OnGlobalStreamItemsResponseReceived(Request, Response, bWasSuccessful); };
SpeckleManager->FetchStreamItems(PostPayload, HandleResponse);
}
}
@@ -0,0 +1,5 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "SpeckleStructs.h"
@@ -2,19 +2,15 @@
#include "SpeckleUnreal.h"
#define LOCTEXT_NAMESPACE "FSpeckleUnrealModule"
IMPLEMENT_MODULE(FSpeckleUnrealModule, SpeckleUnreal)
void FSpeckleUnrealModule::StartupModule()
{
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
}
void FSpeckleUnrealModule::ShutdownModule()
{
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
// we call this function before unloading the module.
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FSpeckleUnrealModule, SpeckleUnreal)
}
@@ -1,4 +1,7 @@
#include "SpeckleUnrealManager.h"
#include "HttpManager.h"
#include "UObject/ConstructorHelpers.h"
#include "Dom/JsonObject.h"
// Sets default values
ASpeckleUnrealManager::ASpeckleUnrealManager()
@@ -10,7 +13,7 @@ ASpeckleUnrealManager::ASpeckleUnrealManager()
Http = &FHttpModule::Get();
// default conversion is millimeters to centimeters because streams tend to be in ml and unreal is in cm by defaults
ScaleFactor = 0.1;
World = GetWorld();
World = AActor::GetWorld();
DefaultMeshOpaqueMaterial = SpeckleMaterial.Object;
DefaultMeshTransparentMaterial = SpeckleGlassMaterial.Object;
@@ -30,8 +33,7 @@ void ASpeckleUnrealManager::BeginPlay()
void ASpeckleUnrealManager::ImportSpeckleObject()
{
FString url = ServerUrl + "/objects/" + StreamID + "/" + ObjectID;
GEngine->AddOnScreenDebugMessage(0, 5.0f, FColor::Green, "[Speckle] Downloading: " + url);
FHttpRequestRef Request = Http->CreateRequest();
Request->SetVerb("GET");
@@ -87,7 +89,7 @@ void ASpeckleUnrealManager::OnStreamTextResponseReceived(FHttpRequestPtr Request
}
GEngine->AddOnScreenDebugMessage(0, 5.0f, FColor::Green, FString::Printf(TEXT("[Speckle] Converting %d objects..."), lineCount));
ImportObjectFromCache(SpeckleObjects[ObjectID]);
for (auto& m : CreatedSpeckleMeshes)
@@ -102,7 +104,6 @@ void ASpeckleUnrealManager::OnStreamTextResponseReceived(FHttpRequestPtr Request
InProgressSpeckleMeshes.Empty();
GEngine->AddOnScreenDebugMessage(0, 5.0f, FColor::Green, FString::Printf(TEXT("[Speckle] Objects imported successfully. Created %d Actors"), CreatedSpeckleMeshes.Num()));
}
ASpeckleUnrealMesh* ASpeckleUnrealManager::GetExistingMesh(const FString &objectId)
@@ -254,15 +255,19 @@ ASpeckleUnrealMesh* ASpeckleUnrealManager::CreateMesh(TSharedPtr<FJsonObject> ob
TArray<TSharedPtr<FJsonValue>> ObjectVertices = SpeckleObjects[verticesId]->GetArrayField("data");
TArray<TSharedPtr<FJsonValue>> ObjectFaces = SpeckleObjects[facesId]->GetArrayField("data");
#if WITH_EDITOR
World = GetWorld();
#endif
if(World == nullptr)
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, FString::Printf(TEXT("Null World")));
return nullptr;
}
AActor* ActorInstance = World->SpawnActor(MeshActor);
ASpeckleUnrealMesh* MeshInstance = (ASpeckleUnrealMesh*)ActorInstance;
//Currently not needed since meshes are placed under this actor.
// #if WITH_EDITOR
// MeshInstance->SetFolderPath(FName(GetActorLabel() + FString(TEXT("_")) + StreamID));
// #endif
// attaches each speckleMesh under this actor (SpeckleManager)
if(MeshInstance != nullptr)
@@ -324,6 +329,240 @@ ASpeckleUnrealMesh* ASpeckleUnrealManager::CreateMesh(TSharedPtr<FJsonObject> ob
return MeshInstance;
}
void ASpeckleUnrealManager::OnCommitsItemsResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
{
if (!bWasSuccessful)
{
GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::Red, "Stream Request failed: " + Response->GetContentAsString());
return;
}
auto responseCode = Response-> GetResponseCode();
if (responseCode != 200)
{
GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::Red,
FString::Printf(TEXT("Error response. Response code %d"), responseCode));
return;
}
FString response = Response->GetContentAsString();
//Create a pointer to hold the json serialized data
TSharedPtr<FJsonObject> JsonObject;
//Create a reader pointer to read the json data
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(response);
ArrayOfCommits.Empty();
//Deserialize the json data given Reader and the actual object to deserialize
if (FJsonSerializer::Deserialize(Reader, JsonObject))
{
for(const auto& pair:JsonObject->Values)
{
auto CommitsArr = JsonObject->GetObjectField(TEXT("data"))
->GetObjectField(TEXT("stream"))
->GetObjectField(TEXT("branch"))
->GetObjectField(TEXT("commits"))
->GetArrayField(TEXT("items"));
for (auto commit : CommitsArr)
{
auto ObjID = commit->AsObject()->GetStringField("referencedObject");
auto Message = commit->AsObject()->GetStringField("message");
auto AuthorName = commit->AsObject()->GetStringField("authorName");
auto BranchName = commit->AsObject()->GetStringField("branchName");
auto Commit = FSpeckleCommit(ObjID, AuthorName, Message, BranchName);
ArrayOfCommits.Add(Commit);
}
}
}
OnCommitsProcessed.Broadcast(ArrayOfCommits);
}
void ASpeckleUnrealManager::OnBranchesItemsResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
{
if (!bWasSuccessful)
{
GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::Red, "Stream Request failed: " + Response->GetContentAsString());
return;
}
auto responseCode = Response-> GetResponseCode();
if (responseCode != 200)
{
GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::Red,
FString::Printf(TEXT("Error response. Response code %d"), responseCode));
return;
}
FString response = Response->GetContentAsString();
//Create a pointer to hold the json serialized data
TSharedPtr<FJsonObject> JsonObject;
//Create a reader pointer to read the json data
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(response);
ArrayOfBranches.Empty();
//Deserialize the json data given Reader and the actual object to deserialize
if (FJsonSerializer::Deserialize(Reader, JsonObject))
{
for(const auto& pair:JsonObject->Values)
{
auto BranchesArr = JsonObject->GetObjectField(TEXT("data"))
->GetObjectField(TEXT("stream"))
->GetObjectField(TEXT("branches"))
->GetArrayField(TEXT("items"));
for (auto b : BranchesArr)
{
auto ID = b->AsObject()->GetStringField("id");
auto Name = b->AsObject()->GetStringField("name");
auto Description = b->AsObject()->GetStringField("description");
auto Branch = FSpeckleBranch(ID, Name, Description);
ArrayOfBranches.Add(Branch);
}
}
}
OnBranchesProcessed.Broadcast(ArrayOfBranches);
}
void ASpeckleUnrealManager::OnStreamItemsResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response,
bool bWasSuccessful)
{
if (!bWasSuccessful)
{
GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::Red, "Stream Request failed: " + Response->GetContentAsString());
return;
}
auto responseCode = Response-> GetResponseCode();
if (responseCode != 200)
{
GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::Red,
FString::Printf(TEXT("Error response. Response code %d"), responseCode));
return;
}
FString response = Response->GetContentAsString();
//Create a pointer to hold the json serialized data
TSharedPtr<FJsonObject> JsonObject;
//Create a reader pointer to read the json data
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(response);
ArrayOfStreams.Empty();
//Deserialize the json data given Reader and the actual object to deserialize
if (FJsonSerializer::Deserialize(Reader, JsonObject))
{
for(const auto& pair:JsonObject->Values)
{
auto StreamsArr = JsonObject->GetObjectField(TEXT("data"))
->GetObjectField(TEXT("user"))
->GetObjectField(TEXT("streams"))
->GetArrayField(TEXT("items"));
for (auto s : StreamsArr)
{
auto ID = s->AsObject()->GetStringField("id");
auto Name = s->AsObject()->GetStringField("name");
auto Description = s->AsObject()->GetStringField("description");
auto Stream = FSpeckleStream(ID, Name, Description);
ArrayOfStreams.Add(Stream);
}
}
}
OnStreamsProcessed.Broadcast(ArrayOfStreams);
}
void ASpeckleUnrealManager::OnGlobalStreamItemsResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response,
bool bWasSuccessful)
{
if (!bWasSuccessful)
{
GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::Red, "Stream Request failed: " + Response->GetContentAsString());
return;
}
auto responseCode = Response-> GetResponseCode();
if (responseCode != 200)
{
GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::Red,
FString::Printf(TEXT("Error response. Response code %d"), responseCode));
return;
}
FString response = Response->GetContentAsString();
//Create a pointer to hold the json serialized data
TSharedPtr<FJsonObject> JsonObject;
//Create a reader pointer to read the json data
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(response);
auto RefObjectID = FString();
//Deserialize the json data given Reader and the actual object to deserialize
if (FJsonSerializer::Deserialize(Reader, JsonObject))
{
for(const auto& pair:JsonObject->Values)
{
RefObjectID = JsonObject->GetObjectField(TEXT("data"))
->GetObjectField(TEXT("stream"))
->GetObjectField(TEXT("branch"))
->GetObjectField("commits")
->GetArrayField("items")[0]->AsObject()->GetStringField("referencedObject");
}
TFunction<void(FHttpRequestPtr, FHttpResponsePtr , bool)> TempResponseHandler = [=](FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
{
FString response = Response->GetContentAsString();
TSharedPtr<FJsonObject> JsonObject;
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(response);
if (FJsonSerializer::Deserialize(Reader, JsonObject))
{
for(const auto& pair:JsonObject->Values)
{
auto GlobalObject = JsonObject->GetObjectField(TEXT("data"))
->GetObjectField(TEXT("stream"))
->GetObjectField(TEXT("object"))
->GetObjectField(TEXT("data"));
auto Region = GlobalObject->GetStringField("Region");
auto Lat = GlobalObject->GetNumberField("Latitude");
auto Long = GlobalObject->GetNumberField("Longitude");
FSpeckleGlobals Global = FSpeckleGlobals(RefObjectID, Region, static_cast<float>(Lat), static_cast<float>(Long));
OnGlobalsProcessed.Broadcast(Global);
}
}
};
FString PostPayload = "{\"query\": \"query{stream (id:\\\"" + StreamID + "\\\"){id name description object(id:\\\"" + RefObjectID + "\\\"){id data}}}\"}";
FetchStreamItems(PostPayload, TempResponseHandler);
}
}
void ASpeckleUnrealManager::FetchStreamItems(FString PostPayload, TFunction<void(FHttpRequestPtr, FHttpResponsePtr , bool)> HandleResponse)
{
FString url = ServerUrl + "/graphql";
FHttpRequestRef Request = Http->CreateRequest();
Request->SetVerb(TEXT("POST"));
Request->SetHeader("Accept-Encoding", TEXT("gzip"));
Request->SetHeader("Content-Type", TEXT("application/json"));
Request->SetHeader("Accept", TEXT("application/json"));
Request->SetHeader("DNT", TEXT("1"));
Request->SetHeader("Origin", TEXT("https://speckle.xyz"));
Request->SetHeader("Authorization", "Bearer " + AuthToken);
Request->SetContentAsString(PostPayload);
Request->OnProcessRequestComplete().BindLambda([=](
FHttpRequestPtr request,
FHttpResponsePtr response,
bool success)
{ HandleResponse(request, response, success); });
Request->SetURL(url);
Request->ProcessRequest();
}
void ASpeckleUnrealManager::DeleteObjects()
{
for (auto& m : CreatedSpeckleMeshes)
@@ -2,6 +2,7 @@
#include "SpeckleUnrealMesh.h"
#include "Materials/MaterialInstanceDynamic.h"
// Sets default values
ASpeckleUnrealMesh::ASpeckleUnrealMesh()
@@ -0,0 +1,8 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "SpeckleWidgetBase.h"
#include "ISpeckleReceiver.h"
@@ -0,0 +1,32 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "SpeckleUnrealManager.h"
#include "UObject/Interface.h"
#include "ISpeckleReceiver.generated.h"
// This class does not need to be modified.
UINTERFACE(MinimalAPI)
class UISpeckleReceiver : public UInterface
{
GENERATED_BODY()
};
/**
*
*/
class SPECKLEUNREAL_API IISpeckleReceiver
{
GENERATED_BODY()
// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:
virtual void ImportSpeckleObject(int CurrIndex) = 0;
virtual void FetchListOfCommits(const FString& BranchName) = 0;
virtual void FetchListOfStreams() = 0;
virtual void FetchListOfBranches() = 0;
virtual void FetchGlobals() = 0;
};
@@ -0,0 +1,44 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "ISpeckleReceiver.h"
#include "Components/ActorComponent.h"
#include "SpeckleRESTHandlerComponent.generated.h"
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class SPECKLEUNREAL_API USpeckleRESTHandlerComponent : public UActorComponent, public IISpeckleReceiver
{
GENERATED_BODY()
public:
// Sets default values for this component's properties
USpeckleRESTHandlerComponent();
protected:
// Called when the game starts
virtual void BeginPlay() override;
public:
UFUNCTION(BlueprintCallable, Category="Speckle REST")
virtual void ImportSpeckleObject(int CurrIndex) override;
UFUNCTION(BlueprintCallable, Category="Speckle REST")
virtual void FetchListOfCommits(const FString& BranchName) override;
UFUNCTION(BlueprintCallable, Category="Speckle REST")
virtual void FetchListOfStreams() override;
UFUNCTION(BlueprintCallable, Category="Speckle REST")
virtual void FetchListOfBranches() override;
UFUNCTION(BlueprintCallable, Category="Speckle REST")
virtual void FetchGlobals() override;
UPROPERTY()
ASpeckleUnrealManager* SpeckleManager;
};
@@ -0,0 +1,136 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "SpeckleStructs.generated.h"
/*
* Struct that holds all the properties required
* from a speckle commit
* received from GraphQL.
*/
USTRUCT(BlueprintType)
struct FSpeckleCommit
{
GENERATED_USTRUCT_BODY()
UPROPERTY(BlueprintReadWrite)
FString ReferenceObjectID;
UPROPERTY(BlueprintReadWrite)
FString AuthorName;
UPROPERTY(BlueprintReadWrite)
FString Message;
UPROPERTY(BlueprintReadWrite)
FString BranchName;
FSpeckleCommit(){};
FSpeckleCommit(const FString& ReferenceObjectID, const FString& AuthorName, const FString& Message, const FString& BranchName)
: ReferenceObjectID(ReferenceObjectID),
AuthorName(AuthorName),
Message(Message),
BranchName(BranchName)
{
}
//Operators overloading
FORCEINLINE bool operator==(const FSpeckleCommit &Other) const
{
return ReferenceObjectID == Other.ReferenceObjectID;
}
};
/*
* Struct that holds all the properties required
* from a speckle Branch
* received from GraphQL.
*/
USTRUCT(BlueprintType)
struct FSpeckleBranch
{
GENERATED_USTRUCT_BODY()
UPROPERTY(BlueprintReadWrite)
FString ID;
UPROPERTY(BlueprintReadWrite)
FString Name;
UPROPERTY(BlueprintReadWrite)
FString Description;
FSpeckleBranch(){};
FSpeckleBranch(const FString& ID, const FString& Name, const FString& Description):
ID(ID), Name(Name), Description(Description){}
};
/*
* Struct that holds all the properties required
* from a speckle Branch
* received from GraphQL.
*/
USTRUCT(BlueprintType)
struct FSpeckleGlobals
{
GENERATED_USTRUCT_BODY()
UPROPERTY(BlueprintReadWrite)
FString ID;
UPROPERTY(BlueprintReadWrite)
FString Region;
UPROPERTY(BlueprintReadWrite)
float Latitude;
UPROPERTY(BlueprintReadWrite)
float Longitude;
FSpeckleGlobals(): Latitude(0), Longitude(0)
{
};
FSpeckleGlobals(const FString& ID, const FString& Region, float Latitude, float Longitude)
: ID(ID),
Region(Region),
Latitude(Latitude),
Longitude(Longitude)
{
}
};
/*
* Struct that holds all the properties required
* from a speckle Branch
* received from GraphQL.
*/
USTRUCT(BlueprintType)
struct FSpeckleStream
{
GENERATED_USTRUCT_BODY()
UPROPERTY(BlueprintReadWrite)
FString ID;
UPROPERTY(BlueprintReadWrite)
FString Name;
UPROPERTY(BlueprintReadWrite)
FString Description;
FSpeckleStream(){};
FSpeckleStream(const FString& ID, const FString& Name, const FString& Description):
ID(ID), Name(Name), Description(Description){}
};
UENUM()
enum ESpeckleItemType {Stream, Commit, Branch};
@@ -3,13 +3,12 @@
#pragma once
#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"
class FSpeckleUnrealModule : public IModuleInterface
{
public:
/** IModuleInterface implementation */
virtual void StartupModule() override;
virtual void ShutdownModule() override;
};
@@ -5,9 +5,9 @@
// json manipulation
#include "Dom/JsonObject.h"
#include "Dom/JsonValue.h"
#include "Serialization/JsonReader.h"
#include "Serialization/JsonSerializer.h"
// #include "Dom/JsonValue.h"
// #include "Serialization/JsonReader.h"
// #include "Serialization/JsonSerializer.h"
// web requests
#include "Runtime/Online/HTTP/Public/Http.h"
@@ -15,13 +15,20 @@
#include "SpeckleUnrealMesh.h"
#include "SpeckleUnrealLayer.h"
#include "GameFramework/Actor.h"
#include "SpeckleStructs.h"
#include "SpeckleUnrealManager.generated.h"
UCLASS(BlueprintType)
UCLASS(BlueprintType, Blueprintable)
class SPECKLEUNREAL_API ASpeckleUnrealManager : public AActor
{
GENERATED_BODY()
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FBranchesRequestProcessed, const TArray<FSpeckleBranch>&, BranchesList);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FCommitsRequestProcessed, const TArray<FSpeckleCommit>&, CommitsList);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FStreamsRequestProcessed, const TArray<FSpeckleStream>&, StreamsList);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FGlobalsRequestProcessed, const FSpeckleGlobals&, GlobalsObject);
public:
FHttpModule* Http;
@@ -29,47 +36,57 @@ public:
UFUNCTION(CallInEditor, Category = "Speckle")
void ImportSpeckleObject();
UFUNCTION(CallInEditor, Category = "Speckle")
UFUNCTION(CallInEditor, BlueprintCallable, Category = "Speckle")
void DeleteObjects();
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Speckle")
FString ServerUrl {
FString ServerUrl
{
"https://speckle.xyz"
};
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Speckle")
FString StreamID {
FString StreamID
{
""
};
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Speckle")
FString ObjectID {
FString ObjectID
{
""
};
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Speckle")
FString AuthToken
{
""
};
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Speckle")
FString AuthToken {
""
};
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Speckle")
TSubclassOf<ASpeckleUnrealMesh> MeshActor {
TSubclassOf<ASpeckleUnrealMesh> MeshActor
{
ASpeckleUnrealMesh::StaticClass()
};
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Speckle")
UMaterialInterface* DefaultMeshOpaqueMaterial;
UMaterialInterface* DefaultMeshOpaqueMaterial;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Speckle")
UMaterialInterface* DefaultMeshTransparentMaterial;
UMaterialInterface* DefaultMeshTransparentMaterial;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Speckle")
bool ImportAtRuntime;
bool ImportAtRuntime;
TArray<USpeckleUnrealLayer*> SpeckleUnrealLayers;
void OnStreamTextResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
void OnCommitsItemsResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
void OnBranchesItemsResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
void OnStreamItemsResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
void OnGlobalStreamItemsResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
// Sets default values for this actor's properties
ASpeckleUnrealManager();
@@ -77,6 +94,26 @@ public:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
UPROPERTY()
TArray<FSpeckleCommit> ArrayOfCommits;
UPROPERTY()
TArray<FSpeckleBranch> ArrayOfBranches;
UPROPERTY()
TArray<FSpeckleStream> ArrayOfStreams;
void FetchStreamItems(FString PostPayload, TFunction<void(FHttpRequestPtr, FHttpResponsePtr , bool)> HandleResponse);
UPROPERTY(BlueprintAssignable, Category = "SpeckleEvents");
FBranchesRequestProcessed OnBranchesProcessed;
UPROPERTY(BlueprintAssignable, Category = "SpeckleEvents");
FCommitsRequestProcessed OnCommitsProcessed;
UPROPERTY(BlueprintAssignable, Category = "SpeckleEvents");
FStreamsRequestProcessed OnStreamsProcessed;
UPROPERTY(BlueprintAssignable, Category = "SpeckleEvents");
FGlobalsRequestProcessed OnGlobalsProcessed;
protected:
UWorld* World;
@@ -84,7 +121,8 @@ protected:
float ScaleFactor;
TMap<FString, TSharedPtr<FJsonObject>> SpeckleObjects;
TMap<FString, TSharedPtr<FJsonObject>> SpeckleCommits;
TMap<FString, ASpeckleUnrealMesh*> CreatedSpeckleMeshes;
TMap<FString, ASpeckleUnrealMesh*> InProgressSpeckleMeshes;
@@ -94,4 +132,17 @@ protected:
UMaterialInterface* CreateMaterial(TSharedPtr<FJsonObject>);
ASpeckleUnrealMesh* CreateMesh(TSharedPtr<FJsonObject>, UMaterialInterface *explicitMaterial = nullptr);
TArray<uint8> FStringToUint8(const FString& InString)
{
TArray<uint8> OutBytes;
// Handle empty strings
if (InString.Len() > 0)
{
FTCHARToUTF8 Converted(*InString); // Convert to UTF8
OutBytes.Append(reinterpret_cast<const uint8*>(Converted.Get()), Converted.Length());
}
return OutBytes;
}
};
@@ -0,0 +1,20 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "SpeckleUnrealManager.h"
#include "Blueprint/UserWidget.h"
#include "SpeckleWidgetBase.generated.h"
/**
*
*/
UCLASS(BlueprintType)
class SPECKLEUNREAL_API USpeckleWidgetBase : public UUserWidget
{
GENERATED_BODY()
public:
};
@@ -29,12 +29,13 @@ public class SpeckleUnreal : ModuleRules
"Http",
"Json",
"JsonUtilities",
"ProceduralMeshComponent"
// ... add other public dependencies that you statically link with here ...
"ProceduralMeshComponent",
"InputCore",
"Slate",
"SlateCore",
}
);
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
@@ -42,6 +43,7 @@ public class SpeckleUnreal : ModuleRules
"Engine",
"Slate",
"SlateCore",
"UMG"
// ... add private dependencies that you statically link with here ...
}
);
@@ -0,0 +1,20 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "FSpeckleEditorCommands.h"
#include "Framework/Commands/Commands.h"
void FSpeckleEditorCommands::RegisterCommands()
{
//we meed to define a localized namespace even if its not used
#define LOCTEXT_NAMESPACE ""
UI_COMMAND(
SpeckleToolBarBtn,
"SpeckleBtn",
"Speckle Editor Button",
EUserInterfaceActionType::Button,
FInputGesture());
#undef LOCTEXT_NAMESPACE
}
@@ -0,0 +1,107 @@
#include "FSpeckleUnrealEditorModule.h"
#include "EditorUtilityWidget.h"
#include "SpeckleUnrealManager.h"
#include "FSpeckleEditorCommands.h"
IMPLEMENT_MODULE(FSpeckleUnrealEditorModule, SpeckleUnrealEditor);
#define LOCTEXT_NAMESPACE "FSpeckleUnrealEditorModule"
void FSpeckleUnrealEditorModule::StartupModule()
{
FSpeckleEditorCommands::Register();
TSharedPtr<FUICommandList> CommandList = MakeShareable(new FUICommandList());
FSpeckleStyle::Initialize();
//map object to function
CommandList->MapAction
(
FSpeckleEditorCommands::Get().SpeckleToolBarBtn,
FExecuteAction::CreateRaw(this, &FSpeckleUnrealEditorModule::SpeckleButtonListener),
FCanExecuteAction()
);
//add to UE4 toolbar
ToolbarExtender = MakeShareable(new FExtender());
Extension = ToolbarExtender->AddToolBarExtension
(
"Misc",
EExtensionHook::After,
CommandList,
FToolBarExtensionDelegate::CreateRaw(this,
&FSpeckleUnrealEditorModule::AddToolbarExtension)
);
FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor");
LevelEditorModule.GetToolBarExtensibilityManager()->AddExtender(ToolbarExtender);
}
void FSpeckleUnrealEditorModule::ShutdownModule()
{
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
// we call this function before unloading the module.
ToolbarExtender->RemoveExtension(Extension.ToSharedRef());
Extension.Reset();
ToolbarExtender.Reset();
FSpeckleStyle::Shutdown();
}
void FSpeckleUnrealEditorModule::SpeckleButtonListener()
{
if(SpeckleEditorWindow == nullptr)
{
//Start the editor Utility widget
auto EditorUIClass = LoadClass<UEditorUtilityWidget>(nullptr,
TEXT("EditorUtilityWidgetBlueprint'/SpeckleUnreal/EWBP_SpeckleEditorWindow.EWBP_SpeckleEditorWindow_C'"));
IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>(TEXT("MainFrame"));
UWorld* World = GEditor->GetEditorWorldContext().World();
check(World);
auto CreatedUMGWidget = Cast<UEditorUtilityWidget>(CreateWidget(World, EditorUIClass));
// create new slate window
SpeckleEditorWindow = SNew(SWindow)
.AutoCenter(EAutoCenter::None)
.IsInitiallyMaximized(false)
.ClientSize(FVector2D(300,500))
.SizingRule(ESizingRule::UserSized)
.SupportsMaximize(false)
.SupportsMinimize(true)
.CreateTitleBar(true)
.HasCloseButton(true)
.MaxHeight(600)
.MaxWidth(400);
// Use UMG in slate
if(CreatedUMGWidget != nullptr)
{
SpeckleEditorWindow->SetContent(CreatedUMGWidget->TakeWidget());
}
// Add Windows to slate app
FSlateApplication & SlateApp = FSlateApplication::Get();
if (MainFrameModule.GetParentWindow().IsValid())
{
SlateApp.AddWindow(SpeckleEditorWindow.ToSharedRef(), true);
}
//Bind delegate when window is closed
OnSpeckleWindowClosed.BindRaw(this, &FSpeckleUnrealEditorModule::OnEditorWindowClosed);
SpeckleEditorWindow->SetOnWindowClosed(OnSpeckleWindowClosed);
}
else // if editor window already exists
{
SpeckleEditorWindow->BringToFront();
}
}
void FSpeckleUnrealEditorModule::OnEditorWindowClosed(const TSharedRef<SWindow>&)
{
UE_LOG(LogTemp, Warning, TEXT("[SPECKLE LOG] :Speckle editor window closed"));
SpeckleEditorWindow = nullptr;
}
#undef LOCTEXT_NAMESPACE
@@ -0,0 +1,134 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "SpeckleEditorWidget.h"
#include "Blueprint/WidgetTree.h"
#include "Components/ComboBoxString.h"
#include "Components/TextBlock.h"
#include "ObjectEditorUtils.h"
#include "Async/Async.h"
#include "SpeckleUnreal/Public/SpeckleUnrealManager.h"
void USpeckleEditorWidget::NativeConstruct()
{
//bind widgets. To make it work in the editor we search based on the WidgetTree.
StreamName = Cast<UTextBlock>(WidgetTree->FindWidget(TEXT("Stream")));
CommitsCBox = Cast<UComboBoxString>(WidgetTree->FindWidget(TEXT("CommitsBox")));
BranchesCBox = Cast<UComboBoxString>(WidgetTree->FindWidget(TEXT("BranchesBox")));
SelectedCommitText = Cast<UTextBlock>(WidgetTree->FindWidget(TEXT("SelectedCommit")));
SpeckleManagersCBox = Cast<UComboBoxString>(WidgetTree->FindWidget(TEXT("SpeckleManagersBox")));
SpeckleManagersCBox->OnSelectionChanged.AddDynamic(this, &USpeckleEditorWidget::SpeckleManagerSelectionListener);
BranchesCBox->OnSelectionChanged.AddDynamic(this,&USpeckleEditorWidget::BranchesBoxSelectionListener);
//Grab all speckleManagers in the scene
FindAllActors(GetWorld(), SpeckleManagers);
if(SpeckleManagers.Num() > 0)
{
CurrentSpeckleManager = SpeckleManagers[0];
//display speckle managers to combo box
for(auto s : SpeckleManagers)
{
SpeckleManagersCBox->AddOption(s->GetName());
}
SpeckleManagersCBox->SetSelectedOption(CurrentSpeckleManager->GetName());
}
else
{
if(GEngine)
{
GEngine->AddOnScreenDebugMessage(1, 10.0f, FColor::Red,
"[SPECKLE LOG]: No available speckle managers in the scene. Place and reopen the window");
}
}
//Bind event handlers to fill in the received items.
if(CurrentSpeckleManager != nullptr)
{
CurrentSpeckleManager->OnBranchesProcessed.AddDynamic(this, &USpeckleEditorWidget::SpeckleBranchesReceived);
CurrentSpeckleManager->OnCommitsProcessed.AddDynamic(this, &USpeckleEditorWidget::SpeckleCommitsReceived);
}
InitUI();
}
void USpeckleEditorWidget::InitUI()
{
if(CurrentSpeckleManager)
{
StreamName->SetText(FText::FromString("Stream ID: " + CurrentSpeckleManager->StreamID));
}
}
void USpeckleEditorWidget::ImportSpeckleObject(UActorComponent* SpeckleActorComponent)
{
if(SpeckleActorComponent != nullptr)
{
const auto SpeckleReceiver = Cast<IISpeckleReceiver>(SpeckleActorComponent);
if(SpeckleReceiver)
{
const auto CurrentIdx = CommitsCBox->FindOptionIndex(CommitsCBox->GetSelectedOption());
SpeckleReceiver->ImportSpeckleObject(CurrentIdx);
}
}
}
void USpeckleEditorWidget::FetchSpeckleCommits(UActorComponent* SpeckleActorComponent)
{
if(SpeckleActorComponent != nullptr)
{
const auto SpeckleReceiver = Cast<IISpeckleReceiver>(SpeckleActorComponent);
if(SpeckleReceiver)
{
SpeckleReceiver->FetchListOfCommits(SelectedBranch);
}
}
}
void USpeckleEditorWidget::SpeckleCommitsReceived(const TArray<FSpeckleCommit>& CommitsList)
{
CommitsCBox->ClearOptions();
for (auto C : CommitsList)
{
CommitsCBox->AddOption(C.Message + " [" + C.AuthorName + "]");
}
}
void USpeckleEditorWidget::FetchSpeckleBranches(UActorComponent* SpeckleActorComponent)
{
if(SpeckleActorComponent != nullptr)
{
const auto SpeckleReceiver = Cast<IISpeckleReceiver>(SpeckleActorComponent);
if(SpeckleReceiver)
{
SpeckleReceiver->FetchListOfBranches();
}
}
}
void USpeckleEditorWidget::SpeckleBranchesReceived(const TArray<FSpeckleBranch>& BranchesList)
{
BranchesCBox->ClearOptions();
for(auto b : BranchesList)
{
BranchesCBox->AddOption(b.Name);
}
if(BranchesCBox->GetOptionCount() > 0)
{
BranchesCBox->SetSelectedOption("main");
SelectedBranch = TEXT("main");
}
}
void USpeckleEditorWidget::SpeckleManagerSelectionListener(FString SelectedItem, ESelectInfo::Type SelectionType)
{
const int32 Idx = SpeckleManagersCBox->FindOptionIndex(SelectedItem);
CurrentSpeckleManager = SpeckleManagers[Idx];
InitUI();
}
@@ -0,0 +1,64 @@
#include "SpeckleStyle.h"
#include "Slate/SlateGameResources.h"
#include "FSpeckleUnrealEditorModule.h"
#include "Styling/SlateStyleRegistry.h"
#include "Interfaces/IPluginManager.h"
#define IMAGE_BRUSH(RelativePath,...) FSlateImageBrush(FSpeckleStyle::InContent(RelativePath,".png"), __VA_ARGS__)
FString FSpeckleStyle::InContent(const FString& RelativePath, const ANSICHAR* Extension)
{
static FString ContentDir = IPluginManager::Get().FindPlugin(TEXT("SpeckleUnreal"))->GetContentDir();
return (ContentDir / RelativePath) + Extension;
}
TSharedPtr<FSlateStyleSet>FSpeckleStyle::SpeckleStyleSet = nullptr;
TSharedPtr<ISlateStyle> FSpeckleStyle::Get()
{
return SpeckleStyleSet;
}
void FSpeckleStyle::Initialize()
{
// Only register once
if (SpeckleStyleSet.IsValid())
{
return;
}
SpeckleStyleSet = MakeShareable<FSlateStyleSet>(new FSlateStyleSet(GetStyleSetName()));
// Const icon sizes
const FVector2D Icon16x16(16.0f, 16.0f);
const FVector2D Icon20x20(20.0f, 20.0f);
const FVector2D Icon24x24(24.0f, 24.0f);
const FVector2D Icon40x40(40.0f, 40.0f);
const FVector2D Icon48x48(48.0f, 48.0f);
//set menu/toolbar icon
SpeckleStyleSet->Set("Speckle.MenuIcon", new IMAGE_BRUSH(TEXT("speckle_icon_64_64"), Icon40x40));
FSlateStyleRegistry::RegisterSlateStyle(*SpeckleStyleSet.Get());
}
void FSpeckleStyle::Shutdown()
{
if (SpeckleStyleSet.IsValid())
{
FSlateStyleRegistry::UnRegisterSlateStyle(*SpeckleStyleSet.Get());
ensure(SpeckleStyleSet.IsUnique());
SpeckleStyleSet.Reset();
}
}
FName FSpeckleStyle::GetStyleSetName()
{
static FName StyleSetName(TEXT("SpeckleStyle"));
return StyleSetName;
}
#undef IMAGE_BRUSH
@@ -0,0 +1,26 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Framework/Commands/Commands.h"
#include "EditorStyleSet.h"
/**
*
*/
class FSpeckleEditorCommands : public TCommands<FSpeckleEditorCommands>
{
public:
FSpeckleEditorCommands() : TCommands<FSpeckleEditorCommands>
(
FName(TEXT("Speckle Commands")),
FText::FromString("Speckle Editor Commands"),
NAME_None,
FEditorStyle::GetStyleSetName()
){};
virtual void RegisterCommands() override;
TSharedPtr<FUICommandInfo> SpeckleToolBarBtn;
};
@@ -0,0 +1,51 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Modules/ModuleInterface.h"
#include "LevelEditor.h"
#include "SlateBasics.h"
#include "Interfaces/IMainFrameModule.h"
#include "FSpeckleEditorCommands.h"
#include "SpeckleStyle.h"
class FSpeckleUnrealEditorModule : public IModuleInterface
{
virtual void StartupModule() override;
virtual void ShutdownModule() override;
// static inline FSpeckleUnrealEditorModule& Get() {
// return FModuleManager::LoadModuleChecked<FSpeckleUnrealEditorModule>("SpeckleUnrealEditor");
// }
//
// static inline bool IsAvailable() {
// return FModuleManager::Get().IsModuleLoaded("SpeckleUnrealEditor");
// }
TSharedPtr<FExtender> ToolbarExtender;
TSharedPtr<const FExtensionBase> Extension;
TSharedPtr<SWindow> SpeckleEditorWindow;
FOnWindowClosed OnSpeckleWindowClosed;
void SpeckleButtonListener();
UFUNCTION()
void OnEditorWindowClosed(const TSharedRef<SWindow>&);
void AddToolbarExtension(FToolBarBuilder &builder)
{
//FSlateIcon IconBrush = FSlateIcon(FEditorStyle::GetStyleSetName(), "LevelEditor.ViewOptions", "LevelEditor.ViewOptions.Small");
FSlateIcon IconBrush = FSlateIcon(FSpeckleStyle::GetStyleSetName(), "Speckle.MenuIcon");
builder.AddToolBarButton
(
FSpeckleEditorCommands::Get().SpeckleToolBarBtn,
NAME_None,
FText::FromString("Speckle"),
FText::FromString("Click to open Speckle Window"),
IconBrush,
NAME_None
);
};
};
@@ -0,0 +1,95 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "EditorUtilityWidget.h"
#include "EngineUtils.h"
#include "SpeckleUnreal/Public/ISpeckleReceiver.h"
#include "SpeckleEditorWidget.generated.h"
class ASpeckleUnrealManager;
UCLASS()
class USpeckleEditorWidget : public UEditorUtilityWidget
{
GENERATED_BODY()
protected:
virtual void NativeConstruct() override;
public:
// BUTTONS
UPROPERTY()
class UButton* ImportObjectButton;
UPROPERTY()
UButton* FetchButton;
//TEXT BLOCKS
UPROPERTY()
class UTextBlock* StreamName;
UPROPERTY()
class UTextBlock* SelectedCommitText;
//COMBO BOXES
UPROPERTY()
class UComboBoxString* BranchesCBox;
UPROPERTY()
class UComboBoxString* CommitsCBox;
UPROPERTY()
class UComboBoxString* SpeckleManagersCBox;
//FUNCTIONS
void InitUI();
UFUNCTION(BlueprintCallable)
void ImportSpeckleObject(UActorComponent* SpeckleReceiver);
UFUNCTION(BlueprintCallable)
void FetchSpeckleCommits(UActorComponent* SpeckleReceiver);
UFUNCTION(BlueprintCallable)
void SpeckleCommitsReceived(const TArray<FSpeckleCommit>& CommitsList);
UFUNCTION(BlueprintCallable)
void FetchSpeckleBranches(UActorComponent* SpeckleReceiver);
UFUNCTION(BlueprintCallable)
void SpeckleBranchesReceived(const TArray<FSpeckleBranch>& BranchesList);
UFUNCTION(BlueprintCallable)
void SpeckleManagerSelectionListener(FString SelectedItem, ESelectInfo::Type SelectionType);
FString SelectedBranch;
UFUNCTION(BlueprintCallable)
void BranchesBoxSelectionListener(FString SelectedItem, ESelectInfo::Type SelectionType)
{
SelectedBranch = SelectedItem;
}
template<typename T>
UFUNCTION(BlueprintCallable)
void FindAllActors(UWorld* World, TArray<T*>& Out)
{
for (TActorIterator<T> It(World); It; ++It)
{
Out.Add(*It);
}
}
UPROPERTY(EditAnywhere)
TSubclassOf<ASpeckleUnrealManager> SpeckleManagerClass;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
ASpeckleUnrealManager* CurrentSpeckleManager;
UPROPERTY()
TArray<ASpeckleUnrealManager*> SpeckleManagers;
};
@@ -0,0 +1,17 @@
#pragma once
#include "SlateBasics.h"
#include "SlateExtras.h"
class FSpeckleStyle
{
public:
static void Initialize();
static void Shutdown();
static TSharedPtr< class ISlateStyle > Get();
static FName GetStyleSetName();
private:
static FString InContent(const FString& RelativePath, const ANSICHAR* Extension);
private:
static TSharedPtr<class FSlateStyleSet> SpeckleStyleSet;
};
@@ -0,0 +1,75 @@
using UnrealBuildTool;
public class SpeckleUnrealEditor : ModuleRules
{
public SpeckleUnrealEditor(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicIncludePaths.AddRange(
new string[] {
// ... add public include paths required here ...
}
);
PrivateIncludePaths.AddRange(
new string[] {
// ... add other private include paths required here ...
}
);
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
"Http",
"Json",
"JsonUtilities",
"ProceduralMeshComponent",
"InputCore",
"Slate",
"SlateCore",
"MainFrame",
"EditorStyle"
}
);
if (Target.bBuildEditor)
{
PublicDependencyModuleNames.AddRange(new string[]
{
"UnrealEd",
});
}
if (Target.Type == TargetType.Editor) // Is UBT building for Editor ?
{
PrivateDependencyModuleNames.Add("SpeckleUnreal");
}
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"Blutility",
"Projects",
"UMG",
"UMGEditor"
// ... add private dependencies that you statically link with here ...
}
);
DynamicallyLoadedModuleNames.AddRange(
new string[]
{
// ... add any modules that your module loads dynamically here ...
}
);
}
}
@@ -19,6 +19,11 @@
"Name": "SpeckleUnreal",
"Type": "Runtime",
"LoadingPhase": "Default"
},
{
"Name": "SpeckleUnrealEditor",
"Type": "Editor",
"LoadingPhase": "PostEngineInit"
}
],
"Plugins": [
+32 -32
View File
@@ -7,9 +7,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Engine", "Engine", "{94A6C6
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Games", "Games", "{8E2F6A87-1826-34F4-940C-CC23A48F9FE4}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UE4", "Intermediate\ProjectFiles\UE4.vcxproj", "{46257A04-9815-4F4E-9B64-E2C866B2C171}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UE4", "Intermediate\ProjectFiles\UE4.vcxproj", "{CE2AC9DC-3204-4D56-954E-856D5121C6CE}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SpeckleUnrealProject", "Intermediate\ProjectFiles\SpeckleUnrealProject.vcxproj", "{A55CB96C-60E7-4AF7-9654-C5FC4B602DAE}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SpeckleUnrealProject", "Intermediate\ProjectFiles\SpeckleUnrealProject.vcxproj", "{9DBAC0A8-8945-4AB3-AFB6-639C4EC5B2E6}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Visualizers", "Visualizers", "{1CCEC849-CC72-4C59-8C36-2F7C38706D4C}"
ProjectSection(SolutionItems) = preProject
@@ -30,40 +30,40 @@ Global
Shipping|Win64 = Shipping|Win64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{46257A04-9815-4F4E-9B64-E2C866B2C171}.DebugGame Editor|Win32.ActiveCfg = BuiltWithUnrealBuildTool|Win32
{46257A04-9815-4F4E-9B64-E2C866B2C171}.DebugGame Editor|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win32
{46257A04-9815-4F4E-9B64-E2C866B2C171}.DebugGame|Win32.ActiveCfg = BuiltWithUnrealBuildTool|Win32
{46257A04-9815-4F4E-9B64-E2C866B2C171}.DebugGame|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win32
{46257A04-9815-4F4E-9B64-E2C866B2C171}.Development Editor|Win32.ActiveCfg = BuiltWithUnrealBuildTool|Win32
{46257A04-9815-4F4E-9B64-E2C866B2C171}.Development Editor|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win32
{46257A04-9815-4F4E-9B64-E2C866B2C171}.Development|Win32.ActiveCfg = BuiltWithUnrealBuildTool|Win32
{46257A04-9815-4F4E-9B64-E2C866B2C171}.Development|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win32
{46257A04-9815-4F4E-9B64-E2C866B2C171}.Shipping|Win32.ActiveCfg = BuiltWithUnrealBuildTool|Win32
{46257A04-9815-4F4E-9B64-E2C866B2C171}.Shipping|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win32
{A55CB96C-60E7-4AF7-9654-C5FC4B602DAE}.DebugGame Editor|Win32.ActiveCfg = Invalid|Win32
{A55CB96C-60E7-4AF7-9654-C5FC4B602DAE}.DebugGame Editor|Win64.ActiveCfg = DebugGame_Editor|x64
{A55CB96C-60E7-4AF7-9654-C5FC4B602DAE}.DebugGame Editor|Win64.Build.0 = DebugGame_Editor|x64
{A55CB96C-60E7-4AF7-9654-C5FC4B602DAE}.DebugGame|Win32.ActiveCfg = DebugGame|Win32
{A55CB96C-60E7-4AF7-9654-C5FC4B602DAE}.DebugGame|Win32.Build.0 = DebugGame|Win32
{A55CB96C-60E7-4AF7-9654-C5FC4B602DAE}.DebugGame|Win64.ActiveCfg = DebugGame|x64
{A55CB96C-60E7-4AF7-9654-C5FC4B602DAE}.DebugGame|Win64.Build.0 = DebugGame|x64
{A55CB96C-60E7-4AF7-9654-C5FC4B602DAE}.Development Editor|Win32.ActiveCfg = Invalid|Win32
{A55CB96C-60E7-4AF7-9654-C5FC4B602DAE}.Development Editor|Win64.ActiveCfg = Development_Editor|x64
{A55CB96C-60E7-4AF7-9654-C5FC4B602DAE}.Development Editor|Win64.Build.0 = Development_Editor|x64
{A55CB96C-60E7-4AF7-9654-C5FC4B602DAE}.Development|Win32.ActiveCfg = Development|Win32
{A55CB96C-60E7-4AF7-9654-C5FC4B602DAE}.Development|Win32.Build.0 = Development|Win32
{A55CB96C-60E7-4AF7-9654-C5FC4B602DAE}.Development|Win64.ActiveCfg = Development|x64
{A55CB96C-60E7-4AF7-9654-C5FC4B602DAE}.Development|Win64.Build.0 = Development|x64
{A55CB96C-60E7-4AF7-9654-C5FC4B602DAE}.Shipping|Win32.ActiveCfg = Shipping|Win32
{A55CB96C-60E7-4AF7-9654-C5FC4B602DAE}.Shipping|Win32.Build.0 = Shipping|Win32
{A55CB96C-60E7-4AF7-9654-C5FC4B602DAE}.Shipping|Win64.ActiveCfg = Shipping|x64
{A55CB96C-60E7-4AF7-9654-C5FC4B602DAE}.Shipping|Win64.Build.0 = Shipping|x64
{CE2AC9DC-3204-4D56-954E-856D5121C6CE}.DebugGame Editor|Win32.ActiveCfg = BuiltWithUnrealBuildTool|Win32
{CE2AC9DC-3204-4D56-954E-856D5121C6CE}.DebugGame Editor|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win32
{CE2AC9DC-3204-4D56-954E-856D5121C6CE}.DebugGame|Win32.ActiveCfg = BuiltWithUnrealBuildTool|Win32
{CE2AC9DC-3204-4D56-954E-856D5121C6CE}.DebugGame|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win32
{CE2AC9DC-3204-4D56-954E-856D5121C6CE}.Development Editor|Win32.ActiveCfg = BuiltWithUnrealBuildTool|Win32
{CE2AC9DC-3204-4D56-954E-856D5121C6CE}.Development Editor|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win32
{CE2AC9DC-3204-4D56-954E-856D5121C6CE}.Development|Win32.ActiveCfg = BuiltWithUnrealBuildTool|Win32
{CE2AC9DC-3204-4D56-954E-856D5121C6CE}.Development|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win32
{CE2AC9DC-3204-4D56-954E-856D5121C6CE}.Shipping|Win32.ActiveCfg = BuiltWithUnrealBuildTool|Win32
{CE2AC9DC-3204-4D56-954E-856D5121C6CE}.Shipping|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win32
{9DBAC0A8-8945-4AB3-AFB6-639C4EC5B2E6}.DebugGame Editor|Win32.ActiveCfg = Invalid|Win32
{9DBAC0A8-8945-4AB3-AFB6-639C4EC5B2E6}.DebugGame Editor|Win64.ActiveCfg = DebugGame_Editor|x64
{9DBAC0A8-8945-4AB3-AFB6-639C4EC5B2E6}.DebugGame Editor|Win64.Build.0 = DebugGame_Editor|x64
{9DBAC0A8-8945-4AB3-AFB6-639C4EC5B2E6}.DebugGame|Win32.ActiveCfg = DebugGame|Win32
{9DBAC0A8-8945-4AB3-AFB6-639C4EC5B2E6}.DebugGame|Win32.Build.0 = DebugGame|Win32
{9DBAC0A8-8945-4AB3-AFB6-639C4EC5B2E6}.DebugGame|Win64.ActiveCfg = DebugGame|x64
{9DBAC0A8-8945-4AB3-AFB6-639C4EC5B2E6}.DebugGame|Win64.Build.0 = DebugGame|x64
{9DBAC0A8-8945-4AB3-AFB6-639C4EC5B2E6}.Development Editor|Win32.ActiveCfg = Invalid|Win32
{9DBAC0A8-8945-4AB3-AFB6-639C4EC5B2E6}.Development Editor|Win64.ActiveCfg = Development_Editor|x64
{9DBAC0A8-8945-4AB3-AFB6-639C4EC5B2E6}.Development Editor|Win64.Build.0 = Development_Editor|x64
{9DBAC0A8-8945-4AB3-AFB6-639C4EC5B2E6}.Development|Win32.ActiveCfg = Development|Win32
{9DBAC0A8-8945-4AB3-AFB6-639C4EC5B2E6}.Development|Win32.Build.0 = Development|Win32
{9DBAC0A8-8945-4AB3-AFB6-639C4EC5B2E6}.Development|Win64.ActiveCfg = Development|x64
{9DBAC0A8-8945-4AB3-AFB6-639C4EC5B2E6}.Development|Win64.Build.0 = Development|x64
{9DBAC0A8-8945-4AB3-AFB6-639C4EC5B2E6}.Shipping|Win32.ActiveCfg = Shipping|Win32
{9DBAC0A8-8945-4AB3-AFB6-639C4EC5B2E6}.Shipping|Win32.Build.0 = Shipping|Win32
{9DBAC0A8-8945-4AB3-AFB6-639C4EC5B2E6}.Shipping|Win64.ActiveCfg = Shipping|x64
{9DBAC0A8-8945-4AB3-AFB6-639C4EC5B2E6}.Shipping|Win64.Build.0 = Shipping|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{46257A04-9815-4F4E-9B64-E2C866B2C171} = {94A6C6F3-99B3-346E-9557-ABF9D4064DBD}
{A55CB96C-60E7-4AF7-9654-C5FC4B602DAE} = {8E2F6A87-1826-34F4-940C-CC23A48F9FE4}
{CE2AC9DC-3204-4D56-954E-856D5121C6CE} = {94A6C6F3-99B3-346E-9557-ABF9D4064DBD}
{9DBAC0A8-8945-4AB3-AFB6-639C4EC5B2E6} = {8E2F6A87-1826-34F4-940C-CC23A48F9FE4}
EndGlobalSection
EndGlobal