feature/blend_tree_editor #1

Open
martin wants to merge 29 commits from feature/blend_tree_editor into main
4 changed files with 86 additions and 28 deletions
Showing only changes of commit a098bc1171 - Show all commits

View File

@ -257,8 +257,7 @@ public:
double sync_position = 0.0;
bool is_synced = false;
// TODO: 2026-02-17: how to initialize loop_mode e.g. for a BlendTree or a StateMachine?
Animation::LoopMode loop_mode = Animation::LOOP_LINEAR;
Animation::LoopMode loop_mode = Animation::LOOP_NONE;
SyncTrack sync_track;
};
NodeTimeInfo node_time_info;
@ -753,6 +752,8 @@ public:
}
tree_graph.nodes[0]->active = true;
tree_graph.nodes[0]->node_time_info.is_synced = node_time_info.is_synced;
for (uint32_t i = 0; i < tree_graph.nodes.size(); i++) {
const Ref<BLTAnimationNode> &node = tree_graph.nodes[i];
@ -777,14 +778,21 @@ public:
const NodeRuntimeData &node_runtime_data = _node_runtime_data[i];
node->calculate_sync_track(node_runtime_data.input_nodes);
if (i == 1) {
node_time_info = node->node_time_info;
}
}
}
void update_time(double p_delta) override {
GodotProfileZone("SyncedBlendTree::update_time");
tree_graph.nodes[0]->node_time_info.delta = p_delta;
tree_graph.nodes[0]->node_time_info.position += p_delta;
BLTAnimationNode::update_time(p_delta);
tree_graph.nodes[0]->node_time_info.delta = node_time_info.delta;
tree_graph.nodes[0]->node_time_info.position = node_time_info.position;
tree_graph.nodes[0]->node_time_info.sync_position = node_time_info.sync_position;
for (uint32_t i = 1; i < tree_graph.nodes.size(); i++) {
const Ref<BLTAnimationNode> &node = tree_graph.nodes[i];

View File

@ -8,7 +8,28 @@ animation = &"Walk-InPlace"
[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_lquwl"]
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_vyt75"]
[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_hom0r"]
[sub_resource type="AnimationNodeBlendTree" id="AnimationNodeBlendTree_vyt75"]
[sub_resource type="AnimationNodeBlendTree" id="AnimationNodeBlendTree_1rfsi"]
nodes/BlendTree/node = SubResource("AnimationNodeBlendTree_vyt75")
nodes/BlendTree/position = Vector2(694.9995, 215.55058)
[sub_resource type="AnimationNodeBlendTree" id="AnimationNodeBlendTree_8tpve"]
graph_offset = Vector2(-782, 179.47485)
nodes/Animation/node = SubResource("AnimationNodeAnimation_vyt75")
nodes/Animation/position = Vector2(-320, 140)
nodes/Blend2/node = SubResource("AnimationNodeBlend2_hom0r")
nodes/Blend2/position = Vector2(-115.66393, 127.37674)
nodes/BlendTree/node = SubResource("AnimationNodeBlendTree_1rfsi")
nodes/BlendTree/position = Vector2(-480, 400)
node_connections = [&"output", 0, &"Blend2", &"Blend2", 0, &"Animation", &"Blend2", 1, &"BlendTree"]
[resource]
graph_offset = Vector2(-217.4643, 82.84979)
nodes/output/position = Vector2(540, 140)
nodes/Animation/node = SubResource("AnimationNodeAnimation_1bvp3")
nodes/Animation/position = Vector2(120, 80)
@ -16,4 +37,6 @@ nodes/Animation/position = Vector2(120, 80)
"nodes/Animation 2/position" = Vector2(80, 320)
nodes/Blend2/node = SubResource("AnimationNodeBlend2_lquwl")
nodes/Blend2/position = Vector2(360, 180)
nodes/BlendTree/node = SubResource("AnimationNodeBlendTree_8tpve")
nodes/BlendTree/position = Vector2(778.0867, 295.33868)
node_connections = [&"output", 0, &"Blend2", &"Blend2", 0, &"Animation", &"Blend2", 1, &"Animation 2"]

View File

@ -34,6 +34,7 @@ glow_enabled = true
[sub_resource type="BLTAnimationNodeBlend2" id="BLTAnimationNodeBlend2_7mycd"]
resource_name = "BLTAnimationNodeBlend2"
position = Vector2(-320, -40)
blend_amount = 0.81
[sub_resource type="BLTAnimationNodeSampler" id="BLTAnimationNodeSampler_272bh"]
resource_name = "BLTAnimationNodeSampler"
@ -43,7 +44,7 @@ animation = &"animation_library/Walk-InPlace"
[sub_resource type="BLTAnimationNodeBlendTree" id="BLTAnimationNodeBlendTree_5vw27"]
resource_name = "BLTAnimationNodeBlendTree"
position = Vector2(-640, -20)
graph_offset = Vector2(-766.67163, -102.823944)
graph_offset = Vector2(-760.67163, -24.823944)
nodes/BLTAnimationNodeSampler/node = SubResource("BLTAnimationNodeSampler_272bh")
nodes/BLTAnimationNodeSampler/graph_offset = Vector2(-490, 7)
node_connections = ["Output", 0, "BLTAnimationNodeSampler"]
@ -51,11 +52,11 @@ node_connections = ["Output", 0, "BLTAnimationNodeSampler"]
[sub_resource type="BLTAnimationNodeSampler" id="BLTAnimationNodeSampler_kek77"]
resource_name = "BLTAnimationNodeSampler"
position = Vector2(-620, 140)
animation = &"animation_library/Walk-InPlace"
animation = &"animation_library/Run-InPlace"
[sub_resource type="BLTAnimationNodeBlendTree" id="BLTAnimationNodeBlendTree_7mycd"]
resource_name = "Root"
graph_offset = Vector2(-1054.4585, -50.771484)
graph_offset = Vector2(-869, -71)
nodes/BLTAnimationNodeBlend2/node = SubResource("BLTAnimationNodeBlend2_7mycd")
nodes/BLTAnimationNodeBlend2/graph_offset = Vector2(-320, -40)
nodes/BLTAnimationNodeSampler/node = SubResource("BLTAnimationNodeSampler_kek77")
@ -318,7 +319,7 @@ libraries/animation_library = ExtResource("3_1bvp3")
animation_player = NodePath("../AnimationPlayer2")
tree_root = SubResource("BLTAnimationNodeBlendTree_7mycd")
skeleton = NodePath("../Armature/Skeleton3D")
parameters/BLTAnimationNodeBlend2/blend_amount = 0.0
parameters/BLTAnimationNodeBlend2/blend_amount = 0.81
[connection signal="value_changed" from="UI/MarginContainer/HBoxContainer/BlendWeightSlider" to="." method="_on_blend_weight_slider_value_changed"]

View File

@ -607,7 +607,6 @@ TEST_CASE_FIXTURE(BlendTreeFixture, "[SceneTree][Blendalot][BlendTreeGraph][Embe
// TestAnimationB
Ref<BLTAnimationNodeSampler> animation_sampler_node_b;
animation_sampler_node_b.instantiate();
animation_sampler_node_b->animation_name = "animation_library/TestAnimationB";
embedded_blend_tree->add_node(animation_sampler_node_b);
embedded_blend_tree->add_connection(animation_sampler_node_b, embedded_blend_tree->get_output_node(), "Output");
@ -619,15 +618,11 @@ TEST_CASE_FIXTURE(BlendTreeFixture, "[SceneTree][Blendalot][BlendTreeGraph][Embe
Ref<BLTAnimationNodeBlend2> blend2;
blend2.instantiate();
blend2->set_name("Blend2");
blend2->blend_weight = 0.5;
blend2->sync = true;
blend_tree->add_node(blend2);
// TestAnimationA
Ref<BLTAnimationNodeSampler> animation_sampler_node_a;
animation_sampler_node_a.instantiate();
animation_sampler_node_a->animation_name = "animation_library/TestAnimationA";
blend_tree->add_node(animation_sampler_node_a);
@ -637,6 +632,12 @@ TEST_CASE_FIXTURE(BlendTreeFixture, "[SceneTree][Blendalot][BlendTreeGraph][Embe
blend_tree->add_connection(embedded_blend_tree, blend2, "Input1");
blend_tree->add_connection(blend2, blend_tree->get_output_node(), "Output");
SUBCASE("Perform regular blend") {
animation_sampler_node_b->animation_name = "animation_library/TestAnimationB";
animation_sampler_node_a->animation_name = "animation_library/TestAnimationA";
blend2->blend_weight = 0.5;
blend2->sync = false;
// Trigger initialization
animation_graph->set_root_animation_node(blend_tree);
GraphEvaluationContext &graph_context = animation_graph->get_context();
@ -654,6 +655,31 @@ TEST_CASE_FIXTURE(BlendTreeFixture, "[SceneTree][Blendalot][BlendTreeGraph][Embe
CHECK(hip_transform_value->loc[0] == doctest::Approx(0.15));
CHECK(hip_transform_value->loc[1] == doctest::Approx(0.3));
CHECK(hip_transform_value->loc[2] == doctest::Approx(0.45));
}
SUBCASE("Perform synced blend") {
animation_sampler_node_b->animation_name = "animation_library/TestAnimationSyncA";
animation_sampler_node_a->animation_name = "animation_library/TestAnimationSyncB";
blend2->blend_weight = 0.5;
blend2->sync = true;
// Trigger initialization
animation_graph->set_root_animation_node(blend_tree);
GraphEvaluationContext &graph_context = animation_graph->get_context();
REQUIRE(blend_tree->initialize(graph_context));
// Perform evaluation
AnimationData *graph_output = graph_context.animation_data_allocator.allocate();
blend_tree->activate_inputs(Vector<Ref<BLTAnimationNode>>());
blend_tree->calculate_sync_track(Vector<Ref<BLTAnimationNode>>());
blend_tree->update_time(0.825);
blend_tree->evaluate(graph_context, LocalVector<AnimationData *>(), *graph_output);
// Check values
AnimationData::TransformTrackValue *hip_transform_value = graph_output->get_value<AnimationData::TransformTrackValue>(test_animation_a->get_tracks()[0]->thash);
CHECK(hip_transform_value->loc[0] == doctest::Approx(1.5));
CHECK(hip_transform_value->loc[1] == doctest::Approx(3.0));
CHECK(hip_transform_value->loc[2] == doctest::Approx(4.5));
}
}
} //namespace TestBlendalotAnimationGraph