This commit is contained in:
2025-04-23 01:18:06 +08:00
parent 83d52181f5
commit 0ea2281199
93 changed files with 8954 additions and 8943 deletions

View File

@@ -0,0 +1,150 @@
#include "FLESHGraph/FLESHCompiler.h"
#include "FLESHGraph/FLESHGraph.h"
#include "FLESHGraph/FLESHGraphNode.h"
#include "Logging/LogMacros.h"
// Define log category
DEFINE_LOG_CATEGORY_STATIC(LogFLESHCompiler, Log, All);
UFLESHCompiler::UFLESHCompiler()
{
// Initialize default values
SourceGraph = nullptr;
bCompilationSuccessful = false;
ErrorMessage = TEXT("");
}
void UFLESHCompiler::Initialize(UFLESHGraph* InGraph)
{
// Set source graph
SourceGraph = InGraph;
// Reset compilation status
bCompilationSuccessful = false;
ErrorMessage = TEXT("");
CompiledNodeData.Empty();
ExecutionOrder.Empty();
UE_LOG(LogFLESHCompiler, Log, TEXT("FLESH Compiler initialized with graph: %s"),
SourceGraph ? *SourceGraph->GetName() : TEXT("Invalid"));
}
bool UFLESHCompiler::Compile()
{
// Check if source graph is valid
if (!SourceGraph)
{
ErrorMessage = TEXT("Invalid source graph");
UE_LOG(LogFLESHCompiler, Error, TEXT("FLESH Compiler error: %s"), *ErrorMessage);
return false;
}
// Reset compilation data
CompiledNodeData.Empty();
ExecutionOrder.Empty();
// Validate graph
if (!ValidateGraph())
{
UE_LOG(LogFLESHCompiler, Error, TEXT("FLESH Compiler error: %s"), *ErrorMessage);
return false;
}
// Process all nodes in the graph
TArray<UFLESHGraphNode*> AllNodes;
// TODO: Get all nodes from graph
// Process each node
for (int32 NodeIndex = 0; NodeIndex < AllNodes.Num(); NodeIndex++)
{
if (!ProcessNode(AllNodes[NodeIndex], NodeIndex))
{
UE_LOG(LogFLESHCompiler, Error, TEXT("FLESH Compiler error: %s"), *ErrorMessage);
return false;
}
}
// Sort nodes in execution order
SortNodes();
// Set compilation status
bCompilationSuccessful = true;
UE_LOG(LogFLESHCompiler, Log, TEXT("FLESH Graph compiled successfully. Nodes: %d, Execution order: %d"),
CompiledNodeData.Num(), ExecutionOrder.Num());
return true;
}
TArray<FFLESHNodeData> UFLESHCompiler::GetCompiledNodeData() const
{
return CompiledNodeData;
}
TArray<int32> UFLESHCompiler::GetExecutionOrder() const
{
return ExecutionOrder;
}
bool UFLESHCompiler::IsCompilationSuccessful() const
{
return bCompilationSuccessful;
}
FString UFLESHCompiler::GetErrorMessage() const
{
return ErrorMessage;
}
bool UFLESHCompiler::ProcessNode(UFLESHGraphNode* Node, int32 NodeIndex)
{
// Check if node is valid
if (!Node)
{
ErrorMessage = FString::Printf(TEXT("Invalid node at index %d"), NodeIndex);
return false;
}
// Create node data
FFLESHNodeData NodeData;
NodeData.NodeName = FName(*Node->GetNodeTitle());
// TODO: Set node type and parameters
// Add node data to compiled data
CompiledNodeData.Add(NodeData);
return true;
}
void UFLESHCompiler::SortNodes()
{
// TODO: Implement topological sort to determine execution order
// For now, just add all nodes in order
for (int32 i = 0; i < CompiledNodeData.Num(); i++)
{
ExecutionOrder.Add(i);
}
}
bool UFLESHCompiler::ValidateGraph()
{
// TODO: Implement graph validation
// Check if source graph is valid
if (!SourceGraph)
{
ErrorMessage = TEXT("Source graph is null");
return false;
}
// Check if graph has at least one node
TArray<UFLESHGraphNode*> AllNodes = SourceGraph->GetAllNodes();
if (AllNodes.Num() == 0)
{
ErrorMessage = TEXT("Graph has no nodes");
return false;
}
return true;
}

