| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  editor_debugger_tree.cpp                                             */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							|  |  |  | /*                      https://godotengine.org                          */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2022-01-03 21:27:34 +01:00
										 |  |  | /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							|  |  |  | /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */ | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* 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 "editor_debugger_tree.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-12 02:46:22 +01:00
										 |  |  | #include "editor/editor_file_dialog.h"
 | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | #include "editor/editor_node.h"
 | 
					
						
							| 
									
										
										
										
											2022-02-12 02:46:22 +01:00
										 |  |  | #include "editor/scene_tree_dock.h"
 | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | #include "scene/debugger/scene_debugger.h"
 | 
					
						
							|  |  |  | #include "scene/resources/packed_scene.h"
 | 
					
						
							| 
									
										
										
										
											2020-03-03 10:36:29 -03:00
										 |  |  | #include "servers/display_server.h"
 | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | EditorDebuggerTree::EditorDebuggerTree() { | 
					
						
							|  |  |  | 	set_v_size_flags(SIZE_EXPAND_FILL); | 
					
						
							|  |  |  | 	set_allow_rmb_select(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Popup
 | 
					
						
							|  |  |  | 	item_menu = memnew(PopupMenu); | 
					
						
							| 
									
										
										
										
											2020-02-21 18:28:45 +01:00
										 |  |  | 	item_menu->connect("id_pressed", callable_mp(this, &EditorDebuggerTree::_item_menu_id_pressed)); | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 	add_child(item_menu); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// File Dialog
 | 
					
						
							|  |  |  | 	file_dialog = memnew(EditorFileDialog); | 
					
						
							| 
									
										
										
										
											2020-02-21 18:28:45 +01:00
										 |  |  | 	file_dialog->connect("file_selected", callable_mp(this, &EditorDebuggerTree::_file_selected)); | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 	add_child(file_dialog); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorDebuggerTree::_notification(int p_what) { | 
					
						
							| 
									
										
										
										
											2022-02-16 00:52:32 +01:00
										 |  |  | 	switch (p_what) { | 
					
						
							|  |  |  | 		case NOTIFICATION_POSTINITIALIZE: { | 
					
						
							|  |  |  | 			connect("cell_selected", callable_mp(this, &EditorDebuggerTree::_scene_tree_selected)); | 
					
						
							|  |  |  | 			connect("item_collapsed", callable_mp(this, &EditorDebuggerTree::_scene_tree_folded)); | 
					
						
							| 
									
										
										
										
											2021-09-18 09:33:18 +02:00
										 |  |  | 			connect("item_mouse_selected", callable_mp(this, &EditorDebuggerTree::_scene_tree_rmb_selected)); | 
					
						
							| 
									
										
										
										
											2022-02-16 00:52:32 +01:00
										 |  |  | 		} break; | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorDebuggerTree::_bind_methods() { | 
					
						
							|  |  |  | 	ADD_SIGNAL(MethodInfo("object_selected", PropertyInfo(Variant::INT, "object_id"), PropertyInfo(Variant::INT, "debugger"))); | 
					
						
							|  |  |  | 	ADD_SIGNAL(MethodInfo("save_node", PropertyInfo(Variant::INT, "object_id"), PropertyInfo(Variant::STRING, "filename"), PropertyInfo(Variant::INT, "debugger"))); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorDebuggerTree::_scene_tree_selected() { | 
					
						
							|  |  |  | 	if (updating_scene_tree) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	TreeItem *item = get_selected(); | 
					
						
							|  |  |  | 	if (!item) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	inspected_object_id = uint64_t(item->get_metadata(0)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-17 18:22:52 -03:00
										 |  |  | 	emit_signal(SNAME("object_selected"), inspected_object_id, debugger_id); | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorDebuggerTree::_scene_tree_folded(Object *p_obj) { | 
					
						
							|  |  |  | 	if (updating_scene_tree) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	TreeItem *item = Object::cast_to<TreeItem>(p_obj); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!item) { | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ObjectID id = ObjectID(uint64_t(item->get_metadata(0))); | 
					
						
							|  |  |  | 	if (unfold_cache.has(id)) { | 
					
						
							|  |  |  | 		unfold_cache.erase(id); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		unfold_cache.insert(id); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-18 09:33:18 +02:00
										 |  |  | void EditorDebuggerTree::_scene_tree_rmb_selected(const Vector2 &p_position, MouseButton p_button) { | 
					
						
							|  |  |  | 	if (p_button != MouseButton::RIGHT) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 	TreeItem *item = get_item_at_position(p_position); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!item) { | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	item->select(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	item_menu->clear(); | 
					
						
							| 
									
										
										
										
											2021-07-17 18:22:52 -03:00
										 |  |  | 	item_menu->add_icon_item(get_theme_icon(SNAME("CreateNewSceneFrom"), SNAME("EditorIcons")), TTR("Save Branch as Scene"), ITEM_MENU_SAVE_REMOTE_NODE); | 
					
						
							|  |  |  | 	item_menu->add_icon_item(get_theme_icon(SNAME("CopyNodePath"), SNAME("EditorIcons")), TTR("Copy Node Path"), ITEM_MENU_COPY_NODE_PATH); | 
					
						
							| 
									
										
										
										
											2021-08-31 17:43:35 +02:00
										 |  |  | 	item_menu->set_position(get_screen_position() + get_local_mouse_position()); | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 	item_menu->popup(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /// Populates inspect_scene_tree given data in nodes as a flat list, encoded depth first.
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | /// Given a nodes array like [R,A,B,C,D,E] the following Tree will be generated, assuming
 | 
					
						
							|  |  |  | /// filter is an empty String, R and A child count are 2, B is 1 and C, D and E are 0.
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | /// R
 | 
					
						
							|  |  |  | /// |-A
 | 
					
						
							|  |  |  | /// | |-B
 | 
					
						
							|  |  |  | /// | | |-C
 | 
					
						
							|  |  |  | /// | |
 | 
					
						
							|  |  |  | /// | |-D
 | 
					
						
							|  |  |  | /// |
 | 
					
						
							|  |  |  | /// |-E
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | void EditorDebuggerTree::update_scene_tree(const SceneDebuggerTree *p_tree, int p_debugger) { | 
					
						
							|  |  |  | 	updating_scene_tree = true; | 
					
						
							|  |  |  | 	const String last_path = get_selected_path(); | 
					
						
							| 
									
										
										
										
											2021-11-17 21:08:55 +01:00
										 |  |  | 	const String filter = SceneTreeDock::get_singleton()->get_filter(); | 
					
						
							| 
									
										
										
										
											2021-02-08 01:19:46 +01:00
										 |  |  | 	bool filter_changed = filter != last_filter; | 
					
						
							|  |  |  | 	TreeItem *scroll_item = nullptr; | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Nodes are in a flatten list, depth first. Use a stack of parents, avoid recursion.
 | 
					
						
							| 
									
										
										
										
											2020-03-17 07:33:00 +01:00
										 |  |  | 	List<Pair<TreeItem *, int>> parents; | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 	for (int i = 0; i < p_tree->nodes.size(); i++) { | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 		TreeItem *parent = nullptr; | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 		if (parents.size()) { // Find last parent.
 | 
					
						
							|  |  |  | 			Pair<TreeItem *, int> &p = parents[0]; | 
					
						
							|  |  |  | 			parent = p.first; | 
					
						
							|  |  |  | 			if (!(--p.second)) { // If no child left, remove it.
 | 
					
						
							|  |  |  | 				parents.pop_front(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// Add this node.
 | 
					
						
							|  |  |  | 		const SceneDebuggerTree::RemoteNode &node = p_tree->nodes[i]; | 
					
						
							|  |  |  | 		TreeItem *item = create_item(parent); | 
					
						
							|  |  |  | 		item->set_text(0, node.name); | 
					
						
							| 
									
										
										
										
											2022-08-29 15:55:49 +02:00
										 |  |  | 		item->set_tooltip_text(0, TTR("Type:") + " " + node.type_name); | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 		Ref<Texture2D> icon = EditorNode::get_singleton()->get_class_icon(node.type_name, ""); | 
					
						
							|  |  |  | 		if (icon.is_valid()) { | 
					
						
							|  |  |  | 			item->set_icon(0, icon); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		item->set_metadata(0, node.id); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Set current item as collapsed if necessary (root is never collapsed)
 | 
					
						
							|  |  |  | 		if (parent) { | 
					
						
							|  |  |  | 			if (!unfold_cache.has(node.id)) { | 
					
						
							|  |  |  | 				item->set_collapsed(true); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// Select previously selected node.
 | 
					
						
							|  |  |  | 		if (debugger_id == p_debugger) { // Can use remote id.
 | 
					
						
							|  |  |  | 			if (node.id == inspected_object_id) { | 
					
						
							|  |  |  | 				item->select(0); | 
					
						
							| 
									
										
										
										
											2021-02-08 01:19:46 +01:00
										 |  |  | 				if (filter_changed) { | 
					
						
							|  |  |  | 					scroll_item = item; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} else { // Must use path
 | 
					
						
							|  |  |  | 			if (last_path == _get_path(item)) { | 
					
						
							|  |  |  | 				updating_scene_tree = false; // Force emission of new selection
 | 
					
						
							|  |  |  | 				item->select(0); | 
					
						
							| 
									
										
										
										
											2021-02-08 01:19:46 +01:00
										 |  |  | 				if (filter_changed) { | 
					
						
							|  |  |  | 					scroll_item = item; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 				updating_scene_tree = true; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Add in front of the parents stack if children are expected.
 | 
					
						
							|  |  |  | 		if (node.child_count) { | 
					
						
							|  |  |  | 			parents.push_front(Pair<TreeItem *, int>(item, node.child_count)); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			// Apply filters.
 | 
					
						
							|  |  |  | 			while (parent) { | 
					
						
							|  |  |  | 				const bool had_siblings = item->get_prev() || item->get_next(); | 
					
						
							| 
									
										
										
										
											2022-01-26 18:03:56 -05:00
										 |  |  | 				if (filter.is_subsequence_ofn(item->get_text(0))) { | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 					break; // Filter matches, must survive.
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 				parent->remove_child(item); | 
					
						
							|  |  |  | 				memdelete(item); | 
					
						
							| 
									
										
										
										
											2021-02-08 01:19:46 +01:00
										 |  |  | 				if (scroll_item == item) { | 
					
						
							|  |  |  | 					scroll_item = nullptr; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 				if (had_siblings) { | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 					break; // Parent must survive.
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 				item = parent; | 
					
						
							|  |  |  | 				parent = item->get_parent(); | 
					
						
							|  |  |  | 				// Check if parent expects more children.
 | 
					
						
							|  |  |  | 				for (int j = 0; j < parents.size(); j++) { | 
					
						
							|  |  |  | 					if (parents[j].first == item) { | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 						parent = nullptr; | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 						break; // Might have more children.
 | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	debugger_id = p_debugger; // Needed by hook, could be avoided if every debugger had its own tree
 | 
					
						
							| 
									
										
										
										
											2021-02-08 01:19:46 +01:00
										 |  |  | 	if (scroll_item) { | 
					
						
							| 
									
										
										
										
											2021-07-17 18:22:52 -03:00
										 |  |  | 		call_deferred(SNAME("scroll_to_item"), scroll_item); | 
					
						
							| 
									
										
										
										
											2021-02-08 01:19:46 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	last_filter = filter; | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 	updating_scene_tree = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 00:01:35 +01:00
										 |  |  | Variant EditorDebuggerTree::get_drag_data(const Point2 &p_point) { | 
					
						
							|  |  |  | 	if (get_button_id_at_position(p_point) != -1) { | 
					
						
							|  |  |  | 		return Variant(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	TreeItem *selected = get_selected(); | 
					
						
							|  |  |  | 	if (!selected) { | 
					
						
							|  |  |  | 		return Variant(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	String path = selected->get_text(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HBoxContainer *hb = memnew(HBoxContainer); | 
					
						
							|  |  |  | 	TextureRect *tf = memnew(TextureRect); | 
					
						
							|  |  |  | 	tf->set_texture(selected->get_icon(0)); | 
					
						
							|  |  |  | 	tf->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); | 
					
						
							|  |  |  | 	hb->add_child(tf); | 
					
						
							|  |  |  | 	Label *label = memnew(Label(path)); | 
					
						
							|  |  |  | 	hb->add_child(label); | 
					
						
							|  |  |  | 	set_drag_preview(hb); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!selected->get_parent() || !selected->get_parent()->get_parent()) { | 
					
						
							|  |  |  | 		path = "."; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		while (selected->get_parent()->get_parent() != get_root()) { | 
					
						
							|  |  |  | 			selected = selected->get_parent(); | 
					
						
							|  |  |  | 			path = selected->get_text(0) + "/" + path; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return vformat("\"%s\"", path); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | String EditorDebuggerTree::get_selected_path() { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!get_selected()) { | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 		return ""; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 	return _get_path(get_selected()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | String EditorDebuggerTree::_get_path(TreeItem *p_item) { | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!p_item, ""); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	if (p_item->get_parent() == nullptr) { | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 		return "/root"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	String text = p_item->get_text(0); | 
					
						
							|  |  |  | 	TreeItem *cur = p_item->get_parent(); | 
					
						
							|  |  |  | 	while (cur) { | 
					
						
							|  |  |  | 		text = cur->get_text(0) + "/" + text; | 
					
						
							|  |  |  | 		cur = cur->get_parent(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return "/" + text; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorDebuggerTree::_item_menu_id_pressed(int p_option) { | 
					
						
							|  |  |  | 	switch (p_option) { | 
					
						
							|  |  |  | 		case ITEM_MENU_SAVE_REMOTE_NODE: { | 
					
						
							|  |  |  | 			file_dialog->set_access(EditorFileDialog::ACCESS_RESOURCES); | 
					
						
							| 
									
										
										
										
											2020-03-06 14:00:16 -03:00
										 |  |  | 			file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			List<String> extensions; | 
					
						
							|  |  |  | 			Ref<PackedScene> sd = memnew(PackedScene); | 
					
						
							|  |  |  | 			ResourceSaver::get_recognized_extensions(sd, &extensions); | 
					
						
							|  |  |  | 			file_dialog->clear_filters(); | 
					
						
							|  |  |  | 			for (int i = 0; i < extensions.size(); i++) { | 
					
						
							| 
									
										
										
										
											2022-07-04 16:26:26 -05:00
										 |  |  | 				file_dialog->add_filter("*." + extensions[i], extensions[i].to_upper()); | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-11 18:45:19 +02:00
										 |  |  | 			file_dialog->popup_file_dialog(); | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 		} break; | 
					
						
							|  |  |  | 		case ITEM_MENU_COPY_NODE_PATH: { | 
					
						
							|  |  |  | 			String text = get_selected_path(); | 
					
						
							| 
									
										
										
										
											2020-12-15 12:04:21 +00:00
										 |  |  | 			if (text.is_empty()) { | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 				return; | 
					
						
							|  |  |  | 			} else if (text == "/root") { | 
					
						
							|  |  |  | 				text = "."; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				text = text.replace("/root/", ""); | 
					
						
							|  |  |  | 				int slash = text.find("/"); | 
					
						
							|  |  |  | 				if (slash < 0) { | 
					
						
							|  |  |  | 					text = "."; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					text = text.substr(slash + 1); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-03-03 10:36:29 -03:00
										 |  |  | 			DisplayServer::get_singleton()->clipboard_set(text); | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 		} break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorDebuggerTree::_file_selected(const String &p_file) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (inspected_object_id.is_null()) { | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-07-17 18:22:52 -03:00
										 |  |  | 	emit_signal(SNAME("save_node"), inspected_object_id, p_file, debugger_id); | 
					
						
							| 
									
										
										
										
											2020-02-07 02:52:05 +01:00
										 |  |  | } |