Files
UnrealEngine/Engine/Source/Editor/SkeletalMeshEditor/Private/SkeletalMeshEditor.h
2025-05-18 13:04:45 +08:00

267 lines
9.0 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Stats/Stats.h"
#include "UObject/GCObject.h"
#include "TickableEditorObject.h"
#include "EditorUndoClient.h"
#include "Toolkits/IToolkitHost.h"
#include "ISkeletalMeshEditor.h"
#include "SkeletalMeshNotifier.h"
#include "Containers/ArrayView.h"
#include "Async/Future.h"
class IDetailLayoutBuilder;
class IDetailsView;
class IPersonaToolkit;
class IPersonaViewport;
class ISkeletonTree;
class USkeletalMesh;
class UClothingAssetBase;
class ISkeletonTreeItem;
struct HActor;
struct FViewportClick;
struct FSkeletalMeshClothBuildParams;
struct FToolMenuContext;
class UToolMenu;
class SSkeletalMeshEditorToolbox;
class FSkeletalMeshEditorBinding;
namespace SkeletalMeshEditorModes
{
// Mode identifiers
extern const FName SkeletalMeshEditorMode;
}
namespace SkeletalMeshEditorTabs
{
// Tab identifiers
extern const FName DetailsTab;
extern const FName SkeletonTreeTab;
extern const FName ViewportTab;
extern const FName AdvancedPreviewTab;
extern const FName AssetDetailsTab;
extern const FName MorphTargetsTab;
extern const FName MeshDetailsTab;
extern const FName AnimationMappingTab;
extern const FName CurveMetadataTab;
extern const FName FindReplaceTab;
}
class FSkeletalMeshEditor : public ISkeletalMeshEditor, public FGCObject, public FEditorUndoClient, public FTickableEditorObject
{
public:
FSkeletalMeshEditor();
virtual ~FSkeletalMeshEditor();
/** Edits the specified Skeleton object */
void InitSkeletalMeshEditor(const EToolkitMode::Type Mode, const TSharedPtr<class IToolkitHost>& InitToolkitHost, class USkeletalMesh* InSkeletalMesh);
/** IHasPersonaToolkit interface */
virtual TSharedRef<class IPersonaToolkit> GetPersonaToolkit() const override { return PersonaToolkit.ToSharedRef(); }
/** IToolkit interface */
virtual void RegisterTabSpawners(const TSharedRef<class FTabManager>& TabManager) override;
virtual void UnregisterTabSpawners(const TSharedRef<class FTabManager>& TabManager) override;
virtual FName GetToolkitFName() const override;
virtual FText GetBaseToolkitName() const override;
virtual FString GetWorldCentricTabPrefix() const override;
virtual FLinearColor GetWorldCentricTabColorScale() const override;
virtual void InitToolMenuContext(FToolMenuContext& MenuContext) override;
virtual void AddViewportOverlayWidget(TSharedRef<SWidget> InOverlaidWidget, int32 ZOrder = INDEX_NONE) override;
virtual void RemoveViewportOverlayWidget(TSharedRef<SWidget> InOverlaidWidget) override;
/** FBaseToolkit overrides */
virtual bool ProcessCommandBindings(const FKeyEvent& InKeyEvent) const override;
//~ Begin FAssetEditorToolkit Interface.
virtual bool OnRequestClose(EAssetEditorCloseReason InCloseReason) override;
//~ End FAssetEditorToolkit Interface.
/** FEditorUndoClient interface */
virtual void PostUndo(bool bSuccess) override;
virtual void PostRedo(bool bSuccess) override;
/** FTickableEditorObject Interface */
virtual void Tick(float DeltaTime) override;
virtual TStatId GetStatId() const override;
virtual ETickableTickType GetTickableTickType() const override { return ETickableTickType::Always; }
/** @return the documentation location for this editor */
virtual FString GetDocumentationLink() const override
{
return FString(TEXT("AnimatingObjects/SkeletalMeshAnimation/Persona/Modes/Mesh"));
}
/** FGCObject interface */
virtual void AddReferencedObjects(FReferenceCollector& Collector) override;
virtual FString GetReferencerName() const override
{
return TEXT("FSkeletalMeshEditor");
}
/** Get the skeleton tree widget */
TSharedRef<class ISkeletonTree> GetSkeletonTree() const { return SkeletonTree.ToSharedRef(); }
/** Get the MorphTargetViewer widget */
TSharedRef<class IMorphTargetViewer> GetMorphTargetViewer() const {return MorphTargetViewer.ToSharedRef(); }
void HandleDetailsCreated(const TSharedRef<class IDetailsView>& InDetailsView);
void HandleMeshDetailsCreated(const TSharedRef<class IDetailsView>& InDetailsView);
void HandleViewportCreated(const TSharedRef<class IPersonaViewport>& InViewport);
UObject* HandleGetAsset();
void HandleObjectsSelected(const TArray<UObject*>& InObjects);
// Returns the currently hosted toolkit. Can be invalid if no toolkit is being hosted.
TSharedPtr<IToolkit> GetHostedToolkit() const { return HostedToolkit; }
virtual TSharedPtr<ISkeletalMeshEditorBinding> GetBinding() override;
private:
void HandleObjectSelected(UObject* InObject);
void HandleSelectionChanged(const TArrayView<TSharedPtr<ISkeletonTreeItem>>& InSelectedItems, ESelectInfo::Type InSelectInfo);
struct FReimportParameters
{
FReimportParameters(int32 InSourceFileIndex, bool bInWithNewFile, bool bInReimportWithDialog)
: SourceFileIndex(InSourceFileIndex)
, bWithNewFile(bInWithNewFile)
, bReimportWithDialog(bInReimportWithDialog)
{}
int32 SourceFileIndex = INDEX_NONE;
bool bWithNewFile = false;
bool bReimportWithDialog = false;
};
void HandleReimportMesh(const FReimportParameters ReimportParameters);
TFuture<bool> HandleReimportMeshInternal(const FReimportParameters& ReimportParameters);
void HandleReimportAllMesh(const FReimportParameters ReimportParameters);
void HandleReimportAllMeshInternal(const FReimportParameters& ReimportParameters);
void HandleOnPreviewSceneSettingsCustomized(IDetailLayoutBuilder& DetailBuilder);
/** Callback for checking whether the UV drawing is switched on. */
bool IsMeshSectionSelectionChecked() const;
void HandleMeshClick(HActor* HitProxy, const FViewportClick& Click);
// Clothing menu handlers (builds and handles clothing context menu options)
void FillApplyClothingAssetMenu(FMenuBuilder& MenuBuilder, int32 InLodIndex, int32 InSectionIndex);
void FillCreateClothingMenu(FMenuBuilder& MenuBuilder, int32 InLodIndex, int32 InSectionIndex);
void FillCreateClothingLodMenu(FMenuBuilder& MenuBuilder, int32 InLodIndex, int32 InSectionIndex);
void OnRemoveClothingAssetMenuItemClicked(int32 InLodIndex, int32 InSectionIndex);
void OnCreateClothingAssetMenuItemClicked(FSkeletalMeshClothBuildParams& Params);
void OnApplyClothingAssetClicked(UClothingAssetBase* InAssetToApply, int32 InMeshLodIndex, int32 InMeshSectionIndex, int32 InClothLodIndex);
bool CanApplyClothing(int32 InLodIndex, int32 InSectionIndex);
bool CanRemoveClothing(int32 InLodIndex, int32 InSectionIndex);
bool CanCreateClothing(int32 InLodIndex, int32 InSectionIndex);
bool CanCreateClothingLod(int32 InLodIndex, int32 InSectionIndex);
void ApplyClothing(UClothingAssetBase* InAsset, int32 InLodIndex, int32 InSectionIndex, int32 InClothingLod);
void RemoveClothing(int32 InLodIndex, int32 InSectionIndex);
//////////////////////////////////////////////////////////////////////////
// Generate LOD sections menu handlers
void OnRemoveSectionFromLodAndBelowMenuItemClicked(int32 LodIndex, int32 SectionIndex);
//////////////////////////////////////////////////////////////////////////
void RegisterReimportContextMenu(const FName InBaseMenuName, bool bWithDialog);
static TSharedPtr<FSkeletalMeshEditor> GetSkeletalMeshEditor(const FToolMenuContext& InMenuContext);
private:
void ExtendMenu();
void BakeMaterials();
void ExtendToolbar();
void BindCommands();
public:
/** Multicast delegate fired on global undo/redo */
FSimpleMulticastDelegate OnPostUndo;
/** Multicast delegate fired on curves changing */
FSimpleMulticastDelegate OnCurvesChanged;
private:
/** The skeleton we are editing */
TObjectPtr<USkeletalMesh> SkeletalMesh;
/** Toolbar extender */
TSharedPtr<FExtender> ToolbarExtender;
/** Menu extender */
TSharedPtr<FExtender> MenuExtender;
/** Persona toolkit */
TSharedPtr<class IPersonaToolkit> PersonaToolkit;
/** Skeleton tree */
TSharedPtr<class ISkeletonTree> SkeletonTree;
/** Morph target viewer */
TSharedPtr<class IMorphTargetViewer> MorphTargetViewer;
/** Viewport */
TSharedPtr<class IPersonaViewport> Viewport;
/** Details panel */
TSharedPtr<class IDetailsView> DetailsView;
// The toolkit we're currently hosting.
TSharedPtr<IToolkit> HostedToolkit;
// The toolbox widget
TSharedPtr<SSkeletalMeshEditorToolbox> ToolboxWidget;
// Binding to send/receive skeletal mesh modifications
TSharedPtr<FSkeletalMeshEditorBinding> Binding;
};
/**
* FSkeletalMeshEditorNotifier
*/
class FSkeletalMeshEditorNotifier: public ISkeletalMeshNotifier
{
public:
FSkeletalMeshEditorNotifier(TSharedRef<FSkeletalMeshEditor> InEditor);
virtual void HandleNotification(const TArray<FName>& BoneNames, const ESkeletalMeshNotifyType InNotifyType) override;
private:
TWeakPtr<FSkeletalMeshEditor> Editor;
};
/**
* FSkeletalMeshEditorBinding
*/
class FSkeletalMeshEditorBinding: public ISkeletalMeshEditorBinding
{
public:
FSkeletalMeshEditorBinding(TSharedRef<FSkeletalMeshEditor> InEditor);
virtual ISkeletalMeshNotifier& GetNotifier() override;
virtual NameFunction GetNameFunction() override;
virtual TArray<FName> GetSelectedBones() const override;
virtual TArray<FName> GetSelectedMorphTargets() const override;
private:
TWeakPtr<FSkeletalMeshEditor> Editor;
FSkeletalMeshEditorNotifier Notifier;
};