View File

@@ -0,0 +1,195 @@
#include "FLESHGraph/FLESHExecutor.h"
#include "Engine/SkeletalMesh.h"
#include "Components/SkeletalMeshComponent.h"
#include "NiagaraSystem.h"
#include "NiagaraComponent.h"
#include "NiagaraFunctionLibrary.h"
#include "Components/DecalComponent.h"
#include "Kismet/GameplayStatics.h"
#include "PhysicalMaterials/PhysicalMaterial.h"
#include "Logging/LogMacros.h"
// Define log category
DEFINE_LOG_CATEGORY_STATIC(LogFLESHExecutor, Log, All);
UFLESHExecutor::UFLESHExecutor()
{
// Initialize default values
Compiler = nullptr;
TargetActor = nullptr;
TargetSkeletalMesh = nullptr;
// Create boolean cut tool
CutTool = CreateDefaultSubobject<UBooleanCutTool>(TEXT("CutTool"));
}
void UFLESHExecutor::Initialize(UFLESHCompiler* InCompiler)
{
// Set compiler reference
Compiler = InCompiler;
UE_LOG(LogFLESHExecutor, Log, TEXT("FLESH Executor initialized with compiler: %s"),
Compiler ? TEXT("Valid") : TEXT("Invalid"));
}
bool UFLESHExecutor::Execute(AActor* InTargetActor)
{
// Set target actor
TargetActor = InTargetActor;
// Find skeletal mesh component
if (!FindTargetSkeletalMesh())
{
UE_LOG(LogFLESHExecutor, Warning, TEXT("FLESH: Cannot execute FLESH graph, skeletal mesh component not found"));
return false;
}
// Check if compiler is valid
if (!Compiler)
{
UE_LOG(LogFLESHExecutor, Warning, TEXT("FLESH: Cannot execute FLESH graph, invalid compiler"));
return false;
}
// Check if compilation was successful
if (!Compiler->IsCompilationSuccessful())
{
UE_LOG(LogFLESHExecutor, Warning, TEXT("FLESH: Cannot execute FLESH graph, compilation failed: %s"),
*Compiler->GetErrorMessage());
return false;
}
// Get execution order from compiler
TArray<int32> ExecutionOrder = Compiler->GetExecutionOrder();
// Get compiled node data
TArray<FFLESHNodeData> CompiledNodeData = Compiler->GetCompiledNodeData();
// Execute nodes in order
for (int32 NodeIndex : ExecutionOrder)
{
// Check if node index is valid
if (!CompiledNodeData.IsValidIndex(NodeIndex))
{
UE_LOG(LogFLESHExecutor, Warning, TEXT("FLESH: Invalid node index in execution order: %d"), NodeIndex);
continue;
}
// Execute node
if (!ExecuteNode(CompiledNodeData[NodeIndex]))
{
UE_LOG(LogFLESHExecutor, Warning, TEXT("FLESH: Failed to execute node: %s"),
*CompiledNodeData[NodeIndex].NodeName.ToString());
return false;
}
}
UE_LOG(LogFLESHExecutor, Log, TEXT("FLESH: Graph executed successfully on actor: %s"),
TargetActor ? *TargetActor->GetName() : TEXT("Invalid"));
return true;
}
void UFLESHExecutor::SetCutTool(UBooleanCutTool* InCutTool)
{
CutTool = InCutTool;
}
UBooleanCutTool* UFLESHExecutor::GetCutTool() const
{
return CutTool;
}
bool UFLESHExecutor::FindTargetSkeletalMesh()
{
// Check if target actor is valid
if (!TargetActor)
{
UE_LOG(LogFLESHExecutor, Warning, TEXT("FLESH: Invalid target actor"));
return false;
}
// Find skeletal mesh component
TargetSkeletalMesh = TargetActor->FindComponentByClass<USkeletalMeshComponent>();
// Check if skeletal mesh component is valid
if (!TargetSkeletalMesh)
{
UE_LOG(LogFLESHExecutor, Warning, TEXT("FLESH: Target actor does not have a skeletal mesh component"));
return false;
}
return true;
}
bool UFLESHExecutor::ExecuteNode(const FFLESHNodeData& NodeData)
{
// Execute node based on type
switch (NodeData.NodeType)
{
case EFLESHNodeType::Cut:
return ExecuteCutNode(NodeData);
case EFLESHNodeType::BloodEffect:
return ExecuteBloodEffectNode(NodeData);
case EFLESHNodeType::Physics:
return ExecutePhysicsNode(NodeData);
case EFLESHNodeType::Organ:
return ExecuteOrganNode(NodeData);
case EFLESHNodeType::Wound:
return ExecuteWoundNode(NodeData);
case EFLESHNodeType::BoneSelection:
return ExecuteBoneSelectionNode(NodeData);
default:
UE_LOG(LogFLESHExecutor, Warning, TEXT("FLESH: Unknown node type for node: %s"),
*NodeData.NodeName.ToString());
return false;
}
}
bool UFLESHExecutor::ExecuteCutNode(const FFLESHNodeData& NodeData)
{
// TODO: Implement cut node execution
UE_LOG(LogFLESHExecutor, Log, TEXT("FLESH: Executing cut node: %s"), *NodeData.NodeName.ToString());
return true;
}
bool UFLESHExecutor::ExecuteBloodEffectNode(const FFLESHNodeData& NodeData)
{
// TODO: Implement blood effect node execution
UE_LOG(LogFLESHExecutor, Log, TEXT("FLESH: Executing blood effect node: %s"), *NodeData.NodeName.ToString());
return true;
}
bool UFLESHExecutor::ExecutePhysicsNode(const FFLESHNodeData& NodeData)
{
// TODO: Implement physics node execution
UE_LOG(LogFLESHExecutor, Log, TEXT("FLESH: Executing physics node: %s"), *NodeData.NodeName.ToString());
return true;
}
bool UFLESHExecutor::ExecuteOrganNode(const FFLESHNodeData& NodeData)
{
// TODO: Implement organ node execution
UE_LOG(LogFLESHExecutor, Log, TEXT("FLESH: Executing organ node: %s"), *NodeData.NodeName.ToString());
return true;
}
bool UFLESHExecutor::ExecuteWoundNode(const FFLESHNodeData& NodeData)
{
// TODO: Implement wound node execution
UE_LOG(LogFLESHExecutor, Log, TEXT("FLESH: Executing wound node: %s"), *NodeData.NodeName.ToString());
return true;
}
bool UFLESHExecutor::ExecuteBoneSelectionNode(const FFLESHNodeData& NodeData)
{
// TODO: Implement bone selection node execution
UE_LOG(LogFLESHExecutor, Log, TEXT("FLESH: Executing bone selection node: %s"), *NodeData.NodeName.ToString());
return true;
}

