Fixed compile when layered tile maps are enabled.

This commit is contained in:
Relintai 2024-03-07 18:57:18 +01:00
parent 27b73fa9f9
commit adea98943c
9 changed files with 170 additions and 104 deletions

View File

@ -3773,6 +3773,8 @@ void LayeredTileMapLayerEditor::_notification(int p_what) {
void LayeredTileMapLayerEditor::_bind_methods() {
ADD_SIGNAL(MethodInfo("change_selected_layer_request", PropertyInfo(Variant::STRING_NAME, "layer_name")));
ClassDB::bind_method(D_METHOD("update_layers_selector"), &LayeredTileMapLayerEditor::update_layers_selector);
ClassDB::bind_method(D_METHOD("_tile_map_layer_changed"), &LayeredTileMapLayerEditor::_tile_map_layer_changed);
ClassDB::bind_method(D_METHOD("_tab_changed"), &LayeredTileMapLayerEditor::_tab_changed);
ClassDB::bind_method(D_METHOD("_layers_selection_item_selected"), &LayeredTileMapLayerEditor::_layers_selection_item_selected);

View File

@ -47,6 +47,7 @@
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/item_list.h"
#include "scene/gui/popup_menu.h"
#include "scene/gui/separator.h"
@ -178,7 +179,7 @@ bool LayeredTileSetAtlasSourceEditor::LayeredAtlasTileProxyObject::_set(const St
if (alternative == 0) {
Vector<String> components = String(p_name).split("/", true, 2);
if (p_name == "atlas_coords") {
Vector2i as_vector2i = Vector2i(p_value);
Vector2i as_vector2i = p_value;
bool has_room_for_tile = tile_set_atlas_source->has_room_for_tile(as_vector2i, tile_set_atlas_source->get_tile_size_in_atlas(coords), tile_set_atlas_source->get_tile_animation_columns(coords), tile_set_atlas_source->get_tile_animation_separation(coords), tile_set_atlas_source->get_tile_animation_frames_count(coords), coords);
ERR_FAIL_COND_V_MSG(!has_room_for_tile, false, "Cannot move the tile, invalid coordinates or not enough room in the atlas for the tile and its animation frames.");
@ -194,7 +195,7 @@ bool LayeredTileSetAtlasSourceEditor::LayeredAtlasTileProxyObject::_set(const St
emit_signal("changed", "atlas_coords");
return true;
} else if (p_name == "size_in_atlas") {
Vector2i as_vector2i = Vector2i(p_value);
Vector2i as_vector2i = p_value;
bool has_room_for_tile = tile_set_atlas_source->has_room_for_tile(coords, as_vector2i, tile_set_atlas_source->get_tile_animation_columns(coords), tile_set_atlas_source->get_tile_animation_separation(coords), tile_set_atlas_source->get_tile_animation_frames_count(coords), coords);
ERR_FAIL_COND_V_MSG(!has_room_for_tile, false, "Invalid size or not enough room in the atlas for the tile.");
tile_set_atlas_source->move_tile_in_atlas(coords, LayeredTileSetSource::INVALID_ATLAS_COORDS, as_vector2i);

View File

@ -42,6 +42,7 @@ class Popup;
class LayeredTileSet;
class Tree;
class VSeparator;
class ConfirmationDialog;
class LayeredTileSetAtlasSourceEditor : public HSplitContainer {
GDCLASS(LayeredTileSetAtlasSourceEditor, HSplitContainer);

View File

@ -472,7 +472,13 @@ void LayeredTileSetEditor::_update_patterns_list() {
int id = patterns_item_list->get_item_count() - 1;
patterns_item_list->set_item_metadata(id, tile_set->get_pattern(i));
patterns_item_list->set_item_tooltip(id, vformat(TTR("Index: %d"), i));
LayeredTilesEditorUtils::get_singleton()->queue_pattern_preview(tile_set, tile_set->get_pattern(i), this, "_pattern_preview_done");
Ref<FuncRef> fref;
fref.instance();
fref->set_instance(this);
fref->set_function("_pattern_preview_done");
LayeredTilesEditorUtils::get_singleton()->queue_pattern_preview(tile_set, tile_set->get_pattern(i), fref);
}
// Update the label visibility.

View File

@ -60,13 +60,17 @@ void LayeredTileSetScenesCollectionSourceEditor::LayeredTileSetScenesCollectionP
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(SNAME("changed"), "id");
emit_signal("changed", "id");
}
int LayeredTileSetScenesCollectionSourceEditor::LayeredTileSetScenesCollectionProxyObject::get_id() {
return source_id;
}
void LayeredTileSetScenesCollectionSourceEditor::LayeredTileSetScenesCollectionProxyObject::_changed_callback(Object *p_changed, const char *p_prop) {
property_list_changed_notify();
}
bool LayeredTileSetScenesCollectionSourceEditor::LayeredTileSetScenesCollectionProxyObject::_set(const StringName &p_name, const Variant &p_value) {
String name = p_name;
if (name == "name") {
@ -76,7 +80,7 @@ bool LayeredTileSetScenesCollectionSourceEditor::LayeredTileSetScenesCollectionP
bool valid = false;
tile_set_scenes_collection_source->set(name, p_value, &valid);
if (valid) {
emit_signal(SNAME("changed"), String(name).utf8().get_data());
emit_signal("changed", String(name).utf8().get_data());
}
return valid;
}
@ -121,7 +125,7 @@ void LayeredTileSetScenesCollectionSourceEditor::LayeredTileSetScenesCollectionP
// 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::property_list_changed_notify));
tile_set_scenes_collection_source->remove_change_receptor(this);
}
tile_set = p_tile_set;
@ -130,9 +134,8 @@ void LayeredTileSetScenesCollectionSourceEditor::LayeredTileSetScenesCollectionP
// 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::property_list_changed_notify))) {
tile_set_scenes_collection_source->connect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::property_list_changed_notify));
}
tile_set_scenes_collection_source->remove_change_receptor(this);
tile_set_scenes_collection_source->add_change_receptor(this);
}
property_list_changed_notify();
@ -150,7 +153,7 @@ bool LayeredTileSetScenesCollectionSourceEditor::LayeredSceneTileProxyObject::_s
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(SNAME("changed"), "id");
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);
@ -160,11 +163,11 @@ bool LayeredTileSetScenesCollectionSourceEditor::LayeredSceneTileProxyObject::_s
return true;
} else if (p_name == "scene") {
tile_set_scenes_collection_source->set_scene_tile_scene(scene_id, p_value);
emit_signal(SNAME("changed"), "scene");
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(SNAME("changed"), "display_placeholder");
emit_signal("changed", "display_placeholder");
return true;
}
@ -220,7 +223,7 @@ void LayeredTileSetScenesCollectionSourceEditor::LayeredSceneTileProxyObject::_b
void LayeredTileSetScenesCollectionSourceEditor::_scenes_collection_source_proxy_object_changed(const String &p_what) {
if (p_what == "id") {
emit_signal(SNAME("source_id_changed"), scenes_collection_source_proxy_object->get_id());
emit_signal("source_id_changed", scenes_collection_source_proxy_object->get_id());
}
}
@ -247,14 +250,14 @@ void LayeredTileSetScenesCollectionSourceEditor::_source_add_pressed() {
if (!scene_select_dialog) {
scene_select_dialog = memnew(EditorFileDialog);
add_child(scene_select_dialog);
scene_select_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
scene_select_dialog->connect("file_selected", callable_mp(this, &LayeredTileSetScenesCollectionSourceEditor::_scene_file_selected));
scene_select_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
scene_select_dialog->connect("file_selected", this, "_scene_file_selected");
for (const String &E : Vector<String>{ "tscn", "scn" }) {
scene_select_dialog->add_filter("*." + E, E.to_upper());
}
scene_select_dialog->add_filter("*.tscn;TSCN");
scene_select_dialog->add_filter("*.scn;SCN");
}
scene_select_dialog->popup_file_dialog();
scene_select_dialog->popup_centered_ratio();
}
void LayeredTileSetScenesCollectionSourceEditor::_scene_file_selected(const String &p_path) {
@ -308,7 +311,7 @@ void LayeredTileSetScenesCollectionSourceEditor::_update_tile_inspector() {
void LayeredTileSetScenesCollectionSourceEditor::_update_action_buttons() {
Vector<int> selected_indices = scene_tiles_list->get_selected_items();
scene_tile_delete_button->set_disabled(selected_indices.size() <= 0 || read_only);
scene_tile_delete_button->set_disabled(selected_indices.size() <= 0);
}
void LayeredTileSetScenesCollectionSourceEditor::_update_scenes_list() {
@ -332,11 +335,13 @@ void LayeredTileSetScenesCollectionSourceEditor::_update_scenes_list() {
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));
scene_tiles_list->add_item(vformat("%s (path:%s id:%d)", scene->get_path().get_file().get_basename(), scene->get_path(), scene_id));
item_index = scene_tiles_list->get_item_count() - 1;
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(SNAME("PackedScene"), "EditorIcons"));
scene_tiles_list->add_item(TTR("Tile with Invalid Scene"), get_theme_icon("PackedScene", "EditorIcons"));
item_index = scene_tiles_list->get_item_count() - 1;
}
scene_tiles_list->set_item_metadata(item_index, scene_id);
@ -363,29 +368,28 @@ void LayeredTileSetScenesCollectionSourceEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
scenes_collection_source_inspector->edit(scenes_collection_source_proxy_object);
/*
scenes_collection_source_inspector->add_custom_property_description("LayeredTileSetScenesCollectionProxyObject", "id", TTR("The tile's unique identifier within this LayeredTileSet. Each tile stores its source ID, so changing one may make tiles invalid."));
scenes_collection_source_inspector->add_custom_property_description("LayeredTileSetScenesCollectionProxyObject", "name", TTR("The human-readable name for the scene collection. Use a descriptive name here for organizational purposes (such as \"obstacles\", \"decoration\", etc.)."));
*/
tile_inspector->edit(tile_proxy_object);
/*
tile_inspector->add_custom_property_description("LayeredSceneTileProxyObject", "id", TTR("ID of the scene tile in the collection. Each painted tile has associated ID, so changing this property may cause your LayeredTileMaps to not display properly."));
tile_inspector->add_custom_property_description("LayeredSceneTileProxyObject", "scene", TTR("Absolute path to the scene associated with this tile."));
tile_inspector->add_custom_property_description("LayeredSceneTileProxyObject", "display_placeholder", TTR("If [code]true[/code], a placeholder marker will be displayed on top of the scene's preview. The marker is displayed anyway if the scene has no valid preview."));
*/
} break;
case NOTIFICATION_THEME_CHANGED: {
scene_tile_add_button->set_icon(get_theme_icon(SNAME("Add"), "EditorIcons"));
scene_tile_delete_button->set_icon(get_theme_icon(SNAME("Remove"), "EditorIcons"));
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) {
read_only = false;
// Add the listener again and check for read-only status.
if (tile_set.is_valid()) {
read_only = EditorNode::get_singleton()->is_resource_read_only(tile_set);
}
// Update everything.
_update_source_inspector();
_update_scenes_list();
@ -409,18 +413,13 @@ void LayeredTileSetScenesCollectionSourceEditor::edit(Ref<LayeredTileSet> p_tile
ERR_FAIL_COND(p_source_id < 0);
ERR_FAIL_COND(p_tile_set->get_source(p_source_id) != p_tile_set_scenes_collection_source);
bool new_read_only_state = false;
if (p_tile_set.is_valid()) {
new_read_only_state = EditorNode::get_singleton()->is_resource_read_only(p_tile_set);
}
if (p_tile_set == tile_set && p_tile_set_scenes_collection_source == tile_set_scenes_collection_source && p_source_id == tile_set_source_id && new_read_only_state == read_only) {
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(CoreStringNames::get_singleton()->changed, callable_mp(this, &LayeredTileSetScenesCollectionSourceEditor::_tile_set_scenes_collection_source_changed));
tile_set_scenes_collection_source->disconnect(CoreStringNames::get_singleton()->changed, this, "_tile_set_scenes_collection_source_changed");
}
// Change the edited object.
@ -428,19 +427,16 @@ void LayeredTileSetScenesCollectionSourceEditor::edit(Ref<LayeredTileSet> p_tile
tile_set_scenes_collection_source = p_tile_set_scenes_collection_source;
tile_set_source_id = p_source_id;
// Read-only status is false by default
read_only = new_read_only_state;
if (tile_set.is_valid()) {
scenes_collection_source_inspector->set_read_only(read_only);
tile_inspector->set_read_only(read_only);
scenes_collection_source_inspector->set_read_only(false);
tile_inspector->set_read_only(false);
scene_tile_add_button->set_disabled(read_only);
scene_tile_add_button->set_disabled(false);
}
// Add the listener again.
if (tile_set_scenes_collection_source) {
tile_set_scenes_collection_source->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &LayeredTileSetScenesCollectionSourceEditor::_tile_set_scenes_collection_source_changed));
tile_set_scenes_collection_source->connect(CoreStringNames::get_singleton()->changed, this, "_tile_set_scenes_collection_source_changed");
}
// Update everything.
@ -507,10 +503,32 @@ bool LayeredTileSetScenesCollectionSourceEditor::_can_drop_data_fw(const Point2
return false;
}
void LayeredTileSetScenesCollectionSourceEditor::_tile_proxy_object_changed(const String &p_what) {
_update_scenes_list();
_update_action_buttons();
}
void LayeredTileSetScenesCollectionSourceEditor::_scene_tiles_list_item_selected(int p_index) {
_update_tile_inspector();
_update_action_buttons();
}
void LayeredTileSetScenesCollectionSourceEditor::_bind_methods() {
ADD_SIGNAL(MethodInfo("source_id_changed", PropertyInfo(Variant::INT, "source_id")));
ClassDB::bind_method(D_METHOD("_scene_thumbnail_done"), &LayeredTileSetScenesCollectionSourceEditor::_scene_thumbnail_done);
ClassDB::bind_method(D_METHOD("_scene_file_selected"), &LayeredTileSetScenesCollectionSourceEditor::_scene_file_selected);
ClassDB::bind_method(D_METHOD("_tile_set_scenes_collection_source_changed"), &LayeredTileSetScenesCollectionSourceEditor::_tile_set_scenes_collection_source_changed);
ClassDB::bind_method(D_METHOD("_drop_data_fw"), &LayeredTileSetScenesCollectionSourceEditor::_drop_data_fw);
ClassDB::bind_method(D_METHOD("_can_drop_data_fw"), &LayeredTileSetScenesCollectionSourceEditor::_can_drop_data_fw);
ClassDB::bind_method(D_METHOD("_scenes_collection_source_proxy_object_changed"), &LayeredTileSetScenesCollectionSourceEditor::_scenes_collection_source_proxy_object_changed);
ClassDB::bind_method(D_METHOD("_tile_proxy_object_changed"), &LayeredTileSetScenesCollectionSourceEditor::_tile_proxy_object_changed);
ClassDB::bind_method(D_METHOD("_scenes_list_item_activated"), &LayeredTileSetScenesCollectionSourceEditor::_scenes_list_item_activated);
ClassDB::bind_method(D_METHOD("_source_add_pressed"), &LayeredTileSetScenesCollectionSourceEditor::_source_add_pressed);
ClassDB::bind_method(D_METHOD("_source_delete_pressed"), &LayeredTileSetScenesCollectionSourceEditor::_source_delete_pressed);
}
LayeredTileSetScenesCollectionSourceEditor::LayeredTileSetScenesCollectionSourceEditor() {
@ -521,7 +539,7 @@ LayeredTileSetScenesCollectionSourceEditor::LayeredTileSetScenesCollectionSource
// Middle panel.
ScrollContainer *middle_panel = memnew(ScrollContainer);
middle_panel->set_horizontal_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
middle_panel->set_enable_h_scroll(false);
middle_panel->set_custom_minimum_size(Size2(200, 0) * EDSCALE);
split_container_right_side->add_child(middle_panel);
@ -535,10 +553,10 @@ LayeredTileSetScenesCollectionSourceEditor::LayeredTileSetScenesCollectionSource
middle_vbox_container->add_child(scenes_collection_source_inspector_label);
scenes_collection_source_proxy_object = memnew(LayeredTileSetScenesCollectionProxyObject());
scenes_collection_source_proxy_object->connect("changed", callable_mp(this, &LayeredTileSetScenesCollectionSourceEditor::_scenes_collection_source_proxy_object_changed));
scenes_collection_source_proxy_object->connect("changed", this, "_scenes_collection_source_proxy_object_changed");
scenes_collection_source_inspector = memnew(EditorInspector);
scenes_collection_source_inspector->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
scenes_collection_source_inspector->set_enable_h_scroll(false);
scenes_collection_source_inspector->set_use_doc_hints(true);
scenes_collection_source_inspector->add_inspector_plugin(memnew(LayeredTileSourceInspectorPlugin));
middle_vbox_container->add_child(scenes_collection_source_inspector);
@ -550,11 +568,10 @@ LayeredTileSetScenesCollectionSourceEditor::LayeredTileSetScenesCollectionSource
middle_vbox_container->add_child(tile_inspector_label);
tile_proxy_object = memnew(LayeredSceneTileProxyObject(this));
tile_proxy_object->connect("changed", callable_mp(this, &LayeredTileSetScenesCollectionSourceEditor::_update_scenes_list).unbind(1));
tile_proxy_object->connect("changed", callable_mp(this, &LayeredTileSetScenesCollectionSourceEditor::_update_action_buttons).unbind(1));
tile_proxy_object->connect("changed", this, "_update_scenes_list");
tile_inspector = memnew(EditorInspector);
tile_inspector->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
tile_inspector->set_enable_v_scroll(false);
tile_inspector->set_use_doc_hints(true);
tile_inspector->set_use_folding(true);
middle_vbox_container->add_child(tile_inspector);
@ -564,14 +581,13 @@ LayeredTileSetScenesCollectionSourceEditor::LayeredTileSetScenesCollectionSource
split_container_right_side->add_child(right_vbox_container);
scene_tiles_list = memnew(ItemList);
scene_tiles_list->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
scene_tiles_list->set_h_size_flags(SIZE_EXPAND_FILL);
scene_tiles_list->set_v_size_flags(SIZE_EXPAND_FILL);
SET_DRAG_FORWARDING_CDU(scene_tiles_list, LayeredTileSetScenesCollectionSourceEditor);
scene_tiles_list->connect("item_selected", callable_mp(this, &LayeredTileSetScenesCollectionSourceEditor::_update_tile_inspector).unbind(1));
scene_tiles_list->connect("item_selected", callable_mp(this, &LayeredTileSetScenesCollectionSourceEditor::_update_action_buttons).unbind(1));
scene_tiles_list->connect("item_activated", callable_mp(this, &LayeredTileSetScenesCollectionSourceEditor::_scenes_list_item_activated));
scene_tiles_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
scene_tiles_list->set_drag_forwarding(this);
scene_tiles_list->connect("item_selected", this, "_scene_tiles_list_item_selected");
scene_tiles_list->connect("item_activated", this, "_scenes_list_item_activated");
right_vbox_container->add_child(scene_tiles_list);
HBoxContainer *scenes_bottom_actions = memnew(HBoxContainer);
@ -579,13 +595,13 @@ LayeredTileSetScenesCollectionSourceEditor::LayeredTileSetScenesCollectionSource
scene_tile_add_button = memnew(Button);
scene_tile_add_button->set_theme_type_variation("FlatButton");
scene_tile_add_button->connect("pressed", callable_mp(this, &LayeredTileSetScenesCollectionSourceEditor::_source_add_pressed));
scene_tile_add_button->connect("pressed", this, "_source_add_pressed");
scenes_bottom_actions->add_child(scene_tile_add_button);
scene_tile_delete_button = memnew(Button);
scene_tile_delete_button->set_theme_type_variation("FlatButton");
scene_tile_delete_button->set_disabled(true);
scene_tile_delete_button->connect("pressed", callable_mp(this, &LayeredTileSetScenesCollectionSourceEditor::_source_delete_pressed));
scene_tile_delete_button->connect("pressed", this, "_source_delete_pressed");
scenes_bottom_actions->add_child(scene_tile_delete_button);
}

View File

@ -55,6 +55,8 @@ private:
int source_id = -1;
protected:
void _changed_callback(Object *p_changed, const char *p_prop);
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;
@ -95,8 +97,6 @@ private:
};
private:
bool read_only = false;
Ref<LayeredTileSet> tile_set;
LayeredTileSetScenesCollectionSource *tile_set_scenes_collection_source = nullptr;
int tile_set_source_id = -1;
@ -135,6 +135,9 @@ private:
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;
void _tile_proxy_object_changed(const String &p_what);
void _scene_tiles_list_item_selected(int p_index);
protected:
void _notification(int p_what);

