瀏覽代碼

Merge pull request #39637 from MCrafterzz/tilemapinprovements

Make tilemap lines/rectangles their own tools
Rémi Verschelde 5 年之前
父節點
當前提交
db168abe7d
共有 2 個文件被更改,包括 173 次插入39 次删除
  1. 170 39
      editor/plugins/tile_map_editor_plugin.cpp
  2. 3 0
      editor/plugins/tile_map_editor_plugin.h

+ 170 - 39
editor/plugins/tile_map_editor_plugin.cpp

@@ -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));

+ 3 - 0
editor/plugins/tile_map_editor_plugin.h

@@ -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;