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.cpp768
1 files changed, 492 insertions, 276 deletions
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 8fd1f5951e..f61fb6bab3 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -37,6 +37,7 @@
#include "editor/plugins/animation_player_editor_plugin.h"
#include "editor_node.h"
#include "editor_scale.h"
+#include "scene/animation/animation_player.h"
#include "scene/main/window.h"
#include "servers/audio/audio_stream.h"
@@ -44,7 +45,7 @@ class AnimationTrackKeyEdit : public Object {
GDCLASS(AnimationTrackKeyEdit, Object);
public:
- bool setting;
+ bool setting = false;
bool _hide_script_from_inspector() {
return true;
@@ -133,7 +134,7 @@ public:
undo_redo->add_do_method(animation.ptr(), "track_remove_key", track, key);
undo_redo->add_do_method(animation.ptr(), "track_insert_key", track, new_time, val, trans);
undo_redo->add_do_method(this, "_key_ofs_changed", animation, key_ofs, new_time);
- undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", track, new_time);
+ undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", track, new_time);
undo_redo->add_undo_method(animation.ptr(), "track_insert_key", track, key_ofs, val, trans);
undo_redo->add_undo_method(this, "_key_ofs_changed", animation, new_time, key_ofs);
@@ -164,7 +165,7 @@ public:
}
switch (animation->track_get_type(track)) {
- case Animation::TYPE_TRANSFORM: {
+ 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;
@@ -228,9 +229,9 @@ public:
if (Variant::can_convert(args[idx].get_type(), t)) {
Variant old = args[idx];
Variant *ptrs[1] = { &old };
- args.write[idx] = Variant::construct(t, (const Variant **)ptrs, 1, err);
+ Variant::construct(t, args.write[idx], (const Variant **)ptrs, 1, err);
} else {
- args.write[idx] = Variant::construct(t, nullptr, 0, err);
+ Variant::construct(t, args.write[idx], nullptr, 0, err);
}
change_notify_deserved = true;
d_new["args"] = args;
@@ -411,7 +412,7 @@ public:
}
switch (animation->track_get_type(track)) {
- case Animation::TYPE_TRANSFORM: {
+ 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];
@@ -522,9 +523,9 @@ public:
}
switch (animation->track_get_type(track)) {
- case Animation::TYPE_TRANSFORM: {
+ case Animation::TYPE_TRANSFORM3D: {
p_list->push_back(PropertyInfo(Variant::VECTOR3, "location"));
- p_list->push_back(PropertyInfo(Variant::QUAT, "rotation"));
+ p_list->push_back(PropertyInfo(Variant::QUATERNION, "rotation"));
p_list->push_back(PropertyInfo(Variant::VECTOR3, "scale"));
} break;
@@ -622,18 +623,18 @@ public:
}
}
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
Ref<Animation> animation;
- int track;
- float key_ofs;
- Node *root_path;
+ int track = -1;
+ float key_ofs = 0;
+ Node *root_path = nullptr;
PropertyInfo hint;
NodePath base;
- bool use_fps;
+ bool use_fps = false;
void notify_change() {
- _change_notify();
+ notify_property_list_changed();
}
Node *get_root_path() {
@@ -642,15 +643,7 @@ public:
void set_use_fps(bool p_enable) {
use_fps = p_enable;
- _change_notify();
- }
-
- AnimationTrackKeyEdit() {
- use_fps = false;
- key_ofs = 0;
- track = -1;
- setting = false;
- root_path = nullptr;
+ notify_property_list_changed();
}
};
@@ -658,7 +651,7 @@ class AnimationMultiTrackKeyEdit : public Object {
GDCLASS(AnimationMultiTrackKeyEdit, Object);
public:
- bool setting;
+ bool setting = false;
bool _hide_script_from_inspector() {
return true;
@@ -765,7 +758,7 @@ public:
undo_redo->add_do_method(animation.ptr(), "track_remove_key", track, key);
undo_redo->add_do_method(animation.ptr(), "track_insert_key", track, new_time, val, trans);
undo_redo->add_do_method(this, "_key_ofs_changed", animation, key_ofs, new_time);
- undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", track, new_time);
+ undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", track, new_time);
undo_redo->add_undo_method(animation.ptr(), "track_insert_key", track, key_ofs, val, trans);
undo_redo->add_undo_method(this, "_key_ofs_changed", animation, new_time, key_ofs);
@@ -788,7 +781,7 @@ public:
}
switch (animation->track_get_type(track)) {
- case Animation::TYPE_TRANSFORM: {
+ 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;
@@ -846,9 +839,9 @@ public:
if (Variant::can_convert(args[idx].get_type(), t)) {
Variant old = args[idx];
Variant *ptrs[1] = { &old };
- args.write[idx] = Variant::construct(t, (const Variant **)ptrs, 1, err);
+ Variant::construct(t, args.write[idx], (const Variant **)ptrs, 1, err);
} else {
- args.write[idx] = Variant::construct(t, nullptr, 0, err);
+ Variant::construct(t, args.write[idx], nullptr, 0, err);
}
change_notify_deserved = true;
d_new["args"] = args;
@@ -1019,7 +1012,7 @@ public:
}
switch (animation->track_get_type(track)) {
- case Animation::TYPE_TRANSFORM: {
+ 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];
@@ -1169,37 +1162,35 @@ public:
if (same_track_type) {
switch (animation->track_get_type(first_track)) {
- case Animation::TYPE_TRANSFORM: {
+ case Animation::TYPE_TRANSFORM3D: {
p_list->push_back(PropertyInfo(Variant::VECTOR3, "location"));
- p_list->push_back(PropertyInfo(Variant::QUAT, "rotation"));
+ p_list->push_back(PropertyInfo(Variant::QUATERNION, "rotation"));
p_list->push_back(PropertyInfo(Variant::VECTOR3, "scale"));
} break;
case Animation::TYPE_VALUE: {
- if (!same_key_type) {
- break;
- }
-
- Variant v = animation->track_get_key_value(first_track, first_key);
+ if (same_key_type) {
+ Variant v = animation->track_get_key_value(first_track, first_key);
- if (hint.type != Variant::NIL) {
- PropertyInfo pi = hint;
- pi.name = "value";
- p_list->push_back(pi);
- } else {
- PropertyHint hint = PROPERTY_HINT_NONE;
- String hint_string;
-
- if (v.get_type() == Variant::OBJECT) {
- //could actually check the object property if exists..? yes i will!
- Ref<Resource> res = v;
- if (res.is_valid()) {
- hint = PROPERTY_HINT_RESOURCE_TYPE;
- hint_string = res->get_class();
+ if (hint.type != Variant::NIL) {
+ PropertyInfo pi = hint;
+ pi.name = "value";
+ p_list->push_back(pi);
+ } else {
+ PropertyHint hint = PROPERTY_HINT_NONE;
+ String hint_string;
+
+ if (v.get_type() == Variant::OBJECT) {
+ //could actually check the object property if exists..? yes i will!
+ Ref<Resource> res = v;
+ if (res.is_valid()) {
+ hint = PROPERTY_HINT_RESOURCE_TYPE;
+ hint_string = res->get_class();
+ }
}
- }
- if (v.get_type() != Variant::NIL) {
- p_list->push_back(PropertyInfo(v.get_type(), "value", hint, hint_string));
+ if (v.get_type() != Variant::NIL) {
+ p_list->push_back(PropertyInfo(v.get_type(), "value", hint, hint_string));
+ }
}
}
@@ -1276,14 +1267,14 @@ public:
Map<int, NodePath> base_map;
PropertyInfo hint;
- Node *root_path;
+ Node *root_path = nullptr;
- bool use_fps;
+ bool use_fps = false;
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
void notify_change() {
- _change_notify();
+ notify_property_list_changed();
}
Node *get_root_path() {
@@ -1292,13 +1283,7 @@ public:
void set_use_fps(bool p_enable) {
use_fps = p_enable;
- _change_notify();
- }
-
- AnimationMultiTrackKeyEdit() {
- use_fps = false;
- setting = false;
- root_path = nullptr;
+ notify_property_list_changed();
}
};
@@ -1397,6 +1382,7 @@ void AnimationTimelineEdit::_notification(int p_what) {
}
Ref<Font> font = get_theme_font("font", "Label");
+ int font_size = get_theme_font_size("font_size", "Label");
Color color = get_theme_color("font_color", "Label");
int zoomw = key_range;
@@ -1488,10 +1474,10 @@ void AnimationTimelineEdit::_notification(int p_what) {
int decimals = 2;
bool step_found = false;
- const int period_width = font->get_char_size('.').width;
- int max_digit_width = font->get_char_size('0').width;
+ const int period_width = font->get_char_size('.', 0, font_size).width;
+ int max_digit_width = font->get_char_size('0', 0, font_size).width;
for (int i = 1; i <= 9; i++) {
- const int digit_width = font->get_char_size('0' + i).width;
+ const int digit_width = font->get_char_size('0' + i, 0, font_size).width;
max_digit_width = MAX(digit_width, max_digit_width);
}
const int max_sc = int(Math::ceil(zoomw / scale));
@@ -1538,8 +1524,8 @@ void AnimationTimelineEdit::_notification(int p_what) {
if (frame != prev_frame && i >= prev_frame_ofs) {
draw_line(Point2(get_name_limit() + i, 0), Point2(get_name_limit() + i, h), linecolor, Math::round(EDSCALE));
- draw_string(font, Point2(get_name_limit() + i + 3 * EDSCALE, (h - font->get_height()) / 2 + font->get_ascent()).floor(), itos(frame), sub ? color_time_dec : color_time_sec, zoomw - i);
- prev_frame_ofs = i + font->get_string_size(itos(frame)).x + 5 * EDSCALE;
+ draw_string(font, Point2(get_name_limit() + i + 3 * EDSCALE, (h - font->get_height(font_size)) / 2 + font->get_ascent(font_size)).floor(), itos(frame), HALIGN_LEFT, zoomw - i, font_size, sub ? color_time_dec : color_time_sec);
+ prev_frame_ofs = i + font->get_string_size(itos(frame), font_size).x + 5 * EDSCALE;
}
}
}
@@ -1556,7 +1542,7 @@ void AnimationTimelineEdit::_notification(int p_what) {
if ((sc / step) != (prev_sc / step) || (prev_sc < 0 && sc >= 0)) {
int scd = sc < 0 ? prev_sc : sc;
draw_line(Point2(get_name_limit() + i, 0), Point2(get_name_limit() + i, h), linecolor, Math::round(EDSCALE));
- draw_string(font, Point2(get_name_limit() + i + 3, (h - font->get_height()) / 2 + font->get_ascent()).floor(), String::num((scd - (scd % step)) / double(SC_ADJ), decimals), sub ? color_time_dec : color_time_sec, zoomw - i);
+ draw_string(font, Point2(get_name_limit() + i + 3, (h - font->get_height(font_size)) / 2 + font->get_ascent(font_size)).floor(), String::num((scd - (scd % step)) / double(SC_ADJ), decimals), HALIGN_LEFT, zoomw - i, font_size, sub ? color_time_dec : color_time_sec);
}
}
}
@@ -1583,7 +1569,8 @@ void AnimationTimelineEdit::set_animation(const Ref<Animation> &p_animation) {
Size2 AnimationTimelineEdit::get_minimum_size() const {
Size2 ms = add_track->get_minimum_size();
Ref<Font> font = get_theme_font("font", "Label");
- ms.height = MAX(ms.height, font->get_height());
+ int font_size = get_theme_font_size("font_size", "Label");
+ ms.height = MAX(ms.height, font->get_height(font_size));
ms.width = get_buttons_width() + add_track->get_minimum_size().width + get_theme_icon("Hsize", "EditorIcons")->get_width() + 2;
return ms;
}
@@ -1597,6 +1584,10 @@ void AnimationTimelineEdit::set_zoom(Range *p_zoom) {
zoom->connect("value_changed", callable_mp(this, &AnimationTimelineEdit::_zoom_changed));
}
+void AnimationTimelineEdit::set_track_edit(AnimationTrackEdit *p_track_edit) {
+ track_edit = p_track_edit;
+}
+
void AnimationTimelineEdit::set_play_position(float p_pos) {
play_position_pos = p_pos;
play_position->update();
@@ -1652,26 +1643,52 @@ void AnimationTimelineEdit::_play_position_draw() {
}
void AnimationTimelineEdit::_gui_input(const Ref<InputEvent> &p_event) {
- Ref<InputEventMouseButton> mb = p_event;
+ ERR_FAIL_COND(p_event.is_null());
+
+ const Ref<InputEventMouseButton> mb = p_event;
+
+ if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
+ get_zoom()->set_value(get_zoom()->get_value() * 1.05);
+ accept_event();
+ }
+
+ if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
+ get_zoom()->set_value(get_zoom()->get_value() / 1.05);
+ accept_event();
+ }
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && hsize_rect.has_point(mb->get_position())) {
+ if (mb.is_valid() && mb->is_pressed() && mb->is_alt_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
+ if (track_edit) {
+ track_edit->get_editor()->goto_prev_step(true);
+ }
+ accept_event();
+ }
+
+ if (mb.is_valid() && mb->is_pressed() && mb->is_alt_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
+ if (track_edit) {
+ track_edit->get_editor()->goto_next_step(true);
+ }
+ accept_event();
+ }
+
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && hsize_rect.has_point(mb->get_position())) {
dragging_hsize = true;
dragging_hsize_from = mb->get_position().x;
dragging_hsize_at = name_limit;
}
- if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && dragging_hsize) {
+ if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && dragging_hsize) {
dragging_hsize = false;
}
if (mb.is_valid() && mb->get_position().x > get_name_limit() && mb->get_position().x < (get_size().width - get_buttons_width())) {
- if (!panning_timeline && mb->get_button_index() == BUTTON_LEFT) {
+ if (!panning_timeline && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
int x = mb->get_position().x - get_name_limit();
float ofs = x / get_zoom_scale() + get_value();
- emit_signal("timeline_changed", ofs, false);
+ emit_signal("timeline_changed", ofs, false, Input::get_singleton()->is_key_pressed(KEY_ALT));
dragging_timeline = true;
}
- if (!dragging_timeline && mb->get_button_index() == BUTTON_MIDDLE) {
+ if (!dragging_timeline && mb->get_button_index() == MOUSE_BUTTON_MIDDLE) {
int x = mb->get_position().x - get_name_limit();
panning_timeline_from = x / get_zoom_scale();
panning_timeline = true;
@@ -1679,11 +1696,11 @@ void AnimationTimelineEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
}
- if (dragging_timeline && mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && !mb->is_pressed()) {
+ if (dragging_timeline && mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT && !mb->is_pressed()) {
dragging_timeline = false;
}
- if (panning_timeline && mb.is_valid() && mb->get_button_index() == BUTTON_MIDDLE && !mb->is_pressed()) {
+ if (panning_timeline && mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_MIDDLE && !mb->is_pressed()) {
panning_timeline = false;
}
@@ -1707,7 +1724,7 @@ void AnimationTimelineEdit::_gui_input(const Ref<InputEvent> &p_event) {
if (dragging_timeline) {
int x = mm->get_position().x - get_name_limit();
float ofs = x / get_zoom_scale() + get_value();
- emit_signal("timeline_changed", ofs, false);
+ emit_signal("timeline_changed", ofs, false, Input::get_singleton()->is_key_pressed(KEY_ALT));
}
if (panning_timeline) {
int x = mm->get_position().x - get_name_limit();
@@ -1751,12 +1768,13 @@ AnimationTimelineEdit::AnimationTimelineEdit() {
editing = false;
name_limit = 150 * EDSCALE;
zoom = nullptr;
+ track_edit = nullptr;
play_position_pos = 0;
play_position = memnew(Control);
play_position->set_mouse_filter(MOUSE_FILTER_PASS);
add_child(play_position);
- play_position->set_anchors_and_margins_preset(PRESET_WIDE);
+ play_position->set_anchors_and_offsets_preset(PRESET_WIDE);
play_position->connect("draw", callable_mp(this, &AnimationTimelineEdit::_play_position_draw));
add_track = memnew(MenuButton);
@@ -1783,7 +1801,8 @@ AnimationTimelineEdit::AnimationTimelineEdit() {
length->set_tooltip(TTR("Animation length (seconds)"));
length->connect("value_changed", callable_mp(this, &AnimationTimelineEdit::_anim_length_changed));
len_hb->add_child(length);
- loop = memnew(ToolButton);
+ loop = memnew(Button);
+ loop->set_flat(true);
loop->set_tooltip(TTR("Animation Looping"));
loop->connect("pressed", callable_mp(this, &AnimationTimelineEdit::_anim_loop_pressed));
loop->set_toggle_mode(true);
@@ -1797,6 +1816,8 @@ AnimationTimelineEdit::AnimationTimelineEdit() {
panning_timeline = false;
dragging_timeline = false;
dragging_hsize = false;
+
+ set_layout_direction(Control::LAYOUT_DIRECTION_LTR);
}
////////////////////////////////////
@@ -1818,6 +1839,7 @@ void AnimationTrackEdit::_notification(int p_what) {
}
Ref<Font> font = get_theme_font("font", "Label");
+ int font_size = get_theme_font_size("font_size", "Label");
Color color = get_theme_color("font_color", "Label");
Ref<Texture2D> type_icons[6] = {
get_theme_icon("KeyValue", "EditorIcons"),
@@ -1889,9 +1911,9 @@ void AnimationTrackEdit::_notification(int p_what) {
path_rect = Rect2(ofs, 0, limit - ofs - hsep, get_size().height);
- Vector2 string_pos = Point2(ofs, (get_size().height - font->get_height()) / 2 + font->get_ascent());
+ Vector2 string_pos = Point2(ofs, (get_size().height - font->get_height(font_size)) / 2 + font->get_ascent(font_size));
string_pos = string_pos.floor();
- draw_string(font, string_pos, text, text_color, limit - ofs - hsep);
+ draw_string(font, string_pos, text, HALIGN_LEFT, limit - ofs - hsep, font_size, text_color);
draw_line(Point2(limit, 0), Point2(limit, get_size().height), linecolor, Math::round(EDSCALE));
}
@@ -2012,7 +2034,7 @@ 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_TRANSFORM) {
+ if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_TRANSFORM3D) {
draw_texture(icon, interp_mode_rect.position);
}
//make it easier to click
@@ -2022,7 +2044,7 @@ void AnimationTrackEdit::_notification(int p_what) {
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_TRANSFORM) {
+ if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_TRANSFORM3D) {
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 {
@@ -2045,7 +2067,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_TRANSFORM) {
+ if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_TRANSFORM3D) {
draw_texture(icon, loop_mode_rect.position);
}
@@ -2055,7 +2077,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_TRANSFORM) {
+ if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_TRANSFORM3D) {
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 {
@@ -2172,6 +2194,7 @@ void AnimationTrackEdit::draw_key(int p_index, float p_pixels_sec, int p_x, bool
if (animation->track_get_type(track) == Animation::TYPE_METHOD) {
Ref<Font> font = get_theme_font("font", "Label");
+ int font_size = get_theme_font_size("font_size", "Label");
Color color = get_theme_color("font_color", "Label");
color.a = 0.5;
@@ -2196,7 +2219,7 @@ void AnimationTrackEdit::draw_key(int p_index, float p_pixels_sec, int p_x, bool
int limit = MAX(0, p_clip_right - p_x - icon_to_draw->get_width());
if (limit > 0) {
- draw_string(font, Vector2(p_x + icon_to_draw->get_width(), int(get_size().height - font->get_height()) / 2 + font->get_ascent()), text, color, limit);
+ draw_string(font, Vector2(p_x + icon_to_draw->get_width(), int(get_size().height - font->get_height(font_size)) / 2 + font->get_ascent(font_size)), text, HALIGN_LEFT, limit, font_size, color);
}
}
@@ -2215,7 +2238,7 @@ void AnimationTrackEdit::draw_rect_clipped(const Rect2 &p_rect, const Color &p_c
return;
}
Rect2 clip = Rect2(clip_left, 0, clip_right - clip_left, get_size().height);
- draw_rect(clip.clip(p_rect), p_color, p_filled);
+ draw_rect(clip.intersection(p_rect), p_color, p_filled);
}
void AnimationTrackEdit::draw_bg(int p_clip_left, int p_clip_right) {
@@ -2224,10 +2247,6 @@ void AnimationTrackEdit::draw_bg(int p_clip_left, int p_clip_right) {
void AnimationTrackEdit::draw_fg(int p_clip_left, int p_clip_right) {
}
-void AnimationTrackEdit::draw_texture_clipped(const Ref<Texture2D> &p_texture, const Vector2 &p_pos) {
- draw_texture_region_clipped(p_texture, Rect2(p_pos, p_texture->get_size()), Rect2(Point2(), p_texture->get_size()));
-}
-
void AnimationTrackEdit::draw_texture_region_clipped(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_region) {
int clip_left = timeline->get_name_limit();
int clip_right = get_size().width - timeline->get_buttons_width();
@@ -2301,9 +2320,10 @@ NodePath AnimationTrackEdit::get_path() const {
Size2 AnimationTrackEdit::get_minimum_size() const {
Ref<Texture2D> texture = get_theme_icon("Object", "EditorIcons");
Ref<Font> font = get_theme_font("font", "Label");
+ int font_size = get_theme_font_size("font_size", "Label");
int separation = get_theme_constant("vseparation", "ItemList");
- int max_h = MAX(texture->get_height(), font->get_height());
+ int max_h = MAX(texture->get_height(), font->get_height(font_size));
max_h = MAX(max_h, get_key_height());
return Vector2(1, max_h + separation);
@@ -2315,6 +2335,7 @@ void AnimationTrackEdit::set_undo_redo(UndoRedo *p_undo_redo) {
void AnimationTrackEdit::set_timeline(AnimationTimelineEdit *p_timeline) {
timeline = p_timeline;
+ timeline->set_track_edit(this);
timeline->connect("zoom_changed", callable_mp(this, &AnimationTrackEdit::_zoom_changed));
timeline->connect("name_limit_changed", callable_mp(this, &AnimationTrackEdit::_zoom_changed));
}
@@ -2357,7 +2378,7 @@ void AnimationTrackEdit::_zoom_changed() {
play_position->update();
}
-void AnimationTrackEdit::_path_entered(const String &p_text) {
+void AnimationTrackEdit::_path_submitted(const String &p_text) {
undo_redo->create_action(TTR("Change Track Path"));
undo_redo->add_do_method(animation.ptr(), "track_set_path", track, p_text);
undo_redo->add_undo_method(animation.ptr(), "track_set_path", track, animation->track_get_path(track));
@@ -2448,7 +2469,7 @@ 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: {
+ case Animation::TYPE_TRANSFORM3D: {
Dictionary d = animation->track_get_key_value(track, key_idx);
if (d.has("location")) {
text += "Pos: " + String(d["location"]) + "\n";
@@ -2531,6 +2552,8 @@ String AnimationTrackEdit::get_tooltip(const Point2 &p_pos) const {
}
void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
+ ERR_FAIL_COND(p_event.is_null());
+
if (p_event->is_pressed()) {
if (ED_GET_SHORTCUT("animation_editor/duplicate_selection")->is_shortcut(p_event)) {
emit_signal("duplicate_request");
@@ -2549,7 +2572,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
Point2 pos = mb->get_position();
if (check_rect.has_point(pos)) {
@@ -2667,7 +2690,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
if (key_idx != -1) {
- if (mb->get_command() || mb->get_shift()) {
+ if (mb->is_command_pressed() || mb->is_shift_pressed()) {
if (editor->is_key_selected(track, key_idx)) {
emit_signal("deselect_key", key_idx);
} else {
@@ -2692,7 +2715,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
}
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
Point2 pos = mb->get_position();
if (pos.x >= timeline->get_name_limit() && pos.x <= get_size().width - timeline->get_buttons_width()) {
// Can do something with menu too! show insert key.
@@ -2722,15 +2745,15 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
}
- if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && clicking_on_name) {
+ if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT && clicking_on_name) {
if (!path) {
path_popup = memnew(Popup);
path_popup->set_wrap_controls(true);
add_child(path_popup);
path = memnew(LineEdit);
path_popup->add_child(path);
- path->set_anchors_and_margins_preset(PRESET_WIDE);
- path->connect("text_entered", callable_mp(this, &AnimationTrackEdit::_path_entered));
+ path->set_anchors_and_offsets_preset(PRESET_WIDE);
+ path->connect("text_submitted", callable_mp(this, &AnimationTrackEdit::_path_submitted));
}
path->set_text(animation->track_get_path(track));
@@ -2739,12 +2762,12 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
path_popup->set_size(path_rect.size);
path_popup->popup();
path->grab_focus();
- path->set_cursor_position(path->get_text().length());
+ path->set_caret_column(path->get_text().length());
clicking_on_name = false;
}
if (mb.is_valid() && moving_selection_attempt) {
- if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (!mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
moving_selection_attempt = false;
if (moving_selection) {
emit_signal("move_selection_commit");
@@ -2755,7 +2778,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
select_single_attempt = -1;
}
- if (moving_selection && mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) {
+ if (moving_selection && mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_RIGHT) {
moving_selection_attempt = false;
moving_selection = false;
emit_signal("move_selection_cancel");
@@ -2763,7 +2786,7 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
Ref<InputEventMouseMotion> mm = p_event;
- if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT && moving_selection_attempt) {
+ if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT && moving_selection_attempt) {
if (!moving_selection) {
moving_selection = true;
emit_signal("move_selection_begin");
@@ -2786,7 +2809,8 @@ Variant AnimationTrackEdit::get_drag_data(const Point2 &p_point) {
drag_data["group"] = base_path;
drag_data["index"] = track;
- ToolButton *tb = memnew(ToolButton);
+ Button *tb = memnew(Button);
+ tb->set_flat(true);
tb->set_text(path_cache);
tb->set_icon(icon_cache);
set_drag_preview(tb);
@@ -2921,7 +2945,7 @@ void AnimationTrackEdit::append_to_selection(const Rect2 &p_box, bool p_deselect
// Left Border including space occupied by keyframes on t=0.
int limit_start_hitbox = timeline->get_name_limit() - type_icon->get_width();
Rect2 select_rect(limit_start_hitbox, 0, get_size().width - timeline->get_name_limit() - timeline->get_buttons_width(), get_size().height);
- select_rect = select_rect.clip(p_box);
+ select_rect = select_rect.intersection(p_box);
// Select should happen in the opposite order of drawing for more accurate overlap select.
for (int i = animation->track_get_key_count(track) - 1; i >= 0; i--) {
@@ -2981,7 +3005,7 @@ AnimationTrackEdit::AnimationTrackEdit() {
play_position = memnew(Control);
play_position->set_mouse_filter(MOUSE_FILTER_PASS);
add_child(play_position);
- play_position->set_anchors_and_margins_preset(PRESET_WIDE);
+ 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
@@ -3034,6 +3058,7 @@ AnimationTrackEdit *AnimationTrackEditPlugin::create_animation_track_edit(Object
void AnimationTrackEditGroup::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
Ref<Font> font = get_theme_font("font", "Label");
+ int font_size = get_theme_font_size("font_size", "Label");
int separation = get_theme_constant("hseparation", "ItemList");
Color color = get_theme_color("font_color", "Label");
@@ -3057,7 +3082,7 @@ void AnimationTrackEditGroup::_notification(int p_what) {
int ofs = 0;
draw_texture(icon, Point2(ofs, int(get_size().height - icon->get_height()) / 2));
ofs += separation + icon->get_width();
- draw_string(font, Point2(ofs, int(get_size().height - font->get_height()) / 2 + font->get_ascent()), node_name, color, timeline->get_name_limit() - ofs);
+ draw_string(font, Point2(ofs, int(get_size().height - font->get_height(font_size)) / 2 + font->get_ascent(font_size)), node_name, HALIGN_LEFT, timeline->get_name_limit() - ofs, font_size, color);
int px = (-timeline->get_value() + timeline->get_play_position()) * timeline->get_zoom_scale() + timeline->get_name_limit();
@@ -3078,9 +3103,10 @@ void AnimationTrackEditGroup::set_type_and_name(const Ref<Texture2D> &p_type, co
Size2 AnimationTrackEditGroup::get_minimum_size() const {
Ref<Font> font = get_theme_font("font", "Label");
+ int font_size = get_theme_font_size("font_size", "Label");
int separation = get_theme_constant("vseparation", "ItemList");
- return Vector2(0, MAX(font->get_height(), icon->get_height()) + separation);
+ return Vector2(0, MAX(font->get_height(font_size), icon->get_height()) + separation);
}
void AnimationTrackEditGroup::set_timeline(AnimationTimelineEdit *p_timeline) {
@@ -3256,8 +3282,8 @@ void AnimationTrackEditor::_name_limit_changed() {
}
}
-void AnimationTrackEditor::_timeline_changed(float p_new_pos, bool p_drag) {
- emit_signal("timeline_changed", p_new_pos, p_drag);
+void AnimationTrackEditor::_timeline_changed(float p_new_pos, bool p_drag, bool p_timeline_only) {
+ emit_signal("timeline_changed", p_new_pos, p_drag, p_timeline_only);
}
void AnimationTrackEditor::_track_remove_request(int p_track) {
@@ -3306,6 +3332,19 @@ void AnimationTrackEditor::set_anim_pos(float p_pos) {
bezier_edit->set_play_position(p_pos);
}
+static bool track_type_is_resettable(Animation::TrackType p_type) {
+ switch (p_type) {
+ case Animation::TYPE_VALUE:
+ [[fallthrough]];
+ case Animation::TYPE_BEZIER:
+ [[fallthrough]];
+ case Animation::TYPE_TRANSFORM3D:
+ 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
@@ -3326,64 +3365,85 @@ void AnimationTrackEditor::_query_insert(const InsertData &p_id) {
insert_data.push_back(p_id);
+ bool reset_allowed = true;
+ AnimationPlayer *player = AnimationPlayerEditor::singleton->get_player();
+ if (player->has_animation("RESET") && player->get_animation("RESET") == animation) {
+ // Avoid messing with the reset animation itself
+ reset_allowed = false;
+ } else {
+ bool some_resettable = false;
+ for (int i = 0; i < insert_data.size(); i++) {
+ if (track_type_is_resettable(insert_data[i].type)) {
+ some_resettable = true;
+ break;
+ }
+ }
+ if (!some_resettable) {
+ reset_allowed = false;
+ }
+ }
+
if (p_id.track_idx == -1) {
- if (bool(EDITOR_DEF("editors/animation/confirm_insert_track", true))) {
- //potential new key, does not exist
- 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;
- }
+ 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;
- }
+ if (insert_data[i].track_idx == -1) {
+ ++num_tracks;
+ }
- if (insert_data[i].type != Animation::TYPE_VALUE) {
- continue;
- }
+ if (insert_data[i].type != Animation::TYPE_VALUE) {
+ continue;
+ }
- switch (insert_data[i].value.get_type()) {
- case Variant::INT:
- case Variant::FLOAT:
- case Variant::VECTOR2:
- case Variant::VECTOR3:
- case Variant::QUAT:
- case Variant::PLANE:
- case Variant::COLOR: {
- // Valid.
- } break;
- default: {
- all_bezier = false;
- }
+ 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 (bool(EDITOR_DEF("editors/animation/confirm_insert_track", true))) {
+ //potential new key, does not exist
if (num_tracks == 1) {
- insert_confirm_text->set_text(vformat(TTR("Create NEW track for %s and insert key?"), p_id.query));
+ 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));
+ 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->get_ok()->set_text(TTR("Create"));
+ insert_confirm_reset->set_visible(reset_allowed);
+
+ insert_confirm->get_ok_button()->set_text(TTR("Create"));
insert_confirm->popup_centered();
insert_query = true;
} else {
- call_deferred("_insert_delay");
+ call_deferred("_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;
}
} else {
if (!insert_query && !insert_queue) {
- call_deferred("_insert_delay");
+ // Create Beziers wouldn't make sense in this case, where no tracks are being created
+ call_deferred("_insert_delay", reset_allowed && EDITOR_GET("editors/animation/default_create_reset_tracks"), false);
insert_queue = true;
}
}
}
-void AnimationTrackEditor::_insert_delay() {
+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;
@@ -3392,13 +3452,18 @@ void AnimationTrackEditor::_insert_delay() {
undo_redo->create_action(TTR("Anim Insert"));
- int last_track = animation->get_track_count();
+ Ref<Animation> reset_anim;
+ if (p_create_reset) {
+ reset_anim = _create_and_get_reset_animation();
+ }
+
+ TrackIndices next_tracks(animation.ptr(), reset_anim.ptr());
bool advance = false;
while (insert_data.size()) {
if (insert_data.front()->get().advance) {
advance = true;
}
- last_track = _confirm_insert(insert_data.front()->get(), last_track);
+ next_tracks = _confirm_insert(insert_data.front()->get(), next_tracks, p_create_reset, reset_anim, p_create_beziers);
insert_data.pop_front();
}
@@ -3412,7 +3477,7 @@ void AnimationTrackEditor::_insert_delay() {
float pos = timeline->get_play_position();
- pos = Math::stepify(pos + step, step);
+ pos = Math::snapped(pos + step, step);
if (pos > animation->get_length()) {
pos = animation->get_length();
}
@@ -3422,7 +3487,7 @@ void AnimationTrackEditor::_insert_delay() {
insert_queue = false;
}
-void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_sub, const Transform &p_xform) {
+void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_sub, const Transform3D &p_xform) {
if (!keying) {
return;
}
@@ -3442,7 +3507,7 @@ void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_
int track_idx = -1;
for (int i = 0; i < animation->get_track_count(); i++) {
- if (animation->track_get_type(i) != Animation::TYPE_TRANSFORM) {
+ if (animation->track_get_type(i) != Animation::TYPE_TRANSFORM3D) {
continue;
}
if (animation->track_get_path(i) != np) {
@@ -3459,7 +3524,7 @@ void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_
id.path = np;
id.track_idx = track_idx;
id.value = p_xform;
- id.type = Animation::TYPE_TRANSFORM;
+ id.type = Animation::TYPE_TRANSFORM3D;
id.query = "node '" + p_node->get_name() + "'";
id.advance = false;
@@ -3555,7 +3620,7 @@ void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_p
if (track_path == np) {
value = p_value; //all good
} else {
- int sep = track_path.find_last(":");
+ int sep = track_path.rfind(":");
if (sep != -1) {
String base_path = track_path.substr(0, sep);
if (base_path == np) {
@@ -3654,7 +3719,7 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari
value = p_value; //all good
} else {
String tpath = animation->track_get_path(i);
- int index = tpath.find_last(":");
+ int index = tpath.rfind(":");
if (NodePath(tpath.substr(0, index + 1)) == np) {
String subindex = tpath.substr(index + 1, tpath.length() - index);
value = p_value.get(subindex);
@@ -3689,12 +3754,34 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari
}
}
+Ref<Animation> AnimationTrackEditor::_create_and_get_reset_animation() {
+ AnimationPlayer *player = AnimationPlayerEditor::singleton->get_player();
+ if (player->has_animation("RESET")) {
+ return player->get_animation("RESET");
+ } else {
+ Ref<Animation> reset_anim;
+ 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_undo_method(player, "remove_animation", "RESET");
+ undo_redo->add_undo_method(AnimationPlayerEditor::singleton, "_animation_player_changed", player);
+ return reset_anim;
+ }
+}
+
void AnimationTrackEditor::_confirm_insert_list() {
undo_redo->create_action(TTR("Anim Create & Insert"));
- int last_track = animation->get_track_count();
+ bool create_reset = insert_confirm_reset->is_visible() && insert_confirm_reset->is_pressed();
+ Ref<Animation> reset_anim;
+ if (create_reset) {
+ reset_anim = _create_and_get_reset_animation();
+ }
+
+ TrackIndices next_tracks(animation.ptr(), reset_anim.ptr());
while (insert_data.size()) {
- last_track = _confirm_insert(insert_data.front()->get(), last_track, insert_confirm_bezier->is_pressed());
+ next_tracks = _confirm_insert(insert_data.front()->get(), next_tracks, create_reset, reset_anim, insert_confirm_bezier->is_pressed());
insert_data.pop_front();
}
@@ -3724,7 +3811,7 @@ PropertyInfo AnimationTrackEditor::_find_hint_for_track(int p_idx, NodePath &r_b
r_base_path = node->get_path();
}
- if (leftover_path.empty()) {
+ if (leftover_path.is_empty()) {
if (r_current_val) {
if (res.is_valid()) {
*r_current_val = res;
@@ -3749,7 +3836,8 @@ PropertyInfo AnimationTrackEditor::_find_hint_for_track(int p_idx, NodePath &r_b
}
for (int i = 0; i < leftover_path.size() - 1; i++) {
- property_info_base = property_info_base.get_named(leftover_path[i]);
+ bool valid;
+ property_info_base = property_info_base.get_named(leftover_path[i], valid);
}
List<PropertyInfo> pinfo;
@@ -3785,7 +3873,7 @@ static Vector<String> _get_bezier_subindices_for_type(Variant::Type p_type, bool
subindices.push_back(":y");
subindices.push_back(":z");
} break;
- case Variant::QUAT: {
+ case Variant::QUATERNION: {
subindices.push_back(":x");
subindices.push_back(":y");
subindices.push_back(":z");
@@ -3813,11 +3901,7 @@ static Vector<String> _get_bezier_subindices_for_type(Variant::Type p_type, bool
return subindices;
}
-int AnimationTrackEditor::_confirm_insert(InsertData p_id, int p_last_track, bool p_create_beziers) {
- if (p_last_track == -1) {
- p_last_track = animation->get_track_count();
- }
-
+AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertData p_id, TrackIndices p_next_tracks, bool p_create_reset, Ref<Animation> p_reset_anim, bool p_create_beziers) {
bool created = false;
if (p_id.track_idx < 0) {
if (p_create_beziers) {
@@ -3829,10 +3913,10 @@ int AnimationTrackEditor::_confirm_insert(InsertData p_id, int p_last_track, boo
id.type = Animation::TYPE_BEZIER;
id.value = p_id.value.get(subindices[i].substr(1, subindices[i].length()));
id.path = String(p_id.path) + subindices[i];
- _confirm_insert(id, p_last_track + i);
+ p_next_tracks = _confirm_insert(id, p_next_tracks, p_create_reset, p_reset_anim, false);
}
- return p_last_track + subindices.size();
+ return p_next_tracks;
}
}
created = true;
@@ -3855,11 +3939,11 @@ int AnimationTrackEditor::_confirm_insert(InsertData p_id, int p_last_track, boo
h.type == Variant::RECT2 ||
h.type == Variant::VECTOR3 ||
h.type == Variant::AABB ||
- h.type == Variant::QUAT ||
+ h.type == Variant::QUATERNION ||
h.type == Variant::COLOR ||
h.type == Variant::PLANE ||
h.type == Variant::TRANSFORM2D ||
- h.type == Variant::TRANSFORM) {
+ h.type == Variant::TRANSFORM3D) {
update_mode = Animation::UPDATE_CONTINUOUS;
}
@@ -3869,7 +3953,7 @@ int AnimationTrackEditor::_confirm_insert(InsertData p_id, int p_last_track, boo
}
}
- p_id.track_idx = p_last_track;
+ p_id.track_idx = p_next_tracks.normal;
undo_redo->add_do_method(animation.ptr(), "add_track", p_id.type);
undo_redo->add_do_method(animation.ptr(), "track_set_path", p_id.track_idx, p_id.path);
@@ -3889,12 +3973,12 @@ int AnimationTrackEditor::_confirm_insert(InsertData p_id, int p_last_track, boo
value = p_id.value;
} break;
- case Animation::TYPE_TRANSFORM: {
- Transform tr = p_id.value;
+ case Animation::TYPE_TRANSFORM3D: {
+ Transform3D tr = p_id.value;
Dictionary d;
d["location"] = tr.origin;
d["scale"] = tr.basis.get_scale();
- d["rotation"] = Quat(tr.basis);
+ d["rotation"] = Quaternion(tr.basis);
value = d;
} break;
case Animation::TYPE_BEZIER: {
@@ -3921,9 +4005,9 @@ int AnimationTrackEditor::_confirm_insert(InsertData p_id, int p_last_track, boo
// Just remove the track.
undo_redo->add_undo_method(this, "_clear_selection", false);
undo_redo->add_undo_method(animation.ptr(), "remove_track", animation->get_track_count());
- p_last_track++;
+ p_next_tracks.normal++;
} else {
- undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", p_id.track_idx, time);
+ undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", p_id.track_idx, time);
int existing = animation->track_find_key(p_id.track_idx, time, true);
if (existing != -1) {
Variant v = animation->track_get_key_value(p_id.track_idx, existing);
@@ -3932,9 +4016,27 @@ int AnimationTrackEditor::_confirm_insert(InsertData p_id, int p_last_track, boo
}
}
+ if (p_create_reset && track_type_is_resettable(p_id.type)) {
+ bool create_reset_track = true;
+ Animation *reset_anim = p_reset_anim.ptr();
+ for (int i = 0; i < reset_anim->get_track_count(); i++) {
+ if (reset_anim->track_get_path(i) == p_id.path) {
+ create_reset_track = false;
+ break;
+ }
+ }
+ if (create_reset_track) {
+ undo_redo->add_do_method(reset_anim, "add_track", p_id.type);
+ undo_redo->add_do_method(reset_anim, "track_set_path", p_next_tracks.reset, p_id.path);
+ undo_redo->add_do_method(reset_anim, "track_insert_key", p_next_tracks.reset, 0.0f, value);
+ undo_redo->add_undo_method(reset_anim, "remove_track", reset_anim->get_track_count());
+ p_next_tracks.reset++;
+ }
+ }
+
undo_redo->commit_action();
- return p_last_track;
+ return p_next_tracks;
}
void AnimationTrackEditor::show_select_node_warning(bool p_show) {
@@ -3954,7 +4056,7 @@ bool AnimationTrackEditor::is_selection_active() const {
}
bool AnimationTrackEditor::is_snap_enabled() const {
- return snap->is_pressed() ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL);
+ return snap->is_pressed() ^ Input::get_singleton()->is_key_pressed(KEY_CTRL);
}
void AnimationTrackEditor::_update_tracks() {
@@ -4010,8 +4112,8 @@ void AnimationTrackEditor::_update_tracks() {
object = res.ptr();
}
- if (object && !leftover_path.empty()) {
- if (pinfo.name.empty()) {
+ if (object && !leftover_path.is_empty()) {
+ if (pinfo.name.is_empty()) {
pinfo.name = leftover_path[leftover_path.size() - 1];
}
@@ -4213,7 +4315,6 @@ void AnimationTrackEditor::_animation_update() {
_update_step_spinbox();
emit_signal("animation_step_changed", animation->get_step());
emit_signal("animation_len_changed", animation->get_length());
- EditorNode::get_singleton()->get_inspector()->refresh();
animation_changing_awaiting_update = false;
}
@@ -4230,6 +4331,7 @@ void AnimationTrackEditor::_notification(int p_what) {
selected_filter->set_icon(get_theme_icon("AnimationFilter", "EditorIcons"));
imported_anim_warning->set_icon(get_theme_icon("NodeWarning", "EditorIcons"));
main_panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree"));
+ edit->get_popup()->set_item_icon(edit->get_popup()->get_item_index(EDIT_APPLY_RESET), get_theme_icon("Reload", "EditorIcons"));
}
if (p_what == NOTIFICATION_READY) {
@@ -4294,8 +4396,8 @@ 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 && !node->is_class("Node3D")) {
- EditorNode::get_singleton()->show_warning(TTR("Transform tracks only apply to 3D-based nodes."));
+ 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."));
return;
}
@@ -4305,7 +4407,7 @@ 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_TRANSFORM3D:
case Animation::TYPE_METHOD: {
undo_redo->create_action(TTR("Add Track"));
undo_redo->add_do_method(animation.ptr(), "add_track", adding_track_type);
@@ -4320,7 +4422,7 @@ void AnimationTrackEditor::_new_track_node_selected(NodePath p_path) {
filter.push_back(Variant::FLOAT);
filter.push_back(Variant::VECTOR2);
filter.push_back(Variant::VECTOR3);
- filter.push_back(Variant::QUAT);
+ filter.push_back(Variant::QUATERNION);
filter.push_back(Variant::PLANE);
filter.push_back(Variant::COLOR);
@@ -4368,7 +4470,9 @@ void AnimationTrackEditor::_add_track(int p_type) {
return;
}
adding_track_type = p_type;
- pick_track->popup_centered_ratio();
+ pick_track->popup_scenetree_dialog();
+ pick_track->get_filter_line_edit()->clear();
+ pick_track->get_filter_line_edit()->grab_focus();
}
void AnimationTrackEditor::_new_track_property_selected(String p_name) {
@@ -4388,11 +4492,11 @@ void AnimationTrackEditor::_new_track_property_selected(String p_name) {
h.type == Variant::RECT2 ||
h.type == Variant::VECTOR3 ||
h.type == Variant::AABB ||
- h.type == Variant::QUAT ||
+ h.type == Variant::QUATERNION ||
h.type == Variant::COLOR ||
h.type == Variant::PLANE ||
h.type == Variant::TRANSFORM2D ||
- h.type == Variant::TRANSFORM) {
+ h.type == Variant::TRANSFORM3D) {
update_mode = Animation::UPDATE_CONTINUOUS;
}
@@ -4472,7 +4576,7 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) {
}
switch (animation->track_get_type(p_track)) {
- case Animation::TYPE_TRANSFORM: {
+ case Animation::TYPE_TRANSFORM3D: {
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;
@@ -4484,15 +4588,15 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) {
return;
}
- Transform xf = base->get_transform();
+ Transform3D xf = base->get_transform();
Vector3 loc = xf.get_origin();
Vector3 scale = xf.basis.get_scale_local();
- Quat rot = xf.basis;
+ Quaternion 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->add_undo_method(animation.ptr(), "track_remove_key_at_time", p_track, p_ofs);
undo_redo->commit_action();
} break;
@@ -4504,7 +4608,7 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) {
undo_redo->create_action(TTR("Add Track Key"));
undo_redo->add_do_method(animation.ptr(), "track_insert_key", p_track, p_ofs, value);
undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
- undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", p_track, p_ofs);
+ undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", p_track, p_ofs);
undo_redo->commit_action();
} break;
@@ -4535,7 +4639,7 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) {
undo_redo->create_action(TTR("Add Track Key"));
undo_redo->add_do_method(animation.ptr(), "track_insert_key", p_track, p_ofs, arr);
- undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", p_track, p_ofs);
+ undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", p_track, p_ofs);
undo_redo->commit_action();
} break;
@@ -4547,7 +4651,7 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) {
undo_redo->create_action(TTR("Add Track Key"));
undo_redo->add_do_method(animation.ptr(), "track_insert_key", p_track, p_ofs, ak);
- undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", p_track, p_ofs);
+ undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", p_track, p_ofs);
undo_redo->commit_action();
} break;
case Animation::TYPE_ANIMATION: {
@@ -4555,7 +4659,7 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) {
undo_redo->create_action(TTR("Add Track Key"));
undo_redo->add_do_method(animation.ptr(), "track_insert_key", p_track, p_ofs, anim);
- undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", p_track, p_ofs);
+ undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", p_track, p_ofs);
undo_redo->commit_action();
} break;
}
@@ -4584,7 +4688,8 @@ void AnimationTrackEditor::_add_method_key(const String &p_method) {
params.push_back(arg);
} else {
Callable::CallError ce;
- Variant arg = Variant::construct(E->get().arguments[i].type, nullptr, 0, ce);
+ Variant arg;
+ Variant::construct(E->get().arguments[i].type, arg, nullptr, 0, ce);
params.push_back(arg);
}
}
@@ -4592,7 +4697,7 @@ void AnimationTrackEditor::_add_method_key(const String &p_method) {
undo_redo->create_action(TTR("Add Method Track Key"));
undo_redo->add_do_method(animation.ptr(), "track_insert_key", insert_key_from_track_call_track, insert_key_from_track_call_ofs, d);
- undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", insert_key_from_track_call_track, insert_key_from_track_call_ofs);
+ undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", insert_key_from_track_call_track, insert_key_from_track_call_ofs);
undo_redo->commit_action();
return;
@@ -4656,10 +4761,10 @@ void AnimationTrackEditor::_move_selection(float p_offset) {
}
struct _AnimMoveRestore {
- int track;
- float time;
+ int track = 0;
+ float time = 0;
Variant key;
- float transition;
+ float transition = 0;
};
//used for undo/redo
@@ -4802,7 +4907,7 @@ void AnimationTrackEditor::_move_selection_commit() {
continue; //already in selection, don't save
}
- undo_redo->add_do_method(animation.ptr(), "track_remove_key_at_position", E->key().track, newtime);
+ undo_redo->add_do_method(animation.ptr(), "track_remove_key_at_time", E->key().track, newtime);
_AnimMoveRestore amr;
amr.key = animation->track_get_key_value(E->key().track, idx);
@@ -4822,7 +4927,7 @@ void AnimationTrackEditor::_move_selection_commit() {
// 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_position", E->key().track, newpos);
+ undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", E->key().track, newpos);
}
// 5 - (undo) reinsert keys
@@ -4882,17 +4987,27 @@ void AnimationTrackEditor::_box_selection_draw() {
void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && mb->is_pressed() && mb->get_command() && mb->get_button_index() == BUTTON_WHEEL_UP) {
+ if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05);
scroll->accept_event();
}
- if (mb.is_valid() && mb->is_pressed() && mb->get_command() && mb->get_button_index() == BUTTON_WHEEL_DOWN) {
+ if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05);
scroll->accept_event();
}
- if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) {
+ if (mb.is_valid() && mb->is_pressed() && mb->is_alt_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_UP) {
+ goto_prev_step(true);
+ scroll->accept_event();
+ }
+
+ if (mb.is_valid() && mb->is_pressed() && mb->is_alt_pressed() && mb->get_button_index() == MOUSE_BUTTON_WHEEL_DOWN) {
+ goto_next_step(true);
+ scroll->accept_event();
+ }
+
+ if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (mb->is_pressed()) {
box_selecting = true;
box_selecting_from = scroll->get_global_transform().xform(mb->get_position());
@@ -4903,7 +5018,7 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) {
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->get_command());
+ 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
@@ -4920,12 +5035,12 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseMotion> mm = p_event;
- if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_MIDDLE) {
+ if (mm.is_valid() && mm->get_button_mask() & MOUSE_BUTTON_MASK_MIDDLE) {
timeline->set_value(timeline->get_value() - mm->get_relative().x / timeline->get_zoom_scale());
}
if (mm.is_valid() && box_selecting) {
- if (!(mm->get_button_mask() & BUTTON_MASK_LEFT)) {
+ if (!(mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT)) {
//no longer
box_selection->hide();
box_selecting = false;
@@ -4933,7 +5048,7 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) {
}
if (!box_selection->is_visible_in_tree()) {
- if (!mm->get_command() && !mm->get_shift()) {
+ if (!mm->is_command_pressed() && !mm->is_shift_pressed()) {
_clear_selection();
}
box_selection->show();
@@ -4952,16 +5067,11 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) {
Rect2 rect(from, to - from);
Rect2 scroll_rect = Rect2(scroll->get_global_position(), scroll->get_size());
- rect = scroll_rect.clip(rect);
+ rect = scroll_rect.intersection(rect);
box_selection->set_position(rect.position);
box_selection->set_size(rect.size);
box_select_rect = rect;
-
- if (get_local_mouse_position().y < 0) {
- //avoid box selection from going up and lose focus to viewport
- warp_mouse(Vector2(mm->get_position().x, 0));
- }
}
}
@@ -5024,7 +5134,7 @@ void AnimationTrackEditor::_anim_duplicate_keys(bool transpose) {
int existing_idx = animation->track_find_key(dst_track, dst_time, true);
undo_redo->add_do_method(animation.ptr(), "track_insert_key", dst_track, dst_time, animation->track_get_key_value(E->key().track, E->key().key), animation->track_get_key_transition(E->key().track, E->key().key));
- undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", dst_track, dst_time);
+ undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", dst_track, dst_time);
Pair<int, float> p;
p.first = dst_track;
@@ -5066,6 +5176,61 @@ void AnimationTrackEditor::_anim_duplicate_keys(bool transpose) {
}
}
+void AnimationTrackEditor::_edit_menu_about_to_popup() {
+ AnimationPlayer *player = AnimationPlayerEditor::singleton->get_player();
+ edit->get_popup()->set_item_disabled(edit->get_popup()->get_item_index(EDIT_APPLY_RESET), !player->can_apply_reset());
+}
+
+void AnimationTrackEditor::goto_prev_step(bool p_from_mouse_event) {
+ if (animation.is_null()) {
+ return;
+ }
+ float step = animation->get_step();
+ if (step == 0) {
+ step = 1;
+ }
+ if (p_from_mouse_event && Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ // Use more precise snapping when holding Shift.
+ // This is used when scrobbling the timeline using Alt + Mouse wheel.
+ step *= 0.25;
+ }
+
+ float pos = timeline->get_play_position();
+ pos = Math::snapped(pos - step, step);
+ if (pos < 0) {
+ pos = 0;
+ }
+ set_anim_pos(pos);
+ emit_signal("timeline_changed", pos, true);
+}
+
+void AnimationTrackEditor::goto_next_step(bool p_from_mouse_event) {
+ if (animation.is_null()) {
+ return;
+ }
+ float step = animation->get_step();
+ if (step == 0) {
+ step = 1;
+ }
+ if (p_from_mouse_event && Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ // Use more precise snapping when holding Shift.
+ // This is used when scrobbling the timeline using Alt + Mouse wheel.
+ // Do not use precise snapping when using the menu action or keyboard shortcut,
+ // as the default keyboard shortcut requires pressing Shift.
+ step *= 0.25;
+ }
+
+ float pos = timeline->get_play_position();
+
+ pos = Math::snapped(pos + step, step);
+ if (pos > animation->get_length()) {
+ pos = animation->get_length();
+ }
+ set_anim_pos(pos);
+
+ emit_signal("timeline_changed", pos, true);
+}
+
void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
last_menu_track_opt = p_option;
switch (p_option) {
@@ -5105,7 +5270,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
}
switch (animation->track_get_type(i)) {
- case Animation::TYPE_TRANSFORM:
+ case Animation::TYPE_TRANSFORM3D:
text += " (Transform)";
break;
case Animation::TYPE_METHOD:
@@ -5139,7 +5304,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
track_clipboard.clear();
TreeItem *root = track_copy_select->get_root();
if (root) {
- TreeItem *it = root->get_children();
+ TreeItem *it = root->get_first_child();
while (it) {
Dictionary md = it->get_metadata(0);
int idx = md["track_idx"];
@@ -5213,7 +5378,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
scale_dialog->popup_centered(Size2(200, 100) * EDSCALE);
} break;
case EDIT_SCALE_CONFIRM: {
- if (selection.empty()) {
+ if (selection.is_empty()) {
return;
}
@@ -5267,7 +5432,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
continue; //already in selection, don't save
}
- undo_redo->add_do_method(animation.ptr(), "track_remove_key_at_position", E->key().track, newtime);
+ undo_redo->add_do_method(animation.ptr(), "track_remove_key_at_time", E->key().track, newtime);
_AnimMoveRestore amr;
amr.key = animation->track_get_key_value(E->key().track, idx);
@@ -5288,7 +5453,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
// 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_position", E->key().track, newpos);
+ undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", E->key().track, newpos);
}
// 5-(undo) reinsert keys
@@ -5351,41 +5516,13 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
}
} break;
case EDIT_GOTO_NEXT_STEP: {
- if (animation.is_null()) {
- break;
- }
- float step = animation->get_step();
- if (step == 0) {
- step = 1;
- }
-
- float pos = timeline->get_play_position();
-
- pos = Math::stepify(pos + step, step);
- if (pos > animation->get_length()) {
- pos = animation->get_length();
- }
- set_anim_pos(pos);
-
- emit_signal("timeline_changed", pos, true);
-
+ goto_next_step(false);
} break;
case EDIT_GOTO_PREV_STEP: {
- if (animation.is_null()) {
- break;
- }
- float step = animation->get_step();
- if (step == 0) {
- step = 1;
- }
-
- float pos = timeline->get_play_position();
- pos = Math::stepify(pos - step, step);
- if (pos < 0) {
- pos = 0;
- }
- set_anim_pos(pos);
- emit_signal("timeline_changed", pos, true);
+ goto_prev_step(false);
+ } break;
+ case EDIT_APPLY_RESET: {
+ AnimationPlayerEditor::singleton->get_player()->apply_reset(true);
} break;
case EDIT_OPTIMIZE_ANIMATION: {
@@ -5505,9 +5642,9 @@ float AnimationTrackEditor::snap_time(float p_value, bool p_relative) {
if (p_relative) {
double rel = Math::fmod(timeline->get_value(), snap_increment);
- p_value = Math::stepify(p_value + rel, snap_increment) - rel;
+ p_value = Math::snapped(p_value + rel, snap_increment) - rel;
} else {
- p_value = Math::stepify(p_value, snap_increment);
+ p_value = Math::snapped(p_value, snap_increment);
}
}
@@ -5521,7 +5658,7 @@ void AnimationTrackEditor::_show_imported_anim_warning() {
}
void AnimationTrackEditor::_select_all_tracks_for_copy() {
- TreeItem *track = track_copy_select->get_root()->get_children();
+ TreeItem *track = track_copy_select->get_root()->get_first_child();
if (!track) {
return;
}
@@ -5535,7 +5672,7 @@ void AnimationTrackEditor::_select_all_tracks_for_copy() {
track = track->get_next();
}
- track = track_copy_select->get_root()->get_children();
+ track = track_copy_select->get_root()->get_first_child();
while (track) {
track->set_checked(0, !all_selected);
track = track->get_next();
@@ -5560,12 +5697,77 @@ void AnimationTrackEditor::_bind_methods() {
ADD_SIGNAL(MethodInfo("animation_step_changed", PropertyInfo(Variant::FLOAT, "step")));
}
+void AnimationTrackEditor::_pick_track_filter_text_changed(const String &p_newtext) {
+ TreeItem *root_item = pick_track->get_scene_tree()->get_scene_tree()->get_root();
+
+ Vector<Node *> select_candidates;
+ Node *to_select = nullptr;
+
+ String filter = pick_track->get_filter_line_edit()->get_text();
+
+ _pick_track_select_recursive(root_item, filter, select_candidates);
+
+ if (!select_candidates.is_empty()) {
+ for (int i = 0; i < select_candidates.size(); ++i) {
+ Node *candidate = select_candidates[i];
+
+ if (((String)candidate->get_name()).to_lower().begins_with(filter.to_lower())) {
+ to_select = candidate;
+ break;
+ }
+ }
+
+ if (!to_select) {
+ to_select = select_candidates[0];
+ }
+ }
+
+ pick_track->get_scene_tree()->set_selected(to_select);
+}
+
+void AnimationTrackEditor::_pick_track_select_recursive(TreeItem *p_item, const String &p_filter, Vector<Node *> &p_select_candidates) {
+ if (!p_item) {
+ return;
+ }
+
+ NodePath np = p_item->get_metadata(0);
+ Node *node = get_node(np);
+
+ if (p_filter != String() && ((String)node->get_name()).findn(p_filter) != -1) {
+ p_select_candidates.push_back(node);
+ }
+
+ TreeItem *c = p_item->get_first_child();
+
+ while (c) {
+ _pick_track_select_recursive(c, p_filter, p_select_candidates);
+ c = c->get_next();
+ }
+}
+
+void AnimationTrackEditor::_pick_track_filter_input(const Ref<InputEvent> &p_ie) {
+ Ref<InputEventKey> k = p_ie;
+
+ if (k.is_valid()) {
+ switch (k->get_keycode()) {
+ case KEY_UP:
+ case KEY_DOWN:
+ case KEY_PAGEUP:
+ case KEY_PAGEDOWN: {
+ pick_track->get_scene_tree()->get_scene_tree()->call("_gui_input", k);
+ pick_track->get_filter_line_edit()->accept_event();
+ } break;
+ }
+ }
+}
+
AnimationTrackEditor::AnimationTrackEditor() {
root = nullptr;
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.
add_child(main_panel);
main_panel->set_v_size_flags(SIZE_EXPAND_FILL);
HBoxContainer *timeline_scroll = memnew(HBoxContainer);
@@ -5584,7 +5786,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
info_message->set_align(Label::ALIGN_CENTER);
info_message->set_autowrap(true);
info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
- info_message->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
+ info_message->set_anchors_and_offsets_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
main_panel->add_child(info_message);
timeline = memnew(AnimationTimelineEdit);
@@ -5640,14 +5842,16 @@ AnimationTrackEditor::AnimationTrackEditor() {
bottom_hb->add_spacer();
- selected_filter = memnew(ToolButton);
+ 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->set_toggle_mode(true);
selected_filter->set_tooltip(TTR("Only show tracks from nodes selected in tree."));
bottom_hb->add_child(selected_filter);
- view_group = memnew(ToolButton);
+ view_group = memnew(Button);
+ view_group->set_flat(true);
view_group->connect("pressed", callable_mp(this, &AnimationTrackEditor::_view_group_toggle));
view_group->set_toggle_mode(true);
view_group->set_tooltip(TTR("Group tracks by node or display them as plain list."));
@@ -5655,7 +5859,8 @@ AnimationTrackEditor::AnimationTrackEditor() {
bottom_hb->add_child(view_group);
bottom_hb->add_child(memnew(VSeparator));
- snap = memnew(ToolButton);
+ snap = memnew(Button);
+ snap->set_flat(true);
snap->set_text(TTR("Snap:") + " ");
bottom_hb->add_child(snap);
snap->set_disabled(true);
@@ -5696,6 +5901,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
timeline->set_zoom(zoom);
edit = memnew(MenuButton);
+ edit->set_shortcut_context(this);
edit->set_text(TTR("Edit"));
edit->set_flat(false);
edit->set_disabled(true);
@@ -5708,26 +5914,29 @@ AnimationTrackEditor::AnimationTrackEditor() {
edit->get_popup()->add_separator();
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/duplicate_selection", TTR("Duplicate Selection"), KEY_MASK_CMD | KEY_D), EDIT_DUPLICATE_SELECTION);
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/duplicate_selection_transposed", TTR("Duplicate Transposed"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_D), EDIT_DUPLICATE_TRANSPOSED);
- edit->get_popup()->set_item_shortcut_disabled(edit->get_popup()->get_item_index(EDIT_DUPLICATE_SELECTION), true);
- edit->get_popup()->set_item_shortcut_disabled(edit->get_popup()->get_item_index(EDIT_DUPLICATE_TRANSPOSED), true);
edit->get_popup()->add_separator();
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/delete_selection", TTR("Delete Selection"), KEY_DELETE), EDIT_DELETE_SELECTION);
- edit->get_popup()->set_item_shortcut_disabled(edit->get_popup()->get_item_index(EDIT_DELETE_SELECTION), true);
- //this shortcut will be checked from the track itself. so no need to enable it here (will conflict with scenetree dock)
edit->get_popup()->add_separator();
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_next_step", TTR("Go to Next Step"), KEY_MASK_CMD | KEY_RIGHT), EDIT_GOTO_NEXT_STEP);
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_prev_step", TTR("Go to Previous Step"), KEY_MASK_CMD | KEY_LEFT), EDIT_GOTO_PREV_STEP);
edit->get_popup()->add_separator();
+ edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/apply_reset", TTR("Apply Reset")), EDIT_APPLY_RESET);
+ edit->get_popup()->add_separator();
edit->get_popup()->add_item(TTR("Optimize Animation"), EDIT_OPTIMIZE_ANIMATION);
edit->get_popup()->add_item(TTR("Clean-Up Animation"), EDIT_CLEAN_UP_ANIMATION);
edit->get_popup()->connect("id_pressed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed));
+ edit->get_popup()->connect("about_to_popup", callable_mp(this, &AnimationTrackEditor::_edit_menu_about_to_popup));
pick_track = memnew(SceneTreeDialog);
add_child(pick_track);
- pick_track->set_title(TTR("Pick the node that will be animated:"));
+ pick_track->register_text_enter(pick_track->get_filter_line_edit());
+ pick_track->set_title(TTR("Pick a node to animate:"));
pick_track->connect("selected", callable_mp(this, &AnimationTrackEditor::_new_track_node_selected));
+ pick_track->get_filter_line_edit()->connect("text_changed", callable_mp(this, &AnimationTrackEditor::_pick_track_filter_text_changed));
+ pick_track->get_filter_line_edit()->connect("gui_input", callable_mp(this, &AnimationTrackEditor::_pick_track_filter_input));
+
prop_selector = memnew(PropertySelector);
add_child(prop_selector);
prop_selector->connect("selected", callable_mp(this, &AnimationTrackEditor::_new_track_property_selected));
@@ -5748,9 +5957,16 @@ AnimationTrackEditor::AnimationTrackEditor() {
insert_confirm->add_child(icvb);
insert_confirm_text = memnew(Label);
icvb->add_child(insert_confirm_text);
+ HBoxContainer *ichb = memnew(HBoxContainer);
+ icvb->add_child(ichb);
insert_confirm_bezier = memnew(CheckBox);
insert_confirm_bezier->set_text(TTR("Use Bezier Curves"));
- icvb->add_child(insert_confirm_bezier);
+ insert_confirm_bezier->set_pressed(EDITOR_GET("editors/animation/default_create_bezier_tracks"));
+ ichb->add_child(insert_confirm_bezier);
+ insert_confirm_reset = memnew(CheckBox);
+ insert_confirm_reset->set_text(TTR("Create RESET Track(s)", ""));
+ insert_confirm_reset->set_pressed(EDITOR_GET("editors/animation/default_create_reset_tracks"));
+ ichb->add_child(insert_confirm_reset);
keying = false;
moving_selection = false;
key_edit = nullptr;
@@ -5758,7 +5974,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
box_selection = memnew(Control);
add_child(box_selection);
- box_selection->set_as_toplevel(true);
+ box_selection->set_as_top_level(true);
box_selection->set_mouse_filter(MOUSE_FILTER_IGNORE);
box_selection->hide();
box_selection->connect("draw", callable_mp(this, &AnimationTrackEditor::_box_selection_draw));
@@ -5767,7 +5983,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
//default plugins
Ref<AnimationTrackEditDefaultPlugin> def_plugin;
- def_plugin.instance();
+ def_plugin.instantiate();
add_track_edit_plugin(def_plugin);
//dialogs
@@ -5798,8 +6014,8 @@ AnimationTrackEditor::AnimationTrackEditor() {
optimize_max_angle->set_step(0.1);
optimize_max_angle->set_value(22);
- optimize_dialog->get_ok()->set_text(TTR("Optimize"));
- optimize_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_CLEAN_UP_ANIMATION_CONFIRM));
+ optimize_dialog->get_ok_button()->set_text(TTR("Optimize"));
+ optimize_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_OPTIMIZE_ANIMATION_CONFIRM));
//
@@ -5823,7 +6039,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
cleanup_vb->add_child(cleanup_all);
cleanup_dialog->set_title(TTR("Clean-Up Animation(s) (NO UNDO!)"));
- cleanup_dialog->get_ok()->set_text(TTR("Clean-Up"));
+ cleanup_dialog->get_ok_button()->set_text(TTR("Clean-Up"));
cleanup_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_CLEAN_UP_ANIMATION_CONFIRM));
@@ -5843,7 +6059,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
track_copy_dialog = memnew(ConfirmationDialog);
add_child(track_copy_dialog);
track_copy_dialog->set_title(TTR("Select Tracks to Copy"));
- track_copy_dialog->get_ok()->set_text(TTR("Copy"));
+ track_copy_dialog->get_ok_button()->set_text(TTR("Copy"));
VBoxContainer *track_vbox = memnew(VBoxContainer);
track_copy_dialog->add_child(track_vbox);