This commit is contained in:
2025-04-17 23:59:17 +08:00
commit 88536f22da
57 changed files with 8094 additions and 0 deletions

View File

@@ -0,0 +1,211 @@
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "DismembermentCompiler.generated.h"
class UDismembermentGraphNode;
class UDismembermentGraph;
/**
* Compiled node data structure
*/
USTRUCT()
struct FCompiledNodeData
{
GENERATED_BODY()
// Node reference
UPROPERTY()
TObjectPtr<UDismembermentGraphNode> Node;
// Input nodes
UPROPERTY()
TArray<int32> InputNodeIndices;
// Output nodes
UPROPERTY()
TArray<int32> OutputNodeIndices;
// Execution order index
int32 ExecutionOrder;
// Constructor
FCompiledNodeData()
: Node(nullptr)
, ExecutionOrder(-1)
{
}
};
/**
* Dismemberment compiler class
* Compiles a dismemberment graph into executable logic
*/
UCLASS()
class FLESHEDITOR_API UDismembermentCompiler : public UObject
{
GENERATED_BODY()
public:
// Constructor
UDismembermentCompiler();
/**
* Compile a dismemberment graph
* @param InGraph - The graph to compile
* @return True if compilation was successful
*/
bool CompileGraph(UDismembermentGraph* InGraph);
/**
* Get the compiled node data
* @return Array of compiled node data
*/
const TArray<FCompiledNodeData>& GetCompiledNodeData() const { return CompiledNodeData; }
/**
* Get the execution order
* @return Array of node indices in execution order
*/
const TArray<int32>& GetExecutionOrder() const { return ExecutionOrder; }
/**
* Add a bone selection
* @param BoneName - Name of the bone to select
*/
void AddBoneSelection(const FName& BoneName);
/**
* Add a cut operation
* @param Location - Location of the cut
* @param Direction - Direction of the cut
* @param Width - Width of the cut
* @param Depth - Depth of the cut
* @param Material - Material to use for the cut surface
*/
void AddCutOperation(const FVector& Location, const FVector& Direction, float Width, float Depth, UMaterialInterface* Material);
/**
* Add a blood effect
* @param Location - Location of the blood effect
* @param BloodEffect - Niagara system for the blood effect
* @param BloodAmount - Amount of blood
* @param BloodPressure - Blood pressure
* @param CreateBloodPool - Whether to create a blood pool
* @param BloodPoolSize - Size of the blood pool
* @param BloodPoolMaterial - Material for the blood pool
*/
void AddBloodEffect(const FVector& Location, UNiagaraSystem* BloodEffect, float BloodAmount, float BloodPressure, bool CreateBloodPool, float BloodPoolSize, UMaterialInterface* BloodPoolMaterial);
/**
* Add a physics simulation
* @param Mass - Mass of the object
* @param LinearDamping - Linear damping
* @param AngularDamping - Angular damping
* @param EnableGravity - Whether to enable gravity
* @param SimulatePhysics - Whether to simulate physics
* @param GenerateOverlapEvents - Whether to generate overlap events
* @param PhysicalMaterial - Physical material to use
* @param ImpulseForce - Force of the impulse
* @param ImpulseRadius - Radius of the impulse
*/
void AddPhysicsSimulation(float Mass, float LinearDamping, float AngularDamping, bool EnableGravity, bool SimulatePhysics, bool GenerateOverlapEvents, UPhysicalMaterial* PhysicalMaterial, float ImpulseForce, float ImpulseRadius);
/**
* Add an organ
* @param OrganMesh - Mesh for the organ
* @param OrganMaterial - Material for the organ
* @param AttachBoneName - Name of the bone to attach to
* @param RelativeLocation - Relative location
* @param RelativeRotation - Relative rotation
* @param RelativeScale - Relative scale
* @param SimulatePhysics - Whether to simulate physics
* @param DamageMultiplier - Damage multiplier
* @param IsCriticalOrgan - Whether this is a critical organ
* @param BloodAmount - Amount of blood
*/
void AddOrgan(UStaticMesh* OrganMesh, UMaterialInterface* OrganMaterial, const FName& AttachBoneName, const FVector& RelativeLocation, const FRotator& RelativeRotation, const FVector& RelativeScale, bool SimulatePhysics, float DamageMultiplier, bool IsCriticalOrgan, float BloodAmount);
/**
* Add a wound effect
* @param WoundSize - Size of the wound
* @param WoundDepth - Depth of the wound
* @param WoundMaterial - Material for the wound
* @param WoundEffect - Effect for the wound
* @param CreateDecal - Whether to create a decal
* @param DecalMaterial - Material for the decal
* @param DecalSize - Size of the decal
* @param DecalLifetime - Lifetime of the decal
* @param AffectBoneHealth - Whether to affect bone health
* @param BoneDamage - Amount of bone damage
*/
void AddWoundEffect(float WoundSize, float WoundDepth, UMaterialInterface* WoundMaterial, UNiagaraSystem* WoundEffect, bool CreateDecal, UMaterialInterface* DecalMaterial, float DecalSize, float DecalLifetime, bool AffectBoneHealth, float BoneDamage);
private:
// The graph being compiled
UPROPERTY()
TObjectPtr<UDismembermentGraph> Graph;
// Compiled node data
UPROPERTY()
TArray<FCompiledNodeData> CompiledNodeData;
// Execution order
UPROPERTY()
TArray<int32> ExecutionOrder;
// Bone selections
UPROPERTY()
TArray<FName> BoneSelections;
// Cut operations
UPROPERTY()
TArray<FTransform> CutOperations;
// Cut materials
UPROPERTY()
TArray<TObjectPtr<UMaterialInterface>> CutMaterials;
// Cut widths
UPROPERTY()
TArray<float> CutWidths;
// Cut depths
UPROPERTY()
TArray<float> CutDepths;
// Blood effects
UPROPERTY()
TArray<FTransform> BloodEffectTransforms;
// Blood effect systems
UPROPERTY()
TArray<TObjectPtr<UNiagaraSystem>> BloodEffectSystems;
// Blood amounts
UPROPERTY()
TArray<float> BloodAmounts;
// Blood pressures
UPROPERTY()
TArray<float> BloodPressures;
// Create blood pools
UPROPERTY()
TArray<bool> CreateBloodPools;
// Blood pool sizes
UPROPERTY()
TArray<float> BloodPoolSizes;
// Blood pool materials
UPROPERTY()
TArray<TObjectPtr<UMaterialInterface>> BloodPoolMaterials;
// Topological sort the nodes
bool TopologicalSort();
// Visit node for topological sort
void VisitNode(int32 NodeIndex, TArray<bool>& Visited, TArray<bool>& TempMark, TArray<int32>& SortedNodes, bool& bHasCycle);
};

