summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/editor/plugins/tile_map_editor_plugin.cpp144
-rw-r--r--tools/editor/plugins/tile_map_editor_plugin.h10
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);