// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Framework/PropertyViewer/FieldIconFinder.h" #include "Framework/PropertyViewer/PropertyPath.h" #include "Widgets/PropertyViewer/SPropertyViewer.h" #include "Types/SlateEnums.h" #include "UObject/Field.h" #include "UObject/Object.h" #include "UObject/WeakObjectPtrTemplates.h" class ITableRow; class SSearchBox; class STableViewBase; template class STreeView; template class TreeFilterHandler; template class TTextFilter; namespace UE::PropertyViewer { class IFieldIterator; class IFieldExpander; class SFieldName; } namespace UE::PropertyViewer::Private { /** * FContainer */ struct FContainer { FContainer(SPropertyViewer::FHandle InIdentifier, TOptional DisplayName, const UStruct* ClassToDisplay); FContainer(SPropertyViewer::FHandle InIdentifier, TOptional DisplayName, UObject* InstanceToDisplay); FContainer(SPropertyViewer::FHandle InIdentifier, TOptional DisplayName, const UScriptStruct* Struct, void* Data); public: SPropertyViewer::FHandle GetIdentifier() const { return Identifier; } void* GetBuffer() const { UObject* PinObjectInstance = ObjectInstance.Get(); return bIsObject ? reinterpret_cast(PinObjectInstance) : StructInstance; } const UStruct* GetStruct() { return Container.Get(); } bool CanEdit() const { return GetBuffer() != nullptr; } bool IsInstance() const { return GetBuffer() != nullptr; } bool IsObjectInstance() const { return bIsObject; } UObject* GetObjectInstance() const { return ObjectInstance.Get(); } bool IsScriptStructInstance() const { return StructInstance != nullptr; } void* GetScriptStructInstance() const { return StructInstance; } TOptional GetDisplayName() const { return DisplayName; } bool IsValid() const; private: SPropertyViewer::FHandle Identifier; TWeakObjectPtr Container; TWeakObjectPtr ObjectInstance; void* StructInstance = nullptr; TOptional DisplayName; bool bIsObject = false; }; /** * FTreeNode */ struct FTreeNode : public TSharedFromThis { public: static TSharedRef MakeContainer(const TSharedPtr& InContainer, TOptional InDisplayName); static TSharedRef MakeField(TSharedPtr InParent, const FProperty* Property, TOptional InDisplayName); static TSharedRef MakeField(TSharedPtr InParent, const UFunction* Function, TOptional InDisplayName); private: TWeakPtr ParentNode; //Either a container, property or function TWeakPtr Container; TWeakObjectPtr FieldOwner; FName PropertyName; FName FunctionName; bool bIsStructProperty = false; bool bIsObjectProperty = false; TOptional OverrideDisplayName; public: TWeakPtr PropertyWidget; TArray, TInlineAllocator<1>> ChildNodes; bool bChildGenerated = false; public: bool IsContainer() const { return Container.IsValid(); } TSharedPtr GetContainer() const { return Container.Pin(); } bool IsField() const { return !PropertyName.IsNone() || !FunctionName.IsNone(); } FFieldVariant GetField() const; TSharedPtr GetParentNode() const { return ParentNode.Pin(); } FPropertyPath GetPropertyPath() const; TArray GetFieldPath() const; TSharedPtr GetOwnerContainer() const; TOptional GetOverrideDisplayName() const { return OverrideDisplayName; } void GetFilterStrings(TArray& OutStrings) const; struct FNodeReference { TWeakObjectPtr Previous; TWeakPtr Node; FNodeReference(UObject* InPrevious, const TWeakPtr& InNode) : Previous(InPrevious) , Node(InNode) {} }; // Returns the object node that was build TArray BuildChildNodes(IFieldIterator& FieldIterator, IFieldExpander& FieldExpander, bool bSortChildNode); void RemoveChild() { ChildNodes.Reset(); bChildGenerated = false; } private: void BuildChildNodesRecursive(IFieldIterator& FieldIterator, IFieldExpander& FieldExpander, bool bSortChildNode, int32 RecursiveCount, TArray& OutTickReference); static bool Sort(const TSharedPtr& NodeA, const TSharedPtr& NodeB); }; /** * FPropertyViewerImpl */ class FPropertyViewerImpl : public TSharedFromThis { public: FPropertyViewerImpl(const SPropertyViewer::FArguments& InArgs); FPropertyViewerImpl(const FPropertyViewerImpl&) = delete; FPropertyViewerImpl& operator=(const FPropertyViewerImpl&) = delete; ~FPropertyViewerImpl(); private: TArray> Containers; TArray NodeReferences; TSharedPtr SearchBoxWidget; TSharedPtr>> TreeWidget; TArray> TreeSource; TArray> FilteredTreeSource; using FTextFilter = TTextFilter>; TSharedPtr SearchFilter; using FTreeFilter = TreeFilterHandler>; TSharedPtr FilterHandler; SPropertyViewer::FGetFieldWidget OnGetPreSlot; SPropertyViewer::FGetFieldWidget OnGetPostSlot; SPropertyViewer::FOnContextMenuOpening OnContextMenuOpening; SPropertyViewer::FOnSelectionChanged OnSelectionChanged; SPropertyViewer::FOnDoubleClicked OnDoubleClicked; SPropertyViewer::FOnDragDetected OnDragDetected; SPropertyViewer::FOnGenerateContainer OnGenerateContainer; SPropertyViewer::EPropertyVisibility PropertyVisibility; TOptional OverrideIconColorSettings; bool bSanitizeName = false; bool bShowFieldIcon = false; bool bUseRows = false; bool bSortChildNode = false; IFieldIterator* FieldIterator = nullptr; IFieldExpander* FieldExpander = nullptr; INotifyHook* NotifyHook = nullptr; bool bOwnFieldIterator = false; bool bOwnFieldExpander = false; public: TSharedRef Construct(const SPropertyViewer::FArguments& InArgs); void Tick(); void AddContainer(SPropertyViewer::FHandle Identifier, TOptional DisplayName, const UStruct* Struct); void AddContainerInstance(SPropertyViewer::FHandle Identifier, TOptional DisplayName, UObject* Object); void AddContainerInstance(SPropertyViewer::FHandle Identifier, TOptional DisplayName, const UScriptStruct* Struct, void* Data); void Remove(SPropertyViewer::FHandle Identifier); void RemoveAll(); TArray GetSelectedItems() const; void SetRawFilterText(const FText& InFilterText); void SetSelection(SPropertyViewer::FHandle Identifier, TArrayView FieldPath); private: void AddContainerInternal(SPropertyViewer::FHandle Identifier, TSharedPtr& NewContainer); TSharedRef CreateSearch(); TSharedRef CreateTree(bool bHasPreWidget, bool bShowPropertyValue, bool bHasPostWidget, ESelectionMode::Type SelectionMode); void HandleSearchChanged(const FText& InFilterText); FText SetRawFilterTextInternal(const FText& InFilterText); void SetHighlightTextRecursive(const TSharedPtr& OwnerNode, const FText& HighlightText); void HandleGetFilterStrings(TSharedPtr Item, TArray& OutStrings); TSharedRef HandleGenerateRow(TSharedPtr Item, const TSharedRef& OwnerTable); void HandleGetChildren(TSharedPtr InParent, TArray>& OutChildren); TSharedPtr HandleContextMenuOpening(); void HandleSelectionChanged(TSharedPtr Item, ESelectInfo::Type SelectionType); void HandleDoubleClick(TSharedPtr Item); FReply HandleDragDetected(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent, const TSharedPtr Item); TSharedPtr FindExistingChild(const TSharedPtr& ContainerNode, TArrayView FieldPath) const; #if WITH_EDITOR void HandleBlueprintCompiled(); void HandleReplaceViewedObjects(const TMap& OldToNewObjectMap); #endif //WITH_EDITOR }; } //namespace