475 lines
15 KiB
C++
475 lines
15 KiB
C++
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "Toolkits/AssetEditorToolkit.h"
|
|
#include "Widgets/Docking/SDockTab.h"
|
|
#include "Widgets/SViewport.h"
|
|
#include "EditorViewportClient.h"
|
|
#include "Widgets/Input/SSearchBox.h"
|
|
#include "Slate/SceneViewport.h"
|
|
#include "Framework/Application/SlateApplication.h"
|
|
#include "Styling/SlateStyleRegistry.h"
|
|
|
|
// Forward declaration for BooleanCutTool
|
|
class FBooleanCutTool;
|
|
|
|
#include "Logging/LogMacros.h"
|
|
#include "FLESHGraph/FLESHCompiler.h"
|
|
#include "FLESHGraph/FLESHExecutor.h"
|
|
|
|
class SDockTab;
|
|
class SGraphEditor;
|
|
class SPropertyTreeView;
|
|
class SAssetBrowser;
|
|
class SMatrixInputWidget;
|
|
class UVisceraNodeObject;
|
|
class FDismembermentEditor;
|
|
|
|
// Forward declaration
|
|
class FFLESHViewportClient;
|
|
|
|
// 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;
|
|
// Override FAssetEditorToolkit methods with correct parameter types
|
|
virtual void OnToolkitHostingStarted(const TSharedRef<class IToolkit>& InToolkit) override;
|
|
virtual void OnToolkitHostingFinished(const TSharedRef<class IToolkit>& InToolkit) override;
|
|
|
|
// 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_LayerSystemPanel(const FSpawnTabArgs& Args);
|
|
TSharedRef<SDockTab> SpawnTab_PhysicsSettings(const FSpawnTabArgs& Args);
|
|
|
|
// Create DismembermentEditor related widgets
|
|
TSharedRef<SBorder> CreateLayerSystemWidget();
|
|
TSharedRef<SBorder> CreatePhysicsSettingsWidget();
|
|
TSharedRef<SWidget> CreateNodeTreeWidget();
|
|
|
|
// Generate node tree row
|
|
TSharedRef<ITableRow> OnGenerateNodeTreeRow(TSharedPtr<FVisceraNodeItem> Item, const TSharedRef<STableViewBase>& OwnerTable);
|
|
|
|
// Get node tree children
|
|
void OnGetNodeTreeChildren(TSharedPtr<FVisceraNodeItem> Item, TArray<TSharedPtr<FVisceraNodeItem>>& OutChildren);
|
|
|
|
// Open node tree right-click menu
|
|
TSharedPtr<SWidget> OnNodeTreeContextMenuOpening();
|
|
|
|
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);
|
|
// Additional tab spawners
|
|
TSharedRef<SDockTab> SpawnTab_DismembermentGraph(const FSpawnTabArgs& Args);
|
|
TSharedRef<SDockTab> SpawnTab_NodeTree(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
|
|
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();
|
|
|
|
// Count total nodes in a tree recursively
|
|
int32 CountNodes(TSharedPtr<FVisceraNodeItem> Node);
|
|
|
|
// 从父节点中递归移除节点
|
|
bool RemoveNodeFromParent(TSharedPtr<FVisceraNodeItem> ParentNode, TSharedPtr<FVisceraNodeItem> NodeToRemove);
|
|
|
|
// 递归复制节点
|
|
void CopyNodeRecursive(TSharedPtr<FVisceraNodeItem> SourceNode, TSharedPtr<FVisceraNodeItem> TargetParentNode);
|
|
|
|
// 查找节点的父节点并添加复制的节点
|
|
bool AddCopyToParent(TSharedPtr<FVisceraNodeItem> CurrentNode, TSharedPtr<FVisceraNodeItem> NodeToFind, TSharedPtr<FVisceraNodeItem> NodeCopy);
|
|
|
|
// 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();
|
|
|
|
// 按钮点击事件处理
|
|
FReply OnResetCameraClicked();
|
|
FReply OnToggleWireframeClicked();
|
|
FReply OnToggleBonesClicked();
|
|
FReply OnImportModelClicked();
|
|
FReply OnSavePresetClicked();
|
|
FReply OnLoadPresetClicked();
|
|
FReply OnBooleanCutClicked();
|
|
|
|
// 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;
|
|
|
|
// The object being edited
|
|
TObjectPtr<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;
|
|
static const FName NodeTreeTabId;
|
|
|
|
// New DismembermentEditor related Widgets
|
|
TSharedPtr<SBorder> LayerSystemWidget;
|
|
TSharedPtr<SBorder> PhysicsSettingsWidget;
|
|
|
|
// Error handling method
|
|
void HandleEditorError(const FText& ErrorMessage);
|
|
|
|
// Layer names for dropdown
|
|
TArray<TSharedPtr<FString>> LayerNames;
|
|
|
|
// Layer descriptions for tooltips
|
|
TMap<FString, FString> LayerDescriptions;
|
|
|
|
// Layer visibility states
|
|
TMap<FString, bool> LayerVisibility;
|
|
|
|
// Node tree root nodes
|
|
TArray<TSharedPtr<FVisceraNodeItem>> NodeTreeRoots;
|
|
|
|
// Get node tree root nodes
|
|
const TArray<TSharedPtr<FVisceraNodeItem>>& GetNodeTreeRoots() const { return NodeTreeRoots; }
|
|
|
|
// Get currently selected node
|
|
TSharedPtr<FVisceraNodeItem> GetSelectedNodeItem() const { return SelectedNodeItem; }
|
|
|
|
// Make these methods public so they can be accessed by FFLESHViewportClient
|
|
friend class FFLESHViewportClient;
|
|
|
|
// Node search filter text
|
|
FText NodeSearchText;
|
|
|
|
// Filtered node tree roots
|
|
TArray<TSharedPtr<FVisceraNodeItem>> FilteredNodeTreeRoots;
|
|
|
|
// Check if a node matches the search filter
|
|
bool DoesNodeMatchFilter(const TSharedPtr<FVisceraNodeItem>& Node) const;
|
|
|
|
// Apply search filter to node tree
|
|
void ApplySearchFilter();
|
|
|
|
// Reset search filter
|
|
void ResetSearchFilter();
|
|
|
|
// Handle node search text changes
|
|
void OnNodeSearchTextChanged(const FText& InFilterText);
|
|
|
|
// Bone tree items
|
|
TArray<TSharedPtr<FBoneTreeItem>> BoneTreeRoots;
|
|
|
|
// Boolean cut tool
|
|
TSharedPtr<class FBooleanCutTool> BooleanCutTool;
|
|
|
|
// FLESH Compiler
|
|
UPROPERTY()
|
|
UFLESHCompiler* FLESHCompiler;
|
|
|
|
// FLESH Executor
|
|
UPROPERTY()
|
|
UFLESHExecutor* FLESHExecutor;
|
|
};
|