Notification changes in UE Wingman
This commit is contained in:
@@ -94,8 +94,8 @@ public:
|
|||||||
UEdGraphNode* Node = F.Node(Entry.Node).Cast<UEdGraphNode>();
|
UEdGraphNode* Node = F.Node(Entry.Node).Cast<UEdGraphNode>();
|
||||||
if (!Node) return;
|
if (!Node) return;
|
||||||
|
|
||||||
TArray<WingProperty> All = WingProperty::GetAll(Node, CPF_Edit);
|
TArray<FWingProperty> All = FWingProperty::GetAll(Node, CPF_Edit);
|
||||||
WingProperty P = WingProperty::FindOneExactMatch(All, Entry.Name);
|
FWingProperty P = FWingProperty::FindOneExactMatch(All, Entry.Name);
|
||||||
if (!P) return;
|
if (!P) return;
|
||||||
|
|
||||||
UWingServer::AddTouchedObject(Node);
|
UWingServer::AddTouchedObject(Node);
|
||||||
|
|||||||
@@ -43,17 +43,17 @@ public:
|
|||||||
WingFetcher F;
|
WingFetcher F;
|
||||||
UObject* Template = F.Walk(Object).Cast<UObject>();
|
UObject* Template = F.Walk(Object).Cast<UObject>();
|
||||||
if (!Template) return;
|
if (!Template) return;
|
||||||
TArray<WingProperty> AllProps = WingProperty::GetAll(Template, CPF_Edit);
|
TArray<FWingProperty> AllProps = FWingProperty::GetAll(Template, CPF_Edit);
|
||||||
TArray<WingProperty> Props = WingProperty::FindAllSubstring(AllProps, Query);
|
TArray<FWingProperty> Props = FWingProperty::FindAllSubstring(AllProps, Query);
|
||||||
if (Local)
|
if (Local)
|
||||||
{
|
{
|
||||||
UClass* ObjClass = Template->GetClass();
|
UClass* ObjClass = Template->GetClass();
|
||||||
Props.RemoveAll([ObjClass](const WingProperty& P) { return P->GetOwnerStruct() != ObjClass; });
|
Props.RemoveAll([ObjClass](const FWingProperty& P) { return P->GetOwnerStruct() != ObjClass; });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Group properties by category.
|
// Group properties by category.
|
||||||
TMap<FString, TArray<WingProperty>> ByCategory;
|
TMap<FString, TArray<FWingProperty>> ByCategory;
|
||||||
for (WingProperty& P : Props)
|
for (FWingProperty& P : Props)
|
||||||
{
|
{
|
||||||
FString Category = P->HasMetaData(TEXT("Category")) ? P->GetMetaData(TEXT("Category")) : FString();
|
FString Category = P->HasMetaData(TEXT("Category")) ? P->GetMetaData(TEXT("Category")) : FString();
|
||||||
ByCategory.FindOrAdd(Category).Add(P);
|
ByCategory.FindOrAdd(Category).Add(P);
|
||||||
@@ -75,7 +75,7 @@ public:
|
|||||||
else
|
else
|
||||||
UWingServer::Printf(TEXT("\n%s:\n"), *Category);
|
UWingServer::Printf(TEXT("\n%s:\n"), *Category);
|
||||||
|
|
||||||
for (WingProperty& P : ByCategory[Category])
|
for (FWingProperty& P : ByCategory[Category])
|
||||||
{
|
{
|
||||||
FString PropName = WingUtils::FormatName(P.Prop);
|
FString PropName = WingUtils::FormatName(P.Prop);
|
||||||
FString ValueStr = P.GetText();
|
FString ValueStr = P.GetText();
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ public:
|
|||||||
UObject* Obj = F.Walk(Object).Cast<UObject>();
|
UObject* Obj = F.Walk(Object).Cast<UObject>();
|
||||||
if (!Obj) return;
|
if (!Obj) return;
|
||||||
|
|
||||||
TArray<WingProperty> All = WingProperty::GetAll(Obj, CPF_Edit);
|
TArray<FWingProperty> All = FWingProperty::GetAll(Obj, CPF_Edit);
|
||||||
WingProperty P = WingProperty::FindOneExactMatch(All, Property);
|
FWingProperty P = FWingProperty::FindOneExactMatch(All, Property);
|
||||||
if (!P) return;
|
if (!P) return;
|
||||||
|
|
||||||
UWingServer::Print(P.GetText());
|
UWingServer::Print(P.GetText());
|
||||||
|
|||||||
@@ -44,11 +44,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validation pass — resolve all properties and values before modifying anything.
|
// Validation pass — resolve all properties and values before modifying anything.
|
||||||
TArray<WingProperty> All = WingProperty::GetAll(Obj, CPF_Edit);
|
TArray<FWingProperty> All = FWingProperty::GetAll(Obj, CPF_Edit);
|
||||||
TArray<TPair<WingProperty, FString>> Resolved;
|
TArray<TPair<FWingProperty, FString>> Resolved;
|
||||||
for (const auto& Pair : Properties.Json->Values)
|
for (const auto& Pair : Properties.Json->Values)
|
||||||
{
|
{
|
||||||
WingProperty P = WingProperty::FindOneExactMatch(All, Pair.Key);
|
FWingProperty P = FWingProperty::FindOneExactMatch(All, Pair.Key);
|
||||||
if (!P) return;
|
if (!P) return;
|
||||||
|
|
||||||
FString ValueStr;
|
FString ValueStr;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ FWingBlueprintVar::FWingBlueprintVar(UBlueprint* BP, const FString& VarName)
|
|||||||
UObject* CDO = BP->GeneratedClass->GetDefaultObject();
|
UObject* CDO = BP->GeneratedClass->GetDefaultObject();
|
||||||
FProperty* Prop = BP->GeneratedClass->FindPropertyByName(VarFName);
|
FProperty* Prop = BP->GeneratedClass->FindPropertyByName(VarFName);
|
||||||
if (CDO && Prop)
|
if (CDO && Prop)
|
||||||
DefaultValueProp = WingProperty(Prop, CDO);
|
DefaultValueProp = FWingProperty(Prop, CDO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,8 +31,8 @@ void FWingBlueprintVar::Dump()
|
|||||||
{
|
{
|
||||||
LoadFlags();
|
LoadFlags();
|
||||||
LoadDefault();
|
LoadDefault();
|
||||||
TArray<WingProperty> Props = MergedProperties();
|
TArray<FWingProperty> Props = MergedProperties();
|
||||||
for (WingProperty& P : Props)
|
for (FWingProperty& P : Props)
|
||||||
{
|
{
|
||||||
UWingServer::Printf(TEXT(" %s %s = %s\n"),
|
UWingServer::Printf(TEXT(" %s %s = %s\n"),
|
||||||
*UWingTypes::TypeToText(P.Prop),
|
*UWingTypes::TypeToText(P.Prop),
|
||||||
@@ -56,7 +56,7 @@ bool FWingBlueprintVar::ApplyJson(const FJsonObject* Json)
|
|||||||
|
|
||||||
LoadFlags();
|
LoadFlags();
|
||||||
|
|
||||||
TArray<WingProperty> Props = MergedProperties();
|
TArray<FWingProperty> Props = MergedProperties();
|
||||||
if (!WingJson::PopulateFromJson(Props, Json, true))
|
if (!WingJson::PopulateFromJson(Props, Json, true))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -131,23 +131,23 @@ bool FWingBlueprintVar::SaveDefault()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
TArray<WingProperty> FWingBlueprintVar::MergedProperties()
|
TArray<FWingProperty> FWingBlueprintVar::MergedProperties()
|
||||||
{
|
{
|
||||||
TArray<WingProperty> Props = WingProperty::GetAll(
|
TArray<FWingProperty> Props = FWingProperty::GetAll(
|
||||||
FBPVariableDescription::StaticStruct(), Desc, CPF_Edit);
|
FBPVariableDescription::StaticStruct(), Desc, CPF_Edit);
|
||||||
|
|
||||||
WingProperty::Remove(Props, TEXT("PropertyFlags"));
|
FWingProperty::Remove(Props, TEXT("PropertyFlags"));
|
||||||
WingProperty::Remove(Props, TEXT("MetaDataArray"));
|
FWingProperty::Remove(Props, TEXT("MetaDataArray"));
|
||||||
WingProperty::Remove(Props, TEXT("VarName"));
|
FWingProperty::Remove(Props, TEXT("VarName"));
|
||||||
WingProperty::Remove(Props, TEXT("VarGuid"));
|
FWingProperty::Remove(Props, TEXT("VarGuid"));
|
||||||
WingProperty::Remove(Props, TEXT("DefaultValue"));
|
FWingProperty::Remove(Props, TEXT("DefaultValue"));
|
||||||
|
|
||||||
Props.Append(WingProperty::GetAll(
|
Props.Append(FWingProperty::GetAll(
|
||||||
FWingBlueprintVar::StaticStruct(), this, (EPropertyFlags)0));
|
FWingBlueprintVar::StaticStruct(), this, (EPropertyFlags)0));
|
||||||
|
|
||||||
// Remove DefaultValue if we don't have a CDO property to back it.
|
// Remove DefaultValue if we don't have a CDO property to back it.
|
||||||
if (!DefaultValueProp)
|
if (!DefaultValueProp)
|
||||||
WingProperty::Remove(Props, TEXT("DefaultValue"));
|
FWingProperty::Remove(Props, TEXT("DefaultValue"));
|
||||||
|
|
||||||
return Props;
|
return Props;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ WingFetcher::WalkFunc WingFetcher::GetWalker(const FString& Step)
|
|||||||
|
|
||||||
void WingFetcher::SetObj(UObject* InObj)
|
void WingFetcher::SetObj(UObject* InObj)
|
||||||
{
|
{
|
||||||
UWingServer::AddTouchedObject(InObj);
|
if (!bSkipNotify)
|
||||||
|
UWingServer::AddTouchedObject(InObj);
|
||||||
Obj = InObj;
|
Obj = InObj;
|
||||||
ResultPin = nullptr;
|
ResultPin = nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include "Dom/JsonValue.h"
|
#include "Dom/JsonValue.h"
|
||||||
|
|
||||||
|
|
||||||
bool WingJson::PopulateFromJson(WingProperty& P, const FJsonObject* Json, bool AllOptional)
|
bool WingJson::PopulateFromJson(FWingProperty& P, const FJsonObject* Json, bool AllOptional)
|
||||||
{
|
{
|
||||||
FString JsonKey = P.Prop->GetName();
|
FString JsonKey = P.Prop->GetName();
|
||||||
bool bOptional = AllOptional || P.Prop->HasMetaData(TEXT("Optional"));
|
bool bOptional = AllOptional || P.Prop->HasMetaData(TEXT("Optional"));
|
||||||
@@ -85,13 +85,13 @@ bool WingJson::PopulateFromJson(WingProperty& P, const FJsonObject* Json, bool A
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool WingJson::PopulateFromJson(
|
bool WingJson::PopulateFromJson(
|
||||||
TArray<WingProperty>& Props, const FJsonObject* Json, bool AllOptional)
|
TArray<FWingProperty>& Props, const FJsonObject* Json, bool AllOptional)
|
||||||
{
|
{
|
||||||
bool Ok = true;
|
bool Ok = true;
|
||||||
|
|
||||||
// Build a set of known property names for the unknown-field check.
|
// Build a set of known property names for the unknown-field check.
|
||||||
TSet<FString> KnownKeys;
|
TSet<FString> KnownKeys;
|
||||||
for (const WingProperty& P : Props)
|
for (const FWingProperty& P : Props)
|
||||||
KnownKeys.Add(P.Prop->GetName());
|
KnownKeys.Add(P.Prop->GetName());
|
||||||
|
|
||||||
// Check for unknown fields in the JSON
|
// Check for unknown fields in the JSON
|
||||||
@@ -105,7 +105,7 @@ bool WingJson::PopulateFromJson(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Populate each property from JSON
|
// Populate each property from JSON
|
||||||
for (WingProperty& P : Props)
|
for (FWingProperty& P : Props)
|
||||||
{
|
{
|
||||||
if (!PopulateFromJson(P, Json, AllOptional)) Ok = false;
|
if (!PopulateFromJson(P, Json, AllOptional)) Ok = false;
|
||||||
}
|
}
|
||||||
@@ -115,7 +115,7 @@ bool WingJson::PopulateFromJson(
|
|||||||
bool WingJson::PopulateFromJson(
|
bool WingJson::PopulateFromJson(
|
||||||
UStruct* StructType, void* Container, const FJsonObject* Json)
|
UStruct* StructType, void* Container, const FJsonObject* Json)
|
||||||
{
|
{
|
||||||
TArray<WingProperty> Props = WingProperty::GetAll(StructType, Container, (EPropertyFlags)0);
|
TArray<FWingProperty> Props = FWingProperty::GetAll(StructType, Container, (EPropertyFlags)0);
|
||||||
return PopulateFromJson(Props, Json);
|
return PopulateFromJson(Props, Json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,29 +3,29 @@
|
|||||||
#include "EdGraph/EdGraph.h"
|
#include "EdGraph/EdGraph.h"
|
||||||
#include "Engine/Blueprint.h"
|
#include "Engine/Blueprint.h"
|
||||||
#include "Materials/Material.h"
|
#include "Materials/Material.h"
|
||||||
|
#include "Materials/MaterialExpression.h"
|
||||||
#include "Kismet2/BlueprintEditorUtils.h"
|
#include "Kismet2/BlueprintEditorUtils.h"
|
||||||
#include "MaterialEditingLibrary.h"
|
#include "MaterialEditingLibrary.h"
|
||||||
|
|
||||||
void WingNotifier::AddTouchedObject(UObject* Obj)
|
void FWingNotifier::AddTouchedObject(UObject* Obj)
|
||||||
{
|
{
|
||||||
if (!Obj) return;
|
if (!Obj) return;
|
||||||
bool bAlreadyInSet = false;
|
bool bAlreadyInSet = false;
|
||||||
TouchedSet.Add(Obj, &bAlreadyInSet);
|
TouchedSet.Add(Obj, &bAlreadyInSet);
|
||||||
if (bAlreadyInSet) return;
|
if (bAlreadyInSet) return;
|
||||||
TouchedArray.Add(Obj);
|
TouchedArray.Add(Obj);
|
||||||
Obj->PreEditChange(nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WingNotifier::SendNotifications()
|
void FWingNotifier::SendNotifications()
|
||||||
{
|
{
|
||||||
TSet<UEdGraphNode*> Nodes;
|
TSet<UEdGraphNode*> Nodes;
|
||||||
TSet<UEdGraph*> Graphs;
|
TSet<UEdGraph*> Graphs;
|
||||||
TSet<UMaterial*> Materials;
|
TSet<UMaterial*> Materials;
|
||||||
|
TSet<UMaterialExpression*> MaterialExpressions;
|
||||||
TSet<UBlueprint*> Blueprints;
|
TSet<UBlueprint*> Blueprints;
|
||||||
for (int32 i = TouchedArray.Num() - 1; i >= 0; --i)
|
for (int32 i = TouchedArray.Num() - 1; i >= 0; --i)
|
||||||
{
|
{
|
||||||
UObject* Obj = TouchedArray[i];
|
UObject* Obj = TouchedArray[i];
|
||||||
Obj->PostEditChange();
|
|
||||||
Obj->MarkPackageDirty();
|
Obj->MarkPackageDirty();
|
||||||
|
|
||||||
if (UEdGraphNode* Node = ::Cast<UEdGraphNode>(Obj))
|
if (UEdGraphNode* Node = ::Cast<UEdGraphNode>(Obj))
|
||||||
@@ -37,12 +37,21 @@ void WingNotifier::SendNotifications()
|
|||||||
if (UBlueprint* BP = ::Cast<UBlueprint>(Obj))
|
if (UBlueprint* BP = ::Cast<UBlueprint>(Obj))
|
||||||
Blueprints.Add(BP);
|
Blueprints.Add(BP);
|
||||||
|
|
||||||
|
if (UMaterialExpression* Expr = ::Cast<UMaterialExpression>(Obj))
|
||||||
|
MaterialExpressions.Add(Expr);
|
||||||
|
|
||||||
|
if (UMaterial* Mat = ::Cast<UMaterial>(Obj))
|
||||||
|
Materials.Add(Mat);
|
||||||
|
|
||||||
if (UMaterialInterface* MatIface = ::Cast<UMaterialInterface>(Obj))
|
if (UMaterialInterface* MatIface = ::Cast<UMaterialInterface>(Obj))
|
||||||
if (UMaterial* BaseMat = MatIface->GetMaterial())
|
if (UMaterial* BaseMat = MatIface->GetMaterial())
|
||||||
Materials.Add(BaseMat);
|
Materials.Add(BaseMat);
|
||||||
}
|
}
|
||||||
for (UEdGraphNode* Node : Nodes)
|
|
||||||
Node->ReconstructNode();
|
for (UMaterialExpression* Expr : MaterialExpressions)
|
||||||
|
Expr->RefreshNode(true);
|
||||||
|
// for (UEdGraphNode* Node : Nodes)
|
||||||
|
// Node->ReconstructNode();
|
||||||
for (UEdGraph* Graph : Graphs)
|
for (UEdGraph* Graph : Graphs)
|
||||||
Graph->NotifyGraphChanged();
|
Graph->NotifyGraphChanged();
|
||||||
for (UMaterial *Material : Materials)
|
for (UMaterial *Material : Materials)
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include "WingServer.h"
|
#include "WingServer.h"
|
||||||
#include "WingTypes.h"
|
#include "WingTypes.h"
|
||||||
#include "Engine/Blueprint.h"
|
#include "Engine/Blueprint.h"
|
||||||
#include "Materials/MaterialExpression.h"
|
|
||||||
#include "MaterialGraph/MaterialGraphNode.h"
|
#include "MaterialGraph/MaterialGraphNode.h"
|
||||||
#include "EdGraph/EdGraphPin.h"
|
#include "EdGraph/EdGraphPin.h"
|
||||||
#include "UObject/EnumProperty.h"
|
#include "UObject/EnumProperty.h"
|
||||||
@@ -14,10 +13,13 @@ static bool IsPinTypeProperty(FProperty* Prop)
|
|||||||
return StructProp && StructProp->Struct == FEdGraphPinType::StaticStruct();
|
return StructProp && StructProp->Struct == FEdGraphPinType::StaticStruct();
|
||||||
}
|
}
|
||||||
|
|
||||||
WingProperty::WingProperty(FProperty* InProp, void* InContainer)
|
FWingProperty::FWingProperty(FProperty* InProp, void* InContainer)
|
||||||
: Prop(InProp), Container(InContainer) {}
|
: Prop(InProp), Container(InContainer) {}
|
||||||
|
|
||||||
FString WingProperty::GetText() const
|
FWingProperty::FWingProperty(FProperty* InProp, UObject* InContainer)
|
||||||
|
: Prop(InProp), Container(static_cast<void*>(InContainer)) {}
|
||||||
|
|
||||||
|
FString FWingProperty::GetText() const
|
||||||
{
|
{
|
||||||
void* ValuePtr = Prop->ContainerPtrToValuePtr<void>(Container);
|
void* ValuePtr = Prop->ContainerPtrToValuePtr<void>(Container);
|
||||||
if (IsPinTypeProperty(Prop))
|
if (IsPinTypeProperty(Prop))
|
||||||
@@ -27,7 +29,7 @@ FString WingProperty::GetText() const
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WingProperty::TryParseEnum(UEnum* Enum, const FString& Text, int64 &OutValue)
|
bool FWingProperty::TryParseEnum(UEnum* Enum, const FString& Text, int64 &OutValue)
|
||||||
{
|
{
|
||||||
int Index = Enum->GetIndexByNameString(Text);
|
int Index = Enum->GetIndexByNameString(Text);
|
||||||
if (Index == INDEX_NONE)
|
if (Index == INDEX_NONE)
|
||||||
@@ -52,10 +54,14 @@ bool WingProperty::TryParseEnum(UEnum* Enum, const FString& Text, int64 &OutValu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WingProperty::TrySetText(const FString &Value)
|
bool FWingProperty::SetText(const FString &Value)
|
||||||
{
|
{
|
||||||
void* ValuePtr = Prop->ContainerPtrToValuePtr<void>(Container);
|
void* ValuePtr = Prop->ContainerPtrToValuePtr<void>(Container);
|
||||||
|
|
||||||
|
// Notify that we're modifying the containing object.
|
||||||
|
if (Prop->GetOwnerClass())
|
||||||
|
UWingServer::AddTouchedObject(static_cast<UObject*>(Container));
|
||||||
|
|
||||||
// Pin types get parsed by UWingTypes.
|
// Pin types get parsed by UWingTypes.
|
||||||
if (IsPinTypeProperty(Prop))
|
if (IsPinTypeProperty(Prop))
|
||||||
return UWingTypes::TextToType(Value, *static_cast<FEdGraphPinType*>(ValuePtr));
|
return UWingTypes::TextToType(Value, *static_cast<FEdGraphPinType*>(ValuePtr));
|
||||||
@@ -92,20 +98,7 @@ bool WingProperty::TrySetText(const FString &Value)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WingProperty::SetText(const FString& Value)
|
void FWingProperty::Collect(UStruct* StructType, void* Container, TArray<FWingProperty> &Props, EPropertyFlags Flags)
|
||||||
{
|
|
||||||
if (!TrySetText(Value)) return false;
|
|
||||||
|
|
||||||
if (Prop->GetOwnerClass()->IsChildOf(UMaterialExpression::StaticClass()))
|
|
||||||
{
|
|
||||||
UMaterialExpression* Expr = static_cast<UMaterialExpression*>(Container);
|
|
||||||
Expr->ForcePropertyValueChanged(Prop);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WingProperty::Collect(UStruct* StructType, void* Container, TArray<WingProperty> &Props, EPropertyFlags Flags)
|
|
||||||
{
|
{
|
||||||
for (TFieldIterator<FProperty> It(StructType); It; ++It)
|
for (TFieldIterator<FProperty> It(StructType); It; ++It)
|
||||||
{
|
{
|
||||||
@@ -114,15 +107,24 @@ void WingProperty::Collect(UStruct* StructType, void* Container, TArray<WingProp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WingProperty::Remove(TArray<WingProperty>& Props, const FString& Name)
|
void FWingProperty::Collect(UObject* Container, TArray<FWingProperty> &Props, EPropertyFlags Flags)
|
||||||
{
|
{
|
||||||
Props.RemoveAll([&](const WingProperty& P) { return P.Prop->GetName() == Name; });
|
for (TFieldIterator<FProperty> It(Container->GetClass()); It; ++It)
|
||||||
|
{
|
||||||
|
if (Flags != 0 && !It->HasAnyPropertyFlags(Flags)) continue;
|
||||||
|
Props.Emplace(*It, Container);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TArray<WingProperty> WingProperty::GetAll(UObject* Obj, EPropertyFlags Flags)
|
void FWingProperty::Remove(TArray<FWingProperty>& Props, const FString& Name)
|
||||||
|
{
|
||||||
|
Props.RemoveAll([&](const FWingProperty& P) { return P.Prop->GetName() == Name; });
|
||||||
|
}
|
||||||
|
|
||||||
|
TArray<FWingProperty> FWingProperty::GetAll(UObject* Obj, EPropertyFlags Flags)
|
||||||
{
|
{
|
||||||
if (!Obj) return {};
|
if (!Obj) return {};
|
||||||
TArray<WingProperty> Result;
|
TArray<FWingProperty> Result;
|
||||||
|
|
||||||
// Blueprints don't have editable properties. So
|
// Blueprints don't have editable properties. So
|
||||||
// instead, we fetch properties from the generated CDO,
|
// instead, we fetch properties from the generated CDO,
|
||||||
@@ -138,7 +140,7 @@ TArray<WingProperty> WingProperty::GetAll(UObject* Obj, EPropertyFlags Flags)
|
|||||||
Obj = BP->GeneratedClass->GetDefaultObject();
|
Obj = BP->GeneratedClass->GetDefaultObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
Collect(Obj->GetClass(), Obj, Result, Flags);
|
Collect(Obj, Result, Flags);
|
||||||
|
|
||||||
// If it's a Material Graph node, also collect properties from
|
// If it's a Material Graph node, also collect properties from
|
||||||
// the associated material expression.
|
// the associated material expression.
|
||||||
@@ -147,24 +149,24 @@ TArray<WingProperty> WingProperty::GetAll(UObject* Obj, EPropertyFlags Flags)
|
|||||||
{
|
{
|
||||||
if (UMaterialExpression* Expr = MatNode->MaterialExpression)
|
if (UMaterialExpression* Expr = MatNode->MaterialExpression)
|
||||||
{
|
{
|
||||||
Collect(Expr->GetClass(), Expr, Result, Flags);
|
Collect(Expr, Result, Flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
TArray<WingProperty> WingProperty::GetAll(UStruct* StructType, void* Container, EPropertyFlags Flags)
|
TArray<FWingProperty> FWingProperty::GetAll(UStruct* StructType, void* Container, EPropertyFlags Flags)
|
||||||
{
|
{
|
||||||
TArray<WingProperty> Result;
|
TArray<FWingProperty> Result;
|
||||||
Collect(StructType, Container, Result, Flags);
|
Collect(StructType, Container, Result, Flags);
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
TArray<WingProperty> WingProperty::FindAllSubstring(const TArray<WingProperty>& Props, const FString& Substring)
|
TArray<FWingProperty> FWingProperty::FindAllSubstring(const TArray<FWingProperty>& Props, const FString& Substring)
|
||||||
{
|
{
|
||||||
if (Substring.IsEmpty()) return Props;
|
if (Substring.IsEmpty()) return Props;
|
||||||
TArray<WingProperty> Result;
|
TArray<FWingProperty> Result;
|
||||||
for (const WingProperty& P : Props)
|
for (const FWingProperty& P : Props)
|
||||||
{
|
{
|
||||||
if (WingUtils::FormatName(P.Prop).Contains(Substring, ESearchCase::IgnoreCase))
|
if (WingUtils::FormatName(P.Prop).Contains(Substring, ESearchCase::IgnoreCase))
|
||||||
Result.Add(P);
|
Result.Add(P);
|
||||||
@@ -172,10 +174,10 @@ TArray<WingProperty> WingProperty::FindAllSubstring(const TArray<WingProperty>&
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
WingProperty WingProperty::FindOneExactMatch(const TArray<WingProperty>& Props, const FString& Name)
|
FWingProperty FWingProperty::FindOneExactMatch(const TArray<FWingProperty>& Props, const FString& Name)
|
||||||
{
|
{
|
||||||
TArray<WingProperty> Matches;
|
TArray<FWingProperty> Matches;
|
||||||
for (const WingProperty& P : Props)
|
for (const FWingProperty& P : Props)
|
||||||
{
|
{
|
||||||
if (WingUtils::Identifies(Name, P.Prop))
|
if (WingUtils::Identifies(Name, P.Prop))
|
||||||
Matches.Add(P);
|
Matches.Add(P);
|
||||||
@@ -183,12 +185,12 @@ WingProperty WingProperty::FindOneExactMatch(const TArray<WingProperty>& Props,
|
|||||||
if (Matches.Num() == 0)
|
if (Matches.Num() == 0)
|
||||||
{
|
{
|
||||||
UWingServer::Printf(TEXT("ERROR: Property '%s' not found\n"), *Name);
|
UWingServer::Printf(TEXT("ERROR: Property '%s' not found\n"), *Name);
|
||||||
return WingProperty();
|
return FWingProperty();
|
||||||
}
|
}
|
||||||
if (Matches.Num() > 1)
|
if (Matches.Num() > 1)
|
||||||
{
|
{
|
||||||
UWingServer::Printf(TEXT("ERROR: Ambiguous property '%s'\n"), *Name);
|
UWingServer::Printf(TEXT("ERROR: Ambiguous property '%s'\n"), *Name);
|
||||||
return WingProperty();
|
return FWingProperty();
|
||||||
}
|
}
|
||||||
return Matches[0];
|
return Matches[0];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -304,7 +304,7 @@ void UWingServer::TryCallHandler(const FString &Line)
|
|||||||
Request->RemoveField(TEXT("command"));
|
Request->RemoveField(TEXT("command"));
|
||||||
|
|
||||||
// Find the handler UClass for the specified command.
|
// Find the handler UClass for the specified command.
|
||||||
UClass** HandlerClass = WingHandlerRegistry.Find(Command);
|
TObjectPtr<UClass>* HandlerClass = WingHandlerRegistry.Find(Command);
|
||||||
if (!HandlerClass)
|
if (!HandlerClass)
|
||||||
{
|
{
|
||||||
UWingServer::Printf(TEXT("Unknown command: %s"), *Command);
|
UWingServer::Printf(TEXT("Unknown command: %s"), *Command);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ struct FWingBlueprintVar
|
|||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
FBPVariableDescription* Desc = nullptr;
|
FBPVariableDescription* Desc = nullptr;
|
||||||
WingProperty DefaultValueProp;
|
FWingProperty DefaultValueProp;
|
||||||
|
|
||||||
FWingBlueprintVar() = default;
|
FWingBlueprintVar() = default;
|
||||||
FWingBlueprintVar(UBlueprint* BP, const FString& VarName);
|
FWingBlueprintVar(UBlueprint* BP, const FString& VarName);
|
||||||
@@ -54,5 +54,5 @@ private:
|
|||||||
void LoadDefault();
|
void LoadDefault();
|
||||||
void SaveFlags();
|
void SaveFlags();
|
||||||
bool SaveDefault();
|
bool SaveDefault();
|
||||||
TArray<WingProperty> MergedProperties();
|
TArray<FWingProperty> MergedProperties();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -105,6 +105,12 @@ public:
|
|||||||
return static_cast<EditorType*>(Editor);
|
return static_cast<EditorType*>(Editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calling SkipNotify disables change notifications
|
||||||
|
// for objects visited by this fetcher. Useful for
|
||||||
|
// read-only operations that don't modify anything.
|
||||||
|
//
|
||||||
|
WingFetcher& SkipNotify() { bSkipNotify = true; return *this; }
|
||||||
|
|
||||||
// Initialize empty. You need to call Asset, or walk
|
// Initialize empty. You need to call Asset, or walk
|
||||||
// a path that starts with an asset.
|
// a path that starts with an asset.
|
||||||
//
|
//
|
||||||
@@ -128,6 +134,7 @@ private:
|
|||||||
|
|
||||||
// True if an error has occurred.
|
// True if an error has occurred.
|
||||||
bool bError = false;
|
bool bError = false;
|
||||||
|
bool bSkipNotify = false;
|
||||||
|
|
||||||
// Internal methods.
|
// Internal methods.
|
||||||
using WalkFunc = WingFetcher& (WingFetcher::*)(const FString&);
|
using WalkFunc = WingFetcher& (WingFetcher::*)(const FString&);
|
||||||
|
|||||||
@@ -10,8 +10,8 @@
|
|||||||
class WingJson
|
class WingJson
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static bool PopulateFromJson(WingProperty& Prop, const FJsonObject* Json, bool AllOptional = false);
|
static bool PopulateFromJson(FWingProperty& Prop, const FJsonObject* Json, bool AllOptional = false);
|
||||||
static bool PopulateFromJson(TArray<WingProperty>& Props, const FJsonObject* Json, bool AllOptional = false);
|
static bool PopulateFromJson(TArray<FWingProperty>& Props, const FJsonObject* Json, bool AllOptional = false);
|
||||||
static bool PopulateFromJson(UStruct* StructType, void* Container, const TSharedPtr<FJsonValue>& JsonValue);
|
static bool PopulateFromJson(UStruct* StructType, void* Container, const TSharedPtr<FJsonValue>& JsonValue);
|
||||||
static bool PopulateFromJson(UStruct* StructType, void* Container, const FJsonObject* Json);
|
static bool PopulateFromJson(UStruct* StructType, void* Container, const FJsonObject* Json);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,18 +1,24 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
|
#include "WingNotifier.generated.h"
|
||||||
|
|
||||||
// Tracks objects that have been touched during an editing operation.
|
// Tracks objects that have been touched during an editing operation.
|
||||||
// Handles PreEditChange/PostEditChange, ReconstructNode, and other
|
// Handles PreEditChange/PostEditChange, ReconstructNode, and other
|
||||||
// notifications that need to happen after modifications.
|
// notifications that need to happen after modifications.
|
||||||
//
|
//
|
||||||
class WingNotifier
|
USTRUCT()
|
||||||
|
struct FWingNotifier
|
||||||
{
|
{
|
||||||
public:
|
GENERATED_BODY()
|
||||||
|
|
||||||
void AddTouchedObject(UObject* Obj);
|
void AddTouchedObject(UObject* Obj);
|
||||||
void SendNotifications();
|
void SendNotifications();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TSet<UObject*> TouchedSet;
|
UPROPERTY()
|
||||||
TArray<UObject*> TouchedArray;
|
TSet<TObjectPtr<UObject>> TouchedSet;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
TArray<TObjectPtr<UObject>> TouchedArray;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,17 +2,17 @@
|
|||||||
|
|
||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
#include "WingUtils.h"
|
#include "WingUtils.h"
|
||||||
|
|
||||||
// A resolved property: the FProperty descriptor plus a pointer to
|
// A resolved property: the FProperty descriptor plus a pointer to
|
||||||
// the value's storage. operator-> forwards to the FProperty.
|
// the value's storage. operator-> forwards to the FProperty.
|
||||||
struct WingProperty
|
struct FWingProperty
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
FProperty* Prop = nullptr;
|
FProperty* Prop = nullptr;
|
||||||
void* Container = nullptr;
|
void* Container = nullptr;
|
||||||
|
|
||||||
WingProperty() = default;
|
FWingProperty() = default;
|
||||||
WingProperty(FProperty* InProp, void* Container);
|
FWingProperty(FProperty* InProp, void* InContainer);
|
||||||
|
FWingProperty(FProperty* InProp, UObject* InContainer);
|
||||||
|
|
||||||
FString GetText() const;
|
FString GetText() const;
|
||||||
bool SetText(const FString& Value);
|
bool SetText(const FString& Value);
|
||||||
@@ -20,14 +20,14 @@ public:
|
|||||||
explicit operator bool() const { return Prop != nullptr; }
|
explicit operator bool() const { return Prop != nullptr; }
|
||||||
FProperty* operator->() const { return Prop; }
|
FProperty* operator->() const { return Prop; }
|
||||||
|
|
||||||
static void Remove(TArray<WingProperty>& Props, const FString& Name);
|
static void Remove(TArray<FWingProperty>& Props, const FString& Name);
|
||||||
static TArray<WingProperty> GetAll(UObject* Obj, EPropertyFlags Flags);
|
static TArray<FWingProperty> GetAll(UObject* Obj, EPropertyFlags Flags);
|
||||||
static TArray<WingProperty> GetAll(UStruct* StructType, void* Container, EPropertyFlags Flags);
|
static TArray<FWingProperty> GetAll(UStruct* StructType, void* Container, EPropertyFlags Flags);
|
||||||
static TArray<WingProperty> FindAllSubstring(const TArray<WingProperty>& Props, const FString& Substring);
|
static TArray<FWingProperty> FindAllSubstring(const TArray<FWingProperty>& Props, const FString& Substring);
|
||||||
static WingProperty FindOneExactMatch(const TArray<WingProperty>& Props, const FString& Name);
|
static FWingProperty FindOneExactMatch(const TArray<FWingProperty>& Props, const FString& Name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool TryParseEnum(UEnum* Enum, const FString& Text, int64 &OutValue);
|
bool TryParseEnum(UEnum* Enum, const FString& Text, int64 &OutValue);
|
||||||
bool TrySetText(const FString &Text);
|
static void Collect(UStruct* StructType, void* Container, TArray<FWingProperty> &Props, EPropertyFlags Flags);
|
||||||
static void Collect(UStruct* StructType, void* Container, TArray<WingProperty> &Props, EPropertyFlags Flags);
|
static void Collect(UObject* Container, TArray<FWingProperty> &Props, EPropertyFlags Flags);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -69,10 +69,12 @@ private:
|
|||||||
static UWingServer* GWingServer;
|
static UWingServer* GWingServer;
|
||||||
|
|
||||||
// ----- Tool dispatch -----
|
// ----- Tool dispatch -----
|
||||||
WingNotifier Notifier;
|
UPROPERTY()
|
||||||
|
FWingNotifier Notifier;
|
||||||
TStringBuilder<16384> HandlerOutput;
|
TStringBuilder<16384> HandlerOutput;
|
||||||
FLogCaptureOutputDevice LogCapture; // installed once at startup, enabled per-request
|
FLogCaptureOutputDevice LogCapture; // installed once at startup, enabled per-request
|
||||||
TMap<FString, UClass*> WingHandlerRegistry; // tool name -> UWingHandler subclass
|
UPROPERTY()
|
||||||
|
TMap<FString, TObjectPtr<UClass>> WingHandlerRegistry; // tool name -> UWingHandler subclass
|
||||||
void BuildWingHandlerRegistry();
|
void BuildWingHandlerRegistry();
|
||||||
|
|
||||||
// Handle a complete JSON line and return the response JSON
|
// Handle a complete JSON line and return the response JSON
|
||||||
|
|||||||
Reference in New Issue
Block a user