Property manipulation now getting closer
This commit is contained in:
@@ -8,39 +8,10 @@
|
||||
#include "Components/PanelSlot.h"
|
||||
#include "MaterialGraph/MaterialGraphNode.h"
|
||||
#include "Materials/MaterialExpression.h"
|
||||
#include "DetailTreeNode.h"
|
||||
#include "PropertyNode.h"
|
||||
#include "ObjectPropertyNode.h"
|
||||
#include "PropertyNode.h"
|
||||
#include "ObjectPropertyNode.h"
|
||||
#include "ItemPropertyNode.h"
|
||||
#include "CategoryPropertyNode.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IsSubObject
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool WingPropHandle::IsSubObject(const TSharedRef<IDetailTreeNode>& Node)
|
||||
{
|
||||
FDetailTreeNode& DetailNode = static_cast<FDetailTreeNode&>(*Node);
|
||||
TSharedPtr<FPropertyNode> PropNode = DetailNode.GetPropertyNode();
|
||||
if (!PropNode.IsValid()) return false;
|
||||
|
||||
FPropertyNode* Current = PropNode.Get();
|
||||
while (true)
|
||||
{
|
||||
if (Current == nullptr) return false;
|
||||
FPropertyNode *Parent = Current->GetParentNode();
|
||||
if (Current->AsObjectNode()) return (Parent != nullptr);
|
||||
Current = Parent;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get Generator
|
||||
// Get Root
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -52,29 +23,66 @@ TSharedRef<IPropertyRowGenerator> WingPropHandle::CreateGenerator()
|
||||
return Module.CreatePropertyRowGenerator(Args);
|
||||
}
|
||||
|
||||
TSharedRef<IPropertyRowGenerator> WingPropHandle::GetGeneratorForObject(UObject* Obj)
|
||||
WingPropHandle::Root& WingPropHandle::GetRootForObject(UObject* Obj)
|
||||
{
|
||||
for (auto& Pair : Generators)
|
||||
for (Root& R : Roots)
|
||||
{
|
||||
if (Pair.Key == Obj) return Pair.Value.ToSharedRef();
|
||||
if (R.Base == (uint8*)Obj) return R;
|
||||
}
|
||||
TSharedRef<IPropertyRowGenerator> Gen = CreateGenerator();
|
||||
Gen->SetObjects({Obj});
|
||||
Generators.Add({Obj, Gen});
|
||||
return Gen;
|
||||
Root& R = Roots.AddDefaulted_GetRef();
|
||||
R.Struct = Obj->GetClass();
|
||||
R.Base = (uint8*)Obj;
|
||||
R.End = R.Base + R.Struct->GetStructureSize();
|
||||
R.Generator = Gen;
|
||||
return R;
|
||||
}
|
||||
|
||||
TSharedRef<IPropertyRowGenerator> WingPropHandle::GetGeneratorForStruct(const UStruct* ScriptStruct, uint8* Data)
|
||||
WingPropHandle::Root& WingPropHandle::GetRootForStruct(const UStruct* ScriptStruct, uint8* Data)
|
||||
{
|
||||
for (auto& Pair : Generators)
|
||||
for (Root& R : Roots)
|
||||
{
|
||||
if (Pair.Key == Data) return Pair.Value.ToSharedRef();
|
||||
if (R.Base == Data) return R;
|
||||
}
|
||||
TSharedRef<IPropertyRowGenerator> Gen = CreateGenerator();
|
||||
TSharedPtr<FStructOnScope> Wrapper = MakeShared<FStructOnScope>(ScriptStruct, Data);
|
||||
Gen->SetStructure(Wrapper);
|
||||
Generators.Add({Data, Gen});
|
||||
return Gen;
|
||||
Root& R = Roots.AddDefaulted_GetRef();
|
||||
R.Struct = ScriptStruct;
|
||||
R.Base = Data;
|
||||
R.End = Data + ScriptStruct->GetStructureSize();
|
||||
R.Generator = Gen;
|
||||
return R;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IsInsideRootObject
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool WingPropHandle::IsInsideRootObject(const Root& Root, IPropertyHandle& Handle)
|
||||
{
|
||||
// Walk up to the topmost property handle that still has a property.
|
||||
// Keep the shared pointers alive so the raw pointer stays valid.
|
||||
TSharedPtr<IPropertyHandle> Held;
|
||||
IPropertyHandle* Top = &Handle;
|
||||
while (true)
|
||||
{
|
||||
TSharedPtr<IPropertyHandle> Parent = Top->GetParentHandle();
|
||||
if (!Parent.IsValid() || !Parent->GetProperty()) break;
|
||||
Held = Parent;
|
||||
Top = Held.Get();
|
||||
}
|
||||
|
||||
// Get the address of the topmost property's data.
|
||||
void* Addr = nullptr;
|
||||
if (Top->GetValueData(Addr) != FPropertyAccess::Success || !Addr)
|
||||
return false;
|
||||
|
||||
uint8* DataPtr = (uint8*)Addr;
|
||||
return DataPtr >= Root.Base && DataPtr < Root.End;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@@ -85,7 +93,6 @@ TSharedRef<IPropertyRowGenerator> WingPropHandle::GetGeneratorForStruct(const US
|
||||
|
||||
void WingPropHandle::AllTreeNodesRecursive(const TSharedRef<IDetailTreeNode>& Node, FlatTree& Out)
|
||||
{
|
||||
if (IsSubObject(Node)) return;
|
||||
if (Node->GetNodeType() == EDetailNodeType::Category)
|
||||
{
|
||||
TArray<TSharedRef<IDetailTreeNode>> Children;
|
||||
@@ -100,12 +107,12 @@ void WingPropHandle::AllTreeNodesRecursive(const TSharedRef<IDetailTreeNode>& No
|
||||
Out.Add(&*Node);
|
||||
}
|
||||
|
||||
WingPropHandle::FlatTree WingPropHandle::AllTreeNodes(TSharedRef<IPropertyRowGenerator> Generator)
|
||||
WingPropHandle::FlatTree WingPropHandle::AllTreeNodes(Root& Root)
|
||||
{
|
||||
FlatTree Result;
|
||||
for (const TSharedRef<IDetailTreeNode>& Root : Generator->GetRootTreeNodes())
|
||||
for (const TSharedRef<IDetailTreeNode>& TreeRoot : Root.Generator->GetRootTreeNodes())
|
||||
{
|
||||
AllTreeNodesRecursive(Root, Result);
|
||||
AllTreeNodesRecursive(TreeRoot, Result);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
@@ -116,18 +123,19 @@ WingPropHandle::FlatTree WingPropHandle::AllTreeNodes(TSharedRef<IPropertyRowGen
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
WingPropHandle::Handles WingPropHandle::AllProperties(TSharedRef<IPropertyRowGenerator> Generator, EPropertyFlags Filter)
|
||||
WingPropHandle::Handles WingPropHandle::AllProperties(Root& Root, EPropertyFlags Filter)
|
||||
{
|
||||
Handles Result;
|
||||
for (IDetailTreeNode* Node : AllTreeNodes(Generator))
|
||||
for (IDetailTreeNode* Node : AllTreeNodes(Root))
|
||||
{
|
||||
TSharedPtr<IPropertyHandle> Handle = Node->CreatePropertyHandle();
|
||||
if (Handle.IsValid() && Handle->GetProperty())
|
||||
{
|
||||
if (Filter == CPF_None || Handle->GetProperty()->HasAllPropertyFlags(Filter))
|
||||
{
|
||||
Result.Add(Handle);
|
||||
}
|
||||
if (Filter != CPF_None && !Handle->GetProperty()->HasAllPropertyFlags(Filter))
|
||||
continue;
|
||||
if (!IsInsideRootObject(Root, *Handle))
|
||||
continue;
|
||||
Result.Add(Handle);
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
@@ -136,13 +144,13 @@ WingPropHandle::Handles WingPropHandle::AllProperties(TSharedRef<IPropertyRowGen
|
||||
WingPropHandle::Handles WingPropHandle::AllProperties(UObject* Obj, EPropertyFlags Filter)
|
||||
{
|
||||
if (!Obj) return {};
|
||||
return AllProperties(GetGeneratorForObject(Obj), Filter);
|
||||
return AllProperties(GetRootForObject(Obj), Filter);
|
||||
}
|
||||
|
||||
WingPropHandle::Handles WingPropHandle::AllProperties(const UStruct* ScriptStruct, uint8* Data, EPropertyFlags Filter)
|
||||
{
|
||||
if (!ScriptStruct || !Data) return {};
|
||||
return AllProperties(GetGeneratorForStruct(ScriptStruct, Data), Filter);
|
||||
return AllProperties(GetRootForStruct(ScriptStruct, Data), Filter);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@@ -151,12 +159,14 @@ WingPropHandle::Handles WingPropHandle::AllProperties(const UStruct* ScriptStruc
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TSharedPtr<IPropertyHandle> WingPropHandle::NamedProperty(TSharedRef<IPropertyRowGenerator> Generator, FName Name)
|
||||
TSharedPtr<IPropertyHandle> WingPropHandle::NamedProperty(Root& Root, FName Name)
|
||||
{
|
||||
for (IDetailTreeNode* Node : AllTreeNodes(Generator))
|
||||
for (IDetailTreeNode* Node : AllTreeNodes(Root))
|
||||
{
|
||||
if (Node->GetNodeName() == Name)
|
||||
return Node->CreatePropertyHandle();
|
||||
if (Node->GetNodeName() != Name) continue;
|
||||
TSharedPtr<IPropertyHandle> Handle = Node->CreatePropertyHandle();
|
||||
if (Handle.IsValid() && IsInsideRootObject(Root, *Handle))
|
||||
return Handle;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -164,13 +174,13 @@ TSharedPtr<IPropertyHandle> WingPropHandle::NamedProperty(TSharedRef<IPropertyRo
|
||||
TSharedPtr<IPropertyHandle> WingPropHandle::NamedProperty(UObject* Obj, FName Name)
|
||||
{
|
||||
if (!Obj) return nullptr;
|
||||
return NamedProperty(GetGeneratorForObject(Obj), Name);
|
||||
return NamedProperty(GetRootForObject(Obj), Name);
|
||||
}
|
||||
|
||||
TSharedPtr<IPropertyHandle> WingPropHandle::NamedProperty(const UStruct* ScriptStruct, uint8* Data, FName Name)
|
||||
{
|
||||
if (!ScriptStruct || !Data) return nullptr;
|
||||
return NamedProperty(GetGeneratorForStruct(ScriptStruct, Data), Name);
|
||||
return NamedProperty(GetRootForStruct(ScriptStruct, Data), Name);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@@ -231,4 +241,3 @@ WingPropHandle::Handles WingPropHandle::GetDetails(UObject* Obj, bool Mutable, E
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,18 +44,23 @@ public:
|
||||
TSharedPtr<IPropertyHandle> NamedProperty(const UStruct* ScriptStruct, uint8* Data, FName Name);
|
||||
|
||||
private:
|
||||
TArray<TPair<void*, TSharedPtr<IPropertyRowGenerator>>> Generators;
|
||||
struct Root
|
||||
{
|
||||
const UStruct* Struct = nullptr;
|
||||
uint8* Base = nullptr;
|
||||
uint8* End = nullptr;
|
||||
TSharedPtr<IPropertyRowGenerator> Generator;
|
||||
};
|
||||
|
||||
// Check whether a detail tree node's property comes from a sub-object.
|
||||
static bool IsSubObject(const TSharedRef<IDetailTreeNode>& Node);
|
||||
static bool IsInsideRootObject(const Root& Root, IPropertyHandle& Handle);
|
||||
TArray<Root> Roots;
|
||||
|
||||
static TSharedRef<IPropertyRowGenerator> CreateGenerator();
|
||||
TSharedRef<IPropertyRowGenerator> GetGeneratorForObject(UObject* Obj);
|
||||
TSharedRef<IPropertyRowGenerator> GetGeneratorForStruct(const UStruct* ScriptStruct, uint8* Data);
|
||||
|
||||
Root& GetRootForObject(UObject* Obj);
|
||||
Root& GetRootForStruct(const UStruct* ScriptStruct, uint8* Data);
|
||||
static void AllTreeNodesRecursive(const TSharedRef<IDetailTreeNode>& Node, FlatTree& Out);
|
||||
static FlatTree AllTreeNodes(TSharedRef<IPropertyRowGenerator> Generator);
|
||||
static FlatTree AllTreeNodes(Root& Root);
|
||||
|
||||
Handles AllProperties(TSharedRef<IPropertyRowGenerator> Generator, EPropertyFlags Filter);
|
||||
static TSharedPtr<IPropertyHandle> NamedProperty(TSharedRef<IPropertyRowGenerator> Generator, FName Name);
|
||||
Handles AllProperties(Root& Root, EPropertyFlags Filter);
|
||||
static TSharedPtr<IPropertyHandle> NamedProperty(Root& Root, FName Name);
|
||||
};
|
||||
|
||||
@@ -6,8 +6,6 @@ public class UEWingman : ModuleRules
|
||||
{
|
||||
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
// Needed for debug dump of FPropertyNode tree (private headers)
|
||||
PrivateIncludePaths.Add(System.IO.Path.Combine(EngineDirectory, "Source/Editor/PropertyEditor/Private"));
|
||||
|
||||
|
||||
PublicDependencyModuleNames.AddRange(new string[]
|
||||
|
||||
Reference in New Issue
Block a user