diff options
-rw-r--r-- | tools/editor/plugins/tile_map_editor_plugin.cpp | 144 | ||||
-rw-r--r-- | tools/editor/plugins/tile_map_editor_plugin.h | 10 |
2 files changed, 136 insertions, 18 deletions
diff --git a/tools/editor/plugins/tile_map_editor_plugin.cpp b/tools/editor/plugins/tile_map_editor_plugin.cpp index e0d08c0756..f6007a63f5 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.cpp +++ b/tools/editor/plugins/tile_map_editor_plugin.cpp @@ -58,6 +58,12 @@ void TileMapEditor::_menu_option(int p_option) { switch(p_option) { + case OPTION_BUCKET_FILL: { + + tool=TOOL_BUCKET; + + canvas_item_editor->update(); + } break; case OPTION_PICK_TILE: { tool=TOOL_PICKING; @@ -270,6 +276,84 @@ void TileMapEditor::_pick_tile(const Point2& p_pos) { canvas_item_editor->update(); } +#define BUCKET_FILL_LIMIT 50 + +DVector<Vector2> TileMapEditor::_bucket_fill(const Point2i& p_start) { + + if (node->get_cell(p_start.x, p_start.y) != TileMap::INVALID_CELL) + return DVector<Vector2>(); + + int id = get_selected_tile(); + + if (id == TileMap::INVALID_CELL) + return DVector<Vector2>(); + + int len = 0; + + DVector<Vector2> points; + points.resize(Math::pow(BUCKET_FILL_LIMIT*2, 2)); + + List<Point2i> queue; + queue.push_back(p_start); + + DVector<Vector2>::Write pw = points.write(); + + while (queue.size()) { + + Point2i n = queue.front()->get(); + queue.pop_front(); + + if (ABS(n.x - p_start.x) > BUCKET_FILL_LIMIT || ABS(n.y - p_start.y) > BUCKET_FILL_LIMIT) + continue; + + if (node->get_cell(n.x, n.y) == TileMap::INVALID_CELL) { + + node->set_cellv(n, id, flip_h, flip_v, transpose); + + pw[++len] = n; + + queue.push_back(n + Point2i(0, 1)); + queue.push_back(n + Point2i(0, -1)); + queue.push_back(n + Point2i(1, 0)); + queue.push_back(n + Point2i(-1, 0)); + } + } + + pw = DVector<Vector2>::Write(); + points.resize(len); + + return points; +} + +#undef BUCKET_FILL_LIMIT + +void TileMapEditor::_fill_points(const DVector<Vector2> p_points, const Dictionary& p_op) { + + int len = p_points.size(); + DVector<Vector2>::Read pr = p_points.read(); + + int id = p_op["id"]; + bool xf = p_op["flip_h"]; + bool yf = p_op["flip_v"]; + bool tr = p_op["transpose"]; + + for (int i=0;i<len;i++) { + + _set_cell(pr[i], id, xf, yf, tr); + } +} + +void TileMapEditor::_erase_points(const DVector<Vector2> p_points) { + + int len = p_points.size(); + DVector<Vector2>::Read pr = p_points.read(); + + for (int i=0;i<len;i++) { + + _set_cell(pr[i], TileMap::INVALID_CELL); + } +} + void TileMapEditor::_select(const Point2i& p_from, const Point2i& p_to) { Point2i begin=p_from; @@ -514,24 +598,10 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { return true; } - if (tool==TOOL_DUPLICATING) { - - Point2 ofs = over_tile-rectangle.pos; - - undo_redo->create_action("Duplicate"); - for (List<TileData>::Element *E=copydata.front();E;E=E->next()) { - - _set_cell(E->get().pos+ofs,E->get().cell,E->get().flip_h,E->get().flip_v,E->get().transpose,true); - } - undo_redo->commit_action(); - - tool=TOOL_NONE; - copydata.clear(); - - canvas_item_editor->update(); - + if (tool!=TOOL_NONE) { return true; } + } else { if (tool!=TOOL_NONE) { @@ -585,9 +655,44 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { canvas_item_editor->update(); } + } else if (tool==TOOL_DUPLICATING) { + + Point2 ofs = over_tile-rectangle.pos; + + undo_redo->create_action("Duplicate"); + for (List<TileData>::Element *E=copydata.front();E;E=E->next()) { + + _set_cell(E->get().pos+ofs,E->get().cell,E->get().flip_h,E->get().flip_v,E->get().transpose,true); + } + undo_redo->commit_action(); + + copydata.clear(); + + canvas_item_editor->update(); + } else if (tool==TOOL_SELECTING) { canvas_item_editor->update(); + + } else if (tool==TOOL_BUCKET) { + + DVector<Vector2> points = _bucket_fill(over_tile); + + if (points.size() == 0) + return false; + + Dictionary op; + op["id"] = get_selected_tile(); + op["flip_h"] = flip_h; + op["flip_v"] = flip_v; + op["transpose"] = transpose; + + undo_redo->create_action("Bucket Fill"); + + undo_redo->add_do_method(this, "_fill_points", points, op); + undo_redo->add_undo_method(this, "_erase_points", points); + + undo_redo->commit_action(); } tool=TOOL_NONE; @@ -1011,7 +1116,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) { + if (tool==TOOL_SELECTING || tool==TOOL_PICKING || tool==TOOL_BUCKET) { return; } @@ -1148,6 +1253,9 @@ void TileMapEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("_canvas_mouse_exit"),&TileMapEditor::_canvas_mouse_exit); ObjectTypeDB::bind_method(_MD("_tileset_settings_changed"),&TileMapEditor::_tileset_settings_changed); ObjectTypeDB::bind_method(_MD("_update_transform_buttons"),&TileMapEditor::_update_transform_buttons); + + ObjectTypeDB::bind_method(_MD("_fill_points"),&TileMapEditor::_fill_points); + ObjectTypeDB::bind_method(_MD("_erase_points"),&TileMapEditor::_erase_points); } TileMapEditor::CellOp TileMapEditor::_get_op_from_cell(const Point2i& p_pos) @@ -1242,6 +1350,8 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { PopupMenu *p = options->get_popup(); + p->add_item("Bucket Fill", OPTION_BUCKET_FILL); + p->add_separator(); p->add_item("Pick Tile", OPTION_PICK_TILE, KEY_CONTROL); p->add_separator(); p->add_item("Select", OPTION_SELECT, KEY_MASK_SHIFT+KEY_B); diff --git a/tools/editor/plugins/tile_map_editor_plugin.h b/tools/editor/plugins/tile_map_editor_plugin.h index 4152a07a97..c0021d2975 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.h +++ b/tools/editor/plugins/tile_map_editor_plugin.h @@ -55,12 +55,14 @@ class TileMapEditor : public VBoxContainer { TOOL_LINE_PAINT, TOOL_LINE_ERASE, TOOL_SELECTING, + TOOL_BUCKET, + TOOL_PICKING, TOOL_DUPLICATING, - TOOL_PICKING }; enum Options { + OPTION_BUCKET_FILL, OPTION_PICK_TILE, OPTION_SELECT, OPTION_DUPLICATE, @@ -123,6 +125,12 @@ class TileMapEditor : public VBoxContainer { List<TileData> copydata; void _pick_tile(const Point2& p_pos); + + DVector<Vector2> _bucket_fill(const Point2i& p_start); + + void _fill_points(const DVector<Vector2> p_points, const Dictionary& p_op); + void _erase_points(const DVector<Vector2> p_points); + 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); |