View File

@@ -0,0 +1,155 @@
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "DismembermentCompiler.h"
#include "DismembermentExecutor.generated.h"
class AActor;
class USkeletalMeshComponent;
class UDismembermentCompiler;
/**
* Dismemberment executor class
* Executes a compiled dismemberment graph
*/
UCLASS()
class FLESHEDITOR_API UDismembermentExecutor : public UObject
{
GENERATED_BODY()
public:
// Constructor
UDismembermentExecutor();
/**
* Initialize the executor with a compiler
* @param InCompiler - The compiler containing the compiled graph
*/
void Initialize(UDismembermentCompiler* InCompiler);
/**
* Execute the compiled graph on a target actor
* @param TargetActor - The actor to apply the dismemberment effects to
* @return True if execution was successful
*/
bool Execute(AActor* TargetActor);
/**
* Get the target actor
* @return The target actor
*/
AActor* GetTargetActor() const { return TargetActor; }
/**
* Get the target skeletal mesh component
* @return The target skeletal mesh component
*/
USkeletalMeshComponent* GetTargetSkeletalMesh() const { return TargetSkeletalMesh; }
/**
* Get the selected bones
* @return Array of selected bone names
*/
const TArray<FName>& GetSelectedBones() const { return SelectedBones; }
/**
* Add a bone to the selection
* @param BoneName - Name of the bone to add
*/
void AddSelectedBone(const FName& BoneName);
/**
* Apply a cut to the target
* @param Location - Location of the cut
* @param Direction - Direction of the cut
* @param Width - Width of the cut
* @param Depth - Depth of the cut
* @param Material - Material to use for the cut surface
* @return True if the cut was successful
*/
bool ApplyCut(const FVector& Location, const FVector& Direction, float Width, float Depth, UMaterialInterface* Material);
/**
* Spawn a blood effect
* @param Location - Location of the blood effect
* @param BloodEffect - Niagara system for the blood effect
* @param BloodAmount - Amount of blood
* @param BloodPressure - Blood pressure
* @param CreateBloodPool - Whether to create a blood pool
* @param BloodPoolSize - Size of the blood pool
* @param BloodPoolMaterial - Material for the blood pool
* @return True if the blood effect was created successfully
*/
bool SpawnBloodEffect(const FVector& Location, UNiagaraSystem* BloodEffect, float BloodAmount, float BloodPressure, bool CreateBloodPool, float BloodPoolSize, UMaterialInterface* BloodPoolMaterial);
/**
* Apply physics simulation
* @param Mass - Mass of the object
* @param LinearDamping - Linear damping
* @param AngularDamping - Angular damping
* @param EnableGravity - Whether to enable gravity
* @param SimulatePhysics - Whether to simulate physics
* @param GenerateOverlapEvents - Whether to generate overlap events
* @param PhysicalMaterial - Physical material to use
* @param ImpulseForce - Force of the impulse
* @param ImpulseRadius - Radius of the impulse
* @return True if the physics simulation was applied successfully
*/
bool ApplyPhysics(float Mass, float LinearDamping, float AngularDamping, bool EnableGravity, bool SimulatePhysics, bool GenerateOverlapEvents, UPhysicalMaterial* PhysicalMaterial, float ImpulseForce, float ImpulseRadius);
/**
* Spawn an organ
* @param OrganMesh - Mesh for the organ
* @param OrganMaterial - Material for the organ
* @param AttachBoneName - Name of the bone to attach to
* @param RelativeLocation - Relative location
* @param RelativeRotation - Relative rotation
* @param RelativeScale - Relative scale
* @param SimulatePhysics - Whether to simulate physics
* @param DamageMultiplier - Damage multiplier
* @param IsCriticalOrgan - Whether this is a critical organ
* @param BloodAmount - Amount of blood
* @return True if the organ was spawned successfully
*/
bool SpawnOrgan(UStaticMesh* OrganMesh, UMaterialInterface* OrganMaterial, const FName& AttachBoneName, const FVector& RelativeLocation, const FRotator& RelativeRotation, const FVector& RelativeScale, bool SimulatePhysics, float DamageMultiplier, bool IsCriticalOrgan, float BloodAmount);
/**
* Apply a wound effect
* @param WoundSize - Size of the wound
* @param WoundDepth - Depth of the wound
* @param WoundMaterial - Material for the wound
* @param WoundEffect - Effect for the wound
* @param CreateDecal - Whether to create a decal
* @param DecalMaterial - Material for the decal
* @param DecalSize - Size of the decal
* @param DecalLifetime - Lifetime of the decal
* @param AffectBoneHealth - Whether to affect bone health
* @param BoneDamage - Amount of bone damage
* @return True if the wound effect was applied successfully
*/
bool ApplyWoundEffect(float WoundSize, float WoundDepth, UMaterialInterface* WoundMaterial, UNiagaraSystem* WoundEffect, bool CreateDecal, UMaterialInterface* DecalMaterial, float DecalSize, float DecalLifetime, bool AffectBoneHealth, float BoneDamage);
private:
// The compiler containing the compiled graph
UPROPERTY()
TObjectPtr<UDismembermentCompiler> Compiler;
// The target actor
UPROPERTY()
TObjectPtr<AActor> TargetActor;
// The target skeletal mesh component
UPROPERTY()
TObjectPtr<USkeletalMeshComponent> TargetSkeletalMesh;
// Selected bones
UPROPERTY()
TArray<FName> SelectedBones;
// Find the target skeletal mesh component
bool FindTargetSkeletalMesh();
// Execute a node
bool ExecuteNode(int32 NodeIndex);
};

