1/**************************************************************************/
2/* tile_set_scenes_collection_source_editor.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#include "tile_set_scenes_collection_source_editor.h"
32
33#include "editor/editor_file_system.h"
34#include "editor/editor_node.h"
35#include "editor/editor_resource_preview.h"
36#include "editor/editor_scale.h"
37#include "editor/editor_settings.h"
38#include "editor/editor_undo_redo_manager.h"
39#include "editor/gui/editor_file_dialog.h"
40#include "editor/plugins/tiles/tile_set_editor.h"
41
42#include "scene/gui/button.h"
43#include "scene/gui/item_list.h"
44#include "scene/gui/label.h"
45#include "scene/gui/split_container.h"
46
47#include "core/core_string_names.h"
48
49void TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::set_id(int p_id) {
50 ERR_FAIL_COND(p_id < 0);
51 if (source_id == p_id) {
52 return;
53 }
54 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));
55
56 int previous_source = source_id;
57 source_id = p_id; // source_id must be updated before, because it's used by the source list update.
58 tile_set->set_source_id(previous_source, p_id);
59 emit_signal(SNAME("changed"), "id");
60}
61
62int TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::get_id() {
63 return source_id;
64}
65
66bool TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::_set(const StringName &p_name, const Variant &p_value) {
67 String name = p_name;
68 if (name == "name") {
69 // Use the resource_name property to store the source's name.
70 name = "resource_name";
71 }
72 bool valid = false;
73 tile_set_scenes_collection_source->set(name, p_value, &valid);
74 if (valid) {
75 emit_signal(SNAME("changed"), String(name).utf8().get_data());
76 }
77 return valid;
78}
79
80bool TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::_get(const StringName &p_name, Variant &r_ret) const {
81 if (!tile_set_scenes_collection_source) {
82 return false;
83 }
84 String name = p_name;
85 if (name == "name") {
86 // Use the resource_name property to store the source's name.
87 name = "resource_name";
88 }
89 bool valid = false;
90 r_ret = tile_set_scenes_collection_source->get(name, &valid);
91 return valid;
92}
93
94void TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::_get_property_list(List<PropertyInfo> *p_list) const {
95 p_list->push_back(PropertyInfo(Variant::STRING, "name", PROPERTY_HINT_NONE, ""));
96}
97
98void TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::_bind_methods() {
99 // -- Shape and layout --
100 ClassDB::bind_method(D_METHOD("set_id", "id"), &TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::set_id);
101 ClassDB::bind_method(D_METHOD("get_id"), &TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::get_id);
102
103 ADD_PROPERTY(PropertyInfo(Variant::INT, "id"), "set_id", "get_id");
104
105 ADD_SIGNAL(MethodInfo("changed", PropertyInfo(Variant::STRING, "what")));
106}
107
108void TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::edit(Ref<TileSet> p_tile_set, TileSetScenesCollectionSource *p_tile_set_scenes_collection_source, int p_source_id) {
109 ERR_FAIL_COND(!p_tile_set.is_valid());
110 ERR_FAIL_NULL(p_tile_set_scenes_collection_source);
111 ERR_FAIL_COND(p_source_id < 0);
112 ERR_FAIL_COND(p_tile_set->get_source(p_source_id) != p_tile_set_scenes_collection_source);
113
114 if (tile_set == p_tile_set && tile_set_scenes_collection_source == p_tile_set_scenes_collection_source && source_id == p_source_id) {
115 return;
116 }
117
118 // Disconnect to changes.
119 if (tile_set_scenes_collection_source) {
120 tile_set_scenes_collection_source->disconnect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed));
121 }
122
123 tile_set = p_tile_set;
124 tile_set_scenes_collection_source = p_tile_set_scenes_collection_source;
125 source_id = p_source_id;
126
127 // Connect to changes.
128 if (tile_set_scenes_collection_source) {
129 if (!tile_set_scenes_collection_source->is_connected(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed))) {
130 tile_set_scenes_collection_source->connect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed));
131 }
132 }
133
134 notify_property_list_changed();
135}
136
137// -- Proxy object used by the tile inspector --
138bool TileSetScenesCollectionSourceEditor::SceneTileProxyObject::_set(const StringName &p_name, const Variant &p_value) {
139 if (!tile_set_scenes_collection_source) {
140 return false;
141 }
142
143 if (p_name == "id") {
144 int as_int = int(p_value);
145 ERR_FAIL_COND_V(as_int < 0, false);
146 ERR_FAIL_COND_V(tile_set_scenes_collection_source->has_scene_tile_id(as_int), false);
147 tile_set_scenes_collection_source->set_scene_tile_id(scene_id, as_int);
148 scene_id = as_int;
149 emit_signal(SNAME("changed"), "id");
150 for (int i = 0; i < tile_set_scenes_collection_source_editor->scene_tiles_list->get_item_count(); i++) {
151 if (int(tile_set_scenes_collection_source_editor->scene_tiles_list->get_item_metadata(i)) == scene_id) {
152 tile_set_scenes_collection_source_editor->scene_tiles_list->select(i);
153 break;
154 }
155 }
156 return true;
157 } else if (p_name == "scene") {
158 tile_set_scenes_collection_source->set_scene_tile_scene(scene_id, p_value);
159 emit_signal(SNAME("changed"), "scene");
160 return true;
161 } else if (p_name == "display_placeholder") {
162 tile_set_scenes_collection_source->set_scene_tile_display_placeholder(scene_id, p_value);
163 emit_signal(SNAME("changed"), "display_placeholder");
164 return true;
165 }
166
167 return false;
168}
169
170bool TileSetScenesCollectionSourceEditor::SceneTileProxyObject::_get(const StringName &p_name, Variant &r_ret) const {
171 if (!tile_set_scenes_collection_source) {
172 return false;
173 }
174
175 if (p_name == "id") {
176 r_ret = scene_id;
177 return true;
178 } else if (p_name == "scene") {
179 r_ret = tile_set_scenes_collection_source->get_scene_tile_scene(scene_id);
180 return true;
181 } else if (p_name == "display_placeholder") {
182 r_ret = tile_set_scenes_collection_source->get_scene_tile_display_placeholder(scene_id);
183 return true;
184 }
185
186 return false;
187}
188
189void TileSetScenesCollectionSourceEditor::SceneTileProxyObject::_get_property_list(List<PropertyInfo> *p_list) const {
190 if (!tile_set_scenes_collection_source) {
191 return;
192 }
193
194 p_list->push_back(PropertyInfo(Variant::INT, "id", PROPERTY_HINT_NONE, ""));
195 p_list->push_back(PropertyInfo(Variant::OBJECT, "scene", PROPERTY_HINT_RESOURCE_TYPE, "PackedScene"));
196 p_list->push_back(PropertyInfo(Variant::BOOL, "display_placeholder", PROPERTY_HINT_NONE, ""));
197}
198
199void TileSetScenesCollectionSourceEditor::SceneTileProxyObject::edit(TileSetScenesCollectionSource *p_tile_set_scenes_collection_source, int p_scene_id) {
200 ERR_FAIL_NULL(p_tile_set_scenes_collection_source);
201 ERR_FAIL_COND(!p_tile_set_scenes_collection_source->has_scene_tile_id(p_scene_id));
202
203 if (tile_set_scenes_collection_source == p_tile_set_scenes_collection_source && scene_id == p_scene_id) {
204 return;
205 }
206
207 tile_set_scenes_collection_source = p_tile_set_scenes_collection_source;
208 scene_id = p_scene_id;
209
210 notify_property_list_changed();
211}
212
213void TileSetScenesCollectionSourceEditor::SceneTileProxyObject::_bind_methods() {
214 ADD_SIGNAL(MethodInfo("changed", PropertyInfo(Variant::STRING, "what")));
215}
216
217void TileSetScenesCollectionSourceEditor::_scenes_collection_source_proxy_object_changed(String p_what) {
218 if (p_what == "id") {
219 emit_signal(SNAME("source_id_changed"), scenes_collection_source_proxy_object->get_id());
220 }
221}
222
223void TileSetScenesCollectionSourceEditor::_tile_set_scenes_collection_source_changed() {
224 tile_set_scenes_collection_source_changed_needs_update = true;
225}
226
227void TileSetScenesCollectionSourceEditor::_scene_thumbnail_done(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, Variant p_ud) {
228 int index = p_ud;
229
230 if (index >= 0 && index < scene_tiles_list->get_item_count()) {
231 scene_tiles_list->set_item_icon(index, p_preview);
232 }
233}
234
235void TileSetScenesCollectionSourceEditor::_scenes_list_item_activated(int p_index) {
236 Ref<PackedScene> packed_scene = tile_set_scenes_collection_source->get_scene_tile_scene(scene_tiles_list->get_item_metadata(p_index));
237 if (packed_scene.is_valid()) {
238 EditorNode::get_singleton()->open_request(packed_scene->get_path());
239 }
240}
241
242void TileSetScenesCollectionSourceEditor::_source_add_pressed() {
243 if (!scene_select_dialog) {
244 scene_select_dialog = memnew(EditorFileDialog);
245 add_child(scene_select_dialog);
246 scene_select_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
247 scene_select_dialog->connect("file_selected", callable_mp(this, &TileSetScenesCollectionSourceEditor::_scene_file_selected));
248
249 for (const String &E : Vector<String>{ "tscn", "scn" }) {
250 scene_select_dialog->add_filter("*." + E, E.to_upper());
251 }
252 }
253 scene_select_dialog->popup_file_dialog();
254}
255
256void TileSetScenesCollectionSourceEditor::_scene_file_selected(const String &p_path) {
257 Ref<PackedScene> scene = ResourceLoader::load(p_path);
258
259 int scene_id = tile_set_scenes_collection_source->get_next_scene_tile_id();
260 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
261 undo_redo->create_action(TTR("Add a Scene Tile"));
262 undo_redo->add_do_method(tile_set_scenes_collection_source, "create_scene_tile", scene, scene_id);
263 undo_redo->add_undo_method(tile_set_scenes_collection_source, "remove_scene_tile", scene_id);
264 undo_redo->commit_action();
265 _update_scenes_list();
266 _update_action_buttons();
267 _update_tile_inspector();
268}
269
270void TileSetScenesCollectionSourceEditor::_source_delete_pressed() {
271 Vector<int> selected_indices = scene_tiles_list->get_selected_items();
272 ERR_FAIL_COND(selected_indices.size() <= 0);
273 int scene_id = scene_tiles_list->get_item_metadata(selected_indices[0]);
274
275 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
276 undo_redo->create_action(TTR("Remove a Scene Tile"));
277 undo_redo->add_do_method(tile_set_scenes_collection_source, "remove_scene_tile", scene_id);
278 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);
279 undo_redo->commit_action();
280 _update_scenes_list();
281 _update_action_buttons();
282 _update_tile_inspector();
283}
284
285void TileSetScenesCollectionSourceEditor::_update_source_inspector() {
286 // Update the proxy object.
287 scenes_collection_source_proxy_object->edit(tile_set, tile_set_scenes_collection_source, tile_set_source_id);
288}
289
290void TileSetScenesCollectionSourceEditor::_update_tile_inspector() {
291 Vector<int> selected_indices = scene_tiles_list->get_selected_items();
292 bool has_atlas_tile_selected = (selected_indices.size() > 0);
293
294 // Update the proxy object.
295 if (has_atlas_tile_selected) {
296 int scene_id = scene_tiles_list->get_item_metadata(selected_indices[0]);
297 tile_proxy_object->edit(tile_set_scenes_collection_source, scene_id);
298 }
299
300 // Update visibility.
301 tile_inspector_label->set_visible(has_atlas_tile_selected);
302 tile_inspector->set_visible(has_atlas_tile_selected);
303}
304
305void TileSetScenesCollectionSourceEditor::_update_action_buttons() {
306 Vector<int> selected_indices = scene_tiles_list->get_selected_items();
307 scene_tile_delete_button->set_disabled(selected_indices.size() <= 0 || read_only);
308}
309
310void TileSetScenesCollectionSourceEditor::_update_scenes_list() {
311 if (!tile_set_scenes_collection_source) {
312 return;
313 }
314
315 // Get the previously selected id.
316 Vector<int> selected_indices = scene_tiles_list->get_selected_items();
317 int old_selected_scene_id = (selected_indices.size() > 0) ? int(scene_tiles_list->get_item_metadata(selected_indices[0])) : -1;
318
319 // Clear the list.
320 scene_tiles_list->clear();
321
322 // Rebuild the list.
323 int to_reselect = -1;
324 for (int i = 0; i < tile_set_scenes_collection_source->get_scene_tiles_count(); i++) {
325 int scene_id = tile_set_scenes_collection_source->get_scene_tile_id(i);
326
327 Ref<PackedScene> scene = tile_set_scenes_collection_source->get_scene_tile_scene(scene_id);
328
329 int item_index = 0;
330 if (scene.is_valid()) {
331 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));
332 Variant udata = i;
333 EditorResourcePreview::get_singleton()->queue_edited_resource_preview(scene, this, "_scene_thumbnail_done", udata);
334 } else {
335 item_index = scene_tiles_list->add_item(TTR("Tile with Invalid Scene"), get_editor_theme_icon(SNAME("PackedScene")));
336 }
337 scene_tiles_list->set_item_metadata(item_index, scene_id);
338
339 if (old_selected_scene_id >= 0 && scene_id == old_selected_scene_id) {
340 to_reselect = i;
341 }
342 }
343 if (scene_tiles_list->get_item_count() == 0) {
344 scene_tiles_list->add_item(TTR("Drag and drop scenes here or use the Add button."));
345 scene_tiles_list->set_item_disabled(-1, true);
346 }
347
348 // Reselect if needed.
349 if (to_reselect >= 0) {
350 scene_tiles_list->select(to_reselect);
351 }
352
353 // Icon size update.
354 int int_size = int(EDITOR_GET("filesystem/file_dialog/thumbnail_size")) * EDSCALE;
355 scene_tiles_list->set_fixed_icon_size(Vector2(int_size, int_size));
356}
357
358void TileSetScenesCollectionSourceEditor::_notification(int p_what) {
359 switch (p_what) {
360 case NOTIFICATION_THEME_CHANGED: {
361 scene_tile_add_button->set_icon(get_editor_theme_icon(SNAME("Add")));
362 scene_tile_delete_button->set_icon(get_editor_theme_icon(SNAME("Remove")));
363 _update_scenes_list();
364 } break;
365
366 case NOTIFICATION_INTERNAL_PROCESS: {
367 if (tile_set_scenes_collection_source_changed_needs_update) {
368 read_only = false;
369 // Add the listener again and check for read-only status.
370 if (tile_set.is_valid()) {
371 read_only = EditorNode::get_singleton()->is_resource_read_only(tile_set);
372 }
373
374 // Update everything.
375 _update_source_inspector();
376 _update_scenes_list();
377 _update_action_buttons();
378 _update_tile_inspector();
379 tile_set_scenes_collection_source_changed_needs_update = false;
380 }
381 } break;
382
383 case NOTIFICATION_VISIBILITY_CHANGED: {
384 // Update things just in case.
385 _update_scenes_list();
386 _update_action_buttons();
387 } break;
388 }
389}
390
391void TileSetScenesCollectionSourceEditor::edit(Ref<TileSet> p_tile_set, TileSetScenesCollectionSource *p_tile_set_scenes_collection_source, int p_source_id) {
392 ERR_FAIL_COND(!p_tile_set.is_valid());
393 ERR_FAIL_NULL(p_tile_set_scenes_collection_source);
394 ERR_FAIL_COND(p_source_id < 0);
395 ERR_FAIL_COND(p_tile_set->get_source(p_source_id) != p_tile_set_scenes_collection_source);
396
397 bool new_read_only_state = false;
398 if (p_tile_set.is_valid()) {
399 new_read_only_state = EditorNode::get_singleton()->is_resource_read_only(p_tile_set);
400 }
401
402 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) {
403 return;
404 }
405
406 // Remove listener for old objects.
407 if (tile_set_scenes_collection_source) {
408 tile_set_scenes_collection_source->disconnect_changed(callable_mp(this, &TileSetScenesCollectionSourceEditor::_tile_set_scenes_collection_source_changed));
409 }
410
411 // Change the edited object.
412 tile_set = p_tile_set;
413 tile_set_scenes_collection_source = p_tile_set_scenes_collection_source;
414 tile_set_source_id = p_source_id;
415
416 // Read-only status is false by default
417 read_only = new_read_only_state;
418
419 if (tile_set.is_valid()) {
420 scenes_collection_source_inspector->set_read_only(read_only);
421 tile_inspector->set_read_only(read_only);
422
423 scene_tile_add_button->set_disabled(read_only);
424 }
425
426 // Add the listener again.
427 if (tile_set_scenes_collection_source) {
428 tile_set_scenes_collection_source->connect_changed(callable_mp(this, &TileSetScenesCollectionSourceEditor::_tile_set_scenes_collection_source_changed));
429 }
430
431 // Update everything.
432 _update_source_inspector();
433 _update_scenes_list();
434 _update_action_buttons();
435 _update_tile_inspector();
436}
437
438void TileSetScenesCollectionSourceEditor::_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
439 if (!_can_drop_data_fw(p_point, p_data, p_from)) {
440 return;
441 }
442
443 if (p_from == scene_tiles_list) {
444 // Handle dropping a texture in the list of atlas resources.
445 Dictionary d = p_data;
446 Vector<String> files = d["files"];
447 for (int i = 0; i < files.size(); i++) {
448 Ref<PackedScene> resource = ResourceLoader::load(files[i]);
449 if (resource.is_valid()) {
450 int scene_id = tile_set_scenes_collection_source->get_next_scene_tile_id();
451 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
452 undo_redo->create_action(TTR("Add a Scene Tile"));
453 undo_redo->add_do_method(tile_set_scenes_collection_source, "create_scene_tile", resource, scene_id);
454 undo_redo->add_undo_method(tile_set_scenes_collection_source, "remove_scene_tile", scene_id);
455 undo_redo->commit_action();
456 }
457 }
458
459 _update_scenes_list();
460 _update_action_buttons();
461 _update_tile_inspector();
462 }
463}
464
465bool TileSetScenesCollectionSourceEditor::_can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
466 if (p_from == scene_tiles_list) {
467 Dictionary d = p_data;
468
469 if (!d.has("type")) {
470 return false;
471 }
472
473 // Check if we have a Texture2D.
474 if (String(d["type"]) == "files") {
475 Vector<String> files = d["files"];
476
477 if (files.size() == 0) {
478 return false;
479 }
480
481 for (int i = 0; i < files.size(); i++) {
482 String file = files[i];
483 String ftype = EditorFileSystem::get_singleton()->get_file_type(file);
484
485 if (!ClassDB::is_parent_class(ftype, "PackedScene")) {
486 return false;
487 }
488 }
489
490 return true;
491 }
492 }
493 return false;
494}
495
496void TileSetScenesCollectionSourceEditor::_bind_methods() {
497 ADD_SIGNAL(MethodInfo("source_id_changed", PropertyInfo(Variant::INT, "source_id")));
498
499 ClassDB::bind_method(D_METHOD("_scene_thumbnail_done"), &TileSetScenesCollectionSourceEditor::_scene_thumbnail_done);
500}
501
502TileSetScenesCollectionSourceEditor::TileSetScenesCollectionSourceEditor() {
503 // -- Right side --
504 HSplitContainer *split_container_right_side = memnew(HSplitContainer);
505 split_container_right_side->set_h_size_flags(SIZE_EXPAND_FILL);
506 add_child(split_container_right_side);
507
508 // Middle panel.
509 ScrollContainer *middle_panel = memnew(ScrollContainer);
510 middle_panel->set_horizontal_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
511 middle_panel->set_custom_minimum_size(Size2(200, 0) * EDSCALE);
512 split_container_right_side->add_child(middle_panel);
513
514 VBoxContainer *middle_vbox_container = memnew(VBoxContainer);
515 middle_vbox_container->set_h_size_flags(SIZE_EXPAND_FILL);
516 middle_panel->add_child(middle_vbox_container);
517
518 // Scenes collection source inspector.
519 scenes_collection_source_inspector_label = memnew(Label);
520 scenes_collection_source_inspector_label->set_text(TTR("Scenes collection properties:"));
521 middle_vbox_container->add_child(scenes_collection_source_inspector_label);
522
523 scenes_collection_source_proxy_object = memnew(TileSetScenesCollectionProxyObject());
524 scenes_collection_source_proxy_object->connect("changed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_scenes_collection_source_proxy_object_changed));
525
526 scenes_collection_source_inspector = memnew(EditorInspector);
527 scenes_collection_source_inspector->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
528 scenes_collection_source_inspector->add_inspector_plugin(memnew(TileSourceInspectorPlugin));
529 scenes_collection_source_inspector->edit(scenes_collection_source_proxy_object);
530 middle_vbox_container->add_child(scenes_collection_source_inspector);
531
532 // Tile inspector.
533 tile_inspector_label = memnew(Label);
534 tile_inspector_label->set_text(TTR("Tile properties:"));
535 tile_inspector_label->hide();
536 middle_vbox_container->add_child(tile_inspector_label);
537
538 tile_proxy_object = memnew(SceneTileProxyObject(this));
539 tile_proxy_object->connect("changed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_update_scenes_list).unbind(1));
540 tile_proxy_object->connect("changed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_update_action_buttons).unbind(1));
541
542 tile_inspector = memnew(EditorInspector);
543 tile_inspector->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
544 tile_inspector->edit(tile_proxy_object);
545 tile_inspector->set_use_folding(true);
546 middle_vbox_container->add_child(tile_inspector);
547
548 // Scenes list.
549 VBoxContainer *right_vbox_container = memnew(VBoxContainer);
550 split_container_right_side->add_child(right_vbox_container);
551
552 scene_tiles_list = memnew(ItemList);
553 scene_tiles_list->set_h_size_flags(SIZE_EXPAND_FILL);
554 scene_tiles_list->set_v_size_flags(SIZE_EXPAND_FILL);
555 SET_DRAG_FORWARDING_CDU(scene_tiles_list, TileSetScenesCollectionSourceEditor);
556 scene_tiles_list->connect("item_selected", callable_mp(this, &TileSetScenesCollectionSourceEditor::_update_tile_inspector).unbind(1));
557 scene_tiles_list->connect("item_selected", callable_mp(this, &TileSetScenesCollectionSourceEditor::_update_action_buttons).unbind(1));
558 scene_tiles_list->connect("item_activated", callable_mp(this, &TileSetScenesCollectionSourceEditor::_scenes_list_item_activated));
559 scene_tiles_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
560 right_vbox_container->add_child(scene_tiles_list);
561
562 HBoxContainer *scenes_bottom_actions = memnew(HBoxContainer);
563 right_vbox_container->add_child(scenes_bottom_actions);
564
565 scene_tile_add_button = memnew(Button);
566 scene_tile_add_button->set_flat(true);
567 scene_tile_add_button->connect("pressed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_source_add_pressed));
568 scenes_bottom_actions->add_child(scene_tile_add_button);
569
570 scene_tile_delete_button = memnew(Button);
571 scene_tile_delete_button->set_flat(true);
572 scene_tile_delete_button->set_disabled(true);
573 scene_tile_delete_button->connect("pressed", callable_mp(this, &TileSetScenesCollectionSourceEditor::_source_delete_pressed));
574 scenes_bottom_actions->add_child(scene_tile_delete_button);
575}
576
577TileSetScenesCollectionSourceEditor::~TileSetScenesCollectionSourceEditor() {
578 memdelete(scenes_collection_source_proxy_object);
579 memdelete(tile_proxy_object);
580}
581