Files
FLESH/Source/FLESHEditor/Private/FLESHEditor.cpp
2025-04-17 23:59:17 +08:00

547 lines
19 KiB
C++

#include "FLESHEditor.h"
#include "FLESHEditorCommands.h"
#include "FLESHEditorStyle.h"
#include "MatrixInputWidget.h"
#include "DismembermentGraph/DismembermentGraphEditor.h"
#include "Framework/Docking/TabManager.h"
#include "Widgets/Docking/SDockTab.h"
#include "Widgets/Layout/SBox.h"
#include "Widgets/Layout/SBorder.h"
#include "Widgets/Input/SButton.h"
#include "PropertyEditorModule.h"
#include "EditorStyleSet.h"
#include "LevelEditor.h"
#include "ToolMenus.h"
#define LOCTEXT_NAMESPACE "FLESHEditor"
const FName FFLESHEditor::ViewportTabId(TEXT("FLESHEditor_Viewport"));
const FName FFLESHEditor::DetailsTabId(TEXT("FLESHEditor_Details"));
const FName FFLESHEditor::AssetBrowserTabId(TEXT("FLESHEditor_AssetBrowser"));
const FName FFLESHEditor::MatrixEditorTabId(TEXT("FLESHEditor_MatrixEditor"));
const FName FFLESHEditor::GraphEditorTabId(TEXT("FLESHEditor_GraphEditor"));
const FName FFLESHEditor::ToolbarTabId(TEXT("FLESHEditor_Toolbar"));
FFLESHEditor::FFLESHEditor()
{
}
FFLESHEditor::~FFLESHEditor()
{
}
void FFLESHEditor::InitFLESHEditor(const EToolkitMode::Type Mode, const TSharedPtr<IToolkitHost>& InitToolkitHost)
{
// Create command list
CreateCommandList();
// Create tab layout
const TSharedRef<FTabManager::FLayout> StandaloneDefaultLayout = FTabManager::NewLayout("FLESHEditorLayout_v1.0")
->AddArea
(
FTabManager::NewPrimaryArea()->SetOrientation(Orient_Vertical)
->Split
(
FTabManager::NewStack()
->SetSizeCoefficient(0.1f)
->AddTab(ToolbarTabId, ETabState::OpenedTab)
)
->Split
(
FTabManager::NewSplitter()->SetOrientation(Orient_Horizontal)
->Split
(
FTabManager::NewSplitter()->SetOrientation(Orient_Vertical)
->SetSizeCoefficient(0.7f)
->Split
(
FTabManager::NewStack()
->SetSizeCoefficient(0.7f)
->AddTab(ViewportTabId, ETabState::OpenedTab)
)
->Split
(
FTabManager::NewStack()
->SetSizeCoefficient(0.3f)
->AddTab(MatrixEditorTabId, ETabState::OpenedTab)
)
)
->Split
(
FTabManager::NewSplitter()->SetOrientation(Orient_Vertical)
->SetSizeCoefficient(0.3f)
->Split
(
FTabManager::NewStack()
->SetSizeCoefficient(0.6f)
->AddTab(DetailsTabId, ETabState::OpenedTab)
)
->Split
(
FTabManager::NewStack()
->SetSizeCoefficient(0.4f)
->AddTab(AssetBrowserTabId, ETabState::OpenedTab)
)
)
)
);
// Initialize toolkit
const bool bCreateDefaultStandaloneMenu = true;
const bool bCreateDefaultToolbar = true;
FAssetEditorToolkit::InitAssetEditor(Mode, InitToolkitHost, FName("FLESHEditorApp"), StandaloneDefaultLayout, bCreateDefaultStandaloneMenu, bCreateDefaultToolbar);
}
void FFLESHEditor::RegisterTabSpawners(const TSharedRef<FTabManager>& InTabManager)
{
FAssetEditorToolkit::RegisterTabSpawners(InTabManager);
// Register tab spawners
InTabManager->RegisterTabSpawner(ViewportTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_Viewport))
.SetDisplayName(LOCTEXT("ViewportTab", "Viewport"))
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
.SetIcon(FSlateIcon(FEditorStyle::GetStyleSetName(), "LevelEditor.Tabs.Viewports"));
InTabManager->RegisterTabSpawner(DetailsTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_Details))
.SetDisplayName(LOCTEXT("DetailsTab", "Details"))
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
.SetIcon(FSlateIcon(FEditorStyle::GetStyleSetName(), "LevelEditor.Tabs.Details"));
InTabManager->RegisterTabSpawner(AssetBrowserTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_AssetBrowser))
.SetDisplayName(LOCTEXT("AssetBrowserTab", "Asset Browser"))
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
.SetIcon(FSlateIcon(FEditorStyle::GetStyleSetName(), "ContentBrowser.TabIcon"));
InTabManager->RegisterTabSpawner(MatrixEditorTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_MatrixEditor))
.SetDisplayName(LOCTEXT("MatrixEditorTab", "Matrix Editor"))
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
.SetIcon(FSlateIcon(FEditorStyle::GetStyleSetName(), "PropertyEditor.Grid.TabIcon"));
InTabManager->RegisterTabSpawner(GraphEditorTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_GraphEditor))
.SetDisplayName(LOCTEXT("GraphEditorTab", "Graph Editor"))
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
.SetIcon(FSlateIcon(FEditorStyle::GetStyleSetName(), "GraphEditor.EventGraph_16x"));
InTabManager->RegisterTabSpawner(ToolbarTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_Toolbar))
.SetDisplayName(LOCTEXT("ToolbarTab", "Toolbar"))
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
.SetIcon(FSlateIcon(FEditorStyle::GetStyleSetName(), "LevelEditor.Tabs.Toolbar"));
}
void FFLESHEditor::UnregisterTabSpawners(const TSharedRef<FTabManager>& InTabManager)
{
FAssetEditorToolkit::UnregisterTabSpawners(InTabManager);
// Unregister tab spawners
InTabManager->UnregisterTabSpawner(ViewportTabId);
InTabManager->UnregisterTabSpawner(DetailsTabId);
InTabManager->UnregisterTabSpawner(AssetBrowserTabId);
InTabManager->UnregisterTabSpawner(MatrixEditorTabId);
InTabManager->UnregisterTabSpawner(GraphEditorTabId);
InTabManager->UnregisterTabSpawner(ToolbarTabId);
}
FName FFLESHEditor::GetToolkitFName() const
{
return FName("FLESHEditor");
}
FText FFLESHEditor::GetBaseToolkitName() const
{
return LOCTEXT("FLESHEditorAppLabel", "FLESH Editor");
}
FString FFLESHEditor::GetWorldCentricTabPrefix() const
{
return TEXT("FLESH ");
}
FLinearColor FFLESHEditor::GetWorldCentricTabColorScale() const
{
return FLinearColor(0.7f, 0.0f, 0.0f, 0.5f);
}
void FFLESHEditor::OpenEditor()
{
// Create new editor instance
TSharedRef<FFLESHEditor> NewEditor = MakeShareable(new FFLESHEditor());
NewEditor->InitFLESHEditor(EToolkitMode::Standalone, nullptr);
}
TSharedRef<SDockTab> FFLESHEditor::SpawnTab_Viewport(const FSpawnTabArgs& Args)
{
return SNew(SDockTab)
.Label(LOCTEXT("ViewportTitle", "Viewport"))
[
CreateViewportWidget()
];
}
TSharedRef<SDockTab> FFLESHEditor::SpawnTab_Details(const FSpawnTabArgs& Args)
{
return SNew(SDockTab)
.Label(LOCTEXT("DetailsTitle", "Details"))
[
CreateDetailsWidget()
];
}
TSharedRef<SDockTab> FFLESHEditor::SpawnTab_AssetBrowser(const FSpawnTabArgs& Args)
{
return SNew(SDockTab)
.Label(LOCTEXT("AssetBrowserTitle", "Asset Browser"))
[
CreateAssetBrowserWidget()
];
}
TSharedRef<SDockTab> FFLESHEditor::SpawnTab_MatrixEditor(const FSpawnTabArgs& Args)
{
return SNew(SDockTab)
.Label(LOCTEXT("MatrixEditorTitle", "Matrix Editor"))
[
CreateMatrixEditorWidget()
];
}
TSharedRef<SDockTab> FFLESHEditor::SpawnTab_GraphEditor(const FSpawnTabArgs& Args)
{
return SNew(SDockTab)
.Label(LOCTEXT("GraphEditorTitle", "Graph Editor"))
[
CreateGraphEditorWidget()
];
}
TSharedRef<SDockTab> FFLESHEditor::SpawnTab_Toolbar(const FSpawnTabArgs& Args)
{
return SNew(SDockTab)
.Label(LOCTEXT("ToolbarTitle", "Toolbar"))
[
CreateToolbarWidget()
];
}
TSharedRef<SWidget> FFLESHEditor::CreateViewportWidget()
{
// Create viewport widget
return SNew(SBorder)
.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
.Padding(4.0f)
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(LOCTEXT("ViewportHeader", "FLESH Viewport"))
.Font(FEditorStyle::GetFontStyle("HeadingFont"))
]
+ SVerticalBox::Slot()
.FillHeight(1.0f)
[
SNew(SBorder)
.BorderImage(FEditorStyle::GetBrush("ToolPanel.DarkGroupBorder"))
.Padding(4.0f)
[
SNew(STextBlock)
.Text(LOCTEXT("ViewportPlaceholder", "Character model and dismemberment effects will be displayed here"))
]
]
];
}
TSharedRef<SWidget> FFLESHEditor::CreateDetailsWidget()
{
// Create details panel
FPropertyEditorModule& PropertyEditorModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
FDetailsViewArgs DetailsViewArgs;
DetailsViewArgs.bUpdatesFromSelection = true;
DetailsViewArgs.bLockable = false;
DetailsViewArgs.bAllowSearch = true;
DetailsViewArgs.NameAreaSettings = FDetailsViewArgs::HideNameArea;
DetailsViewArgs.bHideSelectionTip = true;
DetailsViewArgs.NotifyHook = nullptr;
DetailsViewArgs.bSearchInitialKeyFocus = false;
DetailsViewArgs.ViewIdentifier = NAME_None;
DetailsViewArgs.DefaultsOnlyVisibility = EEditDefaultsOnlyNodeVisibility::Automatic;
DetailsViewArgs.bShowOptions = true;
DetailsViewArgs.bAllowMultipleTopLevelObjects = true;
DetailsWidget = PropertyEditorModule.CreateDetailView(DetailsViewArgs);
return SNew(SBorder)
.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
.Padding(4.0f)
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(LOCTEXT("DetailsHeader", "Property Editor"))
.Font(FEditorStyle::GetFontStyle("HeadingFont"))
]
+ SVerticalBox::Slot()
.FillHeight(1.0f)
[
DetailsWidget.ToSharedRef()
]
];
}
TSharedRef<SWidget> FFLESHEditor::CreateAssetBrowserWidget()
{
// Create asset browser
return SNew(SBorder)
.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
.Padding(4.0f)
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(LOCTEXT("AssetBrowserHeader", "Asset Browser"))
.Font(FEditorStyle::GetFontStyle("HeadingFont"))
]
+ SVerticalBox::Slot()
.FillHeight(1.0f)
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(2.0f)
[
SNew(SButton)
.Text(LOCTEXT("ImportCharacterModel", "Import Character Model"))
.OnClicked_Lambda([this]() { OnImportCharacterModel(); return FReply::Handled(); })
.ButtonStyle(FFLESHEditorStyle::Get(), "FLESHEditor.RoundedButton")
]
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(2.0f)
[
SNew(SButton)
.Text(LOCTEXT("ImportOrganModel", "Import Organ Model"))
.OnClicked_Lambda([this]() { OnImportOrganModel(); return FReply::Handled(); })
.ButtonStyle(FFLESHEditorStyle::Get(), "FLESHEditor.RoundedButton")
]
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(2.0f)
[
SNew(SButton)
.Text(LOCTEXT("ImportSkeletonModel", "Import Skeleton Model"))
.OnClicked_Lambda([this]() { OnImportSkeletonModel(); return FReply::Handled(); })
.ButtonStyle(FFLESHEditorStyle::Get(), "FLESHEditor.RoundedButton")
]
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(2.0f)
[
SNew(SButton)
.Text(LOCTEXT("ImportPhysicsAsset", "Import Physics Asset"))
.OnClicked_Lambda([this]() { OnImportPhysicsAsset(); return FReply::Handled(); })
.ButtonStyle(FFLESHEditorStyle::Get(), "FLESHEditor.RoundedButton")
]
]
];
}
TSharedRef<SWidget> FFLESHEditor::CreateMatrixEditorWidget()
{
// Create matrix editor
MatrixEditorWidget = SNew(SMatrixInputWidget)
.Matrix(FMatrix::Identity)
.OnMatrixChanged_Lambda([this](const FMatrix& NewMatrix) {
// Handle matrix change
});
return SNew(SBorder)
.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
.Padding(4.0f)
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(LOCTEXT("MatrixEditorHeader", "Matrix Editor"))
.Font(FEditorStyle::GetFontStyle("HeadingFont"))
]
+ SVerticalBox::Slot()
.FillHeight(1.0f)
[
MatrixEditorWidget.ToSharedRef()
]
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(2.0f)
[
SNew(SButton)
.Text(LOCTEXT("TestMatrix", "Test Matrix"))
.OnClicked_Lambda([this]() { OnTestMatrix(); return FReply::Handled(); })
.ButtonStyle(FFLESHEditorStyle::Get(), "FLESHEditor.RoundedButton")
]
];
}
TSharedRef<SWidget> FFLESHEditor::CreateGraphEditorWidget()
{
// Create graph editor
return SNew(SBorder)
.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
.Padding(4.0f)
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(LOCTEXT("GraphEditorHeader", "Graph Editor"))
.Font(FEditorStyle::GetFontStyle("HeadingFont"))
]
+ SVerticalBox::Slot()
.FillHeight(1.0f)
[
SNew(SBorder)
.BorderImage(FEditorStyle::GetBrush("ToolPanel.DarkGroupBorder"))
.Padding(4.0f)
[
SNew(STextBlock)
.Text(LOCTEXT("GraphEditorPlaceholder", "Dismemberment system logic graph will be displayed here"))
]
]
];
}
TSharedRef<SWidget> FFLESHEditor::CreateToolbarWidget()
{
// Create toolbar
return SNew(SBorder)
.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
.Padding(4.0f)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
.Padding(2.0f)
[
SNew(SButton)
.Text(LOCTEXT("DismembermentGraphEditor", "Dismemberment Graph Editor"))
.OnClicked_Lambda([this]() { OnOpenDismembermentGraphEditor(); return FReply::Handled(); })
.ButtonStyle(FFLESHEditorStyle::Get(), "FLESHEditor.RoundedButton")
]
+ SHorizontalBox::Slot()
.AutoWidth()
.Padding(2.0f)
[
SNew(SButton)
.Text(LOCTEXT("AnatomicalLayerEditor", "Anatomical Layer Editor"))
.OnClicked_Lambda([this]() { OnOpenAnatomicalLayerEditor(); return FReply::Handled(); })
.ButtonStyle(FFLESHEditorStyle::Get(), "FLESHEditor.RoundedButton")
]
+ SHorizontalBox::Slot()
.AutoWidth()
.Padding(2.0f)
[
SNew(SButton)
.Text(LOCTEXT("BooleanCutTool", "Boolean Cut Tool"))
.OnClicked_Lambda([this]() { OnOpenBooleanCutTool(); return FReply::Handled(); })
.ButtonStyle(FFLESHEditorStyle::Get(), "FLESHEditor.RoundedButton")
]
+ SHorizontalBox::Slot()
.AutoWidth()
.Padding(2.0f)
[
SNew(SButton)
.Text(LOCTEXT("BloodSystemEditor", "Blood System Editor"))
.OnClicked_Lambda([this]() { OnOpenBloodSystemEditor(); return FReply::Handled(); })
.ButtonStyle(FFLESHEditorStyle::Get(), "FLESHEditor.RoundedButton")
]
];
}
void FFLESHEditor::CreateCommandList()
{
// Create command list
CommandList = MakeShareable(new FUICommandList);
// Bind commands
CommandList->MapAction(
FFLESHEditorCommands::Get().OpenDismembermentGraphEditor,
FExecuteAction::CreateSP(this, &FFLESHEditor::OnOpenDismembermentGraphEditor),
FCanExecuteAction());
CommandList->MapAction(
FFLESHEditorCommands::Get().OpenAnatomicalLayerEditor,
FExecuteAction::CreateSP(this, &FFLESHEditor::OnOpenAnatomicalLayerEditor),
FCanExecuteAction());
CommandList->MapAction(
FFLESHEditorCommands::Get().OpenBooleanCutTool,
FExecuteAction::CreateSP(this, &FFLESHEditor::OnOpenBooleanCutTool),
FCanExecuteAction());
CommandList->MapAction(
FFLESHEditorCommands::Get().OpenBloodSystemEditor,
FExecuteAction::CreateSP(this, &FFLESHEditor::OnOpenBloodSystemEditor),
FCanExecuteAction());
}
void FFLESHEditor::OnOpenDismembermentGraphEditor()
{
// Open dismemberment graph editor
FGlobalTabmanager::Get()->TryInvokeTab(GraphEditorTabId);
}
void FFLESHEditor::OnOpenAnatomicalLayerEditor()
{
// Open anatomical layer editor
FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("AnatomicalLayerEditorNotImplemented", "Anatomical Layer Editor is not implemented yet"));
}
void FFLESHEditor::OnOpenBooleanCutTool()
{
// Open boolean cut tool
FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("BooleanCutToolNotImplemented", "Boolean Cut Tool is not implemented yet"));
}
void FFLESHEditor::OnOpenBloodSystemEditor()
{
// Open blood system editor
FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("BloodSystemEditorNotImplemented", "Blood System Editor is not implemented yet"));
}
void FFLESHEditor::OnImportCharacterModel()
{
// Import character model
FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("ImportCharacterModelNotImplemented", "Import Character Model feature is not implemented yet"));
}
void FFLESHEditor::OnImportOrganModel()
{
// Import organ model
FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("ImportOrganModelNotImplemented", "Import Organ Model feature is not implemented yet"));
}
void FFLESHEditor::OnImportSkeletonModel()
{
// Import skeleton model
FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("ImportSkeletonModelNotImplemented", "Import Skeleton Model feature is not implemented yet"));
}
void FFLESHEditor::OnImportPhysicsAsset()
{
// Import physics asset
FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("ImportPhysicsAssetNotImplemented", "Import Physics Asset feature is not implemented yet"));
}
void FFLESHEditor::OnTestMatrix()
{
// Test matrix
FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("TestMatrixNotImplemented", "Test Matrix feature is not implemented yet"));
}
#undef LOCTEXT_NAMESPACE