Skip to content

Commit 9b20f94

Browse files
committed
Add BlendSpace BlendPoint weight smoothing
1 parent ce94b26 commit 9b20f94

10 files changed

+208
-19
lines changed

doc/classes/AnimationNodeBlendSpace1D.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@
7575
<member name="min_space" type="float" setter="set_min_space" getter="get_min_space" default="-1.0">
7676
The blend space's axis's lower limit for the points' position. See [method add_blend_point].
7777
</member>
78+
<member name="smooth" type="bool" setter="set_use_smooth" getter="is_using_smooth" default="false">
79+
If [code]true[/code], while [member sync] is [code]true[/code] a blend point's weight is applied over time using [member smooth_speed].
80+
</member>
81+
<member name="smooth_speed" type="float" setter="set_smooth_speed" getter="get_smooth_speed" default="1.0">
82+
Controls the blend point smoothing speed.
83+
</member>
7884
<member name="snap" type="float" setter="set_snap" getter="get_snap" default="0.1">
7985
Position increment to snap to when moving a point on the axis.
8086
</member>

doc/classes/AnimationNodeBlendSpace2D.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@
110110
<member name="min_space" type="Vector2" setter="set_min_space" getter="get_min_space" default="Vector2(-1, -1)">
111111
The blend space's X and Y axes' lower limit for the points' position. See [method add_blend_point].
112112
</member>
113+
<member name="smooth" type="bool" setter="set_use_smooth" getter="is_using_smooth" default="false">
114+
If [code]true[/code], while [member sync] is [code]true[/code] a blend point's weight is applied over time using [member smooth_speed].
115+
</member>
116+
<member name="smooth_speed" type="float" setter="set_smooth_speed" getter="get_smooth_speed" default="1.0">
117+
Controls the blend point smoothing speed.
118+
</member>
113119
<member name="snap" type="Vector2" setter="set_snap" getter="get_snap" default="Vector2(0.1, 0.1)">
114120
Position increment to snap to when moving a point.
115121
</member>

