Fixed memory leak by introducing virtual node descriptors.

AnimNodeResources do not reference an actual node anymore. However, we still need descriptors to check whether connections are valid.

For this we have VirtualNodeDescriptors for which all sockets point to nullptr.
This commit is contained in:
Martin Felis
2025-02-16 14:22:13 +01:00
parent 4b378adc91
commit 40f631c51a
7 changed files with 175 additions and 162 deletions
+45 -43
View File
@@ -32,12 +32,12 @@ class SimpleAnimSamplerGraphResource {
blend_tree_resource->AddNode(AnimNodeResourceFactory("AnimSampler"));
walk_node = blend_tree_resource->GetNode(walk_node_index);
walk_node->m_name = "WalkAnim";
walk_node->m_socket_accessor->SetPropertyValue(
walk_node->m_virtual_socket_accessor->SetPropertyValue(
"Filename",
std::string("media/Walking-loop.ozz"));
AnimNodeResource* graph_node = blend_tree_resource->GetGraphOutputNode();
graph_node->m_socket_accessor->RegisterInput<AnimData>(
graph_node->m_virtual_socket_accessor->RegisterInput<AnimData>(
"GraphOutput",
nullptr);
@@ -81,11 +81,11 @@ class Blend2GraphResource {
walk_node = blend_tree_resource->GetNode(walk_node_index);
walk_node->m_name = "WalkAnim";
walk_node->m_socket_accessor->SetPropertyValue(
walk_node->m_virtual_socket_accessor->SetPropertyValue(
"Filename",
std::string("media/Walking-loop.ozz"));
run_node = blend_tree_resource->GetNode(run_node_index);
run_node->m_socket_accessor->SetPropertyValue(
run_node->m_virtual_socket_accessor->SetPropertyValue(
"Filename",
std::string("media/Running0-loop.ozz"));
run_node->m_name = "RunAnim";
@@ -93,14 +93,16 @@ class Blend2GraphResource {
blend_node->m_name = "BlendWalkRun";
AnimNodeResource* graph_node = blend_tree_resource->GetGraphOutputNode();
graph_node->m_socket_accessor->RegisterInput<AnimData>(
graph_node->m_virtual_socket_accessor->RegisterInput<AnimData>(
"GraphOutput",
nullptr);
REQUIRE(graph_node->m_socket_accessor->m_inputs.size() == 1);
REQUIRE(blend_node->m_socket_accessor->GetInputIndex("Input0") == 0);
REQUIRE(blend_node->m_socket_accessor->GetInputIndex("Input1") == 1);
blend_node->m_socket_accessor->SetInputValue("Weight", 0.123f);
REQUIRE(graph_node->m_virtual_socket_accessor->m_inputs.size() == 1);
REQUIRE(
blend_node->m_virtual_socket_accessor->GetInputIndex("Input0") == 0);
REQUIRE(
blend_node->m_virtual_socket_accessor->GetInputIndex("Input1") == 1);
blend_node->m_virtual_socket_accessor->SetInputValue("Weight", 0.123f);
blend_tree_resource
->ConnectSockets(walk_node, "Output", blend_node, "Input0");
@@ -152,9 +154,8 @@ class EmbeddedBlendTreeGraphResource {
// Setup parent outputs
AnimNodeResource* parent_blend_tree_outputs =
parent_blend_tree_resource->GetGraphOutputNode();
parent_blend_tree_outputs->m_socket_accessor->RegisterInput<AnimData>(
"Output",
nullptr);
parent_blend_tree_outputs->m_virtual_socket_accessor
->RegisterInput<AnimData>("Output", nullptr);
// Parent AnimSampler
walk_node_index = parent_blend_tree_resource->AddNode(
@@ -162,7 +163,7 @@ class EmbeddedBlendTreeGraphResource {
walk_node_resource = parent_blend_tree_resource->GetNode(walk_node_index);
walk_node_resource->m_name = "WalkAnim";
walk_node_resource->m_socket_accessor->SetPropertyValue(
walk_node_resource->m_virtual_socket_accessor->SetPropertyValue(
"Filename",
std::string("media/Walking-loop.ozz"));
@@ -181,14 +182,14 @@ class EmbeddedBlendTreeGraphResource {
// Embedded: outputs
AnimNodeResource* embedded_outputs =
embedded_blend_tree_resource->GetGraphOutputNode();
embedded_outputs->m_socket_accessor->RegisterInput<AnimData>(
embedded_outputs->m_virtual_socket_accessor->RegisterInput<AnimData>(
"AnimOutput",
nullptr);
// Embedded: inputs
AnimNodeResource* embedded_inputs =
embedded_blend_tree_resource->GetGraphInputNode();
embedded_inputs->m_socket_accessor->RegisterOutput<AnimData>(
embedded_inputs->m_virtual_socket_accessor->RegisterOutput<AnimData>(
"AnimInput",
nullptr);
@@ -197,7 +198,7 @@ class EmbeddedBlendTreeGraphResource {
AnimNodeResourceFactory("SpeedScale"));
AnimNodeResource* embedded_speed_scale_resource =
embedded_blend_tree_resource->GetNode(embedded_speed_scale_index);
embedded_speed_scale_resource->m_socket_accessor->SetInputValue(
embedded_speed_scale_resource->m_virtual_socket_accessor->SetInputValue(
"SpeedScale",
0.1f);
@@ -270,14 +271,13 @@ class EmbeddedTreeBlend2GraphResource {
// Setup parent outputs
AnimNodeResource* parent_blend_tree_outputs =
parent_blend_tree_resource->GetGraphOutputNode();
parent_blend_tree_outputs->m_socket_accessor->RegisterInput<AnimData>(
"Output",
nullptr);
parent_blend_tree_outputs->m_virtual_socket_accessor
->RegisterInput<AnimData>("Output", nullptr);
// Setup parent inputs
AnimNodeResource* parent_blend_tree_inputs =
parent_blend_tree_resource->GetGraphInputNode();
parent_blend_tree_inputs->m_socket_accessor->RegisterOutput<float>(
parent_blend_tree_inputs->m_virtual_socket_accessor->RegisterOutput<float>(
"EmbeddedBlend2Weight",
nullptr);
@@ -287,7 +287,7 @@ class EmbeddedTreeBlend2GraphResource {
walk_node_resource = parent_blend_tree_resource->GetNode(walk_node_index);
walk_node_resource->m_name = "WalkAnim";
walk_node_resource->m_socket_accessor->SetPropertyValue(
walk_node_resource->m_virtual_socket_accessor->SetPropertyValue(
"Filename",
std::string("media/Walking-loop.ozz"));
@@ -320,14 +320,14 @@ class EmbeddedTreeBlend2GraphResource {
// Configure node resources
embedded_blend2_node_resource =
embedded_blend_tree_resource->GetNode(embedded_blend2_node_index);
embedded_blend2_node_resource->m_socket_accessor->SetInputValue(
embedded_blend2_node_resource->m_virtual_socket_accessor->SetInputValue(
"Weight",
0.1f);
embedded_run_node_resource =
embedded_blend_tree_resource->GetNode(embedded_run_node_index);
embedded_run_node_resource->m_name = "RunAnim";
embedded_run_node_resource->m_socket_accessor->SetPropertyValue(
embedded_run_node_resource->m_virtual_socket_accessor->SetPropertyValue(
"Filename",
std::string("media/RunningSlow-loop.ozz"));
@@ -562,7 +562,7 @@ TEST_CASE("AnimSamplerSpeedScaleGraph", "[AnimGraphResource]") {
AnimNodeResource* walk_node = blend_tree_resource.GetNode(walk_node_index);
walk_node->m_name = "WalkAnim";
walk_node->m_socket_accessor->SetPropertyValue(
walk_node->m_virtual_socket_accessor->SetPropertyValue(
"Filename",
std::string("media/Walking-loop.ozz"));
@@ -570,12 +570,12 @@ TEST_CASE("AnimSamplerSpeedScaleGraph", "[AnimGraphResource]") {
blend_tree_resource.GetNode(speed_scale_node_index);
speed_scale_node->m_name = "SpeedScale";
float speed_scale_value = 1.35f;
speed_scale_node->m_socket_accessor->SetInputValue(
speed_scale_node->m_virtual_socket_accessor->SetInputValue(
"SpeedScale",
speed_scale_value);
AnimNodeResource* graph_node = blend_tree_resource.GetGraphOutputNode();
graph_node->m_socket_accessor->RegisterInput<AnimData>(
graph_node->m_virtual_socket_accessor->RegisterInput<AnimData>(
"GraphOutput",
nullptr);
@@ -599,7 +599,7 @@ TEST_CASE("AnimSamplerSpeedScaleGraph", "[AnimGraphResource]") {
Socket* speed_scale_resource_loaded_input =
blend_tree_resource_loaded.GetNode(speed_scale_node_index)
->m_socket_accessor->GetInputSocket("SpeedScale");
->m_virtual_socket_accessor->GetInputSocket("SpeedScale");
REQUIRE(speed_scale_resource_loaded_input != nullptr);
REQUIRE_THAT(
@@ -725,10 +725,10 @@ TEST_CASE_METHOD(
const NodeDescriptor<Blend2Node>* blend2_node_descriptor_loaded =
dynamic_cast<NodeDescriptor<Blend2Node>*>(
blend_tree_resource_loaded->GetNode(blend_node_index)
->m_socket_accessor);
->m_virtual_socket_accessor);
REQUIRE_THAT(
blend_node->m_socket_accessor->GetInputValue<float>("Weight"),
blend_node->m_virtual_socket_accessor->GetInputValue<float>("Weight"),
Catch::Matchers::WithinAbs(
blend2_node_descriptor_loaded->GetInputValue<float>("Weight"),
0.01));
@@ -852,16 +852,16 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") {
AnimNodeResource* graph_output_node =
blend_tree_resource.GetGraphOutputNode();
graph_output_node->m_socket_accessor->RegisterInput<float>(
graph_output_node->m_virtual_socket_accessor->RegisterInput<float>(
"GraphFloatOutput",
nullptr);
graph_output_node->m_socket_accessor->RegisterInput<Vec3>(
graph_output_node->m_virtual_socket_accessor->RegisterInput<Vec3>(
"GraphVec3Output",
nullptr);
AnimNodeResource* graph_input_node_resource =
blend_tree_resource.GetGraphInputNode();
graph_input_node_resource->m_socket_accessor->RegisterOutput<float>(
graph_input_node_resource->m_virtual_socket_accessor->RegisterOutput<float>(
"GraphFloatInput",
nullptr);
@@ -914,24 +914,26 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") {
THEN("Graph inputs and outputs must be in loaded resource as well.") {
REQUIRE(
graph_output_node->m_socket_accessor->m_inputs.size()
== graph_loaded_output_node->m_socket_accessor->m_inputs.size());
graph_output_node->m_virtual_socket_accessor->m_inputs.size()
== graph_loaded_output_node->m_virtual_socket_accessor->m_inputs
.size());
REQUIRE(
graph_input_node_resource->m_socket_accessor->m_outputs.size()
== graph_loaded_input_node->m_socket_accessor->m_outputs.size());
graph_input_node_resource->m_virtual_socket_accessor->m_outputs.size()
== graph_loaded_input_node->m_virtual_socket_accessor->m_outputs
.size());
REQUIRE(
graph_loaded_input_node->m_socket_accessor->GetOutputSocket(
graph_loaded_input_node->m_virtual_socket_accessor->GetOutputSocket(
"GraphFloatInput")
!= nullptr);
REQUIRE(
graph_loaded_output_node->m_socket_accessor->GetInputSocket(
graph_loaded_output_node->m_virtual_socket_accessor->GetInputSocket(
"GraphFloatOutput")
!= nullptr);
REQUIRE(
graph_loaded_output_node->m_socket_accessor->GetInputSocket(
graph_loaded_output_node->m_virtual_socket_accessor->GetInputSocket(
"GraphVec3Output")
!= nullptr);
@@ -1012,18 +1014,18 @@ TEST_CASE("SimpleMathEvaluations", "[AnimGraphResource]") {
AnimNodeResource* graph_output_node =
blend_tree_resource.GetGraphOutputNode();
graph_output_node->m_socket_accessor->RegisterInput<float>(
graph_output_node->m_virtual_socket_accessor->RegisterInput<float>(
"GraphFloat0Output",
nullptr);
graph_output_node->m_socket_accessor->RegisterInput<float>(
graph_output_node->m_virtual_socket_accessor->RegisterInput<float>(
"GraphFloat1Output",
nullptr);
graph_output_node->m_socket_accessor->RegisterInput<float>(
graph_output_node->m_virtual_socket_accessor->RegisterInput<float>(
"GraphFloat2Output",
nullptr);
AnimNodeResource* graph_input_node = blend_tree_resource.GetGraphInputNode();
graph_input_node->m_socket_accessor->RegisterOutput<float>(
graph_input_node->m_virtual_socket_accessor->RegisterOutput<float>(
"GraphFloatInput",
nullptr);