| 
									
										
										
										
											2023-01-05 13:25:55 +01:00
										 |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*  editor_data.cpp                                                       */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*                         This file is part of:                          */ | 
					
						
							|  |  |  | /*                             GODOT ENGINE                               */ | 
					
						
							|  |  |  | /*                        https://godotengine.org                         */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ | 
					
						
							|  |  |  | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* 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.                 */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							| 
									
										
										
										
											2018-01-05 00:50:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | #include "editor_data.h"
 | 
					
						
							| 
									
										
										
										
											2017-01-16 08:04:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-07 19:33:38 -03:00
										 |  |  | #include "core/config/project_settings.h"
 | 
					
						
							| 
									
										
										
										
											2023-03-31 21:17:59 +02:00
										 |  |  | #include "core/extension/gdextension_manager.h"
 | 
					
						
							| 
									
										
										
										
											2021-06-11 14:51:48 +02:00
										 |  |  | #include "core/io/file_access.h"
 | 
					
						
							| 
									
										
										
										
											2018-09-11 18:13:45 +02:00
										 |  |  | #include "core/io/resource_loader.h"
 | 
					
						
							| 
									
										
										
										
											2022-02-12 02:46:22 +01:00
										 |  |  | #include "editor/editor_node.h"
 | 
					
						
							| 
									
										
										
										
											2022-03-25 18:06:46 +01:00
										 |  |  | #include "editor/editor_undo_redo_manager.h"
 | 
					
						
							| 
									
										
										
										
											2025-06-10 16:47:26 +02:00
										 |  |  | #include "editor/inspector/editor_context_menu_plugin.h"
 | 
					
						
							|  |  |  | #include "editor/inspector/multi_node_edit.h"
 | 
					
						
							| 
									
										
										
										
											2024-04-21 01:11:35 -07:00
										 |  |  | #include "editor/plugins/editor_plugin.h"
 | 
					
						
							| 
									
										
										
										
											2025-02-12 00:51:22 +01:00
										 |  |  | #include "scene/property_utils.h"
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | #include "scene/resources/packed_scene.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | void EditorSelectionHistory::cleanup_history() { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < history.size(); i++) { | 
					
						
							|  |  |  | 		bool fail = false; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		for (int j = 0; j < history[i].path.size(); j++) { | 
					
						
							| 
									
										
										
										
											2024-08-25 14:15:10 +02:00
										 |  |  | 			if (history[i].path[j].ref.is_valid()) { | 
					
						
							| 
									
										
										
										
											2023-04-18 14:05:01 +02:00
										 |  |  | 				// If the node is a MultiNodeEdit node, examine it and see if anything is missing from it.
 | 
					
						
							|  |  |  | 				Ref<MultiNodeEdit> multi_node_edit = history[i].path[j].ref; | 
					
						
							|  |  |  | 				if (multi_node_edit.is_valid()) { | 
					
						
							|  |  |  | 					Node *root = EditorNode::get_singleton()->get_edited_scene(); | 
					
						
							|  |  |  | 					if (root) { | 
					
						
							|  |  |  | 						for (int k = 0; k < multi_node_edit->get_node_count(); k++) { | 
					
						
							|  |  |  | 							NodePath np = multi_node_edit->get_node(k); | 
					
						
							|  |  |  | 							Node *multi_node_selected_node = root->get_node_or_null(np); | 
					
						
							|  |  |  | 							if (!multi_node_selected_node) { | 
					
						
							|  |  |  | 								fail = true; | 
					
						
							|  |  |  | 								break; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} else { | 
					
						
							|  |  |  | 						fail = true; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					// Reference is not null - object still alive.
 | 
					
						
							| 
									
										
										
										
											2018-01-08 00:50:51 -05:00
										 |  |  | 					continue; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2023-04-18 14:05:01 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-18 14:05:01 +02:00
										 |  |  | 			if (!fail) { | 
					
						
							|  |  |  | 				Object *obj = ObjectDB::get_instance(history[i].path[j].object); | 
					
						
							|  |  |  | 				if (obj) { | 
					
						
							|  |  |  | 					Node *n = Object::cast_to<Node>(obj); | 
					
						
							|  |  |  | 					if (n && n->is_inside_tree()) { | 
					
						
							|  |  |  | 						// Node valid and inside tree - object still alive.
 | 
					
						
							|  |  |  | 						continue; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					if (!n) { | 
					
						
							|  |  |  | 						// Node possibly still alive.
 | 
					
						
							|  |  |  | 						continue; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} // Else: object not valid - not alive.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				fail = true; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (fail) { | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (fail) { | 
					
						
							| 
									
										
										
										
											2021-07-03 16:17:03 -06:00
										 |  |  | 			history.remove_at(i); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			i--; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	if (current_elem_idx >= history.size()) { | 
					
						
							|  |  |  | 		current_elem_idx = history.size() - 1; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | void EditorSelectionHistory::add_object(ObjectID p_object, const String &p_property, bool p_inspector_only) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	Object *obj = ObjectDB::get_instance(p_object); | 
					
						
							| 
									
										
										
										
											2023-09-09 17:24:40 +02:00
										 |  |  | 	ERR_FAIL_NULL(obj); | 
					
						
							| 
									
										
										
										
											2021-06-04 18:03:15 +02:00
										 |  |  | 	RefCounted *r = Object::cast_to<RefCounted>(obj); | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	_Object o; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (r) { | 
					
						
							| 
									
										
										
										
											2022-05-03 01:43:50 +02:00
										 |  |  | 		o.ref = Ref<RefCounted>(r); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	o.object = p_object; | 
					
						
							|  |  |  | 	o.property = p_property; | 
					
						
							| 
									
										
										
										
											2018-06-18 22:10:48 -03:00
										 |  |  | 	o.inspector_only = p_inspector_only; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	bool has_prev = current_elem_idx >= 0 && current_elem_idx < history.size(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (has_prev) { | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 		history.resize(current_elem_idx + 1); // Clip history to next.
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	HistoryElement h; | 
					
						
							| 
									
										
										
										
											2021-12-09 03:42:46 -06:00
										 |  |  | 	if (!p_property.is_empty() && has_prev) { | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 		// Add a sub property.
 | 
					
						
							|  |  |  | 		HistoryElement &prev_element = history.write[current_elem_idx]; | 
					
						
							|  |  |  | 		h = prev_element; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		h.path.resize(h.level + 1); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		h.path.push_back(o); | 
					
						
							|  |  |  | 		h.level++; | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 		// Create a new history item.
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		h.path.push_back(o); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		h.level = 0; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	history.push_back(h); | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	current_elem_idx++; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-02 16:50:22 -04:00
										 |  |  | void EditorSelectionHistory::replace_object(ObjectID p_old_object, ObjectID p_new_object) { | 
					
						
							|  |  |  | 	for (HistoryElement &element : history) { | 
					
						
							|  |  |  | 		for (int index = 0; index < element.path.size(); index++) { | 
					
						
							|  |  |  | 			if (element.path[index].object == p_old_object) { | 
					
						
							|  |  |  | 				element.path.write[index].object = p_new_object; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | int EditorSelectionHistory::get_history_len() { | 
					
						
							| 
									
										
										
										
											2015-09-01 00:49:47 -03:00
										 |  |  | 	return history.size(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | int EditorSelectionHistory::get_history_pos() { | 
					
						
							|  |  |  | 	return current_elem_idx; | 
					
						
							| 
									
										
										
										
											2015-09-01 00:49:47 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | ObjectID EditorSelectionHistory::get_history_obj(int p_obj) const { | 
					
						
							| 
									
										
										
										
											2020-02-12 14:24:06 -03:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_obj, history.size(), ObjectID()); | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX_V(history[p_obj].level, history[p_obj].path.size(), ObjectID()); | 
					
						
							| 
									
										
										
										
											2015-09-01 00:49:47 -03:00
										 |  |  | 	return history[p_obj].path[history[p_obj].level].object; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | bool EditorSelectionHistory::is_at_beginning() const { | 
					
						
							|  |  |  | 	return current_elem_idx <= 0; | 
					
						
							| 
									
										
										
										
											2015-09-01 00:49:47 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | bool EditorSelectionHistory::is_at_end() const { | 
					
						
							|  |  |  | 	return ((current_elem_idx + 1) >= history.size()); | 
					
						
							| 
									
										
										
										
											2015-09-01 00:49:47 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | bool EditorSelectionHistory::next() { | 
					
						
							| 
									
										
										
										
											2018-01-08 00:50:51 -05:00
										 |  |  | 	cleanup_history(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	if ((current_elem_idx + 1) < history.size()) { | 
					
						
							|  |  |  | 		current_elem_idx++; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | bool EditorSelectionHistory::previous() { | 
					
						
							| 
									
										
										
										
											2018-01-08 00:50:51 -05:00
										 |  |  | 	cleanup_history(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	if (current_elem_idx > 0) { | 
					
						
							|  |  |  | 		current_elem_idx--; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | bool EditorSelectionHistory::is_current_inspector_only() const { | 
					
						
							|  |  |  | 	if (current_elem_idx < 0 || current_elem_idx >= history.size()) { | 
					
						
							| 
									
										
										
										
											2018-06-18 22:10:48 -03:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-06-18 22:10:48 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	const HistoryElement &h = history[current_elem_idx]; | 
					
						
							| 
									
										
										
										
											2018-06-18 22:10:48 -03:00
										 |  |  | 	return h.path[h.level].inspector_only; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | ObjectID EditorSelectionHistory::get_current() { | 
					
						
							|  |  |  | 	if (current_elem_idx < 0 || current_elem_idx >= history.size()) { | 
					
						
							| 
									
										
										
										
											2020-02-12 14:24:06 -03:00
										 |  |  | 		return ObjectID(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	Object *obj = ObjectDB::get_instance(get_history_obj(current_elem_idx)); | 
					
						
							|  |  |  | 	return obj ? obj->get_instance_id() : ObjectID(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | int EditorSelectionHistory::get_path_size() const { | 
					
						
							|  |  |  | 	if (current_elem_idx < 0 || current_elem_idx >= history.size()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	return history[current_elem_idx].path.size(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | ObjectID EditorSelectionHistory::get_path_object(int p_index) const { | 
					
						
							|  |  |  | 	if (current_elem_idx < 0 || current_elem_idx >= history.size()) { | 
					
						
							| 
									
										
										
										
											2020-02-12 14:24:06 -03:00
										 |  |  | 		return ObjectID(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_index, history[current_elem_idx].path.size(), ObjectID()); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	Object *obj = ObjectDB::get_instance(history[current_elem_idx].path[p_index].object); | 
					
						
							|  |  |  | 	return obj ? obj->get_instance_id() : ObjectID(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | String EditorSelectionHistory::get_path_property(int p_index) const { | 
					
						
							|  |  |  | 	if (current_elem_idx < 0 || current_elem_idx >= history.size()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return ""; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_index, history[current_elem_idx].path.size(), ""); | 
					
						
							|  |  |  | 	return history[current_elem_idx].path[p_index].property; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | void EditorSelectionHistory::clear() { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	history.clear(); | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	current_elem_idx = -1; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | EditorSelectionHistory::EditorSelectionHistory() { | 
					
						
							|  |  |  | 	current_elem_idx = -1; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | ////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-11 15:55:47 +02:00
										 |  |  | EditorPlugin *EditorData::get_handling_main_editor(Object *p_object) { | 
					
						
							| 
									
										
										
										
											2020-03-13 04:33:35 -04:00
										 |  |  | 	// We need to iterate backwards so that we can check user-created plugins first.
 | 
					
						
							|  |  |  | 	// Otherwise, it would not be possible for plugins to handle CanvasItem and Spatial nodes.
 | 
					
						
							|  |  |  | 	for (int i = editor_plugins.size() - 1; i > -1; i--) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (editor_plugins[i]->has_main_screen() && editor_plugins[i]->handles(p_object)) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			return editor_plugins[i]; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	return nullptr; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-11 15:55:47 +02:00
										 |  |  | Vector<EditorPlugin *> EditorData::get_handling_sub_editors(Object *p_object) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	Vector<EditorPlugin *> sub_plugins; | 
					
						
							| 
									
										
										
										
											2020-03-13 04:33:35 -04:00
										 |  |  | 	for (int i = editor_plugins.size() - 1; i > -1; i--) { | 
					
						
							| 
									
										
										
										
											2016-03-29 20:02:53 -03:00
										 |  |  | 		if (!editor_plugins[i]->has_main_screen() && editor_plugins[i]->handles(p_object)) { | 
					
						
							|  |  |  | 			sub_plugins.push_back(editor_plugins[i]); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return sub_plugins; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-15 13:25:58 -03:00
										 |  |  | EditorPlugin *EditorData::get_editor_by_name(const String &p_name) { | 
					
						
							| 
									
										
										
										
											2020-03-13 04:33:35 -04:00
										 |  |  | 	for (int i = editor_plugins.size() - 1; i > -1; i--) { | 
					
						
							| 
									
										
										
										
											2024-10-12 19:42:12 -07:00
										 |  |  | 		if (editor_plugins[i]->get_plugin_name() == p_name) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			return editor_plugins[i]; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	return nullptr; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorData::copy_object_params(Object *p_object) { | 
					
						
							|  |  |  | 	clipboard.clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	List<PropertyInfo> pinfo; | 
					
						
							|  |  |  | 	p_object->get_property_list(&pinfo); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-24 15:46:25 +02:00
										 |  |  | 	for (const PropertyInfo &E : pinfo) { | 
					
						
							| 
									
										
										
										
											2023-11-25 22:35:51 +01:00
										 |  |  | 		if (!(E.usage & PROPERTY_USAGE_EDITOR) || E.name == "script" || E.name == "scripts" || E.name == "resource_path") { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		PropertyData pd; | 
					
						
							| 
									
										
										
										
											2021-07-15 23:45:57 -04:00
										 |  |  | 		pd.name = E.name; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		pd.value = p_object->get(pd.name); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		clipboard.push_back(pd); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorData::get_editor_breakpoints(List<String> *p_breakpoints) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < editor_plugins.size(); i++) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		editor_plugins[i]->get_breakpoints(p_breakpoints); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-11 04:17:03 +02:00
										 |  |  | Dictionary EditorData::get_editor_plugin_states() const { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	Dictionary metadata; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < editor_plugins.size(); i++) { | 
					
						
							|  |  |  | 		Dictionary state = editor_plugins[i]->get_state(); | 
					
						
							| 
									
										
										
										
											2020-12-15 12:04:21 +00:00
										 |  |  | 		if (state.is_empty()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-10-12 19:42:12 -07:00
										 |  |  | 		metadata[editor_plugins[i]->get_plugin_name()] = state; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return metadata; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | Dictionary EditorData::get_scene_editor_states(int p_idx) const { | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX_V(p_idx, edited_scene.size(), Dictionary()); | 
					
						
							| 
									
										
										
										
											2016-07-08 13:36:57 -03:00
										 |  |  | 	EditedScene es = edited_scene[p_idx]; | 
					
						
							|  |  |  | 	return es.editor_states; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-11 04:17:03 +02:00
										 |  |  | void EditorData::set_editor_plugin_states(const Dictionary &p_states) { | 
					
						
							| 
									
										
										
										
											2023-04-01 15:18:13 +02:00
										 |  |  | 	if (p_states.is_empty()) { | 
					
						
							|  |  |  | 		for (EditorPlugin *ep : editor_plugins) { | 
					
						
							|  |  |  | 			ep->clear(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-12 06:43:48 +08:00
										 |  |  | 	for (const KeyValue<Variant, Variant> &kv : p_states) { | 
					
						
							|  |  |  | 		String name = kv.key; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		int idx = -1; | 
					
						
							|  |  |  | 		for (int i = 0; i < editor_plugins.size(); i++) { | 
					
						
							| 
									
										
										
										
											2024-10-12 19:42:12 -07:00
										 |  |  | 			if (editor_plugins[i]->get_plugin_name() == name) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				idx = i; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (idx == -1) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-03-12 06:43:48 +08:00
										 |  |  | 		editor_plugins[idx]->set_state(kv.value); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-09 09:08:41 -03:00
										 |  |  | void EditorData::notify_edited_scene_changed() { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < editor_plugins.size(); i++) { | 
					
						
							| 
									
										
										
										
											2015-12-09 09:08:41 -03:00
										 |  |  | 		editor_plugins[i]->edited_scene_changed(); | 
					
						
							| 
									
										
										
										
											2017-07-06 09:18:20 +02:00
										 |  |  | 		editor_plugins[i]->notify_scene_changed(get_edited_scene_root()); | 
					
						
							| 
									
										
										
										
											2015-12-09 09:08:41 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-12 15:43:29 -06:00
										 |  |  | void EditorData::notify_resource_saved(const Ref<Resource> &p_resource) { | 
					
						
							|  |  |  | 	for (int i = 0; i < editor_plugins.size(); i++) { | 
					
						
							|  |  |  | 		editor_plugins[i]->notify_resource_saved(p_resource); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-18 13:06:48 +01:00
										 |  |  | void EditorData::notify_scene_saved(const String &p_path) { | 
					
						
							|  |  |  | 	for (int i = 0; i < editor_plugins.size(); i++) { | 
					
						
							|  |  |  | 		editor_plugins[i]->notify_scene_saved(p_path); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | void EditorData::clear_editor_states() { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < editor_plugins.size(); i++) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		editor_plugins[i]->clear(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorData::save_editor_external_data() { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < editor_plugins.size(); i++) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		editor_plugins[i]->save_external_data(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorData::apply_changes_in_editors() { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < editor_plugins.size(); i++) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		editor_plugins[i]->apply_changes(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorData::paste_object_params(Object *p_object) { | 
					
						
							| 
									
										
										
										
											2020-02-29 08:55:28 +05:30
										 |  |  | 	ERR_FAIL_NULL(p_object); | 
					
						
							| 
									
										
										
										
											2022-03-25 18:06:46 +01:00
										 |  |  | 	undo_redo_manager->create_action(TTR("Paste Params")); | 
					
						
							| 
									
										
										
										
											2021-07-24 15:46:25 +02:00
										 |  |  | 	for (const PropertyData &E : clipboard) { | 
					
						
							| 
									
										
										
										
											2021-07-15 23:45:57 -04:00
										 |  |  | 		String name = E.name; | 
					
						
							| 
									
										
										
										
											2022-03-25 18:06:46 +01:00
										 |  |  | 		undo_redo_manager->add_do_property(p_object, name, E.value); | 
					
						
							|  |  |  | 		undo_redo_manager->add_undo_property(p_object, name, p_object->get(name)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-03-25 18:06:46 +01:00
										 |  |  | 	undo_redo_manager->commit_action(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-08 09:55:22 -06:00
										 |  |  | bool EditorData::call_build() { | 
					
						
							|  |  |  | 	bool result = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (int i = 0; i < editor_plugins.size() && result; i++) { | 
					
						
							|  |  |  | 		result &= editor_plugins[i]->build(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-25 18:06:46 +01:00
										 |  |  | void EditorData::set_scene_as_saved(int p_idx) { | 
					
						
							|  |  |  | 	if (p_idx == -1) { | 
					
						
							|  |  |  | 		p_idx = current_edited_scene; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX(p_idx, edited_scene.size()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-23 23:53:16 +01:00
										 |  |  | 	undo_redo_manager->set_history_as_saved(edited_scene[p_idx].history_id); | 
					
						
							| 
									
										
										
										
											2022-03-25 18:06:46 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool EditorData::is_scene_changed(int p_idx) { | 
					
						
							|  |  |  | 	if (p_idx == -1) { | 
					
						
							|  |  |  | 		p_idx = current_edited_scene; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX_V(p_idx, edited_scene.size(), false); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-23 23:53:16 +01:00
										 |  |  | 	uint64_t current_scene_version = undo_redo_manager->get_or_create_history(edited_scene[p_idx].history_id).undo_redo->get_version(); | 
					
						
							| 
									
										
										
										
											2022-03-25 18:06:46 +01:00
										 |  |  | 	bool is_changed = edited_scene[p_idx].last_checked_version != current_scene_version; | 
					
						
							|  |  |  | 	edited_scene.write[p_idx].last_checked_version = current_scene_version; | 
					
						
							|  |  |  | 	return is_changed; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int EditorData::get_scene_history_id_from_path(const String &p_path) const { | 
					
						
							|  |  |  | 	for (const EditedScene &E : edited_scene) { | 
					
						
							|  |  |  | 		if (E.path == p_path) { | 
					
						
							|  |  |  | 			return E.history_id; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int EditorData::get_current_edited_scene_history_id() const { | 
					
						
							|  |  |  | 	if (current_edited_scene != -1) { | 
					
						
							|  |  |  | 		return edited_scene[current_edited_scene].history_id; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int EditorData::get_scene_history_id(int p_idx) const { | 
					
						
							|  |  |  | 	return edited_scene[p_idx].history_id; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-28 17:39:57 +02:00
										 |  |  | void EditorData::add_undo_redo_inspector_hook_callback(Callable p_callable) { | 
					
						
							|  |  |  | 	undo_redo_callbacks.push_back(p_callable); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorData::remove_undo_redo_inspector_hook_callback(Callable p_callable) { | 
					
						
							|  |  |  | 	undo_redo_callbacks.erase(p_callable); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const Vector<Callable> EditorData::get_undo_redo_inspector_hook_callback() { | 
					
						
							|  |  |  | 	return undo_redo_callbacks; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-31 10:48:45 +02:00
										 |  |  | void EditorData::add_move_array_element_function(const StringName &p_class, Callable p_callable) { | 
					
						
							|  |  |  | 	move_element_functions.insert(p_class, p_callable); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorData::remove_move_array_element_function(const StringName &p_class) { | 
					
						
							|  |  |  | 	move_element_functions.erase(p_class); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Callable EditorData::get_move_array_element_function(const StringName &p_class) const { | 
					
						
							|  |  |  | 	if (move_element_functions.has(p_class)) { | 
					
						
							|  |  |  | 		return move_element_functions[p_class]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return Callable(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | void EditorData::remove_editor_plugin(EditorPlugin *p_plugin) { | 
					
						
							|  |  |  | 	editor_plugins.erase(p_plugin); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorData::add_editor_plugin(EditorPlugin *p_plugin) { | 
					
						
							|  |  |  | 	editor_plugins.push_back(p_plugin); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-27 23:10:44 -03:00
										 |  |  | int EditorData::get_editor_plugin_count() const { | 
					
						
							|  |  |  | 	return editor_plugins.size(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-27 23:10:44 -03:00
										 |  |  | EditorPlugin *EditorData::get_editor_plugin(int p_idx) { | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_idx, editor_plugins.size(), nullptr); | 
					
						
							| 
									
										
										
										
											2016-02-27 23:10:44 -03:00
										 |  |  | 	return editor_plugins[p_idx]; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-11 16:46:53 -05:00
										 |  |  | void EditorData::add_extension_editor_plugin(const StringName &p_class_name, EditorPlugin *p_plugin) { | 
					
						
							|  |  |  | 	ERR_FAIL_COND(extension_editor_plugins.has(p_class_name)); | 
					
						
							|  |  |  | 	extension_editor_plugins.insert(p_class_name, p_plugin); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorData::remove_extension_editor_plugin(const StringName &p_class_name) { | 
					
						
							|  |  |  | 	extension_editor_plugins.erase(p_class_name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool EditorData::has_extension_editor_plugin(const StringName &p_class_name) { | 
					
						
							|  |  |  | 	return extension_editor_plugins.has(p_class_name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | EditorPlugin *EditorData::get_extension_editor_plugin(const StringName &p_class_name) { | 
					
						
							|  |  |  | 	EditorPlugin **plugin = extension_editor_plugins.getptr(p_class_name); | 
					
						
							|  |  |  | 	return plugin == nullptr ? nullptr : *plugin; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-11 15:43:37 -03:00
										 |  |  | void EditorData::add_custom_type(const String &p_type, const String &p_inherits, const Ref<Script> &p_script, const Ref<Texture2D> &p_icon) { | 
					
						
							| 
									
										
										
										
											2019-09-25 10:28:50 +02:00
										 |  |  | 	ERR_FAIL_COND_MSG(p_script.is_null(), "It's not a reference to a valid Script object."); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	CustomType ct; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ct.name = p_type; | 
					
						
							|  |  |  | 	ct.icon = p_icon; | 
					
						
							|  |  |  | 	ct.script = p_script; | 
					
						
							| 
									
										
										
										
											2023-03-31 21:17:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	if (!custom_types.has(p_inherits)) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		custom_types[p_inherits] = Vector<CustomType>(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	custom_types[p_inherits].push_back(ct); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-16 00:13:39 +01:00
										 |  |  | Variant EditorData::instantiate_custom_type(const String &p_type, const String &p_inherits) { | 
					
						
							| 
									
										
										
										
											2018-02-25 01:41:26 +01:00
										 |  |  | 	if (get_custom_types().has(p_inherits)) { | 
					
						
							|  |  |  | 		for (int i = 0; i < get_custom_types()[p_inherits].size(); i++) { | 
					
						
							|  |  |  | 			if (get_custom_types()[p_inherits][i].name == p_type) { | 
					
						
							|  |  |  | 				Ref<Script> script = get_custom_types()[p_inherits][i].script; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-12 00:51:22 +01:00
										 |  |  | 				// Store in a variant to initialize the refcount if needed.
 | 
					
						
							|  |  |  | 				Variant v = ClassDB::instantiate(p_inherits); | 
					
						
							|  |  |  | 				ERR_FAIL_COND_V(!v, Variant()); | 
					
						
							|  |  |  | 				Object *ob = v; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-06 20:25:05 +01:00
										 |  |  | 				Node *n = Object::cast_to<Node>(ob); | 
					
						
							|  |  |  | 				if (n) { | 
					
						
							|  |  |  | 					n->set_name(p_type); | 
					
						
							| 
									
										
										
										
											2018-02-25 01:41:26 +01:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2025-02-12 00:51:22 +01:00
										 |  |  | 				PropertyUtils::assign_custom_type_script(ob, script); | 
					
						
							|  |  |  | 				ob->set_script(script); | 
					
						
							|  |  |  | 				return v; | 
					
						
							| 
									
										
										
										
											2018-02-25 01:41:26 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-06 20:25:05 +01:00
										 |  |  | 	return Variant(); | 
					
						
							| 
									
										
										
										
											2018-02-25 01:41:26 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-28 01:57:34 +01:00
										 |  |  | const EditorData::CustomType *EditorData::get_custom_type_by_name(const String &p_type) const { | 
					
						
							|  |  |  | 	for (const KeyValue<String, Vector<CustomType>> &E : custom_types) { | 
					
						
							|  |  |  | 		for (const CustomType &F : E.value) { | 
					
						
							|  |  |  | 			if (F.name == p_type) { | 
					
						
							|  |  |  | 				return &F; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nullptr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const EditorData::CustomType *EditorData::get_custom_type_by_path(const String &p_path) const { | 
					
						
							|  |  |  | 	for (const KeyValue<String, Vector<CustomType>> &E : custom_types) { | 
					
						
							|  |  |  | 		for (const CustomType &F : E.value) { | 
					
						
							|  |  |  | 			if (F.script->get_path() == p_path) { | 
					
						
							|  |  |  | 				return &F; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nullptr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool EditorData::is_type_recognized(const String &p_type) const { | 
					
						
							|  |  |  | 	return ClassDB::class_exists(p_type) || ScriptServer::is_global_class(p_type) || get_custom_type_by_name(p_type); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void EditorData::remove_custom_type(const String &p_type) { | 
					
						
							| 
									
										
										
										
											2022-05-13 15:04:37 +02:00
										 |  |  | 	for (KeyValue<String, Vector<CustomType>> &E : custom_types) { | 
					
						
							|  |  |  | 		for (int i = 0; i < E.value.size(); i++) { | 
					
						
							|  |  |  | 			if (E.value[i].name == p_type) { | 
					
						
							|  |  |  | 				E.value.remove_at(i); | 
					
						
							|  |  |  | 				if (E.value.is_empty()) { | 
					
						
							|  |  |  | 					custom_types.erase(E.key); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				return; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-22 22:02:57 +03:00
										 |  |  | void EditorData::instantiate_object_properties(Object *p_object) { | 
					
						
							|  |  |  | 	ERR_FAIL_NULL(p_object); | 
					
						
							|  |  |  | 	// Check if any Object-type property should be instantiated.
 | 
					
						
							|  |  |  | 	List<PropertyInfo> pinfo; | 
					
						
							|  |  |  | 	p_object->get_property_list(&pinfo); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-03 14:16:27 +08:00
										 |  |  | 	for (const PropertyInfo &pi : pinfo) { | 
					
						
							| 
									
										
										
										
											2020-10-22 22:02:57 +03:00
										 |  |  | 		if (pi.type == Variant::OBJECT && pi.usage & PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT) { | 
					
						
							|  |  |  | 			Object *prop = ClassDB::instantiate(pi.class_name); | 
					
						
							|  |  |  | 			p_object->set(pi.name, prop); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | int EditorData::add_edited_scene(int p_at_pos) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (p_at_pos < 0) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		p_at_pos = edited_scene.size(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | 	EditedScene es; | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	es.root = nullptr; | 
					
						
							| 
									
										
										
										
											2019-08-15 19:47:21 +02:00
										 |  |  | 	es.path = String(); | 
					
						
							| 
									
										
										
										
											2019-08-28 19:42:27 +02:00
										 |  |  | 	es.file_modified_time = 0; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	es.history_current = -1; | 
					
						
							|  |  |  | 	es.live_edit_root = NodePath(String("/root")); | 
					
						
							| 
									
										
										
										
											2022-03-25 18:06:46 +01:00
										 |  |  | 	es.history_id = last_created_scene++; | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (p_at_pos == edited_scene.size()) { | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | 		edited_scene.push_back(es); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		edited_scene.insert(p_at_pos, es); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (current_edited_scene < 0) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		current_edited_scene = 0; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | 	return p_at_pos; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void EditorData::move_edited_scene_index(int p_idx, int p_to_idx) { | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX(p_idx, edited_scene.size()); | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX(p_to_idx, edited_scene.size()); | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	SWAP(edited_scene.write[p_idx], edited_scene.write[p_to_idx]); | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-06-04 05:36:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void EditorData::remove_scene(int p_idx) { | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX(p_idx, edited_scene.size()); | 
					
						
							| 
									
										
										
										
											2017-07-06 09:18:20 +02:00
										 |  |  | 	if (edited_scene[p_idx].root) { | 
					
						
							|  |  |  | 		for (int i = 0; i < editor_plugins.size(); i++) { | 
					
						
							| 
									
										
										
										
											2021-09-30 16:30:55 +02:00
										 |  |  | 			editor_plugins[i]->notify_scene_closed(edited_scene[p_idx].root->get_scene_file_path()); | 
					
						
							| 
									
										
										
										
											2017-07-06 09:18:20 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | 		memdelete(edited_scene[p_idx].root); | 
					
						
							| 
									
										
										
										
											2022-07-06 10:43:55 +08:00
										 |  |  | 		edited_scene.write[p_idx].root = nullptr; | 
					
						
							| 
									
										
										
										
											2017-07-06 09:18:20 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (current_edited_scene > p_idx) { | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | 		current_edited_scene--; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} else if (current_edited_scene == p_idx && current_edited_scene > 0) { | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | 		current_edited_scene--; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-09 03:42:46 -06:00
										 |  |  | 	if (!edited_scene[p_idx].path.is_empty()) { | 
					
						
							| 
									
										
										
										
											2023-04-09 20:43:55 +02:00
										 |  |  | 		EditorNode::get_singleton()->emit_signal("scene_closed", edited_scene[p_idx].path); | 
					
						
							| 
									
										
										
										
											2021-09-07 22:19:45 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-05 17:42:37 +01:00
										 |  |  | 	if (undo_redo_manager->has_history(edited_scene[p_idx].history_id)) { // Might not exist if scene failed to load.
 | 
					
						
							|  |  |  | 		undo_redo_manager->discard_history(edited_scene[p_idx].history_id); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-07-03 16:17:03 -06:00
										 |  |  | 	edited_scene.remove_at(p_idx); | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-12-13 20:39:01 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-19 17:00:06 +02:00
										 |  |  | bool EditorData::_find_updated_instances(Node *p_root, Node *p_node, HashSet<String> &checked_paths) { | 
					
						
							| 
									
										
										
										
											2015-12-13 20:39:01 -03:00
										 |  |  | 	Ref<SceneState> ss; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	if (p_node == p_root) { | 
					
						
							|  |  |  | 		ss = p_node->get_scene_inherited_state(); | 
					
						
							| 
									
										
										
										
											2021-12-09 03:42:46 -06:00
										 |  |  | 	} else if (!p_node->get_scene_file_path().is_empty()) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		ss = p_node->get_scene_instance_state(); | 
					
						
							| 
									
										
										
										
											2015-12-13 20:39:01 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ss.is_valid()) { | 
					
						
							|  |  |  | 		String path = ss->get_path(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!checked_paths.has(path)) { | 
					
						
							|  |  |  | 			uint64_t modified_time = FileAccess::get_modified_time(path); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			if (modified_time != ss->get_last_modified_time()) { | 
					
						
							| 
									
										
										
										
											2015-12-13 20:39:01 -03:00
										 |  |  | 				return true; //external scene changed
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			checked_paths.insert(path); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < p_node->get_child_count(); i++) { | 
					
						
							|  |  |  | 		bool found = _find_updated_instances(p_root, p_node->get_child(i), checked_paths); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (found) { | 
					
						
							| 
									
										
										
										
											2015-12-13 20:39:01 -03:00
										 |  |  | 			return true; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-12-13 20:39:01 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool EditorData::check_and_update_scene(int p_idx) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_idx, edited_scene.size(), false); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!edited_scene[p_idx].root) { | 
					
						
							| 
									
										
										
										
											2015-12-13 20:39:01 -03:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-13 20:39:01 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-19 17:00:06 +02:00
										 |  |  | 	HashSet<String> checked_scenes; | 
					
						
							| 
									
										
										
										
											2015-12-13 20:39:01 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	bool must_reload = _find_updated_instances(edited_scene[p_idx].root, edited_scene[p_idx].root, checked_scenes); | 
					
						
							| 
									
										
										
										
											2015-12-13 20:39:01 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (must_reload) { | 
					
						
							|  |  |  | 		Ref<PackedScene> pscene; | 
					
						
							| 
									
										
										
										
											2021-06-17 16:03:09 -06:00
										 |  |  | 		pscene.instantiate(); | 
					
						
							| 
									
										
										
										
											2015-12-13 20:39:01 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		EditorProgress ep("update_scene", TTR("Updating Scene"), 2); | 
					
						
							| 
									
										
										
										
											2018-04-22 19:36:01 +02:00
										 |  |  | 		ep.step(TTR("Storing local changes..."), 0); | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 		// Pack first, so it stores diffs to previous version of saved scene.
 | 
					
						
							| 
									
										
										
										
											2015-12-13 20:39:01 -03:00
										 |  |  | 		Error err = pscene->pack(edited_scene[p_idx].root); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		ERR_FAIL_COND_V(err != OK, false); | 
					
						
							| 
									
										
										
										
											2018-04-22 19:36:01 +02:00
										 |  |  | 		ep.step(TTR("Updating scene..."), 1); | 
					
						
							| 
									
										
										
										
											2021-06-17 16:03:09 -06:00
										 |  |  | 		Node *new_scene = pscene->instantiate(PackedScene::GEN_EDIT_STATE_MAIN); | 
					
						
							| 
									
										
										
										
											2023-09-09 17:24:40 +02:00
										 |  |  | 		ERR_FAIL_NULL_V(new_scene, false); | 
					
						
							| 
									
										
										
										
											2015-12-13 20:39:01 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 		// Transfer selection.
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		List<Node *> new_selection; | 
					
						
							| 
									
										
										
										
											2021-07-24 15:46:25 +02:00
										 |  |  | 		for (const Node *E : edited_scene.write[p_idx].selection) { | 
					
						
							| 
									
										
										
										
											2021-07-15 23:45:57 -04:00
										 |  |  | 			NodePath p = edited_scene[p_idx].root->get_path_to(E); | 
					
						
							| 
									
										
										
										
											2015-12-13 20:39:01 -03:00
										 |  |  | 			Node *new_node = new_scene->get_node(p); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 			if (new_node) { | 
					
						
							| 
									
										
										
										
											2015-12-13 20:39:01 -03:00
										 |  |  | 				new_selection.push_back(new_node); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-12-13 20:39:01 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-30 16:30:55 +02:00
										 |  |  | 		new_scene->set_scene_file_path(edited_scene[p_idx].root->get_scene_file_path()); | 
					
						
							| 
									
										
										
										
											2024-03-13 15:35:23 +01:00
										 |  |  | 		Node *old_root = edited_scene[p_idx].root; | 
					
						
							| 
									
										
										
										
											2024-04-09 20:41:16 +08:00
										 |  |  | 		EditorNode::get_singleton()->set_edited_scene(new_scene); | 
					
						
							| 
									
										
										
										
											2024-03-13 15:35:23 +01:00
										 |  |  | 		memdelete(old_root); | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 		edited_scene.write[p_idx].selection = new_selection; | 
					
						
							| 
									
										
										
										
											2015-12-13 20:39:01 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | int EditorData::get_edited_scene() const { | 
					
						
							|  |  |  | 	return current_edited_scene; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-12 21:02:28 +02:00
										 |  |  | int EditorData::get_edited_scene_from_path(const String &p_path) const { | 
					
						
							|  |  |  | 	for (int i = 0; i < edited_scene.size(); i++) { | 
					
						
							|  |  |  | 		if (edited_scene[i].path == p_path) { | 
					
						
							|  |  |  | 			return i; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void EditorData::set_edited_scene(int p_idx) { | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX(p_idx, edited_scene.size()); | 
					
						
							|  |  |  | 	current_edited_scene = p_idx; | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | Node *EditorData::get_edited_scene_root(int p_idx) { | 
					
						
							| 
									
										
										
										
											2016-06-26 00:54:17 -03:00
										 |  |  | 	if (p_idx < 0) { | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 		ERR_FAIL_INDEX_V(current_edited_scene, edited_scene.size(), nullptr); | 
					
						
							| 
									
										
										
										
											2016-06-26 00:54:17 -03:00
										 |  |  | 		return edited_scene[current_edited_scene].root; | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 		ERR_FAIL_INDEX_V(p_idx, edited_scene.size(), nullptr); | 
					
						
							| 
									
										
										
										
											2016-06-26 00:54:17 -03:00
										 |  |  | 		return edited_scene[p_idx].root; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void EditorData::set_edited_scene_root(Node *p_root) { | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX(current_edited_scene, edited_scene.size()); | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	edited_scene.write[current_edited_scene].root = p_root; | 
					
						
							| 
									
										
										
										
											2019-08-15 19:47:21 +02:00
										 |  |  | 	if (p_root) { | 
					
						
							| 
									
										
										
										
											2021-12-09 03:42:46 -06:00
										 |  |  | 		if (!p_root->get_scene_file_path().is_empty()) { | 
					
						
							| 
									
										
										
										
											2021-09-30 16:30:55 +02:00
										 |  |  | 			edited_scene.write[current_edited_scene].path = p_root->get_scene_file_path(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2021-09-30 16:30:55 +02:00
										 |  |  | 			p_root->set_scene_file_path(edited_scene[current_edited_scene].path); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-15 19:47:21 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-08-28 19:42:27 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-09 03:42:46 -06:00
										 |  |  | 	if (!edited_scene[current_edited_scene].path.is_empty()) { | 
					
						
							| 
									
										
										
										
											2019-08-28 19:42:27 +02:00
										 |  |  | 		edited_scene.write[current_edited_scene].file_modified_time = FileAccess::get_modified_time(edited_scene[current_edited_scene].path); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int EditorData::get_edited_scene_count() const { | 
					
						
							|  |  |  | 	return edited_scene.size(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-06 09:18:20 +02:00
										 |  |  | Vector<EditorData::EditedScene> EditorData::get_edited_scenes() const { | 
					
						
							|  |  |  | 	Vector<EditedScene> out_edited_scenes_list = Vector<EditedScene>(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (int i = 0; i < edited_scene.size(); i++) { | 
					
						
							|  |  |  | 		out_edited_scenes_list.push_back(edited_scene[i]); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return out_edited_scenes_list; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-28 19:42:27 +02:00
										 |  |  | void EditorData::set_scene_modified_time(int p_idx, uint64_t p_time) { | 
					
						
							|  |  |  | 	if (p_idx == -1) { | 
					
						
							|  |  |  | 		p_idx = current_edited_scene; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX(p_idx, edited_scene.size()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	edited_scene.write[p_idx].file_modified_time = p_time; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | uint64_t EditorData::get_scene_modified_time(int p_idx) const { | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX_V(p_idx, edited_scene.size(), 0); | 
					
						
							|  |  |  | 	return edited_scene[p_idx].file_modified_time; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-24 14:18:02 -03:00
										 |  |  | String EditorData::get_scene_type(int p_idx) const { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_idx, edited_scene.size(), String()); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!edited_scene[p_idx].root) { | 
					
						
							| 
									
										
										
										
											2015-07-24 14:18:02 -03:00
										 |  |  | 		return ""; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-02 23:03:46 -03:00
										 |  |  | 	return edited_scene[p_idx].root->get_class(); | 
					
						
							| 
									
										
										
										
											2015-07-24 14:18:02 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-23 18:28:30 -03:00
										 |  |  | void EditorData::move_edited_scene_to_index(int p_idx) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX(current_edited_scene, edited_scene.size()); | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX(p_idx, edited_scene.size()); | 
					
						
							| 
									
										
										
										
											2016-01-23 18:28:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	EditedScene es = edited_scene[current_edited_scene]; | 
					
						
							| 
									
										
										
										
											2021-07-03 16:17:03 -06:00
										 |  |  | 	edited_scene.remove_at(current_edited_scene); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	edited_scene.insert(p_idx, es); | 
					
						
							|  |  |  | 	current_edited_scene = p_idx; | 
					
						
							| 
									
										
										
										
											2016-01-23 18:28:30 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-07-26 10:44:10 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | Ref<Script> EditorData::get_scene_root_script(int p_idx) const { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_idx, edited_scene.size(), Ref<Script>()); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!edited_scene[p_idx].root) { | 
					
						
							| 
									
										
										
										
											2015-07-26 10:44:10 -03:00
										 |  |  | 		return Ref<Script>(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	Ref<Script> s = edited_scene[p_idx].root->get_script(); | 
					
						
							| 
									
										
										
										
											2024-08-25 14:15:10 +02:00
										 |  |  | 	if (s.is_null() && edited_scene[p_idx].root->get_child_count()) { | 
					
						
							| 
									
										
										
										
											2015-07-26 10:44:10 -03:00
										 |  |  | 		Node *n = edited_scene[p_idx].root->get_child(0); | 
					
						
							| 
									
										
										
										
											2024-08-25 14:15:10 +02:00
										 |  |  | 		while (s.is_null() && n && n->get_scene_file_path().is_empty()) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			s = n->get_script(); | 
					
						
							|  |  |  | 			n = n->get_parent(); | 
					
						
							| 
									
										
										
										
											2015-07-26 10:44:10 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return s; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-19 18:48:59 +01:00
										 |  |  | String EditorData::get_scene_title(int p_idx, bool p_always_strip_extension) const { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_idx, edited_scene.size(), String()); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!edited_scene[p_idx].root) { | 
					
						
							| 
									
										
										
										
											2017-12-02 16:58:58 +07:00
										 |  |  | 		return TTR("[empty]"); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-12-09 03:42:46 -06:00
										 |  |  | 	if (edited_scene[p_idx].root->get_scene_file_path().is_empty()) { | 
					
						
							| 
									
										
										
										
											2017-12-02 16:58:58 +07:00
										 |  |  | 		return TTR("[unsaved]"); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-19 18:48:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-30 16:30:55 +02:00
										 |  |  | 	const String filename = edited_scene[p_idx].root->get_scene_file_path().get_file(); | 
					
						
							| 
									
										
										
										
											2020-01-19 18:48:59 +01:00
										 |  |  | 	const String basename = filename.get_basename(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (p_always_strip_extension) { | 
					
						
							|  |  |  | 		return basename; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Return the filename including the extension if there's ambiguity (e.g. both `foo.tscn` and `foo.scn` are being edited).
 | 
					
						
							|  |  |  | 	for (int i = 0; i < edited_scene.size(); i++) { | 
					
						
							|  |  |  | 		if (i == p_idx) { | 
					
						
							|  |  |  | 			// Don't compare the edited scene against itself.
 | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-30 16:30:55 +02:00
										 |  |  | 		if (edited_scene[i].root && basename == edited_scene[i].root->get_scene_file_path().get_file().get_basename()) { | 
					
						
							| 
									
										
										
										
											2020-01-19 18:48:59 +01:00
										 |  |  | 			return filename; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-06-16 00:30:03 +09:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-19 18:48:59 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Else, return just the basename as there's no ambiguity.
 | 
					
						
							|  |  |  | 	return basename; | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-26 16:32:12 -03:00
										 |  |  | void EditorData::set_scene_path(int p_idx, const String &p_path) { | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX(p_idx, edited_scene.size()); | 
					
						
							| 
									
										
										
										
											2019-08-15 19:47:21 +02:00
										 |  |  | 	edited_scene.write[p_idx].path = p_path; | 
					
						
							| 
									
										
										
										
											2017-12-26 16:32:12 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!edited_scene[p_idx].root) { | 
					
						
							| 
									
										
										
										
											2017-12-26 16:32:12 -03:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-09-30 16:30:55 +02:00
										 |  |  | 	edited_scene[p_idx].root->set_scene_file_path(p_path); | 
					
						
							| 
									
										
										
										
											2017-12-26 16:32:12 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | String EditorData::get_scene_path(int p_idx) const { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_idx, edited_scene.size(), String()); | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-15 19:47:21 +02:00
										 |  |  | 	if (edited_scene[p_idx].root) { | 
					
						
							| 
									
										
										
										
											2021-12-09 03:42:46 -06:00
										 |  |  | 		if (edited_scene[p_idx].root->get_scene_file_path().is_empty()) { | 
					
						
							| 
									
										
										
										
											2021-09-30 16:30:55 +02:00
										 |  |  | 			edited_scene[p_idx].root->set_scene_file_path(edited_scene[p_idx].path); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2021-09-30 16:30:55 +02:00
										 |  |  | 			return edited_scene[p_idx].root->get_scene_file_path(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-15 19:47:21 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return edited_scene[p_idx].path; | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void EditorData::set_edited_scene_live_edit_root(const NodePath &p_root) { | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX(current_edited_scene, edited_scene.size()); | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	edited_scene.write[current_edited_scene].live_edit_root = p_root; | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | NodePath EditorData::get_edited_scene_live_edit_root() { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX_V(current_edited_scene, edited_scene.size(), String()); | 
					
						
							| 
									
										
										
										
											2015-08-02 12:29:37 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return edited_scene[current_edited_scene].live_edit_root; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | void EditorData::save_edited_scene_state(EditorSelection *p_selection, EditorSelectionHistory *p_history, const Dictionary &p_custom) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX(current_edited_scene, edited_scene.size()); | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 	EditedScene &es = edited_scene.write[current_edited_scene]; | 
					
						
							| 
									
										
										
										
											2019-11-10 09:32:07 +01:00
										 |  |  | 	es.selection = p_selection->get_full_selected_node_list(); | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	es.history_current = p_history->current_elem_idx; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	es.history_stored = p_history->history; | 
					
						
							| 
									
										
										
										
											2023-05-11 04:17:03 +02:00
										 |  |  | 	es.editor_states = get_editor_plugin_states(); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	es.custom_state = p_custom; | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | Dictionary EditorData::restore_edited_scene_state(EditorSelection *p_selection, EditorSelectionHistory *p_history) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX_V(current_edited_scene, edited_scene.size(), Dictionary()); | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-05 13:40:26 +03:00
										 |  |  | 	const EditedScene &es = edited_scene.write[current_edited_scene]; | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	p_history->current_elem_idx = es.history_current; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	p_history->history = es.history_stored; | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	p_selection->clear(); | 
					
						
							| 
									
										
										
										
											2021-07-15 23:45:57 -04:00
										 |  |  | 	for (Node *E : es.selection) { | 
					
						
							|  |  |  | 		p_selection->add_node(E); | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-05-11 04:17:03 +02:00
										 |  |  | 	set_editor_plugin_states(es.editor_states); | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return es.custom_state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorData::clear_edited_scenes() { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < edited_scene.size(); i++) { | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | 		if (edited_scene[i].root) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			memdelete(edited_scene[i].root); | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	edited_scene.clear(); | 
					
						
							| 
									
										
										
										
											2025-07-26 14:03:45 +03:00
										 |  |  | 	SceneTree::get_singleton()->set_edited_scene_root(nullptr); | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorData::set_plugin_window_layout(Ref<ConfigFile> p_layout) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < editor_plugins.size(); i++) { | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | 		editor_plugins[i]->set_window_layout(p_layout); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorData::get_plugin_window_layout(Ref<ConfigFile> p_layout) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < editor_plugins.size(); i++) { | 
					
						
							| 
									
										
										
										
											2015-06-22 00:03:19 -03:00
										 |  |  | 		editor_plugins[i]->get_window_layout(p_layout); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-25 14:43:17 -05:00
										 |  |  | bool EditorData::script_class_is_parent(const String &p_class, const String &p_inherits) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!ScriptServer::is_global_class(p_class)) { | 
					
						
							| 
									
										
										
										
											2018-07-25 14:43:17 -05:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-11-30 17:44:22 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-07 11:37:48 -06:00
										 |  |  | 	String base = p_class; | 
					
						
							|  |  |  | 	while (base != p_inherits) { | 
					
						
							| 
									
										
										
										
											2018-07-25 14:43:17 -05:00
										 |  |  | 		if (ClassDB::class_exists(base)) { | 
					
						
							|  |  |  | 			return ClassDB::is_parent_class(base, p_inherits); | 
					
						
							|  |  |  | 		} else if (ScriptServer::is_global_class(base)) { | 
					
						
							| 
									
										
										
										
											2022-02-07 11:37:48 -06:00
										 |  |  | 			base = ScriptServer::get_global_class_base(base); | 
					
						
							| 
									
										
										
										
											2018-07-25 14:43:17 -05:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-06 20:25:05 +01:00
										 |  |  | Variant EditorData::script_class_instance(const String &p_class) { | 
					
						
							| 
									
										
										
										
											2018-07-28 22:36:43 -05:00
										 |  |  | 	if (ScriptServer::is_global_class(p_class)) { | 
					
						
							| 
									
										
										
										
											2022-11-25 05:21:15 -05:00
										 |  |  | 		Ref<Script> script = script_class_load_script(p_class); | 
					
						
							|  |  |  | 		if (script.is_valid()) { | 
					
						
							| 
									
										
										
										
											2022-12-18 19:19:24 -05:00
										 |  |  | 			// Store in a variant to initialize the refcount if needed.
 | 
					
						
							| 
									
										
										
										
											2025-02-12 00:51:22 +01:00
										 |  |  | 			Variant v = ClassDB::instantiate(script->get_instance_base_type()); | 
					
						
							|  |  |  | 			if (v) { | 
					
						
							|  |  |  | 				Object *obj = v; | 
					
						
							|  |  |  | 				PropertyUtils::assign_custom_type_script(obj, script); | 
					
						
							|  |  |  | 				obj->set_script(script); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2025-02-12 00:51:22 +01:00
										 |  |  | 			return v; | 
					
						
							| 
									
										
										
										
											2018-07-28 22:36:43 -05:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-01-06 20:25:05 +01:00
										 |  |  | 	return Variant(); | 
					
						
							| 
									
										
										
										
											2018-07-28 22:36:43 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-06 13:10:25 +01:00
										 |  |  | Ref<Script> EditorData::script_class_load_script(const String &p_class) const { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!ScriptServer::is_global_class(p_class)) { | 
					
						
							| 
									
										
										
										
											2019-11-06 13:10:25 +01:00
										 |  |  | 		return Ref<Script>(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-06 13:10:25 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	String path = ScriptServer::get_global_class_path(p_class); | 
					
						
							|  |  |  | 	return ResourceLoader::load(path, "Script"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-02 16:40:51 -05:00
										 |  |  | void EditorData::script_class_set_icon_path(const String &p_class, const String &p_icon_path) { | 
					
						
							|  |  |  | 	_script_class_icon_paths[p_class] = p_icon_path; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-28 10:27:56 +01:00
										 |  |  | String EditorData::script_class_get_icon_path(const String &p_class, bool *r_valid) const { | 
					
						
							| 
									
										
										
										
											2018-09-02 16:40:51 -05:00
										 |  |  | 	String current = p_class; | 
					
						
							| 
									
										
										
										
											2025-01-28 10:27:56 +01:00
										 |  |  | 	while (true) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (!ScriptServer::is_global_class(current)) { | 
					
						
							| 
									
										
										
										
											2025-01-28 10:27:56 +01:00
										 |  |  | 			// If the classnames chain has a native class ancestor, we're done with success.
 | 
					
						
							|  |  |  | 			if (r_valid) { | 
					
						
							|  |  |  | 				*r_valid = ClassDB::class_exists(current); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-09-02 16:40:51 -05:00
										 |  |  | 			return String(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-01-28 10:27:56 +01:00
										 |  |  | 		HashMap<StringName, String>::ConstIterator E = _script_class_icon_paths.find(current); | 
					
						
							| 
									
										
										
										
											2025-02-22 04:40:52 +02:00
										 |  |  | 		if ((bool)E) { | 
					
						
							| 
									
										
										
										
											2025-04-30 15:42:29 +03:00
										 |  |  | 			if (r_valid) { | 
					
						
							|  |  |  | 				*r_valid = !E->value.is_empty(); | 
					
						
							|  |  |  | 				return E->value; | 
					
						
							|  |  |  | 			} else if (!E->value.is_empty()) { | 
					
						
							|  |  |  | 				return E->value; | 
					
						
							| 
									
										
										
										
											2025-01-28 10:27:56 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		current = ScriptServer::get_global_class_base(current); | 
					
						
							| 
									
										
										
										
											2018-09-02 16:40:51 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | StringName EditorData::script_class_get_name(const String &p_path) const { | 
					
						
							|  |  |  | 	return _script_class_file_to_path.has(p_path) ? _script_class_file_to_path[p_path] : StringName(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorData::script_class_set_name(const String &p_path, const StringName &p_class) { | 
					
						
							|  |  |  | 	_script_class_file_to_path[p_path] = p_class; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-10 19:44:36 -05:00
										 |  |  | void EditorData::script_class_save_global_classes() { | 
					
						
							|  |  |  | 	List<StringName> global_classes; | 
					
						
							|  |  |  | 	ScriptServer::get_global_class_list(&global_classes); | 
					
						
							|  |  |  | 	Array array_classes; | 
					
						
							|  |  |  | 	for (const StringName &class_name : global_classes) { | 
					
						
							|  |  |  | 		Dictionary d; | 
					
						
							|  |  |  | 		String *icon = _script_class_icon_paths.getptr(class_name); | 
					
						
							|  |  |  | 		d["class"] = class_name; | 
					
						
							|  |  |  | 		d["language"] = ScriptServer::get_global_class_language(class_name); | 
					
						
							|  |  |  | 		d["path"] = ScriptServer::get_global_class_path(class_name); | 
					
						
							|  |  |  | 		d["base"] = ScriptServer::get_global_class_base(class_name); | 
					
						
							|  |  |  | 		d["icon"] = icon ? *icon : String(); | 
					
						
							|  |  |  | 		d["is_abstract"] = ScriptServer::is_global_class_abstract(class_name); | 
					
						
							|  |  |  | 		d["is_tool"] = ScriptServer::is_global_class_tool(class_name); | 
					
						
							|  |  |  | 		array_classes.push_back(d); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ProjectSettings::get_singleton()->store_global_class_list(array_classes); | 
					
						
							| 
									
										
										
										
											2018-07-28 22:36:43 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorData::script_class_load_icon_paths() { | 
					
						
							|  |  |  | 	script_class_clear_icon_paths(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-25 15:08:32 +01:00
										 |  |  | #ifndef DISABLE_DEPRECATED
 | 
					
						
							| 
									
										
										
										
											2018-11-16 15:26:55 +01:00
										 |  |  | 	if (ProjectSettings::get_singleton()->has_setting("_global_script_class_icons")) { | 
					
						
							| 
									
										
										
										
											2022-10-18 16:43:37 +02:00
										 |  |  | 		Dictionary d = GLOBAL_GET("_global_script_class_icons"); | 
					
						
							| 
									
										
										
										
											2018-07-28 22:36:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-12 06:43:48 +08:00
										 |  |  | 		for (const KeyValue<Variant, Variant> &kv : d) { | 
					
						
							|  |  |  | 			String name = kv.key.operator String(); | 
					
						
							|  |  |  | 			_script_class_icon_paths[name] = kv.value; | 
					
						
							| 
									
										
										
										
											2018-09-02 16:40:51 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-16 15:26:55 +01:00
										 |  |  | 			String path = ScriptServer::get_global_class_path(name); | 
					
						
							|  |  |  | 			script_class_set_name(path, name); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-12-25 15:08:32 +01:00
										 |  |  | 		ProjectSettings::get_singleton()->clear("_global_script_class_icons"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Array script_classes = ProjectSettings::get_singleton()->get_global_class_list(); | 
					
						
							|  |  |  | 	for (int i = 0; i < script_classes.size(); i++) { | 
					
						
							|  |  |  | 		Dictionary d = script_classes[i]; | 
					
						
							|  |  |  | 		if (!d.has("class") || !d.has("path") || !d.has("icon")) { | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		String name = d["class"]; | 
					
						
							|  |  |  | 		_script_class_icon_paths[name] = d["icon"]; | 
					
						
							|  |  |  | 		script_class_set_name(d["path"], name); | 
					
						
							| 
									
										
										
										
											2018-07-28 22:36:43 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-31 21:17:59 +02:00
										 |  |  | Ref<Texture2D> EditorData::extension_class_get_icon(const String &p_class) const { | 
					
						
							|  |  |  | 	if (GDExtensionManager::get_singleton()->class_has_icon_path(p_class)) { | 
					
						
							|  |  |  | 		String icon_path = GDExtensionManager::get_singleton()->class_get_icon_path(p_class); | 
					
						
							|  |  |  | 		Ref<Texture2D> icon = _load_script_icon(icon_path); | 
					
						
							|  |  |  | 		if (icon.is_valid()) { | 
					
						
							|  |  |  | 			return icon; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nullptr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-31 21:17:59 +02:00
										 |  |  | Ref<Texture2D> EditorData::_load_script_icon(const String &p_path) const { | 
					
						
							|  |  |  | 	if (!p_path.is_empty() && ResourceLoader::exists(p_path)) { | 
					
						
							|  |  |  | 		Ref<Texture2D> icon = ResourceLoader::load(p_path); | 
					
						
							|  |  |  | 		if (icon.is_valid()) { | 
					
						
							|  |  |  | 			return icon; | 
					
						
							| 
									
										
										
										
											2023-03-31 21:17:59 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nullptr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-28 10:27:56 +01:00
										 |  |  | Ref<Texture2D> EditorData::get_script_icon(const String &p_script_path) { | 
					
						
							| 
									
										
										
										
											2023-03-31 21:17:59 +02:00
										 |  |  | 	// Take from the local cache, if available.
 | 
					
						
							| 
									
										
										
										
											2025-05-27 13:59:13 +02:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		Ref<Texture2D> *icon = _script_icon_cache.getptr(p_script_path); | 
					
						
							|  |  |  | 		if (icon) { | 
					
						
							|  |  |  | 			// Can be an empty value if we can't resolve any icon for this script.
 | 
					
						
							|  |  |  | 			// An empty value is still cached to avoid unnecessary attempts at resolving it again.
 | 
					
						
							|  |  |  | 			return *icon; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-01-28 10:27:56 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Fast path in case the whole hierarchy is made of global classes.
 | 
					
						
							|  |  |  | 	StringName class_name = script_class_get_name(p_script_path); | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (class_name != StringName()) { | 
					
						
							|  |  |  | 			bool icon_valid = false; | 
					
						
							|  |  |  | 			String icon_path = script_class_get_icon_path(class_name, &icon_valid); | 
					
						
							|  |  |  | 			if (icon_valid) { | 
					
						
							|  |  |  | 				Ref<Texture2D> icon = _load_script_icon(icon_path); | 
					
						
							|  |  |  | 				_script_icon_cache[p_script_path] = icon; | 
					
						
							|  |  |  | 				return icon; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-03-31 21:17:59 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-28 10:27:56 +01:00
										 |  |  | 	Ref<Script> base_scr = ResourceLoader::load(p_script_path, "Script"); | 
					
						
							| 
									
										
										
										
											2023-03-31 21:17:59 +02:00
										 |  |  | 	while (base_scr.is_valid()) { | 
					
						
							|  |  |  | 		// Check for scripted classes.
 | 
					
						
							| 
									
										
										
										
											2023-08-24 12:49:20 +02:00
										 |  |  | 		String icon_path; | 
					
						
							| 
									
										
										
										
											2025-01-28 10:27:56 +01:00
										 |  |  | 		StringName base_class_name = script_class_get_name(base_scr->get_path()); | 
					
						
							|  |  |  | 		if (base_scr->is_built_in() || base_class_name == StringName()) { | 
					
						
							| 
									
										
										
										
											2023-08-24 12:49:20 +02:00
										 |  |  | 			icon_path = base_scr->get_class_icon_path(); | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2025-01-28 10:27:56 +01:00
										 |  |  | 			icon_path = script_class_get_icon_path(base_class_name); | 
					
						
							| 
									
										
										
										
											2023-08-24 12:49:20 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-31 21:17:59 +02:00
										 |  |  | 		Ref<Texture2D> icon = _load_script_icon(icon_path); | 
					
						
							| 
									
										
										
										
											2023-03-31 21:17:59 +02:00
										 |  |  | 		if (icon.is_valid()) { | 
					
						
							| 
									
										
										
										
											2025-01-28 10:27:56 +01:00
										 |  |  | 			_script_icon_cache[p_script_path] = icon; | 
					
						
							| 
									
										
										
										
											2023-03-31 21:17:59 +02:00
										 |  |  | 			return icon; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Check for legacy custom classes defined by plugins.
 | 
					
						
							|  |  |  | 		// TODO: Should probably be deprecated in 4.x
 | 
					
						
							|  |  |  | 		const EditorData::CustomType *ctype = get_custom_type_by_path(base_scr->get_path()); | 
					
						
							|  |  |  | 		if (ctype && ctype->icon.is_valid()) { | 
					
						
							| 
									
										
										
										
											2025-01-28 10:27:56 +01:00
										 |  |  | 			_script_icon_cache[p_script_path] = ctype->icon; | 
					
						
							| 
									
										
										
										
											2023-03-31 21:17:59 +02:00
										 |  |  | 			return ctype->icon; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Move to the base class.
 | 
					
						
							|  |  |  | 		base_scr = base_scr->get_base_script(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-25 15:03:59 +02:00
										 |  |  | 	// Check if the base type is an extension-defined type.
 | 
					
						
							| 
									
										
										
										
											2025-01-28 10:27:56 +01:00
										 |  |  | 	Ref<Texture2D> ext_icon = extension_class_get_icon(class_name); | 
					
						
							| 
									
										
										
										
											2023-06-25 15:03:59 +02:00
										 |  |  | 	if (ext_icon.is_valid()) { | 
					
						
							| 
									
										
										
										
											2025-01-28 10:27:56 +01:00
										 |  |  | 		_script_icon_cache[p_script_path] = ext_icon; | 
					
						
							| 
									
										
										
										
											2023-06-25 15:03:59 +02:00
										 |  |  | 		return ext_icon; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-31 21:17:59 +02:00
										 |  |  | 	// If no icon found, cache it as null.
 | 
					
						
							| 
									
										
										
										
											2025-01-28 10:27:56 +01:00
										 |  |  | 	_script_icon_cache[p_script_path] = Ref<Texture2D>(); | 
					
						
							|  |  |  | 	return Ref<Texture2D>(); | 
					
						
							| 
									
										
										
										
											2023-03-31 21:17:59 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorData::clear_script_icon_cache() { | 
					
						
							|  |  |  | 	_script_icon_cache.clear(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | EditorData::EditorData() { | 
					
						
							| 
									
										
										
										
											2022-12-23 23:53:16 +01:00
										 |  |  | 	undo_redo_manager = memnew(EditorUndoRedoManager); | 
					
						
							| 
									
										
										
										
											2018-07-28 22:36:43 -05:00
										 |  |  | 	script_class_load_icon_paths(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-23 23:53:16 +01:00
										 |  |  | EditorData::~EditorData() { | 
					
						
							|  |  |  | 	memdelete(undo_redo_manager); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | ///////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | void EditorSelection::_node_removed(Node *p_node) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!selection.has(p_node)) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	Object *meta = selection[p_node]; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (meta) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		memdelete(meta); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	selection.erase(p_node); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	changed = true; | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	node_list_changed = true; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorSelection::add_node(Node *p_node) { | 
					
						
							| 
									
										
										
										
											2016-02-27 00:32:00 -03:00
										 |  |  | 	ERR_FAIL_NULL(p_node); | 
					
						
							| 
									
										
										
										
											2016-08-24 02:19:48 +09:00
										 |  |  | 	ERR_FAIL_COND(!p_node->is_inside_tree()); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (selection.has(p_node)) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	changed = true; | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	node_list_changed = true; | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	Object *meta = nullptr; | 
					
						
							| 
									
										
										
										
											2021-07-15 23:45:57 -04:00
										 |  |  | 	for (Object *E : editor_plugins) { | 
					
						
							|  |  |  | 		meta = E->call("_get_editor_data", p_node); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		if (meta) { | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	selection[p_node] = meta; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-13 16:56:03 +02:00
										 |  |  | 	p_node->connect(SceneStringName(tree_exiting), callable_mp(this, &EditorSelection::_node_removed).bind(p_node), CONNECT_ONE_SHOT); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorSelection::remove_node(Node *p_node) { | 
					
						
							| 
									
										
										
										
											2016-02-27 00:32:00 -03:00
										 |  |  | 	ERR_FAIL_NULL(p_node); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!selection.has(p_node)) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	changed = true; | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	node_list_changed = true; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	Object *meta = selection[p_node]; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (meta) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		memdelete(meta); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	selection.erase(p_node); | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-13 16:56:03 +02:00
										 |  |  | 	p_node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &EditorSelection::_node_removed)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | bool EditorSelection::is_selected(Node *p_node) const { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return selection.has(p_node); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorSelection::_bind_methods() { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("clear"), &EditorSelection::clear); | 
					
						
							| 
									
										
										
										
											2017-08-09 13:19:41 +02:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("add_node", "node"), &EditorSelection::add_node); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("remove_node", "node"), &EditorSelection::remove_node); | 
					
						
							| 
									
										
										
										
											2018-01-21 01:12:25 -05:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_selected_nodes"), &EditorSelection::get_selected_nodes); | 
					
						
							| 
									
										
										
										
											2024-12-01 06:40:29 -08:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_top_selected_nodes"), &EditorSelection::get_top_selected_nodes); | 
					
						
							|  |  |  | #ifndef DISABLE_DEPRECATED
 | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_transformable_selected_nodes"), &EditorSelection::get_top_selected_nodes); | 
					
						
							|  |  |  | #endif // DISABLE_DEPRECATED
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ADD_SIGNAL(MethodInfo("selection_changed")); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorSelection::add_editor_plugin(Object *p_object) { | 
					
						
							|  |  |  | 	editor_plugins.push_back(p_object); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | void EditorSelection::_update_node_list() { | 
					
						
							|  |  |  | 	if (!node_list_changed) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-01 06:40:29 -08:00
										 |  |  | 	top_selected_node_list.clear(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	// If the selection does not have the parent of the selected node, then add the node to the node list.
 | 
					
						
							|  |  |  | 	// However, if the parent is already selected, then adding this node is redundant as
 | 
					
						
							|  |  |  | 	// it is included with the parent, so skip it.
 | 
					
						
							| 
									
										
										
										
											2021-08-09 14:13:42 -06:00
										 |  |  | 	for (const KeyValue<Node *, Object *> &E : selection) { | 
					
						
							|  |  |  | 		Node *parent = E.key; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		parent = parent->get_parent(); | 
					
						
							|  |  |  | 		bool skip = false; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		while (parent) { | 
					
						
							|  |  |  | 			if (selection.has(parent)) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				skip = true; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			parent = parent->get_parent(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (skip) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-12-01 06:40:29 -08:00
										 |  |  | 		top_selected_node_list.push_back(E.key); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	node_list_changed = true; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorSelection::update() { | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	_update_node_list(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!changed) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	changed = false; | 
					
						
							| 
									
										
										
										
											2017-12-18 22:12:57 +09:00
										 |  |  | 	if (!emitted) { | 
					
						
							|  |  |  | 		emitted = true; | 
					
						
							| 
									
										
										
										
											2023-12-18 15:46:56 +01:00
										 |  |  | 		callable_mp(this, &EditorSelection::_emit_change).call_deferred(); | 
					
						
							| 
									
										
										
										
											2017-12-18 22:12:57 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditorSelection::_emit_change() { | 
					
						
							| 
									
										
										
										
											2021-07-17 18:22:52 -03:00
										 |  |  | 	emit_signal(SNAME("selection_changed")); | 
					
						
							| 
									
										
										
										
											2017-12-18 22:12:57 +09:00
										 |  |  | 	emitted = false; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-01 06:40:29 -08:00
										 |  |  | TypedArray<Node> EditorSelection::get_top_selected_nodes() { | 
					
						
							| 
									
										
										
										
											2022-08-05 03:41:48 +02:00
										 |  |  | 	TypedArray<Node> ret; | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-01 06:40:29 -08:00
										 |  |  | 	for (const Node *E : top_selected_node_list) { | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 		ret.push_back(E); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TypedArray<Node> EditorSelection::get_selected_nodes() { | 
					
						
							|  |  |  | 	TypedArray<Node> ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (const KeyValue<Node *, Object *> &E : selection) { | 
					
						
							|  |  |  | 		ret.push_back(E.key); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-01 06:40:29 -08:00
										 |  |  | const List<Node *> &EditorSelection::get_top_selected_node_list() { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (changed) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		update(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 		_update_node_list(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-12-01 06:40:29 -08:00
										 |  |  | 	return top_selected_node_list; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 16:45:16 +01:00
										 |  |  | List<Node *> EditorSelection::get_full_selected_node_list() { | 
					
						
							|  |  |  | 	List<Node *> node_list; | 
					
						
							| 
									
										
										
										
											2021-08-09 14:13:42 -06:00
										 |  |  | 	for (const KeyValue<Node *, Object *> &E : selection) { | 
					
						
							|  |  |  | 		node_list.push_back(E.key); | 
					
						
							| 
									
										
										
										
											2019-11-04 16:45:16 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return node_list; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | void EditorSelection::clear() { | 
					
						
							| 
									
										
										
										
											2020-12-15 12:04:21 +00:00
										 |  |  | 	while (!selection.is_empty()) { | 
					
						
							| 
									
										
										
										
											2022-05-13 15:04:37 +02:00
										 |  |  | 		remove_node(selection.begin()->key); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	changed = true; | 
					
						
							| 
									
										
										
										
											2022-03-30 20:12:26 +02:00
										 |  |  | 	node_list_changed = true; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | EditorSelection::~EditorSelection() { | 
					
						
							|  |  |  | 	clear(); | 
					
						
							|  |  |  | } |