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 | |
49 | void 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 | |
62 | int TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::get_id() { |
63 | return source_id; |
64 | } |
65 | |
66 | bool 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 | |
80 | bool 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 | |
94 | void TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::_get_property_list(List<PropertyInfo> *p_list) const { |
95 | p_list->push_back(PropertyInfo(Variant::STRING, "name" , PROPERTY_HINT_NONE, "" )); |
96 | } |
97 | |
98 | void 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 | |
108 | void 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 -- |
138 | bool 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 | |
170 | bool 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 | |
189 | void 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 | |
199 | void 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 | |
213 | void TileSetScenesCollectionSourceEditor::SceneTileProxyObject::_bind_methods() { |
214 | ADD_SIGNAL(MethodInfo("changed" , PropertyInfo(Variant::STRING, "what" ))); |
215 | } |
216 | |
217 | void 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 | |
223 | void TileSetScenesCollectionSourceEditor::_tile_set_scenes_collection_source_changed() { |
224 | tile_set_scenes_collection_source_changed_needs_update = true; |
225 | } |
226 | |
227 | void 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 | |
235 | void 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 | |
242 | void 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 | |
256 | void 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 | |
270 | void 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 | |
285 | void 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 | |
290 | void 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 | |
305 | void 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 | |
310 | void 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 | |
358 | void 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 | |
391 | void 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 | |
438 | void 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 | |
465 | bool 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 | |
496 | void 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 | |
502 | TileSetScenesCollectionSourceEditor::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 | |
577 | TileSetScenesCollectionSourceEditor::~TileSetScenesCollectionSourceEditor() { |
578 | memdelete(scenes_collection_source_proxy_object); |
579 | memdelete(tile_proxy_object); |
580 | } |
581 | |