diff --git a/Integration.code-workspace.tpl.json b/Integration.code-workspace.tpl.json index db312414..473218d4 100644 --- a/Integration.code-workspace.tpl.json +++ b/Integration.code-workspace.tpl.json @@ -50,6 +50,9 @@ ], "C_Cpp.autocomplete": "disabled", "search.useIgnoreFiles": true, + "files.readonlyInclude": { + "[UNREALENGINE]/**": true + }, "search.exclude": { "**/Intermediate": true, "**/Saved": true, diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/Create_ClassArg.h b/Plugins/UEWingman/Source/UEWingman/Handlers/Create_ClassArg.h index bdec7f89..f726b4f0 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/Create_ClassArg.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/Create_ClassArg.h @@ -281,7 +281,7 @@ public: } // Set the 'Class' property. - TArray Props = FWingProperty::GetVisible(Factory); + TArray Props = FWingProperty::GetVisible(Factory, true); FWingProperty::Remove(Props, TEXT("BlueprintType")); if (Props.Num() != 1) { diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_Add.h b/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_Add.h index 29b7af7a..c139fb9c 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_Add.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_Add.h @@ -65,7 +65,7 @@ public: // Parse the json array, turning it into an array of spawn node entries. TArray Entries; FSpawnNodeEntry Entry; - TArray Props = FWingProperty::GetAll(&Entry); + TArray Props = FWingProperty::GetAll(nullptr, &Entry, FSpawnNodeEntry::StaticStruct(), true); for (const TSharedPtr& Elt : Nodes.Array) { if (!FWingProperty::PopulateFromJson(Props, *Elt, false, WingOut::Stdout)) return; diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_SetDefaults.h b/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_SetDefaults.h index ef0ae128..da6ac140 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_SetDefaults.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_SetDefaults.h @@ -123,7 +123,7 @@ public: } FSetNodeDefaultEntry Entry; - TArray Props = FWingProperty::GetAll(&Entry); + TArray Props = FWingProperty::GetAll(nullptr, &Entry, FSetNodeDefaultEntry::StaticStruct(), true); for (const TSharedPtr& PinVal : Pins.Array) { if (!FWingProperty::PopulateFromJson(Props, *PinVal, false, WingOut::Stdout)) continue; diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_SetPositions.h b/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_SetPositions.h index d4b398af..8e7daa93 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_SetPositions.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_SetPositions.h @@ -56,7 +56,7 @@ public: int32 SuccessCount = 0; FMoveNodeEntry Entry; - TArray Props = FWingProperty::GetAll(&Entry); + TArray Props = FWingProperty::GetAll(nullptr, &Entry, FMoveNodeEntry::StaticStruct(), true); for (const TSharedPtr& Elt : Nodes.Array) { if (!FWingProperty::PopulateFromJson(Props, *Elt, false, WingOut::Stdout)) continue; diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/GraphPin_Connect.h b/Plugins/UEWingman/Source/UEWingman/Handlers/GraphPin_Connect.h index c8badf4a..823e9c74 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/GraphPin_Connect.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/GraphPin_Connect.h @@ -58,7 +58,7 @@ public: int32 TotalCount = Connections.Array.Num(); FConnectPinsEntry Entry; - TArray EntryProps = FWingProperty::GetAll(&Entry); + TArray EntryProps = FWingProperty::GetAll(nullptr, &Entry, FConnectPinsEntry::StaticStruct(), true); for (const TSharedPtr& ConnVal : Connections.Array) { if (!FWingProperty::PopulateFromJson(EntryProps, *ConnVal, false, WingOut::Stdout)) diff --git a/Plugins/UEWingman/Source/UEWingman/Private/WingFetcher.cpp b/Plugins/UEWingman/Source/UEWingman/Private/WingFetcher.cpp index 63d295f8..35733f1e 100644 --- a/Plugins/UEWingman/Source/UEWingman/Private/WingFetcher.cpp +++ b/Plugins/UEWingman/Source/UEWingman/Private/WingFetcher.cpp @@ -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 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(Obj.Get())) + if (FStructProperty *FSProp = CastField(WProp->Prop)) { - HostObject = SPtr->Object; - HostBase = SPtr->StructBase; - HostType = SPtr->StructType; - HostEditable = SPtr->Editable; + UWingStructRef* Ptr = NewObject(); + Ptr->Object = WProp->Object.Get(); + Ptr->StructType = FSProp->Struct; + Ptr->StructBase = FSProp->ContainerPtrToValuePtr(WProp->Container); + Ptr->Editable = WProp->Editable; + SetObj(Ptr); + return *this; } - - StructProp = FindFProperty(HostType, InternalID); - if (!StructProp) + else { - Errors.Printf(TEXT("ERROR: No struct property '%s' found on %s\n"), *Value, *HostType->GetName()); + Errors.Printf(TEXT("Property %s is not a struct property.\n"), + *WProp->Prop->GetName()); return SetError(); } - - UWingStructRef* Ptr = NewObject(); - Ptr->Object = HostObject; - Ptr->StructType = StructProp->Struct; - Ptr->StructBase = StructProp->ContainerPtrToValuePtr(HostBase); - Ptr->Editable = HostEditable && StructProp->HasAllPropertyFlags(CPF_Edit); - SetObj(Ptr); - return *this; } diff --git a/Plugins/UEWingman/Source/UEWingman/Private/WingParameterEditor.cpp b/Plugins/UEWingman/Source/UEWingman/Private/WingParameterEditor.cpp index 052a02a8..e405ff5d 100644 --- a/Plugins/UEWingman/Source/UEWingman/Private/WingParameterEditor.cpp +++ b/Plugins/UEWingman/Source/UEWingman/Private/WingParameterEditor.cpp @@ -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); } diff --git a/Plugins/UEWingman/Source/UEWingman/Private/WingProperty.cpp b/Plugins/UEWingman/Source/UEWingman/Private/WingProperty.cpp index 7510252b..78b4741c 100644 --- a/Plugins/UEWingman/Source/UEWingman/Private/WingProperty.cpp +++ b/Plugins/UEWingman/Source/UEWingman/Private/WingProperty.cpp @@ -378,25 +378,25 @@ FString FWingProperty::GetCategory() const return Result; } -TArray FWingProperty::GetAll(FWingStructAndUStruct Obj) +TArray FWingProperty::GetAll(UObject *Obj, void *Container, UStruct *Struct, bool Mutable) { TArray Result; - for (TFieldIterator It(Obj.UStructPtr); It; ++It) + for (TFieldIterator 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::GetVisible(FWingStructAndUStruct Obj) +TArray FWingProperty::GetVisible(UObject *Obj, void *Container, UStruct *Struct, bool Mutable) { TArray Result; - for (TFieldIterator It(Obj.UStructPtr); It; ++It) + for (TFieldIterator 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::GetDetails(UObject* Obj, bool Mutable) // of the struct instead. Propagate editability of the host. if (UWingStructRef *SP = Cast(Obj)) { - TArray 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::GetDetails(UObject* Obj, bool Mutable) } } - TArray Result = GetVisible(Obj); + TArray 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::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::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 &Props) -{ - for (FWingProperty &Elt : Props) Elt.Editable = false; -} - bool FWingProperty::CheckEditable(WingOut Errors) const { if (!Editable) diff --git a/Plugins/UEWingman/Source/UEWingman/Private/WingServer.cpp b/Plugins/UEWingman/Source/UEWingman/Private/WingServer.cpp index 9f9cf5bd..9a5a582a 100644 --- a/Plugins/UEWingman/Source/UEWingman/Private/WingServer.cpp +++ b/Plugins/UEWingman/Source/UEWingman/Private/WingServer.cpp @@ -297,7 +297,7 @@ void UWingServer::TryCallHandler(TSharedPtr Request) Handler->Configuration = Found; // Populate the handler object with the request parameters. - TArray Props = FWingProperty::GetVisible(Handler); + TArray Props = FWingProperty::GetVisible(Handler, true); if (!FWingProperty::PopulateFromJson(Props, *Request, false, WingOut::Stdout)) { UWingServer::SuggestHandlerHelp(); diff --git a/Plugins/UEWingman/Source/UEWingman/Private/WingVariables.cpp b/Plugins/UEWingman/Source/UEWingman/Private/WingVariables.cpp index 9dbc1902..7bcf3d05 100644 --- a/Plugins/UEWingman/Source/UEWingman/Private/WingVariables.cpp +++ b/Plugins/UEWingman/Source/UEWingman/Private/WingVariables.cpp @@ -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; diff --git a/Plugins/UEWingman/Source/UEWingman/Public/WingBasics.h b/Plugins/UEWingman/Source/UEWingman/Public/WingBasics.h index 5f46f227..893f47b8 100644 --- a/Plugins/UEWingman/Source/UEWingman/Public/WingBasics.h +++ b/Plugins/UEWingman/Source/UEWingman/Public/WingBasics.h @@ -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>> - FWingStructAndUStruct(T *Struct) : StructPtr(Struct), UStructPtr(Struct->StaticStruct()) {} -}; - - //////////////////////////////////////////////////////////// // // References. @@ -224,11 +192,11 @@ class UWingStructRef : public UObject public: UPROPERTY() UObject* Object; - + + void *StructBase; + UPROPERTY() UStruct* StructType; - - void *StructBase; bool Editable; }; diff --git a/Plugins/UEWingman/Source/UEWingman/Public/WingProperty.h b/Plugins/UEWingman/Source/UEWingman/Public/WingProperty.h index e167748f..5084258f 100644 --- a/Plugins/UEWingman/Source/UEWingman/Public/WingProperty.h +++ b/Plugins/UEWingman/Source/UEWingman/Public/WingProperty.h @@ -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 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 GetAll(FWingStructAndUStruct Obj); + static TArray 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 GetVisible(FWingStructAndUStruct Obj); + static TArray GetVisible(UObject *Obj, void *Container, UStruct *Struct, bool Mutable); + + // Convenience versions of GetAll and GetVisible for UObjects. + // + static TArray GetAll(UObject *Obj, bool Mutable) + { return GetAll(Obj, Obj, Obj->GetClass(), Mutable); } + static TArray 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 &Props); static bool IsUnsigned(FNumericProperty* Prop); static bool IsPinTypeProperty(FProperty *Prop); void PrintExpectsReceived(const TCHAR *Type, WingOut Errors) const;