View File

@ -44,8 +44,10 @@
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/popup_menu.h"
#include "scene/gui/separator.h"
#include "scene/main/control.h"
#include "scene/main/viewport.h"
#include "scene/resources/texture.h"
LayeredTilesEditorUtils *LayeredTilesEditorUtils::singleton = nullptr;
@ -53,16 +55,15 @@ LayeredTileMapEditorPlugin *tile_map_plugin_singleton = nullptr;
LayeredTileSetEditorPlugin *tile_set_plugin_singleton = nullptr;
void LayeredTilesEditorUtils::_preview_frame_started() {
RS::get_singleton()->request_frame_drawn_callback(callable_mp(const_cast<LayeredTilesEditorUtils *>(this), &LayeredTilesEditorUtils::_pattern_preview_done));
RS::get_singleton()->request_frame_drawn_callback(this, "_pattern_preview_done", Variant());
}
void LayeredTilesEditorUtils::_pattern_preview_done() {
void LayeredTilesEditorUtils::_pattern_preview_done(const Variant &p_userdata) {
pattern_preview_done.post();
}
void LayeredTilesEditorUtils::_thread_func(void *ud) {
LayeredTilesEditorUtils *te = static_cast<LayeredTilesEditorUtils *>(ud);
set_current_thread_safe_for_nodes(true);
te->_thread();
}
@ -85,11 +86,11 @@ void LayeredTilesEditorUtils::_thread() {
if (item.pattern.is_valid() && !item.pattern->empty()) {
// Generate the pattern preview
SubViewport *viewport = memnew(SubViewport);
Viewport *viewport = memnew(Viewport);
viewport->set_size(thumbnail_size2);
viewport->set_disable_input(true);
viewport->set_transparent_background(true);
viewport->set_update_mode(SubViewport::UPDATE_ONCE);
viewport->set_update_mode(Viewport::UPDATE_ONCE);
LayeredTileMap *tile_map = memnew(LayeredTileMap);
tile_map->set_tileset(item.tile_set);
@ -124,31 +125,43 @@ void LayeredTilesEditorUtils::_thread() {
tile_map->set_position(-(scale * encompassing_rect.get_center()) + thumbnail_size2 / 2);
// Add the viewport at the last moment to avoid rendering too early.
callable_mp((Node *)EditorNode::get_singleton(), &Node::add_child).call_deferred(viewport, false, Node::INTERNAL_MODE_DISABLED);
RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<LayeredTilesEditorUtils *>(this), &LayeredTilesEditorUtils::_preview_frame_started), Object::CONNECT_ONE_SHOT);
EditorNode::get_singleton()->call_deferred("add_child", viewport);
RS::get_singleton()->connect("frame_pre_draw", this, "_preview_frame_started", varray(), Object::CONNECT_ONESHOT);
pattern_preview_done.wait();
Ref<Image> image = viewport->get_texture()->get_image();
Ref<Image> image = viewport->get_texture()->get_data();
// Find the index for the given pattern. TODO: optimize.
item.callback.call(item.pattern, ImageTexture::create_from_image(image));
Ref<ImageTexture> tex;
tex.instance();
tex->create_from_image(image);
viewport->queue_free();
Array arr;
arr.push_back(item.pattern);
arr.push_back(tex);
item.callback->call_funcv(arr);
viewport->queue_delete();
}
}
}
pattern_thread_exited.set();
}
void LayeredTilesEditorUtils::queue_pattern_preview(Ref<LayeredTileSet> p_tile_set, Ref<LayeredTileMapPattern> p_pattern, Callable p_callback) {
void LayeredTilesEditorUtils::queue_pattern_preview(Ref<LayeredTileSet> p_tile_set, Ref<LayeredTileMapPattern> p_pattern, Ref<FuncRef> p_callback) {
ERR_FAIL_COND(!p_tile_set.is_valid());
ERR_FAIL_COND(!p_pattern.is_valid());
{
MutexLock lock(pattern_preview_mutex);
pattern_preview_queue.push_back({ p_tile_set, p_pattern, p_callback });
}
pattern_preview_sem.post();
}
@ -171,15 +184,15 @@ void LayeredTilesEditorUtils::synchronize_sources_list(Object *p_current_list, O
if (item_list->is_visible_in_tree()) {
// Make sure the selection is not overwritten after sorting.
int atlas_sources_lists_current_mem = atlas_sources_lists_current;
item_list->emit_signal(SNAME("sort_request"));
item_list->emit_signal("sort_request");
atlas_sources_lists_current = atlas_sources_lists_current_mem;
if (atlas_sources_lists_current < 0 || atlas_sources_lists_current >= item_list->get_item_count()) {
item_list->deselect_all();
item_list->unselect_all();
} else {
item_list->set_current(atlas_sources_lists_current);
item_list->ensure_current_is_visible();
item_list->emit_signal(SNAME("item_selected"), atlas_sources_lists_current);
item_list->emit_signal("item_selected", atlas_sources_lists_current);
}
}
}
@ -213,14 +226,14 @@ List<int> LayeredTilesEditorUtils::get_sorted_sources(const Ref<LayeredTileSet>
switch (source_sort) {
case SOURCE_SORT_ID_REVERSE:
// Already sorted.
source_ids.reverse();
source_ids.invert();
break;
case SOURCE_SORT_NAME:
source_ids.sort_custom<SourceNameComparator>();
break;
case SOURCE_SORT_NAME_REVERSE:
source_ids.sort_custom<SourceNameComparator>();
source_ids.reverse();
source_ids.invert();
break;
default: // SOURCE_SORT_ID
break;
@ -285,7 +298,7 @@ void LayeredTilesEditorUtils::display_tile_set_editor_panel() {
}
void LayeredTilesEditorUtils::draw_selection_rect(CanvasItem *p_ci, const Rect2 &p_rect, const Color &p_color) {
Ref<Texture> selection_texture = EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("TileSelection"), EditorStringName(EditorIcons));
Ref<Texture> selection_texture = EditorNode::get_singleton()->get_editor_theme()->get_icon("TileSelection", "EditorIcons");
real_t scale = p_ci->get_global_transform().get_scale().x * 0.5;
p_ci->draw_set_transform(p_rect.position, 0, Vector2(1, 1) / scale);
@ -319,6 +332,8 @@ void LayeredTilesEditorUtils::_bind_methods() {
ClassDB::bind_method(D_METHOD("display_tile_set_editor_panel"), &LayeredTilesEditorUtils::display_tile_set_editor_panel);
ClassDB::bind_method(D_METHOD("synchronize_sources_list"), &LayeredTilesEditorUtils::synchronize_sources_list);
ClassDB::bind_method(D_METHOD("set_atlas_view_transform"), &LayeredTilesEditorUtils::set_atlas_view_transform);
ClassDB::bind_method(D_METHOD("_pattern_preview_done"), &LayeredTilesEditorUtils::_pattern_preview_done);
ClassDB::bind_method(D_METHOD("_preview_frame_started"), &LayeredTilesEditorUtils::_preview_frame_started);
}
void LayeredTileMapEditorPlugin::_tile_map_layer_changed() {
@ -326,7 +341,8 @@ void LayeredTileMapEditorPlugin::_tile_map_layer_changed() {
return;
}
tile_map_changed_needs_update = true;
callable_mp(this, &LayeredTileMapEditorPlugin::_update_tile_map).call_deferred();
call_deferred("_update_tile_map");
}
void LayeredTileMapEditorPlugin::_tile_map_layer_removed() {
@ -380,13 +396,14 @@ void LayeredTileMapEditorPlugin::_edit_tile_map_layer(LayeredTileMapLayer *p_til
// Update the object IDs.
tile_map_layer_id = p_tile_map_layer->get_instance_id();
p_tile_map_layer->connect("changed", callable_mp(this, &LayeredTileMapEditorPlugin::_tile_map_layer_changed));
p_tile_map_layer->connect("tree_exited", callable_mp(this, &LayeredTileMapEditorPlugin::_tile_map_layer_removed));
p_tile_map_layer->connect("changed", this, "_tile_map_layer_changed");
p_tile_map_layer->connect("tree_exited", this, "_tile_map_layer_removed");
if (tile_map_layer_group) {
tile_map_group_id = tile_map_layer_group->get_instance_id();
tile_map_layer_group->connect("child_entered_tree", callable_mp(editor, &LayeredTileMapLayerEditor::update_layers_selector).unbind(1));
tile_map_layer_group->connect("child_exiting_tree", callable_mp(editor, &LayeredTileMapLayerEditor::update_layers_selector).unbind(1));
tile_map_layer_group->connect("child_order_changed", callable_mp(editor, &LayeredTileMapLayerEditor::update_layers_selector));
tile_map_layer_group->connect("child_entered_tree", this, "_tile_map_group_child_tree_changed");
tile_map_layer_group->connect("child_exiting_tree", this, "_tile_map_group_child_tree_changed");
tile_map_layer_group->connect("child_order_changed", editor, "update_layers_selector");
}
// Update the edited tileset.
@ -434,18 +451,30 @@ void LayeredTileMapEditorPlugin::_notification(int p_notification) {
}
}
void LayeredTileMapEditorPlugin::_tile_map_group_child_tree_changed(Node *p_node) {
editor->update_layers_selector();
}
void LayeredTileMapEditorPlugin::_bind_methods() {
ClassDB::bind_method(D_METHOD("_tile_map_layer_changed"), &LayeredTileMapEditorPlugin::_tile_map_layer_changed);
ClassDB::bind_method(D_METHOD("_tile_map_layer_removed"), &LayeredTileMapEditorPlugin::_tile_map_layer_removed);
ClassDB::bind_method(D_METHOD("_tile_map_group_child_tree_changed"), &LayeredTileMapEditorPlugin::_tile_map_group_child_tree_changed);
ClassDB::bind_method(D_METHOD("_update_tile_map"), &LayeredTileMapEditorPlugin::_update_tile_map);
ClassDB::bind_method(D_METHOD("_select_layer"), &LayeredTileMapEditorPlugin::_select_layer);
}
void LayeredTileMapEditorPlugin::edit(Object *p_object) {
LayeredTileMapLayer *edited_layer = Object::cast_to<LayeredTileMapLayer>(ObjectDB::get_instance(tile_map_layer_id));
if (edited_layer) {
edited_layer->disconnect("changed", callable_mp(this, &LayeredTileMapEditorPlugin::_tile_map_layer_changed));
edited_layer->disconnect("tree_exited", callable_mp(this, &LayeredTileMapEditorPlugin::_tile_map_layer_removed));
edited_layer->disconnect("changed", this, "_tile_map_layer_changed");
edited_layer->disconnect("tree_exited", this, "_tile_map_layer_removed");
}
LayeredTileMapLayerGroup *tile_map_group = Object::cast_to<LayeredTileMapLayerGroup>(ObjectDB::get_instance(tile_map_group_id));
if (tile_map_group) {
tile_map_group->disconnect("child_entered_tree", callable_mp(editor, &LayeredTileMapLayerEditor::update_layers_selector).unbind(1));
tile_map_group->disconnect("child_exiting_tree", callable_mp(editor, &LayeredTileMapLayerEditor::update_layers_selector).unbind(1));
tile_map_group->disconnect("child_order_changed", callable_mp(editor, &LayeredTileMapLayerEditor::update_layers_selector));
tile_map_group->disconnect("child_entered_tree", this, "_tile_map_group_child_tree_changed");
tile_map_group->disconnect("child_exiting_tree", this, "_tile_map_group_child_tree_changed");
tile_map_group->disconnect("child_order_changed", editor, "update_layers_selector");
}
tile_map_group_id = ObjectID();
@ -476,11 +505,11 @@ bool LayeredTileMapEditorPlugin::handles(Object *p_object) const {
void LayeredTileMapEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
button->show();
EditorNode::get_bottom_panel()->make_item_visible(editor);
EditorNode::get_singleton()->make_bottom_panel_item_visible(editor);
} else {
button->hide();
if (editor->is_visible_in_tree()) {
EditorNode::get_bottom_panel()->hide_bottom_panel();
EditorNode::get_singleton()->hide_bottom_panel();
}
}
}
@ -495,7 +524,7 @@ void LayeredTileMapEditorPlugin::forward_canvas_draw_over_viewport(Control *p_ov
void LayeredTileMapEditorPlugin::hide_editor() {
if (editor->is_visible_in_tree()) {
EditorNode::get_bottom_panel()->hide_bottom_panel();
EditorNode::get_singleton()->hide_bottom_panel();
}
}
@ -503,7 +532,7 @@ bool LayeredTileMapEditorPlugin::is_editor_visible() const {
return editor->is_visible_in_tree();
}
LayeredTileMapEditorPlugin::LayeredTileMapEditorPlugin() {
LayeredTileMapEditorPlugin::LayeredTileMapEditorPlugin(EditorNode *p_node) {
if (!LayeredTilesEditorUtils::get_singleton()) {
memnew(LayeredTilesEditorUtils);
}
@ -513,10 +542,10 @@ LayeredTileMapEditorPlugin::LayeredTileMapEditorPlugin() {
editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE);
editor->connect("change_selected_layer_request", callable_mp(this, &LayeredTileMapEditorPlugin::_select_layer));
editor->connect("change_selected_layer_request", this, "_select_layer");
editor->hide();
button = EditorNode::get_bottom_panel()->add_item(TTR("LayeredTileMap"), editor);
button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("LayeredTileMap"), editor);
button->hide();
}
@ -541,12 +570,12 @@ void LayeredTileSetEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
button->show();
if (!tile_map_plugin_singleton->is_editor_visible()) {
EditorNode::get_bottom_panel()->make_item_visible(editor);
EditorNode::get_singleton()->make_bottom_panel_item_visible(editor);
}
} else {
button->hide();
if (editor->is_visible_in_tree()) {
EditorNode::get_bottom_panel()->hide_bottom_panel();
EditorNode::get_singleton()->hide_bottom_panel();
}
}
}
@ -555,7 +584,7 @@ ObjectID LayeredTileSetEditorPlugin::get_edited_tileset() const {
return edited_tileset;
}
LayeredTileSetEditorPlugin::LayeredTileSetEditorPlugin() {
LayeredTileSetEditorPlugin::LayeredTileSetEditorPlugin(EditorNode *p_node) {
if (!LayeredTilesEditorUtils::get_singleton()) {
memnew(LayeredTilesEditorUtils);
}
@ -567,7 +596,7 @@ LayeredTileSetEditorPlugin::LayeredTileSetEditorPlugin() {
editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE);
editor->hide();
button = EditorNode::get_bottom_panel()->add_item(TTR("LayeredTileSet"), editor);
button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("LayeredTileSet"), editor);
button->hide();
}

View File

@ -35,6 +35,10 @@
#include "editor/editor_plugin.h"
#include "scene/gui/box_container.h"
#include "core/os/semaphore.h"
#include "core/object/func_ref.h"
#include "layered_tile_atlas_view.h"
#include "layered_tile_map_layer_editor.h"
#include "layered_tile_set_editor.h"
@ -71,7 +75,7 @@ private:
struct QueueItem {
Ref<LayeredTileSet> tile_set;
Ref<LayeredTileMapPattern> pattern;
Callable callback;
Ref<FuncRef> callback;
};
List<QueueItem> pattern_preview_queue;
Mutex pattern_preview_mutex;
@ -81,7 +85,7 @@ private:
SafeFlag pattern_thread_exited;
Semaphore pattern_preview_done;
void _preview_frame_started();
void _pattern_preview_done();
void _pattern_preview_done(const Variant &p_userdata);
static void _thread_func(void *ud);
void _thread();
@ -89,7 +93,7 @@ public:
_FORCE_INLINE_ static LayeredTilesEditorUtils *get_singleton() { return singleton; }
// Pattern preview API.
void queue_pattern_preview(Ref<LayeredTileSet> p_tile_set, Ref<LayeredTileMapPattern> p_pattern, Callable p_callback);
void queue_pattern_preview(Ref<LayeredTileSet> p_tile_set, Ref<LayeredTileMapPattern> p_pattern, Ref<FuncRef> p_callback);
// To synchronize the atlas sources lists.
void set_sources_lists_current(int p_current);
@ -133,9 +137,13 @@ class LayeredTileMapEditorPlugin : public EditorPlugin {
void _edit_tile_map_layer(LayeredTileMapLayer *p_tile_map_layer);
void _edit_tile_map_layer_group(LayeredTileMapLayerGroup *p_tile_map_layer_group);
void _tile_map_group_child_tree_changed(Node *p_node);
protected:
void _notification(int p_notification);
static void _bind_methods();
public:
virtual void edit(Object *p_object);
virtual bool handles(Object *p_object) const;
@ -147,7 +155,7 @@ public:
void hide_editor();
bool is_editor_visible() const;
LayeredTileMapEditorPlugin();
LayeredTileMapEditorPlugin(EditorNode *p_node);
~LayeredTileMapEditorPlugin();
};
@ -166,7 +174,7 @@ public:
ObjectID get_edited_tileset() const;
LayeredTileSetEditorPlugin();
LayeredTileSetEditorPlugin(EditorNode *p_node);
~LayeredTileSetEditorPlugin();
};

View File

@ -52,7 +52,7 @@ void register_layered_tile_map_types(ModuleRegistrationLevel p_level) {
ClassDB::register_class<LayeredTileSet>();
ClassDB::register_class<LayeredTileSetAtlasSource>();
ClassDB::register_class<LayeredTileSetScenesCollectionSource>();
ClassDB::register_class<LayeredTileSetSource>();
ClassDB::register_virtual_class<LayeredTileSetSource>();
NavigationMeshGenerator::get_singleton()->register_geometry_parser_2d(memnew(LayeredTileMap2DNavigationGeometryParser2D));
}