View File

@@ -0,0 +1,22 @@
#pragma once
#include "CoreMinimal.h"
#include "EdGraph/EdGraph.h"
#include "DismembermentGraph.generated.h"
/**
* Dismemberment graph for visual logic design
* Allows for node-based editing of dismemberment system logic
*/
UCLASS()
class FLESHEDITOR_API UDismembermentGraph : public UEdGraph
{
GENERATED_BODY()
public:
UDismembermentGraph();
// The asset that owns this graph
UPROPERTY()
class UDismembermentGraphAsset* OwningAsset;
};

View File

@@ -0,0 +1,80 @@
#pragma once
#include "CoreMinimal.h"
#include "Toolkits/AssetEditorToolkit.h"
#include "GraphEditor.h"
class UDismembermentGraphAsset;
class UDismembermentGraph;
class SDockTab;
/**
* Dismemberment graph editor
* Provides a Mutable-like node editor for dismemberment system logic
*/
class FLESHEDITOR_API FDismembermentGraphEditor : public FAssetEditorToolkit
{
public:
FDismembermentGraphEditor();
virtual ~FDismembermentGraphEditor();
// Initialize the editor
void InitDismembermentGraphEditor(const EToolkitMode::Type Mode, const TSharedPtr<IToolkitHost>& InitToolkitHost, UDismembermentGraphAsset* InAsset);
// 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
// Get the edited asset
UDismembermentGraphAsset* GetEditedAsset() const { return EditedAsset; }
// Get the graph editor widget
TSharedRef<SGraphEditor> GetGraphEditor() const { return GraphEditorWidget.ToSharedRef(); }
private:
// The asset being edited
UDismembermentGraphAsset* EditedAsset;
// The graph editor widget
TSharedPtr<SGraphEditor> GraphEditorWidget;
// Tab spawners
TSharedRef<SDockTab> SpawnTab_GraphCanvas(const FSpawnTabArgs& Args);
TSharedRef<SDockTab> SpawnTab_Properties(const FSpawnTabArgs& Args);
TSharedRef<SDockTab> SpawnTab_Palette(const FSpawnTabArgs& Args);
// Create graph editor widget
TSharedRef<SGraphEditor> CreateGraphEditorWidget();
// Graph editor commands
void CreateCommandList();
TSharedPtr<FUICommandList> GraphEditorCommands;
// Command handlers
void SelectAllNodes();
void DeleteSelectedNodes();
void CutSelectedNodes();
void CopySelectedNodes();
void PasteNodes();
void DuplicateSelectedNodes();
// Graph changed handler
void OnGraphChanged(const FEdGraphEditAction& Action);
// Node selection changed handler
void OnSelectedNodesChanged(const TSet<UObject*>& NewSelection);
// Compile the graph
void CompileGraph();
// Properties panel
TSharedPtr<class IDetailsView> PropertiesWidget;
// Node palette
TSharedPtr<class SDismembermentGraphPalette> PaletteWidget;
};

View File

@@ -0,0 +1,22 @@
#pragma once
#include "CoreMinimal.h"
#include "Factories/Factory.h"
#include "DismembermentGraphEditorFactory.generated.h"
/**
* Factory for creating dismemberment graph assets
*/
UCLASS()
class FLESHEDITOR_API UDismembermentGraphEditorFactory : public UFactory
{
GENERATED_BODY()
public:
UDismembermentGraphEditorFactory();
// UFactory interface
virtual UObject* FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override;
virtual bool ShouldShowInNewMenu() const override;
// End of UFactory interface
};

View File

@@ -0,0 +1,43 @@
#pragma once
#include "CoreMinimal.h"
#include "EdGraph/EdGraphNode.h"
#include "DismembermentGraphNode.generated.h"
/**
* Base class for all dismemberment graph nodes
*/
UCLASS()
class FLESHEDITOR_API UDismembermentGraphNode : public UEdGraphNode
{
GENERATED_BODY()
public:
UDismembermentGraphNode();
// Node title color
UPROPERTY(EditAnywhere, Category = "Appearance")
FLinearColor NodeTitleColor;
// Node category
UPROPERTY(EditAnywhere, Category = "Category")
FText NodeCategory;
// Node description
UPROPERTY(EditAnywhere, Category = "Description")
FText NodeDescription;
// UEdGraphNode interface
virtual void AllocateDefaultPins() override;
virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override;
virtual FLinearColor GetNodeTitleColor() const override;
virtual FText GetTooltipText() const override;
virtual FText GetMenuCategory() const override;
// End of UEdGraphNode interface
// Compile this node into executable logic
virtual void CompileNode(class FDismembermentCompiler* Compiler);
// Execute this node
virtual void ExecuteNode(class FDismembermentExecutor* Executor);
};

