|
@@ -64,6 +64,8 @@ void TileMapEditor::_notification(int p_what) {
|
|
|
}
|
|
|
|
|
|
paint_button->set_icon(get_theme_icon("Edit", "EditorIcons"));
|
|
|
+ line_button->set_icon(get_theme_icon("CurveLinear", "EditorIcons"));
|
|
|
+ rectangle_button->set_icon(get_theme_icon("RectangleShape2D", "EditorIcons"));
|
|
|
bucket_fill_button->set_icon(get_theme_icon("Bucket", "EditorIcons"));
|
|
|
picker_button->set_icon(get_theme_icon("ColorPick", "EditorIcons"));
|
|
|
select_button->set_icon(get_theme_icon("ActionCopy", "EditorIcons"));
|
|
@@ -91,9 +93,10 @@ void TileMapEditor::_notification(int p_what) {
|
|
|
}
|
|
|
|
|
|
void TileMapEditor::_update_button_tool() {
|
|
|
- Button *tb[4] = { paint_button, bucket_fill_button, picker_button, select_button };
|
|
|
+ Button *tb[6] = { paint_button, line_button, rectangle_button, bucket_fill_button, picker_button, select_button };
|
|
|
+
|
|
|
// Unpress all buttons
|
|
|
- for (int i = 0; i < 4; i++) {
|
|
|
+ for (int i = 0; i < 6; i++) {
|
|
|
tb[i]->set_pressed(false);
|
|
|
}
|
|
|
|
|
@@ -103,6 +106,12 @@ void TileMapEditor::_update_button_tool() {
|
|
|
case TOOL_PAINTING: {
|
|
|
paint_button->set_pressed(true);
|
|
|
} break;
|
|
|
+ case TOOL_LINE_PAINT: {
|
|
|
+ line_button->set_pressed(true);
|
|
|
+ } break;
|
|
|
+ case TOOL_RECTANGLE_PAINT: {
|
|
|
+ rectangle_button->set_pressed(true);
|
|
|
+ } break;
|
|
|
case TOOL_BUCKET: {
|
|
|
bucket_fill_button->set_pressed(true);
|
|
|
} break;
|
|
@@ -993,19 +1002,8 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
|
|
|
}
|
|
|
|
|
|
if (tool == TOOL_NONE) {
|
|
|
- if (mb->get_shift()) {
|
|
|
- if (mb->get_command()) {
|
|
|
- tool = TOOL_RECTANGLE_PAINT;
|
|
|
- } else {
|
|
|
- tool = TOOL_LINE_PAINT;
|
|
|
- }
|
|
|
-
|
|
|
- selection_active = false;
|
|
|
- rectangle_begin = over_tile;
|
|
|
-
|
|
|
- _update_button_tool();
|
|
|
- return true;
|
|
|
- }
|
|
|
+ tool = TOOL_PAINTING;
|
|
|
+ _update_button_tool();
|
|
|
|
|
|
if (mb->get_command()) {
|
|
|
tool = TOOL_PICKING;
|
|
@@ -1014,12 +1012,14 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
-
|
|
|
- tool = TOOL_PAINTING;
|
|
|
- _update_button_tool();
|
|
|
}
|
|
|
|
|
|
- if (tool == TOOL_PAINTING) {
|
|
|
+ if (tool == TOOL_LINE_PAINT || tool == TOOL_RECTANGLE_PAINT) {
|
|
|
+ selection_active = false;
|
|
|
+ rectangle_begin = over_tile;
|
|
|
+
|
|
|
+ mouse_down = true;
|
|
|
+ } else if (tool == TOOL_PAINTING) {
|
|
|
Vector<int> ids = get_selected_tiles();
|
|
|
|
|
|
if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) {
|
|
@@ -1050,6 +1050,10 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
|
|
|
paint_undo.clear();
|
|
|
}
|
|
|
} else if (tool == TOOL_LINE_PAINT) {
|
|
|
+ if (!mouse_down) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
Vector<int> ids = get_selected_tiles();
|
|
|
|
|
|
if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) {
|
|
@@ -1062,8 +1066,17 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
|
|
|
paint_undo.clear();
|
|
|
|
|
|
CanvasItemEditor::get_singleton()->update_viewport();
|
|
|
+
|
|
|
+ mouse_down = false;
|
|
|
+ return true;
|
|
|
}
|
|
|
+
|
|
|
+ mouse_down = false;
|
|
|
} else if (tool == TOOL_RECTANGLE_PAINT) {
|
|
|
+ if (!mouse_down) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
Vector<int> ids = get_selected_tiles();
|
|
|
|
|
|
if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) {
|
|
@@ -1076,7 +1089,12 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
|
|
|
_finish_undo();
|
|
|
|
|
|
CanvasItemEditor::get_singleton()->update_viewport();
|
|
|
+
|
|
|
+ mouse_down = false;
|
|
|
+ return true;
|
|
|
}
|
|
|
+
|
|
|
+ mouse_down = false;
|
|
|
} else if (tool == TOOL_PASTING) {
|
|
|
Point2 ofs = over_tile - rectangle.position;
|
|
|
Vector<int> ids;
|
|
@@ -1141,6 +1159,28 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
|
|
|
|
|
|
if (tool == TOOL_PASTING) {
|
|
|
tool = TOOL_NONE;
|
|
|
+
|
|
|
+ CanvasItemEditor::get_singleton()->update_viewport();
|
|
|
+
|
|
|
+ _update_button_tool();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tool == TOOL_LINE_PAINT) {
|
|
|
+ tool = TOOL_LINE_ERASE;
|
|
|
+ mouse_down = true;
|
|
|
+ rectangle_begin = over_tile;
|
|
|
+
|
|
|
+ CanvasItemEditor::get_singleton()->update_viewport();
|
|
|
+
|
|
|
+ _update_button_tool();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tool == TOOL_RECTANGLE_PAINT) {
|
|
|
+ tool = TOOL_RECTANGLE_ERASE;
|
|
|
+ mouse_down = true;
|
|
|
+ rectangle_begin = over_tile;
|
|
|
copydata.clear();
|
|
|
|
|
|
CanvasItemEditor::get_singleton()->update_viewport();
|
|
@@ -1155,39 +1195,74 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
|
|
|
Point2 local = node->world_to_map(xform_inv.xform(mb->get_position()));
|
|
|
|
|
|
_start_undo(TTR("Erase TileMap"));
|
|
|
+ tool = TOOL_ERASING;
|
|
|
+ _set_cell(local, invalid_cell);
|
|
|
|
|
|
- if (mb->get_shift()) {
|
|
|
- if (mb->get_command()) {
|
|
|
- tool = TOOL_RECTANGLE_ERASE;
|
|
|
- } else {
|
|
|
- tool = TOOL_LINE_ERASE;
|
|
|
+ _update_button_tool();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ if (tool == TOOL_LINE_ERASE) {
|
|
|
+ if (!mouse_down) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ tool = TOOL_LINE_PAINT;
|
|
|
+ _update_button_tool();
|
|
|
+
|
|
|
+ Vector<int> ids = get_selected_tiles();
|
|
|
+
|
|
|
+ if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) {
|
|
|
+ _start_undo(TTR("Line Erase"));
|
|
|
+ for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
|
|
|
+ _set_cell(E->key(), invalid_cell, flip_h, flip_v, transpose);
|
|
|
}
|
|
|
+ _finish_undo();
|
|
|
+ paint_undo.clear();
|
|
|
|
|
|
- selection_active = false;
|
|
|
- rectangle_begin = local;
|
|
|
- } else {
|
|
|
- tool = TOOL_ERASING;
|
|
|
+ CanvasItemEditor::get_singleton()->update_viewport();
|
|
|
|
|
|
- _set_cell(local, invalid_cell);
|
|
|
+ mouse_down = false;
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
+ mouse_down = false;
|
|
|
+ } else if (tool == TOOL_RECTANGLE_ERASE) {
|
|
|
+ if (!mouse_down) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ tool = TOOL_RECTANGLE_PAINT;
|
|
|
_update_button_tool();
|
|
|
- return true;
|
|
|
- }
|
|
|
|
|
|
- } else {
|
|
|
- if (tool == TOOL_ERASING || tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) {
|
|
|
- _finish_undo();
|
|
|
+ Vector<int> ids = get_selected_tiles();
|
|
|
+
|
|
|
+ if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) {
|
|
|
+ _start_undo(TTR("Rectangle Erase"));
|
|
|
+ for (int i = rectangle.position.y; i <= rectangle.position.y + rectangle.size.y; i++) {
|
|
|
+ for (int j = rectangle.position.x; j <= rectangle.position.x + rectangle.size.x; j++) {
|
|
|
+ _set_cell(Point2i(j, i), invalid_cell, flip_h, flip_v, transpose);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ _finish_undo();
|
|
|
+ paint_undo.clear();
|
|
|
|
|
|
- if (tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) {
|
|
|
CanvasItemEditor::get_singleton()->update_viewport();
|
|
|
+
|
|
|
+ mouse_down = false;
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
- tool = TOOL_NONE;
|
|
|
+ mouse_down = false;
|
|
|
+ tool = TOOL_RECTANGLE_PAINT;
|
|
|
+ }
|
|
|
|
|
|
+ if (tool == TOOL_ERASING) {
|
|
|
+ tool = TOOL_NONE;
|
|
|
_update_button_tool();
|
|
|
- return true;
|
|
|
|
|
|
+ return true;
|
|
|
} else if (tool == TOOL_BUCKET) {
|
|
|
Vector<int> ids;
|
|
|
ids.push_back(node->get_cell(over_tile.x, over_tile.y));
|
|
@@ -1278,6 +1353,10 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
|
|
|
Vector<int> tmp_cell;
|
|
|
bool erasing = (tool == TOOL_LINE_ERASE);
|
|
|
|
|
|
+ if (!mouse_down) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
tmp_cell.push_back(0);
|
|
|
if (erasing && paint_undo.size()) {
|
|
|
for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
|
|
@@ -1308,7 +1387,20 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
|
|
|
Vector<int> tmp_cell;
|
|
|
tmp_cell.push_back(0);
|
|
|
|
|
|
- _select(rectangle_begin, over_tile);
|
|
|
+ Point2i end_tile = over_tile;
|
|
|
+
|
|
|
+ if (!mouse_down) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mm->get_shift()) {
|
|
|
+ int size = fmax(ABS(end_tile.x - rectangle_begin.x), ABS(end_tile.y - rectangle_begin.y));
|
|
|
+ int xDirection = MAX(MIN(end_tile.x - rectangle_begin.x, 1), -1);
|
|
|
+ int yDirection = MAX(MIN(end_tile.y - rectangle_begin.y, 1), -1);
|
|
|
+ end_tile = rectangle_begin + Point2i(xDirection * size, yDirection * size);
|
|
|
+ }
|
|
|
+
|
|
|
+ _select(rectangle_begin, end_tile);
|
|
|
|
|
|
if (tool == TOOL_RECTANGLE_ERASE) {
|
|
|
if (paint_undo.size()) {
|
|
@@ -1379,6 +1471,20 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
|
|
|
_update_button_tool();
|
|
|
return true;
|
|
|
}
|
|
|
+ if (ED_IS_SHORTCUT("tile_map_editor/line_fill", p_event)) {
|
|
|
+ tool = TOOL_LINE_PAINT;
|
|
|
+ CanvasItemEditor::get_singleton()->update_viewport();
|
|
|
+
|
|
|
+ _update_button_tool();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if (ED_IS_SHORTCUT("tile_map_editor/rectangle_fill", p_event)) {
|
|
|
+ tool = TOOL_RECTANGLE_PAINT;
|
|
|
+ CanvasItemEditor::get_singleton()->update_viewport();
|
|
|
+
|
|
|
+ _update_button_tool();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
if (ED_IS_SHORTCUT("tile_map_editor/bucket_fill", p_event)) {
|
|
|
tool = TOOL_BUCKET;
|
|
|
CanvasItemEditor::get_singleton()->update_viewport();
|
|
@@ -1637,6 +1743,10 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
|
|
|
}
|
|
|
|
|
|
if (tool == TOOL_LINE_PAINT) {
|
|
|
+ if (!mouse_down) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
if (paint_undo.empty()) {
|
|
|
return;
|
|
|
}
|
|
@@ -1652,6 +1762,10 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
|
|
|
}
|
|
|
|
|
|
} else if (tool == TOOL_RECTANGLE_PAINT) {
|
|
|
+ if (!mouse_down) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
Vector<int> ids = get_selected_tiles();
|
|
|
|
|
|
if (ids.size() == 1 && ids[0] == TileMap::INVALID_CELL) {
|
|
@@ -1865,6 +1979,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) {
|
|
|
tool = TOOL_NONE;
|
|
|
selection_active = false;
|
|
|
mouse_over = false;
|
|
|
+ mouse_down = false;
|
|
|
|
|
|
flip_h = false;
|
|
|
flip_v = false;
|
|
@@ -1962,11 +2077,27 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) {
|
|
|
paint_button = memnew(Button);
|
|
|
paint_button->set_flat(true);
|
|
|
paint_button->set_shortcut(ED_SHORTCUT("tile_map_editor/paint_tile", TTR("Paint Tile"), KEY_P));
|
|
|
- paint_button->set_tooltip(TTR("Shift+LMB: Line Draw\nShift+Ctrl+LMB: Rectangle Paint"));
|
|
|
+ paint_button->set_tooltip(TTR("RMB: Erase"));
|
|
|
paint_button->connect("pressed", callable_mp(this, &TileMapEditor::_button_tool_select), make_binds(TOOL_NONE));
|
|
|
paint_button->set_toggle_mode(true);
|
|
|
toolbar->add_child(paint_button);
|
|
|
|
|
|
+ line_button = memnew(Button);
|
|
|
+ line_button->set_flat(true);
|
|
|
+ line_button->set_shortcut(ED_SHORTCUT("tile_map_editor/line_fill", TTR("Line Fill"), KEY_L));
|
|
|
+ line_button->set_tooltip(TTR("RMB: Erase"));
|
|
|
+ line_button->connect("pressed", callable_mp(this, &TileMapEditor::_button_tool_select), make_binds(TOOL_LINE_PAINT));
|
|
|
+ line_button->set_toggle_mode(true);
|
|
|
+ toolbar->add_child(line_button);
|
|
|
+
|
|
|
+ rectangle_button = memnew(Button);
|
|
|
+ rectangle_button->set_flat(true);
|
|
|
+ rectangle_button->set_shortcut(ED_SHORTCUT("tile_map_editor/rectangle_fill", TTR("Rectangle Fill"), KEY_O));
|
|
|
+ rectangle_button->set_tooltip(TTR("Shift+LMB: Keep 1:1 proporsions\nRMB: Erase"));
|
|
|
+ rectangle_button->connect("pressed", callable_mp(this, &TileMapEditor::_button_tool_select), make_binds(TOOL_RECTANGLE_PAINT));
|
|
|
+ rectangle_button->set_toggle_mode(true);
|
|
|
+ toolbar->add_child(rectangle_button);
|
|
|
+
|
|
|
bucket_fill_button = memnew(Button);
|
|
|
bucket_fill_button->set_flat(true);
|
|
|
bucket_fill_button->set_shortcut(ED_SHORTCUT("tile_map_editor/bucket_fill", TTR("Bucket Fill"), KEY_B));
|