You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Dataflow : Support for FProperty on the FNode
#rb none #fyi Ryan.Kautzman, Benn.Gallagher, Gustav.Melich, Cedric.Caillaud #preflight 62a18ec1f73a01bd9811dad8 [CL 20572155 by Brice Criswell in ue5-main branch]
This commit is contained in:
+75
-20
@@ -20,6 +20,7 @@
|
||||
#include "PropertyEditorModule.h"
|
||||
#include "Styling/SlateStyleRegistry.h"
|
||||
#include "Framework/Commands/GenericCommands.h"
|
||||
#include "IStructureDetailsView.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "GeometryCollectionEditorToolkit"
|
||||
|
||||
@@ -27,7 +28,8 @@
|
||||
|
||||
|
||||
const FName FGeometryCollectionEditorToolkit::GraphCanvasTabId(TEXT("GeometryCollectionEditor_GraphCanvas"));
|
||||
const FName FGeometryCollectionEditorToolkit::PropertiesTabId(TEXT("GeometryCollectionEditor_Properties"));
|
||||
const FName FGeometryCollectionEditorToolkit::AssetDetailsTabId(TEXT("GeometryCollectionEditor_AssetDetails"));
|
||||
const FName FGeometryCollectionEditorToolkit::NodeDetailsTabId(TEXT("GeometryCollectionEditor_NodeDetails"));
|
||||
|
||||
void FGeometryCollectionEditorToolkit::InitGeometryCollectionAssetEditor(const EToolkitMode::Type Mode, const TSharedPtr<IToolkitHost>& InitToolkitHost, UObject* ObjectToEdit)
|
||||
{
|
||||
@@ -44,10 +46,11 @@ void FGeometryCollectionEditorToolkit::InitGeometryCollectionAssetEditor(const E
|
||||
Dataflow = GeometryCollection->Dataflow;
|
||||
GeometryCollection->Dataflow->Schema = UDataflowSchema::StaticClass();
|
||||
|
||||
PropertiesEditor = CreatePropertiesEditorWidget(ObjectToEdit);
|
||||
GraphEditor = CreateGraphEditorWidget(Dataflow, PropertiesEditor);
|
||||
NodeDetailsEditor = CreateNodeDetailsEditorWidget(ObjectToEdit);
|
||||
AssetDetailsEditor = CreateAssetDetailsEditorWidget(GeometryCollection);
|
||||
GraphEditor = CreateGraphEditorWidget(Dataflow, NodeDetailsEditor);
|
||||
|
||||
const TSharedRef<FTabManager::FLayout> StandaloneDefaultLayout = FTabManager::NewLayout("GeometryCollectionDataflowEditor_Layout")
|
||||
const TSharedRef<FTabManager::FLayout> StandaloneDefaultLayout = FTabManager::NewLayout("GeometryCollectionDataflowEditor_Layout.V1")
|
||||
->AddArea
|
||||
(
|
||||
FTabManager::NewPrimaryArea()->SetOrientation(Orient_Vertical)
|
||||
@@ -72,7 +75,7 @@ void FGeometryCollectionEditorToolkit::InitGeometryCollectionAssetEditor(const E
|
||||
(
|
||||
FTabManager::NewStack()
|
||||
->SetSizeCoefficient(0.7f)
|
||||
->AddTab(PropertiesTabId, ETabState::OpenedTab)
|
||||
->AddTab(AssetDetailsTabId, ETabState::OpenedTab)
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -85,13 +88,13 @@ void FGeometryCollectionEditorToolkit::InitGeometryCollectionAssetEditor(const E
|
||||
}
|
||||
}
|
||||
|
||||
TSharedRef<SGraphEditor> FGeometryCollectionEditorToolkit::CreateGraphEditorWidget(UDataflow* DataflowToEdit, TSharedPtr<IDetailsView> InPropertiesEditor)
|
||||
TSharedRef<SGraphEditor> FGeometryCollectionEditorToolkit::CreateGraphEditorWidget(UDataflow* DataflowToEdit, TSharedPtr<IStructureDetailsView> InNodeDetailsEditor)
|
||||
{
|
||||
ensure(DataflowToEdit);
|
||||
using namespace Dataflow;
|
||||
IDataflowEditorPlugin& DataflowEditorModule = FModuleManager::LoadModuleChecked<IDataflowEditorPlugin>(TEXT("DataflowEditor"));
|
||||
|
||||
FDataflowEditorCommands::FGraphEvaluationCallback Evaluate = [&](Dataflow::FNode* Node, Dataflow::FConnection* Out)
|
||||
FDataflowEditorCommands::FGraphEvaluationCallback Evaluate = [&](FDataflowNode* Node, Dataflow::FConnection* Out)
|
||||
{
|
||||
float EvalTime = FGameTime::GetTimeSinceAppStart().GetRealTimeSeconds();
|
||||
return Node->Evaluate(FEngineContext(GeometryCollection, Dataflow, EvalTime, FName("UGeometryCollection")), Out);
|
||||
@@ -99,21 +102,56 @@ TSharedRef<SGraphEditor> FGeometryCollectionEditorToolkit::CreateGraphEditorWidg
|
||||
|
||||
return SNew(SDataflowGraphEditor, GeometryCollection)
|
||||
.GraphToEdit(DataflowToEdit)
|
||||
.DetailsView(InPropertiesEditor)
|
||||
.DetailsView(InNodeDetailsEditor)
|
||||
.EvaluateGraph(Evaluate);
|
||||
}
|
||||
|
||||
TSharedPtr<IDetailsView> FGeometryCollectionEditorToolkit::CreatePropertiesEditorWidget(UObject* ObjectToEdit)
|
||||
TSharedPtr<IStructureDetailsView> FGeometryCollectionEditorToolkit::CreateNodeDetailsEditorWidget(UObject* ObjectToEdit)
|
||||
{
|
||||
ensure(ObjectToEdit);
|
||||
FPropertyEditorModule& PropertyEditorModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>(TEXT("PropertyEditor"));
|
||||
|
||||
FDetailsViewArgs DetailsViewArgs;
|
||||
DetailsViewArgs.bAllowSearch = true;
|
||||
DetailsViewArgs.bLockable = false;
|
||||
DetailsViewArgs.bUpdatesFromSelection = false;
|
||||
DetailsViewArgs.NameAreaSettings = FDetailsViewArgs::HideNameArea;
|
||||
DetailsViewArgs.NotifyHook = this;
|
||||
{
|
||||
DetailsViewArgs.bAllowSearch = false;
|
||||
DetailsViewArgs.bHideSelectionTip = true;
|
||||
DetailsViewArgs.bLockable = false;
|
||||
DetailsViewArgs.bSearchInitialKeyFocus = true;
|
||||
DetailsViewArgs.bUpdatesFromSelection = false;
|
||||
DetailsViewArgs.NotifyHook = nullptr;
|
||||
DetailsViewArgs.bShowOptions = true;
|
||||
DetailsViewArgs.bShowModifiedPropertiesOption = false;
|
||||
DetailsViewArgs.bShowScrollBar = false;
|
||||
}
|
||||
|
||||
FStructureDetailsViewArgs StructureViewArgs;
|
||||
{
|
||||
StructureViewArgs.bShowObjects = true;
|
||||
StructureViewArgs.bShowAssets = true;
|
||||
StructureViewArgs.bShowClasses = true;
|
||||
StructureViewArgs.bShowInterfaces = true;
|
||||
}
|
||||
TSharedPtr<IStructureDetailsView> DetailsView = PropertyEditorModule.CreateStructureDetailView(DetailsViewArgs, StructureViewArgs, nullptr);
|
||||
DetailsView->GetDetailsView()->SetObject(ObjectToEdit);
|
||||
|
||||
return DetailsView;
|
||||
|
||||
}
|
||||
|
||||
|
||||
TSharedPtr<IDetailsView> FGeometryCollectionEditorToolkit::CreateAssetDetailsEditorWidget(UObject* ObjectToEdit)
|
||||
{
|
||||
ensure(ObjectToEdit);
|
||||
FPropertyEditorModule& PropertyEditorModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>(TEXT("PropertyEditor"));
|
||||
|
||||
FDetailsViewArgs DetailsViewArgs;
|
||||
{
|
||||
DetailsViewArgs.bAllowSearch = true;
|
||||
DetailsViewArgs.bLockable = false;
|
||||
DetailsViewArgs.bUpdatesFromSelection = false;
|
||||
DetailsViewArgs.NameAreaSettings = FDetailsViewArgs::HideNameArea;
|
||||
DetailsViewArgs.NotifyHook = this;
|
||||
}
|
||||
|
||||
TSharedPtr<IDetailsView> DetailsView = PropertyEditorModule.CreateDetailView(DetailsViewArgs);
|
||||
DetailsView->SetObject(ObjectToEdit);
|
||||
@@ -122,6 +160,7 @@ TSharedPtr<IDetailsView> FGeometryCollectionEditorToolkit::CreatePropertiesEdito
|
||||
}
|
||||
|
||||
|
||||
|
||||
TSharedRef<SDockTab> FGeometryCollectionEditorToolkit::SpawnTab_GraphCanvas(const FSpawnTabArgs& Args)
|
||||
{
|
||||
check(Args.GetTabId() == GraphCanvasTabId);
|
||||
@@ -135,14 +174,25 @@ TSharedRef<SDockTab> FGeometryCollectionEditorToolkit::SpawnTab_GraphCanvas(cons
|
||||
return SpawnedTab;
|
||||
}
|
||||
|
||||
TSharedRef<SDockTab> FGeometryCollectionEditorToolkit::SpawnTab_Properties(const FSpawnTabArgs& Args)
|
||||
TSharedRef<SDockTab> FGeometryCollectionEditorToolkit::SpawnTab_AssetDetails(const FSpawnTabArgs& Args)
|
||||
{
|
||||
check(Args.GetTabId() == PropertiesTabId);
|
||||
check(Args.GetTabId() == AssetDetailsTabId);
|
||||
|
||||
return SNew(SDockTab)
|
||||
.Label(LOCTEXT("GeometryCollectionEditor_Properties_TabTitle", "Details"))
|
||||
.Label(LOCTEXT("GeometryCollectionEditor_AssetDetails_TabTitle", "Asset Details"))
|
||||
[
|
||||
PropertiesEditor.ToSharedRef()
|
||||
AssetDetailsEditor.ToSharedRef()
|
||||
];
|
||||
}
|
||||
|
||||
TSharedRef<SDockTab> FGeometryCollectionEditorToolkit::SpawnTab_NodeDetails(const FSpawnTabArgs& Args)
|
||||
{
|
||||
check(Args.GetTabId() == NodeDetailsTabId);
|
||||
|
||||
return SNew(SDockTab)
|
||||
.Label(LOCTEXT("GeometryCollectionEditor_NodeDetails_TabTitle", "Node Details"))
|
||||
[
|
||||
NodeDetailsEditor->GetWidget()->AsShared()
|
||||
];
|
||||
}
|
||||
|
||||
@@ -156,8 +206,13 @@ void FGeometryCollectionEditorToolkit::RegisterTabSpawners(const TSharedRef<FTab
|
||||
.SetGroup(WorkspaceMenuCategoryRef)
|
||||
.SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "GraphEditor.EventGraph_16x"));
|
||||
|
||||
InTabManager->RegisterTabSpawner(PropertiesTabId, FOnSpawnTab::CreateSP(this, &FGeometryCollectionEditorToolkit::SpawnTab_Properties))
|
||||
.SetDisplayName(LOCTEXT("PropertiesTab", "Details"))
|
||||
InTabManager->RegisterTabSpawner(AssetDetailsTabId, FOnSpawnTab::CreateSP(this, &FGeometryCollectionEditorToolkit::SpawnTab_AssetDetails))
|
||||
.SetDisplayName(LOCTEXT("AssetDetailsTab", "Asset Details"))
|
||||
.SetGroup(WorkspaceMenuCategoryRef)
|
||||
.SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "LevelEditor.Tabs.Details"));
|
||||
|
||||
InTabManager->RegisterTabSpawner(NodeDetailsTabId, FOnSpawnTab::CreateSP(this, &FGeometryCollectionEditorToolkit::SpawnTab_NodeDetails))
|
||||
.SetDisplayName(LOCTEXT("NodeDetailsTab", "Node Details"))
|
||||
.SetGroup(WorkspaceMenuCategoryRef)
|
||||
.SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "LevelEditor.Tabs.Details"));
|
||||
|
||||
|
||||
+15
-7
@@ -34,7 +34,8 @@ public:
|
||||
// Tab spawners
|
||||
virtual void RegisterTabSpawners(const TSharedRef<FTabManager>& TabManager) override;
|
||||
TSharedRef<SDockTab> SpawnTab_GraphCanvas(const FSpawnTabArgs& Args);
|
||||
TSharedRef<SDockTab> SpawnTab_Properties(const FSpawnTabArgs& Args);
|
||||
TSharedRef<SDockTab> SpawnTab_AssetDetails(const FSpawnTabArgs& Args);
|
||||
TSharedRef<SDockTab> SpawnTab_NodeDetails(const FSpawnTabArgs& Args);
|
||||
|
||||
UDataflow* GetDataflow() { return Dataflow; }
|
||||
const UDataflow* GetDataflow() const { return Dataflow; }
|
||||
@@ -42,8 +43,11 @@ public:
|
||||
UGeometryCollection* GetGeometryCollection() { return GeometryCollection; }
|
||||
const UGeometryCollection* GetGeometryCollection() const { return GeometryCollection; }
|
||||
|
||||
TSharedPtr<IDetailsView> GetPropertiesEditor() { return PropertiesEditor; }
|
||||
const TSharedPtr<IDetailsView> GetPropertiesEditor() const { return PropertiesEditor; }
|
||||
TSharedPtr<IDetailsView> GetAssetDetailsEditor() { return AssetDetailsEditor; }
|
||||
const TSharedPtr<IDetailsView> GetAssetDetailsEditor() const { return AssetDetailsEditor; }
|
||||
|
||||
TSharedPtr<IStructureDetailsView> GetNodeDetailsEditor() { return NodeDetailsEditor; }
|
||||
const TSharedPtr<IStructureDetailsView> GetNodeDetailsEditor() const { return NodeDetailsEditor; }
|
||||
|
||||
TSharedPtr<SGraphEditor> GetGraphEditor() { return GraphEditor; }
|
||||
const TSharedPtr<SGraphEditor> GetGraphEditor() const { return GraphEditor; }
|
||||
@@ -51,11 +55,15 @@ public:
|
||||
private:
|
||||
static const FName GraphCanvasTabId;
|
||||
TSharedPtr<SGraphEditor> GraphEditor;
|
||||
TSharedRef<SGraphEditor> CreateGraphEditorWidget(UDataflow* ObjectToEdit, TSharedPtr<IDetailsView> PropertiesEditor);
|
||||
TSharedRef<SGraphEditor> CreateGraphEditorWidget(UDataflow* ObjectToEdit, TSharedPtr<IStructureDetailsView> PropertiesEditor);
|
||||
|
||||
static const FName PropertiesTabId;
|
||||
TSharedPtr<IDetailsView> PropertiesEditor;
|
||||
TSharedPtr<IDetailsView> CreatePropertiesEditorWidget(UObject* ObjectToEdit);
|
||||
static const FName AssetDetailsTabId;
|
||||
TSharedPtr<IDetailsView> AssetDetailsEditor;
|
||||
TSharedPtr<IDetailsView> CreateAssetDetailsEditorWidget(UObject* ObjectToEdit);
|
||||
|
||||
static const FName NodeDetailsTabId;
|
||||
TSharedPtr<IStructureDetailsView> NodeDetailsEditor;
|
||||
TSharedPtr<IStructureDetailsView> CreateNodeDetailsEditorWidget(UObject* ObjectToEdit);
|
||||
|
||||
UDataflow* Dataflow = nullptr;
|
||||
UGeometryCollection* GeometryCollection = nullptr;
|
||||
|
||||
+112
-110
@@ -16,126 +16,128 @@ namespace Dataflow
|
||||
{
|
||||
void GeometryCollectionEngineAssetNodes()
|
||||
{
|
||||
DATAFLOW_NODE_REGISTER_CREATION_FACTORY(GetCollectionAssetNode);
|
||||
DATAFLOW_NODE_REGISTER_CREATION_FACTORY(ExampleCollectionEditNode);
|
||||
DATAFLOW_NODE_REGISTER_CREATION_FACTORY(SetCollectionAssetNode);
|
||||
DATAFLOW_NODE_REGISTER_CREATION_FACTORY(ResetGeometryCollection);
|
||||
DATAFLOW_NODE_REGISTER_CREATION_FACTORY(FGetCollectionAssetDataflowNode);
|
||||
DATAFLOW_NODE_REGISTER_CREATION_FACTORY(FExampleCollectionEditDataflowNode);
|
||||
DATAFLOW_NODE_REGISTER_CREATION_FACTORY(FSetCollectionAssetDataflowNode);
|
||||
DATAFLOW_NODE_REGISTER_CREATION_FACTORY(FResetGeometryCollectionDataflowNode);
|
||||
}
|
||||
}
|
||||
|
||||
void GetCollectionAssetNode::Evaluate(const FContext& Context, FConnection* Out) const
|
||||
void FGetCollectionAssetDataflowNode::Evaluate(const Dataflow::FContext& Context, Dataflow::FConnection* Out) const
|
||||
{
|
||||
if (Output.Get() == Out)
|
||||
{
|
||||
if (Output.Get() == Out)
|
||||
if (const Dataflow::FEngineContext* EngineContext = Context.AsType<Dataflow::FEngineContext>(FName("UGeometryCollection")))
|
||||
{
|
||||
if (const FEngineContext* EngineContext = Context.AsType<FEngineContext>(FName("UGeometryCollection")))
|
||||
if (UGeometryCollection* CollectionAsset = Cast<UGeometryCollection>(EngineContext->Owner))
|
||||
{
|
||||
if (UGeometryCollection* CollectionAsset = Cast<UGeometryCollection>(EngineContext->Owner))
|
||||
{
|
||||
if (const TSharedPtr<FGeometryCollection, ESPMode::ThreadSafe> AssetCollection = CollectionAsset->GetGeometryCollection())
|
||||
{
|
||||
FManagedArrayCollection* NewCollection = AssetCollection->NewCopy<FManagedArrayCollection>();
|
||||
Output->SetValue(FManagedArrayCollectionSharedPtr(NewCollection), Context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExampleCollectionEditNode::Evaluate(const FContext& Context, FConnection* Out) const
|
||||
{
|
||||
if (Output.Get() == Out)
|
||||
{
|
||||
DataType Collection = Input->GetValue(Context);
|
||||
if (Active.GetValue())
|
||||
{
|
||||
TManagedArray<FVector3f>* Vertex = Collection->FindAttribute<FVector3f>("Vertex", "Vertices");
|
||||
for (int i = 0; i < Vertex->Num(); i++)
|
||||
{
|
||||
(*Vertex)[i][1] *= Scale.GetValue();
|
||||
}
|
||||
}
|
||||
Output->SetValue(Collection, Context);
|
||||
}
|
||||
}
|
||||
|
||||
void SetCollectionAssetNode::Evaluate(const FContext& Context, FConnection* Out) const
|
||||
{
|
||||
if (Out == nullptr)
|
||||
{
|
||||
DataType Collection = Input->GetValue(Context);
|
||||
if (const FEngineContext* EngineContext = Context.AsType<FEngineContext>(FName("UGeometryCollection")))
|
||||
{
|
||||
if (UGeometryCollection* CollectionAsset = Cast<UGeometryCollection>(EngineContext->Owner))
|
||||
{
|
||||
TSharedPtr<FGeometryCollection, ESPMode::ThreadSafe> NewCollection(Collection->NewCopy<FGeometryCollection>());
|
||||
CollectionAsset->SetGeometryCollection(NewCollection);
|
||||
CollectionAsset->InvalidateCollection();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ResetGeometryCollection::Evaluate(const FContext& Context, FConnection* Out) const
|
||||
{
|
||||
ManagedArrayOut->SetValue(TSharedPtr<FManagedArrayCollection>(nullptr), Context);
|
||||
|
||||
if (const FEngineContext* EngineContext = Context.AsType<FEngineContext>(FName("UGeometryCollection")))
|
||||
{
|
||||
if (UGeometryCollection* GeometryCollectionObject = Cast<UGeometryCollection>(EngineContext->Owner))
|
||||
{
|
||||
GeometryCollectionObject->Reset();
|
||||
|
||||
const UObject* Owner = EngineContext->Owner;
|
||||
FName AName("GeometrySource");
|
||||
if (Owner && Owner->GetClass())
|
||||
{
|
||||
if (const ::FProperty* UEProperty = Owner->GetClass()->FindPropertyByName(AName))
|
||||
{
|
||||
if (const FArrayProperty* ArrayProperty = CastField<FArrayProperty>(UEProperty))
|
||||
{
|
||||
FScriptArrayHelper_InContainer ArrayHelper(ArrayProperty, Owner);
|
||||
const int32 ArraySize = ArrayHelper.Num();
|
||||
for (int32 Index = 0; Index < ArraySize; ++Index)
|
||||
{
|
||||
if (FGeometryCollectionSource* SourceObject = (FGeometryCollectionSource*)(ArrayHelper.GetRawPtr(Index)))
|
||||
{
|
||||
if (UObject* ResolvedObject = SourceObject->SourceGeometryObject.ResolveObject())
|
||||
{
|
||||
if (UStaticMesh* StaticMesh = Cast<UStaticMesh>(ResolvedObject))
|
||||
{
|
||||
TArray<UMaterialInterface*> Materials;
|
||||
Materials.Reserve(StaticMesh->GetStaticMaterials().Num());
|
||||
|
||||
for (int32 Index2 = 0; Index2 < StaticMesh->GetStaticMaterials().Num(); ++Index2)
|
||||
{
|
||||
UMaterialInterface* CurrMaterial = StaticMesh->GetMaterial(Index2);
|
||||
Materials.Add(CurrMaterial);
|
||||
}
|
||||
|
||||
// Geometry collections usually carry the selection material, which we'll delete before appending
|
||||
UMaterialInterface* BoneSelectedMaterial = LoadObject<UMaterialInterface>(nullptr, UGeometryCollection::GetSelectedMaterialPath(), nullptr, LOAD_None, nullptr);
|
||||
GeometryCollectionObject->Materials.Remove(BoneSelectedMaterial);
|
||||
Materials.Remove(BoneSelectedMaterial);
|
||||
|
||||
FGeometryCollectionEngineConversion::AppendStaticMesh(StaticMesh, Materials, FTransform(), GeometryCollectionObject);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
GeometryCollectionObject->UpdateConvexGeometry();
|
||||
GeometryCollectionObject->InitializeMaterials();
|
||||
GeometryCollectionObject->InvalidateCollection();
|
||||
|
||||
if (const TSharedPtr<FGeometryCollection, ESPMode::ThreadSafe> AssetCollection = GeometryCollectionObject->GetGeometryCollection())
|
||||
if (const TSharedPtr<FGeometryCollection, ESPMode::ThreadSafe> AssetCollection = CollectionAsset->GetGeometryCollection())
|
||||
{
|
||||
FManagedArrayCollection* NewCollection = AssetCollection->NewCopy<FManagedArrayCollection>();
|
||||
ManagedArrayOut->SetValue(FManagedArrayCollectionSharedPtr(NewCollection), Context);
|
||||
Output->SetValue(DataType(NewCollection), Context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FExampleCollectionEditDataflowNode::Evaluate(const Dataflow::FContext& Context, Dataflow::FConnection* Out) const
|
||||
{
|
||||
if (Output.Get() == Out)
|
||||
{
|
||||
DataType Collection = Input->GetValue(Context);
|
||||
if (Active)
|
||||
{
|
||||
TManagedArray<FVector3f>* Vertex = Collection->FindAttribute<FVector3f>("Vertex", "Vertices");
|
||||
for (int i = 0; i < Vertex->Num(); i++)
|
||||
{
|
||||
(*Vertex)[i][1] *= Scale;
|
||||
}
|
||||
}
|
||||
Output->SetValue(Collection, Context);
|
||||
}
|
||||
}
|
||||
|
||||
void FSetCollectionAssetDataflowNode::Evaluate(const Dataflow::FContext& Context, Dataflow::FConnection* Out) const
|
||||
{
|
||||
if (Out == nullptr)
|
||||
{
|
||||
DataType Collection = Input->GetValue(Context);
|
||||
if (const Dataflow::FEngineContext* EngineContext = Context.AsType<Dataflow::FEngineContext>(FName("UGeometryCollection")))
|
||||
{
|
||||
if (UGeometryCollection* CollectionAsset = Cast<UGeometryCollection>(EngineContext->Owner))
|
||||
{
|
||||
TSharedPtr<FGeometryCollection, ESPMode::ThreadSafe> NewCollection(Collection->NewCopy<FGeometryCollection>());
|
||||
CollectionAsset->SetGeometryCollection(NewCollection);
|
||||
CollectionAsset->InvalidateCollection();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FResetGeometryCollectionDataflowNode::Evaluate(const Dataflow::FContext& Context, Dataflow::FConnection* Out) const
|
||||
{
|
||||
ManagedArrayOut->SetValue(TSharedPtr<FManagedArrayCollection>(nullptr), Context);
|
||||
|
||||
if (const Dataflow::FEngineContext* EngineContext = Context.AsType<Dataflow::FEngineContext>(FName("UGeometryCollection")))
|
||||
{
|
||||
if (UGeometryCollection* GeometryCollectionObject = Cast<UGeometryCollection>(EngineContext->Owner))
|
||||
{
|
||||
GeometryCollectionObject->Reset();
|
||||
|
||||
const UObject* Owner = EngineContext->Owner;
|
||||
FName AName("GeometrySource");
|
||||
if (Owner && Owner->GetClass())
|
||||
{
|
||||
if (const ::FProperty* UEProperty = Owner->GetClass()->FindPropertyByName(AName))
|
||||
{
|
||||
if (const FArrayProperty* ArrayProperty = CastField<FArrayProperty>(UEProperty))
|
||||
{
|
||||
FScriptArrayHelper_InContainer ArrayHelper(ArrayProperty, Owner);
|
||||
const int32 ArraySize = ArrayHelper.Num();
|
||||
for (int32 Index = 0; Index < ArraySize; ++Index)
|
||||
{
|
||||
if (FGeometryCollectionSource* SourceObject = (FGeometryCollectionSource*)(ArrayHelper.GetRawPtr(Index)))
|
||||
{
|
||||
if (UObject* ResolvedObject = SourceObject->SourceGeometryObject.ResolveObject())
|
||||
{
|
||||
if (UStaticMesh* StaticMesh = Cast<UStaticMesh>(ResolvedObject))
|
||||
{
|
||||
TArray<UMaterialInterface*> Materials;
|
||||
Materials.Reserve(StaticMesh->GetStaticMaterials().Num());
|
||||
|
||||
for (int32 Index2 = 0; Index2 < StaticMesh->GetStaticMaterials().Num(); ++Index2)
|
||||
{
|
||||
UMaterialInterface* CurrMaterial = StaticMesh->GetMaterial(Index2);
|
||||
Materials.Add(CurrMaterial);
|
||||
}
|
||||
|
||||
// Geometry collections usually carry the selection material, which we'll delete before appending
|
||||
UMaterialInterface* BoneSelectedMaterial = LoadObject<UMaterialInterface>(nullptr, UGeometryCollection::GetSelectedMaterialPath(), nullptr, LOAD_None, nullptr);
|
||||
GeometryCollectionObject->Materials.Remove(BoneSelectedMaterial);
|
||||
Materials.Remove(BoneSelectedMaterial);
|
||||
|
||||
FGeometryCollectionEngineConversion::AppendStaticMesh(StaticMesh, Materials, FTransform(), GeometryCollectionObject);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
GeometryCollectionObject->UpdateConvexGeometry();
|
||||
GeometryCollectionObject->InitializeMaterials();
|
||||
GeometryCollectionObject->InvalidateCollection();
|
||||
|
||||
if (const TSharedPtr<FGeometryCollection, ESPMode::ThreadSafe> AssetCollection = GeometryCollectionObject->GetGeometryCollection())
|
||||
{
|
||||
FManagedArrayCollection* NewCollection = AssetCollection->NewCopy<FManagedArrayCollection>();
|
||||
ManagedArrayOut->SetValue(DataType(NewCollection), Context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+86
-79
@@ -7,89 +7,96 @@
|
||||
#include "CoreMinimal.h"
|
||||
#include "Dataflow/DataflowEngine.h"
|
||||
|
||||
#include "GeometryCollectionNodes.generated.h"
|
||||
|
||||
USTRUCT()
|
||||
struct FGetCollectionAssetDataflowNode : public FDataflowNode
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
DATAFLOW_NODE_DEFINE_INTERNAL(FGetCollectionAssetDataflowNode, "GetCollectionAsset", "GeometryCollection", "")
|
||||
|
||||
public:
|
||||
typedef Dataflow::FManagedArrayCollectionSharedPtr DataType;
|
||||
|
||||
TSharedPtr< class Dataflow::TOutput<DataType> > Output;
|
||||
|
||||
FGetCollectionAssetDataflowNode(const Dataflow::FNodeParameters& InParam, FGuid InGuid = FGuid::NewGuid())
|
||||
: FDataflowNode(InParam, InGuid)
|
||||
, Output(new Dataflow::TOutput<DataType>(Dataflow::TOutputParameters<DataType>({ FName("CollectionOut"), this })))
|
||||
{}
|
||||
|
||||
virtual void Evaluate(const Dataflow::FContext& Context, Dataflow::FConnection* Out) const override;
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct FExampleCollectionEditDataflowNode : public FDataflowNode
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
DATAFLOW_NODE_DEFINE_INTERNAL(FExampleCollectionEditDataflowNode, "ExampleCollectionEdit", "GeometryCollection", "")
|
||||
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, Category = "Dataflow");
|
||||
bool Active = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Dataflow");
|
||||
float Scale = 1.0;
|
||||
|
||||
typedef Dataflow::FManagedArrayCollectionSharedPtr DataType;
|
||||
TSharedPtr< class Dataflow::TInput<DataType> > Input;
|
||||
TSharedPtr< class Dataflow::TOutput<DataType> > Output;
|
||||
|
||||
FExampleCollectionEditDataflowNode(const Dataflow::FNodeParameters& InParam, FGuid InGuid = FGuid::NewGuid())
|
||||
: FDataflowNode(InParam, InGuid)
|
||||
, Input(new Dataflow::TInput<DataType>(Dataflow::TInputParameters<DataType>({ FName("CollectionIn"), this })))
|
||||
, Output(new Dataflow::TOutput<DataType>(Dataflow::TOutputParameters<DataType>({ FName("CollectionOut"), this })))
|
||||
{}
|
||||
|
||||
virtual void Evaluate(const Dataflow::FContext& Context, Dataflow::FConnection* Out) const override;
|
||||
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct FSetCollectionAssetDataflowNode : public FDataflowNode
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
DATAFLOW_NODE_DEFINE_INTERNAL(FSetCollectionAssetDataflowNode, "SetCollectionAsset", "GeometryCollection", "")
|
||||
|
||||
public:
|
||||
typedef Dataflow::FManagedArrayCollectionSharedPtr DataType;
|
||||
TSharedPtr< class Dataflow::TInput<DataType> > Input;
|
||||
|
||||
FSetCollectionAssetDataflowNode(const Dataflow::FNodeParameters& InParam, FGuid InGuid = FGuid::NewGuid())
|
||||
: FDataflowNode(InParam, InGuid)
|
||||
, Input(new Dataflow::TInput<DataType>(Dataflow::TInputParameters<DataType>({ FName("CollectionIn"), this })))
|
||||
{}
|
||||
|
||||
virtual void Evaluate(const Dataflow::FContext& Context, Dataflow::FConnection* Out) const override;
|
||||
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct FResetGeometryCollectionDataflowNode : public FDataflowNode
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
DATAFLOW_NODE_DEFINE_INTERNAL(FResetGeometryCollectionDataflowNode, "ResetGeometryCollection", "GeometryCollection", "")
|
||||
|
||||
public:
|
||||
typedef Dataflow::FManagedArrayCollectionSharedPtr DataType;
|
||||
|
||||
TSharedPtr< class Dataflow::TOutput<DataType> > ManagedArrayOut;
|
||||
|
||||
FResetGeometryCollectionDataflowNode(const Dataflow::FNodeParameters& InParam, FGuid InGuid = FGuid::NewGuid())
|
||||
: FDataflowNode(InParam, InGuid)
|
||||
, ManagedArrayOut(new Dataflow::TOutput<DataType>(Dataflow::TOutputParameters<DataType>({ FName("ManagedArrayOut"), this })))
|
||||
{}
|
||||
|
||||
|
||||
virtual void Evaluate(const Dataflow::FContext& Context, Dataflow::FConnection* Out) const override;
|
||||
|
||||
};
|
||||
|
||||
namespace Dataflow
|
||||
{
|
||||
|
||||
class GetCollectionAssetNode : public FNode
|
||||
{
|
||||
DATAFLOW_NODE_DEFINE_INTERNAL(GetCollectionAssetNode)
|
||||
|
||||
public:
|
||||
typedef FManagedArrayCollectionSharedPtr DataType;
|
||||
|
||||
TSharedPtr< class TOutput<DataType> > Output;
|
||||
|
||||
GetCollectionAssetNode(const FNodeParameters& InParam, FGuid InGuid = FGuid::NewGuid())
|
||||
: FNode(InParam, InGuid)
|
||||
, Output(new TOutput<DataType>(TOutputParameters<DataType>({ FName("CollectionOut"), this })))
|
||||
{}
|
||||
|
||||
virtual void Evaluate(const FContext& Context, FConnection* Out) const override;
|
||||
};
|
||||
|
||||
|
||||
class ExampleCollectionEditNode : public FNode
|
||||
{
|
||||
DATAFLOW_NODE_DEFINE_INTERNAL(ExampleCollectionEditNode)
|
||||
|
||||
public:
|
||||
typedef FManagedArrayCollectionSharedPtr DataType;
|
||||
TSharedPtr< class TInput<DataType> > Input;
|
||||
TSharedPtr< class TOutput<DataType> > Output;
|
||||
TProperty<bool> Active;
|
||||
TProperty<float> Scale;
|
||||
|
||||
ExampleCollectionEditNode(const FNodeParameters& InParam, FGuid InGuid = FGuid::NewGuid())
|
||||
: FNode(InParam, InGuid)
|
||||
, Input(new TInput<DataType>(TInputParameters<DataType>({ FName("CollectionIn"), this })))
|
||||
, Output(new TOutput<DataType>(TOutputParameters<DataType>({ FName("CollectionOut"), this })))
|
||||
, Active({ FName("Active"), true, this })
|
||||
, Scale({ FName("Scale"), 10.f, this })
|
||||
{}
|
||||
|
||||
virtual void Evaluate(const FContext& Context, FConnection* Out) const override;
|
||||
|
||||
};
|
||||
|
||||
class SetCollectionAssetNode : public FNode
|
||||
{
|
||||
DATAFLOW_NODE_DEFINE_INTERNAL(SetCollectionAssetNode)
|
||||
|
||||
public:
|
||||
typedef FManagedArrayCollectionSharedPtr DataType;
|
||||
TSharedPtr< class TInput<DataType> > Input;
|
||||
|
||||
SetCollectionAssetNode(const FNodeParameters& InParam, FGuid InGuid = FGuid::NewGuid())
|
||||
: FNode(InParam, InGuid)
|
||||
, Input(new TInput<DataType>(TInputParameters<DataType>({ FName("CollectionIn"), this })))
|
||||
{}
|
||||
|
||||
virtual void Evaluate(const FContext& Context, FConnection* Out) const override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class ResetGeometryCollection : public FNode
|
||||
{
|
||||
DATAFLOW_NODE_DEFINE_INTERNAL(ResetGeometryCollection)
|
||||
|
||||
public:
|
||||
typedef FManagedArrayCollectionSharedPtr DataType;
|
||||
|
||||
TSharedPtr< class TOutput<DataType> > ManagedArrayOut;
|
||||
|
||||
ResetGeometryCollection(const FNodeParameters& InParam, FGuid InGuid = FGuid::NewGuid())
|
||||
: FNode(InParam, InGuid)
|
||||
, ManagedArrayOut(new TOutput<DataType>(TOutputParameters<DataType>({ FName("ManagedArrayOut"), this })))
|
||||
{}
|
||||
|
||||
|
||||
virtual void Evaluate(const FContext& Context, FConnection* Out) const override;
|
||||
|
||||
};
|
||||
|
||||
void GeometryCollectionEngineAssetNodes();
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user