Consistent with NodeBlendSpace1D option NodeBlendSpace2D
Co-authored-by: Skrapion <rick@firefang.com>
This commit is contained in:
parent
551f5191e5
commit
a0c4f849e0
@ -67,6 +67,9 @@
|
|||||||
</method>
|
</method>
|
||||||
</methods>
|
</methods>
|
||||||
<members>
|
<members>
|
||||||
|
<member name="blend_mode" type="int" setter="set_blend_mode" getter="get_blend_mode" enum="AnimationNodeBlendSpace1D.BlendMode" default="0">
|
||||||
|
Controls the interpolation between animations. See [enum BlendMode] constants.
|
||||||
|
</member>
|
||||||
<member name="max_space" type="float" setter="set_max_space" getter="get_max_space" default="1.0">
|
<member name="max_space" type="float" setter="set_max_space" getter="get_max_space" default="1.0">
|
||||||
The blend space's axis's upper limit for the points' position. See [method add_blend_point].
|
The blend space's axis's upper limit for the points' position. See [method add_blend_point].
|
||||||
</member>
|
</member>
|
||||||
@ -84,4 +87,15 @@
|
|||||||
Label of the virtual axis of the blend space.
|
Label of the virtual axis of the blend space.
|
||||||
</member>
|
</member>
|
||||||
</members>
|
</members>
|
||||||
|
<constants>
|
||||||
|
<constant name="BLEND_MODE_INTERPOLATED" value="0" enum="BlendMode">
|
||||||
|
The interpolation between animations is linear.
|
||||||
|
</constant>
|
||||||
|
<constant name="BLEND_MODE_DISCRETE" value="1" enum="BlendMode">
|
||||||
|
The blend space plays the animation of the node the blending position is closest to. Useful for frame-by-frame 2D animations.
|
||||||
|
</constant>
|
||||||
|
<constant name="BLEND_MODE_DISCRETE_CARRY" value="2" enum="BlendMode">
|
||||||
|
Similar to [constant BLEND_MODE_DISCRETE], but starts the new animation at the last animation's playback position.
|
||||||
|
</constant>
|
||||||
|
</constants>
|
||||||
</class>
|
</class>
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#include "editor/editor_undo_redo_manager.h"
|
#include "editor/editor_undo_redo_manager.h"
|
||||||
#include "scene/animation/animation_blend_tree.h"
|
#include "scene/animation/animation_blend_tree.h"
|
||||||
#include "scene/gui/check_box.h"
|
#include "scene/gui/check_box.h"
|
||||||
|
#include "scene/gui/option_button.h"
|
||||||
#include "scene/gui/panel_container.h"
|
#include "scene/gui/panel_container.h"
|
||||||
|
|
||||||
StringName AnimationNodeBlendSpace1DEditor::get_blend_position_path() const {
|
StringName AnimationNodeBlendSpace1DEditor::get_blend_position_path() const {
|
||||||
@ -335,6 +336,7 @@ void AnimationNodeBlendSpace1DEditor::_update_space() {
|
|||||||
min_value->set_value(blend_space->get_min_space());
|
min_value->set_value(blend_space->get_min_space());
|
||||||
|
|
||||||
sync->set_pressed(blend_space->is_using_sync());
|
sync->set_pressed(blend_space->is_using_sync());
|
||||||
|
interpolation->select(blend_space->get_blend_mode());
|
||||||
|
|
||||||
label_value->set_text(blend_space->get_value_label());
|
label_value->set_text(blend_space->get_value_label());
|
||||||
|
|
||||||
@ -361,6 +363,8 @@ void AnimationNodeBlendSpace1DEditor::_config_changed(double) {
|
|||||||
undo_redo->add_undo_method(blend_space.ptr(), "set_snap", blend_space->get_snap());
|
undo_redo->add_undo_method(blend_space.ptr(), "set_snap", blend_space->get_snap());
|
||||||
undo_redo->add_do_method(blend_space.ptr(), "set_use_sync", sync->is_pressed());
|
undo_redo->add_do_method(blend_space.ptr(), "set_use_sync", sync->is_pressed());
|
||||||
undo_redo->add_undo_method(blend_space.ptr(), "set_use_sync", blend_space->is_using_sync());
|
undo_redo->add_undo_method(blend_space.ptr(), "set_use_sync", blend_space->is_using_sync());
|
||||||
|
undo_redo->add_do_method(blend_space.ptr(), "set_blend_mode", interpolation->get_selected());
|
||||||
|
undo_redo->add_undo_method(blend_space.ptr(), "set_blend_mode", blend_space->get_blend_mode());
|
||||||
undo_redo->add_do_method(this, "_update_space");
|
undo_redo->add_do_method(this, "_update_space");
|
||||||
undo_redo->add_undo_method(this, "_update_space");
|
undo_redo->add_undo_method(this, "_update_space");
|
||||||
undo_redo->commit_action();
|
undo_redo->commit_action();
|
||||||
@ -579,6 +583,10 @@ void AnimationNodeBlendSpace1DEditor::_notification(int p_what) {
|
|||||||
tool_erase->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
|
tool_erase->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
|
||||||
snap->set_icon(get_theme_icon(SNAME("SnapGrid"), SNAME("EditorIcons")));
|
snap->set_icon(get_theme_icon(SNAME("SnapGrid"), SNAME("EditorIcons")));
|
||||||
open_editor->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
|
open_editor->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
|
||||||
|
interpolation->clear();
|
||||||
|
interpolation->add_icon_item(get_theme_icon(SNAME("TrackContinuous"), SNAME("EditorIcons")), "", 0);
|
||||||
|
interpolation->add_icon_item(get_theme_icon(SNAME("TrackDiscrete"), SNAME("EditorIcons")), "", 1);
|
||||||
|
interpolation->add_icon_item(get_theme_icon(SNAME("TrackCapture"), SNAME("EditorIcons")), "", 2);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NOTIFICATION_PROCESS: {
|
case NOTIFICATION_PROCESS: {
|
||||||
@ -639,6 +647,7 @@ void AnimationNodeBlendSpace1DEditor::edit(const Ref<AnimationNode> &p_node) {
|
|||||||
min_value->set_editable(!read_only);
|
min_value->set_editable(!read_only);
|
||||||
max_value->set_editable(!read_only);
|
max_value->set_editable(!read_only);
|
||||||
sync->set_disabled(read_only);
|
sync->set_disabled(read_only);
|
||||||
|
interpolation->set_disabled(read_only);
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimationNodeBlendSpace1DEditor *AnimationNodeBlendSpace1DEditor::singleton = nullptr;
|
AnimationNodeBlendSpace1DEditor *AnimationNodeBlendSpace1DEditor::singleton = nullptr;
|
||||||
@ -707,6 +716,13 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() {
|
|||||||
top_hb->add_child(sync);
|
top_hb->add_child(sync);
|
||||||
sync->connect("toggled", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_config_changed));
|
sync->connect("toggled", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_config_changed));
|
||||||
|
|
||||||
|
top_hb->add_child(memnew(VSeparator));
|
||||||
|
|
||||||
|
top_hb->add_child(memnew(Label(TTR("Blend:"))));
|
||||||
|
interpolation = memnew(OptionButton);
|
||||||
|
top_hb->add_child(interpolation);
|
||||||
|
interpolation->connect("item_selected", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_config_changed));
|
||||||
|
|
||||||
edit_hb = memnew(HBoxContainer);
|
edit_hb = memnew(HBoxContainer);
|
||||||
top_hb->add_child(edit_hb);
|
top_hb->add_child(edit_hb);
|
||||||
edit_hb->add_child(memnew(VSeparator));
|
edit_hb->add_child(memnew(VSeparator));
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "scene/gui/tree.h"
|
#include "scene/gui/tree.h"
|
||||||
|
|
||||||
class CheckBox;
|
class CheckBox;
|
||||||
|
class OptionButton;
|
||||||
class PanelContainer;
|
class PanelContainer;
|
||||||
|
|
||||||
class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin {
|
class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin {
|
||||||
@ -66,6 +67,7 @@ class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin {
|
|||||||
SpinBox *min_value = nullptr;
|
SpinBox *min_value = nullptr;
|
||||||
|
|
||||||
CheckBox *sync = nullptr;
|
CheckBox *sync = nullptr;
|
||||||
|
OptionButton *interpolation = nullptr;
|
||||||
|
|
||||||
HBoxContainer *edit_hb = nullptr;
|
HBoxContainer *edit_hb = nullptr;
|
||||||
SpinBox *edit_value = nullptr;
|
SpinBox *edit_value = nullptr;
|
||||||
|
@ -30,12 +30,20 @@
|
|||||||
|
|
||||||
#include "animation_blend_space_1d.h"
|
#include "animation_blend_space_1d.h"
|
||||||
|
|
||||||
|
#include "animation_blend_tree.h"
|
||||||
|
|
||||||
void AnimationNodeBlendSpace1D::get_parameter_list(List<PropertyInfo> *r_list) const {
|
void AnimationNodeBlendSpace1D::get_parameter_list(List<PropertyInfo> *r_list) const {
|
||||||
r_list->push_back(PropertyInfo(Variant::FLOAT, blend_position));
|
r_list->push_back(PropertyInfo(Variant::FLOAT, blend_position));
|
||||||
|
r_list->push_back(PropertyInfo(Variant::INT, closest, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE));
|
||||||
|
r_list->push_back(PropertyInfo(Variant::FLOAT, length_internal, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE));
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant AnimationNodeBlendSpace1D::get_parameter_default_value(const StringName &p_parameter) const {
|
Variant AnimationNodeBlendSpace1D::get_parameter_default_value(const StringName &p_parameter) const {
|
||||||
|
if (p_parameter == closest) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<AnimationNode> AnimationNodeBlendSpace1D::get_child_by_name(const StringName &p_name) {
|
Ref<AnimationNode> AnimationNodeBlendSpace1D::get_child_by_name(const StringName &p_name) {
|
||||||
@ -77,6 +85,9 @@ void AnimationNodeBlendSpace1D::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("set_value_label", "text"), &AnimationNodeBlendSpace1D::set_value_label);
|
ClassDB::bind_method(D_METHOD("set_value_label", "text"), &AnimationNodeBlendSpace1D::set_value_label);
|
||||||
ClassDB::bind_method(D_METHOD("get_value_label"), &AnimationNodeBlendSpace1D::get_value_label);
|
ClassDB::bind_method(D_METHOD("get_value_label"), &AnimationNodeBlendSpace1D::get_value_label);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_blend_mode", "mode"), &AnimationNodeBlendSpace1D::set_blend_mode);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_blend_mode"), &AnimationNodeBlendSpace1D::get_blend_mode);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeBlendSpace1D::set_use_sync);
|
ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeBlendSpace1D::set_use_sync);
|
||||||
ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeBlendSpace1D::is_using_sync);
|
ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeBlendSpace1D::is_using_sync);
|
||||||
|
|
||||||
@ -91,7 +102,12 @@ void AnimationNodeBlendSpace1D::_bind_methods() {
|
|||||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_max_space", "get_max_space");
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_max_space", "get_max_space");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "snap", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_snap", "get_snap");
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "snap", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_snap", "get_snap");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "value_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_value_label", "get_value_label");
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "value_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_value_label", "get_value_label");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Interpolated,Discrete,Carry", PROPERTY_USAGE_NO_EDITOR), "set_blend_mode", "get_blend_mode");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_use_sync", "is_using_sync");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_use_sync", "is_using_sync");
|
||||||
|
|
||||||
|
BIND_ENUM_CONSTANT(BLEND_MODE_INTERPOLATED);
|
||||||
|
BIND_ENUM_CONSTANT(BLEND_MODE_DISCRETE);
|
||||||
|
BIND_ENUM_CONSTANT(BLEND_MODE_DISCRETE_CARRY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationNodeBlendSpace1D::get_child_nodes(List<ChildNode> *r_child_nodes) {
|
void AnimationNodeBlendSpace1D::get_child_nodes(List<ChildNode> *r_child_nodes) {
|
||||||
@ -214,6 +230,14 @@ String AnimationNodeBlendSpace1D::get_value_label() const {
|
|||||||
return value_label;
|
return value_label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AnimationNodeBlendSpace1D::set_blend_mode(BlendMode p_blend_mode) {
|
||||||
|
blend_mode = p_blend_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimationNodeBlendSpace1D::BlendMode AnimationNodeBlendSpace1D::get_blend_mode() const {
|
||||||
|
return blend_mode;
|
||||||
|
}
|
||||||
|
|
||||||
void AnimationNodeBlendSpace1D::set_use_sync(bool p_sync) {
|
void AnimationNodeBlendSpace1D::set_use_sync(bool p_sync) {
|
||||||
sync = p_sync;
|
sync = p_sync;
|
||||||
}
|
}
|
||||||
@ -241,7 +265,11 @@ double AnimationNodeBlendSpace1D::process(double p_time, bool p_seek, bool p_is_
|
|||||||
}
|
}
|
||||||
|
|
||||||
double blend_pos = get_parameter(blend_position);
|
double blend_pos = get_parameter(blend_position);
|
||||||
|
int cur_closest = get_parameter(closest);
|
||||||
|
double cur_length_internal = get_parameter(length_internal);
|
||||||
|
double max_time_remaining = 0.0;
|
||||||
|
|
||||||
|
if (blend_mode == BLEND_MODE_INTERPOLATED) {
|
||||||
float weights[MAX_BLEND_POINTS] = {};
|
float weights[MAX_BLEND_POINTS] = {};
|
||||||
|
|
||||||
int point_lower = -1;
|
int point_lower = -1;
|
||||||
@ -303,8 +331,6 @@ double AnimationNodeBlendSpace1D::process(double p_time, bool p_seek, bool p_is_
|
|||||||
|
|
||||||
// actually blend the animations now
|
// actually blend the animations now
|
||||||
|
|
||||||
double max_time_remaining = 0.0;
|
|
||||||
|
|
||||||
for (int i = 0; i < blend_points_used; i++) {
|
for (int i = 0; i < blend_points_used; i++) {
|
||||||
if (i == point_lower || i == point_higher) {
|
if (i == point_lower || i == point_higher) {
|
||||||
double remaining = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_is_external_seeking, weights[i], FILTER_IGNORE, true);
|
double remaining = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_is_external_seeking, weights[i], FILTER_IGNORE, true);
|
||||||
@ -313,7 +339,51 @@ double AnimationNodeBlendSpace1D::process(double p_time, bool p_seek, bool p_is_
|
|||||||
blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_is_external_seeking, 0, FILTER_IGNORE, true);
|
blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_is_external_seeking, 0, FILTER_IGNORE, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
int new_closest = -1;
|
||||||
|
double new_closest_dist = 1e20;
|
||||||
|
|
||||||
|
for (int i = 0; i < blend_points_used; i++) {
|
||||||
|
double d = abs(blend_points[i].position - blend_pos);
|
||||||
|
if (d < new_closest_dist) {
|
||||||
|
new_closest = i;
|
||||||
|
new_closest_dist = d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_closest != cur_closest && new_closest != -1) {
|
||||||
|
double from = 0.0;
|
||||||
|
if (blend_mode == BLEND_MODE_DISCRETE_CARRY && cur_closest != -1) {
|
||||||
|
//for ping-pong loop
|
||||||
|
Ref<AnimationNodeAnimation> na_c = static_cast<Ref<AnimationNodeAnimation>>(blend_points[cur_closest].node);
|
||||||
|
Ref<AnimationNodeAnimation> na_n = static_cast<Ref<AnimationNodeAnimation>>(blend_points[new_closest].node);
|
||||||
|
if (!na_c.is_null() && !na_n.is_null()) {
|
||||||
|
na_n->set_backward(na_c->is_backward());
|
||||||
|
}
|
||||||
|
//see how much animation remains
|
||||||
|
from = cur_length_internal - blend_node(blend_points[cur_closest].name, blend_points[cur_closest].node, p_time, false, p_is_external_seeking, 0.0, FILTER_IGNORE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
max_time_remaining = blend_node(blend_points[new_closest].name, blend_points[new_closest].node, from, true, p_is_external_seeking, 1.0, FILTER_IGNORE, true);
|
||||||
|
cur_length_internal = from + max_time_remaining;
|
||||||
|
|
||||||
|
cur_closest = new_closest;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
max_time_remaining = blend_node(blend_points[cur_closest].name, blend_points[cur_closest].node, p_time, p_seek, p_is_external_seeking, 1.0, FILTER_IGNORE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sync) {
|
||||||
|
for (int i = 0; i < blend_points_used; i++) {
|
||||||
|
if (i != cur_closest) {
|
||||||
|
blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_is_external_seeking, 0, FILTER_IGNORE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set_parameter(this->closest, cur_closest);
|
||||||
|
set_parameter(this->length_internal, cur_length_internal);
|
||||||
return max_time_remaining;
|
return max_time_remaining;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,14 @@
|
|||||||
class AnimationNodeBlendSpace1D : public AnimationRootNode {
|
class AnimationNodeBlendSpace1D : public AnimationRootNode {
|
||||||
GDCLASS(AnimationNodeBlendSpace1D, AnimationRootNode);
|
GDCLASS(AnimationNodeBlendSpace1D, AnimationRootNode);
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum BlendMode {
|
||||||
|
BLEND_MODE_INTERPOLATED,
|
||||||
|
BLEND_MODE_DISCRETE,
|
||||||
|
BLEND_MODE_DISCRETE_CARRY,
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
enum {
|
enum {
|
||||||
MAX_BLEND_POINTS = 64
|
MAX_BLEND_POINTS = 64
|
||||||
};
|
};
|
||||||
@ -61,6 +69,10 @@ class AnimationNodeBlendSpace1D : public AnimationRootNode {
|
|||||||
void _tree_changed();
|
void _tree_changed();
|
||||||
|
|
||||||
StringName blend_position = "blend_position";
|
StringName blend_position = "blend_position";
|
||||||
|
StringName closest = "closest";
|
||||||
|
StringName length_internal = "length_internal";
|
||||||
|
|
||||||
|
BlendMode blend_mode = BLEND_MODE_INTERPOLATED;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool sync = false;
|
bool sync = false;
|
||||||
@ -95,6 +107,9 @@ public:
|
|||||||
void set_value_label(const String &p_label);
|
void set_value_label(const String &p_label);
|
||||||
String get_value_label() const;
|
String get_value_label() const;
|
||||||
|
|
||||||
|
void set_blend_mode(BlendMode p_blend_mode);
|
||||||
|
BlendMode get_blend_mode() const;
|
||||||
|
|
||||||
void set_use_sync(bool p_sync);
|
void set_use_sync(bool p_sync);
|
||||||
bool is_using_sync() const;
|
bool is_using_sync() const;
|
||||||
|
|
||||||
@ -107,4 +122,6 @@ public:
|
|||||||
~AnimationNodeBlendSpace1D();
|
~AnimationNodeBlendSpace1D();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
VARIANT_ENUM_CAST(AnimationNodeBlendSpace1D::BlendMode)
|
||||||
|
|
||||||
#endif // ANIMATION_BLEND_SPACE_1D_H
|
#endif // ANIMATION_BLEND_SPACE_1D_H
|
||||||
|
Loading…
Reference in New Issue
Block a user