|
@@ -355,8 +355,6 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
|
|
} else if (atlas_tex.is_valid()) {
|
|
} else if (atlas_tex.is_valid()) {
|
|
undo_redo->add_do_method(atlas_tex.ptr(), "set_region", atlas_tex->get_region());
|
|
undo_redo->add_do_method(atlas_tex.ptr(), "set_region", atlas_tex->get_region());
|
|
undo_redo->add_undo_method(atlas_tex.ptr(), "set_region", rect_prev);
|
|
undo_redo->add_undo_method(atlas_tex.ptr(), "set_region", rect_prev);
|
|
- } else if (node_ninepatch) {
|
|
|
|
- // FIXME: Is this intentional?
|
|
|
|
} else if (node_ninepatch) {
|
|
} else if (node_ninepatch) {
|
|
undo_redo->add_do_method(node_ninepatch, "set_region_rect", node_ninepatch->get_region_rect());
|
|
undo_redo->add_do_method(node_ninepatch, "set_region_rect", node_ninepatch->get_region_rect());
|
|
undo_redo->add_undo_method(node_ninepatch, "set_region_rect", rect_prev);
|
|
undo_redo->add_undo_method(node_ninepatch, "set_region_rect", rect_prev);
|
|
@@ -521,6 +519,10 @@ void TextureRegionEditor::_set_snap_mode(int p_mode) {
|
|
else
|
|
else
|
|
hb_grid->hide();
|
|
hb_grid->hide();
|
|
|
|
|
|
|
|
+ if (snap_mode == SNAP_AUTOSLICE && is_visible() && autoslice_is_dirty) {
|
|
|
|
+ _update_autoslice();
|
|
|
|
+ }
|
|
|
|
+
|
|
edit_draw->update();
|
|
edit_draw->update();
|
|
}
|
|
}
|
|
|
|
|
|
@@ -562,7 +564,8 @@ void TextureRegionEditor::_zoom_in() {
|
|
}
|
|
}
|
|
|
|
|
|
void TextureRegionEditor::_zoom_reset() {
|
|
void TextureRegionEditor::_zoom_reset() {
|
|
- if (draw_zoom == 1) return;
|
|
|
|
|
|
+ if (draw_zoom == 1)
|
|
|
|
+ return;
|
|
draw_zoom = 1;
|
|
draw_zoom = 1;
|
|
edit_draw->update();
|
|
edit_draw->update();
|
|
}
|
|
}
|
|
@@ -585,25 +588,91 @@ void TextureRegionEditor::apply_rect(const Rect2 &rect) {
|
|
atlas_tex->set_region(rect);
|
|
atlas_tex->set_region(rect);
|
|
}
|
|
}
|
|
|
|
|
|
-void TextureRegionEditor::_notification(int p_what) {
|
|
|
|
- switch (p_what) {
|
|
|
|
- case NOTIFICATION_PROCESS: {
|
|
|
|
- if (node_sprite) {
|
|
|
|
- if (node_sprite->is_region()) {
|
|
|
|
|
|
+void TextureRegionEditor::_update_autoslice() {
|
|
|
|
+ autoslice_is_dirty = false;
|
|
|
|
+ autoslice_cache.clear();
|
|
|
|
|
|
- set_process(false);
|
|
|
|
- EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
|
|
|
|
|
|
+ Ref<Texture> texture = NULL;
|
|
|
|
+ if (node_sprite)
|
|
|
|
+ texture = node_sprite->get_texture();
|
|
|
|
+ else if (node_ninepatch)
|
|
|
|
+ texture = node_ninepatch->get_texture();
|
|
|
|
+ else if (obj_styleBox.is_valid())
|
|
|
|
+ texture = obj_styleBox->get_texture();
|
|
|
|
+ else if (atlas_tex.is_valid())
|
|
|
|
+ texture = atlas_tex->get_atlas();
|
|
|
|
+
|
|
|
|
+ if (texture.is_null()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (int y = 0; y < texture->get_height(); y++) {
|
|
|
|
+ for (int x = 0; x < texture->get_width(); x++) {
|
|
|
|
+ if (texture->is_pixel_opaque(x, y)) {
|
|
|
|
+ bool found = false;
|
|
|
|
+ for (List<Rect2>::Element *E = autoslice_cache.front(); E; E = E->next()) {
|
|
|
|
+ Rect2 grown = E->get().grow(1.5);
|
|
|
|
+ if (grown.has_point(Point2(x, y))) {
|
|
|
|
+ E->get().expand_to(Point2(x, y));
|
|
|
|
+ E->get().expand_to(Point2(x + 1, y + 1));
|
|
|
|
+ x = E->get().position.x + E->get().size.x - 1;
|
|
|
|
+ bool merged = true;
|
|
|
|
+ while (merged) {
|
|
|
|
+ merged = false;
|
|
|
|
+ bool queue_erase = false;
|
|
|
|
+ for (List<Rect2>::Element *F = autoslice_cache.front(); F; F = F->next()) {
|
|
|
|
+ if (queue_erase) {
|
|
|
|
+ autoslice_cache.erase(F->prev());
|
|
|
|
+ queue_erase = false;
|
|
|
|
+ }
|
|
|
|
+ if (F == E)
|
|
|
|
+ continue;
|
|
|
|
+ if (E->get().grow(1).intersects(F->get())) {
|
|
|
|
+ E->get().expand_to(F->get().position);
|
|
|
|
+ E->get().expand_to(F->get().position + F->get().size);
|
|
|
|
+ if (F->prev()) {
|
|
|
|
+ F = F->prev();
|
|
|
|
+ autoslice_cache.erase(F->next());
|
|
|
|
+ } else {
|
|
|
|
+ queue_erase = true;
|
|
|
|
+ // Can't delete the first rect in the list.
|
|
|
|
+ }
|
|
|
|
+ merged = true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ found = true;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (!found) {
|
|
|
|
+ Rect2 new_rect(x, y, 1, 1);
|
|
|
|
+ autoslice_cache.push_back(new_rect);
|
|
}
|
|
}
|
|
- } else {
|
|
|
|
- set_process(false);
|
|
|
|
}
|
|
}
|
|
- } break;
|
|
|
|
- case NOTIFICATION_THEME_CHANGED:
|
|
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ cache_map[texture->get_rid()] = autoslice_cache;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void TextureRegionEditor::_notification(int p_what) {
|
|
|
|
+ switch (p_what) {
|
|
case NOTIFICATION_READY: {
|
|
case NOTIFICATION_READY: {
|
|
zoom_out->set_icon(get_icon("ZoomLess", "EditorIcons"));
|
|
zoom_out->set_icon(get_icon("ZoomLess", "EditorIcons"));
|
|
zoom_reset->set_icon(get_icon("ZoomReset", "EditorIcons"));
|
|
zoom_reset->set_icon(get_icon("ZoomReset", "EditorIcons"));
|
|
zoom_in->set_icon(get_icon("ZoomMore", "EditorIcons"));
|
|
zoom_in->set_icon(get_icon("ZoomMore", "EditorIcons"));
|
|
} break;
|
|
} break;
|
|
|
|
+ case NOTIFICATION_VISIBILITY_CHANGED: {
|
|
|
|
+ if (snap_mode == SNAP_AUTOSLICE && is_visible() && autoslice_is_dirty) {
|
|
|
|
+ _update_autoslice();
|
|
|
|
+ }
|
|
|
|
+ } break;
|
|
|
|
+ case MainLoop::NOTIFICATION_WM_FOCUS_IN: {
|
|
|
|
+ // This happens when the user leaves the Editor and returns,
|
|
|
|
+ // he/she could have changed the textures, so the cache is cleared
|
|
|
|
+ cache_map.clear();
|
|
|
|
+ _edit_region();
|
|
|
|
+ } break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -709,57 +778,15 @@ void TextureRegionEditor::_edit_region() {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- autoslice_cache.clear();
|
|
|
|
- Ref<Image> i;
|
|
|
|
- i.instance();
|
|
|
|
- if (i->load(texture->get_path()) == OK) {
|
|
|
|
- BitMap bm;
|
|
|
|
- bm.create_from_image_alpha(i);
|
|
|
|
- for (int y = 0; y < i->get_height(); y++) {
|
|
|
|
- for (int x = 0; x < i->get_width(); x++) {
|
|
|
|
- if (bm.get_bit(Point2(x, y))) {
|
|
|
|
- bool found = false;
|
|
|
|
- for (List<Rect2>::Element *E = autoslice_cache.front(); E; E = E->next()) {
|
|
|
|
- Rect2 grown = E->get().grow(1.5);
|
|
|
|
- if (grown.has_point(Point2(x, y))) {
|
|
|
|
- E->get().expand_to(Point2(x, y));
|
|
|
|
- E->get().expand_to(Point2(x + 1, y + 1));
|
|
|
|
- x = E->get().position.x + E->get().size.x - 1;
|
|
|
|
- bool merged = true;
|
|
|
|
- while (merged) {
|
|
|
|
- merged = false;
|
|
|
|
- bool queue_erase = false;
|
|
|
|
- for (List<Rect2>::Element *F = autoslice_cache.front(); F; F = F->next()) {
|
|
|
|
- if (queue_erase) {
|
|
|
|
- autoslice_cache.erase(F->prev());
|
|
|
|
- queue_erase = false;
|
|
|
|
- }
|
|
|
|
- if (F == E)
|
|
|
|
- continue;
|
|
|
|
- if (E->get().grow(1).intersects(F->get())) {
|
|
|
|
- E->get().expand_to(F->get().position);
|
|
|
|
- E->get().expand_to(F->get().position + F->get().size);
|
|
|
|
- if (F->prev()) {
|
|
|
|
- F = F->prev();
|
|
|
|
- autoslice_cache.erase(F->next());
|
|
|
|
- } else {
|
|
|
|
- queue_erase = true;
|
|
|
|
- //Can't delete the first rect in the list.
|
|
|
|
- }
|
|
|
|
- merged = true;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- found = true;
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if (!found) {
|
|
|
|
- Rect2 new_rect(x, y, 1, 1);
|
|
|
|
- autoslice_cache.push_back(new_rect);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ if (cache_map.has(texture->get_rid())) {
|
|
|
|
+ autoslice_cache = cache_map[texture->get_rid()];
|
|
|
|
+ autoslice_is_dirty = false;
|
|
|
|
+ return;
|
|
|
|
+ } else {
|
|
|
|
+ if (is_visible() && snap_mode == SNAP_AUTOSLICE) {
|
|
|
|
+ _update_autoslice();
|
|
|
|
+ } else {
|
|
|
|
+ autoslice_is_dirty = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|