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 entire animations #80380

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
8 changes: 8 additions & 0 deletions doc/classes/SpriteFrames.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@
Removes all animations. An empty [code]default[/code] animation will be created.
</description>
</method>
<method name="duplicate_animation">
<return type="void" />
<param index="0" name="anim_from" type="StringName" />
<param index="1" name="anim_to" type="StringName" />
<description>
Duplicate all frames [param anim_from] to the [param anim_to].
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Duplicate all frames [param anim_from] to the [param anim_to].
Duplicate all frames from [param anim_from] to [param anim_to].

Copy link
Member

Choose a reason for hiding this comment

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

I think the current description is misleading. It sounds like the animation has to already exist, while it doesn't need to.

</description>
</method>
<method name="get_animation_loop" qualifiers="const">
<return type="bool" />
<param index="0" name="anim" type="StringName" />
Expand Down
39 changes: 39 additions & 0 deletions editor/plugins/sprite_frames_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,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 @@ -1020,6 +1021,36 @@ void SpriteFramesEditor::_animation_add() {
animations->grab_focus();
}

void SpriteFramesEditor::_animation_duplicate() {
if (updating) {
return;
}

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);
}

EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
undo_redo->create_action(TTR("Duplicate Animation"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
undo_redo->add_do_method(frames.ptr(), "add_animation", name);
Copy link
Member

Choose a reason for hiding this comment

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

duplicate_animation() works even if the new animation does not exist, so this step is redundant.

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");
Comment on lines +1044 to +1045
Copy link
Member

Choose a reason for hiding this comment

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

I think this should run after other methods.

undo_redo->add_do_method(frames.ptr(), "duplicate_animation", edited_anim, name);
undo_redo->add_undo_method(frames.ptr(), "remove_animation", name);
Copy link
Member

Choose a reason for hiding this comment

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

This is called twice.

undo_redo->commit_action();

_select_animation(name);
animations->grab_focus();
}

void SpriteFramesEditor::_animation_remove() {
if (updating) {
return;
Expand Down Expand Up @@ -1340,6 +1371,7 @@ void SpriteFramesEditor::edit(Ref<SpriteFrames> p_frames) {
_zoom_reset();

add_anim->set_disabled(read_only);
duplicate_anim->set_disabled(read_only);
delete_anim->set_disabled(read_only);
anim_speed->set_editable(!read_only);
anim_loop->set_disabled(read_only);
Expand Down Expand Up @@ -1659,6 +1691,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 Expand Up @@ -1711,6 +1748,8 @@ SpriteFramesEditor::SpriteFramesEditor() {

add_anim->set_shortcut_context(animations);
add_anim->set_shortcut(ED_SHORTCUT("sprite_frames/new_animation", TTR("Add Animation"), KeyModifierMask::CMD_OR_CTRL | Key::N));
duplicate_anim->set_shortcut_context(animations);
duplicate_anim->set_shortcut(ED_SHORTCUT("sprite_frames/duplicate_animation", TTR("Duplicate Animation"), KeyModifierMask::CMD_OR_CTRL | Key::D));
delete_anim->set_shortcut_context(animations);
delete_anim->set_shortcut(ED_SHORTCUT("sprite_frames/delete_animation", TTR("Delete Animation"), Key::KEY_DELETE));

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 @@ -118,6 +118,7 @@ class SpriteFramesEditor : public HSplitContainer {
int sel;

Button *add_anim = nullptr;
Button *duplicate_anim = nullptr;
Button *delete_anim = nullptr;
SpinBox *anim_speed = nullptr;
Button *anim_loop = nullptr;
Expand Down Expand Up @@ -201,6 +202,7 @@ class SpriteFramesEditor : public HSplitContainer {
void _animation_selected();
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
5 changes: 5 additions & 0 deletions scene/resources/sprite_frames.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ bool SpriteFrames::has_animation(const StringName &p_anim) const {
return animations.has(p_anim);
}

void SpriteFrames::duplicate_animation(const StringName &p_from, const StringName &p_to) {
animations[p_to] = animations[p_from];
}

void SpriteFrames::remove_animation(const StringName &p_anim) {
animations.erase(p_anim);
}
Expand Down Expand Up @@ -227,6 +231,7 @@ void SpriteFrames::_set_animations(const Array &p_animations) {
void SpriteFrames::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_animation", "anim"), &SpriteFrames::add_animation);
ClassDB::bind_method(D_METHOD("has_animation", "anim"), &SpriteFrames::has_animation);
ClassDB::bind_method(D_METHOD("duplicate_animation", "anim_from", "anim_to"), &SpriteFrames::duplicate_animation);
ClassDB::bind_method(D_METHOD("remove_animation", "anim"), &SpriteFrames::remove_animation);
ClassDB::bind_method(D_METHOD("rename_animation", "anim", "newname"), &SpriteFrames::rename_animation);

Expand Down
1 change: 1 addition & 0 deletions scene/resources/sprite_frames.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class SpriteFrames : public Resource {
public:
void add_animation(const StringName &p_anim);
bool has_animation(const StringName &p_anim) const;
void duplicate_animation(const StringName &p_from, const StringName &p_to);
void remove_animation(const StringName &p_anim);
void rename_animation(const StringName &p_prev, const StringName &p_next);

Expand Down
Loading