summaryrefslogtreecommitdiff
path: root/scene/animation
diff options
context:
space:
mode:
Diffstat (limited to 'scene/animation')
-rw-r--r--scene/animation/SCsub2
-rw-r--r--scene/animation/animation_blend_space_2d.cpp185
-rw-r--r--scene/animation/animation_blend_space_2d.h15
-rw-r--r--scene/animation/animation_blend_tree.cpp23
-rw-r--r--scene/animation/animation_blend_tree.h7
-rw-r--r--scene/animation/animation_node_state_machine.cpp1
-rw-r--r--scene/animation/animation_player.cpp14
-rw-r--r--scene/animation/animation_player.h1
-rw-r--r--scene/animation/animation_tree.cpp34
-rw-r--r--scene/animation/animation_tree_player.cpp1
-rw-r--r--scene/animation/skeleton_ik.cpp26
-rw-r--r--scene/animation/skeleton_ik.h6
-rw-r--r--scene/animation/tween.cpp20
-rw-r--r--scene/animation/tween_interpolaters.cpp338
14 files changed, 242 insertions, 431 deletions
diff --git a/scene/animation/SCsub b/scene/animation/SCsub
index bf9125be7f..b01e2fd54d 100644
--- a/scene/animation/SCsub
+++ b/scene/animation/SCsub
@@ -3,5 +3,3 @@
Import('env')
env.add_source_files(env.scene_sources, "*.cpp")
-
-Export('env')
diff --git a/scene/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp
index f5f899a6cd..866b85c4c7 100644
--- a/scene/animation/animation_blend_space_2d.cpp
+++ b/scene/animation/animation_blend_space_2d.cpp
@@ -33,9 +33,17 @@
void AnimationNodeBlendSpace2D::get_parameter_list(List<PropertyInfo> *r_list) const {
r_list->push_back(PropertyInfo(Variant::VECTOR2, blend_position));
+ r_list->push_back(PropertyInfo(Variant::INT, closest, PROPERTY_HINT_NONE, "", 0));
+ r_list->push_back(PropertyInfo(Variant::REAL, length_internal, PROPERTY_HINT_NONE, "", 0));
}
Variant AnimationNodeBlendSpace2D::get_parameter_default_value(const StringName &p_parameter) const {
- return Vector2();
+ if (p_parameter == closest) {
+ return -1;
+ } else if (p_parameter == length_internal) {
+ return 0;
+ } else {
+ return Vector2();
+ }
}
void AnimationNodeBlendSpace2D::get_child_nodes(List<ChildNode> *r_child_nodes) {
@@ -412,84 +420,124 @@ float AnimationNodeBlendSpace2D::process(float p_time, bool p_seek) {
_update_triangles();
Vector2 blend_pos = get_parameter(blend_position);
+ int closest = get_parameter(this->closest);
+ float length_internal = get_parameter(this->length_internal);
+ float mind = 0; //time of min distance point
- if (triangles.size() == 0)
- return 0;
+ if (blend_mode == BLEND_MODE_INTERPOLATED) {
- Vector2 best_point;
- bool first = true;
- int blend_triangle = -1;
- float blend_weights[3] = { 0, 0, 0 };
+ if (triangles.size() == 0)
+ return 0;
- for (int i = 0; i < triangles.size(); i++) {
- Vector2 points[3];
- for (int j = 0; j < 3; j++) {
- points[j] = get_blend_point_position(get_triangle_point(i, j));
- }
+ Vector2 best_point;
+ bool first = true;
+ int blend_triangle = -1;
+ float blend_weights[3] = { 0, 0, 0 };
- if (Geometry::is_point_in_triangle(blend_pos, points[0], points[1], points[2])) {
+ for (int i = 0; i < triangles.size(); i++) {
+ Vector2 points[3];
+ for (int j = 0; j < 3; j++) {
+ points[j] = get_blend_point_position(get_triangle_point(i, j));
+ }
- blend_triangle = i;
- _blend_triangle(blend_pos, points, blend_weights);
- break;
- }
+ if (Geometry::is_point_in_triangle(blend_pos, points[0], points[1], points[2])) {
- for (int j = 0; j < 3; j++) {
- Vector2 s[2] = {
- points[j],
- points[(j + 1) % 3]
- };
- Vector2 closest = Geometry::get_closest_point_to_segment_2d(blend_pos, s);
- if (first || closest.distance_to(blend_pos) < best_point.distance_to(blend_pos)) {
- best_point = closest;
blend_triangle = i;
- first = false;
- float d = s[0].distance_to(s[1]);
- if (d == 0.0) {
- blend_weights[j] = 1.0;
- blend_weights[(j + 1) % 3] = 0.0;
- blend_weights[(j + 2) % 3] = 0.0;
- } else {
- float c = s[0].distance_to(closest) / d;
-
- blend_weights[j] = 1.0 - c;
- blend_weights[(j + 1) % 3] = c;
- blend_weights[(j + 2) % 3] = 0.0;
+ _blend_triangle(blend_pos, points, blend_weights);
+ break;
+ }
+
+ for (int j = 0; j < 3; j++) {
+ Vector2 s[2] = {
+ points[j],
+ points[(j + 1) % 3]
+ };
+ Vector2 closest = Geometry::get_closest_point_to_segment_2d(blend_pos, s);
+ if (first || closest.distance_to(blend_pos) < best_point.distance_to(blend_pos)) {
+ best_point = closest;
+ blend_triangle = i;
+ first = false;
+ float d = s[0].distance_to(s[1]);
+ if (d == 0.0) {
+ blend_weights[j] = 1.0;
+ blend_weights[(j + 1) % 3] = 0.0;
+ blend_weights[(j + 2) % 3] = 0.0;
+ } else {
+ float c = s[0].distance_to(closest) / d;
+
+ blend_weights[j] = 1.0 - c;
+ blend_weights[(j + 1) % 3] = c;
+ blend_weights[(j + 2) % 3] = 0.0;
+ }
}
}
}
- }
- ERR_FAIL_COND_V(blend_triangle == -1, 0); //should never reach here
+ ERR_FAIL_COND_V(blend_triangle == -1, 0); //should never reach here
- int triangle_points[3];
- for (int j = 0; j < 3; j++) {
- triangle_points[j] = get_triangle_point(blend_triangle, j);
- }
+ int triangle_points[3];
+ for (int j = 0; j < 3; j++) {
+ triangle_points[j] = get_triangle_point(blend_triangle, j);
+ }
- first = true;
- float mind;
- for (int i = 0; i < blend_points_used; i++) {
+ first = true;
- bool found = false;
- for (int j = 0; j < 3; j++) {
- if (i == triangle_points[j]) {
- //blend with the given weight
- float t = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, blend_weights[j], FILTER_IGNORE, false);
- if (first || t < mind) {
- mind = t;
- first = false;
+ for (int i = 0; i < blend_points_used; i++) {
+
+ bool found = false;
+ for (int j = 0; j < 3; j++) {
+ if (i == triangle_points[j]) {
+ //blend with the given weight
+ float t = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, blend_weights[j], FILTER_IGNORE, false);
+ if (first || t < mind) {
+ mind = t;
+ first = false;
+ }
+ found = true;
+ break;
}
- found = true;
- break;
+ }
+
+ if (!found) {
+ //ignore
+ blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, 0, FILTER_IGNORE, false);
+ }
+ }
+ } else {
+
+ int new_closest = -1;
+ float new_closest_dist = 1e20;
+
+ for (int i = 0; i < blend_points_used; i++) {
+
+ float d = blend_points[i].position.distance_squared_to(blend_pos);
+ if (d < new_closest_dist) {
+
+ new_closest = i;
+ new_closest_dist = d;
}
}
- if (!found) {
- //ignore
- blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, 0, FILTER_IGNORE, false);
+ if (new_closest != closest) {
+
+ float from = 0;
+ if (blend_mode == BLEND_MODE_DISCRETE_CARRY && closest != -1) {
+ //see how much animation remains
+ from = blend_node(blend_points[closest].name, blend_points[closest].node, p_time, true, 0.0, FILTER_IGNORE, false) - length_internal;
+ }
+
+ mind = blend_node(blend_points[new_closest].name, blend_points[new_closest].node, from, true, 1.0, FILTER_IGNORE, false) + from;
+ length_internal = from + mind;
+
+ closest = new_closest;
+
+ } else {
+ mind = blend_node(blend_points[closest].name, blend_points[closest].node, p_time, p_seek, 1.0, FILTER_IGNORE, false);
}
}
+
+ set_parameter(this->closest, closest);
+ set_parameter(this->length_internal, length_internal);
return mind;
}
@@ -527,6 +575,14 @@ void AnimationNodeBlendSpace2D::_tree_changed() {
emit_signal("tree_changed");
}
+void AnimationNodeBlendSpace2D::set_blend_mode(BlendMode p_blend_mode) {
+ blend_mode = p_blend_mode;
+}
+
+AnimationNodeBlendSpace2D::BlendMode AnimationNodeBlendSpace2D::get_blend_mode() const {
+ return blend_mode;
+}
+
void AnimationNodeBlendSpace2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_blend_point", "node", "pos", "at_index"), &AnimationNodeBlendSpace2D::add_blend_point, DEFVAL(-1));
@@ -565,6 +621,9 @@ void AnimationNodeBlendSpace2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_auto_triangles", "enable"), &AnimationNodeBlendSpace2D::set_auto_triangles);
ClassDB::bind_method(D_METHOD("get_auto_triangles"), &AnimationNodeBlendSpace2D::get_auto_triangles);
+ ClassDB::bind_method(D_METHOD("set_blend_mode", "mode"), &AnimationNodeBlendSpace2D::set_blend_mode);
+ ClassDB::bind_method(D_METHOD("get_blend_mode"), &AnimationNodeBlendSpace2D::get_blend_mode);
+
ClassDB::bind_method(D_METHOD("_tree_changed"), &AnimationNodeBlendSpace2D::_tree_changed);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_triangles", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_auto_triangles", "get_auto_triangles");
@@ -581,6 +640,11 @@ void AnimationNodeBlendSpace2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "snap", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_snap", "get_snap");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "x_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_x_label", "get_x_label");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "y_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_y_label", "get_y_label");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Interpolated,Discrete,Carry", PROPERTY_USAGE_NOEDITOR), "set_blend_mode", "get_blend_mode");
+
+ BIND_ENUM_CONSTANT(BLEND_MODE_INTERPOLATED);
+ BIND_ENUM_CONSTANT(BLEND_MODE_DISCRETE);
+ BIND_ENUM_CONSTANT(BLEND_MODE_DISCRETE_CARRY);
}
AnimationNodeBlendSpace2D::AnimationNodeBlendSpace2D() {
@@ -597,6 +661,9 @@ AnimationNodeBlendSpace2D::AnimationNodeBlendSpace2D() {
y_label = "y";
trianges_dirty = false;
blend_position = "blend_position";
+ closest = "closest";
+ length_internal = "length_internal";
+ blend_mode = BLEND_MODE_INTERPOLATED;
}
AnimationNodeBlendSpace2D::~AnimationNodeBlendSpace2D() {
diff --git a/scene/animation/animation_blend_space_2d.h b/scene/animation/animation_blend_space_2d.h
index 2c684687de..60671f1816 100644
--- a/scene/animation/animation_blend_space_2d.h
+++ b/scene/animation/animation_blend_space_2d.h
@@ -35,7 +35,14 @@
class AnimationNodeBlendSpace2D : public AnimationRootNode {
GDCLASS(AnimationNodeBlendSpace2D, AnimationRootNode)
+public:
+ enum BlendMode {
+ BLEND_MODE_INTERPOLATED,
+ BLEND_MODE_DISCRETE,
+ BLEND_MODE_DISCRETE_CARRY,
+ };
+protected:
enum {
MAX_BLEND_POINTS = 64
};
@@ -56,11 +63,14 @@ class AnimationNodeBlendSpace2D : public AnimationRootNode {
Vector<BlendTriangle> triangles;
StringName blend_position;
+ StringName closest;
+ StringName length_internal;
Vector2 max_space;
Vector2 min_space;
Vector2 snap;
String x_label;
String y_label;
+ BlendMode blend_mode;
void _add_blend_point(int p_index, const Ref<AnimationRootNode> &p_node);
void _set_triangles(const Vector<int> &p_triangles);
@@ -122,10 +132,15 @@ public:
void set_auto_triangles(bool p_enable);
bool get_auto_triangles() const;
+ void set_blend_mode(BlendMode p_blend_mode);
+ BlendMode get_blend_mode() const;
+
virtual Ref<AnimationNode> get_child_by_name(const StringName &p_name);
AnimationNodeBlendSpace2D();
~AnimationNodeBlendSpace2D();
};
+VARIANT_ENUM_CAST(AnimationNodeBlendSpace2D::BlendMode)
+
#endif // ANIMATION_BLEND_SPACE_2D_H
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index b85d4e541e..5b413737a9 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -40,12 +40,11 @@ StringName AnimationNodeAnimation::get_animation() const {
return animation;
}
-float AnimationNodeAnimation::get_playback_time() const {
- return time;
-}
-
Vector<String> (*AnimationNodeAnimation::get_editable_animation_list)() = NULL;
+void AnimationNodeAnimation::get_parameter_list(List<PropertyInfo> *r_list) const {
+ r_list->push_back(PropertyInfo(Variant::REAL, time, PROPERTY_HINT_NONE, "", 0));
+}
void AnimationNodeAnimation::_validate_property(PropertyInfo &property) const {
if (property.name == "animation" && get_editable_animation_list) {
@@ -70,6 +69,8 @@ float AnimationNodeAnimation::process(float p_time, bool p_seek) {
AnimationPlayer *ap = state->player;
ERR_FAIL_COND_V(!ap, 0);
+ float time = get_parameter(this->time);
+
if (!ap->has_animation(animation)) {
AnimationNodeBlendTree *tree = Object::cast_to<AnimationNodeBlendTree>(parent);
@@ -86,6 +87,8 @@ float AnimationNodeAnimation::process(float p_time, bool p_seek) {
Ref<Animation> anim = ap->get_animation(animation);
+ float step;
+
if (p_seek) {
time = p_time;
step = 0;
@@ -109,6 +112,8 @@ float AnimationNodeAnimation::process(float p_time, bool p_seek) {
blend_animation(animation, time, step, p_seek, 1.0);
+ set_parameter(this->time, time);
+
return anim_size - time;
}
@@ -120,16 +125,13 @@ void AnimationNodeAnimation::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_animation", "name"), &AnimationNodeAnimation::set_animation);
ClassDB::bind_method(D_METHOD("get_animation"), &AnimationNodeAnimation::get_animation);
- ClassDB::bind_method(D_METHOD("get_playback_time"), &AnimationNodeAnimation::get_playback_time);
-
ADD_PROPERTY(PropertyInfo(Variant::STRING, "animation"), "set_animation", "get_animation");
}
AnimationNodeAnimation::AnimationNodeAnimation() {
last_version = 0;
skip = false;
- time = 0;
- step = 0;
+ time = "time";
}
////////////////////////////////////////////////////////
@@ -266,7 +268,6 @@ float AnimationNodeOneShot::process(float p_time, bool p_seek) {
if (do_start) {
remaining = os_rem;
- do_start = false;
}
if (!p_seek) {
@@ -699,7 +700,7 @@ String AnimationNodeTransition::get_input_caption(int p_input) const {
if (tree.is_valid() && current >= 0) {
prev = current;
- prev_xfading = xfade;
+ prev_xfading = xfade;
time = 0;
current = p_current;
switched = true;
@@ -770,8 +771,6 @@ float AnimationNodeTransition::process(float p_time, bool p_seek) {
rem = blend_input(current, p_time, p_seek, 1.0 - blend, FILTER_IGNORE, false);
}
- switched = false;
-
if (p_seek) { // don't seek prev animation
blend_input(prev, 0, false, blend, FILTER_IGNORE, false);
time = p_time;
diff --git a/scene/animation/animation_blend_tree.h b/scene/animation/animation_blend_tree.h
index 4ca11e464b..5adb7fd71a 100644
--- a/scene/animation/animation_blend_tree.h
+++ b/scene/animation/animation_blend_tree.h
@@ -38,10 +38,9 @@ class AnimationNodeAnimation : public AnimationRootNode {
GDCLASS(AnimationNodeAnimation, AnimationRootNode);
StringName animation;
+ StringName time;
uint64_t last_version;
- float time;
- float step;
bool skip;
protected:
@@ -50,6 +49,8 @@ protected:
static void _bind_methods();
public:
+ void get_parameter_list(List<PropertyInfo> *r_list) const;
+
static Vector<String> (*get_editable_animation_list)();
virtual String get_caption() const;
@@ -58,8 +59,6 @@ public:
void set_animation(const StringName &p_name);
StringName get_animation() const;
- float get_playback_time() const;
-
AnimationNodeAnimation();
};
diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp
index 5923ad7657..a7af3f687b 100644
--- a/scene/animation/animation_node_state_machine.cpp
+++ b/scene/animation/animation_node_state_machine.cpp
@@ -345,7 +345,6 @@ float AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *sm,
len_current = sm->blend_node(current, sm->states[current].node, 0, true, 1.0, AnimationNode::FILTER_IGNORE, false);
pos_current = 0;
loops_current = 0;
- play_start = false;
}
if (!sm->states.has(current)) {
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 7d91703cf8..7f9953ab43 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -1120,6 +1120,15 @@ void AnimationPlayer::queue(const StringName &p_name) {
queued.push_back(p_name);
}
+PoolVector<String> AnimationPlayer::get_queue() {
+ PoolVector<String> ret;
+ for (List<StringName>::Element *E = queued.front(); E; E = E->next()) {
+ ret.push_back(E->get());
+ }
+
+ return ret;
+}
+
void AnimationPlayer::clear_queue() {
queued.clear();
}
@@ -1348,6 +1357,9 @@ void AnimationPlayer::_animation_changed() {
clear_caches();
emit_signal("caches_cleared");
+ if (is_playing()) {
+ playback.seeked = true; //need to restart stuff, like audio
+ }
}
void AnimationPlayer::_stop_playing_caches() {
@@ -1451,6 +1463,7 @@ void AnimationPlayer::_set_process(bool p_process, bool p_force) {
case ANIMATION_PROCESS_PHYSICS: set_physics_process_internal(p_process && active); break;
case ANIMATION_PROCESS_IDLE: set_process_internal(p_process && active); break;
+ case ANIMATION_PROCESS_MANUAL: break;
}
processing = p_process;
@@ -1599,6 +1612,7 @@ void AnimationPlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_assigned_animation", "anim"), &AnimationPlayer::set_assigned_animation);
ClassDB::bind_method(D_METHOD("get_assigned_animation"), &AnimationPlayer::get_assigned_animation);
ClassDB::bind_method(D_METHOD("queue", "name"), &AnimationPlayer::queue);
+ ClassDB::bind_method(D_METHOD("get_queue"), &AnimationPlayer::get_queue);
ClassDB::bind_method(D_METHOD("clear_queue"), &AnimationPlayer::clear_queue);
ClassDB::bind_method(D_METHOD("set_active", "active"), &AnimationPlayer::set_active);
diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h
index f50b2454ec..b3bf8b1e22 100644
--- a/scene/animation/animation_player.h
+++ b/scene/animation/animation_player.h
@@ -312,6 +312,7 @@ public:
void play(const StringName &p_name = StringName(), float p_custom_blend = -1, float p_custom_scale = 1.0, bool p_from_end = false);
void play_backwards(const StringName &p_name = StringName(), float p_custom_blend = -1);
void queue(const StringName &p_name);
+ PoolVector<String> get_queue();
void clear_queue();
void stop(bool p_reset = true);
bool is_playing() const;
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index eb00f91bb3..2c8cbbdbd1 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -37,9 +37,20 @@
#include "servers/audio/audio_stream.h"
void AnimationNode::get_parameter_list(List<PropertyInfo> *r_list) const {
+ if (get_script_instance()) {
+ Array parameters = get_script_instance()->call("get_parameter_list");
+ for (int i = 0; i < parameters.size(); i++) {
+ Dictionary d = parameters[i];
+ ERR_CONTINUE(d.empty());
+ r_list->push_back(PropertyInfo::from_dict(d));
+ }
+ }
}
Variant AnimationNode::get_parameter_default_value(const StringName &p_parameter) const {
+ if (get_script_instance()) {
+ return get_script_instance()->call("get_parameter_default_value");
+ }
return Variant();
}
@@ -62,6 +73,18 @@ Variant AnimationNode::get_parameter(const StringName &p_name) const {
}
void AnimationNode::get_child_nodes(List<ChildNode> *r_child_nodes) {
+
+ if (get_script_instance()) {
+ Dictionary cn = get_script_instance()->call("get_child_nodes");
+ List<Variant> keys;
+ cn.get_key_list(&keys);
+ for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
+ ChildNode child;
+ child.name = E->get();
+ child.node = cn[E->get()];
+ r_child_nodes->push_back(child);
+ }
+ }
}
void AnimationNode::blend_animation(const StringName &p_animation, float p_time, float p_delta, bool p_seeked, float p_blend) {
@@ -373,6 +396,9 @@ void AnimationNode::_validate_property(PropertyInfo &property) const {
}
Ref<AnimationNode> AnimationNode::get_child_by_name(const StringName &p_name) {
+ if (get_script_instance()) {
+ return get_script_instance()->call("get_child_by_name");
+ }
return Ref<AnimationNode>();
}
@@ -403,6 +429,14 @@ void AnimationNode::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter_enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_filter_enabled", "is_filter_enabled");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "filters", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_filters", "_get_filters");
+ BIND_VMETHOD(MethodInfo(Variant::DICTIONARY, "get_child_nodes"));
+ BIND_VMETHOD(MethodInfo(Variant::ARRAY, "get_parameter_list"));
+ BIND_VMETHOD(MethodInfo(Variant::OBJECT, "get_child_by_name", PropertyInfo(Variant::STRING, "name")));
+ {
+ MethodInfo mi = MethodInfo(Variant::NIL, "get_parameter_default_value", PropertyInfo(Variant::STRING, "name"));
+ mi.return_val.usage = PROPERTY_USAGE_NIL_IS_VARIANT;
+ BIND_VMETHOD(mi);
+ }
BIND_VMETHOD(MethodInfo("process", PropertyInfo(Variant::REAL, "time"), PropertyInfo(Variant::BOOL, "seek")));
BIND_VMETHOD(MethodInfo(Variant::STRING, "get_caption"));
BIND_VMETHOD(MethodInfo(Variant::STRING, "has_filter"));
diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp
index 179f5d9698..524784df53 100644
--- a/scene/animation/animation_tree_player.cpp
+++ b/scene/animation/animation_tree_player.cpp
@@ -877,6 +877,7 @@ void AnimationTreePlayer::_process_animation(float p_delta) {
tr.track->object->call(method, args[0], args[1], args[2], args[3], args[4]);
}
} break;
+ default: {}
}
}
}
diff --git a/scene/animation/skeleton_ik.cpp b/scene/animation/skeleton_ik.cpp
index 69975e6195..3119e29586 100644
--- a/scene/animation/skeleton_ik.cpp
+++ b/scene/animation/skeleton_ik.cpp
@@ -280,7 +280,7 @@ void FabrikInverseKinematic::make_goal(Task *p_task, const Transform &p_inverse_
}
}
-void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool p_use_magnet, const Vector3 &p_magnet_position) {
+void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool override_tip_basis, bool p_use_magnet, const Vector3 &p_magnet_position) {
if (blending_delta <= 0.01f) {
return; // Skip solving
@@ -314,7 +314,10 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool p_u
}
} else {
// Set target orientation to tip
- new_bone_pose.basis = p_task->chain.tips[0].end_effector->goal_transform.basis;
+ if (override_tip_basis)
+ new_bone_pose.basis = p_task->chain.tips[0].end_effector->goal_transform.basis;
+ else
+ new_bone_pose.basis = new_bone_pose.basis * p_task->chain.tips[0].end_effector->goal_transform.basis;
}
p_task->skeleton->set_bone_global_pose(ci->bone, new_bone_pose);
@@ -366,6 +369,9 @@ void SkeletonIK::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_target_node", "node"), &SkeletonIK::set_target_node);
ClassDB::bind_method(D_METHOD("get_target_node"), &SkeletonIK::get_target_node);
+ ClassDB::bind_method(D_METHOD("set_override_tip_basis", "override"), &SkeletonIK::set_override_tip_basis);
+ ClassDB::bind_method(D_METHOD("is_override_tip_basis"), &SkeletonIK::is_override_tip_basis);
+
ClassDB::bind_method(D_METHOD("set_use_magnet", "use"), &SkeletonIK::set_use_magnet);
ClassDB::bind_method(D_METHOD("is_using_magnet"), &SkeletonIK::is_using_magnet);
@@ -388,6 +394,7 @@ void SkeletonIK::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "tip_bone"), "set_tip_bone", "get_tip_bone");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "interpolation", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_interpolation", "get_interpolation");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "target"), "set_target_transform", "get_target_transform");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_tip_basis"), "set_override_tip_basis", "is_override_tip_basis");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_magnet"), "set_use_magnet", "is_using_magnet");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "magnet"), "set_magnet_position", "get_magnet_position");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_node"), "set_target_node", "get_target_node");
@@ -418,11 +425,12 @@ void SkeletonIK::_notification(int p_what) {
SkeletonIK::SkeletonIK() :
Node(),
interpolation(1),
- skeleton(NULL),
- target_node_override(NULL),
+ override_tip_basis(true),
use_magnet(false),
min_distance(0.01),
max_iterations(10),
+ skeleton(NULL),
+ target_node_override(NULL),
task(NULL) {
set_process_priority(1);
@@ -478,6 +486,14 @@ NodePath SkeletonIK::get_target_node() {
return target_node_path_override;
}
+void SkeletonIK::set_override_tip_basis(bool p_override) {
+ override_tip_basis = p_override;
+}
+
+bool SkeletonIK::is_override_tip_basis() const {
+ return override_tip_basis;
+}
+
void SkeletonIK::set_use_magnet(bool p_use) {
use_magnet = p_use;
}
@@ -555,7 +571,7 @@ void SkeletonIK::reload_goal() {
void SkeletonIK::_solve_chain() {
if (!task)
return;
- FabrikInverseKinematic::solve(task, interpolation, use_magnet, magnet_position);
+ FabrikInverseKinematic::solve(task, interpolation, override_tip_basis, use_magnet, magnet_position);
}
#endif // _3D_DISABLED
diff --git a/scene/animation/skeleton_ik.h b/scene/animation/skeleton_ik.h
index 202d6959bb..b9628c479c 100644
--- a/scene/animation/skeleton_ik.h
+++ b/scene/animation/skeleton_ik.h
@@ -138,7 +138,7 @@ public:
// The goal of chain should be always in local space
static void set_goal(Task *p_task, const Transform &p_goal);
static void make_goal(Task *p_task, const Transform &p_inverse_transf, real_t blending_delta);
- static void solve(Task *p_task, real_t blending_delta, bool p_use_magnet, const Vector3 &p_magnet_position);
+ static void solve(Task *p_task, real_t blending_delta, bool override_tip_basis, bool p_use_magnet, const Vector3 &p_magnet_position);
};
class SkeletonIK : public Node {
@@ -149,6 +149,7 @@ class SkeletonIK : public Node {
real_t interpolation;
Transform target;
NodePath target_node_path_override;
+ bool override_tip_basis;
bool use_magnet;
Vector3 magnet_position;
@@ -185,6 +186,9 @@ public:
void set_target_node(const NodePath &p_node);
NodePath get_target_node();
+ void set_override_tip_basis(bool p_override);
+ bool is_override_tip_basis() const;
+
void set_use_magnet(bool p_use);
bool is_using_magnet() const;
diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp
index 82e2bb93e2..3521782417 100644
--- a/scene/animation/tween.cpp
+++ b/scene/animation/tween.cpp
@@ -277,7 +277,10 @@ Variant &Tween::_get_initial_val(InterpolateData &p_data) {
ERR_FAIL_COND_V(error.error != Variant::CallError::CALL_OK, p_data.initial_val);
}
return initial_val;
- } break;
+ }
+
+ case INTER_CALLBACK:
+ break;
}
return p_data.delta_val;
}
@@ -313,7 +316,7 @@ Variant &Tween::_get_delta_val(InterpolateData &p_data) {
if (final_val.get_type() == Variant::INT) final_val = final_val.operator real_t();
_calc_delta_val(p_data.initial_val, final_val, p_data.delta_val);
return p_data.delta_val;
- } break;
+ }
case TARGETING_PROPERTY:
case TARGETING_METHOD: {
@@ -325,7 +328,10 @@ Variant &Tween::_get_delta_val(InterpolateData &p_data) {
//_calc_delta_val(p_data.initial_val, p_data.final_val, p_data.delta_val);
_calc_delta_val(initial_val, p_data.final_val, p_data.delta_val);
return p_data.delta_val;
- } break;
+ }
+
+ case INTER_CALLBACK:
+ break;
}
return p_data.initial_val;
}
@@ -857,12 +863,8 @@ bool Tween::seek(real_t p_time) {
data.finish = false;
}
- switch (data.type) {
- case INTER_PROPERTY:
- case INTER_METHOD:
- break;
- case INTER_CALLBACK:
- continue;
+ if (data.type == INTER_CALLBACK) {
+ continue;
}
Variant result = _run_equation(data);
diff --git a/scene/animation/tween_interpolaters.cpp b/scene/animation/tween_interpolaters.cpp
deleted file mode 100644
index 52aa7403c0..0000000000
--- a/scene/animation/tween_interpolaters.cpp
+++ /dev/null
@@ -1,338 +0,0 @@
-/*************************************************************************/
-/* tween_interpolaters.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-/**
- * Adapted from Penner Easing equations' C++ port.
- * Source: https://github.com/jesusgollonet/ofpennereasing
- * License: BSD-3-clause
- */
-
-#include "tween.h"
-
-const real_t pi = 3.1415926535898;
-
-///////////////////////////////////////////////////////////////////////////
-// linear
-///////////////////////////////////////////////////////////////////////////
-namespace linear {
-static real_t in(real_t t, real_t b, real_t c, real_t d) {
- return c * t / d + b;
-}
-
-static real_t out(real_t t, real_t b, real_t c, real_t d) {
- return c * t / d + b;
-}
-
-static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
- return c * t / d + b;
-}
-
-static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
- return c * t / d + b;
-}
-}; // namespace linear
-///////////////////////////////////////////////////////////////////////////
-// sine
-///////////////////////////////////////////////////////////////////////////
-namespace sine {
-static real_t in(real_t t, real_t b, real_t c, real_t d) {
- return -c * cos(t / d * (pi / 2)) + c + b;
-}
-
-static real_t out(real_t t, real_t b, real_t c, real_t d) {
- return c * sin(t / d * (pi / 2)) + b;
-}
-
-static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
- return -c / 2 * (cos(pi * t / d) - 1) + b;
-}
-
-static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
- return (t < d / 2) ? out(t * 2, b, c / 2, d) : in((t * 2) - d, b + c / 2, c / 2, d);
-}
-}; // namespace sine
-///////////////////////////////////////////////////////////////////////////
-// quint
-///////////////////////////////////////////////////////////////////////////
-namespace quint {
-static real_t in(real_t t, real_t b, real_t c, real_t d) {
- return c * pow(t / d, 5) + b;
-}
-
-static real_t out(real_t t, real_t b, real_t c, real_t d) {
- return c * (pow(t / d - 1, 5) + 1) + b;
-}
-
-static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
- t = t / d * 2;
- if (t < 1) return c / 2 * pow(t, 5) + b;
- return c / 2 * (pow(t - 2, 5) + 2) + b;
-}
-
-static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
- return (t < d / 2) ? out(t * 2, b, c / 2, d) : in((t * 2) - d, b + c / 2, c / 2, d);
-}
-}; // namespace quint
-///////////////////////////////////////////////////////////////////////////
-// quart
-///////////////////////////////////////////////////////////////////////////
-namespace quart {
-static real_t in(real_t t, real_t b, real_t c, real_t d) {
- return c * pow(t / d, 4) + b;
-}
-
-static real_t out(real_t t, real_t b, real_t c, real_t d) {
- return -c * (pow(t / d - 1, 4) - 1) + b;
-}
-
-static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
- t = t / d * 2;
- if (t < 1) return c / 2 * pow(t, 4) + b;
- return -c / 2 * (pow(t - 2, 4) - 2) + b;
-}
-
-static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
- return (t < d / 2) ? out(t * 2, b, c / 2, d) : in((t * 2) - d, b + c / 2, c / 2, d);
-}
-}; // namespace quart
-///////////////////////////////////////////////////////////////////////////
-// quad
-///////////////////////////////////////////////////////////////////////////
-namespace quad {
-static real_t in(real_t t, real_t b, real_t c, real_t d) {
- return c * pow(t / d, 2) + b;
-}
-
-static real_t out(real_t t, real_t b, real_t c, real_t d) {
- t = t / d;
- return -c * t * (t - 2) + b;
-}
-
-static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
- t = t / d * 2;
- if (t < 1) return c / 2 * pow(t, 2) + b;
- return -c / 2 * ((t - 1) * (t - 3) - 1) + b;
-}
-
-static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
- return (t < d / 2) ? out(t * 2, b, c / 2, d) : in((t * 2) - d, b + c / 2, c / 2, d);
-}
-}; // namespace quad
-///////////////////////////////////////////////////////////////////////////
-// expo
-///////////////////////////////////////////////////////////////////////////
-namespace expo {
-static real_t in(real_t t, real_t b, real_t c, real_t d) {
- if (t == 0) return b;
- return c * pow(2, 10 * (t / d - 1)) + b - c * 0.001;
-}
-
-static real_t out(real_t t, real_t b, real_t c, real_t d) {
- if (t == d) return b + c;
- return c * 1.001 * (-pow(2, -10 * t / d) + 1) + b;
-}
-
-static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
- if (t == 0) return b;
- if (t == d) return b + c;
- t = t / d * 2;
- if (t < 1) return c / 2 * pow(2, 10 * (t - 1)) + b - c * 0.0005;
- return c / 2 * 1.0005 * (-pow(2, -10 * (t - 1)) + 2) + b;
-}
-
-static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
- return (t < d / 2) ? out(t * 2, b, c / 2, d) : in((t * 2) - d, b + c / 2, c / 2, d);
-}
-}; // namespace expo
-///////////////////////////////////////////////////////////////////////////
-// elastic
-///////////////////////////////////////////////////////////////////////////
-namespace elastic {
-static real_t in(real_t t, real_t b, real_t c, real_t d) {
- if (t == 0) return b;
- if ((t /= d) == 1) return b + c;
- float p = d * 0.3f;
- float a = c;
- float s = p / 4;
- float postFix = a * pow(2, 10 * (t -= 1)); // this is a fix, again, with post-increment operators
- return -(postFix * sin((t * d - s) * (2 * pi) / p)) + b;
-}
-
-static real_t out(real_t t, real_t b, real_t c, real_t d) {
- if (t == 0) return b;
- if ((t /= d) == 1) return b + c;
- float p = d * 0.3f;
- float a = c;
- float s = p / 4;
- return (a * pow(2, -10 * t) * sin((t * d - s) * (2 * pi) / p) + c + b);
-}
-
-static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
- if (t == 0) return b;
- if ((t /= d / 2) == 2) return b + c;
- float p = d * (0.3f * 1.5f);
- float a = c;
- float s = p / 4;
-
- if (t < 1) {
- float postFix = a * pow(2, 10 * (t -= 1)); // postIncrement is evil
- return -0.5f * (postFix * sin((t * d - s) * (2 * pi) / p)) + b;
- }
- float postFix = a * pow(2, -10 * (t -= 1)); // postIncrement is evil
- return postFix * sin((t * d - s) * (2 * pi) / p) * 0.5f + c + b;
-}
-
-static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
- return (t < d / 2) ? out(t * 2, b, c / 2, d) : in((t * 2) - d, b + c / 2, c / 2, d);
-}
-}; // namespace elastic
-///////////////////////////////////////////////////////////////////////////
-// cubic
-///////////////////////////////////////////////////////////////////////////
-namespace cubic {
-static real_t in(real_t t, real_t b, real_t c, real_t d) {
- return c * (t /= d) * t * t + b;
-}
-
-static real_t out(real_t t, real_t b, real_t c, real_t d) {
- t = t / d - 1;
- return c * (t * t * t + 1) + b;
-}
-
-static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
- if ((t /= d / 2) < 1) return c / 2 * t * t * t + b;
- return c / 2 * ((t -= 2) * t * t + 2) + b;
-}
-
-static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
- return (t < d / 2) ? out(t * 2, b, c / 2, d) : in((t * 2) - d, b + c / 2, c / 2, d);
-}
-}; // namespace cubic
-///////////////////////////////////////////////////////////////////////////
-// circ
-///////////////////////////////////////////////////////////////////////////
-namespace circ {
-static real_t in(real_t t, real_t b, real_t c, real_t d) {
- return -c * (sqrt(1 - (t /= d) * t) - 1) + b; // TODO: ehrich: operation with t is undefined
-}
-
-static real_t out(real_t t, real_t b, real_t c, real_t d) {
- return c * sqrt(1 - (t = t / d - 1) * t) + b; // TODO: ehrich: operation with t is undefined
-}
-
-static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
- if ((t /= d / 2) < 1) return -c / 2 * (sqrt(1 - t * t) - 1) + b;
- return c / 2 * (sqrt(1 - t * (t -= 2)) + 1) + b; // TODO: ehrich: operation with t is undefined
-}
-
-static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
- return (t < d / 2) ? out(t * 2, b, c / 2, d) : in((t * 2) - d, b + c / 2, c / 2, d);
-}
-}; // namespace circ
-///////////////////////////////////////////////////////////////////////////
-// bounce
-///////////////////////////////////////////////////////////////////////////
-namespace bounce {
-static real_t out(real_t t, real_t b, real_t c, real_t d);
-
-static real_t in(real_t t, real_t b, real_t c, real_t d) {
- return c - out(d - t, 0, c, d) + b;
-}
-
-static real_t out(real_t t, real_t b, real_t c, real_t d) {
- if ((t /= d) < (1 / 2.75f)) {
- return c * (7.5625f * t * t) + b;
- } else if (t < (2 / 2.75f)) {
- float postFix = t -= (1.5f / 2.75f);
- return c * (7.5625f * (postFix)*t + .75f) + b;
- } else if (t < (2.5 / 2.75)) {
- float postFix = t -= (2.25f / 2.75f);
- return c * (7.5625f * (postFix)*t + .9375f) + b;
- } else {
- float postFix = t -= (2.625f / 2.75f);
- return c * (7.5625f * (postFix)*t + .984375f) + b;
- }
-}
-
-static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
- return (t < d / 2) ? in(t * 2, b, c / 2, d) : out((t * 2) - d, b + c / 2, c / 2, d);
-}
-
-static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
- return (t < d / 2) ? out(t * 2, b, c / 2, d) : in((t * 2) - d, b + c / 2, c / 2, d);
-}
-}; // namespace bounce
-///////////////////////////////////////////////////////////////////////////
-// back
-///////////////////////////////////////////////////////////////////////////
-namespace back {
-static real_t in(real_t t, real_t b, real_t c, real_t d) {
- float s = 1.70158f;
- float postFix = t /= d;
- return c * (postFix)*t * ((s + 1) * t - s) + b;
-}
-
-static real_t out(real_t t, real_t b, real_t c, real_t d) {
- float s = 1.70158f;
- return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; // TODO: ehrich: operation with t is undefined
-}
-
-static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
- float s = 1.70158f;
- if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525f)) + 1) * t - s)) + b; // TODO: ehrich: operation with s is undefined
- float postFix = t -= 2;
- return c / 2 * ((postFix)*t * (((s *= (1.525f)) + 1) * t + s) + 2) + b; // TODO: ehrich: operation with s is undefined
-}
-
-static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
- return (t < d / 2) ? out(t * 2, b, c / 2, d) : in((t * 2) - d, b + c / 2, c / 2, d);
-}
-}; // namespace back
-
-Tween::interpolater Tween::interpolaters[Tween::TRANS_COUNT][Tween::EASE_COUNT] = {
- { &linear::in, &linear::out, &linear::in_out, &linear::out_in },
- { &sine::in, &sine::out, &sine::in_out, &sine::out_in },
- { &quint::in, &quint::out, &quint::in_out, &quint::out_in },
- { &quart::in, &quart::out, &quart::in_out, &quart::out_in },
- { &quad::in, &quad::out, &quad::in_out, &quad::out_in },
- { &expo::in, &expo::out, &expo::in_out, &expo::out_in },
- { &elastic::in, &elastic::out, &elastic::in_out, &elastic::out_in },
- { &cubic::in, &cubic::out, &cubic::in_out, &cubic::out_in },
- { &circ::in, &circ::out, &circ::in_out, &circ::out_in },
- { &bounce::in, &bounce::out, &bounce::in_out, &bounce::out_in },
- { &back::in, &back::out, &back::in_out, &back::out_in },
-};
-
-real_t Tween::_run_equation(TransitionType p_trans_type, EaseType p_ease_type, real_t t, real_t b, real_t c, real_t d) {
-
- interpolater cb = interpolaters[p_trans_type][p_ease_type];
- ERR_FAIL_COND_V(cb == NULL, b);
- return cb(t, b, c, d);
-}