Skip to content

Commit

Permalink
Enable SpriteFramesEditor to guess the amount of rows and columns of …
Browse files Browse the repository at this point in the history
…a sprite sheet when loading it for the first time
  • Loading branch information
TheSofox committed Aug 26, 2024
1 parent 88f3b5f commit d4c63d8
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 4 deletions.
88 changes: 84 additions & 4 deletions editor/plugins/sprite_frames_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,80 @@ void SpriteFramesEditor::_update_show_settings() {
}
}

void SpriteFramesEditor::_auto_slice_sprite_sheet() {
if (updating_split_settings) {
return;
}
updating_split_settings = true;

const Size2i size = split_sheet_preview->get_texture()->get_size();

const Size2i split_sheet = _estimate_sprite_sheet_size(split_sheet_preview->get_texture());
split_sheet_h->set_value(split_sheet.x);
split_sheet_v->set_value(split_sheet.y);
split_sheet_size_x->set_value(size.x / split_sheet.x);
split_sheet_size_y->set_value(size.y / split_sheet.y);
split_sheet_sep_x->set_value(0);
split_sheet_sep_y->set_value(0);
split_sheet_offset_x->set_value(0);
split_sheet_offset_y->set_value(0);

updating_split_settings = false;

frames_selected.clear();
selected_count = 0;
last_frame_selected = -1;
split_sheet_preview->queue_redraw();
}

bool SpriteFramesEditor::_matches_background_color(const Color &background_color, const Color &pixel_color) {
if ((background_color.a == 0 && pixel_color.a == 0) || background_color.is_equal_approx(pixel_color)) {
return true;
}

return pow(background_color.r - pixel_color.r, 2) + pow(background_color.g - pixel_color.g, 2) + pow(background_color.b - pixel_color.b, 2) + pow(background_color.a - pixel_color.a, 2) < 0.04;
}

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_background = 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_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()) {
Expand All @@ -530,10 +604,11 @@ void SpriteFramesEditor::_prepare_sprite_sheet(const String &p_file) {
// Different texture, reset to 4x4.
dominant_param = PARAM_FRAME_COUNT;
updating_split_settings = true;
split_sheet_h->set_value(4);
split_sheet_v->set_value(4);
split_sheet_size_x->set_value(size.x / 4);
split_sheet_size_y->set_value(size.y / 4);
const Size2i split_sheet = Size2i(4, 4);
split_sheet_h->set_value(split_sheet.x);
split_sheet_v->set_value(split_sheet.y);
split_sheet_size_x->set_value(size.x / split_sheet.x);
split_sheet_size_y->set_value(size.y / split_sheet.y);
split_sheet_sep_x->set_value(0);
split_sheet_sep_y->set_value(0);
split_sheet_offset_x->set_value(0);
Expand Down Expand Up @@ -2290,6 +2365,11 @@ SpriteFramesEditor::SpriteFramesEditor() {
split_sheet_offset_hb->add_child(split_sheet_offset_vb);
split_sheet_settings_vb->add_child(split_sheet_offset_hb);

Button *auto_slice = memnew(Button);
auto_slice->set_text(TTR("Auto-Slice"));
auto_slice->connect(SceneStringName(pressed), callable_mp(this, &SpriteFramesEditor::_auto_slice_sprite_sheet));
split_sheet_settings_vb->add_child(auto_slice);

split_sheet_hb->add_child(split_sheet_settings_vb);

file_split_sheet = memnew(EditorFileDialog);
Expand Down
3 changes: 3 additions & 0 deletions editor/plugins/sprite_frames_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,9 @@ class SpriteFramesEditor : public HSplitContainer {
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);

void _open_sprite_sheet();
void _auto_slice_sprite_sheet();
bool _matches_background_color(const Color &background_color, const Color &pixel_color);
Size2i _estimate_sprite_sheet_size(const Ref<Texture2D> texture);
void _prepare_sprite_sheet(const String &p_file);
int _sheet_preview_position_to_frame_index(const Vector2 &p_position);
void _sheet_preview_draw();
Expand Down

0 comments on commit d4c63d8

Please sign in to comment.