Removed Transform type track from the Animation. This leaves a few things, like the skeleton editor broken, it will be fixed soon.

This commit is contained in:
Relintai 2022-08-09 17:40:42 +02:00
parent 5cd0ea7e60
commit 6d293dc7a3
16 changed files with 147 additions and 1032 deletions

View File

@ -477,25 +477,6 @@
Swaps the track [code]idx[/code]'s index position with the track [code]with_idx[/code].
</description>
</method>
<method name="transform_track_insert_key">
<return type="int" />
<argument index="0" name="track_idx" type="int" />
<argument index="1" name="time" type="float" />
<argument index="2" name="location" type="Vector3" />
<argument index="3" name="rotation" type="Quat" />
<argument index="4" name="scale" type="Vector3" />
<description>
Insert a transform key for a transform track.
</description>
</method>
<method name="transform_track_interpolate" qualifiers="const">
<return type="Array" />
<argument index="0" name="track_idx" type="int" />
<argument index="1" name="time_sec" type="float" />
<description>
Returns the interpolated value of a transform track at a given time (in seconds). An array consisting of 3 elements: position ([Vector3]), rotation ([Quat]) and scale ([Vector3]).
</description>
</method>
<method name="value_track_get_key_indices" qualifiers="const">
<return type="PoolIntArray" />
<argument index="0" name="track_idx" type="int" />
@ -552,25 +533,22 @@
<constant name="TYPE_VALUE" value="0" enum="TrackType">
Value tracks set values in node properties, but only those which can be Interpolated.
</constant>
<constant name="TYPE_TRANSFORM" value="1" enum="TrackType">
Transform tracks are used to change node local transforms or skeleton pose bones. Transitions are interpolated.
<constant name="TYPE_POSITION_3D" value="1" enum="TrackType">
</constant>
<constant name="TYPE_POSITION_3D" value="2" enum="TrackType">
<constant name="TYPE_ROTATION_3D" value="2" enum="TrackType">
</constant>
<constant name="TYPE_ROTATION_3D" value="3" enum="TrackType">
<constant name="TYPE_SCALE_3D" value="3" enum="TrackType">
</constant>
<constant name="TYPE_SCALE_3D" value="4" enum="TrackType">
</constant>
<constant name="TYPE_METHOD" value="5" enum="TrackType">
<constant name="TYPE_METHOD" value="4" enum="TrackType">
Method tracks call functions with given arguments per key.
</constant>
<constant name="TYPE_BEZIER" value="6" enum="TrackType">
<constant name="TYPE_BEZIER" value="5" enum="TrackType">
Bezier tracks are used to interpolate a value using custom curves. They can also be used to animate sub-properties of vectors and colors (e.g. alpha value of a [Color]).
</constant>
<constant name="TYPE_AUDIO" value="7" enum="TrackType">
<constant name="TYPE_AUDIO" value="6" enum="TrackType">
Audio tracks are used to play an audio stream with either type of [AudioStreamPlayer]. The stream can be trimmed and previewed in the animation.
</constant>
<constant name="TYPE_ANIMATION" value="8" enum="TrackType">
<constant name="TYPE_ANIMATION" value="7" enum="TrackType">
Animation tracks play animations in other [AnimationPlayer] nodes.
</constant>
<constant name="INTERPOLATION_NEAREST" value="0" enum="InterpolationType">

View File

@ -22,7 +22,7 @@
<method name="get_root_motion_transform" qualifiers="const">
<return type="Transform" />
<description>
Retrieve the motion of the [member root_motion_track] as a [Transform] that can be used elsewhere. If [member root_motion_track] is not a path to a track of type [constant Animation.TYPE_TRANSFORM], [constant Animation.TYPE_POSITION_3D], [constant Animation.TYPE_SCALE_3D] or [constant Animation.TYPE_ROTATION_3D], returns an identity transformation. See also [member root_motion_track] and [RootMotionView].
Retrieve the motion of the [member root_motion_track] as a [Transform] that can be used elsewhere. If [member root_motion_track] is not a path to a track of type [constant Animation.TYPE_POSITION_3D], [constant Animation.TYPE_SCALE_3D] or [constant Animation.TYPE_ROTATION_3D], returns an identity transformation. See also [member root_motion_track] and [RootMotionView].
</description>
</method>
<method name="rename_parameter">
@ -45,7 +45,7 @@
</member>
<member name="root_motion_track" type="NodePath" setter="set_root_motion_track" getter="get_root_motion_track" default="NodePath(&quot;&quot;)">
The path to the Animation track used for root motion. Paths must be valid scene-tree paths to a node, and must be specified starting from the parent node of the node that will reproduce the animation. To specify a track that controls properties or bones, append its name after the path, separated by [code]":"[/code]. For example, [code]"character/skeleton:ankle"[/code] or [code]"character/mesh:transform/local"[/code].
If the track has type [constant Animation.TYPE_TRANSFORM], [constant Animation.TYPE_POSITION_3D], [constant Animation.TYPE_ROTATION_3D] or [constant Animation.TYPE_SCALE_3D], the transformation will be cancelled visually, and the animation will appear to stay in place. See also [method get_root_motion_transform] and [RootMotionView].
If the track has type [constant Animation.TYPE_POSITION_3D], [constant Animation.TYPE_ROTATION_3D] or [constant Animation.TYPE_SCALE_3D], the transformation will be cancelled visually, and the animation will appear to stay in place. See also [method get_root_motion_transform] and [RootMotionView].
</member>
<member name="tree_root" type="AnimationNode" setter="set_tree_root" getter="get_tree_root">
The root animation node of this [AnimationTree]. See [AnimationNode].

View File

@ -52,11 +52,9 @@
Returns the amount of bones in the skeleton.
</description>
</method>
<method name="get_bone_custom_pose" qualifiers="const">
<return type="Transform" />
<argument index="0" name="bone_idx" type="int" />
<method name="create_skin_from_rest_transforms">
<return type="Skin" />
<description>
Returns the custom pose of the specified bone. Custom pose is applied on top of the rest pose.
</description>
</method>
<method name="get_bone_global_pose" qualifiers="const">
@ -127,12 +125,6 @@
[i]Deprecated soon.[/i]
</description>
</method>
<method name="is_bone_rest_disabled" qualifiers="const">
<return type="bool" />
<argument index="0" name="bone_idx" type="int" />
<description>
</description>
</method>
<method name="localize_rests">
<return type="void" />
<description>
@ -173,20 +165,6 @@
<description>
</description>
</method>
<method name="set_bone_custom_pose">
<return type="void" />
<argument index="0" name="bone_idx" type="int" />
<argument index="1" name="custom_pose" type="Transform" />
<description>
</description>
</method>
<method name="set_bone_disable_rest">
<return type="void" />
<argument index="0" name="bone_idx" type="int" />
<argument index="1" name="disable" type="bool" />
<description>
</description>
</method>
<method name="set_bone_global_pose_override">
<return type="void" />
<argument index="0" name="bone_idx" type="int" />
@ -212,14 +190,6 @@
[b]Note:[/b] [code]parent_idx[/code] must be less than [code]bone_idx[/code].
</description>
</method>
<method name="set_bone_pose">
<return type="void" />
<argument index="0" name="bone_idx" type="int" />
<argument index="1" name="pose" type="Transform" />
<description>
Sets the pose transform for bone [code]bone_idx[/code]. Prefer set_bone_pose_position, set_bone_pose_rotation, or set_bone_pose_scale instead.
</description>
</method>
<method name="set_bone_pose_position">
<return type="void" />
<argument index="0" name="bone_idx" type="int" />

View File

