Files
FLESH/Source/FLESHEditor/Public/FLESHEditor.h
2025-04-21 20:08:05 +08:00

382 lines
12 KiB
C++

#pragma once
#include "CoreMinimal.h"
#include "Toolkits/AssetEditorToolkit.h"
#include "Widgets/Docking/SDockTab.h"
#include "BooleanCutTool.h"
#include "EditorUndoClient.h"
#include "Logging/LogMacros.h"
class SDockTab;
class SGraphEditor;
class SPropertyTreeView;
class SAssetBrowser;
class SMatrixInputWidget;
class FFLESHViewportClient;
class FSceneViewport;
class UVisceraNodeObject;
class FDismembermentEditor;
// Define log category
DECLARE_LOG_CATEGORY_EXTERN(LogFLESHEditor, Log, All);
/**
* Bone tree item structure
*/
struct FBoneTreeItem : public TSharedFromThis<FBoneTreeItem>
{
// Bone name
FName BoneName;
// Display name for UI
FString DisplayName;
// Bone type (e.g., "Root", "Limb", "Joint", etc.)
FString BoneType;
// Parent bone item
TWeakPtr<FBoneTreeItem> ParentItem;
// Child bone items
TArray<TSharedPtr<FBoneTreeItem>> Children;
// Constructor
FBoneTreeItem(FName InBoneName, const FString& InDisplayName, const FString& InBoneType = TEXT(""))
: BoneName(InBoneName)
, DisplayName(InDisplayName)
, BoneType(InBoneType)
{
}
// Add a child bone
void AddChild(TSharedPtr<FBoneTreeItem> Child)
{
Children.Add(Child);
Child->ParentItem = SharedThis(this);
}
};
/**
* Viscera node item structure
*/
struct FVisceraNodeItem : public TSharedFromThis<FVisceraNodeItem>
{
// Node name
FName NodeName;
// Display name for UI
FString DisplayName;
// Node type (e.g., "SoftBody", "Anchor", "Collision", "Tetra", "LineChain", "Plane", etc.)
FString NodeType;
// Parent node item
TWeakPtr<FVisceraNodeItem> ParentItem;
// Child node items
TArray<TSharedPtr<FVisceraNodeItem>> Children;
// Physical properties
TMap<FName, float> FloatProperties;
TMap<FName, FVector> VectorProperties;
TMap<FName, FName> NameProperties;
TMap<FName, bool> BoolProperties;
TArray<FVector> PointsArray;
// Constructor
FVisceraNodeItem(FName InNodeName, const FString& InDisplayName, const FString& InNodeType = TEXT(""))
: NodeName(InNodeName)
, DisplayName(InDisplayName)
, NodeType(InNodeType)
{
// Initialize default properties based on node type
if (InNodeType.Equals(TEXT("SoftBody")))
{
// Default SoftBody properties
FloatProperties.Add(TEXT("GravityStrength"), 1.0f);
FloatProperties.Add(TEXT("MinFrameSpeed"), 0.0f);
FloatProperties.Add(TEXT("MaxFrameSpeed"), 200.0f);
FloatProperties.Add(TEXT("ExternalFrameLerp"), 1.0f);
FloatProperties.Add(TEXT("InitialGPUInfluence"), 0.5f);
FloatProperties.Add(TEXT("SubstepTime"), 0.01667f);
FloatProperties.Add(TEXT("SolverIterations"), 1.0f);
BoolProperties.Add(TEXT("EnableSimulation"), true);
BoolProperties.Add(TEXT("RecomputeNormals"), true);
}
else if (InNodeType.Equals(TEXT("Anchor")))
{
// Default Anchor properties
FloatProperties.Add(TEXT("Radius"), 5.0f);
FloatProperties.Add(TEXT("Stiffness"), 1.0f);
VectorProperties.Add(TEXT("Location"), FVector::ZeroVector);
NameProperties.Add(TEXT("BoneName"), NAME_None);
}
else if (InNodeType.Equals(TEXT("LineChain")))
{
// Default LineChain properties
FloatProperties.Add(TEXT("Stiffness"), 0.5f);
FloatProperties.Add(TEXT("Thickness"), 1.0f);
// Default with two points
PointsArray.Add(FVector(-10.0f, 0.0f, 0.0f));
PointsArray.Add(FVector(10.0f, 0.0f, 0.0f));
}
else if (InNodeType.Equals(TEXT("Tetra")))
{
// Default Tetra properties
FloatProperties.Add(TEXT("Stiffness"), 0.7f);
// Default tetrahedron points
PointsArray.Add(FVector(0.0f, 0.0f, 0.0f));
PointsArray.Add(FVector(10.0f, 0.0f, 0.0f));
PointsArray.Add(FVector(0.0f, 10.0f, 0.0f));
PointsArray.Add(FVector(0.0f, 0.0f, 10.0f));
}
else if (InNodeType.Equals(TEXT("Plane")))
{
// Default Plane properties
FloatProperties.Add(TEXT("Stiffness"), 1.0f);
VectorProperties.Add(TEXT("Location"), FVector::ZeroVector);
VectorProperties.Add(TEXT("Normal"), FVector::UpVector);
}
}
// Add a child node
void AddChild(TSharedPtr<FVisceraNodeItem> Child)
{
Children.Add(Child);
Child->ParentItem = SharedThis(this);
}
// Set a float property
void SetFloatProperty(FName PropertyName, float Value)
{
FloatProperties.Add(PropertyName, Value);
}
// Set a vector property
void SetVectorProperty(FName PropertyName, const FVector& Value)
{
VectorProperties.Add(PropertyName, Value);
}
// Set a name property
void SetNameProperty(FName PropertyName, FName Value)
{
NameProperties.Add(PropertyName, Value);
}
// Set a bool property
void SetBoolProperty(FName PropertyName, bool Value)
{
BoolProperties.Add(PropertyName, Value);
}
// Add a point to the points array
void AddPoint(const FVector& Point)
{
PointsArray.Add(Point);
}
// Clear all points
void ClearPoints()
{
PointsArray.Empty();
}
};
/**
* FLESH Main Editor
* Provides the main editing functionality for the dismemberment system
*/
class FLESHEDITOR_API FFLESHEditor : public FAssetEditorToolkit, public FEditorUndoClient
{
public:
FFLESHEditor();
virtual ~FFLESHEditor();
// Initialize the editor
void InitFLESHEditor(const EToolkitMode::Type Mode, const TSharedPtr<IToolkitHost>& InitToolkitHost, UObject* InObject);
// FAssetEditorToolkit interface
virtual void RegisterTabSpawners(const TSharedRef<FTabManager>& TabManager) override;
virtual void UnregisterTabSpawners(const TSharedRef<FTabManager>& TabManager) override;
virtual FName GetToolkitFName() const override;
virtual FText GetBaseToolkitName() const override;
virtual FString GetWorldCentricTabPrefix() const override;
virtual FLinearColor GetWorldCentricTabColorScale() const override;
// End of FAssetEditorToolkit interface
// FEditorUndoClient interface
virtual void PostUndo(bool bSuccess) override;
virtual void PostRedo(bool bSuccess) override;
// Open the editor
void OpenEditor();
// Get whether the editor is initialized
bool IsEditorInitialized();
// Get the editing object
UObject* GetEditingObject() const { return EditingObject; }
// Add DismembermentEditor related tab spawners
TSharedRef<SDockTab> SpawnTab_LayerSystem(const FSpawnTabArgs& Args);
TSharedRef<SDockTab> SpawnTab_PhysicsSettings(const FSpawnTabArgs& Args);
// Create DismembermentEditor related widgets
TSharedRef<SBorder> CreateLayerSystemWidget();
TSharedRef<SBorder> CreatePhysicsSettingsWidget();
private:
// Tab spawners
TSharedRef<SDockTab> SpawnTab_Viewport(const FSpawnTabArgs& Args);
TSharedRef<SDockTab> SpawnTab_Details(const FSpawnTabArgs& Args);
TSharedRef<SDockTab> SpawnTab_AssetBrowser(const FSpawnTabArgs& Args);
TSharedRef<SDockTab> SpawnTab_MatrixEditor(const FSpawnTabArgs& Args);
TSharedRef<SDockTab> SpawnTab_GraphEditor(const FSpawnTabArgs& Args);
TSharedRef<SDockTab> SpawnTab_Toolbar(const FSpawnTabArgs& Args);
// Create viewport widget
TSharedRef<SWidget> CreateViewportWidget();
// Create details panel
TSharedRef<SWidget> CreateDetailsWidget();
// Create asset browser
TSharedRef<SWidget> CreateAssetBrowserWidget();
// Create matrix editor
TSharedRef<SWidget> CreateMatrixEditorWidget();
// Create graph editor
TSharedRef<SWidget> CreateGraphEditorWidget();
// Create toolbar
TSharedRef<SWidget> CreateToolbarWidget();
// Create command list
void CreateCommandList();
// Extend toolbar with custom buttons
void ExtendToolbar();
// Generate bone tree row
TSharedRef<ITableRow> OnGenerateBoneRow(TSharedPtr<FBoneTreeItem> Item, const TSharedRef<STableViewBase>& OwnerTable);
// Get bone children
void OnGetBoneChildren(TSharedPtr<FBoneTreeItem> Item, TArray<TSharedPtr<FBoneTreeItem>>& OutChildren);
// Bone selection changed
void OnBoneSelectionChanged(TSharedPtr<FBoneTreeItem> Item, ESelectInfo::Type SelectInfo);
// Build bone hierarchy
void BuildBoneHierarchy();
// Build viscera node tree
void BuildVisceraNodeTree();
// Tree view generation methods
TSharedRef<ITableRow> OnGenerateNodeRow(TSharedPtr<FVisceraNodeItem> InItem, const TSharedRef<STableViewBase>& OwnerTable);
void OnGetNodeChildren(TSharedPtr<FVisceraNodeItem> InItem, TArray<TSharedPtr<FVisceraNodeItem>>& OutChildren);
void OnNodeSelectionChanged(TSharedPtr<FVisceraNodeItem> InItem, ESelectInfo::Type SelectInfo);
// Context menu for node tree
TSharedPtr<SWidget> OnGetNodeContextMenu(TSharedPtr<FVisceraNodeItem> InItem);
// Add new viscera node
void AddNewVisceraNode(const FString& NodeType, TSharedPtr<FVisceraNodeItem> ParentItem = nullptr);
// Command handlers
void OnOpenDismembermentGraphEditor();
void OnOpenAnatomicalLayerEditor();
void OnOpenBooleanCutTool();
void OnOpenBloodSystemEditor();
void OnImportCharacterModel();
void OnImportOrganModel();
void OnImportSkeletonModel();
void OnImportPhysicsAsset();
void OnTestMatrix();
void OnImportModel();
void OnSavePreset();
void OnLoadPreset();
// Viewport widget
TSharedPtr<class SViewport> ViewportWidget;
// Details panel
TSharedPtr<class IDetailsView> DetailsWidget;
// Asset browser
TSharedPtr<SAssetBrowser> AssetBrowserWidget;
// Matrix editor
TSharedPtr<SMatrixInputWidget> MatrixEditorWidget;
// Graph editor
TSharedPtr<SGraphEditor> GraphEditorWidget;
// Toolbar
TSharedPtr<class SBorder> ToolbarWidget;
// Bone tree view
TSharedPtr<STreeView<TSharedPtr<FBoneTreeItem>>> BoneTreeView;
// Node tree view
TSharedPtr<STreeView<TSharedPtr<FVisceraNodeItem>>> NodeTreeView;
// Bone items array
TArray<TSharedPtr<FBoneTreeItem>> BoneItems;
// Node items array
TArray<TSharedPtr<FVisceraNodeItem>> NodeItems;
// Cutting plane names
TArray<TSharedPtr<FName>> CuttingPlaneNames;
// Currently selected bone
TSharedPtr<FBoneTreeItem> SelectedBoneItem;
// Currently selected node
TSharedPtr<FVisceraNodeItem> SelectedNodeItem;
// Command list
TSharedPtr<FUICommandList> CommandList;
// Flag to track if the editor is initialized
bool bIsEditorInitialized;
// Viewport client
TSharedPtr<FFLESHViewportClient> ViewportClient;
// Scene viewport
TSharedPtr<FSceneViewport> Viewport;
// Viewport related methods
FReply OnResetCameraClicked();
FReply OnToggleWireframeClicked();
FReply OnToggleBonesClicked();
// The object being edited
UObject* EditingObject;
// Tab IDs
static const FName ViewportTabId;
static const FName DetailsTabId;
static const FName AssetBrowserTabId;
static const FName MatrixEditorTabId;
static const FName GraphEditorTabId;
static const FName ToolbarTabId;
static const FName LayerSystemTabId;
static const FName PhysicsSettingsTabId;
static const FName DismembermentGraphTabId;
// Is the editor initialized?
bool bIsInitialized;
// New DismembermentEditor related Widgets
TSharedPtr<SBorder> LayerSystemWidget;
TSharedPtr<SBorder> PhysicsSettingsWidget;
// Error handling method
void HandleEditorError(const FText& ErrorMessage);
};