View File

@@ -0,0 +1,230 @@
#include "FLESHGraph/FLESHGraph.h"
#include "FLESHGraph/FLESHGraphNode.h"
#include "Logging/LogMacros.h"
// Define log category
DEFINE_LOG_CATEGORY_STATIC(LogFLESHGraph, Log, All);
UFLESHGraph::UFLESHGraph()
{
// Initialize default values
RootNode = nullptr;
}
void UFLESHGraph::Initialize()
{
// Clear graph
ClearGraph();
UE_LOG(LogFLESHGraph, Log, TEXT("FLESH graph initialized"));
}
UFLESHGraphNode* UFLESHGraph::AddNode(TSubclassOf<UFLESHGraphNode> NodeClass, const FVector2D& Position)
{
// Check if node class is valid
if (!NodeClass)
{
UE_LOG(LogFLESHGraph, Warning, TEXT("FLESH: Invalid node class"));
return nullptr;
}
// Create new node
UFLESHGraphNode* NewNode = NewObject<UFLESHGraphNode>(this, NodeClass);
if (!NewNode)
{
UE_LOG(LogFLESHGraph, Warning, TEXT("FLESH: Failed to create node"));
return nullptr;
}
// Set node position
NewNode->SetNodePosition(Position);
// Add to node list
Nodes.Add(NewNode);
// If it's the first node, set as root node
if (Nodes.Num() == 1)
{
RootNode = NewNode;
}
UE_LOG(LogFLESHGraph, Log, TEXT("FLESH: Added new node: %s"), *NewNode->GetNodeTitle());
return NewNode;
}
bool UFLESHGraph::RemoveNode(UFLESHGraphNode* Node)
{
// Check if node is valid
if (!Node)
{
UE_LOG(LogFLESHGraph, Warning, TEXT("FLESH: Trying to remove invalid node"));
return false;
}
// Disconnect from other nodes
TArray<UFLESHGraphNode*> InputNodes = Node->GetInputNodes();
TArray<UFLESHGraphNode*> OutputNodes = Node->GetOutputNodes();
for (UFLESHGraphNode* InputNode : InputNodes)
{
DisconnectNodes(InputNode, Node);
}
for (UFLESHGraphNode* OutputNode : OutputNodes)
{
DisconnectNodes(Node, OutputNode);
}
// If it's the root node, reset root node
if (Node == RootNode)
{
RootNode = nullptr;
// If there are other nodes, choose the first one as the new root node
if (Nodes.Num() > 1)
{
for (UFLESHGraphNode* OtherNode : Nodes)
{
if (OtherNode != Node)
{
RootNode = OtherNode;
break;
}
}
}
}
// Remove from node list
bool bRemoved = Nodes.Remove(Node) > 0;
if (bRemoved)
{
UE_LOG(LogFLESHGraph, Log, TEXT("FLESH: Removed node: %s"), *Node->GetNodeTitle());
}
else
{
UE_LOG(LogFLESHGraph, Warning, TEXT("FLESH: Node is not in graph: %s"), *Node->GetNodeTitle());
}
return bRemoved;
}
bool UFLESHGraph::ConnectNodes(UFLESHGraphNode* SourceNode, UFLESHGraphNode* TargetNode)
{
// Check if nodes are valid
if (!SourceNode || !TargetNode)
{
UE_LOG(LogFLESHGraph, Warning, TEXT("FLESH: Trying to connect invalid nodes"));
return false;
}
// Add connection
bool bSourceAdded = SourceNode->AddOutputNode(TargetNode);
bool bTargetAdded = TargetNode->AddInputNode(SourceNode);
if (bSourceAdded && bTargetAdded)
{
UE_LOG(LogFLESHGraph, Log, TEXT("FLESH: Connected nodes: %s -> %s"),
*SourceNode->GetNodeTitle(), *TargetNode->GetNodeTitle());
return true;
}
else
{
// If adding failed, rollback changes
if (bSourceAdded)
{
SourceNode->RemoveOutputNode(TargetNode);
}
if (bTargetAdded)
{
TargetNode->RemoveInputNode(SourceNode);
}
UE_LOG(LogFLESHGraph, Warning, TEXT("FLESH: Connecting nodes failed: %s -> %s"),
*SourceNode->GetNodeTitle(), *TargetNode->GetNodeTitle());
return false;
}
}
bool UFLESHGraph::DisconnectNodes(UFLESHGraphNode* SourceNode, UFLESHGraphNode* TargetNode)
{
// Check if nodes are valid
if (!SourceNode || !TargetNode)
{
UE_LOG(LogFLESHGraph, Warning, TEXT("FLESH: Trying to disconnect invalid nodes"));
return false;
}
// Remove connection
bool bSourceRemoved = SourceNode->RemoveOutputNode(TargetNode);
bool bTargetRemoved = TargetNode->RemoveInputNode(SourceNode);
if (bSourceRemoved && bTargetRemoved)
{
UE_LOG(LogFLESHGraph, Log, TEXT("FLESH: Disconnected nodes: %s -> %s"),
*SourceNode->GetNodeTitle(), *TargetNode->GetNodeTitle());
return true;
}
else
{
UE_LOG(LogFLESHGraph, Warning, TEXT("FLESH: Disconnecting nodes failed: %s -> %s"),
*SourceNode->GetNodeTitle(), *TargetNode->GetNodeTitle());
return false;
}
}
TArray<UFLESHGraphNode*> UFLESHGraph::GetAllNodes() const
{
return Nodes;
}
UFLESHGraphNode* UFLESHGraph::GetRootNode() const
{
return RootNode;
}
void UFLESHGraph::SetRootNode(UFLESHGraphNode* InRootNode)
{
// Check if node is in graph
if (InRootNode && Nodes.Contains(InRootNode))
{
RootNode = InRootNode;
UE_LOG(LogFLESHGraph, Log, TEXT("FLESH: Set new root node: %s"), *RootNode->GetNodeTitle());
}
else if (!InRootNode)
{
RootNode = nullptr;
UE_LOG(LogFLESHGraph, Log, TEXT("FLESH: Clear root node"));
}
else
{
UE_LOG(LogFLESHGraph, Warning, TEXT("FLESH: Trying to set node not in graph as root node"));
}
}
void UFLESHGraph::ClearGraph()
{
// Clear node list
Nodes.Empty();
// Clear root node
RootNode = nullptr;
UE_LOG(LogFLESHGraph, Log, TEXT("FLESH: Cleared graph"));
}
bool UFLESHGraph::SaveGraph()
{
// TODO: implement graph saving feature
UE_LOG(LogFLESHGraph, Log, TEXT("FLESH: Graph saving feature not implemented"));
return false;
}
bool UFLESHGraph::LoadGraph()
{
// TODO: implement graph loading feature
UE_LOG(LogFLESHGraph, Log, TEXT("FLESH: Graph loading feature not implemented"));
return false;
}

