More work on properties
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#include "WingServer.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingFactories.h"
|
||||
#include "WingPropHandle.h"
|
||||
#include "WingTypes.h"
|
||||
#include "Factories/BlueprintFactory.h"
|
||||
#include "Factories/BlueprintMacroFactory.h"
|
||||
@@ -73,31 +74,26 @@ public:
|
||||
// Make the factory.
|
||||
UClass *FactoryClass = Cast<UClass>(ConfigurationObject);
|
||||
UFactory *Factory = NewObject<UFactory>(GetTransientPackage(), FactoryClass);
|
||||
|
||||
// Get the 'ParentClass' property.
|
||||
FProperty *Prop = FactoryClass->FindPropertyByName(FName(TEXT("ParentClass")));
|
||||
FClassProperty *CProp = CastField<FClassProperty>(Prop);
|
||||
|
||||
// Check that things are on track.
|
||||
if ((Factory == nullptr) || (CProp == nullptr))
|
||||
if (Factory == nullptr)
|
||||
{
|
||||
UWingServer::Printf(TEXT("In Create_Blueprint, factory creation is buggy\n"));
|
||||
UWingServer::Printf(TEXT("ERROR: factory creation failed (bug)\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Store the parentclass, if specified.
|
||||
if (ParentClassObj)
|
||||
// Get the 'ParentClass' property.
|
||||
WingPropHandle Props;
|
||||
TSharedPtr<IPropertyHandle> PCProp = Props.NamedProperty(Factory, TEXT("ParentClass"), true);
|
||||
if (!PCProp) return;
|
||||
|
||||
// Store the parent class.
|
||||
FPropertyAccess::Result SetResult = PCProp->SetValue(ParentClassObj);
|
||||
if (SetResult != FPropertyAccess::Result::Success)
|
||||
{
|
||||
if (!ParentClassObj->IsChildOf(CProp->MetaClass))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ParentClass must be child of %s.\n"),
|
||||
*WingUtils::FormatName(CProp->MetaClass));
|
||||
return;
|
||||
}
|
||||
CProp->SetObjectPropertyValue_InContainer(Factory, ParentClassObj);
|
||||
UWingServer::Printf(TEXT("ERROR: property does not allow value: %s\n"), *ParentClass);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the asset.
|
||||
// Create the asset using the factory.
|
||||
UObject *Blueprint = WingFactories::CreateAsset(Path, Factory);
|
||||
if (Blueprint == nullptr) return;
|
||||
UWingServer::Printf(TEXT("Created.\n"));
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "WingServer.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingFactories.h"
|
||||
#include "WingProperty.h"
|
||||
#include "WingPropHandle.h"
|
||||
#include "Factories/BlueprintFunctionLibraryFactory.h"
|
||||
#include "Create_UsingFactory.generated.h"
|
||||
|
||||
@@ -30,7 +30,8 @@ public:
|
||||
UFactory* CDO = Class->GetDefaultObject<UFactory>();
|
||||
if (!CDO->CanCreateNew() || !CDO->ShouldShowInNewMenu()) continue;
|
||||
|
||||
TArray<FName> ConfigProps = FWingProperty::GetNames(Class, CPF_Edit);
|
||||
WingPropHandle Props;
|
||||
TArray<TSharedPtr<IPropertyHandle>> ConfigProps = Props.AllProperties(CDO, true, CPF_Edit);
|
||||
if (ConfigProps.Num() > 0) continue;
|
||||
|
||||
FString FactoryName = WingFactories::DeriveFactoryName(Class);
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "WingServer.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingFetcher.h"
|
||||
#include "WingProperty.h"
|
||||
#include "WingTypes.h"
|
||||
#include "WingUtils.h"
|
||||
#include "Property_Dump.generated.h"
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Property_Dump : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(meta=(Description="Target object"))
|
||||
FString Object;
|
||||
|
||||
UPROPERTY(meta=(Optional, Description="Substring filter for property names"))
|
||||
FString Query;
|
||||
|
||||
UPROPERTY(meta=(Optional, Description="Only show properties declared on the object's own class, not inherited ones"))
|
||||
bool Local = false;
|
||||
|
||||
virtual void Register() override
|
||||
{
|
||||
UWingServer::AddHandler(this,
|
||||
TEXT("List all blueprint-visible properties, showing current values and which are editable."));
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
// Resolve the path to an object and get its editable template.
|
||||
WingFetcher F;
|
||||
UObject* Template = F.Walk(Object).Cast<UObject>();
|
||||
if (!Template) return;
|
||||
TArray<FWingProperty> AllProps = FWingProperty::GetDetailsImmutable(Template, CPF_Edit);
|
||||
TArray<FWingProperty> Props = FWingProperty::FindAllSubstring(AllProps, Query);
|
||||
if (Local)
|
||||
{
|
||||
UClass* ObjClass = Template->GetClass();
|
||||
Props.RemoveAll([ObjClass](const FWingProperty& P) { return P->GetOwnerStruct() != ObjClass; });
|
||||
}
|
||||
|
||||
if (Props.IsEmpty())
|
||||
{
|
||||
UWingServer::Print(TEXT(" (no blueprint-visible properties found)\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
FString CurrentCategory;
|
||||
for (FWingProperty& P : Props)
|
||||
{
|
||||
FString Category = P.GetCategory();
|
||||
if (Category != CurrentCategory)
|
||||
{
|
||||
CurrentCategory = Category;
|
||||
UWingServer::Printf(TEXT("\n%s:\n"), *CurrentCategory);
|
||||
}
|
||||
|
||||
bool bEditable = !P->HasAnyPropertyFlags(CPF_EditConst);
|
||||
UWingServer::Printf(TEXT(" %s %s %s = %s\n"),
|
||||
bEditable ? TEXT("editable") : TEXT("readonly"),
|
||||
*UWingTypes::TypeToText(P.Prop),
|
||||
*WingUtils::FormatName(P.Prop),
|
||||
*P.GetTruncatedText(100));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,46 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "WingServer.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingFetcher.h"
|
||||
#include "WingProperty.h"
|
||||
#include "WingUtils.h"
|
||||
#include "Property_Get.generated.h"
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Property_Get : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(meta=(Description="Target object"))
|
||||
FString Object;
|
||||
|
||||
UPROPERTY(meta=(Description="Property name"))
|
||||
FString Property;
|
||||
|
||||
virtual void Register() override
|
||||
{
|
||||
UWingServer::AddHandler(this,
|
||||
TEXT("Get the value of a single property."));
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
UObject* Obj = F.Walk(Object).Cast<UObject>();
|
||||
if (!Obj) return;
|
||||
|
||||
TArray<FWingProperty> All = FWingProperty::GetDetailsMutable(Obj, CPF_Edit);
|
||||
FWingProperty *P = WingUtils::FindOneWithExternalID(Property, All, TEXT("Property"));
|
||||
if (!P) return;
|
||||
|
||||
UWingServer::Print(P->GetText());
|
||||
UWingServer::Print(TEXT("\n"));
|
||||
}
|
||||
};
|
||||
@@ -1,64 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "WingServer.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingFetcher.h"
|
||||
#include "WingProperty.h"
|
||||
#include "WingUtils.h"
|
||||
#include "Property_Set.generated.h"
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
UCLASS()
|
||||
class UWing_Property_Set : public UWingHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(meta=(Description="Target object"))
|
||||
FString Object;
|
||||
|
||||
UPROPERTY(meta=(Description="Object mapping property names to new values in Unreal text format"))
|
||||
FWingJsonObject Properties;
|
||||
|
||||
virtual void Register() override
|
||||
{
|
||||
UWingServer::AddHandler(this,
|
||||
TEXT("Set one or more editable properties. Values use Unreal text format."));
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
// Resolve the path to an object and get its editable template.
|
||||
WingFetcher F;
|
||||
UObject* Obj = F.Walk(Object).Cast<UObject>();
|
||||
if (!Obj) return;
|
||||
|
||||
if (!Properties.Json || Properties.Json->Values.Num() == 0)
|
||||
{
|
||||
UWingServer::Print(TEXT("Error: No properties specified\n"));
|
||||
return;
|
||||
}
|
||||
TArray<FWingProperty> All = FWingProperty::GetDetailsMutable(Obj, CPF_Edit);
|
||||
int SuccessCount = 0;
|
||||
|
||||
// Validation pass — resolve all properties and values before modifying anything.
|
||||
for (const auto& Pair : Properties.Json->Values)
|
||||
{
|
||||
FWingProperty *P = WingUtils::FindOneWithExternalID(Pair.Key, All, TEXT("Property"));
|
||||
if (!P) return;
|
||||
}
|
||||
|
||||
// Assignment Pass - store the values.
|
||||
for (const auto& Pair : Properties.Json->Values)
|
||||
{
|
||||
FWingProperty *P = WingUtils::FindOneWithExternalID(Pair.Key, All, TEXT("Property"));
|
||||
if (P && P->SetJson(Pair.Value)) SuccessCount++;
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("Set %d/%d properties.\n"), SuccessCount, Properties.Json->Values.Num());
|
||||
}
|
||||
};
|
||||
@@ -164,7 +164,7 @@ WingPropHandle::Handles WingPropHandle::AllProperties(const UStruct* ScriptStruc
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TSharedPtr<IPropertyHandle> WingPropHandle::NamedProperty(Root& Root, FName Name, bool RootFilter)
|
||||
TSharedPtr<IPropertyHandle> WingPropHandle::TryNamedProperty(Root& Root, FName Name, bool RootFilter)
|
||||
{
|
||||
for (IDetailTreeNode* Node : AllTreeNodes(Root))
|
||||
{
|
||||
@@ -176,16 +176,32 @@ TSharedPtr<IPropertyHandle> WingPropHandle::NamedProperty(Root& Root, FName Name
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TSharedPtr<IPropertyHandle> WingPropHandle::NamedProperty(UObject* Obj, FName Name, bool RootFilter)
|
||||
TSharedPtr<IPropertyHandle> WingPropHandle::TryNamedProperty(UObject* Obj, FName Name, bool RootFilter)
|
||||
{
|
||||
if (!Obj) return nullptr;
|
||||
return NamedProperty(GetRootForObject(Obj), Name, RootFilter);
|
||||
return TryNamedProperty(GetRootForObject(Obj), Name, RootFilter);
|
||||
}
|
||||
|
||||
TSharedPtr<IPropertyHandle> WingPropHandle::TryNamedProperty(const UStruct* ScriptStruct, uint8* Data, FName Name, bool RootFilter)
|
||||
{
|
||||
if (!ScriptStruct || !Data) return nullptr;
|
||||
return TryNamedProperty(GetRootForStruct(ScriptStruct, Data), Name, RootFilter);
|
||||
}
|
||||
|
||||
TSharedPtr<IPropertyHandle> WingPropHandle::NamedProperty(UObject* Obj, FName Name, bool RootFilter)
|
||||
{
|
||||
TSharedPtr<IPropertyHandle> Result = TryNamedProperty(Obj, Name, RootFilter);
|
||||
if (!Result)
|
||||
UWingServer::Printf(TEXT("ERROR: Property '%s' not found\n"), *Name.ToString());
|
||||
return Result;
|
||||
}
|
||||
|
||||
TSharedPtr<IPropertyHandle> WingPropHandle::NamedProperty(const UStruct* ScriptStruct, uint8* Data, FName Name, bool RootFilter)
|
||||
{
|
||||
if (!ScriptStruct || !Data) return nullptr;
|
||||
return NamedProperty(GetRootForStruct(ScriptStruct, Data), Name, RootFilter);
|
||||
TSharedPtr<IPropertyHandle> Result = TryNamedProperty(ScriptStruct, Data, Name, RootFilter);
|
||||
if (!Result)
|
||||
UWingServer::Printf(TEXT("ERROR: Property '%s' not found\n"), *Name.ToString());
|
||||
return Result;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -36,10 +36,14 @@ public:
|
||||
|
||||
// Get a single named property from a UObject.
|
||||
// If RootFilter is true, only properties inside the root object are returned.
|
||||
TSharedPtr<IPropertyHandle> NamedProperty(UObject* Obj, FName Name, bool RootFilter);
|
||||
TSharedPtr<IPropertyHandle> TryNamedProperty(UObject* Obj, FName Name, bool RootFilter);
|
||||
|
||||
// Get a single named property from a struct.
|
||||
// If RootFilter is true, only properties inside the root object are returned.
|
||||
TSharedPtr<IPropertyHandle> TryNamedProperty(const UStruct* ScriptStruct, uint8* Data, FName Name, bool RootFilter);
|
||||
|
||||
// Like TryNamedProperty, but prints an error if the property is not found.
|
||||
TSharedPtr<IPropertyHandle> NamedProperty(UObject* Obj, FName Name, bool RootFilter);
|
||||
TSharedPtr<IPropertyHandle> NamedProperty(const UStruct* ScriptStruct, uint8* Data, FName Name, bool RootFilter);
|
||||
|
||||
// Get "details panel" properties for an object. Handles special
|
||||
@@ -79,5 +83,5 @@ private:
|
||||
static FlatTree AllTreeNodes(Root& Root);
|
||||
|
||||
Handles AllProperties(Root& Root, bool RootFilter, EPropertyFlags Filter);
|
||||
static TSharedPtr<IPropertyHandle> NamedProperty(Root& Root, FName Name, bool RootFilter);
|
||||
static TSharedPtr<IPropertyHandle> TryNamedProperty(Root& Root, FName Name, bool RootFilter);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user