diff options
Diffstat (limited to 'scene/animation/animation_tree.cpp')
-rw-r--r-- | scene/animation/animation_tree.cpp | 171 |
1 files changed, 114 insertions, 57 deletions
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 64c71697a5..92af15d5d3 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -198,12 +198,11 @@ double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<Stri blendw[i] = 0.0; //all to zero by default } - const NodePath *K = nullptr; - while ((K = filter.next(K))) { - if (!state->track_map.has(*K)) { + for (const KeyValue<NodePath, bool> &E : filter) { + if (!state->track_map.has(E.key)) { continue; } - int idx = state->track_map[*K]; + int idx = state->track_map[E.key]; blendw[idx] = 1.0; //filtered goes to one } @@ -374,9 +373,8 @@ bool AnimationNode::has_filter() const { Array AnimationNode::_get_filters() const { Array paths; - const NodePath *K = nullptr; - while ((K = filter.next(K))) { - paths.push_back(String(*K)); //use strings, so sorting is possible + for (const KeyValue<NodePath, bool> &E : filter) { + paths.push_back(String(E.key)); //use strings, so sorting is possible } paths.sort(); //done so every time the scene is saved, it does not change @@ -488,7 +486,7 @@ void AnimationTree::set_active(bool p_active) { } if (!active && is_inside_tree()) { - for (Set<TrackCache *>::Element *E = playing_caches.front(); E; E = E->next()) { + for (RBSet<TrackCache *>::Element *E = playing_caches.front(); E; E = E->next()) { if (ObjectDB::get_instance(E->get()->object_id)) { E->get()->object->call(SNAME("stop")); } @@ -540,6 +538,11 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { List<StringName> sname; player->get_animation_list(&sname); + Ref<Animation> reset_anim; + bool has_reset_anim = player->has_animation(SceneStringNames::get_singleton()->RESET); + if (has_reset_anim) { + reset_anim = player->get_animation(SceneStringNames::get_singleton()->RESET); + } for (const StringName &E : sname) { Ref<Animation> anim = player->get_animation(E); for (int i = 0; i < anim->get_track_count(); i++) { @@ -565,7 +568,7 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { } if (!track) { - RES resource; + Ref<Resource> resource; Vector<StringName> leftover_path; Node *child = parent->get_node_and_resource(path, resource, leftover_path); @@ -593,6 +596,12 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { track = track_value; + if (has_reset_anim) { + int rt = reset_anim->find_track(path, track_type); + if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) { + track_value->init_value = reset_anim->track_get_key_value(rt, 0); + } + } } break; case Animation::TYPE_POSITION_3D: case Animation::TYPE_ROTATION_3D: @@ -612,16 +621,17 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { track_xform->skeleton = nullptr; track_xform->bone_idx = -1; + bool has_rest = false; if (path.get_subname_count() == 1 && Object::cast_to<Skeleton3D>(node_3d)) { Skeleton3D *sk = Object::cast_to<Skeleton3D>(node_3d); track_xform->skeleton = sk; int bone_idx = sk->find_bone(path.get_subname(0)); if (bone_idx != -1) { + has_rest = true; track_xform->bone_idx = bone_idx; Transform3D rest = sk->get_bone_rest(bone_idx); track_xform->init_loc = rest.origin; - track_xform->ref_rot = rest.basis.get_rotation_quaternion(); - track_xform->init_rot = track_xform->ref_rot.log(); + track_xform->init_rot = rest.basis.get_rotation_quaternion(); track_xform->init_scale = rest.basis.get_scale(); } } @@ -645,6 +655,25 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { } } + // For non Skeleton3D bone animation. + if (has_reset_anim && !has_rest) { + int rt = reset_anim->find_track(path, track_type); + if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) { + switch (track_type) { + case Animation::TYPE_POSITION_3D: { + track_xform->init_loc = reset_anim->track_get_key_value(rt, 0); + } break; + case Animation::TYPE_ROTATION_3D: { + track_xform->init_rot = reset_anim->track_get_key_value(rt, 0); + } break; + case Animation::TYPE_SCALE_3D: { + track_xform->init_scale = reset_anim->track_get_key_value(rt, 0); + } break; + default: { + } + } + } + } #endif // _3D_DISABLED } break; case Animation::TYPE_BLEND_SHAPE: { @@ -675,6 +704,13 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { track_bshape->object = mesh_3d; track_bshape->object_id = mesh_3d->get_instance_id(); track = track_bshape; + + if (has_reset_anim) { + int rt = reset_anim->find_track(path, track_type); + if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) { + track_bshape->init_value = reset_anim->track_get_key_value(rt, 0); + } + } #endif } break; case Animation::TYPE_METHOD: { @@ -704,6 +740,13 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { track_bezier->object_id = track_bezier->object->get_instance_id(); track = track_bezier; + + if (has_reset_anim) { + int rt = reset_anim->find_track(path, track_type); + if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) { + track_bezier->init_value = reset_anim->track_get_key_value(rt, 0); + } + } } break; case Animation::TYPE_AUDIO: { TrackCacheAudio *track_audio = memnew(TrackCacheAudio); @@ -758,11 +801,10 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { List<NodePath> to_delete; - const NodePath *K = nullptr; - while ((K = track_cache.next(K))) { - TrackCache *tc = track_cache[*K]; + for (const KeyValue<NodePath, TrackCache *> &K : track_cache) { + TrackCache *tc = track_cache[K.key]; if (tc->setup_pass != setup_pass) { - to_delete.push_back(*K); + to_delete.push_back(K.key); } } @@ -775,10 +817,9 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { state.track_map.clear(); - K = nullptr; int idx = 0; - while ((K = track_cache.next(K))) { - state.track_map[*K] = idx; + for (const KeyValue<NodePath, TrackCache *> &K : track_cache) { + state.track_map[K.key] = idx; idx++; } @@ -790,9 +831,8 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { } void AnimationTree::_clear_caches() { - const NodePath *K = nullptr; - while ((K = track_cache.next(K))) { - memdelete(track_cache[*K]); + for (KeyValue<NodePath, TrackCache *> &K : track_cache) { + memdelete(K.value); } playing_caches.clear(); @@ -950,13 +990,13 @@ void AnimationTree::_process_graph(double p_delta) { case Animation::TYPE_POSITION_3D: { #ifndef _3D_DISABLED TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track); - if (t->process_pass != process_pass) { - t->process_pass = process_pass; - t->loc = t->init_loc; - t->rot = t->init_rot; - t->scale = t->init_scale; - } if (track->root_motion) { + if (t->process_pass != process_pass) { + t->process_pass = process_pass; + t->loc = Vector3(0, 0, 0); + t->rot = Quaternion(0, 0, 0, 1); + t->scale = Vector3(0, 0, 0); + } double prev_time = time - delta; if (!backward) { if (prev_time < 0) { @@ -1026,6 +1066,12 @@ void AnimationTree::_process_graph(double p_delta) { prev_time = !backward ? 0 : (double)a->get_length(); } else { + if (t->process_pass != process_pass) { + t->process_pass = process_pass; + t->loc = t->init_loc; + t->rot = t->init_rot; + t->scale = t->init_scale; + } Vector3 loc; Error err = a->position_track_interpolate(i, time, &loc); @@ -1040,13 +1086,13 @@ void AnimationTree::_process_graph(double p_delta) { case Animation::TYPE_ROTATION_3D: { #ifndef _3D_DISABLED TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track); - if (t->process_pass != process_pass) { - t->process_pass = process_pass; - t->loc = t->init_loc; - t->rot = t->init_rot; - t->scale = t->init_scale; - } if (track->root_motion) { + if (t->process_pass != process_pass) { + t->process_pass = process_pass; + t->loc = Vector3(0, 0, 0); + t->rot = Quaternion(0, 0, 0, 1); + t->scale = Vector3(0, 0, 0); + } double prev_time = time - delta; if (!backward) { if (prev_time < 0) { @@ -1091,7 +1137,7 @@ void AnimationTree::_process_graph(double p_delta) { continue; } a->rotation_track_interpolate(i, (double)a->get_length(), &rot[1]); - t->rot += (rot[1].log() - rot[0].log()) * blend; + t->rot = (t->rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized(); prev_time = 0; } } else { @@ -1101,7 +1147,7 @@ void AnimationTree::_process_graph(double p_delta) { continue; } a->rotation_track_interpolate(i, 0, &rot[1]); - t->rot += (rot[1].log() - rot[0].log()) * blend; + t->rot = (t->rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized(); prev_time = 0; } } @@ -1112,10 +1158,16 @@ void AnimationTree::_process_graph(double p_delta) { } a->rotation_track_interpolate(i, time, &rot[1]); - t->rot += (rot[1].log() - rot[0].log()) * blend; + t->rot = (t->rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized(); prev_time = !backward ? 0 : (double)a->get_length(); } else { + if (t->process_pass != process_pass) { + t->process_pass = process_pass; + t->loc = t->init_loc; + t->rot = t->init_rot; + t->scale = t->init_scale; + } Quaternion rot; Error err = a->rotation_track_interpolate(i, time, &rot); @@ -1123,23 +1175,20 @@ void AnimationTree::_process_graph(double p_delta) { continue; } - if (signbit(rot.dot(t->ref_rot))) { - rot = -rot; - } - t->rot += (rot.log() - t->init_rot) * blend; + t->rot = (t->rot * Quaternion().slerp(t->init_rot.inverse() * rot, blend)).normalized(); } #endif // _3D_DISABLED } break; case Animation::TYPE_SCALE_3D: { #ifndef _3D_DISABLED TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track); - if (t->process_pass != process_pass) { - t->process_pass = process_pass; - t->loc = t->init_loc; - t->rot = t->init_rot; - t->scale = t->init_scale; - } if (track->root_motion) { + if (t->process_pass != process_pass) { + t->process_pass = process_pass; + t->loc = Vector3(0, 0, 0); + t->rot = Quaternion(0, 0, 0, 1); + t->scale = Vector3(0, 0, 0); + } double prev_time = time - delta; if (!backward) { if (prev_time < 0) { @@ -1209,6 +1258,12 @@ void AnimationTree::_process_graph(double p_delta) { prev_time = !backward ? 0 : (double)a->get_length(); } else { + if (t->process_pass != process_pass) { + t->process_pass = process_pass; + t->loc = t->init_loc; + t->rot = t->init_rot; + t->scale = t->init_scale; + } Vector3 scale; Error err = a->scale_track_interpolate(i, time, &scale); @@ -1226,7 +1281,7 @@ void AnimationTree::_process_graph(double p_delta) { if (t->process_pass != process_pass) { t->process_pass = process_pass; - t->value = 0; + t->value = t->init_value; } float value; @@ -1238,7 +1293,7 @@ void AnimationTree::_process_graph(double p_delta) { continue; } - t->value += value * blend; + t->value += (value - t->init_value) * blend; #endif // _3D_DISABLED } break; case Animation::TYPE_VALUE: { @@ -1256,10 +1311,14 @@ void AnimationTree::_process_graph(double p_delta) { if (t->process_pass != process_pass) { t->process_pass = process_pass; - t->value = value; - t->value.zero(); + if (!t->init_value) { + t->init_value = value; + t->init_value.zero(); + } + t->value = t->init_value; } + Variant::sub(value, t->init_value, value); Variant::blend(t->value, value, blend, t->value); } else { if (blend < CMP_EPSILON) { @@ -1303,10 +1362,10 @@ void AnimationTree::_process_graph(double p_delta) { if (t->process_pass != process_pass) { t->process_pass = process_pass; - t->value = 0; + t->value = t->init_value; } - t->value += bezier * blend; + t->value += (bezier - t->init_value) * blend; } break; case Animation::TYPE_AUDIO: { if (blend < CMP_EPSILON) { @@ -1505,9 +1564,8 @@ void AnimationTree::_process_graph(double p_delta) { { // finally, set the tracks - const NodePath *K = nullptr; - while ((K = track_cache.next(K))) { - TrackCache *track = track_cache[*K]; + for (const KeyValue<NodePath, TrackCache *> &K : track_cache) { + TrackCache *track = K.value; if (track->process_pass != process_pass) { continue; //not processed, ignore } @@ -1516,12 +1574,11 @@ void AnimationTree::_process_graph(double p_delta) { case Animation::TYPE_POSITION_3D: { #ifndef _3D_DISABLED TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track); - t->rot = t->rot.exp(); if (t->root_motion) { Transform3D xform; xform.origin = t->loc; - xform.basis.set_quaternion_scale(t->rot, t->scale); + xform.basis.set_quaternion_scale(t->rot, Vector3(1, 1, 1) + t->scale); root_motion_transform = xform; |