View File

@@ -0,0 +1,46 @@
#pragma once
#include "CoreMinimal.h"
#include "DismembermentGraphNode.h"
#include "DismembermentGraphNodeBloodEffect.generated.h"
/**
* Node for creating blood effects in the dismemberment graph
*/
UCLASS()
class FLESHEDITOR_API UDismembermentGraphNodeBloodEffect : public UDismembermentGraphNode
{
GENERATED_BODY()
public:
UDismembermentGraphNodeBloodEffect();
// Blood effect parameters
UPROPERTY(EditAnywhere, Category = "Blood Effect")
TObjectPtr<UNiagaraSystem> BloodEffect;
UPROPERTY(EditAnywhere, Category = "Blood Effect")
float BloodAmount;
UPROPERTY(EditAnywhere, Category = "Blood Effect")
float BloodPressure;
UPROPERTY(EditAnywhere, Category = "Blood Effect")
bool bCreateBloodPool;
UPROPERTY(EditAnywhere, Category = "Blood Effect", meta = (EditCondition = "bCreateBloodPool"))
float BloodPoolSize;
UPROPERTY(EditAnywhere, Category = "Blood Effect", meta = (EditCondition = "bCreateBloodPool"))
TObjectPtr<UMaterialInterface> BloodPoolMaterial;
// UEdGraphNode interface
virtual void AllocateDefaultPins() override;
virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override;
// End of UEdGraphNode interface
// UDismembermentGraphNode interface
virtual void CompileNode(class FDismembermentCompiler* Compiler) override;
virtual void ExecuteNode(class FDismembermentExecutor* Executor) override;
// End of UDismembermentGraphNode interface
};

View File

@@ -0,0 +1,40 @@
#pragma once
#include "CoreMinimal.h"
#include "DismembermentGraphNode.h"
#include "DismembermentGraphNodeBoneSelect.generated.h"
/**
* Node for selecting bones in the dismemberment graph
*/
UCLASS()
class FLESHEDITOR_API UDismembermentGraphNodeBoneSelect : public UDismembermentGraphNode
{
GENERATED_BODY()
public:
UDismembermentGraphNodeBoneSelect();
// Bone selection parameters
UPROPERTY(EditAnywhere, Category = "Bone Selection")
TArray<FName> BoneNames;
UPROPERTY(EditAnywhere, Category = "Bone Selection")
bool bUseRegex;
UPROPERTY(EditAnywhere, Category = "Bone Selection", meta = (EditCondition = "bUseRegex"))
FString BoneNamePattern;
UPROPERTY(EditAnywhere, Category = "Bone Selection")
bool bIncludeChildren;
// UEdGraphNode interface
virtual void AllocateDefaultPins() override;
virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override;
// End of UEdGraphNode interface
// UDismembermentGraphNode interface
virtual void CompileNode(class FDismembermentCompiler* Compiler) override;
virtual void ExecuteNode(class FDismembermentExecutor* Executor) override;
// End of UDismembermentGraphNode interface
};

View File

@@ -0,0 +1,40 @@
#pragma once
#include "CoreMinimal.h"
#include "DismembermentGraphNode.h"
#include "DismembermentGraphNodeCut.generated.h"
/**
* Node for performing a cut operation in the dismemberment graph
*/
UCLASS()
class FLESHEDITOR_API UDismembermentGraphNodeCut : public UDismembermentGraphNode
{
GENERATED_BODY()
public:
UDismembermentGraphNodeCut();
// Cut parameters
UPROPERTY(EditAnywhere, Category = "Cut Parameters")
float CutWidth;
UPROPERTY(EditAnywhere, Category = "Cut Parameters")
float CutDepth;
UPROPERTY(EditAnywhere, Category = "Cut Parameters")
bool bUseCustomMaterial;
UPROPERTY(EditAnywhere, Category = "Cut Parameters", meta = (EditCondition = "bUseCustomMaterial"))
TObjectPtr<UMaterialInterface> CustomCutMaterial;
// UEdGraphNode interface
virtual void AllocateDefaultPins() override;
virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override;
// End of UEdGraphNode interface
// UDismembermentGraphNode interface
virtual void CompileNode(class FDismembermentCompiler* Compiler) override;
virtual void ExecuteNode(class FDismembermentExecutor* Executor) override;
// End of UDismembermentGraphNode interface
};

View File

@@ -0,0 +1,58 @@
#pragma once
#include "CoreMinimal.h"
#include "DismembermentGraphNode.h"
#include "DismembermentGraphNodeOrgan.generated.h"
/**
* Node for organ simulation in the dismemberment graph
*/
UCLASS()
class FLESHEDITOR_API UDismembermentGraphNodeOrgan : public UDismembermentGraphNode
{
GENERATED_BODY()
public:
UDismembermentGraphNodeOrgan();
// Organ parameters
UPROPERTY(EditAnywhere, Category = "Organ Parameters")
TObjectPtr<UStaticMesh> OrganMesh;
UPROPERTY(EditAnywhere, Category = "Organ Parameters")
TObjectPtr<UMaterialInterface> OrganMaterial;
UPROPERTY(EditAnywhere, Category = "Organ Parameters")
FName AttachBoneName;
UPROPERTY(EditAnywhere, Category = "Organ Parameters")
FVector RelativeLocation;
UPROPERTY(EditAnywhere, Category = "Organ Parameters")
FRotator RelativeRotation;
UPROPERTY(EditAnywhere, Category = "Organ Parameters")
FVector RelativeScale;
UPROPERTY(EditAnywhere, Category = "Organ Parameters")
bool bSimulatePhysics;
UPROPERTY(EditAnywhere, Category = "Organ Parameters")
float DamageMultiplier;
UPROPERTY(EditAnywhere, Category = "Organ Parameters")
bool bIsCriticalOrgan;
UPROPERTY(EditAnywhere, Category = "Organ Parameters")
float BloodAmount;
// UEdGraphNode interface
virtual void AllocateDefaultPins() override;
virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override;
// End of UEdGraphNode interface
// UDismembermentGraphNode interface
virtual void CompileNode(class FDismembermentCompiler* Compiler) override;
virtual void ExecuteNode(class FDismembermentExecutor* Executor) override;
// End of UDismembermentGraphNode interface
};