editor/plugins/animation_blend_space_1d_editor.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,8 @@ void AnimationNodeBlendSpace1DEditor::_update_space() {
336336

337337
sync->set_pressed(blend_space->is_using_sync());
338338
interpolation->select(blend_space->get_blend_mode());
339+
smooth->set_pressed(blend_space->is_using_smooth());
340+
smooth_speed->set_value(blend_space->get_smooth_speed());
339341

340342
label_value->set_text(blend_space->get_value_label());
341343

@@ -364,6 +366,11 @@ void AnimationNodeBlendSpace1DEditor::_config_changed(double) {
364366
undo_redo->add_undo_method(blend_space.ptr(), "set_use_sync", blend_space->is_using_sync());
365367
undo_redo->add_do_method(blend_space.ptr(), "set_blend_mode", interpolation->get_selected());
366368
undo_redo->add_undo_method(blend_space.ptr(), "set_blend_mode", blend_space->get_blend_mode());
369+
undo_redo->add_do_method(blend_space.ptr(), "set_use_smooth", smooth->is_pressed());
370+
undo_redo->add_undo_method(blend_space.ptr(), "set_use_smooth", blend_space->is_using_smooth());
371+
smooth_hb->set_visible((sync->is_pressed() && interpolation->get_selected() == AnimationNodeBlendSpace1D::BLEND_MODE_INTERPOLATED));
372+
undo_redo->add_do_method(blend_space.ptr(), "set_smooth_speed", smooth_speed->get_value());
373+
undo_redo->add_undo_method(blend_space.ptr(), "set_use_smooth", blend_space->get_smooth_speed());
367374
undo_redo->add_do_method(this, "_update_space");
368375
undo_redo->add_undo_method(this, "_update_space");
369376
undo_redo->commit_action();
@@ -646,6 +653,8 @@ void AnimationNodeBlendSpace1DEditor::edit(const Ref<AnimationNode> &p_node) {
646653
min_value->set_editable(!read_only);
647654
max_value->set_editable(!read_only);
648655
sync->set_disabled(read_only);
656+
smooth->set_disabled(read_only);
657+
smooth_speed->set_editable(!read_only);
649658
interpolation->set_disabled(read_only);
650659
}
651660

@@ -728,6 +737,24 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() {
728737
top_hb->add_child(interpolation);
729738
interpolation->connect(SceneStringName(item_selected), callable_mp(this, &AnimationNodeBlendSpace1DEditor::_config_changed));
730739

740+
smooth_hb = memnew(HBoxContainer);
741+
top_hb->add_child(smooth_hb);
742+
smooth_hb->add_child(memnew(VSeparator));
743+
744+
smooth_hb->add_child(memnew(Label(TTR("Smooth:"))));
745+
smooth = memnew(CheckBox);
746+
smooth_hb->add_child(smooth);
747+
smooth->connect(SceneStringName(toggled), callable_mp(this, &AnimationNodeBlendSpace1DEditor::_config_changed));
748+
749+
smooth_hb->add_child(memnew(Label(TTR("Speed:"))));
750+
751+
smooth_speed = memnew(SpinBox);
752+
smooth_hb->add_child(smooth_speed);
753+
smooth_speed->set_min(0.01);
754+
smooth_speed->set_step(0.01);
755+
smooth_speed->set_max(1000);
756+
smooth_speed->connect(SceneStringName(value_changed), callable_mp(this, &AnimationNodeBlendSpace1DEditor::_config_changed));
757+
731758
edit_hb = memnew(HBoxContainer);
732759
top_hb->add_child(edit_hb);
733760
edit_hb->add_child(memnew(VSeparator));

editor/plugins/animation_blend_space_1d_editor.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin {
6868
CheckBox *sync = nullptr;
6969
OptionButton *interpolation = nullptr;
7070

71+
HBoxContainer *smooth_hb = nullptr;
72+
CheckBox *smooth = nullptr;
73+
SpinBox *smooth_speed = nullptr;
74+
7175
HBoxContainer *edit_hb = nullptr;
7276
SpinBox *edit_value = nullptr;
7377
Button *open_editor = nullptr;

editor/plugins/animation_blend_space_2d_editor.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ void AnimationNodeBlendSpace2DEditor::edit(const Ref<AnimationNode> &p_node) {
8888
tool_triangle->set_disabled(read_only);
8989
auto_triangles->set_disabled(read_only);
9090
sync->set_disabled(read_only);
91+
smooth->set_disabled(read_only);
9192
interpolation->set_disabled(read_only);
9293
}
9394

@@ -650,6 +651,8 @@ void AnimationNodeBlendSpace2DEditor::_update_space() {
650651

651652
sync->set_pressed(blend_space->is_using_sync());
652653
interpolation->select(blend_space->get_blend_mode());
654+
smooth->set_pressed(blend_space->is_using_smooth());
655+
smooth_speed->set_value(blend_space->get_smooth_speed());
653656

654657
max_x_value->set_value(blend_space->get_max_space().x);
655658
max_y_value->set_value(blend_space->get_max_space().y);
@@ -686,6 +689,12 @@ void AnimationNodeBlendSpace2DEditor::_config_changed(double) {
686689
undo_redo->add_undo_method(blend_space.ptr(), "set_use_sync", blend_space->is_using_sync());
687690
undo_redo->add_do_method(blend_space.ptr(), "set_blend_mode", interpolation->get_selected());
688691
undo_redo->add_undo_method(blend_space.ptr(), "set_blend_mode", blend_space->get_blend_mode());
692+
undo_redo->add_do_method(blend_space.ptr(), "set_use_smooth", smooth->is_pressed());
693+
smooth_hb->set_visible((sync->is_pressed() && interpolation->get_selected() == AnimationNodeBlendSpace2D::BLEND_MODE_INTERPOLATED));
694+
undo_redo->add_undo_method(blend_space.ptr(), "set_use_smooth", blend_space->is_using_smooth());
695+
undo_redo->add_do_method(blend_space.ptr(), "set_smooth_speed", smooth_speed->get_value());
696+
undo_redo->add_undo_method(blend_space.ptr(), "set_use_smooth", blend_space->get_smooth_speed());
697+
689698
undo_redo->add_do_method(this, "_update_space");
690699
undo_redo->add_undo_method(this, "_update_space");
691700
undo_redo->commit_action();
@@ -978,6 +987,24 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() {
978987
top_hb->add_child(interpolation);
979988
interpolation->connect(SceneStringName(item_selected), callable_mp(this, &AnimationNodeBlendSpace2DEditor::_config_changed));
980989

990+
smooth_hb = memnew(HBoxContainer);
991+
top_hb->add_child(smooth_hb);
992+
smooth_hb->add_child(memnew(VSeparator));
993+
994+
smooth_hb->add_child(memnew(Label(TTR("Smooth:"))));
995+
smooth = memnew(CheckBox);
996+
smooth_hb->add_child(smooth);
997+
smooth->connect(SceneStringName(toggled), callable_mp(this, &AnimationNodeBlendSpace2DEditor::_config_changed));
998+
999+
smooth_hb->add_child(memnew(Label(TTR("Speed:"))));
1000+
1001+
smooth_speed = memnew(SpinBox);
1002+
smooth_hb->add_child(smooth_speed);
1003+
smooth_speed->set_min(0.01);
1004+
smooth_speed->set_step(0.01);
1005+
smooth_speed->set_max(1000);
1006+
smooth_speed->connect(SceneStringName(value_changed), callable_mp(this, &AnimationNodeBlendSpace2DEditor::_config_changed));
1007+
9811008
edit_hb = memnew(HBoxContainer);
9821009
top_hb->add_child(edit_hb);
9831010
edit_hb->add_child(memnew(VSeparator));

editor/plugins/animation_blend_space_2d_editor.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,13 @@ class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin {
6060
SpinBox *snap_x = nullptr;
6161
SpinBox *snap_y = nullptr;
6262
CheckBox *sync = nullptr;
63+
6364
OptionButton *interpolation = nullptr;
6465

66+
HBoxContainer *smooth_hb = nullptr;
67+
CheckBox *smooth = nullptr;
68+
SpinBox *smooth_speed = nullptr;
69+
6570
Button *auto_triangles = nullptr;
6671

6772
LineEdit *label_x = nullptr;

scene/animation/animation_blend_space_1d.cpp

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ void AnimationNodeBlendSpace1D::_bind_methods() {
104104
ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeBlendSpace1D::set_use_sync);
105105
ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeBlendSpace1D::is_using_sync);
106106

107+
ClassDB::bind_method(D_METHOD("set_smooth_speed", "speed"), &AnimationNodeBlendSpace1D::set_smooth_speed);
108+
ClassDB::bind_method(D_METHOD("get_smooth_speed"), &AnimationNodeBlendSpace1D::get_smooth_speed);
109+
110+
ClassDB::bind_method(D_METHOD("set_use_smooth", "enable"), &AnimationNodeBlendSpace1D::set_use_smooth);
111+
ClassDB::bind_method(D_METHOD("is_using_smooth"), &AnimationNodeBlendSpace1D::is_using_smooth);
112+
107113
ClassDB::bind_method(D_METHOD("_add_blend_point", "index", "node"), &AnimationNodeBlendSpace1D::_add_blend_point);
108114

109115
for (int i = 0; i < MAX_BLEND_POINTS; i++) {
@@ -117,6 +123,8 @@ void AnimationNodeBlendSpace1D::_bind_methods() {
117123
ADD_PROPERTY(PropertyInfo(Variant::STRING, "value_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_value_label", "get_value_label");
118124
ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Interpolated,Discrete,Carry", PROPERTY_USAGE_NO_EDITOR), "set_blend_mode", "get_blend_mode");
119125
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_use_sync", "is_using_sync");
126+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smooth", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_use_smooth", "is_using_smooth");
127+
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "smooth_speed", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_smooth_speed", "get_smooth_speed");
120128

121129
BIND_ENUM_CONSTANT(BLEND_MODE_INTERPOLATED);
122130
BIND_ENUM_CONSTANT(BLEND_MODE_DISCRETE);
@@ -269,6 +277,21 @@ bool AnimationNodeBlendSpace1D::is_using_sync() const {
269277
return sync;
270278
}
271279

280+
void AnimationNodeBlendSpace1D::set_smooth_speed(const float &p_speed) {
281+
smooth_speed = p_speed;
282+
}
283+
284+
float AnimationNodeBlendSpace1D::get_smooth_speed() const {
285+
return smooth_speed;
286+
}
287+
void AnimationNodeBlendSpace1D::set_use_smooth(const bool &p_smooth) {
288+
smooth = p_smooth;
289+
}
290+
291+
bool AnimationNodeBlendSpace1D::is_using_smooth() const {
292+
return smooth;
293+
}
294+
272295
void AnimationNodeBlendSpace1D::_add_blend_point(int p_index, const Ref<AnimationRootNode> &p_node) {
273296
if (p_index == blend_points_used) {
274297
add_blend_point(p_node, 0);
@@ -281,7 +304,6 @@ AnimationNode::NodeTimeInfo AnimationNodeBlendSpace1D::_process(const AnimationM
281304
if (!blend_points_used) {
282305
return NodeTimeInfo();
283306
}
284-
285307
AnimationMixer::PlaybackInfo pi = p_playback_info;
286308

287309
if (blend_points_used == 1) {
@@ -347,18 +369,46 @@ AnimationNode::NodeTimeInfo AnimationNodeBlendSpace1D::_process(const AnimationM
347369
// actually blend the animations now
348370
bool first = true;
349371
double max_weight = 0.0;
372+
373+
int mind_idx = 0;
374+
//calculate the true weights before hand
350375
for (int i = 0; i < blend_points_used; i++) {
376+
bool found = false;
351377
if (i == point_lower || i == point_higher) {
352-
pi.weight = weights[i];
353-
NodeTimeInfo t = blend_node(blend_points[i].node, blend_points[i].name, pi, FILTER_IGNORE, true, p_test_only);
354-
if (first || pi.weight > max_weight) {
378+
blend_points[i].weight = (smooth && sync) ? Math::move_toward(blend_points[i].weight, weights[i], static_cast<float>(pi.delta * smooth_speed)) : weights[i];
379+
if (first || blend_points[i].weight > max_weight) {
355380
max_weight = pi.weight;
356-
mind = t;
357381
first = false;
358382
}
359-
} else if (sync) {
360-
pi.weight = 0;
361-
blend_node(blend_points[i].node, blend_points[i].name, pi, FILTER_IGNORE, true, p_test_only);
383+
found = true;
384+
}
385+
if (!found) {
386+
if (sync) {
387+
blend_points[i].weight = (smooth) ? MAX(Math::move_toward(blend_points[i].weight, 0.0f, static_cast<float>(pi.delta * smooth_speed)), 0.0) : 0.0;
388+
} else {
389+
blend_points[i].weight = -1.0;
390+
}
391+
}
392+
}
393+
float sum_of_weight = 0.0;
394+
if (smooth && sync) {
395+
for (int i = 0; i < blend_points_used; i++) {
396+
sum_of_weight += blend_points[i].weight;
397+
}
398+
if (sum_of_weight <= 0.0) {
399+
sum_of_weight = 1.0;
400+
}
401+
}
402+
//now we apply them
403+
for (int i = 0; i < blend_points_used; i++) {
404+
blend_points[i].weight = (smooth && sync) ? blend_points[i].weight / sum_of_weight : blend_points[i].weight;
405+
if (blend_points[i].weight == -1.0) {
406+
continue;
407+
}
408+
pi.weight = blend_points[i].weight;
409+
NodeTimeInfo t = blend_node(blend_points[i].node, blend_points[i].name, pi, FILTER_IGNORE, true, p_test_only);
410+
if (mind_idx == i) {
411+
mind = t;
362412
}
363413
}
364414
} else {

scene/animation/animation_blend_space_1d.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class AnimationNodeBlendSpace1D : public AnimationRootNode {
5151
StringName name;
5252
Ref<AnimationRootNode> node;
5353
float position = 0.0;
54+
float weight = 0.0;
5455
};
5556

5657
BlendPoint blend_points[MAX_BLEND_POINTS];
@@ -61,6 +62,9 @@ class AnimationNodeBlendSpace1D : public AnimationRootNode {
6162

6263
float snap = 0.1;
6364

65+
bool smooth = false;
66+
float smooth_speed = 1.0;
67+
6468
String value_label = "value";
6569

6670
void _add_blend_point(int p_index, const Ref<AnimationRootNode> &p_node);
@@ -112,6 +116,12 @@ class AnimationNodeBlendSpace1D : public AnimationRootNode {
112116
void set_use_sync(bool p_sync);
113117
bool is_using_sync() const;
114118

119+
void set_smooth_speed(const float &p_speed);
120+
float get_smooth_speed() const;
121+
122+
void set_use_smooth(const bool &p_smooth);
123+
bool is_using_smooth() const;
124+
115125
virtual NodeTimeInfo _process(const AnimationMixer::PlaybackInfo p_playback_info, bool p_test_only = false) override;
116126
String get_caption() const override;
117127

0 commit comments

Comments
 (0)