Added bucket fill preview

This commit is contained in:
Marc Gilleron 2016-12-31 17:42:05 +01:00
parent 86e428eea0
commit 36d0281a2b
2 changed files with 87 additions and 8 deletions

View file

@ -289,7 +289,7 @@ void TileMapEditor::_pick_tile(const Point2& p_pos) {
canvas_item_editor->update();
}
DVector<Vector2> TileMapEditor::_bucket_fill(const Point2i& p_start, bool erase) {
DVector<Vector2> 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<Vector2> TileMapEditor::_bucket_fill(const Point2i& p_start, bool erase)
return DVector<Vector2>();
}
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<Vector2>();
bucket_cache_tile = prev_id;
bucket_cache_rect = r;
}
else {
return bucket_cache;
}
}
DVector<Vector2> points;
List<Point2i> queue;
@ -319,9 +348,17 @@ DVector<Vector2> 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<Vector2> TileMapEditor::_bucket_fill(const Point2i& p_start, bool erase)
}
}
return points;
return preview ? bucket_cache : points;
}
void TileMapEditor::_fill_points(const DVector<Vector2> 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<Vector2> points = _bucket_fill(p_point, false, true);
DVector<Vector2>::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();
}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////

View file

@ -106,6 +106,11 @@ class TileMapEditor : public VBoxContainer {
Point2i over_tile;
bool * bucket_cache_visited;
Rect2i bucket_cache_rect;
int bucket_cache_tile;
DVector<Vector2> bucket_cache;
struct CellOp {
int idx;
bool xf;
@ -129,7 +134,7 @@ class TileMapEditor : public VBoxContainer {
void _pick_tile(const Point2& p_pos);
DVector<Vector2> _bucket_fill(const Point2i& p_start, bool erase=false);
DVector<Vector2> _bucket_fill(const Point2i& p_start, bool erase=false, bool preview=false);
void _fill_points(const DVector<Vector2> p_points, const Dictionary& p_op);
void _erase_points(const DVector<Vector2> 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 {