View File

@@ -0,0 +1,55 @@
#pragma once
#include "CoreMinimal.h"
#include "DismembermentGraphNode.h"
#include "DismembermentGraphNodePhysics.generated.h"
/**
* Node for physics simulation in the dismemberment graph
*/
UCLASS()
class FLESHEDITOR_API UDismembermentGraphNodePhysics : public UDismembermentGraphNode
{
GENERATED_BODY()
public:
UDismembermentGraphNodePhysics();
// Physics parameters
UPROPERTY(EditAnywhere, Category = "Physics Parameters")
float Mass;
UPROPERTY(EditAnywhere, Category = "Physics Parameters")
float LinearDamping;
UPROPERTY(EditAnywhere, Category = "Physics Parameters")
float AngularDamping;
UPROPERTY(EditAnywhere, Category = "Physics Parameters")
bool bEnableGravity;
UPROPERTY(EditAnywhere, Category = "Physics Parameters")
bool bSimulatePhysics;
UPROPERTY(EditAnywhere, Category = "Physics Parameters")
bool bGenerateOverlapEvents;
UPROPERTY(EditAnywhere, Category = "Physics Parameters")
TObjectPtr<UPhysicalMaterial> PhysicalMaterial;
UPROPERTY(EditAnywhere, Category = "Physics Parameters")
float ImpulseForce;
UPROPERTY(EditAnywhere, Category = "Physics Parameters")
float ImpulseRadius;
// UEdGraphNode interface
virtual void AllocateDefaultPins() override;
virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override;
// End of UEdGraphNode interface
// UDismembermentGraphNode interface
virtual void CompileNode(class FDismembermentCompiler* Compiler) override;
virtual void ExecuteNode(class FDismembermentExecutor* Executor) override;
// End of UDismembermentGraphNode interface
};

View File

@@ -0,0 +1,58 @@
#pragma once
#include "CoreMinimal.h"
#include "DismembermentGraphNode.h"
#include "DismembermentGraphNodeWound.generated.h"
/**
* Node for wound effects in the dismemberment graph
*/
UCLASS()
class FLESHEDITOR_API UDismembermentGraphNodeWound : public UDismembermentGraphNode
{
GENERATED_BODY()
public:
UDismembermentGraphNodeWound();
// Wound parameters
UPROPERTY(EditAnywhere, Category = "Wound Parameters")
float WoundSize;
UPROPERTY(EditAnywhere, Category = "Wound Parameters")
float WoundDepth;
UPROPERTY(EditAnywhere, Category = "Wound Parameters")
TObjectPtr<UMaterialInterface> WoundMaterial;
UPROPERTY(EditAnywhere, Category = "Wound Parameters")
TObjectPtr<UNiagaraSystem> WoundEffect;
UPROPERTY(EditAnywhere, Category = "Wound Parameters")
bool bCreateDecal;
UPROPERTY(EditAnywhere, Category = "Wound Parameters", meta = (EditCondition = "bCreateDecal"))
TObjectPtr<UMaterialInterface> DecalMaterial;
UPROPERTY(EditAnywhere, Category = "Wound Parameters", meta = (EditCondition = "bCreateDecal"))
float DecalSize;
UPROPERTY(EditAnywhere, Category = "Wound Parameters", meta = (EditCondition = "bCreateDecal"))
float DecalLifetime;
UPROPERTY(EditAnywhere, Category = "Wound Parameters")
bool bAffectBoneHealth;
UPROPERTY(EditAnywhere, Category = "Wound Parameters", meta = (EditCondition = "bAffectBoneHealth"))
float BoneDamage;
// UEdGraphNode interface
virtual void AllocateDefaultPins() override;
virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override;
// End of UEdGraphNode interface
// UDismembermentGraphNode interface
virtual void CompileNode(class FDismembermentCompiler* Compiler) override;
virtual void ExecuteNode(class FDismembermentExecutor* Executor) override;
// End of UDismembermentGraphNode interface
};

View File

