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

Code before:

			[[fallthrough]];
		}
		case NOTIFICATION_THEME_CHANGED: {
			autoplay_icon = get_editor_theme_icon(SNAME("AutoPlay"));
			stop_icon = get_editor_theme_icon(SNAME("Stop"));
			pause_icon = get_editor_theme_icon(SNAME("Pause"));
			_update_stop_icon();

			autoplay->set_icon(get_editor_theme_icon(SNAME("AutoPlay")));
			anim_loop->set_icon(get_editor_theme_icon(SNAME("Loop")));
			play->set_icon(get_editor_theme_icon(SNAME("PlayStart")));
			play_from->set_icon(get_editor_theme_icon(SNAME("Play")));
			play_bw->set_icon(get_editor_theme_icon(SNAME("PlayStartBackwards")));
			play_bw_from->set_icon(get_editor_theme_icon(SNAME("PlayBackwards")));

			load->set_icon(get_editor_theme_icon(SNAME("Load")));
			load_sheet->set_icon(get_editor_theme_icon(SNAME("SpriteSheet")));
			copy->set_icon(get_editor_theme_icon(SNAME("ActionCopy")));
			paste->set_icon(get_editor_theme_icon(SNAME("ActionPaste")));
			empty_before->set_icon(get_editor_theme_icon(SNAME("InsertBefore")));
			empty_after->set_icon(get_editor_theme_icon(SNAME("InsertAfter")));
			move_up->set_icon(get_editor_theme_icon(SNAME("MoveLeft")));
			move_down->set_icon(get_editor_theme_icon(SNAME("MoveRight")));
			delete_frame->set_icon(get_editor_theme_icon(SNAME("Remove")));
			zoom_out->set_icon(get_editor_theme_icon(SNAME("ZoomLess")));
			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")));
			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")));
			split_sheet_zoom_reset->set_icon(get_editor_theme_icon(SNAME("ZoomReset")));
			split_sheet_zoom_in->set_icon(get_editor_theme_icon(SNAME("ZoomMore")));
			split_sheet_scroll->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree")));

			_update_show_settings();
		} break;

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

void SpriteFramesEditor::_file_load_request(const Vector<String> &p_path, int p_at_pos) {
	ERR_FAIL_COND(!frames->has_animation(edited_anim));

Review comment (suggestion):
A little simplified/shortened. AFAICT should do pretty much same thing (haven't tested :upside_down_face:). Also should be faster as you do not early-`break` out of the inner loops.
```suggestion
Size2i SpriteFramesEditor::_estimate_sprite_sheet_size(const Ref<Texture2D> texture) {
	Ref<Image> image = texture->get_image();
	Size2i size = texture->get_size();

	Color assumed_background_color = image->get_pixel(0, 0);
	Size2i sheet_size = Size2i(0, 0);

	bool previous_line_contigous = true;
	for (int x = 0; x < size.x; x++) {
		int y = 0;
		while (y < size.y && _matches_background_color(assumed_background_color, image->get_pixel(x, y))) {
			y++;
		}
		bool current_line_contigous = (y == size.y);
		if (previous_line_contigous && !current_line_contigous) {
			sheet_size.x++;
		}
		previous_line_contigous = current_line_contigous;
	}

	previous_line_contigous = true;
	for (int y = 0; y < size.y; y++) {
		int x = 0;
		while (x < size.x && _matches_background_color(assumed_background_color, image->get_pixel(x, y))) {
			x++;
		}
		bool current_line_contigous = (x == size.x);
		if (previous_line_contigous && !current_line_contigous) {
			sheet_size.y++;
		}
		previous_line_contigous = current_line_contigous;
	}
	
	if (sheet_size.x == 0) {
		sheet_size.x = 4;
	}
	if (sheet_size.y == 0) {
		sheet_size.y = 4;
	}

	return sheet_size;
}
```

Code after:
		bool current_line_background = (y == size.y);
		if (previous_line_background && !current_line_background) {
			sheet_size.x++;
		}
		previous_line_background = current_line_background;
	}

	previous_line_background = true;
	for (int y = 0; y < size.y; y++) {
		int x = 0;
		while (x < size.x && _matches_background_color(assumed_background_color, image->get_pixel(x, y))) {
			x++;
		}
		bool current_line_background = (x == size.x);
		if (previous_line_background && !current_line_background) {
			sheet_size.y++;
		}
		previous_line_background = current_line_background;
	}

	if (sheet_size == Size2i(0, 0) || sheet_size == Size2i(1, 1)) {
		sheet_size = Size2i(4, 4);
	}

	return sheet_size;
}

void SpriteFramesEditor::_prepare_sprite_sheet(const String &p_file) {
	Ref<Texture2D> texture = ResourceLoader::load(p_file);
	if (texture.is_null()) {
		EditorNode::get_singleton()->show_warning(TTR("Unable to load images"));
		ERR_FAIL_COND(texture.is_null());
	}
	frames_selected.clear();
	selected_count = 0;
	last_frame_selected = -1;

	bool new_texture = texture != split_sheet_preview->get_texture();
	split_sheet_preview->set_texture(texture);
	if (new_texture) {
		// Reset spin max.
		const Size2i size = texture->get_size();
		split_sheet_size_x->set_max(size.x);
		split_sheet_size_y->set_max(size.y);
		split_sheet_sep_x->set_max(size.x);
		split_sheet_sep_y->set_max(size.y);
		split_sheet_offset_x->set_max(size.x);
		split_sheet_offset_y->set_max(size.y);

		if (size != previous_texture_size) {
			// Different texture, reset to 4x4.