Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow duplicating animation sprites #67533

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions editor/plugins/sprite_frames_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ void SpriteFramesEditor::_notification(int p_what) {
zoom_reset->set_icon(get_theme_icon(SNAME("ZoomReset"), SNAME("EditorIcons")));
zoom_in->set_icon(get_theme_icon(SNAME("ZoomMore"), SNAME("EditorIcons")));
add_anim->set_icon(get_theme_icon(SNAME("New"), SNAME("EditorIcons")));
duplicate_anim->set_icon(get_theme_icon(SNAME("Duplicate"), SNAME("EditorIcons")));
delete_anim->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
anim_search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
split_sheet_zoom_out->set_icon(get_theme_icon(SNAME("ZoomLess"), SNAME("EditorIcons")));
Expand Down Expand Up @@ -800,6 +801,44 @@ void SpriteFramesEditor::_animation_add() {
animations->grab_focus();
}

void SpriteFramesEditor::_animation_duplicate() {
if (!frames->has_animation(edited_anim)) {
return;
}

int counter = 1;
String name = String(edited_anim) + " " + itos(counter);
while (frames->has_animation(name)) {
counter++;
name = String(edited_anim) + " " + itos(counter);
}

undo_redo->create_action(TTR("Duplicate Animation"));
undo_redo->add_do_method(frames, "add_animation", name);
Copy link
Member

@groud groud Oct 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a big issue, but I wonder if it's the best to duplicate manually each property of the animation. If we add a property on SpriteFrames's animation, then this will break.
I think it would be better to modify the SpriteFrames.animations property directly instead, that should make it future-proof.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you explain deeper please, I think I didnt got it! what I got was: create a for loop and execute each action like the animation was being created manually?

Copy link
Member

@groud groud Oct 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, that's fine and it works. But if we someday add a new property to an animation, then it will break because you will be missing an action to copy the new property in the new create animation. So instead, I think you could use the SpriteFrames.animations property instead.
It would be something like:

undo_redo->add_undo_property(frames, "animations", frames.animations);
// Find the animation to duplicate in the frames.animations array, put it in the duplicated_animation variable.
...
//
Array new_animations = frames.animations;
new_animations.push_back(duplicated_animation); 
undo_redo->add_do_property(frames, "animations", new_animations);

But if you think it's too complex your solution works too, I don't mind much, it might just be a bit less future-proof.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anyway, I will approve the PR anyway, I think it's good to merge as-is.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SpriteFrames have a struct named Anim, so it's easy to duplicate everything at once. But this needs to be done in SpriteFrames, something like duplicate_animation(animation, new_animation) and the code

void duplicate_animation(from, to) {
animation[to] = animations[from];
}

(structs are passed by value, so this should be enough)

undo_redo->add_do_method(frames, "set_animation_loop", name, frames->get_animation_loop(edited_anim));
undo_redo->add_do_method(frames, "set_animation_speed", name, frames->get_animation_speed(edited_anim));
for (int i = 0; i < frames->get_frame_count(edited_anim); i++) {
undo_redo->add_do_method(frames, "add_frame", name, frames->get_frame(edited_anim, i));
}
undo_redo->add_undo_method(frames, "remove_animation", name);
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");

// Not sure whether this part is needed/wanted (`_animation_add` is doing the same thing).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should do something about this comment. Either use _animation_add() here if it's possible, or add a FIXME or something.

List<Node *> nodes;
_find_anim_sprites(EditorNode::get_singleton()->get_edited_scene(), &nodes, Ref<SpriteFrames>(frames));
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();
animations->grab_focus();
}

void SpriteFramesEditor::_animation_remove() {
if (updating) {
return;
Expand Down Expand Up @@ -1035,6 +1074,7 @@ void SpriteFramesEditor::edit(SpriteFrames *p_frames) {

add_anim->set_disabled(read_only);
delete_anim->set_disabled(read_only);
duplicate_anim->set_disabled(read_only);
anim_speed->set_editable(!read_only);
anim_loop->set_disabled(read_only);
load->set_disabled(read_only);
Expand Down Expand Up @@ -1206,6 +1246,11 @@ SpriteFramesEditor::SpriteFramesEditor() {
hbc_animlist->add_child(add_anim);
add_anim->connect("pressed", callable_mp(this, &SpriteFramesEditor::_animation_add));

duplicate_anim = memnew(Button);
duplicate_anim->set_flat(true);
hbc_animlist->add_child(duplicate_anim);
duplicate_anim->connect("pressed", callable_mp(this, &SpriteFramesEditor::_animation_duplicate));

delete_anim = memnew(Button);
delete_anim->set_flat(true);
hbc_animlist->add_child(delete_anim);
Expand Down
2 changes: 2 additions & 0 deletions editor/plugins/sprite_frames_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class SpriteFramesEditor : public HSplitContainer {
int sel;

Button *add_anim = nullptr;
Button *duplicate_anim = nullptr;
Button *delete_anim = nullptr;
LineEdit *anim_search_box = nullptr;

Expand Down Expand Up @@ -139,6 +140,7 @@ class SpriteFramesEditor : public HSplitContainer {
void _animation_select();
void _animation_name_edited();
void _animation_add();
void _animation_duplicate();
void _animation_remove();
void _animation_remove_confirmed();
void _animation_search_text_changed(const String &p_text);
Expand Down