@@ -0,0 +1,84 @@
#pragma once
#include "CoreMinimal.h"
#include "Widgets/SCompoundWidget.h"
#include "Widgets/Views/STableRow.h"
#include "Widgets/Views/STreeView.h"
class FDismembermentGraphEditor;
/**
* Node category structure for the palette
*/
struct FDismembermentGraphNodeCategory
{
// Category name
FText CategoryName;
// Child nodes
TArray<TSharedPtr<FDismembermentGraphNodeCategory>> Children;
// Node classes in this category
TArray<UClass*> NodeClasses;
// Constructor
FDismembermentGraphNodeCategory(const FText& InCategoryName)
: CategoryName(InCategoryName)
{
}
};
/**
* Node palette widget for the dismemberment graph editor
*/
class FLESHEDITOR_API SDismembermentGraphPalette : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SDismembermentGraphPalette) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs, TSharedPtr<FDismembermentGraphEditor> InGraphEditor);
private:
// The graph editor that owns this palette
TWeakPtr<FDismembermentGraphEditor> GraphEditor;
// Root categories
TArray<TSharedPtr<FDismembermentGraphNodeCategory>> RootCategories;
// Tree view widget
TSharedPtr<STreeView<TSharedPtr<FDismembermentGraphNodeCategory>>> CategoriesTreeView;
// Search box widget
TSharedPtr<class SSearchBox> SearchBox;
// Search filter
TSharedPtr<class FDismembermentGraphNodeSearchFilter> SearchFilter;
// Initialize the palette
void InitializePalette();
// Create a category tree item
TSharedRef<ITableRow> OnGenerateCategoryRow(TSharedPtr<FDismembermentGraphNodeCategory> Category, const TSharedRef<STableViewBase>& OwnerTable);
// Get child categories
void OnGetCategoryChildren(TSharedPtr<FDismembermentGraphNodeCategory> Category, TArray<TSharedPtr<FDismembermentGraphNodeCategory>>& OutChildren);
// Category is expanded
void OnCategoryExpansionChanged(TSharedPtr<FDismembermentGraphNodeCategory> Category, bool bExpanded);
// Search text changed
void OnSearchTextChanged(const FText& InFilterText);
// Create a node from the palette
FReply OnCreateNode(UClass* NodeClass, const FVector2D& ScreenPosition, const FVector2D& GraphPosition);
// Handle drag detected
FReply OnDragDetected(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent, UClass* NodeClass);
// Create default categories
void CreateDefaultCategories();
// Add a node class to the palette
void AddNodeClassToCategory(UClass* NodeClass, const FText& CategoryName);
};

View File

@@ -0,0 +1,168 @@
#pragma once
#include "CoreMinimal.h"
#include "EdGraph/EdGraphSchema.h"
#include "DismembermentGraphSchema.generated.h"
class UDismembermentGraphNode;
/**
* Connection response
*/
USTRUCT()
struct FDismembermentGraphConnectionResponse
{
GENERATED_BODY()
// Response type
UPROPERTY()
int32 Response;
// Response text
UPROPERTY()
FText Message;
// Pin names that would be broken
UPROPERTY()
TArray<FText> BreakingPins;
// Constructor
FDismembermentGraphConnectionResponse()
: Response(0)
{
}
};
/**
* Connection response types
*/
struct FDismembermentGraphConnectionResponse_K2
{
enum Type
{
// No error
OK = 0,
// Generic error
ERROR_INCOMPATIBLE = 1,
// Disallowed pin connection
ERROR_DISALLOWED = 2,
// Self-connection not allowed
ERROR_SELF_CONNECTION = 3,
// Cycle not allowed
ERROR_CYCLE = 4
};
};
/**
* Pin type
*/
USTRUCT()
struct FDismembermentGraphPinType
{
GENERATED_BODY()
// Pin category
UPROPERTY()
FName PinCategory;
// Constructor
FDismembermentGraphPinType()
{
}
// Constructor with category
FDismembermentGraphPinType(const FName& InPinCategory)
: PinCategory(InPinCategory)
{
}
// Equality operator
bool operator==(const FDismembermentGraphPinType& Other) const
{
return PinCategory == Other.PinCategory;
}
// Inequality operator
bool operator!=(const FDismembermentGraphPinType& Other) const
{
return !(*this == Other);
}
};
/**
* Dismemberment graph schema
*/
UCLASS()
class FLESHEDITOR_API UDismembermentGraphSchema : public UEdGraphSchema
{
GENERATED_BODY()
public:
// Pin categories
static const FName PC_Exec;
static const FName PC_Bone;
static const FName PC_Cut;
static const FName PC_Blood;
static const FName PC_Physics;
static const FName PC_Organ;
static const FName PC_Wound;
// UEdGraphSchema interface
virtual void GetGraphContextActions(FGraphContextMenuBuilder& ContextMenuBuilder) const override;
virtual void GetContextMenuActions(UToolMenu* Menu, UGraphNodeContextMenuContext* Context) const override;
virtual const FPinConnectionResponse CanCreateConnection(const UEdGraphPin* A, const UEdGraphPin* B) const override;
virtual bool TryCreateConnection(UEdGraphPin* A, UEdGraphPin* B) const override;
virtual bool ShouldHidePinDefaultValue(UEdGraphPin* Pin) const override;
virtual FLinearColor GetPinTypeColor(const FEdGraphPinType& PinType) const override;
virtual void BreakNodeLinks(UEdGraphNode& TargetNode) const override;
virtual void BreakPinLinks(UEdGraphPin& TargetPin, bool bSendsNodeNotification) const override;
virtual void BreakSinglePinLink(UEdGraphPin* SourcePin, UEdGraphPin* TargetPin) const override;
virtual void DroppedAssetsOnGraph(const TArray<FAssetData>& Assets, const FVector2D& GraphPosition, UEdGraph* Graph) const override;
virtual void DroppedAssetsOnNode(const TArray<FAssetData>& Assets, const FVector2D& GraphPosition, UEdGraphNode* Node) const override;
virtual void DroppedAssetsOnPin(const TArray<FAssetData>& Assets, const FVector2D& GraphPosition, UEdGraphPin* Pin) const override;
virtual void GetAssetsNodeHoverMessage(const TArray<FAssetData>& Assets, const UEdGraphNode* HoverNode, FString& OutTooltipText, bool& OutOkIcon) const override;
virtual void GetAssetsPinHoverMessage(const TArray<FAssetData>& Assets, const UEdGraphPin* HoverPin, FString& OutTooltipText, bool& OutOkIcon) const override;
// End of UEdGraphSchema interface
/**
* Check if two pins can be connected
* @param PinA - First pin
* @param PinB - Second pin
* @param OutResponse - Connection response
* @return True if the pins can be connected
*/
bool CanConnectPins(const UEdGraphPin* PinA, const UEdGraphPin* PinB, FDismembermentGraphConnectionResponse& OutResponse) const;
/**
* Check if connecting two pins would create a cycle
* @param PinA - First pin
* @param PinB - Second pin
* @return True if connecting the pins would create a cycle
*/
bool WouldCreateCycle(const UEdGraphPin* PinA, const UEdGraphPin* PinB) const;
/**
* Get the pin type from a pin
* @param Pin - The pin to get the type from
* @return The pin type
*/
static FDismembermentGraphPinType GetPinType(const UEdGraphPin* Pin);
/**
* Get the pin type color
* @param PinType - The pin type
* @return The pin color
*/
static FLinearColor GetPinTypeColor(const FDismembermentGraphPinType& PinType);
/**
* Create a new node
* @param NodeClass - Class of the node to create
* @param ParentGraph - Graph to create the node in
* @param NodePosX - X position of the node
* @param NodePosY - Y position of the node
* @param bSelectNewNode - Whether to select the new node
* @return The created node
*/
static UDismembermentGraphNode* CreateNode(TSubclassOf<UDismembermentGraphNode> NodeClass, UEdGraph* ParentGraph, float NodePosX, float NodePosY, bool bSelectNewNode = true);
};

