更新 Source/FLESHEditor/Private/DismembermentEditor.cpp

This commit is contained in:
2025-04-21 18:17:01 +08:00
parent 96feec1de7
commit f142457a31

View File

@@ -1,61 +1,362 @@
#pragma once
#include "DismembermentEditor.h"
#include "Widgets/Docking/SDockTab.h"
#include "PropertyEditorModule.h"
#include "Modules/ModuleManager.h"
#include "IDetailsView.h"
#include "Widgets/Layout/SBorder.h"
#include "Styling/AppStyle.h"
#include "Engine/SkeletalMesh.h"
#include "Framework/Commands/UICommandList.h"
#include "Framework/MultiBox/MultiBoxBuilder.h"
#include "ToolMenus.h"
#include "CoreMinimal.h"
#include "Toolkits/AssetEditorToolkit.h"
#include "EditorUndoClient.h"
// Define tab names
const FName FDismembermentEditor::ViewportTabId(TEXT("DismembermentEditor_Viewport"));
const FName FDismembermentEditor::DetailsTabId(TEXT("DismembermentEditor_Details"));
const FName FDismembermentEditor::LayerSystemTabId(TEXT("DismembermentEditor_LayerSystem"));
const FName FDismembermentEditor::PhysicsSettingsTabId(TEXT("DismembermentEditor_PhysicsSettings"));
class USkeletalMesh;
class SDockTab;
class IDetailsView;
class SBorder;
/**
* Dismemberment System Editor
* Provides real-time boolean cutting and multi-layer system editing functionality
*/
class FDismembermentEditor : public FAssetEditorToolkit, public FEditorUndoClient
// Constructor
FDismembermentEditor::FDismembermentEditor()
: SkeletalMesh(nullptr)
{
public:
FDismembermentEditor();
virtual ~FDismembermentEditor();
}
// Destructor
FDismembermentEditor::~FDismembermentEditor()
{
}
// Initialize the editor
void FDismembermentEditor::InitDismembermentEditor(const EToolkitMode::Type Mode, const TSharedPtr<IToolkitHost>& InitToolkitHost, USkeletalMesh* InSkeletalMesh)
{
// Set the skeletal mesh being edited
SkeletalMesh = InSkeletalMesh;
void InitDismembermentEditor(const EToolkitMode::Type Mode, const TSharedPtr<IToolkitHost>& InitToolkitHost, USkeletalMesh* InSkeletalMesh);
// Create the layout
CreateEditorLayout();
virtual FName GetToolkitFName() const override;
virtual FText GetBaseToolkitName() const override;
virtual FString GetWorldCentricTabPrefix() const override;
virtual FLinearColor GetWorldCentricTabColorScale() const override;
// Create the toolbar
CreateEditorToolbar();
virtual void PostUndo(bool bSuccess) override;
virtual void PostRedo(bool bSuccess) override;
// Initialize the asset editor
InitAssetEditor(Mode, InitToolkitHost, FName("DismembermentEditorApp"),
FTabManager::FLayout::NullLayout,
/*bCreateDefaultStandaloneMenu=*/ true,
/*bCreateDefaultToolbar=*/ true,
InSkeletalMesh);
private:
void CreateEditorLayout();
void CreateEditorToolbar();
// Register for undo/redo
GEditor->RegisterForUndo(this);
}
// Get the toolkit name
FName FDismembermentEditor::GetToolkitFName() const
{
return FName("DismembermentEditor");
}
// Get the base toolkit name
FText FDismembermentEditor::GetBaseToolkitName() const
{
return FText::FromString("Dismemberment Editor");
}
// Get the world centric tab prefix
FString FDismembermentEditor::GetWorldCentricTabPrefix() const
{
return "DismembermentEditor";
}
// Get the world centric tab color scale
FLinearColor FDismembermentEditor::GetWorldCentricTabColorScale() const
{
return FLinearColor(0.3f, 0.2f, 0.5f, 0.5f);
}
// Post undo handler
void FDismembermentEditor::PostUndo(bool bSuccess)
{
// Refresh the views
if (DetailsWidget.IsValid())
{
DetailsWidget->ForceRefresh();
}
}
// Post redo handler
void FDismembermentEditor::PostRedo(bool bSuccess)
{
// Refresh the views
if (DetailsWidget.IsValid())
{
DetailsWidget->ForceRefresh();
}
}
// Create the editor layout
void FDismembermentEditor::CreateEditorLayout()
{
// Create the layout
TSharedRef<FTabManager::FLayout> StandaloneDefaultLayout = FTabManager::NewLayout("Standalone_DismembermentEditor_Layout_v1")
->AddArea
(
FTabManager::NewPrimaryArea()->SetOrientation(Orient_Vertical)
// In UE5.5.4, toolbar is no longer a separate tab
// Skip the toolbar tab section and directly create the main content area
->Split
(
FTabManager::NewSplitter()->SetOrientation(Orient_Horizontal)->SetSizeCoefficient(0.9f)
->Split
(
FTabManager::NewStack()
->SetSizeCoefficient(0.7f)
->AddTab(ViewportTabId, ETabState::OpenedTab)
)
->Split
(
FTabManager::NewSplitter()->SetOrientation(Orient_Vertical)
->SetSizeCoefficient(0.3f)
->Split
(
FTabManager::NewStack()
->SetSizeCoefficient(0.4f)
->AddTab(DetailsTabId, ETabState::OpenedTab)
)
->Split
(
FTabManager::NewStack()
->SetSizeCoefficient(0.3f)
->AddTab(LayerSystemTabId, ETabState::OpenedTab)
)
->Split
(
FTabManager::NewStack()
->SetSizeCoefficient(0.3f)
->AddTab(PhysicsSettingsTabId, ETabState::OpenedTab)
)
)
)
);
// Set the layout
FAssetEditorToolkit::InitAssetEditor(
EToolkitMode::Standalone,
TSharedPtr<IToolkitHost>(),
FName("DismembermentEditorApp"),
StandaloneDefaultLayout,
true,
true,
SkeletalMesh
);
}
// Create the editor toolbar
void FDismembermentEditor::CreateEditorToolbar()
{
// Create command list
TSharedPtr<FUICommandList> CommandList = MakeShareable(new FUICommandList);
void RegisterTabSpawners(const TSharedRef<FTabManager>& InTabManager);
void UnregisterTabSpawners(const TSharedRef<FTabManager>& InTabManager);
// Get the toolbar builder
TSharedPtr<FExtender> ToolbarExtender = MakeShareable(new FExtender);
TSharedRef<SDockTab> SpawnTab_Viewport(const FSpawnTabArgs& Args);
TSharedRef<SDockTab> SpawnTab_Details(const FSpawnTabArgs& Args);
TSharedRef<SDockTab> SpawnTab_LayerSystem(const FSpawnTabArgs& Args);
TSharedRef<SDockTab> SpawnTab_PhysicsSettings(const FSpawnTabArgs& Args);
ToolbarExtender->AddToolBarExtension(
"Asset",
EExtensionHook::After,
CommandList,
FToolBarExtensionDelegate::CreateLambda([this](FToolBarBuilder& ToolbarBuilder)
{
ToolbarBuilder.BeginSection("Dismemberment");
{
ToolbarBuilder.AddToolBarButton(
FUIAction(FExecuteAction::CreateSP(this, &FDismembermentEditor::PerformBooleanCut)),
NAME_None,
FText::FromString("Boolean Cut"),
FText::FromString("Perform a boolean cut operation"),
FSlateIcon(FAppStyle::GetAppStyleSetName(), "ClassIcon.CurveBase"),
EUserInterfaceActionType::Button
);
ToolbarBuilder.AddToolBarButton(
FUIAction(FExecuteAction::CreateSP(this, &FDismembermentEditor::AddNewLayer)),
NAME_None,
FText::FromString("Add Layer"),
FText::FromString("Add a new anatomical layer"),
FSlateIcon(FAppStyle::GetAppStyleSetName(), "ClassIcon.Layer"),
EUserInterfaceActionType::Button
);
ToolbarBuilder.AddToolBarButton(
FUIAction(FExecuteAction::CreateSP(this, &FDismembermentEditor::PreviewEffects)),
NAME_None,
FText::FromString("Preview"),
FText::FromString("Preview the dismemberment effects"),
FSlateIcon(FAppStyle::GetAppStyleSetName(), "ClassIcon.ParticleSystem"),
EUserInterfaceActionType::Button
);
ToolbarBuilder.AddToolBarButton(
FUIAction(FExecuteAction::CreateSP(this, &FDismembermentEditor::SaveEdits)),
NAME_None,
FText::FromString("Save"),
FText::FromString("Save the dismemberment setup"),
FSlateIcon(FAppStyle::GetAppStyleSetName(), "AssetEditor.SaveAsset"),
EUserInterfaceActionType::Button
);
}
ToolbarBuilder.EndSection();
})
);
void PerformBooleanCut();
void AddNewLayer();
void SaveEdits();
void PreviewEffects();
// Add the extender
AddToolbarExtender(ToolbarExtender);
}
// Register tab spawners
void FDismembermentEditor::RegisterTabSpawners(const TSharedRef<FTabManager>& InTabManager)
{
// Call the base implementation
FAssetEditorToolkit::RegisterTabSpawners(InTabManager);
private:
USkeletalMesh* SkeletalMesh;
// Register the tab spawners
InTabManager->RegisterTabSpawner(ViewportTabId, FOnSpawnTab::CreateSP(this, &FDismembermentEditor::SpawnTab_Viewport))
.SetDisplayName(FText::FromString("Viewport"))
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
.SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "LevelEditor.Tabs.Viewports"));
InTabManager->RegisterTabSpawner(DetailsTabId, FOnSpawnTab::CreateSP(this, &FDismembermentEditor::SpawnTab_Details))
.SetDisplayName(FText::FromString("Details"))
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
.SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "LevelEditor.Tabs.Details"));
InTabManager->RegisterTabSpawner(LayerSystemTabId, FOnSpawnTab::CreateSP(this, &FDismembermentEditor::SpawnTab_LayerSystem))
.SetDisplayName(FText::FromString("Layer System"))
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
.SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "ClassIcon.Layer"));
InTabManager->RegisterTabSpawner(PhysicsSettingsTabId, FOnSpawnTab::CreateSP(this, &FDismembermentEditor::SpawnTab_PhysicsSettings))
.SetDisplayName(FText::FromString("Physics Settings"))
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
.SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "ClassIcon.PhysicsAsset"));
}
// Unregister tab spawners
void FDismembermentEditor::UnregisterTabSpawners(const TSharedRef<FTabManager>& InTabManager)
{
// Call the base implementation
FAssetEditorToolkit::UnregisterTabSpawners(InTabManager);
TSharedPtr<SBorder> ViewportWidget;
TSharedPtr<IDetailsView> DetailsWidget;
TSharedPtr<SBorder> LayerSystemWidget;
TSharedPtr<SBorder> PhysicsSettingsWidget;
// Unregister the tab spawners
InTabManager->UnregisterTabSpawner(ViewportTabId);
InTabManager->UnregisterTabSpawner(DetailsTabId);
InTabManager->UnregisterTabSpawner(LayerSystemTabId);
InTabManager->UnregisterTabSpawner(PhysicsSettingsTabId);
}
// Spawn the viewport tab
TSharedRef<SDockTab> FDismembermentEditor::SpawnTab_Viewport(const FSpawnTabArgs& Args)
{
// Create the viewport widget
ViewportWidget = SNew(SBorder)
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
.Padding(FMargin(4.0f))
[
SNew(STextBlock)
.Text(FText::FromString("Viewport will be implemented here"))
];
static const FName ViewportTabId;
static const FName DetailsTabId;
static const FName LayerSystemTabId;
static const FName PhysicsSettingsTabId;
};
// Create the tab
return SNew(SDockTab)
.Label(FText::FromString("Viewport"))
[
ViewportWidget.ToSharedRef()
];
}
// Spawn the details tab
TSharedRef<SDockTab> FDismembermentEditor::SpawnTab_Details(const FSpawnTabArgs& Args)
{
// Create the details view
FPropertyEditorModule& PropertyEditorModule = FModuleManager::GetModuleChecked<FPropertyEditorModule>("PropertyEditor");
FDetailsViewArgs DetailsViewArgs;
DetailsViewArgs.bUpdatesFromSelection = true;
DetailsViewArgs.bLockable = false;
DetailsViewArgs.bAllowSearch = true;
DetailsViewArgs.NameAreaSettings = FDetailsViewArgs::HideNameArea;
DetailsViewArgs.bHideSelectionTip = true;
DetailsWidget = PropertyEditorModule.CreateDetailView(DetailsViewArgs);
DetailsWidget->SetObject(SkeletalMesh);
// Create the tab
return SNew(SDockTab)
.Label(FText::FromString("Details"))
[
DetailsWidget.ToSharedRef()
];
}
// Spawn the layer system tab
TSharedRef<SDockTab> FDismembermentEditor::SpawnTab_LayerSystem(const FSpawnTabArgs& Args)
{
// Create the layer system widget
LayerSystemWidget = SNew(SBorder)
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
.Padding(FMargin(4.0f))
[
SNew(STextBlock)
.Text(FText::FromString("Layer System will be implemented here"))
];
// Create the tab
return SNew(SDockTab)
.Label(FText::FromString("Layer System"))
[
LayerSystemWidget.ToSharedRef()
];
}
// Spawn the physics settings tab
TSharedRef<SDockTab> FDismembermentEditor::SpawnTab_PhysicsSettings(const FSpawnTabArgs& Args)
{
// Create the physics settings widget
PhysicsSettingsWidget = SNew(SBorder)
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
.Padding(FMargin(4.0f))
[
SNew(STextBlock)
.Text(FText::FromString("Physics Settings will be implemented here"))
];
// Create the tab
return SNew(SDockTab)
.Label(FText::FromString("Physics Settings"))
[
PhysicsSettingsWidget.ToSharedRef()
];
}
// Perform a boolean cut operation
void FDismembermentEditor::PerformBooleanCut()
{
// To be implemented
}
// Add a new layer
void FDismembermentEditor::AddNewLayer()
{
// To be implemented
}
// Save the edits
void FDismembermentEditor::SaveEdits()
{
// To be implemented
}
// Preview the effects
void FDismembermentEditor::PreviewEffects()
{
// To be implemented
}