|
@@ -129,6 +129,9 @@ void AnimationMixer::_validate_property(PropertyInfo &p_property) const {
|
|
|
p_property.usage |= PROPERTY_USAGE_READ_ONLY;
|
|
|
}
|
|
|
#endif // TOOLS_ENABLED
|
|
|
+ if (root_motion_track.is_empty() && p_property.name == "root_motion_local") {
|
|
|
+ p_property.usage = PROPERTY_USAGE_NONE;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
@@ -1212,6 +1215,10 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
|
|
|
}
|
|
|
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
|
|
|
if (track->root_motion && calc_root) {
|
|
|
+ int rot_track = -1;
|
|
|
+ if (root_motion_local) {
|
|
|
+ rot_track = a->find_track(a->track_get_path(i), Animation::TYPE_ROTATION_3D);
|
|
|
+ }
|
|
|
double prev_time = time - delta;
|
|
|
if (!backward) {
|
|
|
if (Animation::is_less_approx(prev_time, start)) {
|
|
@@ -1246,41 +1253,92 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- Vector3 loc[2];
|
|
|
- if (!backward) {
|
|
|
- if (Animation::is_greater_approx(prev_time, time)) {
|
|
|
- Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]);
|
|
|
- if (err != OK) {
|
|
|
- continue;
|
|
|
+ if (rot_track >= 0) {
|
|
|
+ Vector3 loc[2];
|
|
|
+ Quaternion rot;
|
|
|
+ if (!backward) {
|
|
|
+ if (Animation::is_greater_approx(prev_time, time)) {
|
|
|
+ Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]);
|
|
|
+ if (err != OK) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx);
|
|
|
+ a->try_position_track_interpolate(i, end, &loc[1]);
|
|
|
+ loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx);
|
|
|
+
|
|
|
+ a->try_rotation_track_interpolate(rot_track, end, &rot);
|
|
|
+ rot = post_process_key_value(a, rot_track, rot, t->object_id, t->bone_idx);
|
|
|
+
|
|
|
+ root_motion_cache.loc += rot.xform_inv(loc[1] - loc[0]) * blend;
|
|
|
+ prev_time = start;
|
|
|
}
|
|
|
- loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx);
|
|
|
- a->try_position_track_interpolate(i, end, &loc[1]);
|
|
|
- loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx);
|
|
|
- root_motion_cache.loc += (loc[1] - loc[0]) * blend;
|
|
|
- prev_time = start;
|
|
|
+ } else {
|
|
|
+ if (Animation::is_less_approx(prev_time, time)) {
|
|
|
+ Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]);
|
|
|
+ if (err != OK) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx);
|
|
|
+ a->try_position_track_interpolate(i, start, &loc[1]);
|
|
|
+ loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx);
|
|
|
+
|
|
|
+ a->try_rotation_track_interpolate(rot_track, start, &rot);
|
|
|
+ rot = post_process_key_value(a, rot_track, rot, t->object_id, t->bone_idx);
|
|
|
+
|
|
|
+ root_motion_cache.loc += rot.xform_inv(loc[1] - loc[0]) * blend;
|
|
|
+ prev_time = end;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]);
|
|
|
+ if (err != OK) {
|
|
|
+ continue;
|
|
|
}
|
|
|
+ loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx);
|
|
|
+ a->try_position_track_interpolate(i, time, &loc[1]);
|
|
|
+ loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx);
|
|
|
+
|
|
|
+ a->try_rotation_track_interpolate(rot_track, time, &rot);
|
|
|
+ rot = post_process_key_value(a, rot_track, rot, t->object_id, t->bone_idx);
|
|
|
+
|
|
|
+ root_motion_cache.loc += rot.xform_inv(loc[1] - loc[0]) * blend;
|
|
|
+ prev_time = !backward ? start : end;
|
|
|
} else {
|
|
|
- if (Animation::is_less_approx(prev_time, time)) {
|
|
|
- Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]);
|
|
|
- if (err != OK) {
|
|
|
- continue;
|
|
|
+ Vector3 loc[2];
|
|
|
+ if (!backward) {
|
|
|
+ if (Animation::is_greater_approx(prev_time, time)) {
|
|
|
+ Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]);
|
|
|
+ if (err != OK) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx);
|
|
|
+ a->try_position_track_interpolate(i, end, &loc[1]);
|
|
|
+ loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx);
|
|
|
+ root_motion_cache.loc += (loc[1] - loc[0]) * blend;
|
|
|
+ prev_time = start;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (Animation::is_less_approx(prev_time, time)) {
|
|
|
+ Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]);
|
|
|
+ if (err != OK) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx);
|
|
|
+ a->try_position_track_interpolate(i, start, &loc[1]);
|
|
|
+ loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx);
|
|
|
+ root_motion_cache.loc += (loc[1] - loc[0]) * blend;
|
|
|
+ prev_time = end;
|
|
|
}
|
|
|
- loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx);
|
|
|
- a->try_position_track_interpolate(i, start, &loc[1]);
|
|
|
- loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx);
|
|
|
- root_motion_cache.loc += (loc[1] - loc[0]) * blend;
|
|
|
- prev_time = end;
|
|
|
}
|
|
|
+ Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]);
|
|
|
+ if (err != OK) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx);
|
|
|
+ a->try_position_track_interpolate(i, time, &loc[1]);
|
|
|
+ loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx);
|
|
|
+ root_motion_cache.loc += (loc[1] - loc[0]) * blend;
|
|
|
+ prev_time = !backward ? start : end;
|
|
|
}
|
|
|
- Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]);
|
|
|
- if (err != OK) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx);
|
|
|
- a->try_position_track_interpolate(i, time, &loc[1]);
|
|
|
- loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx);
|
|
|
- root_motion_cache.loc += (loc[1] - loc[0]) * blend;
|
|
|
- prev_time = !backward ? start : end;
|
|
|
}
|
|
|
{
|
|
|
Vector3 loc;
|
|
@@ -1355,6 +1413,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
|
|
|
}
|
|
|
rot[0] = post_process_key_value(a, i, rot[0], t->object_id, t->bone_idx);
|
|
|
a->try_rotation_track_interpolate(i, start, &rot[1]);
|
|
|
+ rot[1] = post_process_key_value(a, i, rot[1], t->object_id, t->bone_idx);
|
|
|
root_motion_cache.rot = (root_motion_cache.rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized();
|
|
|
prev_time = end;
|
|
|
}
|
|
@@ -1430,8 +1489,8 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
|
|
|
}
|
|
|
scale[0] = post_process_key_value(a, i, scale[0], t->object_id, t->bone_idx);
|
|
|
a->try_scale_track_interpolate(i, end, &scale[1]);
|
|
|
- root_motion_cache.scale += (scale[1] - scale[0]) * blend;
|
|
|
scale[1] = post_process_key_value(a, i, scale[1], t->object_id, t->bone_idx);
|
|
|
+ root_motion_cache.scale += (scale[1] - scale[0]) * blend;
|
|
|
prev_time = start;
|
|
|
}
|
|
|
} else {
|
|
@@ -2002,12 +2061,21 @@ void AnimationMixer::clear_caches() {
|
|
|
|
|
|
void AnimationMixer::set_root_motion_track(const NodePath &p_track) {
|
|
|
root_motion_track = p_track;
|
|
|
+ notify_property_list_changed();
|
|
|
}
|
|
|
|
|
|
NodePath AnimationMixer::get_root_motion_track() const {
|
|
|
return root_motion_track;
|
|
|
}
|
|
|
|
|
|
+void AnimationMixer::set_root_motion_local(bool p_enabled) {
|
|
|
+ root_motion_local = p_enabled;
|
|
|
+}
|
|
|
+
|
|
|
+bool AnimationMixer::is_root_motion_local() const {
|
|
|
+ return root_motion_local;
|
|
|
+}
|
|
|
+
|
|
|
Vector3 AnimationMixer::get_root_motion_position() const {
|
|
|
return root_motion_position;
|
|
|
}
|
|
@@ -2353,6 +2421,8 @@ void AnimationMixer::_bind_methods() {
|
|
|
/* ---- Root motion accumulator for Skeleton3D ---- */
|
|
|
ClassDB::bind_method(D_METHOD("set_root_motion_track", "path"), &AnimationMixer::set_root_motion_track);
|
|
|
ClassDB::bind_method(D_METHOD("get_root_motion_track"), &AnimationMixer::get_root_motion_track);
|
|
|
+ ClassDB::bind_method(D_METHOD("set_root_motion_local", "enabled"), &AnimationMixer::set_root_motion_local);
|
|
|
+ ClassDB::bind_method(D_METHOD("is_root_motion_local"), &AnimationMixer::is_root_motion_local);
|
|
|
|
|
|
ClassDB::bind_method(D_METHOD("get_root_motion_position"), &AnimationMixer::get_root_motion_position);
|
|
|
ClassDB::bind_method(D_METHOD("get_root_motion_rotation"), &AnimationMixer::get_root_motion_rotation);
|
|
@@ -2380,6 +2450,7 @@ void AnimationMixer::_bind_methods() {
|
|
|
|
|
|
ADD_GROUP("Root Motion", "root_motion_");
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_motion_track"), "set_root_motion_track", "get_root_motion_track");
|
|
|
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "root_motion_local"), "set_root_motion_local", "is_root_motion_local");
|
|
|
|
|
|
ADD_GROUP("Audio", "audio_");
|
|
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "audio_max_polyphony", PROPERTY_HINT_RANGE, "1,127,1"), "set_audio_max_polyphony", "get_audio_max_polyphony");
|