// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "BlueprintEditor.h" #include "Components/ActorComponent.h" #include "Components/SceneComponent.h" #include "Containers/Array.h" #include "Containers/BitArray.h" #include "Containers/Map.h" #include "Containers/Set.h" #include "Containers/SparseArray.h" #include "Containers/UnrealString.h" #include "CoreMinimal.h" #include "Delegates/Delegate.h" #include "Engine/SCS_Node.h" #include "Framework/Commands/UIAction.h" #include "Framework/SlateDelegates.h" #include "Framework/Views/ITypedTableView.h" #include "GameFramework/Actor.h" #include "HAL/PlatformCrt.h" #include "HAL/PlatformMath.h" #include "Input/Reply.h" #include "Internationalization/Text.h" #include "Layout/Clipping.h" #include "Layout/Visibility.h" #include "Misc/AssertionMacros.h" #include "Misc/Attribute.h" #include "Misc/Optional.h" #include "SComponentClassCombo.h" #include "ScopedTransaction.h" #include "Styling/SlateBrush.h" #include "Styling/SlateColor.h" #include "Styling/SlateTypes.h" #include "Templates/Casts.h" #include "Templates/SharedPointer.h" #include "Templates/SubclassOf.h" #include "Templates/TypeHash.h" #include "Templates/UniquePtr.h" #include "Templates/UnrealTemplate.h" #include "Types/SlateEnums.h" #include "UObject/NameTypes.h" #include "UObject/UnrealNames.h" #include "UObject/WeakObjectPtr.h" #include "UObject/WeakObjectPtrTemplates.h" #include "Widgets/DeclarativeSyntaxSupport.h" #include "Widgets/SBoxPanel.h" #include "Widgets/SCompoundWidget.h" #include "Widgets/SToolTip.h" #include "Widgets/SWidget.h" #include "Widgets/Views/STableRow.h" #include "Widgets/Views/STableViewBase.h" #include "Widgets/Views/STreeView.h" class FDragDropEvent; class FExtender; class FMenuBuilder; class FSCSEditorTreeNode; class FUICommandList; class ISCSEditorUICustomization; class ITableRow; class SHeaderRow; class SHorizontalBox; class SInlineEditableTextBlock; class SSCSEditor; class SScrollBar; class SSearchBox; class SToolTip; class SVerticalBox; class SWidget; class UBlueprint; class UChildActorComponent; class UClass; class UObject; class UPrimitiveComponent; class USCS_Node; class USimpleConstructionScript; class UToolMenu; struct EventData; struct FGeometry; struct FKeyEvent; struct FPointerEvent; struct FSlateBrush; template class TFunctionRef; // SCS editor tree node pointer types using FSCSEditorTreeNodePtrType = TSharedPtr; using FSCSEditorActorNodePtrType = TSharedPtr; using FSCSEditorChildActorNodePtrType = TSharedPtr; /** * FSCSEditorTreeNode * * Wrapper class for nodes displayed in the SCS (Simple Construction Script) editor tree widget. */ class KISMET_API FSCSEditorTreeNode : public TSharedFromThis { public: /** Delegate for when the context menu requests a rename */ DECLARE_DELEGATE(FOnRenameRequested); enum ENodeType { ComponentNode, RootActorNode, SeparatorNode, ChildActorNode, }; /** * Constructs an empty tree node. */ FSCSEditorTreeNode(FSCSEditorTreeNode::ENodeType InNodeType); /** * @return The name to identify this node. */ virtual FName GetNodeID() const; /** * @return The name of the variable represented by this node. */ virtual FName GetVariableName() const; /** * @return The string to be used in the tree display. */ virtual FString GetDisplayString() const; /** * @return The name of this node in text. */ virtual FText GetDisplayName() const; /** * @return The SCS node that is represented by this object, or NULL if there is no associated SCS node. */ virtual class USCS_Node* GetSCSNode() const; /** * @param ActualEditedBlueprint currently edited blueprint * @note Derived classes should override GetOrCreateEditableObjectForBlueprint(). * @return The component template that can be editable for actual class. */ inline UActorComponent* GetOrCreateEditableComponentTemplate(UBlueprint* ActualEditedBlueprint) const { // @TODO - Deprecate this public API in favor of GetEditableObjectForBlueprint(). return Cast(GetOrCreateEditableObjectForBlueprint(ActualEditedBlueprint)); } /** * Finds the component instance represented by this node contained within a given Actor instance. * * @param InActor The Actor instance to use as the container object for finding the component instance. * @return The component instance represented by this node and contained within the given Actor instance, or NULL if not found. */ virtual UActorComponent* FindComponentInstanceInActor(const AActor* InActor) const; /** * @return This object's parent node (or an invalid reference if no parent is assigned). */ FSCSEditorTreeNodePtrType GetParent() const { return ParentNodePtr; } /** * @return The set of nodes which are parented to this node (read-only). */ const TArray& GetChildren() const { return Children; } /** * @return The root of the actor subtree to which this node belongs. */ FSCSEditorActorNodePtrType GetActorRootNode() const { return ActorRootNodePtr; } /** * Sets the actor root to the given node for this node along with any children. */ void SetActorRootNode(FSCSEditorActorNodePtrType InActorNode); /** * @return Type of node */ ENodeType GetNodeType() const; /** * @return True if this represents an actor node type */ bool IsActorNode() const { return NodeType == ENodeType::RootActorNode || NodeType == ENodeType::ChildActorNode; } /** * @return True if this represents a component node type */ bool IsComponentNode() const { return NodeType == ENodeType::ComponentNode; } /** * @param bEvenIfPendingKill If false, nullptr will be returned if the cached component template is pending kill. * If true, it will be returned regardless (this is used for recaching the component template if the objects * have been reinstanced following construction script execution). * * @note Deliberately non-virtual, for performance reasons. * @warning This will not return the right component for components overridden by the inherited component handler, you need to call GetOrCreateEditableComponentTemplate instead * @return The component template or instance represented by this node, if it's a component node. */ inline UActorComponent* GetComponentTemplate(bool bEvenIfPendingKill = false) const { // @todo - Deprecate this API? For backwards-compatibility, this continues to provide non-const access to the internal object instance specifically as a component reference. return Cast(WeakObjectPtr.Get(bEvenIfPendingKill)); } /** * @param bEvenIfPendingKill If false, nullptr will be returned if the cached object instance is pending kill. * If true, it will be returned regardless (this is used for recaching the object if the objects * have been reinstanced following construction script execution). * * @note Deliberately non-virtual, for performance reasons. * @return A read-only reference to the object represented by this node. */ template inline const T* GetObject(bool bEvenIfPendingKill = false) const { return Cast(WeakObjectPtr.Get(bEvenIfPendingKill)); } /** * @param InBlueprint The Blueprint in which the object will be edited. * * @note May not be the same as the value returned by GetObject(). * @return A reference to the object represented by this node that can be modified within the given Blueprint. */ template inline T* GetEditableObjectForBlueprint(UBlueprint* InBlueprint) const { return Cast(GetOrCreateEditableObjectForBlueprint(InBlueprint)); } /** * Sets the internal object instance represented by this node. */ inline void SetObject(UObject* InObject) { WeakObjectPtr = InObject; } /** * @return Whether or not this node is a direct child of the given node. */ bool IsDirectlyAttachedTo(FSCSEditorTreeNodePtrType InNodePtr) const { return ParentNodePtr == InNodePtr; } /** * @return Whether or not this node is a child (direct or indirect) of the given node. */ bool IsAttachedTo(FSCSEditorTreeNodePtrType InNodePtr) const; /** * Finds the closest ancestor node in the given node set. * * @param InNodes The given node set. * @return One of the nodes from the set, or an invalid node reference if the set does not contain any ancestor nodes. */ FSCSEditorTreeNodePtrType FindClosestParent(TArray InNodes); /** * Adds the given node as a child node. * * @param InChildNodePtr The node to add as a child node. */ virtual void AddChild(FSCSEditorTreeNodePtrType InChildNodePtr); /** * Adds a child node for the given SCS node. * * @param InSCSNode The SCS node to for which to create a child node. * @param bIsInheritedSCS Whether or not the given SCS node is inherited from a parent. * @return A reference to the new child node or the existing child node if a match is found. */ FSCSEditorTreeNodePtrType AddChild(USCS_Node* InSCSNode, bool bIsInheritedSCS); /** * Adds a child node for the given component template. * * @param InComponentTemplate The component template for which to create a child node. * @return A reference to the new child node or the existing child node if a match is found. */ FSCSEditorTreeNodePtrType AddChildFromComponent(UActorComponent* InComponentTemplate); /** * Attempts to find a reference to the child node that matches the given SCS node. * * @param InSCSNode The SCS node to match. * @param bRecursiveSearch Whether or not to recursively search child nodes (default == false). * @param OutDepth If non-NULL, the depth of the child node will be returned in this parameter on success (default == NULL). * @return The child node that matches the given SCS node, or an invalid node reference if no match was found. */ FSCSEditorTreeNodePtrType FindChild(const USCS_Node* InSCSNode, bool bRecursiveSearch = false, uint32* OutDepth = NULL) const; /** * Attempts to find a reference to the child node that matches the given component template. * * @param InComponentTemplate The component template instance to match. * @param bRecursiveSearch Whether or not to recursively search child nodes (default == false). * @param OutDepth If non-NULL, the depth of the child node will be returned in this parameter on success (default == NULL). * @return The child node with a component template that matches the given component template instance, or an invalid node reference if no match was found. */ FSCSEditorTreeNodePtrType FindChild(const UActorComponent* InComponentTemplate, bool bRecursiveSearch = false, uint32* OutDepth = NULL) const; /** * Attempts to find a reference to the child node that matches the given component variable or instance name. * * @param InVariableOrInstanceName The component variable or instance name to match. * @param bRecursiveSearch Whether or not to recursively search child nodes (default == false). * @param OutDepth If non-NULL, the depth of the child node will be returned in this parameter on success (default == NULL). * @return The child node with a component variable or instance name that matches the given name, or an invalid node reference if no match was found. */ FSCSEditorTreeNodePtrType FindChild(const FName& InVariableOrInstanceName, bool bRecursiveSearch = false, uint32* OutDepth = NULL) const; /** * Removes the given node from the list of child nodes. * * @param InChildNodePtr The child node to remove. */ virtual void RemoveChild(FSCSEditorTreeNodePtrType InChildNodePtr); bool IsSceneComponent() const { return Cast(GetComponentTemplate()) != nullptr; } /** Returns the associated child actor node if applicable to this node type. */ virtual FSCSEditorChildActorNodePtrType GetChildActorNode() { return nullptr; } // Tries to find a SCS node that was likely responsible for creating the specified instance component. Note: This is not always possible to do! static USCS_Node* FindSCSNodeForInstance(const UActorComponent* InstanceComponent, UClass* ClassToSearch); /** * Creates the correct type of node based on the component (instanced or not, etc...) */ static FSCSEditorTreeNodePtrType FactoryNodeFromComponent(UActorComponent* InComponent); // Destructor virtual ~FSCSEditorTreeNode() {} /** * Ends the 'Create + enter initial name' transaction of this node. The creation of a node is 'ongoing' as long as the initial name of * the node is in edition mode. When the text is not in edit mode anymore, the ongoing create transaction ends and the node * is considered fully created. */ void CloseOngoingCreateTransaction(); protected: // Called when this node is being removed via a RemoveChild call virtual void RemoveMeAsChild() {} // Provides derived classes with non-const access to the object represented by this node (e.g. for rename operations, etc.). This should not be made public. template inline T* GetMutableObject() const { return Cast(WeakObjectPtr.Get()); } // Derived classes can override to create and/or return a reference to an alternate editable object. virtual UObject* GetOrCreateEditableObjectForBlueprint(UBlueprint* InBlueprint) const; public: /** * @return The Blueprint to which the object represented by this node belongs (requires implementation in subclass). */ virtual UBlueprint* GetBlueprint() const = 0; /** * @return Whether or not this object represents a "native" component template (i.e. one that is not found in the SCS tree). */ virtual bool IsNativeComponent() const { return false; } /** * @return Whether or not this object represents a root component. */ virtual bool IsRootComponent() const { return false; } /** * @return Whether or not this object represents an inherited SCS node (one from a SCS node in a parent Blueprint). */ virtual bool IsInheritedSCSNode() const { return false; } /** * @return Whether or not this object was declared in the current class (or instance). Anything inherited cannot be reorganized (renamed, reparented, etc...). */ virtual bool IsInheritedComponent() const { return IsNativeComponent() || IsInheritedSCSNode(); } /** * @return Whether or not this node represents an instanced object (i.e. not a template). */ virtual bool IsInstanced() const { return false; } /** * @return Whether or not this node represents an instanced actor object. */ bool IsInstancedActor() const { return IsInstanced() && IsActorNode(); } /** * @return Whether or not this node represents an instanced component object. */ bool IsInstancedComponent() const { return IsInstanced() && IsComponentNode(); } /** * @return Whether or not this node represents a Blueprint (i.e. non-native) component object. */ bool IsBlueprintComponent() const { return IsComponentNode() && !IsNativeComponent(); } /** * @return Whether or not this object represents a component instance that was created by the user and not by a native or Blueprint-generated class. */ virtual bool IsUserInstancedComponent() const { return false; } /** * @return Whether or not this object represents the default SCS scene root component. */ virtual bool IsDefaultSceneRoot() const { return false; } /** * @return Whether or not this object represents a node that can be deleted from the SCS tree. */ virtual bool CanDelete() const { return false; } /** * @return Whether or not this object represents a node that can be reparented to other nodes based on its context. */ virtual bool CanReparent() const { return false; } /** * @return Whether or not we can edit properties for the object represented by this node. */ virtual bool CanEdit() const { return false; } /** * @return Whether or not we can rename the object or variable represented by this node. */ virtual bool CanRename() const { return false; } /** * Requests a rename on the node. * @param OngoingCreateTransaction The transaction scoping the node creation which will end once the node is named by the user or null if the rename is not part of a the creation process. */ void OnRequestRename(TUniquePtr OngoingCreateTransaction); /** Renames the object or variable represented by this node */ virtual void OnCompleteRename(const FText& InNewName); /** Sets up the delegate for a rename operation */ void SetRenameRequestedDelegate(FOnRenameRequested InRenameRequested) { RenameRequestedDelegate = InRenameRequested; } /** Query that determines if this item should be filtered out or not */ virtual bool IsFlaggedForFiltration() const { return ensureMsgf(FilterFlags != EFilteredState::Unknown, TEXT("Querying a bad filtration state.")) ? (FilterFlags & EFilteredState::FilteredInMask) == 0 : false; } /** Returns whether the node will match the given type (for filtering) */ virtual bool MatchesFilterType(const UClass* InFilterType) const; /** Refreshes this item's filtration state. Set bRecursive to 'true' to refresh any child nodes as well */ virtual bool RefreshFilteredState(const UClass* InFilterType, const TArray& InFilterTerms, bool bRecursive); protected: /** Sets this item's filtration state. Use bUpdateParent to make sure the parent's EFilteredState::ChildMatches flag is properly updated based off the new state */ void SetCachedFilterState(bool bMatchesFilter, bool bUpdateParent); /** Updates the EFilteredState::ChildMatches flag, based off of children's current state */ void RefreshCachedChildFilterState(bool bUpdateParent); /** Used to update the EFilteredState::ChildMatches flag for parent nodes, when this item's filtration state has changed */ void ApplyFilteredStateToParent(); // Scope the creation of a node which ends when the initial 'name' is given/accepted by the user, which can be several frames after the node was actually created. TUniquePtr OngoingCreateTransaction; private: // The type of tree node ENodeType NodeType; // Weak ptr to the object instance represented by this node (e.g. component template) TWeakObjectPtr WeakObjectPtr; // Actual tree structure FSCSEditorTreeNodePtrType ParentNodePtr; FSCSEditorActorNodePtrType ActorRootNodePtr; TArray Children; /** Handles rename requests */ FOnRenameRequested RenameRequestedDelegate; enum EFilteredState { FilteredOut = 0x00, MatchesFilter = (1 << 0), ChildMatches = (1 << 1), FilteredInMask = (MatchesFilter | ChildMatches), Unknown = 0xFC // ~FilteredInMask }; uint8 FilterFlags; }; ////////////////////////////////////////////////////////////////////////// // class KISMET_API FSCSEditorTreeNodeComponentBase : public FSCSEditorTreeNode { protected: FSCSEditorTreeNodeComponentBase() : FSCSEditorTreeNode(FSCSEditorTreeNode::ComponentNode) { } public: // FSCSEditorTreeNode interface virtual FName GetVariableName() const override; virtual FString GetDisplayString() const override; virtual bool CanRename() const override { return !IsInheritedComponent() && !IsDefaultSceneRoot(); } virtual bool CanDelete() const override { return !IsInheritedComponent() && !IsDefaultSceneRoot(); } virtual bool CanReparent() const override; virtual UBlueprint* GetBlueprint() const override; virtual FSCSEditorChildActorNodePtrType GetChildActorNode(); virtual bool MatchesFilterType(const UClass* InFilterType) const override; // End of FSCSEditorTreeNode interface private: /** Child actor node associated with this component node, if applicable. */ FSCSEditorChildActorNodePtrType ChildActorNodePtr; }; ////////////////////////////////////////////////////////////////////////// // FSCSEditorTreeNodeInstancedInheritedComponent - A inherited component in the instanced case (either an inherited SCS node or an inherited native component) class KISMET_API FSCSEditorTreeNodeInstancedInheritedComponent : public FSCSEditorTreeNodeComponentBase { public: /** * Constructs a wrapper around a component template not contained within an SCS tree node (e.g. "native" components). * * @param InComponentTemplate The component template represented by this object. */ FSCSEditorTreeNodeInstancedInheritedComponent(AActor* Owner, UActorComponent* InComponentTemplate); // FSCSEditorTreeNode public interface virtual bool IsNativeComponent() const override; virtual bool IsRootComponent() const override; virtual bool IsInheritedSCSNode() const override; virtual bool IsInstanced() const override { return true; } virtual bool IsInheritedComponent() const override { return true; } virtual bool IsDefaultSceneRoot() const override; virtual bool CanEdit() const override; virtual FText GetDisplayName() const override; // End of FSCSEditorTreeNode public interface private: TWeakObjectPtr InstancedComponentOwnerPtr; }; ////////////////////////////////////////////////////////////////////////// // FSCSEditorTreeNodeInstanceAddedComponent - A unique-to-this instance component class KISMET_API FSCSEditorTreeNodeInstanceAddedComponent : public FSCSEditorTreeNodeComponentBase { public: /** * Constructs a wrapper around a component template not contained within an SCS tree node (e.g. "native" components). * * @param InComponentTemplate The component template represented by this object. */ FSCSEditorTreeNodeInstanceAddedComponent(AActor* Owner, UActorComponent* InComponentTemplate); // FSCSEditorTreeNode public interface virtual bool IsRootComponent() const override; virtual bool IsInstanced() const override { return true; } virtual bool IsUserInstancedComponent() const override { return true; } virtual bool IsDefaultSceneRoot() const override; virtual bool CanEdit() const override { return true; } virtual FName GetVariableName() const override { return NAME_None; } virtual FString GetDisplayString() const override; virtual FText GetDisplayName() const override; virtual void OnCompleteRename(const FText& InNewName) override; // End of FSCSEditorTreeNode public interface protected: // FSCSEditorTreeNode protected interface virtual void RemoveMeAsChild() override; // End of FSCSEditorTreeNode protected interface private: FName InstancedComponentName; TWeakObjectPtr InstancedComponentOwnerPtr; }; ////////////////////////////////////////////////////////////////////////// // FSCSEditorTreeNodeComponent - A generic component in the non-instanced case (either a SCS node or an inherited native component) class KISMET_API FSCSEditorTreeNodeComponent : public FSCSEditorTreeNodeComponentBase { public: /** * Constructs a wrapper around a component template contained within an SCS tree node. * * @param InSCSNode The SCS tree node represented by this object. * @param bInIsInherited Whether or not the SCS tree node is inherited from a parent Blueprint class. */ FSCSEditorTreeNodeComponent(class USCS_Node* InSCSNode, bool bInIsInherited = false); /** * Constructs a wrapper around a component template not contained within an SCS tree node (e.g. "native" components). * * @param InComponentTemplate The component template represented by this object. */ FSCSEditorTreeNodeComponent(UActorComponent* InComponentTemplate); // FSCSEditorTreeNode public interface virtual bool IsNativeComponent() const override; virtual bool IsRootComponent() const override; virtual bool IsInheritedSCSNode() const override; virtual bool IsDefaultSceneRoot() const override; virtual bool CanEdit() const override; virtual FText GetDisplayName() const override; virtual class USCS_Node* GetSCSNode() const override; virtual void OnCompleteRename(const FText& InNewName) override; // End of FSCSEditorTreeNode public interface protected: // FSCSEditorTreeNode protected interface virtual void RemoveMeAsChild() override; virtual UObject* GetOrCreateEditableObjectForBlueprint(UBlueprint* InBlueprint) const override; // End of FSCSEditorTreeNode protected interface /** Get overridden template component, specialized in given blueprint */ UActorComponent* INTERNAL_GetOverridenComponentTemplate(UBlueprint* Blueprint) const; private: // Was this component inherited from a parent class or introduced in this class? bool bIsInheritedSCS; // Is this the template coming from an SCS node? TWeakObjectPtr SCSNodePtr; }; class KISMET_API FSCSEditorTreeNodeActorBase : public FSCSEditorTreeNode { public: FSCSEditorTreeNodeActorBase(FSCSEditorTreeNode::ENodeType InNodeType, AActor* InActor) : FSCSEditorTreeNode(InNodeType) { SetObject(InActor); } FSCSEditorTreeNodePtrType GetOwnerNode() const; void SetOwnerNode(FSCSEditorTreeNodePtrType NewOwnerNode); FSCSEditorTreeNodePtrType GetSceneRootNode() const; void SetSceneRootNode(FSCSEditorTreeNodePtrType NewSceneRootNode); /** Returns the set of root nodes */ const TArray& GetComponentNodes() const; // FSCSEditorTreeNode public interface virtual FName GetNodeID() const override; virtual bool IsInstanced() const override; virtual bool CanEdit() const override { return true; } virtual void AddChild(FSCSEditorTreeNodePtrType InChildNodePtr) override; virtual void RemoveChild(FSCSEditorTreeNodePtrType InChildNodePtr) override; virtual UBlueprint* GetBlueprint() const override; // End of FSCSEditorTreeNode public interface protected: using Super = FSCSEditorTreeNode; private: /** The actor's subtree owner (if valid) */ FSCSEditorTreeNodePtrType OwnerNodePtr; /** The actor's scene root node (if valid) */ FSCSEditorTreeNodePtrType SceneRootNodePtr; /** Root set of components (contains the root scene component and any non-scene component nodes) */ TArray ComponentNodes; }; class KISMET_API FSCSEditorTreeNodeRootActor : public FSCSEditorTreeNodeActorBase { public: FSCSEditorTreeNodeRootActor(AActor* InActor, bool bInAllowRename) : FSCSEditorTreeNodeActorBase(FSCSEditorTreeNode::RootActorNode, InActor) , bAllowRename(bInAllowRename) , CachedFilterType(nullptr) { } // FSCSEditorTreeNode public interface virtual bool CanRename() const override { return bAllowRename; } virtual void OnCompleteRename(const FText& InNewName) override; virtual void AddChild(FSCSEditorTreeNodePtrType InChildNodePtr) override; virtual void RemoveChild(FSCSEditorTreeNodePtrType InChildNodePtr) override; virtual bool RefreshFilteredState(const UClass* InFilterType, const TArray& InFilterTerms, bool bRecursive) override; // End of FSCSEditorTreeNode public interface private: bool bAllowRename; const UClass* CachedFilterType; TArray CachedFilterTerms; TWeakPtr SceneComponentSeparatorNodePtr; TWeakPtr NonSceneComponentSeparatorNodePtr; }; class KISMET_API FSCSEditorTreeNodeChildActor : public FSCSEditorTreeNodeActorBase { public: FSCSEditorTreeNodeChildActor(AActor* InActor) : FSCSEditorTreeNodeActorBase(FSCSEditorTreeNode::ChildActorNode, InActor) { } // FSCSEditorTreeNode public interface virtual bool IsFlaggedForFiltration() const override; // End of FSCSEditorTreeNode public interface UChildActorComponent* GetChildActorComponent() const; }; class KISMET_API FSCSEditorTreeNodeSeparator : public FSCSEditorTreeNode { public: FSCSEditorTreeNodeSeparator() : FSCSEditorTreeNode(FSCSEditorTreeNode::SeparatorNode) { } // FSCSEditorTreeNode public interface virtual UBlueprint* GetBlueprint() const override { return nullptr; } virtual bool MatchesFilterType(const UClass* InFilterType) const override; // End of FSCSEditorTreeNode public interface /** If the given type matches the tree view filter, the separator will also be flagged for filtration. */ void AddFilteredComponentType(const TSubclassOf& InFilteredType); private: TArray FilteredTypes; }; ////////////////////////////////////////////////////////////////////////// // SSCS_RowWidget class SSCS_RowWidget : public SMultiColumnTableRow { public: SLATE_BEGIN_ARGS( SSCS_RowWidget ){} SLATE_END_ARGS() void Construct( const FArguments& InArgs, TSharedPtr InSCSEditor, FSCSEditorTreeNodePtrType InNodePtr, TSharedPtr InOwnerTableView ); virtual ~SSCS_RowWidget(); // SMultiColumnTableRow interface virtual TSharedRef GenerateWidgetForColumn( const FName& ColumnName ) override; // End of SMultiColumnTableRow // SWidget interface virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; // End of SWidget interface /** Get the blueprint we are editing */ UBlueprint* GetBlueprint() const; FText GetNameLabel() const; FText GetTooltipText() const; FSlateColor GetColorTintForIcon() const; FSlateColor GetColorTintForText() const; FString GetDocumentationLink() const; FString GetDocumentationExcerptName() const; KISMET_API static FSlateColor GetColorTintForIcon(FSCSEditorTreeNodePtrType InNode); FText GetAssetName() const; FText GetAssetPath() const; EVisibility GetAssetVisibility() const; /* Get the node used by the row Widget */ virtual FSCSEditorTreeNodePtrType GetNode() const { return TreeNodePtr; }; protected: virtual ESelectionMode::Type GetSelectionMode() const override; virtual const FSlateBrush* GetIconBrush() const; static void AddToToolTipInfoBox(const TSharedRef& InfoBox, const FText& Key, TSharedRef ValueIcon, const TAttribute& Value, bool bImportant); /** Commits the new name of the component */ void OnNameTextCommit(const FText& InNewName, ETextCommit::Type InTextCommit); private: /** Verifies the name of the component when changing it */ bool OnNameTextVerifyChanged(const FText& InNewText, FText& OutErrorMessage); /** Builds a context menu popup for dropping a child node onto the scene root node */ TSharedPtr BuildSceneRootDropActionMenu(FSCSEditorTreeNodePtrType DroppedNodePtr); /** Creates a tooltip for this row */ TSharedRef CreateToolTipWidget() const; /** Drag-drop handlers */ void HandleOnDragEnter(const FDragDropEvent& DragDropEvent); void HandleOnDragLeave(const FDragDropEvent& DragDropEvent); FReply HandleOnDragDetected(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent); TOptional HandleOnCanAcceptDrop(const FDragDropEvent& DragDropEvent, EItemDropZone DropZone, FSCSEditorTreeNodePtrType TargetItem); FReply HandleOnAcceptDrop(const FDragDropEvent& DragDropEvent, EItemDropZone DropZone, FSCSEditorTreeNodePtrType TargetItem); /** Handler for attaching a single node to this node */ void OnAttachToDropAction(FSCSEditorTreeNodePtrType DroppedNodePtr) { TArray DroppedNodePtrs; DroppedNodePtrs.Add(DroppedNodePtr); OnAttachToDropAction(DroppedNodePtrs); } /** Handler for attaching one or more nodes to this node */ void OnAttachToDropAction(const TArray& DroppedNodePtrs); /** Handler for detaching one or more nodes from the current parent and reattaching to the existing scene root node */ void OnDetachFromDropAction(const TArray& DroppedNodePtrs); /** Handler for making the given node the new scene root node */ void OnMakeNewRootDropAction(FSCSEditorTreeNodePtrType DroppedNodePtr); /** Tasks to perform after handling a drop action */ void PostDragDropAction(bool bRegenerateTreeNodes); /** * Retrieves an image brush signifying the specified component's mobility (could sometimes be NULL). * * @returns A pointer to the FSlateBrush to use (NULL for Static and Non-SceneComponents) */ FSlateBrush const* GetMobilityIconImage() const; /** * Retrieves tooltip text describing the specified component's mobility. * * @returns An FText object containing a description of the component's mobility */ FText GetMobilityToolTipText() const; /** * Retrieves tooltip text describing where the component was first introduced (for inherited components). * * @returns An FText object containing a description of when the component was first introduced */ FText GetIntroducedInToolTipText() const; /** * Retrieves tooltip text describing how the component was introduced * * @returns An FText object containing a description of when the component was first introduced */ FText GetComponentAddSourceToolTipText() const; /** * Retrieves tooltip text for the specified Native Component's underlying Name * * @returns An FText object containing the Component's Name */ FText GetNativeComponentNameToolTipText() const; /** * Retrieves a tooltip text describing if the component is marked Editor only or not * * @returns An FText object containing a description of if the component is marked Editor only or not */ FText GetComponentEditorOnlyTooltipText() const; public: /** Pointer back to owning SCSEditor 2 tool */ TWeakPtr SCSEditor; TSharedPtr InlineWidget; private: /** Pointer to node we represent */ FSCSEditorTreeNodePtrType TreeNodePtr; }; class SSCS_RowWidget_ActorRoot : public SSCS_RowWidget { public: // SMultiColumnTableRow interface virtual TSharedRef GenerateWidgetForColumn(const FName& ColumnName) override; // End of SMultiColumnTableRow protected: /** Gets the associated actor node */ FSCSEditorActorNodePtrType GetActorNode() const; /** Data accessors */ virtual const FSlateBrush* GetIconBrush() const override; private: /** Creates a tooltip for this row */ TSharedRef CreateToolTipWidget() const; /** Called to validate the actor name */ bool OnVerifyActorLabelChanged(const FText& InLabel, FText& OutErrorMessage); /** Data accessors */ FText GetActorDisplayText() const; FText GetActorContextText() const; FText GetActorClassNameText() const; FText GetActorSuperClassNameText() const; FText GetActorMobilityText() const; }; class SSCS_RowWidget_Separator : public SSCS_RowWidget { public: // SMultiColumnTableRow interface virtual TSharedRef GenerateWidgetForColumn(const FName& ColumnName) override; // End of SMultiColumnTableRow private: }; ////////////////////////////////////////////////////////////////////////// // SSCSEditorDragDropTree - implements STreeView for our specific node type and adds drag/drop functionality class SSCSEditorDragDropTree : public STreeView { public: SLATE_BEGIN_ARGS( SSCSEditorDragDropTree ) : _SCSEditor( NULL ) , _OnGenerateRow() , _OnGetChildren() , _OnSetExpansionRecursive() , _TreeItemsSource( static_cast< TArray* >(NULL) ) //@todo Slate Syntax: Initializing from NULL without a cast , _ItemHeight(16) , _OnContextMenuOpening() , _OnMouseButtonDoubleClick() , _OnSelectionChanged() , _OnExpansionChanged() , _SelectionMode(ESelectionMode::Multi) , _ClearSelectionOnClick(true) , _ExternalScrollbar() , _OnTableViewBadState() { _Clipping = EWidgetClipping::ClipToBounds; } SLATE_ARGUMENT( SSCSEditor*, SCSEditor ) SLATE_EVENT( FOnGenerateRow, OnGenerateRow ) SLATE_EVENT( FOnItemScrolledIntoView, OnItemScrolledIntoView ) SLATE_EVENT( FOnGetChildren, OnGetChildren ) SLATE_EVENT( FOnSetExpansionRecursive, OnSetExpansionRecursive ) SLATE_ARGUMENT( TArray* , TreeItemsSource ) SLATE_ATTRIBUTE( float, ItemHeight ) SLATE_EVENT( FOnContextMenuOpening, OnContextMenuOpening ) SLATE_EVENT( FOnMouseButtonDoubleClick, OnMouseButtonDoubleClick ) SLATE_EVENT( FOnSelectionChanged, OnSelectionChanged ) SLATE_EVENT( FOnExpansionChanged, OnExpansionChanged ) SLATE_ATTRIBUTE( ESelectionMode::Type, SelectionMode ) SLATE_ARGUMENT( TSharedPtr, HeaderRow ) SLATE_ARGUMENT ( bool, ClearSelectionOnClick ) SLATE_ARGUMENT( TSharedPtr, ExternalScrollbar ) SLATE_EVENT( FOnTableViewBadState, OnTableViewBadState ) SLATE_END_ARGS() /** Object construction - mostly defers to the base STreeView */ void Construct( const FArguments& InArgs ); // SWidget interface virtual FReply OnDragOver( const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent ) override; virtual FReply OnDrop( const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent ) override; // End SWidget interface private: /** Pointer to the SSCSEditor that owns this widget */ SSCSEditor* SCSEditor; }; ////////////////////////////////////////////////////////////////////////// // SSCSEditor typedef SSCSEditorDragDropTree SSCSTreeType; /* Component editor mode */ namespace EComponentEditorMode { enum Type { /* View/edit the SCS in a BGPC */ BlueprintSCS, /* View/edit the Actor instance */ ActorInstance }; }; class UE_DEPRECATED(5.0, "SSCSEditor has been deprecated, use a child class of SSubobjectEditor instead.") SSCSEditor; class KISMET_API SSCSEditor : public SCompoundWidget { public: DECLARE_DELEGATE_RetVal_OneParam(class USCS_Node*, FOnAddNewComponent, class UClass*); DECLARE_DELEGATE_RetVal_OneParam(class USCS_Node*, FOnAddExistingComponent, class UActorComponent*); DECLARE_DELEGATE_OneParam(FOnSelectionUpdated, const TArray&); DECLARE_DELEGATE_OneParam(FOnItemDoubleClicked, const FSCSEditorTreeNodePtrType); DECLARE_DELEGATE_OneParam(FOnHighlightPropertyInDetailsView, const class FPropertyPath&); SLATE_BEGIN_ARGS( SSCSEditor ) :_EditorMode(EComponentEditorMode::BlueprintSCS) ,_IsDiffing(false) ,_ActorContext(nullptr) ,_PreviewActor(nullptr) ,_AllowEditing(true) ,_HideComponentClassCombo(false) ,_ComponentTypeFilter() ,_OnSelectionUpdated() ,_OnHighlightPropertyInDetailsView() {} SLATE_ARGUMENT(EComponentEditorMode::Type, EditorMode) SLATE_ARGUMENT(bool, IsDiffing) SLATE_ATTRIBUTE(class AActor*, ActorContext) SLATE_ATTRIBUTE(class AActor*, PreviewActor) SLATE_ATTRIBUTE(bool, AllowEditing) SLATE_ATTRIBUTE(bool, HideComponentClassCombo) SLATE_ATTRIBUTE(TSubclassOf, ComponentTypeFilter) SLATE_EVENT(FOnSelectionUpdated, OnSelectionUpdated) SLATE_EVENT(FOnItemDoubleClicked, OnItemDoubleClicked) SLATE_EVENT(FOnHighlightPropertyInDetailsView, OnHighlightPropertyInDetailsView) SLATE_EVENT(FSimpleDelegate, OnObjectReplaced) SLATE_END_ARGS() void Construct(const FArguments& InArgs); ~SSCSEditor(); /** SWidget interface */ virtual FReply OnKeyDown( const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent ); /** Used by tree control - make a widget for a table row from a node */ TSharedRef MakeTableRowWidget(FSCSEditorTreeNodePtrType InNodePtr, const TSharedRef& OwnerTable); /** Used by tree control - get children for a specified node */ void OnGetChildrenForTree(FSCSEditorTreeNodePtrType InNodePtr, TArray& OutChildren); /** Returns true if editing is allowed */ bool IsEditingAllowed() const; /** gets the actor root */ FSCSEditorActorNodePtrType GetActorNode() const; /** get the root scene node */ FSCSEditorTreeNodePtrType GetSceneRootNode() const; void SetSceneRootNode(FSCSEditorTreeNodePtrType NewSceneRootNode); /** Adds a component to the SCS tree */ struct FAddNewComponentParams { FAddNewComponentParams() : bSkipMarkBlueprintModified(false) , bSetFocusToNewItem(true) , bConformTransformToParent(true) { } /** Optionally skip marking this blueprint as modified (e.g. if we're handling that externally */ bool bSkipMarkBlueprintModified; /** Whether the newly created component should be focused */ bool bSetFocusToNewItem; /** Whether the newly created component should keep its transform, or conform it to its parent */ bool bConformTransformToParent; }; /** Adds a component to the SCS Table @param NewComponentClass (In) The class to add @param Asset (In) Optional asset to assign to the component @param Params (In) Parameter block of optional behavior flags */ UActorComponent* AddNewComponent(UClass* NewComponentClass, UObject* Asset, const FAddNewComponentParams Params = FAddNewComponentParams()); struct FAddedNodeDetails { FSCSEditorTreeNodePtrType NewNodePtr; FSCSEditorTreeNodePtrType ParentNodePtr; }; /** Adds a new SCS Node to the component Table @param OutNodeDetails (Out) Struct to be populated by the tree node pointers of the new node and its parent @param OngoingCreateTransaction (In) The transaction containing the creation of the node. The transaction will remain ongoing until the node gets its initial name from user. @param NewNode (In) The SCS node to add @param Asset (In) Optional asset to assign to the component @param bMarkBlueprintModified (In) Whether or not to mark the Blueprint as structurally modified @param bSetFocusToNewItem (In) Select the new item and activate the inline rename widget (default is true) */ void AddNewNode(FAddedNodeDetails& OutNodeDetails, TUniquePtr OngoingCreateTransaction, USCS_Node* NewNode, UObject* Asset, bool bMarkBlueprintModified, bool bSetFocusToNewItem = true); /** Adds a new SCS Node to the component Table @param OngoingCreateTransaction (In) The transaction containing the creation of the node. The transaction will remain ongoing until the node gets its initial name from user. @param NewNode (In) The SCS node to add @param Asset (In) Optional asset to assign to the component @param bMarkBlueprintModified (In) Whether or not to mark the Blueprint as structurally modified @param bSetFocusToNewItem (In) Select the new item and activate the inline rename widget (default is true) @return The reference of the newly created ActorComponent */ UActorComponent* AddNewNode(TUniquePtr OngoingCreateTransaction, USCS_Node* NewNode, UObject* Asset, bool bMarkBlueprintModified, bool bSetFocusToNewItem = true); /** Adds a new component instance node to the component Table @param OngoingCreateTransaction (In) The transaction containing the creation of the node. The transaction will remain ongoing until the node gets its initial name from user. @param NewInstanceComponent (In) The component being added to the actor instance @param InParentNodePtr (In) The node this component will be added to @param Asset (In) Optional asset to assign to the component @param bSetFocusToNewItem (In) Select the new item and activate the inline rename widget (default is true) */ void AddNewNodeForInstancedComponent(TUniquePtr OngoingCreateTransaction, UActorComponent* NewInstanceComponent, FSCSEditorTreeNodePtrType InParentNodePtr, UObject* Asset, bool bSetFocusToNewItem = true); /** Returns true if the specified component is currently selected */ bool IsComponentSelected(const UPrimitiveComponent* PrimComponent) const; /** Assigns a selection override delegate to the specified component */ void SetSelectionOverride(UPrimitiveComponent* PrimComponent) const; /** Cut selected node(s) */ void CutSelectedNodes(); bool CanCutNodes() const; /** Copy selected node(s) */ void CopySelectedNodes(); bool CanCopyNodes() const; /** Pastes previously copied node(s) */ void PasteNodes(); bool CanPasteNodes() const; /** Callbacks to duplicate the selected component */ bool CanDuplicateComponent() const; void OnDuplicateComponent(); /** Removes existing selected component nodes from the SCS */ void OnDeleteNodes(); bool CanDeleteNodes() const; /** Callbacks to find references of the selected component */ void OnFindReferences(bool bSearchAllBlueprints, const EGetFindReferenceSearchStringFlags Flags); /** Removes an existing component node from the tree */ void RemoveComponentNode(FSCSEditorTreeNodePtrType InNodePtr); /** Called when selection in the tree changes */ void OnTreeSelectionChanged(FSCSEditorTreeNodePtrType InSelectedNodePtr, ESelectInfo::Type SelectInfo); /** Called when the Actor is selected. */ void OnActorSelected(const ECheckBoxState NewCheckedState); /** Called to determine if actor is selected. */ ECheckBoxState OnIsActorSelected() const; /** Update any associated selection (e.g. details view) from the passed in nodes */ void UpdateSelectionFromNodes(const TArray &SelectedNodes ); /** Refresh the tree control to reflect changes in the SCS */ void UpdateTree(bool bRegenerateTreeNodes = true); /** Dumps out the tree view contents to the log (used to assist with debugging widget hierarchy issues) */ void DumpTree(); /** Forces the details panel to refresh on the same objects */ void RefreshSelectionDetails(); /** Clears the current selection */ void ClearSelection(); /** Get the currently selected tree nodes */ TArray GetSelectedNodes() const; /** Get the number of currently selected tree nodes */ int32 GetNumSelectedNodes() const { return SCSTreeWidget->GetNumItemsSelected(); } /** * Fills out an events section in ui. * @param Menu the menu to add the events section into * @param Blueprint the active blueprint context being edited * @param SelectedClass the common component class to build the events list from * @param CanExecuteActionDelegate the delegate to query whether or not to execute the UI action * @param GetSelectedObjectsDelegate the delegate to fill the currently select variables / components */ static void BuildMenuEventsSection( FMenuBuilder& Menu, UBlueprint* Blueprint, UClass* SelectedClass, FCanExecuteAction CanExecuteActionDelegate, FGetSelectedObjectsDelegate GetSelectedObjectsDelegate ); /** * Given an actor component, attempts to find an associated tree node. * * @param ActorComponent The component associated with the node. * @param bIncludeAttachedComponents Whether or not to include components attached to each node in the search (default is true). * @return A shared pointer to a tree node. The pointer will be invalid if no match could be found. */ FSCSEditorTreeNodePtrType GetNodeFromActorComponent(const UActorComponent* ActorComponent, bool bIncludeAttachedComponents = true) const; /** Select the root of the tree */ void SelectRoot(); /** Select the given tree node */ void SelectNode(FSCSEditorTreeNodePtrType InNodeToSelect, bool IsCntrlDown); /** * Set the expansion state of a node * * @param InNodeToChange The node to be expanded/collapsed * @param bIsExpanded True to expand the node, false to collapse it */ void SetNodeExpansionState(FSCSEditorTreeNodePtrType InNodeToChange, const bool bIsExpanded); /** * Highlight a tree node and, optionally, a property with in it * * @param TreeNodeName Name of the treenode to be highlighted * @param Property The name of the property to be highlighted in the details view * @return True if the node was found in this Editor, otherwise false */ void HighlightTreeNode( FName TreeNodeName, const class FPropertyPath& Property ); /** * Highlight a tree node and, optionally, a property with in it * * @param Node A Reference to the Node SCS_Node to be highlighted * @param Property The name of the property to be highlighted in the details view */ void HighlightTreeNode( const USCS_Node* Node, FName Property ); /** * Function to save current state of SimpleConstructionScript and nodes associated with it. * * @param: SimpleContructionScript object reference. */ static void SaveSCSCurrentState( USimpleConstructionScript* SCSObj ); /** * Function to save the current state of SCS_Node and its children * * @param: Reference of the SCS_Node to be saved */ static void SaveSCSNode(USCS_Node* Node); /** Is this node still used by the Simple Construction Script */ bool IsNodeInSimpleConstructionScript(USCS_Node* Node) const; /** * Fills the supplied array with the currently selected objects * @param OutSelectedItems The array to fill. */ void GetSelectedItemsForContextMenu(TArray& OutSelectedItems) const; /** @return Array of the editable objects selected in the tree */ TArray GetSelectedEditableObjects() const; /** Provides access to the Blueprint context that's being edited */ class UBlueprint* GetBlueprint() const; /** @return The current editor mode (editing live actors or editing blueprints) */ EComponentEditorMode::Type GetEditorMode() const { return EditorMode; } /** Try to handle a drag-drop operation */ FReply TryHandleAssetDragDropOperation(const FDragDropEvent& DragDropEvent); /** Handler for recursively expanding/collapsing items */ void SetItemExpansionRecursive(FSCSEditorTreeNodePtrType Model, bool bInExpansionState); /** Callback for the action trees to get the filter text */ FText GetFilterText() const; /** Called at the end of each frame. */ void OnPostTick(float); /** Return the button widgets that can add components or create/edit blueprints */ TSharedPtr GetToolButtonsBox(); /** Sets UI customizations of this SCSEditor. */ void SetUICustomization(TSharedPtr InUICustomization); protected: FSCSEditorTreeNodePtrType FindOrCreateParentForExistingComponent(UActorComponent* InActorComponent, FSCSEditorActorNodePtrType ActorRootNode); FSCSEditorTreeNodePtrType FindParentForNewComponent(UActorComponent* NewComponent) const; FSCSEditorTreeNodePtrType FindParentForNewNode(USCS_Node* NewNode) const; /** Add a component from the selection in the combo box */ UActorComponent* PerformComboAddClass(TSubclassOf ComponentClass, EComponentCreateAction::Type ComponentCreateAction, UObject* AssetOverride); /** Called to display context menu when right clicking on the widget */ TSharedPtr< SWidget > CreateContextMenu(); /** Registers context menu by name for later access */ void RegisterContextMenu(); /** Populate context menu on the fly */ void PopulateContextMenu(UToolMenu* InMenu); /** Called when the level editor requests a component to be renamed. */ void OnLevelComponentRequestRename(const UActorComponent* InComponent); /** Checks to see if renaming is allowed on the selected component */ bool CanRenameComponent() const; /** * Requests a rename on the selected component just after creation so that the user can provide the initial * component name (overwriting the default generated one), which is considered part of the creation process. * @param OngoingCreateTransaction The ongoing transaction started when the component was created. */ void OnRenameComponent(TUniquePtr OngoingCreateTransaction); /** * Requests a rename on the selected component. */ void OnRenameComponent(); /** Called when component objects are replaced following construction script execution */ void OnObjectsReplaced(const TMap& OldToNewInstanceMap); /** Helper method to update component pointers held by the given actor node's subtree */ void ReplaceComponentReferencesInTree(FSCSEditorActorNodePtrType InActorNode, const TMap& OldToNewInstanceMap, bool& OutHasChanges); /** Update component pointers held by tree nodes if components have been replaced following construction script execution */ void ReplaceComponentReferencesInTree(const TArray& Nodes, const TMap& OldToNewInstanceMap, bool& OutHasChanges); /** * Function to create events for the current selection * @param Blueprint the active blueprint context * @param EventName the event to add * @param GetSelectedObjectsDelegate the delegate to gather information about current selection * @param NodeIndex an index to a specified node to add event for or < 0 for all selected nodes. */ static void CreateEventsForSelection(UBlueprint* Blueprint, FName EventName, FGetSelectedObjectsDelegate GetSelectedObjectsDelegate); /** * Function to construct an event for a node * @param Blueprint the nodes blueprint * @param EventName the event to add * @param EventData the event data structure describing the node */ static void ConstructEvent(UBlueprint* Blueprint, const FName EventName, const FComponentEventConstructionData EventData); /** * Function to view an event for a node * @param Blueprint the nodes blueprint * @param EventName the event to view * @param EventData the event data structure describing the node */ static void ViewEvent(UBlueprint* Blueprint, const FName EventName, const FComponentEventConstructionData EventData); /** Helper method to add a tree node for the given SCS node */ FSCSEditorTreeNodePtrType AddTreeNode(USCS_Node* InSCSNode, FSCSEditorTreeNodePtrType InParentNodePtr, const bool bIsInheritedSCS); /** Helper method to add a tree node for the given actor component */ FSCSEditorTreeNodePtrType AddTreeNodeFromComponent(UActorComponent* InSceneComponent, FSCSEditorTreeNodePtrType InParentTreeNode = FSCSEditorTreeNodePtrType()); /** Helper method to add a tree node for the given node's child actor node, if present */ FSCSEditorTreeNodePtrType AddTreeNodeFromChildActor(FSCSEditorTreeNodePtrType InNodePtr); /** Helper method to recursively find a tree node for the given SCS node starting at the given tree node */ FSCSEditorTreeNodePtrType FindTreeNode(const USCS_Node* InSCSNode, FSCSEditorTreeNodePtrType InStartNodePtr = FSCSEditorTreeNodePtrType()) const; /** Helper method to recursively find a tree node for the given scene component starting at the given tree node */ FSCSEditorTreeNodePtrType FindTreeNode(const UActorComponent* InComponent, FSCSEditorTreeNodePtrType InStartNodePtr = FSCSEditorTreeNodePtrType()) const; /** Helper method to recursively find a tree node for the given variable or instance name starting at the given tree node */ FSCSEditorTreeNodePtrType FindTreeNode(const FName& InVariableOrInstanceName, FSCSEditorTreeNodePtrType InStartNodePtr = FSCSEditorTreeNodePtrType()) const; /** Callback when a component item is scrolled into view */ void OnItemScrolledIntoView( FSCSEditorTreeNodePtrType InItem, const TSharedPtr& InWidget); /** Callback when a component item is double clicked. */ void HandleItemDoubleClicked(FSCSEditorTreeNodePtrType InItem); /** Recursively visits the given node + its children and invokes the given function for each. */ void DepthFirstTraversal(const FSCSEditorTreeNodePtrType& InNodePtr, TSet& OutVisitedNodes, const TFunctionRef InFunction) const; /** Returns the set of expandable nodes that are currently collapsed in the UI */ void GetCollapsedNodes(const FSCSEditorTreeNodePtrType& InNodePtr, TSet& OutCollapsedNodes) const; /** @return The visibility of the promote to blueprint button (only visible with an actor instance that is not created from a blueprint)*/ EVisibility GetPromoteToBlueprintButtonVisibility() const; /** @return The visibility of the Edit Blueprint button (only visible with an actor instance that is created from a blueprint)*/ EVisibility GetEditBlueprintButtonVisibility() const; /** @return The visibility of the Add Component combo button */ EVisibility GetComponentClassComboButtonVisibility() const; /** @return The visibility of the components tree */ EVisibility GetComponentsTreeVisibility() const; /** @return The visibility of the components filter box */ EVisibility GetComponentsFilterBoxVisibility() const; /** @return the tooltip describing how many properties will be applied to the blueprint */ FText OnGetApplyChangesToBlueprintTooltip() const; /** @return the tooltip describing how many properties will be reset to the blueprint default*/ FText OnGetResetToBlueprintDefaultsTooltip() const; /** Opens the blueprint editor for the blueprint being viewed by the scseditor */ void OnOpenBlueprintEditor(bool bForceCodeEditing) const; /** Propagates instance changes to the blueprint */ void OnApplyChangesToBlueprint() const; /** Resets instance changes to the blueprint default */ void OnResetToBlueprintDefaults(); /** Converts the current actor instance to a blueprint */ void PromoteToBlueprint() const; /** Called when the promote to blueprint button is clicked */ FReply OnPromoteToBlueprintClicked(); /** gets a root nodes of the tree */ const TArray& GetRootNodes() const; /** * Creates a new C++ component from the specified class type * The user will be prompted to pick a new subclass name and code will be recompiled * * @return The new class that was created */ UClass* CreateNewCPPComponent(TSubclassOf ComponentClass); /** * Creates a new Blueprint component from the specified class type * The user will be prompted to pick a new subclass name and a blueprint asset will be created * * @return The new class that was created */ UClass* CreateNewBPComponent(TSubclassOf ComponentClass); /** Recursively updates the filtered state for each component item */ void OnFilterTextChanged(const FText& InFilterText); /** * Compares the filter bar's text with the item's component name. Use * bRecursive to refresh the state of child nodes as well. Returns true if * the node is set to be filtered out */ bool RefreshFilteredState(FSCSEditorTreeNodePtrType TreeNode, bool bRecursive); /** Helper method to construct the subtree for the given actor (root) node. */ void BuildSubTreeForActorNode(FSCSEditorActorNodePtrType InActorNode); /** @return Type of component to filter the tree view with or nullptr if there's no filter. */ TSubclassOf GetComponentTypeFilterToApply() const; public: /** Tree widget */ TSharedPtr SCSTreeWidget; /** Command list for handling actions in the SSCSEditor */ TSharedPtr< FUICommandList > CommandList; /** Name of a node that has been requested to be renamed */ FName DeferredRenameRequest; /** Scope the creation of a component which ends when the initial component 'name' is given/accepted by the user, which can be several frames after the component was actually created. */ TUniquePtr DeferredOngoingCreateTransaction; /** Used to unregister from the post tick event. */ FDelegateHandle PostTickHandle; /** Attribute that provides access to the Actor context for which we are viewing/editing the SCS. */ TAttribute ActorContext; /** Attribute that provides access to a "preview" Actor context (may not be same as the Actor context that's being edited. */ TAttribute PreviewActor; /** Attribute to indicate whether or not editing is allowed. */ TAttribute AllowEditing; /** Attribute to indicate whether or not the "Add Component" button is visible. If true, new components cannot be added to the Blueprint. */ TAttribute HideComponentClassCombo; /** Attribute to limit visible nodes to a particular component type when filtering the tree view. */ TAttribute> ComponentTypeFilter; /** Delegate to invoke on selection update. */ FOnSelectionUpdated OnSelectionUpdated; /** Delegate to invoke when an item in the tree is double clicked. */ FOnItemDoubleClicked OnItemDoubleClicked; /** Delegate to invoke when the given property should be highlighted in the details view (e.g. diff). */ FOnHighlightPropertyInDetailsView OnHighlightPropertyInDetailsView; /** Delegate to invoke when objects within the SCS tree are replaced (eg, via re-instancing from a BP compile) */ FSimpleDelegate OnObjectReplaced; /** Returns the Actor context for which we are viewing/editing the SCS. Can return null. Should not be cached as it may change from frame to frame. */ class AActor* GetActorContext() const; private: /** Indicates which editor mode we're in. */ EComponentEditorMode::Type EditorMode; /** Root set of tree */ TArray RootNodes; /* Root Tree Node*/ TSharedPtr ActorMenuExtender; /** Flag to enable/disable component editing */ bool bEnableComponentEditing; /** Gate to prevent changing the selection while selection change is being broadcast. */ bool bUpdatingSelection; /** Controls whether or not to allow calls to UpdateTree() */ bool bAllowTreeUpdates; /** TRUE if this SCSEditor is currently the target of a diff */ bool bIsDiffing; /** The filter box that handles filtering for the tree. */ TSharedPtr< SSearchBox > FilterBox; /** The tools buttons box **/ TSharedPtr ButtonBox; /** SCSEditor UI customizations */ TSharedPtr UICustomization; /** SCSEditor UI extension */ TSharedPtr ExtensionPanel; };