summaryrefslogtreecommitdiff
path: root/editor/animation_track_editor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'editor/animation_track_editor.cpp')
-rw-r--r--editor/animation_track_editor.cpp738
1 files changed, 441 insertions, 297 deletions
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index ff2818f027..7f118532c9 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -165,21 +165,40 @@ public:
}
switch (animation->track_get_type(track)) {
- case Animation::TYPE_TRANSFORM3D: {
- 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();
+ case Animation::TYPE_POSITION_3D:
+ case Animation::TYPE_ROTATION_3D:
+ case Animation::TYPE_SCALE_3D: {
+ if (name == "position" || name == "rotation" || name == "scale") {
+ Variant old = animation->track_get_key_value(track, key);
+ setting = true;
+ String chan;
+ switch (animation->track_get_type(track)) {
+ case Animation::TYPE_POSITION_3D:
+ chan = "Position3D";
+ break;
+ case Animation::TYPE_ROTATION_3D:
+ chan = "Rotation3D";
+ break;
+ case Animation::TYPE_SCALE_3D:
+ chan = "Scale3D";
+ break;
+ default: {
+ }
+ }
+
+ undo_redo->create_action(vformat(TTR("Anim Change %s"), chan));
+ undo_redo->add_do_method(animation.ptr(), "track_set_key_value", track, key, p_value);
+ undo_redo->add_undo_method(animation.ptr(), "track_set_key_value", track, key, 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;
+ }
- setting = false;
- return true;
} break;
+ case Animation::TYPE_BLEND_SHAPE:
case Animation::TYPE_VALUE: {
if (name == "value") {
Variant value = p_value;
@@ -412,13 +431,15 @@ public:
}
switch (animation->track_get_type(track)) {
- case Animation::TYPE_TRANSFORM3D: {
- Dictionary d = animation->track_get_key_value(track, key);
- ERR_FAIL_COND_V(!d.has(name), false);
- r_ret = d[p_name];
- return true;
-
+ case Animation::TYPE_POSITION_3D:
+ case Animation::TYPE_ROTATION_3D:
+ case Animation::TYPE_SCALE_3D: {
+ if (name == "position" || name == "rotation" || name == "scale") {
+ r_ret = animation->track_get_key_value(track, key);
+ return true;
+ }
} break;
+ case Animation::TYPE_BLEND_SHAPE:
case Animation::TYPE_VALUE: {
if (name == "value") {
r_ret = animation->track_get_key_value(track, key);
@@ -523,11 +544,17 @@ public:
}
switch (animation->track_get_type(track)) {
- case Animation::TYPE_TRANSFORM3D: {
- p_list->push_back(PropertyInfo(Variant::VECTOR3, "location"));
- p_list->push_back(PropertyInfo(Variant::QUATERNION, "rotation"));
+ case Animation::TYPE_POSITION_3D: {
+ p_list->push_back(PropertyInfo(Variant::VECTOR3, "position"));
+ } break;
+ case Animation::TYPE_ROTATION_3D: {
+ p_list->push_back(PropertyInfo(Variant::VECTOR3, "rotation"));
+ } break;
+ case Animation::TYPE_SCALE_3D: {
p_list->push_back(PropertyInfo(Variant::VECTOR3, "scale"));
-
+ } break;
+ case Animation::TYPE_BLEND_SHAPE: {
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "value"));
} break;
case Animation::TYPE_VALUE: {
Variant v = animation->track_get_key_value(track, key);
@@ -541,7 +568,7 @@ public:
String hint_string;
if (v.get_type() == Variant::OBJECT) {
- //could actually check the object property if exists..? yes i will!
+ // Could actually check the object property if exists..? Yes I will!
Ref<Resource> res = v;
if (res.is_valid()) {
hint = PROPERTY_HINT_RESOURCE_TYPE;
@@ -700,16 +727,15 @@ public:
return;
}
- for (Map<int, List<float>>::Element *E = key_ofs_map.front(); E; E = E->next()) {
+ for (const KeyValue<int, List<float>> &E : key_ofs_map) {
int key = 0;
- for (float &F : E->value()) {
- float key_ofs = F;
+ for (const float &key_ofs : E.value) {
if (from != key_ofs) {
key++;
continue;
}
- int track = E->key();
+ int track = E.key;
key_ofs_map[track][key] = to;
if (setting) {
@@ -726,10 +752,9 @@ public:
bool _set(const StringName &p_name, const Variant &p_value) {
bool update_obj = false;
bool change_notify_deserved = false;
- for (Map<int, List<float>>::Element *E = key_ofs_map.front(); E; E = E->next()) {
- int track = E->key();
- for (float &F : E->value()) {
- float key_ofs = F;
+ for (const KeyValue<int, List<float>> &E : key_ofs_map) {
+ int track = E.key;
+ for (const float &key_ofs : E.value) {
int key = animation->track_find_key(track, key_ofs, true);
ERR_FAIL_COND_V(key == -1, false);
@@ -781,19 +806,34 @@ public:
}
switch (animation->track_get_type(track)) {
- case Animation::TYPE_TRANSFORM3D: {
- Dictionary d_old = animation->track_get_key_value(track, key);
- Dictionary d_new = d_old.duplicate();
- d_new[p_name] = p_value;
-
+ case Animation::TYPE_POSITION_3D:
+ case Animation::TYPE_ROTATION_3D:
+ case Animation::TYPE_SCALE_3D: {
+ Variant old = animation->track_get_key_value(track, key);
if (!setting) {
+ String chan;
+ switch (animation->track_get_type(track)) {
+ case Animation::TYPE_POSITION_3D:
+ chan = "Position3D";
+ break;
+ case Animation::TYPE_ROTATION_3D:
+ chan = "Rotation3D";
+ break;
+ case Animation::TYPE_SCALE_3D:
+ chan = "Scale3D";
+ break;
+ default: {
+ }
+ }
+
setting = true;
- undo_redo->create_action(TTR("Anim Multi Change Transform"));
+ undo_redo->create_action(vformat(TTR("Anim Multi Change %s"), chan));
}
- 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(animation.ptr(), "track_set_key_value", track, key, p_value);
+ undo_redo->add_undo_method(animation.ptr(), "track_set_key_value", track, key, old);
update_obj = true;
} break;
+ case Animation::TYPE_BLEND_SHAPE:
case Animation::TYPE_VALUE: {
if (name == "value") {
Variant value = p_value;
@@ -984,10 +1024,9 @@ public:
}
bool _get(const StringName &p_name, Variant &r_ret) const {
- for (Map<int, List<float>>::Element *E = key_ofs_map.front(); E; E = E->next()) {
- int track = E->key();
- for (float &F : E->value()) {
- float key_ofs = F;
+ for (const KeyValue<int, List<float>> &E : key_ofs_map) {
+ int track = E.key;
+ for (const float &key_ofs : E.value) {
int key = animation->track_find_key(track, key_ofs, true);
ERR_CONTINUE(key == -1);
@@ -1012,13 +1051,16 @@ public:
}
switch (animation->track_get_type(track)) {
- case Animation::TYPE_TRANSFORM3D: {
- Dictionary d = animation->track_get_key_value(track, key);
- ERR_FAIL_COND_V(!d.has(name), false);
- r_ret = d[p_name];
- return true;
+ case Animation::TYPE_POSITION_3D:
+ case Animation::TYPE_ROTATION_3D:
+ case Animation::TYPE_SCALE_3D: {
+ if (name == "position" || name == "rotation" || name == "scale") {
+ r_ret = animation->track_get_key_value(track, key);
+ return true;
+ }
} break;
+ case Animation::TYPE_BLEND_SHAPE:
case Animation::TYPE_VALUE: {
if (name == "value") {
r_ret = animation->track_get_key_value(track, key);
@@ -1119,15 +1161,15 @@ public:
bool show_time = true;
bool same_track_type = true;
bool same_key_type = true;
- for (Map<int, List<float>>::Element *E = key_ofs_map.front(); E; E = E->next()) {
- int track = E->key();
+ for (const KeyValue<int, List<float>> &E : key_ofs_map) {
+ int track = E.key;
ERR_FAIL_INDEX(track, animation->get_track_count());
if (first_track < 0) {
first_track = track;
}
- if (show_time && E->value().size() > 1) {
+ if (show_time && E.value.size() > 1) {
show_time = false;
}
@@ -1137,7 +1179,7 @@ public:
same_key_type = false;
}
- for (float &F : E->value()) {
+ for (const float &F : E.value) {
int key = animation->track_find_key(track, F, true);
ERR_FAIL_COND(key == -1);
if (first_key < 0) {
@@ -1162,11 +1204,18 @@ public:
if (same_track_type) {
switch (animation->track_get_type(first_track)) {
- case Animation::TYPE_TRANSFORM3D: {
- p_list->push_back(PropertyInfo(Variant::VECTOR3, "location"));
- p_list->push_back(PropertyInfo(Variant::QUATERNION, "rotation"));
+ case Animation::TYPE_POSITION_3D: {
+ p_list->push_back(PropertyInfo(Variant::VECTOR3, "position"));
+ } break;
+ case Animation::TYPE_ROTATION_3D: {
+ p_list->push_back(PropertyInfo(Variant::QUATERNION, "scale"));
+ } break;
+ case Animation::TYPE_SCALE_3D: {
p_list->push_back(PropertyInfo(Variant::VECTOR3, "scale"));
} break;
+ case Animation::TYPE_BLEND_SHAPE: {
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "value"));
+ } break;
case Animation::TYPE_VALUE: {
if (same_key_type) {
Variant v = animation->track_get_key_value(first_track, first_key);
@@ -1180,7 +1229,7 @@ public:
String hint_string;
if (v.get_type() == Variant::OBJECT) {
- //could actually check the object property if exists..? yes i will!
+ // Could actually check the object property if exists..? Yes I will!
Ref<Resource> res = v;
if (res.is_valid()) {
hint = PROPERTY_HINT_RESOURCE_TYPE;
@@ -1362,7 +1411,10 @@ void AnimationTimelineEdit::_notification(int p_what) {
add_track->get_popup()->clear();
add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyValue"), SNAME("EditorIcons")), TTR("Property Track"));
- add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyXform"), SNAME("EditorIcons")), TTR("3D Transform Track"));
+ add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyXPosition"), SNAME("EditorIcons")), TTR("3D Position Track"));
+ add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyXRotation"), SNAME("EditorIcons")), TTR("3D Rotation Track"));
+ add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyXScale"), SNAME("EditorIcons")), TTR("3D Scale Track"));
+ add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyBlendShape"), SNAME("EditorIcons")), TTR("Blend Shape Track"));
add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyCall"), SNAME("EditorIcons")), TTR("Call Method Track"));
add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyBezier"), SNAME("EditorIcons")), TTR("Bezier Curve Track"));
add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyAudio"), SNAME("EditorIcons")), TTR("Audio Playback Track"));
@@ -1391,7 +1443,7 @@ void AnimationTimelineEdit::_notification(int p_what) {
float l = animation->get_length();
if (l <= 0) {
- l = 0.001; //avoid crashor
+ l = 0.001; // Avoid crashor.
}
Ref<Texture2D> hsize_icon = get_theme_icon(SNAME("Hsize"), SNAME("EditorIcons"));
@@ -1404,18 +1456,12 @@ void AnimationTimelineEdit::_notification(int p_what) {
for (int i = 0; i < animation->get_track_count(); i++) {
if (animation->track_get_key_count(i) > 0) {
float beg = animation->track_get_key_time(i, 0);
- /*if (animation->track_get_type(i) == Animation::TYPE_BEZIER) {
- beg += animation->bezier_track_get_key_in_handle(i, 0).x;
- }* not worth it since they have no use */
if (beg < time_min) {
time_min = beg;
}
float end = animation->track_get_key_time(i, animation->track_get_key_count(i) - 1);
- /*if (animation->track_get_type(i) == Animation::TYPE_BEZIER) {
- end += animation->bezier_track_get_key_out_handle(i, animation->track_get_key_count(i) - 1).x;
- } not worth it since they have no use */
if (end > time_max) {
time_max = end;
@@ -1425,8 +1471,6 @@ void AnimationTimelineEdit::_notification(int p_what) {
float extra = (zoomw / scale) * 0.5;
- //if (time_min < -0.001)
- // time_min -= extra;
time_max += extra;
set_min(time_min);
set_max(time_max);
@@ -1642,7 +1686,7 @@ void AnimationTimelineEdit::_play_position_draw() {
}
}
-void AnimationTimelineEdit::_gui_input(const Ref<InputEvent> &p_event) {
+void AnimationTimelineEdit::gui_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
const Ref<InputEventMouseButton> mb = p_event;
@@ -1754,8 +1798,6 @@ void AnimationTimelineEdit::_track_added(int p_track) {
}
void AnimationTimelineEdit::_bind_methods() {
- ClassDB::bind_method("_gui_input", &AnimationTimelineEdit::_gui_input);
-
ADD_SIGNAL(MethodInfo("zoom_changed"));
ADD_SIGNAL(MethodInfo("name_limit_changed"));
ADD_SIGNAL(MethodInfo("timeline_changed", PropertyInfo(Variant::FLOAT, "position"), PropertyInfo(Variant::BOOL, "drag")));
@@ -1841,9 +1883,12 @@ void AnimationTrackEdit::_notification(int p_what) {
Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
Color color = get_theme_color(SNAME("font_color"), SNAME("Label"));
- Ref<Texture2D> type_icons[6] = {
+ Ref<Texture2D> type_icons[9] = {
get_theme_icon(SNAME("KeyValue"), SNAME("EditorIcons")),
- get_theme_icon(SNAME("KeyXform"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("KeyTrackPosition"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("KeyTrackRotation"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("KeyTrackScale"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("KeyTrackBlendShape"), SNAME("EditorIcons")),
get_theme_icon(SNAME("KeyCall"), SNAME("EditorIcons")),
get_theme_icon(SNAME("KeyBezier"), SNAME("EditorIcons")),
get_theme_icon(SNAME("KeyAudio"), SNAME("EditorIcons")),
@@ -1858,7 +1903,7 @@ void AnimationTrackEdit::_notification(int p_what) {
{
Ref<Texture2D> check = animation->track_is_enabled(track) ? get_theme_icon(SNAME("checked"), SNAME("CheckBox")) : get_theme_icon(SNAME("unchecked"), SNAME("CheckBox"));
- int ofs = in_group ? check->get_width() : 0; //not the best reference for margin but..
+ int ofs = in_group ? check->get_width() : 0; // Not the best reference for margin but..
check_rect = Rect2(Point2(ofs, int(get_size().height - check->get_height()) / 2), check->get_size());
draw_texture(check, check_rect.position);
@@ -1976,7 +2021,7 @@ void AnimationTrackEdit::_notification(int p_what) {
ofs += hsep;
{
- //callmode
+ // Callmode.
Animation::UpdateMode update_mode;
@@ -1995,7 +2040,7 @@ void AnimationTrackEdit::_notification(int p_what) {
if (animation->track_get_type(track) == Animation::TYPE_VALUE) {
draw_texture(update_icon, update_mode_rect.position);
}
- //make it easier to click
+ // Make it easier to click.
update_mode_rect.position.y = 0;
update_mode_rect.size.y = get_size().height;
@@ -2024,7 +2069,7 @@ void AnimationTrackEdit::_notification(int p_what) {
}
{
- //interp
+ // Interp.
Animation::InterpolationType interp_mode = animation->track_get_interpolation_type(track);
@@ -2034,17 +2079,17 @@ void AnimationTrackEdit::_notification(int p_what) {
interp_mode_rect.position.y = int(get_size().height - icon->get_height()) / 2;
interp_mode_rect.size = icon->get_size();
- if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_TRANSFORM3D) {
+ if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D) {
draw_texture(icon, interp_mode_rect.position);
}
- //make it easier to click
+ // Make it easier to click.
interp_mode_rect.position.y = 0;
interp_mode_rect.size.y = get_size().height;
ofs += icon->get_width() + hsep;
interp_mode_rect.size.x += hsep;
- if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_TRANSFORM3D) {
+ if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == 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 {
@@ -2057,7 +2102,7 @@ void AnimationTrackEdit::_notification(int p_what) {
}
{
- //loop
+ // Loop.
bool loop_wrap = animation->track_get_interpolation_loop_wrap(track);
@@ -2067,7 +2112,7 @@ void AnimationTrackEdit::_notification(int p_what) {
loop_mode_rect.position.y = int(get_size().height - icon->get_height()) / 2;
loop_mode_rect.size = icon->get_size();
- if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_TRANSFORM3D) {
+ if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D) {
draw_texture(icon, loop_mode_rect.position);
}
@@ -2077,7 +2122,7 @@ void AnimationTrackEdit::_notification(int p_what) {
ofs += icon->get_width() + hsep;
loop_mode_rect.size.x += hsep;
- if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_TRANSFORM3D) {
+ if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == 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 {
@@ -2090,7 +2135,7 @@ void AnimationTrackEdit::_notification(int p_what) {
}
{
- //erase
+ // Erase.
Ref<Texture2D> icon = get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"));
@@ -2137,7 +2182,7 @@ Rect2 AnimationTrackEdit::get_key_rect(int p_index, float p_pixels_sec) {
}
Rect2 rect = Rect2(-type_icon->get_width() / 2, 0, type_icon->get_width(), get_size().height);
- //make it a big easier to click
+ // Make it a big easier to click.
rect.position.x -= rect.size.x * 0.5;
rect.size.x *= 2;
return rect;
@@ -2226,7 +2271,7 @@ void AnimationTrackEdit::draw_key(int p_index, float p_pixels_sec, int p_x, bool
draw_texture(icon_to_draw, ofs);
}
-//helper
+// Helper.
void AnimationTrackEdit::draw_rect_clipped(const Rect2 &p_rect, const Color &p_color, bool p_filled) {
int clip_left = timeline->get_name_limit();
int clip_right = get_size().width - timeline->get_buttons_width();
@@ -2251,7 +2296,7 @@ void AnimationTrackEdit::draw_texture_region_clipped(const Ref<Texture2D> &p_tex
int clip_left = timeline->get_name_limit();
int clip_right = get_size().width - timeline->get_buttons_width();
- //clip left and right
+ // Clip left and right.
if (clip_left > p_rect.position.x + p_rect.size.x) {
return;
}
@@ -2297,9 +2342,12 @@ void AnimationTrackEdit::set_animation_and_track(const Ref<Animation> &p_animati
track = p_track;
update();
- Ref<Texture2D> type_icons[6] = {
+ Ref<Texture2D> type_icons[9] = {
get_theme_icon(SNAME("KeyValue"), SNAME("EditorIcons")),
- get_theme_icon(SNAME("KeyXform"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("KeyXPosition"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("KeyXRotation"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("KeyXScale"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("KeyBlendShape"), SNAME("EditorIcons")),
get_theme_icon(SNAME("KeyCall"), SNAME("EditorIcons")),
get_theme_icon(SNAME("KeyBezier"), SNAME("EditorIcons")),
get_theme_icon(SNAME("KeyAudio"), SNAME("EditorIcons")),
@@ -2460,7 +2508,7 @@ String AnimationTrackEdit::get_tooltip(const Point2 &p_pos) const {
key_distance = distance;
}
} else {
- //first one does it
+ // First one does it.
break;
}
}
@@ -2469,17 +2517,21 @@ 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_TRANSFORM3D: {
- 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";
- }
+ case Animation::TYPE_POSITION_3D: {
+ Vector3 t = animation->track_get_key_value(track, key_idx);
+ text += "Position: " + String(t) + "\n";
+ } break;
+ case Animation::TYPE_ROTATION_3D: {
+ Quaternion t = animation->track_get_key_value(track, key_idx);
+ text += "Rotation: " + String(t) + "\n";
+ } break;
+ case Animation::TYPE_SCALE_3D: {
+ Vector3 t = animation->track_get_key_value(track, key_idx);
+ text += "Scale: " + String(t) + "\n";
+ } break;
+ case Animation::TYPE_BLEND_SHAPE: {
+ float t = animation->track_get_key_value(track, key_idx);
+ text += "Blend Shape: " + itos(t) + "\n";
} break;
case Animation::TYPE_VALUE: {
const Variant &v = animation->track_get_key_value(track, key_idx);
@@ -2551,7 +2603,7 @@ String AnimationTrackEdit::get_tooltip(const Point2 &p_pos) const {
return Control::get_tooltip(p_pos);
}
-void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
+void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
if (p_event->is_pressed()) {
@@ -2965,8 +3017,6 @@ void AnimationTrackEdit::append_to_selection(const Rect2 &p_box, bool p_deselect
}
void AnimationTrackEdit::_bind_methods() {
- ClassDB::bind_method("_gui_input", &AnimationTrackEdit::_gui_input);
-
ADD_SIGNAL(MethodInfo("timeline_changed", PropertyInfo(Variant::FLOAT, "position"), PropertyInfo(Variant::BOOL, "drag")));
ADD_SIGNAL(MethodInfo("remove_request", PropertyInfo(Variant::INT, "track")));
ADD_SIGNAL(MethodInfo("dropped", PropertyInfo(Variant::INT, "from_track"), PropertyInfo(Variant::INT, "to_track")));
@@ -3008,7 +3058,7 @@ AnimationTrackEdit::AnimationTrackEdit() {
play_position->set_anchors_and_offsets_preset(PRESET_WIDE);
play_position->connect("draw", callable_mp(this, &AnimationTrackEdit::_play_position_draw));
set_focus_mode(FOCUS_CLICK);
- set_mouse_filter(MOUSE_FILTER_PASS); //scroll has to work too for selection
+ set_mouse_filter(MOUSE_FILTER_PASS); // Scroll has to work too for selection.
}
//////////////////////////////////////
@@ -3336,39 +3386,31 @@ static bool track_type_is_resettable(Animation::TrackType p_type) {
switch (p_type) {
case Animation::TYPE_VALUE:
[[fallthrough]];
+ case Animation::TYPE_BLEND_SHAPE:
+ [[fallthrough]];
case Animation::TYPE_BEZIER:
[[fallthrough]];
- case Animation::TYPE_TRANSFORM3D:
+ case Animation::TYPE_POSITION_3D:
+ [[fallthrough]];
+ case Animation::TYPE_ROTATION_3D:
+ [[fallthrough]];
+ case Animation::TYPE_SCALE_3D:
return true;
default:
return false;
}
}
-void AnimationTrackEditor::_query_insert(const InsertData &p_id) {
- if (insert_frame != Engine::get_singleton()->get_frames_drawn()) {
- //clear insert list for the frame if frame changed
- if (insert_confirm->is_visible()) {
- return; //do nothing
- }
- insert_data.clear();
- insert_query = false;
- }
- insert_frame = Engine::get_singleton()->get_frames_drawn();
-
- for (const InsertData &E : insert_data) {
- //prevent insertion of multiple tracks
- if (E.path == p_id.path) {
- return; //already inserted a track for this on this frame
- }
- }
-
- insert_data.push_back(p_id);
+void AnimationTrackEditor::make_insert_queue() {
+ insert_data.clear();
+ insert_queue = true;
+}
+void AnimationTrackEditor::commit_insert_queue() {
bool reset_allowed = true;
- AnimationPlayer *player = AnimationPlayerEditor::singleton->get_player();
+ AnimationPlayer *player = AnimationPlayerEditor::get_singleton()->get_player();
if (player->has_animation("RESET") && player->get_animation("RESET") == animation) {
- // Avoid messing with the reset animation itself
+ // Avoid messing with the reset animation itself.
reset_allowed = false;
} else {
bool some_resettable = false;
@@ -3383,74 +3425,82 @@ void AnimationTrackEditor::_query_insert(const InsertData &p_id) {
}
}
- if (p_id.track_idx == -1) {
- int num_tracks = 0;
- bool all_bezier = true;
- for (int i = 0; i < insert_data.size(); i++) {
- if (insert_data[i].type != Animation::TYPE_VALUE && insert_data[i].type != Animation::TYPE_BEZIER) {
- all_bezier = false;
- }
-
- if (insert_data[i].track_idx == -1) {
- ++num_tracks;
- }
+ // Organize insert data.
+ int num_tracks = 0;
+ String last_track_query;
+ bool all_bezier = true;
+ for (int i = 0; i < insert_data.size(); i++) {
+ if (insert_data[i].type != Animation::TYPE_VALUE && insert_data[i].type != Animation::TYPE_BEZIER) {
+ all_bezier = false;
+ }
- if (insert_data[i].type != Animation::TYPE_VALUE) {
- continue;
- }
+ if (insert_data[i].track_idx == -1) {
+ ++num_tracks;
+ last_track_query = insert_data[i].query;
+ }
- switch (insert_data[i].value.get_type()) {
- case Variant::INT:
- case Variant::FLOAT:
- case Variant::VECTOR2:
- case Variant::VECTOR3:
- case Variant::QUATERNION:
- case Variant::PLANE:
- case Variant::COLOR: {
- // Valid.
- } break;
- default: {
- all_bezier = false;
- }
- }
+ if (insert_data[i].type != Animation::TYPE_VALUE) {
+ continue;
}
- if (bool(EDITOR_DEF("editors/animation/confirm_insert_track", true))) {
- //potential new key, does not exist
- if (num_tracks == 1) {
- // TRANSLATORS: %s will be replaced by a phrase describing the target of track.
- insert_confirm_text->set_text(vformat(TTR("Create new track for %s and insert key?"), p_id.query));
- } else {
- insert_confirm_text->set_text(vformat(TTR("Create %d new tracks and insert keys?"), num_tracks));
+ switch (insert_data[i].value.get_type()) {
+ case Variant::INT:
+ case Variant::FLOAT:
+ case Variant::VECTOR2:
+ case Variant::VECTOR3:
+ case Variant::QUATERNION:
+ case Variant::PLANE:
+ case Variant::COLOR: {
+ // Valid.
+ } break;
+ default: {
+ all_bezier = false;
}
+ }
+ }
- insert_confirm_bezier->set_visible(all_bezier);
- insert_confirm_reset->set_visible(reset_allowed);
-
- insert_confirm->get_ok_button()->set_text(TTR("Create"));
- insert_confirm->popup_centered();
- insert_query = true;
+ if (bool(EDITOR_DEF("editors/animation/confirm_insert_track", true)) && num_tracks > 0) {
+ // Potentially a new key, does not exist.
+ if (num_tracks == 1) {
+ // TRANSLATORS: %s will be replaced by a phrase describing the target of track.
+ insert_confirm_text->set_text(vformat(TTR("Create new track for %s and insert key?"), last_track_query));
} else {
- call_deferred(SNAME("_insert_delay"), reset_allowed && EDITOR_GET("editors/animation/default_create_reset_tracks"), all_bezier && EDITOR_GET("editors/animation/default_create_bezier_tracks"));
- insert_queue = true;
+ insert_confirm_text->set_text(vformat(TTR("Create %d new tracks and insert keys?"), num_tracks));
}
+ insert_confirm_bezier->set_visible(all_bezier);
+ insert_confirm_reset->set_visible(reset_allowed);
+
+ insert_confirm->get_ok_button()->set_text(TTR("Create"));
+ insert_confirm->popup_centered();
} else {
- if (!insert_query && !insert_queue) {
- // Create Beziers wouldn't make sense in this case, where no tracks are being created
- call_deferred(SNAME("_insert_delay"), reset_allowed && EDITOR_GET("editors/animation/default_create_reset_tracks"), false);
- insert_queue = true;
- }
+ _insert_track(reset_allowed && EDITOR_GET("editors/animation/default_create_reset_tracks"), all_bezier && EDITOR_GET("editors/animation/default_create_bezier_tracks"));
}
+
+ insert_queue = false;
}
-void AnimationTrackEditor::_insert_delay(bool p_create_reset, bool p_create_beziers) {
- if (insert_query) {
- //discard since it's entered into query mode
- insert_queue = false;
- return;
+void AnimationTrackEditor::_query_insert(const InsertData &p_id) {
+ if (!insert_queue) {
+ insert_data.clear();
+ }
+
+ for (const InsertData &E : insert_data) {
+ // Prevent insertion of multiple tracks.
+ if (E.path == p_id.path) {
+ return; // Already inserted a track this frame.
+ }
+ }
+
+ insert_data.push_back(p_id);
+
+ // Without queue, commit immediately.
+ if (!insert_queue) {
+ commit_insert_queue();
}
+}
+void AnimationTrackEditor::_insert_track(bool p_create_reset, bool p_create_beziers) {
undo_redo->create_action(TTR("Anim Insert"));
Ref<Animation> reset_anim;
@@ -3485,7 +3535,6 @@ void AnimationTrackEditor::_insert_delay(bool p_create_reset, bool p_create_bezi
set_anim_pos(pos);
emit_signal(SNAME("timeline_changed"), pos, true);
}
- insert_queue = false;
}
void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_sub, const Transform3D &p_xform) {
@@ -3497,7 +3546,7 @@ void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_
}
ERR_FAIL_COND(!root);
- //let's build a node path
+ // Let's build a node path.
String path = root->get_path_to(p_node);
if (p_sub != "") {
path += ":" + p_sub;
@@ -3505,45 +3554,86 @@ void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_
NodePath np = path;
- int track_idx = -1;
+ int position_idx = -1;
+ int rotation_idx = -1;
+ int scale_idx = -1;
for (int i = 0; i < animation->get_track_count(); i++) {
- if (animation->track_get_type(i) != Animation::TYPE_TRANSFORM3D) {
- continue;
- }
if (animation->track_get_path(i) != np) {
continue;
}
- track_idx = i;
- break;
+ if (animation->track_get_type(i) == Animation::TYPE_POSITION_3D) {
+ position_idx = i;
+ }
+ if (animation->track_get_type(i) == Animation::TYPE_ROTATION_3D) {
+ rotation_idx = i;
+ }
+ if (animation->track_get_type(i) == Animation::TYPE_SCALE_3D) {
+ scale_idx = i;
+ }
}
InsertData id;
- Dictionary val;
-
id.path = np;
- id.track_idx = track_idx;
- id.value = p_xform;
- id.type = Animation::TYPE_TRANSFORM3D;
// TRANSLATORS: This describes the target of new animation track, will be inserted into another string.
id.query = vformat(TTR("node '%s'"), p_node->get_name());
id.advance = false;
- //dialog insert
+ {
+ id.track_idx = position_idx;
+ id.value = p_xform.origin;
+ id.type = Animation::TYPE_POSITION_3D;
+ _query_insert(id);
+ }
+ {
+ id.track_idx = rotation_idx;
+ id.value = p_xform.basis.get_rotation_quaternion();
+ id.type = Animation::TYPE_ROTATION_3D;
+ _query_insert(id);
+ }
+ {
+ id.track_idx = scale_idx;
+ id.value = p_xform.basis.get_scale();
+ id.type = Animation::TYPE_SCALE_3D;
+ _query_insert(id);
+ }
+}
+
+bool AnimationTrackEditor::has_transform_track(Node3D *p_node, const String &p_sub) {
+ if (!keying) {
+ return false;
+ }
+ if (!animation.is_valid()) {
+ return false;
+ }
+ if (!root) {
+ return false;
+ }
- _query_insert(id);
+ //let's build a node path
+ String path = root->get_path_to(p_node);
+ if (p_sub != "") {
+ path += ":" + p_sub;
+ }
+ int track_id = animation->find_track(path);
+ if (track_id >= 0) {
+ if (animation->track_get_type(track_id) == Animation::TYPE_POSITION_3D || animation->track_get_type(track_id) == Animation::TYPE_ROTATION_3D || animation->track_get_type(track_id) == Animation::TYPE_SCALE_3D) {
+ return true;
+ }
+ }
+ return false;
}
void AnimationTrackEditor::_insert_animation_key(NodePath p_path, const Variant &p_value) {
String path = p_path;
- //animation property is a special case, always creates an animation track
+ // Animation property is a special case, always creates an animation track.
for (int i = 0; i < animation->get_track_count(); i++) {
String np = animation->track_get_path(i);
if (path == np && animation->track_get_type(i) == Animation::TYPE_ANIMATION) {
- //exists
+ // Exists.
InsertData id;
id.path = path;
id.track_idx = i;
@@ -3552,7 +3642,7 @@ void AnimationTrackEditor::_insert_animation_key(NodePath p_path, const Variant
// TRANSLATORS: This describes the target of new animation track, will be inserted into another string.
id.query = TTR("animation");
id.advance = false;
- //dialog insert
+ // Dialog insert.
_query_insert(id);
return;
}
@@ -3565,20 +3655,20 @@ void AnimationTrackEditor::_insert_animation_key(NodePath p_path, const Variant
id.type = Animation::TYPE_ANIMATION;
id.query = TTR("animation");
id.advance = false;
- //dialog insert
+ // Dialog insert.
_query_insert(id);
}
void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_property, const Variant &p_value, bool p_only_if_exists) {
ERR_FAIL_COND(!root);
- //let's build a node path
+ // Let's build a node path.
Node *node = p_node;
String path = root->get_path_to(node);
if (Object::cast_to<AnimationPlayer>(node) && p_property == "current_animation") {
- if (node == AnimationPlayerEditor::singleton->get_player()) {
+ if (node == AnimationPlayerEditor::get_singleton()->get_player()) {
EditorNode::get_singleton()->show_warning(TTR("AnimationPlayer can't animate itself, only other players."));
return;
}
@@ -3597,7 +3687,7 @@ void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_p
NodePath np = path;
- //locate track
+ // Locate track.
bool inserted = false;
@@ -3615,14 +3705,14 @@ void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_p
// TRANSLATORS: This describes the target of new animation track, will be inserted into another string.
id.query = vformat(TTR("property '%s'"), p_property);
id.advance = false;
- //dialog insert
+ // Dialog insert.
_query_insert(id);
inserted = true;
} else if (animation->track_get_type(i) == Animation::TYPE_BEZIER) {
Variant value;
String track_path = animation->track_get_path(i);
if (track_path == np) {
- value = p_value; //all good
+ value = p_value; // All good.
} else {
int sep = track_path.rfind(":");
if (sep != -1) {
@@ -3645,7 +3735,7 @@ void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_p
id.type = Animation::TYPE_BEZIER;
id.query = vformat(TTR("property '%s'"), p_property);
id.advance = false;
- //dialog insert
+ // Dialog insert.
_query_insert(id);
inserted = true;
}
@@ -3661,7 +3751,7 @@ void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_p
id.type = Animation::TYPE_VALUE;
id.query = vformat(TTR("property '%s'"), p_property);
id.advance = false;
- //dialog insert
+ // Dialog insert.
_query_insert(id);
}
@@ -3669,7 +3759,7 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari
EditorHistory *history = EditorNode::get_singleton()->get_editor_history();
ERR_FAIL_COND(!root);
- //let's build a node path
+ // Let's build a node path.
ERR_FAIL_COND(history->get_path_size() == 0);
Object *obj = ObjectDB::get_instance(history->get_path_object(0));
ERR_FAIL_COND(!Object::cast_to<Node>(obj));
@@ -3679,7 +3769,7 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari
String path = root->get_path_to(node);
if (Object::cast_to<AnimationPlayer>(node) && p_property == "current_animation") {
- if (node == AnimationPlayerEditor::singleton->get_player()) {
+ if (node == AnimationPlayerEditor::get_singleton()->get_player()) {
EditorNode::get_singleton()->show_warning(TTR("AnimationPlayer can't animate itself, only other players."));
return;
}
@@ -3697,10 +3787,11 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari
NodePath np = path;
- //locate track
+ // Locate track.
bool inserted = false;
+ make_insert_queue();
for (int i = 0; i < animation->get_track_count(); i++) {
if (animation->track_get_type(i) == Animation::TYPE_VALUE) {
if (animation->track_get_path(i) != np) {
@@ -3714,13 +3805,13 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari
id.type = Animation::TYPE_VALUE;
id.query = vformat(TTR("property '%s'"), p_property);
id.advance = p_advance;
- //dialog insert
+ // Dialog insert.
_query_insert(id);
inserted = true;
} else if (animation->track_get_type(i) == Animation::TYPE_BEZIER) {
Variant value;
if (animation->track_get_path(i) == np) {
- value = p_value; //all good
+ value = p_value; // All good.
} else {
String tpath = animation->track_get_path(i);
int index = tpath.rfind(":");
@@ -3739,11 +3830,12 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari
id.type = Animation::TYPE_BEZIER;
id.query = vformat(TTR("property '%s'"), p_property);
id.advance = p_advance;
- //dialog insert
+ // Dialog insert.
_query_insert(id);
inserted = true;
}
}
+ commit_insert_queue();
if (!inserted) {
InsertData id;
@@ -3753,13 +3845,13 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari
id.type = Animation::TYPE_VALUE;
id.query = vformat(TTR("property '%s'"), p_property);
id.advance = p_advance;
- //dialog insert
+ // Dialog insert.
_query_insert(id);
}
}
Ref<Animation> AnimationTrackEditor::_create_and_get_reset_animation() {
- AnimationPlayer *player = AnimationPlayerEditor::singleton->get_player();
+ AnimationPlayer *player = AnimationPlayerEditor::get_singleton()->get_player();
if (player->has_animation("RESET")) {
return player->get_animation("RESET");
} else {
@@ -3767,9 +3859,9 @@ Ref<Animation> AnimationTrackEditor::_create_and_get_reset_animation() {
reset_anim.instantiate();
reset_anim->set_length(ANIM_MIN_LENGTH);
undo_redo->add_do_method(player, "add_animation", "RESET", reset_anim);
- undo_redo->add_do_method(AnimationPlayerEditor::singleton, "_animation_player_changed", player);
+ undo_redo->add_do_method(AnimationPlayerEditor::get_singleton(), "_animation_player_changed", player);
undo_redo->add_undo_method(player, "remove_animation", "RESET");
- undo_redo->add_undo_method(AnimationPlayerEditor::singleton, "_animation_player_changed", player);
+ undo_redo->add_undo_method(AnimationPlayerEditor::get_singleton(), "_animation_player_changed", player);
return reset_anim;
}
}
@@ -3936,7 +4028,7 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD
animation->add_track(p_id.type);
animation->track_set_path(animation->get_track_count() - 1, p_id.path);
PropertyInfo h = _find_hint_for_track(animation->get_track_count() - 1, np);
- animation->remove_track(animation->get_track_count() - 1); //hack
+ animation->remove_track(animation->get_track_count() - 1); // Hack.
if (h.type == Variant::FLOAT ||
h.type == Variant::VECTOR2 ||
@@ -3973,18 +4065,14 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD
Variant value;
switch (p_id.type) {
+ case Animation::TYPE_POSITION_3D:
+ case Animation::TYPE_ROTATION_3D:
+ case Animation::TYPE_SCALE_3D:
+ case Animation::TYPE_BLEND_SHAPE:
case Animation::TYPE_VALUE: {
value = p_id.value;
} break;
- case Animation::TYPE_TRANSFORM3D: {
- Transform3D tr = p_id.value;
- Dictionary d;
- d["location"] = tr.origin;
- d["scale"] = tr.basis.get_scale();
- d["rotation"] = Quaternion(tr.basis);
- value = d;
- } break;
case Animation::TYPE_BEZIER: {
Array array;
array.resize(5);
@@ -4085,7 +4173,7 @@ void AnimationTrackEditor::_update_tracks() {
for (int i = 0; i < animation->get_track_count(); i++) {
AnimationTrackEdit *track_edit = nullptr;
- //find hint and info for plugin
+ // Find hint and info for plugin.
if (use_filter) {
NodePath path = animation->track_get_path(i);
@@ -4093,10 +4181,10 @@ void AnimationTrackEditor::_update_tracks() {
if (root && root->has_node(path)) {
Node *node = root->get_node(path);
if (!node) {
- continue; // no node, no filter
+ continue; // No node, no filter.
}
if (!EditorNode::get_singleton()->get_editor_selection()->is_selected(node)) {
- continue; //skip track due to not selected
+ continue; // Skip track due to not selected.
}
}
}
@@ -4158,7 +4246,7 @@ void AnimationTrackEditor::_update_tracks() {
}
if (track_edit == nullptr) {
- //no valid plugin_found
+ // No valid plugin_found.
track_edit = memnew(AnimationTrackEdit);
}
@@ -4233,11 +4321,11 @@ void AnimationTrackEditor::_update_tracks() {
void AnimationTrackEditor::_animation_changed() {
if (animation_changing_awaiting_update) {
- return; //all will be updated, don't bother with anything
+ return; // All will be updated, don't bother with anything.
}
if (key_edit && key_edit->setting) {
- //if editing a key, just update the edited track, makes refresh less costly
+ // If editing a key, just update the edited track, makes refresh less costly.
if (key_edit->track < track_edits.size()) {
if (animation->track_get_type(key_edit->track) == Animation::TYPE_BEZIER) {
bezier_edit->update();
@@ -4291,7 +4379,7 @@ void AnimationTrackEditor::_animation_update() {
}
if (track_edits.size() == animation->get_track_count()) {
- //check tracks are the same
+ // Check tracks are the same.
for (int i = 0; i < track_edits.size(); i++) {
if (track_edits[i]->get_path() != animation->track_get_path(i)) {
@@ -4400,8 +4488,13 @@ 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_TRANSFORM3D && !node->is_class("Node3D")) {
- EditorNode::get_singleton()->show_warning(TTR("Transform3D tracks only apply to 3D-based nodes."));
+ if (adding_track_type == Animation::TYPE_BLEND_SHAPE && !node->is_class("MeshInstance3D")) {
+ EditorNode::get_singleton()->show_warning(TTR("Blend Shape tracks only apply to MeshInstance3D nodes."));
+ return;
+ }
+
+ 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("Node3D")) {
+ EditorNode::get_singleton()->show_warning(TTR("Position/Rotation/Scale 3D tracks only apply to 3D-based nodes."));
return;
}
@@ -4411,7 +4504,16 @@ 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_TRANSFORM3D:
+ case Animation::TYPE_BLEND_SHAPE: {
+ adding_track_path = path_to;
+ Vector<Variant::Type> filter;
+ filter.push_back(Variant::FLOAT);
+ prop_selector->set_type_filter(filter);
+ prop_selector->select_property_from_instance(node);
+ } break;
+ case Animation::TYPE_POSITION_3D:
+ case Animation::TYPE_ROTATION_3D:
+ case Animation::TYPE_SCALE_3D:
case Animation::TYPE_METHOD: {
undo_redo->create_action(TTR("Add Track"));
undo_redo->add_do_method(animation.ptr(), "add_track", adding_track_type);
@@ -4453,7 +4555,7 @@ void AnimationTrackEditor::_new_track_node_selected(NodePath p_path) {
return;
}
- if (node == AnimationPlayerEditor::singleton->get_player()) {
+ if (node == AnimationPlayerEditor::get_singleton()->get_player()) {
EditorNode::get_singleton()->show_warning(TTR("AnimationPlayer can't animate itself, only other players."));
return;
}
@@ -4485,12 +4587,12 @@ void AnimationTrackEditor::_new_track_property_selected(String p_name) {
if (adding_track_type == Animation::TYPE_VALUE) {
Animation::UpdateMode update_mode = Animation::UPDATE_DISCRETE;
{
- //hack
+ // Hack.
NodePath np;
animation->add_track(Animation::TYPE_VALUE);
animation->track_set_path(animation->get_track_count() - 1, full_path);
PropertyInfo h = _find_hint_for_track(animation->get_track_count() - 1, np);
- animation->remove_track(animation->get_track_count() - 1); //hack
+ animation->remove_track(animation->get_track_count() - 1); // Hack.
if (h.type == Variant::FLOAT ||
h.type == Variant::VECTOR2 ||
h.type == Variant::RECT2 ||
@@ -4518,12 +4620,12 @@ void AnimationTrackEditor::_new_track_property_selected(String p_name) {
} else {
Vector<String> subindices;
{
- //hack
+ // Hack.
NodePath np;
animation->add_track(Animation::TYPE_VALUE);
animation->track_set_path(animation->get_track_count() - 1, full_path);
PropertyInfo h = _find_hint_for_track(animation->get_track_count() - 1, np);
- animation->remove_track(animation->get_track_count() - 1); //hack
+ animation->remove_track(animation->get_track_count() - 1); // Hack.
bool valid;
subindices = _get_bezier_subindices_for_type(h.type, &valid);
if (!valid) {
@@ -4575,12 +4677,32 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) {
if (snap->is_pressed() && step->get_value() != 0) {
p_ofs = snap_time(p_ofs);
}
- while (animation->track_find_key(p_track, p_ofs, true) != -1) { //make sure insertion point is valid
+ while (animation->track_find_key(p_track, p_ofs, true) != -1) { // Make sure insertion point is valid.
p_ofs += 0.001;
}
switch (animation->track_get_type(p_track)) {
- case Animation::TYPE_TRANSFORM3D: {
+ 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."));
+ return;
+ }
+ Node3D *base = Object::cast_to<Node3D>(root->get_node(animation->track_get_path(p_track)));
+
+ if (!base) {
+ EditorNode::get_singleton()->show_warning(TTR("Track is not of type Node3D, can't insert key"));
+ return;
+ }
+
+ Vector3 pos = base->get_position();
+
+ undo_redo->create_action(TTR("Add Position Key"));
+ undo_redo->add_do_method(animation.ptr(), "position_track_insert_key", p_track, p_ofs, pos);
+ undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", p_track, p_ofs);
+ undo_redo->commit_action();
+
+ } break;
+ case Animation::TYPE_ROTATION_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."));
return;
@@ -4592,18 +4714,35 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) {
return;
}
- Transform3D xf = base->get_transform();
+ Quaternion rot = base->get_transform().basis.operator Quaternion();
+
+ undo_redo->create_action(TTR("Add Rotation Key"));
+ undo_redo->add_do_method(animation.ptr(), "rotation_track_insert_key", p_track, p_ofs, rot);
+ undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", p_track, p_ofs);
+ undo_redo->commit_action();
+
+ } break;
+ case Animation::TYPE_SCALE_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."));
+ return;
+ }
+ Node3D *base = Object::cast_to<Node3D>(root->get_node(animation->track_get_path(p_track)));
+
+ if (!base) {
+ EditorNode::get_singleton()->show_warning(TTR("Track is not of type Node3D, can't insert key"));
+ return;
+ }
- Vector3 loc = xf.get_origin();
- Vector3 scale = xf.basis.get_scale_local();
- Quaternion rot = xf.basis;
+ Vector3 scale = base->get_scale();
- 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->create_action(TTR("Add Scale Key"));
+ undo_redo->add_do_method(animation.ptr(), "scale_track_insert_key", p_track, p_ofs, scale);
undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", p_track, p_ofs);
undo_redo->commit_action();
} break;
+ case Animation::TYPE_BLEND_SHAPE:
case Animation::TYPE_VALUE: {
NodePath bp;
Variant value;
@@ -4770,16 +4909,16 @@ struct _AnimMoveRestore {
Variant key;
float transition = 0;
};
-//used for undo/redo
+// Used for undo/redo.
void AnimationTrackEditor::_clear_key_edit() {
if (key_edit) {
- //if key edit is the object being inspected, remove it first
+ // If key edit is the object being inspected, remove it first.
if (EditorNode::get_singleton()->get_inspector()->get_edited_object() == key_edit) {
EditorNode::get_singleton()->push_item(nullptr);
}
- //then actually delete it
+ // Then actually delete it.
memdelete(key_edit);
key_edit = nullptr;
}
@@ -4835,8 +4974,8 @@ void AnimationTrackEditor::_update_key_edit() {
Map<int, List<float>> key_ofs_map;
Map<int, NodePath> base_map;
int first_track = -1;
- for (Map<SelectedKey, KeyInfo>::Element *E = selection.front(); E; E = E->next()) {
- int track = E->key().track;
+ for (const KeyValue<SelectedKey, KeyInfo> &E : selection) {
+ int track = E.key.track;
if (first_track < 0) {
first_track = track;
}
@@ -4846,7 +4985,7 @@ void AnimationTrackEditor::_update_key_edit() {
base_map[track] = NodePath();
}
- key_ofs_map[track].push_back(animation->track_get_key_time(track, E->key().key));
+ key_ofs_map[track].push_back(animation->track_get_key_time(track, E.key.key));
}
multi_key_edit->key_ofs_map = key_ofs_map;
multi_key_edit->base_map = base_map;
@@ -4893,11 +5032,11 @@ void AnimationTrackEditor::_move_selection_commit() {
List<_AnimMoveRestore> to_restore;
float motion = moving_selection_offset;
- // 1 - remove the keys
+ // 1 - remove the keys.
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
undo_redo->add_do_method(animation.ptr(), "track_remove_key", E->key().track, E->key().key);
}
- // 2 - remove overlapped keys
+ // 2 - Remove overlapped keys.
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
float newtime = snap_time(E->get().pos + motion);
int idx = animation->track_find_key(E->key().track, newtime, true);
@@ -4908,7 +5047,7 @@ void AnimationTrackEditor::_move_selection_commit() {
sk.key = idx;
sk.track = E->key().track;
if (selection.has(sk)) {
- continue; //already in selection, don't save
+ continue; // Already in selection, don't save.
}
undo_redo->add_do_method(animation.ptr(), "track_remove_key_at_time", E->key().track, newtime);
@@ -4922,24 +5061,24 @@ void AnimationTrackEditor::_move_selection_commit() {
to_restore.push_back(amr);
}
- // 3 - move the keys (re insert them)
+ // 3 - Move the keys (Reinsert them).
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
float newpos = snap_time(E->get().pos + motion);
undo_redo->add_do_method(animation.ptr(), "track_insert_key", E->key().track, newpos, animation->track_get_key_value(E->key().track, E->key().key), animation->track_get_key_transition(E->key().track, E->key().key));
}
- // 4 - (undo) remove inserted keys
+ // 4 - (Undo) Remove inserted keys.
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
float newpos = snap_time(E->get().pos + motion);
undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", E->key().track, newpos);
}
- // 5 - (undo) reinsert keys
+ // 5 - (Undo) Reinsert keys.
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
undo_redo->add_undo_method(animation.ptr(), "track_insert_key", E->key().track, E->get().pos, animation->track_get_key_value(E->key().track, E->key().key), animation->track_get_key_transition(E->key().track, E->key().key));
}
- // 6 - (undo) reinsert overlapped keys
+ // 6 - (Undo) Reinsert overlapped keys.
for (_AnimMoveRestore &amr : to_restore) {
undo_redo->add_undo_method(animation.ptr(), "track_insert_key", amr.track, amr.time, amr.key, amr.transition);
}
@@ -4947,7 +5086,7 @@ void AnimationTrackEditor::_move_selection_commit() {
undo_redo->add_do_method(this, "_clear_selection_for_anim", animation);
undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
- // 7 - reselect
+ // 7 - Reselect.
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
float oldpos = E->get().pos;
float newpos = snap_time(oldpos + motion);
@@ -5017,18 +5156,18 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) {
box_select_rect = Rect2();
} else if (box_selecting) {
if (box_selection->is_visible_in_tree()) {
- //only if moved
+ // Only if moved.
for (int i = 0; i < track_edits.size(); i++) {
Rect2 local_rect = box_select_rect;
local_rect.position -= track_edits[i]->get_global_position();
track_edits[i]->append_to_selection(local_rect, mb->is_command_pressed());
}
- if (_get_track_selected() == -1 && track_edits.size() > 0) { //minimal hack to make shortcuts work
+ if (_get_track_selected() == -1 && track_edits.size() > 0) { // Minimal hack to make shortcuts work.
track_edits[track_edits.size() - 1]->grab_focus();
}
} else {
- _clear_selection(); //clear it
+ _clear_selection(); // Clear it.
}
box_selection->hide();
@@ -5044,7 +5183,7 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) {
if (mm.is_valid() && box_selecting) {
if (!(mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT)) {
- //no longer
+ // No longer.
box_selection->hide();
box_selecting = false;
return;
@@ -5084,16 +5223,16 @@ void AnimationTrackEditor::_cancel_bezier_edit() {
}
void AnimationTrackEditor::_bezier_edit(int p_for_track) {
- _clear_selection(); //bezier probably wants to use a separate selection mode
+ _clear_selection(); // Bezier probably wants to use a separate selection mode.
bezier_edit->set_root(root);
bezier_edit->set_animation_and_track(animation, p_for_track);
scroll->hide();
bezier_edit->show();
- //search everything within the track and curve- edit it
+ // Search everything within the track and curve - edit it.
}
void AnimationTrackEditor::_anim_duplicate_keys(bool transpose) {
- //duplicait!
+ // Duplicait!
if (selection.size() && animation.is_valid() && (!transpose || (_get_track_selected() >= 0 && _get_track_selected() < animation->get_track_count()))) {
int top_track = 0x7FFFFFFF;
float top_time = 1e10;
@@ -5151,7 +5290,7 @@ void AnimationTrackEditor::_anim_duplicate_keys(bool transpose) {
undo_redo->commit_action();
- //reselect duplicated
+ // Reselect duplicated.
Map<SelectedKey, KeyInfo> new_selection;
for (const Pair<int, float> &E : new_selection_values) {
@@ -5180,7 +5319,7 @@ void AnimationTrackEditor::_anim_duplicate_keys(bool transpose) {
}
void AnimationTrackEditor::_edit_menu_about_to_popup() {
- AnimationPlayer *player = AnimationPlayerEditor::singleton->get_player();
+ AnimationPlayer *player = AnimationPlayerEditor::get_singleton()->get_player();
edit->get_popup()->set_item_disabled(edit->get_popup()->get_item_index(EDIT_APPLY_RESET), !player->can_apply_reset());
}
@@ -5263,7 +5402,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
text += sn[j];
}
- path = NodePath(node->get_path().get_names(), path.get_subnames(), true); //store full path instead for copying
+ path = NodePath(node->get_path().get_names(), path.get_subnames(), true); // Store full path instead for copying.
} else {
text = path;
int sep = text.find(":");
@@ -5273,8 +5412,17 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
}
switch (animation->track_get_type(i)) {
- case Animation::TYPE_TRANSFORM3D:
- text += " (Transform)";
+ case Animation::TYPE_POSITION_3D:
+ text += " (Position)";
+ break;
+ case Animation::TYPE_ROTATION_3D:
+ text += " (Rotation)";
+ break;
+ case Animation::TYPE_SCALE_3D:
+ text += " (Scale)";
+ break;
+ case Animation::TYPE_BLEND_SHAPE:
+ text += " (BlendShape)";
break;
case Animation::TYPE_METHOD:
text += " (Methods)";
@@ -5390,8 +5538,8 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
float len = -1e20;
float pivot = 0;
- for (Map<SelectedKey, KeyInfo>::Element *E = selection.front(); E; E = E->next()) {
- float t = animation->track_get_key_time(E->key().track, E->key().key);
+ for (const KeyValue<SelectedKey, KeyInfo> &E : selection) {
+ float t = animation->track_get_key_time(E.key.track, E.key.key);
if (t < from_t) {
from_t = t;
}
@@ -5417,11 +5565,11 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
List<_AnimMoveRestore> to_restore;
- // 1-remove the keys
+ // 1 - Remove the keys.
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
undo_redo->add_do_method(animation.ptr(), "track_remove_key", E->key().track, E->key().key);
}
- // 2- remove overlapped keys
+ // 2 - Remove overlapped keys.
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
float newtime = (E->get().pos - from_t) * s + from_t;
int idx = animation->track_find_key(E->key().track, newtime, true);
@@ -5432,7 +5580,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
sk.key = idx;
sk.track = E->key().track;
if (selection.has(sk)) {
- continue; //already in selection, don't save
+ continue; // Already in selection, don't save.
}
undo_redo->add_do_method(animation.ptr(), "track_remove_key_at_time", E->key().track, newtime);
@@ -5447,24 +5595,24 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
}
#define _NEW_POS(m_ofs) (((s > 0) ? m_ofs : from_t + (len - (m_ofs - from_t))) - pivot) * ABS(s) + from_t
- // 3-move the keys (re insert them)
+ // 3 - Move the keys (re insert them).
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
float newpos = _NEW_POS(E->get().pos);
undo_redo->add_do_method(animation.ptr(), "track_insert_key", E->key().track, newpos, animation->track_get_key_value(E->key().track, E->key().key), animation->track_get_key_transition(E->key().track, E->key().key));
}
- // 4-(undo) remove inserted keys
+ // 4 - (Undo) Remove inserted keys.
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
float newpos = _NEW_POS(E->get().pos);
undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", E->key().track, newpos);
}
- // 5-(undo) reinsert keys
+ // 5 - (Undo) Reinsert keys.
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
undo_redo->add_undo_method(animation.ptr(), "track_insert_key", E->key().track, E->get().pos, animation->track_get_key_value(E->key().track, E->key().key), animation->track_get_key_transition(E->key().track, E->key().key));
}
- // 6-(undo) reinsert overlapped keys
+ // 6 - (Undo) Reinsert overlapped keys.
for (_AnimMoveRestore &amr : to_restore) {
undo_redo->add_undo_method(animation.ptr(), "track_insert_key", amr.track, amr.time, amr.key, amr.transition);
}
@@ -5472,7 +5620,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
undo_redo->add_do_method(this, "_clear_selection_for_anim", animation);
undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
- // 7-reselect
+ // 7-reselect.
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
float oldpos = E->get().pos;
float newpos = _NEW_POS(oldpos);
@@ -5524,7 +5672,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
goto_prev_step(false);
} break;
case EDIT_APPLY_RESET: {
- AnimationPlayerEditor::singleton->get_player()->apply_reset(true);
+ AnimationPlayerEditor::get_singleton()->get_player()->apply_reset(true);
} break;
case EDIT_OPTIMIZE_ANIMATION: {
@@ -5544,9 +5692,9 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
case EDIT_CLEAN_UP_ANIMATION_CONFIRM: {
if (cleanup_all->is_pressed()) {
List<StringName> names;
- AnimationPlayerEditor::singleton->get_player()->get_animation_list(&names);
+ AnimationPlayerEditor::get_singleton()->get_player()->get_animation_list(&names);
for (const StringName &E : names) {
- _cleanup_animation(AnimationPlayerEditor::singleton->get_player()->get_animation(E));
+ _cleanup_animation(AnimationPlayerEditor::get_singleton()->get_player()->get_animation(E));
}
} else {
_cleanup_animation(animation);
@@ -5621,7 +5769,7 @@ bool AnimationTrackEditor::is_grouping_tracks() {
void AnimationTrackEditor::_selection_changed() {
if (selected_filter->is_pressed()) {
- _update_tracks(); //needs updatin
+ _update_tracks(); // Needs updatin.
} else {
for (int i = 0; i < track_edits.size(); i++) {
track_edits[i]->update();
@@ -5690,7 +5838,6 @@ void AnimationTrackEditor::_bind_methods() {
ClassDB::bind_method("_animation_update", &AnimationTrackEditor::_animation_update);
ClassDB::bind_method("_track_grab_focus", &AnimationTrackEditor::_track_grab_focus);
ClassDB::bind_method("_update_tracks", &AnimationTrackEditor::_update_tracks);
- ClassDB::bind_method("_insert_delay", &AnimationTrackEditor::_insert_delay);
ClassDB::bind_method("_clear_selection_for_anim", &AnimationTrackEditor::_clear_selection_for_anim);
ClassDB::bind_method("_select_at_anim", &AnimationTrackEditor::_select_at_anim);
@@ -5761,7 +5908,7 @@ void AnimationTrackEditor::_pick_track_filter_input(const Ref<InputEvent> &p_ie)
case KEY_DOWN:
case KEY_PAGEUP:
case KEY_PAGEDOWN: {
- pick_track->get_scene_tree()->get_scene_tree()->call("_gui_input", k);
+ pick_track->get_scene_tree()->get_scene_tree()->gui_input(k);
pick_track->get_filter_line_edit()->accept_event();
} break;
default:
@@ -5776,7 +5923,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
undo_redo = EditorNode::get_singleton()->get_undo_redo();
main_panel = memnew(PanelContainer);
- main_panel->set_focus_mode(FOCUS_ALL); // allow panel to have focus so that shortcuts work as expected.
+ main_panel->set_focus_mode(FOCUS_ALL); // Allow panel to have focus so that shortcuts work as expected.
add_child(main_panel);
main_panel->set_v_size_flags(SIZE_EXPAND_FILL);
HBoxContainer *timeline_scroll = memnew(HBoxContainer);
@@ -5812,7 +5959,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
scroll->set_v_size_flags(SIZE_EXPAND_FILL);
VScrollBar *sb = scroll->get_v_scrollbar();
scroll->remove_child(sb);
- timeline_scroll->add_child(sb); //move here so timeline and tracks are always aligned
+ timeline_scroll->add_child(sb); // Move here so timeline and tracks are always aligned.
scroll->connect("gui_input", callable_mp(this, &AnimationTrackEditor::_scroll_input));
bezier_edit = memnew(AnimationBezierTrackEdit);
@@ -5853,7 +6000,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
selected_filter = memnew(Button);
selected_filter->set_flat(true);
- selected_filter->connect("pressed", callable_mp(this, &AnimationTrackEditor::_view_group_toggle)); //same function works the same
+ selected_filter->connect("pressed", callable_mp(this, &AnimationTrackEditor::_view_group_toggle)); // Same function works the same.
selected_filter->set_toggle_mode(true);
selected_filter->set_tooltip(TTR("Only show tracks from nodes selected in tree."));
@@ -5954,9 +6101,6 @@ AnimationTrackEditor::AnimationTrackEditor() {
add_child(method_selector);
method_selector->connect("selected", callable_mp(this, &AnimationTrackEditor::_add_method_key));
- inserting = false;
- insert_query = false;
- insert_frame = 0;
insert_queue = false;
insert_confirm = memnew(ConfirmationDialog);
@@ -5989,13 +6133,13 @@ AnimationTrackEditor::AnimationTrackEditor() {
box_selection->connect("draw", callable_mp(this, &AnimationTrackEditor::_box_selection_draw));
box_selecting = false;
- //default plugins
+ // Default Plugins.
Ref<AnimationTrackEditDefaultPlugin> def_plugin;
def_plugin.instantiate();
add_track_edit_plugin(def_plugin);
- //dialogs
+ // Dialogs.
optimize_dialog = memnew(ConfirmationDialog);
add_child(optimize_dialog);