Repository: godotengine/godot
File: editor/scene/sprite_frames_editor_plugin.cpp (C++)

Code before:
	}
	undo_redo->add_do_method(this, "_select_animation", new_edited);
	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();
}

StringName SpriteFramesEditor::_find_next_animation() {
	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.get(0)) {
			return anim_names.get(1);
		} else {
			return anim_names.get(0);
		}
	} else {
		return StringName();
	}
}

String SpriteFramesEditor::_generate_unique_animation_name(const String &p_base_name) const {
	String nnsep;
	switch (GLOBAL_GET("editor/naming/node_name_num_separator").operator int()) {
		case 0:
			nnsep = "";
			break;
		case 1:
			nnsep = " ";
			break;
		case 2:
			nnsep = "_";
			break;
		case 3:
			nnsep = "-";
			break;
		default:
			nnsep = " ";
			break;
	}

	String name_string = p_base_name;
	String nums;
	for (int i = name_string.length() - 1; i >= 0; i--) {
		char32_t n = name_string[i];
		if (is_digit(n)) {
			nums = String::chr(name_string[i]) + nums;
		} else {
			break;

Review comment (suggestion):
I don't think the animation name should rely on the `editor/naming/node_name_num_separator` project setting, and I'm not sure if we should add a separate setting for animations here. I'd prefer the `snake_case_123` option be hardcoded here until a proposal for such configurability appears.

Code after:
			texture = (*p_frames)[i].texture;
			duration = (*p_frames)[i].duration;
		} else {
			texture = frames->get_frame_texture(edited_anim, i);
			duration = frames->get_frame_duration(edited_anim, i);
		}
		undo_redo->add_undo_method(frames.ptr(), "add_frame", edited_anim, texture, duration);
	}
	undo_redo->add_do_method(this, "_select_animation", new_edited);
	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();
}

StringName SpriteFramesEditor::_find_next_animation() {
	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.get(0)) {
			return anim_names.get(1);
		} else {
			return anim_names.get(0);
		}
	} else {
		return StringName();
	}
}

String SpriteFramesEditor::_generate_unique_animation_name(const String &p_base_name) const {
	if (!frames->has_animation(p_base_name)) {
		return p_base_name;
	}

	int count = 2;
	String new_name = p_base_name;
	PackedStringArray split = new_name.split("_");
	int last_index = split.size() - 1;
	if (last_index > 0 && split[last_index].is_valid_int() && split[last_index].to_int() >= 0) {
		count = split[last_index].to_int();
		split.remove_at(last_index);
		new_name = String("_").join(split);
	}
	while (true) {
		String attempt = new_name;
		attempt += vformat("_%d", count);
		if (frames->has_animation(attempt)) {
			count++;
			continue;
		}