| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /**************************************************************************/ | 
					
						
							| 
									
										
										
										
											2017-08-05 21:55:37 +07:00
										 |  |  | /*  node_path.cpp                                                         */ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*                         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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-05 09:12:53 -03:00
										 |  |  | #include "node_path.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-18 19:56:23 +08:00
										 |  |  | #include "core/variant/variant.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-02 15:08:35 -03:00
										 |  |  | void NodePath::_update_hash_cache() const { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	uint32_t h = data->absolute ? 1 : 0; | 
					
						
							|  |  |  | 	int pc = data->path.size(); | 
					
						
							|  |  |  | 	const StringName *sn = data->path.ptr(); | 
					
						
							|  |  |  | 	for (int i = 0; i < pc; i++) { | 
					
						
							|  |  |  | 		h = h ^ sn[i].hash(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	int spc = data->subpath.size(); | 
					
						
							|  |  |  | 	const StringName *ssn = data->subpath.ptr(); | 
					
						
							|  |  |  | 	for (int i = 0; i < spc; i++) { | 
					
						
							|  |  |  | 		h = h ^ ssn[i].hash(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-02 15:08:35 -03:00
										 |  |  | 	data->hash_cache_valid = true; | 
					
						
							|  |  |  | 	data->hash_cache = h; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-19 21:26:12 -03:00
										 |  |  | void NodePath::prepend_period() { | 
					
						
							|  |  |  | 	if (data->path.size() && data->path[0].operator String() != ".") { | 
					
						
							|  |  |  | 		data->path.insert(0, "."); | 
					
						
							| 
									
										
										
										
											2018-07-02 15:08:35 -03:00
										 |  |  | 		data->hash_cache_valid = false; | 
					
						
							| 
									
										
										
										
											2016-07-19 21:26:12 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | bool NodePath::is_absolute() const { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!data) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return data->absolute; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | int NodePath::get_name_count() const { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!data) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return data->path.size(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | StringName NodePath::get_name(int p_idx) const { | 
					
						
							| 
									
										
										
										
											2023-09-09 16:11:33 +02:00
										 |  |  | 	ERR_FAIL_NULL_V(data, StringName()); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_idx, data->path.size(), StringName()); | 
					
						
							|  |  |  | 	return data->path[p_idx]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int NodePath::get_subname_count() const { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!data) { | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							|  |  |  | 	return data->subpath.size(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | StringName NodePath::get_subname(int p_idx) const { | 
					
						
							| 
									
										
										
										
											2023-09-09 16:11:33 +02:00
										 |  |  | 	ERR_FAIL_NULL_V(data, StringName()); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_idx, data->subpath.size(), StringName()); | 
					
						
							|  |  |  | 	return data->subpath[p_idx]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-17 14:38:44 -04:00
										 |  |  | int NodePath::get_total_name_count() const { | 
					
						
							|  |  |  | 	if (!data) { | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return data->path.size() + data->subpath.size(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | void NodePath::unref() { | 
					
						
							|  |  |  | 	if (data && data->refcount.unref()) { | 
					
						
							|  |  |  | 		memdelete(data); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	data = nullptr; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | bool NodePath::operator==(const NodePath &p_path) const { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (data == p_path.data) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return true; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!data || !p_path.data) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (data->absolute != p_path.data->absolute) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-02 15:08:35 -03:00
										 |  |  | 	int path_size = data->path.size(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (path_size != p_path.data->path.size()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2018-07-02 15:08:35 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int subpath_size = data->subpath.size(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-02 15:08:35 -03:00
										 |  |  | 	if (subpath_size != p_path.data->subpath.size()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2018-07-02 15:08:35 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-02 15:08:35 -03:00
										 |  |  | 	const StringName *l_path_ptr = data->path.ptr(); | 
					
						
							|  |  |  | 	const StringName *r_path_ptr = p_path.data->path.ptr(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (int i = 0; i < path_size; i++) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (l_path_ptr[i] != r_path_ptr[i]) { | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-02 15:08:35 -03:00
										 |  |  | 	const StringName *l_subpath_ptr = data->subpath.ptr(); | 
					
						
							|  |  |  | 	const StringName *r_subpath_ptr = p_path.data->subpath.ptr(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (int i = 0; i < subpath_size; i++) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (l_subpath_ptr[i] != r_subpath_ptr[i]) { | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | bool NodePath::operator!=(const NodePath &p_path) const { | 
					
						
							|  |  |  | 	return (!(*this == p_path)); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | void NodePath::operator=(const NodePath &p_path) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (this == &p_path) { | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							|  |  |  | 	unref(); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	if (p_path.data && p_path.data->refcount.ref()) { | 
					
						
							|  |  |  | 		data = p_path.data; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NodePath::operator String() const { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!data) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return String(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	String ret; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (data->absolute) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		ret = "/"; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	for (int i = 0; i < data->path.size(); i++) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (i > 0) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			ret += "/"; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		ret += data->path[i].operator String(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (int i = 0; i < data->subpath.size(); i++) { | 
					
						
							|  |  |  | 		ret += ":" + data->subpath[i].operator String(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Vector<StringName> NodePath::get_names() const { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (data) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return data->path; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return Vector<StringName>(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-05-30 23:20:15 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | Vector<StringName> NodePath::get_subnames() const { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (data) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return data->subpath; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	return Vector<StringName>(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-27 17:06:50 +09:00
										 |  |  | StringName NodePath::get_concatenated_names() const { | 
					
						
							| 
									
										
										
										
											2023-09-09 16:11:33 +02:00
										 |  |  | 	ERR_FAIL_NULL_V(data, StringName()); | 
					
						
							| 
									
										
										
										
											2022-06-27 17:06:50 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!data->concatenated_path) { | 
					
						
							|  |  |  | 		int pc = data->path.size(); | 
					
						
							|  |  |  | 		String concatenated; | 
					
						
							|  |  |  | 		const StringName *sn = data->path.ptr(); | 
					
						
							|  |  |  | 		for (int i = 0; i < pc; i++) { | 
					
						
							| 
									
										
										
										
											2024-06-09 18:35:23 +09:00
										 |  |  | 			if (i > 0) { | 
					
						
							|  |  |  | 				concatenated += "/"; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			concatenated += sn[i].operator String(); | 
					
						
							| 
									
										
										
										
											2022-06-27 17:06:50 +09:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		data->concatenated_path = concatenated; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return data->concatenated_path; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-30 23:20:15 +03:00
										 |  |  | StringName NodePath::get_concatenated_subnames() const { | 
					
						
							| 
									
										
										
										
											2023-09-09 16:11:33 +02:00
										 |  |  | 	ERR_FAIL_NULL_V(data, StringName()); | 
					
						
							| 
									
										
										
										
											2017-05-30 23:20:15 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!data->concatenated_subpath) { | 
					
						
							|  |  |  | 		int spc = data->subpath.size(); | 
					
						
							|  |  |  | 		String concatenated; | 
					
						
							|  |  |  | 		const StringName *ssn = data->subpath.ptr(); | 
					
						
							|  |  |  | 		for (int i = 0; i < spc; i++) { | 
					
						
							| 
									
										
										
										
											2024-06-09 18:35:23 +09:00
										 |  |  | 			if (i > 0) { | 
					
						
							|  |  |  | 				concatenated += ":"; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			concatenated += ssn[i].operator String(); | 
					
						
							| 
									
										
										
										
											2017-05-30 23:20:15 +03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		data->concatenated_subpath = concatenated; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return data->concatenated_subpath; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-17 14:38:44 -04:00
										 |  |  | NodePath NodePath::slice(int p_begin, int p_end) const { | 
					
						
							|  |  |  | 	const int name_count = get_name_count(); | 
					
						
							|  |  |  | 	const int total_count = get_total_name_count(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int begin = CLAMP(p_begin, -total_count, total_count); | 
					
						
							|  |  |  | 	if (begin < 0) { | 
					
						
							|  |  |  | 		begin += total_count; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	int end = CLAMP(p_end, -total_count, total_count); | 
					
						
							|  |  |  | 	if (end < 0) { | 
					
						
							|  |  |  | 		end += total_count; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-12-30 21:22:26 +01:00
										 |  |  | 	const int sub_begin = MAX(begin - name_count, 0); | 
					
						
							| 
									
										
										
										
											2023-09-17 14:38:44 -04:00
										 |  |  | 	const int sub_end = MAX(end - name_count, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const Vector<StringName> names = get_names().slice(begin, end); | 
					
						
							|  |  |  | 	const Vector<StringName> sub_names = get_subnames().slice(sub_begin, sub_end); | 
					
						
							|  |  |  | 	const bool absolute = is_absolute() && (begin == 0); | 
					
						
							|  |  |  | 	return NodePath(names, sub_names, absolute); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | NodePath NodePath::rel_path_to(const NodePath &p_np) const { | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!is_absolute(), NodePath()); | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!p_np.is_absolute(), NodePath()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Vector<StringName> src_dirs = get_names(); | 
					
						
							|  |  |  | 	Vector<StringName> dst_dirs = p_np.get_names(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//find common parent
 | 
					
						
							|  |  |  | 	int common_parent = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (true) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (src_dirs.size() == common_parent) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if (dst_dirs.size() == common_parent) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if (src_dirs[common_parent] != dst_dirs[common_parent]) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		common_parent++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	common_parent--; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Vector<StringName> relpath; | 
					
						
							| 
									
										
										
										
											2021-07-09 11:21:27 -07:00
										 |  |  | 	relpath.resize(src_dirs.size() + dst_dirs.size() + 1); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-09 11:21:27 -07:00
										 |  |  | 	StringName *relpath_ptr = relpath.ptrw(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int path_size = 0; | 
					
						
							|  |  |  | 	StringName back_str(".."); | 
					
						
							|  |  |  | 	for (int i = common_parent + 1; i < src_dirs.size(); i++) { | 
					
						
							|  |  |  | 		relpath_ptr[path_size++] = back_str; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (int i = common_parent + 1; i < dst_dirs.size(); i++) { | 
					
						
							| 
									
										
										
										
											2021-07-09 11:21:27 -07:00
										 |  |  | 		relpath_ptr[path_size++] = dst_dirs[i]; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-09 11:21:27 -07:00
										 |  |  | 	if (path_size == 0) { | 
					
						
							|  |  |  | 		relpath_ptr[path_size++] = "."; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-09 11:21:27 -07:00
										 |  |  | 	relpath.resize(path_size); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-30 23:20:15 +03:00
										 |  |  | 	return NodePath(relpath, p_np.get_subnames(), false); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NodePath NodePath::get_as_property_path() const { | 
					
						
							| 
									
										
										
										
											2019-10-09 15:02:31 +02:00
										 |  |  | 	if (!data || !data->path.size()) { | 
					
						
							| 
									
										
										
										
											2017-11-22 14:13:56 +02:00
										 |  |  | 		return *this; | 
					
						
							| 
									
										
										
										
											2017-05-30 23:20:15 +03:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		Vector<StringName> new_path = data->subpath; | 
					
						
							| 
									
										
										
										
											2017-11-22 14:13:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		String initial_subname = data->path[0]; | 
					
						
							| 
									
										
										
										
											2018-04-21 22:35:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-26 17:38:02 +02:00
										 |  |  | 		for (int i = 1; i < data->path.size(); i++) { | 
					
						
							| 
									
										
										
										
											2018-04-21 22:35:23 +08:00
										 |  |  | 			initial_subname += "/" + data->path[i]; | 
					
						
							| 
									
										
										
										
											2017-11-22 14:13:56 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		new_path.insert(0, initial_subname); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-30 23:20:15 +03:00
										 |  |  | 		return NodePath(Vector<StringName>(), new_path, false); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-12 17:01:17 +02:00
										 |  |  | bool NodePath::is_empty() const { | 
					
						
							|  |  |  | 	return !data; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-10 09:09:09 -03:00
										 |  |  | void NodePath::simplify() { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!data) { | 
					
						
							| 
									
										
										
										
											2015-10-10 09:09:09 -03:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-10-10 09:09:09 -03:00
										 |  |  | 	for (int i = 0; i < data->path.size(); i++) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (data->path.size() == 1) { | 
					
						
							| 
									
										
										
										
											2015-10-10 09:09:09 -03:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-10-10 09:09:09 -03:00
										 |  |  | 		if (data->path[i].operator String() == ".") { | 
					
						
							| 
									
										
										
										
											2021-07-03 16:17:03 -06:00
										 |  |  | 			data->path.remove_at(i); | 
					
						
							| 
									
										
										
										
											2015-10-10 09:09:09 -03:00
										 |  |  | 			i--; | 
					
						
							| 
									
										
										
										
											2020-12-08 20:58:49 +02:00
										 |  |  | 		} else if (i > 0 && data->path[i].operator String() == ".." && data->path[i - 1].operator String() != "." && data->path[i - 1].operator String() != "..") { | 
					
						
							| 
									
										
										
										
											2015-10-10 09:09:09 -03:00
										 |  |  | 			//remove both
 | 
					
						
							| 
									
										
										
										
											2021-07-03 16:17:03 -06:00
										 |  |  | 			data->path.remove_at(i - 1); | 
					
						
							|  |  |  | 			data->path.remove_at(i - 1); | 
					
						
							| 
									
										
										
										
											2015-10-10 09:09:09 -03:00
										 |  |  | 			i -= 2; | 
					
						
							| 
									
										
										
										
											2025-03-20 00:07:31 +08:00
										 |  |  | 			if (data->path.is_empty()) { | 
					
						
							| 
									
										
										
										
											2015-10-10 09:09:09 -03:00
										 |  |  | 				data->path.push_back("."); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-02 15:08:35 -03:00
										 |  |  | 	data->hash_cache_valid = false; | 
					
						
							| 
									
										
										
										
											2015-10-10 09:09:09 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NodePath NodePath::simplified() const { | 
					
						
							|  |  |  | 	NodePath np = *this; | 
					
						
							|  |  |  | 	np.simplify(); | 
					
						
							|  |  |  | 	return np; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-12 17:01:17 +02:00
										 |  |  | NodePath::NodePath(const Vector<StringName> &p_path, bool p_absolute) { | 
					
						
							| 
									
										
										
										
											2025-03-20 00:07:31 +08:00
										 |  |  | 	if (p_path.is_empty() && !p_absolute) { | 
					
						
							| 
									
										
										
										
											2020-05-12 17:01:17 +02:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-12 17:01:17 +02:00
										 |  |  | 	data = memnew(Data); | 
					
						
							|  |  |  | 	data->refcount.init(); | 
					
						
							|  |  |  | 	data->absolute = p_absolute; | 
					
						
							|  |  |  | 	data->path = p_path; | 
					
						
							|  |  |  | 	data->hash_cache_valid = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NodePath::NodePath(const Vector<StringName> &p_path, const Vector<StringName> &p_subpath, bool p_absolute) { | 
					
						
							| 
									
										
										
										
											2025-03-20 00:07:31 +08:00
										 |  |  | 	if (p_path.is_empty() && p_subpath.is_empty() && !p_absolute) { | 
					
						
							| 
									
										
										
										
											2020-05-12 17:01:17 +02:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-12 17:01:17 +02:00
										 |  |  | 	data = memnew(Data); | 
					
						
							|  |  |  | 	data->refcount.init(); | 
					
						
							|  |  |  | 	data->absolute = p_absolute; | 
					
						
							|  |  |  | 	data->path = p_path; | 
					
						
							|  |  |  | 	data->subpath = p_subpath; | 
					
						
							|  |  |  | 	data->hash_cache_valid = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NodePath::NodePath(const NodePath &p_path) { | 
					
						
							|  |  |  | 	if (p_path.data && p_path.data->refcount.ref()) { | 
					
						
							|  |  |  | 		data = p_path.data; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NodePath::NodePath(const String &p_path) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (p_path.length() == 0) { | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							|  |  |  | 	String path = p_path; | 
					
						
							|  |  |  | 	Vector<StringName> subpath; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-26 15:08:25 +02:00
										 |  |  | 	bool absolute = (path[0] == '/'); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	bool last_is_slash = true; | 
					
						
							|  |  |  | 	int slices = 0; | 
					
						
							| 
									
										
										
										
											2024-11-16 18:52:15 +01:00
										 |  |  | 	int subpath_pos = path.find_char(':'); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (subpath_pos != -1) { | 
					
						
							|  |  |  | 		int from = subpath_pos + 1; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		for (int i = from; i <= path.length(); i++) { | 
					
						
							|  |  |  | 			if (path[i] == ':' || path[i] == 0) { | 
					
						
							|  |  |  | 				String str = path.substr(from, i - from); | 
					
						
							| 
									
										
										
										
											2021-12-09 03:42:46 -06:00
										 |  |  | 				if (str.is_empty()) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 					if (path[i] == 0) { | 
					
						
							| 
									
										
										
										
											2017-05-30 23:20:15 +03:00
										 |  |  | 						continue; // Allow end-of-path :
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2017-05-30 23:20:15 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-11 16:17:49 +02:00
										 |  |  | 					ERR_FAIL_MSG(vformat("Invalid NodePath '%s'.", p_path)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2017-05-30 23:20:15 +03:00
										 |  |  | 				subpath.push_back(str); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				from = i + 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		path = path.substr(0, subpath_pos); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-26 15:08:25 +02:00
										 |  |  | 	for (int i = (int)absolute; i < path.length(); i++) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		if (path[i] == '/') { | 
					
						
							|  |  |  | 			last_is_slash = true; | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 			if (last_is_slash) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				slices++; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			last_is_slash = false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (slices == 0 && !absolute && !subpath.size()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	data = memnew(Data); | 
					
						
							|  |  |  | 	data->refcount.init(); | 
					
						
							| 
									
										
										
										
											2019-06-26 15:08:25 +02:00
										 |  |  | 	data->absolute = absolute; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	data->subpath = subpath; | 
					
						
							| 
									
										
										
										
											2018-07-02 15:08:35 -03:00
										 |  |  | 	data->hash_cache_valid = false; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (slices == 0) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 	data->path.resize(slices); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	last_is_slash = true; | 
					
						
							| 
									
										
										
										
											2019-06-26 15:08:25 +02:00
										 |  |  | 	int from = (int)absolute; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	int slice = 0; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-26 15:08:25 +02:00
										 |  |  | 	for (int i = (int)absolute; i < path.length() + 1; i++) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		if (path[i] == '/' || path[i] == 0) { | 
					
						
							|  |  |  | 			if (!last_is_slash) { | 
					
						
							|  |  |  | 				String name = path.substr(from, i - from); | 
					
						
							|  |  |  | 				ERR_FAIL_INDEX(slice, data->path.size()); | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 				data->path.write[slice++] = name; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			from = i + 1; | 
					
						
							|  |  |  | 			last_is_slash = true; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			last_is_slash = false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NodePath::~NodePath() { | 
					
						
							|  |  |  | 	unref(); | 
					
						
							|  |  |  | } |