#pragma once #include "CoreMinimal.h" #include "UObject/NoExportTypes.h" #include "NiagaraSystem.h" #include "DismembermentCompiler.generated.h" class UDismembermentGraphNode; class UDismembermentGraph; /** * Dismemberment node type enum */ UENUM(BlueprintType) enum class EDismembermentNodeType : uint8 { None UMETA(DisplayName = "None"), Cut UMETA(DisplayName = "Cut"), BloodEffect UMETA(DisplayName = "Blood Effect"), Physics UMETA(DisplayName = "Physics"), Organ UMETA(DisplayName = "Organ"), Wound UMETA(DisplayName = "Wound"), BoneSelection UMETA(DisplayName = "Bone Selection") }; /** * Dismemberment node data structure */ USTRUCT(BlueprintType) struct FDismembermentNodeData { GENERATED_BODY() // Node name UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dismemberment") FName NodeName; // Node type UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dismemberment") EDismembermentNodeType NodeType; // Node parameters UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dismemberment") TMap FloatParameters; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dismemberment") TMap VectorParameters; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dismemberment") TMap RotatorParameters; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dismemberment") TMap BoolParameters; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dismemberment") TMap NameParameters; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dismemberment") TMap ObjectParameters; // Constructor FDismembermentNodeData() : NodeType(EDismembermentNodeType::None) { } // Get float parameter float GetFloatParameter(const FName& ParamName, float DefaultValue = 0.0f) const { if (const float* Value = FloatParameters.Find(ParamName)) { return *Value; } return DefaultValue; } // Get vector parameter FVector GetVectorParameter(const FName& ParamName, const FVector& DefaultValue = FVector::ZeroVector) const { if (const FVector* Value = VectorParameters.Find(ParamName)) { return *Value; } return DefaultValue; } // Get rotator parameter FRotator GetRotatorParameter(const FName& ParamName, const FRotator& DefaultValue = FRotator::ZeroRotator) const { if (const FRotator* Value = RotatorParameters.Find(ParamName)) { return *Value; } return DefaultValue; } // Get bool parameter bool GetBoolParameter(const FName& ParamName, bool DefaultValue = false) const { if (const bool* Value = BoolParameters.Find(ParamName)) { return *Value; } return DefaultValue; } // Get name parameter FName GetNameParameter(const FName& ParamName, const FName& DefaultValue = NAME_None) const { if (const FName* Value = NameParameters.Find(ParamName)) { return *Value; } return DefaultValue; } // Get object parameter UObject* GetObjectParameter(const FName& ParamName, UObject* DefaultValue = nullptr) const { if (UObject* const* Value = ObjectParameters.Find(ParamName)) { return *Value; } return DefaultValue; } }; /** * Compiled node data structure */ USTRUCT() struct FCompiledNodeData { GENERATED_BODY() // Node reference UPROPERTY() TObjectPtr Node; // Input nodes UPROPERTY() TArray InputNodeIndices; // Output nodes UPROPERTY() TArray 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& GetCompiledNodeData() const { return CompiledNodeData; } /** * Get the execution order * @param OutExecutionOrder - Array to fill with node indices in execution order * @return True if execution order is valid */ bool GetExecutionOrder(TArray& OutExecutionOrder) const { if (ExecutionOrder.Num() == 0) { return false; } OutExecutionOrder = ExecutionOrder; return true; } /** * Get node data for a specific node index * @param NodeIndex - Index of the node * @param OutNodeData - Node data to fill * @return True if node data is valid */ bool GetNodeData(int32 NodeIndex, FDismembermentNodeData& OutNodeData) const; /** * 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 Graph; // Compiled node data UPROPERTY() TArray CompiledNodeData; // Execution order UPROPERTY() TArray ExecutionOrder; // Bone selections UPROPERTY() TArray BoneSelections; // Cut operations UPROPERTY() TArray CutOperations; // Cut materials UPROPERTY() TArray> CutMaterials; // Cut widths UPROPERTY() TArray CutWidths; // Cut depths UPROPERTY() TArray CutDepths; // Blood effects UPROPERTY() TArray BloodEffectTransforms; // Blood effect systems UPROPERTY() TArray> BloodEffectSystems; // Blood amounts UPROPERTY() TArray BloodAmounts; // Blood pressures UPROPERTY() TArray BloodPressures; // Create blood pools UPROPERTY() TArray CreateBloodPools; // Blood pool sizes UPROPERTY() TArray BloodPoolSizes; // Blood pool materials UPROPERTY() TArray> BloodPoolMaterials; // Topological sort the nodes bool TopologicalSort(); // Visit node for topological sort void VisitNode(int32 NodeIndex, TArray& Visited, TArray& TempMark, TArray& SortedNodes, bool& bHasCycle); };