summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
authorSilc Renew <tokage.it.lab@gmail.com>2023-01-21 14:51:03 +0900
committerSilc Renew <tokage.it.lab@gmail.com>2023-01-26 12:40:19 +0900
commit17bf6238fc3dca1b2ec6c1a0bbe11d5e7d7a8113 (patch)
tree3b4bb69db09279c346c203687954b3296a9570e6 /editor
parent35c37ce4ce5d1559ae4548ebb2c0c7286cb90a3d (diff)
Make AnimatedSprite's playback API consistent with AnimationPlayer
Diffstat (limited to 'editor')
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp10
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp500
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.h43
-rw-r--r--editor/project_converter_3_to_4.cpp2
4 files changed, 444 insertions, 111 deletions
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 06241d07cf..30e06bfcf4 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -245,7 +245,7 @@ void AnimationPlayerEditor::_play_bw_pressed() {
player->stop(); //so it won't blend with itself
}
ERR_FAIL_COND_EDMSG(!_validate_tracks(player->get_animation(current)), "Animation tracks may have any invalid key, abort playing.");
- player->play(current, -1, -1, true);
+ player->play_backwards(current);
}
//unstop
@@ -262,7 +262,7 @@ void AnimationPlayerEditor::_play_bw_from_pressed() {
}
ERR_FAIL_COND_EDMSG(!_validate_tracks(player->get_animation(current)), "Animation tracks may have any invalid key, abort playing.");
player->seek(time);
- player->play(current, -1, -1, true);
+ player->play_backwards(current);
}
//unstop
@@ -452,7 +452,9 @@ float AnimationPlayerEditor::_get_editor_step() const {
}
void AnimationPlayerEditor::_animation_name_edited() {
- player->stop();
+ if (player->is_playing()) {
+ player->stop();
+ }
String new_name = name->get_text();
if (!AnimationLibrary::is_valid_animation_name(new_name)) {
@@ -1675,7 +1677,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug
stop = memnew(Button);
stop->set_flat(true);
hb->add_child(stop);
- stop->set_tooltip_text(TTR("Stop animation playback. (S)"));
+ stop->set_tooltip_text(TTR("Pause/stop animation playback. (S)"));
play = memnew(Button);
play->set_flat(true);
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index 74c9286325..a7b32ce0c3 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -40,7 +40,6 @@
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/scene_tree_dock.h"
-#include "scene/3d/sprite_3d.h"
#include "scene/gui/center_container.h"
#include "scene/gui/margin_container.h"
#include "scene/gui/panel_container.h"
@@ -252,8 +251,7 @@ void SpriteFramesEditor::_sheet_add_frames() {
const Size2i separation = _get_separation();
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Add Frame"));
-
+ undo_redo->create_action(TTR("Add Frame"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
int fc = frames->get_frame_count(edited_anim);
for (const int &E : frames_selected) {
@@ -265,8 +263,8 @@ void SpriteFramesEditor::_sheet_add_frames() {
at->set_atlas(split_sheet_preview->get_texture());
at->set_region(Rect2(offset + frame_coords * (frame_size + separation), frame_size));
- undo_redo->add_do_method(frames, "add_frame", edited_anim, at, 1.0, -1);
- undo_redo->add_undo_method(frames, "remove_frame", edited_anim, fc);
+ undo_redo->add_do_method(frames.ptr(), "add_frame", edited_anim, at, 1.0, -1);
+ undo_redo->add_undo_method(frames.ptr(), "remove_frame", edited_anim, fc);
}
undo_redo->add_do_method(this, "_update_library");
@@ -415,8 +413,23 @@ void SpriteFramesEditor::_prepare_sprite_sheet(const String &p_file) {
void SpriteFramesEditor::_notification(int p_what) {
switch (p_what) {
- case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_ENTER_TREE: {
+ get_tree()->connect("node_removed", callable_mp(this, &SpriteFramesEditor::_node_removed));
+
+ [[fallthrough]];
+ }
case NOTIFICATION_THEME_CHANGED: {
+ autoplay_icon = get_theme_icon(SNAME("AutoPlay"), SNAME("EditorIcons"));
+ stop_icon = get_theme_icon(SNAME("Stop"), SNAME("EditorIcons"));
+ pause_icon = get_theme_icon(SNAME("Pause"), SNAME("EditorIcons"));
+ _update_stop_icon();
+
+ autoplay->set_icon(get_theme_icon(SNAME("AutoPlay"), SNAME("EditorIcons")));
+ play->set_icon(get_theme_icon(SNAME("PlayStart"), SNAME("EditorIcons")));
+ play_from->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons")));
+ play_bw->set_icon(get_theme_icon(SNAME("PlayStartBackwards"), SNAME("EditorIcons")));
+ play_bw_from->set_icon(get_theme_icon(SNAME("PlayBackwards"), SNAME("EditorIcons")));
+
load->set_icon(get_theme_icon(SNAME("Load"), SNAME("EditorIcons")));
load_sheet->set_icon(get_theme_icon(SNAME("SpriteSheet"), SNAME("EditorIcons")));
copy->set_icon(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")));
@@ -441,6 +454,10 @@ void SpriteFramesEditor::_notification(int p_what) {
case NOTIFICATION_READY: {
add_theme_constant_override("autohide", 1); // Fixes the dragger always showing up.
} break;
+
+ case NOTIFICATION_EXIT_TREE: {
+ get_tree()->disconnect("node_removed", callable_mp(this, &SpriteFramesEditor::_node_removed));
+ } break;
}
}
@@ -471,14 +488,14 @@ void SpriteFramesEditor::_file_load_request(const Vector<String> &p_path, int p_
}
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Add Frame"));
+ undo_redo->create_action(TTR("Add Frame"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
int fc = frames->get_frame_count(edited_anim);
int count = 0;
for (const Ref<Texture2D> &E : resources) {
- undo_redo->add_do_method(frames, "add_frame", edited_anim, E, 1.0, p_at_pos == -1 ? -1 : p_at_pos + count);
- undo_redo->add_undo_method(frames, "remove_frame", edited_anim, p_at_pos == -1 ? fc : p_at_pos);
+ undo_redo->add_do_method(frames.ptr(), "add_frame", edited_anim, E, 1.0, p_at_pos == -1 ? -1 : p_at_pos + count);
+ undo_redo->add_undo_method(frames.ptr(), "remove_frame", edited_anim, p_at_pos == -1 ? fc : p_at_pos);
count++;
}
undo_redo->add_do_method(this, "_update_library");
@@ -542,9 +559,9 @@ void SpriteFramesEditor::_paste_pressed() {
}
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Paste Frame"));
- undo_redo->add_do_method(frames, "add_frame", edited_anim, texture, duration);
- undo_redo->add_undo_method(frames, "remove_frame", edited_anim, frames->get_frame_count(edited_anim));
+ undo_redo->create_action(TTR("Paste Frame"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "add_frame", edited_anim, texture, duration);
+ undo_redo->add_undo_method(frames.ptr(), "remove_frame", edited_anim, frames->get_frame_count(edited_anim));
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
undo_redo->commit_action();
@@ -585,9 +602,9 @@ void SpriteFramesEditor::_empty_pressed() {
Ref<Texture2D> texture;
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Add Empty"));
- undo_redo->add_do_method(frames, "add_frame", edited_anim, texture, 1.0, from);
- undo_redo->add_undo_method(frames, "remove_frame", edited_anim, from);
+ undo_redo->create_action(TTR("Add Empty"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "add_frame", edited_anim, texture, 1.0, from);
+ undo_redo->add_undo_method(frames.ptr(), "remove_frame", edited_anim, from);
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
undo_redo->commit_action();
@@ -609,9 +626,9 @@ void SpriteFramesEditor::_empty2_pressed() {
Ref<Texture2D> texture;
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Add Empty"));
- undo_redo->add_do_method(frames, "add_frame", edited_anim, texture, 1.0, from + 1);
- undo_redo->add_undo_method(frames, "remove_frame", edited_anim, from + 1);
+ undo_redo->create_action(TTR("Add Empty"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "add_frame", edited_anim, texture, 1.0, from + 1);
+ undo_redo->add_undo_method(frames.ptr(), "remove_frame", edited_anim, from + 1);
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
undo_redo->commit_action();
@@ -633,11 +650,11 @@ void SpriteFramesEditor::_up_pressed() {
sel -= 1;
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Move Frame"));
- undo_redo->add_do_method(frames, "set_frame", edited_anim, to_move, frames->get_frame_texture(edited_anim, to_move - 1), frames->get_frame_duration(edited_anim, to_move - 1));
- undo_redo->add_do_method(frames, "set_frame", edited_anim, to_move - 1, frames->get_frame_texture(edited_anim, to_move), frames->get_frame_duration(edited_anim, to_move));
- undo_redo->add_undo_method(frames, "set_frame", edited_anim, to_move, frames->get_frame_texture(edited_anim, to_move), frames->get_frame_duration(edited_anim, to_move));
- undo_redo->add_undo_method(frames, "set_frame", edited_anim, to_move - 1, frames->get_frame_texture(edited_anim, to_move - 1), frames->get_frame_duration(edited_anim, to_move - 1));
+ undo_redo->create_action(TTR("Move Frame"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "set_frame", edited_anim, to_move, frames->get_frame_texture(edited_anim, to_move - 1), frames->get_frame_duration(edited_anim, to_move - 1));
+ undo_redo->add_do_method(frames.ptr(), "set_frame", edited_anim, to_move - 1, frames->get_frame_texture(edited_anim, to_move), frames->get_frame_duration(edited_anim, to_move));
+ undo_redo->add_undo_method(frames.ptr(), "set_frame", edited_anim, to_move, frames->get_frame_texture(edited_anim, to_move), frames->get_frame_duration(edited_anim, to_move));
+ undo_redo->add_undo_method(frames.ptr(), "set_frame", edited_anim, to_move - 1, frames->get_frame_texture(edited_anim, to_move - 1), frames->get_frame_duration(edited_anim, to_move - 1));
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
undo_redo->commit_action();
@@ -659,11 +676,11 @@ void SpriteFramesEditor::_down_pressed() {
sel += 1;
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Move Frame"));
- undo_redo->add_do_method(frames, "set_frame", edited_anim, to_move, frames->get_frame_texture(edited_anim, to_move + 1), frames->get_frame_duration(edited_anim, to_move + 1));
- undo_redo->add_do_method(frames, "set_frame", edited_anim, to_move + 1, frames->get_frame_texture(edited_anim, to_move), frames->get_frame_duration(edited_anim, to_move));
- undo_redo->add_undo_method(frames, "set_frame", edited_anim, to_move, frames->get_frame_texture(edited_anim, to_move), frames->get_frame_duration(edited_anim, to_move));
- undo_redo->add_undo_method(frames, "set_frame", edited_anim, to_move + 1, frames->get_frame_texture(edited_anim, to_move + 1), frames->get_frame_duration(edited_anim, to_move + 1));
+ undo_redo->create_action(TTR("Move Frame"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "set_frame", edited_anim, to_move, frames->get_frame_texture(edited_anim, to_move + 1), frames->get_frame_duration(edited_anim, to_move + 1));
+ undo_redo->add_do_method(frames.ptr(), "set_frame", edited_anim, to_move + 1, frames->get_frame_texture(edited_anim, to_move), frames->get_frame_duration(edited_anim, to_move));
+ undo_redo->add_undo_method(frames.ptr(), "set_frame", edited_anim, to_move, frames->get_frame_texture(edited_anim, to_move), frames->get_frame_duration(edited_anim, to_move));
+ undo_redo->add_undo_method(frames.ptr(), "set_frame", edited_anim, to_move + 1, frames->get_frame_texture(edited_anim, to_move + 1), frames->get_frame_duration(edited_anim, to_move + 1));
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
undo_redo->commit_action();
@@ -682,15 +699,15 @@ void SpriteFramesEditor::_delete_pressed() {
}
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Delete Resource"));
- undo_redo->add_do_method(frames, "remove_frame", edited_anim, to_delete);
- undo_redo->add_undo_method(frames, "add_frame", edited_anim, frames->get_frame_texture(edited_anim, to_delete), frames->get_frame_duration(edited_anim, to_delete), to_delete);
+ undo_redo->create_action(TTR("Delete Resource"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "remove_frame", edited_anim, to_delete);
+ undo_redo->add_undo_method(frames.ptr(), "add_frame", edited_anim, frames->get_frame_texture(edited_anim, to_delete), frames->get_frame_duration(edited_anim, to_delete), to_delete);
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
undo_redo->commit_action();
}
-void SpriteFramesEditor::_animation_select() {
+void SpriteFramesEditor::_animation_selected() {
if (updating) {
return;
}
@@ -705,9 +722,42 @@ void SpriteFramesEditor::_animation_select() {
TreeItem *selected = animations->get_selected();
ERR_FAIL_COND(!selected);
edited_anim = selected->get_text(0);
+
+ if (animated_sprite) {
+ sprite_node_updating = true;
+ animated_sprite->call("set_animation", edited_anim);
+ sprite_node_updating = false;
+ }
+
_update_library(true);
}
+void SpriteFramesEditor::_sync_animation() {
+ if (!animated_sprite || sprite_node_updating) {
+ return;
+ }
+ _select_animation(animated_sprite->call("get_animation"), false);
+ _update_stop_icon();
+}
+
+void SpriteFramesEditor::_select_animation(const String &p_name, bool p_update_node) {
+ TreeItem *selected = nullptr;
+ selected = animations->get_item_with_text(p_name);
+ if (!selected) {
+ return;
+ };
+
+ edited_anim = selected->get_text(0);
+
+ if (animated_sprite) {
+ if (p_update_node) {
+ animated_sprite->call("set_animation", edited_anim);
+ }
+ }
+
+ _update_library();
+}
+
static void _find_anim_sprites(Node *p_node, List<Node *> *r_nodes, Ref<SpriteFrames> p_sfames) {
Node *edited = EditorNode::get_singleton()->get_edited_scene();
if (!edited) {
@@ -765,26 +815,48 @@ void SpriteFramesEditor::_animation_name_edited() {
name = new_name + " " + itos(counter);
}
- List<Node *> nodes;
- _find_anim_sprites(EditorNode::get_singleton()->get_edited_scene(), &nodes, Ref<SpriteFrames>(frames));
-
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Rename Animation"));
- undo_redo->add_do_method(frames, "rename_animation", edited_anim, name);
- undo_redo->add_undo_method(frames, "rename_animation", name, edited_anim);
-
- for (Node *E : nodes) {
- String current = E->call("get_animation");
- undo_redo->add_do_method(E, "set_animation", name);
- undo_redo->add_undo_method(E, "set_animation", edited_anim);
- }
-
+ undo_redo->create_action(TTR("Rename Animation"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ _rename_node_animation(undo_redo, false, edited_anim, "", "");
+ undo_redo->add_do_method(frames.ptr(), "rename_animation", edited_anim, name);
+ undo_redo->add_undo_method(frames.ptr(), "rename_animation", name, edited_anim);
+ _rename_node_animation(undo_redo, false, edited_anim, name, name);
+ _rename_node_animation(undo_redo, true, edited_anim, edited_anim, edited_anim);
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
+ undo_redo->commit_action();
- edited_anim = name;
+ _select_animation(name);
+ animations->grab_focus();
+}
- undo_redo->commit_action();
+void SpriteFramesEditor::_rename_node_animation(EditorUndoRedoManager *undo_redo, bool is_undo, const String &p_filter, const String &p_new_animation, const String &p_new_autoplay) {
+ List<Node *> nodes;
+ _find_anim_sprites(EditorNode::get_singleton()->get_edited_scene(), &nodes, Ref<SpriteFrames>(frames));
+
+ if (is_undo) {
+ for (Node *E : nodes) {
+ String current_name = E->call("get_animation");
+ if (current_name == p_filter) {
+ undo_redo->add_undo_method(E, "set_animation", p_new_animation);
+ }
+ String autoplay_name = E->call("get_autoplay");
+ if (autoplay_name == p_filter) {
+ undo_redo->add_undo_method(E, "set_autoplay", p_new_autoplay);
+ }
+ }
+ } else {
+ for (Node *E : nodes) {
+ String current_name = E->call("get_animation");
+ if (current_name == p_filter) {
+ undo_redo->add_do_method(E, "set_animation", p_new_animation);
+ }
+ String autoplay_name = E->call("get_autoplay");
+ if (autoplay_name == p_filter) {
+ undo_redo->add_do_method(E, "set_autoplay", p_new_autoplay);
+ }
+ }
+ }
}
void SpriteFramesEditor::_animation_add() {
@@ -795,25 +867,15 @@ void SpriteFramesEditor::_animation_add() {
name = vformat("new_animation_%d", counter);
}
- List<Node *> nodes;
- _find_anim_sprites(EditorNode::get_singleton()->get_edited_scene(), &nodes, Ref<SpriteFrames>(frames));
-
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Add Animation"));
- undo_redo->add_do_method(frames, "add_animation", name);
- undo_redo->add_undo_method(frames, "remove_animation", name);
+ undo_redo->create_action(TTR("Add Animation"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "add_animation", name);
+ undo_redo->add_undo_method(frames.ptr(), "remove_animation", name);
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
-
- for (Node *E : nodes) {
- String current = E->call("get_animation");
- undo_redo->add_do_method(E, "set_animation", name);
- undo_redo->add_undo_method(E, "set_animation", current);
- }
-
- edited_anim = name;
-
undo_redo->commit_action();
+
+ _select_animation(name);
animations->grab_focus();
}
@@ -831,24 +893,39 @@ void SpriteFramesEditor::_animation_remove() {
}
void SpriteFramesEditor::_animation_remove_confirmed() {
+ StringName new_edited;
+ List<StringName> anim_names;
+ frames->get_animation_list(&anim_names);
+ anim_names.sort_custom<StringName::AlphCompare>();
+ if (anim_names.size() >= 2) {
+ if (edited_anim == anim_names[0]) {
+ new_edited = anim_names[1];
+ } else {
+ new_edited = anim_names[0];
+ }
+ } else {
+ new_edited = StringName();
+ }
+
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Remove Animation"));
- undo_redo->add_do_method(frames, "remove_animation", edited_anim);
- undo_redo->add_undo_method(frames, "add_animation", edited_anim);
- undo_redo->add_undo_method(frames, "set_animation_speed", edited_anim, frames->get_animation_speed(edited_anim));
- undo_redo->add_undo_method(frames, "set_animation_loop", edited_anim, frames->get_animation_loop(edited_anim));
+ undo_redo->create_action(TTR("Remove Animation"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ _rename_node_animation(undo_redo, false, edited_anim, new_edited, "");
+ undo_redo->add_do_method(frames.ptr(), "remove_animation", edited_anim);
+ undo_redo->add_undo_method(frames.ptr(), "add_animation", edited_anim);
+ _rename_node_animation(undo_redo, true, edited_anim, edited_anim, edited_anim);
+ undo_redo->add_undo_method(frames.ptr(), "set_animation_speed", edited_anim, frames->get_animation_speed(edited_anim));
+ undo_redo->add_undo_method(frames.ptr(), "set_animation_loop", edited_anim, frames->get_animation_loop(edited_anim));
int fc = frames->get_frame_count(edited_anim);
for (int i = 0; i < fc; i++) {
Ref<Texture2D> texture = frames->get_frame_texture(edited_anim, i);
float duration = frames->get_frame_duration(edited_anim, i);
- undo_redo->add_undo_method(frames, "add_frame", edited_anim, texture, duration);
+ undo_redo->add_undo_method(frames.ptr(), "add_frame", edited_anim, texture, duration);
}
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
-
- edited_anim = StringName();
-
undo_redo->commit_action();
+
+ _select_animation(new_edited);
}
void SpriteFramesEditor::_animation_search_text_changed(const String &p_text) {
@@ -861,9 +938,9 @@ void SpriteFramesEditor::_animation_loop_changed() {
}
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Change Animation Loop"));
- undo_redo->add_do_method(frames, "set_animation_loop", edited_anim, anim_loop->is_pressed());
- undo_redo->add_undo_method(frames, "set_animation_loop", edited_anim, frames->get_animation_loop(edited_anim));
+ undo_redo->create_action(TTR("Change Animation Loop"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "set_animation_loop", edited_anim, anim_loop->is_pressed());
+ undo_redo->add_undo_method(frames.ptr(), "set_animation_loop", edited_anim, frames->get_animation_loop(edited_anim));
undo_redo->add_do_method(this, "_update_library", true);
undo_redo->add_undo_method(this, "_update_library", true);
undo_redo->commit_action();
@@ -875,9 +952,9 @@ void SpriteFramesEditor::_animation_speed_changed(double p_value) {
}
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Change Animation FPS"), UndoRedo::MERGE_ENDS);
- undo_redo->add_do_method(frames, "set_animation_speed", edited_anim, p_value);
- undo_redo->add_undo_method(frames, "set_animation_speed", edited_anim, frames->get_animation_speed(edited_anim));
+ undo_redo->create_action(TTR("Change Animation FPS"), UndoRedo::MERGE_ENDS, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "set_animation_speed", edited_anim, p_value);
+ undo_redo->add_undo_method(frames.ptr(), "set_animation_speed", edited_anim, frames->get_animation_speed(edited_anim));
undo_redo->add_do_method(this, "_update_library", true);
undo_redo->add_undo_method(this, "_update_library", true);
undo_redo->commit_action();
@@ -927,9 +1004,9 @@ void SpriteFramesEditor::_frame_duration_changed(double p_value) {
float old_duration = frames->get_frame_duration(edited_anim, index);
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- undo_redo->create_action(TTR("Set Frame Duration"));
- undo_redo->add_do_method(frames, "set_frame", edited_anim, index, texture, p_value);
- undo_redo->add_undo_method(frames, "set_frame", edited_anim, index, texture, old_duration);
+ undo_redo->create_action(TTR("Set Frame Duration"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "set_frame", edited_anim, index, texture, p_value);
+ undo_redo->add_undo_method(frames.ptr(), "set_frame", edited_anim, index, texture, old_duration);
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
undo_redo->commit_action();
@@ -968,6 +1045,10 @@ void SpriteFramesEditor::_zoom_reset() {
}
void SpriteFramesEditor::_update_library(bool p_skip_selector) {
+ if (frames.is_null()) {
+ return;
+ }
+
updating = true;
frame_duration->set_value(1.0); // Default.
@@ -998,12 +1079,27 @@ void SpriteFramesEditor::_update_library(bool p_skip_selector) {
it->set_text(0, name);
it->set_editable(0, true);
+ if (animated_sprite) {
+ if (name == String(animated_sprite->call("get_autoplay"))) {
+ it->set_icon(0, autoplay_icon);
+ }
+ }
+
if (E == edited_anim) {
it->select(0);
}
}
}
+ if (animated_sprite) {
+ String autoplay_name = animated_sprite->call("get_autoplay");
+ if (autoplay_name.is_empty()) {
+ autoplay->set_pressed(false);
+ } else {
+ autoplay->set_pressed(String(edited_anim) == autoplay_name);
+ }
+ }
+
frame_list->clear();
if (!frames->has_animation(edited_anim)) {
@@ -1061,20 +1157,25 @@ void SpriteFramesEditor::_update_library(bool p_skip_selector) {
updating = false;
}
-void SpriteFramesEditor::edit(SpriteFrames *p_frames) {
- bool new_read_only_state = false;
- if (p_frames) {
- new_read_only_state = EditorNode::get_singleton()->is_resource_read_only(p_frames);
+void SpriteFramesEditor::_edit() {
+ if (!animated_sprite) {
+ return;
}
+ edit(animated_sprite->call("get_sprite_frames"));
+}
+
+void SpriteFramesEditor::edit(Ref<SpriteFrames> p_frames) {
+ _update_stop_icon();
- if (frames == p_frames && new_read_only_state == read_only) {
+ if (!p_frames.is_valid()) {
+ frames.unref();
return;
}
frames = p_frames;
- read_only = new_read_only_state;
+ read_only = EditorNode::get_singleton()->is_resource_read_only(p_frames);
- if (p_frames) {
+ if (p_frames.is_valid()) {
if (!p_frames->has_animation(edited_anim)) {
List<StringName> anim_names;
frames->get_animation_list(&anim_names);
@@ -1107,6 +1208,8 @@ void SpriteFramesEditor::edit(SpriteFrames *p_frames) {
move_up->set_disabled(read_only);
move_down->set_disabled(read_only);
delete_frame->set_disabled(read_only);
+
+ _fetch_sprite_node(); // Fetch node after set frames.
}
Variant SpriteFramesEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
@@ -1215,18 +1318,18 @@ void SpriteFramesEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
duration = frames->get_frame_duration(edited_anim, from_frame);
}
- undo_redo->create_action(TTR("Move Frame"));
- undo_redo->add_do_method(frames, "remove_frame", edited_anim, from_frame == -1 ? frames->get_frame_count(edited_anim) : from_frame);
- undo_redo->add_do_method(frames, "add_frame", edited_anim, texture, duration, at_pos == -1 ? -1 : at_pos);
- undo_redo->add_undo_method(frames, "remove_frame", edited_anim, at_pos == -1 ? frames->get_frame_count(edited_anim) - 1 : at_pos);
- undo_redo->add_undo_method(frames, "add_frame", edited_anim, texture, duration, from_frame);
+ undo_redo->create_action(TTR("Move Frame"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "remove_frame", edited_anim, from_frame == -1 ? frames->get_frame_count(edited_anim) : from_frame);
+ undo_redo->add_do_method(frames.ptr(), "add_frame", edited_anim, texture, duration, at_pos == -1 ? -1 : at_pos);
+ undo_redo->add_undo_method(frames.ptr(), "remove_frame", edited_anim, at_pos == -1 ? frames->get_frame_count(edited_anim) - 1 : at_pos);
+ undo_redo->add_undo_method(frames.ptr(), "add_frame", edited_anim, texture, duration, from_frame);
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
undo_redo->commit_action();
} else {
- undo_redo->create_action(TTR("Add Frame"));
- undo_redo->add_do_method(frames, "add_frame", edited_anim, texture, 1.0, at_pos == -1 ? -1 : at_pos);
- undo_redo->add_undo_method(frames, "remove_frame", edited_anim, at_pos == -1 ? frames->get_frame_count(edited_anim) : at_pos);
+ undo_redo->create_action(TTR("Add Frame"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ undo_redo->add_do_method(frames.ptr(), "add_frame", edited_anim, texture, 1.0, at_pos == -1 ? -1 : at_pos);
+ undo_redo->add_undo_method(frames.ptr(), "remove_frame", edited_anim, at_pos == -1 ? frames->get_frame_count(edited_anim) : at_pos);
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
undo_redo->commit_action();
@@ -1245,10 +1348,156 @@ void SpriteFramesEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
}
}
+void SpriteFramesEditor::_update_stop_icon() {
+ bool is_playing = false;
+ if (animated_sprite) {
+ is_playing = animated_sprite->call("is_playing");
+ }
+ if (is_playing) {
+ stop->set_icon(pause_icon);
+ } else {
+ stop->set_icon(stop_icon);
+ }
+}
+
+void SpriteFramesEditor::_remove_sprite_node() {
+ if (!animated_sprite) {
+ return;
+ }
+ if (animated_sprite->is_connected("sprite_frames_changed", callable_mp(this, &SpriteFramesEditor::_edit))) {
+ animated_sprite->disconnect("sprite_frames_changed", callable_mp(this, &SpriteFramesEditor::_edit));
+ }
+ if (animated_sprite->is_connected("animation_changed", callable_mp(this, &SpriteFramesEditor::_sync_animation))) {
+ animated_sprite->disconnect("animation_changed", callable_mp(this, &SpriteFramesEditor::_sync_animation));
+ }
+ if (animated_sprite->is_connected("animation_finished", callable_mp(this, &SpriteFramesEditor::_update_stop_icon))) {
+ animated_sprite->disconnect("animation_finished", callable_mp(this, &SpriteFramesEditor::_update_stop_icon));
+ }
+ animated_sprite = nullptr;
+}
+
+void SpriteFramesEditor::_fetch_sprite_node() {
+ Node *selected = nullptr;
+ EditorSelection *editor_selection = EditorNode::get_singleton()->get_editor_selection();
+ if (editor_selection->get_selected_node_list().size() == 1) {
+ selected = editor_selection->get_selected_node_list()[0];
+ }
+
+ bool show_node_edit = false;
+ AnimatedSprite2D *as2d = Object::cast_to<AnimatedSprite2D>(selected);
+ AnimatedSprite3D *as3d = Object::cast_to<AnimatedSprite3D>(selected);
+ if (as2d || as3d) {
+ if (frames != selected->call("get_sprite_frames")) {
+ _remove_sprite_node();
+ } else {
+ animated_sprite = selected;
+ if (!animated_sprite->is_connected("sprite_frames_changed", callable_mp(this, &SpriteFramesEditor::_edit))) {
+ animated_sprite->connect("sprite_frames_changed", callable_mp(this, &SpriteFramesEditor::_edit));
+ }
+ if (!animated_sprite->is_connected("animation_changed", callable_mp(this, &SpriteFramesEditor::_sync_animation))) {
+ animated_sprite->connect("animation_changed", callable_mp(this, &SpriteFramesEditor::_sync_animation), CONNECT_DEFERRED);
+ }
+ if (!animated_sprite->is_connected("animation_finished", callable_mp(this, &SpriteFramesEditor::_update_stop_icon))) {
+ animated_sprite->connect("animation_finished", callable_mp(this, &SpriteFramesEditor::_update_stop_icon));
+ }
+ show_node_edit = true;
+ }
+ } else {
+ _remove_sprite_node();
+ }
+
+ if (show_node_edit) {
+ _sync_animation();
+ autoplay_container->show();
+ playback_container->show();
+ } else {
+ _update_library(); // To init autoplay icon.
+ autoplay_container->hide();
+ playback_container->hide();
+ }
+}
+
+void SpriteFramesEditor::_play_pressed() {
+ if (animated_sprite) {
+ animated_sprite->call("stop");
+ animated_sprite->call("play", animated_sprite->call("get_animation"));
+ }
+ _update_stop_icon();
+}
+
+void SpriteFramesEditor::_play_from_pressed() {
+ if (animated_sprite) {
+ animated_sprite->call("play", animated_sprite->call("get_animation"));
+ }
+ _update_stop_icon();
+}
+
+void SpriteFramesEditor::_play_bw_pressed() {
+ if (animated_sprite) {
+ animated_sprite->call("stop");
+ animated_sprite->call("play_backwards", animated_sprite->call("get_animation"));
+ }
+ _update_stop_icon();
+}
+
+void SpriteFramesEditor::_play_bw_from_pressed() {
+ if (animated_sprite) {
+ animated_sprite->call("play_backwards", animated_sprite->call("get_animation"));
+ }
+ _update_stop_icon();
+}
+
+void SpriteFramesEditor::_stop_pressed() {
+ if (animated_sprite) {
+ if (animated_sprite->call("is_playing")) {
+ animated_sprite->call("pause");
+ } else {
+ animated_sprite->call("stop");
+ }
+ }
+ _update_stop_icon();
+}
+
+void SpriteFramesEditor::_autoplay_pressed() {
+ if (updating) {
+ return;
+ }
+
+ if (animated_sprite) {
+ EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
+ undo_redo->create_action(TTR("Toggle Autoplay"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
+ String current = animated_sprite->call("get_animation");
+ String current_auto = animated_sprite->call("get_autoplay");
+ if (current == current_auto) {
+ //unset
+ undo_redo->add_do_method(animated_sprite, "set_autoplay", "");
+ undo_redo->add_undo_method(animated_sprite, "set_autoplay", current_auto);
+ } else {
+ //set
+ undo_redo->add_do_method(animated_sprite, "set_autoplay", current);
+ undo_redo->add_undo_method(animated_sprite, "set_autoplay", current_auto);
+ }
+ undo_redo->add_do_method(this, "_update_library");
+ undo_redo->add_undo_method(this, "_update_library");
+ undo_redo->commit_action();
+ }
+
+ _update_library();
+}
+
void SpriteFramesEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update_library", "skipsel"), &SpriteFramesEditor::_update_library, DEFVAL(false));
}
+void SpriteFramesEditor::_node_removed(Node *p_node) {
+ if (animated_sprite) {
+ if (animated_sprite != p_node) {
+ return;
+ }
+ _remove_sprite_node();
+ }
+}
+
SpriteFramesEditor::SpriteFramesEditor() {
VBoxContainer *vbc_animlist = memnew(VBoxContainer);
add_child(vbc_animlist);
@@ -1272,8 +1521,16 @@ SpriteFramesEditor::SpriteFramesEditor() {
delete_anim->set_disabled(true);
delete_anim->connect("pressed", callable_mp(this, &SpriteFramesEditor::_animation_remove));
+ autoplay_container = memnew(HBoxContainer);
+ hbc_animlist->add_child(autoplay_container);
+ autoplay_container->add_child(memnew(VSeparator));
+ autoplay = memnew(Button);
+ autoplay->set_flat(true);
+ autoplay->set_tooltip_text(TTR("Autoplay on Load"));
+ autoplay_container->add_child(autoplay);
+
anim_search_box = memnew(LineEdit);
- hbc_animlist->add_child(anim_search_box);
+ sub_vb->add_child(anim_search_box);
anim_search_box->set_h_size_flags(SIZE_EXPAND_FILL);
anim_search_box->set_placeholder(TTR("Filter Animations"));
anim_search_box->set_clear_button_enabled(true);
@@ -1283,7 +1540,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
sub_vb->add_child(animations);
animations->set_v_size_flags(SIZE_EXPAND_FILL);
animations->set_hide_root(true);
- animations->connect("cell_selected", callable_mp(this, &SpriteFramesEditor::_animation_select));
+ animations->connect("cell_selected", callable_mp(this, &SpriteFramesEditor::_animation_selected));
animations->connect("item_edited", callable_mp(this, &SpriteFramesEditor::_animation_name_edited));
animations->set_allow_reselect(true);
@@ -1319,6 +1576,44 @@ SpriteFramesEditor::SpriteFramesEditor() {
HBoxContainer *hbc = memnew(HBoxContainer);
sub_vb->add_child(hbc);
+ playback_container = memnew(HBoxContainer);
+ hbc->add_child(playback_container);
+
+ play_bw_from = memnew(Button);
+ play_bw_from->set_flat(true);
+ play_bw_from->set_tooltip_text(TTR("Play selected animation backwards from current pos. (A)"));
+ playback_container->add_child(play_bw_from);
+
+ play_bw = memnew(Button);
+ play_bw->set_flat(true);
+ play_bw->set_tooltip_text(TTR("Play selected animation backwards from end. (Shift+A)"));
+ playback_container->add_child(play_bw);
+
+ stop = memnew(Button);
+ stop->set_flat(true);
+ stop->set_tooltip_text(TTR("Pause/stop animation playback. (S)"));
+ playback_container->add_child(stop);
+
+ play = memnew(Button);
+ play->set_flat(true);
+ play->set_tooltip_text(TTR("Play selected animation from start. (Shift+D)"));
+ playback_container->add_child(play);
+
+ play_from = memnew(Button);
+ play_from->set_flat(true);
+ play_from->set_tooltip_text(TTR("Play selected animation from current pos. (D)"));
+ playback_container->add_child(play_from);
+
+ playback_container->add_child(memnew(VSeparator));
+
+ autoplay->connect("pressed", callable_mp(this, &SpriteFramesEditor::_autoplay_pressed));
+ autoplay->set_toggle_mode(true);
+ play->connect("pressed", callable_mp(this, &SpriteFramesEditor::_play_pressed));
+ play_from->connect("pressed", callable_mp(this, &SpriteFramesEditor::_play_from_pressed));
+ play_bw->connect("pressed", callable_mp(this, &SpriteFramesEditor::_play_bw_pressed));
+ play_bw_from->connect("pressed", callable_mp(this, &SpriteFramesEditor::_play_bw_from_pressed));
+ stop->connect("pressed", callable_mp(this, &SpriteFramesEditor::_stop_pressed));
+
load = memnew(Button);
load->set_flat(true);
hbc->add_child(load);
@@ -1369,9 +1664,10 @@ SpriteFramesEditor::SpriteFramesEditor() {
frame_duration = memnew(SpinBox);
frame_duration->set_prefix(String::utf8("×"));
- frame_duration->set_min(0);
+ frame_duration->set_min(SPRITE_FRAME_MINIMUM_DURATION); // Avoid zero div.
frame_duration->set_max(10);
frame_duration->set_step(0.01);
+ frame_duration->set_allow_lesser(false);
frame_duration->set_allow_greater(true);
hbc->add_child(frame_duration);
@@ -1616,16 +1912,16 @@ SpriteFramesEditor::SpriteFramesEditor() {
}
void SpriteFramesEditorPlugin::edit(Object *p_object) {
- SpriteFrames *s;
+ Ref<SpriteFrames> s;
AnimatedSprite2D *animated_sprite = Object::cast_to<AnimatedSprite2D>(p_object);
if (animated_sprite) {
- s = *animated_sprite->get_sprite_frames();
+ s = animated_sprite->get_sprite_frames();
} else {
AnimatedSprite3D *animated_sprite_3d = Object::cast_to<AnimatedSprite3D>(p_object);
if (animated_sprite_3d) {
- s = *animated_sprite_3d->get_sprite_frames();
+ s = animated_sprite_3d->get_sprite_frames();
} else {
- s = Object::cast_to<SpriteFrames>(p_object);
+ s = p_object;
}
}
diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h
index a5e0e54fb8..19ecfb00ed 100644
--- a/editor/plugins/sprite_frames_editor_plugin.h
+++ b/editor/plugins/sprite_frames_editor_plugin.h
@@ -33,6 +33,7 @@
#include "editor/editor_plugin.h"
#include "scene/2d/animated_sprite_2d.h"
+#include "scene/3d/sprite_3d.h"
#include "scene/gui/button.h"
#include "scene/gui/check_button.h"
#include "scene/gui/dialogs.h"
@@ -57,6 +58,9 @@ public:
class SpriteFramesEditor : public HSplitContainer {
GDCLASS(SpriteFramesEditor, HSplitContainer);
+ Ref<SpriteFrames> frames;
+ Node *animated_sprite = nullptr;
+
enum {
PARAM_USE_CURRENT, // Used in callbacks to indicate `dominant_param` should be not updated.
PARAM_FRAME_COUNT, // Keep "Horizontal" & "Vertical" values.
@@ -66,6 +70,17 @@ class SpriteFramesEditor : public HSplitContainer {
bool read_only = false;
+ Ref<Texture2D> autoplay_icon;
+ Ref<Texture2D> stop_icon;
+ Ref<Texture2D> pause_icon;
+
+ HBoxContainer *playback_container = nullptr;
+ Button *stop = nullptr;
+ Button *play = nullptr;
+ Button *play_from = nullptr;
+ Button *play_bw = nullptr;
+ Button *play_bw_from = nullptr;
+
Button *load = nullptr;
Button *load_sheet = nullptr;
Button *delete_frame = nullptr;
@@ -85,6 +100,8 @@ class SpriteFramesEditor : public HSplitContainer {
Button *add_anim = nullptr;
Button *delete_anim = nullptr;
+ HBoxContainer *autoplay_container = nullptr;
+ Button *autoplay = nullptr;
LineEdit *anim_search_box = nullptr;
Tree *animations = nullptr;
@@ -95,8 +112,6 @@ class SpriteFramesEditor : public HSplitContainer {
AcceptDialog *dialog = nullptr;
- SpriteFrames *frames = nullptr;
-
StringName edited_anim;
ConfirmationDialog *delete_dialog = nullptr;
@@ -146,7 +161,15 @@ class SpriteFramesEditor : public HSplitContainer {
void _frame_duration_changed(double p_value);
void _update_library(bool p_skip_selector = false);
- void _animation_select();
+ void _update_stop_icon();
+ void _play_pressed();
+ void _play_from_pressed();
+ void _play_bw_pressed();
+ void _play_bw_from_pressed();
+ void _autoplay_pressed();
+ void _stop_pressed();
+
+ void _animation_selected();
void _animation_name_edited();
void _animation_add();
void _animation_remove();
@@ -183,12 +206,24 @@ class SpriteFramesEditor : public HSplitContainer {
void _sheet_zoom_reset();
void _sheet_select_clear_all_frames();
+ void _edit();
+ void _regist_scene_undo(EditorUndoRedoManager *undo_redo);
+ void _fetch_sprite_node();
+ void _remove_sprite_node();
+
+ bool sprite_node_updating = false;
+ void _sync_animation();
+
+ void _select_animation(const String &p_name, bool p_update_node = true);
+ void _rename_node_animation(EditorUndoRedoManager *undo_redo, bool is_undo, const String &p_filter, const String &p_new_animation, const String &p_new_autoplay);
+
protected:
void _notification(int p_what);
+ void _node_removed(Node *p_node);
static void _bind_methods();
public:
- void edit(SpriteFrames *p_frames);
+ void edit(Ref<SpriteFrames> p_frames);
SpriteFramesEditor();
};
diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp
index 5f61d10f9d..204575f021 100644
--- a/editor/project_converter_3_to_4.cpp
+++ b/editor/project_converter_3_to_4.cpp
@@ -215,7 +215,6 @@ static const char *gdscript_function_renames[][2] = {
{ "_get_configuration_warning", "_get_configuration_warnings" }, // Node
{ "_set_current", "set_current" }, // Camera2D
{ "_set_editor_description", "set_editor_description" }, // Node
- { "_set_playing", "set_playing" }, // AnimatedSprite3D
{ "_toplevel_raise_self", "_top_level_raise_self" }, // CanvasItem
{ "_update_wrap_at", "_update_wrap_at_column" }, // TextEdit
{ "add_animation", "add_animation_library" }, // AnimationPlayer
@@ -1168,6 +1167,7 @@ static const char *gdscript_properties_renames[][2] = {
{ "unit_db", "volume_db" }, // AudioStreamPlayer3D
{ "unit_offset", "progress_ratio" }, // PathFollow2D, PathFollow3D
{ "vseparation", "v_separation" }, // Theme
+ { "frames", "sprite_frames" }, // AnimatedSprite2D, AnimatedSprite3D
{ nullptr, nullptr },
};