summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/classes/TileMap.xml5
-rw-r--r--doc/classes/TileMapLayerGroup.xml17
-rw-r--r--editor/plugins/tiles/tile_map_layer_editor.cpp (renamed from editor/plugins/tiles/tile_map_editor.cpp)1342
-rw-r--r--editor/plugins/tiles/tile_map_layer_editor.h (renamed from editor/plugins/tiles/tile_map_editor.h)79
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.cpp152
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.h16
-rw-r--r--misc/extension_api_validation/4.2-stable.expected9
-rw-r--r--scene/2d/tile_map.cpp317
-rw-r--r--scene/2d/tile_map.h26
-rw-r--r--scene/2d/tile_map_layer.cpp322
-rw-r--r--scene/2d/tile_map_layer.h33
-rw-r--r--scene/2d/tile_map_layer_group.cpp148
-rw-r--r--scene/2d/tile_map_layer_group.h73
-rw-r--r--scene/register_scene_types.cpp1
-rw-r--r--scene/resources/tile_set.cpp191
-rw-r--r--scene/resources/tile_set.h13
16 files changed, 1496 insertions, 1248 deletions
diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml
index b08eb5c013..695ffca1a3 100644
--- a/doc/classes/TileMap.xml
+++ b/doc/classes/TileMap.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="TileMap" inherits="Node2D" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="TileMap" inherits="TileMapLayerGroup" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Node for 2D tile-based maps.
</brief_description>
@@ -488,9 +488,6 @@
The quadrant size does not apply on Y-sorted layers, as tiles are be grouped by Y position instead in that case.
[b]Note:[/b] As quadrants are created according to the map's coordinate system, the quadrant's "square shape" might not look like square in the TileMap's local coordinate system.
</member>
- <member name="tile_set" type="TileSet" setter="set_tileset" getter="get_tileset">
- The assigned [TileSet].
- </member>
</members>
<signals>
<signal name="changed">
diff --git a/doc/classes/TileMapLayerGroup.xml b/doc/classes/TileMapLayerGroup.xml
new file mode 100644
index 0000000000..3787d3bb17
--- /dev/null
+++ b/doc/classes/TileMapLayerGroup.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="TileMapLayerGroup" inherits="Node2D" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ Groups a set of tile map layers together, allowing them to share a provided [TileSet].
+ </brief_description>
+ <description>
+ Groups together tile map layers as part or the same map, replacing the [TileMap] node. Child layers will use this node's [member tile_set].
+ The editor also uses [TileMapLayerGroup] as a way to store which layers are selected in a given group. This allows highlighting the currently selected layers.
+ </description>
+ <tutorials>
+ </tutorials>
+ <members>
+ <member name="tile_set" type="TileSet" setter="set_tileset" getter="get_tileset">
+ The assigned [TileSet]. This TileSet will be applied to all child layers.
+ </member>
+ </members>
+</class>
diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_layer_editor.cpp
index c34878b54e..1551fabc0c 100644
--- a/editor/plugins/tiles/tile_map_editor.cpp
+++ b/editor/plugins/tiles/tile_map_layer_editor.cpp
@@ -1,5 +1,5 @@
/**************************************************************************/
-/* tile_map_editor.cpp */
+/* tile_map_layer_editor.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
-#include "tile_map_editor.h"
+#include "tile_map_layer_editor.h"
#include "tiles_editor_plugin.h"
@@ -40,6 +40,7 @@
#include "editor/themes/editor_scale.h"
#include "scene/2d/camera_2d.h"
+#include "scene/2d/tile_map_layer.h"
#include "scene/gui/center_container.h"
#include "scene/gui/split_container.h"
@@ -47,22 +48,26 @@
#include "core/math/geometry_2d.h"
#include "core/os/keyboard.h"
-void TileMapEditorTilesPlugin::tile_set_changed() {
+TileMapLayer *TileMapLayerSubEditorPlugin::_get_edited_layer() const {
+ return Object::cast_to<TileMapLayer>(ObjectDB::get_instance(edited_tile_map_layer_id));
+}
+
+void TileMapLayerEditorTilesPlugin::tile_set_changed() {
_update_fix_selected_and_hovered();
_update_tile_set_sources_list();
_update_source_display();
_update_patterns_list();
}
-void TileMapEditorTilesPlugin::_on_random_tile_checkbox_toggled(bool p_pressed) {
+void TileMapLayerEditorTilesPlugin::_on_random_tile_checkbox_toggled(bool p_pressed) {
scatter_controls_container->set_visible(p_pressed);
}
-void TileMapEditorTilesPlugin::_on_scattering_spinbox_changed(double p_value) {
+void TileMapLayerEditorTilesPlugin::_on_scattering_spinbox_changed(double p_value) {
scattering = p_value;
}
-void TileMapEditorTilesPlugin::_update_toolbar() {
+void TileMapLayerEditorTilesPlugin::_update_toolbar() {
// Stop draggig if needed.
_stop_dragging();
@@ -96,13 +101,13 @@ void TileMapEditorTilesPlugin::_update_toolbar() {
}
}
-void TileMapEditorTilesPlugin::_update_transform_buttons() {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditorTilesPlugin::_update_transform_buttons() {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
if (tile_set.is_null() || selection_pattern.is_null()) {
return;
}
@@ -126,7 +131,7 @@ void TileMapEditorTilesPlugin::_update_transform_buttons() {
}
}
-void TileMapEditorTilesPlugin::_set_transform_buttons_state(const Vector<Button *> &p_enabled_buttons, const Vector<Button *> &p_disabled_buttons, const String &p_why_disabled) {
+void TileMapLayerEditorTilesPlugin::_set_transform_buttons_state(const Vector<Button *> &p_enabled_buttons, const Vector<Button *> &p_disabled_buttons, const String &p_why_disabled) {
for (Button *button : p_enabled_buttons) {
button->set_disabled(false);
button->set_tooltip_text("");
@@ -137,14 +142,14 @@ void TileMapEditorTilesPlugin::_set_transform_buttons_state(const Vector<Button
}
}
-Vector<TileMapSubEditorPlugin::TabData> TileMapEditorTilesPlugin::get_tabs() const {
- Vector<TileMapSubEditorPlugin::TabData> tabs;
+Vector<TileMapLayerSubEditorPlugin::TabData> TileMapLayerEditorTilesPlugin::get_tabs() const {
+ Vector<TileMapLayerSubEditorPlugin::TabData> tabs;
tabs.push_back({ toolbar, tiles_bottom_panel });
tabs.push_back({ toolbar, patterns_bottom_panel });
return tabs;
}
-void TileMapEditorTilesPlugin::_tab_changed() {
+void TileMapLayerEditorTilesPlugin::_tab_changed() {
if (tiles_bottom_panel->is_visible_in_tree()) {
_update_selection_pattern_from_tileset_tiles_selection();
} else if (patterns_bottom_panel->is_visible_in_tree()) {
@@ -152,7 +157,7 @@ void TileMapEditorTilesPlugin::_tab_changed() {
}
}
-void TileMapEditorTilesPlugin::_update_tile_set_sources_list() {
+void TileMapLayerEditorTilesPlugin::_update_tile_set_sources_list() {
// Update the sources.
int old_current = sources_list->get_current();
int old_source = -1;
@@ -161,13 +166,13 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() {
}
sources_list->clear();
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
@@ -244,15 +249,15 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() {
TilesEditorUtils::get_singleton()->set_sources_lists_current(sources_list->get_current());
}
-void TileMapEditorTilesPlugin::_update_source_display() {
+void TileMapLayerEditorTilesPlugin::_update_source_display() {
// Update the atlas display.
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
@@ -291,14 +296,14 @@ void TileMapEditorTilesPlugin::_update_source_display() {
}
}
-void TileMapEditorTilesPlugin::_patterns_item_list_gui_input(const Ref<InputEvent> &p_event) {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditorTilesPlugin::_patterns_item_list_gui_input(const Ref<InputEvent> &p_event) {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid() || EditorNode::get_singleton()->is_resource_read_only(tile_set)) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
@@ -327,7 +332,7 @@ void TileMapEditorTilesPlugin::_patterns_item_list_gui_input(const Ref<InputEven
}
}
-void TileMapEditorTilesPlugin::_pattern_preview_done(Ref<TileMapPattern> p_pattern, Ref<Texture2D> p_texture) {
+void TileMapLayerEditorTilesPlugin::_pattern_preview_done(Ref<TileMapPattern> p_pattern, Ref<Texture2D> p_texture) {
// TODO optimize ?
for (int i = 0; i < patterns_item_list->get_item_count(); i++) {
if (patterns_item_list->get_item_metadata(i) == p_pattern) {
@@ -337,14 +342,14 @@ void TileMapEditorTilesPlugin::_pattern_preview_done(Ref<TileMapPattern> p_patte
}
}
-void TileMapEditorTilesPlugin::_update_patterns_list() {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditorTilesPlugin::_update_patterns_list() {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
@@ -354,7 +359,7 @@ void TileMapEditorTilesPlugin::_update_patterns_list() {
int id = patterns_item_list->add_item("");
patterns_item_list->set_item_metadata(id, tile_set->get_pattern(i));
patterns_item_list->set_item_tooltip(id, vformat(TTR("Index: %d"), i));
- TilesEditorUtils::get_singleton()->queue_pattern_preview(tile_set, tile_set->get_pattern(i), callable_mp(this, &TileMapEditorTilesPlugin::_pattern_preview_done));
+ TilesEditorUtils::get_singleton()->queue_pattern_preview(tile_set, tile_set->get_pattern(i), callable_mp(this, &TileMapLayerEditorTilesPlugin::_pattern_preview_done));
}
// Update the label visibility.
@@ -369,14 +374,14 @@ void TileMapEditorTilesPlugin::_update_patterns_list() {
select_last_pattern = false;
}
-void TileMapEditorTilesPlugin::_update_atlas_view() {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditorTilesPlugin::_update_atlas_view() {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
@@ -385,19 +390,19 @@ void TileMapEditorTilesPlugin::_update_atlas_view() {
TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
ERR_FAIL_NULL(atlas_source);
- tile_atlas_view->set_atlas_source(*tile_map->get_tileset(), atlas_source, source_id);
+ tile_atlas_view->set_atlas_source(*tile_set, atlas_source, source_id);
TilesEditorUtils::get_singleton()->synchronize_atlas_view(tile_atlas_view);
tile_atlas_control->queue_redraw();
}
-void TileMapEditorTilesPlugin::_update_scenes_collection_view() {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditorTilesPlugin::_update_scenes_collection_view() {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
@@ -440,7 +445,7 @@ void TileMapEditorTilesPlugin::_update_scenes_collection_view() {
scene_tiles_list->set_fixed_icon_size(Vector2(int_size, int_size));
}
-void TileMapEditorTilesPlugin::_scene_thumbnail_done(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, Variant p_ud) {
+void TileMapLayerEditorTilesPlugin::_scene_thumbnail_done(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, Variant p_ud) {
int index = p_ud;
if (index >= 0 && index < scene_tiles_list->get_item_count()) {
@@ -448,14 +453,14 @@ void TileMapEditorTilesPlugin::_scene_thumbnail_done(const String &p_path, const
}
}
-void TileMapEditorTilesPlugin::_scenes_list_multi_selected(int p_index, bool p_selected) {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditorTilesPlugin::_scenes_list_multi_selected(int p_index, bool p_selected) {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
@@ -484,7 +489,7 @@ void TileMapEditorTilesPlugin::_scenes_list_multi_selected(int p_index, bool p_s
_update_selection_pattern_from_tileset_tiles_selection();
}
-void TileMapEditorTilesPlugin::_scenes_list_lmb_empty_clicked(const Vector2 &p_pos, MouseButton p_mouse_button_index) {
+void TileMapLayerEditorTilesPlugin::_scenes_list_lmb_empty_clicked(const Vector2 &p_pos, MouseButton p_mouse_button_index) {
if (p_mouse_button_index != MouseButton::LEFT) {
return;
}
@@ -496,7 +501,7 @@ void TileMapEditorTilesPlugin::_scenes_list_lmb_empty_clicked(const Vector2 &p_p
_update_selection_pattern_from_tileset_tiles_selection();
}
-void TileMapEditorTilesPlugin::_update_theme() {
+void TileMapLayerEditorTilesPlugin::_update_theme() {
source_sort_button->set_icon(tiles_bottom_panel->get_editor_theme_icon(SNAME("Sort")));
select_tool_button->set_icon(tiles_bottom_panel->get_editor_theme_icon(SNAME("ToolSelect")));
paint_tool_button->set_icon(tiles_bottom_panel->get_editor_theme_icon(SNAME("Edit")));
@@ -517,7 +522,7 @@ void TileMapEditorTilesPlugin::_update_theme() {
_update_tile_set_sources_list();
}
-bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
+bool TileMapLayerEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
if (!(tiles_bottom_panel->is_visible_in_tree() || patterns_bottom_panel->is_visible_in_tree())) {
// If the bottom editor is not visible, we ignore inputs.
return false;
@@ -528,18 +533,13 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
return false;
}
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return false;
}
- if (tile_map_layer < 0) {
- return false;
- }
- ERR_FAIL_INDEX_V(tile_map_layer, tile_map->get_layers_count(), false);
-
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return false;
}
@@ -552,7 +552,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
for (const Vector2i &E : tile_map_selection) {
coords_array.push_back(E);
}
- tile_map_clipboard = tile_map->get_pattern(tile_map_layer, coords_array);
+ tile_map_clipboard = edited_layer->get_pattern(coords_array);
}
if (ED_IS_SHORTCUT("tiles_editor/cut", p_event)) {
@@ -560,9 +560,9 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
if (!tile_map_selection.is_empty()) {
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
undo_redo->create_action(TTR("Delete tiles"));
- for (const Vector2i &E : tile_map_selection) {
- undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
- undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E, tile_map->get_cell_source_id(tile_map_layer, E), tile_map->get_cell_atlas_coords(tile_map_layer, E), tile_map->get_cell_alternative_tile(tile_map_layer, E));
+ for (const Vector2i &coords : tile_map_selection) {
+ undo_redo->add_do_method(edited_layer, "set_cell", coords, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
+ undo_redo->add_undo_method(edited_layer, "set_cell", coords, edited_layer->get_cell_source_id(coords), edited_layer->get_cell_atlas_coords(coords), edited_layer->get_cell_alternative_tile(coords));
}
undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection());
tile_map_selection.clear();
@@ -592,9 +592,9 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
if (!tile_map_selection.is_empty()) {
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
undo_redo->create_action(TTR("Delete tiles"));
- for (const Vector2i &E : tile_map_selection) {
- undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
- undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E, tile_map->get_cell_source_id(tile_map_layer, E), tile_map->get_cell_atlas_coords(tile_map_layer, E), tile_map->get_cell_alternative_tile(tile_map_layer, E));
+ for (const Vector2i &coords : tile_map_selection) {
+ undo_redo->add_do_method(edited_layer, "set_cell", coords, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
+ undo_redo->add_undo_method(edited_layer, "set_cell", coords, edited_layer->get_cell_source_id(coords), edited_layer->get_cell_atlas_coords(coords), edited_layer->get_cell_alternative_tile(coords));
}
undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection());
tile_map_selection.clear();
@@ -626,7 +626,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid()) {
has_mouse = true;
- Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform_with_canvas();
+ Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * edited_layer->get_global_transform_with_canvas();
Vector2 mpos = xform.affine_inverse().xform(mm->get_position());
switch (drag_type) {
@@ -635,28 +635,28 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) {
Vector2i coords = E.key;
if (!drag_modified.has(coords)) {
- drag_modified.insert(coords, tile_map->get_cell(tile_map_layer, coords));
+ drag_modified.insert(coords, edited_layer->get_cell(coords));
if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) {
continue;
}
- tile_map->set_cell(tile_map_layer, coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
+ edited_layer->set_cell(coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
}
}
_fix_invalid_tiles_in_tile_map_selection();
} break;
case DRAG_TYPE_BUCKET: {
- Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->local_to_map(drag_last_mouse_pos), tile_map->local_to_map(mpos));
+ Vector<Vector2i> line = TileMapLayerEditor::get_line(edited_layer, tile_set->local_to_map(drag_last_mouse_pos), tile_set->local_to_map(mpos));
for (int i = 0; i < line.size(); i++) {
if (!drag_modified.has(line[i])) {
HashMap<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_contiguous_checkbox->is_pressed(), drag_erasing);
for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) {
Vector2i coords = E.key;
if (!drag_modified.has(coords)) {
- drag_modified.insert(coords, tile_map->get_cell(tile_map_layer, coords));
+ drag_modified.insert(coords, edited_layer->get_cell(coords));
if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) {
continue;
}
- tile_map->set_cell(tile_map_layer, coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
+ edited_layer->set_cell(coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
}
}
}
@@ -675,7 +675,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
has_mouse = true;
- Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform_with_canvas();
+ Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * edited_layer->get_global_transform_with_canvas();
Vector2 mpos = xform.affine_inverse().xform(mb->get_position());
if (mb->get_button_index() == MouseButton::LEFT || mb->get_button_index() == MouseButton::RIGHT) {
@@ -692,15 +692,15 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
}
} else if (tool_buttons_group->get_pressed_button() == select_tool_button) {
drag_start_mouse_pos = mpos;
- if (tile_map_selection.has(tile_map->local_to_map(drag_start_mouse_pos)) && !mb->is_shift_pressed() && !mb->is_command_or_control_pressed()) {
+ if (tile_map_selection.has(tile_set->local_to_map(drag_start_mouse_pos)) && !mb->is_shift_pressed() && !mb->is_command_or_control_pressed()) {
// Move the selection
_update_selection_pattern_from_tilemap_selection(); // Make sure the pattern is up to date before moving.
drag_type = DRAG_TYPE_MOVE;
drag_modified.clear();
for (const Vector2i &E : tile_map_selection) {
Vector2i coords = E;
- drag_modified.insert(coords, tile_map->get_cell(tile_map_layer, coords));
- tile_map->set_cell(tile_map_layer, coords, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
+ drag_modified.insert(coords, edited_layer->get_cell(coords));
+ edited_layer->set_cell(coords, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
}
} else {
// Select tiles
@@ -724,9 +724,9 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
}
Vector2i coords = E.key;
if (!drag_modified.has(coords)) {
- drag_modified.insert(coords, tile_map->get_cell(tile_map_layer, coords));
+ drag_modified.insert(coords, edited_layer->get_cell(coords));
}
- tile_map->set_cell(tile_map_layer, coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
+ edited_layer->set_cell(coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
}
_fix_invalid_tiles_in_tile_map_selection();
} else if (tool_buttons_group->get_pressed_button() == line_tool_button || (tool_buttons_group->get_pressed_button() == paint_tool_button && Input::get_singleton()->is_key_pressed(Key::SHIFT) && !Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL))) {
@@ -741,18 +741,18 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
drag_type = DRAG_TYPE_BUCKET;
drag_start_mouse_pos = mpos;
drag_modified.clear();
- Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->local_to_map(drag_last_mouse_pos), tile_map->local_to_map(mpos));
+ Vector<Vector2i> line = TileMapLayerEditor::get_line(edited_layer, tile_set->local_to_map(drag_last_mouse_pos), tile_set->local_to_map(mpos));
for (int i = 0; i < line.size(); i++) {
if (!drag_modified.has(line[i])) {
HashMap<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_contiguous_checkbox->is_pressed(), drag_erasing);
for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) {
Vector2i coords = E.key;
if (!drag_modified.has(coords)) {
- drag_modified.insert(coords, tile_map->get_cell(tile_map_layer, coords));
+ drag_modified.insert(coords, edited_layer->get_cell(coords));
if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) {
continue;
}
- tile_map->set_cell(tile_map_layer, coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
+ edited_layer->set_cell(coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
}
}
}
@@ -778,28 +778,23 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
return false;
}
-void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_overlay) {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
- return;
- }
-
- if (tile_map_layer < 0) {
+void TileMapLayerEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_overlay) {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- ERR_FAIL_INDEX(tile_map_layer, tile_map->get_layers_count());
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
- if (!tile_map->is_visible_in_tree()) {
+ if (!edited_layer->is_visible_in_tree()) {
return;
}
- Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform_with_canvas();
- Vector2 mpos = tile_map->get_local_mouse_position();
+ Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * edited_layer->get_global_transform_with_canvas();
+ Vector2 mpos = edited_layer->get_local_mouse_position();
Vector2i tile_shape_size = tile_set->get_tile_size();
// Draw the selection.
@@ -810,7 +805,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
} else {
Color grid_color = EDITOR_GET("editors/tiles_editor/grid_color");
Color selection_color = Color().from_hsv(Math::fposmod(grid_color.get_h() + 0.5, 1.0), grid_color.get_s(), grid_color.get_v(), 1.0);
- tile_map->draw_cells_outline(p_overlay, tile_map_selection, selection_color, xform);
+ tile_set->draw_cells_outline(p_overlay, tile_map_selection, selection_color, xform);
}
}
@@ -821,33 +816,33 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
if (drag_type == DRAG_TYPE_PICK) {
// Draw the area being picked.
- Rect2i rect = Rect2i(tile_map->local_to_map(drag_start_mouse_pos), tile_map->local_to_map(mpos) - tile_map->local_to_map(drag_start_mouse_pos)).abs();
+ Rect2i rect = Rect2i(tile_set->local_to_map(drag_start_mouse_pos), tile_set->local_to_map(mpos) - tile_set->local_to_map(drag_start_mouse_pos)).abs();
rect.size += Vector2i(1, 1);
for (int x = rect.position.x; x < rect.get_end().x; x++) {
for (int y = rect.position.y; y < rect.get_end().y; y++) {
Vector2i coords = Vector2i(x, y);
- if (tile_map->get_cell_source_id(tile_map_layer, coords) != TileSet::INVALID_SOURCE) {
- Transform2D tile_xform(0, tile_shape_size, 0, tile_map->map_to_local(coords));
+ if (edited_layer->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
+ Transform2D tile_xform(0, tile_shape_size, 0, tile_set->map_to_local(coords));
tile_set->draw_tile_shape(p_overlay, xform * tile_xform, Color(1.0, 1.0, 1.0), false);
}
}
}
} else if (drag_type == DRAG_TYPE_SELECT) {
// Draw the area being selected.
- Rect2i rect = Rect2i(tile_map->local_to_map(drag_start_mouse_pos), tile_map->local_to_map(mpos) - tile_map->local_to_map(drag_start_mouse_pos)).abs();
+ Rect2i rect = Rect2i(tile_set->local_to_map(drag_start_mouse_pos), tile_set->local_to_map(mpos) - tile_set->local_to_map(drag_start_mouse_pos)).abs();
rect.size += Vector2i(1, 1);
RBSet<Vector2i> to_draw;
for (int x = rect.position.x; x < rect.get_end().x; x++) {
for (int y = rect.position.y; y < rect.get_end().y; y++) {
Vector2i coords = Vector2i(x, y);
- if (tile_map->get_cell_source_id(tile_map_layer, coords) != TileSet::INVALID_SOURCE) {
+ if (edited_layer->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
to_draw.insert(coords);
}
- Transform2D tile_xform(0, tile_shape_size, 0, tile_map->map_to_local(coords));
+ Transform2D tile_xform(0, tile_shape_size, 0, tile_set->map_to_local(coords));
tile_set->draw_tile_shape(p_overlay, xform * tile_xform, Color(1.0, 1.0, 1.0, 0.2), true);
}
}
- tile_map->draw_cells_outline(p_overlay, to_draw, Color(1.0, 1.0, 1.0), xform);
+ tile_set->draw_cells_outline(p_overlay, to_draw, Color(1.0, 1.0, 1.0), xform);
} else if (drag_type == DRAG_TYPE_MOVE) {
if (!(patterns_item_list->is_visible_in_tree() && patterns_item_list->has_point(patterns_item_list->get_local_mouse_position()))) {
// Preview when moving.
@@ -858,12 +853,12 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
for (const Vector2i &E : tile_map_selection) {
top_left = top_left.min(E);
}
- Vector2i offset = drag_start_mouse_pos - tile_map->map_to_local(top_left);
- offset = tile_map->local_to_map(mpos - offset) - tile_map->local_to_map(drag_start_mouse_pos - offset);
+ Vector2i offset = drag_start_mouse_pos - tile_set->map_to_local(top_left);
+ offset = tile_set->local_to_map(mpos - offset) - tile_set->local_to_map(drag_start_mouse_pos - offset);
TypedArray<Vector2i> selection_used_cells = selection_pattern->get_used_cells();
for (int i = 0; i < selection_used_cells.size(); i++) {
- Vector2i coords = tile_map->map_pattern(offset + top_left, selection_used_cells[i], selection_pattern);
+ Vector2i coords = tile_set->map_pattern(offset + top_left, selection_used_cells[i], selection_pattern);
preview[coords] = TileMapCell(selection_pattern->get_cell_source_id(selection_used_cells[i]), selection_pattern->get_cell_atlas_coords(selection_used_cells[i]), selection_pattern->get_cell_alternative_tile(selection_used_cells[i]));
}
}
@@ -872,7 +867,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
Vector2 mouse_offset = (Vector2(tile_map_clipboard->get_size()) / 2.0 - Vector2(0.5, 0.5)) * tile_set->get_tile_size();
TypedArray<Vector2i> clipboard_used_cells = tile_map_clipboard->get_used_cells();
for (int i = 0; i < clipboard_used_cells.size(); i++) {
- Vector2i coords = tile_map->map_pattern(tile_map->local_to_map(mpos - mouse_offset), clipboard_used_cells[i], tile_map_clipboard);
+ Vector2i coords = tile_set->map_pattern(tile_set->local_to_map(mpos - mouse_offset), clipboard_used_cells[i], tile_map_clipboard);
preview[coords] = TileMapCell(tile_map_clipboard->get_cell_source_id(clipboard_used_cells[i]), tile_map_clipboard->get_cell_atlas_coords(clipboard_used_cells[i]), tile_map_clipboard->get_cell_alternative_tile(clipboard_used_cells[i]));
}
} else if (!picker_button->is_pressed() && !(drag_type == DRAG_TYPE_NONE && Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL) && !Input::get_singleton()->is_key_pressed(Key::SHIFT))) {
@@ -893,11 +888,11 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
}
} else if (drag_type == DRAG_TYPE_RECT) {
// Preview for a rect pattern.
- preview = _draw_rect(tile_map->local_to_map(drag_start_mouse_pos), tile_map->local_to_map(mpos), drag_erasing);
+ preview = _draw_rect(tile_set->local_to_map(drag_start_mouse_pos), tile_set->local_to_map(mpos), drag_erasing);
expand_grid = true;
} else if (tool_buttons_group->get_pressed_button() == bucket_tool_button && drag_type == DRAG_TYPE_NONE) {
// Preview for a fill pattern.
- preview = _draw_bucket_fill(tile_map->local_to_map(mpos), bucket_contiguous_checkbox->is_pressed(), erase_button->is_pressed());
+ preview = _draw_bucket_fill(tile_set->local_to_map(mpos), bucket_contiguous_checkbox->is_pressed(), erase_button->is_pressed());
}
// Expand the grid if needed
@@ -931,7 +926,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
float opacity = CLAMP(MIN(left_opacity, MIN(right_opacity, MIN(top_opacity, bottom_opacity))) + 0.1, 0.0f, 1.0f);
Transform2D tile_xform;
- tile_xform.set_origin(tile_map->map_to_local(Vector2(x, y)));
+ tile_xform.set_origin(tile_set->map_to_local(Vector2(x, y)));
tile_xform.set_scale(tile_shape_size);
Color color = grid_color;
color.a = color.a * opacity;
@@ -944,7 +939,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
// Draw the preview.
for (const KeyValue<Vector2i, TileMapCell> &E : preview) {
Transform2D tile_xform;
- tile_xform.set_origin(tile_map->map_to_local(E.key));
+ tile_xform.set_origin(tile_set->map_to_local(E.key));
tile_xform.set_scale(tile_set->get_tile_size());
if (!(drag_erasing || erase_button->is_pressed()) && random_tile_toggle->is_pressed()) {
tile_set->draw_tile_shape(p_overlay, xform * tile_xform, Color(1.0, 1.0, 1.0, 0.5), true);
@@ -969,9 +964,9 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
bool transpose = tile_data->get_transpose() ^ bool(E.value.alternative_tile & TileSetAtlasSource::TRANSFORM_TRANSPOSE);
if (transpose) {
- dest_rect.position = (tile_map->map_to_local(E.key) - Vector2(dest_rect.size.y, dest_rect.size.x) / 2 - tile_offset);
+ dest_rect.position = (tile_set->map_to_local(E.key) - Vector2(dest_rect.size.y, dest_rect.size.x) / 2 - tile_offset);
} else {
- dest_rect.position = (tile_map->map_to_local(E.key) - dest_rect.size / 2 - tile_offset);
+ dest_rect.position = (tile_set->map_to_local(E.key) - dest_rect.size / 2 - tile_offset);
}
if (tile_data->get_flip_h() ^ bool(E.value.alternative_tile & TileSetAtlasSource::TRANSFORM_FLIP_H)) {
@@ -983,10 +978,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
}
// Get the tile modulation.
- Color modulate = tile_data->get_modulate();
- Color self_modulate = tile_map->get_modulate_in_tree() * tile_map->get_self_modulate();
- modulate *= self_modulate;
- modulate *= tile_map->get_layer_modulate(tile_map_layer);
+ Color modulate = tile_data->get_modulate() * edited_layer->get_modulate_in_tree() * edited_layer->get_self_modulate();
// Draw the tile.
p_overlay->draw_set_transform_matrix(xform);
@@ -1006,9 +998,9 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
int font_size = p_overlay->get_theme_font_size(SNAME("font_size"), SNAME("Label"));
Point2 msgpos = Point2(20 * EDSCALE, p_overlay->get_size().y - 20 * EDSCALE);
- String text = tile_map->local_to_map(tile_map->get_local_mouse_position());
+ String text = tile_set->local_to_map(edited_layer->get_local_mouse_position());
if (drag_type == DRAG_TYPE_RECT) {
- Vector2i size = tile_map->local_to_map(tile_map->get_local_mouse_position()) - tile_map->local_to_map(drag_start_mouse_pos);
+ Vector2i size = tile_set->local_to_map(edited_layer->get_local_mouse_position()) - tile_set->local_to_map(drag_start_mouse_pos);
text += vformat(" %s (%dx%d)", TTR("Drawing Rect:"), ABS(size.x) + 1, ABS(size.y) + 1);
}
@@ -1018,19 +1010,19 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
}
}
-void TileMapEditorTilesPlugin::_mouse_exited_viewport() {
+void TileMapLayerEditorTilesPlugin::_mouse_exited_viewport() {
has_mouse = false;
CanvasItemEditor::get_singleton()->update_viewport();
}
-TileMapCell TileMapEditorTilesPlugin::_pick_random_tile(Ref<TileMapPattern> p_pattern) {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+TileMapCell TileMapLayerEditorTilesPlugin::_pick_random_tile(Ref<TileMapPattern> p_pattern) {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return TileMapCell();
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return TileMapCell();
}
@@ -1075,14 +1067,14 @@ TileMapCell TileMapEditorTilesPlugin::_pick_random_tile(Ref<TileMapPattern> p_pa
return TileMapCell();
}
-HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_start_drag_mouse_pos, Vector2 p_from_mouse_pos, Vector2 p_to_mouse_pos, bool p_erase) {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+HashMap<Vector2i, TileMapCell> TileMapLayerEditorTilesPlugin::_draw_line(Vector2 p_start_drag_mouse_pos, Vector2 p_from_mouse_pos, Vector2 p_to_mouse_pos, bool p_erase) {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return HashMap<Vector2i, TileMapCell>();
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return HashMap<Vector2i, TileMapCell>();
}
@@ -1097,7 +1089,7 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_st
// Paint the tiles on the tile map.
if (!p_erase && random_tile_toggle->is_pressed()) {
// Paint a random tile.
- Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->local_to_map(p_from_mouse_pos), tile_map->local_to_map(p_to_mouse_pos));
+ Vector<Vector2i> line = TileMapLayerEditor::get_line(edited_layer, tile_set->local_to_map(p_from_mouse_pos), tile_set->local_to_map(p_to_mouse_pos));
for (int i = 0; i < line.size(); i++) {
output.insert(line[i], _pick_random_tile(pattern));
}
@@ -1105,17 +1097,17 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_st
// Paint the pattern.
// If we paint several tiles, we virtually move the mouse as if it was in the center of the "brush"
Vector2 mouse_offset = (Vector2(pattern->get_size()) / 2.0 - Vector2(0.5, 0.5)) * tile_set->get_tile_size();
- Vector2i last_hovered_cell = tile_map->local_to_map(p_from_mouse_pos - mouse_offset);
- Vector2i new_hovered_cell = tile_map->local_to_map(p_to_mouse_pos - mouse_offset);
- Vector2i drag_start_cell = tile_map->local_to_map(p_start_drag_mouse_pos - mouse_offset);
+ Vector2i last_hovered_cell = tile_set->local_to_map(p_from_mouse_pos - mouse_offset);
+ Vector2i new_hovered_cell = tile_set->local_to_map(p_to_mouse_pos - mouse_offset);
+ Vector2i drag_start_cell = tile_set->local_to_map(p_start_drag_mouse_pos - mouse_offset);
TypedArray<Vector2i> used_cells = pattern->get_used_cells();
Vector2i offset = Vector2i(Math::posmod(drag_start_cell.x, pattern->get_size().x), Math::posmod(drag_start_cell.y, pattern->get_size().y)); // Note: no posmodv for Vector2i for now. Meh.s
- Vector<Vector2i> line = TileMapEditor::get_line(tile_map, (last_hovered_cell - offset) / pattern->get_size(), (new_hovered_cell - offset) / pattern->get_size());
+ Vector<Vector2i> line = TileMapLayerEditor::get_line(edited_layer, (last_hovered_cell - offset) / pattern->get_size(), (new_hovered_cell - offset) / pattern->get_size());
for (int i = 0; i < line.size(); i++) {
Vector2i top_left = line[i] * pattern->get_size() + offset;
for (int j = 0; j < used_cells.size(); j++) {
- Vector2i coords = tile_map->map_pattern(top_left, used_cells[j], pattern);
+ Vector2i coords = tile_set->map_pattern(top_left, used_cells[j], pattern);
output.insert(coords, TileMapCell(pattern->get_cell_source_id(used_cells[j]), pattern->get_cell_atlas_coords(used_cells[j]), pattern->get_cell_alternative_tile(used_cells[j])));
}
}
@@ -1124,14 +1116,14 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_st
return output;
}
-HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_rect(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase) {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+HashMap<Vector2i, TileMapCell> TileMapLayerEditorTilesPlugin::_draw_rect(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase) {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return HashMap<Vector2i, TileMapCell>();
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return HashMap<Vector2i, TileMapCell>();
}
@@ -1183,22 +1175,18 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_rect(Vector2i p_s
return output;
}
-HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i p_coords, bool p_contiguous, bool p_erase) {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+HashMap<Vector2i, TileMapCell> TileMapLayerEditorTilesPlugin::_draw_bucket_fill(Vector2i p_coords, bool p_contiguous, bool p_erase) {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return HashMap<Vector2i, TileMapCell>();
}
- if (tile_map_layer < 0) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return HashMap<Vector2i, TileMapCell>();
}
- HashMap<Vector2i, TileMapCell> output;
- ERR_FAIL_INDEX_V(tile_map_layer, tile_map->get_layers_count(), output);
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
- return HashMap<Vector2i, TileMapCell>();
- }
+ HashMap<Vector2i, TileMapCell> output;
// Get or create the pattern.
Ref<TileMapPattern> erase_pattern;
@@ -1207,12 +1195,12 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vecto
Ref<TileMapPattern> pattern = p_erase ? erase_pattern : selection_pattern;
if (!pattern->is_empty()) {
- TileMapCell source_cell = tile_map->get_cell(tile_map_layer, p_coords);
+ TileMapCell source_cell = edited_layer->get_cell(p_coords);
// If we are filling empty tiles, compute the tilemap boundaries.
Rect2i boundaries;
if (source_cell.source_id == TileSet::INVALID_SOURCE) {
- boundaries = tile_map->get_used_rect();
+ boundaries = edited_layer->get_used_rect();
}
if (p_contiguous) {
@@ -1224,9 +1212,9 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vecto
Vector2i coords = to_check.back()->get();
to_check.pop_back();
if (!already_checked.has(coords)) {
- if (source_cell.source_id == tile_map->get_cell_source_id(tile_map_layer, coords) &&
- source_cell.get_atlas_coords() == tile_map->get_cell_atlas_coords(tile_map_layer, coords) &&
- source_cell.alternative_tile == tile_map->get_cell_alternative_tile(tile_map_layer, coords) &&
+ if (source_cell.source_id == edited_layer->get_cell_source_id(coords) &&
+ source_cell.get_atlas_coords() == edited_layer->get_cell_atlas_coords(coords) &&
+ source_cell.alternative_tile == edited_layer->get_cell_alternative_tile(coords) &&
(source_cell.source_id != TileSet::INVALID_SOURCE || boundaries.has_point(coords))) {
if (!p_erase && random_tile_toggle->is_pressed()) {
// Paint a random tile.
@@ -1244,7 +1232,7 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vecto
}
// Get surrounding tiles (handles different tile shapes).
- TypedArray<Vector2i> around = tile_map->get_surrounding_cells(coords);
+ TypedArray<Vector2i> around = tile_set->get_surrounding_cells(coords);
for (int i = 0; i < around.size(); i++) {
to_check.push_back(around[i]);
}
@@ -1256,7 +1244,7 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vecto
// Replace all tiles like the source.
TypedArray<Vector2i> to_check;
if (source_cell.source_id == TileSet::INVALID_SOURCE) {
- Rect2i rect = tile_map->get_used_rect();
+ Rect2i rect = edited_layer->get_used_rect();
if (!rect.has_area()) {
rect = Rect2i(p_coords, Vector2i(1, 1));
}
@@ -1266,13 +1254,13 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vecto
}
}
} else {
- to_check = tile_map->get_used_cells(tile_map_layer);
+ to_check = edited_layer->get_used_cells();
}
for (int i = 0; i < to_check.size(); i++) {
Vector2i coords = to_check[i];
- if (source_cell.source_id == tile_map->get_cell_source_id(tile_map_layer, coords) &&
- source_cell.get_atlas_coords() == tile_map->get_cell_atlas_coords(tile_map_layer, coords) &&
- source_cell.alternative_tile == tile_map->get_cell_alternative_tile(tile_map_layer, coords) &&
+ if (source_cell.source_id == edited_layer->get_cell_source_id(coords) &&
+ source_cell.get_atlas_coords() == edited_layer->get_cell_atlas_coords(coords) &&
+ source_cell.alternative_tile == edited_layer->get_cell_alternative_tile(coords) &&
(source_cell.source_id != TileSet::INVALID_SOURCE || boundaries.has_point(coords))) {
if (!p_erase && random_tile_toggle->is_pressed()) {
// Paint a random tile.
@@ -1295,27 +1283,22 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vecto
return output;
}
-void TileMapEditorTilesPlugin::_stop_dragging() {
+void TileMapLayerEditorTilesPlugin::_stop_dragging() {
if (drag_type == DRAG_TYPE_NONE) {
return;
}
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- if (tile_map_layer < 0) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
- ERR_FAIL_INDEX(tile_map_layer, tile_map->get_layers_count());
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
- return;
- }
-
- Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform_with_canvas();
+ Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * edited_layer->get_global_transform_with_canvas();
Vector2 mpos = xform.affine_inverse().xform(CanvasItemEditor::get_singleton()->get_viewport_control()->get_local_mouse_position());
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
@@ -1327,7 +1310,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
if (!Input::get_singleton()->is_key_pressed(Key::SHIFT) && !Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL)) {
tile_map_selection.clear();
}
- Rect2i rect = Rect2i(tile_map->local_to_map(drag_start_mouse_pos), tile_map->local_to_map(mpos) - tile_map->local_to_map(drag_start_mouse_pos)).abs();
+ Rect2i rect = Rect2i(tile_set->local_to_map(drag_start_mouse_pos), tile_set->local_to_map(mpos) - tile_set->local_to_map(drag_start_mouse_pos)).abs();
for (int x = rect.position.x; x <= rect.get_end().x; x++) {
for (int y = rect.position.y; y <= rect.get_end().y; y++) {
Vector2i coords = Vector2i(x, y);
@@ -1336,7 +1319,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
tile_map_selection.erase(coords);
}
} else {
- if (tile_map->get_cell_source_id(tile_map_layer, coords) != TileSet::INVALID_SOURCE) {
+ if (edited_layer->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
tile_map_selection.insert(coords);
}
}
@@ -1352,7 +1335,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
if (patterns_item_list->is_visible_in_tree() && patterns_item_list->has_point(patterns_item_list->get_local_mouse_position())) {
// Restore the cells.
for (KeyValue<Vector2i, TileMapCell> kv : drag_modified) {
- tile_map->set_cell(tile_map_layer, kv.key, kv.value.source_id, kv.value.get_atlas_coords(), kv.value.alternative_tile);
+ edited_layer->set_cell(kv.key, kv.value.source_id, kv.value.get_atlas_coords(), kv.value.alternative_tile);
}
if (!EditorNode::get_singleton()->is_resource_read_only(tile_set)) {
@@ -1375,8 +1358,8 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
}
// Get the offset from the mouse.
- Vector2i offset = drag_start_mouse_pos - tile_map->map_to_local(top_left);
- offset = tile_map->local_to_map(mpos - offset) - tile_map->local_to_map(drag_start_mouse_pos - offset);
+ Vector2i offset = drag_start_mouse_pos - tile_set->map_to_local(top_left);
+ offset = tile_set->local_to_map(mpos - offset) - tile_set->local_to_map(drag_start_mouse_pos - offset);
TypedArray<Vector2i> selection_used_cells = selection_pattern->get_used_cells();
@@ -1384,37 +1367,37 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
Vector2i coords;
HashMap<Vector2i, TileMapCell> cells_undo;
for (int i = 0; i < selection_used_cells.size(); i++) {
- coords = tile_map->map_pattern(top_left, selection_used_cells[i], selection_pattern);
+ coords = tile_set->map_pattern(top_left, selection_used_cells[i], selection_pattern);
cells_undo[coords] = TileMapCell(drag_modified[coords].source_id, drag_modified[coords].get_atlas_coords(), drag_modified[coords].alternative_tile);
- coords = tile_map->map_pattern(top_left + offset, selection_used_cells[i], selection_pattern);
- cells_undo[coords] = TileMapCell(tile_map->get_cell_source_id(tile_map_layer, coords), tile_map->get_cell_atlas_coords(tile_map_layer, coords), tile_map->get_cell_alternative_tile(tile_map_layer, coords));
+ coords = tile_set->map_pattern(top_left + offset, selection_used_cells[i], selection_pattern);
+ cells_undo[coords] = TileMapCell(edited_layer->get_cell_source_id(coords), edited_layer->get_cell_atlas_coords(coords), edited_layer->get_cell_alternative_tile(coords));
}
// Build the list of cells to do.
HashMap<Vector2i, TileMapCell> cells_do;
for (int i = 0; i < selection_used_cells.size(); i++) {
- coords = tile_map->map_pattern(top_left, selection_used_cells[i], selection_pattern);
+ coords = tile_set->map_pattern(top_left, selection_used_cells[i], selection_pattern);
cells_do[coords] = TileMapCell();
}
for (int i = 0; i < selection_used_cells.size(); i++) {
- coords = tile_map->map_pattern(top_left + offset, selection_used_cells[i], selection_pattern);
+ coords = tile_set->map_pattern(top_left + offset, selection_used_cells[i], selection_pattern);
cells_do[coords] = TileMapCell(selection_pattern->get_cell_source_id(selection_used_cells[i]), selection_pattern->get_cell_atlas_coords(selection_used_cells[i]), selection_pattern->get_cell_alternative_tile(selection_used_cells[i]));
}
// Move the tiles.
undo_redo->create_action(TTR("Move tiles"));
for (const KeyValue<Vector2i, TileMapCell> &E : cells_do) {
- undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
+ undo_redo->add_do_method(edited_layer, "set_cell", E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
}
for (const KeyValue<Vector2i, TileMapCell> &E : cells_undo) {
- undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
+ undo_redo->add_undo_method(edited_layer, "set_cell", E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
}
// Update the selection.
undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection());
tile_map_selection.clear();
for (int i = 0; i < selection_used_cells.size(); i++) {
- coords = tile_map->map_pattern(top_left + offset, selection_used_cells[i], selection_pattern);
+ coords = tile_set->map_pattern(top_left + offset, selection_used_cells[i], selection_pattern);
tile_map_selection.insert(coords);
}
undo_redo->add_do_method(this, "_set_tile_map_selection", _get_tile_map_selection());
@@ -1422,7 +1405,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
}
} break;
case DRAG_TYPE_PICK: {
- Rect2i rect = Rect2i(tile_map->local_to_map(drag_start_mouse_pos), tile_map->local_to_map(mpos) - tile_map->local_to_map(drag_start_mouse_pos)).abs();
+ Rect2i rect = Rect2i(tile_set->local_to_map(drag_start_mouse_pos), tile_set->local_to_map(mpos) - tile_set->local_to_map(drag_start_mouse_pos)).abs();
rect.size += Vector2i(1, 1);
int picked_source = -1;
@@ -1431,7 +1414,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
for (int y = rect.position.y; y < rect.get_end().y; y++) {
Vector2i coords = Vector2i(x, y);
- int source = tile_map->get_cell_source_id(tile_map_layer, coords);
+ int source = edited_layer->get_cell_source_id(coords);
if (source != TileSet::INVALID_SOURCE) {
coords_array.push_back(coords);
if (picked_source == -1) {
@@ -1454,7 +1437,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
sources_list->ensure_current_is_visible();
}
- Ref<TileMapPattern> new_selection_pattern = tile_map->get_pattern(tile_map_layer, coords_array);
+ Ref<TileMapPattern> new_selection_pattern = edited_layer->get_pattern(coords_array);
if (!new_selection_pattern->is_empty()) {
selection_pattern = new_selection_pattern;
_update_tileset_selection_from_selection_pattern();
@@ -1464,8 +1447,8 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
case DRAG_TYPE_PAINT: {
undo_redo->create_action(TTR("Paint tiles"));
for (const KeyValue<Vector2i, TileMapCell> &E : drag_modified) {
- undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key));
- undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
+ undo_redo->add_do_method(edited_layer, "set_cell", E.key, edited_layer->get_cell_source_id(E.key), edited_layer->get_cell_atlas_coords(E.key), edited_layer->get_cell_alternative_tile(E.key));
+ undo_redo->add_undo_method(edited_layer, "set_cell", E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
}
undo_redo->commit_action(false);
} break;
@@ -1476,28 +1459,28 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) {
continue;
}
- undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
- undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key));
+ undo_redo->add_do_method(edited_layer, "set_cell", E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
+ undo_redo->add_undo_method(edited_layer, "set_cell", E.key, edited_layer->get_cell_source_id(E.key), edited_layer->get_cell_atlas_coords(E.key), edited_layer->get_cell_alternative_tile(E.key));
}
undo_redo->commit_action();
} break;
case DRAG_TYPE_RECT: {
- HashMap<Vector2i, TileMapCell> to_draw = _draw_rect(tile_map->local_to_map(drag_start_mouse_pos), tile_map->local_to_map(mpos), drag_erasing);
+ HashMap<Vector2i, TileMapCell> to_draw = _draw_rect(tile_set->local_to_map(drag_start_mouse_pos), tile_set->local_to_map(mpos), drag_erasing);
undo_redo->create_action(TTR("Paint tiles"));
for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) {
if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) {
continue;
}
- undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
- undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key));
+ undo_redo->add_do_method(edited_layer, "set_cell", E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
+ undo_redo->add_undo_method(edited_layer, "set_cell", E.key, edited_layer->get_cell_source_id(E.key), edited_layer->get_cell_atlas_coords(E.key), edited_layer->get_cell_alternative_tile(E.key));
}
undo_redo->commit_action();
} break;
case DRAG_TYPE_BUCKET: {
undo_redo->create_action(TTR("Paint tiles"));
for (const KeyValue<Vector2i, TileMapCell> &E : drag_modified) {
- undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key));
- undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
+ undo_redo->add_do_method(edited_layer, "set_cell", E.key, edited_layer->get_cell_source_id(E.key), edited_layer->get_cell_atlas_coords(E.key), edited_layer->get_cell_alternative_tile(E.key));
+ undo_redo->add_undo_method(edited_layer, "set_cell", E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
}
undo_redo->commit_action(false);
} break;
@@ -1506,9 +1489,9 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
undo_redo->create_action(TTR("Paste tiles"));
TypedArray<Vector2i> used_cells = tile_map_clipboard->get_used_cells();
for (int i = 0; i < used_cells.size(); i++) {
- Vector2i coords = tile_map->map_pattern(tile_map->local_to_map(mpos - mouse_offset), used_cells[i], tile_map_clipboard);
- undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, coords, tile_map_clipboard->get_cell_source_id(used_cells[i]), tile_map_clipboard->get_cell_atlas_coords(used_cells[i]), tile_map_clipboard->get_cell_alternative_tile(used_cells[i]));
- undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, coords, tile_map->get_cell_source_id(tile_map_layer, coords), tile_map->get_cell_atlas_coords(tile_map_layer, coords), tile_map->get_cell_alternative_tile(tile_map_layer, coords));
+ Vector2i coords = tile_set->map_pattern(tile_set->local_to_map(mpos - mouse_offset), used_cells[i], tile_map_clipboard);
+ undo_redo->add_do_method(edited_layer, "set_cell", coords, tile_map_clipboard->get_cell_source_id(used_cells[i]), tile_map_clipboard->get_cell_atlas_coords(used_cells[i]), tile_map_clipboard->get_cell_alternative_tile(used_cells[i]));
+ undo_redo->add_undo_method(edited_layer, "set_cell", coords, edited_layer->get_cell_source_id(coords), edited_layer->get_cell_atlas_coords(coords), edited_layer->get_cell_alternative_tile(coords));
}
undo_redo->commit_action();
} break;
@@ -1518,7 +1501,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
drag_type = DRAG_TYPE_NONE;
}
-void TileMapEditorTilesPlugin::_apply_transform(int p_type) {
+void TileMapLayerEditorTilesPlugin::_apply_transform(int p_type) {
if (selection_pattern.is_null() || selection_pattern->is_empty()) {
return;
}
@@ -1558,7 +1541,7 @@ void TileMapEditorTilesPlugin::_apply_transform(int p_type) {
CanvasItemEditor::get_singleton()->update_viewport();
}
-int TileMapEditorTilesPlugin::_get_transformed_alternative(int p_alternative_id, int p_transform) {
+int TileMapLayerEditorTilesPlugin::_get_transformed_alternative(int p_alternative_id, int p_transform) {
bool transform_flip_h = p_alternative_id & TileSetAtlasSource::TRANSFORM_FLIP_H;
bool transform_flip_v = p_alternative_id & TileSetAtlasSource::TRANSFORM_FLIP_V;
bool transform_transpose = p_alternative_id & TileSetAtlasSource::TRANSFORM_TRANSPOSE;
@@ -1606,9 +1589,9 @@ int TileMapEditorTilesPlugin::_get_transformed_alternative(int p_alternative_id,
int(transform_transpose) * TileSetAtlasSource::TRANSFORM_TRANSPOSE;
}
-void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditorTilesPlugin::_update_fix_selected_and_hovered() {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
hovered_tile.source_id = TileSet::INVALID_SOURCE;
hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
@@ -1618,9 +1601,8 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() {
selection_pattern.instantiate();
return;
}
-
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
hovered_tile.source_id = TileSet::INVALID_SOURCE;
hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
@@ -1676,15 +1658,15 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() {
}
}
-void TileMapEditorTilesPlugin::_fix_invalid_tiles_in_tile_map_selection() {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditorTilesPlugin::_fix_invalid_tiles_in_tile_map_selection() {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
RBSet<Vector2i> to_remove;
for (Vector2i selected : tile_map_selection) {
- TileMapCell cell = tile_map->get_cell(tile_map_layer, selected);
+ TileMapCell cell = edited_layer->get_cell(selected);
if (cell.source_id == TileSet::INVALID_SOURCE && cell.get_atlas_coords() == TileSetSource::INVALID_ATLAS_COORDS && cell.alternative_tile == TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) {
to_remove.insert(selected);
}
@@ -1694,43 +1676,41 @@ void TileMapEditorTilesPlugin::_fix_invalid_tiles_in_tile_map_selection() {
tile_map_selection.erase(cell);
}
}
-void TileMapEditorTilesPlugin::patterns_item_list_empty_clicked(const Vector2 &p_pos, MouseButton p_mouse_button_index) {
+void TileMapLayerEditorTilesPlugin::patterns_item_list_empty_clicked(const Vector2 &p_pos, MouseButton p_mouse_button_index) {
if (p_mouse_button_index == MouseButton::LEFT) {
_update_selection_pattern_from_tileset_pattern_selection();
}
}
-void TileMapEditorTilesPlugin::_update_selection_pattern_from_tilemap_selection() {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditorTilesPlugin::_update_selection_pattern_from_tilemap_selection() {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
- ERR_FAIL_INDEX(tile_map_layer, tile_map->get_layers_count());
-
selection_pattern.instantiate();
TypedArray<Vector2i> coords_array;
for (const Vector2i &E : tile_map_selection) {
coords_array.push_back(E);
}
- selection_pattern = tile_map->get_pattern(tile_map_layer, coords_array);
+ selection_pattern = edited_layer->get_pattern(coords_array);
_update_transform_buttons();
}
-void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_tiles_selection() {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditorTilesPlugin::_update_selection_pattern_from_tileset_tiles_selection() {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
@@ -1797,14 +1777,14 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_tiles_sele
_update_transform_buttons();
}
-void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_pattern_selection() {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditorTilesPlugin::_update_selection_pattern_from_tileset_pattern_selection() {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
@@ -1821,7 +1801,7 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_pattern_se
CanvasItemEditor::get_singleton()->update_viewport();
}
-void TileMapEditorTilesPlugin::_update_tileset_selection_from_selection_pattern() {
+void TileMapLayerEditorTilesPlugin::_update_tileset_selection_from_selection_pattern() {
tile_set_selection.clear();
TypedArray<Vector2i> used_cells = selection_pattern->get_used_cells();
for (int i = 0; i < used_cells.size(); i++) {
@@ -1836,14 +1816,14 @@ void TileMapEditorTilesPlugin::_update_tileset_selection_from_selection_pattern(
_update_transform_buttons();
}
-void TileMapEditorTilesPlugin::_tile_atlas_control_draw() {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditorTilesPlugin::_tile_atlas_control_draw() {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
@@ -1908,21 +1888,21 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() {
}
}
-void TileMapEditorTilesPlugin::_tile_atlas_control_mouse_exited() {
+void TileMapLayerEditorTilesPlugin::_tile_atlas_control_mouse_exited() {
hovered_tile.source_id = TileSet::INVALID_SOURCE;
hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
tile_atlas_control->queue_redraw();
}
-void TileMapEditorTilesPlugin::_tile_atlas_control_gui_input(const Ref<InputEvent> &p_event) {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditorTilesPlugin::_tile_atlas_control_gui_input(const Ref<InputEvent> &p_event) {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
@@ -2021,14 +2001,14 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_gui_input(const Ref<InputEven
}
}
-void TileMapEditorTilesPlugin::_tile_alternatives_control_draw() {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditorTilesPlugin::_tile_alternatives_control_draw() {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
@@ -2066,21 +2046,21 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_draw() {
}
}
-void TileMapEditorTilesPlugin::_tile_alternatives_control_mouse_exited() {
+void TileMapLayerEditorTilesPlugin::_tile_alternatives_control_mouse_exited() {
hovered_tile.source_id = TileSet::INVALID_SOURCE;
hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
alternative_tiles_control->queue_redraw();
}
-void TileMapEditorTilesPlugin::_tile_alternatives_control_gui_input(const Ref<InputEvent> &p_event) {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditorTilesPlugin::_tile_alternatives_control_gui_input(const Ref<InputEvent> &p_event) {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
@@ -2139,7 +2119,7 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_gui_input(const Ref<In
}
}
-void TileMapEditorTilesPlugin::_set_tile_map_selection(const TypedArray<Vector2i> &p_selection) {
+void TileMapLayerEditorTilesPlugin::_set_tile_map_selection(const TypedArray<Vector2i> &p_selection) {
tile_map_selection.clear();
for (int i = 0; i < p_selection.size(); i++) {
tile_map_selection.insert(p_selection[i]);
@@ -2149,7 +2129,7 @@ void TileMapEditorTilesPlugin::_set_tile_map_selection(const TypedArray<Vector2i
CanvasItemEditor::get_singleton()->update_viewport();
}
-TypedArray<Vector2i> TileMapEditorTilesPlugin::_get_tile_map_selection() const {
+TypedArray<Vector2i> TileMapLayerEditorTilesPlugin::_get_tile_map_selection() const {
TypedArray<Vector2i> output;
for (const Vector2i &E : tile_map_selection) {
output.push_back(E);
@@ -2157,20 +2137,35 @@ TypedArray<Vector2i> TileMapEditorTilesPlugin::_get_tile_map_selection() const {
return output;
}
-void TileMapEditorTilesPlugin::edit(ObjectID p_tile_map_id, int p_tile_map_layer) {
+void TileMapLayerEditorTilesPlugin::_set_source_sort(int p_sort) {
+ for (int i = 0; i != TilesEditorUtils::SOURCE_SORT_MAX; i++) {
+ source_sort_button->get_popup()->set_item_checked(i, (i == (int)p_sort));
+ }
+ TilesEditorUtils::get_singleton()->set_sorting_option(p_sort);
+ _update_tile_set_sources_list();
+ EditorSettings::get_singleton()->set_project_metadata("editor_metadata", "tile_source_sort", p_sort);
+}
+
+void TileMapLayerEditorTilesPlugin::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_scene_thumbnail_done"), &TileMapLayerEditorTilesPlugin::_scene_thumbnail_done);
+ ClassDB::bind_method(D_METHOD("_set_tile_map_selection", "selection"), &TileMapLayerEditorTilesPlugin::_set_tile_map_selection);
+ ClassDB::bind_method(D_METHOD("_get_tile_map_selection"), &TileMapLayerEditorTilesPlugin::_get_tile_map_selection);
+}
+
+void TileMapLayerEditorTilesPlugin::edit(ObjectID p_tile_map_layer_id) {
_stop_dragging(); // Avoids staying in a wrong drag state.
// Disable sort button if the tileset is read-only
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (tile_map) {
- Ref<TileSet> tile_set = tile_map->get_tileset();
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (edited_layer) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
if (tile_set.is_valid()) {
source_sort_button->set_disabled(EditorNode::get_singleton()->is_resource_read_only(tile_set));
}
}
- if (tile_map_id != p_tile_map_id) {
- tile_map_id = p_tile_map_id;
+ if (edited_tile_map_layer_id != p_tile_map_layer_id) {
+ edited_tile_map_layer_id = p_tile_map_layer_id;
// Clear the selection.
tile_set_selection.clear();
@@ -2179,28 +2174,13 @@ void TileMapEditorTilesPlugin::edit(ObjectID p_tile_map_id, int p_tile_map_layer
selection_pattern.instantiate();
}
- tile_map_layer = p_tile_map_layer;
+ edited_tile_map_layer_id = p_tile_map_layer_id;
}
-void TileMapEditorTilesPlugin::_set_source_sort(int p_sort) {
- for (int i = 0; i != TilesEditorUtils::SOURCE_SORT_MAX; i++) {
- source_sort_button->get_popup()->set_item_checked(i, (i == (int)p_sort));
- }
- TilesEditorUtils::get_singleton()->set_sorting_option(p_sort);
- _update_tile_set_sources_list();
- EditorSettings::get_singleton()->set_project_metadata("editor_metadata", "tile_source_sort", p_sort);
-}
-
-void TileMapEditorTilesPlugin::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_scene_thumbnail_done"), &TileMapEditorTilesPlugin::_scene_thumbnail_done);
- ClassDB::bind_method(D_METHOD("_set_tile_map_selection", "selection"), &TileMapEditorTilesPlugin::_set_tile_map_selection);
- ClassDB::bind_method(D_METHOD("_get_tile_map_selection"), &TileMapEditorTilesPlugin::_get_tile_map_selection);
-}
-
-TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
+TileMapLayerEditorTilesPlugin::TileMapLayerEditorTilesPlugin() {
CanvasItemEditor::get_singleton()
->get_viewport_control()
- ->connect("mouse_exited", callable_mp(this, &TileMapEditorTilesPlugin::_mouse_exited_viewport));
+ ->connect("mouse_exited", callable_mp(this, &TileMapLayerEditorTilesPlugin::_mouse_exited_viewport));
// --- Shortcuts ---
ED_SHORTCUT("tiles_editor/cut", TTR("Cut"), KeyModifierMask::CMD_OR_CTRL | Key::X);
@@ -2225,7 +2205,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
select_tool_button->set_toggle_mode(true);
select_tool_button->set_button_group(tool_buttons_group);
select_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/selection_tool", TTR("Selection"), Key::S));
- select_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar));
+ select_tool_button->connect("pressed", callable_mp(this, &TileMapLayerEditorTilesPlugin::_update_toolbar));
tilemap_tiles_tools_buttons->add_child(select_tool_button);
viewport_shortcut_buttons.push_back(select_tool_button);
@@ -2235,7 +2215,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
paint_tool_button->set_button_group(tool_buttons_group);
paint_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/paint_tool", TTR("Paint"), Key::D));
paint_tool_button->set_tooltip_text(TTR("Shift: Draw line.") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL) + TTR("Shift: Draw rectangle."));
- paint_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar));
+ paint_tool_button->connect("pressed", callable_mp(this, &TileMapLayerEditorTilesPlugin::_update_toolbar));
tilemap_tiles_tools_buttons->add_child(paint_tool_button);
viewport_shortcut_buttons.push_back(paint_tool_button);
@@ -2245,7 +2225,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
line_tool_button->set_button_group(tool_buttons_group);
// TRANSLATORS: This refers to the line tool in the tilemap editor.
line_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/line_tool", TTR("Line", "Tool"), Key::L));
- line_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar));
+ line_tool_button->connect("pressed", callable_mp(this, &TileMapLayerEditorTilesPlugin::_update_toolbar));
tilemap_tiles_tools_buttons->add_child(line_tool_button);
viewport_shortcut_buttons.push_back(line_tool_button);
@@ -2254,7 +2234,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
rect_tool_button->set_toggle_mode(true);
rect_tool_button->set_button_group(tool_buttons_group);
rect_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/rect_tool", TTR("Rect"), Key::R));
- rect_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar));
+ rect_tool_button->connect("pressed", callable_mp(this, &TileMapLayerEditorTilesPlugin::_update_toolbar));
tilemap_tiles_tools_buttons->add_child(rect_tool_button);
viewport_shortcut_buttons.push_back(rect_tool_button);
@@ -2263,7 +2243,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
bucket_tool_button->set_toggle_mode(true);
bucket_tool_button->set_button_group(tool_buttons_group);
bucket_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/bucket_tool", TTR("Bucket"), Key::B));
- bucket_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar));
+ bucket_tool_button->connect("pressed", callable_mp(this, &TileMapLayerEditorTilesPlugin::_update_toolbar));
tilemap_tiles_tools_buttons->add_child(bucket_tool_button);
toolbar->add_child(tilemap_tiles_tools_buttons);
viewport_shortcut_buttons.push_back(bucket_tool_button);
@@ -2305,28 +2285,28 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
transform_button_rotate_left->set_theme_type_variation("FlatButton");
transform_button_rotate_left->set_shortcut(ED_SHORTCUT("tiles_editor/rotate_tile_left", TTR("Rotate Tile Left"), Key::Z));
transform_toolbar->add_child(transform_button_rotate_left);
- transform_button_rotate_left->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_apply_transform).bind(TRANSFORM_ROTATE_LEFT));
+ transform_button_rotate_left->connect("pressed", callable_mp(this, &TileMapLayerEditorTilesPlugin::_apply_transform).bind(TRANSFORM_ROTATE_LEFT));
viewport_shortcut_buttons.push_back(transform_button_rotate_left);
transform_button_rotate_right = memnew(Button);
transform_button_rotate_right->set_theme_type_variation("FlatButton");
transform_button_rotate_right->set_shortcut(ED_SHORTCUT("tiles_editor/rotate_tile_right", TTR("Rotate Tile Right"), Key::X));
transform_toolbar->add_child(transform_button_rotate_right);
- transform_button_rotate_right->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_apply_transform).bind(TRANSFORM_ROTATE_RIGHT));
+ transform_button_rotate_right->connect("pressed", callable_mp(this, &TileMapLayerEditorTilesPlugin::_apply_transform).bind(TRANSFORM_ROTATE_RIGHT));
viewport_shortcut_buttons.push_back(transform_button_rotate_right);
transform_button_flip_h = memnew(Button);
transform_button_flip_h->set_theme_type_variation("FlatButton");
transform_button_flip_h->set_shortcut(ED_SHORTCUT("tiles_editor/flip_tile_horizontal", TTR("Flip Tile Horizontally"), Key::C));
transform_toolbar->add_child(transform_button_flip_h);
- transform_button_flip_h->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_apply_transform).bind(TRANSFORM_FLIP_H));
+ transform_button_flip_h->connect("pressed", callable_mp(this, &TileMapLayerEditorTilesPlugin::_apply_transform).bind(TRANSFORM_FLIP_H));
viewport_shortcut_buttons.push_back(transform_button_flip_h);
transform_button_flip_v = memnew(Button);
transform_button_flip_v->set_theme_type_variation("FlatButton");
transform_button_flip_v->set_shortcut(ED_SHORTCUT("tiles_editor/flip_tile_vertical", TTR("Flip Tile Vertically"), Key::V));
transform_toolbar->add_child(transform_button_flip_v);
- transform_button_flip_v->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_apply_transform).bind(TRANSFORM_FLIP_V));
+ transform_button_flip_v->connect("pressed", callable_mp(this, &TileMapLayerEditorTilesPlugin::_apply_transform).bind(TRANSFORM_FLIP_V));
viewport_shortcut_buttons.push_back(transform_button_flip_v);
// Separator 2.
@@ -2345,7 +2325,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
random_tile_toggle->set_theme_type_variation("FlatButton");
random_tile_toggle->set_toggle_mode(true);
random_tile_toggle->set_tooltip_text(TTR("Place Random Tile"));
- random_tile_toggle->connect("toggled", callable_mp(this, &TileMapEditorTilesPlugin::_on_random_tile_checkbox_toggled));
+ random_tile_toggle->connect("toggled", callable_mp(this, &TileMapLayerEditorTilesPlugin::_on_random_tile_checkbox_toggled));
tools_settings->add_child(random_tile_toggle);
// Random tile scattering.
@@ -2362,7 +2342,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
scatter_spinbox->set_step(0.001);
scatter_spinbox->set_tooltip_text(TTR("Modifies the chance of painting nothing instead of a randomly selected tile."));
scatter_spinbox->get_line_edit()->add_theme_constant_override("minimum_character_width", 4);
- scatter_spinbox->connect("value_changed", callable_mp(this, &TileMapEditorTilesPlugin::_on_scattering_spinbox_changed));
+ scatter_spinbox->connect("value_changed", callable_mp(this, &TileMapLayerEditorTilesPlugin::_on_scattering_spinbox_changed));
scatter_controls_container->add_child(scatter_spinbox);
tools_settings->add_child(scatter_controls_container);
@@ -2377,9 +2357,9 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
// FIXME: This can trigger theme updates when the nodes that we want to update are not yet available.
// The toolbar should be extracted to a dedicated control and theme updates should be handled through
// the notification.
- tiles_bottom_panel->connect("theme_changed", callable_mp(this, &TileMapEditorTilesPlugin::_update_theme));
- tiles_bottom_panel->connect("visibility_changed", callable_mp(this, &TileMapEditorTilesPlugin::_stop_dragging));
- tiles_bottom_panel->connect("visibility_changed", callable_mp(this, &TileMapEditorTilesPlugin::_tab_changed));
+ tiles_bottom_panel->connect("theme_changed", callable_mp(this, &TileMapLayerEditorTilesPlugin::_update_theme));
+ tiles_bottom_panel->connect("visibility_changed", callable_mp(this, &TileMapLayerEditorTilesPlugin::_stop_dragging));
+ tiles_bottom_panel->connect("visibility_changed", callable_mp(this, &TileMapLayerEditorTilesPlugin::_tab_changed));
tiles_bottom_panel->set_name(TTR("Tiles"));
missing_source_label = memnew(Label);
@@ -2412,7 +2392,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
source_sort_button->set_tooltip_text(TTR("Sort sources"));
PopupMenu *p = source_sort_button->get_popup();
- p->connect("id_pressed", callable_mp(this, &TileMapEditorTilesPlugin::_set_source_sort));
+ p->connect("id_pressed", callable_mp(this, &TileMapLayerEditorTilesPlugin::_set_source_sort));
p->add_radio_check_item(TTR("Sort by ID (Ascending)"), TilesEditorUtils::SOURCE_SORT_ID);
p->add_radio_check_item(TTR("Sort by ID (Descending)"), TilesEditorUtils::SOURCE_SORT_ID_REVERSE);
p->add_radio_check_item(TTR("Sort by Name (Ascending)"), TilesEditorUtils::SOURCE_SORT_NAME);
@@ -2428,13 +2408,13 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
sources_list->set_stretch_ratio(0.25);
sources_list->set_custom_minimum_size(Size2(70, 0) * EDSCALE);
sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
- sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_fix_selected_and_hovered).unbind(1));
- sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_source_display).unbind(1));
+ sources_list->connect("item_selected", callable_mp(this, &TileMapLayerEditorTilesPlugin::_update_fix_selected_and_hovered).unbind(1));
+ sources_list->connect("item_selected", callable_mp(this, &TileMapLayerEditorTilesPlugin::_update_source_display).unbind(1));
sources_list->connect("item_selected", callable_mp(TilesEditorUtils::get_singleton(), &TilesEditorUtils::set_sources_lists_current));
sources_list->connect("item_activated", callable_mp(TilesEditorUtils::get_singleton(), &TilesEditorUtils::display_tile_set_editor_panel).unbind(1));
sources_list->connect("visibility_changed", callable_mp(TilesEditorUtils::get_singleton(), &TilesEditorUtils::synchronize_sources_list).bind(sources_list, source_sort_button));
sources_list->add_user_signal(MethodInfo("sort_request"));
- sources_list->connect("sort_request", callable_mp(this, &TileMapEditorTilesPlugin::_update_tile_set_sources_list));
+ sources_list->connect("sort_request", callable_mp(this, &TileMapLayerEditorTilesPlugin::_update_tile_set_sources_list));
split_container_left_side->add_child(sources_list);
split_container_left_side->add_child(sources_bottom_actions);
@@ -2448,15 +2428,15 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
atlas_sources_split_container->add_child(tile_atlas_view);
tile_atlas_control = memnew(Control);
- tile_atlas_control->connect("draw", callable_mp(this, &TileMapEditorTilesPlugin::_tile_atlas_control_draw));
- tile_atlas_control->connect("mouse_exited", callable_mp(this, &TileMapEditorTilesPlugin::_tile_atlas_control_mouse_exited));
- tile_atlas_control->connect("gui_input", callable_mp(this, &TileMapEditorTilesPlugin::_tile_atlas_control_gui_input));
+ tile_atlas_control->connect("draw", callable_mp(this, &TileMapLayerEditorTilesPlugin::_tile_atlas_control_draw));
+ tile_atlas_control->connect("mouse_exited", callable_mp(this, &TileMapLayerEditorTilesPlugin::_tile_atlas_control_mouse_exited));
+ tile_atlas_control->connect("gui_input", callable_mp(this, &TileMapLayerEditorTilesPlugin::_tile_atlas_control_gui_input));
tile_atlas_view->add_control_over_atlas_tiles(tile_atlas_control);
alternative_tiles_control = memnew(Control);
- alternative_tiles_control->connect("draw", callable_mp(this, &TileMapEditorTilesPlugin::_tile_alternatives_control_draw));
- alternative_tiles_control->connect("mouse_exited", callable_mp(this, &TileMapEditorTilesPlugin::_tile_alternatives_control_mouse_exited));
- alternative_tiles_control->connect("gui_input", callable_mp(this, &TileMapEditorTilesPlugin::_tile_alternatives_control_gui_input));
+ alternative_tiles_control->connect("draw", callable_mp(this, &TileMapLayerEditorTilesPlugin::_tile_alternatives_control_draw));
+ alternative_tiles_control->connect("mouse_exited", callable_mp(this, &TileMapLayerEditorTilesPlugin::_tile_alternatives_control_mouse_exited));
+ alternative_tiles_control->connect("gui_input", callable_mp(this, &TileMapLayerEditorTilesPlugin::_tile_alternatives_control_gui_input));
tile_atlas_view->add_control_over_alternative_tiles(alternative_tiles_control);
// Scenes collection source.
@@ -2465,8 +2445,8 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
scene_tiles_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
scene_tiles_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
scene_tiles_list->set_select_mode(ItemList::SELECT_MULTI);
- scene_tiles_list->connect("multi_selected", callable_mp(this, &TileMapEditorTilesPlugin::_scenes_list_multi_selected));
- scene_tiles_list->connect("empty_clicked", callable_mp(this, &TileMapEditorTilesPlugin::_scenes_list_lmb_empty_clicked));
+ scene_tiles_list->connect("multi_selected", callable_mp(this, &TileMapLayerEditorTilesPlugin::_scenes_list_multi_selected));
+ scene_tiles_list->connect("empty_clicked", callable_mp(this, &TileMapLayerEditorTilesPlugin::_scenes_list_lmb_empty_clicked));
scene_tiles_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
atlas_sources_split_container->add_child(scene_tiles_list);
@@ -2483,7 +2463,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
// --- Bottom panel patterns ---
patterns_bottom_panel = memnew(VBoxContainer);
patterns_bottom_panel->set_name(TTR("Patterns"));
- patterns_bottom_panel->connect("visibility_changed", callable_mp(this, &TileMapEditorTilesPlugin::_tab_changed));
+ patterns_bottom_panel->connect("visibility_changed", callable_mp(this, &TileMapLayerEditorTilesPlugin::_tab_changed));
int thumbnail_size = 64;
patterns_item_list = memnew(ItemList);
@@ -2494,10 +2474,10 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
patterns_item_list->set_max_text_lines(2);
patterns_item_list->set_fixed_icon_size(Size2(thumbnail_size, thumbnail_size));
patterns_item_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- patterns_item_list->connect("gui_input", callable_mp(this, &TileMapEditorTilesPlugin::_patterns_item_list_gui_input));
- patterns_item_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_pattern_selection).unbind(1));
- patterns_item_list->connect("item_activated", callable_mp(this, &TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_pattern_selection).unbind(1));
- patterns_item_list->connect("empty_clicked", callable_mp(this, &TileMapEditorTilesPlugin::patterns_item_list_empty_clicked));
+ patterns_item_list->connect("gui_input", callable_mp(this, &TileMapLayerEditorTilesPlugin::_patterns_item_list_gui_input));
+ patterns_item_list->connect("item_selected", callable_mp(this, &TileMapLayerEditorTilesPlugin::_update_selection_pattern_from_tileset_pattern_selection).unbind(1));
+ patterns_item_list->connect("item_activated", callable_mp(this, &TileMapLayerEditorTilesPlugin::_update_selection_pattern_from_tileset_pattern_selection).unbind(1));
+ patterns_item_list->connect("empty_clicked", callable_mp(this, &TileMapLayerEditorTilesPlugin::patterns_item_list_empty_clicked));
patterns_bottom_panel->add_child(patterns_item_list);
patterns_help_label = memnew(Label);
@@ -2510,16 +2490,16 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
_update_source_display();
}
-TileMapEditorTilesPlugin::~TileMapEditorTilesPlugin() {
+TileMapLayerEditorTilesPlugin::~TileMapLayerEditorTilesPlugin() {
}
-void TileMapEditorTerrainsPlugin::tile_set_changed() {
+void TileMapLayerEditorTerrainsPlugin::tile_set_changed() {
_update_terrains_cache();
_update_terrains_tree();
_update_tiles_list();
}
-void TileMapEditorTerrainsPlugin::_update_toolbar() {
+void TileMapLayerEditorTerrainsPlugin::_update_toolbar() {
// Hide all settings.
for (int i = 0; i < tools_settings->get_child_count(); i++) {
Object::cast_to<CanvasItem>(tools_settings->get_child(i))->hide();
@@ -2539,28 +2519,28 @@ void TileMapEditorTerrainsPlugin::_update_toolbar() {
}
}
-Vector<TileMapSubEditorPlugin::TabData> TileMapEditorTerrainsPlugin::get_tabs() const {
- Vector<TileMapSubEditorPlugin::TabData> tabs;
+Vector<TileMapLayerSubEditorPlugin::TabData> TileMapLayerEditorTerrainsPlugin::get_tabs() const {
+ Vector<TileMapLayerSubEditorPlugin::TabData> tabs;
tabs.push_back({ toolbar, main_vbox_container });
return tabs;
}
-HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrain_path_or_connect(const Vector<Vector2i> &p_to_paint, int p_terrain_set, int p_terrain, bool p_connect) const {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+HashMap<Vector2i, TileMapCell> TileMapLayerEditorTerrainsPlugin::_draw_terrain_path_or_connect(const Vector<Vector2i> &p_to_paint, int p_terrain_set, int p_terrain, bool p_connect) const {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return HashMap<Vector2i, TileMapCell>();
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return HashMap<Vector2i, TileMapCell>();
}
HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_output;
if (p_connect) {
- terrain_fill_output = tile_map->terrain_fill_connect(tile_map_layer, p_to_paint, p_terrain_set, p_terrain, false);
+ terrain_fill_output = edited_layer->terrain_fill_connect(p_to_paint, p_terrain_set, p_terrain, false);
} else {
- terrain_fill_output = tile_map->terrain_fill_path(tile_map_layer, p_to_paint, p_terrain_set, p_terrain, false);
+ terrain_fill_output = edited_layer->terrain_fill_path(p_to_paint, p_terrain_set, p_terrain, false);
}
// Make the painted path a set for faster lookups
@@ -2577,7 +2557,7 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrain_path_o
} else {
// Avoids updating the painted path from the output if the new pattern is the same as before.
TileSet::TerrainsPattern in_map_terrain_pattern = TileSet::TerrainsPattern(*tile_set, p_terrain_set);
- TileMapCell cell = tile_map->get_cell(tile_map_layer, kv.key);
+ TileMapCell cell = edited_layer->get_cell(kv.key);
if (cell.source_id != TileSet::INVALID_SOURCE) {
TileSetSource *source = *tile_set->get_source(cell.source_id);
TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
@@ -2597,18 +2577,18 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrain_path_o
return output;
}
-HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrain_pattern(const Vector<Vector2i> &p_to_paint, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+HashMap<Vector2i, TileMapCell> TileMapLayerEditorTerrainsPlugin::_draw_terrain_pattern(const Vector<Vector2i> &p_to_paint, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return HashMap<Vector2i, TileMapCell>();
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return HashMap<Vector2i, TileMapCell>();
}
- HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_output = tile_map->terrain_fill_pattern(tile_map_layer, p_to_paint, p_terrain_set, p_terrains_pattern, false);
+ HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_output = edited_layer->terrain_fill_pattern(p_to_paint, p_terrain_set, p_terrains_pattern, false);
// Make the painted path a set for faster lookups
HashSet<Vector2i> painted_set;
@@ -2624,7 +2604,7 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrain_patter
} else {
// Avoids updating the painted path from the output if the new pattern is the same as before.
TileSet::TerrainsPattern in_map_terrain_pattern = TileSet::TerrainsPattern(*tile_set, p_terrain_set);
- TileMapCell cell = tile_map->get_cell(tile_map_layer, kv.key);
+ TileMapCell cell = edited_layer->get_cell(kv.key);
if (cell.source_id != TileSet::INVALID_SOURCE) {
TileSetSource *source = *tile_set->get_source(cell.source_id);
TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
@@ -2644,38 +2624,38 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_terrain_patter
return output;
}
-HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_line(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase) {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+HashMap<Vector2i, TileMapCell> TileMapLayerEditorTerrainsPlugin::_draw_line(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase) {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return HashMap<Vector2i, TileMapCell>();
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return HashMap<Vector2i, TileMapCell>();
}
if (p_erase) {
- return _draw_terrain_pattern(TileMapEditor::get_line(tile_map, p_start_cell, p_end_cell), selected_terrain_set, TileSet::TerrainsPattern(*tile_set, selected_terrain_set));
+ return _draw_terrain_pattern(TileMapLayerEditor::get_line(edited_layer, p_start_cell, p_end_cell), selected_terrain_set, TileSet::TerrainsPattern(*tile_set, selected_terrain_set));
} else {
if (selected_type == SELECTED_TYPE_CONNECT) {
- return _draw_terrain_path_or_connect(TileMapEditor::get_line(tile_map, p_start_cell, p_end_cell), selected_terrain_set, selected_terrain, true);
+ return _draw_terrain_path_or_connect(TileMapLayerEditor::get_line(edited_layer, p_start_cell, p_end_cell), selected_terrain_set, selected_terrain, true);
} else if (selected_type == SELECTED_TYPE_PATH) {
- return _draw_terrain_path_or_connect(TileMapEditor::get_line(tile_map, p_start_cell, p_end_cell), selected_terrain_set, selected_terrain, false);
+ return _draw_terrain_path_or_connect(TileMapLayerEditor::get_line(edited_layer, p_start_cell, p_end_cell), selected_terrain_set, selected_terrain, false);
} else { // SELECTED_TYPE_PATTERN
- return _draw_terrain_pattern(TileMapEditor::get_line(tile_map, p_start_cell, p_end_cell), selected_terrain_set, selected_terrains_pattern);
+ return _draw_terrain_pattern(TileMapLayerEditor::get_line(edited_layer, p_start_cell, p_end_cell), selected_terrain_set, selected_terrains_pattern);
}
}
}
-HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_rect(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase) {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+HashMap<Vector2i, TileMapCell> TileMapLayerEditorTerrainsPlugin::_draw_rect(Vector2i p_start_cell, Vector2i p_end_cell, bool p_erase) {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return HashMap<Vector2i, TileMapCell>();
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return HashMap<Vector2i, TileMapCell>();
}
@@ -2702,18 +2682,18 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_rect(Vector2i
}
}
-RBSet<Vector2i> TileMapEditorTerrainsPlugin::_get_cells_for_bucket_fill(Vector2i p_coords, bool p_contiguous) {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+RBSet<Vector2i> TileMapLayerEditorTerrainsPlugin::_get_cells_for_bucket_fill(Vector2i p_coords, bool p_contiguous) {
+ const TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return RBSet<Vector2i>();
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return RBSet<Vector2i>();
}
- TileMapCell source_cell = tile_map->get_cell(tile_map_layer, p_coords);
+ TileMapCell source_cell = edited_layer->get_cell(p_coords);
TileSet::TerrainsPattern source_pattern(*tile_set, selected_terrain_set);
if (source_cell.source_id != TileSet::INVALID_SOURCE) {
@@ -2732,7 +2712,7 @@ RBSet<Vector2i> TileMapEditorTerrainsPlugin::_get_cells_for_bucket_fill(Vector2i
// If we are filling empty tiles, compute the tilemap boundaries.
Rect2i boundaries;
if (source_cell.source_id == TileSet::INVALID_SOURCE) {
- boundaries = tile_map->get_used_rect();
+ boundaries = edited_layer->get_used_rect();
}
RBSet<Vector2i> output;
@@ -2747,12 +2727,12 @@ RBSet<Vector2i> TileMapEditorTerrainsPlugin::_get_cells_for_bucket_fill(Vector2i
if (!already_checked.has(coords)) {
// Get the candidate cell pattern.
TileSet::TerrainsPattern candidate_pattern(*tile_set, selected_terrain_set);
- if (tile_map->get_cell_source_id(tile_map_layer, coords) != TileSet::INVALID_SOURCE) {
+ if (edited_layer->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
TileData *tile_data = nullptr;
- Ref<TileSetSource> source = tile_set->get_source(tile_map->get_cell_source_id(tile_map_layer, coords));
+ Ref<TileSetSource> source = tile_set->get_source(edited_layer->get_cell_source_id(coords));
Ref<TileSetAtlasSource> atlas_source = source;
if (atlas_source.is_valid()) {
- tile_data = atlas_source->get_tile_data(tile_map->get_cell_atlas_coords(tile_map_layer, coords), tile_map->get_cell_alternative_tile(tile_map_layer, coords));
+ tile_data = atlas_source->get_tile_data(edited_layer->get_cell_atlas_coords(coords), edited_layer->get_cell_alternative_tile(coords));
}
if (tile_data) {
candidate_pattern = tile_data->get_terrains_pattern();
@@ -2764,7 +2744,7 @@ RBSet<Vector2i> TileMapEditorTerrainsPlugin::_get_cells_for_bucket_fill(Vector2i
output.insert(coords);
// Get surrounding tiles (handles different tile shapes).
- TypedArray<Vector2i> around = tile_map->get_surrounding_cells(coords);
+ TypedArray<Vector2i> around = tile_set->get_surrounding_cells(coords);
for (int i = 0; i < around.size(); i++) {
to_check.push_back(around[i]);
}
@@ -2776,7 +2756,7 @@ RBSet<Vector2i> TileMapEditorTerrainsPlugin::_get_cells_for_bucket_fill(Vector2i
// Replace all tiles like the source.
TypedArray<Vector2i> to_check;
if (source_cell.source_id == TileSet::INVALID_SOURCE) {
- Rect2i rect = tile_map->get_used_rect();
+ Rect2i rect = edited_layer->get_used_rect();
if (!rect.has_area()) {
rect = Rect2i(p_coords, Vector2i(1, 1));
}
@@ -2786,18 +2766,18 @@ RBSet<Vector2i> TileMapEditorTerrainsPlugin::_get_cells_for_bucket_fill(Vector2i
}
}
} else {
- to_check = tile_map->get_used_cells(tile_map_layer);
+ to_check = edited_layer->get_used_cells();
}
for (int i = 0; i < to_check.size(); i++) {
Vector2i coords = to_check[i];
// Get the candidate cell pattern.
TileSet::TerrainsPattern candidate_pattern;
- if (tile_map->get_cell_source_id(tile_map_layer, coords) != TileSet::INVALID_SOURCE) {
+ if (edited_layer->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
TileData *tile_data = nullptr;
- Ref<TileSetSource> source = tile_set->get_source(tile_map->get_cell_source_id(tile_map_layer, coords));
+ Ref<TileSetSource> source = tile_set->get_source(edited_layer->get_cell_source_id(coords));
Ref<TileSetAtlasSource> atlas_source = source;
if (atlas_source.is_valid()) {
- tile_data = atlas_source->get_tile_data(tile_map->get_cell_atlas_coords(tile_map_layer, coords), tile_map->get_cell_alternative_tile(tile_map_layer, coords));
+ tile_data = atlas_source->get_tile_data(edited_layer->get_cell_atlas_coords(coords), edited_layer->get_cell_alternative_tile(coords));
}
if (tile_data) {
candidate_pattern = tile_data->get_terrains_pattern();
@@ -2813,14 +2793,14 @@ RBSet<Vector2i> TileMapEditorTerrainsPlugin::_get_cells_for_bucket_fill(Vector2i
return output;
}
-HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_bucket_fill(Vector2i p_coords, bool p_contiguous, bool p_erase) {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+HashMap<Vector2i, TileMapCell> TileMapLayerEditorTerrainsPlugin::_draw_bucket_fill(Vector2i p_coords, bool p_contiguous, bool p_erase) {
+ const TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return HashMap<Vector2i, TileMapCell>();
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ const Ref<TileSet> &tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return HashMap<Vector2i, TileMapCell>();
}
@@ -2841,25 +2821,25 @@ HashMap<Vector2i, TileMapCell> TileMapEditorTerrainsPlugin::_draw_bucket_fill(Ve
}
}
-void TileMapEditorTerrainsPlugin::_stop_dragging() {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditorTerrainsPlugin::_stop_dragging() {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ const Ref<TileSet> &tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
- Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform_with_canvas();
+ Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * edited_layer->get_global_transform_with_canvas();
Vector2 mpos = xform.affine_inverse().xform(CanvasItemEditor::get_singleton()->get_viewport_control()->get_local_mouse_position());
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
switch (drag_type) {
case DRAG_TYPE_PICK: {
- Vector2i coords = tile_map->local_to_map(mpos);
- TileMapCell cell = tile_map->get_cell(tile_map_layer, coords);
+ Vector2i coords = tile_set->local_to_map(mpos);
+ TileMapCell cell = edited_layer->get_cell(coords);
TileData *tile_data = nullptr;
Ref<TileSetSource> source = tile_set->get_source(cell.source_id);
@@ -2926,40 +2906,40 @@ void TileMapEditorTerrainsPlugin::_stop_dragging() {
case DRAG_TYPE_PAINT: {
undo_redo->create_action(TTR("Paint terrain"));
for (const KeyValue<Vector2i, TileMapCell> &E : drag_modified) {
- undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key));
- undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
+ undo_redo->add_do_method(edited_layer, "set_cell", E.key, edited_layer->get_cell_source_id(E.key), edited_layer->get_cell_atlas_coords(E.key), edited_layer->get_cell_alternative_tile(E.key));
+ undo_redo->add_undo_method(edited_layer, "set_cell", E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
}
undo_redo->commit_action(false);
} break;
case DRAG_TYPE_LINE: {
- HashMap<Vector2i, TileMapCell> to_draw = _draw_line(tile_map->local_to_map(drag_start_mouse_pos), tile_map->local_to_map(mpos), drag_erasing);
+ HashMap<Vector2i, TileMapCell> to_draw = _draw_line(tile_set->local_to_map(drag_start_mouse_pos), tile_set->local_to_map(mpos), drag_erasing);
undo_redo->create_action(TTR("Paint terrain"));
for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) {
if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) {
continue;
}
- undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
- undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key));
+ undo_redo->add_do_method(edited_layer, "set_cell", E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
+ undo_redo->add_undo_method(edited_layer, "set_cell", E.key, edited_layer->get_cell_source_id(E.key), edited_layer->get_cell_atlas_coords(E.key), edited_layer->get_cell_alternative_tile(E.key));
}
undo_redo->commit_action();
} break;
case DRAG_TYPE_RECT: {
- HashMap<Vector2i, TileMapCell> to_draw = _draw_rect(tile_map->local_to_map(drag_start_mouse_pos), tile_map->local_to_map(mpos), drag_erasing);
+ HashMap<Vector2i, TileMapCell> to_draw = _draw_rect(tile_set->local_to_map(drag_start_mouse_pos), tile_set->local_to_map(mpos), drag_erasing);
undo_redo->create_action(TTR("Paint terrain"));
for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) {
if (!drag_erasing && E.value.source_id == TileSet::INVALID_SOURCE) {
continue;
}
- undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
- undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key));
+ undo_redo->add_do_method(edited_layer, "set_cell", E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
+ undo_redo->add_undo_method(edited_layer, "set_cell", E.key, edited_layer->get_cell_source_id(E.key), edited_layer->get_cell_atlas_coords(E.key), edited_layer->get_cell_alternative_tile(E.key));
}
undo_redo->commit_action();
} break;
case DRAG_TYPE_BUCKET: {
undo_redo->create_action(TTR("Paint terrain"));
for (const KeyValue<Vector2i, TileMapCell> &E : drag_modified) {
- undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, tile_map->get_cell_source_id(tile_map_layer, E.key), tile_map->get_cell_atlas_coords(tile_map_layer, E.key), tile_map->get_cell_alternative_tile(tile_map_layer, E.key));
- undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
+ undo_redo->add_do_method(edited_layer, "set_cell", E.key, edited_layer->get_cell_source_id(E.key), edited_layer->get_cell_atlas_coords(E.key), edited_layer->get_cell_alternative_tile(E.key));
+ undo_redo->add_undo_method(edited_layer, "set_cell", E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
}
undo_redo->commit_action(false);
} break;
@@ -2970,19 +2950,19 @@ void TileMapEditorTerrainsPlugin::_stop_dragging() {
drag_type = DRAG_TYPE_NONE;
}
-void TileMapEditorTerrainsPlugin::_mouse_exited_viewport() {
+void TileMapLayerEditorTerrainsPlugin::_mouse_exited_viewport() {
has_mouse = false;
CanvasItemEditor::get_singleton()->update_viewport();
}
-void TileMapEditorTerrainsPlugin::_update_selection() {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditorTerrainsPlugin::_update_selection() {
+ const TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
@@ -3018,7 +2998,7 @@ void TileMapEditorTerrainsPlugin::_update_selection() {
}
}
-bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
+bool TileMapLayerEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
if (!main_vbox_container->is_visible_in_tree()) {
// If the bottom editor is not visible, we ignore inputs.
return false;
@@ -3028,21 +3008,16 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent>
return false;
}
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return false;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return false;
}
- if (tile_map_layer < 0) {
- return false;
- }
- ERR_FAIL_COND_V(tile_map_layer >= tile_map->get_layers_count(), false);
-
_update_selection();
Ref<InputEventKey> k = p_event;
@@ -3058,18 +3033,18 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent>
Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid()) {
has_mouse = true;
- Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform_with_canvas();
+ Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * edited_layer->get_global_transform_with_canvas();
Vector2 mpos = xform.affine_inverse().xform(mm->get_position());
switch (drag_type) {
case DRAG_TYPE_PAINT: {
if (selected_terrain_set >= 0) {
- HashMap<Vector2i, TileMapCell> to_draw = _draw_line(tile_map->local_to_map(drag_last_mouse_pos), tile_map->local_to_map(mpos), drag_erasing);
+ HashMap<Vector2i, TileMapCell> to_draw = _draw_line(tile_set->local_to_map(drag_last_mouse_pos), tile_set->local_to_map(mpos), drag_erasing);
for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) {
if (!drag_modified.has(E.key)) {
- drag_modified[E.key] = tile_map->get_cell(tile_map_layer, E.key);
+ drag_modified[E.key] = edited_layer->get_cell(E.key);
}
- tile_map->set_cell(tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
+ edited_layer->set_cell(E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
}
}
} break;
@@ -3085,7 +3060,7 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent>
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
has_mouse = true;
- Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform_with_canvas();
+ Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * edited_layer->get_global_transform_with_canvas();
Vector2 mpos = xform.affine_inverse().xform(mb->get_position());
if (mb->get_button_index() == MouseButton::LEFT || mb->get_button_index() == MouseButton::RIGHT) {
@@ -3108,11 +3083,11 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent>
drag_start_mouse_pos = mpos;
drag_modified.clear();
- Vector2i cell = tile_map->local_to_map(mpos);
+ Vector2i cell = tile_set->local_to_map(mpos);
HashMap<Vector2i, TileMapCell> to_draw = _draw_line(cell, cell, drag_erasing);
for (const KeyValue<Vector2i, TileMapCell> &E : to_draw) {
- drag_modified[E.key] = tile_map->get_cell(tile_map_layer, E.key);
- tile_map->set_cell(tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
+ drag_modified[E.key] = edited_layer->get_cell(E.key);
+ edited_layer->set_cell(E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
}
} else if (tool_buttons_group->get_pressed_button() == line_tool_button || (tool_buttons_group->get_pressed_button() == paint_tool_button && Input::get_singleton()->is_key_pressed(Key::SHIFT) && !Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL))) {
if (selected_terrain_set < 0 || selected_terrain < 0 || (selected_type == SELECTED_TYPE_PATTERN && !selected_terrains_pattern.is_valid())) {
@@ -3135,7 +3110,7 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent>
drag_type = DRAG_TYPE_BUCKET;
drag_start_mouse_pos = mpos;
drag_modified.clear();
- Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->local_to_map(drag_last_mouse_pos), tile_map->local_to_map(mpos));
+ Vector<Vector2i> line = TileMapLayerEditor::get_line(edited_layer, tile_set->local_to_map(drag_last_mouse_pos), tile_set->local_to_map(mpos));
for (int i = 0; i < line.size(); i++) {
if (!drag_modified.has(line[i])) {
HashMap<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_contiguous_checkbox->is_pressed(), drag_erasing);
@@ -3145,9 +3120,9 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent>
}
Vector2i coords = E.key;
if (!drag_modified.has(coords)) {
- drag_modified.insert(coords, tile_map->get_cell(tile_map_layer, coords));
+ drag_modified.insert(coords, edited_layer->get_cell(coords));
}
- tile_map->set_cell(tile_map_layer, coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
+ edited_layer->set_cell(coords, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile);
}
}
}
@@ -3169,28 +3144,23 @@ bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent>
return false;
}
-void TileMapEditorTerrainsPlugin::forward_canvas_draw_over_viewport(Control *p_overlay) {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditorTerrainsPlugin::forward_canvas_draw_over_viewport(Control *p_overlay) {
+ const TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- if (tile_map_layer < 0) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
- ERR_FAIL_INDEX(tile_map_layer, tile_map->get_layers_count());
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ if (!edited_layer->is_visible_in_tree()) {
return;
}
- if (!tile_map->is_visible_in_tree()) {
- return;
- }
-
- Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform_with_canvas();
- Vector2 mpos = tile_map->get_local_mouse_position();
+ Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * edited_layer->get_global_transform_with_canvas();
+ Vector2 mpos = edited_layer->get_local_mouse_position();
Vector2i tile_shape_size = tile_set->get_tile_size();
// Handle the preview of the tiles to be placed.
@@ -3200,10 +3170,10 @@ void TileMapEditorTerrainsPlugin::forward_canvas_draw_over_viewport(Control *p_o
if (drag_type == DRAG_TYPE_PICK) {
// Draw the area being picked.
- Vector2i coords = tile_map->local_to_map(mpos);
- if (tile_map->get_cell_source_id(tile_map_layer, coords) != TileSet::INVALID_SOURCE) {
+ Vector2i coords = tile_set->local_to_map(mpos);
+ if (edited_layer->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
Transform2D tile_xform;
- tile_xform.set_origin(tile_map->map_to_local(coords));
+ tile_xform.set_origin(tile_set->map_to_local(coords));
tile_xform.set_scale(tile_shape_size);
tile_set->draw_tile_shape(p_overlay, xform * tile_xform, Color(1.0, 1.0, 1.0), false);
}
@@ -3211,15 +3181,15 @@ void TileMapEditorTerrainsPlugin::forward_canvas_draw_over_viewport(Control *p_o
bool expand_grid = false;
if (tool_buttons_group->get_pressed_button() == paint_tool_button && drag_type == DRAG_TYPE_NONE) {
// Preview for a single tile.
- preview.insert(tile_map->local_to_map(mpos));
+ preview.insert(tile_set->local_to_map(mpos));
expand_grid = true;
} else if (tool_buttons_group->get_pressed_button() == line_tool_button || drag_type == DRAG_TYPE_LINE) {
if (drag_type == DRAG_TYPE_NONE) {
// Preview for a single tile.
- preview.insert(tile_map->local_to_map(mpos));
+ preview.insert(tile_set->local_to_map(mpos));
} else if (drag_type == DRAG_TYPE_LINE) {
// Preview for a line.
- Vector<Vector2i> line = TileMapEditor::get_line(tile_map, tile_map->local_to_map(drag_start_mouse_pos), tile_map->local_to_map(mpos));
+ Vector<Vector2i> line = TileMapLayerEditor::get_line(edited_layer, tile_set->local_to_map(drag_start_mouse_pos), tile_set->local_to_map(mpos));
for (int i = 0; i < line.size(); i++) {
preview.insert(line[i]);
}
@@ -3228,8 +3198,8 @@ void TileMapEditorTerrainsPlugin::forward_canvas_draw_over_viewport(Control *p_o
} else if (drag_type == DRAG_TYPE_RECT) {
// Preview for a rect.
Rect2i rect;
- rect.set_position(tile_map->local_to_map(drag_start_mouse_pos));
- rect.set_end(tile_map->local_to_map(mpos));
+ rect.set_position(tile_set->local_to_map(drag_start_mouse_pos));
+ rect.set_end(tile_set->local_to_map(mpos));
rect = rect.abs();
HashMap<Vector2i, TileSet::TerrainsPattern> to_draw;
@@ -3241,7 +3211,7 @@ void TileMapEditorTerrainsPlugin::forward_canvas_draw_over_viewport(Control *p_o
expand_grid = true;
} else if (tool_buttons_group->get_pressed_button() == bucket_tool_button && drag_type == DRAG_TYPE_NONE) {
// Preview for a fill.
- preview = _get_cells_for_bucket_fill(tile_map->local_to_map(mpos), bucket_contiguous_checkbox->is_pressed());
+ preview = _get_cells_for_bucket_fill(tile_set->local_to_map(mpos), bucket_contiguous_checkbox->is_pressed());
}
// Expand the grid if needed
@@ -3274,7 +3244,7 @@ void TileMapEditorTerrainsPlugin::forward_canvas_draw_over_viewport(Control *p_o
float opacity = CLAMP(MIN(left_opacity, MIN(right_opacity, MIN(top_opacity, bottom_opacity))) + 0.1, 0.0f, 1.0f);
Transform2D tile_xform;
- tile_xform.set_origin(tile_map->map_to_local(Vector2(x, y)));
+ tile_xform.set_origin(tile_set->map_to_local(Vector2(x, y)));
tile_xform.set_scale(tile_shape_size);
Color color = grid_color;
color.a = color.a * opacity;
@@ -3287,7 +3257,7 @@ void TileMapEditorTerrainsPlugin::forward_canvas_draw_over_viewport(Control *p_o
// Draw the preview.
for (const Vector2i &E : preview) {
Transform2D tile_xform;
- tile_xform.set_origin(tile_map->map_to_local(E));
+ tile_xform.set_origin(tile_set->map_to_local(E));
tile_xform.set_scale(tile_set->get_tile_size());
if (drag_erasing || erase_button->is_pressed()) {
tile_set->draw_tile_shape(p_overlay, xform * tile_xform, Color(0.0, 0.0, 0.0, 0.5), true);
@@ -3299,14 +3269,14 @@ void TileMapEditorTerrainsPlugin::forward_canvas_draw_over_viewport(Control *p_o
}
}
-void TileMapEditorTerrainsPlugin::_update_terrains_cache() {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditorTerrainsPlugin::_update_terrains_cache() {
+ const TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
@@ -3365,17 +3335,15 @@ void TileMapEditorTerrainsPlugin::_update_terrains_cache() {
}
}
-void TileMapEditorTerrainsPlugin::_update_terrains_tree() {
+void TileMapLayerEditorTerrainsPlugin::_update_terrains_tree() {
terrains_tree->clear();
terrains_tree->create_item();
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
- return;
- }
+ const TileMapLayer *edited_layer = _get_edited_layer();
+ ERR_FAIL_NULL(edited_layer);
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
@@ -3413,16 +3381,16 @@ void TileMapEditorTerrainsPlugin::_update_terrains_tree() {
}
}
-void TileMapEditorTerrainsPlugin::_update_tiles_list() {
+void TileMapLayerEditorTerrainsPlugin::_update_tiles_list() {
terrains_tile_list->clear();
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+ const TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
@@ -3513,7 +3481,7 @@ void TileMapEditorTerrainsPlugin::_update_tiles_list() {
}
}
-void TileMapEditorTerrainsPlugin::_update_theme() {
+void TileMapLayerEditorTerrainsPlugin::_update_theme() {
paint_tool_button->set_icon(main_vbox_container->get_editor_theme_icon(SNAME("Edit")));
line_tool_button->set_icon(main_vbox_container->get_editor_theme_icon(SNAME("Line")));
rect_tool_button->set_icon(main_vbox_container->get_editor_theme_icon(SNAME("Rectangle")));
@@ -3525,27 +3493,25 @@ void TileMapEditorTerrainsPlugin::_update_theme() {
_update_tiles_list();
}
-void TileMapEditorTerrainsPlugin::edit(ObjectID p_tile_map_id, int p_tile_map_layer) {
+void TileMapLayerEditorTerrainsPlugin::edit(ObjectID p_edited_tile_map_layer_id) {
_stop_dragging(); // Avoids staying in a wrong drag state.
- if (tile_map_id != p_tile_map_id) {
- tile_map_id = p_tile_map_id;
+ if (edited_tile_map_layer_id != p_edited_tile_map_layer_id) {
+ edited_tile_map_layer_id = p_edited_tile_map_layer_id;
// Clear the selection.
_update_terrains_cache();
_update_terrains_tree();
_update_tiles_list();
}
-
- tile_map_layer = p_tile_map_layer;
}
-TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() {
+TileMapLayerEditorTerrainsPlugin::TileMapLayerEditorTerrainsPlugin() {
main_vbox_container = memnew(VBoxContainer);
// FIXME: This can trigger theme updates when the nodes that we want to update are not yet available.
// The toolbar should be extracted to a dedicated control and theme updates should be handled through
// the notification.
- main_vbox_container->connect("theme_changed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_theme));
+ main_vbox_container->connect("theme_changed", callable_mp(this, &TileMapLayerEditorTerrainsPlugin::_update_theme));
main_vbox_container->set_name(TTR("Terrains"));
HSplitContainer *tilemap_tab_terrains = memnew(HSplitContainer);
@@ -3559,7 +3525,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() {
terrains_tree->set_custom_minimum_size(Size2(70, 0) * EDSCALE);
terrains_tree->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
terrains_tree->set_hide_root(true);
- terrains_tree->connect("item_selected", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_tiles_list));
+ terrains_tree->connect("item_selected", callable_mp(this, &TileMapLayerEditorTerrainsPlugin::_update_tiles_list));
tilemap_tab_terrains->add_child(terrains_tree);
terrains_tile_list = memnew(ItemList);
@@ -3584,7 +3550,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() {
paint_tool_button->set_button_group(tool_buttons_group);
paint_tool_button->set_pressed(true);
paint_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/paint_tool", TTR("Paint"), Key::D));
- paint_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_toolbar));
+ paint_tool_button->connect("pressed", callable_mp(this, &TileMapLayerEditorTerrainsPlugin::_update_toolbar));
tilemap_tiles_tools_buttons->add_child(paint_tool_button);
viewport_shortcut_buttons.push_back(paint_tool_button);
@@ -3593,7 +3559,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() {
line_tool_button->set_toggle_mode(true);
line_tool_button->set_button_group(tool_buttons_group);
line_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/line_tool", TTR("Line"), Key::L));
- line_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_toolbar));
+ line_tool_button->connect("pressed", callable_mp(this, &TileMapLayerEditorTerrainsPlugin::_update_toolbar));
tilemap_tiles_tools_buttons->add_child(line_tool_button);
viewport_shortcut_buttons.push_back(line_tool_button);
@@ -3602,7 +3568,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() {
rect_tool_button->set_toggle_mode(true);
rect_tool_button->set_button_group(tool_buttons_group);
rect_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/rect_tool", TTR("Rect"), Key::R));
- rect_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_toolbar));
+ rect_tool_button->connect("pressed", callable_mp(this, &TileMapLayerEditorTerrainsPlugin::_update_toolbar));
tilemap_tiles_tools_buttons->add_child(rect_tool_button);
viewport_shortcut_buttons.push_back(rect_tool_button);
@@ -3611,7 +3577,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() {
bucket_tool_button->set_toggle_mode(true);
bucket_tool_button->set_button_group(tool_buttons_group);
bucket_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/bucket_tool", TTR("Bucket"), Key::B));
- bucket_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_toolbar));
+ bucket_tool_button->connect("pressed", callable_mp(this, &TileMapLayerEditorTerrainsPlugin::_update_toolbar));
tilemap_tiles_tools_buttons->add_child(bucket_tool_button);
viewport_shortcut_buttons.push_back(bucket_tool_button);
@@ -3654,10 +3620,14 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() {
tools_settings->add_child(bucket_contiguous_checkbox);
}
-TileMapEditorTerrainsPlugin::~TileMapEditorTerrainsPlugin() {
+TileMapLayerEditorTerrainsPlugin::~TileMapLayerEditorTerrainsPlugin() {
}
-void TileMapEditor::_notification(int p_what) {
+TileMapLayer *TileMapLayerEditor::_get_edited_layer() const {
+ return Object::cast_to<TileMapLayer>(ObjectDB::get_instance(edited_tile_map_layer_id));
+}
+
+void TileMapLayerEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
missing_tile_texture = get_editor_theme_icon(SNAME("StatusWarning"));
@@ -3671,7 +3641,8 @@ void TileMapEditor::_notification(int p_what) {
case NOTIFICATION_INTERNAL_PROCESS: {
if (is_visible_in_tree() && tileset_changed_needs_update) {
_update_bottom_panel();
- _update_layers_selection();
+ update_layers_selector();
+ _update_highlighting_toggle();
tabs_plugins[tabs_bar->get_current_tab()]->tile_set_changed();
CanvasItemEditor::get_singleton()->update_viewport();
tileset_changed_needs_update = false;
@@ -3681,79 +3652,76 @@ void TileMapEditor::_notification(int p_what) {
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
toggle_grid_button->set_pressed(EDITOR_GET("editors/tiles_editor/display_grid"));
} break;
-
- case NOTIFICATION_VISIBILITY_CHANGED: {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (tile_map) {
- if (is_visible_in_tree()) {
- tile_map->set_selected_layer(tile_map_layer);
- } else {
- tile_map->set_selected_layer(-1);
- }
- }
- } break;
}
}
-void TileMapEditor::_on_grid_toggled(bool p_pressed) {
+void TileMapLayerEditor::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("change_selected_layer_request", PropertyInfo(Variant::STRING_NAME, "layer_name")));
+}
+
+void TileMapLayerEditor::_on_grid_toggled(bool p_pressed) {
EditorSettings::get_singleton()->set("editors/tiles_editor/display_grid", p_pressed);
CanvasItemEditor::get_singleton()->update_viewport();
}
-void TileMapEditor::_layers_selection_item_selected(int p_index) {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map || tile_map->get_layers_count() <= 0) {
- return;
- }
+void TileMapLayerEditor::_layers_selection_item_selected(int p_index) {
+ emit_signal("change_selected_layer_request", layers_selection_button->get_item_metadata(p_index));
+}
+
+void TileMapLayerEditor::_highlight_selected_layer_button_toggled(bool p_pressed) {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ ERR_FAIL_NULL(edited_layer);
- tile_map_layer = p_index;
- _update_layers_selection();
+ TileMapLayerGroup *tile_map_layer_group = Object::cast_to<TileMapLayerGroup>(edited_layer->get_parent());
+ ERR_FAIL_NULL(tile_map_layer_group);
+
+ tile_map_layer_group->set_highlight_selected_layer(p_pressed);
}
-void TileMapEditor::_advanced_menu_button_id_pressed(int p_id) {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditor::_advanced_menu_button_id_pressed(int p_id) {
+ TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
if (p_id == 0) { // Replace Tile Proxies
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
undo_redo->create_action(TTR("Replace Tiles with Proxies"));
- for (int layer_index = 0; layer_index < tile_map->get_layers_count(); layer_index++) {
- TypedArray<Vector2i> used_cells = tile_map->get_used_cells(layer_index);
- for (int i = 0; i < used_cells.size(); i++) {
- Vector2i cell_coords = used_cells[i];
- TileMapCell from = tile_map->get_cell(layer_index, cell_coords);
- Array to_array = tile_set->map_tile_proxy(from.source_id, from.get_atlas_coords(), from.alternative_tile);
- TileMapCell to;
- to.source_id = to_array[0];
- to.set_atlas_coords(to_array[1]);
- to.alternative_tile = to_array[2];
- if (from != to) {
- undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, cell_coords, to.source_id, to.get_atlas_coords(), to.alternative_tile);
- undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, cell_coords, from.source_id, from.get_atlas_coords(), from.alternative_tile);
- }
+ TypedArray<Vector2i> used_cells = edited_layer->get_used_cells();
+ for (int i = 0; i < used_cells.size(); i++) {
+ Vector2i cell_coords = used_cells[i];
+ TileMapCell from = edited_layer->get_cell(cell_coords);
+ Array to_array = tile_set->map_tile_proxy(from.source_id, from.get_atlas_coords(), from.alternative_tile);
+ TileMapCell to;
+ to.source_id = to_array[0];
+ to.set_atlas_coords(to_array[1]);
+ to.alternative_tile = to_array[2];
+ if (from != to) {
+ undo_redo->add_do_method(edited_layer, "set_cell", cell_coords, to.source_id, to.get_atlas_coords(), to.alternative_tile);
+ undo_redo->add_undo_method(edited_layer, "set_cell", cell_coords, from.source_id, from.get_atlas_coords(), from.alternative_tile);
}
}
+
undo_redo->commit_action();
}
}
-void TileMapEditor::_update_bottom_panel() {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditor::_update_bottom_panel() {
+ const TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
+
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
// Update the visibility of controls.
- missing_tileset_label->set_visible(!tile_set.is_valid());
- for (TileMapSubEditorPlugin::TabData &tab_data : tabs_data) {
+ missing_tileset_label->set_visible(tile_set.is_null());
+ for (TileMapLayerSubEditorPlugin::TabData &tab_data : tabs_data) {
tab_data.panel->hide();
}
if (tile_set.is_valid()) {
@@ -3761,11 +3729,11 @@ void TileMapEditor::_update_bottom_panel() {
}
}
-Vector<Vector2i> TileMapEditor::get_line(TileMap *p_tile_map, Vector2i p_from_cell, Vector2i p_to_cell) {
- ERR_FAIL_NULL_V(p_tile_map, Vector<Vector2i>());
+Vector<Vector2i> TileMapLayerEditor::get_line(const TileMapLayer *p_tile_map_layer, Vector2i p_from_cell, Vector2i p_to_cell) {
+ ERR_FAIL_NULL_V(p_tile_map_layer, Vector<Vector2i>());
- Ref<TileSet> tile_set = p_tile_map->get_tileset();
- ERR_FAIL_COND_V(!tile_set.is_valid(), Vector<Vector2i>());
+ Ref<TileSet> tile_set = p_tile_map_layer->get_effective_tile_set();
+ ERR_FAIL_COND_V(tile_set.is_null(), Vector<Vector2i>());
if (tile_set->get_tile_shape() == TileSet::TILE_SHAPE_SQUARE) {
return Geometry2D::bresenham_line(p_from_cell, p_to_cell);
@@ -3775,8 +3743,8 @@ Vector<Vector2i> TileMapEditor::get_line(TileMap *p_tile_map, Vector2i p_from_ce
Vector<Point2i> points;
bool transposed = tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_VERTICAL;
- p_from_cell = TileMap::transform_coords_layout(p_from_cell, tile_set->get_tile_offset_axis(), tile_set->get_tile_layout(), TileSet::TILE_LAYOUT_STACKED);
- p_to_cell = TileMap::transform_coords_layout(p_to_cell, tile_set->get_tile_offset_axis(), tile_set->get_tile_layout(), TileSet::TILE_LAYOUT_STACKED);
+ p_from_cell = TileSet::transform_coords_layout(p_from_cell, tile_set->get_tile_offset_axis(), tile_set->get_tile_layout(), TileSet::TILE_LAYOUT_STACKED);
+ p_to_cell = TileSet::transform_coords_layout(p_to_cell, tile_set->get_tile_offset_axis(), tile_set->get_tile_layout(), TileSet::TILE_LAYOUT_STACKED);
if (transposed) {
SWAP(p_from_cell.x, p_from_cell.y);
SWAP(p_to_cell.x, p_to_cell.y);
@@ -3787,7 +3755,7 @@ Vector<Vector2i> TileMapEditor::get_line(TileMap *p_tile_map, Vector2i p_from_ce
Vector2i sign = delta.sign();
Vector2i current = p_from_cell;
- points.push_back(TileMap::transform_coords_layout(transposed ? Vector2i(current.y, current.x) : current, tile_set->get_tile_offset_axis(), TileSet::TILE_LAYOUT_STACKED, tile_set->get_tile_layout()));
+ points.push_back(TileSet::transform_coords_layout(transposed ? Vector2i(current.y, current.x) : current, tile_set->get_tile_offset_axis(), TileSet::TILE_LAYOUT_STACKED, tile_set->get_tile_layout()));
int err = 0;
if (ABS(delta.y) < ABS(delta.x)) {
@@ -3805,7 +3773,7 @@ Vector<Vector2i> TileMapEditor::get_line(TileMap *p_tile_map, Vector2i p_from_ce
current += Vector2i(sign.x, 0);
err += err_step.y;
}
- points.push_back(TileMap::transform_coords_layout(transposed ? Vector2i(current.y, current.x) : current, tile_set->get_tile_offset_axis(), TileSet::TILE_LAYOUT_STACKED, tile_set->get_tile_layout()));
+ points.push_back(TileSet::transform_coords_layout(transposed ? Vector2i(current.y, current.x) : current, tile_set->get_tile_offset_axis(), TileSet::TILE_LAYOUT_STACKED, tile_set->get_tile_layout()));
}
} else {
Vector2i err_step = delta.abs();
@@ -3826,7 +3794,7 @@ Vector<Vector2i> TileMapEditor::get_line(TileMap *p_tile_map, Vector2i p_from_ce
}
err += err_step.y;
}
- points.push_back(TileMap::transform_coords_layout(transposed ? Vector2i(current.y, current.x) : current, tile_set->get_tile_offset_axis(), TileSet::TILE_LAYOUT_STACKED, tile_set->get_tile_layout()));
+ points.push_back(TileSet::transform_coords_layout(transposed ? Vector2i(current.y, current.x) : current, tile_set->get_tile_offset_axis(), TileSet::TILE_LAYOUT_STACKED, tile_set->get_tile_layout()));
}
}
@@ -3834,27 +3802,30 @@ Vector<Vector2i> TileMapEditor::get_line(TileMap *p_tile_map, Vector2i p_from_ce
}
}
-void TileMapEditor::_tile_map_changed() {
+void TileMapLayerEditor::_tile_map_layer_changed() {
tileset_changed_needs_update = true;
}
-void TileMapEditor::_tab_changed(int p_tab_id) {
+void TileMapLayerEditor::_tab_changed(int p_tab_id) {
// Make the plugin edit the correct tilemap.
- tabs_plugins[tabs_bar->get_current_tab()]->edit(tile_map_id, tile_map_layer);
+ tabs_plugins[tabs_bar->get_current_tab()]->edit(edited_tile_map_layer_id);
// Update toolbar.
- for (TileMapSubEditorPlugin::TabData &tab_data : tabs_data) {
+ for (TileMapLayerSubEditorPlugin::TabData &tab_data : tabs_data) {
tab_data.toolbar->hide();
}
tabs_data[p_tab_id].toolbar->show();
// Update visible panel.
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- for (TileMapSubEditorPlugin::TabData &tab_data : tabs_data) {
+ for (TileMapLayerSubEditorPlugin::TabData &tab_data : tabs_data) {
tab_data.panel->hide();
}
- if (tile_map && tile_map->get_tileset().is_valid()) {
- tabs_data[tabs_bar->get_current_tab()].panel->show();
+
+ TileMapLayer *tile_map_layer = _get_edited_layer();
+ if (tile_map_layer) {
+ if (tile_map_layer->get_effective_tile_set().is_valid()) {
+ tabs_data[tabs_bar->get_current_tab()].panel->show();
+ }
}
// Graphical update.
@@ -3862,83 +3833,46 @@ void TileMapEditor::_tab_changed(int p_tab_id) {
CanvasItemEditor::get_singleton()->update_viewport();
}
-void TileMapEditor::_layers_select_next_or_previous(bool p_next) {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditor::_layers_select_next_or_previous(bool p_next) {
+ const TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- if (tile_map->get_layers_count() < 1) {
+ TileMapLayerGroup *tile_map_layer_group = Object::cast_to<TileMapLayerGroup>(edited_layer->get_parent());
+ if (!tile_map_layer_group) {
return;
}
- if (tile_map_layer < 0) {
- tile_map_layer = 0;
- }
-
int inc = p_next ? 1 : -1;
- int origin_layer = tile_map_layer;
- tile_map_layer = Math::posmod((tile_map_layer + inc), tile_map->get_layers_count());
- while (tile_map_layer != origin_layer) {
- if (tile_map->is_layer_enabled(tile_map_layer)) {
+ int index = Math::posmod(edited_layer->get_index() + inc, tile_map_layer_group->get_child_count());
+ const TileMapLayer *new_selected_layer = Object::cast_to<TileMapLayer>(tile_map_layer_group->get_child(index));
+ while (new_selected_layer != edited_layer) {
+ if (new_selected_layer && new_selected_layer->is_enabled()) {
break;
}
- tile_map_layer = Math::posmod((tile_map_layer + inc), tile_map->get_layers_count());
+ index = Math::posmod((index + inc), tile_map_layer_group->get_child_count());
+ new_selected_layer = Object::cast_to<TileMapLayer>(tile_map_layer_group->get_child(index));
}
- _update_layers_selection();
+ if (new_selected_layer != edited_layer) {
+ emit_signal("change_selected_layer_request", new_selected_layer->get_name());
+ }
}
-void TileMapEditor::_update_layers_selection() {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditor::_update_highlighting_toggle() {
+ const TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- // Update the selected layer.
- if (is_visible_in_tree() && tile_map->get_layers_count() >= 1) {
- tile_map_layer = CLAMP(tile_map_layer, 0, tile_map->get_layers_count() - 1);
-
- // Search for an enabled layer if the current one is not.
- int origin_layer = tile_map_layer;
- while (tile_map_layer >= 0 && !tile_map->is_layer_enabled(tile_map_layer)) {
- tile_map_layer--;
- }
- if (tile_map_layer < 0) {
- tile_map_layer = origin_layer;
- while (tile_map_layer < tile_map->get_layers_count() && !tile_map->is_layer_enabled(tile_map_layer)) {
- tile_map_layer++;
- }
- }
- if (tile_map_layer >= tile_map->get_layers_count()) {
- tile_map_layer = -1;
- }
- } else {
- tile_map_layer = -1;
- }
- tile_map->set_selected_layer(toggle_highlight_selected_layer_button->is_pressed() ? tile_map_layer : -1);
- tileset_changed_needs_update = false; // Update is not needed here and actually causes problems.
-
- layers_selection_button->clear();
- if (tile_map->get_layers_count() > 0) {
- // Build the list of layers.
- for (int i = 0; i < tile_map->get_layers_count(); i++) {
- String name = tile_map->get_layer_name(i);
- layers_selection_button->add_item(name.is_empty() ? vformat(TTR("Layer %d"), i) : name, i);
- layers_selection_button->set_item_disabled(i, !tile_map->is_layer_enabled(i));
- }
-
- layers_selection_button->set_disabled(false);
- layers_selection_button->select(tile_map_layer);
- } else {
- layers_selection_button->set_disabled(true);
- layers_selection_button->set_text(TTR("No Layers"));
+ TileMapLayerGroup *tile_map_layer_group = Object::cast_to<TileMapLayerGroup>(edited_layer->get_parent());
+ if (tile_map_layer_group) {
+ toggle_highlight_selected_layer_button->set_pressed(tile_map_layer_group->is_highlighting_selected_layer());
}
-
- tabs_plugins[tabs_bar->get_current_tab()]->edit(tile_map_id, tile_map_layer);
}
-void TileMapEditor::_move_tile_map_array_element(Object *p_undo_redo, Object *p_edited, String p_array_prefix, int p_from_index, int p_to_pos) {
+void TileMapLayerEditor::_move_tile_map_array_element(Object *p_undo_redo, Object *p_edited, String p_array_prefix, int p_from_index, int p_to_pos) {
EditorUndoRedoManager *undo_redo_man = Object::cast_to<EditorUndoRedoManager>(p_undo_redo);
ERR_FAIL_NULL(undo_redo_man);
@@ -4010,7 +3944,7 @@ void TileMapEditor::_move_tile_map_array_element(Object *p_undo_redo, Object *p_
}
}
-bool TileMapEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
+bool TileMapLayerEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
if (ED_IS_SHORTCUT("tiles_editor/select_next_layer", p_event) && p_event->is_pressed()) {
_layers_select_next_or_previous(true);
return true;
@@ -4024,74 +3958,71 @@ bool TileMapEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
return tabs_plugins[tabs_bar->get_current_tab()]->forward_canvas_gui_input(p_event);
}
-void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (!tile_map) {
+void TileMapLayerEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
+ const TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
return;
}
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (!tile_set.is_valid()) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_null()) {
return;
}
- if (!tile_map->is_visible_in_tree()) {
+ if (!edited_layer->is_visible_in_tree()) {
return;
}
- Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * tile_map->get_global_transform_with_canvas();
+ Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * edited_layer->get_global_transform_with_canvas();
Transform2D xform_inv = xform.affine_inverse();
Vector2i tile_shape_size = tile_set->get_tile_size();
// Draw tiles with invalid IDs in the grid.
- if (tile_map_layer >= 0) {
- ERR_FAIL_COND(tile_map_layer >= tile_map->get_layers_count());
- TypedArray<Vector2i> used_cells = tile_map->get_used_cells(tile_map_layer);
- for (int i = 0; i < used_cells.size(); i++) {
- Vector2i coords = used_cells[i];
- int tile_source_id = tile_map->get_cell_source_id(tile_map_layer, coords);
- if (tile_source_id >= 0) {
- Vector2i tile_atlas_coords = tile_map->get_cell_atlas_coords(tile_map_layer, coords);
- int tile_alternative_tile = tile_map->get_cell_alternative_tile(tile_map_layer, coords);
-
- TileSetSource *source = nullptr;
- if (tile_set->has_source(tile_source_id)) {
- source = *tile_set->get_source(tile_source_id);
- }
-
- if (!source || !source->has_tile(tile_atlas_coords) || !source->has_alternative_tile(tile_atlas_coords, tile_alternative_tile)) {
- // Generate a random color from the hashed values of the tiles.
- Array a = tile_set->map_tile_proxy(tile_source_id, tile_atlas_coords, tile_alternative_tile);
- if (int(a[0]) == tile_source_id && Vector2i(a[1]) == tile_atlas_coords && int(a[2]) == tile_alternative_tile) {
- // Only display the pattern if we have no proxy tile.
- Array to_hash;
- to_hash.push_back(tile_source_id);
- to_hash.push_back(tile_atlas_coords);
- to_hash.push_back(tile_alternative_tile);
- uint32_t hash = RandomPCG(to_hash.hash()).rand();
-
- Color color;
- color = color.from_hsv(
- (float)((hash >> 24) & 0xFF) / 256.0,
- Math::lerp(0.5, 1.0, (float)((hash >> 16) & 0xFF) / 256.0),
- Math::lerp(0.5, 1.0, (float)((hash >> 8) & 0xFF) / 256.0),
- 0.8);
-
- // Draw the scaled tile.
- Transform2D tile_xform;
- tile_xform.set_origin(tile_map->map_to_local(coords));
- tile_xform.set_scale(tile_shape_size);
- tile_set->draw_tile_shape(p_overlay, xform * tile_xform, color, true, warning_pattern_texture);
- }
+ TypedArray<Vector2i> used_cells = edited_layer->get_used_cells();
+ for (int i = 0; i < used_cells.size(); i++) {
+ Vector2i coords = used_cells[i];
+ int tile_source_id = edited_layer->get_cell_source_id(coords);
+ if (tile_source_id >= 0) {
+ Vector2i tile_atlas_coords = edited_layer->get_cell_atlas_coords(coords);
+ int tile_alternative_tile = edited_layer->get_cell_alternative_tile(coords);
+
+ TileSetSource *source = nullptr;
+ if (tile_set->has_source(tile_source_id)) {
+ source = *tile_set->get_source(tile_source_id);
+ }
- // Draw the warning icon.
- Vector2::Axis min_axis = missing_tile_texture->get_size().min_axis_index();
- Vector2 icon_size;
- icon_size[min_axis] = tile_set->get_tile_size()[min_axis] / 3;
- icon_size[(min_axis + 1) % 2] = (icon_size[min_axis] * missing_tile_texture->get_size()[(min_axis + 1) % 2] / missing_tile_texture->get_size()[min_axis]);
- Rect2 rect = Rect2(xform.xform(tile_map->map_to_local(coords)) - (icon_size * xform.get_scale() / 2), icon_size * xform.get_scale());
- p_overlay->draw_texture_rect(missing_tile_texture, rect);
+ if (!source || !source->has_tile(tile_atlas_coords) || !source->has_alternative_tile(tile_atlas_coords, tile_alternative_tile)) {
+ // Generate a random color from the hashed values of the tiles.
+ Array a = tile_set->map_tile_proxy(tile_source_id, tile_atlas_coords, tile_alternative_tile);
+ if (int(a[0]) == tile_source_id && Vector2i(a[1]) == tile_atlas_coords && int(a[2]) == tile_alternative_tile) {
+ // Only display the pattern if we have no proxy tile.
+ Array to_hash;
+ to_hash.push_back(tile_source_id);
+ to_hash.push_back(tile_atlas_coords);
+ to_hash.push_back(tile_alternative_tile);
+ uint32_t hash = RandomPCG(to_hash.hash()).rand();
+
+ Color color;
+ color = color.from_hsv(
+ (float)((hash >> 24) & 0xFF) / 256.0,
+ Math::lerp(0.5, 1.0, (float)((hash >> 16) & 0xFF) / 256.0),
+ Math::lerp(0.5, 1.0, (float)((hash >> 8) & 0xFF) / 256.0),
+ 0.8);
+
+ // Draw the scaled tile.
+ Transform2D tile_xform;
+ tile_xform.set_origin(tile_set->map_to_local(coords));
+ tile_xform.set_scale(tile_shape_size);
+ tile_set->draw_tile_shape(p_overlay, xform * tile_xform, color, true, warning_pattern_texture);
}
+
+ // Draw the warning icon.
+ Vector2::Axis min_axis = missing_tile_texture->get_size().min_axis_index();
+ Vector2 icon_size;
+ icon_size[min_axis] = tile_set->get_tile_size()[min_axis] / 3;
+ icon_size[(min_axis + 1) % 2] = (icon_size[min_axis] * missing_tile_texture->get_size()[(min_axis + 1) % 2] / missing_tile_texture->get_size()[min_axis]);
+ Rect2 rect = Rect2(xform.xform(tile_set->map_to_local(coords)) - (icon_size * xform.get_scale() / 2), icon_size * xform.get_scale());
+ p_overlay->draw_texture_rect(missing_tile_texture, rect);
}
}
}
@@ -4102,13 +4033,13 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
// Determine the drawn area.
Size2 screen_size = p_overlay->get_size();
Rect2i screen_rect;
- screen_rect.position = tile_map->local_to_map(xform_inv.xform(Vector2()));
- screen_rect.expand_to(tile_map->local_to_map(xform_inv.xform(Vector2(0, screen_size.height))));
- screen_rect.expand_to(tile_map->local_to_map(xform_inv.xform(Vector2(screen_size.width, 0))));
- screen_rect.expand_to(tile_map->local_to_map(xform_inv.xform(screen_size)));
+ screen_rect.position = tile_set->local_to_map(xform_inv.xform(Vector2()));
+ screen_rect.expand_to(tile_set->local_to_map(xform_inv.xform(Vector2(0, screen_size.height))));
+ screen_rect.expand_to(tile_set->local_to_map(xform_inv.xform(Vector2(screen_size.width, 0))));
+ screen_rect.expand_to(tile_set->local_to_map(xform_inv.xform(screen_size)));
screen_rect = screen_rect.grow(1);
- Rect2i tilemap_used_rect = tile_map->get_used_rect();
+ Rect2i tilemap_used_rect = edited_layer->get_used_rect();
Rect2i displayed_rect = tilemap_used_rect.intersection(screen_rect);
displayed_rect = displayed_rect.grow(fading);
@@ -4138,7 +4069,7 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
float opacity = CLAMP(MIN(left_opacity, MIN(right_opacity, MIN(top_opacity, bottom_opacity))) + 0.1, 0.0f, 1.0f);
Transform2D tile_xform;
- tile_xform.set_origin(tile_map->map_to_local(Vector2(x, y)));
+ tile_xform.set_origin(tile_set->map_to_local(Vector2(x, y)));
tile_xform.set_scale(tile_shape_size);
Color color = grid_color;
color.a = color.a * opacity;
@@ -4151,7 +4082,7 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
/*Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
for (int x = displayed_rect.position.x; x < (displayed_rect.position.x + displayed_rect.size.x); x++) {
for (int y = displayed_rect.position.y; y < (displayed_rect.position.y + displayed_rect.size.y); y++) {
- p_overlay->draw_string(font, xform.xform(tile_map->map_to_local(Vector2(x, y))) + Vector2i(-tile_shape_size.x / 2, 0), vformat("%s", Vector2(x, y)));
+ p_overlay->draw_string(font, xform.xform(tile_set->map_to_local(Vector2(x, y))) + Vector2i(-tile_shape_size.x / 2, 0), vformat("%s", Vector2(x, y)));
}
}*/
@@ -4159,65 +4090,100 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
tabs_plugins[tabs_bar->get_current_tab()]->forward_canvas_draw_over_viewport(p_overlay);
}
-void TileMapEditor::edit(TileMap *p_tile_map) {
- if (p_tile_map && p_tile_map->get_instance_id() == tile_map_id) {
+void TileMapLayerEditor::edit(TileMapLayer *p_tile_map_layer) {
+ if (p_tile_map_layer && p_tile_map_layer->get_instance_id() == edited_tile_map_layer_id) {
return;
}
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (tile_map) {
- // Unselect layer if we are changing tile_map.
- if (tile_map != p_tile_map) {
- tile_map->set_selected_layer(-1);
- }
-
- // Disconnect to changes.
- tile_map->disconnect("changed", callable_mp(this, &TileMapEditor::_tile_map_changed));
+ // Disconnect to changes.
+ TileMapLayer *tile_map_layer = _get_edited_layer();
+ if (tile_map_layer) {
+ tile_map_layer->disconnect("changed", callable_mp(this, &TileMapLayerEditor::_tile_map_layer_changed));
}
- if (p_tile_map) {
+ // Update the edited layer.
+ if (p_tile_map_layer) {
// Change the edited object.
- tile_map_id = p_tile_map->get_instance_id();
- tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
+ edited_tile_map_layer_id = p_tile_map_layer->get_instance_id();
+
+ tile_map_layer = _get_edited_layer();
// Connect to changes.
- if (!tile_map->is_connected("changed", callable_mp(this, &TileMapEditor::_tile_map_changed))) {
- tile_map->connect("changed", callable_mp(this, &TileMapEditor::_tile_map_changed));
+ if (!tile_map_layer->is_connected("changed", callable_mp(this, &TileMapLayerEditor::_tile_map_layer_changed))) {
+ tile_map_layer->connect("changed", callable_mp(this, &TileMapLayerEditor::_tile_map_layer_changed));
}
} else {
- tile_map_id = ObjectID();
+ edited_tile_map_layer_id = ObjectID();
}
- _update_layers_selection();
+ update_layers_selector();
+ _update_highlighting_toggle();
// Call the plugins.
- tabs_plugins[tabs_bar->get_current_tab()]->edit(tile_map_id, tile_map_layer);
+ tabs_plugins[tabs_bar->get_current_tab()]->edit(edited_tile_map_layer_id);
+
+ _tile_map_layer_changed();
+}
+
+void TileMapLayerEditor::update_layers_selector() {
+ const TileMapLayer *edited_layer = _get_edited_layer();
+ if (!edited_layer) {
+ return;
+ }
+
+ TileMapLayerGroup *tile_map_layer_group = Object::cast_to<TileMapLayerGroup>(edited_layer->get_parent());
+ if (tile_map_layer_group) {
+ // Update the selector
+ layers_selection_button->show();
+ layers_selection_button->clear();
- _tile_map_changed();
+ // Build the list of layers.
+ for (int i = 0; i < tile_map_layer_group->get_child_count(); i++) {
+ const TileMapLayer *layer = Object::cast_to<TileMapLayer>(tile_map_layer_group->get_child(i));
+ if (layer) {
+ int index = layers_selection_button->get_item_count();
+ layers_selection_button->add_item(layer->get_name());
+ layers_selection_button->set_item_disabled(index, !layer->is_enabled());
+ layers_selection_button->set_item_metadata(index, layer->get_name());
+ if (edited_layer == layer) {
+ layers_selection_button->select(index);
+ }
+ }
+ }
+
+ // Disable the button if there's no layer to select.
+ layers_selection_button->set_disabled(false);
+ if (layers_selection_button->get_item_count() == 0) {
+ layers_selection_button->set_disabled(true);
+ layers_selection_button->set_text(TTR("No Layers"));
+ }
+ } else {
+ layers_selection_button->hide();
+ }
}
-TileMapEditor::TileMapEditor() {
+TileMapLayerEditor::TileMapLayerEditor() {
set_process_internal(true);
// Shortcuts.
- ED_SHORTCUT("tiles_editor/select_next_layer", TTR("Select Next Tile Map Layer"), Key::PAGEUP);
- ED_SHORTCUT("tiles_editor/select_previous_layer", TTR("Select Previous Tile Map Layer"), Key::PAGEDOWN);
+ ED_SHORTCUT("tiles_editor/select_next_layer", TTR("Select Next Tile Map Layer"), Key::PAGEDOWN);
+ ED_SHORTCUT("tiles_editor/select_previous_layer", TTR("Select Previous Tile Map Layer"), Key::PAGEUP);
// TileMap editor plugins
- tile_map_editor_plugins.push_back(memnew(TileMapEditorTilesPlugin));
- tile_map_editor_plugins.push_back(memnew(TileMapEditorTerrainsPlugin));
+ tile_map_editor_plugins.push_back(memnew(TileMapLayerEditorTilesPlugin));
+ tile_map_editor_plugins.push_back(memnew(TileMapLayerEditorTerrainsPlugin));
// TabBar.
tabs_bar = memnew(TabBar);
tabs_bar->set_clip_tabs(false);
for (int plugin_index = 0; plugin_index < tile_map_editor_plugins.size(); plugin_index++) {
- Vector<TileMapSubEditorPlugin::TabData> tabs_vector = tile_map_editor_plugins[plugin_index]->get_tabs();
+ Vector<TileMapLayerSubEditorPlugin::TabData> tabs_vector = tile_map_editor_plugins[plugin_index]->get_tabs();
for (int tab_index = 0; tab_index < tabs_vector.size(); tab_index++) {
tabs_bar->add_tab(tabs_vector[tab_index].panel->get_name());
tabs_data.push_back(tabs_vector[tab_index]);
tabs_plugins.push_back(tile_map_editor_plugins[plugin_index]);
}
}
- tabs_bar->connect("tab_changed", callable_mp(this, &TileMapEditor::_tab_changed));
+ tabs_bar->connect("tab_changed", callable_mp(this, &TileMapLayerEditor::_tab_changed));
// --- TileMap toolbar ---
tile_map_toolbar = memnew(HFlowContainer);
@@ -4228,7 +4194,7 @@ TileMapEditor::TileMapEditor() {
tile_map_toolbar->add_child(tabs_bar);
// Tabs toolbars.
- for (TileMapSubEditorPlugin::TabData &tab_data : tabs_data) {
+ for (TileMapLayerSubEditorPlugin::TabData &tab_data : tabs_data) {
tab_data.toolbar->hide();
if (!tab_data.toolbar->get_parent()) {
tile_map_toolbar->add_child(tab_data.toolbar);
@@ -4246,14 +4212,14 @@ TileMapEditor::TileMapEditor() {
layers_selection_button->set_custom_minimum_size(Size2(200, 0));
layers_selection_button->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS);
layers_selection_button->set_tooltip_text(TTR("TileMap Layers"));
- layers_selection_button->connect("item_selected", callable_mp(this, &TileMapEditor::_layers_selection_item_selected));
+ layers_selection_button->connect("item_selected", callable_mp(this, &TileMapLayerEditor::_layers_selection_item_selected));
tile_map_toolbar->add_child(layers_selection_button);
toggle_highlight_selected_layer_button = memnew(Button);
toggle_highlight_selected_layer_button->set_theme_type_variation("FlatButton");
toggle_highlight_selected_layer_button->set_toggle_mode(true);
toggle_highlight_selected_layer_button->set_pressed(true);
- toggle_highlight_selected_layer_button->connect("pressed", callable_mp(this, &TileMapEditor::_update_layers_selection));
+ toggle_highlight_selected_layer_button->connect("toggled", callable_mp(this, &TileMapLayerEditor::_highlight_selected_layer_button_toggled));
toggle_highlight_selected_layer_button->set_tooltip_text(TTR("Highlight Selected TileMap Layer"));
tile_map_toolbar->add_child(toggle_highlight_selected_layer_button);
@@ -4264,7 +4230,7 @@ TileMapEditor::TileMapEditor() {
toggle_grid_button->set_theme_type_variation("FlatButton");
toggle_grid_button->set_toggle_mode(true);
toggle_grid_button->set_tooltip_text(TTR("Toggle grid visibility."));
- toggle_grid_button->connect("toggled", callable_mp(this, &TileMapEditor::_on_grid_toggled));
+ toggle_grid_button->connect("toggled", callable_mp(this, &TileMapLayerEditor::_on_grid_toggled));
tile_map_toolbar->add_child(toggle_grid_button);
// Advanced settings menu button.
@@ -4272,7 +4238,7 @@ TileMapEditor::TileMapEditor() {
advanced_menu_button->set_flat(false);
advanced_menu_button->set_theme_type_variation("FlatButton");
advanced_menu_button->get_popup()->add_item(TTR("Automatically Replace Tiles with Proxies"));
- advanced_menu_button->get_popup()->connect("id_pressed", callable_mp(this, &TileMapEditor::_advanced_menu_button_id_pressed));
+ advanced_menu_button->get_popup()->connect("id_pressed", callable_mp(this, &TileMapLayerEditor::_advanced_menu_button_id_pressed));
tile_map_toolbar->add_child(advanced_menu_button);
missing_tileset_label = memnew(Label);
@@ -4294,10 +4260,10 @@ TileMapEditor::TileMapEditor() {
_tab_changed(0);
// Registers UndoRedo inspector callback.
- EditorNode::get_editor_data().add_move_array_element_function(SNAME("TileMap"), callable_mp(this, &TileMapEditor::_move_tile_map_array_element));
+ EditorNode::get_editor_data().add_move_array_element_function(SNAME("TileMap"), callable_mp(this, &TileMapLayerEditor::_move_tile_map_array_element));
}
-TileMapEditor::~TileMapEditor() {
+TileMapLayerEditor::~TileMapLayerEditor() {
for (int i = 0; i < tile_map_editor_plugins.size(); i++) {
memdelete(tile_map_editor_plugins[i]);
}
diff --git a/editor/plugins/tiles/tile_map_editor.h b/editor/plugins/tiles/tile_map_layer_editor.h
index c9a1efe62d..2a01a3c17a 100644
--- a/editor/plugins/tiles/tile_map_editor.h
+++ b/editor/plugins/tiles/tile_map_layer_editor.h
@@ -1,5 +1,5 @@
/**************************************************************************/
-/* tile_map_editor.h */
+/* tile_map_layer_editor.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
-#ifndef TILE_MAP_EDITOR_H
-#define TILE_MAP_EDITOR_H
+#ifndef TILE_MAP_LAYER_EDITOR_H
+#define TILE_MAP_LAYER_EDITOR_H
#include "tile_atlas_view.h"
@@ -48,9 +48,13 @@
#include "scene/gui/tab_bar.h"
#include "scene/gui/tree.h"
-class TileMapEditor;
+class TileMapLayerEditor;
+
+class TileMapLayerSubEditorPlugin : public Object {
+protected:
+ ObjectID edited_tile_map_layer_id;
+ TileMapLayer *_get_edited_layer() const;
-class TileMapSubEditorPlugin : public Object {
public:
struct TabData {
Control *toolbar = nullptr;
@@ -64,11 +68,11 @@ public:
virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return false; };
virtual void forward_canvas_draw_over_viewport(Control *p_overlay){};
virtual void tile_set_changed(){};
- virtual void edit(ObjectID p_tile_map_id, int p_tile_map_layer){};
+ virtual void edit(ObjectID p_tile_map_layer_id){};
};
-class TileMapEditorTilesPlugin : public TileMapSubEditorPlugin {
- GDCLASS(TileMapEditorTilesPlugin, TileMapSubEditorPlugin);
+class TileMapLayerEditorTilesPlugin : public TileMapLayerSubEditorPlugin {
+ GDCLASS(TileMapLayerEditorTilesPlugin, TileMapLayerSubEditorPlugin);
public:
enum {
@@ -79,10 +83,6 @@ public:
};
private:
- ObjectID tile_map_id;
- int tile_map_layer = -1;
- virtual void edit(ObjectID p_tile_map_id, int p_tile_map_layer) override;
-
///// Toolbar /////
HBoxContainer *toolbar = nullptr;
@@ -237,18 +237,16 @@ public:
virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override;
virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override;
- TileMapEditorTilesPlugin();
- ~TileMapEditorTilesPlugin();
+ virtual void edit(ObjectID p_tile_map_layer_id) override;
+
+ TileMapLayerEditorTilesPlugin();
+ ~TileMapLayerEditorTilesPlugin();
};
-class TileMapEditorTerrainsPlugin : public TileMapSubEditorPlugin {
- GDCLASS(TileMapEditorTerrainsPlugin, TileMapSubEditorPlugin);
+class TileMapLayerEditorTerrainsPlugin : public TileMapLayerSubEditorPlugin {
+ GDCLASS(TileMapLayerEditorTerrainsPlugin, TileMapLayerSubEditorPlugin);
private:
- ObjectID tile_map_id;
- int tile_map_layer = -1;
- virtual void edit(ObjectID p_tile_map_id, int p_tile_map_layer) override;
-
// Toolbar.
HBoxContainer *toolbar = nullptr;
@@ -331,28 +329,33 @@ public:
virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override;
virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override;
- TileMapEditorTerrainsPlugin();
- ~TileMapEditorTerrainsPlugin();
+ virtual void edit(ObjectID p_tile_map_layer_id) override;
+
+ TileMapLayerEditorTerrainsPlugin();
+ ~TileMapLayerEditorTerrainsPlugin();
};
-class TileMapEditor : public VBoxContainer {
- GDCLASS(TileMapEditor, VBoxContainer);
+class TileMapLayerEditor : public VBoxContainer {
+ GDCLASS(TileMapLayerEditor, VBoxContainer);
private:
bool tileset_changed_needs_update = false;
- ObjectID tile_map_id;
- int tile_map_layer = -1;
+
+ ObjectID edited_tile_map_layer_id;
+ TileMapLayer *_get_edited_layer() const;
// Vector to keep plugins.
- Vector<TileMapSubEditorPlugin *> tile_map_editor_plugins;
+ Vector<TileMapLayerSubEditorPlugin *> tile_map_editor_plugins;
// Toolbar.
HFlowContainer *tile_map_toolbar = nullptr;
OptionButton *layers_selection_button = nullptr;
- Button *toggle_highlight_selected_layer_button = nullptr;
void _layers_selection_item_selected(int p_index);
+ Button *toggle_highlight_selected_layer_button = nullptr;
+ void _highlight_selected_layer_button_toggled(bool p_pressed);
+
Button *toggle_grid_button = nullptr;
void _on_grid_toggled(bool p_pressed);
@@ -362,8 +365,8 @@ private:
// Bottom panel.
Label *missing_tileset_label = nullptr;
TabBar *tabs_bar = nullptr;
- LocalVector<TileMapSubEditorPlugin::TabData> tabs_data;
- LocalVector<TileMapSubEditorPlugin *> tabs_plugins;
+ LocalVector<TileMapLayerSubEditorPlugin::TabData> tabs_data;
+ LocalVector<TileMapLayerSubEditorPlugin *> tabs_plugins;
void _update_bottom_panel();
// TileMap.
@@ -371,31 +374,33 @@ private:
Ref<Texture2D> warning_pattern_texture;
// CallBack.
- void _tile_map_changed();
+ void _tile_map_layer_changed();
void _tab_changed(int p_tab_changed);
// Updates.
void _layers_select_next_or_previous(bool p_next);
- void _update_layers_selection();
+ void _update_highlighting_toggle();
// Inspector undo/redo callback.
void _move_tile_map_array_element(Object *p_undo_redo, Object *p_edited, String p_array_prefix, int p_from_index, int p_to_pos);
protected:
void _notification(int p_what);
+ static void _bind_methods();
void _draw_shape(Control *p_control, Rect2 p_region, TileSet::TileShape p_shape, TileSet::TileOffsetAxis p_offset_axis, Color p_color);
public:
bool forward_canvas_gui_input(const Ref<InputEvent> &p_event);
void forward_canvas_draw_over_viewport(Control *p_overlay);
- void edit(TileMap *p_tile_map);
+ void edit(TileMapLayer *p_tile_map_layer);
+ void update_layers_selector();
- TileMapEditor();
- ~TileMapEditor();
+ TileMapLayerEditor();
+ ~TileMapLayerEditor();
// Static functions.
- static Vector<Vector2i> get_line(TileMap *p_tile_map, Vector2i p_from_cell, Vector2i p_to_cell);
+ static Vector<Vector2i> get_line(const TileMapLayer *p_tile_map_layer, Vector2i p_from_cell, Vector2i p_to_cell);
};
-#endif // TILE_MAP_EDITOR_H
+#endif // TILE_MAP_LAYER_EDITOR_H
diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp
index 65f52bc92c..8ef052c71f 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.cpp
+++ b/editor/plugins/tiles/tiles_editor_plugin.cpp
@@ -40,8 +40,8 @@
#include "editor/editor_string_names.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "editor/themes/editor_scale.h"
-
#include "scene/2d/tile_map.h"
+#include "scene/2d/tile_map_layer.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/control.h"
@@ -324,7 +324,7 @@ TilesEditorUtils::~TilesEditorUtils() {
singleton = nullptr;
}
-void TileMapEditorPlugin::_tile_map_changed() {
+void TileMapEditorPlugin::_tile_map_layer_changed() {
if (tile_map_changed_needs_update) {
return;
}
@@ -332,23 +332,105 @@ void TileMapEditorPlugin::_tile_map_changed() {
callable_mp(this, &TileMapEditorPlugin::_update_tile_map).call_deferred();
}
-void TileMapEditorPlugin::_update_tile_map() {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
+void TileMapEditorPlugin::_tile_map_layer_removed() {
+ // Workaround for TileMap, making sure the editor stays open when you delete the currently edited layer.
+ TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_group_id));
if (tile_map) {
- Ref<TileSet> tile_set = tile_map->get_tileset();
- if (tile_set.is_valid() && edited_tileset != tile_set->get_instance_id()) {
- tile_set_plugin_singleton->edit(tile_map->get_tileset().ptr());
+ edit(tile_map);
+ }
+}
+
+void TileMapEditorPlugin::_update_tile_map() {
+ TileMapLayer *edited_layer = Object::cast_to<TileMapLayer>(ObjectDB::get_instance(tile_map_layer_id));
+ if (edited_layer) {
+ Ref<TileSet> tile_set = edited_layer->get_effective_tile_set();
+ if (tile_set.is_valid() && tile_set_id != tile_set->get_instance_id()) {
+ tile_set_plugin_singleton->edit(tile_set.ptr());
tile_set_plugin_singleton->make_visible(true);
- edited_tileset = tile_set->get_instance_id();
+ tile_set_id = tile_set->get_instance_id();
} else if (tile_set.is_null()) {
tile_set_plugin_singleton->edit(nullptr);
tile_set_plugin_singleton->make_visible(false);
- edited_tileset = ObjectID();
+ tile_set_id = ObjectID();
}
}
tile_map_changed_needs_update = false;
}
+void TileMapEditorPlugin::_select_layer(const StringName &p_name) {
+ TileMapLayer *edited_layer = Object::cast_to<TileMapLayer>(ObjectDB::get_instance(tile_map_layer_id));
+ ERR_FAIL_NULL(edited_layer);
+
+ Node *parent = edited_layer->get_parent();
+ ERR_FAIL_NULL(parent);
+
+ TileMapLayer *new_layer = Object::cast_to<TileMapLayer>(parent->get_node_or_null(String(p_name)));
+ edit(new_layer);
+}
+
+void TileMapEditorPlugin::_edit_tile_map_layer(TileMapLayer *p_tile_map_layer) {
+ ERR_FAIL_NULL(p_tile_map_layer);
+
+ editor->edit(p_tile_map_layer);
+
+ // Update the selected layers in the TileMapLayerGroup parent node.
+ TileMapLayerGroup *tile_map_layer_group = Object::cast_to<TileMapLayerGroup>(p_tile_map_layer->get_parent());
+ if (tile_map_layer_group) {
+ Vector<StringName> selected;
+ selected.push_back(p_tile_map_layer->get_name());
+ tile_map_layer_group->set_selected_layers(selected);
+ }
+
+ // Update the object IDs.
+ tile_map_layer_id = p_tile_map_layer->get_instance_id();
+ p_tile_map_layer->connect("changed", callable_mp(this, &TileMapEditorPlugin::_tile_map_layer_changed));
+ p_tile_map_layer->connect("tree_exited", callable_mp(this, &TileMapEditorPlugin::_tile_map_layer_removed));
+ if (tile_map_layer_group) {
+ tile_map_group_id = tile_map_layer_group->get_instance_id();
+ tile_map_layer_group->connect("child_entered_tree", callable_mp(editor, &TileMapLayerEditor::update_layers_selector).unbind(1));
+ tile_map_layer_group->connect("child_exiting_tree", callable_mp(editor, &TileMapLayerEditor::update_layers_selector).unbind(1));
+ tile_map_layer_group->connect("child_order_changed", callable_mp(editor, &TileMapLayerEditor::update_layers_selector));
+ }
+
+ // Update the edited tileset.
+ Ref<TileSet> tile_set = p_tile_map_layer->get_effective_tile_set();
+ if (tile_set.is_valid()) {
+ tile_set_plugin_singleton->edit(tile_set.ptr());
+ tile_set_plugin_singleton->make_visible(true);
+ tile_set_id = tile_set->get_instance_id();
+ } else {
+ tile_set_plugin_singleton->edit(nullptr);
+ tile_set_plugin_singleton->make_visible(false);
+ }
+}
+
+void TileMapEditorPlugin::_edit_tile_map_layer_group(TileMapLayerGroup *p_tile_map_layer_group) {
+ ERR_FAIL_NULL(p_tile_map_layer_group);
+
+ Vector<StringName> selected_layers = p_tile_map_layer_group->get_selected_layers();
+
+ TileMapLayer *selected_layer = nullptr;
+ if (selected_layers.size() > 0) {
+ // Edit the selected layer.
+ selected_layer = Object::cast_to<TileMapLayer>(p_tile_map_layer_group->get_node_or_null(String(selected_layers[0])));
+ }
+ if (!selected_layer) {
+ // Edit the first layer found.
+ for (int i = 0; i < p_tile_map_layer_group->get_child_count(); i++) {
+ selected_layer = Object::cast_to<TileMapLayer>(p_tile_map_layer_group->get_child(i));
+ if (selected_layer) {
+ break;
+ }
+ }
+ }
+
+ if (selected_layer) {
+ _edit_tile_map_layer(selected_layer);
+ } else {
+ editor->edit(nullptr);
+ }
+}
+
void TileMapEditorPlugin::_notification(int p_notification) {
if (p_notification == NOTIFICATION_EXIT_TREE) {
get_tree()->queue_delete(TilesEditorUtils::get_singleton());
@@ -356,39 +438,42 @@ void TileMapEditorPlugin::_notification(int p_notification) {
}
void TileMapEditorPlugin::edit(Object *p_object) {
- TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
- if (tile_map) {
- tile_map->disconnect("changed", callable_mp(this, &TileMapEditorPlugin::_tile_map_changed));
+ TileMapLayer *edited_layer = Object::cast_to<TileMapLayer>(ObjectDB::get_instance(tile_map_layer_id));
+ if (edited_layer) {
+ edited_layer->disconnect("changed", callable_mp(this, &TileMapEditorPlugin::_tile_map_layer_changed));
+ edited_layer->disconnect("tree_exited", callable_mp(this, &TileMapEditorPlugin::_tile_map_layer_removed));
}
- tile_map = Object::cast_to<TileMap>(p_object);
- if (tile_map) {
- tile_map_id = tile_map->get_instance_id();
- } else {
- tile_map_id = ObjectID();
+ TileMapLayerGroup *tile_map_group = Object::cast_to<TileMapLayerGroup>(ObjectDB::get_instance(tile_map_group_id));
+ if (tile_map_group) {
+ tile_map_group->disconnect("child_entered_tree", callable_mp(editor, &TileMapLayerEditor::update_layers_selector).unbind(1));
+ tile_map_group->disconnect("child_exiting_tree", callable_mp(editor, &TileMapLayerEditor::update_layers_selector).unbind(1));
+ tile_map_group->disconnect("child_order_changed", callable_mp(editor, &TileMapLayerEditor::update_layers_selector));
}
- editor->edit(tile_map);
- if (tile_map) {
- tile_map->connect("changed", callable_mp(this, &TileMapEditorPlugin::_tile_map_changed));
+ tile_map_group_id = ObjectID();
+ tile_map_layer_id = ObjectID();
+ tile_set_id = ObjectID();
- if (tile_map->get_tileset().is_valid()) {
- tile_set_plugin_singleton->edit(tile_map->get_tileset().ptr());
- tile_set_plugin_singleton->make_visible(true);
- edited_tileset = tile_map->get_tileset()->get_instance_id();
- }
- } else if (edited_tileset.is_valid()) {
- // Hide the TileSet editor, unless another TileSet is being edited.
- if (tile_set_plugin_singleton->get_edited_tileset() == edited_tileset) {
- tile_set_plugin_singleton->edit(nullptr);
- tile_set_plugin_singleton->make_visible(false);
+ TileMapLayerGroup *tile_map_layer_group = Object::cast_to<TileMap>(p_object);
+ TileMapLayer *tile_map_layer = Object::cast_to<TileMapLayer>(p_object);
+ if (tile_map_layer_group) {
+ _edit_tile_map_layer_group(tile_map_layer_group);
+ } else if (tile_map_layer) {
+ _edit_tile_map_layer(tile_map_layer);
+ } else {
+ // Deselect the layer in the group.
+ if (edited_layer) {
+ tile_map_layer_group = Object::cast_to<TileMapLayerGroup>(edited_layer->get_parent());
+ if (tile_map_layer_group) {
+ tile_map_layer_group->set_selected_layers(Vector<StringName>());
+ }
}
- edited_tileset = ObjectID();
}
}
bool TileMapEditorPlugin::handles(Object *p_object) const {
- return Object::cast_to<TileMap>(p_object) != nullptr;
+ return Object::cast_to<TileMapLayer>(p_object) != nullptr || Object::cast_to<TileMapLayerGroup>(p_object) != nullptr;
}
void TileMapEditorPlugin::make_visible(bool p_visible) {
@@ -427,10 +512,11 @@ TileMapEditorPlugin::TileMapEditorPlugin() {
}
tile_map_plugin_singleton = this;
- editor = memnew(TileMapEditor);
+ editor = memnew(TileMapLayerEditor);
editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE);
+ editor->connect("change_selected_layer_request", callable_mp(this, &TileMapEditorPlugin::_select_layer));
editor->hide();
button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("TileMap"), editor);
diff --git a/editor/plugins/tiles/tiles_editor_plugin.h b/editor/plugins/tiles/tiles_editor_plugin.h
index 6ca115454a..ac3e8986d6 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.h
+++ b/editor/plugins/tiles/tiles_editor_plugin.h
@@ -35,7 +35,7 @@
#include "scene/gui/box_container.h"
#include "tile_atlas_view.h"
-#include "tile_map_editor.h"
+#include "tile_map_layer_editor.h"
#include "tile_set_editor.h"
class TilesEditorUtils : public Object {
@@ -113,15 +113,21 @@ public:
class TileMapEditorPlugin : public EditorPlugin {
GDCLASS(TileMapEditorPlugin, EditorPlugin);
- TileMapEditor *editor = nullptr;
+ TileMapLayerEditor *editor = nullptr;
Button *button = nullptr;
- ObjectID tile_map_id;
+ ObjectID tile_map_layer_id;
+ ObjectID tile_map_group_id; // Allow keeping the layer selector up to date.
bool tile_map_changed_needs_update = false;
- ObjectID edited_tileset; // The TileSet associated with the TileMap.
+ ObjectID tile_set_id; // The TileSet associated with the TileMap.
- void _tile_map_changed();
+ void _tile_map_layer_changed();
+ void _tile_map_layer_removed();
void _update_tile_map();
+ void _select_layer(const StringName &p_name);
+
+ void _edit_tile_map_layer(TileMapLayer *p_tile_map_layer);
+ void _edit_tile_map_layer_group(TileMapLayerGroup *p_tile_map_layer_group);
protected:
void _notification(int p_notification);
diff --git a/misc/extension_api_validation/4.2-stable.expected b/misc/extension_api_validation/4.2-stable.expected
index 9b1aacc2e9..88622364d8 100644
--- a/misc/extension_api_validation/4.2-stable.expected
+++ b/misc/extension_api_validation/4.2-stable.expected
@@ -104,3 +104,12 @@ Validate extension JSON: Error: Field 'classes/GLTFBufferView/methods/get_byte_s
Validate extension JSON: Error: Field 'classes/GLTFBufferView/methods/get_indices': is_const changed value in new API, from false to true.
Change AudioStreamPlayer* is_autoplay_enabled and GLTFBufferView getters to be const.
+
+
+GH-87379
+--------
+Validate extension JSON: API was removed: classes/TileMap/methods/get_tileset
+Validate extension JSON: API was removed: classes/TileMap/methods/set_tileset
+Validate extension JSON: API was removed: classes/TileMap/properties/tile_set
+
+Moved to the parent TileMapLayerGroup class. No change should be necessary.
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index f40ee1f506..4cbcfa6dc2 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -49,131 +49,8 @@
ERR_FAIL_INDEX_V(layer, (int)layers.size(), err_value); \
return layers[layer]->function(__VA_ARGS__);
-Vector2i TileMap::transform_coords_layout(const Vector2i &p_coords, TileSet::TileOffsetAxis p_offset_axis, TileSet::TileLayout p_from_layout, TileSet::TileLayout p_to_layout) {
- // Transform to stacked layout.
- Vector2i output = p_coords;
- if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
- SWAP(output.x, output.y);
- }
- switch (p_from_layout) {
- case TileSet::TILE_LAYOUT_STACKED:
- break;
- case TileSet::TILE_LAYOUT_STACKED_OFFSET:
- if (output.y % 2) {
- output.x -= 1;
- }
- break;
- case TileSet::TILE_LAYOUT_STAIRS_RIGHT:
- case TileSet::TILE_LAYOUT_STAIRS_DOWN:
- if ((p_from_layout == TileSet::TILE_LAYOUT_STAIRS_RIGHT) ^ (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL)) {
- if (output.y < 0 && bool(output.y % 2)) {
- output = Vector2i(output.x + output.y / 2 - 1, output.y);
- } else {
- output = Vector2i(output.x + output.y / 2, output.y);
- }
- } else {
- if (output.x < 0 && bool(output.x % 2)) {
- output = Vector2i(output.x / 2 - 1, output.x + output.y * 2);
- } else {
- output = Vector2i(output.x / 2, output.x + output.y * 2);
- }
- }
- break;
- case TileSet::TILE_LAYOUT_DIAMOND_RIGHT:
- case TileSet::TILE_LAYOUT_DIAMOND_DOWN:
- if ((p_from_layout == TileSet::TILE_LAYOUT_DIAMOND_RIGHT) ^ (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL)) {
- if ((output.x + output.y) < 0 && (output.x - output.y) % 2) {
- output = Vector2i((output.x + output.y) / 2 - 1, output.y - output.x);
- } else {
- output = Vector2i((output.x + output.y) / 2, -output.x + output.y);
- }
- } else {
- if ((output.x - output.y) < 0 && (output.x + output.y) % 2) {
- output = Vector2i((output.x - output.y) / 2 - 1, output.x + output.y);
- } else {
- output = Vector2i((output.x - output.y) / 2, output.x + output.y);
- }
- }
- break;
- }
-
- switch (p_to_layout) {
- case TileSet::TILE_LAYOUT_STACKED:
- break;
- case TileSet::TILE_LAYOUT_STACKED_OFFSET:
- if (output.y % 2) {
- output.x += 1;
- }
- break;
- case TileSet::TILE_LAYOUT_STAIRS_RIGHT:
- case TileSet::TILE_LAYOUT_STAIRS_DOWN:
- if ((p_to_layout == TileSet::TILE_LAYOUT_STAIRS_RIGHT) ^ (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL)) {
- if (output.y < 0 && (output.y % 2)) {
- output = Vector2i(output.x - output.y / 2 + 1, output.y);
- } else {
- output = Vector2i(output.x - output.y / 2, output.y);
- }
- } else {
- if (output.y % 2) {
- if (output.y < 0) {
- output = Vector2i(2 * output.x + 1, -output.x + output.y / 2 - 1);
- } else {
- output = Vector2i(2 * output.x + 1, -output.x + output.y / 2);
- }
- } else {
- output = Vector2i(2 * output.x, -output.x + output.y / 2);
- }
- }
- break;
- case TileSet::TILE_LAYOUT_DIAMOND_RIGHT:
- case TileSet::TILE_LAYOUT_DIAMOND_DOWN:
- if ((p_to_layout == TileSet::TILE_LAYOUT_DIAMOND_RIGHT) ^ (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL)) {
- if (output.y % 2) {
- if (output.y > 0) {
- output = Vector2i(output.x - output.y / 2, output.x + output.y / 2 + 1);
- } else {
- output = Vector2i(output.x - output.y / 2 + 1, output.x + output.y / 2);
- }
- } else {
- output = Vector2i(output.x - output.y / 2, output.x + output.y / 2);
- }
- } else {
- if (output.y % 2) {
- if (output.y < 0) {
- output = Vector2i(output.x + output.y / 2, -output.x + output.y / 2 - 1);
- } else {
- output = Vector2i(output.x + output.y / 2 + 1, -output.x + output.y / 2);
- }
- } else {
- output = Vector2i(output.x + output.y / 2, -output.x + output.y / 2);
- }
- }
- break;
- }
-
- if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
- SWAP(output.x, output.y);
- }
-
- return output;
-}
-
-void TileMap::set_selected_layer(int p_layer_id) {
- ERR_FAIL_COND(p_layer_id < -1 || p_layer_id >= (int)layers.size());
- if (selected_layer == p_layer_id) {
- return;
- }
- selected_layer = p_layer_id;
+void TileMap::_emit_changed() {
emit_signal(CoreStringNames::get_singleton()->changed);
-
- // Update the layers modulation.
- for (TileMapLayer *layer : layers) {
- layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_SELECTED_LAYER);
- }
-}
-
-int TileMap::get_selected_layer() const {
- return selected_layer;
}
void TileMap::_notification(int p_what) {
@@ -188,7 +65,6 @@ void TileMap::_notification(int p_what) {
if (is_inside_tree() && collision_animatable && !in_editor) {
// Update transform on the physics tick when in animatable mode.
last_valid_transform = new_transform;
- print_line("Physics: ", new_transform);
set_notify_local_transform(false);
set_global_transform(new_transform);
set_notify_local_transform(true);
@@ -207,7 +83,6 @@ void TileMap::_notification(int p_what) {
// Store last valid transform.
new_transform = get_global_transform();
- print_line("local XFORM: ", last_valid_transform);
// ... but then revert changes.
set_notify_local_transform(false);
set_global_transform(last_valid_transform);
@@ -225,55 +100,6 @@ void TileMap::force_update(int p_layer) {
}
#endif
-void TileMap::queue_internal_update() {
- if (pending_update) {
- return;
- }
- pending_update = true;
- callable_mp(this, &TileMap::_internal_update).call_deferred();
-}
-
-void TileMap::_internal_update() {
- // Other updates.
- if (!pending_update) {
- return;
- }
-
- // Update dirty quadrants on layers.
- for (TileMapLayer *layer : layers) {
- layer->internal_update();
- }
-
- pending_update = false;
-}
-
-void TileMap::set_tileset(const Ref<TileSet> &p_tileset) {
- if (p_tileset == tile_set) {
- return;
- }
-
- // Set the tileset, registering to its changes.
- if (tile_set.is_valid()) {
- tile_set->disconnect_changed(callable_mp(this, &TileMap::_tile_set_changed));
- }
-
- tile_set = p_tileset;
-
- if (tile_set.is_valid()) {
- tile_set->connect_changed(callable_mp(this, &TileMap::_tile_set_changed));
- }
-
- for (TileMapLayer *layer : layers) {
- layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_TILE_SET);
- }
-
- emit_signal(CoreStringNames::get_singleton()->changed);
-}
-
-Ref<TileSet> TileMap::get_tileset() const {
- return tile_set;
-}
-
void TileMap::set_rendering_quadrant_size(int p_size) {
ERR_FAIL_COND_MSG(p_size < 1, "TileMapQuadrant size cannot be smaller than 1.");
@@ -281,7 +107,7 @@ void TileMap::set_rendering_quadrant_size(int p_size) {
for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_QUADRANT_SIZE);
}
- emit_signal(CoreStringNames::get_singleton()->changed);
+ _emit_changed();
}
int TileMap::get_rendering_quadrant_size() const {
@@ -392,10 +218,11 @@ void TileMap::add_layer(int p_to_pos) {
for (uint32_t i = 0; i < layers.size(); i++) {
layers[i]->set_layer_index_in_tile_map_node(i);
}
- queue_internal_update();
+ new_layer->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TileMap::_emit_changed));
+
notify_property_list_changed();
- emit_signal(CoreStringNames::get_singleton()->changed);
+ _emit_changed();
update_configuration_warnings();
}
@@ -412,14 +239,9 @@ void TileMap::move_layer(int p_layer, int p_to_pos) {
move_child(layer, i);
layers[i]->set_layer_index_in_tile_map_node(i);
}
- queue_internal_update();
notify_property_list_changed();
- if (selected_layer == p_layer) {
- selected_layer = p_to_pos < p_layer ? p_to_pos - 1 : p_to_pos;
- }
-
- emit_signal(CoreStringNames::get_singleton()->changed);
+ _emit_changed();
update_configuration_warnings();
}
@@ -433,14 +255,9 @@ void TileMap::remove_layer(int p_layer) {
for (uint32_t i = 0; i < layers.size(); i++) {
layers[i]->set_layer_index_in_tile_map_node(i);
}
- queue_internal_update();
notify_property_list_changed();
- if (selected_layer >= p_layer) {
- selected_layer -= 1;
- }
-
- emit_signal(CoreStringNames::get_singleton()->changed);
+ _emit_changed();
update_configuration_warnings();
}
@@ -533,7 +350,7 @@ void TileMap::set_collision_visibility_mode(TileMap::VisibilityMode p_show_colli
for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_COLLISION_VISIBILITY_MODE);
}
- emit_signal(CoreStringNames::get_singleton()->changed);
+ _emit_changed();
}
TileMap::VisibilityMode TileMap::get_collision_visibility_mode() const {
@@ -548,7 +365,7 @@ void TileMap::set_navigation_visibility_mode(TileMap::VisibilityMode p_show_navi
for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_NAVIGATION_VISIBILITY_MODE);
}
- emit_signal(CoreStringNames::get_singleton()->changed);
+ _emit_changed();
}
TileMap::VisibilityMode TileMap::get_navigation_visibility_mode() const {
@@ -563,7 +380,7 @@ void TileMap::set_y_sort_enabled(bool p_enable) {
for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_Y_SORT_ENABLED);
}
- emit_signal(CoreStringNames::get_singleton()->changed);
+ _emit_changed();
update_configuration_warnings();
}
@@ -671,8 +488,9 @@ void TileMap::clear() {
}
void TileMap::update_internals() {
- pending_update = true;
- _internal_update();
+ for (TileMapLayer *layer : layers) {
+ layer->update_internals();
+ }
}
void TileMap::notify_runtime_tile_data_update(int p_layer) {
@@ -721,10 +539,11 @@ bool TileMap::_set(const StringName &p_name, const Variant &p_value) {
add_child(new_layer);
new_layer->set_name("Layer0");
new_layer->set_layer_index_in_tile_map_node(0);
+ new_layer->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TileMap::_emit_changed));
layers.push_back(new_layer);
}
layers[0]->set_tile_data(format, p_value);
- emit_signal(CoreStringNames::get_singleton()->changed);
+ _emit_changed();
return true;
}
return false;
@@ -745,11 +564,12 @@ bool TileMap::_set(const StringName &p_name, const Variant &p_value) {
add_child(new_layer);
new_layer->set_name(vformat("Layer%d", index));
new_layer->set_layer_index_in_tile_map_node(index);
+ new_layer->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TileMap::_emit_changed));
layers.push_back(new_layer);
}
notify_property_list_changed();
- emit_signal(CoreStringNames::get_singleton()->changed);
+ _emit_changed();
update_configuration_warnings();
}
@@ -776,7 +596,7 @@ bool TileMap::_set(const StringName &p_name, const Variant &p_value) {
return true;
} else if (components[1] == "tile_data") {
layers[index]->set_tile_data(format, p_value);
- emit_signal(CoreStringNames::get_singleton()->changed);
+ _emit_changed();
return true;
} else {
return false;
@@ -1014,93 +834,12 @@ void TileMap::set_texture_repeat(CanvasItem::TextureRepeat p_texture_repeat) {
}
}
-TypedArray<Vector2i> TileMap::get_surrounding_cells(const Vector2i &coords) {
+TypedArray<Vector2i> TileMap::get_surrounding_cells(const Vector2i &p_coords) {
if (!tile_set.is_valid()) {
return TypedArray<Vector2i>();
}
- TypedArray<Vector2i> around;
- TileSet::TileShape shape = tile_set->get_tile_shape();
- if (shape == TileSet::TILE_SHAPE_SQUARE) {
- around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE));
- around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE));
- around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_LEFT_SIDE));
- around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_TOP_SIDE));
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC) {
- around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE));
- around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE));
- around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE));
- around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE));
- } else {
- if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE));
- around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE));
- around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE));
- around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_LEFT_SIDE));
- around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE));
- around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE));
- } else {
- around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE));
- around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE));
- around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE));
- around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE));
- around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_TOP_SIDE));
- around.push_back(get_neighbor_cell(coords, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE));
- }
- }
-
- return around;
-}
-
-void TileMap::draw_cells_outline(Control *p_control, const RBSet<Vector2i> &p_cells, Color p_color, Transform2D p_transform) {
- if (!tile_set.is_valid()) {
- return;
- }
-
- // Create a set.
- Vector2i tile_size = tile_set->get_tile_size();
- Vector<Vector2> polygon = tile_set->get_tile_shape_polygon();
- TileSet::TileShape shape = tile_set->get_tile_shape();
-
- for (const Vector2i &E : p_cells) {
- Vector2 center = map_to_local(E);
-
-#define DRAW_SIDE_IF_NEEDED(side, polygon_index_from, polygon_index_to) \
- if (!p_cells.has(get_neighbor_cell(E, side))) { \
- Vector2 from = p_transform.xform(center + polygon[polygon_index_from] * tile_size); \
- Vector2 to = p_transform.xform(center + polygon[polygon_index_to] * tile_size); \
- p_control->draw_line(from, to, p_color); \
- }
-
- if (shape == TileSet::TILE_SHAPE_SQUARE) {
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_RIGHT_SIDE, 1, 2);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, 2, 3);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_LEFT_SIDE, 3, 0);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_SIDE, 0, 1);
- } else if (shape == TileSet::TILE_SHAPE_ISOMETRIC) {
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 2, 3);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 1, 2);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 3, 0);
- } else {
- if (tile_set->get_tile_offset_axis() == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 2, 3);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_LEFT_SIDE, 1, 2);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 5, 0);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_RIGHT_SIDE, 4, 5);
- } else {
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, 4, 5);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 5, 0);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_SIDE, 1, 2);
- DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 2, 3);
- }
- }
- }
-#undef DRAW_SIDE_IF_NEEDED
+ return tile_set->get_surrounding_cells(p_coords);
}
Array TileMap::get_configuration_warnings() const {
@@ -1171,9 +910,6 @@ void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("force_update", "layer"), &TileMap::force_update, DEFVAL(-1));
#endif // DISABLE_DEPRECATED
- ClassDB::bind_method(D_METHOD("set_tileset", "tileset"), &TileMap::set_tileset);
- ClassDB::bind_method(D_METHOD("get_tileset"), &TileMap::get_tileset);
-
ClassDB::bind_method(D_METHOD("set_rendering_quadrant_size", "size"), &TileMap::set_rendering_quadrant_size);
ClassDB::bind_method(D_METHOD("get_rendering_quadrant_size"), &TileMap::get_rendering_quadrant_size);
@@ -1244,7 +980,6 @@ void TileMap::_bind_methods() {
GDVIRTUAL_BIND(_use_tile_data_runtime_update, "layer", "coords");
GDVIRTUAL_BIND(_tile_data_runtime_update, "layer", "coords", "tile_data");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "tile_set", PROPERTY_HINT_RESOURCE_TYPE, "TileSet"), "set_tileset", "get_tileset");
ADD_PROPERTY(PropertyInfo(Variant::INT, "rendering_quadrant_size", PROPERTY_HINT_RANGE, "1,128,1"), "set_rendering_quadrant_size", "get_rendering_quadrant_size");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_animatable"), "set_collision_animatable", "is_collision_animatable");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_visibility_mode", PROPERTY_HINT_ENUM, "Default,Force Show,Force Hide"), "set_collision_visibility_mode", "get_collision_visibility_mode");
@@ -1261,28 +996,18 @@ void TileMap::_bind_methods() {
BIND_ENUM_CONSTANT(VISIBILITY_MODE_FORCE_SHOW);
}
-void TileMap::_tile_set_changed() {
- emit_signal(CoreStringNames::get_singleton()->changed);
- for (TileMapLayer *layer : layers) {
- layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_TILE_SET);
- }
- update_configuration_warnings();
-}
-
TileMap::TileMap() {
TileMapLayer *new_layer = memnew(TileMapLayer);
add_child(new_layer);
new_layer->set_name("Layer0");
new_layer->set_layer_index_in_tile_map_node(0);
+ new_layer->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TileMap::_emit_changed));
layers.push_back(new_layer);
default_layer = memnew(TileMapLayer);
}
TileMap::~TileMap() {
- if (tile_set.is_valid()) {
- tile_set->disconnect_changed(callable_mp(this, &TileMap::_tile_set_changed));
- }
memdelete(default_layer);
}
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index 22efbf018f..9e66dd4dd9 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -31,7 +31,7 @@
#ifndef TILE_MAP_H
#define TILE_MAP_H
-#include "scene/2d/node_2d.h"
+#include "scene/2d/tile_map_layer_group.h"
#include "scene/resources/tile_set.h"
class Control;
@@ -45,8 +45,8 @@ enum TileMapDataFormat {
FORMAT_MAX,
};
-class TileMap : public Node2D {
- GDCLASS(TileMap, Node2D);
+class TileMap : public TileMapLayerGroup {
+ GDCLASS(TileMap, TileMapLayerGroup);
public:
enum VisibilityMode {
@@ -64,7 +64,6 @@ private:
static constexpr float FP_ADJUST = 0.00001;
// Properties.
- Ref<TileSet> tile_set;
int rendering_quadrant_size = 16;
bool collision_animatable = false;
VisibilityMode collision_visibility_mode = VISIBILITY_MODE_DEFAULT;
@@ -73,14 +72,12 @@ private:
// Layers.
LocalVector<TileMapLayer *> layers;
TileMapLayer *default_layer; // Dummy layer to fetch default values.
- int selected_layer = -1;
- bool pending_update = false;
// Transforms for collision_animatable.
Transform2D last_valid_transform;
Transform2D new_transform;
- void _tile_set_changed();
+ void _emit_changed();
protected:
bool _set(const StringName &p_name, const Variant &p_value);
@@ -103,8 +100,6 @@ protected:
#endif
public:
- static Vector2i transform_coords_layout(const Vector2i &p_coords, TileSet::TileOffsetAxis p_offset_axis, TileSet::TileLayout p_from_layout, TileSet::TileLayout p_to_layout);
-
#ifdef TOOLS_ENABLED
virtual Rect2 _edit_get_rect() const override;
#endif
@@ -113,13 +108,6 @@ public:
void force_update(int p_layer);
#endif
- // Called by TileMapLayers.
- void queue_internal_update();
- void _internal_update();
-
- void set_tileset(const Ref<TileSet> &p_tileset);
- Ref<TileSet> get_tileset() const;
-
void set_rendering_quadrant_size(int p_size);
int get_rendering_quadrant_size() const;
@@ -148,9 +136,6 @@ public:
void set_layer_navigation_map(int p_layer, RID p_map);
RID get_layer_navigation_map(int p_layer) const;
- void set_selected_layer(int p_layer_id); // For editor use.
- int get_selected_layer() const;
-
void set_collision_animatable(bool p_collision_animatable);
bool is_collision_animatable() const;
@@ -224,8 +209,7 @@ public:
void notify_runtime_tile_data_update(int p_layer = -1);
// Helpers?
- TypedArray<Vector2i> get_surrounding_cells(const Vector2i &coords);
- void draw_cells_outline(Control *p_control, const RBSet<Vector2i> &p_cells, Color p_color, Transform2D p_transform = Transform2D());
+ TypedArray<Vector2i> get_surrounding_cells(const Vector2i &p_coords);
// Virtual function to modify the TileData at runtime.
GDVIRTUAL2R(bool, _use_tile_data_runtime_update, int, Vector2i);
diff --git a/scene/2d/tile_map_layer.cpp b/scene/2d/tile_map_layer.cpp
index df79b3fee6..0888852de5 100644
--- a/scene/2d/tile_map_layer.cpp
+++ b/scene/2d/tile_map_layer.cpp
@@ -44,14 +44,6 @@ TileMap *TileMapLayer::_fetch_tilemap() const {
return TileMap::cast_to<TileMap>(get_parent());
}
-Ref<TileSet> TileMapLayer::_fetch_tileset() const {
- TileMap *tile_map_node = _fetch_tilemap();
- if (!tile_map_node) {
- return Ref<TileSet>();
- }
- return tile_map_node->get_tileset();
-}
-
#ifdef DEBUG_ENABLED
/////////////////////////////// Debug //////////////////////////////////////////
constexpr int TILE_MAP_DEBUG_QUADRANT_SIZE = 16;
@@ -63,7 +55,7 @@ Vector2i TileMapLayer::_coords_to_debug_quadrant_coords(const Vector2i &p_coords
}
void TileMapLayer::_debug_update() {
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
RenderingServer *rs = RenderingServer::get_singleton();
// Check if we should cleanup everything.
@@ -192,7 +184,7 @@ void TileMapLayer::_debug_quadrants_update_cell(CellData &r_cell_data, SelfList<
/////////////////////////////// Rendering //////////////////////////////////////
void TileMapLayer::_rendering_update() {
const TileMap *tile_map_node = _fetch_tilemap();
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
RenderingServer *rs = RenderingServer::get_singleton();
// Check if we should cleanup everything.
@@ -206,17 +198,22 @@ void TileMapLayer::_rendering_update() {
// Modulate the layer.
Color layer_modulate = get_modulate();
- int selected_layer = tile_map_node->get_selected_layer();
- if (selected_layer >= 0 && layer_index_in_tile_map_node != selected_layer) {
- int z_selected = tile_map_node->get_layer_z_index(selected_layer);
- int layer_z_index = get_z_index();
- if (layer_z_index < z_selected || (layer_z_index == z_selected && layer_index_in_tile_map_node < selected_layer)) {
- layer_modulate = layer_modulate.darkened(0.5);
- } else if (layer_z_index > z_selected || (layer_z_index == z_selected && layer_index_in_tile_map_node > selected_layer)) {
- layer_modulate = layer_modulate.darkened(0.5);
- layer_modulate.a *= 0.3;
+#ifdef TOOLS_ENABLED
+ const Vector<StringName> selected_layers = tile_map_node->get_selected_layers();
+ if (tile_map_node->is_highlighting_selected_layer() && selected_layers.size() == 1 && get_name() != selected_layers[0]) {
+ TileMapLayer *selected_layer = Object::cast_to<TileMapLayer>(tile_map_node->get_node_or_null(String(selected_layers[0])));
+ if (selected_layer) {
+ int z_selected = selected_layer->get_z_index();
+ int layer_z_index = get_z_index();
+ if (layer_z_index < z_selected || (layer_z_index == z_selected && get_index() < selected_layer->get_index())) {
+ layer_modulate = layer_modulate.darkened(0.5);
+ } else if (layer_z_index > z_selected || (layer_z_index == z_selected && get_index() > selected_layer->get_index())) {
+ layer_modulate = layer_modulate.darkened(0.5);
+ layer_modulate.a *= 0.3;
+ }
}
}
+#endif // TOOLS_ENABLED
rs->canvas_item_set_modulate(get_canvas_item(), layer_modulate);
}
@@ -228,7 +225,7 @@ void TileMapLayer::_rendering_update() {
// Check if anything changed that might change the quadrant shape.
// If so, recreate everything.
bool quandrant_shape_changed = dirty.flags[DIRTY_FLAGS_TILE_MAP_QUADRANT_SIZE] ||
- (is_y_sort_enabled() && (dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ENABLED] || dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN] || dirty.flags[DIRTY_FLAGS_TILE_MAP_Y_SORT_ENABLED] || dirty.flags[DIRTY_FLAGS_LAYER_LOCAL_TRANSFORM] || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET]));
+ (is_y_sort_enabled() && (dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ENABLED] || dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN] || dirty.flags[DIRTY_FLAGS_TILE_MAP_Y_SORT_ENABLED] || dirty.flags[DIRTY_FLAGS_LAYER_LOCAL_TRANSFORM] || dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET]));
// Free all quadrants.
if (forced_cleanup || quandrant_shape_changed) {
@@ -247,7 +244,7 @@ void TileMapLayer::_rendering_update() {
if (!forced_cleanup) {
// List all quadrants to update, recreating them if needed.
- if (dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE] || _rendering_was_cleaned_up) {
+ if (dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE] || _rendering_was_cleaned_up) {
// Update all cells.
for (KeyValue<Vector2i, CellData> &kv : tile_map) {
CellData &cell_data = kv.value;
@@ -427,7 +424,7 @@ void TileMapLayer::_rendering_update() {
_rendering_occluders_clear_cell(kv.value);
}
} else {
- if (_rendering_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET]) {
+ if (_rendering_was_cleaned_up || dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET]) {
// Update all cells.
for (KeyValue<Vector2i, CellData> &kv : tile_map) {
_rendering_occluders_update_cell(kv.value);
@@ -448,7 +445,7 @@ void TileMapLayer::_rendering_update() {
void TileMapLayer::_rendering_notification(int p_what) {
RenderingServer *rs = RenderingServer::get_singleton();
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
if (p_what == NOTIFICATION_TRANSFORM_CHANGED || p_what == NOTIFICATION_ENTER_CANVAS || p_what == NOTIFICATION_VISIBILITY_CHANGED) {
if (tile_set.is_valid()) {
Transform2D tilemap_xform = get_global_transform();
@@ -469,7 +466,7 @@ void TileMapLayer::_rendering_notification(int p_what) {
void TileMapLayer::_rendering_quadrants_update_cell(CellData &r_cell_data, SelfList<RenderingQuadrant>::List &r_dirty_rendering_quadrant_list) {
const TileMap *tile_map_node = _fetch_tilemap();
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
// Check if the cell is valid and retrieve its y_sort_origin.
bool is_valid = false;
@@ -569,7 +566,7 @@ void TileMapLayer::_rendering_occluders_clear_cell(CellData &r_cell_data) {
}
void TileMapLayer::_rendering_occluders_update_cell(CellData &r_cell_data) {
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
RenderingServer *rs = RenderingServer::get_singleton();
// Free unused occluders then resize the occluders array.
@@ -638,7 +635,7 @@ void TileMapLayer::_rendering_occluders_update_cell(CellData &r_cell_data) {
#ifdef DEBUG_ENABLED
void TileMapLayer::_rendering_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data) {
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
ERR_FAIL_COND(!tile_set.is_valid());
if (!Engine::get_singleton()->is_editor_hint()) {
@@ -687,7 +684,7 @@ void TileMapLayer::_rendering_draw_cell_debug(const RID &p_canvas_item, const Ve
/////////////////////////////// Physics //////////////////////////////////////
void TileMapLayer::_physics_update() {
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
// Check if we should cleanup everything.
bool forced_cleanup = in_destructor || !enabled || !is_inside_tree() || !tile_set.is_valid();
@@ -697,7 +694,7 @@ void TileMapLayer::_physics_update() {
_physics_clear_cell(kv.value);
}
} else {
- if (_physics_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_USE_KINEMATIC_BODIES] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) {
+ if (_physics_was_cleaned_up || dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_USE_KINEMATIC_BODIES] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) {
// Update all cells.
for (KeyValue<Vector2i, CellData> &kv : tile_map) {
_physics_update_cell(kv.value);
@@ -717,7 +714,7 @@ void TileMapLayer::_physics_update() {
}
void TileMapLayer::_physics_notification(int p_what) {
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
Transform2D gl_transform = get_global_transform();
PhysicsServer2D *ps = PhysicsServer2D::get_singleton();
@@ -771,7 +768,7 @@ void TileMapLayer::_physics_clear_cell(CellData &r_cell_data) {
void TileMapLayer::_physics_update_cell(CellData &r_cell_data) {
const TileMap *tile_map_node = _fetch_tilemap();
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
Transform2D gl_transform = get_global_transform();
RID space = get_world_2d()->get_space();
PhysicsServer2D *ps = PhysicsServer2D::get_singleton();
@@ -889,7 +886,7 @@ void TileMapLayer::_physics_update_cell(CellData &r_cell_data) {
void TileMapLayer::_physics_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data) {
// Draw the debug collision shapes.
TileMap *tile_map_node = _fetch_tilemap();
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
ERR_FAIL_COND(!tile_set.is_valid());
if (!get_tree()) {
@@ -945,7 +942,7 @@ void TileMapLayer::_physics_draw_cell_debug(const RID &p_canvas_item, const Vect
void TileMapLayer::_navigation_update() {
ERR_FAIL_NULL(NavigationServer2D::get_singleton());
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
NavigationServer2D *ns = NavigationServer2D::get_singleton();
// Check if we should cleanup everything.
@@ -982,7 +979,7 @@ void TileMapLayer::_navigation_update() {
_navigation_clear_cell(kv.value);
}
} else {
- if (_navigation_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) {
+ if (_navigation_was_cleaned_up || dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) {
// Update all cells.
for (KeyValue<Vector2i, CellData> &kv : tile_map) {
_navigation_update_cell(kv.value);
@@ -1002,7 +999,7 @@ void TileMapLayer::_navigation_update() {
}
void TileMapLayer::_navigation_notification(int p_what) {
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
if (p_what == NOTIFICATION_TRANSFORM_CHANGED) {
if (tile_set.is_valid()) {
Transform2D tilemap_xform = get_global_transform();
@@ -1037,7 +1034,7 @@ void TileMapLayer::_navigation_clear_cell(CellData &r_cell_data) {
void TileMapLayer::_navigation_update_cell(CellData &r_cell_data) {
const TileMap *tile_map_node = _fetch_tilemap();
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
NavigationServer2D *ns = NavigationServer2D::get_singleton();
Transform2D gl_xform = get_global_transform();
@@ -1136,7 +1133,7 @@ void TileMapLayer::_navigation_draw_cell_debug(const RID &p_canvas_item, const V
return;
}
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
RenderingServer *rs = RenderingServer::get_singleton();
const NavigationServer2D *ns2d = NavigationServer2D::get_singleton();
@@ -1222,7 +1219,7 @@ void TileMapLayer::_navigation_draw_cell_debug(const RID &p_canvas_item, const V
/////////////////////////////// Scenes //////////////////////////////////////
void TileMapLayer::_scenes_update() {
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
// Check if we should cleanup everything.
bool forced_cleanup = in_destructor || !enabled || !is_inside_tree() || !tile_set.is_valid();
@@ -1233,7 +1230,7 @@ void TileMapLayer::_scenes_update() {
_scenes_clear_cell(kv.value);
}
} else {
- if (_scenes_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) {
+ if (_scenes_was_cleaned_up || dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) {
// Update all cells.
for (KeyValue<Vector2i, CellData> &kv : tile_map) {
_scenes_update_cell(kv.value);
@@ -1268,7 +1265,7 @@ void TileMapLayer::_scenes_clear_cell(CellData &r_cell_data) {
void TileMapLayer::_scenes_update_cell(CellData &r_cell_data) {
TileMap *tile_map_node = _fetch_tilemap();
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
// Clear the scene in any case.
_scenes_clear_cell(r_cell_data);
@@ -1305,7 +1302,7 @@ void TileMapLayer::_scenes_update_cell(CellData &r_cell_data) {
#ifdef DEBUG_ENABLED
void TileMapLayer::_scenes_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data) {
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
ERR_FAIL_COND(!tile_set.is_valid());
if (!Engine::get_singleton()->is_editor_hint()) {
@@ -1356,13 +1353,13 @@ void TileMapLayer::_scenes_draw_cell_debug(const RID &p_canvas_item, const Vecto
void TileMapLayer::_build_runtime_update_tile_data() {
const TileMap *tile_map_node = _fetch_tilemap();
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
// Check if we should cleanup everything.
bool forced_cleanup = in_destructor || !enabled || !tile_set.is_valid() || !is_visible_in_tree();
if (!forced_cleanup) {
if (tile_map_node->GDVIRTUAL_IS_OVERRIDDEN(_use_tile_data_runtime_update) && tile_map_node->GDVIRTUAL_IS_OVERRIDDEN(_tile_data_runtime_update)) {
- if (_runtime_update_tile_data_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_MAP_TILE_SET]) {
+ if (_runtime_update_tile_data_was_cleaned_up || dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET]) {
for (KeyValue<Vector2i, CellData> &E : tile_map) {
_build_runtime_update_tile_data_for_cell(E.value);
}
@@ -1386,7 +1383,7 @@ void TileMapLayer::_build_runtime_update_tile_data() {
void TileMapLayer::_build_runtime_update_tile_data_for_cell(CellData &r_cell_data, bool p_auto_add_to_dirty_list) {
TileMap *tile_map_node = _fetch_tilemap();
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
TileMapCell &c = r_cell_data.cell;
TileSetSource *source;
@@ -1428,8 +1425,8 @@ void TileMapLayer::_clear_runtime_update_tile_data() {
}
}
-TileSet::TerrainsPattern TileMapLayer::_get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, const RBSet<TerrainConstraint> &p_constraints, TileSet::TerrainsPattern p_current_pattern) {
- const Ref<TileSet> &tile_set = _fetch_tileset();
+TileSet::TerrainsPattern TileMapLayer::_get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, const RBSet<TerrainConstraint> &p_constraints, TileSet::TerrainsPattern p_current_pattern) const {
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
if (!tile_set.is_valid()) {
return TileSet::TerrainsPattern();
}
@@ -1490,7 +1487,7 @@ TileSet::TerrainsPattern TileMapLayer::_get_best_terrain_pattern_for_constraints
}
RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_added_pattern(const Vector2i &p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const {
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
if (!tile_set.is_valid()) {
return RBSet<TerrainConstraint>();
}
@@ -1511,7 +1508,7 @@ RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_added_patte
}
RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_painted_cells_list(const RBSet<Vector2i> &p_painted, int p_terrain_set, bool p_ignore_empty_terrains) const {
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
if (!tile_set.is_valid()) {
return RBSet<TerrainConstraint>();
}
@@ -1599,8 +1596,7 @@ RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_painted_cel
}
void TileMapLayer::_renamed() {
- TileMap *tile_map_node = _fetch_tilemap();
- tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
+ emit_signal(CoreStringNames::get_singleton()->changed);
}
void TileMapLayer::_update_notify_local_transform() {
@@ -1614,6 +1610,66 @@ void TileMapLayer::_update_notify_local_transform() {
set_notify_local_transform(notify);
}
+void TileMapLayer::_queue_internal_update() {
+ if (pending_update) {
+ return;
+ }
+ pending_update = true;
+ callable_mp(this, &TileMapLayer::_deferred_internal_update).call_deferred();
+}
+
+void TileMapLayer::_deferred_internal_update() {
+ // Other updates.
+ if (!pending_update) {
+ return;
+ }
+
+ // Update dirty quadrants on layers.
+ _internal_update();
+
+ pending_update = false;
+}
+
+void TileMapLayer::_internal_update() {
+ // Find TileData that need a runtime modification.
+ // This may add cells to the dirty list is a runtime modification has been notified.
+ _build_runtime_update_tile_data();
+
+ // Update all subsystems.
+ _rendering_update();
+ _physics_update();
+ _navigation_update();
+ _scenes_update();
+#ifdef DEBUG_ENABLED
+ _debug_update();
+#endif // DEBUG_ENABLED
+
+ _clear_runtime_update_tile_data();
+
+ // Clear the "what is dirty" flags.
+ for (int i = 0; i < DIRTY_FLAGS_MAX; i++) {
+ dirty.flags[i] = false;
+ }
+
+ // List the cells to delete definitely.
+ Vector<Vector2i> to_delete;
+ for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) {
+ CellData &cell_data = *cell_data_list_element->self();
+ // Select the the cell from tile_map if it is invalid.
+ if (cell_data.cell.source_id == TileSet::INVALID_SOURCE) {
+ to_delete.push_back(cell_data.coords);
+ }
+ }
+
+ // Remove cells that are empty after the cleanup.
+ for (const Vector2i &coords : to_delete) {
+ tile_map.erase(coords);
+ }
+
+ // Clear the dirty cells list.
+ dirty.cell_list.clear();
+}
+
void TileMapLayer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_POSTINITIALIZE: {
@@ -1623,32 +1679,27 @@ void TileMapLayer::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
_update_notify_local_transform();
dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE] = true;
- TileMap *tile_map_node = _fetch_tilemap();
- tile_map_node->queue_internal_update();
+ _queue_internal_update();
} break;
case NOTIFICATION_EXIT_TREE: {
dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE] = true;
- TileMap *tile_map_node = _fetch_tilemap();
- tile_map_node->queue_internal_update();
+ _queue_internal_update();
} break;
case TileMap::NOTIFICATION_ENTER_CANVAS: {
dirty.flags[DIRTY_FLAGS_LAYER_IN_CANVAS] = true;
- TileMap *tile_map_node = _fetch_tilemap();
- tile_map_node->queue_internal_update();
+ _queue_internal_update();
} break;
case TileMap::NOTIFICATION_EXIT_CANVAS: {
dirty.flags[DIRTY_FLAGS_LAYER_IN_CANVAS] = true;
- TileMap *tile_map_node = _fetch_tilemap();
- tile_map_node->queue_internal_update();
+ _queue_internal_update();
} break;
case TileMap::NOTIFICATION_VISIBILITY_CHANGED: {
dirty.flags[DIRTY_FLAGS_LAYER_VISIBILITY] = true;
- TileMap *tile_map_node = _fetch_tilemap();
- tile_map_node->queue_internal_update();
+ _queue_internal_update();
} break;
}
@@ -1657,18 +1708,23 @@ void TileMapLayer::_notification(int p_what) {
_navigation_notification(p_what);
}
+void TileMapLayer::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMapLayer::set_cell, DEFVAL(TileSet::INVALID_SOURCE), DEFVAL(TileSetSource::INVALID_ATLAS_COORDS), DEFVAL(0));
+
+ ADD_SIGNAL(MethodInfo(CoreStringNames::get_singleton()->changed));
+}
+
void TileMapLayer::set_layer_index_in_tile_map_node(int p_index) {
if (p_index == layer_index_in_tile_map_node) {
return;
}
- TileMap *tile_map_node = _fetch_tilemap();
layer_index_in_tile_map_node = p_index;
dirty.flags[DIRTY_FLAGS_LAYER_INDEX_IN_TILE_MAP_NODE] = true;
- tile_map_node->queue_internal_update();
+ _queue_internal_update();
}
Rect2 TileMapLayer::get_rect(bool &r_changed) const {
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
if (tile_set.is_null()) {
r_changed = rect_cache != Rect2();
return Rect2();
@@ -1702,8 +1758,8 @@ Rect2 TileMapLayer::get_rect(bool &r_changed) const {
return rect_cache;
}
-HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_constraints(const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> &p_constraints) {
- const Ref<TileSet> &tile_set = _fetch_tileset();
+HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_constraints(const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> &p_constraints) const {
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
if (!tile_set.is_valid()) {
return HashMap<Vector2i, TileSet::TerrainsPattern>();
}
@@ -1750,9 +1806,9 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_constrain
return output;
}
-HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_connect(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) {
+HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_connect(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) const {
HashMap<Vector2i, TileSet::TerrainsPattern> output;
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
ERR_FAIL_COND_V(!tile_set.is_valid(), output);
ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), output);
@@ -1856,9 +1912,9 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_connect(c
return output;
}
-HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_path(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) {
+HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_path(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) const {
HashMap<Vector2i, TileSet::TerrainsPattern> output;
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
ERR_FAIL_COND_V(!tile_set.is_valid(), output);
ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), output);
@@ -1930,9 +1986,9 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_path(cons
return output;
}
-HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_pattern(const Vector<Vector2i> &p_coords_array, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern, bool p_ignore_empty_terrains) {
+HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_pattern(const Vector<Vector2i> &p_coords_array, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern, bool p_ignore_empty_terrains) const {
HashMap<Vector2i, TileSet::TerrainsPattern> output;
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
ERR_FAIL_COND_V(!tile_set.is_valid(), output);
ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), output);
@@ -1988,7 +2044,7 @@ TileMapCell TileMapLayer::get_cell(const Vector2i &p_coords, bool p_use_proxies)
return TileMapCell();
} else {
TileMapCell c = tile_map.find(p_coords)->value.cell;
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
if (p_use_proxies && tile_set.is_valid()) {
Array proxyed = tile_set->map_tile_proxy(c.source_id, c.get_atlas_coords(), c.alternative_tile);
c.source_id = proxyed[0];
@@ -2064,7 +2120,7 @@ void TileMapLayer::set_tile_data(TileMapDataFormat p_format, const Vector<int> &
coord_y = decode_uint16(&local[10]);
}
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
if (tile_set.is_valid()) {
Array a = tile_set->compatibility_tilemap_map(v, Vector2i(coord_x, coord_y), flip_h, flip_v, transpose);
if (a.size() == 3) {
@@ -2105,49 +2161,19 @@ Vector<int> TileMapLayer::get_tile_data() const {
}
void TileMapLayer::notify_tile_map_change(DirtyFlags p_what) {
- TileMap *tile_map_node = _fetch_tilemap();
- dirty.flags[p_what] = true;
- tile_map_node->queue_internal_update();
-}
-
-void TileMapLayer::internal_update() {
- // Find TileData that need a runtime modification.
- // This may add cells to the dirty list is a runtime modification has been notified.
- _build_runtime_update_tile_data();
-
- // Update all subsystems.
- _rendering_update();
- _physics_update();
- _navigation_update();
- _scenes_update();
-#ifdef DEBUG_ENABLED
- _debug_update();
-#endif // DEBUG_ENABLED
-
- _clear_runtime_update_tile_data();
-
- // Clear the "what is dirty" flags.
- for (int i = 0; i < DIRTY_FLAGS_MAX; i++) {
- dirty.flags[i] = false;
+ if (p_what == DIRTY_FLAGS_LAYER_GROUP_SELECTED_LAYERS ||
+ p_what == DIRTY_FLAGS_LAYER_GROUP_HIGHLIGHT_SELECTED ||
+ p_what == DIRTY_FLAGS_LAYER_GROUP_TILE_SET) {
+ emit_signal(CoreStringNames::get_singleton()->changed);
}
- // List the cells to delete definitely.
- Vector<Vector2i> to_delete;
- for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) {
- CellData &cell_data = *cell_data_list_element->self();
- // Select the the cell from tile_map if it is invalid.
- if (cell_data.cell.source_id == TileSet::INVALID_SOURCE) {
- to_delete.push_back(cell_data.coords);
- }
- }
-
- // Remove cells that are empty after the cleanup.
- for (const Vector2i &coords : to_delete) {
- tile_map.erase(coords);
- }
+ dirty.flags[p_what] = true;
+ _queue_internal_update();
+}
- // Clear the dirty cells list.
- dirty.cell_list.clear();
+void TileMapLayer::update_internals() {
+ pending_update = true;
+ _deferred_internal_update();
}
void TileMapLayer::set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i p_atlas_coords, int p_alternative_tile) {
@@ -2190,10 +2216,7 @@ void TileMapLayer::set_cell(const Vector2i &p_coords, int p_source_id, const Vec
if (!E->value.dirty_list_element.in_list()) {
dirty.cell_list.add(&(E->value.dirty_list_element));
}
- TileMap *tile_map_node = _fetch_tilemap();
- if (tile_map_node) { // Needed to avoid crashes in destructor.
- tile_map_node->queue_internal_update();
- }
+ _queue_internal_update();
used_rect_cache_dirty = true;
}
@@ -2210,7 +2233,7 @@ int TileMapLayer::get_cell_source_id(const Vector2i &p_coords, bool p_use_proxie
return TileSet::INVALID_SOURCE;
}
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
if (p_use_proxies && tile_set.is_valid()) {
Array proxyed = tile_set->map_tile_proxy(E->value.cell.source_id, E->value.cell.get_atlas_coords(), E->value.cell.alternative_tile);
return proxyed[0];
@@ -2227,7 +2250,7 @@ Vector2i TileMapLayer::get_cell_atlas_coords(const Vector2i &p_coords, bool p_us
return TileSetSource::INVALID_ATLAS_COORDS;
}
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
if (p_use_proxies && tile_set.is_valid()) {
Array proxyed = tile_set->map_tile_proxy(E->value.cell.source_id, E->value.cell.get_atlas_coords(), E->value.cell.alternative_tile);
return proxyed[1];
@@ -2244,7 +2267,7 @@ int TileMapLayer::get_cell_alternative_tile(const Vector2i &p_coords, bool p_use
return TileSetSource::INVALID_TILE_ALTERNATIVE;
}
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
if (p_use_proxies && tile_set.is_valid()) {
Array proxyed = tile_set->map_tile_proxy(E->value.cell.source_id, E->value.cell.get_atlas_coords(), E->value.cell.alternative_tile);
return proxyed[2];
@@ -2259,7 +2282,7 @@ TileData *TileMapLayer::get_cell_tile_data(const Vector2i &p_coords, bool p_use_
return nullptr;
}
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
Ref<TileSetAtlasSource> source = tile_set->get_source(source_id);
if (source.is_valid()) {
return source->get_tile_data(get_cell_atlas_coords(p_coords, p_use_proxies), get_cell_alternative_tile(p_coords, p_use_proxies));
@@ -2277,7 +2300,7 @@ void TileMapLayer::clear() {
}
Ref<TileMapPattern> TileMapLayer::get_pattern(TypedArray<Vector2i> p_coords_array) {
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
ERR_FAIL_COND_V(!tile_set.is_valid(), nullptr);
Ref<TileMapPattern> output;
@@ -2331,7 +2354,7 @@ Ref<TileMapPattern> TileMapLayer::get_pattern(TypedArray<Vector2i> p_coords_arra
}
void TileMapLayer::set_pattern(const Vector2i &p_position, const Ref<TileMapPattern> p_pattern) {
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
ERR_FAIL_COND(tile_set.is_null());
ERR_FAIL_COND(p_pattern.is_null());
@@ -2343,7 +2366,7 @@ void TileMapLayer::set_pattern(const Vector2i &p_position, const Ref<TileMapPatt
}
void TileMapLayer::set_cells_terrain_connect(TypedArray<Vector2i> p_cells, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) {
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
ERR_FAIL_COND(!tile_set.is_valid());
ERR_FAIL_INDEX(p_terrain_set, tile_set->get_terrain_sets_count());
@@ -2383,7 +2406,7 @@ void TileMapLayer::set_cells_terrain_connect(TypedArray<Vector2i> p_cells, int p
}
void TileMapLayer::set_cells_terrain_path(TypedArray<Vector2i> p_path, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) {
- const Ref<TileSet> &tile_set = _fetch_tileset();
+ const Ref<TileSet> &tile_set = get_effective_tile_set();
ERR_FAIL_COND(!tile_set.is_valid());
ERR_FAIL_INDEX(p_terrain_set, tile_set->get_terrain_sets_count());
@@ -2490,10 +2513,10 @@ void TileMapLayer::set_enabled(bool p_enabled) {
}
enabled = p_enabled;
dirty.flags[DIRTY_FLAGS_LAYER_ENABLED] = true;
- TileMap *tile_map_node = _fetch_tilemap();
- tile_map_node->queue_internal_update();
- tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
+ _queue_internal_update();
+ emit_signal(CoreStringNames::get_singleton()->changed);
+ TileMap *tile_map_node = _fetch_tilemap();
tile_map_node->update_configuration_warnings();
}
@@ -2507,9 +2530,8 @@ void TileMapLayer::set_self_modulate(const Color &p_self_modulate) {
}
CanvasItem::set_self_modulate(p_self_modulate);
dirty.flags[DIRTY_FLAGS_LAYER_SELF_MODULATE] = true;
- TileMap *tile_map_node = _fetch_tilemap();
- tile_map_node->queue_internal_update();
- tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
+ _queue_internal_update();
+ emit_signal(CoreStringNames::get_singleton()->changed);
}
void TileMapLayer::set_y_sort_enabled(bool p_y_sort_enabled) {
@@ -2518,10 +2540,10 @@ void TileMapLayer::set_y_sort_enabled(bool p_y_sort_enabled) {
}
CanvasItem::set_y_sort_enabled(p_y_sort_enabled);
dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ENABLED] = true;
- TileMap *tile_map_node = _fetch_tilemap();
- tile_map_node->queue_internal_update();
- tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
+ _queue_internal_update();
+ emit_signal(CoreStringNames::get_singleton()->changed);
+ TileMap *tile_map_node = _fetch_tilemap();
tile_map_node->update_configuration_warnings();
_update_notify_local_transform();
}
@@ -2532,9 +2554,8 @@ void TileMapLayer::set_y_sort_origin(int p_y_sort_origin) {
}
y_sort_origin = p_y_sort_origin;
dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN] = true;
- TileMap *tile_map_node = _fetch_tilemap();
- tile_map_node->queue_internal_update();
- tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
+ _queue_internal_update();
+ emit_signal(CoreStringNames::get_singleton()->changed);
}
int TileMapLayer::get_y_sort_origin() const {
@@ -2547,19 +2568,18 @@ void TileMapLayer::set_z_index(int p_z_index) {
}
CanvasItem::set_z_index(p_z_index);
dirty.flags[DIRTY_FLAGS_LAYER_Z_INDEX] = true;
- TileMap *tile_map_node = _fetch_tilemap();
- tile_map_node->queue_internal_update();
- tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
+ _queue_internal_update();
+ emit_signal(CoreStringNames::get_singleton()->changed);
+ TileMap *tile_map_node = _fetch_tilemap();
tile_map_node->update_configuration_warnings();
}
void TileMapLayer::set_use_kinematic_bodies(bool p_use_kinematic_bodies) {
use_kinematic_bodies = p_use_kinematic_bodies;
dirty.flags[DIRTY_FLAGS_LAYER_USE_KINEMATIC_BODIES] = p_use_kinematic_bodies;
- TileMap *tile_map_node = _fetch_tilemap();
- tile_map_node->queue_internal_update();
- tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
+ _queue_internal_update();
+ emit_signal(CoreStringNames::get_singleton()->changed);
}
bool TileMapLayer::is_using_kinematic_bodies() const {
@@ -2572,9 +2592,8 @@ void TileMapLayer::set_navigation_enabled(bool p_enabled) {
}
navigation_enabled = p_enabled;
dirty.flags[DIRTY_FLAGS_LAYER_NAVIGATION_ENABLED] = true;
- TileMap *tile_map_node = _fetch_tilemap();
- tile_map_node->queue_internal_update();
- tile_map_node->emit_signal(CoreStringNames::get_singleton()->changed);
+ _queue_internal_update();
+ emit_signal(CoreStringNames::get_singleton()->changed);
}
bool TileMapLayer::is_navigation_enabled() const {
@@ -2595,7 +2614,7 @@ RID TileMapLayer::get_navigation_map() const {
}
void TileMapLayer::fix_invalid_tiles() {
- Ref<TileSet> tileset = _fetch_tileset();
+ Ref<TileSet> tileset = get_effective_tile_set();
ERR_FAIL_COND_MSG(tileset.is_null(), "Cannot call fix_invalid_tiles() on a TileMap without a valid TileSet.");
RBSet<Vector2i> coords;
@@ -2618,6 +2637,15 @@ Vector2i TileMapLayer::get_coords_for_body_rid(RID p_physics_body) const {
return bodies_coords[p_physics_body];
}
+Ref<TileSet> TileMapLayer::get_effective_tile_set() const {
+ TileMapLayerGroup *tile_map_layer_group = Object::cast_to<TileMapLayerGroup>(get_parent());
+ if (tile_map_layer_group) {
+ return tile_map_layer_group->get_tileset();
+ } else {
+ return Ref<TileSet>();
+ }
+}
+
TileMapLayer::TileMapLayer() {
set_notify_transform(true);
}
@@ -2625,7 +2653,7 @@ TileMapLayer::TileMapLayer() {
TileMapLayer::~TileMapLayer() {
in_destructor = true;
clear();
- internal_update();
+ _internal_update();
}
HashMap<Vector2i, TileSet::CellNeighbor> TerrainConstraint::get_overlapping_coords_and_peering_bits() const {
diff --git a/scene/2d/tile_map_layer.h b/scene/2d/tile_map_layer.h
index 2cc57f50d1..6cf432bc24 100644
--- a/scene/2d/tile_map_layer.h
+++ b/scene/2d/tile_map_layer.h
@@ -232,13 +232,15 @@ public:
DIRTY_FLAGS_LAYER_NAVIGATION_ENABLED,
DIRTY_FLAGS_LAYER_INDEX_IN_TILE_MAP_NODE,
- DIRTY_FLAGS_TILE_MAP_SELECTED_LAYER,
+ DIRTY_FLAGS_LAYER_GROUP_SELECTED_LAYERS,
+ DIRTY_FLAGS_LAYER_GROUP_HIGHLIGHT_SELECTED,
+ DIRTY_FLAGS_LAYER_GROUP_TILE_SET,
+
DIRTY_FLAGS_TILE_MAP_LIGHT_MASK,
DIRTY_FLAGS_TILE_MAP_MATERIAL,
DIRTY_FLAGS_TILE_MAP_USE_PARENT_MATERIAL,
DIRTY_FLAGS_TILE_MAP_TEXTURE_FILTER,
DIRTY_FLAGS_TILE_MAP_TEXTURE_REPEAT,
- DIRTY_FLAGS_TILE_MAP_TILE_SET,
DIRTY_FLAGS_TILE_MAP_QUADRANT_SIZE,
DIRTY_FLAGS_TILE_MAP_COLLISION_VISIBILITY_MODE,
DIRTY_FLAGS_TILE_MAP_NAVIGATION_VISIBILITY_MODE,
@@ -259,6 +261,7 @@ private:
// Internal.
int layer_index_in_tile_map_node = -1;
HashMap<Vector2i, CellData> tile_map;
+ bool pending_update = false;
// Dirty flag. Allows knowing what was modified since the last update.
struct {
@@ -275,7 +278,6 @@ private:
// Method to fetch the TileSet to use
TileMap *_fetch_tilemap() const;
- Ref<TileSet> _fetch_tileset() const;
// Runtime tile data.
bool _runtime_update_tile_data_was_cleaned_up = false;
@@ -331,15 +333,21 @@ private:
#endif // DEBUG_ENABLED
// Terrains.
- TileSet::TerrainsPattern _get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, const RBSet<TerrainConstraint> &p_constraints, TileSet::TerrainsPattern p_current_pattern);
+ TileSet::TerrainsPattern _get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, const RBSet<TerrainConstraint> &p_constraints, TileSet::TerrainsPattern p_current_pattern) const;
RBSet<TerrainConstraint> _get_terrain_constraints_from_added_pattern(const Vector2i &p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const;
RBSet<TerrainConstraint> _get_terrain_constraints_from_painted_cells_list(const RBSet<Vector2i> &p_painted, int p_terrain_set, bool p_ignore_empty_terrains) const;
void _renamed();
void _update_notify_local_transform();
+ // Internal updates.
+ void _queue_internal_update();
+ void _deferred_internal_update();
+ void _internal_update();
+
protected:
void _notification(int p_what);
+ static void _bind_methods();
public:
// TileMap node.
@@ -349,10 +357,10 @@ public:
Rect2 get_rect(bool &r_changed) const;
// Terrains.
- HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_constraints(const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> &p_constraints); // Not exposed.
- HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_connect(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); // Not exposed.
- HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_path(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true); // Not exposed.
- HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_pattern(const Vector<Vector2i> &p_coords_array, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern, bool p_ignore_empty_terrains = true); // Not exposed.
+ HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_constraints(const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> &p_constraints) const; // Not exposed.
+ HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_connect(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true) const; // Not exposed.
+ HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_path(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains = true) const; // Not exposed.
+ HashMap<Vector2i, TileSet::TerrainsPattern> terrain_fill_pattern(const Vector<Vector2i> &p_coords_array, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern, bool p_ignore_empty_terrains = true) const; // Not exposed.
// Not exposed to users.
TileMapCell get_cell(const Vector2i &p_coords, bool p_use_proxies = false) const;
@@ -361,10 +369,10 @@ public:
void set_tile_data(TileMapDataFormat p_format, const Vector<int> &p_data);
Vector<int> get_tile_data() const;
void notify_tile_map_change(DirtyFlags p_what);
- void internal_update();
- // --- Exposed in TileMap ---
+ void update_internals();
+ // --- Exposed in TileMap ---
// Cells manipulation.
void set_cell(const Vector2i &p_coords, int p_source_id = TileSet::INVALID_SOURCE, const Vector2i p_atlas_coords = TileSetSource::INVALID_ATLAS_COORDS, int p_alternative_tile = 0);
void erase_cell(const Vector2i &p_coords);
@@ -410,6 +418,11 @@ public:
bool has_body_rid(RID p_physics_body) const;
Vector2i get_coords_for_body_rid(RID p_physics_body) const; // For finding tiles from collision.
+ // Helper.
+ Ref<TileSet> get_effective_tile_set() const;
+
+ // ---
+
TileMapLayer();
~TileMapLayer();
};
diff --git a/scene/2d/tile_map_layer_group.cpp b/scene/2d/tile_map_layer_group.cpp
new file mode 100644
index 0000000000..ac0de380a3
--- /dev/null
+++ b/scene/2d/tile_map_layer_group.cpp
@@ -0,0 +1,148 @@
+/**************************************************************************/
+/* tile_map_layer_group.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "tile_map_layer_group.h"
+
+#include "core/core_string_names.h"
+#include "scene/2d/tile_map_layer.h"
+#include "scene/resources/tile_set.h"
+
+#ifdef TOOLS_ENABLED
+
+void TileMapLayerGroup::_cleanup_selected_layers() {
+ for (int i = 0; i < selected_layers.size(); i++) {
+ const String name = selected_layers[i];
+ TileMapLayer *layer = Object::cast_to<TileMapLayer>(get_node_or_null(name));
+ if (!layer) {
+ selected_layers.remove_at(i);
+ i--;
+ }
+ }
+}
+
+#endif // TOOLS_ENABLED
+
+void TileMapLayerGroup::_tile_set_changed() {
+ for (int i = 0; i < get_child_count(); i++) {
+ TileMapLayer *layer = Object::cast_to<TileMapLayer>(get_child(i));
+ if (layer) {
+ layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_LAYER_GROUP_TILE_SET);
+ }
+ }
+
+ update_configuration_warnings();
+}
+
+#ifdef TOOLS_ENABLED
+
+void TileMapLayerGroup::set_selected_layers(Vector<StringName> p_layer_names) {
+ selected_layers = p_layer_names;
+ _cleanup_selected_layers();
+
+ // Update the layers modulation.
+ for (int i = 0; i < get_child_count(); i++) {
+ TileMapLayer *layer = Object::cast_to<TileMapLayer>(get_child(i));
+ if (layer) {
+ layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_LAYER_GROUP_SELECTED_LAYERS);
+ }
+ }
+}
+
+Vector<StringName> TileMapLayerGroup::get_selected_layers() const {
+ return selected_layers;
+}
+
+void TileMapLayerGroup::set_highlight_selected_layer(bool p_highlight_selected_layer) {
+ if (highlight_selected_layer == p_highlight_selected_layer) {
+ return;
+ }
+
+ highlight_selected_layer = p_highlight_selected_layer;
+
+ for (int i = 0; i < get_child_count(); i++) {
+ TileMapLayer *layer = Object::cast_to<TileMapLayer>(get_child(i));
+ if (layer) {
+ layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_LAYER_GROUP_HIGHLIGHT_SELECTED);
+ }
+ }
+}
+
+bool TileMapLayerGroup::is_highlighting_selected_layer() const {
+ return highlight_selected_layer;
+}
+
+#endif // TOOLS_ENABLED
+
+void TileMapLayerGroup::remove_child_notify(Node *p_child) {
+#ifdef TOOLS_ENABLED
+ _cleanup_selected_layers();
+#endif // TOOLS_ENABLED
+}
+
+void TileMapLayerGroup::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_tileset", "tileset"), &TileMapLayerGroup::set_tileset);
+ ClassDB::bind_method(D_METHOD("get_tileset"), &TileMapLayerGroup::get_tileset);
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "tile_set", PROPERTY_HINT_RESOURCE_TYPE, "TileSet"), "set_tileset", "get_tileset");
+}
+
+void TileMapLayerGroup::set_tileset(const Ref<TileSet> &p_tileset) {
+ if (p_tileset == tile_set) {
+ return;
+ }
+
+ // Set the tileset, registering to its changes.
+ if (tile_set.is_valid()) {
+ tile_set->disconnect_changed(callable_mp(this, &TileMapLayerGroup::_tile_set_changed));
+ }
+
+ tile_set = p_tileset;
+
+ if (tile_set.is_valid()) {
+ tile_set->connect_changed(callable_mp(this, &TileMapLayerGroup::_tile_set_changed));
+ }
+
+ for (int i = 0; i < get_child_count(); i++) {
+ TileMapLayer *layer = Object::cast_to<TileMapLayer>(get_child(i));
+ if (layer) {
+ layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_LAYER_GROUP_TILE_SET);
+ }
+ }
+}
+
+Ref<TileSet> TileMapLayerGroup::get_tileset() const {
+ return tile_set;
+}
+
+TileMapLayerGroup::~TileMapLayerGroup() {
+ if (tile_set.is_valid()) {
+ tile_set->disconnect_changed(callable_mp(this, &TileMapLayerGroup::_tile_set_changed));
+ }
+}
diff --git a/scene/2d/tile_map_layer_group.h b/scene/2d/tile_map_layer_group.h
new file mode 100644
index 0000000000..d80c244f80
--- /dev/null
+++ b/scene/2d/tile_map_layer_group.h
@@ -0,0 +1,73 @@
+/**************************************************************************/
+/* tile_map_layer_group.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef TILE_MAP_LAYER_GROUP_H
+#define TILE_MAP_LAYER_GROUP_H
+
+#include "scene/2d/node_2d.h"
+
+class TileSet;
+
+class TileMapLayerGroup : public Node2D {
+ GDCLASS(TileMapLayerGroup, Node2D);
+
+private:
+ mutable Vector<StringName> selected_layers;
+ bool highlight_selected_layer = true;
+
+#ifdef TOOLS_ENABLED
+ void _cleanup_selected_layers();
+#endif
+ void _tile_set_changed();
+
+protected:
+ Ref<TileSet> tile_set;
+
+ virtual void remove_child_notify(Node *p_child) override;
+
+ static void _bind_methods();
+
+public:
+#ifdef TOOLS_ENABLED
+ // For editor use.
+ void set_selected_layers(Vector<StringName> p_layer_names);
+ Vector<StringName> get_selected_layers() const;
+ void set_highlight_selected_layer(bool p_highlight_selected_layer);
+ bool is_highlighting_selected_layer() const;
+#endif
+
+ // Accessors.
+ void set_tileset(const Ref<TileSet> &p_tileset);
+ Ref<TileSet> get_tileset() const;
+
+ ~TileMapLayerGroup();
+};
+
+#endif // TILE_MAP_LAYER_GROUP_H
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 64a1c72f9d..c7d044caf2 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -783,6 +783,7 @@ void register_scene_types() {
GDREGISTER_CLASS(TileMapPattern);
GDREGISTER_CLASS(TileData);
GDREGISTER_CLASS(TileMap);
+ GDREGISTER_ABSTRACT_CLASS(TileMapLayerGroup);
GDREGISTER_CLASS(ParallaxBackground);
GDREGISTER_CLASS(ParallaxLayer);
GDREGISTER_CLASS(TouchScreenButton);
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 66e1b7bcf9..96891f2480 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -1478,7 +1478,7 @@ TileMapCell TileSet::get_random_tile_from_terrains_pattern(int p_terrain_set, Ti
ERR_FAIL_V(TileMapCell());
}
-Vector<Vector2> TileSet::get_tile_shape_polygon() {
+Vector<Vector2> TileSet::get_tile_shape_polygon() const {
Vector<Vector2> points;
if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
points.push_back(Vector2(-0.5, -0.5));
@@ -1519,7 +1519,7 @@ Vector<Vector2> TileSet::get_tile_shape_polygon() {
return points;
}
-void TileSet::draw_tile_shape(CanvasItem *p_canvas_item, Transform2D p_transform, Color p_color, bool p_filled, Ref<Texture2D> p_texture) {
+void TileSet::draw_tile_shape(CanvasItem *p_canvas_item, Transform2D p_transform, Color p_color, bool p_filled, Ref<Texture2D> p_texture) const {
if (tile_meshes_dirty) {
Vector<Vector2> shape = get_tile_shape_polygon();
Vector<Vector2> uvs;
@@ -2165,7 +2165,40 @@ Vector2i TileSet::get_neighbor_cell(const Vector2i &p_coords, TileSet::CellNeigh
}
}
-Vector2i TileSet::map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern) {
+TypedArray<Vector2i> TileSet::get_surrounding_cells(const Vector2i &p_coords) const {
+ TypedArray<Vector2i> around;
+ if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
+ around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE));
+ around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE));
+ around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_LEFT_SIDE));
+ around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_TOP_SIDE));
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE));
+ around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE));
+ around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE));
+ around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE));
+ } else {
+ if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_RIGHT_SIDE));
+ around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE));
+ around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE));
+ around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_LEFT_SIDE));
+ around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE));
+ around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE));
+ } else {
+ around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE));
+ around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_BOTTOM_SIDE));
+ around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE));
+ around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE));
+ around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_TOP_SIDE));
+ around.push_back(get_neighbor_cell(p_coords, TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE));
+ }
+ }
+
+ return around;
+}
+
+Vector2i TileSet::map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern) const {
ERR_FAIL_COND_V(p_pattern.is_null(), Vector2i());
ERR_FAIL_COND_V(!p_pattern->has_cell(p_coords_in_pattern), Vector2i());
@@ -2189,6 +2222,49 @@ Vector2i TileSet::map_pattern(const Vector2i &p_position_in_tilemap, const Vecto
return output;
}
+void TileSet::draw_cells_outline(CanvasItem *p_canvas_item, const RBSet<Vector2i> &p_cells, Color p_color, Transform2D p_transform) const {
+ Vector<Vector2> polygon = get_tile_shape_polygon();
+ for (const Vector2i &E : p_cells) {
+ Vector2 center = map_to_local(E);
+
+#define DRAW_SIDE_IF_NEEDED(side, polygon_index_from, polygon_index_to) \
+ if (!p_cells.has(get_neighbor_cell(E, side))) { \
+ Vector2 from = p_transform.xform(center + polygon[polygon_index_from] * tile_size); \
+ Vector2 to = p_transform.xform(center + polygon[polygon_index_to] * tile_size); \
+ p_canvas_item->draw_line(from, to, p_color); \
+ }
+
+ if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_RIGHT_SIDE, 1, 2);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, 2, 3);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_LEFT_SIDE, 3, 0);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_SIDE, 0, 1);
+ } else if (tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) {
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 2, 3);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 1, 2);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 3, 0);
+ } else {
+ if (tile_offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 2, 3);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_LEFT_SIDE, 1, 2);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 5, 0);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_RIGHT_SIDE, 4, 5);
+ } else {
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE, 3, 4);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE, 4, 5);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE, 5, 0);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE, 0, 1);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_SIDE, 1, 2);
+ DRAW_SIDE_IF_NEEDED(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE, 2, 3);
+ }
+ }
+ }
+#undef DRAW_SIDE_IF_NEEDED
+}
+
Vector<Point2> TileSet::get_terrain_polygon(int p_terrain_set) {
if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
return _get_square_terrain_polygon(tile_size);
@@ -3185,6 +3261,115 @@ void TileSet::reset_state() {
tile_size = Size2i(16, 16);
}
+Vector2i TileSet::transform_coords_layout(const Vector2i &p_coords, TileSet::TileOffsetAxis p_offset_axis, TileSet::TileLayout p_from_layout, TileSet::TileLayout p_to_layout) {
+ // Transform to stacked layout.
+ Vector2i output = p_coords;
+ if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
+ SWAP(output.x, output.y);
+ }
+ switch (p_from_layout) {
+ case TileSet::TILE_LAYOUT_STACKED:
+ break;
+ case TileSet::TILE_LAYOUT_STACKED_OFFSET:
+ if (output.y % 2) {
+ output.x -= 1;
+ }
+ break;
+ case TileSet::TILE_LAYOUT_STAIRS_RIGHT:
+ case TileSet::TILE_LAYOUT_STAIRS_DOWN:
+ if ((p_from_layout == TileSet::TILE_LAYOUT_STAIRS_RIGHT) ^ (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL)) {
+ if (output.y < 0 && bool(output.y % 2)) {
+ output = Vector2i(output.x + output.y / 2 - 1, output.y);
+ } else {
+ output = Vector2i(output.x + output.y / 2, output.y);
+ }
+ } else {
+ if (output.x < 0 && bool(output.x % 2)) {
+ output = Vector2i(output.x / 2 - 1, output.x + output.y * 2);
+ } else {
+ output = Vector2i(output.x / 2, output.x + output.y * 2);
+ }
+ }
+ break;
+ case TileSet::TILE_LAYOUT_DIAMOND_RIGHT:
+ case TileSet::TILE_LAYOUT_DIAMOND_DOWN:
+ if ((p_from_layout == TileSet::TILE_LAYOUT_DIAMOND_RIGHT) ^ (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL)) {
+ if ((output.x + output.y) < 0 && (output.x - output.y) % 2) {
+ output = Vector2i((output.x + output.y) / 2 - 1, output.y - output.x);
+ } else {
+ output = Vector2i((output.x + output.y) / 2, -output.x + output.y);
+ }
+ } else {
+ if ((output.x - output.y) < 0 && (output.x + output.y) % 2) {
+ output = Vector2i((output.x - output.y) / 2 - 1, output.x + output.y);
+ } else {
+ output = Vector2i((output.x - output.y) / 2, output.x + output.y);
+ }
+ }
+ break;
+ }
+
+ switch (p_to_layout) {
+ case TileSet::TILE_LAYOUT_STACKED:
+ break;
+ case TileSet::TILE_LAYOUT_STACKED_OFFSET:
+ if (output.y % 2) {
+ output.x += 1;
+ }
+ break;
+ case TileSet::TILE_LAYOUT_STAIRS_RIGHT:
+ case TileSet::TILE_LAYOUT_STAIRS_DOWN:
+ if ((p_to_layout == TileSet::TILE_LAYOUT_STAIRS_RIGHT) ^ (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL)) {
+ if (output.y < 0 && (output.y % 2)) {
+ output = Vector2i(output.x - output.y / 2 + 1, output.y);
+ } else {
+ output = Vector2i(output.x - output.y / 2, output.y);
+ }
+ } else {
+ if (output.y % 2) {
+ if (output.y < 0) {
+ output = Vector2i(2 * output.x + 1, -output.x + output.y / 2 - 1);
+ } else {
+ output = Vector2i(2 * output.x + 1, -output.x + output.y / 2);
+ }
+ } else {
+ output = Vector2i(2 * output.x, -output.x + output.y / 2);
+ }
+ }
+ break;
+ case TileSet::TILE_LAYOUT_DIAMOND_RIGHT:
+ case TileSet::TILE_LAYOUT_DIAMOND_DOWN:
+ if ((p_to_layout == TileSet::TILE_LAYOUT_DIAMOND_RIGHT) ^ (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL)) {
+ if (output.y % 2) {
+ if (output.y > 0) {
+ output = Vector2i(output.x - output.y / 2, output.x + output.y / 2 + 1);
+ } else {
+ output = Vector2i(output.x - output.y / 2 + 1, output.x + output.y / 2);
+ }
+ } else {
+ output = Vector2i(output.x - output.y / 2, output.x + output.y / 2);
+ }
+ } else {
+ if (output.y % 2) {
+ if (output.y < 0) {
+ output = Vector2i(output.x + output.y / 2, -output.x + output.y / 2 - 1);
+ } else {
+ output = Vector2i(output.x + output.y / 2 + 1, -output.x + output.y / 2);
+ }
+ } else {
+ output = Vector2i(output.x + output.y / 2, -output.x + output.y / 2);
+ }
+ }
+ break;
+ }
+
+ if (p_offset_axis == TileSet::TILE_OFFSET_AXIS_VERTICAL) {
+ SWAP(output.x, output.y);
+ }
+
+ return output;
+}
+
const Vector2i TileSetSource::INVALID_ATLAS_COORDS = Vector2i(-1, -1);
const int TileSetSource::INVALID_TILE_ALTERNATIVE = -1;
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index 0a6d879047..f26ed461c3 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -319,7 +319,7 @@ private:
Ref<ArrayMesh> tile_lines_mesh;
Ref<ArrayMesh> tile_filled_mesh;
- bool tile_meshes_dirty = true;
+ mutable bool tile_meshes_dirty = true;
// Physics
struct PhysicsLayer {
@@ -527,15 +527,17 @@ public:
TileMapCell get_random_tile_from_terrains_pattern(int p_terrain_set, TerrainsPattern p_terrain_tile_pattern);
// Helpers
- Vector<Vector2> get_tile_shape_polygon();
- void draw_tile_shape(CanvasItem *p_canvas_item, Transform2D p_transform, Color p_color, bool p_filled = false, Ref<Texture2D> p_texture = Ref<Texture2D>());
+ Vector<Vector2> get_tile_shape_polygon() const;
+ void draw_tile_shape(CanvasItem *p_canvas_item, Transform2D p_transform, Color p_color, bool p_filled = false, Ref<Texture2D> p_texture = Ref<Texture2D>()) const;
// Used by TileMap/TileMapLayer
Vector2 map_to_local(const Vector2i &p_pos) const;
Vector2i local_to_map(const Vector2 &p_pos) const;
bool is_existing_neighbor(TileSet::CellNeighbor p_cell_neighbor) const;
Vector2i get_neighbor_cell(const Vector2i &p_coords, TileSet::CellNeighbor p_cell_neighbor) const;
- Vector2i map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern);
+ TypedArray<Vector2i> get_surrounding_cells(const Vector2i &p_coords) const;
+ Vector2i map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern) const;
+ void draw_cells_outline(CanvasItem *p_canvas_item, const RBSet<Vector2i> &p_cells, Color p_color, Transform2D p_transform = Transform2D()) const;
Vector<Point2> get_terrain_polygon(int p_terrain_set);
Vector<Point2> get_terrain_peering_bit_polygon(int p_terrain_set, TileSet::CellNeighbor p_bit);
@@ -545,6 +547,9 @@ public:
// Resource management
virtual void reset_state() override;
+ // Helpers.
+ static Vector2i transform_coords_layout(const Vector2i &p_coords, TileSet::TileOffsetAxis p_offset_axis, TileSet::TileLayout p_from_layout, TileSet::TileLayout p_to_layout);
+
TileSet();
~TileSet();
};