Texture Region: Cache auto-slice information into the texture. Fixes #11503
This commit is contained in:
parent
12290c172a
commit
1f4a891a9c
|
@ -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::_update_autoslice() {
|
||||||
|
autoslice_is_dirty = false;
|
||||||
|
autoslice_cache.clear();
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cache_map[texture->get_rid()] = autoslice_cache;
|
||||||
|
}
|
||||||
|
|
||||||
void TextureRegionEditor::_notification(int p_what) {
|
void TextureRegionEditor::_notification(int p_what) {
|
||||||
switch (p_what) {
|
switch (p_what) {
|
||||||
case NOTIFICATION_PROCESS: {
|
|
||||||
if (node_sprite) {
|
|
||||||
if (node_sprite->is_region()) {
|
|
||||||
|
|
||||||
set_process(false);
|
|
||||||
EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
set_process(false);
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
case NOTIFICATION_THEME_CHANGED:
|
|
||||||
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();
|
if (cache_map.has(texture->get_rid())) {
|
||||||
Ref<Image> i;
|
autoslice_cache = cache_map[texture->get_rid()];
|
||||||
i.instance();
|
autoslice_is_dirty = false;
|
||||||
if (i->load(texture->get_path()) == OK) {
|
return;
|
||||||
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 {
|
} else {
|
||||||
queue_erase = true;
|
if (is_visible() && snap_mode == SNAP_AUTOSLICE) {
|
||||||
//Can't delete the first rect in the list.
|
_update_autoslice();
|
||||||
}
|
} else {
|
||||||
merged = true;
|
autoslice_is_dirty = true;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
Rect2 new_rect(x, y, 1, 1);
|
|
||||||
autoslice_cache.push_back(new_rect);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,9 @@ class TextureRegionEditor : public Control {
|
||||||
Rect2 rect_prev;
|
Rect2 rect_prev;
|
||||||
float prev_margin;
|
float prev_margin;
|
||||||
int edited_margin;
|
int edited_margin;
|
||||||
|
Map<RID, List<Rect2> > cache_map;
|
||||||
List<Rect2> autoslice_cache;
|
List<Rect2> autoslice_cache;
|
||||||
|
bool autoslice_is_dirty;
|
||||||
|
|
||||||
bool drag;
|
bool drag;
|
||||||
bool creating;
|
bool creating;
|
||||||
|
@ -110,6 +112,7 @@ class TextureRegionEditor : public Control {
|
||||||
void _zoom_reset();
|
void _zoom_reset();
|
||||||
void _zoom_out();
|
void _zoom_out();
|
||||||
void apply_rect(const Rect2 &rect);
|
void apply_rect(const Rect2 &rect);
|
||||||
|
void _update_autoslice();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
|
|
Loading…
Reference in New Issue