Преглед на файлове

Add duplicate animation

Co-authored-by: Nonunknown <[email protected]>
Ainsley Su преди 1 година
родител
ревизия
57bc1d7574

+ 8 - 0
doc/classes/SpriteFrames.xml

@@ -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>
+				Duplicates the animation [param anim_from] to a new animation named [param anim_to]. Fails if [param anim_to] already exists, or if [param anim_from] does not exist.
+			</description>
+		</method>
 		<method name="get_animation_loop" qualifiers="const">
 			<return type="bool" />
 			<param index="0" name="anim" type="StringName" />

+ 44 - 0
editor/plugins/sprite_frames_editor_plugin.cpp

@@ -659,6 +659,7 @@ void SpriteFramesEditor::_notification(int p_what) {
 			zoom_reset->set_icon(get_editor_theme_icon(SNAME("ZoomReset")));
 			zoom_in->set_icon(get_editor_theme_icon(SNAME("ZoomMore")));
 			add_anim->set_icon(get_editor_theme_icon(SNAME("New")));
+			duplicate_anim->set_icon(get_editor_theme_icon(SNAME("Duplicate")));
 			delete_anim->set_icon(get_editor_theme_icon(SNAME("Remove")));
 			anim_search_box->set_right_icon(get_editor_theme_icon(SNAME("Search")));
 			split_sheet_zoom_out->set_icon(get_editor_theme_icon(SNAME("ZoomLess")));
@@ -1179,6 +1180,41 @@ 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 new_name = edited_anim;
+	PackedStringArray name_component = new_name.rsplit("_", true, 1);
+	String base_name = name_component[0];
+	if (name_component.size() > 1 && name_component[1].is_valid_int() && name_component[1].to_int() >= 0) {
+		counter = name_component[1].to_int();
+	}
+	new_name = base_name + "_" + itos(counter);
+	while (frames->has_animation(new_name)) {
+		counter++;
+		new_name = base_name + "_" + 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(), "duplicate_animation", edited_anim, new_name);
+	undo_redo->add_undo_method(frames.ptr(), "remove_animation", new_name);
+	undo_redo->add_do_method(this, "_select_animation", new_name);
+	undo_redo->add_undo_method(this, "_select_animation", edited_anim);
+	undo_redo->add_do_method(this, "_update_library");
+	undo_redo->add_undo_method(this, "_update_library");
+	undo_redo->commit_action();
+
+	animations->grab_focus();
+}
+
 void SpriteFramesEditor::_animation_remove() {
 	if (updating) {
 		return;
@@ -1541,6 +1577,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);
@@ -1865,6 +1902,11 @@ SpriteFramesEditor::SpriteFramesEditor() {
 	hbc_animlist->add_child(add_anim);
 	add_anim->connect(SceneStringName(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(SceneStringName(pressed), callable_mp(this, &SpriteFramesEditor::_animation_duplicate));
+
 	delete_anim = memnew(Button);
 	delete_anim->set_theme_type_variation("FlatButton");
 	hbc_animlist->add_child(delete_anim);
@@ -1918,6 +1960,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));
 

+ 2 - 0
editor/plugins/sprite_frames_editor_plugin.h

@@ -121,6 +121,7 @@ class SpriteFramesEditor : public HSplitContainer {
 	Vector<int> selection;
 
 	Button *add_anim = nullptr;
+	Button *duplicate_anim = nullptr;
 	Button *delete_anim = nullptr;
 	SpinBox *anim_speed = nullptr;
 	Button *anim_loop = nullptr;
@@ -210,6 +211,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);

+ 7 - 0
scene/resources/sprite_frames.cpp

@@ -106,6 +106,12 @@ 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) {
+	ERR_FAIL_COND_MSG(!animations.has(p_from), vformat("SpriteFrames doesn't have animation '%s'.", p_from));
+	ERR_FAIL_COND_MSG(animations.has(p_to), vformat("Animation '%s' already exists.", p_to));
+	animations[p_to] = animations[p_from];
+}
+
 void SpriteFrames::remove_animation(const StringName &p_anim) {
 	animations.erase(p_anim);
 }
@@ -246,6 +252,7 @@ void SpriteFrames::get_argument_options(const StringName &p_function, int p_idx,
 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);
 

+ 1 - 0
scene/resources/sprite_frames.h

@@ -60,6 +60,7 @@ protected:
 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);