From 2a60bf1cd975e80d28965e42577080681af05914 Mon Sep 17 00:00:00 2001 From: Marc Gilleron Date: Sat, 31 Dec 2016 17:42:05 +0100 Subject: [PATCH] Added bucket fill preview (cherry picked from commit 36d0281a2bc0b89f3566382113905b929216969c) --- .../editor/plugins/tile_map_editor_plugin.cpp | 84 +++++++++++++++++-- tools/editor/plugins/tile_map_editor_plugin.h | 11 ++- 2 files changed, 87 insertions(+), 8 deletions(-) diff --git a/tools/editor/plugins/tile_map_editor_plugin.cpp b/tools/editor/plugins/tile_map_editor_plugin.cpp index 43fe7d7ea9..00c89534cf 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.cpp +++ b/tools/editor/plugins/tile_map_editor_plugin.cpp @@ -289,7 +289,7 @@ void TileMapEditor::_pick_tile(const Point2& p_pos) { canvas_item_editor->update(); } -DVector TileMapEditor::_bucket_fill(const Point2i& p_start, bool erase) { +DVector TileMapEditor::_bucket_fill(const Point2i& p_start, bool erase, bool preview) { int prev_id = node->get_cell(p_start.x, p_start.y); int id = TileMap::INVALID_CELL; @@ -300,10 +300,39 @@ DVector TileMapEditor::_bucket_fill(const Point2i& p_start, bool erase) return DVector(); } - Rect2 r = node->get_item_rect(); + Rect2i r = node->get_item_rect(); r.pos = r.pos/node->get_cell_size(); r.size = r.size/node->get_cell_size(); + int area = r.get_area(); + if(preview) { + // Test if we can re-use the result from preview bucket fill + bool invalidate_cache = false; + // Area changed + if(r != bucket_cache_rect) + _clear_bucket_cache(); + // Cache grid is not initialized + if(bucket_cache_visited == 0) { + bucket_cache_visited = new bool[area]; + invalidate_cache = true; + } + // Tile ID changed or position wasn't visited by the previous fill + int loc = (p_start.x - r.get_pos().x) + (p_start.y - r.get_pos().y) * r.get_size().x; + if(prev_id != bucket_cache_tile || !bucket_cache_visited[loc]) { + invalidate_cache = true; + } + if(invalidate_cache) { + for(int i = 0; i < area; ++i) + bucket_cache_visited[i] = false; + bucket_cache = DVector(); + bucket_cache_tile = prev_id; + bucket_cache_rect = r; + } + else { + return bucket_cache; + } + } + DVector points; List queue; @@ -319,9 +348,17 @@ DVector TileMapEditor::_bucket_fill(const Point2i& p_start, bool erase) if (node->get_cell(n.x, n.y) == prev_id) { - node->set_cellv(n, id, flip_h, flip_v, transpose); - - points.push_back(n); + if(preview) { + int loc = (n.x - r.get_pos().x) + (n.y - r.get_pos().y) * r.get_size().x; + if(bucket_cache_visited[loc]) + continue; + bucket_cache_visited[loc] = true; + bucket_cache.push_back(n); + } + else { + node->set_cellv(n, id, flip_h, flip_v, transpose); + points.push_back(n); + } queue.push_back(n + Point2i(0, 1)); queue.push_back(n + Point2i(0, -1)); @@ -330,7 +367,7 @@ DVector TileMapEditor::_bucket_fill(const Point2i& p_start, bool erase) } } - return points; + return preview ? bucket_cache : points; } void TileMapEditor::_fill_points(const DVector p_points, const Dictionary& p_op) { @@ -468,6 +505,25 @@ void TileMapEditor::_draw_cell(int p_cell, const Point2i& p_point, bool p_flip_h canvas_item_editor->draw_texture_rect_region(t, rect, r, Color(1,1,1,0.5), p_transpose); } +void TileMapEditor::_draw_fill_preview(int p_cell, const Point2i& p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Matrix32& p_xform) { + + DVector points = _bucket_fill(p_point, false, true); + DVector::Read pr = points.read(); + int len = points.size(); + int time_after = OS::get_singleton()->get_ticks_msec(); + + for(int i = 0; i < len; ++i) { + _draw_cell(p_cell, pr[i], p_flip_h, p_flip_v, p_transpose, p_xform); + } +} + +void TileMapEditor::_clear_bucket_cache() { + if(bucket_cache_visited) { + delete[] bucket_cache_visited; + bucket_cache_visited = 0; + } +} + void TileMapEditor::_update_copydata() { copydata.clear(); @@ -1148,7 +1204,7 @@ void TileMapEditor::_canvas_draw() { canvas_item_editor->draw_line(endpoints[i],endpoints[(i+1)%4],col,2); - if (tool==TOOL_SELECTING || tool==TOOL_PICKING || tool==TOOL_BUCKET) { + if (tool==TOOL_SELECTING || tool==TOOL_PICKING) { return; } @@ -1214,6 +1270,11 @@ void TileMapEditor::_canvas_draw() { canvas_item_editor->draw_colored_polygon(points, Color(0.2,1.0,0.8,0.2)); + } else if(tool == TOOL_BUCKET) { + + int tile = get_selected_tile(); + _draw_fill_preview(tile, over_tile, flip_h, flip_v, transpose, xform); + } else { int st = get_selected_tile(); @@ -1264,6 +1325,8 @@ void TileMapEditor::edit(Node *p_tile_map) { if (node) node->connect("settings_changed",this,"_tileset_settings_changed"); + _clear_bucket_cache(); + } void TileMapEditor::_tileset_settings_changed() { @@ -1365,6 +1428,9 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { flip_v=false; transpose=false; + bucket_cache_tile = -1; + bucket_cache_visited = 0; + ED_SHORTCUT("tile_map_editor/erase_selection", TTR("Erase selection"), KEY_DELETE); ED_SHORTCUT("tile_map_editor/find_tile", TTR("Find tile"), KEY_MASK_CMD+KEY_F); ED_SHORTCUT("tile_map_editor/transpose", TTR("Transpose")); @@ -1479,6 +1545,10 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { rotate_0->set_pressed(true); } +TileMapEditor::~TileMapEditor() { + _clear_bucket_cache(); +} + /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// diff --git a/tools/editor/plugins/tile_map_editor_plugin.h b/tools/editor/plugins/tile_map_editor_plugin.h index 4b47dccd15..4df439db6b 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.h +++ b/tools/editor/plugins/tile_map_editor_plugin.h @@ -106,6 +106,11 @@ class TileMapEditor : public VBoxContainer { Point2i over_tile; + bool * bucket_cache_visited; + Rect2i bucket_cache_rect; + int bucket_cache_tile; + DVector bucket_cache; + struct CellOp { int idx; bool xf; @@ -129,7 +134,7 @@ class TileMapEditor : public VBoxContainer { void _pick_tile(const Point2& p_pos); - DVector _bucket_fill(const Point2i& p_start, bool erase=false); + DVector _bucket_fill(const Point2i& p_start, bool erase=false, bool preview=false); void _fill_points(const DVector p_points, const Dictionary& p_op); void _erase_points(const DVector p_points); @@ -137,6 +142,9 @@ class TileMapEditor : public VBoxContainer { void _select(const Point2i& p_from, const Point2i& p_to); void _draw_cell(int p_cell, const Point2i& p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Matrix32& p_xform); + void _draw_fill_preview(int p_cell, const Point2i& p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Matrix32& p_xform); + void _clear_bucket_cache(); + void _update_copydata(); int get_selected_tile() const; @@ -171,6 +179,7 @@ public: void edit(Node *p_tile_map); TileMapEditor(EditorNode *p_editor); + ~TileMapEditor(); }; class TileMapEditorPlugin : public EditorPlugin {