summaryrefslogtreecommitdiff
path: root/editor/plugins/tiles
diff options
context:
space:
mode:
authorRĂ©mi Verschelde <remi@verschelde.fr>2021-05-20 14:32:40 +0200
committerGitHub <noreply@github.com>2021-05-20 14:32:40 +0200
commita6a75e2c095d67ffb5a40a6e65f9901bcfd54667 (patch)
treeeab6a887e4fea6639f66b48dbe7e23eed5411a0d /editor/plugins/tiles
parent342f3efc7ec41f3a4e439c0c0e6a2d0f0f2fbe41 (diff)
parentd8bb53cd2194fed58f1a55e60b9f1b863c6e9cc7 (diff)
Merge pull request #48812 from groud/tilemap_scenes_painting
Implement scenes tiles in TileMaps
Diffstat (limited to 'editor/plugins/tiles')
-rw-r--r--editor/plugins/tiles/tile_atlas_view.cpp38
-rw-r--r--editor/plugins/tiles/tile_data_editors.cpp2
-rw-r--r--editor/plugins/tiles/tile_map_editor.cpp333
-rw-r--r--editor/plugins/tiles/tile_map_editor.h38
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.cpp98
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.h23
-rw-r--r--editor/plugins/tiles/tile_set_editor.cpp109
-rw-r--r--editor/plugins/tiles/tile_set_editor.h6
-rw-r--r--editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp511
-rw-r--r--editor/plugins/tiles/tile_set_scenes_collection_source_editor.h139
10 files changed, 1096 insertions, 201 deletions
diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp
index 8c5bb56287..6e82951d3d 100644
--- a/editor/plugins/tiles/tile_atlas_view.cpp
+++ b/editor/plugins/tiles/tile_atlas_view.cpp
@@ -195,9 +195,9 @@ void TileAtlasView::_base_tiles_root_control_gui_input(const Ref<InputEvent> &p_
if (mm.is_valid()) {
Transform2D xform = base_tiles_drawing_root->get_transform().affine_inverse();
Vector2i coords = get_atlas_tile_coords_at_pos(xform.xform(mm->get_position()));
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
coords = tile_set_atlas_source->get_tile_at_coords(coords);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
base_tiles_root_control->set_tooltip(vformat(TTR("Source: %d\nAtlas coordinates: %s\nAlternative: 0"), source_id, coords));
}
}
@@ -215,7 +215,7 @@ void TileAtlasView::_draw_base_tiles() {
for (int x = 0; x < grid_size.x; x++) {
for (int y = 0; y < grid_size.y; y++) {
Vector2i coords = Vector2i(x, y);
- if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
Rect2i rect = Rect2i(texture_region_size * coords + margins, texture_region_size);
base_tiles_draw->draw_texture_rect_region(texture, rect, rect);
}
@@ -229,17 +229,23 @@ void TileAtlasView::_draw_base_tiles() {
rect.set_end(Vector2i(texture->get_size().x, margins.y));
base_tiles_draw->draw_texture_rect_region(texture, rect, rect);
// Bottom
- rect.position = Vector2i(0, margins.y + (grid_size.y * texture_region_size.y));
- rect.set_end(texture->get_size());
- base_tiles_draw->draw_texture_rect_region(texture, rect, rect);
+ int bottom_border = margins.y + (grid_size.y * texture_region_size.y);
+ if (bottom_border < texture->get_size().y) {
+ rect.position = Vector2i(0, bottom_border);
+ rect.set_end(texture->get_size());
+ base_tiles_draw->draw_texture_rect_region(texture, rect, rect);
+ }
// Left
rect.position = Vector2i(0, margins.y);
rect.set_end(Vector2i(margins.x, margins.y + (grid_size.y * texture_region_size.y)));
base_tiles_draw->draw_texture_rect_region(texture, rect, rect);
// Right.
- rect.position = Vector2i(margins.x + (grid_size.x * texture_region_size.x), margins.y);
- rect.set_end(Vector2i(texture->get_size().x, margins.y + (grid_size.y * texture_region_size.y)));
- base_tiles_draw->draw_texture_rect_region(texture, rect, rect);
+ int right_border = margins.x + (grid_size.x * texture_region_size.x);
+ if (right_border < texture->get_size().x) {
+ rect.position = Vector2i(right_border, margins.y);
+ rect.set_end(Vector2i(texture->get_size().x, margins.y + (grid_size.y * texture_region_size.y)));
+ base_tiles_draw->draw_texture_rect_region(texture, rect, rect);
+ }
// Draw actual tiles, using their properties (modulation, etc...)
for (int i = 0; i < tile_set_atlas_source->get_tiles_count(); i++) {
@@ -249,7 +255,7 @@ void TileAtlasView::_draw_base_tiles() {
Vector2i offset_pos = (margins + (atlas_coords * texture_region_size) + tile_set_atlas_source->get_tile_texture_region(atlas_coords).size / 2 + tile_set_atlas_source->get_tile_effective_texture_offset(atlas_coords, 0));
// Draw the tile.
- TileSetAtlasPluginRendering::draw_tile(base_tiles_draw->get_canvas_item(), offset_pos, tile_set, source_id, atlas_coords, 0);
+ TileSetPluginAtlasRendering::draw_tile(base_tiles_draw->get_canvas_item(), offset_pos, tile_set, source_id, atlas_coords, 0);
}
}
}
@@ -268,7 +274,7 @@ void TileAtlasView::_draw_base_tiles_texture_grid() {
for (int y = 0; y < grid_size.y; y++) {
Vector2i origin = margins + (Vector2i(x, y) * (texture_region_size + separation));
Vector2i base_tile_coords = tile_set_atlas_source->get_tile_at_coords(Vector2i(x, y));
- if (base_tile_coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (base_tile_coords != TileSetSource::INVALID_ATLAS_COORDS) {
if (base_tile_coords == Vector2i(x, y)) {
// Draw existing tile.
Vector2i size_in_atlas = tile_set_atlas_source->get_tile_size_in_atlas(base_tile_coords);
@@ -299,7 +305,7 @@ void TileAtlasView::_draw_base_tiles_dark() {
Vector2i origin = margins + (Vector2i(x, y) * (texture_region_size + separation));
Vector2i base_tile_coords = tile_set_atlas_source->get_tile_at_coords(Vector2i(x, y));
- if (base_tile_coords == TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (base_tile_coords == TileSetSource::INVALID_ATLAS_COORDS) {
// Draw the grid.
base_tiles_dark->draw_rect(Rect2i(origin, texture_region_size), Color(0.0, 0.0, 0.0, 0.5), true);
}
@@ -331,7 +337,7 @@ void TileAtlasView::_alternative_tiles_root_control_gui_input(const Ref<InputEve
Vector3i coords3 = get_alternative_tile_at_pos(xform.xform(mm->get_position()));
Vector2i coords = Vector2i(coords3.x, coords3.y);
int alternative_id = coords3.z;
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && alternative_id != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS && alternative_id != TileSetSource::INVALID_TILE_ALTERNATIVE) {
alternative_tiles_root_control->set_tooltip(vformat(TTR("Source: %d\nAtlas coordinates: %s\nAlternative: %d"), source_id, coords, alternative_id));
}
}
@@ -364,7 +370,7 @@ void TileAtlasView::_draw_alternatives() {
}
// Draw the tile.
- TileSetAtlasPluginRendering::draw_tile(alternatives_draw->get_canvas_item(), offset_pos, tile_set, source_id, atlas_coords, alternative_id);
+ TileSetPluginAtlasRendering::draw_tile(alternatives_draw->get_canvas_item(), offset_pos, tile_set, source_id, atlas_coords, alternative_id);
// Increment the x position.
current_pos.x += transposed ? texture_region.size.y : texture_region.size.x;
@@ -464,7 +470,7 @@ Vector2i TileAtlasView::get_atlas_tile_coords_at_pos(const Vector2 p_pos) const
return ret;
}
- return TileSetAtlasSource::INVALID_ATLAS_COORDS;
+ return TileSetSource::INVALID_ATLAS_COORDS;
}
void TileAtlasView::_update_alternative_tiles_rect_cache() {
@@ -506,7 +512,7 @@ Vector3i TileAtlasView::get_alternative_tile_at_pos(const Vector2 p_pos) const {
}
}
- return Vector3i(TileSetAtlasSource::INVALID_ATLAS_COORDS.x, TileSetAtlasSource::INVALID_ATLAS_COORDS.y, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ return Vector3i(TileSetSource::INVALID_ATLAS_COORDS.x, TileSetSource::INVALID_ATLAS_COORDS.y, TileSetSource::INVALID_TILE_ALTERNATIVE);
}
Rect2i TileAtlasView::get_alternative_tile_rect(const Vector2i p_coords, int p_alternative_tile) {
diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp
index 0b674bec39..d2665a3a2b 100644
--- a/editor/plugins/tiles/tile_data_editors.cpp
+++ b/editor/plugins/tiles/tile_data_editors.cpp
@@ -166,7 +166,7 @@ void TileDataTerrainsEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform
Vector<String> components = String(p_property).split("/", true);
if (components[0] == "terrain_mode" || components[0] == "terrain" || components[0] == "terrains_peering_bit") {
- TileSetAtlasPluginTerrain::draw_terrains(p_canvas_item, p_transform, p_tile_set, tile_data);
+ TileSetPluginAtlasTerrain::draw_terrains(p_canvas_item, p_transform, p_tile_set, tile_data);
}
}
diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp
index 73640a78c2..80ba396936 100644
--- a/editor/plugins/tiles/tile_map_editor.cpp
+++ b/editor/plugins/tiles/tile_map_editor.cpp
@@ -32,6 +32,7 @@
#include "tiles_editor_plugin.h"
+#include "editor/editor_resource_preview.h"
#include "editor/editor_scale.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
@@ -55,7 +56,7 @@ void TileMapEditorTilesPlugin::_notification(int p_what) {
picker_button->set_icon(get_theme_icon("ColorPick", "EditorIcons"));
erase_button->set_icon(get_theme_icon("Eraser", "EditorIcons"));
- missing_texture_texture = get_theme_icon("TileSet", "EditorIcons");
+ missing_atlas_texture_icon = get_theme_icon("TileSet", "EditorIcons");
break;
case NOTIFICATION_VISIBILITY_CHANGED:
_stop_dragging();
@@ -64,9 +65,8 @@ void TileMapEditorTilesPlugin::_notification(int p_what) {
void TileMapEditorTilesPlugin::tile_set_changed() {
_update_fix_selected_and_hovered();
- _update_bottom_panel();
_update_tile_set_sources_list();
- _update_atlas_view();
+ _update_bottom_panel();
}
void TileMapEditorTilesPlugin::_on_random_tile_checkbox_toggled(bool p_pressed) {
@@ -146,19 +146,38 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() {
for (int i = 0; i < tile_set->get_source_count(); i++) {
int source_id = tile_set->get_source_id(i);
- // TODO: handle with virtual functions
TileSetSource *source = *tile_set->get_source(source_id);
+
+ Ref<Texture2D> texture;
+ String item_text;
+
+ // Atlas source.
TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
if (atlas_source) {
- Ref<Texture2D> texture = atlas_source->get_texture();
+ texture = atlas_source->get_texture();
if (texture.is_valid()) {
- sources_list->add_item(vformat("%s - (id:%d)", texture->get_path().get_file(), source_id), texture);
+ item_text = vformat("%s (id:%d)", texture->get_path().get_file(), source_id);
} else {
- sources_list->add_item(vformat("No Texture Atlas Source - (id:%d)", source_id), missing_texture_texture);
+ item_text = vformat("No Texture Atlas Source (id:%d)", source_id);
}
- } else {
- sources_list->add_item(vformat("Unknown Type Source - (id:%d)", source_id), missing_texture_texture);
}
+
+ // Scene collection source.
+ TileSetScenesCollectionSource *scene_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source);
+ if (scene_collection_source) {
+ texture = get_theme_icon("PackedScene", "EditorIcons");
+ item_text = vformat(TTR("Scene Collection Source (id:%d)"), source_id);
+ }
+
+ // Use default if not valid.
+ if (item_text.is_empty()) {
+ item_text = vformat(TTR("Unknown Type Source (id:%d)"), source_id);
+ }
+ if (!texture.is_valid()) {
+ texture = missing_atlas_texture_icon;
+ }
+
+ sources_list->add_item(item_text, texture);
sources_list->set_item_metadata(i, source_id);
}
@@ -176,7 +195,7 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() {
TilesEditor::get_singleton()->set_atlas_sources_lists_current(sources_list->get_current());
}
-void TileMapEditorTilesPlugin::_update_atlas_view() {
+void TileMapEditorTilesPlugin::_update_bottom_panel() {
// Update the atlas display.
TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
if (!tile_map) {
@@ -185,39 +204,161 @@ void TileMapEditorTilesPlugin::_update_atlas_view() {
Ref<TileSet> tile_set = tile_map->get_tileset();
if (!tile_set.is_valid()) {
- tile_atlas_view->hide();
return;
}
int source_index = sources_list->get_current();
if (source_index >= 0 && source_index < sources_list->get_item_count()) {
+ atlas_sources_split_container->show();
+ missing_source_label->hide();
+
int source_id = sources_list->get_item_metadata(source_index);
TileSetSource *source = *tile_set->get_source(source_id);
TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
+ TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source);
+
if (atlas_source) {
- tile_atlas_view->set_atlas_source(*tile_map->get_tileset(), atlas_source, source_id);
tile_atlas_view->show();
+ scene_tiles_list->hide();
+ invalid_source_label->hide();
+ _update_atlas_view();
+ } else if (scenes_collection_source) {
+ tile_atlas_view->hide();
+ scene_tiles_list->show();
+ invalid_source_label->hide();
+ _update_scenes_collection_view();
+ } else {
+ tile_atlas_view->hide();
+ scene_tiles_list->hide();
+ invalid_source_label->show();
}
} else {
+ atlas_sources_split_container->hide();
+ missing_source_label->show();
+
tile_atlas_view->hide();
+ scene_tiles_list->hide();
+ invalid_source_label->hide();
}
+}
- // Synchronize atlas view.
- TilesEditor::get_singleton()->synchronize_atlas_view(tile_atlas_view);
+void TileMapEditorTilesPlugin::_update_atlas_view() {
+ 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;
+ }
+
+ int source_id = sources_list->get_item_metadata(sources_list->get_current());
+ TileSetSource *source = *tile_set->get_source(source_id);
+ TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
+ ERR_FAIL_COND(!atlas_source);
+
+ tile_atlas_view->set_atlas_source(*tile_map->get_tileset(), atlas_source, source_id);
+ TilesEditor::get_singleton()->synchronize_atlas_view(tile_atlas_view);
tile_atlas_control->update();
}
-void TileMapEditorTilesPlugin::_update_bottom_panel() {
+void TileMapEditorTilesPlugin::_update_scenes_collection_view() {
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;
+ }
+
+ int source_id = sources_list->get_item_metadata(sources_list->get_current());
+ TileSetSource *source = *tile_set->get_source(source_id);
+ TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source);
+ ERR_FAIL_COND(!scenes_collection_source);
+
+ // Clear the list.
+ scene_tiles_list->clear();
+
+ // Rebuild the list.
+ for (int i = 0; i < scenes_collection_source->get_scene_tiles_count(); i++) {
+ int scene_id = scenes_collection_source->get_scene_tile_id(i);
+
+ Ref<PackedScene> scene = scenes_collection_source->get_scene_tile_scene(scene_id);
+
+ int item_index = 0;
+ if (scene.is_valid()) {
+ item_index = scene_tiles_list->add_item(vformat("%s (path:%s id:%d)", scene->get_path().get_file().get_basename(), scene->get_path(), scene_id));
+ Variant udata = i;
+ EditorResourcePreview::get_singleton()->queue_edited_resource_preview(scene, this, "_scene_thumbnail_done", udata);
+ } else {
+ item_index = scene_tiles_list->add_item(TTR("Tile with Invalid Scene"), get_theme_icon("PackedScene", "EditorIcons"));
+ }
+ scene_tiles_list->set_item_metadata(item_index, scene_id);
- // Update the tabs.
- missing_source_label->set_visible(tile_set.is_valid() && tile_set->get_source_count() == 0);
- atlas_sources_split_container->set_visible(tile_set.is_valid() && tile_set->get_source_count() > 0);
+ // Check if in selection.
+ if (tile_set_selection.has(TileMapCell(source_id, Vector2i(), scene_id))) {
+ scene_tiles_list->select(item_index, false);
+ }
+ }
+
+ // Icon size update.
+ int int_size = int(EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size")) * EDSCALE;
+ 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) {
+ int index = p_ud;
+
+ if (index >= 0 && index < scene_tiles_list->get_item_count()) {
+ scene_tiles_list->set_item_icon(index, p_preview);
+ }
+}
+
+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) {
+ return;
+ }
+
+ Ref<TileSet> tile_set = tile_map->get_tileset();
+ if (!tile_set.is_valid()) {
+ return;
+ }
+
+ // Add or remove the Tile form the selection.
+ int scene_id = scene_tiles_list->get_item_metadata(p_index);
+ int source_id = sources_list->get_item_metadata(sources_list->get_current());
+ TileSetSource *source = *tile_set->get_source(source_id);
+ TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source);
+ ERR_FAIL_COND(!scenes_collection_source);
+
+ TileMapCell selected = TileMapCell(source_id, Vector2i(), scene_id);
+
+ // Clear the selection if shift is not pressed.
+ if (!Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ tile_set_selection.clear();
+ }
+
+ if (p_selected) {
+ tile_set_selection.insert(selected);
+ } else {
+ if (tile_set_selection.has(selected)) {
+ tile_set_selection.erase(selected);
+ }
+ }
+
+ _update_selection_pattern_from_tileset_selection();
+}
+
+void TileMapEditorTilesPlugin::_scenes_list_nothing_selected() {
+ scene_tiles_list->deselect_all();
+ tile_set_selection.clear();
+ tile_map_selection.clear();
+ selection_pattern->clear();
+ _update_selection_pattern_from_tileset_selection();
}
bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
@@ -257,7 +398,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, TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ undo_redo->add_do_method(tile_map, "set_cell", E->get(), -1, 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());
@@ -288,7 +429,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, TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ undo_redo->add_do_method(tile_map, "set_cell", E->get(), -1, 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());
@@ -364,7 +505,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
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, TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ tile_map->set_cell(coords, -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
}
} else {
// Select tiles
@@ -467,7 +608,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
}
}
- // handle the preview of the tiles to be placed.
+ // Handle the preview of the tiles to be placed.
if (is_visible_in_tree() && has_mouse) { // Only if the tilemap editor is opened and the viewport is hovered.
Map<Vector2i, TileMapCell> preview;
Rect2i drawn_grid_rect;
@@ -583,11 +724,10 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
// Draw the preview.
for (Map<Vector2i, TileMapCell>::Element *E = preview.front(); E; E = E->next()) {
+ Vector2i size = tile_set->get_tile_size();
+ Vector2 position = tile_map->map_to_world(E->key()) - size / 2;
+ Rect2 cell_region = xform.xform(Rect2(position, size));
if (!erase_button->is_pressed() && random_tile_checkbox->is_pressed()) {
- Vector2i size = tile_set->get_tile_size();
- Vector2 position = tile_map->map_to_world(E->key()) - size / 2;
- Rect2 cell_region = xform.xform(Rect2(position, size));
-
tile_set->draw_tile_shape(p_overlay, cell_region, Color(1.0, 1.0, 1.0, 0.5), true);
} else {
if (tile_set->has_source(E->get().source_id)) {
@@ -629,12 +769,10 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
// Draw the tile.
p_overlay->draw_texture_rect_region(atlas_source->get_texture(), dest_rect, source_rect, modulate * Color(1.0, 1.0, 1.0, 0.5), transpose, tile_set->is_uv_clipping());
+ } else {
+ tile_set->draw_tile_shape(p_overlay, cell_region, Color(1.0, 1.0, 1.0, 0.5), true);
}
} else {
- Vector2i size = tile_set->get_tile_size();
- Vector2 position = tile_map->map_to_world(E->key()) - size / 2;
- Rect2 cell_region = xform.xform(Rect2(position, size));
-
tile_set->draw_tile_shape(p_overlay, cell_region, Color(0.0, 0.0, 0.0, 0.5), true);
}
}
@@ -669,7 +807,9 @@ TileMapCell TileMapEditorTilesPlugin::_pick_random_tile(const TileMapPattern *p_
TileSetSource *source = *tile_set->get_source(source_id);
TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
if (atlas_source) {
- sum += Object::cast_to<TileData>(atlas_source->get_tile_data(atlas_coords, alternative_tile))->get_probability();
+ TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(atlas_coords, alternative_tile));
+ ERR_FAIL_COND_V(!tile_data, TileMapCell());
+ sum += tile_data->get_probability();
} else {
sum += 1.0;
}
@@ -698,7 +838,7 @@ TileMapCell TileMapEditorTilesPlugin::_pick_random_tile(const TileMapPattern *p_
return TileMapCell();
}
-Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_start_drag_mouse_pos, Vector2 p_from_mouse_pos, Vector2i p_to_mouse_pos) {
+Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_start_drag_mouse_pos, Vector2 p_from_mouse_pos, Vector2 p_to_mouse_pos) {
TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
if (!tile_map) {
return Map<Vector2i, TileMapCell>();
@@ -711,7 +851,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, TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
TileMapPattern *pattern = erase_button->is_pressed() ? &erase_pattern : selection_pattern;
Map<Vector2i, TileMapCell> output;
@@ -763,7 +903,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, TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ erase_pattern.set_cell(Vector2i(0, 0), -1, 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.
@@ -814,7 +954,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, TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
TileMapPattern *pattern = erase_button->is_pressed() ? &erase_pattern : selection_pattern;
Map<Vector2i, TileMapCell> output;
@@ -1090,8 +1230,8 @@ 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.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS);
- hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
+ hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
tile_set_selection.clear();
tile_map_selection.clear();
selection_pattern->clear();
@@ -1101,8 +1241,8 @@ 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.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS);
- hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
+ hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
tile_set_selection.clear();
tile_map_selection.clear();
selection_pattern->clear();
@@ -1112,8 +1252,8 @@ 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.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS);
- hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
+ hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
tile_set_selection.clear();
tile_map_selection.clear();
selection_pattern->clear();
@@ -1128,8 +1268,8 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() {
!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.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS);
- hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
+ hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
}
// Selection if needed.
@@ -1187,6 +1327,7 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_selection(
per_source[E->get().source_id].push_back(&(E->get()));
}
+ int vertical_offset = 0;
for (Map<int, List<const TileMapCell *>>::Element *E_source = per_source.front(); E_source; E_source = E_source->next()) {
// Per source.
List<const TileMapCell *> unorganized;
@@ -1199,24 +1340,21 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_selection(
// Organize using coordinates.
for (List<const TileMapCell *>::Element *E_cell = E_source->get().front(); E_cell; E_cell = E_cell->next()) {
const TileMapCell *current = E_cell->get();
- if (organized_pattern.has(current->get_atlas_coords())) {
- if (current->alternative_tile < organized_pattern[current->get_atlas_coords()]->alternative_tile) {
- unorganized.push_back(organized_pattern[current->get_atlas_coords()]);
- organized_pattern[current->get_atlas_coords()] = current;
- } else {
- unorganized.push_back(current);
- }
- } else {
+ if (current->alternative_tile == 0) {
organized_pattern[current->get_atlas_coords()] = current;
+ } else {
+ unorganized.push_back(current);
}
}
// Compute the encompassing rect for the organized pattern.
Map<Vector2i, const TileMapCell *>::Element *E_cell = organized_pattern.front();
- encompassing_rect_coords = Rect2i(E_cell->key(), Vector2i(1, 1));
- for (; E_cell; E_cell = E_cell->next()) {
- encompassing_rect_coords.expand_to(E_cell->key() + Vector2i(1, 1));
- encompassing_rect_coords.expand_to(E_cell->key());
+ if (E_cell) {
+ encompassing_rect_coords = Rect2i(E_cell->key(), Vector2i(1, 1));
+ for (; E_cell; E_cell = E_cell->next()) {
+ encompassing_rect_coords.expand_to(E_cell->key() + Vector2i(1, 1));
+ encompassing_rect_coords.expand_to(E_cell->key());
+ }
}
} else {
// Add everything unorganized.
@@ -1227,12 +1365,15 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_selection(
// Now add everything to the output pattern.
for (Map<Vector2i, const TileMapCell *>::Element *E_cell = organized_pattern.front(); E_cell; E_cell = E_cell->next()) {
- selection_pattern->set_cell(E_cell->key() - encompassing_rect_coords.position, E_cell->get()->source_id, E_cell->get()->get_atlas_coords(), E_cell->get()->alternative_tile);
+ selection_pattern->set_cell(E_cell->key() - encompassing_rect_coords.position + Vector2i(0, vertical_offset), E_cell->get()->source_id, E_cell->get()->get_atlas_coords(), E_cell->get()->alternative_tile);
}
Vector2i organized_size = selection_pattern->get_size();
+ int unorganized_index = 0;
for (List<const TileMapCell *>::Element *E_cell = unorganized.front(); E_cell; E_cell = E_cell->next()) {
- selection_pattern->set_cell(Vector2(organized_size.x, 0), E_cell->get()->source_id, E_cell->get()->get_atlas_coords(), E_cell->get()->alternative_tile);
+ selection_pattern->set_cell(Vector2(organized_size.x + unorganized_index, vertical_offset), E_cell->get()->source_id, E_cell->get()->get_atlas_coords(), E_cell->get()->alternative_tile);
+ unorganized_index++;
}
+ vertical_offset += MAX(organized_size.y, 1);
}
CanvasItemEditor::get_singleton()->update_viewport();
}
@@ -1246,7 +1387,7 @@ void TileMapEditorTilesPlugin::_update_tileset_selection_from_selection_pattern(
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)));
}
}
- _update_atlas_view();
+ _update_bottom_panel();
}
void TileMapEditorTilesPlugin::_tile_atlas_control_draw() {
@@ -1283,7 +1424,7 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() {
}
// Draw the hovered tile.
- if (hovered_tile.get_atlas_coords() != TileSetAtlasSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile == 0 && !tile_set_dragging_selection) {
+ if (hovered_tile.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile == 0 && !tile_set_dragging_selection) {
tile_atlas_control->draw_rect(atlas->get_tile_texture_region(hovered_tile.get_atlas_coords()), Color(1.0, 1.0, 1.0), false);
}
@@ -1299,7 +1440,7 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() {
for (int x = region.position.x; x < region.get_end().x; x++) {
for (int y = region.position.y; y < region.get_end().y; y++) {
Vector2i tile = atlas->get_tile_at_coords(Vector2i(x, y));
- if (tile != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (tile != TileSetSource::INVALID_ATLAS_COORDS) {
to_draw.insert(tile);
}
}
@@ -1313,8 +1454,8 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() {
void TileMapEditorTilesPlugin::_tile_atlas_control_mouse_exited() {
hovered_tile.source_id = -1;
- hovered_tile.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS);
- hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
+ hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
tile_set_dragging_selection = false;
tile_atlas_control->update();
}
@@ -1347,12 +1488,12 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_gui_input(const Ref<InputEven
// Update the hovered tile
hovered_tile.source_id = source_id;
- hovered_tile.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS);
- hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
+ hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position());
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
coords = atlas->get_tile_at_coords(coords);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
hovered_tile.set_atlas_coords(coords);
hovered_tile.alternative_tile = 0;
}
@@ -1373,7 +1514,7 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_gui_input(const Ref<InputEven
tile_set_selection.clear();
}
- if (hovered_tile.get_atlas_coords() != TileSetAtlasSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile == 0) {
+ if (hovered_tile.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile == 0) {
if (mb->is_shift_pressed() && tile_set_selection.has(TileMapCell(source_id, hovered_tile.get_atlas_coords(), 0))) {
tile_set_selection.erase(TileMapCell(source_id, hovered_tile.get_atlas_coords(), 0));
} else {
@@ -1389,18 +1530,18 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_gui_input(const Ref<InputEven
// Compute the covered area.
Vector2i start_tile = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_set_drag_start_mouse_pos);
Vector2i end_tile = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position());
- if (start_tile != TileSetAtlasSource::INVALID_ATLAS_COORDS && end_tile != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (start_tile != TileSetSource::INVALID_ATLAS_COORDS && end_tile != TileSetSource::INVALID_ATLAS_COORDS) {
Rect2i region = Rect2i(start_tile, end_tile - start_tile).abs();
region.size += Vector2i(1, 1);
// To update the selection, we copy the selected/not selected status of the tiles we drag from.
Vector2i start_coords = atlas->get_tile_at_coords(start_tile);
- if (mb->is_shift_pressed() && start_coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && !tile_set_selection.has(TileMapCell(source_id, start_coords, 0))) {
+ if (mb->is_shift_pressed() && start_coords != TileSetSource::INVALID_ATLAS_COORDS && !tile_set_selection.has(TileMapCell(source_id, start_coords, 0))) {
// Remove from the selection.
for (int x = region.position.x; x < region.get_end().x; x++) {
for (int y = region.position.y; y < region.get_end().y; y++) {
Vector2i tile_coords = atlas->get_tile_at_coords(Vector2i(x, y));
- if (tile_coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && tile_set_selection.has(TileMapCell(source_id, tile_coords, 0))) {
+ if (tile_coords != TileSetSource::INVALID_ATLAS_COORDS && tile_set_selection.has(TileMapCell(source_id, tile_coords, 0))) {
tile_set_selection.erase(TileMapCell(source_id, tile_coords, 0));
}
}
@@ -1410,7 +1551,7 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_gui_input(const Ref<InputEven
for (int x = region.position.x; x < region.get_end().x; x++) {
for (int y = region.position.y; y < region.get_end().y; y++) {
Vector2i tile_coords = atlas->get_tile_at_coords(Vector2i(x, y));
- if (tile_coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (tile_coords != TileSetSource::INVALID_ATLAS_COORDS) {
tile_set_selection.insert(TileMapCell(source_id, tile_coords, 0));
}
}
@@ -1453,7 +1594,7 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_draw() {
// Draw the selection.
for (Set<TileMapCell>::Element *E = tile_set_selection.front(); E; E = E->next()) {
- if (E->get().source_id == source_id && E->get().get_atlas_coords() != TileSetAtlasSource::INVALID_ATLAS_COORDS && E->get().alternative_tile > 0) {
+ if (E->get().source_id == source_id && E->get().get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && E->get().alternative_tile > 0) {
Rect2i rect = tile_atlas_view->get_alternative_tile_rect(E->get().get_atlas_coords(), E->get().alternative_tile);
if (rect != Rect2i()) {
alternative_tiles_control->draw_rect(rect, Color(0.2, 0.2, 1.0), false);
@@ -1462,7 +1603,7 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_draw() {
}
// Draw hovered tile.
- if (hovered_tile.get_atlas_coords() != TileSetAtlasSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile > 0) {
+ if (hovered_tile.get_atlas_coords() != TileSetSource::INVALID_ATLAS_COORDS && hovered_tile.alternative_tile > 0) {
Rect2i rect = tile_atlas_view->get_alternative_tile_rect(hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile);
if (rect != Rect2i()) {
alternative_tiles_control->draw_rect(rect, Color(1.0, 1.0, 1.0), false);
@@ -1472,8 +1613,8 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_draw() {
void TileMapEditorTilesPlugin::_tile_alternatives_control_mouse_exited() {
hovered_tile.source_id = -1;
- hovered_tile.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS);
- hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
+ hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
tile_set_dragging_selection = false;
alternative_tiles_control->update();
}
@@ -1506,12 +1647,12 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_gui_input(const Ref<In
// Update the hovered tile
hovered_tile.source_id = source_id;
- hovered_tile.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS);
- hovered_tile.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
+ hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
Vector3i alternative_coords = tile_atlas_view->get_alternative_tile_at_pos(alternative_tiles_control->get_local_mouse_position());
Vector2i coords = Vector2i(alternative_coords.x, alternative_coords.y);
int alternative = alternative_coords.z;
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && alternative != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS && alternative != TileSetSource::INVALID_TILE_ALTERNATIVE) {
hovered_tile.set_atlas_coords(coords);
hovered_tile.alternative_tile = alternative;
}
@@ -1530,7 +1671,7 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_gui_input(const Ref<In
tile_set_selection.clear();
}
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && alternative != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS && alternative != TileSetAtlasSource::INVALID_TILE_ALTERNATIVE) {
if (mb->is_shift_pressed() && tile_set_selection.has(TileMapCell(source_id, hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile))) {
tile_set_selection.erase(TileMapCell(source_id, hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile));
} else {
@@ -1565,13 +1706,14 @@ TypedArray<Vector2i> TileMapEditorTilesPlugin::_get_tile_map_selection() const {
void TileMapEditorTilesPlugin::edit(ObjectID p_tile_map_id) {
tile_map_id = p_tile_map_id;
- // Clean the selection.
+ // Clear the selection.
tile_set_selection.clear();
tile_map_selection.clear();
selection_pattern->clear();
}
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);
}
@@ -1718,20 +1860,20 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
sources_list->set_h_size_flags(SIZE_EXPAND_FILL);
sources_list->set_stretch_ratio(0.25);
sources_list->set_custom_minimum_size(Size2i(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_atlas_view).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->set_drag_forwarding(this);
atlas_sources_split_container->add_child(sources_list);
+ // Tile atlas source.
tile_atlas_view = memnew(TileAtlasView);
tile_atlas_view->set_h_size_flags(SIZE_EXPAND_FILL);
tile_atlas_view->set_v_size_flags(SIZE_EXPAND_FILL);
tile_atlas_view->set_texture_grid_visible(false);
tile_atlas_view->set_tile_shape_grid_visible(false);
tile_atlas_view->connect("transform_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_atlas_view_transform));
- //tile_atlas_view->connect("visibility_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::synchronize_atlas_view), varray(tile_atlas_view));
atlas_sources_split_container->add_child(tile_atlas_view);
tile_atlas_control = memnew(Control);
@@ -1746,6 +1888,27 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
alternative_tiles_control->connect("gui_input", callable_mp(this, &TileMapEditorTilesPlugin::_tile_alternatives_control_gui_input));
tile_atlas_view->add_control_over_alternative_tiles(alternative_tiles_control);
+ // Scenes collection source.
+ scene_tiles_list = memnew(ItemList);
+ scene_tiles_list->set_h_size_flags(SIZE_EXPAND_FILL);
+ scene_tiles_list->set_v_size_flags(SIZE_EXPAND_FILL);
+ scene_tiles_list->set_drag_forwarding(this);
+ 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("nothing_selected", callable_mp(this, &TileMapEditorTilesPlugin::_scenes_list_nothing_selected));
+ scene_tiles_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
+ atlas_sources_split_container->add_child(scene_tiles_list);
+
+ // Invalid source label.
+ invalid_source_label = memnew(Label);
+ invalid_source_label->set_text(TTR("Invalid source selected."));
+ invalid_source_label->set_h_size_flags(SIZE_EXPAND_FILL);
+ invalid_source_label->set_v_size_flags(SIZE_EXPAND_FILL);
+ invalid_source_label->set_align(Label::ALIGN_CENTER);
+ invalid_source_label->set_valign(Label::VALIGN_CENTER);
+ invalid_source_label->hide();
+ atlas_sources_split_container->add_child(invalid_source_label);
+
_update_bottom_panel();
}
@@ -2771,8 +2934,8 @@ void TileMapEditorTerrainsPlugin::_update_terrains_cache() {
TileMapCell empty_cell;
empty_cell.source_id = -1;
- empty_cell.set_atlas_coords(TileSetAtlasSource::INVALID_ATLAS_COORDS);
- empty_cell.alternative_tile = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ 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);
}
}
diff --git a/editor/plugins/tiles/tile_map_editor.h b/editor/plugins/tiles/tile_map_editor.h
index f780686b82..a1fb9af3ef 100644
--- a/editor/plugins/tiles/tile_map_editor.h
+++ b/editor/plugins/tiles/tile_map_editor.h
@@ -58,7 +58,7 @@ private:
ObjectID tile_map_id;
virtual void edit(ObjectID p_tile_map_id) override;
- // Toolbar.
+ ///// Toolbar /////
HBoxContainer *toolbar;
Ref<ButtonGroup> tool_buttons_group;
@@ -84,7 +84,7 @@ private:
void _update_toolbar();
- // Tilemap editing.
+ ///// Tilemap editing. /////
bool has_mouse = false;
void _mouse_exited_viewport();
@@ -105,12 +105,12 @@ private:
Map<Vector2i, TileMapCell> drag_modified;
TileMapCell _pick_random_tile(const TileMapPattern *p_pattern);
- Map<Vector2i, TileMapCell> _draw_line(Vector2 p_start_drag_mouse_pos, Vector2 p_from_mouse_pos, Vector2i p_to_mouse_pos);
- Map<Vector2i, TileMapCell> _draw_rect(Vector2i p_start_mouse_pos, Vector2i p_end_mouse_pos);
+ Map<Vector2i, TileMapCell> _draw_line(Vector2 p_start_drag_mouse_pos, Vector2 p_from_mouse_pos, Vector2 p_to_mouse_pos);
+ Map<Vector2i, TileMapCell> _draw_rect(Vector2i p_start_cell, Vector2i p_end_cell);
Map<Vector2i, TileMapCell> _draw_bucket_fill(Vector2i p_coords, bool p_contiguous);
void _stop_dragging();
- // Selection system.
+ ///// Selection system. /////
Set<Vector2i> tile_map_selection;
TileMapPattern *tile_map_clipboard = memnew(TileMapPattern);
TileMapPattern *selection_pattern = memnew(TileMapPattern);
@@ -124,22 +124,24 @@ private:
void _update_tileset_selection_from_selection_pattern();
void _update_fix_selected_and_hovered();
- // Bottom panel.
- bool tile_set_dragging_selection = false;
- Vector2i tile_set_drag_start_mouse_pos;
-
+ ///// Bottom panel. ////.
Label *missing_source_label;
- HSplitContainer *atlas_sources_split_container;
+ Label *invalid_source_label;
ItemList *sources_list;
- TileAtlasView *tile_atlas_view;
- Ref<Texture2D> missing_texture_texture;
+
+ Ref<Texture2D> missing_atlas_texture_icon;
void _update_tile_set_sources_list();
- void _update_atlas_view();
void _update_bottom_panel();
+ // Atlas sources.
TileMapCell hovered_tile;
+ TileAtlasView *tile_atlas_view;
+ HSplitContainer *atlas_sources_split_container;
+
+ bool tile_set_dragging_selection = false;
+ Vector2i tile_set_drag_start_mouse_pos;
Control *tile_atlas_control;
void _tile_atlas_control_mouse_exited();
@@ -151,6 +153,16 @@ private:
void _tile_alternatives_control_mouse_exited();
void _tile_alternatives_control_gui_input(const Ref<InputEvent> &p_event);
+ void _update_atlas_view();
+
+ // Scenes collection sources.
+ ItemList *scene_tiles_list;
+
+ void _update_scenes_collection_view();
+ void _scene_thumbnail_done(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, Variant p_ud);
+ void _scenes_list_multi_selected(int p_index, bool p_selected);
+ void _scenes_list_nothing_selected();
+
// Update callback
virtual void tile_set_changed() override;
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
index 324e429592..b6e1a318cb 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
@@ -53,10 +53,10 @@ void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::set_id(int p_id) {
if (source_id == p_id) {
return;
}
- ERR_FAIL_COND_MSG(tile_set->has_source(p_id), vformat("Cannot change TileSet atlas source ID. Another atlas source exists with id %d.", p_id));
+ ERR_FAIL_COND_MSG(tile_set->has_source(p_id), vformat("Cannot change TileSet Atlas Source ID. Another source exists with id %d.", p_id));
int previous_source = source_id;
- source_id = p_id; // source_id must be updated before, because it's used by the atlas source list update.
+ source_id = p_id; // source_id must be updated before, because it's used by the source list update.
tile_set->set_source_id(previous_source, p_id);
emit_signal("changed", "id");
}
@@ -126,7 +126,7 @@ void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::edit(Ref<TileSet>
}
// -- Proxy object used by the tile inspector --
-bool TileSetAtlasSourceEditor::TileProxyObject::_set(const StringName &p_name, const Variant &p_value) {
+bool TileSetAtlasSourceEditor::AtlasTileProxyObject::_set(const StringName &p_name, const Variant &p_value) {
if (!tile_set_atlas_source) {
return false;
}
@@ -152,9 +152,9 @@ bool TileSetAtlasSourceEditor::TileProxyObject::_set(const StringName &p_name, c
return true;
} else if (alternative == 0 && p_name == "size_in_atlas") {
Vector2i as_vector2i = Vector2i(p_value);
- ERR_FAIL_COND_V(!tile_set_atlas_source->can_move_tile_in_atlas(coords, TileSetAtlasSource::INVALID_ATLAS_COORDS, as_vector2i), false);
+ ERR_FAIL_COND_V(!tile_set_atlas_source->can_move_tile_in_atlas(coords, TileSetSource::INVALID_ATLAS_COORDS, as_vector2i), false);
- tile_set_atlas_source->move_tile_in_atlas(coords, TileSetAtlasSource::INVALID_ATLAS_COORDS, as_vector2i);
+ tile_set_atlas_source->move_tile_in_atlas(coords, TileSetSource::INVALID_ATLAS_COORDS, as_vector2i);
emit_signal("changed", "size_in_atlas");
return true;
} else if (alternative > 0 && p_name == "alternative_id") {
@@ -197,7 +197,7 @@ bool TileSetAtlasSourceEditor::TileProxyObject::_set(const StringName &p_name, c
return any_valid;
}
-bool TileSetAtlasSourceEditor::TileProxyObject::_get(const StringName &p_name, Variant &r_ret) const {
+bool TileSetAtlasSourceEditor::AtlasTileProxyObject::_get(const StringName &p_name, Variant &r_ret) const {
if (!tile_set_atlas_source) {
return false;
}
@@ -237,7 +237,7 @@ bool TileSetAtlasSourceEditor::TileProxyObject::_get(const StringName &p_name, V
return false;
}
-void TileSetAtlasSourceEditor::TileProxyObject::_get_property_list(List<PropertyInfo> *p_list) const {
+void TileSetAtlasSourceEditor::AtlasTileProxyObject::_get_property_list(List<PropertyInfo> *p_list) const {
if (!tile_set_atlas_source) {
return;
}
@@ -310,12 +310,11 @@ void TileSetAtlasSourceEditor::TileProxyObject::_get_property_list(List<Property
}
}
-void TileSetAtlasSourceEditor::TileProxyObject::edit(TileSetAtlasSource *p_tile_set_atlas_source, int p_source_id, Set<TileSelection> p_tiles) {
+void TileSetAtlasSourceEditor::AtlasTileProxyObject::edit(TileSetAtlasSource *p_tile_set_atlas_source, Set<TileSelection> p_tiles) {
ERR_FAIL_COND(!p_tile_set_atlas_source);
- ERR_FAIL_COND(p_source_id < 0);
ERR_FAIL_COND(p_tiles.is_empty());
for (Set<TileSelection>::Element *E = p_tiles.front(); E; E = E->next()) {
- ERR_FAIL_COND(E->get().tile == TileSetAtlasSource::INVALID_ATLAS_COORDS);
+ ERR_FAIL_COND(E->get().tile == TileSetSource::INVALID_ATLAS_COORDS);
ERR_FAIL_COND(E->get().alternative < 0);
}
@@ -333,7 +332,6 @@ void TileSetAtlasSourceEditor::TileProxyObject::edit(TileSetAtlasSource *p_tile_
}
tile_set_atlas_source = p_tile_set_atlas_source;
- source_id = p_source_id;
tiles = Set<TileSelection>(p_tiles);
// Connect to changes.
@@ -352,7 +350,7 @@ void TileSetAtlasSourceEditor::TileProxyObject::edit(TileSetAtlasSource *p_tile_
notify_property_list_changed();
}
-void TileSetAtlasSourceEditor::TileProxyObject::_bind_methods() {
+void TileSetAtlasSourceEditor::AtlasTileProxyObject::_bind_methods() {
ADD_SIGNAL(MethodInfo("changed", PropertyInfo(Variant::STRING, "what")));
}
@@ -391,12 +389,12 @@ void TileSetAtlasSourceEditor::_update_fix_selected_and_hovered_tiles() {
// Fix hovered.
if (!tile_set_atlas_source->has_tile(hovered_base_tile_coords)) {
- hovered_base_tile_coords = TileSetAtlasSource::INVALID_ATLAS_COORDS;
+ hovered_base_tile_coords = TileSetSource::INVALID_ATLAS_COORDS;
}
Vector2i coords = Vector2i(hovered_alternative_tile_coords.x, hovered_alternative_tile_coords.y);
int alternative = hovered_alternative_tile_coords.z;
if (!tile_set_atlas_source->has_tile(coords) || !tile_set_atlas_source->has_alternative_tile(coords, alternative)) {
- hovered_alternative_tile_coords = Vector3i(TileSetAtlasSource::INVALID_ATLAS_COORDS.x, TileSetAtlasSource::INVALID_ATLAS_COORDS.y, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ hovered_alternative_tile_coords = Vector3i(TileSetSource::INVALID_ATLAS_COORDS.x, TileSetSource::INVALID_ATLAS_COORDS.y, TileSetSource::INVALID_TILE_ALTERNATIVE);
}
}
@@ -405,7 +403,7 @@ void TileSetAtlasSourceEditor::_update_tile_inspector() {
// Update the proxy object.
if (has_atlas_tile_selected) {
- tile_proxy_object->edit(tile_set_atlas_source, tile_set_atlas_source_id, selection);
+ tile_proxy_object->edit(tile_set_atlas_source, selection);
}
// Update visibility.
@@ -486,7 +484,7 @@ void TileSetAtlasSourceEditor::_update_toolbar() {
}
void TileSetAtlasSourceEditor::_tile_atlas_control_mouse_exited() {
- hovered_base_tile_coords = TileSetAtlasSource::INVALID_ATLAS_COORDS;
+ hovered_base_tile_coords = TileSetSource::INVALID_ATLAS_COORDS;
tile_atlas_control->update();
tile_atlas_control_unscaled->update();
tile_atlas_view->update();
@@ -514,7 +512,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven
if (selection.size() == 1) {
// Change the cursor depending on the hovered thing.
TileSelection selected = selection.front()->get();
- if (selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS && selected.alternative == 0) {
+ if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selected.alternative == 0) {
Vector2 mouse_local_pos = tile_atlas_control->get_local_mouse_position();
Vector2i size_in_atlas = tile_set_atlas_source->get_tile_size_in_atlas(selected.tile);
Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile);
@@ -560,7 +558,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven
Vector<Point2i> line = Geometry2D::bresenham_line(last_base_tiles_coords, new_base_tiles_coords);
for (int i = 0; i < line.size(); i++) {
- if (tile_set_atlas_source->get_tile_at_coords(line[i]) == TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (tile_set_atlas_source->get_tile_at_coords(line[i]) == TileSetSource::INVALID_ATLAS_COORDS) {
tile_set_atlas_source->create_tile(line[i]);
drag_modified_tiles.insert(line[i]);
}
@@ -576,7 +574,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven
Vector<Point2i> line = Geometry2D::bresenham_line(last_base_tiles_coords, new_base_tiles_coords);
for (int i = 0; i < line.size(); i++) {
Vector2i base_tile_coords = tile_set_atlas_source->get_tile_at_coords(line[i]);
- if (base_tile_coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (base_tile_coords != TileSetSource::INVALID_ATLAS_COORDS) {
drag_modified_tiles.insert(base_tile_coords);
}
}
@@ -662,17 +660,17 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven
// Remove a first tile.
Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
coords = tile_set_atlas_source->get_tile_at_coords(coords);
}
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
drag_modified_tiles.insert(coords);
}
} else {
if (mb->is_shift_pressed()) {
// Create a big tile.
Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
// Setup the dragging info, only if we start on an empty tile.
drag_type = DRAG_TYPE_CREATE_BIG_TILE;
drag_start_mouse_pos = mouse_local_pos;
@@ -692,7 +690,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven
// Create a first tile if needed.
Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
tile_set_atlas_source->create_tile(coords);
drag_modified_tiles.insert(coords);
}
@@ -710,7 +708,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven
if (mb->is_shift_pressed()) {
// Create a big tile.
Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS && tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
// Setup the dragging info, only if we start on an empty tile.
drag_type = DRAG_TYPE_CREATE_BIG_TILE;
drag_start_mouse_pos = mouse_local_pos;
@@ -732,7 +730,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven
drag_type = DRAG_TYPE_NONE;
if (selection.size() == 1) {
TileSelection selected = selection.front()->get();
- if (selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS && selected.alternative == 0) {
+ if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selected.alternative == 0) {
Vector2i size_in_atlas = tile_set_atlas_source->get_tile_size_in_atlas(selected.tile);
Rect2 region = tile_set_atlas_source->get_tile_texture_region(selected.tile);
Size2 zoomed_size = resize_handle->get_size() / tile_atlas_view->get_zoom();
@@ -771,17 +769,17 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven
// Selecting then dragging a tile.
if (drag_type == DRAG_TYPE_NONE) {
- TileSelection selected = { TileSetAtlasSource::INVALID_ATLAS_COORDS, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE };
+ TileSelection selected = { TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE };
Vector2i coords = tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
coords = tile_set_atlas_source->get_tile_at_coords(coords);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
selected = { coords, 0 };
}
}
bool shift = mb->is_shift_pressed();
- if (!shift && selection.size() == 1 && selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS && selection.has(selected)) {
+ if (!shift && selection.size() == 1 && selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selection.has(selected)) {
// Start move dragging.
drag_type = DRAG_TYPE_MOVE_TILE;
drag_start_mouse_pos = mouse_local_pos;
@@ -812,13 +810,13 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven
// Right click pressed.
TileSelection selected = { tile_atlas_view->get_atlas_tile_coords_at_pos(mouse_local_pos), 0 };
- if (selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) {
selected.tile = tile_set_atlas_source->get_tile_at_coords(selected.tile);
}
// Set the selection if needed.
if (selection.size() <= 1) {
- if (selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) {
undo_redo->create_action(TTR("Select tiles"));
undo_redo->add_undo_method(this, "_set_selection_from_array", _get_selection_as_array());
selection.clear();
@@ -831,15 +829,15 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_gui_input(const Ref<InputEven
}
// Pops up the correct menu, depending on whether we have a tile or not.
- if (selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS && selection.has(selected)) {
+ if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS && selection.has(selected)) {
// We have a tile.
menu_option_coords = selected.tile;
menu_option_alternative = 0;
base_tile_popup_menu->popup(Rect2i(get_global_mouse_position(), Size2i()));
- } else if (hovered_base_tile_coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ } else if (hovered_base_tile_coords != TileSetSource::INVALID_ATLAS_COORDS) {
// We don't have a tile, but can create one.
menu_option_coords = hovered_base_tile_coords;
- menu_option_alternative = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ menu_option_alternative = TileSetSource::INVALID_TILE_ALTERNATIVE;
empty_base_tile_popup_menu->popup(Rect2i(get_global_mouse_position(), Size2i()));
}
} else {
@@ -902,7 +900,7 @@ void TileSetAtlasSourceEditor::_end_dragging() {
for (int x = area.get_position().x; x < area.get_end().x; x++) {
for (int y = area.get_position().y; y < area.get_end().y; y++) {
Vector2i coords = Vector2i(x, y);
- if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
undo_redo->add_do_method(tile_set_atlas_source, "create_tile", coords);
undo_redo->add_undo_method(tile_set_atlas_source, "remove_tile", coords);
}
@@ -923,7 +921,7 @@ void TileSetAtlasSourceEditor::_end_dragging() {
for (int x = area.get_position().x; x < area.get_end().x; x++) {
for (int y = area.get_position().y; y < area.get_end().y; y++) {
Vector2i coords = tile_set_atlas_source->get_tile_at_coords(Vector2i(x, y));
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
to_delete.insert(coords);
}
}
@@ -964,8 +962,8 @@ void TileSetAtlasSourceEditor::_end_dragging() {
case DRAG_TYPE_RECT_SELECT: {
Vector2i start_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(drag_start_mouse_pos);
Vector2i new_base_tiles_coords = tile_atlas_view->get_atlas_tile_coords_at_pos(tile_atlas_control->get_local_mouse_position());
- ERR_FAIL_COND(start_base_tiles_coords == TileSetAtlasSource::INVALID_ATLAS_COORDS);
- ERR_FAIL_COND(new_base_tiles_coords == TileSetAtlasSource::INVALID_ATLAS_COORDS);
+ ERR_FAIL_COND(start_base_tiles_coords == TileSetSource::INVALID_ATLAS_COORDS);
+ ERR_FAIL_COND(new_base_tiles_coords == TileSetSource::INVALID_ATLAS_COORDS);
Rect2i region = Rect2i(start_base_tiles_coords, new_base_tiles_coords - start_base_tiles_coords).abs();
region.size += Vector2i(1, 1);
@@ -977,7 +975,7 @@ void TileSetAtlasSourceEditor::_end_dragging() {
bool add_to_selection = true;
if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
Vector2i coords = tile_set_atlas_source->get_tile_at_coords(start_base_tiles_coords);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
if (selection.has({ coords, 0 })) {
add_to_selection = false;
}
@@ -991,7 +989,7 @@ void TileSetAtlasSourceEditor::_end_dragging() {
for (int y = region.position.y; y < region.get_end().y; y++) {
Vector2i coords = Vector2i(x, y);
coords = tile_set_atlas_source->get_tile_at_coords(coords);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
if (add_to_selection && !selection.has({ coords, 0 })) {
selection.insert({ coords, 0 });
} else if (!add_to_selection && selection.has({ coords, 0 })) {
@@ -1243,7 +1241,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
for (int x = area.get_position().x; x < area.get_end().x; x++) {
for (int y = area.get_position().y; y < area.get_end().y; y++) {
Vector2i coords = tile_set_atlas_source->get_tile_at_coords(Vector2i(x, y));
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
to_paint.insert(coords);
}
}
@@ -1266,7 +1264,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
for (int x = area.get_position().x; x < area.get_end().x; x++) {
for (int y = area.get_position().y; y < area.get_end().y; y++) {
Vector2i coords = Vector2i(x, y);
- if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
Vector2i origin = margins + (coords * (tile_size + separation));
tile_atlas_control->draw_rect(Rect2i(origin, tile_size), Color(1.0, 1.0, 1.0), false);
}
@@ -1290,7 +1288,7 @@ void TileSetAtlasSourceEditor::_tile_atlas_control_draw() {
Vector2i grid_size = tile_set_atlas_source->get_atlas_grid_size();
if (hovered_base_tile_coords.x >= 0 && hovered_base_tile_coords.y >= 0 && hovered_base_tile_coords.x < grid_size.x && hovered_base_tile_coords.y < grid_size.y) {
Vector2i hovered_tile = tile_set_atlas_source->get_tile_at_coords(hovered_base_tile_coords);
- if (hovered_tile != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (hovered_tile != TileSetSource::INVALID_ATLAS_COORDS) {
// Draw existing hovered tile.
tile_atlas_control->draw_rect(tile_set_atlas_source->get_tile_texture_region(hovered_tile), Color(1.0, 1.0, 1.0), false);
} else {
@@ -1349,7 +1347,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In
selection.clear();
TileSelection selected = { Vector2i(tile.x, tile.y), int(tile.z) };
- if (selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) {
selection.insert(selected);
}
@@ -1364,7 +1362,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In
selection.clear();
TileSelection selected = { Vector2i(tile.x, tile.y), int(tile.z) };
- if (selected.tile != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) {
selection.insert(selected);
}
@@ -1387,7 +1385,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In
}
void TileSetAtlasSourceEditor::_tile_alternatives_control_mouse_exited() {
- hovered_alternative_tile_coords = Vector3i(TileSetAtlasSource::INVALID_ATLAS_COORDS.x, TileSetAtlasSource::INVALID_ATLAS_COORDS.y, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ hovered_alternative_tile_coords = Vector3i(TileSetSource::INVALID_ATLAS_COORDS.x, TileSetSource::INVALID_ATLAS_COORDS.y, TileSetSource::INVALID_TILE_ALTERNATIVE);
tile_atlas_control->update();
tile_atlas_control_unscaled->update();
alternative_tiles_control->update();
@@ -1399,7 +1397,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_draw() {
if (tools_button_group->get_pressed_button() == tool_select_button) {
// Draw hovered tile.
Vector2i coords = Vector2(hovered_alternative_tile_coords.x, hovered_alternative_tile_coords.y);
- if (coords != TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (coords != TileSetSource::INVALID_ATLAS_COORDS) {
Rect2i rect = tile_atlas_view->get_alternative_tile_rect(coords, hovered_alternative_tile_coords.z);
if (rect != Rect2i()) {
alternative_tiles_control->draw_rect(rect, Color(1.0, 1.0, 1.0), false);
@@ -1441,7 +1439,7 @@ void TileSetAtlasSourceEditor::_undo_redo_inspector_callback(Object *p_undo_redo
#define ADD_UNDO(obj, property) undo_redo->add_undo_property(obj, property, tile_data->get(property));
- TileProxyObject *tile_data = Object::cast_to<TileProxyObject>(p_edited);
+ AtlasTileProxyObject *tile_data = Object::cast_to<AtlasTileProxyObject>(p_edited);
if (tile_data) {
Vector<String> components = String(p_property).split("/", true, 2);
if (components.size() == 2 && components[1] == "shapes_count") {
@@ -1518,7 +1516,7 @@ void TileSetAtlasSourceEditor::_auto_create_tiles() {
for (int x = 0; x < grid_size.x; x++) {
// Check if we have a tile at the coord
Vector2i coords = Vector2i(x, y);
- if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetAtlasSource::INVALID_ATLAS_COORDS) {
+ if (tile_set_atlas_source->get_tile_at_coords(coords) == TileSetSource::INVALID_ATLAS_COORDS) {
// Check if the texture is empty at the given coords.
Rect2i region = Rect2i(margins + (coords * (texture_region_size + separation)), texture_region_size);
bool is_opaque = false;
@@ -1673,7 +1671,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() {
tile_inspector_label->hide();
middle_vbox_container->add_child(tile_inspector_label);
- tile_proxy_object = memnew(TileProxyObject(this));
+ tile_proxy_object = memnew(AtlasTileProxyObject(this));
tile_proxy_object->connect("changed", callable_mp(this, &TileSetAtlasSourceEditor::_update_atlas_view).unbind(1));
tile_inspector = memnew(EditorInspector);
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.h b/editor/plugins/tiles/tile_set_atlas_source_editor.h
index ff68aa8288..70f2cdbe01 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.h
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.h
@@ -45,8 +45,8 @@ class TileSetAtlasSourceEditor : public HBoxContainer {
private:
// A class to store which tiles are selected.
struct TileSelection {
- Vector2i tile = TileSetAtlasSource::INVALID_ATLAS_COORDS;
- int alternative = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ Vector2i tile = TileSetSource::INVALID_ATLAS_COORDS;
+ int alternative = TileSetSource::INVALID_TILE_ALTERNATIVE;
bool operator<(const TileSelection &p_other) const {
if (tile == p_other.tile) {
@@ -80,14 +80,13 @@ private:
};
// -- Proxy object for a tile, needed by the inspector --
- class TileProxyObject : public Object {
- GDCLASS(TileProxyObject, Object);
+ class AtlasTileProxyObject : public Object {
+ GDCLASS(AtlasTileProxyObject, Object);
private:
TileSetAtlasSourceEditor *tiles_set_atlas_source_editor;
TileSetAtlasSource *tile_set_atlas_source = nullptr;
- int source_id;
Set<TileSelection> tiles = Set<TileSelection>();
protected:
@@ -99,10 +98,10 @@ private:
public:
// Update the proxyed object.
- void edit(TileSetAtlasSource *p_tile_set_atlas_source, int p_source_id = -1, Set<TileSelection> p_tiles = Set<TileSelection>());
+ void edit(TileSetAtlasSource *p_tile_set_atlas_source, Set<TileSelection> p_tiles = Set<TileSelection>());
- TileProxyObject(TileSetAtlasSourceEditor *p_tiles_editor_source_tab) {
- tiles_set_atlas_source_editor = p_tiles_editor_source_tab;
+ AtlasTileProxyObject(TileSetAtlasSourceEditor *p_tiles_set_atlas_source_editor) {
+ tiles_set_atlas_source_editor = p_tiles_set_atlas_source_editor;
}
};
@@ -115,7 +114,7 @@ private:
bool tile_set_atlas_source_changed_needs_update = false;
// -- Inspector --
- TileProxyObject *tile_proxy_object;
+ AtlasTileProxyObject *tile_proxy_object;
Label *tile_inspector_label;
EditorInspector *tile_inspector;
String selected_property;
@@ -175,7 +174,7 @@ private:
ADVANCED_AUTO_REMOVE_TILES,
};
Vector2i menu_option_coords;
- int menu_option_alternative = TileSetAtlasSource::INVALID_TILE_ALTERNATIVE;
+ int menu_option_alternative = TileSetSource::INVALID_TILE_ALTERNATIVE;
void _menu_option(int p_option);
// Tool buttons.
@@ -198,7 +197,7 @@ private:
Array _get_selection_as_array();
// A control on the tile atlas to draw and handle input events.
- Vector2i hovered_base_tile_coords = TileSetAtlasSource::INVALID_ATLAS_COORDS;
+ Vector2i hovered_base_tile_coords = TileSetSource::INVALID_ATLAS_COORDS;
PopupMenu *base_tile_popup_menu;
PopupMenu *empty_base_tile_popup_menu;
@@ -213,7 +212,7 @@ private:
void _tile_atlas_view_transform_changed();
// A control over the alternative tiles.
- Vector3i hovered_alternative_tile_coords = Vector3i(TileSetAtlasSource::INVALID_ATLAS_COORDS.x, TileSetAtlasSource::INVALID_ATLAS_COORDS.y, TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+ Vector3i hovered_alternative_tile_coords = Vector3i(TileSetSource::INVALID_ATLAS_COORDS.x, TileSetSource::INVALID_ATLAS_COORDS.y, TileSetSource::INVALID_TILE_ALTERNATIVE);
PopupMenu *alternative_tile_popup_menu;
Control *alternative_tiles_control;
diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp
index 5573fae670..05ebe408a5 100644
--- a/editor/plugins/tiles/tile_set_editor.cpp
+++ b/editor/plugins/tiles/tile_set_editor.cpp
@@ -140,20 +140,39 @@ void TileSetEditor::_update_atlas_sources_list(int force_selected_id) {
for (int i = 0; i < tile_set->get_source_count(); i++) {
int source_id = tile_set->get_source_id(i);
- // TODO: handle with virtual functions
TileSetSource *source = *tile_set->get_source(source_id);
+
+ Ref<Texture2D> texture;
+ String item_text;
+
+ // Atlas source.
TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
if (atlas_source) {
- Ref<Texture2D> texture = atlas_source->get_texture();
+ texture = atlas_source->get_texture();
if (texture.is_valid()) {
- sources_list->add_item(vformat("%s - (id:%d)", texture->get_path().get_file(), source_id), texture);
+ item_text = vformat("%s (id:%d)", texture->get_path().get_file(), source_id);
} else {
- sources_list->add_item(vformat("No texture atlas source - (id:%d)", source_id), missing_texture_texture);
+ item_text = vformat(TTR("No Texture Atlas Source (id:%d)"), source_id);
}
- } else {
- sources_list->add_item(vformat("Unknown type source - (id:%d)", source_id), missing_texture_texture);
}
- sources_list->set_item_metadata(sources_list->get_item_count() - 1, source_id);
+
+ // Scene collection source.
+ TileSetScenesCollectionSource *scene_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source);
+ if (scene_collection_source) {
+ texture = get_theme_icon("PackedScene", "EditorIcons");
+ item_text = vformat(TTR("Scene Collection Source (id:%d)"), source_id);
+ }
+
+ // Use default if not valid.
+ if (item_text.is_empty()) {
+ item_text = vformat(TTR("Unknown Type Source (id:%d)"), source_id);
+ }
+ if (!texture.is_valid()) {
+ texture = missing_texture_texture;
+ }
+
+ sources_list->add_item(item_text, texture);
+ sources_list->set_item_metadata(i, source_id);
}
// Set again the current selected item if needed.
@@ -193,35 +212,63 @@ void TileSetEditor::_source_selected(int p_source_index) {
if (p_source_index >= 0) {
int source_id = sources_list->get_item_metadata(p_source_index);
TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(*tile_set->get_source(source_id));
+ TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(*tile_set->get_source(source_id));
if (atlas_source) {
- tile_set_atlas_source_editor->edit(*tile_set, atlas_source, source_id);
no_source_selected_label->hide();
+ tile_set_atlas_source_editor->edit(*tile_set, atlas_source, source_id);
tile_set_atlas_source_editor->show();
+ tile_set_scenes_collection_source_editor->hide();
+ } else if (scenes_collection_source) {
+ no_source_selected_label->hide();
+ tile_set_atlas_source_editor->hide();
+ tile_set_scenes_collection_source_editor->edit(*tile_set, scenes_collection_source, source_id);
+ tile_set_scenes_collection_source_editor->show();
} else {
no_source_selected_label->show();
tile_set_atlas_source_editor->hide();
+ tile_set_scenes_collection_source_editor->hide();
}
} else {
no_source_selected_label->show();
tile_set_atlas_source_editor->hide();
+ tile_set_scenes_collection_source_editor->hide();
}
}
-void TileSetEditor::_source_add_pressed() {
+void TileSetEditor::_source_add_id_pressed(int p_id_pressed) {
ERR_FAIL_COND(!tile_set.is_valid());
- int source_id = tile_set->get_next_source_id();
+ switch (p_id_pressed) {
+ case 0: {
+ int source_id = tile_set->get_next_source_id();
- Ref<TileSetAtlasSource> atlas_source = memnew(TileSetAtlasSource);
+ Ref<TileSetAtlasSource> atlas_source = memnew(TileSetAtlasSource);
- // Add a new source.
- undo_redo->create_action(TTR("Add atlas source"));
- undo_redo->add_do_method(*tile_set, "add_source", atlas_source, source_id);
- undo_redo->add_do_method(*atlas_source, "set_texture_region_size", tile_set->get_tile_size());
- undo_redo->add_undo_method(*tile_set, "remove_source", source_id);
- undo_redo->commit_action();
+ // Add a new source.
+ undo_redo->create_action(TTR("Add atlas source"));
+ undo_redo->add_do_method(*tile_set, "add_source", atlas_source, source_id);
+ undo_redo->add_do_method(*atlas_source, "set_texture_region_size", tile_set->get_tile_size());
+ undo_redo->add_undo_method(*tile_set, "remove_source", source_id);
+ undo_redo->commit_action();
+
+ _update_atlas_sources_list(source_id);
+ } break;
+ case 1: {
+ int source_id = tile_set->get_next_source_id();
+
+ Ref<TileSetScenesCollectionSource> scene_collection_source = memnew(TileSetScenesCollectionSource);
- _update_atlas_sources_list(source_id);
+ // Add a new source.
+ undo_redo->create_action(TTR("Add atlas source"));
+ undo_redo->add_do_method(*tile_set, "add_source", scene_collection_source, source_id);
+ undo_redo->add_undo_method(*tile_set, "remove_source", source_id);
+ undo_redo->commit_action();
+
+ _update_atlas_sources_list(source_id);
+ } break;
+ default:
+ ERR_FAIL();
+ }
}
void TileSetEditor::_source_delete_pressed() {
@@ -434,6 +481,7 @@ void TileSetEditor::edit(Ref<TileSet> p_tile_set) {
}
tile_set_atlas_source_editor->hide();
+ tile_set_scenes_collection_source_editor->hide();
no_source_selected_label->show();
}
@@ -464,6 +512,7 @@ TileSetEditor::TileSetEditor() {
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->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
sources_list->set_drag_forwarding(this);
split_container_left_side->add_child(sources_list);
@@ -477,11 +526,19 @@ TileSetEditor::TileSetEditor() {
sources_delete_button->connect("pressed", callable_mp(this, &TileSetEditor::_source_delete_pressed));
sources_bottom_actions->add_child(sources_delete_button);
- sources_add_button = memnew(Button);
+ sources_add_button = memnew(MenuButton);
sources_add_button->set_flat(true);
- sources_add_button->connect("pressed", callable_mp(this, &TileSetEditor::_source_add_pressed));
+ sources_add_button->get_popup()->add_item(TTR("Atlas"));
+ sources_add_button->get_popup()->add_item(TTR("Scenes Collection"));
+ sources_add_button->get_popup()->connect("id_pressed", callable_mp(this, &TileSetEditor::_source_add_id_pressed));
sources_bottom_actions->add_child(sources_add_button);
+ // Right side container.
+ VBoxContainer *split_container_right_side = memnew(VBoxContainer);
+ split_container_right_side->set_h_size_flags(SIZE_EXPAND_FILL);
+ split_container_right_side->set_v_size_flags(SIZE_EXPAND_FILL);
+ split_container->add_child(split_container_right_side);
+
// No source selected.
no_source_selected_label = memnew(Label);
no_source_selected_label->set_text(TTR("No TileSet source selected. Select or create a TileSet source."));
@@ -489,16 +546,24 @@ TileSetEditor::TileSetEditor() {
no_source_selected_label->set_v_size_flags(SIZE_EXPAND_FILL);
no_source_selected_label->set_align(Label::ALIGN_CENTER);
no_source_selected_label->set_valign(Label::VALIGN_CENTER);
- split_container->add_child(no_source_selected_label);
+ split_container_right_side->add_child(no_source_selected_label);
// Atlases editor.
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));
- split_container->add_child(tile_set_atlas_source_editor);
+ split_container_right_side->add_child(tile_set_atlas_source_editor);
tile_set_atlas_source_editor->hide();
+ // Scenes collection editor.
+ 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));
+ split_container_right_side->add_child(tile_set_scenes_collection_source_editor);
+ tile_set_scenes_collection_source_editor->hide();
+
// Registers UndoRedo inspector callback.
EditorNode::get_singleton()->get_editor_data().add_undo_redo_inspector_hook_callback(callable_mp(this, &TileSetEditor::_undo_redo_inspector_callback));
}
diff --git a/editor/plugins/tiles/tile_set_editor.h b/editor/plugins/tiles/tile_set_editor.h
index c4aebb40a2..d508c04319 100644
--- a/editor/plugins/tiles/tile_set_editor.h
+++ b/editor/plugins/tiles/tile_set_editor.h
@@ -35,6 +35,7 @@
#include "scene/resources/tile_set.h"
#include "tile_data_editors.h"
#include "tile_set_atlas_source_editor.h"
+#include "tile_set_scenes_collection_source_editor.h"
class TileSetEditor : public VBoxContainer {
GDCLASS(TileSetEditor, VBoxContainer);
@@ -47,6 +48,7 @@ private:
Label *no_source_selected_label;
TileSetAtlasSourceEditor *tile_set_atlas_source_editor;
+ TileSetScenesCollectionSourceEditor *tile_set_scenes_collection_source_editor;
UndoRedo *undo_redo = EditorNode::get_undo_redo();
@@ -64,11 +66,11 @@ private:
// -- Sources management --
Button *sources_delete_button;
- Button *sources_add_button;
+ MenuButton *sources_add_button;
ItemList *sources_list;
Ref<Texture2D> missing_texture_texture;
void _source_selected(int p_source_index);
- void _source_add_pressed();
+ void _source_add_id_pressed(int p_id_pressed);
void _source_delete_pressed();
void _tile_set_changed();
diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
new file mode 100644
index 0000000000..568d4ca8d7
--- /dev/null
+++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
@@ -0,0 +1,511 @@
+/*************************************************************************/
+/* tile_set_scenes_collection_source_editor.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_set_scenes_collection_source_editor.h"
+
+#include "editor/editor_resource_preview.h"
+#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
+
+#include "scene/gui/item_list.h"
+
+#include "core/core_string_names.h"
+
+void TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::set_id(int p_id) {
+ ERR_FAIL_COND(p_id < 0);
+ if (source_id == p_id) {
+ return;
+ }
+ ERR_FAIL_COND_MSG(tile_set->has_source(p_id), vformat("Cannot change TileSet Scenes Collection source ID. Another TileSet source exists with id %d.", p_id));
+
+ int previous_source = source_id;
+ source_id = p_id; // source_id must be updated before, because it's used by the source list update.
+ tile_set->set_source_id(previous_source, p_id);
+ emit_signal("changed", "id");
+}
+
+int TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::get_id() {
+ return source_id;
+}
+
+bool TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::_set(const StringName &p_name, const Variant &p_value) {
+ bool valid = false;
+ tile_set_scenes_collection_source->set(p_name, p_value, &valid);
+ if (valid) {
+ emit_signal("changed", String(p_name).utf8().get_data());
+ }
+ return valid;
+}
+
+bool TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::_get(const StringName &p_name, Variant &r_ret) const {
+ if (!tile_set_scenes_collection_source) {
+ return false;
+ }
+ bool valid = false;
+ r_ret = tile_set_scenes_collection_source->get(p_name, &valid);
+ return valid;
+}
+
+void TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::_bind_methods() {
+ // -- Shape and layout --
+ ClassDB::bind_method(D_METHOD("set_id", "id"), &TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::set_id);
+ ClassDB::bind_method(D_METHOD("get_id"), &TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::get_id);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "id"), "set_id", "get_id");
+
+ ADD_SIGNAL(MethodInfo("changed", PropertyInfo(Variant::STRING, "what")));
+}
+
+void TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::edit(Ref<TileSet> p_tile_set, TileSetScenesCollectionSource *p_tile_set_scenes_collection_source, int p_source_id) {
+ ERR_FAIL_COND(!p_tile_set.is_valid());
+ ERR_FAIL_COND(!p_tile_set_scenes_collection_source);
+ ERR_FAIL_COND(p_source_id < 0);
+ ERR_FAIL_COND(p_tile_set->get_source(p_source_id) != p_tile_set_scenes_collection_source);
+
+ // Disconnect to changes.
+ if (tile_set_scenes_collection_source) {
+ tile_set_scenes_collection_source->disconnect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed));
+ }
+
+ tile_set = p_tile_set;
+ tile_set_scenes_collection_source = p_tile_set_scenes_collection_source;
+ source_id = p_source_id;
+
+ // Connect to changes.
+ if (tile_set_scenes_collection_source) {
+ if (!tile_set_scenes_collection_source->is_connected(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed))) {
+ tile_set_scenes_collection_source->connect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed));
+ }
+ }
+
+ notify_property_list_changed();
+}
+
+// -- Proxy object used by the tile inspector --
+bool TileSetScenesCollectionSourceEditor::SceneTileProxyObject::_set(const StringName &p_name, const Variant &p_value) {
+ if (!tile_set_scenes_collection_source) {
+ return false;
+ }
+
+ if (p_name == "id") {
+ int as_int = int(p_value);
+ ERR_FAIL_COND_V(as_int < 0, false);
+ ERR_FAIL_COND_V(tile_set_scenes_collection_source->has_scene_tile_id(as_int), false);
+ tile_set_scenes_collection_source->set_scene_tile_id(scene_id, as_int);
+ scene_id = as_int;
+ emit_signal("changed", "id");
+ for (int i = 0; i < tile_set_scenes_collection_source_editor->scene_tiles_list->get_item_count(); i++) {
+ if (int(tile_set_scenes_collection_source_editor->scene_tiles_list->get_item_metadata(i)) == scene_id) {
+ tile_set_scenes_collection_source_editor->scene_tiles_list->select(i);
+ break;
+ }
+ }
+ return true;
+ } else if (p_name == "scene") {
+ tile_set_scenes_collection_source->set_scene_tile_scene(scene_id, p_value);
+ emit_signal("changed", "scene");
+ return true;
+ } else if (p_name == "display_placeholder") {
+ tile_set_scenes_collection_source->set_scene_tile_display_placeholder(scene_id, p_value);
+ emit_signal("changed", "display_placeholder");
+ return true;
+ }
+
+ return false;
+}
+
+bool TileSetScenesCollectionSourceEditor::SceneTileProxyObject::_get(const StringName &p_name, Variant &r_ret) const {
+ if (!tile_set_scenes_collection_source) {
+ return false;
+ }
+
+ if (p_name == "id") {
+ r_ret = scene_id;
+ return true;
+ } else if (p_name == "scene") {
+ r_ret = tile_set_scenes_collection_source->get_scene_tile_scene(scene_id);
+ return true;
+ } else if (p_name == "display_placeholder") {
+ r_ret = tile_set_scenes_collection_source->get_scene_tile_display_placeholder(scene_id);
+ return true;
+ }
+
+ return false;
+}
+
+void TileSetScenesCollectionSourceEditor::SceneTileProxyObject::_get_property_list(List<PropertyInfo> *p_list) const {
+ if (!tile_set_scenes_collection_source) {
+ return;
+ }
+
+ p_list->push_back(PropertyInfo(Variant::INT, "id", PROPERTY_HINT_NONE, ""));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "scene", PROPERTY_HINT_RESOURCE_TYPE, "PackedScene"));
+ p_list->push_back(PropertyInfo(Variant::BOOL, "display_placeholder", PROPERTY_HINT_NONE, ""));
+}
+
+void TileSetScenesCollectionSourceEditor::SceneTileProxyObject::edit(TileSetScenesCollectionSource *p_tile_set_scenes_collection_source, int p_scene_id) {
+ ERR_FAIL_COND(!p_tile_set_scenes_collection_source);
+ ERR_FAIL_COND(!p_tile_set_scenes_collection_source->has_scene_tile_id(p_scene_id));
+
+ tile_set_scenes_collection_source = p_tile_set_scenes_collection_source;
+ scene_id = p_scene_id;
+
+ notify_property_list_changed();
+}
+
+void TileSetScenesCollectionSourceEditor::SceneTileProxyObject::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("changed", PropertyInfo(Variant::STRING, "what")));
+}
+
+void TileSetScenesCollectionSourceEditor::_scenes_collection_source_proxy_object_changed(String p_what) {
+ if (p_what == "id") {
+ emit_signal("source_id_changed", scenes_collection_source_proxy_object->get_id());
+ }
+}
+
+void TileSetScenesCollectionSourceEditor::_tile_set_scenes_collection_source_changed() {
+ tile_set_scenes_collection_source_changed_needs_update = true;
+}
+
+void TileSetScenesCollectionSourceEditor::_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()) {
+ scene_tiles_list->set_item_icon(index, p_preview);
+ }
+}
+
+void TileSetScenesCollectionSourceEditor::_scenes_list_item_activated(int p_index) {
+ Ref<PackedScene> packed_scene = tile_set_scenes_collection_source->get_scene_tile_scene(scene_tiles_list->get_item_metadata(p_index));
+ if (packed_scene.is_valid()) {
+ EditorNode::get_singleton()->open_request(packed_scene->get_path());
+ }
+}
+
+void TileSetScenesCollectionSourceEditor::_source_add_pressed() {
+ int scene_id = tile_set_scenes_collection_source->get_next_scene_tile_id();
+ undo_redo->create_action(TTR("Add a Scene Tile"));
+ undo_redo->add_do_method(tile_set_scenes_collection_source, "create_scene_tile", Ref<PackedScene>(), scene_id);
+ undo_redo->add_undo_method(tile_set_scenes_collection_source, "remove_scene_tile", scene_id);
+ undo_redo->commit_action();
+ _update_scenes_list();
+ _update_action_buttons();
+ _update_tile_inspector();
+}
+
+void TileSetScenesCollectionSourceEditor::_source_delete_pressed() {
+ Vector<int> selected_indices = scene_tiles_list->get_selected_items();
+ ERR_FAIL_COND(selected_indices.size() <= 0);
+ int scene_id = scene_tiles_list->get_item_metadata(selected_indices[0]);
+
+ undo_redo->create_action(TTR("Remove a Scene Tile"));
+ undo_redo->add_do_method(tile_set_scenes_collection_source, "remove_scene_tile", scene_id);
+ undo_redo->add_undo_method(tile_set_scenes_collection_source, "create_scene_tile", tile_set_scenes_collection_source->get_scene_tile_scene(scene_id), scene_id);
+ undo_redo->commit_action();
+ _update_scenes_list();
+ _update_action_buttons();
+ _update_tile_inspector();
+}
+
+void TileSetScenesCollectionSourceEditor::_update_source_inspector() {
+ // Update the proxy object.
+ scenes_collection_source_proxy_object->edit(tile_set, tile_set_scenes_collection_source, tile_set_source_id);
+}
+
+void TileSetScenesCollectionSourceEditor::_update_tile_inspector() {
+ Vector<int> selected_indices = scene_tiles_list->get_selected_items();
+ bool has_atlas_tile_selected = (selected_indices.size() > 0);
+
+ // Update the proxy object.
+ if (has_atlas_tile_selected) {
+ int scene_id = scene_tiles_list->get_item_metadata(selected_indices[0]);
+ tile_proxy_object->edit(tile_set_scenes_collection_source, scene_id);
+ }
+
+ // Update visibility.
+ tile_inspector_label->set_visible(has_atlas_tile_selected);
+ tile_inspector->set_visible(has_atlas_tile_selected);
+}
+
+void TileSetScenesCollectionSourceEditor::_update_action_buttons() {
+ Vector<int> selected_indices = scene_tiles_list->get_selected_items();
+ scene_tile_delete_button->set_disabled(selected_indices.size() <= 0);
+}
+
+void TileSetScenesCollectionSourceEditor::_update_scenes_list() {
+ if (!tile_set_scenes_collection_source) {
+ return;
+ }
+
+ // Get the previously selected id.
+ Vector<int> selected_indices = scene_tiles_list->get_selected_items();
+ int old_selected_scene_id = (selected_indices.size() > 0) ? int(scene_tiles_list->get_item_metadata(selected_indices[0])) : -1;
+
+ // Clear the list.
+ scene_tiles_list->clear();
+
+ // Rebuild the list.
+ int to_reselect = -1;
+ for (int i = 0; i < tile_set_scenes_collection_source->get_scene_tiles_count(); i++) {
+ int scene_id = tile_set_scenes_collection_source->get_scene_tile_id(i);
+
+ Ref<PackedScene> scene = tile_set_scenes_collection_source->get_scene_tile_scene(scene_id);
+
+ int item_index = 0;
+ if (scene.is_valid()) {
+ item_index = scene_tiles_list->add_item(vformat("%s (path:%s id:%d)", scene->get_path().get_file().get_basename(), scene->get_path(), scene_id));
+ Variant udata = i;
+ EditorResourcePreview::get_singleton()->queue_edited_resource_preview(scene, this, "_scene_thumbnail_done", udata);
+ } else {
+ item_index = scene_tiles_list->add_item(TTR("Tile with Invalid Scene"), get_theme_icon("PackedScene", "EditorIcons"));
+ }
+ scene_tiles_list->set_item_metadata(item_index, scene_id);
+
+ if (old_selected_scene_id >= 0 && scene_id == old_selected_scene_id) {
+ to_reselect = i;
+ }
+ }
+
+ // Reselect if needed.
+ if (to_reselect >= 0) {
+ scene_tiles_list->select(to_reselect);
+ }
+
+ // Icon size update.
+ int int_size = int(EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size")) * EDSCALE;
+ scene_tiles_list->set_fixed_icon_size(Vector2(int_size, int_size));
+}
+
+void TileSetScenesCollectionSourceEditor::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED:
+ scene_tile_add_button->set_icon(get_theme_icon("Add", "EditorIcons"));
+ scene_tile_delete_button->set_icon(get_theme_icon("Remove", "EditorIcons"));
+ _update_scenes_list();
+ break;
+ case NOTIFICATION_INTERNAL_PROCESS:
+ if (tile_set_scenes_collection_source_changed_needs_update) {
+ // Update everything.
+ _update_source_inspector();
+ _update_scenes_list();
+ _update_action_buttons();
+ _update_tile_inspector();
+ tile_set_scenes_collection_source_changed_needs_update = false;
+ }
+ break;
+ case NOTIFICATION_VISIBILITY_CHANGED:
+ // Update things just in case.
+ _update_scenes_list();
+ _update_action_buttons();
+ break;
+ default:
+ break;
+ }
+}
+
+void TileSetScenesCollectionSourceEditor::edit(Ref<TileSet> p_tile_set, TileSetScenesCollectionSource *p_tile_set_scenes_collection_source, int p_source_id) {
+ ERR_FAIL_COND(!p_tile_set.is_valid());
+ ERR_FAIL_COND(!p_tile_set_scenes_collection_source);
+ ERR_FAIL_COND(p_source_id < 0);
+ ERR_FAIL_COND(p_tile_set->get_source(p_source_id) != p_tile_set_scenes_collection_source);
+
+ if (p_tile_set == tile_set && p_tile_set_scenes_collection_source == tile_set_scenes_collection_source && p_source_id == tile_set_source_id) {
+ return;
+ }
+
+ // Remove listener for old objects.
+ if (tile_set_scenes_collection_source) {
+ tile_set_scenes_collection_source->disconnect("changed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_tile_set_scenes_collection_source_changed));
+ }
+
+ // Change the edited object.
+ tile_set = p_tile_set;
+ tile_set_scenes_collection_source = p_tile_set_scenes_collection_source;
+ tile_set_source_id = p_source_id;
+
+ // Add the listener again.
+ if (tile_set_scenes_collection_source) {
+ tile_set_scenes_collection_source->connect("changed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_tile_set_scenes_collection_source_changed));
+ }
+
+ // Update everything.
+ _update_source_inspector();
+ _update_scenes_list();
+ _update_action_buttons();
+ _update_tile_inspector();
+}
+
+void TileSetScenesCollectionSourceEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
+ if (!can_drop_data_fw(p_point, p_data, p_from)) {
+ return;
+ }
+
+ if (p_from == scene_tiles_list) {
+ // Handle dropping a texture in the list of atlas resources.
+ int scene_id = -1;
+ Dictionary d = p_data;
+ Vector<String> files = d["files"];
+ for (int i = 0; i < files.size(); i++) {
+ Ref<PackedScene> resource = ResourceLoader::load(files[i]);
+ if (resource.is_valid()) {
+ scene_id = tile_set_scenes_collection_source->get_next_scene_tile_id();
+ undo_redo->create_action(TTR("Add a Scene Tile"));
+ undo_redo->add_do_method(tile_set_scenes_collection_source, "create_scene_tile", resource, scene_id);
+ undo_redo->add_undo_method(tile_set_scenes_collection_source, "remove_scene_tile", scene_id);
+ undo_redo->commit_action();
+ }
+ }
+
+ _update_scenes_list();
+ _update_action_buttons();
+ _update_tile_inspector();
+ }
+}
+
+bool TileSetScenesCollectionSourceEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
+ if (p_from == scene_tiles_list) {
+ Dictionary d = p_data;
+
+ if (!d.has("type")) {
+ return false;
+ }
+
+ // Check if we have a Texture2D.
+ if (String(d["type"]) == "files") {
+ Vector<String> files = d["files"];
+
+ if (files.size() == 0) {
+ return false;
+ }
+
+ for (int i = 0; i < files.size(); i++) {
+ String file = files[i];
+ String ftype = EditorFileSystem::get_singleton()->get_file_type(file);
+
+ if (!ClassDB::is_parent_class(ftype, "PackedScene")) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+ return false;
+}
+
+void TileSetScenesCollectionSourceEditor::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("source_id_changed", PropertyInfo(Variant::INT, "source_id")));
+
+ ClassDB::bind_method(D_METHOD("_scene_thumbnail_done"), &TileSetScenesCollectionSourceEditor::_scene_thumbnail_done);
+ ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &TileSetScenesCollectionSourceEditor::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("drop_data_fw"), &TileSetScenesCollectionSourceEditor::drop_data_fw);
+}
+
+TileSetScenesCollectionSourceEditor::TileSetScenesCollectionSourceEditor() {
+ // -- Right side --
+ HSplitContainer *split_container_right_side = memnew(HSplitContainer);
+ split_container_right_side->set_h_size_flags(SIZE_EXPAND_FILL);
+ add_child(split_container_right_side);
+
+ // Middle panel.
+ ScrollContainer *middle_panel = memnew(ScrollContainer);
+ middle_panel->set_enable_h_scroll(false);
+ middle_panel->set_custom_minimum_size(Size2i(200, 0) * EDSCALE);
+ split_container_right_side->add_child(middle_panel);
+
+ VBoxContainer *middle_vbox_container = memnew(VBoxContainer);
+ middle_vbox_container->set_h_size_flags(SIZE_EXPAND_FILL);
+ middle_panel->add_child(middle_vbox_container);
+
+ // Scenes collection source inspector.
+ scenes_collection_source_inspector_label = memnew(Label);
+ scenes_collection_source_inspector_label->set_text(TTR("Scenes collection properties:"));
+ middle_vbox_container->add_child(scenes_collection_source_inspector_label);
+
+ scenes_collection_source_proxy_object = memnew(TileSetScenesCollectionProxyObject());
+ scenes_collection_source_proxy_object->connect("changed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_scenes_collection_source_proxy_object_changed));
+
+ scenes_collection_source_inspector = memnew(EditorInspector);
+ scenes_collection_source_inspector->set_undo_redo(undo_redo);
+ scenes_collection_source_inspector->set_enable_v_scroll(false);
+ scenes_collection_source_inspector->edit(scenes_collection_source_proxy_object);
+ middle_vbox_container->add_child(scenes_collection_source_inspector);
+
+ // Tile inspector.
+ tile_inspector_label = memnew(Label);
+ tile_inspector_label->set_text(TTR("Tile properties:"));
+ tile_inspector_label->hide();
+ middle_vbox_container->add_child(tile_inspector_label);
+
+ tile_proxy_object = memnew(SceneTileProxyObject(this));
+ tile_proxy_object->connect("changed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_update_scenes_list).unbind(1));
+ tile_proxy_object->connect("changed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_update_action_buttons).unbind(1));
+
+ tile_inspector = memnew(EditorInspector);
+ tile_inspector->set_undo_redo(undo_redo);
+ tile_inspector->set_enable_v_scroll(false);
+ tile_inspector->edit(tile_proxy_object);
+ tile_inspector->set_use_folding(true);
+ middle_vbox_container->add_child(tile_inspector);
+
+ // Scenes list.
+ VBoxContainer *right_vbox_container = memnew(VBoxContainer);
+ split_container_right_side->add_child(right_vbox_container);
+
+ scene_tiles_list = memnew(ItemList);
+ scene_tiles_list->set_h_size_flags(SIZE_EXPAND_FILL);
+ scene_tiles_list->set_v_size_flags(SIZE_EXPAND_FILL);
+ scene_tiles_list->set_drag_forwarding(this);
+ scene_tiles_list->connect("item_selected", callable_mp(this, &TileSetScenesCollectionSourceEditor::_update_tile_inspector).unbind(1));
+ scene_tiles_list->connect("item_selected", callable_mp(this, &TileSetScenesCollectionSourceEditor::_update_action_buttons).unbind(1));
+ scene_tiles_list->connect("item_activated", callable_mp(this, &TileSetScenesCollectionSourceEditor::_scenes_list_item_activated));
+ scene_tiles_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
+ right_vbox_container->add_child(scene_tiles_list);
+
+ HBoxContainer *scenes_bottom_actions = memnew(HBoxContainer);
+ right_vbox_container->add_child(scenes_bottom_actions);
+
+ scene_tile_add_button = memnew(Button);
+ scene_tile_add_button->set_flat(true);
+ scene_tile_add_button->connect("pressed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_source_add_pressed));
+ scenes_bottom_actions->add_child(scene_tile_add_button);
+
+ scene_tile_delete_button = memnew(Button);
+ scene_tile_delete_button->set_flat(true);
+ scene_tile_delete_button->set_disabled(true);
+ scene_tile_delete_button->connect("pressed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_source_delete_pressed));
+ scenes_bottom_actions->add_child(scene_tile_delete_button);
+}
+
+TileSetScenesCollectionSourceEditor::~TileSetScenesCollectionSourceEditor() {
+ memdelete(scenes_collection_source_proxy_object);
+ memdelete(tile_proxy_object);
+}
diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h
new file mode 100644
index 0000000000..195aa79bc4
--- /dev/null
+++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h
@@ -0,0 +1,139 @@
+/*************************************************************************/
+/* tile_set_scenes_collection_source_editor.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_SET_SCENES_COLLECTION_SOURCE_EDITOR_H
+#define TILE_SET_SCENES_COLLECTION_SOURCE_EDITOR_H
+
+#include "editor/editor_node.h"
+#include "scene/gui/box_container.h"
+#include "scene/resources/tile_set.h"
+
+class TileSetScenesCollectionSourceEditor : public HBoxContainer {
+ GDCLASS(TileSetScenesCollectionSourceEditor, HBoxContainer);
+
+private:
+ // -- Proxy object for an atlas source, needed by the inspector --
+ class TileSetScenesCollectionProxyObject : public Object {
+ GDCLASS(TileSetScenesCollectionProxyObject, Object);
+
+ private:
+ Ref<TileSet> tile_set;
+ TileSetScenesCollectionSource *tile_set_scenes_collection_source = nullptr;
+ int source_id = -1;
+
+ protected:
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+ static void _bind_methods();
+
+ public:
+ void set_id(int p_id);
+ int get_id();
+
+ void edit(Ref<TileSet> p_tile_set, TileSetScenesCollectionSource *p_tile_set_scenes_collection_source, int p_source_id);
+ };
+
+ // -- Proxy object for a tile, needed by the inspector --
+ class SceneTileProxyObject : public Object {
+ GDCLASS(SceneTileProxyObject, Object);
+
+ private:
+ TileSetScenesCollectionSourceEditor *tile_set_scenes_collection_source_editor;
+
+ TileSetScenesCollectionSource *tile_set_scenes_collection_source = nullptr;
+ int source_id;
+ int scene_id;
+
+ protected:
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+ void _get_property_list(List<PropertyInfo> *p_list) const;
+
+ static void _bind_methods();
+
+ public:
+ // Update the proxyed object.
+ void edit(TileSetScenesCollectionSource *p_tile_set_atlas_source, int p_scene_id);
+
+ SceneTileProxyObject(TileSetScenesCollectionSourceEditor *p_tiles_set_scenes_collection_source_editor) {
+ tile_set_scenes_collection_source_editor = p_tiles_set_scenes_collection_source_editor;
+ }
+ };
+
+private:
+ Ref<TileSet> tile_set;
+ TileSetScenesCollectionSource *tile_set_scenes_collection_source = nullptr;
+ int tile_set_source_id = -1;
+
+ UndoRedo *undo_redo = EditorNode::get_undo_redo();
+
+ bool tile_set_scenes_collection_source_changed_needs_update = false;
+
+ // Source inspector.
+ TileSetScenesCollectionProxyObject *scenes_collection_source_proxy_object;
+ Label *scenes_collection_source_inspector_label;
+ EditorInspector *scenes_collection_source_inspector;
+
+ // Tile inspector.
+ SceneTileProxyObject *tile_proxy_object;
+ Label *tile_inspector_label;
+ EditorInspector *tile_inspector;
+
+ ItemList *scene_tiles_list;
+ Button *scene_tile_add_button;
+ Button *scene_tile_delete_button;
+
+ void _tile_set_scenes_collection_source_changed();
+ void _scenes_collection_source_proxy_object_changed(String p_what);
+ void _scene_thumbnail_done(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, Variant p_ud);
+ void _scenes_list_item_activated(int p_index);
+
+ void _source_add_pressed();
+ void _source_delete_pressed();
+
+ // Update methods.
+ void _update_source_inspector();
+ void _update_tile_inspector();
+ void _update_scenes_list();
+ void _update_action_buttons();
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ void edit(Ref<TileSet> p_tile_set, TileSetScenesCollectionSource *p_tile_set_scenes_collection_source, int p_source_id);
+ void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
+ bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
+ TileSetScenesCollectionSourceEditor();
+ ~TileSetScenesCollectionSourceEditor();
+};
+
+#endif