Update
This commit is contained in:
@@ -19,6 +19,11 @@
|
|||||||
"Name": "FLESH",
|
"Name": "FLESH",
|
||||||
"Type": "Runtime",
|
"Type": "Runtime",
|
||||||
"LoadingPhase": "Default"
|
"LoadingPhase": "Default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "FLESHEditor",
|
||||||
|
"Type": "Editor",
|
||||||
|
"LoadingPhase": "Default"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"Plugins": [
|
"Plugins": [
|
||||||
@@ -32,7 +37,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Name": "GeometryScripting",
|
"Name": "GeometryScripting",
|
||||||
"Enabled": false
|
"Enabled": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Name": "ChaosCloth",
|
"Name": "ChaosCloth",
|
||||||
@@ -54,5 +59,11 @@
|
|||||||
"Name": "ProceduralMeshComponent",
|
"Name": "ProceduralMeshComponent",
|
||||||
"Enabled": true
|
"Enabled": true
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"Dependencies": [
|
||||||
|
{
|
||||||
|
"Name": "GeometryScripting",
|
||||||
|
"Enabled": true
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
### Real-time Dismemberment Editor Development Guide
|
### Real-time Dismemberment Editor Development Guide
|
||||||
|
|
||||||
#### 引擎版本:UE5.5
|
#### 引擎版本:UE5.5
|
||||||
|
@@ -11,8 +11,8 @@ public class FLESH : ModuleRules
|
|||||||
PublicIncludePaths.AddRange(
|
PublicIncludePaths.AddRange(
|
||||||
new string[] {
|
new string[] {
|
||||||
// ... add public include paths required here ...
|
// ... add public include paths required here ...
|
||||||
"$(EngineDir)/Plugins/Experimental/GeometryScripting/Source/GeometryScriptingCore/Public",
|
// "$(EngineDir)/Plugins/Experimental/GeometryScripting/Source/GeometryScriptingCore/Public",
|
||||||
"$(EngineDir)/Plugins/Experimental/GeometryScripting/Source/GeometryScriptingEditor/Public"
|
// "$(EngineDir)/Plugins/Experimental/GeometryScripting/Source/GeometryScriptingEditor/Public"
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -1,258 +0,0 @@
|
|||||||
#include "BooleanCutTool.h"
|
|
||||||
#include "Engine/StaticMesh.h"
|
|
||||||
#include "Engine/SkeletalMesh.h"
|
|
||||||
#include "ProceduralMeshComponent.h"
|
|
||||||
#include "Materials/MaterialInterface.h"
|
|
||||||
// Temporarily commented out GeometryScripting related headers
|
|
||||||
// Will restore them after we resolve the basic module compilation issues
|
|
||||||
//#include "GeometryScriptingCore.h"
|
|
||||||
//#include "GeometryScript/MeshBooleanFunctions.h"
|
|
||||||
//#include "GeometryScript/MeshPrimitiveFunctions.h"
|
|
||||||
//#include "DynamicMesh/DynamicMesh3.h"
|
|
||||||
//#include "GeometryScript/MeshTransformFunctions.h"
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
UBooleanCutTool::UBooleanCutTool()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform boolean cut on static mesh
|
|
||||||
TArray<UStaticMesh*> UBooleanCutTool::CutStaticMesh(UStaticMesh* TargetMesh, const FCutPlane& CutPlane, bool bCreateCap)
|
|
||||||
{
|
|
||||||
TArray<UStaticMesh*> Result;
|
|
||||||
|
|
||||||
// Check if target mesh is valid
|
|
||||||
if (!TargetMesh)
|
|
||||||
{
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create cut plane mesh
|
|
||||||
UStaticMesh* CutPlaneMesh = CreateCutPlaneMesh(CutPlane);
|
|
||||||
if (!CutPlaneMesh)
|
|
||||||
{
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use GeometryScript to perform boolean cut
|
|
||||||
// Note: This is just a framework, actual implementation requires GeometryScript API
|
|
||||||
|
|
||||||
// Create positive part mesh
|
|
||||||
UStaticMesh* PositiveMesh = NewObject<UStaticMesh>();
|
|
||||||
// TODO: Use GeometryScript to perform boolean difference operation for positive part
|
|
||||||
|
|
||||||
// Create negative part mesh
|
|
||||||
UStaticMesh* NegativeMesh = NewObject<UStaticMesh>();
|
|
||||||
// TODO: Use GeometryScript to perform boolean difference operation for negative part
|
|
||||||
|
|
||||||
// If cap creation is needed
|
|
||||||
if (bCreateCap)
|
|
||||||
{
|
|
||||||
// TODO: Create cap for positive and negative parts
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add to result array
|
|
||||||
Result.Add(PositiveMesh);
|
|
||||||
Result.Add(NegativeMesh);
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform boolean cut on skeletal mesh
|
|
||||||
TArray<USkeletalMesh*> UBooleanCutTool::CutSkeletalMesh(USkeletalMesh* TargetMesh, const FCutPlane& CutPlane, FName BoneName, bool bCreateCap)
|
|
||||||
{
|
|
||||||
TArray<USkeletalMesh*> Result;
|
|
||||||
|
|
||||||
// Check if target mesh is valid
|
|
||||||
if (!TargetMesh)
|
|
||||||
{
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create cut plane mesh
|
|
||||||
UStaticMesh* CutPlaneMesh = CreateCutPlaneMesh(CutPlane);
|
|
||||||
if (!CutPlaneMesh)
|
|
||||||
{
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use GeometryScript to perform boolean cut
|
|
||||||
// Note: This is just a framework, actual implementation requires GeometryScript API
|
|
||||||
|
|
||||||
// If bone name is specified, only cut the part influenced by the bone
|
|
||||||
if (BoneName != NAME_None)
|
|
||||||
{
|
|
||||||
// TODO: Get vertices influenced by the bone, only cut these vertices
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create positive part skeletal mesh
|
|
||||||
USkeletalMesh* PositiveMesh = NewObject<USkeletalMesh>();
|
|
||||||
// TODO: Use GeometryScript to perform boolean difference operation for positive part
|
|
||||||
|
|
||||||
// Create negative part skeletal mesh
|
|
||||||
USkeletalMesh* NegativeMesh = NewObject<USkeletalMesh>();
|
|
||||||
// TODO: Use GeometryScript to perform boolean difference operation for negative part
|
|
||||||
|
|
||||||
// If cap creation is needed
|
|
||||||
if (bCreateCap)
|
|
||||||
{
|
|
||||||
// TODO: Create cap for positive and negative parts
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add to result array
|
|
||||||
Result.Add(PositiveMesh);
|
|
||||||
Result.Add(NegativeMesh);
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform boolean cut on procedural mesh
|
|
||||||
TArray<UProceduralMeshComponent*> UBooleanCutTool::CutProceduralMesh(UProceduralMeshComponent* TargetMesh, const FCutPlane& CutPlane, bool bCreateCap)
|
|
||||||
{
|
|
||||||
TArray<UProceduralMeshComponent*> Result;
|
|
||||||
|
|
||||||
// Check if target mesh is valid
|
|
||||||
if (!TargetMesh)
|
|
||||||
{
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get mesh data
|
|
||||||
TArray<FVector> Vertices;
|
|
||||||
TArray<int32> Triangles;
|
|
||||||
TArray<FVector> Normals;
|
|
||||||
TArray<FVector2D> UVs;
|
|
||||||
TArray<FColor> VertexColors;
|
|
||||||
TArray<FProcMeshTangent> Tangents;
|
|
||||||
|
|
||||||
// In UE5.5.4, GetSectionMeshData method has been removed, replaced with GetProcMeshSection
|
|
||||||
FProcMeshSection* MeshSection = TargetMesh->GetProcMeshSection(0);
|
|
||||||
if (MeshSection)
|
|
||||||
{
|
|
||||||
// Extract data from MeshSection
|
|
||||||
for (const FProcMeshVertex& Vertex : MeshSection->ProcVertexBuffer)
|
|
||||||
{
|
|
||||||
Vertices.Add(Vertex.Position);
|
|
||||||
Normals.Add(Vertex.Normal);
|
|
||||||
UVs.Add(Vertex.UV0);
|
|
||||||
VertexColors.Add(Vertex.Color);
|
|
||||||
Tangents.Add(Vertex.Tangent);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert indices
|
|
||||||
for (uint32 Index : MeshSection->ProcIndexBuffer)
|
|
||||||
{
|
|
||||||
Triangles.Add(static_cast<int32>(Index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate intersection points between cut plane and mesh
|
|
||||||
TArray<FVector> IntersectionPoints = CalculateIntersectionPoints(Vertices, Triangles, CutPlane);
|
|
||||||
|
|
||||||
// Create positive part procedural mesh
|
|
||||||
UProceduralMeshComponent* PositiveMesh = NewObject<UProceduralMeshComponent>(TargetMesh->GetOwner());
|
|
||||||
PositiveMesh->RegisterComponent();
|
|
||||||
|
|
||||||
// Create negative part procedural mesh
|
|
||||||
UProceduralMeshComponent* NegativeMesh = NewObject<UProceduralMeshComponent>(TargetMesh->GetOwner());
|
|
||||||
NegativeMesh->RegisterComponent();
|
|
||||||
|
|
||||||
// Split mesh
|
|
||||||
TArray<FVector> PositiveVertices;
|
|
||||||
TArray<int32> PositiveTriangles;
|
|
||||||
TArray<FVector> PositiveNormals;
|
|
||||||
TArray<FVector2D> PositiveUVs;
|
|
||||||
TArray<FColor> PositiveVertexColors;
|
|
||||||
TArray<FProcMeshTangent> PositiveTangents;
|
|
||||||
|
|
||||||
TArray<FVector> NegativeVertices;
|
|
||||||
TArray<int32> NegativeTriangles;
|
|
||||||
TArray<FVector> NegativeNormals;
|
|
||||||
TArray<FVector2D> NegativeUVs;
|
|
||||||
TArray<FColor> NegativeVertexColors;
|
|
||||||
TArray<FProcMeshTangent> NegativeTangents;
|
|
||||||
|
|
||||||
// TODO: Split mesh data based on cut plane
|
|
||||||
|
|
||||||
// Create positive part mesh
|
|
||||||
PositiveMesh->CreateMeshSection(0, PositiveVertices, PositiveTriangles, PositiveNormals, PositiveUVs, PositiveVertexColors, PositiveTangents, true);
|
|
||||||
|
|
||||||
// Create negative part mesh
|
|
||||||
NegativeMesh->CreateMeshSection(0, NegativeVertices, NegativeTriangles, NegativeNormals, NegativeUVs, NegativeVertexColors, NegativeTangents, true);
|
|
||||||
|
|
||||||
// If cap creation is needed
|
|
||||||
if (bCreateCap)
|
|
||||||
{
|
|
||||||
CreateCapMesh(IntersectionPoints, CutPlane, PositiveMesh);
|
|
||||||
CreateCapMesh(IntersectionPoints, CutPlane, NegativeMesh);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set material
|
|
||||||
if (CutMaterial)
|
|
||||||
{
|
|
||||||
PositiveMesh->SetMaterial(0, TargetMesh->GetMaterial(0));
|
|
||||||
PositiveMesh->SetMaterial(1, CutMaterial);
|
|
||||||
|
|
||||||
NegativeMesh->SetMaterial(0, TargetMesh->GetMaterial(0));
|
|
||||||
NegativeMesh->SetMaterial(1, CutMaterial);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add to result array
|
|
||||||
Result.Add(PositiveMesh);
|
|
||||||
Result.Add(NegativeMesh);
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create cut plane mesh
|
|
||||||
UStaticMesh* UBooleanCutTool::CreateCutPlaneMesh(const FCutPlane& CutPlane)
|
|
||||||
{
|
|
||||||
// Create a plane mesh
|
|
||||||
UStaticMesh* PlaneMesh = NewObject<UStaticMesh>();
|
|
||||||
|
|
||||||
// TODO: Use GeometryScript to create plane mesh
|
|
||||||
// Note: This is just a framework, actual implementation requires GeometryScript API
|
|
||||||
|
|
||||||
return PlaneMesh;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set cut material
|
|
||||||
void UBooleanCutTool::SetCutMaterial(UMaterialInterface* Material)
|
|
||||||
{
|
|
||||||
CutMaterial = Material;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get cut material
|
|
||||||
UMaterialInterface* UBooleanCutTool::GetCutMaterial() const
|
|
||||||
{
|
|
||||||
return CutMaterial;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate intersection points between cut plane and mesh
|
|
||||||
TArray<FVector> UBooleanCutTool::CalculateIntersectionPoints(const TArray<FVector>& Vertices, const TArray<int32>& Indices, const FCutPlane& CutPlane)
|
|
||||||
{
|
|
||||||
// Simplify the implementation of this method to resolve compilation issues
|
|
||||||
TArray<FVector> IntersectionPoints;
|
|
||||||
|
|
||||||
// TODO: Restore the complete implementation after resolving GeometryScripting issues
|
|
||||||
|
|
||||||
return IntersectionPoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create cap mesh
|
|
||||||
void UBooleanCutTool::CreateCapMesh(const TArray<FVector>& IntersectionPoints, const FCutPlane& CutPlane, UProceduralMeshComponent* TargetMesh)
|
|
||||||
{
|
|
||||||
// Check if there are enough intersection points
|
|
||||||
if (IntersectionPoints.Num() < 3)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Create cap mesh using intersection points
|
|
||||||
// Note: This is just a framework, actual implementation requires more complex algorithm
|
|
||||||
|
|
||||||
// 1. Project intersection points onto cut plane
|
|
||||||
// 2. Triangulate projected points
|
|
||||||
// 3. Create cap mesh
|
|
||||||
// 4. Add to target mesh
|
|
||||||
}
|
|
@@ -3,8 +3,8 @@
|
|||||||
#include "Engine/SkeletalMesh.h"
|
#include "Engine/SkeletalMesh.h"
|
||||||
#include "ProceduralMeshComponent.h"
|
#include "ProceduralMeshComponent.h"
|
||||||
#include "Materials/MaterialInterface.h"
|
#include "Materials/MaterialInterface.h"
|
||||||
// 暂时注释掉 GeometryScripting 相关头文件
|
// Temporarily commented out GeometryScripting related headers
|
||||||
// 当我们解决了基础模块的编译问题后再恢复
|
// Will restore them after we resolve the basic module compilation issues
|
||||||
//#include "GeometryScriptingCore.h"
|
//#include "GeometryScriptingCore.h"
|
||||||
//#include "GeometryScript/MeshBooleanFunctions.h"
|
//#include "GeometryScript/MeshBooleanFunctions.h"
|
||||||
//#include "GeometryScript/MeshPrimitiveFunctions.h"
|
//#include "GeometryScript/MeshPrimitiveFunctions.h"
|
||||||
@@ -125,11 +125,11 @@ TArray<UProceduralMeshComponent*> UBooleanCutTool::CutProceduralMesh(UProcedural
|
|||||||
TArray<FColor> VertexColors;
|
TArray<FColor> VertexColors;
|
||||||
TArray<FProcMeshTangent> Tangents;
|
TArray<FProcMeshTangent> Tangents;
|
||||||
|
|
||||||
// 在 UE5.5.4 中,GetSectionMeshData 方法已不存在,改为使用 GetProcMeshSection 方法
|
// In UE5.5.4, GetSectionMeshData method has been removed, replaced with GetProcMeshSection
|
||||||
FProcMeshSection* MeshSection = TargetMesh->GetProcMeshSection(0);
|
FProcMeshSection* MeshSection = TargetMesh->GetProcMeshSection(0);
|
||||||
if (MeshSection)
|
if (MeshSection)
|
||||||
{
|
{
|
||||||
// 从 MeshSection 中提取数据
|
// Extract data from MeshSection
|
||||||
for (const FProcMeshVertex& Vertex : MeshSection->ProcVertexBuffer)
|
for (const FProcMeshVertex& Vertex : MeshSection->ProcVertexBuffer)
|
||||||
{
|
{
|
||||||
Vertices.Add(Vertex.Position);
|
Vertices.Add(Vertex.Position);
|
||||||
@@ -139,7 +139,7 @@ TArray<UProceduralMeshComponent*> UBooleanCutTool::CutProceduralMesh(UProcedural
|
|||||||
Tangents.Add(Vertex.Tangent);
|
Tangents.Add(Vertex.Tangent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 转换索引
|
// Convert indices
|
||||||
for (uint32 Index : MeshSection->ProcIndexBuffer)
|
for (uint32 Index : MeshSection->ProcIndexBuffer)
|
||||||
{
|
{
|
||||||
Triangles.Add(static_cast<int32>(Index));
|
Triangles.Add(static_cast<int32>(Index));
|
||||||
@@ -231,10 +231,10 @@ UMaterialInterface* UBooleanCutTool::GetCutMaterial() const
|
|||||||
// Calculate intersection points between cut plane and mesh
|
// Calculate intersection points between cut plane and mesh
|
||||||
TArray<FVector> UBooleanCutTool::CalculateIntersectionPoints(const TArray<FVector>& Vertices, const TArray<int32>& Indices, const FCutPlane& CutPlane)
|
TArray<FVector> UBooleanCutTool::CalculateIntersectionPoints(const TArray<FVector>& Vertices, const TArray<int32>& Indices, const FCutPlane& CutPlane)
|
||||||
{
|
{
|
||||||
// 暂时简化该方法的实现,以解决编译问题
|
// Simplify the implementation of this method to resolve compilation issues
|
||||||
TArray<FVector> IntersectionPoints;
|
TArray<FVector> IntersectionPoints;
|
||||||
|
|
||||||
// TODO: 当我们解决了 GeometryScripting 相关的问题后再恢复完整实现
|
// TODO: Restore the complete implementation after resolving GeometryScripting issues
|
||||||
|
|
||||||
return IntersectionPoints;
|
return IntersectionPoints;
|
||||||
}
|
}
|
||||||
|
@@ -1,92 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
|
||||||
#include "GameFramework/Actor.h"
|
|
||||||
#include "BloodPool.generated.h"
|
|
||||||
|
|
||||||
// Forward declarations
|
|
||||||
class UBoxComponent;
|
|
||||||
class UDecalComponent;
|
|
||||||
class UMaterialInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Blood pool actor class, used to create blood pools on surfaces
|
|
||||||
*/
|
|
||||||
UCLASS()
|
|
||||||
class FLESH_API ABloodPool : public AActor
|
|
||||||
{
|
|
||||||
GENERATED_BODY()
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Sets default values for this actor's properties
|
|
||||||
ABloodPool();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Called when the game starts
|
|
||||||
virtual void BeginPlay() override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Set the blood pool size
|
|
||||||
* @param NewSize - New size for the blood pool
|
|
||||||
*/
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "FLESH|Blood")
|
|
||||||
void SetPoolSize(float NewSize);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the blood pool color
|
|
||||||
* @param NewColor - New color for the blood pool
|
|
||||||
*/
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "FLESH|Blood")
|
|
||||||
void SetPoolColor(const FLinearColor& NewColor);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start blood pool expansion
|
|
||||||
* @param InExpansionRate - Rate of expansion
|
|
||||||
* @param MaxSize - Maximum size
|
|
||||||
*/
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "FLESH|Blood")
|
|
||||||
void StartExpansion(float InExpansionRate = 1.0f, float MaxSize = 3.0f);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Collision component for surface detection
|
|
||||||
UPROPERTY(VisibleAnywhere, Category = "Components")
|
|
||||||
TObjectPtr<UBoxComponent> Collision;
|
|
||||||
|
|
||||||
// Decal component for rendering the blood pool
|
|
||||||
UPROPERTY(VisibleAnywhere, Category = "Components")
|
|
||||||
TObjectPtr<UDecalComponent> Decal;
|
|
||||||
|
|
||||||
// Blood pool decal material
|
|
||||||
UPROPERTY(EditAnywhere, Category = "Appearance")
|
|
||||||
TObjectPtr<UMaterialInterface> DecalMaterial;
|
|
||||||
|
|
||||||
// Current blood pool size
|
|
||||||
UPROPERTY(EditAnywhere, Category = "Appearance")
|
|
||||||
float PoolSize = 1.0f;
|
|
||||||
|
|
||||||
// Blood pool color
|
|
||||||
UPROPERTY(EditAnywhere, Category = "Appearance")
|
|
||||||
FLinearColor PoolColor = FLinearColor::Red;
|
|
||||||
|
|
||||||
// Expansion rate
|
|
||||||
UPROPERTY(EditAnywhere, Category = "Expansion")
|
|
||||||
float ExpansionRate = 0.5f;
|
|
||||||
|
|
||||||
// Maximum blood pool size
|
|
||||||
UPROPERTY(EditAnywhere, Category = "Expansion")
|
|
||||||
float MaxPoolSize = 2.0f;
|
|
||||||
|
|
||||||
// Whether the pool is expanding
|
|
||||||
UPROPERTY()
|
|
||||||
bool bIsExpanding = false;
|
|
||||||
|
|
||||||
// Blood pool expansion timer handle
|
|
||||||
FTimerHandle ExpansionTimerHandle;
|
|
||||||
|
|
||||||
// Internal function to update the blood pool size
|
|
||||||
void UpdatePoolSize();
|
|
||||||
|
|
||||||
// Internal function to expand the blood pool
|
|
||||||
void ExpandPool();
|
|
||||||
};
|
|
@@ -6,6 +6,8 @@
|
|||||||
// Forward declaration
|
// Forward declaration
|
||||||
class UDismembermentGraphBase;
|
class UDismembermentGraphBase;
|
||||||
|
|
||||||
|
#include "DismembermentGraph/DismembermentGraphBase.h"
|
||||||
|
|
||||||
#include "DismembermentGraphAsset.generated.h"
|
#include "DismembermentGraphAsset.generated.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -22,7 +24,7 @@ public:
|
|||||||
|
|
||||||
// The graph owned by this asset
|
// The graph owned by this asset
|
||||||
UPROPERTY()
|
UPROPERTY()
|
||||||
class UDismembermentGraphBase* Graph;
|
TObjectPtr<class UDismembermentGraphBase> Graph;
|
||||||
|
|
||||||
// Compile the graph into executable logic
|
// Compile the graph into executable logic
|
||||||
UFUNCTION(BlueprintCallable, Category = "FLESH|Dismemberment")
|
UFUNCTION(BlueprintCallable, Category = "FLESH|Dismemberment")
|
||||||
|
@@ -5,10 +5,10 @@
|
|||||||
#include "DismembermentGraphBase.generated.h"
|
#include "DismembermentGraphBase.generated.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dismemberment graph base class
|
* Dismemberment graph base class (Rewritten)
|
||||||
* Used for visual programming of dismemberment logic
|
* Provides extensible, multi-layer, and serializable node graph for procedural dismemberment logic
|
||||||
*/
|
*/
|
||||||
UCLASS()
|
UCLASS(BlueprintType)
|
||||||
class FLESH_API UDismembermentGraphBase : public UObject
|
class FLESH_API UDismembermentGraphBase : public UObject
|
||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
@@ -16,23 +16,35 @@ class FLESH_API UDismembermentGraphBase : public UObject
|
|||||||
public:
|
public:
|
||||||
UDismembermentGraphBase();
|
UDismembermentGraphBase();
|
||||||
|
|
||||||
// Graph nodes
|
// All nodes in the graph (supports multiple node types)
|
||||||
UPROPERTY()
|
UPROPERTY(VisibleAnywhere, Instanced, Category = "Graph")
|
||||||
TArray<class UEdGraphNode*> Nodes;
|
TArray<TObjectPtr<class UEdGraphNode>> Nodes;
|
||||||
|
|
||||||
// Compilation status
|
// Compilation status
|
||||||
UPROPERTY()
|
UPROPERTY(VisibleAnywhere, Category = "Graph")
|
||||||
bool bCompiled;
|
bool bCompiled;
|
||||||
|
|
||||||
// Clear graph
|
// Multi-layer support: each layer can represent bone, organ, skin, etc.
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Graph|Layers")
|
||||||
|
TArray<FName> Layers;
|
||||||
|
|
||||||
|
// Patch data for each layer (future extensibility)
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Graph|Patch")
|
||||||
|
TMap<FName, FString> LayerPatchData;
|
||||||
|
|
||||||
|
// Clear all nodes and reset graph
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Graph")
|
||||||
void ClearGraph();
|
void ClearGraph();
|
||||||
|
|
||||||
// Add node
|
// Add a node to the graph
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Graph")
|
||||||
class UEdGraphNode* AddNode(TSubclassOf<class UEdGraphNode> NodeClass, const FVector2D& Position);
|
class UEdGraphNode* AddNode(TSubclassOf<class UEdGraphNode> NodeClass, const FVector2D& Position);
|
||||||
|
|
||||||
// Remove node
|
// Remove a node from the graph
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Graph")
|
||||||
void RemoveNode(class UEdGraphNode* Node);
|
void RemoveNode(class UEdGraphNode* Node);
|
||||||
|
|
||||||
// Create connection
|
// Serialize graph to string (for asset versioning, debugging, etc.)
|
||||||
void CreateConnection(class UEdGraphPin* A, class UEdGraphPin* B);
|
UFUNCTION(BlueprintCallable, Category = "Graph")
|
||||||
|
FString SerializeGraph() const;
|
||||||
};
|
};
|
||||||
|
84
Source/FLESH/Public/Gore/BloodPool.h
Normal file
84
Source/FLESH/Public/Gore/BloodPool.h
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
// @ 2025, Copyright Virtuos Games. All rights reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "GameFramework/Actor.h"
|
||||||
|
#include "NiagaraComponent.h"
|
||||||
|
#include "NiagaraSystem.h"
|
||||||
|
#include "BloodPool.generated.h"
|
||||||
|
|
||||||
|
class UNiagaraSystem;
|
||||||
|
class UNiagaraComponent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blood pool actor that creates a decal and blood burst effect
|
||||||
|
* Used to simulate blood pooling under dismembered body parts
|
||||||
|
*/
|
||||||
|
UCLASS(Blueprintable)
|
||||||
|
class FLESH_API ABloodPool : public AActor
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Sets default values for this actor's properties
|
||||||
|
ABloodPool();
|
||||||
|
|
||||||
|
virtual void BeginPlay() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create blood pool
|
||||||
|
* @param World - World object
|
||||||
|
* @param Location - Blood pool location
|
||||||
|
* @param Scale - Blood pool size
|
||||||
|
* @param BloodPoolTemplate - Blood pool template class
|
||||||
|
* @return Created blood pool Actor
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Dismemberment|Gore", meta = (WorldContext = "World"))
|
||||||
|
static ABloodPool* CreateBloodPool(UWorld* World, const FVector& Location, float Scale = 1.0f, TSubclassOf<ABloodPool> BloodPoolTemplate = nullptr);
|
||||||
|
|
||||||
|
// Components
|
||||||
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components")
|
||||||
|
TObjectPtr<class UBoxComponent> Collision;
|
||||||
|
|
||||||
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components")
|
||||||
|
TObjectPtr<class UDecalComponent> Decal;
|
||||||
|
|
||||||
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components")
|
||||||
|
TObjectPtr<UNiagaraComponent> BloodBurstEffect;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
FVector RemapSizeForDecal(const FVector In) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Visual Effects
|
||||||
|
/** The blood decal material to use */
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Dismemberment|Visual Effects", meta=(DisplayPriority=1))
|
||||||
|
TObjectPtr<UMaterialInterface> DecalMaterial = nullptr;
|
||||||
|
|
||||||
|
/** The blood burst Niagara system to use */
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Dismemberment|Visual Effects", meta=(DisplayPriority=2))
|
||||||
|
TObjectPtr<UNiagaraSystem> BloodBurstSystem;
|
||||||
|
|
||||||
|
// Timing Parameters
|
||||||
|
/** Adds a delay before the blood decal appears */
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Dismemberment|Timing", meta=(ExposeOnSpawn="true", ClampMin="0.0", UIMin="0.0", DisplayPriority=1))
|
||||||
|
float StartDelay = 0.f;
|
||||||
|
|
||||||
|
/** The lifetime of the blood before it dries up and fades away */
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Dismemberment|Timing", meta=(ExposeOnSpawn="true", ClampMin="1.0", UIMin="1.0", DisplayPriority=2))
|
||||||
|
float MaxLifetime = 60.f;
|
||||||
|
|
||||||
|
/** Time it takes to interpolate to the new size and location */
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Dismemberment|Timing", meta=(ExposeOnSpawn="true", ClampMin="0.0", UIMin="0.0", DisplayPriority=3))
|
||||||
|
float InterpTime = 0.3f;
|
||||||
|
|
||||||
|
// Appearance Parameters
|
||||||
|
/** Size of the blood decal */
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Dismemberment|Appearance", meta=(ExposeOnSpawn="true", DisplayPriority=1))
|
||||||
|
FVector DecalSize = FVector(100);
|
||||||
|
|
||||||
|
/** Relative rotation of the decal */
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Dismemberment|Appearance", meta=(ExposeOnSpawn="true", DisplayPriority=2))
|
||||||
|
FRotator DecalRotation = FRotator(0);
|
||||||
|
};
|
@@ -11,20 +11,51 @@
|
|||||||
#include "Modules/ModuleManager.h"
|
#include "Modules/ModuleManager.h"
|
||||||
#include "GraphEditorActions.h"
|
#include "GraphEditorActions.h"
|
||||||
#include "AssetTypeActions_Base.h"
|
#include "AssetTypeActions_Base.h"
|
||||||
|
#include "DismembermentGraph/DismembermentGraphSchema.h"
|
||||||
|
#include "DismembermentGraph/SDismembermentGraphNode.h"
|
||||||
|
#include "DismembermentGraph/DismembermentGraphEditorFactory.h"
|
||||||
|
#include "DismembermentGraph/DismembermentGraphPalette.h"
|
||||||
|
#include "DismembermentGraph/DismembermentGraphNodeFactory.h"
|
||||||
|
#include "Styling/AppStyle.h"
|
||||||
|
#include "GraphEditorSettings.h"
|
||||||
|
#include "EdGraph/EdGraphSchema.h"
|
||||||
|
|
||||||
#define LOCTEXT_NAMESPACE "DismembermentGraphEditor"
|
#define LOCTEXT_NAMESPACE "DismembermentGraphEditor"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dismemberment graph schema actions factory
|
* Dismemberment graph asset type actions
|
||||||
*/
|
*/
|
||||||
class FDismembermentGraphSchemaActionMenuBuilder : public FGraphSchemaActionMenuBuilder
|
class FDismembermentGraphAssetTypeActions : public FAssetTypeActions_Base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Constructor
|
// Constructor
|
||||||
FDismembermentGraphSchemaActionMenuBuilder(const UEdGraphSchema* InSchema)
|
FDismembermentGraphAssetTypeActions(EAssetTypeCategories::Type InAssetCategory)
|
||||||
: FGraphSchemaActionMenuBuilder(InSchema)
|
: AssetCategory(InAssetCategory)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FAssetTypeActions_Base interface
|
||||||
|
virtual FText GetName() const override { return LOCTEXT("DismembermentGraphAssetName", "Dismemberment Graph"); }
|
||||||
|
virtual FColor GetTypeColor() const override { return FColor(255, 64, 64); }
|
||||||
|
virtual UClass* GetSupportedClass() const override { return UDismembermentGraphAsset::StaticClass(); }
|
||||||
|
virtual uint32 GetCategories() override { return AssetCategory; }
|
||||||
|
virtual bool HasActions(const TArray<UObject*>& InObjects) const override { return false; }
|
||||||
|
virtual void OpenAssetEditor(const TArray<UObject*>& InObjects, TSharedPtr<IToolkitHost> EditWithinLevelEditor) override
|
||||||
|
{
|
||||||
|
for (UObject* Object : InObjects)
|
||||||
|
{
|
||||||
|
if (UDismembermentGraphAsset* GraphAsset = Cast<UDismembermentGraphAsset>(Object))
|
||||||
|
{
|
||||||
|
TSharedRef<FDismembermentGraphEditor> NewEditor = MakeShareable(new FDismembermentGraphEditor());
|
||||||
|
NewEditor->InitDismembermentGraphEditor(EToolkitMode::Standalone, EditWithinLevelEditor, GraphAsset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// End of FAssetTypeActions_Base interface
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Asset category
|
||||||
|
EAssetTypeCategories::Type AssetCategory;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,7 +74,7 @@ public:
|
|||||||
DismembermentGraphAssetCategoryBit = AssetTools.RegisterAdvancedAssetCategory(FName(TEXT("Dismemberment")), LOCTEXT("DismembermentGraphAssetCategory", "Dismemberment"));
|
DismembermentGraphAssetCategoryBit = AssetTools.RegisterAdvancedAssetCategory(FName(TEXT("Dismemberment")), LOCTEXT("DismembermentGraphAssetCategory", "Dismemberment"));
|
||||||
|
|
||||||
// Register asset type actions
|
// Register asset type actions
|
||||||
TSharedPtr<IAssetTypeActions> Action = MakeShareable(new FDismembermentGraphAssetTypeActions(DismembermentGraphAssetCategoryBit));
|
TSharedRef<IAssetTypeActions> Action = MakeShareable(new FDismembermentGraphAssetTypeActions(DismembermentGraphAssetCategoryBit));
|
||||||
AssetTools.RegisterAssetTypeActions(Action);
|
AssetTools.RegisterAssetTypeActions(Action);
|
||||||
RegisteredAssetTypeActions.Add(Action);
|
RegisteredAssetTypeActions.Add(Action);
|
||||||
|
|
||||||
@@ -100,84 +131,7 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
// Comment out this line to avoid module redefinition
|
||||||
* Dismemberment graph asset type actions
|
// IMPLEMENT_MODULE(FDismembermentGraphEditorModule, FLESHEditor)
|
||||||
*/
|
|
||||||
class FDismembermentGraphAssetTypeActions : public FAssetTypeActions_Base
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Constructor
|
|
||||||
FDismembermentGraphAssetTypeActions(EAssetTypeCategories::Type InAssetCategory)
|
|
||||||
: AssetCategory(InAssetCategory)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// FAssetTypeActions_Base interface
|
|
||||||
virtual FText GetName() const override { return LOCTEXT("DismembermentGraphAssetName", "Dismemberment Graph"); }
|
|
||||||
virtual FColor GetTypeColor() const override { return FColor(255, 64, 64); }
|
|
||||||
virtual UClass* GetSupportedClass() const override { return UDismembermentGraphAsset::StaticClass(); }
|
|
||||||
virtual uint32 GetCategories() override { return AssetCategory; }
|
|
||||||
virtual bool HasActions(const TArray<UObject*>& InObjects) const override { return false; }
|
|
||||||
virtual void OpenAssetEditor(const TArray<UObject*>& InObjects, TSharedPtr<IToolkitHost> EditWithinLevelEditor) override
|
|
||||||
{
|
|
||||||
for (UObject* Object : InObjects)
|
|
||||||
{
|
|
||||||
if (UDismembermentGraphAsset* GraphAsset = Cast<UDismembermentGraphAsset>(Object))
|
|
||||||
{
|
|
||||||
TSharedRef<FDismembermentGraphEditor> NewEditor = MakeShareable(new FDismembermentGraphEditor());
|
|
||||||
NewEditor->InitDismembermentGraphEditor(EToolkitMode::Standalone, EditWithinLevelEditor, GraphAsset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// End of FAssetTypeActions_Base interface
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Asset category
|
|
||||||
EAssetTypeCategories::Type AssetCategory;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dismemberment graph node factory
|
|
||||||
*/
|
|
||||||
class FDismembermentGraphNodeFactory : public FGraphPanelNodeFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Constructor
|
|
||||||
FDismembermentGraphNodeFactory()
|
|
||||||
: NodeClass(nullptr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
FDismembermentGraphNodeFactory(UClass* InNodeClass, const FText& InDisplayName, const FText& InTooltip)
|
|
||||||
: NodeClass(InNodeClass)
|
|
||||||
, DisplayName(InDisplayName)
|
|
||||||
, Tooltip(InTooltip)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// FGraphPanelNodeFactory interface
|
|
||||||
virtual TSharedPtr<SGraphNode> CreateNode(UEdGraphNode* Node) const override
|
|
||||||
{
|
|
||||||
if (NodeClass && Node->IsA(NodeClass))
|
|
||||||
{
|
|
||||||
return SNew(SDismembermentGraphNode, Node);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
// End of FGraphPanelNodeFactory interface
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Node class
|
|
||||||
UClass* NodeClass;
|
|
||||||
|
|
||||||
// Display name
|
|
||||||
FText DisplayName;
|
|
||||||
|
|
||||||
// Tooltip
|
|
||||||
FText Tooltip;
|
|
||||||
};
|
|
||||||
|
|
||||||
IMPLEMENT_MODULE(FDismembermentGraphEditorModule, FLESHEditor)
|
|
||||||
|
|
||||||
#undef LOCTEXT_NAMESPACE
|
#undef LOCTEXT_NAMESPACE
|
||||||
|
@@ -84,7 +84,7 @@ void UDismembermentGraphSchema::GetContextMenuActions(UToolMenu* Menu, UGraphNod
|
|||||||
FUIAction(
|
FUIAction(
|
||||||
FExecuteAction::CreateLambda([Context]()
|
FExecuteAction::CreateLambda([Context]()
|
||||||
{
|
{
|
||||||
if (UDismembermentGraphNode* Node = Cast<UDismembermentGraphNode>(Context->Node))
|
if (const UDismembermentGraphNode* Node = Cast<UDismembermentGraphNode>(Context->Node))
|
||||||
{
|
{
|
||||||
// TODO: Implement node preview
|
// TODO: Implement node preview
|
||||||
}
|
}
|
||||||
@@ -100,7 +100,7 @@ void UDismembermentGraphSchema::GetContextMenuActions(UToolMenu* Menu, UGraphNod
|
|||||||
// Add general graph actions
|
// Add general graph actions
|
||||||
{
|
{
|
||||||
FToolMenuSection& Section = Menu->AddSection("DismembermentGraphActions", LOCTEXT("GraphActionsMenuHeader", "Graph Actions"));
|
FToolMenuSection& Section = Menu->AddSection("DismembermentGraphActions", LOCTEXT("GraphActionsMenuHeader", "Graph Actions"));
|
||||||
Section.AddMenuEntry(FGraphEditorCommands::Get().SelectAllNodes);
|
Section.AddMenuEntry(FGenericCommands::Get().SelectAll);
|
||||||
Section.AddMenuEntry(
|
Section.AddMenuEntry(
|
||||||
"ArrangeNodes",
|
"ArrangeNodes",
|
||||||
LOCTEXT("ArrangeNodes", "Arrange Nodes"),
|
LOCTEXT("ArrangeNodes", "Arrange Nodes"),
|
||||||
|
@@ -23,7 +23,7 @@ void SDismembermentGraphNode::UpdateGraphNode()
|
|||||||
ContentScale.Bind(this, &SGraphNode::GetContentScale);
|
ContentScale.Bind(this, &SGraphNode::GetContentScale);
|
||||||
LeftNodeBox.Reset();
|
LeftNodeBox.Reset();
|
||||||
RightNodeBox.Reset();
|
RightNodeBox.Reset();
|
||||||
OutputPinBox.Reset();
|
// OutputPinBox.Reset(); // Comment out this line because OutputPinBox is not defined
|
||||||
|
|
||||||
// Setup the node title
|
// Setup the node title
|
||||||
TSharedPtr<SNodeTitle> NodeTitle = SNew(SNodeTitle, GraphNode);
|
TSharedPtr<SNodeTitle> NodeTitle = SNew(SNodeTitle, GraphNode);
|
||||||
@@ -274,7 +274,7 @@ TSharedRef<SWidget> SDismembermentGraphNode::GetNodeBodyWidget()
|
|||||||
|
|
||||||
return SNew(STextBlock)
|
return SNew(STextBlock)
|
||||||
.Text(DismembermentNode->GetTooltipText())
|
.Text(DismembermentNode->GetTooltipText())
|
||||||
.TextStyle(FEditorStyle::Get(), "Graph.StateNode.Description")
|
.TextStyle(FAppStyle::Get(), "Graph.StateNode.Description")
|
||||||
.WrapTextAt(200.0f);
|
.WrapTextAt(200.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,7 +295,7 @@ TSharedRef<SWidget> SDismembermentGraphNode::GetNodePreviewWidget()
|
|||||||
[
|
[
|
||||||
SNew(STextBlock)
|
SNew(STextBlock)
|
||||||
.Text(NSLOCTEXT("SDismembermentGraphNode", "Preview", "Preview"))
|
.Text(NSLOCTEXT("SDismembermentGraphNode", "Preview", "Preview"))
|
||||||
.TextStyle(FEditorStyle::Get(), "Graph.StateNode.Description")
|
.TextStyle(FAppStyle::Get(), "Graph.StateNode.Description")
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
#include "Widgets/Layout/SBorder.h"
|
#include "Widgets/Layout/SBorder.h"
|
||||||
#include "Widgets/Input/SButton.h"
|
#include "Widgets/Input/SButton.h"
|
||||||
#include "PropertyEditorModule.h"
|
#include "PropertyEditorModule.h"
|
||||||
#include "EditorStyleSet.h"
|
#include "Styling/AppStyle.h"
|
||||||
#include "LevelEditor.h"
|
#include "LevelEditor.h"
|
||||||
#include "ToolMenus.h"
|
#include "ToolMenus.h"
|
||||||
|
|
||||||
@@ -30,10 +30,10 @@ FFLESHEditor::~FFLESHEditor()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void FFLESHEditor::InitFLESHEditor(const EToolkitMode::Type Mode, const TSharedPtr<IToolkitHost>& InitToolkitHost)
|
void FFLESHEditor::InitFLESHEditor(const EToolkitMode::Type Mode, const TSharedPtr<IToolkitHost>& InitToolkitHost, UObject* InObject)
|
||||||
{
|
{
|
||||||
// Create command list
|
// Create command list
|
||||||
CreateCommandList();
|
this->CreateCommandList();
|
||||||
|
|
||||||
// Create tab layout
|
// Create tab layout
|
||||||
const TSharedRef<FTabManager::FLayout> StandaloneDefaultLayout = FTabManager::NewLayout("FLESHEditorLayout_v1.0")
|
const TSharedRef<FTabManager::FLayout> StandaloneDefaultLayout = FTabManager::NewLayout("FLESHEditorLayout_v1.0")
|
||||||
@@ -89,7 +89,7 @@ void FFLESHEditor::InitFLESHEditor(const EToolkitMode::Type Mode, const TSharedP
|
|||||||
// Initialize toolkit
|
// Initialize toolkit
|
||||||
const bool bCreateDefaultStandaloneMenu = true;
|
const bool bCreateDefaultStandaloneMenu = true;
|
||||||
const bool bCreateDefaultToolbar = true;
|
const bool bCreateDefaultToolbar = true;
|
||||||
FAssetEditorToolkit::InitAssetEditor(Mode, InitToolkitHost, FName("FLESHEditorApp"), StandaloneDefaultLayout, bCreateDefaultStandaloneMenu, bCreateDefaultToolbar);
|
this->InitAssetEditor(Mode, InitToolkitHost, FName("FLESHEditorApp"), StandaloneDefaultLayout, bCreateDefaultStandaloneMenu, bCreateDefaultToolbar, InObject, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FFLESHEditor::RegisterTabSpawners(const TSharedRef<FTabManager>& InTabManager)
|
void FFLESHEditor::RegisterTabSpawners(const TSharedRef<FTabManager>& InTabManager)
|
||||||
@@ -100,32 +100,32 @@ void FFLESHEditor::RegisterTabSpawners(const TSharedRef<FTabManager>& InTabManag
|
|||||||
InTabManager->RegisterTabSpawner(ViewportTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_Viewport))
|
InTabManager->RegisterTabSpawner(ViewportTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_Viewport))
|
||||||
.SetDisplayName(LOCTEXT("ViewportTab", "Viewport"))
|
.SetDisplayName(LOCTEXT("ViewportTab", "Viewport"))
|
||||||
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
|
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
|
||||||
.SetIcon(FSlateIcon(FEditorStyle::GetStyleSetName(), "LevelEditor.Tabs.Viewports"));
|
.SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "LevelEditor.Tabs.Viewports"));
|
||||||
|
|
||||||
InTabManager->RegisterTabSpawner(DetailsTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_Details))
|
InTabManager->RegisterTabSpawner(DetailsTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_Details))
|
||||||
.SetDisplayName(LOCTEXT("DetailsTab", "Details"))
|
.SetDisplayName(LOCTEXT("DetailsTab", "Details"))
|
||||||
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
|
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
|
||||||
.SetIcon(FSlateIcon(FEditorStyle::GetStyleSetName(), "LevelEditor.Tabs.Details"));
|
.SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "LevelEditor.Tabs.Details"));
|
||||||
|
|
||||||
InTabManager->RegisterTabSpawner(AssetBrowserTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_AssetBrowser))
|
InTabManager->RegisterTabSpawner(AssetBrowserTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_AssetBrowser))
|
||||||
.SetDisplayName(LOCTEXT("AssetBrowserTab", "Asset Browser"))
|
.SetDisplayName(LOCTEXT("AssetBrowserTab", "Asset Browser"))
|
||||||
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
|
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
|
||||||
.SetIcon(FSlateIcon(FEditorStyle::GetStyleSetName(), "ContentBrowser.TabIcon"));
|
.SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "ContentBrowser.TabIcon"));
|
||||||
|
|
||||||
InTabManager->RegisterTabSpawner(MatrixEditorTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_MatrixEditor))
|
InTabManager->RegisterTabSpawner(MatrixEditorTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_MatrixEditor))
|
||||||
.SetDisplayName(LOCTEXT("MatrixEditorTab", "Matrix Editor"))
|
.SetDisplayName(LOCTEXT("MatrixEditorTab", "Matrix Editor"))
|
||||||
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
|
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
|
||||||
.SetIcon(FSlateIcon(FEditorStyle::GetStyleSetName(), "PropertyEditor.Grid.TabIcon"));
|
.SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "PropertyEditor.Grid.TabIcon"));
|
||||||
|
|
||||||
InTabManager->RegisterTabSpawner(GraphEditorTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_GraphEditor))
|
InTabManager->RegisterTabSpawner(GraphEditorTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_GraphEditor))
|
||||||
.SetDisplayName(LOCTEXT("GraphEditorTab", "Graph Editor"))
|
.SetDisplayName(LOCTEXT("GraphEditorTab", "Graph Editor"))
|
||||||
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
|
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
|
||||||
.SetIcon(FSlateIcon(FEditorStyle::GetStyleSetName(), "GraphEditor.EventGraph_16x"));
|
.SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "GraphEditor.EventGraph_16x"));
|
||||||
|
|
||||||
InTabManager->RegisterTabSpawner(ToolbarTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_Toolbar))
|
InTabManager->RegisterTabSpawner(ToolbarTabId, FOnSpawnTab::CreateSP(this, &FFLESHEditor::SpawnTab_Toolbar))
|
||||||
.SetDisplayName(LOCTEXT("ToolbarTab", "Toolbar"))
|
.SetDisplayName(LOCTEXT("ToolbarTab", "Toolbar"))
|
||||||
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
|
.SetGroup(WorkspaceMenuCategory.ToSharedRef())
|
||||||
.SetIcon(FSlateIcon(FEditorStyle::GetStyleSetName(), "LevelEditor.Tabs.Toolbar"));
|
.SetIcon(FSlateIcon(FAppStyle::GetAppStyleSetName(), "LevelEditor.Tabs.Toolbar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FFLESHEditor::UnregisterTabSpawners(const TSharedRef<FTabManager>& InTabManager)
|
void FFLESHEditor::UnregisterTabSpawners(const TSharedRef<FTabManager>& InTabManager)
|
||||||
@@ -165,7 +165,7 @@ void FFLESHEditor::OpenEditor()
|
|||||||
{
|
{
|
||||||
// Create new editor instance
|
// Create new editor instance
|
||||||
TSharedRef<FFLESHEditor> NewEditor = MakeShareable(new FFLESHEditor());
|
TSharedRef<FFLESHEditor> NewEditor = MakeShareable(new FFLESHEditor());
|
||||||
NewEditor->InitFLESHEditor(EToolkitMode::Standalone, nullptr);
|
NewEditor->InitFLESHEditor(EToolkitMode::Standalone, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TSharedRef<SDockTab> FFLESHEditor::SpawnTab_Viewport(const FSpawnTabArgs& Args)
|
TSharedRef<SDockTab> FFLESHEditor::SpawnTab_Viewport(const FSpawnTabArgs& Args)
|
||||||
@@ -226,7 +226,7 @@ TSharedRef<SWidget> FFLESHEditor::CreateViewportWidget()
|
|||||||
{
|
{
|
||||||
// Create viewport widget
|
// Create viewport widget
|
||||||
return SNew(SBorder)
|
return SNew(SBorder)
|
||||||
.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
||||||
.Padding(4.0f)
|
.Padding(4.0f)
|
||||||
[
|
[
|
||||||
SNew(SVerticalBox)
|
SNew(SVerticalBox)
|
||||||
@@ -235,13 +235,13 @@ TSharedRef<SWidget> FFLESHEditor::CreateViewportWidget()
|
|||||||
[
|
[
|
||||||
SNew(STextBlock)
|
SNew(STextBlock)
|
||||||
.Text(LOCTEXT("ViewportHeader", "FLESH Viewport"))
|
.Text(LOCTEXT("ViewportHeader", "FLESH Viewport"))
|
||||||
.Font(FEditorStyle::GetFontStyle("HeadingFont"))
|
.Font(FAppStyle::GetFontStyle("HeadingFont"))
|
||||||
]
|
]
|
||||||
+ SVerticalBox::Slot()
|
+ SVerticalBox::Slot()
|
||||||
.FillHeight(1.0f)
|
.FillHeight(1.0f)
|
||||||
[
|
[
|
||||||
SNew(SBorder)
|
SNew(SBorder)
|
||||||
.BorderImage(FEditorStyle::GetBrush("ToolPanel.DarkGroupBorder"))
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.DarkGroupBorder"))
|
||||||
.Padding(4.0f)
|
.Padding(4.0f)
|
||||||
[
|
[
|
||||||
SNew(STextBlock)
|
SNew(STextBlock)
|
||||||
@@ -270,7 +270,7 @@ TSharedRef<SWidget> FFLESHEditor::CreateDetailsWidget()
|
|||||||
DetailsWidget = PropertyEditorModule.CreateDetailView(DetailsViewArgs);
|
DetailsWidget = PropertyEditorModule.CreateDetailView(DetailsViewArgs);
|
||||||
|
|
||||||
return SNew(SBorder)
|
return SNew(SBorder)
|
||||||
.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
||||||
.Padding(4.0f)
|
.Padding(4.0f)
|
||||||
[
|
[
|
||||||
SNew(SVerticalBox)
|
SNew(SVerticalBox)
|
||||||
@@ -279,7 +279,7 @@ TSharedRef<SWidget> FFLESHEditor::CreateDetailsWidget()
|
|||||||
[
|
[
|
||||||
SNew(STextBlock)
|
SNew(STextBlock)
|
||||||
.Text(LOCTEXT("DetailsHeader", "Property Editor"))
|
.Text(LOCTEXT("DetailsHeader", "Property Editor"))
|
||||||
.Font(FEditorStyle::GetFontStyle("HeadingFont"))
|
.Font(FAppStyle::GetFontStyle("HeadingFont"))
|
||||||
]
|
]
|
||||||
+ SVerticalBox::Slot()
|
+ SVerticalBox::Slot()
|
||||||
.FillHeight(1.0f)
|
.FillHeight(1.0f)
|
||||||
@@ -293,7 +293,7 @@ TSharedRef<SWidget> FFLESHEditor::CreateAssetBrowserWidget()
|
|||||||
{
|
{
|
||||||
// Create asset browser
|
// Create asset browser
|
||||||
return SNew(SBorder)
|
return SNew(SBorder)
|
||||||
.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
||||||
.Padding(4.0f)
|
.Padding(4.0f)
|
||||||
[
|
[
|
||||||
SNew(SVerticalBox)
|
SNew(SVerticalBox)
|
||||||
@@ -302,7 +302,7 @@ TSharedRef<SWidget> FFLESHEditor::CreateAssetBrowserWidget()
|
|||||||
[
|
[
|
||||||
SNew(STextBlock)
|
SNew(STextBlock)
|
||||||
.Text(LOCTEXT("AssetBrowserHeader", "Asset Browser"))
|
.Text(LOCTEXT("AssetBrowserHeader", "Asset Browser"))
|
||||||
.Font(FEditorStyle::GetFontStyle("HeadingFont"))
|
.Font(FAppStyle::GetFontStyle("HeadingFont"))
|
||||||
]
|
]
|
||||||
+ SVerticalBox::Slot()
|
+ SVerticalBox::Slot()
|
||||||
.FillHeight(1.0f)
|
.FillHeight(1.0f)
|
||||||
@@ -358,7 +358,7 @@ TSharedRef<SWidget> FFLESHEditor::CreateMatrixEditorWidget()
|
|||||||
});
|
});
|
||||||
|
|
||||||
return SNew(SBorder)
|
return SNew(SBorder)
|
||||||
.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
||||||
.Padding(4.0f)
|
.Padding(4.0f)
|
||||||
[
|
[
|
||||||
SNew(SVerticalBox)
|
SNew(SVerticalBox)
|
||||||
@@ -367,7 +367,7 @@ TSharedRef<SWidget> FFLESHEditor::CreateMatrixEditorWidget()
|
|||||||
[
|
[
|
||||||
SNew(STextBlock)
|
SNew(STextBlock)
|
||||||
.Text(LOCTEXT("MatrixEditorHeader", "Matrix Editor"))
|
.Text(LOCTEXT("MatrixEditorHeader", "Matrix Editor"))
|
||||||
.Font(FEditorStyle::GetFontStyle("HeadingFont"))
|
.Font(FAppStyle::GetFontStyle("HeadingFont"))
|
||||||
]
|
]
|
||||||
+ SVerticalBox::Slot()
|
+ SVerticalBox::Slot()
|
||||||
.FillHeight(1.0f)
|
.FillHeight(1.0f)
|
||||||
@@ -390,7 +390,7 @@ TSharedRef<SWidget> FFLESHEditor::CreateGraphEditorWidget()
|
|||||||
{
|
{
|
||||||
// Create graph editor
|
// Create graph editor
|
||||||
return SNew(SBorder)
|
return SNew(SBorder)
|
||||||
.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
||||||
.Padding(4.0f)
|
.Padding(4.0f)
|
||||||
[
|
[
|
||||||
SNew(SVerticalBox)
|
SNew(SVerticalBox)
|
||||||
@@ -399,13 +399,13 @@ TSharedRef<SWidget> FFLESHEditor::CreateGraphEditorWidget()
|
|||||||
[
|
[
|
||||||
SNew(STextBlock)
|
SNew(STextBlock)
|
||||||
.Text(LOCTEXT("GraphEditorHeader", "Graph Editor"))
|
.Text(LOCTEXT("GraphEditorHeader", "Graph Editor"))
|
||||||
.Font(FEditorStyle::GetFontStyle("HeadingFont"))
|
.Font(FAppStyle::GetFontStyle("HeadingFont"))
|
||||||
]
|
]
|
||||||
+ SVerticalBox::Slot()
|
+ SVerticalBox::Slot()
|
||||||
.FillHeight(1.0f)
|
.FillHeight(1.0f)
|
||||||
[
|
[
|
||||||
SNew(SBorder)
|
SNew(SBorder)
|
||||||
.BorderImage(FEditorStyle::GetBrush("ToolPanel.DarkGroupBorder"))
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.DarkGroupBorder"))
|
||||||
.Padding(4.0f)
|
.Padding(4.0f)
|
||||||
[
|
[
|
||||||
SNew(STextBlock)
|
SNew(STextBlock)
|
||||||
@@ -419,7 +419,7 @@ TSharedRef<SWidget> FFLESHEditor::CreateToolbarWidget()
|
|||||||
{
|
{
|
||||||
// Create toolbar
|
// Create toolbar
|
||||||
return SNew(SBorder)
|
return SNew(SBorder)
|
||||||
.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
|
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
|
||||||
.Padding(4.0f)
|
.Padding(4.0f)
|
||||||
[
|
[
|
||||||
SNew(SHorizontalBox)
|
SNew(SHorizontalBox)
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
#include "Widgets/Input/SButton.h"
|
#include "Widgets/Input/SButton.h"
|
||||||
#include "Widgets/Layout/SBox.h"
|
#include "Widgets/Layout/SBox.h"
|
||||||
#include "Widgets/Layout/SScrollBox.h"
|
#include "Widgets/Layout/SScrollBox.h"
|
||||||
#include "EditorStyleSet.h"
|
#include "Styling/AppStyle.h"
|
||||||
|
|
||||||
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
||||||
|
|
||||||
@@ -214,7 +214,8 @@ void SMatrixInputWidget::UpdateUI()
|
|||||||
int32 Index = Row * 4 + Col;
|
int32 Index = Row * 4 + Col;
|
||||||
if (NumericEntryBoxes.IsValidIndex(Index) && NumericEntryBoxes[Index].IsValid())
|
if (NumericEntryBoxes.IsValidIndex(Index) && NumericEntryBoxes[Index].IsValid())
|
||||||
{
|
{
|
||||||
NumericEntryBoxes[Index]->SetValue(Matrix.M[Row][Col]);
|
// Set value using TOptional<float> instead of SetText or SetValue
|
||||||
|
NumericEntryBoxes[Index]->SetValue(TOptional<float>(Matrix.M[Row][Col]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,5 +18,5 @@ public:
|
|||||||
|
|
||||||
// The asset that owns this graph
|
// The asset that owns this graph
|
||||||
UPROPERTY()
|
UPROPERTY()
|
||||||
class UDismembermentGraphAsset* OwningAsset;
|
TObjectPtr<class UDismembermentGraphAsset> OwningAsset;
|
||||||
};
|
};
|
||||||
|
@@ -0,0 +1,51 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "EdGraphUtilities.h"
|
||||||
|
|
||||||
|
class UDismembermentGraphNode;
|
||||||
|
class SDismembermentGraphNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dismemberment graph node factory
|
||||||
|
* Used to create visual representations of dismemberment graph nodes
|
||||||
|
*/
|
||||||
|
class FDismembermentGraphNodeFactory : public FGraphPanelNodeFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Constructor
|
||||||
|
FDismembermentGraphNodeFactory();
|
||||||
|
|
||||||
|
FDismembermentGraphNodeFactory(UClass* InNodeClass, const FText& InDisplayName, const FText& InTooltip);
|
||||||
|
|
||||||
|
// FGraphPanelNodeFactory interface
|
||||||
|
virtual TSharedPtr<SGraphNode> CreateNode(UEdGraphNode* Node) const override;
|
||||||
|
// End of interface
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Node class
|
||||||
|
UClass* NodeClass;
|
||||||
|
|
||||||
|
// Display name
|
||||||
|
FText DisplayName;
|
||||||
|
|
||||||
|
// Tooltip
|
||||||
|
FText Tooltip;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dismemberment schema action - New node
|
||||||
|
* Used to create new nodes in the context menu
|
||||||
|
*/
|
||||||
|
class FDismembermentSchemaAction_NewNode : public FEdGraphSchemaAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Constructor
|
||||||
|
FDismembermentSchemaAction_NewNode(const FText& InNodeCategory, const FText& InMenuDesc, const FText& InToolTip, const int32 InGrouping);
|
||||||
|
|
||||||
|
// Perform action
|
||||||
|
virtual UEdGraphNode* PerformAction(UEdGraph* ParentGraph, UEdGraphPin* FromPin, const FVector2D Location, bool bSelectNewNode = true) override;
|
||||||
|
|
||||||
|
// Node class
|
||||||
|
TSubclassOf<UDismembermentGraphNode> NodeClass;
|
||||||
|
};
|
@@ -21,7 +21,7 @@ public:
|
|||||||
virtual ~FFLESHEditor();
|
virtual ~FFLESHEditor();
|
||||||
|
|
||||||
// Initialize the editor
|
// Initialize the editor
|
||||||
void InitFLESHEditor(const EToolkitMode::Type Mode, const TSharedPtr<IToolkitHost>& InitToolkitHost);
|
void InitFLESHEditor(const EToolkitMode::Type Mode, const TSharedPtr<IToolkitHost>& InitToolkitHost, UObject* InObject);
|
||||||
|
|
||||||
// FAssetEditorToolkit interface
|
// FAssetEditorToolkit interface
|
||||||
virtual void RegisterTabSpawners(const TSharedRef<FTabManager>& TabManager) override;
|
virtual void RegisterTabSpawners(const TSharedRef<FTabManager>& TabManager) override;
|
||||||
|
@@ -7,6 +7,9 @@
|
|||||||
#include "Widgets/Layout/SBox.h"
|
#include "Widgets/Layout/SBox.h"
|
||||||
#include "Widgets/Layout/SGridPanel.h"
|
#include "Widgets/Layout/SGridPanel.h"
|
||||||
|
|
||||||
|
// Define matrix change delegate type
|
||||||
|
DECLARE_DELEGATE_OneParam(FOnMatrixChanged, const FMatrix&);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matrix input widget for the FLESH editor
|
* Matrix input widget for the FLESH editor
|
||||||
* Allows inputting transformation matrices for precise cutting operations
|
* Allows inputting transformation matrices for precise cutting operations
|
||||||
@@ -67,6 +70,3 @@ private:
|
|||||||
/** Updates the UI from the matrix value */
|
/** Updates the UI from the matrix value */
|
||||||
void UpdateUI();
|
void UpdateUI();
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Delegate for matrix value changes */
|
|
||||||
DECLARE_DELEGATE_OneParam(FOnMatrixChanged, const FMatrix&);
|
|
||||||
|
Reference in New Issue
Block a user