diff options
Diffstat (limited to 'scene/animation')
-rw-r--r-- | scene/animation/animation_tree.cpp | 57 | ||||
-rw-r--r-- | scene/animation/animation_tree.h | 9 | ||||
-rw-r--r-- | scene/animation/root_motion_view.cpp | 8 |
3 files changed, 52 insertions, 22 deletions
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index bb4bbb4673..50165773d0 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -221,7 +221,7 @@ double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<Stri } blendw[i] = blendr[i] * p_blend; - if (blendw[i] > CMP_EPSILON) { + if (!Math::is_zero_approx(blendw[i])) { any_valid = true; } } @@ -236,7 +236,7 @@ double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<Stri } blendw[i] = blendr[i] * p_blend; - if (blendw[i] > CMP_EPSILON) { + if (!Math::is_zero_approx(blendw[i])) { any_valid = true; } } @@ -252,7 +252,7 @@ double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<Stri blendw[i] = blendr[i]; //not filtered, do not blend } - if (blendw[i] > CMP_EPSILON) { + if (!Math::is_zero_approx(blendw[i])) { any_valid = true; } } @@ -263,7 +263,7 @@ double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<Stri for (int i = 0; i < blend_count; i++) { //regular blend blendw[i] = blendr[i] * p_blend; - if (blendw[i] > CMP_EPSILON) { + if (!Math::is_zero_approx(blendw[i])) { any_valid = true; } } @@ -586,6 +586,7 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { track_value->object = child; } + track_value->is_discrete = anim->value_track_get_update_mode(i) == Animation::UPDATE_DISCRETE || anim->value_track_get_update_mode(i) == Animation::UPDATE_TRIGGER; track_value->is_using_angle = anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_LINEAR_ANGLE || anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_CUBIC_ANGLE; track_value->subpath = leftover_path; @@ -799,8 +800,18 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { } } else if (track_cache_type == Animation::TYPE_VALUE) { // If it has at least one angle interpolation, it also uses angle interpolation for blending. - TrackCacheValue *track_value = memnew(TrackCacheValue); + TrackCacheValue *track_value = static_cast<TrackCacheValue *>(track); + bool was_discrete = track_value->is_discrete; + bool was_using_angle = track_value->is_using_angle; + track_value->is_discrete |= anim->value_track_get_update_mode(i) == Animation::UPDATE_DISCRETE || anim->value_track_get_update_mode(i) == Animation::UPDATE_TRIGGER; track_value->is_using_angle |= anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_LINEAR_ANGLE || anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_CUBIC_ANGLE; + + if (was_discrete != track_value->is_discrete) { + WARN_PRINT_ONCE("Tracks with different update modes are blended. Blending prioritizes Discrete/Trigger mode, so other update mode tracks will not be blended."); + } + if (was_using_angle != track_value->is_using_angle) { + WARN_PRINT_ONCE("Tracks for rotation with different interpolation types are blended. Blending prioritizes angle interpolation, so the blending result uses the shortest path referenced to the initial (RESET animation) value."); + } } track->setup_pass = setup_pass; @@ -872,7 +883,9 @@ void AnimationTree::_process_graph(double p_delta) { _update_properties(); //if properties need updating, update them //check all tracks, see if they need modification - root_motion_transform = Transform3D(); + root_motion_position = Vector3(0, 0, 0); + root_motion_rotation = Quaternion(0, 0, 0, 1); + root_motion_scale = Vector3(0, 0, 0); if (!root.is_valid()) { ERR_PRINT("AnimationTree: root AnimationNode is not set, disabling playback."); @@ -971,7 +984,7 @@ void AnimationTree::_process_graph(double p_delta) { if (track->root_motion) { t->loc = Vector3(0, 0, 0); t->rot = Quaternion(0, 0, 0, 1); - t->scale = Vector3(0, 0, 0); + t->scale = Vector3(1, 1, 1); } else { t->loc = t->init_loc; t->rot = t->init_rot; @@ -1026,7 +1039,7 @@ void AnimationTree::_process_graph(double p_delta) { int blend_idx = state.track_map[path]; ERR_CONTINUE(blend_idx < 0 || blend_idx >= state.track_count); real_t blend = (*as.track_blends)[blend_idx] * weight; - if (blend < CMP_EPSILON) { + if (Math::is_zero_approx(blend)) { continue; // Nothing to blend. } @@ -1617,11 +1630,9 @@ void AnimationTree::_process_graph(double p_delta) { TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track); if (t->root_motion) { - Transform3D xform; - xform.origin = t->loc; - xform.basis.set_quaternion_scale(t->rot, Vector3(1, 1, 1) + t->scale); - - root_motion_transform = xform; + root_motion_position = root_motion_rotation.xform_inv(t->loc); + root_motion_rotation = t->rot; + root_motion_scale = t->scale - Vector3(1, 1, 1); } else if (t->skeleton && t->bone_idx >= 0) { if (t->loc_used) { @@ -1659,6 +1670,10 @@ void AnimationTree::_process_graph(double p_delta) { case Animation::TYPE_VALUE: { TrackCacheValue *t = static_cast<TrackCacheValue *>(track); + if (t->is_discrete) { + break; // Don't overwrite the value set by UPDATE_DISCRETE or UPDATE_TRIGGER. + } + if (t->init_value.get_type() == Variant::BOOL) { t->object->set_indexed(t->subpath, t->value.operator real_t() >= 0.5); } else { @@ -1830,8 +1845,16 @@ NodePath AnimationTree::get_root_motion_track() const { return root_motion_track; } -Transform3D AnimationTree::get_root_motion_transform() const { - return root_motion_transform; +Vector3 AnimationTree::get_root_motion_position() const { + return root_motion_position; +} + +Quaternion AnimationTree::get_root_motion_rotation() const { + return root_motion_rotation; +} + +Vector3 AnimationTree::get_root_motion_scale() const { + return root_motion_scale; } void AnimationTree::_tree_changed() { @@ -1989,7 +2012,9 @@ void AnimationTree::_bind_methods() { ClassDB::bind_method(D_METHOD("set_root_motion_track", "path"), &AnimationTree::set_root_motion_track); ClassDB::bind_method(D_METHOD("get_root_motion_track"), &AnimationTree::get_root_motion_track); - ClassDB::bind_method(D_METHOD("get_root_motion_transform"), &AnimationTree::get_root_motion_transform); + ClassDB::bind_method(D_METHOD("get_root_motion_position"), &AnimationTree::get_root_motion_position); + ClassDB::bind_method(D_METHOD("get_root_motion_rotation"), &AnimationTree::get_root_motion_rotation); + ClassDB::bind_method(D_METHOD("get_root_motion_scale"), &AnimationTree::get_root_motion_scale); ClassDB::bind_method(D_METHOD("_update_properties"), &AnimationTree::_update_properties); diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index ae0926c22a..a4b0f992dc 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -232,6 +232,7 @@ private: Variant init_value; Variant value; Vector<StringName> subpath; + bool is_discrete = false; bool is_using_angle = false; TrackCacheValue() { type = Animation::TYPE_VALUE; } }; @@ -293,7 +294,9 @@ private: bool started = true; NodePath root_motion_track; - Transform3D root_motion_transform; + Vector3 root_motion_position = Vector3(0, 0, 0); + Quaternion root_motion_rotation = Quaternion(0, 0, 0, 1); + Vector3 root_motion_scale = Vector3(0, 0, 0); friend class AnimationNode; bool properties_dirty = true; @@ -349,7 +352,9 @@ public: void set_root_motion_track(const NodePath &p_track); NodePath get_root_motion_track() const; - Transform3D get_root_motion_transform() const; + Vector3 get_root_motion_position() const; + Quaternion get_root_motion_rotation() const; + Vector3 get_root_motion_scale() const; real_t get_connection_activity(const StringName &p_path, int p_connection) const; void advance(double p_time); diff --git a/scene/animation/root_motion_view.cpp b/scene/animation/root_motion_view.cpp index 47f08219a9..a6ccb4a576 100644 --- a/scene/animation/root_motion_view.cpp +++ b/scene/animation/root_motion_view.cpp @@ -103,7 +103,8 @@ void RootMotionView::_notification(int p_what) { set_physics_process_internal(false); } - transform = tree->get_root_motion_transform(); + transform.origin = tree->get_root_motion_position(); + transform.basis = tree->get_root_motion_rotation(); // Scale is meaningless. } } @@ -113,9 +114,8 @@ void RootMotionView::_notification(int p_what) { first = false; - transform.orthonormalize(); //don't want scale, too imprecise - - accumulated = accumulated * transform; + accumulated.origin += transform.origin; + accumulated.basis *= transform.basis; accumulated.origin.x = Math::fposmod(accumulated.origin.x, cell_size); if (zero_y) { accumulated.origin.y = 0; |