825 lines
28 KiB
C++
825 lines
28 KiB
C++
#include "FLESHEditor.h"
|
|
#include "FLESHEditorCommands.h"
|
|
#include "FLESHEditorStyle.h"
|
|
#include "MatrixInputWidget.h"
|
|
#include "DismembermentGraph/DismembermentGraphEditor.h"
|
|
#include "DismembermentEditor.h"
|
|
#include "AnatomicalStructureBrush.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 "Framework/Commands/UICommandList.h"
|
|
#include "Framework/MultiBox/MultiBoxBuilder.h"
|
|
#include "ToolMenus.h"
|
|
#include "Misc/MessageDialog.h"
|
|
|
|
// Define log category
|
|
DEFINE_LOG_CATEGORY(LogFLESHEditor);
|
|
|
|
// Define localization namespace
|
|
#define LOCTEXT_NAMESPACE "FLESHEditor"
|
|
|
|
// Define static tab IDs
|
|
const FName FFLESHEditor::ViewportTabId(TEXT("Viewport"));
|
|
const FName FFLESHEditor::DetailsTabId(TEXT("Details"));
|
|
const FName FFLESHEditor::AssetBrowserTabId(TEXT("AssetBrowser"));
|
|
const FName FFLESHEditor::MatrixEditorTabId(TEXT("MatrixEditor"));
|
|
const FName FFLESHEditor::GraphEditorTabId(TEXT("GraphEditor"));
|
|
const FName FFLESHEditor::ToolbarTabId(TEXT("Toolbar"));
|
|
const FName FFLESHEditor::LayerSystemTabId(TEXT("LayerSystem"));
|
|
const FName FFLESHEditor::PhysicsSettingsTabId(TEXT("PhysicsSettings"));
|
|
const FName FFLESHEditor::DismembermentGraphTabId(TEXT("DismembermentGraph"));
|
|
|
|
// Constructor
|
|
FFLESHEditor::FFLESHEditor()
|
|
: CommandList(MakeShareable(new FUICommandList))
|
|
, EditingObject(nullptr)
|
|
, bIsInitialized(false)
|
|
{
|
|
UE_LOG(LogFLESHEditor, Log, TEXT("FLESH Editor constructor called"));
|
|
}
|
|
|
|
// Destructor
|
|
FFLESHEditor::~FFLESHEditor()
|
|
{
|
|
// Unregister from any events
|
|
if (GEditor)
|
|
{
|
|
GEditor->UnregisterForUndo(this);
|
|
}
|
|
|
|
UE_LOG(LogFLESHEditor, Log, TEXT("FLESH Editor destructor called"));
|
|
}
|
|
|
|
// Initialize the editor
|
|
void FFLESHEditor::InitFLESHEditor(const EToolkitMode::Type Mode, const TSharedPtr<IToolkitHost>& InitToolkitHost, UObject* InObject)
|
|
{
|
|
UE_LOG(LogFLESHEditor, Log, TEXT("Initializing FLESH Editor"));
|
|
|
|
try
|
|
{
|
|
// Set the object being edited
|
|
EditingObject = InObject;
|
|
|
|
if (!EditingObject)
|
|
{
|
|
HandleEditorError(LOCTEXT("InitNoObject", "Failed to initialize FLESH Editor: No object specified"));
|
|
return;
|
|
}
|
|
|
|
// Register commands
|
|
FFLESHEditorCommands::Register();
|
|
|
|
// Register for undo/redo
|
|
GEditor->RegisterForUndo(this);
|
|
|
|
// Create the layout
|
|
const TSharedRef<FTabManager::FLayout> StandaloneDefaultLayout = FTabManager::NewLayout("Standalone_FLESHEditor_Layout_v1")
|
|
->AddArea
|
|
(
|
|
FTabManager::NewPrimaryArea()->SetOrientation(Orient_Vertical)
|
|
->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)
|
|
)
|
|
)
|
|
)
|
|
);
|
|
|
|
// Initialize the asset editor
|
|
FAssetEditorToolkit::InitAssetEditor(
|
|
Mode,
|
|
InitToolkitHost,
|
|
FName("FLESHEditorApp"),
|
|
StandaloneDefaultLayout,
|
|
/*bCreateDefaultStandaloneMenu=*/ true,
|
|
/*bCreateDefaultToolbar=*/ true,
|
|
EditingObject
|
|
);
|
|
|
|
// Create the command list
|
|
CreateCommandList();
|
|
|
|
// Register tab spawners
|
|
RegisterTabSpawners(GetTabManager().ToSharedRef());
|
|
|
|
// Extend toolbar
|
|
ExtendToolbar();
|
|
|
|
// Set initialization flag
|
|
bIsInitialized = true;
|
|
|
|
UE_LOG(LogFLESHEditor, Log, TEXT("FLESH Editor initialized successfully"));
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
HandleEditorError(FText::Format(LOCTEXT("InitException", "Exception during FLESH Editor initialization: {0}"), FText::FromString(UTF8_TO_TCHAR(e.what()))));
|
|
}
|
|
catch (...)
|
|
{
|
|
HandleEditorError(LOCTEXT("InitUnknownError", "Unknown exception during FLESH Editor initialization"));
|
|
}
|
|
}
|
|
|
|
// FEditorUndoClient interface
|
|
void FFLESHEditor::PostUndo(bool bSuccess)
|
|
{
|
|
if (bSuccess)
|
|
{
|
|
// Refresh the views
|
|
if (DetailsWidget.IsValid())
|
|
{
|
|
DetailsWidget->ForceRefresh();
|
|
}
|
|
}
|
|
}
|
|
|
|
void FFLESHEditor::PostRedo(bool bSuccess)
|
|
{
|
|
if (bSuccess)
|
|
{
|
|
// Refresh the views
|
|
if (DetailsWidget.IsValid())
|
|
{
|
|
DetailsWidget->ForceRefresh();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Tab spawners
|
|
TSharedRef<SDockTab> FFLESHEditor::SpawnTab_Viewport(const FSpawnTabArgs& Args)
|
|
{
|
|
UE_LOG(LogFLESHEditor, Log, TEXT("Spawning Viewport tab"));
|
|
|
|
try
|
|
{
|
|
// Create the viewport widget
|
|
TSharedRef<SWidget> ViewportContent = SNew(SBorder)
|
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
|
.Padding(FMargin(4.0f))
|
|
[
|
|
SNew(SVerticalBox)
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.Padding(0, 0, 0, 4)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(LOCTEXT("ViewportTitle", "FLESH Viewport"))
|
|
.Font(FCoreStyle::GetDefaultFontStyle("Bold", 12))
|
|
]
|
|
+ SVerticalBox::Slot()
|
|
.FillHeight(1.0f)
|
|
[
|
|
SNew(SBorder)
|
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.DarkGroupBorder"))
|
|
.Padding(FMargin(4.0f))
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(LOCTEXT("ViewportImplementation", "Viewport implementation will be added here"))
|
|
.AutoWrapText(true)
|
|
]
|
|
]
|
|
];
|
|
|
|
// Create the tab
|
|
TSharedRef<SDockTab> NewTab = SNew(SDockTab)
|
|
.Label(LOCTEXT("ViewportTab", "Viewport"))
|
|
[
|
|
ViewportContent
|
|
];
|
|
|
|
return NewTab;
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
UE_LOG(LogFLESHEditor, Error, TEXT("Exception spawning Viewport tab: %s"), UTF8_TO_TCHAR(e.what()));
|
|
|
|
// Create an error widget
|
|
TSharedRef<SWidget> ErrorWidget = SNew(SBorder)
|
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
|
.Padding(FMargin(4.0f))
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(FText::Format(LOCTEXT("ViewportTabError", "Error spawning Viewport tab: {0}"), FText::FromString(UTF8_TO_TCHAR(e.what()))))
|
|
];
|
|
|
|
// Create the tab with the error widget
|
|
TSharedRef<SDockTab> NewTab = SNew(SDockTab)
|
|
.Label(LOCTEXT("ViewportTab", "Viewport"))
|
|
[
|
|
ErrorWidget
|
|
];
|
|
|
|
return NewTab;
|
|
}
|
|
catch (...)
|
|
{
|
|
UE_LOG(LogFLESHEditor, Error, TEXT("Unknown exception spawning Viewport tab"));
|
|
|
|
// Create an error widget
|
|
TSharedRef<SWidget> ErrorWidget = SNew(SBorder)
|
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
|
.Padding(FMargin(4.0f))
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(LOCTEXT("ViewportTabUnknownError", "Unknown error spawning Viewport tab"))
|
|
];
|
|
|
|
// Create the tab with the error widget
|
|
TSharedRef<SDockTab> NewTab = SNew(SDockTab)
|
|
.Label(LOCTEXT("ViewportTab", "Viewport"))
|
|
[
|
|
ErrorWidget
|
|
];
|
|
|
|
return NewTab;
|
|
}
|
|
}
|
|
|
|
TSharedRef<SDockTab> FFLESHEditor::SpawnTab_Details(const FSpawnTabArgs& Args)
|
|
{
|
|
UE_LOG(LogFLESHEditor, Log, TEXT("Spawning Details tab"));
|
|
|
|
try
|
|
{
|
|
// Create the details widget
|
|
TSharedRef<SWidget> DetailsContent = SNew(SBorder)
|
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
|
.Padding(FMargin(4.0f))
|
|
[
|
|
SNew(SVerticalBox)
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.Padding(0, 0, 0, 4)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(LOCTEXT("DetailsTitle", "Details"))
|
|
.Font(FCoreStyle::GetDefaultFontStyle("Bold", 12))
|
|
]
|
|
+ SVerticalBox::Slot()
|
|
.FillHeight(1.0f)
|
|
[
|
|
SNew(SBorder)
|
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.DarkGroupBorder"))
|
|
.Padding(FMargin(4.0f))
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(LOCTEXT("DetailsImplementation", "Details implementation will be added here"))
|
|
.AutoWrapText(true)
|
|
]
|
|
]
|
|
];
|
|
|
|
// Create the tab
|
|
TSharedRef<SDockTab> NewTab = SNew(SDockTab)
|
|
.Label(LOCTEXT("DetailsTab", "Details"))
|
|
[
|
|
DetailsContent
|
|
];
|
|
|
|
return NewTab;
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
UE_LOG(LogFLESHEditor, Error, TEXT("Exception spawning Details tab: %s"), UTF8_TO_TCHAR(e.what()));
|
|
|
|
// Create an error widget
|
|
TSharedRef<SWidget> ErrorWidget = SNew(SBorder)
|
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
|
.Padding(FMargin(4.0f))
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(FText::Format(LOCTEXT("DetailsTabError", "Error spawning Details tab: {0}"), FText::FromString(UTF8_TO_TCHAR(e.what()))))
|
|
];
|
|
|
|
// Create the tab with the error widget
|
|
TSharedRef<SDockTab> NewTab = SNew(SDockTab)
|
|
.Label(LOCTEXT("DetailsTab", "Details"))
|
|
[
|
|
ErrorWidget
|
|
];
|
|
|
|
return NewTab;
|
|
}
|
|
catch (...)
|
|
{
|
|
UE_LOG(LogFLESHEditor, Error, TEXT("Unknown exception spawning Details tab"));
|
|
|
|
// Create an error widget
|
|
TSharedRef<SWidget> ErrorWidget = SNew(SBorder)
|
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
|
.Padding(FMargin(4.0f))
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(LOCTEXT("DetailsTabUnknownError", "Unknown error spawning Details tab"))
|
|
];
|
|
|
|
// Create the tab with the error widget
|
|
TSharedRef<SDockTab> NewTab = SNew(SDockTab)
|
|
.Label(LOCTEXT("DetailsTab", "Details"))
|
|
[
|
|
ErrorWidget
|
|
];
|
|
|
|
return NewTab;
|
|
}
|
|
}
|
|
|
|
// DismembermentEditor related tab spawners
|
|
TSharedRef<SDockTab> FFLESHEditor::SpawnTab_LayerSystem(const FSpawnTabArgs& Args)
|
|
{
|
|
UE_LOG(LogFLESHEditor, Log, TEXT("Spawning Layer System tab"));
|
|
|
|
try
|
|
{
|
|
// Create the layer system widget
|
|
TSharedRef<SWidget> WidgetContent = CreateLayerSystemWidget();
|
|
|
|
// Create the tab
|
|
TSharedRef<SDockTab> NewTab = SNew(SDockTab)
|
|
.Label(LOCTEXT("LayerSystemTab", "Layer System"))
|
|
[
|
|
WidgetContent
|
|
];
|
|
|
|
return NewTab;
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
UE_LOG(LogFLESHEditor, Error, TEXT("Exception spawning Layer System tab: %s"), UTF8_TO_TCHAR(e.what()));
|
|
|
|
// Create an error widget
|
|
TSharedRef<SWidget> ErrorWidget = SNew(SBorder)
|
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
|
.Padding(FMargin(4.0f))
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(FText::Format(LOCTEXT("LayerSystemTabError", "Error spawning Layer System tab: {0}"), FText::FromString(UTF8_TO_TCHAR(e.what()))))
|
|
];
|
|
|
|
// Create the tab with the error widget
|
|
TSharedRef<SDockTab> NewTab = SNew(SDockTab)
|
|
.Label(LOCTEXT("LayerSystemTab", "Layer System"))
|
|
[
|
|
ErrorWidget
|
|
];
|
|
|
|
return NewTab;
|
|
}
|
|
catch (...)
|
|
{
|
|
UE_LOG(LogFLESHEditor, Error, TEXT("Unknown exception spawning Layer System tab"));
|
|
|
|
// Create an error widget
|
|
TSharedRef<SWidget> ErrorWidget = SNew(SBorder)
|
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
|
.Padding(FMargin(4.0f))
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(LOCTEXT("LayerSystemTabUnknownError", "Unknown error spawning Layer System tab"))
|
|
];
|
|
|
|
// Create the tab with the error widget
|
|
TSharedRef<SDockTab> NewTab = SNew(SDockTab)
|
|
.Label(LOCTEXT("LayerSystemTab", "Layer System"))
|
|
[
|
|
ErrorWidget
|
|
];
|
|
|
|
return NewTab;
|
|
}
|
|
}
|
|
|
|
TSharedRef<SDockTab> FFLESHEditor::SpawnTab_PhysicsSettings(const FSpawnTabArgs& Args)
|
|
{
|
|
UE_LOG(LogFLESHEditor, Log, TEXT("Spawning Physics Settings tab"));
|
|
|
|
try
|
|
{
|
|
// Create the physics settings widget
|
|
TSharedRef<SWidget> WidgetContent = CreatePhysicsSettingsWidget();
|
|
|
|
// Create the tab
|
|
TSharedRef<SDockTab> NewTab = SNew(SDockTab)
|
|
.Label(LOCTEXT("PhysicsSettingsTab", "Physics Settings"))
|
|
[
|
|
WidgetContent
|
|
];
|
|
|
|
return NewTab;
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
UE_LOG(LogFLESHEditor, Error, TEXT("Exception spawning Physics Settings tab: %s"), UTF8_TO_TCHAR(e.what()));
|
|
|
|
// Create an error widget
|
|
TSharedRef<SWidget> ErrorWidget = SNew(SBorder)
|
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
|
.Padding(FMargin(4.0f))
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(FText::Format(LOCTEXT("PhysicsSettingsTabError", "Error spawning Physics Settings tab: {0}"), FText::FromString(UTF8_TO_TCHAR(e.what()))))
|
|
];
|
|
|
|
// Create the tab with the error widget
|
|
TSharedRef<SDockTab> NewTab = SNew(SDockTab)
|
|
.Label(LOCTEXT("PhysicsSettingsTab", "Physics Settings"))
|
|
[
|
|
ErrorWidget
|
|
];
|
|
|
|
return NewTab;
|
|
}
|
|
catch (...)
|
|
{
|
|
UE_LOG(LogFLESHEditor, Error, TEXT("Unknown exception spawning Physics Settings tab"));
|
|
|
|
// Create an error widget
|
|
TSharedRef<SWidget> ErrorWidget = SNew(SBorder)
|
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
|
.Padding(FMargin(4.0f))
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(LOCTEXT("PhysicsSettingsTabUnknownError", "Unknown error spawning Physics Settings tab"))
|
|
];
|
|
|
|
// Create the tab with the error widget
|
|
TSharedRef<SDockTab> NewTab = SNew(SDockTab)
|
|
.Label(LOCTEXT("PhysicsSettingsTab", "Physics Settings"))
|
|
[
|
|
ErrorWidget
|
|
];
|
|
|
|
return NewTab;
|
|
}
|
|
}
|
|
|
|
// Create DismembermentEditor related widgets
|
|
TSharedRef<SBorder> FFLESHEditor::CreateLayerSystemWidget()
|
|
{
|
|
UE_LOG(LogFLESHEditor, Log, TEXT("Creating Layer System widget"));
|
|
|
|
try
|
|
{
|
|
// Create a placeholder widget for now
|
|
TSharedRef<SBorder> Widget = SNew(SBorder)
|
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
|
.Padding(FMargin(4.0f))
|
|
[
|
|
SNew(SVerticalBox)
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.Padding(0, 0, 0, 4)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(LOCTEXT("LayerSystemTitle", "Anatomical Layer System"))
|
|
.Font(FCoreStyle::GetDefaultFontStyle("Bold", 12))
|
|
]
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.Padding(0, 0, 0, 4)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(LOCTEXT("LayerSystemDescription", "Configure anatomical layers for the mesh"))
|
|
.AutoWrapText(true)
|
|
]
|
|
+ SVerticalBox::Slot()
|
|
.FillHeight(1.0f)
|
|
[
|
|
SNew(SBorder)
|
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.DarkGroupBorder"))
|
|
.Padding(FMargin(4.0f))
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(LOCTEXT("LayerSystemImplementation", "Layer System implementation will be added here"))
|
|
.AutoWrapText(true)
|
|
]
|
|
]
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.Padding(0, 4, 0, 0)
|
|
[
|
|
SNew(SButton)
|
|
.Text(LOCTEXT("AddLayerButton", "Add Layer"))
|
|
.ToolTipText(LOCTEXT("AddLayerTooltip", "Add a new anatomical layer"))
|
|
.OnClicked_Lambda([]() { return FReply::Handled(); })
|
|
]
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.Padding(0, 4, 0, 0)
|
|
[
|
|
SNew(SButton)
|
|
.Text(LOCTEXT("RemoveLayerButton", "Remove Layer"))
|
|
.ToolTipText(LOCTEXT("RemoveLayerTooltip", "Remove the selected anatomical layer"))
|
|
.OnClicked_Lambda([]() { return FReply::Handled(); })
|
|
]
|
|
];
|
|
|
|
// Store the widget in the class member
|
|
LayerSystemWidget = Widget;
|
|
|
|
return Widget;
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
UE_LOG(LogFLESHEditor, Error, TEXT("Exception creating Layer System widget: %s"), UTF8_TO_TCHAR(e.what()));
|
|
|
|
// Create an error widget
|
|
TSharedRef<SBorder> ErrorWidget = SNew(SBorder)
|
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
|
.Padding(FMargin(4.0f))
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(FText::Format(LOCTEXT("LayerSystemWidgetError", "Error creating Layer System widget: {0}"), FText::FromString(UTF8_TO_TCHAR(e.what()))))
|
|
.AutoWrapText(true)
|
|
];
|
|
|
|
return ErrorWidget;
|
|
}
|
|
catch (...)
|
|
{
|
|
UE_LOG(LogFLESHEditor, Error, TEXT("Unknown exception creating Layer System widget"));
|
|
|
|
// Create an error widget
|
|
TSharedRef<SBorder> ErrorWidget = SNew(SBorder)
|
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
|
.Padding(FMargin(4.0f))
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(LOCTEXT("LayerSystemWidgetUnknownError", "Unknown error creating Layer System widget"))
|
|
.AutoWrapText(true)
|
|
];
|
|
|
|
return ErrorWidget;
|
|
}
|
|
}
|
|
|
|
TSharedRef<SBorder> FFLESHEditor::CreatePhysicsSettingsWidget()
|
|
{
|
|
UE_LOG(LogFLESHEditor, Log, TEXT("Creating Physics Settings widget"));
|
|
|
|
try
|
|
{
|
|
// Create a placeholder widget for now
|
|
TSharedRef<SBorder> Widget = SNew(SBorder)
|
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
|
.Padding(FMargin(4.0f))
|
|
[
|
|
SNew(SVerticalBox)
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.Padding(0, 0, 0, 4)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(LOCTEXT("PhysicsSettingsTitle", "Physics Settings"))
|
|
.Font(FCoreStyle::GetDefaultFontStyle("Bold", 12))
|
|
]
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.Padding(0, 0, 0, 4)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(LOCTEXT("PhysicsSettingsDescription", "Configure physics properties for dismemberment"))
|
|
.AutoWrapText(true)
|
|
]
|
|
+ SVerticalBox::Slot()
|
|
.FillHeight(1.0f)
|
|
[
|
|
SNew(SBorder)
|
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.DarkGroupBorder"))
|
|
.Padding(FMargin(4.0f))
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(LOCTEXT("PhysicsSettingsImplementation", "Physics Settings implementation will be added here"))
|
|
.AutoWrapText(true)
|
|
]
|
|
]
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.Padding(0, 4, 0, 0)
|
|
[
|
|
SNew(SButton)
|
|
.Text(LOCTEXT("ApplyPhysicsButton", "Apply Physics"))
|
|
.ToolTipText(LOCTEXT("ApplyPhysicsTooltip", "Apply physics settings to the mesh"))
|
|
.OnClicked_Lambda([]() { return FReply::Handled(); })
|
|
]
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.Padding(0, 4, 0, 0)
|
|
[
|
|
SNew(SButton)
|
|
.Text(LOCTEXT("ResetPhysicsButton", "Reset Physics"))
|
|
.ToolTipText(LOCTEXT("ResetPhysicsTooltip", "Reset physics settings to default"))
|
|
.OnClicked_Lambda([]() { return FReply::Handled(); })
|
|
]
|
|
];
|
|
|
|
// Store the widget in the class member
|
|
PhysicsSettingsWidget = Widget;
|
|
|
|
return Widget;
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
UE_LOG(LogFLESHEditor, Error, TEXT("Exception creating Physics Settings widget: %s"), UTF8_TO_TCHAR(e.what()));
|
|
|
|
// Create an error widget
|
|
TSharedRef<SBorder> ErrorWidget = SNew(SBorder)
|
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
|
.Padding(FMargin(4.0f))
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(FText::Format(LOCTEXT("PhysicsSettingsWidgetError", "Error creating Physics Settings widget: {0}"), FText::FromString(UTF8_TO_TCHAR(e.what()))))
|
|
.AutoWrapText(true)
|
|
];
|
|
|
|
return ErrorWidget;
|
|
}
|
|
catch (...)
|
|
{
|
|
UE_LOG(LogFLESHEditor, Error, TEXT("Unknown exception creating Physics Settings widget"));
|
|
|
|
// Create an error widget
|
|
TSharedRef<SBorder> ErrorWidget = SNew(SBorder)
|
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
|
.Padding(FMargin(4.0f))
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(LOCTEXT("PhysicsSettingsWidgetUnknownError", "Unknown error creating Physics Settings widget"))
|
|
.AutoWrapText(true)
|
|
];
|
|
|
|
return ErrorWidget;
|
|
}
|
|
}
|
|
|
|
// Create command list
|
|
void FFLESHEditor::CreateCommandList()
|
|
{
|
|
UE_LOG(LogFLESHEditor, Log, TEXT("Creating command list"));
|
|
|
|
// Make sure the command list is valid
|
|
if (!CommandList.IsValid())
|
|
{
|
|
CommandList = MakeShareable(new FUICommandList);
|
|
}
|
|
|
|
// Bind commands
|
|
const FFLESHEditorCommands& Commands = FFLESHEditorCommands::Get();
|
|
|
|
// Example command binding
|
|
CommandList->MapAction(
|
|
Commands.OpenDismembermentGraphEditor,
|
|
FExecuteAction::CreateSP(this, &FFLESHEditor::OnOpenDismembermentGraphEditor),
|
|
FCanExecuteAction());
|
|
}
|
|
|
|
// Extend toolbar with custom buttons
|
|
void FFLESHEditor::ExtendToolbar()
|
|
{
|
|
UE_LOG(LogFLESHEditor, Log, TEXT("Extending toolbar"));
|
|
|
|
struct Local
|
|
{
|
|
static void FillToolbar(FToolBarBuilder& ToolbarBuilder)
|
|
{
|
|
ToolbarBuilder.BeginSection("FLESH");
|
|
{
|
|
ToolbarBuilder.AddToolBarButton(FFLESHEditorCommands::Get().OpenDismembermentGraphEditor,
|
|
NAME_None,
|
|
LOCTEXT("DismembermentGraphButtonLabel", "Dismemberment Graph"),
|
|
LOCTEXT("DismembermentGraphButtonTooltip", "Open the Dismemberment Graph Editor"),
|
|
FSlateIcon(FAppStyle::GetAppStyleSetName(), "ClassIcon.Blueprint"));
|
|
}
|
|
ToolbarBuilder.EndSection();
|
|
}
|
|
};
|
|
|
|
TSharedPtr<FExtender> ToolbarExtender = MakeShareable(new FExtender);
|
|
|
|
ToolbarExtender->AddToolBarExtension(
|
|
"Asset",
|
|
EExtensionHook::After,
|
|
CommandList,
|
|
FToolBarExtensionDelegate::CreateStatic(&Local::FillToolbar)
|
|
);
|
|
|
|
AddToolbarExtender(ToolbarExtender);
|
|
}
|
|
|
|
// Command handlers
|
|
void FFLESHEditor::OnOpenDismembermentGraphEditor()
|
|
{
|
|
UE_LOG(LogFLESHEditor, Log, TEXT("Opening Dismemberment Graph Editor"));
|
|
|
|
// Implementation will be added in the future
|
|
}
|
|
|
|
// Error handling method
|
|
void FFLESHEditor::HandleEditorError(const FText& ErrorMessage)
|
|
{
|
|
UE_LOG(LogFLESHEditor, Error, TEXT("%s"), *ErrorMessage.ToString());
|
|
|
|
// Show a message dialog
|
|
FMessageDialog::Open(EAppMsgType::Ok, ErrorMessage);
|
|
}
|
|
|
|
// Check if editor is initialized
|
|
bool FFLESHEditor::IsEditorInitialized()
|
|
{
|
|
return bIsInitialized;
|
|
}
|
|
|
|
// FAssetEditorToolkit interface
|
|
void FFLESHEditor::RegisterTabSpawners(const TSharedRef<FTabManager>& InTabManager)
|
|
{
|
|
FAssetEditorToolkit::RegisterTabSpawners(InTabManager);
|
|
|
|
// Register viewport tab
|
|
InTabManager->RegisterTabSpawner(ViewportTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_Viewport))
|
|
.SetDisplayName(LOCTEXT("ViewportTab", "Viewport"))
|
|
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
|
|
.SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "LevelEditor.Tabs.Viewports"));
|
|
|
|
// Register details tab
|
|
InTabManager->RegisterTabSpawner(DetailsTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_Details))
|
|
.SetDisplayName(LOCTEXT("DetailsTab", "Details"))
|
|
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
|
|
.SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "LevelEditor.Tabs.Details"));
|
|
|
|
// Register layer system tab
|
|
InTabManager->RegisterTabSpawner(LayerSystemTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_LayerSystem))
|
|
.SetDisplayName(LOCTEXT("LayerSystemTab", "Layer System"))
|
|
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
|
|
.SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "LevelEditor.Tabs.Layers"));
|
|
|
|
// Register physics settings tab
|
|
InTabManager->RegisterTabSpawner(PhysicsSettingsTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_PhysicsSettings))
|
|
.SetDisplayName(LOCTEXT("PhysicsSettingsTab", "Physics Settings"))
|
|
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
|
|
.SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "LevelEditor.Tabs.WorldSettings"));
|
|
}
|
|
|
|
void FFLESHEditor::UnregisterTabSpawners(const TSharedRef<FTabManager>& InTabManager)
|
|
{
|
|
FAssetEditorToolkit::UnregisterTabSpawners(InTabManager);
|
|
|
|
// Unregister all tabs
|
|
InTabManager->UnregisterTabSpawner(ViewportTabId);
|
|
InTabManager->UnregisterTabSpawner(DetailsTabId);
|
|
InTabManager->UnregisterTabSpawner(LayerSystemTabId);
|
|
InTabManager->UnregisterTabSpawner(PhysicsSettingsTabId);
|
|
}
|
|
|
|
FName FFLESHEditor::GetToolkitFName() const
|
|
{
|
|
return FName("FLESHEditor");
|
|
}
|
|
|
|
FText FFLESHEditor::GetBaseToolkitName() const
|
|
{
|
|
return LOCTEXT("AppLabel", "FLESH Editor");
|
|
}
|
|
|
|
FString FFLESHEditor::GetWorldCentricTabPrefix() const
|
|
{
|
|
return LOCTEXT("WorldCentricTabPrefix", "FLESH ").ToString();
|
|
}
|
|
|
|
FLinearColor FFLESHEditor::GetWorldCentricTabColorScale() const
|
|
{
|
|
return FLinearColor(0.7f, 0.0f, 0.0f, 0.5f); // Dark red color
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|