// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "Components/ActorComponent.h" #include "Components/SceneComponent.h" #include "SubobjectDataSubsystem.h" #include "Widgets/SCompoundWidget.h" #include "Widgets/Views/STableRow.h" #include "Widgets/Views/STreeView.h" #include "Framework/Commands/UICommandList.h" #include "SComponentClassCombo.h" #include "BlueprintEditor.h" // FComponentEventConstructionData #include "ScopedTransaction.h" class SSubobjectEditor; class SToolTip; class SExtensionPanel; class AActor; class FSubobjectEditorTreeNode; class SInlineEditableTextBlock; class ISCSEditorUICustomization; class UBlueprint; class UToolMenu; class UPrimitiveComponent; // Tree node pointer types using FSubobjectEditorTreeNodePtrType = TSharedPtr; ///////////////////////////////////////////////////// // FSubobjectEditorTreeNode /** * Wrapper struct that represents access an singe subobject that is used * by slate as a layout for columns/rows should look like */ class SUBOBJECTEDITOR_API FSubobjectEditorTreeNode : public TSharedFromThis { public: /** Delegate for when the context menu requests a rename */ DECLARE_DELEGATE(FOnRenameRequested); explicit FSubobjectEditorTreeNode(const FSubobjectDataHandle& DataSource, bool InbIsSeperator = false); ~FSubobjectEditorTreeNode() = default; bool IsSeperator() const { return bIsSeperator; } // If this subobject is an actor component, then return its template. Otherwise it will // return null const UActorComponent* GetComponentTemplate() const; const UObject* GetObject(bool bEvenIfPendingKill = false) const; // Get a pointer to the subobject data that this slate node is representing FSubobjectData* GetDataSource() const; // Get the subobject handle that this slate node is representing FSubobjectDataHandle GetDataHandle() const { return DataHandle; } /** Get the slate parent of this single tree node */ FSubobjectEditorTreeNodePtrType GetParent() const { return ParentNodePtr; } /** Get the display name of this single tree node */ FString GetDisplayString() const; bool IsComponentNode() const; // Returns true if this is the root actor node of the tree bool IsRootActorNode() const; bool CanReparent() const; FName GetVariableName() const; // Returns true if this subobject data handle is valid bool IsValid() const { return bIsSeperator || DataHandle.IsValid(); } bool IsChildSubtreeNode() const; bool IsNativeComponent() const; // Returns true if this node is attached to the given slate node bool IsAttachedTo(FSubobjectEditorTreeNodePtrType InNodePtr) const; /** * @return Whether or not this node is a direct child of the given node. */ bool IsDirectlyAttachedTo(FSubobjectEditorTreeNodePtrType InNodePtr) const; bool CanDelete() const; bool CanRename() const; /** * @return The set of nodes which are parented to this node (read-only). */ const TArray& GetChildren() const { return Children; } // Add the given slate node to our child array and set it's parent to us // This had no effect on the actual structure of the subobjects this node represents // it is purely visual void AddChild(FSubobjectEditorTreeNodePtrType AttachToPtr); // Remove the given slate node from our children array void RemoveChild(FSubobjectEditorTreeNodePtrType InChildNodePtr); // Attempts to find the given subobject handle in the slate children on this node. Nullptr if none are found. FSubobjectEditorTreeNodePtrType FindChild(const FSubobjectDataHandle& InHandle); /** Query that determines if this item should be filtered out or not */ bool IsFlaggedForFiltration() const; /** 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); /** Used to update the EFilteredState::ChildMatches flag for parent nodes, when this item's filtration state has changed */ void ApplyFilteredStateToParent(); /** Updates the EFilteredState::ChildMatches flag, based off of children's current state */ void RefreshCachedChildFilterState(bool bUpdateParent); /** Refreshes this item's filtration state. Set bRecursive to 'true' to refresh any child nodes as well */ bool RefreshFilteredState(const UClass* InFilterType, const TArray& InFilterTerms, bool bRecursive); /** Returns whether the node will match the given type (for filtering) */ bool MatchesFilterType(const UClass* InFilterType) const; void SetOngoingCreateTransaction(TUniquePtr InTransaction); void CloseOngoingCreateTransaction(); void GetOngoingCreateTransaction(TUniquePtr& OutPtr) { OutPtr = MoveTemp(OngoingCreateTransaction); } bool HasOngoingTransaction() const { return OngoingCreateTransaction.IsValid(); } /** Sets up the delegate for a rename operation */ void SetRenameRequestedDelegate(FOnRenameRequested InRenameRequested) { RenameRequestedDelegate = InRenameRequested; } FOnRenameRequested GetRenameRequestedDelegate() { return RenameRequestedDelegate; } protected: /** Pointer to the parent of this subobject */ FSubobjectEditorTreeNodePtrType ParentNodePtr; // 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; /** Handles rename requests */ FOnRenameRequested RenameRequestedDelegate; /** * Any children that this subobject has in the hierarchy, used to * collapsed things within in the tree */ TArray Children; /** The data source of this subobject */ FSubobjectDataHandle DataHandle; enum EFilteredState { FilteredOut = 0x00, MatchesFilter = (1 << 0), ChildMatches = (1 << 1), FilteredInMask = (MatchesFilter | ChildMatches), Unknown = 0xFC // ~FilteredInMask }; uint8 FilterFlags; /** A flag that indicates that this is a separator slate node and has no valid data */ uint8 bIsSeperator : 1; }; ///////////////////////////////////////////////////// // SSubobjectEditorDragDropTree /** Implements the specific node type and add drag/drop functionality */ class SSubobjectEditorDragDropTree : public STreeView { public: SLATE_BEGIN_ARGS(SSubobjectEditorDragDropTree) : _SubobjectEditor(nullptr) , _OnGenerateRow() , _OnGetChildren() , _OnSetExpansionRecursive() , _TreeItemsSource(static_cast*>(nullptr)) , _ItemHeight(16) , _OnContextMenuOpening() , _OnMouseButtonDoubleClick() , _OnSelectionChanged() , _SelectionMode(ESelectionMode::Multi) , _ClearSelectionOnClick(true) , _ExternalScrollbar() , _OnTableViewBadState() { _Clipping = EWidgetClipping::ClipToBounds; } SLATE_ARGUMENT(SSubobjectEditor*, SubobjectEditor) SLATE_EVENT(FOnGenerateRow, OnGenerateRow) SLATE_EVENT(FOnItemScrolledIntoView, OnItemScrolledIntoView) SLATE_EVENT(FOnGetChildren, OnGetChildren) SLATE_EVENT(FOnSetExpansionRecursive, OnSetExpansionRecursive) SLATE_ARGUMENT(TArray*, TreeItemsSource) SLATE_ATTRIBUTE_DEPRECATED(float, ItemHeight, 5.5, "The ItemHeight is only used for Tile. See ShouldArrangeAsTiles") SLATE_EVENT(FOnContextMenuOpening, OnContextMenuOpening) SLATE_EVENT(FOnMouseButtonDoubleClick, OnMouseButtonDoubleClick) SLATE_EVENT(FOnSelectionChanged, OnSelectionChanged) 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: SSubobjectEditor* SubobjectEditor; }; ///////////////////////////////////////////////////// // SSubobject_RowWidget /** * A row widget that represents a single subobject within the tree. */ class SSubobject_RowWidget : public SMultiColumnTableRow { public: SLATE_BEGIN_ARGS(SSubobject_RowWidget) {} SLATE_END_ARGS() void Construct(const FArguments& InArgs, TWeakPtr InEditor, FSubobjectEditorTreeNodePtrType InNodePtr, TSharedPtr InOwnerTableView); // SMultiColumnTableRow interface virtual TSharedRef GenerateWidgetForColumn(const FName& ColumnName) override; protected: virtual ESelectionMode::Type GetSelectionMode() const override; // End of SMultiColumnTableRow /** 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, FSubobjectEditorTreeNodePtrType TargetItem); FReply HandleOnAcceptDrop(const FDragDropEvent& DragDropEvent, EItemDropZone DropZone, FSubobjectEditorTreeNodePtrType TargetItem); public: /** Get the asset name of this subobject from the asset brokerage */ FText GetAssetName() const; /** Get the asset path of this subobject from the asset brokerage */ FText GetAssetPath() const; FText GetNameLabel() const; /** Check if this asset is visible from the asset brokerage */ EVisibility GetAssetVisibility() const; virtual const FSlateBrush* GetIconBrush() const; FSlateColor GetColorTintForIcon() const; FSubobjectEditorTreeNodePtrType GetSubobjectPtr() const { return SubobjectPtr; } private: static void AddToToolTipInfoBox(const TSharedRef& InfoBox, const FText& Key, TSharedRef ValueIcon, const TAttribute& Value, bool bImportant); /** Creates a tooltip for this row */ TSharedRef CreateToolTipWidget() const; /** Create the tooltip for component subobjects */ TSharedRef CreateComponentTooltipWidget(const FSubobjectEditorTreeNodePtrType& InNode) const; /** Create the tooltip for actor subobjects */ TSharedRef CreateActorTooltipWidget(const FSubobjectEditorTreeNodePtrType& InNode) const; FText GetTooltipText() const; FText GetActorClassNameText() const; FText GetActorSuperClassNameText() const; FText GetActorMobilityText() const; /** Returns a widget that represents the inheritance of this subobject which includes a hyperlink to edit the property */ TSharedRef GetInheritedLinkWidget(); /** Gets the context of this subobject, such as "(Self)" or "(Instance)" for actors. */ FText GetObjectContextText() const; FString GetDocumentationLink() const; FString GetDocumentationExcerptName() const; /** Callback used when the user clicks on a blueprint inherited variable */ void OnEditBlueprintClicked(); EVisibility GetEditBlueprintVisibility() const; EVisibility GetEditNativeCppVisibility() const; /** Callback used when the user clicks on a native inherited variable */ void OnEditNativeCppClicked(); /** * 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 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 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 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; /** * Retrieves tooltip text for the specified Native Component's underlying Name * * @returns An FText object containing the Component's Name */ FText GetNativeComponentNameToolTipText() const; FText GetActorDisplayText() const; /** Commits the new name of the component */ void OnNameTextCommit(const FText& InNewName, ETextCommit::Type InTextCommit); /** Verifies the name of the component when changing it */ bool OnNameTextVerifyChanged(const FText& InNewText, FText& OutErrorMessage); bool IsReadOnly() const; TWeakPtr SubobjectEditor; TSharedPtr InlineWidget; FSubobjectEditorTreeNodePtrType SubobjectPtr; }; ///////////////////////////////////////////////////// // SSubobjectEditor /** * The base class viewer for subobject editing in Slate. This displays * all subobjects of a given actor or blueprint. A subobject can be a native * component on an actor or inherited components from a native or blueprint parent. */ class SUBOBJECTEDITOR_API SSubobjectEditor : public SCompoundWidget { public: DECLARE_DELEGATE_OneParam(FOnSelectionUpdated, const TArray&); DECLARE_DELEGATE_OneParam(FOnItemDoubleClicked, const FSubobjectEditorTreeNodePtrType); protected: // Do not allow public construction of this widget! SSubobjectEditor() = default; virtual ~SSubobjectEditor() = default; /** Delegate to invoke on selection update. */ FOnSelectionUpdated OnSelectionUpdated; /** Delegate to invoke when an item in the tree is double clicked. */ FOnItemDoubleClicked OnItemDoubleClicked; /** Attribute that provides access to the Object context for which we are viewing/editing. */ TAttribute ObjectContext; /** 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; ///////////////////////////////////////////////////////// // Widget Callbacks protected: TSharedRef MakeTableRowWidget(FSubobjectEditorTreeNodePtrType InNodePtr, const TSharedRef& OwnerTable); /** @return The visibility of the components tree */ EVisibility GetComponentsTreeVisibility() const; /** Used by tree control - get children for a specified subobject node */ void OnGetChildrenForTree(FSubobjectEditorTreeNodePtrType InNodePtr, TArray& OutChildren); /** Update any associated selection (e.g. details view) from the passed in nodes */ void UpdateSelectionFromNodes(const TArray& SelectedNodes); /** Called when selection in the tree changes */ void OnTreeSelectionChanged(FSubobjectEditorTreeNodePtrType InSelectedNodePtr, ESelectInfo::Type SelectInfo); /** Callback when a component item is double clicked. */ void HandleItemDoubleClicked(FSubobjectEditorTreeNodePtrType InItem); void OnFindReferences(bool bSearchAllBlueprints, const EGetFindReferenceSearchStringFlags Flags); /** @return The visibility of the components filter box */ EVisibility GetComponentsFilterBoxVisibility() const; /** Recursively updates the filtered state for each component item */ void OnFilterTextChanged(const FText& InFilterText); /** Callback when a component item is scrolled into view */ void OnItemScrolledIntoView(FSubobjectEditorTreeNodePtrType InItem, const TSharedPtr& InWidget); /** SWidget interface */ virtual FReply OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) override; public: /** Select the given tree node */ void SelectNode(FSubobjectEditorTreeNodePtrType InNodeToSelect, bool bIsCntrlDown); /** Select the given tree node if there is on that matches the given handle */ void SelectNodeFromHandle(const FSubobjectDataHandle& InHandle, bool bIsCntrlDown); /** Update the contents of the Subobject Tree based on the current context */ 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(); /** Select the root of the tree */ void SelectRoot(); /** Get the tint color that any subobject editor icons should use. The default is the foreground color. */ virtual FSlateColor GetColorTintForIcon(FSubobjectEditorTreeNodePtrType Node) const; /** Get the currently selected nodes from the tree sorted in order from parent to child */ TArray GetSelectedNodes() const; /** Returns the number of currently selected nodes in the tree */ int32 GetNumSelectedNodes() const { return TreeWidget->GetSelectedItems().Num(); } /** Get the currently selected handles from the tree sorted in order from parent to child */ TArray GetSelectedHandles() const; virtual FSubobjectEditorTreeNodePtrType GetSceneRootNode() const; /** Try to handle a drag-drop operation */ FReply TryHandleAssetDragDropOperation(const FDragDropEvent& DragDropEvent); /** Sets UI customizations of this SCSEditor. */ void SetUICustomization(TSharedPtr InUICustomization); virtual bool IsEditingAllowed() const; /** Return the button widgets that can add components or create/edit blueprints */ TSharedPtr GetToolButtonsBox() const; TSharedPtr GetCommandList() const { return CommandList; } TSharedPtr GetDragDropTree() const { return TreeWidget; } // Drag/drop operations /** Handler for attaching a single node to this node */ void OnAttachToDropAction(FSubobjectEditorTreeNodePtrType DroppedOn, FSubobjectEditorTreeNodePtrType DroppedNodePtr) { TArray DroppedNodePtrs; DroppedNodePtrs.Add(DroppedNodePtr); OnAttachToDropAction(DroppedOn, DroppedNodePtrs); } virtual void OnAttachToDropAction(FSubobjectEditorTreeNodePtrType DroppedOn, const TArray& DroppedNodePtrs) = 0; virtual void OnDetachFromDropAction(const TArray& DroppedNodePtrs) = 0; virtual void OnMakeNewRootDropAction(FSubobjectEditorTreeNodePtrType DroppedNodePtr) = 0; virtual void PostDragDropAction(bool bRegenerateTreeNodes) = 0; /** Builds a context menu popup for dropping a child node onto the scene root node */ virtual TSharedPtr BuildSceneRootDropActionMenu(FSubobjectEditorTreeNodePtrType DroppedOntoNodePtr, FSubobjectEditorTreeNodePtrType DroppedNodePtr) = 0; virtual bool CanMakeNewRootOnDrag(UBlueprint* DraggedFromBlueprint) const { return false; } /** Provides access to the Blueprint context that's being edited */ UBlueprint* GetBlueprint() const; // Attempt to find an existing slate node that matches the given handle virtual FSubobjectEditorTreeNodePtrType FindSlateNodeForObject(const UObject* InObject, bool bIncludeAttachmentComponents = true) const; /** 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; /** * Fills the supplied array with the currently selected objects * @param OutSelectedItems The array to fill. */ void GetSelectedItemsForContextMenu(TArray& OutSelectedItems) const; /** Return an array of the current slate node hierarchy in the tree */ const TArray& GetRootNodes() const { return RootNodes; }; // Attempt to find an existing slate node that matches the given handle FSubobjectEditorTreeNodePtrType FindSlateNodeForHandle(const FSubobjectDataHandle& Handle, FSubobjectEditorTreeNodePtrType InStartNodePtr = FSubobjectEditorTreeNodePtrType()) const; // Attempt to find an existing slate node that has a given variable name FSubobjectEditorTreeNodePtrType FindSlateNodeForVariableName(FName InVariableName) const; /** Pointer to the current object that is represented by the subobject editor */ UObject* GetObjectContext() const; /** SubobjectHandle of the current object that is represented by the subobject editor */ FSubobjectDataHandle GetObjectContextHandle() const; /** Refresh the type list presented by the add component button when clicked */ void RefreshComponentTypesList(); protected: /** Restore the previous selection state when updating the tree */ virtual void RestoreSelectionState(TArray& SelectedTreeNodes, bool bFallBackToVariableName = true); /** If true, then the blueprint should be modified on TryHandleAssetDragDropOperation */ virtual bool ShouldModifyBPOnAssetDrop() const { return false; } bool CanCutNodes() const; void CutSelectedNodes(); bool CanCopyNodes() const; virtual void CopySelectedNodes() = 0; /** Pastes previously copied node(s) */ virtual bool CanPasteNodes() const; virtual void PasteNodes() = 0; public: /** Removes existing selected component nodes from the SCS */ virtual bool CanDeleteNodes() const; virtual void OnDeleteNodes() = 0; protected: bool CanDuplicateComponent() const; virtual void OnDuplicateComponent() = 0; /** Checks to see if renaming is allowed on the selected component */ bool CanRenameComponent() const; void OnRenameComponent(); void OnRenameComponent(TUniquePtr InComponentCreateTransaction); /** Called at the end of each frame. */ void OnPostTick(float); ///////////////////////////////////////////////////////// // Widgets /** Root set of tree that represents all subobjects for the current context */ TArray RootNodes; /** Tree widget */ TSharedPtr TreeWidget; /** Command list for handling actions in the editor. */ TSharedPtr CommandList; /** The filter box that handles filtering for the tree. */ TSharedPtr FilterBox; /** The tools buttons box */ TSharedPtr ButtonBox; /** The add component button / type selector */ TSharedPtr ComponentClassCombo; /** 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; /** SCSEditor UI customizations */ TSharedPtr UICustomization; /** SCSEditor UI extension */ TSharedPtr ExtensionPanel; /** 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; /** Name of a node that has been requested to be renamed */ FSubobjectDataHandle DeferredRenameRequest; /** * The handle to the current root context. If this is different in between * UpdateTree calls, then we know the context has changed and we should clean up * the subobject memory layout. */ FSubobjectDataHandle CachedRootHandle; virtual FMenuBuilder CreateMenuBuilder(); /** Constructs the slate drag/drop tree for this subobject editor */ virtual void ConstructTreeWidget(); /** Creates a list of commands */ virtual void CreateCommandList(); /** Recursively visits the given node + its children and invokes the given function for each. */ void DepthFirstTraversal(const FSubobjectEditorTreeNodePtrType& InNodePtr, TSet& OutVisitedNodes, const TFunctionRef InFunction) const; /** Returns the set of expandable nodes that are currently collapsed in the UI */ void GetCollapsedNodes(const FSubobjectEditorTreeNodePtrType& InNodePtr, TSet& OutCollapsedNodes) const; // Attempt to find an existing slate node that matches the given handle static FSubobjectEditorTreeNodePtrType FindOrCreateSlateNodeForHandle(const FSubobjectDataHandle& Handle, TMap& ExistingNodes); /** * 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(FSubobjectEditorTreeNodePtrType InNodeToChange, const bool bIsExpanded); /** Handler for recursively expanding/collapsing items */ void SetItemExpansionRecursive(FSubobjectEditorTreeNodePtrType Model, bool bInExpansionState); /** Registers context menu by name for later access */ void RegisterContextMenu(); /** Called to display context menu when right clicking on the widget */ TSharedPtr CreateContextMenu(); /** Populate context menu on the fly */ void PopulateContextMenu(UToolMenu* InMenu); /** Populate the context menu with implementation specific details */ virtual void PopulateContextMenuImpl(UToolMenu* InMenu, TArray& InSelectedItems, bool bIsChildActorSubtreeNodeSelected) = 0; /** @return Type of component to filter the tree view with or nullptr if there's no filter. */ TSubclassOf GetComponentTypeFilterToApply() const; /** * 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(FSubobjectEditorTreeNodePtrType TreeNode, bool bRecursive); /** Callback for the action trees to get the filter text */ FText GetFilterText() const; /** Converts the current actor instance to a blueprint */ void PromoteToBlueprint() const; /** Called when the promote to blueprint button is clicked */ FReply OnPromoteToBlueprintClicked(); /** Opens the blueprint editor for the blueprint being viewed by the scseditor */ void OnOpenBlueprintEditor(bool bForceCodeEditing) const; /** * Spawns a new SWindow giving the user options for creating a new C++ component class. * The user will be prompted to pick a new subclass name and code will be recompiled * * @return The new class that was created */ UClass* SpawnCreateNewCppComponentWindow(TSubclassOf ComponentClass); /** * Spawns a new SWindow giving the user options for creating a new blueprint component class. * 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* SpawnCreateNewBPComponentWindow(TSubclassOf ComponentClass); /** Add a component from the selection in the combo box */ FSubobjectDataHandle PerformComboAddClass(TSubclassOf ComponentClass, EComponentCreateAction::Type ComponentCreateAction, UObject* AssetOverride); /** @return The visibility of the promote to blueprint button (only visible with an actor instance that is not created from a blueprint)*/ virtual EVisibility GetPromoteToBlueprintButtonVisibility() const; /** @return The visibility of the Edit Blueprint button (only visible with an actor instance that is created from a blueprint)*/ virtual EVisibility GetEditBlueprintButtonVisibility() const; /** @return The visibility of the Add Component combo button */ virtual EVisibility GetComponentClassComboButtonVisibility() const; /** If true, then the tree widget will clear selection on click. */ virtual bool ClearSelectionOnClick() const { return false; } /** Indicates whether or not the search bar and inline buttons are visible. */ virtual bool ShowInlineSearchWithButtons() const { return false; } /** Add a new subobject to the given parent via the subobject data subsystem */ virtual FSubobjectDataHandle AddNewSubobject(const FSubobjectDataHandle& ParentHandle, UClass* NewClass, UObject* AssetOverride, FText& OutFailReason, TUniquePtr InOngoingTransaction) = 0; /////////////////////////////////////// // Utils struct Utils { /** Populate an array of subobject handles based on an array of the slate node ptr */ static void PopulateHandlesArray(const TArray& SlateNodePtrs, TArray& OutHandles); }; };