1 /*************************************************************************/
2 /*  tile_map_editor_plugin.cpp                                           */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
10 /*                                                                       */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the       */
13 /* "Software"), to deal in the Software without restriction, including   */
14 /* without limitation the rights to use, copy, modify, merge, publish,   */
15 /* distribute, sublicense, and/or sell copies of the Software, and to    */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions:                                             */
18 /*                                                                       */
19 /* The above copyright notice and this permission notice shall be        */
20 /* included in all copies or substantial portions of the Software.       */
21 /*                                                                       */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
29 /*************************************************************************/
30 
31 #include "tile_map_editor_plugin.h"
32 
33 #include "canvas_item_editor_plugin.h"
34 #include "core/math/math_funcs.h"
35 #include "core/os/input.h"
36 #include "core/os/keyboard.h"
37 #include "editor/editor_scale.h"
38 #include "editor/editor_settings.h"
39 #include "scene/gui/split_container.h"
40 
_node_removed(Node * p_node)41 void TileMapEditor::_node_removed(Node *p_node) {
42 
43 	if (p_node == node) {
44 		node = NULL;
45 	}
46 }
47 
_notification(int p_what)48 void TileMapEditor::_notification(int p_what) {
49 
50 	switch (p_what) {
51 
52 		case NOTIFICATION_PROCESS: {
53 
54 			if (bucket_queue.size()) {
55 				CanvasItemEditor::get_singleton()->update_viewport();
56 			}
57 
58 		} break;
59 
60 		case NOTIFICATION_ENTER_TREE: {
61 
62 			get_tree()->connect("node_removed", this, "_node_removed");
63 			FALLTHROUGH;
64 		}
65 
66 		case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
67 
68 			if (is_visible_in_tree()) {
69 				_update_palette();
70 			}
71 
72 			paint_button->set_icon(get_icon("Edit", "EditorIcons"));
73 			bucket_fill_button->set_icon(get_icon("Bucket", "EditorIcons"));
74 			picker_button->set_icon(get_icon("ColorPick", "EditorIcons"));
75 			select_button->set_icon(get_icon("ActionCopy", "EditorIcons"));
76 
77 			rotate_left_button->set_icon(get_icon("RotateLeft", "EditorIcons"));
78 			rotate_right_button->set_icon(get_icon("RotateRight", "EditorIcons"));
79 			flip_horizontal_button->set_icon(get_icon("MirrorX", "EditorIcons"));
80 			flip_vertical_button->set_icon(get_icon("MirrorY", "EditorIcons"));
81 			clear_transform_button->set_icon(get_icon("Clear", "EditorIcons"));
82 
83 			search_box->set_right_icon(get_icon("Search", "EditorIcons"));
84 			search_box->set_clear_button_enabled(true);
85 
86 			PopupMenu *p = options->get_popup();
87 			p->set_item_icon(p->get_item_index(OPTION_CUT), get_icon("ActionCut", "EditorIcons"));
88 			p->set_item_icon(p->get_item_index(OPTION_COPY), get_icon("Duplicate", "EditorIcons"));
89 			p->set_item_icon(p->get_item_index(OPTION_ERASE_SELECTION), get_icon("Remove", "EditorIcons"));
90 
91 		} break;
92 
93 		case NOTIFICATION_EXIT_TREE: {
94 			get_tree()->disconnect("node_removed", this, "_node_removed");
95 		} break;
96 	}
97 }
98 
_update_button_tool()99 void TileMapEditor::_update_button_tool() {
100 
101 	ToolButton *tb[4] = { paint_button, bucket_fill_button, picker_button, select_button };
102 	// Unpress all buttons
103 	for (int i = 0; i < 4; i++) {
104 		tb[i]->set_pressed(false);
105 	}
106 
107 	// Press the good button
108 	switch (tool) {
109 		case TOOL_NONE:
110 		case TOOL_PAINTING: {
111 			paint_button->set_pressed(true);
112 		} break;
113 		case TOOL_BUCKET: {
114 			bucket_fill_button->set_pressed(true);
115 		} break;
116 		case TOOL_PICKING: {
117 			picker_button->set_pressed(true);
118 		} break;
119 		case TOOL_SELECTING: {
120 			select_button->set_pressed(true);
121 		} break;
122 		default:
123 			break;
124 	}
125 
126 	if (tool != TOOL_PICKING)
127 		last_tool = tool;
128 }
129 
_button_tool_select(int p_tool)130 void TileMapEditor::_button_tool_select(int p_tool) {
131 	tool = (Tool)p_tool;
132 	_update_button_tool();
133 	switch (tool) {
134 		case TOOL_SELECTING: {
135 
136 			selection_active = false;
137 		} break;
138 		default:
139 			break;
140 	}
141 	CanvasItemEditor::get_singleton()->update_viewport();
142 }
143 
_menu_option(int p_option)144 void TileMapEditor::_menu_option(int p_option) {
145 
146 	switch (p_option) {
147 		case OPTION_COPY: {
148 
149 			_update_copydata();
150 
151 			if (selection_active) {
152 				tool = TOOL_PASTING;
153 
154 				CanvasItemEditor::get_singleton()->update_viewport();
155 			}
156 		} break;
157 		case OPTION_ERASE_SELECTION: {
158 
159 			if (!selection_active)
160 				return;
161 
162 			_start_undo(TTR("Erase Selection"));
163 			_erase_selection();
164 			_finish_undo();
165 
166 			selection_active = false;
167 			copydata.clear();
168 
169 			CanvasItemEditor::get_singleton()->update_viewport();
170 		} break;
171 		case OPTION_FIX_INVALID: {
172 
173 			undo_redo->create_action(TTR("Fix Invalid Tiles"));
174 			undo_redo->add_undo_method(node, "set", "tile_data", node->get("tile_data"));
175 			node->fix_invalid_tiles();
176 			undo_redo->add_do_method(node, "set", "tile_data", node->get("tile_data"));
177 			undo_redo->commit_action();
178 
179 		} break;
180 		case OPTION_CUT: {
181 
182 			if (selection_active) {
183 				_update_copydata();
184 
185 				_start_undo(TTR("Cut Selection"));
186 				_erase_selection();
187 				_finish_undo();
188 
189 				selection_active = false;
190 
191 				tool = TOOL_PASTING;
192 
193 				CanvasItemEditor::get_singleton()->update_viewport();
194 			}
195 		} break;
196 	}
197 	_update_button_tool();
198 }
199 
_palette_selected(int index)200 void TileMapEditor::_palette_selected(int index) {
201 	_update_palette();
202 }
203 
_palette_multi_selected(int index,bool selected)204 void TileMapEditor::_palette_multi_selected(int index, bool selected) {
205 	_update_palette();
206 }
207 
_palette_input(const Ref<InputEvent> & p_event)208 void TileMapEditor::_palette_input(const Ref<InputEvent> &p_event) {
209 	const Ref<InputEventMouseButton> mb = p_event;
210 
211 	// Zoom in/out using Ctrl + mouse wheel.
212 	if (mb.is_valid() && mb->is_pressed() && mb->get_command()) {
213 		if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_UP) {
214 			size_slider->set_value(size_slider->get_value() + 0.2);
215 		}
216 
217 		if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_DOWN) {
218 			size_slider->set_value(size_slider->get_value() - 0.2);
219 		}
220 	}
221 }
222 
_canvas_mouse_enter()223 void TileMapEditor::_canvas_mouse_enter() {
224 
225 	mouse_over = true;
226 	CanvasItemEditor::get_singleton()->update_viewport();
227 }
228 
_canvas_mouse_exit()229 void TileMapEditor::_canvas_mouse_exit() {
230 
231 	mouse_over = false;
232 	CanvasItemEditor::get_singleton()->update_viewport();
233 }
234 
get_selected_tiles() const235 Vector<int> TileMapEditor::get_selected_tiles() const {
236 
237 	Vector<int> items = palette->get_selected_items();
238 
239 	if (items.size() == 0) {
240 		items.push_back(TileMap::INVALID_CELL);
241 		return items;
242 	}
243 
244 	for (int i = items.size() - 1; i >= 0; i--) {
245 		items.write[i] = palette->get_item_metadata(items[i]);
246 	}
247 	return items;
248 }
249 
set_selected_tiles(Vector<int> p_tiles)250 void TileMapEditor::set_selected_tiles(Vector<int> p_tiles) {
251 
252 	palette->unselect_all();
253 
254 	for (int i = p_tiles.size() - 1; i >= 0; i--) {
255 		int idx = palette->find_metadata(p_tiles[i]);
256 
257 		if (idx >= 0) {
258 			palette->select(idx, false);
259 		}
260 	}
261 
262 	palette->ensure_current_is_visible();
263 }
264 
_create_cell_dictionary(int tile,bool flip_x,bool flip_y,bool transpose,Vector2 autotile_coord)265 Dictionary TileMapEditor::_create_cell_dictionary(int tile, bool flip_x, bool flip_y, bool transpose, Vector2 autotile_coord) {
266 
267 	Dictionary cell;
268 
269 	cell["id"] = tile;
270 	cell["flip_h"] = flip_x;
271 	cell["flip_y"] = flip_y;
272 	cell["transpose"] = transpose;
273 	cell["auto_coord"] = autotile_coord;
274 
275 	return cell;
276 }
277 
_create_set_cell_undo_redo(const Vector2 & p_vec,const CellOp & p_cell_old,const CellOp & p_cell_new)278 void TileMapEditor::_create_set_cell_undo_redo(const Vector2 &p_vec, const CellOp &p_cell_old, const CellOp &p_cell_new) {
279 
280 	Dictionary cell_old = _create_cell_dictionary(p_cell_old.idx, p_cell_old.xf, p_cell_old.yf, p_cell_old.tr, p_cell_old.ac);
281 	Dictionary cell_new = _create_cell_dictionary(p_cell_new.idx, p_cell_new.xf, p_cell_new.yf, p_cell_new.tr, p_cell_new.ac);
282 
283 	undo_redo->add_undo_method(node, "_set_celld", p_vec, cell_old);
284 	undo_redo->add_do_method(node, "_set_celld", p_vec, cell_new);
285 }
286 
_start_undo(const String & p_action)287 void TileMapEditor::_start_undo(const String &p_action) {
288 
289 	undo_data.clear();
290 	undo_redo->create_action(p_action);
291 }
292 
_finish_undo()293 void TileMapEditor::_finish_undo() {
294 
295 	if (undo_data.size()) {
296 		for (Map<Point2i, CellOp>::Element *E = undo_data.front(); E; E = E->next()) {
297 			_create_set_cell_undo_redo(E->key(), E->get(), _get_op_from_cell(E->key()));
298 		}
299 
300 		undo_data.clear();
301 	}
302 
303 	undo_redo->commit_action();
304 }
305 
_set_cell(const Point2i & p_pos,Vector<int> p_values,bool p_flip_h,bool p_flip_v,bool p_transpose,const Point2i & p_autotile_coord)306 void TileMapEditor::_set_cell(const Point2i &p_pos, Vector<int> p_values, bool p_flip_h, bool p_flip_v, bool p_transpose, const Point2i &p_autotile_coord) {
307 
308 	ERR_FAIL_COND(!node);
309 
310 	if (p_values.size() == 0)
311 		return;
312 
313 	int p_value = p_values[Math::rand() % p_values.size()];
314 	int prev_val = node->get_cell(p_pos.x, p_pos.y);
315 
316 	bool prev_flip_h = node->is_cell_x_flipped(p_pos.x, p_pos.y);
317 	bool prev_flip_v = node->is_cell_y_flipped(p_pos.x, p_pos.y);
318 	bool prev_transpose = node->is_cell_transposed(p_pos.x, p_pos.y);
319 	Vector2 prev_position = node->get_cell_autotile_coord(p_pos.x, p_pos.y);
320 
321 	Vector2 position;
322 	int current = manual_palette->get_current();
323 	if (current != -1) {
324 		if (tool != TOOL_PASTING) {
325 			position = manual_palette->get_item_metadata(current);
326 		} else {
327 			position = p_autotile_coord;
328 		}
329 	} else {
330 		// If there is no manual tile selected, that either means that
331 		// autotiling is enabled, or the given tile is not autotiling. Either
332 		// way, the coordinate of the tile does not matter, so assigning it to
333 		// the coordinate of the existing tile works fine.
334 		position = prev_position;
335 	}
336 
337 	if (p_value == prev_val && p_flip_h == prev_flip_h && p_flip_v == prev_flip_v && p_transpose == prev_transpose && prev_position == position)
338 		return; // Check that it's actually different.
339 
340 	for (int y = p_pos.y - 1; y <= p_pos.y + 1; y++) {
341 		for (int x = p_pos.x - 1; x <= p_pos.x + 1; x++) {
342 			Point2i p = Point2i(x, y);
343 			if (!undo_data.has(p)) {
344 				undo_data[p] = _get_op_from_cell(p);
345 			}
346 		}
347 	}
348 
349 	node->_set_celld(p_pos, _create_cell_dictionary(p_value, p_flip_h, p_flip_v, p_transpose, p_autotile_coord));
350 
351 	if (tool == TOOL_PASTING)
352 		return;
353 
354 	if (manual_autotile || (p_value != -1 && node->get_tileset()->tile_get_tile_mode(p_value) == TileSet::ATLAS_TILE)) {
355 		if (current != -1) {
356 			node->set_cell_autotile_coord(p_pos.x, p_pos.y, position);
357 		} else if (node->get_tileset()->tile_get_tile_mode(p_value) == TileSet::ATLAS_TILE && priority_atlastile) {
358 			// BIND_CENTER is used to indicate that bitmask should not update for this tile cell.
359 			node->get_tileset()->autotile_set_bitmask(p_value, Vector2(p_pos.x, p_pos.y), TileSet::BIND_CENTER);
360 			node->update_cell_bitmask(p_pos.x, p_pos.y);
361 		}
362 	} else {
363 		node->update_bitmask_area(Point2(p_pos));
364 	}
365 }
366 
_manual_toggled(bool p_enabled)367 void TileMapEditor::_manual_toggled(bool p_enabled) {
368 	manual_autotile = p_enabled;
369 	_update_palette();
370 }
371 
_priority_toggled(bool p_enabled)372 void TileMapEditor::_priority_toggled(bool p_enabled) {
373 	priority_atlastile = p_enabled;
374 	_update_palette();
375 }
376 
_text_entered(const String & p_text)377 void TileMapEditor::_text_entered(const String &p_text) {
378 
379 	canvas_item_editor_viewport->grab_focus();
380 }
381 
_text_changed(const String & p_text)382 void TileMapEditor::_text_changed(const String &p_text) {
383 	_update_palette();
384 }
385 
_sbox_input(const Ref<InputEvent> & p_ie)386 void TileMapEditor::_sbox_input(const Ref<InputEvent> &p_ie) {
387 
388 	Ref<InputEventKey> k = p_ie;
389 
390 	if (k.is_valid() && (k->get_scancode() == KEY_UP ||
391 								k->get_scancode() == KEY_DOWN ||
392 								k->get_scancode() == KEY_PAGEUP ||
393 								k->get_scancode() == KEY_PAGEDOWN)) {
394 
395 		palette->call("_gui_input", k);
396 		search_box->accept_event();
397 	}
398 }
399 
400 // Implementation detail of TileMapEditor::_update_palette();
401 // In modern C++ this could have been inside its body.
402 namespace {
403 struct _PaletteEntry {
404 	int id;
405 	String name;
406 
operator <__anond3b8d91f0111::_PaletteEntry407 	bool operator<(const _PaletteEntry &p_rhs) const {
408 		return name < p_rhs.name;
409 	}
410 };
411 } // namespace
412 
_update_palette()413 void TileMapEditor::_update_palette() {
414 
415 	if (!node)
416 		return;
417 
418 	// Update the clear button.
419 	clear_transform_button->set_disabled(!flip_h && !flip_v && !transpose);
420 
421 	// Update the palette.
422 	Vector<int> selected = get_selected_tiles();
423 	int selected_single = palette->get_current();
424 	int selected_manual = manual_palette->get_current();
425 	palette->clear();
426 	manual_palette->clear();
427 	manual_palette->hide();
428 
429 	Ref<TileSet> tileset = node->get_tileset();
430 	if (tileset.is_null()) {
431 		search_box->set_text("");
432 		search_box->set_editable(false);
433 		info_message->show();
434 		return;
435 	}
436 
437 	search_box->set_editable(true);
438 	info_message->hide();
439 
440 	List<int> tiles;
441 	tileset->get_tile_list(&tiles);
442 	if (tiles.empty())
443 		return;
444 
445 	float min_size = EDITOR_DEF("editors/tile_map/preview_size", 64);
446 	min_size *= EDSCALE;
447 	int hseparation = EDITOR_DEF("editors/tile_map/palette_item_hseparation", 8);
448 	bool show_tile_names = bool(EDITOR_DEF("editors/tile_map/show_tile_names", true));
449 	bool show_tile_ids = bool(EDITOR_DEF("editors/tile_map/show_tile_ids", false));
450 	bool sort_by_name = bool(EDITOR_DEF("editors/tile_map/sort_tiles_by_name", true));
451 
452 	palette->add_constant_override("hseparation", hseparation * EDSCALE);
453 
454 	palette->set_fixed_icon_size(Size2(min_size, min_size));
455 	palette->set_fixed_column_width(min_size * MAX(size_slider->get_value(), 1));
456 	palette->set_same_column_width(true);
457 	manual_palette->set_fixed_icon_size(Size2(min_size, min_size));
458 	manual_palette->set_same_column_width(true);
459 
460 	String filter = search_box->get_text().strip_edges();
461 
462 	Vector<_PaletteEntry> entries;
463 
464 	for (List<int>::Element *E = tiles.front(); E; E = E->next()) {
465 
466 		String name = tileset->tile_get_name(E->get());
467 
468 		if (name != "") {
469 			if (show_tile_ids) {
470 				if (sort_by_name) {
471 					name = name + " - " + itos(E->get());
472 				} else {
473 					name = itos(E->get()) + " - " + name;
474 				}
475 			}
476 		} else {
477 			name = "#" + itos(E->get());
478 		}
479 
480 		if (filter != "" && !filter.is_subsequence_ofi(name))
481 			continue;
482 
483 		const _PaletteEntry entry = { E->get(), name };
484 		entries.push_back(entry);
485 	}
486 
487 	if (sort_by_name) {
488 		entries.sort();
489 	}
490 
491 	for (int i = 0; i < entries.size(); i++) {
492 
493 		if (show_tile_names) {
494 			palette->add_item(entries[i].name);
495 		} else {
496 			palette->add_item(String());
497 		}
498 
499 		Ref<Texture> tex = tileset->tile_get_texture(entries[i].id);
500 
501 		if (tex.is_valid()) {
502 			Rect2 region = tileset->tile_get_region(entries[i].id);
503 
504 			if (tileset->tile_get_tile_mode(entries[i].id) == TileSet::AUTO_TILE || tileset->tile_get_tile_mode(entries[i].id) == TileSet::ATLAS_TILE) {
505 				int spacing = tileset->autotile_get_spacing(entries[i].id);
506 				region.size = tileset->autotile_get_size(entries[i].id);
507 				region.position += (region.size + Vector2(spacing, spacing)) * tileset->autotile_get_icon_coordinate(entries[i].id);
508 			}
509 
510 			// Transpose and flip.
511 			palette->set_item_icon_transposed(palette->get_item_count() - 1, transpose);
512 			if (flip_h) {
513 				region.size.x = -region.size.x;
514 			}
515 			if (flip_v) {
516 				region.size.y = -region.size.y;
517 			}
518 
519 			// Set region.
520 			if (region.size != Size2())
521 				palette->set_item_icon_region(palette->get_item_count() - 1, region);
522 
523 			// Set icon.
524 			palette->set_item_icon(palette->get_item_count() - 1, tex);
525 
526 			// Modulation.
527 			Color color = tileset->tile_get_modulate(entries[i].id);
528 			palette->set_item_icon_modulate(palette->get_item_count() - 1, color);
529 		}
530 
531 		palette->set_item_metadata(palette->get_item_count() - 1, entries[i].id);
532 	}
533 
534 	int sel_tile = selected.get(0);
535 	if (selected.get(0) != TileMap::INVALID_CELL) {
536 		set_selected_tiles(selected);
537 		sel_tile = selected.get(Math::rand() % selected.size());
538 	} else if (palette->get_item_count() > 0) {
539 		palette->select(0);
540 		sel_tile = palette->get_selected_items().get(0);
541 	}
542 
543 	if (sel_tile != TileMap::INVALID_CELL && ((manual_autotile && tileset->tile_get_tile_mode(sel_tile) == TileSet::AUTO_TILE) || (!priority_atlastile && tileset->tile_get_tile_mode(sel_tile) == TileSet::ATLAS_TILE))) {
544 
545 		const Map<Vector2, uint32_t> &tiles2 = tileset->autotile_get_bitmask_map(sel_tile);
546 
547 		Vector<Vector2> entries2;
548 		for (const Map<Vector2, uint32_t>::Element *E = tiles2.front(); E; E = E->next()) {
549 			entries2.push_back(E->key());
550 		}
551 		// Sort tiles in row-major order.
552 		struct SwapComparator {
553 			_FORCE_INLINE_ bool operator()(const Vector2 &v_l, const Vector2 &v_r) const {
554 				return v_l.y != v_r.y ? v_l.y < v_r.y : v_l.x < v_r.x;
555 			}
556 		};
557 		entries2.sort_custom<SwapComparator>();
558 
559 		Ref<Texture> tex = tileset->tile_get_texture(sel_tile);
560 
561 		for (int i = 0; i < entries2.size(); i++) {
562 
563 			manual_palette->add_item(String());
564 
565 			if (tex.is_valid()) {
566 
567 				Rect2 region = tileset->tile_get_region(sel_tile);
568 				int spacing = tileset->autotile_get_spacing(sel_tile);
569 				region.size = tileset->autotile_get_size(sel_tile); // !!
570 				region.position += (region.size + Vector2(spacing, spacing)) * entries2[i];
571 
572 				if (!region.has_no_area())
573 					manual_palette->set_item_icon_region(manual_palette->get_item_count() - 1, region);
574 
575 				manual_palette->set_item_icon(manual_palette->get_item_count() - 1, tex);
576 			}
577 
578 			manual_palette->set_item_metadata(manual_palette->get_item_count() - 1, entries2[i]);
579 		}
580 	}
581 
582 	if (manual_palette->get_item_count() > 0) {
583 		// Only show the manual palette if at least tile exists in it.
584 		if (selected_manual == -1 || selected_single != palette->get_current())
585 			selected_manual = 0;
586 		if (selected_manual < manual_palette->get_item_count())
587 			manual_palette->set_current(selected_manual);
588 		manual_palette->show();
589 	}
590 
591 	if (sel_tile != TileMap::INVALID_CELL && tileset->tile_get_tile_mode(sel_tile) == TileSet::AUTO_TILE) {
592 		manual_button->show();
593 		priority_button->hide();
594 	} else {
595 		manual_button->hide();
596 		priority_button->show();
597 	}
598 }
599 
_pick_tile(const Point2 & p_pos)600 void TileMapEditor::_pick_tile(const Point2 &p_pos) {
601 
602 	int id = node->get_cell(p_pos.x, p_pos.y);
603 
604 	if (id == TileMap::INVALID_CELL)
605 		return;
606 
607 	if (search_box->get_text() != "") {
608 		search_box->set_text("");
609 		_update_palette();
610 	}
611 
612 	flip_h = node->is_cell_x_flipped(p_pos.x, p_pos.y);
613 	flip_v = node->is_cell_y_flipped(p_pos.x, p_pos.y);
614 	transpose = node->is_cell_transposed(p_pos.x, p_pos.y);
615 	autotile_coord = node->get_cell_autotile_coord(p_pos.x, p_pos.y);
616 
617 	Vector<int> selected;
618 	selected.push_back(id);
619 	set_selected_tiles(selected);
620 	_update_palette();
621 
622 	if ((manual_autotile && node->get_tileset()->tile_get_tile_mode(id) == TileSet::AUTO_TILE) || (!priority_atlastile && node->get_tileset()->tile_get_tile_mode(id) == TileSet::ATLAS_TILE)) {
623 		manual_palette->select(manual_palette->find_metadata((Point2)autotile_coord));
624 	}
625 
626 	CanvasItemEditor::get_singleton()->update_viewport();
627 }
628 
_bucket_fill(const Point2i & p_start,bool erase,bool preview)629 PoolVector<Vector2> TileMapEditor::_bucket_fill(const Point2i &p_start, bool erase, bool preview) {
630 
631 	int prev_id = node->get_cell(p_start.x, p_start.y);
632 	Vector<int> ids;
633 	ids.push_back(TileMap::INVALID_CELL);
634 	if (!erase) {
635 		ids = get_selected_tiles();
636 
637 		if (ids.size() == 0 || ids[0] == TileMap::INVALID_CELL)
638 			return PoolVector<Vector2>();
639 	} else if (prev_id == TileMap::INVALID_CELL) {
640 		return PoolVector<Vector2>();
641 	}
642 
643 	if (ids.size() == 1 && ids[0] == prev_id) {
644 		// Same ID, nothing to change
645 		return PoolVector<Vector2>();
646 	}
647 
648 	Rect2i r = node->get_used_rect();
649 
650 	int area = r.get_area();
651 	if (preview) {
652 		// Test if we can re-use the result from preview bucket fill
653 		bool invalidate_cache = false;
654 		// Area changed
655 		if (r != bucket_cache_rect)
656 			_clear_bucket_cache();
657 		// Cache grid is not initialized
658 		if (bucket_cache_visited == NULL) {
659 			bucket_cache_visited = new bool[area];
660 			invalidate_cache = true;
661 		}
662 		// Tile ID changed or position wasn't visited by the previous fill
663 		const int loc = (p_start.x - r.position.x) + (p_start.y - r.position.y) * r.get_size().x;
664 		const bool in_range = 0 <= loc && loc < area;
665 		if (prev_id != bucket_cache_tile || (in_range && !bucket_cache_visited[loc])) {
666 			invalidate_cache = true;
667 		}
668 		if (invalidate_cache) {
669 			for (int i = 0; i < area; ++i)
670 				bucket_cache_visited[i] = false;
671 			bucket_cache = PoolVector<Vector2>();
672 			bucket_cache_tile = prev_id;
673 			bucket_cache_rect = r;
674 			bucket_queue.clear();
675 		}
676 	}
677 
678 	PoolVector<Vector2> points;
679 	Vector<Vector2> non_preview_cache;
680 	int count = 0;
681 	int limit = 0;
682 
683 	if (preview) {
684 		limit = 1024;
685 	} else {
686 		bucket_queue.clear();
687 	}
688 
689 	bucket_queue.push_back(p_start);
690 
691 	while (bucket_queue.size()) {
692 
693 		Point2i n = bucket_queue.front()->get();
694 		bucket_queue.pop_front();
695 
696 		if (!r.has_point(n))
697 			continue;
698 
699 		if (node->get_cell(n.x, n.y) == prev_id) {
700 
701 			if (preview) {
702 				int loc = (n.x - r.position.x) + (n.y - r.position.y) * r.get_size().x;
703 				if (bucket_cache_visited[loc])
704 					continue;
705 				bucket_cache_visited[loc] = true;
706 				bucket_cache.push_back(n);
707 			} else {
708 				if (non_preview_cache.find(n) >= 0)
709 					continue;
710 				points.push_back(n);
711 				non_preview_cache.push_back(n);
712 			}
713 
714 			bucket_queue.push_back(Point2i(n.x, n.y + 1));
715 			bucket_queue.push_back(Point2i(n.x, n.y - 1));
716 			bucket_queue.push_back(Point2i(n.x + 1, n.y));
717 			bucket_queue.push_back(Point2i(n.x - 1, n.y));
718 			count++;
719 		}
720 
721 		if (limit > 0 && count >= limit) {
722 			break;
723 		}
724 	}
725 
726 	return preview ? bucket_cache : points;
727 }
728 
_fill_points(const PoolVector<Vector2> & p_points,const Dictionary & p_op)729 void TileMapEditor::_fill_points(const PoolVector<Vector2> &p_points, const Dictionary &p_op) {
730 
731 	int len = p_points.size();
732 	PoolVector<Vector2>::Read pr = p_points.read();
733 
734 	Vector<int> ids = p_op["id"];
735 	bool xf = p_op["flip_h"];
736 	bool yf = p_op["flip_v"];
737 	bool tr = p_op["transpose"];
738 
739 	for (int i = 0; i < len; i++) {
740 		_set_cell(pr[i], ids, xf, yf, tr);
741 		node->make_bitmask_area_dirty(pr[i]);
742 	}
743 	if (!manual_autotile)
744 		node->update_dirty_bitmask();
745 }
746 
_erase_points(const PoolVector<Vector2> & p_points)747 void TileMapEditor::_erase_points(const PoolVector<Vector2> &p_points) {
748 
749 	int len = p_points.size();
750 	PoolVector<Vector2>::Read pr = p_points.read();
751 
752 	for (int i = 0; i < len; i++) {
753 
754 		_set_cell(pr[i], invalid_cell);
755 	}
756 }
757 
_select(const Point2i & p_from,const Point2i & p_to)758 void TileMapEditor::_select(const Point2i &p_from, const Point2i &p_to) {
759 
760 	Point2i begin = p_from;
761 	Point2i end = p_to;
762 
763 	if (begin.x > end.x) {
764 
765 		SWAP(begin.x, end.x);
766 	}
767 	if (begin.y > end.y) {
768 
769 		SWAP(begin.y, end.y);
770 	}
771 
772 	rectangle.position = begin;
773 	rectangle.size = end - begin;
774 
775 	CanvasItemEditor::get_singleton()->update_viewport();
776 }
777 
_erase_selection()778 void TileMapEditor::_erase_selection() {
779 	if (!selection_active)
780 		return;
781 
782 	for (int i = rectangle.position.y; i <= rectangle.position.y + rectangle.size.y; i++) {
783 		for (int j = rectangle.position.x; j <= rectangle.position.x + rectangle.size.x; j++) {
784 
785 			_set_cell(Point2i(j, i), invalid_cell, false, false, false);
786 		}
787 	}
788 }
789 
_draw_cell(Control * p_viewport,int p_cell,const Point2i & p_point,bool p_flip_h,bool p_flip_v,bool p_transpose,const Point2i & p_autotile_coord,const Transform2D & p_xform)790 void TileMapEditor::_draw_cell(Control *p_viewport, int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Point2i &p_autotile_coord, const Transform2D &p_xform) {
791 
792 	Ref<Texture> t = node->get_tileset()->tile_get_texture(p_cell);
793 
794 	if (t.is_null())
795 		return;
796 
797 	Vector2 tile_ofs = node->get_tileset()->tile_get_texture_offset(p_cell);
798 
799 	Rect2 r = node->get_tileset()->tile_get_region(p_cell);
800 	if (node->get_tileset()->tile_get_tile_mode(p_cell) == TileSet::AUTO_TILE || node->get_tileset()->tile_get_tile_mode(p_cell) == TileSet::ATLAS_TILE) {
801 		Vector2 offset;
802 		if (tool != TOOL_PASTING) {
803 			int selected = manual_palette->get_current();
804 			if ((manual_autotile || (node->get_tileset()->tile_get_tile_mode(p_cell) == TileSet::ATLAS_TILE && !priority_atlastile)) && selected != -1) {
805 				offset = manual_palette->get_item_metadata(selected);
806 			} else {
807 				offset = node->get_tileset()->autotile_get_icon_coordinate(p_cell);
808 			}
809 		} else {
810 			offset = p_autotile_coord;
811 		}
812 
813 		int spacing = node->get_tileset()->autotile_get_spacing(p_cell);
814 		r.size = node->get_tileset()->autotile_get_size(p_cell);
815 		r.position += (r.size + Vector2(spacing, spacing)) * offset;
816 	}
817 	Size2 cell_size = node->get_cell_size();
818 	bool centered_texture = node->is_centered_textures_enabled();
819 	bool compatibility_mode_enabled = node->is_compatibility_mode_enabled();
820 	Rect2 rect = Rect2();
821 	rect.position = node->map_to_world(p_point) + node->get_cell_draw_offset();
822 
823 	if (r.has_no_area()) {
824 		rect.size = t->get_size();
825 	} else {
826 		rect.size = r.size;
827 	}
828 
829 	if (compatibility_mode_enabled && !centered_texture) {
830 		if (rect.size.y > rect.size.x) {
831 			if ((p_flip_h && (p_flip_v || p_transpose)) || (p_flip_v && !p_transpose))
832 				tile_ofs.y += rect.size.y - rect.size.x;
833 		} else if (rect.size.y < rect.size.x) {
834 			if ((p_flip_v && (p_flip_h || p_transpose)) || (p_flip_h && !p_transpose))
835 				tile_ofs.x += rect.size.x - rect.size.y;
836 		}
837 	}
838 
839 	if (p_transpose) {
840 		SWAP(tile_ofs.x, tile_ofs.y);
841 		if (centered_texture) {
842 			rect.position.x += cell_size.x / 2 - rect.size.y / 2;
843 			rect.position.y += cell_size.y / 2 - rect.size.x / 2;
844 		}
845 	} else if (centered_texture) {
846 		rect.position += cell_size / 2 - rect.size / 2;
847 	}
848 
849 	if (p_flip_h) {
850 		rect.size.x *= -1.0;
851 		tile_ofs.x *= -1.0;
852 	}
853 
854 	if (p_flip_v) {
855 		rect.size.y *= -1.0;
856 		tile_ofs.y *= -1.0;
857 	}
858 
859 	if (compatibility_mode_enabled && !centered_texture) {
860 		if (node->get_tile_origin() == TileMap::TILE_ORIGIN_TOP_LEFT) {
861 
862 			rect.position += tile_ofs;
863 		} else if (node->get_tile_origin() == TileMap::TILE_ORIGIN_BOTTOM_LEFT) {
864 
865 			rect.position += tile_ofs;
866 
867 			if (p_transpose) {
868 				if (p_flip_h)
869 					rect.position.x -= cell_size.x;
870 				else
871 					rect.position.x += cell_size.x;
872 			} else {
873 				if (p_flip_v)
874 					rect.position.y -= cell_size.y;
875 				else
876 					rect.position.y += cell_size.y;
877 			}
878 
879 		} else if (node->get_tile_origin() == TileMap::TILE_ORIGIN_CENTER) {
880 
881 			rect.position += tile_ofs;
882 
883 			if (p_flip_h)
884 				rect.position.x -= cell_size.x / 2;
885 			else
886 				rect.position.x += cell_size.x / 2;
887 
888 			if (p_flip_v)
889 				rect.position.y -= cell_size.y / 2;
890 			else
891 				rect.position.y += cell_size.y / 2;
892 		}
893 	} else {
894 		rect.position += tile_ofs;
895 	}
896 
897 	Color modulate = node->get_tileset()->tile_get_modulate(p_cell);
898 	modulate.a = 0.5;
899 
900 	Transform2D old_transform = p_viewport->get_viewport_transform();
901 	p_viewport->draw_set_transform_matrix(p_xform); // Take into account TileMap transformation when displaying cell
902 	if (r.has_no_area()) {
903 		p_viewport->draw_texture_rect(t, rect, false, modulate, p_transpose);
904 	} else {
905 		p_viewport->draw_texture_rect_region(t, rect, r, modulate, p_transpose);
906 	}
907 	p_viewport->draw_set_transform_matrix(old_transform);
908 }
909 
_draw_fill_preview(Control * p_viewport,int p_cell,const Point2i & p_point,bool p_flip_h,bool p_flip_v,bool p_transpose,const Point2i & p_autotile_coord,const Transform2D & p_xform)910 void TileMapEditor::_draw_fill_preview(Control *p_viewport, int p_cell, const Point2i &p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Point2i &p_autotile_coord, const Transform2D &p_xform) {
911 
912 	PoolVector<Vector2> points = _bucket_fill(p_point, false, true);
913 	PoolVector<Vector2>::Read pr = points.read();
914 	int len = points.size();
915 
916 	for (int i = 0; i < len; ++i) {
917 		_draw_cell(p_viewport, p_cell, pr[i], p_flip_h, p_flip_v, p_transpose, p_autotile_coord, p_xform);
918 	}
919 }
920 
_clear_bucket_cache()921 void TileMapEditor::_clear_bucket_cache() {
922 	if (bucket_cache_visited) {
923 		delete[] bucket_cache_visited;
924 		bucket_cache_visited = NULL;
925 	}
926 }
927 
_update_copydata()928 void TileMapEditor::_update_copydata() {
929 
930 	copydata.clear();
931 
932 	if (!selection_active)
933 		return;
934 
935 	for (int i = rectangle.position.y; i <= rectangle.position.y + rectangle.size.y; i++) {
936 
937 		for (int j = rectangle.position.x; j <= rectangle.position.x + rectangle.size.x; j++) {
938 
939 			TileData tcd;
940 
941 			tcd.cell = node->get_cell(j, i);
942 			if (tcd.cell != TileMap::INVALID_CELL) {
943 				tcd.pos = Point2i(j, i);
944 				tcd.flip_h = node->is_cell_x_flipped(j, i);
945 				tcd.flip_v = node->is_cell_y_flipped(j, i);
946 				tcd.transpose = node->is_cell_transposed(j, i);
947 				tcd.autotile_coord = node->get_cell_autotile_coord(j, i);
948 			}
949 
950 			copydata.push_back(tcd);
951 		}
952 	}
953 }
954 
line(int x0,int x1,int y0,int y1)955 static inline Vector<Point2i> line(int x0, int x1, int y0, int y1) {
956 
957 	Vector<Point2i> points;
958 
959 	float dx = ABS(x1 - x0);
960 	float dy = ABS(y1 - y0);
961 
962 	int x = x0;
963 	int y = y0;
964 
965 	int sx = x0 > x1 ? -1 : 1;
966 	int sy = y0 > y1 ? -1 : 1;
967 
968 	if (dx > dy) {
969 		float err = dx / 2;
970 
971 		for (; x != x1; x += sx) {
972 			points.push_back(Vector2(x, y));
973 
974 			err -= dy;
975 			if (err < 0) {
976 				y += sy;
977 				err += dx;
978 			}
979 		}
980 	} else {
981 		float err = dy / 2;
982 
983 		for (; y != y1; y += sy) {
984 			points.push_back(Vector2(x, y));
985 
986 			err -= dx;
987 			if (err < 0) {
988 				x += sx;
989 				err += dy;
990 			}
991 		}
992 	}
993 
994 	points.push_back(Vector2(x, y));
995 
996 	return points;
997 }
998 
forward_gui_input(const Ref<InputEvent> & p_event)999 bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
1000 
1001 	if (!node || !node->get_tileset().is_valid() || !node->is_visible_in_tree() || CanvasItemEditor::get_singleton()->get_current_tool() != CanvasItemEditor::TOOL_SELECT)
1002 		return false;
1003 
1004 	Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
1005 	Transform2D xform_inv = xform.affine_inverse();
1006 
1007 	Ref<InputEventMouseButton> mb = p_event;
1008 
1009 	if (mb.is_valid()) {
1010 		if (mb->get_button_index() == BUTTON_LEFT) {
1011 
1012 			if (mb->is_pressed()) {
1013 
1014 				if (Input::get_singleton()->is_key_pressed(KEY_SPACE))
1015 					return false; // Drag.
1016 
1017 				if (tool == TOOL_NONE) {
1018 
1019 					if (mb->get_shift()) {
1020 
1021 						if (mb->get_command())
1022 							tool = TOOL_RECTANGLE_PAINT;
1023 						else
1024 							tool = TOOL_LINE_PAINT;
1025 
1026 						selection_active = false;
1027 						rectangle_begin = over_tile;
1028 
1029 						_update_button_tool();
1030 						return true;
1031 					}
1032 
1033 					if (mb->get_command()) {
1034 						tool = TOOL_PICKING;
1035 						_pick_tile(over_tile);
1036 						_update_button_tool();
1037 
1038 						return true;
1039 					}
1040 
1041 					tool = TOOL_PAINTING;
1042 					_update_button_tool();
1043 				}
1044 
1045 				if (tool == TOOL_PAINTING) {
1046 
1047 					Vector<int> ids = get_selected_tiles();
1048 
1049 					if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) {
1050 
1051 						tool = TOOL_PAINTING;
1052 
1053 						_start_undo(TTR("Paint TileMap"));
1054 					}
1055 				} else if (tool == TOOL_PICKING) {
1056 
1057 					_pick_tile(over_tile);
1058 				} else if (tool == TOOL_SELECTING) {
1059 
1060 					selection_active = true;
1061 					rectangle_begin = over_tile;
1062 				}
1063 
1064 				_update_button_tool();
1065 				return true;
1066 
1067 			} else {
1068 				// Mousebutton was released.
1069 				if (tool != TOOL_NONE) {
1070 
1071 					if (tool == TOOL_PAINTING) {
1072 
1073 						Vector<int> ids = get_selected_tiles();
1074 
1075 						if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) {
1076 
1077 							_set_cell(over_tile, ids, flip_h, flip_v, transpose);
1078 							_finish_undo();
1079 
1080 							paint_undo.clear();
1081 						}
1082 					} else if (tool == TOOL_LINE_PAINT) {
1083 
1084 						Vector<int> ids = get_selected_tiles();
1085 
1086 						if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) {
1087 
1088 							_start_undo(TTR("Line Draw"));
1089 							for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
1090 
1091 								_set_cell(E->key(), ids, flip_h, flip_v, transpose);
1092 							}
1093 							_finish_undo();
1094 
1095 							paint_undo.clear();
1096 
1097 							CanvasItemEditor::get_singleton()->update_viewport();
1098 						}
1099 					} else if (tool == TOOL_RECTANGLE_PAINT) {
1100 
1101 						Vector<int> ids = get_selected_tiles();
1102 
1103 						if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) {
1104 
1105 							_start_undo(TTR("Rectangle Paint"));
1106 							for (int i = rectangle.position.y; i <= rectangle.position.y + rectangle.size.y; i++) {
1107 								for (int j = rectangle.position.x; j <= rectangle.position.x + rectangle.size.x; j++) {
1108 
1109 									_set_cell(Point2i(j, i), ids, flip_h, flip_v, transpose);
1110 								}
1111 							}
1112 							_finish_undo();
1113 
1114 							CanvasItemEditor::get_singleton()->update_viewport();
1115 						}
1116 					} else if (tool == TOOL_PASTING) {
1117 
1118 						Point2 ofs = over_tile - rectangle.position;
1119 						Vector<int> ids;
1120 
1121 						_start_undo(TTR("Paste"));
1122 						ids.push_back(0);
1123 						for (List<TileData>::Element *E = copydata.front(); E; E = E->next()) {
1124 
1125 							ids.write[0] = E->get().cell;
1126 							_set_cell(E->get().pos + ofs, ids, E->get().flip_h, E->get().flip_v, E->get().transpose, E->get().autotile_coord);
1127 						}
1128 						_finish_undo();
1129 
1130 						CanvasItemEditor::get_singleton()->update_viewport();
1131 
1132 						return true; // We want to keep the Pasting tool.
1133 					} else if (tool == TOOL_SELECTING) {
1134 
1135 						CanvasItemEditor::get_singleton()->update_viewport();
1136 
1137 					} else if (tool == TOOL_BUCKET) {
1138 
1139 						PoolVector<Vector2> points = _bucket_fill(over_tile);
1140 
1141 						if (points.size() == 0)
1142 							return false;
1143 
1144 						_start_undo(TTR("Bucket Fill"));
1145 
1146 						Dictionary op;
1147 						op["id"] = get_selected_tiles();
1148 						op["flip_h"] = flip_h;
1149 						op["flip_v"] = flip_v;
1150 						op["transpose"] = transpose;
1151 
1152 						_fill_points(points, op);
1153 
1154 						_finish_undo();
1155 
1156 						// So the fill preview is cleared right after the click.
1157 						CanvasItemEditor::get_singleton()->update_viewport();
1158 
1159 						// We want to keep the bucket-tool active.
1160 						return true;
1161 					}
1162 
1163 					tool = TOOL_NONE;
1164 					_update_button_tool();
1165 
1166 					return true;
1167 				}
1168 			}
1169 		} else if (mb->get_button_index() == BUTTON_RIGHT) {
1170 
1171 			if (mb->is_pressed()) {
1172 
1173 				if (tool == TOOL_SELECTING || selection_active) {
1174 
1175 					tool = TOOL_NONE;
1176 					selection_active = false;
1177 
1178 					CanvasItemEditor::get_singleton()->update_viewport();
1179 
1180 					_update_button_tool();
1181 					return true;
1182 				}
1183 
1184 				if (tool == TOOL_PASTING) {
1185 
1186 					tool = TOOL_NONE;
1187 					copydata.clear();
1188 
1189 					CanvasItemEditor::get_singleton()->update_viewport();
1190 
1191 					_update_button_tool();
1192 					return true;
1193 				}
1194 
1195 				if (tool == TOOL_NONE) {
1196 
1197 					paint_undo.clear();
1198 
1199 					Point2 local = node->world_to_map(xform_inv.xform(mb->get_position()));
1200 
1201 					_start_undo(TTR("Erase TileMap"));
1202 
1203 					if (mb->get_shift()) {
1204 						if (mb->get_command())
1205 							tool = TOOL_RECTANGLE_ERASE;
1206 						else
1207 							tool = TOOL_LINE_ERASE;
1208 
1209 						selection_active = false;
1210 						rectangle_begin = local;
1211 					} else {
1212 
1213 						tool = TOOL_ERASING;
1214 
1215 						_set_cell(local, invalid_cell);
1216 					}
1217 
1218 					_update_button_tool();
1219 					return true;
1220 				}
1221 
1222 			} else {
1223 				if (tool == TOOL_ERASING || tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) {
1224 
1225 					_finish_undo();
1226 
1227 					if (tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) {
1228 						CanvasItemEditor::get_singleton()->update_viewport();
1229 					}
1230 
1231 					tool = TOOL_NONE;
1232 
1233 					_update_button_tool();
1234 					return true;
1235 
1236 				} else if (tool == TOOL_BUCKET) {
1237 
1238 					Vector<int> ids;
1239 					ids.push_back(node->get_cell(over_tile.x, over_tile.y));
1240 					Dictionary pop;
1241 					pop["id"] = ids;
1242 					pop["flip_h"] = node->is_cell_x_flipped(over_tile.x, over_tile.y);
1243 					pop["flip_v"] = node->is_cell_y_flipped(over_tile.x, over_tile.y);
1244 					pop["transpose"] = node->is_cell_transposed(over_tile.x, over_tile.y);
1245 
1246 					PoolVector<Vector2> points = _bucket_fill(over_tile, true);
1247 
1248 					if (points.size() == 0)
1249 						return false;
1250 
1251 					undo_redo->create_action(TTR("Bucket Fill"));
1252 
1253 					undo_redo->add_do_method(this, "_erase_points", points);
1254 					undo_redo->add_undo_method(this, "_fill_points", points, pop);
1255 
1256 					undo_redo->commit_action();
1257 				}
1258 			}
1259 		}
1260 	}
1261 
1262 	Ref<InputEventMouseMotion> mm = p_event;
1263 
1264 	if (mm.is_valid()) {
1265 
1266 		Point2i new_over_tile = node->world_to_map(xform_inv.xform(mm->get_position()));
1267 		Point2i old_over_tile = over_tile;
1268 
1269 		if (new_over_tile != over_tile) {
1270 
1271 			over_tile = new_over_tile;
1272 			CanvasItemEditor::get_singleton()->update_viewport();
1273 		}
1274 
1275 		int tile_under = node->get_cell(over_tile.x, over_tile.y);
1276 		String tile_name = "none";
1277 
1278 		if (node->get_tileset()->has_tile(tile_under))
1279 			tile_name = node->get_tileset()->tile_get_name(tile_under);
1280 		tile_info->show();
1281 		tile_info->set_text(String::num(over_tile.x) + ", " + String::num(over_tile.y) + " [" + tile_name + "]");
1282 
1283 		if (tool == TOOL_PAINTING) {
1284 
1285 			// Paint using bresenham line to prevent holes in painting if the user moves fast.
1286 
1287 			Vector<Point2i> points = line(old_over_tile.x, over_tile.x, old_over_tile.y, over_tile.y);
1288 			Vector<int> ids = get_selected_tiles();
1289 
1290 			for (int i = 0; i < points.size(); ++i) {
1291 
1292 				Point2i pos = points[i];
1293 
1294 				if (!paint_undo.has(pos)) {
1295 					paint_undo[pos] = _get_op_from_cell(pos);
1296 				}
1297 
1298 				_set_cell(pos, ids, flip_h, flip_v, transpose);
1299 			}
1300 
1301 			return true;
1302 		}
1303 
1304 		if (tool == TOOL_ERASING) {
1305 
1306 			// Erase using bresenham line to prevent holes in painting if the user moves fast.
1307 
1308 			Vector<Point2i> points = line(old_over_tile.x, over_tile.x, old_over_tile.y, over_tile.y);
1309 
1310 			for (int i = 0; i < points.size(); ++i) {
1311 
1312 				Point2i pos = points[i];
1313 
1314 				_set_cell(pos, invalid_cell);
1315 			}
1316 
1317 			return true;
1318 		}
1319 
1320 		if (tool == TOOL_SELECTING) {
1321 
1322 			_select(rectangle_begin, over_tile);
1323 
1324 			return true;
1325 		}
1326 
1327 		if (tool == TOOL_LINE_PAINT || tool == TOOL_LINE_ERASE) {
1328 
1329 			Vector<int> ids = get_selected_tiles();
1330 			Vector<int> tmp_cell;
1331 			bool erasing = (tool == TOOL_LINE_ERASE);
1332 
1333 			tmp_cell.push_back(0);
1334 			if (erasing && paint_undo.size()) {
1335 
1336 				for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
1337 
1338 					tmp_cell.write[0] = E->get().idx;
1339 					_set_cell(E->key(), tmp_cell, E->get().xf, E->get().yf, E->get().tr);
1340 				}
1341 			}
1342 
1343 			paint_undo.clear();
1344 
1345 			if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) {
1346 
1347 				Vector<Point2i> points = line(rectangle_begin.x, over_tile.x, rectangle_begin.y, over_tile.y);
1348 
1349 				for (int i = 0; i < points.size(); i++) {
1350 
1351 					paint_undo[points[i]] = _get_op_from_cell(points[i]);
1352 
1353 					if (erasing)
1354 						_set_cell(points[i], invalid_cell);
1355 				}
1356 
1357 				CanvasItemEditor::get_singleton()->update_viewport();
1358 			}
1359 
1360 			return true;
1361 		}
1362 		if (tool == TOOL_RECTANGLE_PAINT || tool == TOOL_RECTANGLE_ERASE) {
1363 
1364 			Vector<int> tmp_cell;
1365 			tmp_cell.push_back(0);
1366 
1367 			_select(rectangle_begin, over_tile);
1368 
1369 			if (tool == TOOL_RECTANGLE_ERASE) {
1370 
1371 				if (paint_undo.size()) {
1372 
1373 					for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
1374 
1375 						tmp_cell.write[0] = E->get().idx;
1376 						_set_cell(E->key(), tmp_cell, E->get().xf, E->get().yf, E->get().tr);
1377 					}
1378 				}
1379 
1380 				paint_undo.clear();
1381 
1382 				for (int i = rectangle.position.y; i <= rectangle.position.y + rectangle.size.y; i++) {
1383 					for (int j = rectangle.position.x; j <= rectangle.position.x + rectangle.size.x; j++) {
1384 
1385 						Point2i tile = Point2i(j, i);
1386 						paint_undo[tile] = _get_op_from_cell(tile);
1387 
1388 						_set_cell(tile, invalid_cell);
1389 					}
1390 				}
1391 			}
1392 
1393 			return true;
1394 		}
1395 		if (tool == TOOL_PICKING && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
1396 
1397 			_pick_tile(over_tile);
1398 
1399 			return true;
1400 		}
1401 	}
1402 
1403 	Ref<InputEventKey> k = p_event;
1404 
1405 	if (k.is_valid() && k->is_pressed()) {
1406 
1407 		if (last_tool == TOOL_NONE && tool == TOOL_PICKING && k->get_scancode() == KEY_SHIFT && k->get_command()) {
1408 			// trying to draw a rectangle with the painting tool, so change to the correct tool
1409 			tool = last_tool;
1410 
1411 			CanvasItemEditor::get_singleton()->update_viewport();
1412 			_update_button_tool();
1413 		}
1414 
1415 		if (k->get_scancode() == KEY_ESCAPE) {
1416 
1417 			if (tool == TOOL_PASTING)
1418 				copydata.clear();
1419 			else if (tool == TOOL_SELECTING || selection_active)
1420 				selection_active = false;
1421 
1422 			tool = TOOL_NONE;
1423 
1424 			CanvasItemEditor::get_singleton()->update_viewport();
1425 
1426 			_update_button_tool();
1427 			return true;
1428 		}
1429 
1430 		if (!mouse_over) {
1431 			// Editor shortcuts should not fire if mouse not in viewport.
1432 			return false;
1433 		}
1434 
1435 		if (ED_IS_SHORTCUT("tile_map_editor/paint_tile", p_event)) {
1436 			// NOTE: We do not set tool = TOOL_PAINTING as this begins painting
1437 			// immediately without pressing the left mouse button first.
1438 			tool = TOOL_NONE;
1439 			CanvasItemEditor::get_singleton()->update_viewport();
1440 
1441 			_update_button_tool();
1442 			return true;
1443 		}
1444 		if (ED_IS_SHORTCUT("tile_map_editor/bucket_fill", p_event)) {
1445 			tool = TOOL_BUCKET;
1446 			CanvasItemEditor::get_singleton()->update_viewport();
1447 
1448 			_update_button_tool();
1449 			return true;
1450 		}
1451 		if (ED_IS_SHORTCUT("tile_map_editor/erase_selection", p_event)) {
1452 			_menu_option(OPTION_ERASE_SELECTION);
1453 
1454 			_update_button_tool();
1455 			return true;
1456 		}
1457 		if (ED_IS_SHORTCUT("tile_map_editor/select", p_event)) {
1458 			tool = TOOL_SELECTING;
1459 			selection_active = false;
1460 
1461 			CanvasItemEditor::get_singleton()->update_viewport();
1462 
1463 			_update_button_tool();
1464 			return true;
1465 		}
1466 		if (ED_IS_SHORTCUT("tile_map_editor/copy_selection", p_event)) {
1467 			_update_copydata();
1468 
1469 			if (selection_active) {
1470 				tool = TOOL_PASTING;
1471 
1472 				CanvasItemEditor::get_singleton()->update_viewport();
1473 
1474 				_update_button_tool();
1475 				return true;
1476 			}
1477 		}
1478 		if (ED_IS_SHORTCUT("tile_map_editor/cut_selection", p_event)) {
1479 			if (selection_active) {
1480 				_update_copydata();
1481 
1482 				_start_undo(TTR("Cut Selection"));
1483 				_erase_selection();
1484 				_finish_undo();
1485 
1486 				selection_active = false;
1487 
1488 				tool = TOOL_PASTING;
1489 
1490 				CanvasItemEditor::get_singleton()->update_viewport();
1491 				_update_button_tool();
1492 				return true;
1493 			}
1494 		}
1495 		if (ED_IS_SHORTCUT("tile_map_editor/find_tile", p_event)) {
1496 			search_box->select_all();
1497 			search_box->grab_focus();
1498 
1499 			return true;
1500 		}
1501 		if (ED_IS_SHORTCUT("tile_map_editor/rotate_left", p_event)) {
1502 			_rotate(-1);
1503 			CanvasItemEditor::get_singleton()->update_viewport();
1504 			return true;
1505 		}
1506 		if (ED_IS_SHORTCUT("tile_map_editor/rotate_right", p_event)) {
1507 			_rotate(1);
1508 			CanvasItemEditor::get_singleton()->update_viewport();
1509 			return true;
1510 		}
1511 		if (ED_IS_SHORTCUT("tile_map_editor/flip_horizontal", p_event)) {
1512 			_flip_horizontal();
1513 			CanvasItemEditor::get_singleton()->update_viewport();
1514 			return true;
1515 		}
1516 		if (ED_IS_SHORTCUT("tile_map_editor/flip_vertical", p_event)) {
1517 			_flip_vertical();
1518 			CanvasItemEditor::get_singleton()->update_viewport();
1519 			return true;
1520 		}
1521 		if (ED_IS_SHORTCUT("tile_map_editor/clear_transform", p_event)) {
1522 			_clear_transform();
1523 			CanvasItemEditor::get_singleton()->update_viewport();
1524 			return true;
1525 		}
1526 		if (ED_IS_SHORTCUT("tile_map_editor/transpose", p_event)) {
1527 			transpose = !transpose;
1528 			_update_palette();
1529 			CanvasItemEditor::get_singleton()->update_viewport();
1530 			return true;
1531 		}
1532 	} else if (k.is_valid()) { // Release event.
1533 
1534 		if (tool == TOOL_NONE) {
1535 
1536 			if (k->get_scancode() == KEY_SHIFT && k->get_command()) {
1537 
1538 				tool = TOOL_PICKING;
1539 				_update_button_tool();
1540 			}
1541 		} else if (tool == TOOL_PICKING) {
1542 
1543 #ifdef APPLE_STYLE_KEYS
1544 			if (k->get_scancode() == KEY_META) {
1545 #else
1546 			if (k->get_scancode() == KEY_CONTROL) {
1547 #endif
1548 				// Go back to that last tool if KEY_CONTROL was released.
1549 				tool = last_tool;
1550 
1551 				CanvasItemEditor::get_singleton()->update_viewport();
1552 				_update_button_tool();
1553 			}
1554 		}
1555 	}
1556 	return false;
1557 }
1558 
1559 void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
1560 
1561 	if (!node || CanvasItemEditor::get_singleton()->get_current_tool() != CanvasItemEditor::TOOL_SELECT)
1562 		return;
1563 
1564 	Transform2D cell_xf = node->get_cell_transform();
1565 	Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
1566 	Transform2D xform_inv = xform.affine_inverse();
1567 
1568 	Size2 screen_size = p_overlay->get_size();
1569 	{
1570 		Rect2 aabb;
1571 		aabb.position = node->world_to_map(xform_inv.xform(Vector2()));
1572 		aabb.expand_to(node->world_to_map(xform_inv.xform(Vector2(0, screen_size.height))));
1573 		aabb.expand_to(node->world_to_map(xform_inv.xform(Vector2(screen_size.width, 0))));
1574 		aabb.expand_to(node->world_to_map(xform_inv.xform(screen_size)));
1575 		Rect2i si = aabb.grow(1.0);
1576 
1577 		if (node->get_half_offset() != TileMap::HALF_OFFSET_X && node->get_half_offset() != TileMap::HALF_OFFSET_NEGATIVE_X) {
1578 
1579 			int max_lines = 2000; //avoid crash if size too small
1580 
1581 			for (int i = (si.position.x) - 1; i <= (si.position.x + si.size.x); i++) {
1582 
1583 				Vector2 from = xform.xform(node->map_to_world(Vector2(i, si.position.y)));
1584 				Vector2 to = xform.xform(node->map_to_world(Vector2(i, si.position.y + si.size.y + 1)));
1585 
1586 				Color col = i == 0 ? Color(1, 0.8, 0.2, 0.5) : Color(1, 0.3, 0.1, 0.2);
1587 				p_overlay->draw_line(from, to, col, 1);
1588 				if (max_lines-- == 0)
1589 					break;
1590 			}
1591 		} else {
1592 
1593 			int max_lines = 10000; //avoid crash if size too small
1594 
1595 			for (int i = (si.position.x) - 1; i <= (si.position.x + si.size.x); i++) {
1596 
1597 				for (int j = (si.position.y) - 1; j <= (si.position.y + si.size.y); j++) {
1598 
1599 					Vector2 ofs;
1600 					if (ABS(j) & 1) {
1601 						ofs = cell_xf[0] * (node->get_half_offset() == TileMap::HALF_OFFSET_X ? 0.5 : -0.5);
1602 					}
1603 
1604 					Vector2 from = xform.xform(node->map_to_world(Vector2(i, j), true) + ofs);
1605 					Vector2 to = xform.xform(node->map_to_world(Vector2(i, j + 1), true) + ofs);
1606 
1607 					Color col = i == 0 ? Color(1, 0.8, 0.2, 0.5) : Color(1, 0.3, 0.1, 0.2);
1608 					p_overlay->draw_line(from, to, col, 1);
1609 
1610 					if (--max_lines == 0)
1611 						break;
1612 				}
1613 				if (max_lines == 0)
1614 					break;
1615 			}
1616 		}
1617 
1618 		int max_lines = 10000; //avoid crash if size too small
1619 
1620 		if (node->get_half_offset() != TileMap::HALF_OFFSET_Y && node->get_half_offset() != TileMap::HALF_OFFSET_NEGATIVE_Y) {
1621 
1622 			for (int i = (si.position.y) - 1; i <= (si.position.y + si.size.y); i++) {
1623 
1624 				Vector2 from = xform.xform(node->map_to_world(Vector2(si.position.x, i)));
1625 				Vector2 to = xform.xform(node->map_to_world(Vector2(si.position.x + si.size.x + 1, i)));
1626 
1627 				Color col = i == 0 ? Color(1, 0.8, 0.2, 0.5) : Color(1, 0.3, 0.1, 0.2);
1628 				p_overlay->draw_line(from, to, col, 1);
1629 
1630 				if (max_lines-- == 0)
1631 					break;
1632 			}
1633 		} else {
1634 
1635 			for (int i = (si.position.y) - 1; i <= (si.position.y + si.size.y); i++) {
1636 
1637 				for (int j = (si.position.x) - 1; j <= (si.position.x + si.size.x); j++) {
1638 
1639 					Vector2 ofs;
1640 					if (ABS(j) & 1) {
1641 						ofs = cell_xf[1] * (node->get_half_offset() == TileMap::HALF_OFFSET_Y ? 0.5 : -0.5);
1642 					}
1643 
1644 					Vector2 from = xform.xform(node->map_to_world(Vector2(j, i), true) + ofs);
1645 					Vector2 to = xform.xform(node->map_to_world(Vector2(j + 1, i), true) + ofs);
1646 
1647 					Color col = i == 0 ? Color(1, 0.8, 0.2, 0.5) : Color(1, 0.3, 0.1, 0.2);
1648 					p_overlay->draw_line(from, to, col, 1);
1649 
1650 					if (--max_lines == 0)
1651 						break;
1652 				}
1653 				if (max_lines == 0)
1654 					break;
1655 			}
1656 		}
1657 	}
1658 
1659 	if (selection_active) {
1660 
1661 		Vector<Vector2> points;
1662 		points.push_back(xform.xform(node->map_to_world((rectangle.position))));
1663 		points.push_back(xform.xform(node->map_to_world((rectangle.position + Point2(rectangle.size.x + 1, 0)))));
1664 		points.push_back(xform.xform(node->map_to_world((rectangle.position + Point2(rectangle.size.x + 1, rectangle.size.y + 1)))));
1665 		points.push_back(xform.xform(node->map_to_world((rectangle.position + Point2(0, rectangle.size.y + 1)))));
1666 
1667 		p_overlay->draw_colored_polygon(points, Color(0.2, 0.8, 1, 0.4));
1668 	}
1669 
1670 	if (mouse_over && node->get_tileset().is_valid()) {
1671 
1672 		Vector2 endpoints[4] = {
1673 			node->map_to_world(over_tile, true),
1674 			node->map_to_world((over_tile + Point2(1, 0)), true),
1675 			node->map_to_world((over_tile + Point2(1, 1)), true),
1676 			node->map_to_world((over_tile + Point2(0, 1)), true)
1677 		};
1678 
1679 		for (int i = 0; i < 4; i++) {
1680 			if (node->get_half_offset() == TileMap::HALF_OFFSET_X && ABS(over_tile.y) & 1)
1681 				endpoints[i] += cell_xf[0] * 0.5;
1682 			if (node->get_half_offset() == TileMap::HALF_OFFSET_NEGATIVE_X && ABS(over_tile.y) & 1)
1683 				endpoints[i] += cell_xf[0] * -0.5;
1684 			if (node->get_half_offset() == TileMap::HALF_OFFSET_Y && ABS(over_tile.x) & 1)
1685 				endpoints[i] += cell_xf[1] * 0.5;
1686 			if (node->get_half_offset() == TileMap::HALF_OFFSET_NEGATIVE_Y && ABS(over_tile.x) & 1)
1687 				endpoints[i] += cell_xf[1] * -0.5;
1688 			endpoints[i] = xform.xform(endpoints[i]);
1689 		}
1690 		Color col;
1691 		if (node->get_cell(over_tile.x, over_tile.y) != TileMap::INVALID_CELL)
1692 			col = Color(0.2, 0.8, 1.0, 0.8);
1693 		else
1694 			col = Color(1.0, 0.4, 0.2, 0.8);
1695 
1696 		for (int i = 0; i < 4; i++)
1697 			p_overlay->draw_line(endpoints[i], endpoints[(i + 1) % 4], col, 2);
1698 
1699 		bool bucket_preview = EditorSettings::get_singleton()->get("editors/tile_map/bucket_fill_preview");
1700 		if (tool == TOOL_SELECTING || tool == TOOL_PICKING || !bucket_preview) {
1701 			return;
1702 		}
1703 
1704 		if (tool == TOOL_LINE_PAINT) {
1705 
1706 			if (paint_undo.empty())
1707 				return;
1708 
1709 			Vector<int> ids = get_selected_tiles();
1710 
1711 			if (ids.size() == 1 && ids[0] == TileMap::INVALID_CELL)
1712 				return;
1713 
1714 			for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) {
1715 
1716 				_draw_cell(p_overlay, ids[0], E->key(), flip_h, flip_v, transpose, autotile_coord, xform);
1717 			}
1718 
1719 		} else if (tool == TOOL_RECTANGLE_PAINT) {
1720 
1721 			Vector<int> ids = get_selected_tiles();
1722 
1723 			if (ids.size() == 1 && ids[0] == TileMap::INVALID_CELL)
1724 				return;
1725 
1726 			for (int i = rectangle.position.y; i <= rectangle.position.y + rectangle.size.y; i++) {
1727 				for (int j = rectangle.position.x; j <= rectangle.position.x + rectangle.size.x; j++) {
1728 
1729 					_draw_cell(p_overlay, ids[0], Point2i(j, i), flip_h, flip_v, transpose, autotile_coord, xform);
1730 				}
1731 			}
1732 		} else if (tool == TOOL_PASTING) {
1733 
1734 			if (copydata.empty())
1735 				return;
1736 
1737 			Ref<TileSet> ts = node->get_tileset();
1738 
1739 			if (ts.is_null())
1740 				return;
1741 
1742 			Point2 ofs = over_tile - rectangle.position;
1743 
1744 			for (List<TileData>::Element *E = copydata.front(); E; E = E->next()) {
1745 
1746 				if (!ts->has_tile(E->get().cell))
1747 					continue;
1748 
1749 				TileData tcd = E->get();
1750 
1751 				_draw_cell(p_overlay, tcd.cell, tcd.pos + ofs, tcd.flip_h, tcd.flip_v, tcd.transpose, tcd.autotile_coord, xform);
1752 			}
1753 
1754 			Rect2i duplicate = rectangle;
1755 			duplicate.position = over_tile;
1756 
1757 			Vector<Vector2> points;
1758 			points.push_back(xform.xform(node->map_to_world(duplicate.position)));
1759 			points.push_back(xform.xform(node->map_to_world((duplicate.position + Point2(duplicate.size.x + 1, 0)))));
1760 			points.push_back(xform.xform(node->map_to_world((duplicate.position + Point2(duplicate.size.x + 1, duplicate.size.y + 1)))));
1761 			points.push_back(xform.xform(node->map_to_world((duplicate.position + Point2(0, duplicate.size.y + 1)))));
1762 
1763 			p_overlay->draw_colored_polygon(points, Color(0.2, 1.0, 0.8, 0.2));
1764 
1765 		} else if (tool == TOOL_BUCKET) {
1766 
1767 			Vector<int> tiles = get_selected_tiles();
1768 			_draw_fill_preview(p_overlay, tiles[0], over_tile, flip_h, flip_v, transpose, autotile_coord, xform);
1769 
1770 		} else {
1771 
1772 			Vector<int> st = get_selected_tiles();
1773 
1774 			if (st.size() == 1 && st[0] == TileMap::INVALID_CELL)
1775 				return;
1776 
1777 			_draw_cell(p_overlay, st[0], over_tile, flip_h, flip_v, transpose, autotile_coord, xform);
1778 		}
1779 	}
1780 }
1781 
1782 void TileMapEditor::edit(Node *p_tile_map) {
1783 
1784 	search_box->set_text("");
1785 
1786 	if (!canvas_item_editor_viewport) {
1787 		canvas_item_editor_viewport = CanvasItemEditor::get_singleton()->get_viewport_control();
1788 	}
1789 
1790 	if (node)
1791 		node->disconnect("settings_changed", this, "_tileset_settings_changed");
1792 	if (p_tile_map) {
1793 
1794 		node = Object::cast_to<TileMap>(p_tile_map);
1795 		if (!canvas_item_editor_viewport->is_connected("mouse_entered", this, "_canvas_mouse_enter"))
1796 			canvas_item_editor_viewport->connect("mouse_entered", this, "_canvas_mouse_enter");
1797 		if (!canvas_item_editor_viewport->is_connected("mouse_exited", this, "_canvas_mouse_exit"))
1798 			canvas_item_editor_viewport->connect("mouse_exited", this, "_canvas_mouse_exit");
1799 
1800 		_update_palette();
1801 
1802 	} else {
1803 		node = NULL;
1804 
1805 		if (canvas_item_editor_viewport->is_connected("mouse_entered", this, "_canvas_mouse_enter"))
1806 			canvas_item_editor_viewport->disconnect("mouse_entered", this, "_canvas_mouse_enter");
1807 		if (canvas_item_editor_viewport->is_connected("mouse_exited", this, "_canvas_mouse_exit"))
1808 			canvas_item_editor_viewport->disconnect("mouse_exited", this, "_canvas_mouse_exit");
1809 
1810 		_update_palette();
1811 	}
1812 
1813 	if (node)
1814 		node->connect("settings_changed", this, "_tileset_settings_changed");
1815 
1816 	_clear_bucket_cache();
1817 }
1818 
1819 void TileMapEditor::_tileset_settings_changed() {
1820 
1821 	_update_palette();
1822 	CanvasItemEditor::get_singleton()->update_viewport();
1823 }
1824 
1825 void TileMapEditor::_icon_size_changed(float p_value) {
1826 	if (node) {
1827 		palette->set_icon_scale(p_value);
1828 		manual_palette->set_icon_scale(p_value);
1829 		_update_palette();
1830 	}
1831 }
1832 
1833 void TileMapEditor::_bind_methods() {
1834 
1835 	ClassDB::bind_method(D_METHOD("_manual_toggled"), &TileMapEditor::_manual_toggled);
1836 	ClassDB::bind_method(D_METHOD("_priority_toggled"), &TileMapEditor::_priority_toggled);
1837 	ClassDB::bind_method(D_METHOD("_text_entered"), &TileMapEditor::_text_entered);
1838 	ClassDB::bind_method(D_METHOD("_text_changed"), &TileMapEditor::_text_changed);
1839 	ClassDB::bind_method(D_METHOD("_sbox_input"), &TileMapEditor::_sbox_input);
1840 	ClassDB::bind_method(D_METHOD("_button_tool_select"), &TileMapEditor::_button_tool_select);
1841 	ClassDB::bind_method(D_METHOD("_menu_option"), &TileMapEditor::_menu_option);
1842 	ClassDB::bind_method(D_METHOD("_canvas_mouse_enter"), &TileMapEditor::_canvas_mouse_enter);
1843 	ClassDB::bind_method(D_METHOD("_canvas_mouse_exit"), &TileMapEditor::_canvas_mouse_exit);
1844 	ClassDB::bind_method(D_METHOD("_tileset_settings_changed"), &TileMapEditor::_tileset_settings_changed);
1845 	ClassDB::bind_method(D_METHOD("_rotate"), &TileMapEditor::_rotate);
1846 	ClassDB::bind_method(D_METHOD("_flip_horizontal"), &TileMapEditor::_flip_horizontal);
1847 	ClassDB::bind_method(D_METHOD("_flip_vertical"), &TileMapEditor::_flip_vertical);
1848 	ClassDB::bind_method(D_METHOD("_clear_transform"), &TileMapEditor::_clear_transform);
1849 	ClassDB::bind_method(D_METHOD("_palette_selected"), &TileMapEditor::_palette_selected);
1850 	ClassDB::bind_method(D_METHOD("_palette_multi_selected"), &TileMapEditor::_palette_multi_selected);
1851 	ClassDB::bind_method(D_METHOD("_palette_input"), &TileMapEditor::_palette_input);
1852 
1853 	ClassDB::bind_method(D_METHOD("_fill_points"), &TileMapEditor::_fill_points);
1854 	ClassDB::bind_method(D_METHOD("_erase_points"), &TileMapEditor::_erase_points);
1855 
1856 	ClassDB::bind_method(D_METHOD("_icon_size_changed"), &TileMapEditor::_icon_size_changed);
1857 	ClassDB::bind_method(D_METHOD("_node_removed"), &TileMapEditor::_node_removed);
1858 }
1859 
1860 TileMapEditor::CellOp TileMapEditor::_get_op_from_cell(const Point2i &p_pos) {
1861 	CellOp op;
1862 	op.idx = node->get_cell(p_pos.x, p_pos.y);
1863 	if (op.idx != TileMap::INVALID_CELL) {
1864 		if (node->is_cell_x_flipped(p_pos.x, p_pos.y))
1865 			op.xf = true;
1866 		if (node->is_cell_y_flipped(p_pos.x, p_pos.y))
1867 			op.yf = true;
1868 		if (node->is_cell_transposed(p_pos.x, p_pos.y))
1869 			op.tr = true;
1870 		op.ac = node->get_cell_autotile_coord(p_pos.x, p_pos.y);
1871 	}
1872 	return op;
1873 }
1874 
1875 void TileMapEditor::_rotate(int steps) {
1876 	const bool normal_rotation_matrix[][3] = {
1877 		{ false, false, false },
1878 		{ true, true, false },
1879 		{ false, true, true },
1880 		{ true, false, true }
1881 	};
1882 
1883 	const bool mirrored_rotation_matrix[][3] = {
1884 		{ false, true, false },
1885 		{ true, true, true },
1886 		{ false, false, true },
1887 		{ true, false, false }
1888 	};
1889 
1890 	if (transpose ^ flip_h ^ flip_v) {
1891 		// Odd number of flags activated = mirrored rotation
1892 		for (int i = 0; i < 4; i++) {
1893 			if (transpose == mirrored_rotation_matrix[i][0] &&
1894 					flip_h == mirrored_rotation_matrix[i][1] &&
1895 					flip_v == mirrored_rotation_matrix[i][2]) {
1896 				int new_id = Math::wrapi(i + steps, 0, 4);
1897 				transpose = mirrored_rotation_matrix[new_id][0];
1898 				flip_h = mirrored_rotation_matrix[new_id][1];
1899 				flip_v = mirrored_rotation_matrix[new_id][2];
1900 				break;
1901 			}
1902 		}
1903 	} else {
1904 		// Even number of flags activated = normal rotation
1905 		for (int i = 0; i < 4; i++) {
1906 			if (transpose == normal_rotation_matrix[i][0] &&
1907 					flip_h == normal_rotation_matrix[i][1] &&
1908 					flip_v == normal_rotation_matrix[i][2]) {
1909 				int new_id = Math::wrapi(i + steps, 0, 4);
1910 				transpose = normal_rotation_matrix[new_id][0];
1911 				flip_h = normal_rotation_matrix[new_id][1];
1912 				flip_v = normal_rotation_matrix[new_id][2];
1913 				break;
1914 			}
1915 		}
1916 	}
1917 
1918 	_update_palette();
1919 }
1920 
1921 void TileMapEditor::_flip_horizontal() {
1922 	flip_h = !flip_h;
1923 	_update_palette();
1924 }
1925 
1926 void TileMapEditor::_flip_vertical() {
1927 	flip_v = !flip_v;
1928 	_update_palette();
1929 }
1930 
1931 void TileMapEditor::_clear_transform() {
1932 	transpose = false;
1933 	flip_h = false;
1934 	flip_v = false;
1935 	_update_palette();
1936 }
1937 
1938 TileMapEditor::TileMapEditor(EditorNode *p_editor) {
1939 
1940 	node = NULL;
1941 	manual_autotile = false;
1942 	priority_atlastile = false;
1943 	manual_position = Vector2(0, 0);
1944 	canvas_item_editor_viewport = NULL;
1945 	editor = p_editor;
1946 	undo_redo = EditorNode::get_undo_redo();
1947 
1948 	tool = TOOL_NONE;
1949 	selection_active = false;
1950 	mouse_over = false;
1951 
1952 	flip_h = false;
1953 	flip_v = false;
1954 	transpose = false;
1955 
1956 	bucket_cache_tile = -1;
1957 	bucket_cache_visited = NULL;
1958 
1959 	invalid_cell.resize(1);
1960 	invalid_cell.write[0] = TileMap::INVALID_CELL;
1961 
1962 	ED_SHORTCUT("tile_map_editor/erase_selection", TTR("Erase Selection"), KEY_DELETE);
1963 	ED_SHORTCUT("tile_map_editor/find_tile", TTR("Find Tile"), KEY_MASK_CMD + KEY_F);
1964 	ED_SHORTCUT("tile_map_editor/transpose", TTR("Transpose"), KEY_T);
1965 
1966 	HBoxContainer *tool_hb = memnew(HBoxContainer);
1967 	add_child(tool_hb);
1968 
1969 	manual_button = memnew(CheckBox);
1970 	manual_button->set_text(TTR("Disable Autotile"));
1971 	manual_button->connect("toggled", this, "_manual_toggled");
1972 	add_child(manual_button);
1973 
1974 	priority_button = memnew(CheckBox);
1975 	priority_button->set_text(TTR("Enable Priority"));
1976 	priority_button->connect("toggled", this, "_priority_toggled");
1977 	add_child(priority_button);
1978 
1979 	search_box = memnew(LineEdit);
1980 	search_box->set_placeholder(TTR("Filter tiles"));
1981 	search_box->set_h_size_flags(SIZE_EXPAND_FILL);
1982 	search_box->connect("text_entered", this, "_text_entered");
1983 	search_box->connect("text_changed", this, "_text_changed");
1984 	search_box->connect("gui_input", this, "_sbox_input");
1985 	add_child(search_box);
1986 
1987 	size_slider = memnew(HSlider);
1988 	size_slider->set_h_size_flags(SIZE_EXPAND_FILL);
1989 	size_slider->set_min(0.1f);
1990 	size_slider->set_max(4.0f);
1991 	size_slider->set_step(0.1f);
1992 	size_slider->set_value(1.0f);
1993 	size_slider->connect("value_changed", this, "_icon_size_changed");
1994 	add_child(size_slider);
1995 
1996 	int mw = EDITOR_DEF("editors/tile_map/palette_min_width", 80);
1997 
1998 	VSplitContainer *palette_container = memnew(VSplitContainer);
1999 	palette_container->set_v_size_flags(SIZE_EXPAND_FILL);
2000 	palette_container->set_custom_minimum_size(Size2(mw, 0));
2001 	add_child(palette_container);
2002 
2003 	// Add tile palette.
2004 	palette = memnew(ItemList);
2005 	palette->set_h_size_flags(SIZE_EXPAND_FILL);
2006 	palette->set_v_size_flags(SIZE_EXPAND_FILL);
2007 	palette->set_max_columns(0);
2008 	palette->set_icon_mode(ItemList::ICON_MODE_TOP);
2009 	palette->set_max_text_lines(2);
2010 	palette->set_select_mode(ItemList::SELECT_MULTI);
2011 	palette->add_constant_override("vseparation", 8 * EDSCALE);
2012 	palette->connect("item_selected", this, "_palette_selected");
2013 	palette->connect("multi_selected", this, "_palette_multi_selected");
2014 	palette->connect("gui_input", this, "_palette_input");
2015 	palette_container->add_child(palette);
2016 
2017 	// Add message for when no texture is selected.
2018 	info_message = memnew(Label);
2019 	info_message->set_text(TTR("Give a TileSet resource to this TileMap to use its tiles."));
2020 	info_message->set_valign(Label::VALIGN_CENTER);
2021 	info_message->set_align(Label::ALIGN_CENTER);
2022 	info_message->set_autowrap(true);
2023 	info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
2024 	info_message->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
2025 	palette->add_child(info_message);
2026 
2027 	// Add autotile override palette.
2028 	manual_palette = memnew(ItemList);
2029 	manual_palette->set_h_size_flags(SIZE_EXPAND_FILL);
2030 	manual_palette->set_v_size_flags(SIZE_EXPAND_FILL);
2031 	manual_palette->set_max_columns(0);
2032 	manual_palette->set_icon_mode(ItemList::ICON_MODE_TOP);
2033 	manual_palette->set_max_text_lines(2);
2034 	manual_palette->hide();
2035 	palette_container->add_child(manual_palette);
2036 
2037 	// Add menu items.
2038 	toolbar = memnew(HBoxContainer);
2039 	toolbar->hide();
2040 	CanvasItemEditor::get_singleton()->add_control_to_menu_panel(toolbar);
2041 
2042 	toolbar->add_child(memnew(VSeparator));
2043 
2044 	// Tools.
2045 	paint_button = memnew(ToolButton);
2046 	paint_button->set_shortcut(ED_SHORTCUT("tile_map_editor/paint_tile", TTR("Paint Tile"), KEY_P));
2047 	paint_button->set_tooltip(TTR("Shift+LMB: Line Draw\nShift+Ctrl+LMB: Rectangle Paint"));
2048 	paint_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_NONE));
2049 	paint_button->set_toggle_mode(true);
2050 	toolbar->add_child(paint_button);
2051 
2052 	bucket_fill_button = memnew(ToolButton);
2053 	bucket_fill_button->set_shortcut(ED_SHORTCUT("tile_map_editor/bucket_fill", TTR("Bucket Fill"), KEY_B));
2054 	bucket_fill_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_BUCKET));
2055 	bucket_fill_button->set_toggle_mode(true);
2056 	toolbar->add_child(bucket_fill_button);
2057 
2058 	picker_button = memnew(ToolButton);
2059 	picker_button->set_shortcut(ED_SHORTCUT("tile_map_editor/pick_tile", TTR("Pick Tile"), KEY_I));
2060 	picker_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_PICKING));
2061 	picker_button->set_toggle_mode(true);
2062 	toolbar->add_child(picker_button);
2063 
2064 	select_button = memnew(ToolButton);
2065 	select_button->set_shortcut(ED_SHORTCUT("tile_map_editor/select", TTR("Select"), KEY_M));
2066 	select_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_SELECTING));
2067 	select_button->set_toggle_mode(true);
2068 	toolbar->add_child(select_button);
2069 
2070 	_update_button_tool();
2071 
2072 	// Container to the right of the toolbar.
2073 	toolbar_right = memnew(HBoxContainer);
2074 	toolbar_right->hide();
2075 	toolbar_right->set_h_size_flags(SIZE_EXPAND_FILL);
2076 	toolbar_right->set_alignment(BoxContainer::ALIGN_END);
2077 	CanvasItemEditor::get_singleton()->add_control_to_menu_panel(toolbar_right);
2078 
2079 	// Tile position.
2080 	tile_info = memnew(Label);
2081 	tile_info->set_modulate(Color(1, 1, 1, 0.8));
2082 	tile_info->set_mouse_filter(MOUSE_FILTER_IGNORE);
2083 	tile_info->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("main", "EditorFonts"));
2084 	// The tile info is only displayed after a tile has been hovered.
2085 	tile_info->hide();
2086 	CanvasItemEditor::get_singleton()->add_control_to_info_overlay(tile_info);
2087 
2088 	// Menu.
2089 	options = memnew(MenuButton);
2090 	options->set_text("TileMap");
2091 	options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("TileMap", "EditorIcons"));
2092 	options->set_process_unhandled_key_input(false);
2093 	toolbar_right->add_child(options);
2094 
2095 	PopupMenu *p = options->get_popup();
2096 	p->add_shortcut(ED_SHORTCUT("tile_map_editor/cut_selection", TTR("Cut Selection"), KEY_MASK_CMD + KEY_X), OPTION_CUT);
2097 	p->add_shortcut(ED_SHORTCUT("tile_map_editor/copy_selection", TTR("Copy Selection"), KEY_MASK_CMD + KEY_C), OPTION_COPY);
2098 	p->add_shortcut(ED_GET_SHORTCUT("tile_map_editor/erase_selection"), OPTION_ERASE_SELECTION);
2099 	p->add_separator();
2100 	p->add_item(TTR("Fix Invalid Tiles"), OPTION_FIX_INVALID);
2101 	p->connect("id_pressed", this, "_menu_option");
2102 
2103 	rotate_left_button = memnew(ToolButton);
2104 	rotate_left_button->set_tooltip(TTR("Rotate Left"));
2105 	rotate_left_button->set_focus_mode(FOCUS_NONE);
2106 	rotate_left_button->connect("pressed", this, "_rotate", varray(-1));
2107 	rotate_left_button->set_shortcut(ED_SHORTCUT("tile_map_editor/rotate_left", TTR("Rotate Left"), KEY_A));
2108 	tool_hb->add_child(rotate_left_button);
2109 
2110 	rotate_right_button = memnew(ToolButton);
2111 	rotate_right_button->set_tooltip(TTR("Rotate Right"));
2112 	rotate_right_button->set_focus_mode(FOCUS_NONE);
2113 	rotate_right_button->connect("pressed", this, "_rotate", varray(1));
2114 	rotate_right_button->set_shortcut(ED_SHORTCUT("tile_map_editor/rotate_right", TTR("Rotate Right"), KEY_S));
2115 	tool_hb->add_child(rotate_right_button);
2116 
2117 	flip_horizontal_button = memnew(ToolButton);
2118 	flip_horizontal_button->set_tooltip(TTR("Flip Horizontally"));
2119 	flip_horizontal_button->set_focus_mode(FOCUS_NONE);
2120 	flip_horizontal_button->connect("pressed", this, "_flip_horizontal");
2121 	flip_horizontal_button->set_shortcut(ED_SHORTCUT("tile_map_editor/flip_horizontal", TTR("Flip Horizontally"), KEY_X));
2122 	tool_hb->add_child(flip_horizontal_button);
2123 
2124 	flip_vertical_button = memnew(ToolButton);
2125 	flip_vertical_button->set_tooltip(TTR("Flip Vertically"));
2126 	flip_vertical_button->set_focus_mode(FOCUS_NONE);
2127 	flip_vertical_button->connect("pressed", this, "_flip_vertical");
2128 	flip_vertical_button->set_shortcut(ED_SHORTCUT("tile_map_editor/flip_vertical", TTR("Flip Vertically"), KEY_Z));
2129 	tool_hb->add_child(flip_vertical_button);
2130 
2131 	clear_transform_button = memnew(ToolButton);
2132 	clear_transform_button->set_tooltip(TTR("Clear Transform"));
2133 	clear_transform_button->set_focus_mode(FOCUS_NONE);
2134 	clear_transform_button->connect("pressed", this, "_clear_transform");
2135 	clear_transform_button->set_shortcut(ED_SHORTCUT("tile_map_editor/clear_transform", TTR("Clear Transform"), KEY_W));
2136 	tool_hb->add_child(clear_transform_button);
2137 
2138 	clear_transform_button->set_disabled(true);
2139 }
2140 
2141 TileMapEditor::~TileMapEditor() {
2142 	_clear_bucket_cache();
2143 	copydata.clear();
2144 }
2145 
2146 ///////////////////////////////////////////////////////////////
2147 ///////////////////////////////////////////////////////////////
2148 ///////////////////////////////////////////////////////////////
2149 
2150 void TileMapEditorPlugin::_notification(int p_what) {
2151 
2152 	if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
2153 
2154 		switch ((int)EditorSettings::get_singleton()->get("editors/tile_map/editor_side")) {
2155 			case 0: { // Left.
2156 				CanvasItemEditor::get_singleton()->get_palette_split()->move_child(tile_map_editor, 0);
2157 			} break;
2158 			case 1: { // Right.
2159 				CanvasItemEditor::get_singleton()->get_palette_split()->move_child(tile_map_editor, 1);
2160 			} break;
2161 		}
2162 	}
2163 }
2164 
2165 void TileMapEditorPlugin::edit(Object *p_object) {
2166 
2167 	tile_map_editor->edit(Object::cast_to<Node>(p_object));
2168 }
2169 
2170 bool TileMapEditorPlugin::handles(Object *p_object) const {
2171 
2172 	return p_object->is_class("TileMap");
2173 }
2174 
2175 void TileMapEditorPlugin::make_visible(bool p_visible) {
2176 
2177 	if (p_visible) {
2178 
2179 		tile_map_editor->show();
2180 		tile_map_editor->get_toolbar()->show();
2181 		tile_map_editor->get_toolbar_right()->show();
2182 		// `tile_info` isn't shown here, as it's displayed after a tile has been hovered.
2183 		// Otherwise, a translucent black rectangle would be visible as there would be an
2184 		// empty Label in the CanvasItemEditor's info overlay.
2185 
2186 		// Change to TOOL_SELECT when TileMap node is selected, to prevent accidental movement.
2187 		CanvasItemEditor::get_singleton()->set_current_tool(CanvasItemEditor::TOOL_SELECT);
2188 	} else {
2189 
2190 		tile_map_editor->hide();
2191 		tile_map_editor->get_toolbar()->hide();
2192 		tile_map_editor->get_toolbar_right()->hide();
2193 		tile_map_editor->get_tile_info()->hide();
2194 		tile_map_editor->edit(NULL);
2195 	}
2196 }
2197 
2198 TileMapEditorPlugin::TileMapEditorPlugin(EditorNode *p_node) {
2199 
2200 	EDITOR_DEF("editors/tile_map/preview_size", 64);
2201 	EDITOR_DEF("editors/tile_map/palette_item_hseparation", 8);
2202 	EDITOR_DEF("editors/tile_map/show_tile_names", true);
2203 	EDITOR_DEF("editors/tile_map/show_tile_ids", false);
2204 	EDITOR_DEF("editors/tile_map/sort_tiles_by_name", true);
2205 	EDITOR_DEF("editors/tile_map/bucket_fill_preview", true);
2206 	EDITOR_DEF("editors/tile_map/editor_side", 1);
2207 	EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "editors/tile_map/editor_side", PROPERTY_HINT_ENUM, "Left,Right"));
2208 
2209 	tile_map_editor = memnew(TileMapEditor(p_node));
2210 	switch ((int)EditorSettings::get_singleton()->get("editors/tile_map/editor_side")) {
2211 		case 0: { // Left.
2212 			add_control_to_container(CONTAINER_CANVAS_EDITOR_SIDE_LEFT, tile_map_editor);
2213 		} break;
2214 		case 1: { // Right.
2215 			add_control_to_container(CONTAINER_CANVAS_EDITOR_SIDE_RIGHT, tile_map_editor);
2216 		} break;
2217 	}
2218 	tile_map_editor->hide();
2219 }
2220 
2221 TileMapEditorPlugin::~TileMapEditorPlugin() {
2222 }
2223