// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "UObject/WeakObjectPtr.h" #include "EditorUndoClient.h" #include "StateTreeViewModel.generated.h" class FMenuBuilder; class UStateTree; class UStateTreeEditorData; class UStateTreeState; enum class ECheckBoxState : uint8; enum class EStateTreeBreakpointType : uint8; struct FPropertyChangedEvent; struct FStateTreeDebugger; struct FStateTreeDebuggerBreakpoint; struct FStateTreeEditorBreakpoint; struct FStateTreePropertyPathBinding; enum class EStateTreeViewModelInsert : uint8 { Before, After, Into, }; enum class UE_DEPRECATED(5.6, "Use the enum with the E prefix") FStateTreeViewModelInsert : uint8 { Before, After, Into, }; /** * ModelView for editing StateTreeEditorData. */ class STATETREEEDITORMODULE_API FStateTreeViewModel : public FEditorUndoClient, public TSharedFromThis { public: DECLARE_MULTICAST_DELEGATE(FOnAssetChanged); DECLARE_MULTICAST_DELEGATE_TwoParams(FOnStatesChanged, const TSet& /*AffectedStates*/, const FPropertyChangedEvent& /*PropertyChangedEvent*/); DECLARE_MULTICAST_DELEGATE_TwoParams(FOnStateAdded, UStateTreeState* /*ParentState*/, UStateTreeState* /*NewState*/); DECLARE_MULTICAST_DELEGATE_OneParam(FOnStatesRemoved, const TSet& /*AffectedParents*/); DECLARE_MULTICAST_DELEGATE_TwoParams(FOnStatesMoved, const TSet& /*AffectedParents*/, const TSet& /*MovedStates*/); DECLARE_MULTICAST_DELEGATE_OneParam(FOnStateNodesChanged, const UStateTreeState* /*AffectedState*/); DECLARE_MULTICAST_DELEGATE_OneParam(FOnSelectionChanged, const TArray>& /*SelectedStates*/); DECLARE_MULTICAST_DELEGATE_TwoParams(FOnBringNodeToFocus, const UStateTreeState* /*State*/, const FGuid /*NodeID*/); FStateTreeViewModel(); virtual ~FStateTreeViewModel() override; void Init(UStateTreeEditorData* InTreeData); //~ FEditorUndoClient virtual void PostUndo(bool bSuccess) override; virtual void PostRedo(bool bSuccess) override; // Selection handling. void ClearSelection(); void SetSelection(UStateTreeState* Selected); void SetSelection(const TArray>& InSelection); bool IsSelected(const UStateTreeState* State) const; bool IsChildOfSelection(const UStateTreeState* State) const; void GetSelectedStates(TArray& OutSelectedStates) const; void GetSelectedStates(TArray>& OutSelectedStates) const; bool HasSelection() const; void BringNodeToFocus(UStateTreeState* State, const FGuid NodeID); // Returns associated state tree asset. const UStateTree* GetStateTree() const; const UStateTreeEditorData* GetStateTreeEditorData() const; const UStateTreeState* GetStateByID(const FGuid StateID) const; UStateTreeState* GetMutableStateByID(const FGuid StateID) const; // Returns array of subtrees to edit. TArray>* GetSubTrees() const; int32 GetSubTreeCount() const; void GetSubTrees(TArray>& OutSubtrees) const; /** Find the states that are linked to the provided StateID. */ void GetLinkStates(FGuid StateID, TArray& LinkingIn, TArray& LinkedOut) const; // Gets and sets StateTree view expansion state store in the asset. void SetPersistentExpandedStates(TSet>& InExpandedStates); void GetPersistentExpandedStates(TSet>& OutExpandedStates); // State manipulation void AddState(UStateTreeState* AfterState); void AddChildState(UStateTreeState* ParentState); void RenameState(UStateTreeState* State, FName NewName); void RemoveSelectedStates(); void CopySelectedStates(); bool CanPasteStatesFromClipboard() const; void PasteStatesFromClipboard(UStateTreeState* AfterState); void PasteStatesAsChildrenFromClipboard(UStateTreeState* ParentState); void DuplicateSelectedStates(); void MoveSelectedStatesBefore(UStateTreeState* TargetState); void MoveSelectedStatesAfter(UStateTreeState* TargetState); void MoveSelectedStatesInto(UStateTreeState* TargetState); bool CanEnableStates() const; bool CanDisableStates() const; void SetSelectedStatesEnabled(bool bEnable); // EditorNode and Transition manipulation // @todo: support Add, ReplaceWith and Rename void DeleteNode(TWeakObjectPtr State, const FGuid& ID); void DeleteAllNodes(TWeakObjectPtr State, const FGuid& ID); void CopyNode(TWeakObjectPtr State, const FGuid& ID); void PasteNode(TWeakObjectPtr State, const FGuid& ID); void DuplicateNode(TWeakObjectPtr State, const FGuid& ID); // Force to update the view externally. void NotifyAssetChangedExternally() const; void NotifyStatesChangedExternally(const TSet& ChangedStates, const FPropertyChangedEvent& PropertyChangedEvent) const; // Debugging #if WITH_STATETREE_TRACE_DEBUGGER bool CanAddStateBreakpoint(EStateTreeBreakpointType Type) const; bool CanRemoveStateBreakpoint(EStateTreeBreakpointType Type) const; ECheckBoxState GetStateBreakpointCheckState(EStateTreeBreakpointType Type) const; void HandleEnableStateBreakpoint(EStateTreeBreakpointType Type); UStateTreeState* FindStateAssociatedToBreakpoint(FStateTreeDebuggerBreakpoint Breakpoint) const; TSharedRef GetDebugger() const { return Debugger; } void RefreshDebuggerBreakpoints(); #endif // WITH_STATETREE_TRACE_DEBUGGER bool IsStateActiveInDebugger(const UStateTreeState& State) const; // Called when the whole asset is updated (i.e. undo/redo). FOnAssetChanged& GetOnAssetChanged() { return OnAssetChanged; } // Called when States are changed (i.e. change name or properties). FOnStatesChanged& GetOnStatesChanged() { return OnStatesChanged; } // Called each time a state is added. FOnStateAdded& GetOnStateAdded() { return OnStateAdded; } // Called each time a states are removed. FOnStatesRemoved& GetOnStatesRemoved() { return OnStatesRemoved; } // Called each time a state is removed. FOnStatesMoved& GetOnStatesMoved() { return OnStatesMoved; } // Called each time a state's Editor nodes or transitions are changed except from the DetailsView. FOnStateNodesChanged& GetOnStateNodesChanged() { return OnStateNodesChanged; } // Called each time the selection changes. FOnSelectionChanged& GetOnSelectionChanged() { return OnSelectionChanged; } FOnBringNodeToFocus& GetOnBringNodeToFocus() { return OnBringNodeToFocus; } protected: void GetExpandedStatesRecursive(UStateTreeState* State, TSet>& ExpandedStates); void MoveSelectedStates(UStateTreeState* TargetState, const EStateTreeViewModelInsert RelativeLocation); void PasteStatesAsChildrenFromText(const FString& TextToImport, UStateTreeState* ParentState, const int32 IndexToInsertAt); void HandleIdentifierChanged(const UStateTree& StateTree) const; void BindToDebuggerDelegates(); TWeakObjectPtr TreeDataWeak; TSet> SelectedStates; #if WITH_STATETREE_TRACE_DEBUGGER void HandleBreakpointsChanged(const UStateTree& StateTree); void HandlePostCompile(const UStateTree& StateTree); TSharedRef Debugger; TArray ActiveStates; #endif // WITH_STATETREE_TRACE_DEBUGGER FOnAssetChanged OnAssetChanged; FOnStatesChanged OnStatesChanged; FOnStateAdded OnStateAdded; FOnStatesRemoved OnStatesRemoved; FOnStatesMoved OnStatesMoved; FOnStateNodesChanged OnStateNodesChanged; FOnSelectionChanged OnSelectionChanged; FOnBringNodeToFocus OnBringNodeToFocus; }; /** Helper class to allow to copy bindings into clipboard. */ UCLASS(Hidden) class STATETREEEDITORMODULE_API UStateTreeClipboardBindings : public UObject { GENERATED_BODY() public: UPROPERTY() TArray Bindings; };