Merge pull request #7401 from Zylann/bucket_fill_preview
Bucket fill preview
This commit is contained in:
commit
3fc4ee6243
2 changed files with 89 additions and 9 deletions
|
@ -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,8 +1204,8 @@ 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) {
|
||||
|
||||
bool bucket_preview = EditorSettings::get_singleton()->get("tile_map/bucket_fill_preview");
|
||||
if (tool==TOOL_SELECTING || tool==TOOL_PICKING || !bucket_preview) {
|
||||
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();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
@ -1512,6 +1582,7 @@ TileMapEditorPlugin::TileMapEditorPlugin(EditorNode *p_node) {
|
|||
EDITOR_DEF("tile_map/preview_size",64);
|
||||
EDITOR_DEF("tile_map/palette_item_hseparation",8);
|
||||
EDITOR_DEF("tile_map/show_tile_names", true);
|
||||
EDITOR_DEF("tile_map/bucket_fill_preview", true);
|
||||
|
||||
tile_map_editor = memnew( TileMapEditor(p_node) );
|
||||
add_control_to_container(CONTAINER_CANVAS_EDITOR_SIDE, tile_map_editor);
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue