summaryrefslogtreecommitdiff
path: root/editor/plugins/tiles
diff options
context:
space:
mode:
authorGilles Roudière <gilles.roudiere@gmail.com>2021-07-06 14:43:03 +0200
committerGilles Roudière <gilles.roudiere@gmail.com>2021-07-21 12:36:37 +0200
commit5d34a81e52877034295fc79e4f4b01d0cfa7dfb1 (patch)
treefd6ae48af033bd91e1ed74e9abcd68ea8db39844 /editor/plugins/tiles
parentb2187797dfe5fd35b50506abf5502449e3f990ee (diff)
Implement atlas merging and tile proxies
Diffstat (limited to 'editor/plugins/tiles')
-rw-r--r--editor/plugins/tiles/atlas_merging_dialog.cpp320
-rw-r--r--editor/plugins/tiles/atlas_merging_dialog.h86
-rw-r--r--editor/plugins/tiles/tile_atlas_view.h2
-rw-r--r--editor/plugins/tiles/tile_map_editor.cpp202
-rw-r--r--editor/plugins/tiles/tile_map_editor.h10
-rw-r--r--editor/plugins/tiles/tile_proxies_manager_dialog.cpp476
-rw-r--r--editor/plugins/tiles/tile_proxies_manager_dialog.h90
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.cpp2
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.h4
-rw-r--r--editor/plugins/tiles/tile_set_editor.cpp83
-rw-r--r--editor/plugins/tiles/tile_set_editor.h13
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.cpp4
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.h4
13 files changed, 1176 insertions, 120 deletions
diff --git a/editor/plugins/tiles/atlas_merging_dialog.cpp b/editor/plugins/tiles/atlas_merging_dialog.cpp
new file mode 100644
index 0000000000..bbafc7802b
--- /dev/null
+++ b/editor/plugins/tiles/atlas_merging_dialog.cpp
@@ -0,0 +1,320 @@
+/*************************************************************************/
+/* atlas_merging_dialog.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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 "atlas_merging_dialog.h"
+
+#include "editor/editor_scale.h"
+
+#include "scene/gui/control.h"
+#include "scene/gui/split_container.h"
+
+void AtlasMergingDialog::_property_changed(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing) {
+ _set(p_property, p_value);
+}
+
+void AtlasMergingDialog::_generate_merged(Vector<Ref<TileSetAtlasSource>> p_atlas_sources, int p_max_columns) {
+ merged.instantiate();
+ merged_mapping.clear();
+
+ if (p_atlas_sources.size() >= 2) {
+ Ref<Image> output_image;
+ output_image.instantiate();
+ output_image->create(1, 1, false, Image::FORMAT_RGBA8);
+
+ // Compute the new texture region size.
+ Vector2i new_texture_region_size;
+ for (int source_index = 0; source_index < p_atlas_sources.size(); source_index++) {
+ Ref<TileSetAtlasSource> atlas_source = p_atlas_sources[source_index];
+ new_texture_region_size = new_texture_region_size.max(atlas_source->get_texture_region_size());
+ }
+
+ // Generate the merged TileSetAtlasSource.
+ Vector2i atlas_offset;
+ int line_height = 0;
+ for (int source_index = 0; source_index < p_atlas_sources.size(); source_index++) {
+ Ref<TileSetAtlasSource> atlas_source = p_atlas_sources[source_index];
+ merged_mapping.push_back(Map<Vector2i, Vector2i>());
+
+ // Layout the tiles.
+ Vector2i atlas_size;
+
+ for (int tile_index = 0; tile_index < atlas_source->get_tiles_count(); tile_index++) {
+ Vector2i tile_id = atlas_source->get_tile_id(tile_index);
+ atlas_size = atlas_size.max(tile_id + atlas_source->get_tile_size_in_atlas(tile_id));
+
+ Rect2i new_tile_rect_in_altas = Rect2i(atlas_offset + tile_id, atlas_source->get_tile_size_in_atlas(tile_id));
+
+ // Create tiles and alternatives, then copy their properties.
+ for (int alternative_index = 0; alternative_index < atlas_source->get_alternative_tiles_count(tile_id); alternative_index++) {
+ int alternative_id = atlas_source->get_alternative_tile_id(tile_id, alternative_index);
+ if (alternative_id == 0) {
+ merged->create_tile(new_tile_rect_in_altas.position, new_tile_rect_in_altas.size);
+ } else {
+ merged->create_alternative_tile(new_tile_rect_in_altas.position, alternative_index);
+ }
+
+ // Copy the properties.
+ TileData *original_tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(tile_id, alternative_id));
+ List<PropertyInfo> properties;
+ original_tile_data->get_property_list(&properties);
+ for (List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
+ const StringName &property_name = E->get().name;
+ merged->set(property_name, original_tile_data->get(property_name));
+ }
+
+ // Add to the mapping.
+ merged_mapping[source_index][tile_id] = new_tile_rect_in_altas.position;
+ }
+
+ // Copy the texture.
+ Rect2i src_rect = atlas_source->get_tile_texture_region(tile_id);
+ Rect2 dst_rect_wide = Rect2i(new_tile_rect_in_altas.position * new_texture_region_size, new_tile_rect_in_altas.size * new_texture_region_size);
+ if (dst_rect_wide.get_end().x > output_image->get_width() || dst_rect_wide.get_end().y > output_image->get_height()) {
+ output_image->crop(MAX(dst_rect_wide.get_end().x, output_image->get_width()), MAX(dst_rect_wide.get_end().y, output_image->get_height()));
+ }
+ output_image->blit_rect(atlas_source->get_texture()->get_image(), src_rect, (dst_rect_wide.get_position() + dst_rect_wide.get_end()) / 2 - src_rect.size / 2);
+ }
+
+ // Compute the atlas offset.
+ line_height = MAX(atlas_size.y, line_height);
+ atlas_offset.x += atlas_size.x;
+ if (atlas_offset.x >= p_max_columns) {
+ atlas_offset.x = 0;
+ atlas_offset.y += line_height;
+ line_height = 0;
+ }
+ }
+
+ Ref<ImageTexture> output_image_texture;
+ output_image_texture.instantiate();
+ output_image_texture->create_from_image(output_image);
+
+ merged->set_texture(output_image_texture);
+ merged->set_texture_region_size(new_texture_region_size);
+ }
+}
+
+void AtlasMergingDialog::_update_texture() {
+ Vector<int> selected = atlas_merging_atlases_list->get_selected_items();
+ if (selected.size() >= 2) {
+ Vector<Ref<TileSetAtlasSource>> to_merge;
+ for (int i = 0; i < selected.size(); i++) {
+ int source_id = atlas_merging_atlases_list->get_item_metadata(selected[i]);
+ to_merge.push_back(tile_set->get_source(source_id));
+ }
+ _generate_merged(to_merge, next_line_after_column);
+ preview->set_texture(merged->get_texture());
+ preview->show();
+ select_2_atlases_label->hide();
+ get_ok_button()->set_disabled(false);
+ merge_button->set_disabled(false);
+ } else {
+ _generate_merged(Vector<Ref<TileSetAtlasSource>>(), next_line_after_column);
+ preview->set_texture(Ref<Texture2D>());
+ preview->hide();
+ select_2_atlases_label->show();
+ get_ok_button()->set_disabled(true);
+ merge_button->set_disabled(true);
+ }
+}
+
+void AtlasMergingDialog::_merge_confirmed(String p_path) {
+ ERR_FAIL_COND(!merged.is_valid());
+
+ Ref<ImageTexture> output_image_texture = merged->get_texture();
+ output_image_texture->get_image()->save_png(p_path);
+
+ Ref<Texture2D> new_texture_resource = ResourceLoader::load(p_path, "Texture2D");
+ merged->set_texture(new_texture_resource);
+
+ undo_redo->create_action("Merge TileSetAtlasSource");
+ int next_id = tile_set->get_next_source_id();
+ undo_redo->add_do_method(*tile_set, "add_source", merged, next_id);
+ undo_redo->add_undo_method(*tile_set, "remove_source", next_id);
+
+ if (delete_original_atlases) {
+ // Delete originals if needed.
+ Vector<int> selected = atlas_merging_atlases_list->get_selected_items();
+ for (int i = 0; i < selected.size(); i++) {
+ int source_id = atlas_merging_atlases_list->get_item_metadata(selected[i]);
+ Ref<TileSetAtlasSource> tas = tile_set->get_source(source_id);
+ undo_redo->add_do_method(*tile_set, "remove_source", source_id);
+ undo_redo->add_undo_method(*tile_set, "add_source", tas, source_id);
+
+ // Add the tile proxies.
+ for (int tile_index = 0; tile_index < tas->get_tiles_count(); tile_index++) {
+ Vector2i tile_id = tas->get_tile_id(tile_index);
+ undo_redo->add_do_method(*tile_set, "set_coords_level_tile_proxy", source_id, tile_id, next_id, merged_mapping[i][tile_id]);
+ if (tile_set->has_coords_level_tile_proxy(source_id, tile_id)) {
+ Array a = tile_set->get_coords_level_tile_proxy(source_id, tile_id);
+ undo_redo->add_undo_method(*tile_set, "set_coords_level_tile_proxy", a[0], a[1]);
+ } else {
+ undo_redo->add_undo_method(*tile_set, "remove_coords_level_tile_proxy", source_id, tile_id);
+ }
+ }
+ }
+ }
+ undo_redo->commit_action();
+ commited_actions_count++;
+
+ hide();
+}
+
+void AtlasMergingDialog::ok_pressed() {
+ delete_original_atlases = false;
+ editor_file_dialog->popup_file_dialog();
+}
+
+void AtlasMergingDialog::cancel_pressed() {
+ for (int i = 0; i < commited_actions_count; i++) {
+ undo_redo->undo();
+ }
+ commited_actions_count = 0;
+}
+
+void AtlasMergingDialog::custom_action(const String &p_action) {
+ if (p_action == "merge") {
+ delete_original_atlases = true;
+ editor_file_dialog->popup_file_dialog();
+ }
+}
+
+bool AtlasMergingDialog::_set(const StringName &p_name, const Variant &p_value) {
+ if (p_name == "next_line_after_column" && p_value.get_type() == Variant::INT) {
+ next_line_after_column = p_value;
+ _update_texture();
+ return true;
+ }
+ return false;
+}
+
+bool AtlasMergingDialog::_get(const StringName &p_name, Variant &r_ret) const {
+ if (p_name == "next_line_after_column") {
+ r_ret = next_line_after_column;
+ return true;
+ }
+ return false;
+}
+
+void AtlasMergingDialog::update_tile_set(Ref<TileSet> p_tile_set) {
+ ERR_FAIL_COND(!p_tile_set.is_valid());
+ tile_set = p_tile_set;
+
+ atlas_merging_atlases_list->clear();
+ for (int i = 0; i < p_tile_set->get_source_count(); i++) {
+ int source_id = p_tile_set->get_source_id(i);
+ Ref<TileSetAtlasSource> atlas_source = p_tile_set->get_source(source_id);
+ if (atlas_source.is_valid()) {
+ Ref<Texture2D> texture = atlas_source->get_texture();
+ if (texture.is_valid()) {
+ String item_text = vformat("%s (id:%d)", texture->get_path().get_file(), source_id);
+ atlas_merging_atlases_list->add_item(item_text, texture);
+ atlas_merging_atlases_list->set_item_metadata(atlas_merging_atlases_list->get_item_count() - 1, source_id);
+ }
+ }
+ }
+
+ get_ok_button()->set_disabled(true);
+ merge_button->set_disabled(true);
+
+ commited_actions_count = 0;
+}
+
+AtlasMergingDialog::AtlasMergingDialog() {
+ // Atlas merging window.
+ set_title(TTR("Atlas Merging"));
+ set_hide_on_ok(false);
+
+ // Ok buttons
+ get_ok_button()->set_text(TTR("Merge (Keep original Atlases)"));
+ get_ok_button()->set_disabled(true);
+ merge_button = add_button(TTR("Merge"), true, "merge");
+ merge_button->set_disabled(true);
+
+ HSplitContainer *atlas_merging_h_split_container = memnew(HSplitContainer);
+ atlas_merging_h_split_container->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ atlas_merging_h_split_container->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ add_child(atlas_merging_h_split_container);
+
+ // Atlas sources item list.
+ atlas_merging_atlases_list = memnew(ItemList);
+ atlas_merging_atlases_list->set_fixed_icon_size(Size2i(60, 60) * EDSCALE);
+ atlas_merging_atlases_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ atlas_merging_atlases_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ atlas_merging_atlases_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
+ atlas_merging_atlases_list->set_custom_minimum_size(Size2(100, 200));
+ atlas_merging_atlases_list->set_select_mode(ItemList::SELECT_MULTI);
+ atlas_merging_atlases_list->connect("multi_selected", callable_mp(this, &AtlasMergingDialog::_update_texture).unbind(2));
+ atlas_merging_h_split_container->add_child(atlas_merging_atlases_list);
+
+ VBoxContainer *atlas_merging_right_panel = memnew(VBoxContainer);
+ atlas_merging_right_panel->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ atlas_merging_h_split_container->add_child(atlas_merging_right_panel);
+
+ // Settings.
+ Label *settings_label = memnew(Label);
+ settings_label->set_text(TTR("Settings:"));
+ atlas_merging_right_panel->add_child(settings_label);
+
+ columns_editor_property = memnew(EditorPropertyInteger);
+ columns_editor_property->set_label(TTR("Next Line After Column"));
+ columns_editor_property->set_object_and_property(this, "next_line_after_column");
+ columns_editor_property->update_property();
+ columns_editor_property->connect("property_changed", callable_mp(this, &AtlasMergingDialog::_property_changed));
+ atlas_merging_right_panel->add_child(columns_editor_property);
+
+ // Preview.
+ Label *preview_label = memnew(Label);
+ preview_label->set_text(TTR("Preview:"));
+ atlas_merging_right_panel->add_child(preview_label);
+
+ preview = memnew(TextureRect);
+ preview->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ preview->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ preview->set_expand(true);
+ preview->hide();
+ preview->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED);
+ atlas_merging_right_panel->add_child(preview);
+
+ select_2_atlases_label = memnew(Label);
+ select_2_atlases_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ select_2_atlases_label->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ select_2_atlases_label->set_align(Label::ALIGN_CENTER);
+ select_2_atlases_label->set_valign(Label::VALIGN_CENTER);
+ select_2_atlases_label->set_text(TTR("Please select two atlases or more."));
+ atlas_merging_right_panel->add_child(select_2_atlases_label);
+
+ // The file dialog to choose the texture path.
+ editor_file_dialog = memnew(EditorFileDialog);
+ editor_file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
+ editor_file_dialog->add_filter("*.png");
+ editor_file_dialog->connect("file_selected", callable_mp(this, &AtlasMergingDialog::_merge_confirmed));
+ add_child(editor_file_dialog);
+}
diff --git a/editor/plugins/tiles/atlas_merging_dialog.h b/editor/plugins/tiles/atlas_merging_dialog.h
new file mode 100644
index 0000000000..7cb54bc17e
--- /dev/null
+++ b/editor/plugins/tiles/atlas_merging_dialog.h
@@ -0,0 +1,86 @@
+/*************************************************************************/
+/* atlas_merging_dialog.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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 ATLAS_MERGING_DIALOG_H
+#define ATLAS_MERGING_DIALOG_H
+
+#include "editor/editor_node.h"
+#include "editor/editor_properties.h"
+
+#include "scene/gui/dialogs.h"
+#include "scene/gui/item_list.h"
+#include "scene/gui/texture_rect.h"
+#include "scene/resources/tile_set.h"
+
+class AtlasMergingDialog : public ConfirmationDialog {
+ GDCLASS(AtlasMergingDialog, ConfirmationDialog);
+
+private:
+ int commited_actions_count = 0;
+ bool delete_original_atlases = true;
+ Ref<TileSetAtlasSource> merged;
+ LocalVector<Map<Vector2i, Vector2i>> merged_mapping;
+ Ref<TileSet> tile_set;
+
+ UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+
+ // Settings.
+ int next_line_after_column = 30;
+
+ // GUI.
+ ItemList *atlas_merging_atlases_list;
+ EditorPropertyVector2i *texture_region_size_editor_property;
+ EditorPropertyInteger *columns_editor_property;
+ TextureRect *preview;
+ Label *select_2_atlases_label;
+ EditorFileDialog *editor_file_dialog;
+ Button *merge_button;
+
+ void _property_changed(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing);
+
+ void _generate_merged(Vector<Ref<TileSetAtlasSource>> p_atlas_sources, int p_max_columns);
+ void _update_texture();
+ void _merge_confirmed(String p_path);
+
+protected:
+ virtual void ok_pressed() override;
+ virtual void cancel_pressed() override;
+ virtual void custom_action(const String &) override;
+
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+
+public:
+ void update_tile_set(Ref<TileSet> p_tile_set);
+
+ AtlasMergingDialog();
+};
+
+#endif // ATLAS_MERGING_DIALOG_H
diff --git a/editor/plugins/tiles/tile_atlas_view.h b/editor/plugins/tiles/tile_atlas_view.h
index bafc2b3985..b2046f4322 100644
--- a/editor/plugins/tiles/tile_atlas_view.h
+++ b/editor/plugins/tiles/tile_atlas_view.h
@@ -47,7 +47,7 @@ class TileAtlasView : public Control {
private:
TileSet *tile_set;
TileSetAtlasSource *tile_set_atlas_source;
- int source_id = -1;
+ int source_id = TileSet::INVALID_SOURCE;
enum DragType {
DRAG_TYPE_NONE,
diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp
index 6e3c55d801..44822bec3a 100644
--- a/editor/plugins/tiles/tile_map_editor.cpp
+++ b/editor/plugins/tiles/tile_map_editor.cpp
@@ -56,18 +56,11 @@ void TileMapEditorTilesPlugin::_notification(int p_what) {
picker_button->set_icon(get_theme_icon(SNAME("ColorPick"), SNAME("EditorIcons")));
erase_button->set_icon(get_theme_icon(SNAME("Eraser"), SNAME("EditorIcons")));
- toggle_grid_button->set_icon(get_theme_icon(SNAME("Grid"), SNAME("EditorIcons")));
-
missing_atlas_texture_icon = get_theme_icon(SNAME("TileSet"), SNAME("EditorIcons"));
-
- toggle_grid_button->set_pressed(EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid"));
break;
case NOTIFICATION_VISIBILITY_CHANGED:
_stop_dragging();
break;
- case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED:
- toggle_grid_button->set_pressed(EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid"));
- break;
}
}
@@ -85,10 +78,6 @@ void TileMapEditorTilesPlugin::_on_scattering_spinbox_changed(double p_value) {
scattering = p_value;
}
-void TileMapEditorTilesPlugin::_on_grid_toggled(bool p_pressed) {
- EditorSettings::get_singleton()->set("editors/tiles_editor/display_grid", p_pressed);
-}
-
void TileMapEditorTilesPlugin::_update_toolbar() {
// Stop draggig if needed.
_stop_dragging();
@@ -204,7 +193,7 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() {
}
// Synchronize
- TilesEditor::get_singleton()->set_atlas_sources_lists_current(sources_list->get_current());
+ TilesEditor::get_singleton()->set_sources_lists_current(sources_list->get_current());
}
void TileMapEditorTilesPlugin::_update_bottom_panel() {
@@ -410,7 +399,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
if (!tile_map_selection.is_empty()) {
undo_redo->create_action(TTR("Delete tiles"));
for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) {
- undo_redo->add_do_method(tile_map, "set_cell", E->get(), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
+ undo_redo->add_do_method(tile_map, "set_cell", E->get(), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
undo_redo->add_undo_method(tile_map, "set_cell", E->get(), tile_map->get_cell_source_id(E->get()), tile_map->get_cell_atlas_coords(E->get()), tile_map->get_cell_alternative_tile(E->get()));
}
undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection());
@@ -441,7 +430,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
if (!tile_map_selection.is_empty()) {
undo_redo->create_action(TTR("Delete tiles"));
for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) {
- undo_redo->add_do_method(tile_map, "set_cell", E->get(), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
+ undo_redo->add_do_method(tile_map, "set_cell", E->get(), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
undo_redo->add_undo_method(tile_map, "set_cell", E->get(), tile_map->get_cell_source_id(E->get()), tile_map->get_cell_atlas_coords(E->get()), tile_map->get_cell_alternative_tile(E->get()));
}
undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection());
@@ -462,12 +451,12 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
case DRAG_TYPE_PAINT: {
Map<Vector2i, TileMapCell> to_draw = _draw_line(drag_start_mouse_pos, drag_last_mouse_pos, mpos);
for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) {
- if (!erase_button->is_pressed() && E->get().source_id == -1) {
+ if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) {
continue;
}
Vector2i coords = E->key();
if (!drag_modified.has(coords)) {
- drag_modified.insert(coords, TileMapCell(tile_map->get_cell_source_id(coords), tile_map->get_cell_atlas_coords(coords), tile_map->get_cell_alternative_tile(coords)));
+ drag_modified.insert(coords, tile_map->get_cell(coords));
}
tile_map->set_cell(coords, E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
}
@@ -478,12 +467,12 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
if (!drag_modified.has(line[i])) {
Map<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_continuous_checkbox->is_pressed());
for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) {
- if (!erase_button->is_pressed() && E->get().source_id == -1) {
+ if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) {
continue;
}
Vector2i coords = E->key();
if (!drag_modified.has(coords)) {
- drag_modified.insert(coords, TileMapCell(tile_map->get_cell_source_id(coords), tile_map->get_cell_atlas_coords(coords), tile_map->get_cell_alternative_tile(coords)));
+ drag_modified.insert(coords, tile_map->get_cell(coords));
}
tile_map->set_cell(coords, E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
}
@@ -516,8 +505,8 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
drag_modified.clear();
for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) {
Vector2i coords = E->get();
- drag_modified.insert(coords, TileMapCell(tile_map->get_cell_source_id(coords), tile_map->get_cell_atlas_coords(coords), tile_map->get_cell_alternative_tile(coords)));
- tile_map->set_cell(coords, -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
+ drag_modified.insert(coords, tile_map->get_cell(coords));
+ tile_map->set_cell(coords, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
}
} else {
// Select tiles
@@ -536,12 +525,12 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
drag_modified.clear();
Map<Vector2i, TileMapCell> to_draw = _draw_line(drag_start_mouse_pos, mpos, mpos);
for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) {
- if (!erase_button->is_pressed() && E->get().source_id == -1) {
+ if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) {
continue;
}
Vector2i coords = E->key();
if (!drag_modified.has(coords)) {
- drag_modified.insert(coords, TileMapCell(tile_map->get_cell_source_id(coords), tile_map->get_cell_atlas_coords(coords), tile_map->get_cell_alternative_tile(coords)));
+ drag_modified.insert(coords, tile_map->get_cell(coords));
}
tile_map->set_cell(coords, E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
}
@@ -562,12 +551,12 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
if (!drag_modified.has(line[i])) {
Map<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_continuous_checkbox->is_pressed());
for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) {
- if (!erase_button->is_pressed() && E->get().source_id == -1) {
+ if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) {
continue;
}
Vector2i coords = E->key();
if (!drag_modified.has(coords)) {
- drag_modified.insert(coords, TileMapCell(tile_map->get_cell_source_id(coords), tile_map->get_cell_atlas_coords(coords), tile_map->get_cell_alternative_tile(coords)));
+ drag_modified.insert(coords, tile_map->get_cell(coords));
}
tile_map->set_cell(coords, E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
}
@@ -634,7 +623,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
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(coords) != -1) {
+ if (tile_map->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
Rect2 cell_region = xform.xform(Rect2(tile_map->map_to_world(coords) - tile_shape_size / 2, tile_shape_size));
tile_set->draw_tile_shape(p_overlay, cell_region, Color(1.0, 1.0, 1.0), false);
}
@@ -648,7 +637,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
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(coords) != -1) {
+ if (tile_map->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
to_draw.insert(coords);
}
}
@@ -871,7 +860,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_start_
// Get or create the pattern.
TileMapPattern erase_pattern;
- erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
+ erase_pattern.set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
TileMapPattern *pattern = erase_button->is_pressed() ? &erase_pattern : selection_pattern;
Map<Vector2i, TileMapCell> output;
@@ -923,7 +912,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_rect(Vector2i p_start
// Get or create the pattern.
TileMapPattern erase_pattern;
- erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
+ erase_pattern.set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
TileMapPattern *pattern = erase_button->is_pressed() ? &erase_pattern : selection_pattern;
// Compute the offset to align things to the bottom or right.
@@ -974,7 +963,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i
// Get or create the pattern.
TileMapPattern erase_pattern;
- erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
+ erase_pattern.set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
TileMapPattern *pattern = erase_button->is_pressed() ? &erase_pattern : selection_pattern;
Map<Vector2i, TileMapCell> output;
@@ -983,7 +972,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i
// If we are filling empty tiles, compute the tilemap boundaries.
Rect2i boundaries;
- if (source.source_id == -1) {
+ if (source.source_id == TileSet::INVALID_SOURCE) {
boundaries = tile_map->get_used_rect();
}
@@ -999,7 +988,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i
if (source.source_id == tile_map->get_cell_source_id(coords) &&
source.get_atlas_coords() == tile_map->get_cell_atlas_coords(coords) &&
source.alternative_tile == tile_map->get_cell_alternative_tile(coords) &&
- (source.source_id != -1 || boundaries.has_point(coords))) {
+ (source.source_id != TileSet::INVALID_SOURCE || boundaries.has_point(coords))) {
if (!erase_button->is_pressed() && random_tile_checkbox->is_pressed()) {
// Paint a random tile.
output.insert(coords, _pick_random_tile(pattern));
@@ -1027,7 +1016,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i
} else {
// Replace all tiles like the source.
TypedArray<Vector2i> to_check;
- if (source.source_id == -1) {
+ if (source.source_id == TileSet::INVALID_SOURCE) {
Rect2i rect = tile_map->get_used_rect();
if (rect.size.x <= 0 || rect.size.y <= 0) {
rect = Rect2i(p_coords, Vector2i(1, 1));
@@ -1045,7 +1034,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i
if (source.source_id == tile_map->get_cell_source_id(coords) &&
source.get_atlas_coords() == tile_map->get_cell_atlas_coords(coords) &&
source.alternative_tile == tile_map->get_cell_alternative_tile(coords) &&
- (source.source_id != -1 || boundaries.has_point(coords))) {
+ (source.source_id != TileSet::INVALID_SOURCE || boundaries.has_point(coords))) {
if (!erase_button->is_pressed() && random_tile_checkbox->is_pressed()) {
// Paint a random tile.
output.insert(coords, _pick_random_tile(pattern));
@@ -1102,7 +1091,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
tile_map_selection.erase(coords);
}
} else {
- if (tile_map->get_cell_source_id(coords) != -1) {
+ if (tile_map->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
tile_map_selection.insert(coords);
}
}
@@ -1173,7 +1162,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
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(coords) != -1) {
+ if (tile_map->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
coords_array.push_back(coords);
}
}
@@ -1198,7 +1187,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
Map<Vector2i, TileMapCell> to_draw = _draw_line(drag_start_mouse_pos, drag_start_mouse_pos, mpos);
undo_redo->create_action(TTR("Paint tiles"));
for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) {
- if (!erase_button->is_pressed() && E->get().source_id == -1) {
+ if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) {
continue;
}
undo_redo->add_do_method(tile_map, "set_cell", E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
@@ -1210,7 +1199,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
Map<Vector2i, TileMapCell> to_draw = _draw_rect(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos));
undo_redo->create_action(TTR("Paint tiles"));
for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) {
- if (!erase_button->is_pressed() && E->get().source_id == -1) {
+ if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) {
continue;
}
undo_redo->add_do_method(tile_map, "set_cell", E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
@@ -1221,7 +1210,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
case DRAG_TYPE_BUCKET: {
undo_redo->create_action(TTR("Paint tiles"));
for (Map<Vector2i, TileMapCell>::Element *E = drag_modified.front(); E; E = E->next()) {
- if (!erase_button->is_pressed() && E->get().source_id == -1) {
+ if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) {
continue;
}
undo_redo->add_do_method(tile_map, "set_cell", E->key(), tile_map->get_cell_source_id(E->key()), tile_map->get_cell_atlas_coords(E->key()), tile_map->get_cell_alternative_tile(E->key()));
@@ -1249,7 +1238,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() {
TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
if (!tile_map) {
- hovered_tile.source_id = -1;
+ 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_set_selection.clear();
@@ -1260,7 +1249,7 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() {
Ref<TileSet> tile_set = tile_map->get_tileset();
if (!tile_set.is_valid()) {
- hovered_tile.source_id = -1;
+ 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_set_selection.clear();
@@ -1271,7 +1260,7 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() {
int source_index = sources_list->get_current();
if (source_index < 0 || source_index >= sources_list->get_item_count()) {
- hovered_tile.source_id = -1;
+ 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_set_selection.clear();
@@ -1287,7 +1276,7 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() {
!tile_set->has_source(hovered_tile.source_id) ||
!tile_set->get_source(hovered_tile.source_id)->has_tile(hovered_tile.get_atlas_coords()) ||
!tile_set->get_source(hovered_tile.source_id)->has_alternative_tile(hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile)) {
- hovered_tile.source_id = -1;
+ hovered_tile.source_id = TileSet::INVALID_SOURCE;
hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
}
@@ -1403,7 +1392,7 @@ void TileMapEditorTilesPlugin::_update_tileset_selection_from_selection_pattern(
TypedArray<Vector2i> used_cells = selection_pattern->get_used_cells();
for (int i = 0; i < used_cells.size(); i++) {
Vector2i coords = used_cells[i];
- if (selection_pattern->get_cell_source_id(coords) != -1) {
+ if (selection_pattern->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
tile_set_selection.insert(TileMapCell(selection_pattern->get_cell_source_id(coords), selection_pattern->get_cell_atlas_coords(coords), selection_pattern->get_cell_alternative_tile(coords)));
}
}
@@ -1475,7 +1464,7 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() {
}
void TileMapEditorTilesPlugin::_tile_atlas_control_mouse_exited() {
- hovered_tile.source_id = -1;
+ 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_set_dragging_selection = false;
@@ -1634,7 +1623,7 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_draw() {
}
void TileMapEditorTilesPlugin::_tile_alternatives_control_mouse_exited() {
- hovered_tile.source_id = -1;
+ 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_set_dragging_selection = false;
@@ -1856,19 +1845,6 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
_on_random_tile_checkbox_toggled(false);
- // Wide empty separation control.
- Control *h_empty_space = memnew(Control);
- h_empty_space->set_h_size_flags(SIZE_EXPAND_FILL);
- toolbar->add_child(h_empty_space);
-
- // Grid toggle.
- toggle_grid_button = memnew(Button);
- toggle_grid_button->set_flat(true);
- toggle_grid_button->set_toggle_mode(true);
- toggle_grid_button->set_tooltip(TTR("Toggle grid visibility."));
- toggle_grid_button->connect("toggled", callable_mp(this, &TileMapEditorTilesPlugin::_on_grid_toggled));
- toolbar->add_child(toggle_grid_button);
-
// Default tool.
paint_tool_button->set_pressed(true);
_update_toolbar();
@@ -1898,8 +1874,8 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
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_bottom_panel).unbind(1));
- sources_list->connect("item_selected", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_atlas_sources_lists_current));
- sources_list->connect("visibility_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::synchronize_atlas_sources_list), varray(sources_list));
+ sources_list->connect("item_selected", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_sources_lists_current));
+ sources_list->connect("visibility_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::synchronize_sources_list), varray(sources_list));
atlas_sources_split_container->add_child(sources_list);
// Tile atlas source.
@@ -2968,7 +2944,7 @@ void TileMapEditorTerrainsPlugin::_update_terrains_cache() {
}
TileMapCell empty_cell;
- empty_cell.source_id = -1;
+ empty_cell.source_id = TileSet::INVALID_SOURCE;
empty_cell.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
empty_cell.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
per_terrain_terrains_tile_patterns_tiles[i][empty_pattern].insert(empty_cell);
@@ -3190,6 +3166,9 @@ void TileMapEditor::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED:
missing_tile_texture = get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"));
warning_pattern_texture = get_theme_icon(SNAME("WarningPattern"), SNAME("EditorIcons"));
+ advanced_menu_button->set_icon(get_theme_icon(SNAME("Tools"), SNAME("EditorIcons")));
+ toggle_grid_button->set_icon(get_theme_icon(SNAME("Grid"), SNAME("EditorIcons")));
+ toggle_grid_button->set_pressed(EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid"));
break;
case NOTIFICATION_INTERNAL_PROCESS:
if (is_visible_in_tree() && tileset_changed_needs_update) {
@@ -3199,6 +3178,44 @@ void TileMapEditor::_notification(int p_what) {
tileset_changed_needs_update = false;
}
break;
+ case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED:
+ toggle_grid_button->set_pressed(EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid"));
+ break;
+ }
+}
+
+void TileMapEditor::_on_grid_toggled(bool p_pressed) {
+ EditorSettings::get_singleton()->set("editors/tiles_editor/display_grid", 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) {
+ return;
+ }
+
+ Ref<TileSet> tile_set = tile_map->get_tileset();
+ if (!tile_set.is_valid()) {
+ return;
+ }
+
+ if (p_id == 0) { // Replace Tile Proxies
+ undo_redo->create_action(TTR("Replace Tiles with Proxies"));
+ TypedArray<Vector2i> used_cells = tile_map->get_used_cells();
+ for (int i = 0; i < used_cells.size(); i++) {
+ Vector2i cell_coords = used_cells[i];
+ TileMapCell from = tile_map->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(tile_map, "set_cell", cell_coords, to.source_id, to.get_atlas_coords(), to.alternative_tile);
+ undo_redo->add_undo_method(tile_map, "set_cell", cell_coords, from.source_id, from.get_atlas_coords(), from.alternative_tile);
+ }
+ }
+ undo_redo->commit_action();
}
}
@@ -3349,7 +3366,6 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
Vector2i tile_shape_size = tile_set->get_tile_size();
// Draw tiles with invalid IDs in the grid.
- float icon_ratio = MIN(missing_tile_texture->get_size().x / tile_set->get_tile_size().x, missing_tile_texture->get_size().y / tile_set->get_tile_size().y) / 3;
TypedArray<Vector2i> used_cells = tile_map->get_used_cells();
for (int i = 0; i < used_cells.size(); i++) {
Vector2i coords = used_cells[i];
@@ -3365,25 +3381,33 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
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 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.
- Rect2 cell_region = xform.xform(Rect2(tile_map->map_to_world(coords) - Vector2(tile_shape_size) / 2, Vector2(tile_shape_size)));
- tile_set->draw_tile_shape(p_overlay, cell_region, color, true, warning_pattern_texture);
+ 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.
+ Rect2 cell_region = xform.xform(Rect2(tile_map->map_to_world(coords) - Vector2(tile_shape_size) / 2, Vector2(tile_shape_size)));
+ tile_set->draw_tile_shape(p_overlay, cell_region, color, true, warning_pattern_texture);
+ }
// Draw the warning icon.
- Rect2 rect = Rect2(xform.xform(tile_map->map_to_world(coords)) - (icon_ratio * missing_tile_texture->get_size() * xform.get_scale() / 2), icon_ratio * missing_tile_texture->get_size() * xform.get_scale());
+ int min_axis = missing_tile_texture->get_size().min_axis();
+ 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_world(coords)) - (icon_size * xform.get_scale() / 2), icon_size * xform.get_scale());
p_overlay->draw_texture_rect(missing_tile_texture, rect);
}
}
@@ -3503,6 +3527,26 @@ TileMapEditor::TileMapEditor() {
tilemap_toolbar->add_child(tile_map_editor_plugins[i]->get_toolbar());
}
+ // Wide empty separation control.
+ Control *h_empty_space = memnew(Control);
+ h_empty_space->set_h_size_flags(SIZE_EXPAND_FILL);
+ tilemap_toolbar->add_child(h_empty_space);
+
+ // Grid toggle.
+ toggle_grid_button = memnew(Button);
+ toggle_grid_button->set_flat(true);
+ toggle_grid_button->set_toggle_mode(true);
+ toggle_grid_button->set_tooltip(TTR("Toggle grid visibility."));
+ toggle_grid_button->connect("toggled", callable_mp(this, &TileMapEditor::_on_grid_toggled));
+ tilemap_toolbar->add_child(toggle_grid_button);
+
+ // Advanced settings menu button.
+ advanced_menu_button = memnew(MenuButton);
+ advanced_menu_button->set_flat(true);
+ 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));
+ tilemap_toolbar->add_child(advanced_menu_button);
+
missing_tileset_label = memnew(Label);
missing_tileset_label->set_text(TTR("The edited TileMap node has no TileSet resource."));
missing_tileset_label->set_h_size_flags(SIZE_EXPAND_FILL);
diff --git a/editor/plugins/tiles/tile_map_editor.h b/editor/plugins/tiles/tile_map_editor.h
index a6f4ec3021..236774a06b 100644
--- a/editor/plugins/tiles/tile_map_editor.h
+++ b/editor/plugins/tiles/tile_map_editor.h
@@ -82,9 +82,6 @@ private:
void _on_random_tile_checkbox_toggled(bool p_pressed);
void _on_scattering_spinbox_changed(double p_value);
- Button *toggle_grid_button;
- void _on_grid_toggled(bool p_pressed);
-
void _update_toolbar();
///// Tilemap editing. /////
@@ -300,6 +297,7 @@ class TileMapEditor : public VBoxContainer {
GDCLASS(TileMapEditor, VBoxContainer);
private:
+ UndoRedo *undo_redo = EditorNode::get_undo_redo();
bool tileset_changed_needs_update = false;
ObjectID tile_map_id;
@@ -309,6 +307,12 @@ private:
// Toolbar.
HBoxContainer *tilemap_toolbar;
+ Button *toggle_grid_button;
+ void _on_grid_toggled(bool p_pressed);
+
+ MenuButton *advanced_menu_button;
+ void _advanced_menu_button_id_pressed(int p_id);
+
// Bottom panel
Label *missing_tileset_label;
Tabs *tabs;
diff --git a/editor/plugins/tiles/tile_proxies_manager_dialog.cpp b/editor/plugins/tiles/tile_proxies_manager_dialog.cpp
new file mode 100644
index 0000000000..e5e7efa531
--- /dev/null
+++ b/editor/plugins/tiles/tile_proxies_manager_dialog.cpp
@@ -0,0 +1,476 @@
+/*************************************************************************/
+/* tile_proxies_manager_dialog.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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_proxies_manager_dialog.h"
+
+#include "editor/editor_scale.h"
+
+void TileProxiesManagerDialog::_right_clicked(int p_item, Vector2 p_local_mouse_pos, Object *p_item_list) {
+ ItemList *item_list = Object::cast_to<ItemList>(p_item_list);
+ popup_menu->set_size(Vector2(1, 1));
+ popup_menu->set_position(get_position() + item_list->get_global_mouse_position());
+ popup_menu->popup();
+}
+
+void TileProxiesManagerDialog::_menu_id_pressed(int p_id) {
+ if (p_id == 0) {
+ // Delete.
+ _delete_selected_bindings();
+ }
+}
+
+void TileProxiesManagerDialog::_delete_selected_bindings() {
+ undo_redo->create_action("Remove Tile Proxies");
+
+ Vector<int> source_level_selected = source_level_list->get_selected_items();
+ for (int i = 0; i < source_level_selected.size(); i++) {
+ int key = source_level_list->get_item_metadata(source_level_selected[i]);
+ int val = tile_set->get_source_level_tile_proxy(key);
+ undo_redo->add_do_method(*tile_set, "remove_source_level_tile_proxy", key);
+ undo_redo->add_undo_method(*tile_set, "set_source_level_tile_proxy", key, val);
+ }
+
+ Vector<int> coords_level_selected = coords_level_list->get_selected_items();
+ for (int i = 0; i < coords_level_selected.size(); i++) {
+ Array key = coords_level_list->get_item_metadata(coords_level_selected[i]);
+ Array val = tile_set->get_coords_level_tile_proxy(key[0], key[1]);
+ undo_redo->add_do_method(*tile_set, "remove_coords_level_tile_proxy", key[0], key[1]);
+ undo_redo->add_undo_method(*tile_set, "set_coords_level_tile_proxy", key[0], key[1], val[0], val[1]);
+ }
+
+ Vector<int> alternative_level_selected = alternative_level_list->get_selected_items();
+ for (int i = 0; i < alternative_level_selected.size(); i++) {
+ Array key = alternative_level_list->get_item_metadata(alternative_level_selected[i]);
+ Array val = tile_set->get_coords_level_tile_proxy(key[0], key[1]);
+ undo_redo->add_do_method(*tile_set, "remove_alternative_level_tile_proxy", key[0], key[1], key[2]);
+ undo_redo->add_undo_method(*tile_set, "set_alternative_level_tile_proxy", key[0], key[1], key[2], val[0], val[1], val[2]);
+ }
+ undo_redo->add_do_method(this, "_update_lists");
+ undo_redo->add_undo_method(this, "_update_lists");
+ undo_redo->commit_action();
+
+ commited_actions_count += 1;
+}
+
+void TileProxiesManagerDialog::_update_lists() {
+ source_level_list->clear();
+ coords_level_list->clear();
+ alternative_level_list->clear();
+
+ Array proxies = tile_set->get_source_level_tile_proxies();
+ for (int i = 0; i < proxies.size(); i++) {
+ Array proxy = proxies[i];
+ String text = vformat("%s", proxy[0]).rpad(5) + "-> " + vformat("%s", proxy[1]);
+ int id = source_level_list->add_item(text);
+ source_level_list->set_item_metadata(id, proxy[0]);
+ }
+
+ proxies = tile_set->get_coords_level_tile_proxies();
+ for (int i = 0; i < proxies.size(); i++) {
+ Array proxy = proxies[i];
+ String text = vformat("%s, %s", proxy[0], proxy[1]).rpad(17) + "-> " + vformat("%s, %s", proxy[2], proxy[3]);
+ int id = coords_level_list->add_item(text);
+ coords_level_list->set_item_metadata(id, proxy.slice(0, 2));
+ }
+
+ proxies = tile_set->get_alternative_level_tile_proxies();
+ for (int i = 0; i < proxies.size(); i++) {
+ Array proxy = proxies[i];
+ String text = vformat("%s, %s, %s", proxy[0], proxy[1], proxy[2]).rpad(24) + "-> " + vformat("%s, %s, %s", proxy[3], proxy[4], proxy[5]);
+ int id = alternative_level_list->add_item(text);
+ alternative_level_list->set_item_metadata(id, proxy.slice(0, 3));
+ }
+}
+
+void TileProxiesManagerDialog::_update_enabled_property_editors() {
+ if (from.source_id == TileSet::INVALID_SOURCE) {
+ from.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
+ to.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
+ from.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
+ to.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
+ coords_from_property_editor->hide();
+ coords_to_property_editor->hide();
+ alternative_from_property_editor->hide();
+ alternative_to_property_editor->hide();
+ } else if (from.get_atlas_coords().x == -1 || from.get_atlas_coords().y == -1) {
+ from.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
+ to.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
+ coords_from_property_editor->show();
+ coords_to_property_editor->show();
+ alternative_from_property_editor->hide();
+ alternative_to_property_editor->hide();
+ } else {
+ coords_from_property_editor->show();
+ coords_to_property_editor->show();
+ alternative_from_property_editor->show();
+ alternative_to_property_editor->show();
+ }
+
+ source_from_property_editor->update_property();
+ source_to_property_editor->update_property();
+ coords_from_property_editor->update_property();
+ coords_to_property_editor->update_property();
+ alternative_from_property_editor->update_property();
+ alternative_to_property_editor->update_property();
+}
+
+void TileProxiesManagerDialog::_property_changed(const String &p_path, const Variant &p_value, const String &p_name, bool p_changing) {
+ _set(p_path, p_value);
+}
+
+void TileProxiesManagerDialog::_add_button_pressed() {
+ if (from.source_id != TileSet::INVALID_SOURCE && to.source_id != TileSet::INVALID_SOURCE) {
+ Vector2i from_coords = from.get_atlas_coords();
+ Vector2i to_coords = to.get_atlas_coords();
+ if (from_coords.x >= 0 && from_coords.y >= 0 && to_coords.x >= 0 && to_coords.y >= 0) {
+ if (from.alternative_tile != TileSetSource::INVALID_TILE_ALTERNATIVE && to.alternative_tile != TileSetSource::INVALID_TILE_ALTERNATIVE) {
+ undo_redo->create_action("Create Alternative-level Tile Proxy");
+ undo_redo->add_do_method(*tile_set, "set_alternative_level_tile_proxy", from.source_id, from.get_atlas_coords(), from.alternative_tile, to.source_id, to.get_atlas_coords(), to.alternative_tile);
+ if (tile_set->has_alternative_level_tile_proxy(from.source_id, from.get_atlas_coords(), from.alternative_tile)) {
+ Array a = tile_set->get_alternative_level_tile_proxy(from.source_id, from.get_atlas_coords(), from.alternative_tile);
+ undo_redo->add_undo_method(*tile_set, "set_alternative_level_tile_proxy", to.source_id, to.get_atlas_coords(), to.alternative_tile, a[0], a[1], a[2]);
+ } else {
+ undo_redo->add_undo_method(*tile_set, "remove_alternative_level_tile_proxy", from.source_id, from.get_atlas_coords(), from.alternative_tile);
+ }
+ } else {
+ undo_redo->create_action("Create Coords-level Tile Proxy");
+ undo_redo->add_do_method(*tile_set, "set_coords_level_tile_proxy", from.source_id, from.get_atlas_coords(), to.source_id, to.get_atlas_coords());
+ if (tile_set->has_coords_level_tile_proxy(from.source_id, from.get_atlas_coords())) {
+ Array a = tile_set->get_coords_level_tile_proxy(from.source_id, from.get_atlas_coords());
+ undo_redo->add_undo_method(*tile_set, "set_coords_level_tile_proxy", to.source_id, to.get_atlas_coords(), a[0], a[1]);
+ } else {
+ undo_redo->add_undo_method(*tile_set, "remove_coords_level_tile_proxy", from.source_id, from.get_atlas_coords());
+ }
+ }
+ } else {
+ undo_redo->create_action("Create source-level Tile Proxy");
+ undo_redo->add_do_method(*tile_set, "set_source_level_tile_proxy", from.source_id, to.source_id);
+ if (tile_set->has_source_level_tile_proxy(from.source_id)) {
+ undo_redo->add_undo_method(*tile_set, "set_source_level_tile_proxy", to.source_id, tile_set->get_source_level_tile_proxy(from.source_id));
+ } else {
+ undo_redo->add_undo_method(*tile_set, "remove_source_level_tile_proxy", from.source_id);
+ }
+ }
+ undo_redo->add_do_method(this, "_update_lists");
+ undo_redo->add_undo_method(this, "_update_lists");
+ undo_redo->commit_action();
+ commited_actions_count++;
+ }
+}
+
+void TileProxiesManagerDialog::_clear_invalid_button_pressed() {
+ undo_redo->create_action("Delete All Invalid Tile Proxies");
+
+ undo_redo->add_do_method(*tile_set, "cleanup_invalid_tile_proxies");
+
+ Array proxies = tile_set->get_source_level_tile_proxies();
+ for (int i = 0; i < proxies.size(); i++) {
+ Array proxy = proxies[i];
+ undo_redo->add_undo_method(*tile_set, "set_source_level_tile_proxy", proxy[0], proxy[1]);
+ }
+
+ proxies = tile_set->get_coords_level_tile_proxies();
+ for (int i = 0; i < proxies.size(); i++) {
+ Array proxy = proxies[i];
+ undo_redo->add_undo_method(*tile_set, "set_coords_level_tile_proxy", proxy[0], proxy[1], proxy[2], proxy[3]);
+ }
+
+ proxies = tile_set->get_alternative_level_tile_proxies();
+ for (int i = 0; i < proxies.size(); i++) {
+ Array proxy = proxies[i];
+ undo_redo->add_undo_method(*tile_set, "set_alternative_level_tile_proxy", proxy[0], proxy[1], proxy[2], proxy[3], proxy[4], proxy[5]);
+ }
+ undo_redo->add_do_method(this, "_update_lists");
+ undo_redo->add_undo_method(this, "_update_lists");
+ undo_redo->commit_action();
+}
+
+void TileProxiesManagerDialog::_clear_all_button_pressed() {
+ undo_redo->create_action("Delete All Tile Proxies");
+
+ undo_redo->add_do_method(*tile_set, "clear_tile_proxies");
+
+ Array proxies = tile_set->get_source_level_tile_proxies();
+ for (int i = 0; i < proxies.size(); i++) {
+ Array proxy = proxies[i];
+ undo_redo->add_undo_method(*tile_set, "set_source_level_tile_proxy", proxy[0], proxy[1]);
+ }
+
+ proxies = tile_set->get_coords_level_tile_proxies();
+ for (int i = 0; i < proxies.size(); i++) {
+ Array proxy = proxies[i];
+ undo_redo->add_undo_method(*tile_set, "set_coords_level_tile_proxy", proxy[0], proxy[1], proxy[2], proxy[3]);
+ }
+
+ proxies = tile_set->get_alternative_level_tile_proxies();
+ for (int i = 0; i < proxies.size(); i++) {
+ Array proxy = proxies[i];
+ undo_redo->add_undo_method(*tile_set, "set_alternative_level_tile_proxy", proxy[0], proxy[1], proxy[2], proxy[3], proxy[4], proxy[5]);
+ }
+ undo_redo->add_do_method(this, "_update_lists");
+ undo_redo->add_undo_method(this, "_update_lists");
+ undo_redo->commit_action();
+}
+
+bool TileProxiesManagerDialog::_set(const StringName &p_name, const Variant &p_value) {
+ if (p_name == "from_source") {
+ from.source_id = MAX(int(p_value), -1);
+ } else if (p_name == "from_coords") {
+ from.set_atlas_coords(Vector2i(p_value).max(Vector2i(-1, -1)));
+ } else if (p_name == "from_alternative") {
+ from.alternative_tile = MAX(int(p_value), -1);
+ } else if (p_name == "to_source") {
+ to.source_id = MAX(int(p_value), 0);
+ } else if (p_name == "to_coords") {
+ to.set_atlas_coords(Vector2i(p_value).max(Vector2i(0, 0)));
+ } else if (p_name == "to_alternative") {
+ to.alternative_tile = MAX(int(p_value), 0);
+ } else {
+ return false;
+ }
+ _update_enabled_property_editors();
+ return true;
+}
+
+bool TileProxiesManagerDialog::_get(const StringName &p_name, Variant &r_ret) const {
+ if (p_name == "from_source") {
+ r_ret = from.source_id;
+ } else if (p_name == "from_coords") {
+ r_ret = from.get_atlas_coords();
+ } else if (p_name == "from_alternative") {
+ r_ret = from.alternative_tile;
+ } else if (p_name == "to_source") {
+ r_ret = to.source_id;
+ } else if (p_name == "to_coords") {
+ r_ret = to.get_atlas_coords();
+ } else if (p_name == "to_alternative") {
+ r_ret = to.alternative_tile;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+void TileProxiesManagerDialog::_unhandled_key_input(Ref<InputEvent> p_event) {
+ ERR_FAIL_COND(p_event.is_null());
+
+ if (p_event->is_pressed() && !p_event->is_echo() && (Object::cast_to<InputEventKey>(p_event.ptr()) || Object::cast_to<InputEventJoypadButton>(p_event.ptr()) || Object::cast_to<InputEventAction>(*p_event))) {
+ if (!is_inside_tree() || !is_visible()) {
+ return;
+ }
+
+ if (popup_menu->activate_item_by_event(p_event, false)) {
+ set_input_as_handled();
+ }
+ }
+}
+
+void TileProxiesManagerDialog::cancel_pressed() {
+ for (int i = 0; i < commited_actions_count; i++) {
+ undo_redo->undo();
+ }
+ commited_actions_count = 0;
+}
+
+void TileProxiesManagerDialog::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_update_lists"), &TileProxiesManagerDialog::_update_lists);
+ ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &TileProxiesManagerDialog::_unhandled_key_input);
+}
+
+void TileProxiesManagerDialog::update_tile_set(Ref<TileSet> p_tile_set) {
+ ERR_FAIL_COND(!p_tile_set.is_valid());
+ tile_set = p_tile_set;
+ commited_actions_count = 0;
+ _update_lists();
+}
+
+TileProxiesManagerDialog::TileProxiesManagerDialog() {
+ // Tile proxy management window.
+ set_title(TTR("Tile Proxies Management"));
+ set_process_unhandled_key_input(true);
+
+ to.source_id = 0;
+ to.set_atlas_coords(Vector2i());
+ to.alternative_tile = 0;
+
+ VBoxContainer *vbox_container = memnew(VBoxContainer);
+ vbox_container->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ vbox_container->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ add_child(vbox_container);
+
+ Label *source_level_label = memnew(Label);
+ source_level_label->set_text(TTR("Source-level proxies"));
+ vbox_container->add_child(source_level_label);
+
+ source_level_list = memnew(ItemList);
+ source_level_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ source_level_list->set_select_mode(ItemList::SELECT_MULTI);
+ source_level_list->set_allow_rmb_select(true);
+ source_level_list->connect("item_rmb_selected", callable_mp(this, &TileProxiesManagerDialog::_right_clicked), varray(source_level_list));
+ vbox_container->add_child(source_level_list);
+
+ Label *coords_level_label = memnew(Label);
+ coords_level_label->set_text(TTR("Coords-level proxies"));
+ vbox_container->add_child(coords_level_label);
+
+ coords_level_list = memnew(ItemList);
+ coords_level_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ coords_level_list->set_select_mode(ItemList::SELECT_MULTI);
+ coords_level_list->set_allow_rmb_select(true);
+ coords_level_list->connect("item_rmb_selected", callable_mp(this, &TileProxiesManagerDialog::_right_clicked), varray(coords_level_list));
+ vbox_container->add_child(coords_level_list);
+
+ Label *alternative_level_label = memnew(Label);
+ alternative_level_label->set_text(TTR("Alternative-level proxies"));
+ vbox_container->add_child(alternative_level_label);
+
+ alternative_level_list = memnew(ItemList);
+ alternative_level_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ alternative_level_list->set_select_mode(ItemList::SELECT_MULTI);
+ alternative_level_list->set_allow_rmb_select(true);
+ alternative_level_list->connect("item_rmb_selected", callable_mp(this, &TileProxiesManagerDialog::_right_clicked), varray(alternative_level_list));
+ vbox_container->add_child(alternative_level_list);
+
+ popup_menu = memnew(PopupMenu);
+ popup_menu->add_shortcut(ED_GET_SHORTCUT("ui_text_delete"));
+ popup_menu->connect("id_pressed", callable_mp(this, &TileProxiesManagerDialog::_menu_id_pressed));
+ add_child(popup_menu);
+
+ // Add proxy panel.
+ HSeparator *h_separator = memnew(HSeparator);
+ vbox_container->add_child(h_separator);
+
+ Label *add_label = memnew(Label);
+ add_label->set_text(TTR("Add a new tile proxy:"));
+ vbox_container->add_child(add_label);
+
+ HBoxContainer *hboxcontainer = memnew(HBoxContainer);
+ vbox_container->add_child(hboxcontainer);
+
+ // From
+ VBoxContainer *vboxcontainer_from = memnew(VBoxContainer);
+ vboxcontainer_from->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ hboxcontainer->add_child(vboxcontainer_from);
+
+ source_from_property_editor = memnew(EditorPropertyInteger);
+ source_from_property_editor->set_label(TTR("From Source"));
+ source_from_property_editor->set_object_and_property(this, "from_source");
+ source_from_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
+ source_from_property_editor->set_selectable(false);
+ source_from_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ source_from_property_editor->setup(-1, 99999, 1, true, false);
+ vboxcontainer_from->add_child(source_from_property_editor);
+
+ coords_from_property_editor = memnew(EditorPropertyVector2i);
+ coords_from_property_editor->set_label(TTR("From Coords"));
+ coords_from_property_editor->set_object_and_property(this, "from_coords");
+ coords_from_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
+ coords_from_property_editor->set_selectable(false);
+ coords_from_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ coords_from_property_editor->setup(-1, 99999, true);
+ coords_from_property_editor->hide();
+ vboxcontainer_from->add_child(coords_from_property_editor);
+
+ alternative_from_property_editor = memnew(EditorPropertyInteger);
+ alternative_from_property_editor->set_label(TTR("From Alternative"));
+ alternative_from_property_editor->set_object_and_property(this, "from_alternative");
+ alternative_from_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
+ alternative_from_property_editor->set_selectable(false);
+ alternative_from_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ alternative_from_property_editor->setup(-1, 99999, 1, true, false);
+ alternative_from_property_editor->hide();
+ vboxcontainer_from->add_child(alternative_from_property_editor);
+
+ // To
+ VBoxContainer *vboxcontainer_to = memnew(VBoxContainer);
+ vboxcontainer_to->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ hboxcontainer->add_child(vboxcontainer_to);
+
+ source_to_property_editor = memnew(EditorPropertyInteger);
+ source_to_property_editor->set_label(TTR("To Source"));
+ source_to_property_editor->set_object_and_property(this, "to_source");
+ source_to_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
+ source_to_property_editor->set_selectable(false);
+ source_to_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ source_to_property_editor->setup(-1, 99999, 1, true, false);
+ vboxcontainer_to->add_child(source_to_property_editor);
+
+ coords_to_property_editor = memnew(EditorPropertyVector2i);
+ coords_to_property_editor->set_label(TTR("To Coords"));
+ coords_to_property_editor->set_object_and_property(this, "to_coords");
+ coords_to_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
+ coords_to_property_editor->set_selectable(false);
+ coords_to_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ coords_to_property_editor->setup(-1, 99999, true);
+ coords_to_property_editor->hide();
+ vboxcontainer_to->add_child(coords_to_property_editor);
+
+ alternative_to_property_editor = memnew(EditorPropertyInteger);
+ alternative_to_property_editor->set_label(TTR("To Alternative"));
+ alternative_to_property_editor->set_object_and_property(this, "to_alternative");
+ alternative_to_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
+ alternative_to_property_editor->set_selectable(false);
+ alternative_to_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ alternative_to_property_editor->setup(-1, 99999, 1, true, false);
+ alternative_to_property_editor->hide();
+ vboxcontainer_to->add_child(alternative_to_property_editor);
+
+ Button *add_button = memnew(Button);
+ add_button->set_text(TTR("Add"));
+ add_button->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
+ add_button->connect("pressed", callable_mp(this, &TileProxiesManagerDialog::_add_button_pressed));
+ vbox_container->add_child(add_button);
+
+ h_separator = memnew(HSeparator);
+ vbox_container->add_child(h_separator);
+
+ // Generic actions.
+ Label *generic_actions_label = memnew(Label);
+ generic_actions_label->set_text(TTR("Global actions:"));
+ vbox_container->add_child(generic_actions_label);
+
+ hboxcontainer = memnew(HBoxContainer);
+ vbox_container->add_child(hboxcontainer);
+
+ Button *clear_invalid_button = memnew(Button);
+ clear_invalid_button->set_text(TTR("Clear Invalid"));
+ clear_invalid_button->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
+ clear_invalid_button->connect("pressed", callable_mp(this, &TileProxiesManagerDialog::_clear_invalid_button_pressed));
+ hboxcontainer->add_child(clear_invalid_button);
+
+ Button *clear_all_button = memnew(Button);
+ clear_all_button->set_text(TTR("Clear All"));
+ clear_all_button->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
+ clear_all_button->connect("pressed", callable_mp(this, &TileProxiesManagerDialog::_clear_all_button_pressed));
+ hboxcontainer->add_child(clear_all_button);
+
+ h_separator = memnew(HSeparator);
+ vbox_container->add_child(h_separator);
+}
diff --git a/editor/plugins/tiles/tile_proxies_manager_dialog.h b/editor/plugins/tiles/tile_proxies_manager_dialog.h
new file mode 100644
index 0000000000..f6898e960b
--- /dev/null
+++ b/editor/plugins/tiles/tile_proxies_manager_dialog.h
@@ -0,0 +1,90 @@
+/*************************************************************************/
+/* tile_proxies_manager_dialog.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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_PROXIES_MANAGER_DIALOG_H
+#define TILE_PROXIES_MANAGER_DIALOG_H
+
+#include "editor/editor_node.h"
+#include "editor/editor_properties.h"
+
+#include "scene/gui/dialogs.h"
+#include "scene/gui/item_list.h"
+#include "scene/resources/tile_set.h"
+
+class TileProxiesManagerDialog : public ConfirmationDialog {
+ GDCLASS(TileProxiesManagerDialog, ConfirmationDialog);
+
+private:
+ int commited_actions_count = 0;
+ Ref<TileSet> tile_set;
+
+ UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+
+ TileMapCell from;
+ TileMapCell to;
+
+ // GUI
+ ItemList *source_level_list;
+ ItemList *coords_level_list;
+ ItemList *alternative_level_list;
+
+ EditorPropertyInteger *source_from_property_editor;
+ EditorPropertyVector2i *coords_from_property_editor;
+ EditorPropertyInteger *alternative_from_property_editor;
+ EditorPropertyInteger *source_to_property_editor;
+ EditorPropertyVector2i *coords_to_property_editor;
+ EditorPropertyInteger *alternative_to_property_editor;
+
+ PopupMenu *popup_menu;
+ void _right_clicked(int p_item, Vector2 p_local_mouse_pos, Object *p_item_list);
+ void _menu_id_pressed(int p_id);
+ void _delete_selected_bindings();
+ void _update_lists();
+ void _update_enabled_property_editors();
+ void _property_changed(const String &p_path, const Variant &p_value, const String &p_name, bool p_changing);
+ void _add_button_pressed();
+
+ void _clear_invalid_button_pressed();
+ void _clear_all_button_pressed();
+
+protected:
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+ void _unhandled_key_input(Ref<InputEvent> p_event);
+ virtual void cancel_pressed() override;
+ static void _bind_methods();
+
+public:
+ void update_tile_set(Ref<TileSet> p_tile_set);
+
+ TileProxiesManagerDialog();
+};
+
+#endif // TILE_PROXIES_MANAGER_DIALOG_H
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
index 6b617cf4d8..de910dfd32 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
@@ -745,7 +745,7 @@ void TileSetAtlasSourceEditor::_update_atlas_view() {
button->add_theme_style_override("hover", memnew(StyleBoxEmpty));
button->add_theme_style_override("focus", memnew(StyleBoxEmpty));
button->add_theme_style_override("pressed", memnew(StyleBoxEmpty));
- button->connect("pressed", callable_mp(tile_set_atlas_source, &TileSetAtlasSource::create_alternative_tile), varray(tile_id, -1));
+ button->connect("pressed", callable_mp(tile_set_atlas_source, &TileSetAtlasSource::create_alternative_tile), varray(tile_id, TileSetSource::INVALID_TILE_ALTERNATIVE));
button->set_rect(Rect2(Vector2(pos.x, pos.y + (y_increment - texture_region_base_size.y) / 2.0), Vector2(texture_region_base_size_min, texture_region_base_size_min)));
button->set_expand_icon(true);
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.h b/editor/plugins/tiles/tile_set_atlas_source_editor.h
index dbb0756a16..501416c340 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.h
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.h
@@ -65,7 +65,7 @@ private:
private:
Ref<TileSet> tile_set;
TileSetAtlasSource *tile_set_atlas_source = nullptr;
- int source_id = -1;
+ int source_id = TileSet::INVALID_SOURCE;
protected:
bool _set(const StringName &p_name, const Variant &p_value);
@@ -108,7 +108,7 @@ private:
Ref<TileSet> tile_set;
TileSetAtlasSource *tile_set_atlas_source = nullptr;
- int tile_set_atlas_source_id = -1;
+ int tile_set_atlas_source_id = TileSet::INVALID_SOURCE;
UndoRedo *undo_redo = EditorNode::get_undo_redo();
diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp
index 76ce6f0065..ba98a7d6b3 100644
--- a/editor/plugins/tiles/tile_set_editor.cpp
+++ b/editor/plugins/tiles/tile_set_editor.cpp
@@ -50,7 +50,7 @@ void TileSetEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, C
if (p_from == sources_list) {
// Handle dropping a texture in the list of atlas resources.
- int source_id = -1;
+ int source_id = TileSet::INVALID_SOURCE;
int added = 0;
Dictionary d = p_data;
Vector<String> files = d["files"];
@@ -77,7 +77,7 @@ void TileSetEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, C
}
// Update the selected source (thus triggering an update).
- _update_atlas_sources_list(source_id);
+ _update_sources_list(source_id);
}
}
@@ -114,11 +114,11 @@ bool TileSetEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_dat
return false;
}
-void TileSetEditor::_update_atlas_sources_list(int force_selected_id) {
+void TileSetEditor::_update_sources_list(int force_selected_id) {
ERR_FAIL_COND(!tile_set.is_valid());
// Get the previously selected id.
- int old_selected = -1;
+ int old_selected = TileSet::INVALID_SOURCE;
if (sources_list->get_current() >= 0) {
int source_id = sources_list->get_item_metadata(sources_list->get_current());
if (tile_set->has_source(source_id)) {
@@ -126,7 +126,7 @@ void TileSetEditor::_update_atlas_sources_list(int force_selected_id) {
}
}
- int to_select = -1;
+ int to_select = TileSet::INVALID_SOURCE;
if (force_selected_id >= 0) {
to_select = force_selected_id;
} else if (old_selected >= 0) {
@@ -200,7 +200,7 @@ void TileSetEditor::_update_atlas_sources_list(int force_selected_id) {
_source_selected(sources_list->get_current());
// Synchronize the lists.
- TilesEditor::get_singleton()->set_atlas_sources_lists_current(sources_list->get_current());
+ TilesEditor::get_singleton()->set_sources_lists_current(sources_list->get_current());
}
void TileSetEditor::_source_selected(int p_source_index) {
@@ -235,6 +235,23 @@ void TileSetEditor::_source_selected(int p_source_index) {
}
}
+void TileSetEditor::_source_delete_pressed() {
+ ERR_FAIL_COND(!tile_set.is_valid());
+
+ // Update the selected source.
+ int to_delete = sources_list->get_item_metadata(sources_list->get_current());
+
+ Ref<TileSetSource> source = tile_set->get_source(to_delete);
+
+ // Remove the source.
+ undo_redo->create_action(TTR("Remove source"));
+ undo_redo->add_do_method(*tile_set, "remove_source", to_delete);
+ undo_redo->add_undo_method(*tile_set, "add_source", source, to_delete);
+ undo_redo->commit_action();
+
+ _update_sources_list();
+}
+
void TileSetEditor::_source_add_id_pressed(int p_id_pressed) {
ERR_FAIL_COND(!tile_set.is_valid());
@@ -251,7 +268,7 @@ void TileSetEditor::_source_add_id_pressed(int p_id_pressed) {
undo_redo->add_undo_method(*tile_set, "remove_source", source_id);
undo_redo->commit_action();
- _update_atlas_sources_list(source_id);
+ _update_sources_list(source_id);
} break;
case 1: {
int source_id = tile_set->get_next_source_id();
@@ -264,28 +281,26 @@ void TileSetEditor::_source_add_id_pressed(int p_id_pressed) {
undo_redo->add_undo_method(*tile_set, "remove_source", source_id);
undo_redo->commit_action();
- _update_atlas_sources_list(source_id);
+ _update_sources_list(source_id);
} break;
default:
ERR_FAIL();
}
}
-void TileSetEditor::_source_delete_pressed() {
+void TileSetEditor::_sources_advanced_menu_id_pressed(int p_id_pressed) {
ERR_FAIL_COND(!tile_set.is_valid());
- // Update the selected source.
- int to_delete = sources_list->get_item_metadata(sources_list->get_current());
-
- Ref<TileSetSource> source = tile_set->get_source(to_delete);
-
- // Remove the source.
- undo_redo->create_action(TTR("Remove source"));
- undo_redo->add_do_method(*tile_set, "remove_source", to_delete);
- undo_redo->add_undo_method(*tile_set, "add_source", source, to_delete);
- undo_redo->commit_action();
-
- _update_atlas_sources_list();
+ switch (p_id_pressed) {
+ case 0: {
+ atlas_merging_dialog->update_tile_set(tile_set);
+ atlas_merging_dialog->popup_centered_ratio(0.5);
+ } break;
+ case 1: {
+ tile_proxies_manager_dialog->update_tile_set(tile_set);
+ tile_proxies_manager_dialog->popup_centered_ratio(0.5);
+ } break;
+ }
}
void TileSetEditor::_notification(int p_what) {
@@ -294,6 +309,7 @@ void TileSetEditor::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED:
sources_delete_button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
sources_add_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
+ sources_advanced_menu_button->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
missing_texture_texture = get_theme_icon(SNAME("TileSet"), SNAME("EditorIcons"));
break;
case NOTIFICATION_INTERNAL_PROCESS:
@@ -301,7 +317,7 @@ void TileSetEditor::_notification(int p_what) {
if (tile_set.is_valid()) {
tile_set->set_edited(true);
}
- _update_atlas_sources_list();
+ _update_sources_list();
tile_set_changed_needs_update = false;
}
break;
@@ -414,7 +430,7 @@ void TileSetEditor::edit(Ref<TileSet> p_tile_set) {
// Add the listener again.
if (tile_set.is_valid()) {
tile_set->connect("changed", callable_mp(this, &TileSetEditor::_tile_set_changed));
- _update_atlas_sources_list();
+ _update_sources_list();
}
tile_set_atlas_source_editor->hide();
@@ -447,8 +463,8 @@ TileSetEditor::TileSetEditor() {
sources_list->set_h_size_flags(SIZE_EXPAND_FILL);
sources_list->set_v_size_flags(SIZE_EXPAND_FILL);
sources_list->connect("item_selected", callable_mp(this, &TileSetEditor::_source_selected));
- sources_list->connect("item_selected", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_atlas_sources_lists_current));
- sources_list->connect("visibility_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::synchronize_atlas_sources_list), varray(sources_list));
+ sources_list->connect("item_selected", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_sources_lists_current));
+ sources_list->connect("visibility_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::synchronize_sources_list), varray(sources_list));
sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
sources_list->set_drag_forwarding(this);
split_container_left_side->add_child(sources_list);
@@ -470,6 +486,19 @@ TileSetEditor::TileSetEditor() {
sources_add_button->get_popup()->connect("id_pressed", callable_mp(this, &TileSetEditor::_source_add_id_pressed));
sources_bottom_actions->add_child(sources_add_button);
+ sources_advanced_menu_button = memnew(MenuButton);
+ sources_advanced_menu_button->set_flat(true);
+ sources_advanced_menu_button->get_popup()->add_item(TTR("Open Atlas Merging Tool"));
+ sources_advanced_menu_button->get_popup()->add_item(TTR("Manage Tile Proxies"));
+ sources_advanced_menu_button->get_popup()->connect("id_pressed", callable_mp(this, &TileSetEditor::_sources_advanced_menu_id_pressed));
+ sources_bottom_actions->add_child(sources_advanced_menu_button);
+
+ atlas_merging_dialog = memnew(AtlasMergingDialog);
+ add_child(atlas_merging_dialog);
+
+ tile_proxies_manager_dialog = memnew(TileProxiesManagerDialog);
+ add_child(tile_proxies_manager_dialog);
+
// Right side container.
VBoxContainer *split_container_right_side = memnew(VBoxContainer);
split_container_right_side->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -489,7 +518,7 @@ TileSetEditor::TileSetEditor() {
tile_set_atlas_source_editor = memnew(TileSetAtlasSourceEditor);
tile_set_atlas_source_editor->set_h_size_flags(SIZE_EXPAND_FILL);
tile_set_atlas_source_editor->set_v_size_flags(SIZE_EXPAND_FILL);
- tile_set_atlas_source_editor->connect("source_id_changed", callable_mp(this, &TileSetEditor::_update_atlas_sources_list));
+ tile_set_atlas_source_editor->connect("source_id_changed", callable_mp(this, &TileSetEditor::_update_sources_list));
split_container_right_side->add_child(tile_set_atlas_source_editor);
tile_set_atlas_source_editor->hide();
@@ -497,7 +526,7 @@ TileSetEditor::TileSetEditor() {
tile_set_scenes_collection_source_editor = memnew(TileSetScenesCollectionSourceEditor);
tile_set_scenes_collection_source_editor->set_h_size_flags(SIZE_EXPAND_FILL);
tile_set_scenes_collection_source_editor->set_v_size_flags(SIZE_EXPAND_FILL);
- tile_set_scenes_collection_source_editor->connect("source_id_changed", callable_mp(this, &TileSetEditor::_update_atlas_sources_list));
+ tile_set_scenes_collection_source_editor->connect("source_id_changed", callable_mp(this, &TileSetEditor::_update_sources_list));
split_container_right_side->add_child(tile_set_scenes_collection_source_editor);
tile_set_scenes_collection_source_editor->hide();
diff --git a/editor/plugins/tiles/tile_set_editor.h b/editor/plugins/tiles/tile_set_editor.h
index 9e50aca62f..970e3fabb6 100644
--- a/editor/plugins/tiles/tile_set_editor.h
+++ b/editor/plugins/tiles/tile_set_editor.h
@@ -31,8 +31,10 @@
#ifndef TILE_SET_EDITOR_H
#define TILE_SET_EDITOR_H
+#include "atlas_merging_dialog.h"
#include "scene/gui/box_container.h"
#include "scene/resources/tile_set.h"
+#include "tile_proxies_manager_dialog.h"
#include "tile_set_atlas_source_editor.h"
#include "tile_set_scenes_collection_source_editor.h"
@@ -51,16 +53,21 @@ private:
UndoRedo *undo_redo = EditorNode::get_undo_redo();
- void _update_atlas_sources_list(int force_selected_id = -1);
+ void _update_sources_list(int force_selected_id = -1);
- // -- Sources management --
+ // Sources management.
Button *sources_delete_button;
MenuButton *sources_add_button;
+ MenuButton *sources_advanced_menu_button;
ItemList *sources_list;
Ref<Texture2D> missing_texture_texture;
void _source_selected(int p_source_index);
- void _source_add_id_pressed(int p_id_pressed);
void _source_delete_pressed();
+ void _source_add_id_pressed(int p_id_pressed);
+ void _sources_advanced_menu_id_pressed(int p_id_pressed);
+
+ AtlasMergingDialog *atlas_merging_dialog;
+ TileProxiesManagerDialog *tile_proxies_manager_dialog;
void _tile_set_changed();
diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp
index 339efc7b99..79b869b511 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.cpp
+++ b/editor/plugins/tiles/tiles_editor_plugin.cpp
@@ -118,11 +118,11 @@ void TilesEditor::_update_editors() {
CanvasItemEditor::get_singleton()->update_viewport();
}
-void TilesEditor::set_atlas_sources_lists_current(int p_current) {
+void TilesEditor::set_sources_lists_current(int p_current) {
atlas_sources_lists_current = p_current;
}
-void TilesEditor::synchronize_atlas_sources_list(Object *p_current) {
+void TilesEditor::synchronize_sources_list(Object *p_current) {
ItemList *item_list = Object::cast_to<ItemList>(p_current);
ERR_FAIL_COND(!item_list);
diff --git a/editor/plugins/tiles/tiles_editor_plugin.h b/editor/plugins/tiles/tiles_editor_plugin.h
index 6cc6f51598..f976d68938 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.h
+++ b/editor/plugins/tiles/tiles_editor_plugin.h
@@ -76,8 +76,8 @@ public:
void forward_canvas_draw_over_viewport(Control *p_overlay) { tilemap_editor->forward_canvas_draw_over_viewport(p_overlay); }
// To synchronize the atlas sources lists.
- void set_atlas_sources_lists_current(int p_current);
- void synchronize_atlas_sources_list(Object *p_current);
+ void set_sources_lists_current(int p_current);
+ void synchronize_sources_list(Object *p_current);
void set_atlas_view_transform(float p_zoom, Vector2 p_scroll);
void synchronize_atlas_view(Object *p_current);