@ -215,22 +215,6 @@ public:
}
switch (animation->track_get_type(track)) {
case Animation::TYPE_TRANSFORM: {
Dictionary d_old = animation->track_get_key_value(track, key);
Dictionary d_new = d_old.duplicate();
d_new[p_name] = p_value;
setting = true;
undo_redo->create_action(TTR("Anim Change Transform"));
undo_redo->add_do_method(animation.ptr(), "track_set_key_value", track, key, d_new);
undo_redo->add_undo_method(animation.ptr(), "track_set_key_value", track, key, d_old);
undo_redo->add_do_method(this, "_update_obj", animation);
undo_redo->add_undo_method(this, "_update_obj", animation);
undo_redo->commit_action();
setting = false;
return true;
} break;
case Animation::TYPE_POSITION_3D:
case Animation::TYPE_ROTATION_3D:
case Animation::TYPE_SCALE_3D: {
@ -496,13 +480,6 @@ public:
}
switch (animation->track_get_type(track)) {
case Animation::TYPE_TRANSFORM: {
Dictionary d = animation->track_get_key_value(track, key);
ERR_FAIL_COND_V(!d.has(name), false);
r_ret = d[p_name];
return true;
} break;
case Animation::TYPE_POSITION_3D:
case Animation::TYPE_ROTATION_3D:
case Animation::TYPE_SCALE_3D: {
@ -615,12 +592,6 @@ public:
}
switch (animation->track_get_type(track)) {
case Animation::TYPE_TRANSFORM: {
p_list->push_back(PropertyInfo(Variant::VECTOR3, "location"));
p_list->push_back(PropertyInfo(Variant::QUAT, "rotation"));
p_list->push_back(PropertyInfo(Variant::VECTOR3, "scale"));
} break;
case Animation::TYPE_POSITION_3D: {
p_list->push_back(PropertyInfo(Variant::VECTOR3, "position"));
@ -894,19 +865,6 @@ public:
}
switch (animation->track_get_type(track)) {
case Animation::TYPE_TRANSFORM: {
Dictionary d_old = animation->track_get_key_value(track, key);
Dictionary d_new = d_old.duplicate();
d_new[p_name] = p_value;
if (!setting) {
setting = true;
undo_redo->create_action(TTR("Anim Multi Change Transform"));
}
undo_redo->add_do_method(animation.ptr(), "track_set_key_value", track, key, d_new);
undo_redo->add_undo_method(animation.ptr(), "track_set_key_value", track, key, d_old);
update_obj = true;
} break;
case Animation::TYPE_POSITION_3D:
case Animation::TYPE_ROTATION_3D:
case Animation::TYPE_SCALE_3D: {
@ -1152,13 +1110,6 @@ public:
}
switch (animation->track_get_type(track)) {
case Animation::TYPE_TRANSFORM: {
Dictionary d = animation->track_get_key_value(track, key);
ERR_FAIL_COND_V(!d.has(name), false);
r_ret = d[p_name];
return true;
} break;
case Animation::TYPE_POSITION_3D:
case Animation::TYPE_ROTATION_3D:
case Animation::TYPE_SCALE_3D: {
@ -1311,11 +1262,6 @@ public:
if (same_track_type) {
switch (animation->track_get_type(first_track)) {
case Animation::TYPE_TRANSFORM: {
p_list->push_back(PropertyInfo(Variant::VECTOR3, "location"));
p_list->push_back(PropertyInfo(Variant::QUAT, "rotation"));
p_list->push_back(PropertyInfo(Variant::VECTOR3, "scale"));
} break;
case Animation::TYPE_POSITION_3D: {
p_list->push_back(PropertyInfo(Variant::VECTOR3, "position"));
} break;
@ -1527,7 +1473,6 @@ void AnimationTimelineEdit::_notification(int p_what) {
add_track->get_popup()->clear();
add_track->get_popup()->add_icon_item(get_icon("KeyValue", "EditorIcons"), TTR("Property Track"));
add_track->get_popup()->add_icon_item(get_icon("KeyXform", "EditorIcons"), TTR("3D Transform Track"));
add_track->get_popup()->add_icon_item(get_icon("KeyXPosition", "EditorIcons"), TTR("3D Position Track"));
add_track->get_popup()->add_icon_item(get_icon("KeyXRotation", "EditorIcons"), TTR("3D Rotation Track"));
add_track->get_popup()->add_icon_item(get_icon("KeyXScale", "EditorIcons"), TTR("3D Scale Track"));
@ -2210,7 +2155,7 @@ void AnimationTrackEdit::_notification(int p_what) {
Animation::TrackType track_type = animation->track_get_type(track);
if (track_type == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_TRANSFORM || track_type == Animation::TYPE_POSITION_3D || track_type == Animation::TYPE_SCALE_3D || track_type == Animation::TYPE_ROTATION_3D) {
if (track_type == Animation::TYPE_VALUE || track_type == Animation::TYPE_POSITION_3D || track_type == Animation::TYPE_SCALE_3D || track_type == Animation::TYPE_ROTATION_3D) {
draw_texture(icon, interp_mode_rect.position);
}
@ -2221,7 +2166,7 @@ void AnimationTrackEdit::_notification(int p_what) {
ofs += icon->get_width() + hsep;
interp_mode_rect.size.x += hsep;
if (track_type == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_TRANSFORM || track_type == Animation::TYPE_POSITION_3D || track_type == Animation::TYPE_SCALE_3D || track_type == Animation::TYPE_ROTATION_3D) {
if (track_type == Animation::TYPE_VALUE || track_type == Animation::TYPE_POSITION_3D || track_type == Animation::TYPE_SCALE_3D || track_type == Animation::TYPE_ROTATION_3D) {
draw_texture(down_icon, Vector2(ofs, int(get_size().height - down_icon->get_height()) / 2));
interp_mode_rect.size.x += down_icon->get_width();
} else {
@ -2246,7 +2191,7 @@ void AnimationTrackEdit::_notification(int p_what) {
Animation::TrackType track_type = animation->track_get_type(track);
if (track_type == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_TRANSFORM || track_type == Animation::TYPE_POSITION_3D || track_type == Animation::TYPE_SCALE_3D || track_type == Animation::TYPE_ROTATION_3D) {
if (track_type == Animation::TYPE_VALUE || track_type == Animation::TYPE_POSITION_3D || track_type == Animation::TYPE_SCALE_3D || track_type == Animation::TYPE_ROTATION_3D) {
draw_texture(icon, loop_mode_rect.position);
}
@ -2256,7 +2201,7 @@ void AnimationTrackEdit::_notification(int p_what) {
ofs += icon->get_width() + hsep;
loop_mode_rect.size.x += hsep;
if (track_type == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_TRANSFORM || track_type == Animation::TYPE_POSITION_3D || track_type == Animation::TYPE_SCALE_3D || track_type == Animation::TYPE_ROTATION_3D) {
if (track_type == Animation::TYPE_VALUE || track_type == Animation::TYPE_POSITION_3D || track_type == Animation::TYPE_SCALE_3D || track_type == Animation::TYPE_ROTATION_3D) {
draw_texture(down_icon, Vector2(ofs, int(get_size().height - down_icon->get_height()) / 2));
loop_mode_rect.size.x += down_icon->get_width();
} else {
@ -2585,9 +2530,8 @@ bool AnimationTrackEdit::_is_value_key_valid(const Variant &p_key_value, Variant
}
Ref<Texture> AnimationTrackEdit::_get_key_type_icon() const {
Ref<Texture> type_icons[9] = {
Ref<Texture> type_icons[8] = {
get_icon("KeyValue", "EditorIcons"),
get_icon("KeyXform", "EditorIcons"),
get_icon("KeyXPosition", "EditorIcons"),
get_icon("KeyXRotation", "EditorIcons"),
get_icon("KeyXScale", "EditorIcons"),
@ -2658,18 +2602,6 @@ String AnimationTrackEdit::get_tooltip(const Point2 &p_pos) const {
if (key_idx != -1) {
String text = TTR("Time (s): ") + rtos(animation->track_get_key_time(track, key_idx)) + "\n";
switch (animation->track_get_type(track)) {
case Animation::TYPE_TRANSFORM: {
Dictionary d = animation->track_get_key_value(track, key_idx);
if (d.has("location")) {
text += "Pos: " + String(d["location"]) + "\n";
}
if (d.has("rotation")) {
text += "Rot: " + String(d["rotation"]) + "\n";
}
if (d.has("scale")) {
text += "Scale: " + String(d["scale"]) + "\n";
}
} break;
case Animation::TYPE_POSITION_3D: {
Vector3 t = animation->track_get_key_value(track, key_idx);
text += TTR("Position:") + " " + String(t) + "\n";
@ -3540,7 +3472,6 @@ static bool track_type_is_resettable(Animation::TrackType p_type) {
switch (p_type) {
case Animation::TYPE_VALUE:
case Animation::TYPE_BEZIER:
case Animation::TYPE_TRANSFORM:
case Animation::TYPE_POSITION_3D:
case Animation::TYPE_ROTATION_3D:
case Animation::TYPE_SCALE_3D:
@ -4199,14 +4130,6 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD
value = p_id.value;
} break;
case Animation::TYPE_TRANSFORM: {
Transform tr = p_id.value;
Dictionary d;
d["location"] = tr.origin;
d["scale"] = tr.basis.get_scale();
d["rotation"] = Quat(tr.basis);
value = d;
} break;
case Animation::TYPE_POSITION_3D:
case Animation::TYPE_ROTATION_3D:
case Animation::TYPE_SCALE_3D: {
@ -4629,7 +4552,7 @@ void AnimationTrackEditor::_new_track_node_selected(NodePath p_path) {
ERR_FAIL_COND(!node);
NodePath path_to = root->get_path_to(node);
if ((adding_track_type == Animation::TYPE_TRANSFORM || adding_track_type == Animation::TYPE_POSITION_3D || adding_track_type == Animation::TYPE_ROTATION_3D || adding_track_type == Animation::TYPE_SCALE_3D) && !node->is_class("Spatial")) {
if ((adding_track_type == Animation::TYPE_POSITION_3D || adding_track_type == Animation::TYPE_ROTATION_3D || adding_track_type == Animation::TYPE_SCALE_3D) && !node->is_class("Spatial")) {
EditorNode::get_singleton()->show_warning(TTR("Transform/Position/Rotation/Scale 3D tracks only apply to Spatial-based nodes."));
return;
}
@ -4640,7 +4563,6 @@ void AnimationTrackEditor::_new_track_node_selected(NodePath p_path) {
prop_selector->set_type_filter(Vector<Variant::Type>());
prop_selector->select_property_from_instance(node);
} break;
case Animation::TYPE_TRANSFORM:
case Animation::TYPE_POSITION_3D:
case Animation::TYPE_ROTATION_3D:
case Animation::TYPE_SCALE_3D:
@ -4813,30 +4735,6 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) {
}
switch (animation->track_get_type(p_track)) {
case Animation::TYPE_TRANSFORM: {
if (!root->has_node(animation->track_get_path(p_track))) {
EditorNode::get_singleton()->show_warning(TTR("Track path is invalid, so can't add a key."));
return;
}
Spatial *base = Object::cast_to<Spatial>(root->get_node(animation->track_get_path(p_track)));
if (!base) {
EditorNode::get_singleton()->show_warning(TTR("Track is not of type Spatial, can't insert key"));
return;
}
Transform xf = base->get_transform();
Vector3 loc = xf.get_origin();
Vector3 scale = xf.basis.get_scale_local();
Quat rot = xf.basis;
undo_redo->create_action(TTR("Add Transform Track Key"));
undo_redo->add_do_method(animation.ptr(), "transform_track_insert_key", p_track, p_ofs, loc, rot, scale);
undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", p_track, p_ofs);
undo_redo->commit_action();
} break;
case Animation::TYPE_POSITION_3D: {
if (!root->has_node(animation->track_get_path(p_track))) {
EditorNode::get_singleton()->show_warning(TTR("Track path is invalid, so can't add a key."));
@ -5575,9 +5473,6 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
String track_type;
switch (animation->track_get_type(i)) {
case Animation::TYPE_TRANSFORM:
track_type = TTR("Transform");
break;
case Animation::TYPE_POSITION_3D:
track_type += TTR("Position");
break;

View File

@ -674,13 +674,7 @@ void ResourceImporterScene::_create_clips(Node *scene, const Array &p_clips, boo
new_anim->track_set_path(dtrack, default_anim->track_get_path(j));
if (kt > (from + 0.01) && k > 0) {
if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM) {
Quat q;
Vector3 p;
Vector3 s;
default_anim->transform_track_interpolate(j, from, &p, &q, &s);
new_anim->transform_track_insert_key(dtrack, 0, p, q, s);
} else if (default_anim->track_get_type(j) == Animation::TYPE_POSITION_3D) {
if (default_anim->track_get_type(j) == Animation::TYPE_POSITION_3D) {
Vector3 p;
default_anim->position_track_interpolate(j, from, &p);
new_anim->position_track_insert_key(dtrack, 0, p);
@ -699,13 +693,7 @@ void ResourceImporterScene::_create_clips(Node *scene, const Array &p_clips, boo
}
}
if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM) {
Quat q;
Vector3 p;
Vector3 s;
default_anim->transform_track_get_key(j, k, &p, &q, &s);
new_anim->transform_track_insert_key(dtrack, kt - from, p, q, s);
} else if (default_anim->track_get_type(j) == Animation::TYPE_POSITION_3D) {
if (default_anim->track_get_type(j) == Animation::TYPE_POSITION_3D) {
Vector3 p;
default_anim->position_track_get_key(j, k, &p);
new_anim->position_track_insert_key(dtrack, kt - from, p);
@ -724,13 +712,7 @@ void ResourceImporterScene::_create_clips(Node *scene, const Array &p_clips, boo
}
if (dtrack != -1 && kt >= to) {
if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM) {
Quat q;
Vector3 p;
Vector3 s;
default_anim->transform_track_interpolate(j, to, &p, &q, &s);
new_anim->transform_track_insert_key(dtrack, to - from, p, q, s);
} else if (default_anim->track_get_type(j) == Animation::TYPE_POSITION_3D) {
if (default_anim->track_get_type(j) == Animation::TYPE_POSITION_3D) {
Vector3 p;
default_anim->position_track_interpolate(j, to, &p);
new_anim->position_track_insert_key(dtrack, to - from, p);
@ -753,15 +735,7 @@ void ResourceImporterScene::_create_clips(Node *scene, const Array &p_clips, boo
new_anim->add_track(default_anim->track_get_type(j));
dtrack = new_anim->get_track_count() - 1;
new_anim->track_set_path(dtrack, default_anim->track_get_path(j));
if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM) {
Quat q;
Vector3 p;
Vector3 s;
default_anim->transform_track_interpolate(j, from, &p, &q, &s);
new_anim->transform_track_insert_key(dtrack, 0, p, q, s);
default_anim->transform_track_interpolate(j, to, &p, &q, &s);
new_anim->transform_track_insert_key(dtrack, to - from, p, q, s);
} else if (default_anim->track_get_type(j) == Animation::TYPE_POSITION_3D) {
if (default_anim->track_get_type(j) == Animation::TYPE_POSITION_3D) {
Vector3 p;
default_anim->position_track_interpolate(j, from, &p);
new_anim->position_track_insert_key(dtrack, 0, p);

View File

@ -5843,9 +5843,67 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
const bool transform_affects_skinned_mesh_instance = gltf_node->skeleton < 0 && gltf_node->skin >= 0;
if ((track.rotation_track.values.size() || track.translation_track.values.size() || track.scale_track.values.size()) && !transform_affects_skinned_mesh_instance) {
//make transform track
int track_idx = animation->get_track_count();
animation->add_track(Animation::TYPE_TRANSFORM);
animation->track_set_path(track_idx, transform_node_path);
int base_idx = animation->get_track_count();
int position_idx = -1;
int rotation_idx = -1;
int scale_idx = -1;
if (track.translation_track.values.size()) {
Vector3 base_pos = state->nodes[track_i->key()]->translation;
bool not_default = false; //discard the track if all it contains is default values
for (int i = 0; i < track.translation_track.times.size(); i++) {
Vector3 value = track.translation_track.values[track.translation_track.interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE ? (1 + i * 3) : i];
if (!value.is_equal_approx(base_pos)) {
not_default = true;
break;
}
}
if (not_default) {
position_idx = base_idx;
animation->add_track(Animation::TYPE_POSITION_3D);
animation->track_set_path(position_idx, transform_node_path);
animation->track_set_imported(position_idx, true); //helps merging later
base_idx++;
}
}
if (track.rotation_track.values.size()) {
Quat base_rot = state->nodes[track_i->key()]->rotation.normalized();
bool not_default = false; //discard the track if all it contains is default values
for (int i = 0; i < track.rotation_track.times.size(); i++) {
Quat value = track.rotation_track.values[track.rotation_track.interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE ? (1 + i * 3) : i].normalized();
if (!value.is_equal_approx(base_rot)) {
not_default = true;
break;
}
}
if (not_default) {
rotation_idx = base_idx;
animation->add_track(Animation::TYPE_ROTATION_3D);
animation->track_set_path(rotation_idx, transform_node_path);
animation->track_set_imported(rotation_idx, true); //helps merging later
base_idx++;
}
}
if (track.scale_track.values.size()) {
Vector3 base_scale = state->nodes[track_i->key()]->scale;
bool not_default = false; //discard the track if all it contains is default values
for (int i = 0; i < track.scale_track.times.size(); i++) {
Vector3 value = track.scale_track.values[track.scale_track.interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE ? (1 + i * 3) : i];
if (!value.is_equal_approx(base_scale)) {
not_default = true;
break;
}
}
if (not_default) {
scale_idx = base_idx;
animation->add_track(Animation::TYPE_SCALE_3D);
animation->track_set_path(scale_idx, transform_node_path);
animation->track_set_imported(scale_idx, true); //helps merging later
base_idx++;
}
}
//first determine animation length
const double increment = 1.0 / bake_fps;
@ -5855,15 +5913,15 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
Quat base_rot;
Vector3 base_scale = Vector3(1, 1, 1);
if (!track.rotation_track.values.size()) {
if (rotation_idx == -1) {
base_rot = state->nodes[track_i->key()]->rotation.normalized();
}
if (!track.translation_track.values.size()) {
if (position_idx == -1) {
base_pos = state->nodes[track_i->key()]->translation;
}
if (!track.scale_track.values.size()) {
if (scale_idx == -1) {
base_scale = state->nodes[track_i->key()]->scale;
}
@ -5873,15 +5931,15 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
Quat rot = base_rot;
Vector3 scale = base_scale;
if (track.translation_track.times.size()) {
if (position_idx >= 0) {
pos = _interpolate_track<Vector3>(track.translation_track.times, track.translation_track.values, time, track.translation_track.interpolation);
}
if (track.rotation_track.times.size()) {
if (rotation_idx >= 0) {
rot = _interpolate_track<Quat>(track.rotation_track.times, track.rotation_track.values, time, track.rotation_track.interpolation);
}
if (track.scale_track.times.size()) {
if (scale_idx >= 0) {
scale = _interpolate_track<Vector3>(track.scale_track.times, track.scale_track.values, time, track.scale_track.interpolation);
}
@ -5900,12 +5958,22 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
pos = xform.origin;
}
animation->transform_track_insert_key(track_idx, time, pos, rot, scale);
if (position_idx >= 0) {
animation->position_track_insert_key(position_idx, time, pos);
}
if (rotation_idx >= 0) {
animation->rotation_track_insert_key(rotation_idx, time, rot);
}
if (scale_idx >= 0) {
animation->scale_track_insert_key(scale_idx, time, scale);
}
if (last) {
break;
}
time += increment;
if (time >= length) {
last = true;
time = length;
@ -6123,6 +6191,8 @@ void GLTFDocument::_process_mesh_instances(Ref<GLTFState> state, Node *scene_roo
}
GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state, GLTFAnimation::Track p_track, Ref<Animation> p_animation, Transform p_bone_rest, int32_t p_track_i, GLTFNodeIndex p_node_i) {
//TODO PORT
/*
Animation::InterpolationType interpolation = p_animation->track_get_interpolation_type(p_track_i);
GLTFAnimation::Interpolation gltf_interpolation = GLTFAnimation::INTERP_LINEAR;
@ -6304,7 +6374,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state
}
}
}
*/
return p_track;
}

View File

@ -1394,7 +1394,8 @@ bool ModuleSkeletonEditor::forward_spatial_gui_input(int p_index, Camera *p_came
if (rest_mode) {
skeleton->set_bone_rest(skeleton->get_selected_bone(), t);
} else {
skeleton->set_bone_pose(skeleton->get_selected_bone(), t);
//TODO
//skeleton->set_bone_pose(skeleton->get_selected_bone(), t);
//skeleton->set_bone_pose_position(p_id, t.origin);
//skeleton->set_bone_pose_rotation(p_id, t.basis.operator Quaternion());
//skeleton->set_bone_pose_scale(p_id, t.basis.get_scale());
@ -1471,7 +1472,8 @@ bool ModuleSkeletonEditor::forward_spatial_gui_input(int p_index, Camera *p_came
if (rest_mode) {
skeleton->set_bone_rest(skeleton->get_selected_bone(), t);
} else {
skeleton->set_bone_pose(skeleton->get_selected_bone(), t);
//TODO
//skeleton->set_bone_pose(skeleton->get_selected_bone(), t);
}
sev->update_surface();
@ -1547,7 +1549,8 @@ bool ModuleSkeletonEditor::forward_spatial_gui_input(int p_index, Camera *p_came
if (rest_mode) {
skeleton->set_bone_rest(skeleton->get_selected_bone(), t);
} else {
skeleton->set_bone_pose(skeleton->get_selected_bone(), t);
//TODO
//skeleton->set_bone_pose(skeleton->get_selected_bone(), t);
}
sev->update_surface();

View File

@ -93,8 +93,6 @@ bool Skeleton::_set(const StringName &p_path, const Variant &p_value) {
set_bone_rest(which, p_value);
} else if (what == "enabled") {
set_bone_enabled(which, p_value);
} else if (what == "pose") {
set_bone_pose(which, p_value);
} else if (what == "position") {
set_bone_pose_position(which, p_value);
} else if (what == "rotation") {
@ -142,8 +140,6 @@ bool Skeleton::_get(const StringName &p_path, Variant &r_ret) const {
r_ret = get_bone_rest(which);
} else if (what == "enabled") {
r_ret = is_bone_enabled(which);
} else if (what == "pose") {
r_ret = get_bone_pose(which);
} else if (what == "position") {
r_ret = get_bone_pose_position(which);
} else if (what == "rotation") {
@ -176,7 +172,6 @@ void Skeleton::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::INT, prep + "parent", PROPERTY_HINT_RANGE, "-1," + itos(bones.size() - 1) + ",1"));
p_list->push_back(PropertyInfo(Variant::TRANSFORM, prep + "rest"));
p_list->push_back(PropertyInfo(Variant::BOOL, prep + "enabled"));
p_list->push_back(PropertyInfo(Variant::TRANSFORM, prep + "pose", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
p_list->push_back(PropertyInfo(Variant::VECTOR3, prep + "position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
p_list->push_back(PropertyInfo(Variant::QUAT, prep + "rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
p_list->push_back(PropertyInfo(Variant::VECTOR3, prep + "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
@ -577,19 +572,6 @@ void Skeleton::clear_bones() {
// posing api
void Skeleton::set_bone_pose(int p_bone, const Transform &p_pose) {
const int bone_size = bones.size();
ERR_FAIL_INDEX(p_bone, bone_size);
bones.write[p_bone].pose_position = p_pose.origin;
bones.write[p_bone].pose_rotation = p_pose.basis.operator Quat();
bones.write[p_bone].pose_scale = p_pose.basis.get_scale();
bones.write[p_bone].pose_cache_dirty = true;
if (is_inside_tree()) {
_make_dirty();
}
}
void Skeleton::set_bone_pose_position(int p_bone, const Vector3 &p_position) {
const int bone_size = bones.size();
ERR_FAIL_INDEX(p_bone, bone_size);
@ -1001,7 +983,6 @@ void Skeleton::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear_bones"), &Skeleton::clear_bones);
ClassDB::bind_method(D_METHOD("set_bone_pose", "bone_idx", "pose"), &Skeleton::set_bone_pose);
ClassDB::bind_method(D_METHOD("set_bone_pose_position", "bone_idx", "position"), &Skeleton::set_bone_pose_position);
ClassDB::bind_method(D_METHOD("set_bone_pose_rotation", "bone_idx", "rotation"), &Skeleton::set_bone_pose_rotation);
ClassDB::bind_method(D_METHOD("set_bone_pose_scale", "bone_idx", "scale"), &Skeleton::set_bone_pose_scale);

View File

@ -95,11 +95,11 @@ private:
pose_cache_dirty = false;
}
}
bool pose_cache_dirty = true;
bool pose_cache_dirty;
Transform pose_cache;
Vector3 pose_position;
Quat pose_rotation;
Vector3 pose_scale = Vector3(1, 1, 1);
Vector3 pose_scale;
Transform pose_global;
Transform pose_global_no_override;
@ -122,6 +122,8 @@ private:
parent = -1;
enabled = true;
disable_rest = false;
pose_cache_dirty = true;
pose_scale = Vector3(1, 1, 1);
custom_pose_enable = false;
global_pose_override_amount = 0;
global_pose_override_reset = false;
@ -205,7 +207,6 @@ public:
// posing api
void set_bone_pose(int p_bone, const Transform &p_pose);
void set_bone_pose_position(int p_bone, const Vector3 &p_position);
void set_bone_pose_rotation(int p_bone, const Quat &p_rotation);
void set_bone_pose_scale(int p_bone, const Vector3 &p_scale);

View File

@ -65,15 +65,11 @@ void AnimatedValuesBackup::restore() const {
if (entry->bone_idx == -1) {
entry->object->set_indexed(entry->subpath, entry->value);
} else {
if (entry->value.get_type() == Variant::TRANSFORM) {
Object::cast_to<Skeleton>(entry->object)->set_bone_pose(entry->bone_idx, entry->value);
} else {
Array arr = entry->value;
if (arr.size() == 3) {
Object::cast_to<Skeleton>(entry->object)->set_bone_pose_position(entry->bone_idx, arr[0]);
Object::cast_to<Skeleton>(entry->object)->set_bone_pose_rotation(entry->bone_idx, arr[1]);
Object::cast_to<Skeleton>(entry->object)->set_bone_pose_scale(entry->bone_idx, arr[2]);
}
Array arr = entry->value;
if (arr.size() == 3) {
Object::cast_to<Skeleton>(entry->object)->set_bone_pose_position(entry->bone_idx, arr[0]);
Object::cast_to<Skeleton>(entry->object)->set_bone_pose_rotation(entry->bone_idx, arr[1]);
Object::cast_to<Skeleton>(entry->object)->set_bone_pose_scale(entry->bone_idx, arr[2]);
}
}
}
@ -298,33 +294,7 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov
node_cache->node_2d = Object::cast_to<Node2D>(child);
#ifndef _3D_DISABLED
if (a->track_get_type(i) == Animation::TYPE_TRANSFORM) {
// special cases and caches for transform tracks
// cache spatial
node_cache->spatial = Object::cast_to<Spatial>(child);
// cache skeleton
node_cache->skeleton = Object::cast_to<Skeleton>(child);
if (node_cache->skeleton) {
if (a->track_get_path(i).get_subname_count() == 1) {
StringName bone_name = a->track_get_path(i).get_subname(0);
node_cache->bone_idx = node_cache->skeleton->find_bone(bone_name);
if (node_cache->bone_idx < 0) {
// broken track (nonexistent bone)
node_cache->skeleton = nullptr;
node_cache->spatial = nullptr;
ERR_CONTINUE(node_cache->bone_idx < 0);
}
} else {
// no property, just use spatialnode
node_cache->skeleton = nullptr;
}
}
node_cache->transform_used = true;
} else if (a->track_get_type(i) == Animation::TYPE_POSITION_3D || a->track_get_type(i) == Animation::TYPE_ROTATION_3D || a->track_get_type(i) == Animation::TYPE_SCALE_3D) {
if (a->track_get_type(i) == Animation::TYPE_POSITION_3D || a->track_get_type(i) == Animation::TYPE_ROTATION_3D || a->track_get_type(i) == Animation::TYPE_SCALE_3D) {
// special cases and caches for transform tracks
if (node_cache->last_setup_pass != setup_pass) {
@ -439,38 +409,6 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
}
switch (a->track_get_type(i)) {
case Animation::TYPE_TRANSFORM: {
#ifndef _3D_DISABLED
if (!nc->spatial) {
continue;
}
Vector3 loc;
Quat rot;
Vector3 scale;
Error err = a->transform_track_interpolate(i, p_time, &loc, &rot, &scale);
//ERR_CONTINUE(err!=OK); //used for testing, should be removed
if (err != OK) {
continue;
}
if (nc->accum_pass != accum_pass) {
ERR_CONTINUE(cache_update_size >= NODE_CACHE_UPDATE_MAX);
cache_update[cache_update_size++] = nc;
nc->accum_pass = accum_pass;
nc->loc_accum = loc;
nc->rot_accum = rot;
nc->scale_accum = scale;
} else {
nc->loc_accum = nc->loc_accum.linear_interpolate(loc, p_interp);
nc->rot_accum = nc->rot_accum.slerp(rot, p_interp);
nc->scale_accum = nc->scale_accum.linear_interpolate(scale, p_interp);
}
#endif // _3D_DISABLED
} break;
case Animation::TYPE_POSITION_3D: {
#ifndef _3D_DISABLED
if (!nc->spatial) {
@ -1009,37 +947,25 @@ void AnimationPlayer::_animation_update_transforms() {
#ifndef _3D_DISABLED
if (nc->skeleton && nc->bone_idx >= 0) {
if (nc->transform_used) {
t.origin = nc->loc_accum;
t.basis.set_quat_scale(nc->rot_accum, nc->scale_accum);
nc->skeleton->set_bone_pose(nc->bone_idx, t);
} else {
if (nc->loc_used) {
nc->skeleton->set_bone_pose_position(nc->bone_idx, nc->loc_accum);
}
if (nc->rot_used) {
nc->skeleton->set_bone_pose_rotation(nc->bone_idx, nc->rot_accum);
}
if (nc->scale_used) {
nc->skeleton->set_bone_pose_scale(nc->bone_idx, nc->scale_accum);
}
if (nc->loc_used) {
nc->skeleton->set_bone_pose_position(nc->bone_idx, nc->loc_accum);
}
if (nc->rot_used) {
nc->skeleton->set_bone_pose_rotation(nc->bone_idx, nc->rot_accum);
}
if (nc->scale_used) {
nc->skeleton->set_bone_pose_scale(nc->bone_idx, nc->scale_accum);
}
} else if (nc->spatial) {
if (nc->transform_used) {
t.origin = nc->loc_accum;
t.basis.set_quat_scale(nc->rot_accum, nc->scale_accum);
nc->spatial->set_transform(t);
} else {
if (nc->loc_used) {
nc->spatial->set_translation(nc->loc_accum);
}
if (nc->rot_used) {
nc->spatial->set_rotation(nc->rot_accum.get_euler());
}
if (nc->scale_used) {
nc->spatial->set_scale(nc->scale_accum);
}
if (nc->loc_used) {
nc->spatial->set_translation(nc->loc_accum);
}
if (nc->rot_used) {
nc->spatial->set_rotation(nc->rot_accum.get_euler());
}
if (nc->scale_used) {
nc->spatial->set_scale(nc->scale_accum);
}
}
#endif // _3D_DISABLED
@ -1718,18 +1644,12 @@ Ref<AnimatedValuesBackup> AnimationPlayer::backup_animated_values(Node *p_root_o
AnimatedValuesBackup::Entry entry;
if (nc->transform_used) {
entry.object = nc->skeleton;
entry.bone_idx = nc->bone_idx;
entry.value = nc->skeleton->get_bone_pose(nc->bone_idx);
} else {
Array arr;
arr.resize(3);
arr[0] = nc->skeleton->get_bone_pose_position(nc->bone_idx);
arr[1] = nc->skeleton->get_bone_pose_rotation(nc->bone_idx);
arr[2] = nc->skeleton->get_bone_pose_scale(nc->bone_idx);
entry.value = nc;
}
Array arr;
arr.resize(3);
arr[0] = nc->skeleton->get_bone_pose_position(nc->bone_idx);
arr[1] = nc->skeleton->get_bone_pose_rotation(nc->bone_idx);
arr[2] = nc->skeleton->get_bone_pose_scale(nc->bone_idx);
entry.value = nc;
backup->entries.push_back(entry);
} else {

View File

@ -106,7 +106,6 @@ private:
int bone_idx;
// accumulated transforms
bool transform_used;
bool loc_used;
bool rot_used;
bool scale_used;
@ -174,7 +173,6 @@ private:
audio_start(0.0),
audio_len(0.0),
animation_playing(false) {
transform_used = false;
loc_used = false;
rot_used = false;
scale_used = false;

View File

@ -590,38 +590,6 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
track = track_value;
} break;
case Animation::TYPE_TRANSFORM: {
#ifndef _3D_DISABLED
Spatial *spatial = Object::cast_to<Spatial>(child);
if (!spatial) {
ERR_PRINT("AnimationTree: '" + String(E->get()) + "', transform track does not point to spatial: '" + String(path) + "'");
continue;
}
TrackCacheTransform *track_xform = memnew(TrackCacheTransform);
track_xform->type = Animation::TYPE_TRANSFORM;
track_xform->spatial = spatial;
track_xform->skeleton = nullptr;
track_xform->bone_idx = -1;
track_xform->transform_used = true;
if (path.get_subname_count() == 1 && Object::cast_to<Skeleton>(spatial)) {
Skeleton *sk = Object::cast_to<Skeleton>(spatial);
track_xform->skeleton = sk;
int bone_idx = sk->find_bone(path.get_subname(0));
if (bone_idx != -1) {
track_xform->bone_idx = bone_idx;
}
}
track_xform->object = spatial;
track_xform->object_id = track_xform->object->get_instance_id();
track = track_xform;
#endif
} break;
case Animation::TYPE_POSITION_3D:
case Animation::TYPE_ROTATION_3D:
@ -640,7 +608,6 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
track_xform->spatial = spatial;
track_xform->skeleton = nullptr;
track_xform->bone_idx = -1;
track_xform->transform_used = true;
if (path.get_subname_count() == 1 && Object::cast_to<Skeleton>(spatial)) {
Skeleton *sk = Object::cast_to<Skeleton>(spatial);
@ -912,7 +879,7 @@ void AnimationTree::_process_graph(float p_delta) {
TrackCache *track = track_cache[path];
Animation::TrackType ttype = a->track_get_type(i);
if (ttype != Animation::TYPE_TRANSFORM && ttype != Animation::TYPE_POSITION_3D && ttype != Animation::TYPE_ROTATION_3D && ttype != Animation::TYPE_SCALE_3D && track->type != ttype) {
if (ttype != Animation::TYPE_POSITION_3D && ttype != Animation::TYPE_ROTATION_3D && ttype != Animation::TYPE_SCALE_3D && track->type != ttype) {
//broken animation, but avoid error spamming
continue;
}
@ -931,95 +898,6 @@ void AnimationTree::_process_graph(float p_delta) {
}
switch (track->type) {
case Animation::TYPE_TRANSFORM: {
#ifndef _3D_DISABLED
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
if (track->root_motion) {
if (t->process_pass != process_pass) {
t->process_pass = process_pass;
t->loc = Vector3();
t->rot = Quat();
t->rot_blend_accum = 0;
t->scale = Vector3(1, 1, 1);
}
float prev_time = time - delta;
if (prev_time < 0) {
if (!a->has_loop()) {
prev_time = 0;
} else {
prev_time = a->get_length() + prev_time;
}
}
Vector3 loc[2];
Quat rot[2];
Vector3 scale[2];
if (prev_time > time) {
Error err = a->transform_track_interpolate(i, prev_time, &loc[0], &rot[0], &scale[0]);
if (err != OK) {
continue;
}
a->transform_track_interpolate(i, a->get_length(), &loc[1], &rot[1], &scale[1]);
t->loc += (loc[1] - loc[0]) * blend;
t->scale += (scale[1] - scale[0]) * blend;
Quat q = Quat().slerp(rot[0].normalized().inverse() * rot[1].normalized(), blend).normalized();
t->rot = (t->rot * q).normalized();
prev_time = 0;
}
Error err = a->transform_track_interpolate(i, prev_time, &loc[0], &rot[0], &scale[0]);
if (err != OK) {
continue;
}
a->transform_track_interpolate(i, time, &loc[1], &rot[1], &scale[1]);
t->loc += (loc[1] - loc[0]) * blend;
t->scale += (scale[1] - scale[0]) * blend;
Quat q = Quat().slerp(rot[0].normalized().inverse() * rot[1].normalized(), blend).normalized();
t->rot = (t->rot * q).normalized();
prev_time = 0;
} else {
Vector3 loc;
Quat rot;
Vector3 scale;
Error err = a->transform_track_interpolate(i, time, &loc, &rot, &scale);
//ERR_CONTINUE(err!=OK); //used for testing, should be removed
if (t->process_pass != process_pass) {
t->process_pass = process_pass;
t->loc = loc;
t->rot = rot;
t->rot_blend_accum = 0;
t->scale = scale;
}
if (err != OK) {
continue;
}
t->loc = t->loc.linear_interpolate(loc, blend);
if (t->rot_blend_accum == 0) {
t->rot = rot;
t->rot_blend_accum = blend;
} else {
float rot_total = t->rot_blend_accum + blend;
t->rot = rot.slerp(t->rot, t->rot_blend_accum / rot_total).normalized();
t->rot_blend_accum = rot_total;
}
t->scale = t->scale.linear_interpolate(scale, blend);
}
#endif
} break;
case Animation::TYPE_POSITION_3D: {
#ifndef _3D_DISABLED
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
@ -1482,29 +1360,6 @@ void AnimationTree::_process_graph(float p_delta) {
}
switch (track->type) {
case Animation::TYPE_TRANSFORM: {
#ifndef _3D_DISABLED
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
Transform xform;
xform.origin = t->loc;
xform.basis.set_quat_scale(t->rot, t->scale);
if (t->root_motion) {
root_motion_transform = xform;
if (t->skeleton && t->bone_idx >= 0) {
root_motion_transform = (t->skeleton->get_bone_rest(t->bone_idx) * root_motion_transform) * t->skeleton->get_bone_rest(t->bone_idx).affine_inverse();
}
} else if (t->skeleton && t->bone_idx >= 0) {
t->skeleton->set_bone_pose(t->bone_idx, xform);
} else if (!t->skeleton) {
t->spatial->set_transform(xform);
}
#endif
} break;
case Animation::TYPE_POSITION_3D: {
#ifndef _3D_DISABLED
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);

View File

@ -188,7 +188,6 @@ private:
Spatial *spatial;
Skeleton *skeleton;
int bone_idx;
bool transform_used;
bool loc_used;
bool rot_used;
bool scale_used;
@ -202,7 +201,6 @@ private:
spatial = nullptr;
bone_idx = -1;
skeleton = nullptr;
transform_used = false;
loc_used = false;
rot_used = false;
scale_used = false;

View File

@ -846,23 +846,7 @@ void AnimationTreePlayer::_process_animation(float p_delta) {
}
switch (a->track_get_type(tr.local_track)) {
case Animation::TYPE_TRANSFORM: { ///< Transform a node or a bone.
Vector3 loc;
Quat rot;
Vector3 scale;
a->transform_track_interpolate(tr.local_track, anim_list->time, &loc, &rot, &scale);
tr.track->loc += loc * tr.weight;
scale.x -= 1.0;
scale.y -= 1.0;
scale.z -= 1.0;
tr.track->scale += scale * tr.weight;
tr.track->rot = tr.track->rot * empty_rot.slerp(rot, tr.weight);
} break;
case Animation::TYPE_VALUE: { ///< Set a value in a property, can be interpolated.
if (a->value_track_get_update_mode(tr.local_track) == Animation::UPDATE_CONTINUOUS) {
@ -917,7 +901,7 @@ void AnimationTreePlayer::_process_animation(float p_delta) {
if (t.bone_idx >= 0) {
if (t.skeleton) {
t.skeleton->set_bone_pose(t.bone_idx, xform);
//t.skeleton->set_bone_pose(t.bone_idx, xform);
}
} else if (t.spatial) {

View File

@ -43,9 +43,7 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) {
if (tracks.size() == track && what == "type") {
String type = p_value;
if (type == "transform") {
add_track(TYPE_TRANSFORM);
} else if (type == "position_3d") {
if (type == "position_3d") {
add_track(TYPE_POSITION_3D);
} else if (type == "rotation_3d") {
add_track(TYPE_ROTATION_3D);
@ -81,36 +79,7 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) {
} else if (what == "enabled") {
track_set_enabled(track, p_value);
} else if (what == "keys" || what == "key_values") {
if (track_get_type(track) == TYPE_TRANSFORM) {
TransformTrack *tt = static_cast<TransformTrack *>(tracks[track]);
PoolVector<float> values = p_value;
int vcount = values.size();
ERR_FAIL_COND_V(vcount % 12, false); // should be multiple of 11
PoolVector<float>::Read r = values.read();
tt->transforms.resize(vcount / 12);
for (int i = 0; i < (vcount / 12); i++) {
TKey<TransformKey> &tk = tt->transforms.write[i];
const float *ofs = &r[i * 12];
tk.time = ofs[0];
tk.transition = ofs[1];
tk.value.loc.x = ofs[2];
tk.value.loc.y = ofs[3];
tk.value.loc.z = ofs[4];
tk.value.rot.x = ofs[5];
tk.value.rot.y = ofs[6];
tk.value.rot.z = ofs[7];
tk.value.rot.w = ofs[8];
tk.value.scale.x = ofs[9];
tk.value.scale.y = ofs[10];
tk.value.scale.z = ofs[11];
}
} else if (track_get_type(track) == TYPE_POSITION_3D) {
if (track_get_type(track) == TYPE_POSITION_3D) {
PositionTrack *tt = static_cast<PositionTrack *>(tracks[track]);
Vector<real_t> values = p_value;
int vcount = values.size();
@ -391,9 +360,6 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const {
ERR_FAIL_INDEX_V(track, tracks.size(), false);
if (what == "type") {
switch (track_get_type(track)) {
case TYPE_TRANSFORM:
r_ret = "transform";
break;
case TYPE_POSITION_3D:
r_ret = "position_3d";
break;
@ -433,40 +399,7 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const {
} else if (what == "enabled") {
r_ret = track_is_enabled(track);
} else if (what == "keys") {
if (track_get_type(track) == TYPE_TRANSFORM) {
PoolVector<real_t> keys;
int kk = track_get_key_count(track);
keys.resize(kk * 12);
PoolVector<real_t>::Write w = keys.write();
int idx = 0;
for (int i = 0; i < track_get_key_count(track); i++) {
Vector3 loc;
Quat rot;
Vector3 scale;
transform_track_get_key(track, i, &loc, &rot, &scale);
w[idx++] = track_get_key_time(track, i);
w[idx++] = track_get_key_transition(track, i);
w[idx++] = loc.x;
w[idx++] = loc.y;
w[idx++] = loc.z;
w[idx++] = rot.x;
w[idx++] = rot.y;
w[idx++] = rot.z;
w[idx++] = rot.w;
w[idx++] = scale.x;
w[idx++] = scale.y;
w[idx++] = scale.z;
}
w.release();
r_ret = keys;
return true;
} else if (track_get_type(track) == TYPE_POSITION_3D) {
if (track_get_type(track) == TYPE_POSITION_3D) {
Vector<real_t> keys;
int kk = track_get_key_count(track);
keys.resize(kk * 5);
@ -748,10 +681,6 @@ int Animation::add_track(TrackType p_type, int p_at_pos) {
}
switch (p_type) {
case TYPE_TRANSFORM: {
TransformTrack *tt = memnew(TransformTrack);
tracks.insert(p_at_pos, tt);
} break;
case TYPE_POSITION_3D: {
PositionTrack *tt = memnew(PositionTrack);
tracks.insert(p_at_pos, tt);
@ -798,11 +727,6 @@ void Animation::remove_track(int p_track) {
Track *t = tracks[p_track];
switch (t->type) {
case TYPE_TRANSFORM: {
TransformTrack *tt = static_cast<TransformTrack *>(t);
_clear(tt->transforms);
} break;
case TYPE_POSITION_3D: {
PositionTrack *tt = static_cast<PositionTrack *>(t);
//ERR_FAIL_COND_MSG(tt->compressed_track >= 0, "Compressed tracks can't be manually removed. Call clear() to get rid of compression first.");
@ -936,45 +860,6 @@ void Animation::_clear(T &p_keys) {
p_keys.clear();
}
Error Animation::transform_track_get_key(int p_track, int p_key, Vector3 *r_loc, Quat *r_rot, Vector3 *r_scale) const {
ERR_FAIL_INDEX_V(p_track, tracks.size(), ERR_INVALID_PARAMETER);
Track *t = tracks[p_track];
TransformTrack *tt = static_cast<TransformTrack *>(t);
ERR_FAIL_COND_V(t->type != TYPE_TRANSFORM, ERR_INVALID_PARAMETER);
ERR_FAIL_INDEX_V(p_key, tt->transforms.size(), ERR_INVALID_PARAMETER);
if (r_loc) {
*r_loc = tt->transforms[p_key].value.loc;
}
if (r_rot) {
*r_rot = tt->transforms[p_key].value.rot;
}
if (r_scale) {
*r_scale = tt->transforms[p_key].value.scale;
}
return OK;
}
int Animation::transform_track_insert_key(int p_track, float p_time, const Vector3 &p_loc, const Quat &p_rot, const Vector3 &p_scale) {
ERR_FAIL_INDEX_V(p_track, tracks.size(), -1);
Track *t = tracks[p_track];
ERR_FAIL_COND_V(t->type != TYPE_TRANSFORM, -1);
TransformTrack *tt = static_cast<TransformTrack *>(t);
TKey<TransformKey> tkey;
tkey.time = p_time;
tkey.value.loc = p_loc;
tkey.value.rot = p_rot;
tkey.value.scale = p_scale;
int ret = _insert(p_time, tt->transforms, tkey);
emit_changed();
return ret;
}
int Animation::position_track_insert_key(int p_track, double p_time, const Vector3 &p_position) {
ERR_FAIL_INDEX_V(p_track, tracks.size(), -1);
Track *t = tracks[p_track];
@ -1212,12 +1097,6 @@ void Animation::track_remove_key(int p_track, int p_idx) {
Track *t = tracks[p_track];
switch (t->type) {
case TYPE_TRANSFORM: {
TransformTrack *tt = static_cast<TransformTrack *>(t);
ERR_FAIL_INDEX(p_idx, tt->transforms.size());
tt->transforms.remove(p_idx);
} break;
case TYPE_POSITION_3D: {
PositionTrack *tt = static_cast<PositionTrack *>(t);
@ -1285,18 +1164,6 @@ int Animation::track_find_key(int p_track, float p_time, bool p_exact) const {
Track *t = tracks[p_track];
switch (t->type) {
case TYPE_TRANSFORM: {
TransformTrack *tt = static_cast<TransformTrack *>(t);
int k = _find(tt->transforms, p_time);
if (k < 0 || k >= tt->transforms.size()) {
return -1;
}
if (tt->transforms[k].time != p_time && p_exact) {
return -1;
}
return k;
} break;
case TYPE_POSITION_3D: {
PositionTrack *tt = static_cast<PositionTrack *>(t);
@ -1454,27 +1321,6 @@ void Animation::track_insert_key(int p_track, float p_time, const Variant &p_key
Track *t = tracks[p_track];
switch (t->type) {
case TYPE_TRANSFORM: {
Dictionary d = p_key;
Vector3 loc;
if (d.has("location")) {
loc = d["location"];
}
Quat rot;
if (d.has("rotation")) {
rot = d["rotation"];
}
Vector3 scale;
if (d.has("scale")) {
scale = d["scale"];
}
int idx = transform_track_insert_key(p_track, p_time, loc, rot, scale);
track_set_key_transition(p_track, idx, p_transition);
} break;
case TYPE_POSITION_3D: {
ERR_FAIL_COND((p_key.get_type() != Variant::VECTOR3) && (p_key.get_type() != Variant::VECTOR3I));
int idx = position_track_insert_key(p_track, p_time, p_key);
@ -1574,10 +1420,6 @@ int Animation::track_get_key_count(int p_track) const {
Track *t = tracks[p_track];
switch (t->type) {
case TYPE_TRANSFORM: {
TransformTrack *tt = static_cast<TransformTrack *>(t);
return tt->transforms.size();
} break;
case TYPE_POSITION_3D: {
PositionTrack *tt = static_cast<PositionTrack *>(t);
//if (tt->compressed_track >= 0) {
@ -1630,17 +1472,6 @@ Variant Animation::track_get_key_value(int p_track, int p_key_idx) const {
Track *t = tracks[p_track];
switch (t->type) {
case TYPE_TRANSFORM: {
TransformTrack *tt = static_cast<TransformTrack *>(t);
ERR_FAIL_INDEX_V(p_key_idx, tt->transforms.size(), Variant());
Dictionary d;
d["location"] = tt->transforms[p_key_idx].value.loc;
d["rotation"] = tt->transforms[p_key_idx].value.rot;
d["scale"] = tt->transforms[p_key_idx].value.scale;
return d;
} break;
case TYPE_POSITION_3D: {
Vector3 value;
position_track_get_key(p_track, p_key_idx, &value);
@ -1713,11 +1544,6 @@ float Animation::track_get_key_time(int p_track, int p_key_idx) const {
Track *t = tracks[p_track];
switch (t->type) {
case TYPE_TRANSFORM: {
TransformTrack *tt = static_cast<TransformTrack *>(t);
ERR_FAIL_INDEX_V(p_key_idx, tt->transforms.size(), -1);
return tt->transforms[p_key_idx].time;
} break;
case TYPE_POSITION_3D: {
PositionTrack *tt = static_cast<PositionTrack *>(t);
@ -1806,15 +1632,6 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, float p_time) {
Track *t = tracks[p_track];
switch (t->type) {
case TYPE_TRANSFORM: {
TransformTrack *tt = static_cast<TransformTrack *>(t);
ERR_FAIL_INDEX(p_key_idx, tt->transforms.size());
TKey<TransformKey> key = tt->transforms[p_key_idx];
key.time = p_time;
tt->transforms.remove(p_key_idx);
_insert(p_time, tt->transforms, key);
return;
}
case TYPE_POSITION_3D: {
PositionTrack *tt = static_cast<PositionTrack *>(t);
//ERR_FAIL_COND(tt->compressed_track >= 0);
@ -1900,11 +1717,6 @@ float Animation::track_get_key_transition(int p_track, int p_key_idx) const {
Track *t = tracks[p_track];
switch (t->type) {
case TYPE_TRANSFORM: {
TransformTrack *tt = static_cast<TransformTrack *>(t);
ERR_FAIL_INDEX_V(p_key_idx, tt->transforms.size(), -1);
return tt->transforms[p_key_idx].transition;
} break;
case TYPE_POSITION_3D: {
PositionTrack *tt = static_cast<PositionTrack *>(t);
@ -1972,23 +1784,6 @@ void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p
Track *t = tracks[p_track];
switch (t->type) {
case TYPE_TRANSFORM: {
TransformTrack *tt = static_cast<TransformTrack *>(t);
ERR_FAIL_INDEX(p_key_idx, tt->transforms.size());
Dictionary d = p_value;
if (d.has("location")) {
tt->transforms.write[p_key_idx].value.loc = d["location"];
}
if (d.has("rotation")) {
tt->transforms.write[p_key_idx].value.rot = d["rotation"];
}
if (d.has("scale")) {
tt->transforms.write[p_key_idx].value.scale = d["scale"];
}
} break;
case TYPE_POSITION_3D: {
ERR_FAIL_COND((p_value.get_type() != Variant::VECTOR3) && (p_value.get_type() != Variant::VECTOR3I));
PositionTrack *tt = static_cast<PositionTrack *>(t);
@ -2082,11 +1877,6 @@ void Animation::track_set_key_transition(int p_track, int p_key_idx, float p_tra
Track *t = tracks[p_track];
switch (t->type) {
case TYPE_TRANSFORM: {
TransformTrack *tt = static_cast<TransformTrack *>(t);
ERR_FAIL_INDEX(p_key_idx, tt->transforms.size());
tt->transforms.write[p_key_idx].transition = p_transition;
} break;
case TYPE_POSITION_3D: {
PositionTrack *tt = static_cast<PositionTrack *>(t);
//ERR_FAIL_COND(tt->compressed_track >= 0);
@ -2164,15 +1954,6 @@ int Animation::_find(const Vector<K> &p_keys, float p_time) const {
return middle;
}
Animation::TransformKey Animation::_interpolate(const Animation::TransformKey &p_a, const Animation::TransformKey &p_b, float p_c) const {
TransformKey ret;
ret.loc = _interpolate(p_a.loc, p_b.loc, p_c);
ret.rot = _interpolate(p_a.rot, p_b.rot, p_c);
ret.scale = _interpolate(p_a.scale, p_b.scale, p_c);
return ret;
}
Vector3 Animation::_interpolate(const Vector3 &p_a, const Vector3 &p_b, float p_c) const {
return p_a.linear_interpolate(p_b, p_c);
}
@ -2189,15 +1970,6 @@ float Animation::_interpolate(const float &p_a, const float &p_b, float p_c) con
return p_a * (1.0 - p_c) + p_b * p_c;
}
Animation::TransformKey Animation::_cubic_interpolate(const Animation::TransformKey &p_pre_a, const Animation::TransformKey &p_a, const Animation::TransformKey &p_b, const Animation::TransformKey &p_post_b, float p_c) const {
Animation::TransformKey tk;
tk.loc = p_a.loc.cubic_interpolate(p_b.loc, p_pre_a.loc, p_post_b.loc, p_c);
tk.scale = p_a.scale.cubic_interpolate(p_b.scale, p_pre_a.scale, p_post_b.scale, p_c);
tk.rot = p_a.rot.cubic_slerp(p_b.rot, p_pre_a.rot, p_post_b.rot, p_c);
return tk;
}
Vector3 Animation::_cubic_interpolate(const Vector3 &p_pre_a, const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_post_b, float p_c) const {
return p_a.cubic_interpolate(p_b, p_pre_a, p_post_b, p_c);
}
@ -2446,36 +2218,6 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, float p_time, Interpola
// do a barrel roll
}
Error Animation::transform_track_interpolate(int p_track, float p_time, Vector3 *r_loc, Quat *r_rot, Vector3 *r_scale) const {
ERR_FAIL_INDEX_V(p_track, tracks.size(), ERR_INVALID_PARAMETER);
Track *t = tracks[p_track];
ERR_FAIL_COND_V(t->type != TYPE_TRANSFORM, ERR_INVALID_PARAMETER);
TransformTrack *tt = static_cast<TransformTrack *>(t);
bool ok = false;
TransformKey tk = _interpolate(tt->transforms, p_time, tt->interpolation, tt->loop_wrap, &ok);
if (!ok) {
return ERR_UNAVAILABLE;
}
if (r_loc) {
*r_loc = tk.loc;
}
if (r_rot) {
*r_rot = tk.rot;
}
if (r_scale) {
*r_scale = tk.scale;
}
return OK;
}
Variant Animation::value_track_interpolate(int p_track, float p_time) const {
ERR_FAIL_INDEX_V(p_track, tracks.size(), 0);
Track *t = tracks[p_track];
@ -2651,12 +2393,6 @@ void Animation::track_get_key_indices_in_range(int p_track, float p_time, float
// handle loop by splitting
switch (t->type) {
case TYPE_TRANSFORM: {
const TransformTrack *tt = static_cast<const TransformTrack *>(t);
_track_get_key_indices_in_range(tt->transforms, from_time, length, p_indices);
_track_get_key_indices_in_range(tt->transforms, 0, to_time, p_indices);
} break;
case TYPE_POSITION_3D: {
const PositionTrack *tt = static_cast<const PositionTrack *>(t);
_track_get_key_indices_in_range(tt->positions, from_time, length, p_indices);
@ -2725,11 +2461,6 @@ void Animation::track_get_key_indices_in_range(int p_track, float p_time, float
}
switch (t->type) {
case TYPE_TRANSFORM: {
const TransformTrack *tt = static_cast<const TransformTrack *>(t);
_track_get_key_indices_in_range(tt->transforms, from_time, to_time, p_indices);
} break;
case TYPE_POSITION_3D: {
const PositionTrack *tt = static_cast<const PositionTrack *>(t);
//if (tt->compressed_track >= 0) {
@ -3358,7 +3089,6 @@ void Animation::_bind_methods() {
ClassDB::bind_method(D_METHOD("track_set_enabled", "track_idx", "enabled"), &Animation::track_set_enabled);
ClassDB::bind_method(D_METHOD("track_is_enabled", "track_idx"), &Animation::track_is_enabled);
ClassDB::bind_method(D_METHOD("transform_track_insert_key", "track_idx", "time", "location", "rotation", "scale"), &Animation::transform_track_insert_key);
ClassDB::bind_method(D_METHOD("position_track_insert_key", "track_idx", "time", "position"), &Animation::position_track_insert_key);
ClassDB::bind_method(D_METHOD("rotation_track_insert_key", "track_idx", "time", "rotation"), &Animation::rotation_track_insert_key);
ClassDB::bind_method(D_METHOD("scale_track_insert_key", "track_idx", "time", "scale"), &Animation::scale_track_insert_key);
@ -3382,7 +3112,6 @@ void Animation::_bind_methods() {
ClassDB::bind_method(D_METHOD("track_set_interpolation_loop_wrap", "track_idx", "interpolation"), &Animation::track_set_interpolation_loop_wrap);
ClassDB::bind_method(D_METHOD("track_get_interpolation_loop_wrap", "track_idx"), &Animation::track_get_interpolation_loop_wrap);
ClassDB::bind_method(D_METHOD("transform_track_interpolate", "track_idx", "time_sec"), &Animation::_transform_track_interpolate);
ClassDB::bind_method(D_METHOD("value_track_set_update_mode", "track_idx", "mode"), &Animation::value_track_set_update_mode);
ClassDB::bind_method(D_METHOD("value_track_get_update_mode", "track_idx"), &Animation::value_track_get_update_mode);
@ -3436,7 +3165,6 @@ void Animation::_bind_methods() {
ADD_SIGNAL(MethodInfo("tracks_changed"));
BIND_ENUM_CONSTANT(TYPE_VALUE);
BIND_ENUM_CONSTANT(TYPE_TRANSFORM);
BIND_ENUM_CONSTANT(TYPE_POSITION_3D);
BIND_ENUM_CONSTANT(TYPE_ROTATION_3D);
BIND_ENUM_CONSTANT(TYPE_SCALE_3D);
@ -3466,173 +3194,6 @@ void Animation::clear() {
emit_signal(SceneStringNames::get_singleton()->tracks_changed);
}
bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, const TKey<TransformKey> &t1, const TKey<TransformKey> &t2, float p_alowed_linear_err, float p_alowed_angular_err, float p_max_optimizable_angle, const Vector3 &p_norm) {
real_t c = (t1.time - t0.time) / (t2.time - t0.time);
real_t t[3] = { -1, -1, -1 };
{ //translation
const Vector3 &v0 = t0.value.loc;
const Vector3 &v1 = t1.value.loc;
const Vector3 &v2 = t2.value.loc;
if (v0.is_equal_approx(v2)) {
//0 and 2 are close, let's see if 1 is close
if (!v0.is_equal_approx(v1)) {
//not close, not optimizable
return false;
}
} else {
Vector3 pd = (v2 - v0);
float d0 = pd.dot(v0);
float d1 = pd.dot(v1);
float d2 = pd.dot(v2);
if (d1 < d0 || d1 > d2) {
return false;
}
Vector3 s[2] = { v0, v2 };
real_t d = Geometry::get_closest_point_to_segment(v1, s).distance_to(v1);
if (d > pd.length() * p_alowed_linear_err) {
return false; //beyond allowed error for colinearity
}
if (p_norm != Vector3() && Math::acos(pd.normalized().dot(p_norm)) > p_alowed_angular_err) {
return false;
}
t[0] = (d1 - d0) / (d2 - d0);
}
}
{ //rotation
const Quat &q0 = t0.value.rot;
const Quat &q1 = t1.value.rot;
const Quat &q2 = t2.value.rot;
//localize both to rotation from q0
if (q0.is_equal_approx(q2)) {
if (!q0.is_equal_approx(q1)) {
return false;
}
} else {
Quat r02 = (q0.inverse() * q2).normalized();
Quat r01 = (q0.inverse() * q1).normalized();
Vector3 v02, v01;
real_t a02, a01;
r02.get_axis_angle(v02, a02);
r01.get_axis_angle(v01, a01);
if (Math::abs(a02) > p_max_optimizable_angle) {
return false;
}
if (v01.dot(v02) < 0) {
//make sure both rotations go the same way to compare
v02 = -v02;
a02 = -a02;
}
real_t err_01 = Math::acos(v01.normalized().dot(v02.normalized())) / Math_PI;
if (err_01 > p_alowed_angular_err) {
//not rotating in the same axis
return false;
}
if (a01 * a02 < 0) {
//not rotating in the same direction
return false;
}
real_t tr = a01 / a02;
if (tr < 0 || tr > 1) {
return false; //rotating too much or too less
}
t[1] = tr;
}
}
{ //scale
const Vector3 &v0 = t0.value.scale;
const Vector3 &v1 = t1.value.scale;
const Vector3 &v2 = t2.value.scale;
if (v0.is_equal_approx(v2)) {
//0 and 2 are close, let's see if 1 is close
if (!v0.is_equal_approx(v1)) {
//not close, not optimizable
return false;
}
} else {
Vector3 pd = (v2 - v0);
float d0 = pd.dot(v0);
float d1 = pd.dot(v1);
float d2 = pd.dot(v2);
if (d1 < d0 || d1 > d2) {
return false; //beyond segment range
}
Vector3 s[2] = { v0, v2 };
real_t d = Geometry::get_closest_point_to_segment(v1, s).distance_to(v1);
if (d > pd.length() * p_alowed_linear_err) {
return false; //beyond allowed error for colinearity
}
t[2] = (d1 - d0) / (d2 - d0);
}
}
bool erase = false;
if (t[0] == -1 && t[1] == -1 && t[2] == -1) {
erase = true;
} else {
erase = true;
real_t lt = -1;
for (int j = 0; j < 3; j++) {
//search for t on first, one must be it
if (t[j] != -1) {
lt = t[j]; //official t
//validate rest
for (int k = j + 1; k < 3; k++) {
if (t[k] == -1) {
continue;
}
if (Math::abs(lt - t[k]) > p_alowed_linear_err) {
erase = false;
break;
}
}
break;
}
}
ERR_FAIL_COND_V(lt == -1, false);
if (erase) {
if (Math::abs(lt - c) > p_alowed_linear_err) {
//todo, evaluate changing the transition if this fails?
//this could be done as a second pass and would be
//able to optimize more
erase = false;
}
}
}
return erase;
}
bool Animation::_position_track_optimize_key(const TKey<Vector3> &t0, const TKey<Vector3> &t1, const TKey<Vector3> &t2, real_t p_allowed_linear_err, real_t p_allowed_angular_error, const Vector3 &p_norm) {
const Vector3 &v0 = t0.value;
const Vector3 &v1 = t1.value;
@ -3753,46 +3314,6 @@ bool Animation::_scale_track_optimize_key(const TKey<Vector3> &t0, const TKey<Ve
return true;
}
void Animation::_transform_track_optimize(int p_idx, float p_allowed_linear_err, float p_allowed_angular_err, float p_max_optimizable_angle) {
ERR_FAIL_INDEX(p_idx, tracks.size());
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_TRANSFORM);
TransformTrack *tt = static_cast<TransformTrack *>(tracks[p_idx]);
bool prev_erased = false;
TKey<TransformKey> first_erased;
Vector3 norm;
for (int i = 1; i < tt->transforms.size() - 1; i++) {
TKey<TransformKey> &t0 = tt->transforms.write[i - 1];
TKey<TransformKey> &t1 = tt->transforms.write[i];
TKey<TransformKey> &t2 = tt->transforms.write[i + 1];
bool erase = _transform_track_optimize_key(t0, t1, t2, p_allowed_linear_err, p_allowed_angular_err, p_max_optimizable_angle, norm);
if (erase && !prev_erased) {
norm = (t2.value.loc - t1.value.loc).normalized();
}
if (prev_erased && !_transform_track_optimize_key(t0, first_erased, t2, p_allowed_linear_err, p_allowed_angular_err, p_max_optimizable_angle, norm)) {
//avoid error to go beyond first erased key
erase = false;
}
if (erase) {
if (!prev_erased) {
first_erased = t1;
prev_erased = true;
}
tt->transforms.remove(i);
i--;
} else {
prev_erased = false;
norm = Vector3();
}
}
}
void Animation::_position_track_optimize(int p_idx, real_t p_allowed_linear_err, real_t p_allowed_angular_err) {
ERR_FAIL_INDEX(p_idx, tracks.size());
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_POSITION_3D);
@ -3903,9 +3424,7 @@ void Animation::_scale_track_optimize(int p_idx, real_t p_allowed_linear_err) {
void Animation::optimize(float p_allowed_linear_err, float p_allowed_angular_err, float p_max_optimizable_angle) {
for (int i = 0; i < tracks.size(); i++) {
if (tracks[i]->type == TYPE_TRANSFORM) {
_transform_track_optimize(i, p_allowed_linear_err, p_allowed_angular_err, p_max_optimizable_angle);
} else if (tracks[i]->type == TYPE_POSITION_3D) {
if (tracks[i]->type == TYPE_POSITION_3D) {
_position_track_optimize(i, p_allowed_linear_err, p_allowed_angular_err);
} else if (tracks[i]->type == TYPE_ROTATION_3D) {
_rotation_track_optimize(i, p_allowed_angular_err, p_max_optimizable_angle);

View File

@ -41,7 +41,6 @@ class Animation : public Resource {
public:
enum TrackType {
TYPE_VALUE, ///< Set a value in a property, can be interpolated.
TYPE_TRANSFORM, ///< Transform a node or a bone.
TYPE_POSITION_3D, ///< Position 3D track
TYPE_ROTATION_3D, ///< Rotation 3D track
TYPE_SCALE_3D, ///< Scale 3D track
@ -124,14 +123,6 @@ private:
ScaleTrack() { type = TYPE_SCALE_3D; }
};
/* TRANSFORM TRACK */
struct TransformTrack : public Track {
Vector<TKey<TransformKey>> transforms;
TransformTrack() { type = TYPE_TRANSFORM; }
};
/* PROPERTY VALUE TRACK */
struct ValueTrack : public Track {
@ -218,14 +209,11 @@ private:
template <class K>
inline int _find(const Vector<K> &p_keys, float p_time) const;
_FORCE_INLINE_ Animation::TransformKey _interpolate(const Animation::TransformKey &p_a, const Animation::TransformKey &p_b, float p_c) const;
_FORCE_INLINE_ Vector3 _interpolate(const Vector3 &p_a, const Vector3 &p_b, float p_c) const;
_FORCE_INLINE_ Quat _interpolate(const Quat &p_a, const Quat &p_b, float p_c) const;
_FORCE_INLINE_ Variant _interpolate(const Variant &p_a, const Variant &p_b, float p_c) const;
_FORCE_INLINE_ float _interpolate(const float &p_a, const float &p_b, float p_c) const;
_FORCE_INLINE_ Animation::TransformKey _cubic_interpolate(const Animation::TransformKey &p_pre_a, const Animation::TransformKey &p_a, const Animation::TransformKey &p_b, const Animation::TransformKey &p_post_b, float p_c) const;
_FORCE_INLINE_ Vector3 _cubic_interpolate(const Vector3 &p_pre_a, const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_post_b, float p_c) const;
_FORCE_INLINE_ Quat _cubic_interpolate(const Quat &p_pre_a, const Quat &p_a, const Quat &p_b, const Quat &p_post_b, float p_c) const;
_FORCE_INLINE_ Variant _cubic_interpolate(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, float p_c) const;
@ -246,18 +234,6 @@ private:
// bind helpers
private:
Array _transform_track_interpolate(int p_track, float p_time) const {
Vector3 loc;
Quat rot;
Vector3 scale;
transform_track_interpolate(p_track, p_time, &loc, &rot, &scale);
Array ret;
ret.push_back(loc);
ret.push_back(rot);
ret.push_back(scale);
return ret;
}
PoolVector<int> _value_track_get_key_indices(int p_track, float p_time, float p_delta) const {
List<int> idxs;
value_track_get_key_indices(p_track, p_time, p_delta, &idxs);
@ -268,6 +244,7 @@ private:
}
return idxr;
}
PoolVector<int> _method_track_get_key_indices(int p_track, float p_time, float p_delta) const {
List<int> idxs;
method_track_get_key_indices(p_track, p_time, p_delta, &idxs);
@ -279,9 +256,6 @@ private:
return idxr;
}
bool _transform_track_optimize_key(const TKey<TransformKey> &t0, const TKey<TransformKey> &t1, const TKey<TransformKey> &t2, float p_alowed_linear_err, float p_alowed_angular_err, float p_max_optimizable_angle, const Vector3 &p_norm);
void _transform_track_optimize(int p_idx, float p_allowed_linear_err = 0.05, float p_allowed_angular_err = 0.01, float p_max_optimizable_angle = Math_PI * 0.125);
bool _position_track_optimize_key(const TKey<Vector3> &t0, const TKey<Vector3> &t1, const TKey<Vector3> &t2, real_t p_alowed_linear_err, real_t p_allowed_angular_error, const Vector3 &p_norm);
bool _rotation_track_optimize_key(const TKey<Quat> &t0, const TKey<Quat> &t1, const TKey<Quat> &t2, real_t p_allowed_angular_error, float p_max_optimizable_angle);
bool _scale_track_optimize_key(const TKey<Vector3> &t0, const TKey<Vector3> &t1, const TKey<Vector3> &t2, real_t p_allowed_linear_error);
@ -332,9 +306,6 @@ public:
float track_get_key_time(int p_track, int p_key_idx) const;
float track_get_key_transition(int p_track, int p_key_idx) const;
int transform_track_insert_key(int p_track, float p_time, const Vector3 &p_loc, const Quat &p_rot = Quat(), const Vector3 &p_scale = Vector3());
Error transform_track_get_key(int p_track, int p_key, Vector3 *r_loc, Quat *r_rot, Vector3 *r_scale) const;
int position_track_insert_key(int p_track, double p_time, const Vector3 &p_position);
Error position_track_get_key(int p_track, int p_key, Vector3 *r_position) const;
Error position_track_interpolate(int p_track, double p_time, Vector3 *r_interpolation) const;
@ -375,8 +346,6 @@ public:
void track_set_interpolation_loop_wrap(int p_track, bool p_enable);
bool track_get_interpolation_loop_wrap(int p_track) const;
Error transform_track_interpolate(int p_track, float p_time, Vector3 *r_loc, Quat *r_rot, Vector3 *r_scale) const;
Variant value_track_interpolate(int p_track, float p_time) const;
void value_track_get_key_indices(int p_track, float p_time, float p_delta, List<int> *p_indices) const;
void value_track_set_update_mode(int p_track, UpdateMode p_mode);