View File

@@ -0,0 +1,167 @@
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "DismembermentPreviewManager.generated.h"
// Add a log category declaration
DECLARE_LOG_CATEGORY_EXTERN(LogFLESHPreview, Log, All);
class UDismembermentGraphNode;
class USkeletalMeshComponent;
class AActor;
class UWorld;
class UNiagaraComponent;
class UDecalComponent;
class UStaticMeshComponent;
/**
* Preview manager for dismemberment effects
* Handles real-time preview of dismemberment nodes
*/
UCLASS()
class FLESHEDITOR_API UDismembermentPreviewManager : public UObject
{
GENERATED_BODY()
public:
// Constructor
UDismembermentPreviewManager();
/**
* Initialize the preview manager
* @param InWorld - The world to create the preview in
*/
void Initialize(TObjectPtr<UWorld> InWorld);
/**
* Clean up the preview manager
*/
void Cleanup();
/**
* Set the target actor for preview
* @param InActor - The actor to preview on
*/
void SetTargetActor(TObjectPtr<AActor> InActor);
/**
* Preview a node
* @param Node - The node to preview
* @return True if the preview was successful
*/
bool PreviewNode(TObjectPtr<UDismembermentGraphNode> Node);
/**
* Clear the current preview
*/
void ClearPreview();
/**
* Update the preview
* @param DeltaTime - Time since last update
*/
void Tick(float DeltaTime);
/**
* Get the target actor
* @return The target actor
*/
TObjectPtr<AActor> GetTargetActor() const { return TargetActor; }
/**
* Get the target skeletal mesh component
* @return The target skeletal mesh component
*/
TObjectPtr<USkeletalMeshComponent> GetTargetSkeletalMesh() const { return TargetSkeletalMesh; }
private:
// The world to create the preview in
UPROPERTY()
TObjectPtr<UWorld> World;
// The target actor
UPROPERTY()
TObjectPtr<AActor> TargetActor;
// The target skeletal mesh component
UPROPERTY()
TObjectPtr<USkeletalMeshComponent> TargetSkeletalMesh;
// The currently previewed node
UPROPERTY()
TObjectPtr<UDismembermentGraphNode> PreviewedNode;
// Preview components
UPROPERTY()
TArray<TObjectPtr<UNiagaraComponent>> PreviewNiagaraComponents;
UPROPERTY()
TArray<TObjectPtr<UDecalComponent>> PreviewDecalComponents;
UPROPERTY()
TArray<TObjectPtr<UStaticMeshComponent>> PreviewStaticMeshComponents;
// Preview cut plane mesh
UPROPERTY()
TObjectPtr<UStaticMeshComponent> PreviewCutPlaneMesh;
// Preview bone selections
UPROPERTY()
TArray<FName> PreviewBoneSelections;
// Preview cut locations
UPROPERTY()
TArray<FTransform> PreviewCutTransforms;
// Preview blood effect locations
UPROPERTY()
TArray<FTransform> PreviewBloodEffectTransforms;
// Preview organ locations
UPROPERTY()
TArray<FTransform> PreviewOrganTransforms;
// Preview wound locations
UPROPERTY()
TArray<FTransform> PreviewWoundTransforms;
// Find the target skeletal mesh component
bool FindTargetSkeletalMesh();
// Preview a cut node
bool PreviewCutNode(TObjectPtr<class UDismembermentGraphNodeCut> CutNode);
// Preview a bone select node
bool PreviewBoneSelectNode(TObjectPtr<class UDismembermentGraphNodeBoneSelect> BoneSelectNode);
// Preview a blood effect node
bool PreviewBloodEffectNode(TObjectPtr<class UDismembermentGraphNodeBloodEffect> BloodEffectNode);
// Preview a physics node
bool PreviewPhysicsNode(TObjectPtr<class UDismembermentGraphNodePhysics> PhysicsNode);
// Preview an organ node
bool PreviewOrganNode(TObjectPtr<class UDismembermentGraphNodeOrgan> OrganNode);
// Preview a wound node
bool PreviewWoundNode(TObjectPtr<class UDismembermentGraphNodeWound> WoundNode);
// Create a preview cut plane mesh
TObjectPtr<UStaticMeshComponent> CreatePreviewCutPlaneMesh(const FVector& Location, const FVector& Direction, float Width, float Depth, UMaterialInterface* Material);
// Create a preview blood effect
TObjectPtr<UNiagaraComponent> CreatePreviewBloodEffect(const FVector& Location, UNiagaraSystem* BloodEffect, float BloodAmount, float BloodPressure);
// Create a preview blood pool
TObjectPtr<UDecalComponent> CreatePreviewBloodPool(const FVector& Location, float Size, UMaterialInterface* Material);
// Create a preview organ
TObjectPtr<UStaticMeshComponent> CreatePreviewOrgan(UStaticMesh* OrganMesh, UMaterialInterface* OrganMaterial, const FName& AttachBoneName, const FVector& RelativeLocation, const FRotator& RelativeRotation, const FVector& RelativeScale);
// Create a preview wound
TObjectPtr<UDecalComponent> CreatePreviewWound(const FVector& Location, float Size, UMaterialInterface* Material);
// Clear all preview components
void ClearPreviewComponents();
};