View File

@@ -0,0 +1,164 @@
#include "FLESHGraph/FLESHGraphNode.h"
#include "Logging/LogMacros.h"
// 定义日志类别
DEFINE_LOG_CATEGORY_STATIC(LogFLESHGraphNode, Log, All);
UFLESHGraphNode::UFLESHGraphNode()
{
// 初始化默认值
NodeTitle = TEXT("FLESH节点");
NodeType = EFLESHNodeType::None;
NodeColor = FLinearColor(0.5f, 0.5f, 0.5f);
NodePosition = FVector2D::ZeroVector;
}
FString UFLESHGraphNode::GetNodeTitle() const
{
return NodeTitle;
}
EFLESHNodeType UFLESHGraphNode::GetNodeType() const
{
return NodeType;
}
FLinearColor UFLESHGraphNode::GetNodeColor() const
{
return NodeColor;
}
FVector2D UFLESHGraphNode::GetNodePosition() const
{
return NodePosition;
}
void UFLESHGraphNode::SetNodePosition(const FVector2D& InPosition)
{
NodePosition = InPosition;
}
TArray<UFLESHGraphNode*> UFLESHGraphNode::GetInputNodes() const
{
return InputNodes;
}
TArray<UFLESHGraphNode*> UFLESHGraphNode::GetOutputNodes() const
{
return OutputNodes;
}
bool UFLESHGraphNode::AddInputNode(UFLESHGraphNode* Node)
{
// 检查节点是否有效
if (!Node)
{
UE_LOG(LogFLESHGraphNode, Warning, TEXT("FLESH: 尝试添加无效的输入节点"));
return false;
}
// 检查节点是否已经在输入列表中
if (InputNodes.Contains(Node))
{
UE_LOG(LogFLESHGraphNode, Warning, TEXT("FLESH: 节点已经在输入列表中: %s"), *Node->GetNodeTitle());
return false;
}
// 添加到输入列表
InputNodes.Add(Node);
UE_LOG(LogFLESHGraphNode, Log, TEXT("FLESH: 添加了输入节点: %s -> %s"), *Node->GetNodeTitle(), *GetNodeTitle());
return true;
}
bool UFLESHGraphNode::AddOutputNode(UFLESHGraphNode* Node)
{
// 检查节点是否有效
if (!Node)
{
UE_LOG(LogFLESHGraphNode, Warning, TEXT("FLESH: 尝试添加无效的输出节点"));
return false;
}
// 检查节点是否已经在输出列表中
if (OutputNodes.Contains(Node))
{
UE_LOG(LogFLESHGraphNode, Warning, TEXT("FLESH: 节点已经在输出列表中: %s"), *Node->GetNodeTitle());
return false;
}
// 添加到输出列表
OutputNodes.Add(Node);
UE_LOG(LogFLESHGraphNode, Log, TEXT("FLESH: 添加了输出节点: %s -> %s"), *GetNodeTitle(), *Node->GetNodeTitle());
return true;
}
bool UFLESHGraphNode::RemoveInputNode(UFLESHGraphNode* Node)
{
// 检查节点是否有效
if (!Node)
{
UE_LOG(LogFLESHGraphNode, Warning, TEXT("FLESH: 尝试移除无效的输入节点"));
return false;
}
// 从输入列表中移除
bool bRemoved = InputNodes.Remove(Node) > 0;
if (bRemoved)
{
UE_LOG(LogFLESHGraphNode, Log, TEXT("FLESH: 移除了输入节点: %s -> %s"), *Node->GetNodeTitle(), *GetNodeTitle());
}
else
{
UE_LOG(LogFLESHGraphNode, Warning, TEXT("FLESH: 节点不在输入列表中: %s"), *Node->GetNodeTitle());
}
return bRemoved;
}
bool UFLESHGraphNode::RemoveOutputNode(UFLESHGraphNode* Node)
{
// 检查节点是否有效
if (!Node)
{
UE_LOG(LogFLESHGraphNode, Warning, TEXT("FLESH: 尝试移除无效的输出节点"));
return false;
}
// 从输出列表中移除
bool bRemoved = OutputNodes.Remove(Node) > 0;
if (bRemoved)
{
UE_LOG(LogFLESHGraphNode, Log, TEXT("FLESH: 移除了输出节点: %s -> %s"), *GetNodeTitle(), *Node->GetNodeTitle());
}
else
{
UE_LOG(LogFLESHGraphNode, Warning, TEXT("FLESH: 节点不在输出列表中: %s"), *Node->GetNodeTitle());
}
return bRemoved;
}
bool UFLESHGraphNode::CompileNode(FFLESHNodeData& OutNodeData)
{
// 设置基本节点数据
OutNodeData.NodeName = FName(*GetNodeTitle());
OutNodeData.NodeType = GetNodeType();
// 设置连接的节点
OutNodeData.ConnectedNodes.Empty();
for (UFLESHGraphNode* OutputNode : OutputNodes)
{
// TODO: 获取节点索引
// OutNodeData.ConnectedNodes.Add(NodeIndex);
}
UE_LOG(LogFLESHGraphNode, Log, TEXT("FLESH: 编译了节点: %s"), *GetNodeTitle());
return true;
}