WingProperty now contains an object pointer. This made it possible to implement structprop a lot better, it now can dig into objects it couldn't dig into before, including structprop-within-structprop
This commit is contained in:
@@ -50,6 +50,9 @@
|
||||
],
|
||||
"C_Cpp.autocomplete": "disabled",
|
||||
"search.useIgnoreFiles": true,
|
||||
"files.readonlyInclude": {
|
||||
"[UNREALENGINE]/**": true
|
||||
},
|
||||
"search.exclude": {
|
||||
"**/Intermediate": true,
|
||||
"**/Saved": true,
|
||||
|
||||
@@ -281,7 +281,7 @@ public:
|
||||
}
|
||||
|
||||
// Set the 'Class' property.
|
||||
TArray<FWingProperty> Props = FWingProperty::GetVisible(Factory);
|
||||
TArray<FWingProperty> Props = FWingProperty::GetVisible(Factory, true);
|
||||
FWingProperty::Remove(Props, TEXT("BlueprintType"));
|
||||
if (Props.Num() != 1)
|
||||
{
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
// Parse the json array, turning it into an array of spawn node entries.
|
||||
TArray<FSpawnNodeEntry> Entries;
|
||||
FSpawnNodeEntry Entry;
|
||||
TArray<FWingProperty> Props = FWingProperty::GetAll(&Entry);
|
||||
TArray<FWingProperty> Props = FWingProperty::GetAll(nullptr, &Entry, FSpawnNodeEntry::StaticStruct(), true);
|
||||
for (const TSharedPtr<FJsonValue>& Elt : Nodes.Array)
|
||||
{
|
||||
if (!FWingProperty::PopulateFromJson(Props, *Elt, false, WingOut::Stdout)) return;
|
||||
|
||||
@@ -123,7 +123,7 @@ public:
|
||||
}
|
||||
|
||||
FSetNodeDefaultEntry Entry;
|
||||
TArray<FWingProperty> Props = FWingProperty::GetAll(&Entry);
|
||||
TArray<FWingProperty> Props = FWingProperty::GetAll(nullptr, &Entry, FSetNodeDefaultEntry::StaticStruct(), true);
|
||||
for (const TSharedPtr<FJsonValue>& PinVal : Pins.Array)
|
||||
{
|
||||
if (!FWingProperty::PopulateFromJson(Props, *PinVal, false, WingOut::Stdout)) continue;
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
int32 SuccessCount = 0;
|
||||
|
||||
FMoveNodeEntry Entry;
|
||||
TArray<FWingProperty> Props = FWingProperty::GetAll(&Entry);
|
||||
TArray<FWingProperty> Props = FWingProperty::GetAll(nullptr, &Entry, FMoveNodeEntry::StaticStruct(), true);
|
||||
for (const TSharedPtr<FJsonValue>& Elt : Nodes.Array)
|
||||
{
|
||||
if (!FWingProperty::PopulateFromJson(Props, *Elt, false, WingOut::Stdout)) continue;
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
int32 TotalCount = Connections.Array.Num();
|
||||
|
||||
FConnectPinsEntry Entry;
|
||||
TArray<FWingProperty> EntryProps = FWingProperty::GetAll(&Entry);
|
||||
TArray<FWingProperty> EntryProps = FWingProperty::GetAll(nullptr, &Entry, FConnectPinsEntry::StaticStruct(), true);
|
||||
for (const TSharedPtr<FJsonValue>& ConnVal : Connections.Array)
|
||||
{
|
||||
if (!FWingProperty::PopulateFromJson(EntryProps, *ConnVal, false, WingOut::Stdout))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "WingFetcher.h"
|
||||
#include "WingServer.h"
|
||||
#include "WingBasics.h"
|
||||
#include "WingProperty.h"
|
||||
#include "WingUtils.h"
|
||||
#include "WingComponent.h"
|
||||
#include "Engine/Blueprint.h"
|
||||
@@ -368,36 +369,27 @@ WingFetcher& WingFetcher::StructProp(const FString& Value)
|
||||
return SetError();
|
||||
}
|
||||
|
||||
FStructProperty* StructProp = nullptr;
|
||||
TArray<FWingProperty> Details =
|
||||
FWingProperty::GetDetails(Obj.Get(), true);
|
||||
|
||||
// The "host" is the object containing this property.
|
||||
UObject *HostObject = Obj.Get();
|
||||
void *HostBase = Obj.Get();
|
||||
UStruct *HostType = Obj.Get()->GetClass();
|
||||
bool HostEditable = true;
|
||||
FWingProperty *WProp = WingUtils::FindOneWithInternalID(
|
||||
InternalID, Details, TEXT("Property"), WingOut::Stdout);
|
||||
if (!WProp) return SetError();
|
||||
|
||||
// If we are *already* inside a UWingStructRef, update the host
|
||||
// fields, to make it possible to navigate even further inside.
|
||||
if (UWingStructRef *SPtr = ::Cast<UWingStructRef>(Obj.Get()))
|
||||
if (FStructProperty *FSProp = CastField<FStructProperty>(WProp->Prop))
|
||||
{
|
||||
HostObject = SPtr->Object;
|
||||
HostBase = SPtr->StructBase;
|
||||
HostType = SPtr->StructType;
|
||||
HostEditable = SPtr->Editable;
|
||||
}
|
||||
|
||||
StructProp = FindFProperty<FStructProperty>(HostType, InternalID);
|
||||
if (!StructProp)
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: No struct property '%s' found on %s\n"), *Value, *HostType->GetName());
|
||||
return SetError();
|
||||
}
|
||||
|
||||
UWingStructRef* Ptr = NewObject<UWingStructRef>();
|
||||
Ptr->Object = HostObject;
|
||||
Ptr->StructType = StructProp->Struct;
|
||||
Ptr->StructBase = StructProp->ContainerPtrToValuePtr<void>(HostBase);
|
||||
Ptr->Editable = HostEditable && StructProp->HasAllPropertyFlags(CPF_Edit);
|
||||
Ptr->Object = WProp->Object.Get();
|
||||
Ptr->StructType = FSProp->Struct;
|
||||
Ptr->StructBase = FSProp->ContainerPtrToValuePtr<void>(WProp->Container);
|
||||
Ptr->Editable = WProp->Editable;
|
||||
SetObj(Ptr);
|
||||
return *this;
|
||||
}
|
||||
else
|
||||
{
|
||||
Errors.Printf(TEXT("Property %s is not a struct property.\n"),
|
||||
*WProp->Prop->GetName());
|
||||
return SetError();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@ bool FWingParameterEditor::AddOverride(
|
||||
|
||||
// Parse the value string.
|
||||
FWingParameterEditor Editor;
|
||||
if (!FWingProperty(GS->Property, &Editor, true).SetText(StrVal, Errors)) return false;
|
||||
if (!FWingProperty(nullptr, &Editor, GS->Property, true).SetText(StrVal, Errors)) return false;
|
||||
Meta->Value = GS->Getter(Editor);
|
||||
|
||||
// Apply the update.
|
||||
@@ -308,7 +308,7 @@ void FWingParameterEditor::Print(const Info &ID, const Metadata &Meta)
|
||||
}
|
||||
FWingParameterEditor Editor;
|
||||
GS->Setter(Editor, Meta.Value);
|
||||
FString StrVal = FWingProperty(GS->Property, &Editor, false).GetText();
|
||||
FString StrVal = FWingProperty(nullptr, &Editor, GS->Property, false).GetText();
|
||||
WingOut::Stdout.Printf(TEXT(" %s %s\n"),
|
||||
*StringID(ID), *StrVal);
|
||||
}
|
||||
|
||||
@@ -378,25 +378,25 @@ FString FWingProperty::GetCategory() const
|
||||
return Result;
|
||||
}
|
||||
|
||||
TArray<FWingProperty> FWingProperty::GetAll(FWingStructAndUStruct Obj)
|
||||
TArray<FWingProperty> FWingProperty::GetAll(UObject *Obj, void *Container, UStruct *Struct, bool Mutable)
|
||||
{
|
||||
TArray<FWingProperty> Result;
|
||||
for (TFieldIterator<FProperty> It(Obj.UStructPtr); It; ++It)
|
||||
for (TFieldIterator<FProperty> It(Struct); It; ++It)
|
||||
{
|
||||
bool Editable = !It->HasAnyPropertyFlags(CPF_EditConst);
|
||||
Result.Add(FWingProperty(*It, Obj.StructPtr, Editable));
|
||||
bool Editable = Mutable && !It->HasAnyPropertyFlags(CPF_EditConst);
|
||||
Result.Emplace(Obj, Container, *It, Editable);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
TArray<FWingProperty> FWingProperty::GetVisible(FWingStructAndUStruct Obj)
|
||||
TArray<FWingProperty> FWingProperty::GetVisible(UObject *Obj, void *Container, UStruct *Struct, bool Mutable)
|
||||
{
|
||||
TArray<FWingProperty> Result;
|
||||
for (TFieldIterator<FProperty> It(Obj.UStructPtr); It; ++It)
|
||||
for (TFieldIterator<FProperty> It(Struct); It; ++It)
|
||||
{
|
||||
if (!It->HasAllPropertyFlags(CPF_Edit)) continue;
|
||||
bool Editable = !It->HasAnyPropertyFlags(CPF_EditConst);
|
||||
Result.Add(FWingProperty(*It, Obj.StructPtr, Editable));
|
||||
bool Editable = Mutable && !It->HasAnyPropertyFlags(CPF_EditConst);
|
||||
Result.Emplace(Obj, Container, *It, Editable);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
@@ -436,10 +436,8 @@ TArray<FWingProperty> FWingProperty::GetDetails(UObject* Obj, bool Mutable)
|
||||
// of the struct instead. Propagate editability of the host.
|
||||
if (UWingStructRef *SP = Cast<UWingStructRef>(Obj))
|
||||
{
|
||||
TArray<FWingProperty> Result =
|
||||
GetVisible(FWingStructAndUStruct(SP->StructBase, SP->StructType));
|
||||
if (!Mutable || (!SP->Editable)) StripEditable(Result);
|
||||
return Result;
|
||||
return GetVisible(SP->Object, SP->StructBase,
|
||||
SP->StructType, Mutable && SP->Editable);
|
||||
}
|
||||
|
||||
// Blueprints don't have editable properties. So
|
||||
@@ -465,7 +463,7 @@ TArray<FWingProperty> FWingProperty::GetDetails(UObject* Obj, bool Mutable)
|
||||
}
|
||||
}
|
||||
|
||||
TArray<FWingProperty> Result = GetVisible(Obj);
|
||||
TArray<FWingProperty> Result = GetVisible(Obj, Mutable);
|
||||
|
||||
// If it's a Material Graph node, also collect properties from
|
||||
// the associated material expression.
|
||||
@@ -474,7 +472,7 @@ TArray<FWingProperty> FWingProperty::GetDetails(UObject* Obj, bool Mutable)
|
||||
{
|
||||
if (UMaterialExpression* Expr = MatNode->MaterialExpression)
|
||||
{
|
||||
Result.Append(GetVisible(Expr));
|
||||
Result.Append(GetVisible(Expr, Mutable));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -486,13 +484,12 @@ TArray<FWingProperty> FWingProperty::GetDetails(UObject* Obj, bool Mutable)
|
||||
FWingProperty::Remove(Result, TEXT("Slot"));
|
||||
if (UPanelSlot* Slot = Widget->Slot)
|
||||
{
|
||||
Result.Append(GetVisible(Slot));
|
||||
Result.Append(GetVisible(Slot, Mutable));
|
||||
}
|
||||
FProperty *VarProp = Widget->GetClass()->FindPropertyByName(TEXT("bIsVariable"));
|
||||
if (VarProp) Result.Add(FWingProperty(VarProp, Widget, true));
|
||||
if (VarProp) Result.Emplace(Widget, Widget, VarProp, true);
|
||||
}
|
||||
|
||||
if (!Mutable) StripEditable(Result);
|
||||
return Result;
|
||||
}
|
||||
|
||||
@@ -580,11 +577,6 @@ bool FWingProperty::CheckImportTextResult(const FString &Value, WingOut Errors)
|
||||
return true;
|
||||
}
|
||||
|
||||
void FWingProperty::StripEditable(TArray<FWingProperty> &Props)
|
||||
{
|
||||
for (FWingProperty &Elt : Props) Elt.Editable = false;
|
||||
}
|
||||
|
||||
bool FWingProperty::CheckEditable(WingOut Errors) const
|
||||
{
|
||||
if (!Editable)
|
||||
|
||||
@@ -297,7 +297,7 @@ void UWingServer::TryCallHandler(TSharedPtr<FJsonObject> Request)
|
||||
Handler->Configuration = Found;
|
||||
|
||||
// Populate the handler object with the request parameters.
|
||||
TArray<FWingProperty> Props = FWingProperty::GetVisible(Handler);
|
||||
TArray<FWingProperty> Props = FWingProperty::GetVisible(Handler, true);
|
||||
if (!FWingProperty::PopulateFromJson(Props, *Request, false, WingOut::Stdout))
|
||||
{
|
||||
UWingServer::SuggestHandlerHelp();
|
||||
|
||||
@@ -325,7 +325,7 @@ WingVariables::Var WingVariables::LoadBlueprintVariableDescription(FBPVariableDe
|
||||
FProperty* Prop = CDO->GetClass()->FindPropertyByName(Desc.VarName);
|
||||
if (Prop)
|
||||
{
|
||||
Result.DefaultValue = FWingProperty(Prop, CDO, false).GetText();
|
||||
Result.DefaultValue = FWingProperty(CDO, CDO, Prop, false).GetText();
|
||||
Result.DefaultSpecified = true;
|
||||
}
|
||||
}
|
||||
@@ -500,7 +500,7 @@ bool WingVariables::ModifyBlueprintDefaults(WingOut Errors)
|
||||
*WingTokenizer::ExternalizeID(Input.Name));
|
||||
return false;
|
||||
}
|
||||
if (!FWingProperty(Prop, CDO, true).SetText(Input.DefaultValue, Errors)) return false;
|
||||
if (!FWingProperty(CDO, CDO, Prop, true).SetText(Input.DefaultValue, Errors)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -129,38 +129,6 @@ private:
|
||||
FStringBuilderBase *Buffer;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// FWingStructAndUStruct.
|
||||
//
|
||||
// A pointer to a struct, and also a pointer to a UStruct
|
||||
// that describes the struct. This also can store a
|
||||
// UObject and the UClass that describes the UObject.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
// A FWingStructAndUStruct is a pointer to a struct and its associated ustruct.
|
||||
//
|
||||
struct FWingStructAndUStruct
|
||||
{
|
||||
void *StructPtr;
|
||||
UStruct *UStructPtr;
|
||||
|
||||
// Explicit constructor.
|
||||
explicit FWingStructAndUStruct(void *Base, UStruct *S) : StructPtr(Base), UStructPtr(S) {}
|
||||
|
||||
// Copy constructor.
|
||||
FWingStructAndUStruct(FWingStructAndUStruct &Src) : StructPtr(Src.StructPtr), UStructPtr(Src.UStructPtr) {}
|
||||
|
||||
// Construct from a UObject.
|
||||
FWingStructAndUStruct(UObject *Obj) : StructPtr(Obj), UStructPtr(Obj->GetClass()) {}
|
||||
|
||||
// Construct from a UStruct pointer.
|
||||
template<class T, typename = std::enable_if_t<!std::is_base_of_v<UObject, T>>>
|
||||
FWingStructAndUStruct(T *Struct) : StructPtr(Struct), UStructPtr(Struct->StaticStruct()) {}
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// References.
|
||||
@@ -225,10 +193,10 @@ public:
|
||||
UPROPERTY()
|
||||
UObject* Object;
|
||||
|
||||
void *StructBase;
|
||||
|
||||
UPROPERTY()
|
||||
UStruct* StructType;
|
||||
|
||||
void *StructBase;
|
||||
|
||||
bool Editable;
|
||||
};
|
||||
|
||||
@@ -3,20 +3,24 @@
|
||||
#include "CoreMinimal.h"
|
||||
#include "WingBasics.h"
|
||||
|
||||
// A resolved property: the FProperty descriptor plus a pointer to
|
||||
// the value's storage.
|
||||
//
|
||||
struct FWingProperty
|
||||
{
|
||||
// To understand the following fields, imagine an object
|
||||
// that contains a struct, which contains another struct,
|
||||
// which contains another struct, which contains a field F.
|
||||
// In that case, Object points to the object that
|
||||
// contains everything, whereas Container points to the
|
||||
// innermost struct that contains the property.
|
||||
|
||||
FProperty* Prop = nullptr;
|
||||
TStrongObjectPtr<UObject> Object = nullptr;
|
||||
void* Container = nullptr;
|
||||
FProperty* Prop = nullptr;
|
||||
bool Editable = false;
|
||||
|
||||
// Construct a property reference.
|
||||
//
|
||||
FWingProperty(FProperty* InProp, void* InContainer, bool Edit)
|
||||
: Prop(InProp), Container(InContainer), Editable(Edit) {}
|
||||
FWingProperty(UObject *InObject, void* InContainer, FProperty* InProp, bool Edit)
|
||||
: Object(InObject), Container(InContainer), Prop(InProp), Editable(Edit) {}
|
||||
|
||||
// Construct a null property reference.
|
||||
//
|
||||
@@ -72,14 +76,23 @@ struct FWingProperty
|
||||
//
|
||||
// This gets the properties that are literally present in the
|
||||
// specified object or struct. No special interpretation is done.
|
||||
// If mutable is false, all properties will be marked non-editable.
|
||||
//
|
||||
static TArray<FWingProperty> GetAll(FWingStructAndUStruct Obj);
|
||||
static TArray<FWingProperty> GetAll(UObject *Obj, void *Container, UStruct *Struct, bool Mutable);
|
||||
|
||||
// Get all the visible properties of the specified object or struct.
|
||||
//
|
||||
// This gets the properties that have CPF_Edit marked on them.
|
||||
// If mutable is false, all properties will be marked non-editable.
|
||||
//
|
||||
static TArray<FWingProperty> GetVisible(FWingStructAndUStruct Obj);
|
||||
static TArray<FWingProperty> GetVisible(UObject *Obj, void *Container, UStruct *Struct, bool Mutable);
|
||||
|
||||
// Convenience versions of GetAll and GetVisible for UObjects.
|
||||
//
|
||||
static TArray<FWingProperty> GetAll(UObject *Obj, bool Mutable)
|
||||
{ return GetAll(Obj, Obj, Obj->GetClass(), Mutable); }
|
||||
static TArray<FWingProperty> GetVisible(UObject *Obj, bool Mutable)
|
||||
{ return GetVisible(Obj, Obj, Obj->GetClass(), Mutable); }
|
||||
|
||||
// Get just the names of the properties of the specified struct/class.
|
||||
//
|
||||
@@ -119,7 +132,6 @@ struct FWingProperty
|
||||
//
|
||||
|
||||
private:
|
||||
static void StripEditable(TArray<FWingProperty> &Props);
|
||||
static bool IsUnsigned(FNumericProperty* Prop);
|
||||
static bool IsPinTypeProperty(FProperty *Prop);
|
||||
void PrintExpectsReceived(const TCHAR *Type, WingOut Errors) const;
|
||||
|
||||
Reference in New Issue
Block a user