View File

@@ -0,0 +1,68 @@
#pragma once
#include "CoreMinimal.h"
#include "SGraphNode.h"
class UDismembermentGraphNode;
/**
* Visual representation of a dismemberment graph node
*/
class FLESHEDITOR_API SDismembermentGraphNode : public SGraphNode
{
public:
SLATE_BEGIN_ARGS(SDismembermentGraphNode) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs, UEdGraphNode* InNode);
// SGraphNode interface
virtual void UpdateGraphNode() override;
virtual void CreatePinWidgets() override;
virtual void AddPin(const TSharedRef<SGraphPin>& PinToAdd) override;
virtual TSharedPtr<SToolTip> GetComplexTooltip() override;
virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual FReply OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual FReply OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual void OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual void OnMouseLeave(const FPointerEvent& MouseEvent) override;
// End of SGraphNode interface
protected:
// Get the dismemberment graph node
UDismembermentGraphNode* GetDismembermentGraphNode() const;
// Get the node title widget
TSharedRef<SWidget> GetNodeTitleWidget();
// Get the node body widget
TSharedRef<SWidget> GetNodeBodyWidget();
// Get the node preview widget
TSharedRef<SWidget> GetNodePreviewWidget();
// Node color
FSlateColor GetNodeColor() const;
// Node title color
FSlateColor GetNodeTitleColor() const;
// Node title text
FText GetNodeTitle() const;
// Node category text
FText GetNodeCategory() const;
// Node description text
FText GetNodeDescription() const;
// Is the node selected
bool IsNodeSelected() const;
// Is the node hovered
bool IsNodeHovered() const;
private:
// Is the node hovered
bool bIsHovered;
};

View File

@@ -0,0 +1,120 @@
#pragma once
#include "CoreMinimal.h"
#include "Widgets/SCompoundWidget.h"
#include "EditorViewportClient.h"
#include "SEditorViewport.h"
class UDismembermentPreviewManager;
class USkeletalMesh;
class AActor;
class FPreviewScene;
class SDismembermentPreviewViewportClient;
/**
* Viewport for previewing dismemberment effects
*/
class FLESHEDITOR_API SDismembermentPreviewViewport : public SEditorViewport
{
public:
SLATE_BEGIN_ARGS(SDismembermentPreviewViewport)
{}
SLATE_END_ARGS()
/**
* Constructs the viewport widget
*/
void Construct(const FArguments& InArgs);
/**
* Destructor
*/
virtual ~SDismembermentPreviewViewport();
/**
* Set the preview manager
* @param InPreviewManager - The preview manager to use
*/
void SetPreviewManager(UDismembermentPreviewManager* InPreviewManager);
/**
* Set the preview skeletal mesh
* @param InSkeletalMesh - The skeletal mesh to preview
*/
void SetPreviewSkeletalMesh(USkeletalMesh* InSkeletalMesh);
/**
* Get the preview actor
* @return The preview actor
*/
AActor* GetPreviewActor() const;
/**
* Refresh the viewport
*/
void RefreshViewport();
protected:
// SEditorViewport interface
virtual TSharedRef<FEditorViewportClient> MakeEditorViewportClient() override;
virtual void OnFocusViewportToSelection() override;
virtual bool IsVisible() const override;
// End of SEditorViewport interface
private:
// The preview scene
TSharedPtr<FPreviewScene> PreviewScene;
// The viewport client
TSharedPtr<SDismembermentPreviewViewportClient> ViewportClient;
// The preview manager
TObjectPtr<UDismembermentPreviewManager> PreviewManager;
// The preview actor
TObjectPtr<AActor> PreviewActor;
// Create the preview actor
void CreatePreviewActor();
// Update the preview actor
void UpdatePreviewActor();
};
/**
* Viewport client for previewing dismemberment effects
*/
class SDismembermentPreviewViewportClient : public FEditorViewportClient
{
public:
/**
* Constructor
* @param InPreviewScene - The preview scene
* @param InViewportWidget - The viewport widget
*/
SDismembermentPreviewViewportClient(FPreviewScene* InPreviewScene, const TWeakPtr<SDismembermentPreviewViewport>& InViewportWidget);
/**
* Destructor
*/
virtual ~SDismembermentPreviewViewportClient();
// FEditorViewportClient interface
virtual void Tick(float DeltaSeconds) override;
virtual void Draw(const FSceneView* View, FPrimitiveDrawInterface* PDI) override;
virtual void DrawCanvas(FViewport& InViewport, FSceneView& View, FCanvas& Canvas) override;
// End of FEditorViewportClient interface
/**
* Set the preview manager
* @param InPreviewManager - The preview manager to use
*/
void SetPreviewManager(UDismembermentPreviewManager* InPreviewManager);
private:
// The viewport widget
TWeakPtr<SDismembermentPreviewViewport> ViewportWidget;
// The preview manager
TObjectPtr<UDismembermentPreviewManager> PreviewManager;
};