Make tilemap lines/rectangles their own tools

This commit is contained in:
Marcus Elg 2020-06-18 10:29:37 +02:00
parent 277d2f1f50
commit 8e2608b2d6
2 changed files with 178 additions and 44 deletions

View file

@ -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"));
if (mb->get_shift()) {
if (mb->get_command()) {
tool = TOOL_RECTANGLE_ERASE;
} else {
tool = TOOL_LINE_ERASE;
}
selection_active = false;
rectangle_begin = local;
} else {
tool = TOOL_ERASING;
_set_cell(local, invalid_cell);
}
tool = TOOL_ERASING;
_set_cell(local, invalid_cell);
_update_button_tool();
return true;
}
} else {
if (tool == TOOL_ERASING || tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) {
_finish_undo();
if (tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) {
CanvasItemEditor::get_singleton()->update_viewport();
if (tool == TOOL_LINE_ERASE) {
if (!mouse_down) {
return true;
}
tool = TOOL_NONE;
tool = TOOL_LINE_PAINT;
_update_button_tool();
return true;
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();
CanvasItemEditor::get_singleton()->update_viewport();
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();
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();
CanvasItemEditor::get_singleton()->update_viewport();
mouse_down = false;
return true;
}
mouse_down = false;
tool = TOOL_RECTANGLE_PAINT;
}
if (tool == TOOL_ERASING) {
tool = TOOL_NONE;
_update_button_tool();
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));

View file

@ -88,6 +88,8 @@ class TileMapEditor : public VBoxContainer {
MenuButton *options;
Button *paint_button;
Button *line_button;
Button *rectangle_button;
Button *bucket_fill_button;
Button *picker_button;
Button *select_button;
@ -106,6 +108,7 @@ class TileMapEditor : public VBoxContainer {
bool selection_active;
bool mouse_over;
bool mouse_down;
bool flip_h;
bool flip_v;