summaryrefslogtreecommitdiffstats
path: root/editor/plugins/sprite_frames_editor_plugin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'editor/plugins/sprite_frames_editor_plugin.cpp')
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp124
1 files changed, 105 insertions, 19 deletions
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index d1da61e5fc..ff5aca6cb0 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -504,6 +504,82 @@ 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 &p_background_color, const Color &p_pixel_color) {
+ if ((p_background_color.a == 0 && p_pixel_color.a == 0) || p_background_color.is_equal_approx(p_pixel_color)) {
+ return true;
+ }
+
+ Color d = p_background_color - p_pixel_color;
+ // 0.04f is the threshold for how much a colour can deviate from background colour and still be considered a match. Arrived at through experimentation, can be tweaked.
+ return (d.r * d.r) + (d.g * d.g) + (d.b * d.b) + (d.a * d.a) < 0.04f;
+}
+
+Size2i SpriteFramesEditor::_estimate_sprite_sheet_size(const Ref<Texture2D> p_texture) {
+ Ref<Image> image = p_texture->get_image();
+ Size2i size = p_texture->get_size();
+
+ Color assumed_background_color = image->get_pixel(0, 0);
+ Size2i sheet_size;
+
+ 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()) {
@@ -530,10 +606,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);
@@ -953,7 +1030,7 @@ void SpriteFramesEditor::_sync_animation() {
}
void SpriteFramesEditor::_select_animation(const String &p_name, bool p_update_node) {
- if (!frames->has_animation(p_name)) {
+ if (frames.is_null() || !frames->has_animation(p_name)) {
return;
}
edited_anim = p_name;
@@ -1056,10 +1133,12 @@ void SpriteFramesEditor::_rename_node_animation(EditorUndoRedoManager *undo_redo
for (Node *E : nodes) {
String current_name = E->call("get_animation");
if (current_name == p_filter) {
+ undo_redo->force_fixed_history(); // Fixes corner-case when editing SpriteFrames stored as separate file.
undo_redo->add_undo_method(E, "set_animation", p_new_animation);
}
String autoplay_name = E->call("get_autoplay");
if (autoplay_name == p_filter) {
+ undo_redo->force_fixed_history();
undo_redo->add_undo_method(E, "set_autoplay", p_new_autoplay);
}
}
@@ -1067,10 +1146,12 @@ void SpriteFramesEditor::_rename_node_animation(EditorUndoRedoManager *undo_redo
for (Node *E : nodes) {
String current_name = E->call("get_animation");
if (current_name == p_filter) {
+ undo_redo->force_fixed_history();
undo_redo->add_do_method(E, "set_animation", p_new_animation);
}
String autoplay_name = E->call("get_autoplay");
if (autoplay_name == p_filter) {
+ undo_redo->force_fixed_history();
undo_redo->add_do_method(E, "set_autoplay", p_new_autoplay);
}
}
@@ -1816,7 +1897,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
anim_speed->set_step(0.01);
anim_speed->set_custom_arrow_step(1);
anim_speed->set_tooltip_text(TTR("Animation Speed"));
- anim_speed->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_animation_speed_changed));
+ anim_speed->connect(SceneStringName(value_changed), callable_mp(this, &SpriteFramesEditor::_animation_speed_changed));
hbc_animlist->add_child(anim_speed);
anim_search_box = memnew(LineEdit);
@@ -1824,7 +1905,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
anim_search_box->set_h_size_flags(SIZE_EXPAND_FILL);
anim_search_box->set_placeholder(TTR("Filter Animations"));
anim_search_box->set_clear_button_enabled(true);
- anim_search_box->connect("text_changed", callable_mp(this, &SpriteFramesEditor::_animation_search_text_changed));
+ anim_search_box->connect(SceneStringName(text_changed), callable_mp(this, &SpriteFramesEditor::_animation_search_text_changed));
animations = memnew(Tree);
sub_vb->add_child(animations);
@@ -1960,7 +2041,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
frame_duration->set_custom_arrow_step(0.1);
frame_duration->set_allow_lesser(false);
frame_duration->set_allow_greater(true);
- frame_duration->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_frame_duration_changed));
+ frame_duration->connect(SceneStringName(value_changed), callable_mp(this, &SpriteFramesEditor::_frame_duration_changed));
hbc_frame_duration->add_child(frame_duration);
// Wide empty separation control. (like BoxContainer::add_spacer())
@@ -2058,12 +2139,12 @@ SpriteFramesEditor::SpriteFramesEditor() {
delete_dialog = memnew(ConfirmationDialog);
add_child(delete_dialog);
- delete_dialog->connect("confirmed", callable_mp(this, &SpriteFramesEditor::_animation_remove_confirmed));
+ delete_dialog->connect(SceneStringName(confirmed), callable_mp(this, &SpriteFramesEditor::_animation_remove_confirmed));
split_sheet_dialog = memnew(ConfirmationDialog);
add_child(split_sheet_dialog);
split_sheet_dialog->set_title(TTR("Select Frames"));
- split_sheet_dialog->connect("confirmed", callable_mp(this, &SpriteFramesEditor::_sheet_add_frames));
+ split_sheet_dialog->connect(SceneStringName(confirmed), callable_mp(this, &SpriteFramesEditor::_sheet_add_frames));
HBoxContainer *split_sheet_hb = memnew(HBoxContainer);
split_sheet_dialog->add_child(split_sheet_hb);
@@ -2091,7 +2172,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
split_sheet_order->add_item(TTR("Top to Bottom, Right to Left"), FRAME_ORDER_TOP_BOTTOM_RIGHT_LEFT);
split_sheet_order->add_item(TTR("Bottom to Top, Left to Right"), FRAME_ORDER_BOTTOM_TOP_LEFT_RIGHT);
split_sheet_order->add_item(TTR("Bottom to Top, Right to Left"), FRAME_ORDER_BOTTOM_TOP_RIGHT_LEFT);
- split_sheet_order->connect("item_selected", callable_mp(this, &SpriteFramesEditor::_sheet_order_selected));
+ split_sheet_order->connect(SceneStringName(item_selected), callable_mp(this, &SpriteFramesEditor::_sheet_order_selected));
split_sheet_menu_hb->add_child(split_sheet_order);
Button *select_all = memnew(Button);
@@ -2183,7 +2264,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
split_sheet_h->set_step(1);
split_sheet_h->set_select_all_on_focus(true);
split_sheet_h_hb->add_child(split_sheet_h);
- split_sheet_h->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_FRAME_COUNT));
+ split_sheet_h->connect(SceneStringName(value_changed), callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_FRAME_COUNT));
split_sheet_settings_vb->add_child(split_sheet_h_hb);
HBoxContainer *split_sheet_v_hb = memnew(HBoxContainer);
@@ -2200,7 +2281,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
split_sheet_v->set_step(1);
split_sheet_v->set_select_all_on_focus(true);
split_sheet_v_hb->add_child(split_sheet_v);
- split_sheet_v->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_FRAME_COUNT));
+ split_sheet_v->connect(SceneStringName(value_changed), callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_FRAME_COUNT));
split_sheet_settings_vb->add_child(split_sheet_v_hb);
HBoxContainer *split_sheet_size_hb = memnew(HBoxContainer);
@@ -2219,7 +2300,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
split_sheet_size_x->set_step(1);
split_sheet_size_x->set_suffix("px");
split_sheet_size_x->set_select_all_on_focus(true);
- split_sheet_size_x->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_SIZE));
+ split_sheet_size_x->connect(SceneStringName(value_changed), callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_SIZE));
split_sheet_size_vb->add_child(split_sheet_size_x);
split_sheet_size_y = memnew(SpinBox);
split_sheet_size_y->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -2227,7 +2308,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
split_sheet_size_y->set_step(1);
split_sheet_size_y->set_suffix("px");
split_sheet_size_y->set_select_all_on_focus(true);
- split_sheet_size_y->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_SIZE));
+ split_sheet_size_y->connect(SceneStringName(value_changed), callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_SIZE));
split_sheet_size_vb->add_child(split_sheet_size_y);
split_sheet_size_hb->add_child(split_sheet_size_vb);
split_sheet_settings_vb->add_child(split_sheet_size_hb);
@@ -2247,14 +2328,14 @@ SpriteFramesEditor::SpriteFramesEditor() {
split_sheet_sep_x->set_step(1);
split_sheet_sep_x->set_suffix("px");
split_sheet_sep_x->set_select_all_on_focus(true);
- split_sheet_sep_x->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_USE_CURRENT));
+ split_sheet_sep_x->connect(SceneStringName(value_changed), callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_USE_CURRENT));
split_sheet_sep_vb->add_child(split_sheet_sep_x);
split_sheet_sep_y = memnew(SpinBox);
split_sheet_sep_y->set_min(0);
split_sheet_sep_y->set_step(1);
split_sheet_sep_y->set_suffix("px");
split_sheet_sep_y->set_select_all_on_focus(true);
- split_sheet_sep_y->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_USE_CURRENT));
+ split_sheet_sep_y->connect(SceneStringName(value_changed), callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_USE_CURRENT));
split_sheet_sep_vb->add_child(split_sheet_sep_y);
split_sheet_sep_hb->add_child(split_sheet_sep_vb);
split_sheet_settings_vb->add_child(split_sheet_sep_hb);
@@ -2274,18 +2355,23 @@ SpriteFramesEditor::SpriteFramesEditor() {
split_sheet_offset_x->set_step(1);
split_sheet_offset_x->set_suffix("px");
split_sheet_offset_x->set_select_all_on_focus(true);
- split_sheet_offset_x->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_USE_CURRENT));
+ split_sheet_offset_x->connect(SceneStringName(value_changed), callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_USE_CURRENT));
split_sheet_offset_vb->add_child(split_sheet_offset_x);
split_sheet_offset_y = memnew(SpinBox);
split_sheet_offset_y->set_min(0);
split_sheet_offset_y->set_step(1);
split_sheet_offset_y->set_suffix("px");
split_sheet_offset_y->set_select_all_on_focus(true);
- split_sheet_offset_y->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_USE_CURRENT));
+ split_sheet_offset_y->connect(SceneStringName(value_changed), callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed).bind(PARAM_USE_CURRENT));
split_sheet_offset_vb->add_child(split_sheet_offset_y);
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);