mirror of
				https://github.com/godotengine/godot.git
				synced 2025-11-03 23:21:15 +00:00 
			
		
		
		
	Merge pull request #104047 from YYF233333/dict_iter
Add const iteration support to `Dictionary`
This commit is contained in:
		
						commit
						22a7079afd
					
				
					 34 changed files with 131 additions and 179 deletions
				
			
		| 
						 | 
				
			
			@ -1555,11 +1555,8 @@ static void gdextension_placeholder_script_instance_update(GDExtensionScriptInst
 | 
			
		|||
		properties_list.push_back(PropertyInfo::from_dict(d));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	List<Variant> keys;
 | 
			
		||||
	values.get_key_list(&keys);
 | 
			
		||||
 | 
			
		||||
	for (const Variant &E : keys) {
 | 
			
		||||
		values_map.insert(E, values[E]);
 | 
			
		||||
	for (const KeyValue<Variant, Variant> &kv : values) {
 | 
			
		||||
		values_map.insert(kv.key, kv.value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	placeholder->update(properties_list, values_map);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -922,12 +922,9 @@ Variant JSON::_from_native(const Variant &p_variant, bool p_full_objects, int p_
 | 
			
		|||
 | 
			
		||||
			ERR_FAIL_COND_V_MSG(p_depth > Variant::MAX_RECURSION_DEPTH, ret, "Variant is too deep. Bailing.");
 | 
			
		||||
 | 
			
		||||
			List<Variant> keys;
 | 
			
		||||
			dict.get_key_list(&keys);
 | 
			
		||||
 | 
			
		||||
			for (const Variant &key : keys) {
 | 
			
		||||
				args.push_back(_from_native(key, p_full_objects, p_depth + 1));
 | 
			
		||||
				args.push_back(_from_native(dict[key], p_full_objects, p_depth + 1));
 | 
			
		||||
			for (const KeyValue<Variant, Variant> &kv : dict) {
 | 
			
		||||
				args.push_back(_from_native(kv.key, p_full_objects, p_depth + 1));
 | 
			
		||||
				args.push_back(_from_native(kv.value, p_full_objects, p_depth + 1));
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return ret;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1849,19 +1849,16 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
 | 
			
		|||
			}
 | 
			
		||||
			r_len += 4;
 | 
			
		||||
 | 
			
		||||
			List<Variant> keys;
 | 
			
		||||
			dict.get_key_list(&keys);
 | 
			
		||||
 | 
			
		||||
			for (const Variant &key : keys) {
 | 
			
		||||
			for (const KeyValue<Variant, Variant> &kv : dict) {
 | 
			
		||||
				int len;
 | 
			
		||||
				Error err = encode_variant(key, buf, len, p_full_objects, p_depth + 1);
 | 
			
		||||
				Error err = encode_variant(kv.key, buf, len, p_full_objects, p_depth + 1);
 | 
			
		||||
				ERR_FAIL_COND_V(err, err);
 | 
			
		||||
				ERR_FAIL_COND_V(len % 4, ERR_BUG);
 | 
			
		||||
				r_len += len;
 | 
			
		||||
				if (buf) {
 | 
			
		||||
					buf += len;
 | 
			
		||||
				}
 | 
			
		||||
				const Variant *value = dict.getptr(key);
 | 
			
		||||
				const Variant *value = dict.getptr(kv.key);
 | 
			
		||||
				ERR_FAIL_NULL_V(value, ERR_BUG);
 | 
			
		||||
				err = encode_variant(*value, buf, len, p_full_objects, p_depth + 1);
 | 
			
		||||
				ERR_FAIL_COND_V(err, err);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -268,14 +268,12 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd
 | 
			
		|||
			encode_uint32(TYPE_DICT, &tmpdata.write[pos + 0]);
 | 
			
		||||
			encode_uint32(len, &tmpdata.write[pos + 4]);
 | 
			
		||||
 | 
			
		||||
			List<Variant> keys;
 | 
			
		||||
			d.get_key_list(&keys);
 | 
			
		||||
			List<DictKey> sortk;
 | 
			
		||||
 | 
			
		||||
			for (const Variant &key : keys) {
 | 
			
		||||
			for (const KeyValue<Variant, Variant> &kv : d) {
 | 
			
		||||
				DictKey dk;
 | 
			
		||||
				dk.hash = key.hash();
 | 
			
		||||
				dk.key = key;
 | 
			
		||||
				dk.hash = kv.key.hash();
 | 
			
		||||
				dk.key = kv.key;
 | 
			
		||||
				sortk.push_back(dk);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -322,11 +322,9 @@ void Resource::_find_sub_resources(const Variant &p_variant, HashSet<Ref<Resourc
 | 
			
		|||
		} break;
 | 
			
		||||
		case Variant::DICTIONARY: {
 | 
			
		||||
			Dictionary d = p_variant;
 | 
			
		||||
			List<Variant> keys;
 | 
			
		||||
			d.get_key_list(&keys);
 | 
			
		||||
			for (const Variant &k : keys) {
 | 
			
		||||
				_find_sub_resources(k, p_resources_found);
 | 
			
		||||
				_find_sub_resources(d[k], p_resources_found);
 | 
			
		||||
			for (const KeyValue<Variant, Variant> &kv : d) {
 | 
			
		||||
				_find_sub_resources(kv.key, p_resources_found);
 | 
			
		||||
				_find_sub_resources(kv.value, p_resources_found);
 | 
			
		||||
			}
 | 
			
		||||
		} break;
 | 
			
		||||
		case Variant::OBJECT: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1876,12 +1876,9 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
 | 
			
		|||
			Dictionary d = p_property;
 | 
			
		||||
			f->store_32(uint32_t(d.size()));
 | 
			
		||||
 | 
			
		||||
			List<Variant> keys;
 | 
			
		||||
			d.get_key_list(&keys);
 | 
			
		||||
 | 
			
		||||
			for (const Variant &E : keys) {
 | 
			
		||||
				write_variant(f, E, resource_map, external_resources, string_map);
 | 
			
		||||
				write_variant(f, d[E], resource_map, external_resources, string_map);
 | 
			
		||||
			for (const KeyValue<Variant, Variant> &kv : d) {
 | 
			
		||||
				write_variant(f, kv.key, resource_map, external_resources, string_map);
 | 
			
		||||
				write_variant(f, kv.value, resource_map, external_resources, string_map);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		} break;
 | 
			
		||||
| 
						 | 
				
			
			@ -2086,12 +2083,9 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant
 | 
			
		|||
			Dictionary d = p_variant;
 | 
			
		||||
			_find_resources(d.get_typed_key_script());
 | 
			
		||||
			_find_resources(d.get_typed_value_script());
 | 
			
		||||
			List<Variant> keys;
 | 
			
		||||
			d.get_key_list(&keys);
 | 
			
		||||
			for (const Variant &E : keys) {
 | 
			
		||||
				_find_resources(E);
 | 
			
		||||
				Variant v = d[E];
 | 
			
		||||
				_find_resources(v);
 | 
			
		||||
			for (const KeyValue<Variant, Variant> &kv : d) {
 | 
			
		||||
				_find_resources(kv.key);
 | 
			
		||||
				_find_resources(kv.value);
 | 
			
		||||
			}
 | 
			
		||||
		} break;
 | 
			
		||||
		case Variant::NODE_PATH: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1339,10 +1339,8 @@ void ResourceLoader::load_translation_remaps() {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	Dictionary remaps = GLOBAL_GET("internationalization/locale/translation_remaps");
 | 
			
		||||
	List<Variant> keys;
 | 
			
		||||
	remaps.get_key_list(&keys);
 | 
			
		||||
	for (const Variant &E : keys) {
 | 
			
		||||
		Array langs = remaps[E];
 | 
			
		||||
	for (const KeyValue<Variant, Variant> &kv : remaps) {
 | 
			
		||||
		Array langs = kv.value;
 | 
			
		||||
		Vector<String> lang_remaps;
 | 
			
		||||
		lang_remaps.resize(langs.size());
 | 
			
		||||
		String *lang_remaps_ptrw = lang_remaps.ptrw();
 | 
			
		||||
| 
						 | 
				
			
			@ -1350,7 +1348,7 @@ void ResourceLoader::load_translation_remaps() {
 | 
			
		|||
			*lang_remaps_ptrw++ = lang;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		translation_remaps[String(E)] = lang_remaps;
 | 
			
		||||
		translation_remaps[String(kv.key)] = lang_remaps;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1640,12 +1640,10 @@ void Object::_clear_internal_resource_paths(const Variant &p_var) {
 | 
			
		|||
		} break;
 | 
			
		||||
		case Variant::DICTIONARY: {
 | 
			
		||||
			Dictionary d = p_var;
 | 
			
		||||
			List<Variant> keys;
 | 
			
		||||
			d.get_key_list(&keys);
 | 
			
		||||
 | 
			
		||||
			for (const Variant &E : keys) {
 | 
			
		||||
				_clear_internal_resource_paths(E);
 | 
			
		||||
				_clear_internal_resource_paths(d[E]);
 | 
			
		||||
			for (const KeyValue<Variant, Variant> &kv : d) {
 | 
			
		||||
				_clear_internal_resource_paths(kv.key);
 | 
			
		||||
				_clear_internal_resource_paths(kv.value);
 | 
			
		||||
			}
 | 
			
		||||
		} break;
 | 
			
		||||
		default: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -192,10 +192,8 @@ public:
 | 
			
		|||
	virtual void get_constants(HashMap<StringName, Variant> *p_constants) override {
 | 
			
		||||
		Dictionary constants;
 | 
			
		||||
		GDVIRTUAL_CALL(_get_constants, constants);
 | 
			
		||||
		List<Variant> keys;
 | 
			
		||||
		constants.get_key_list(&keys);
 | 
			
		||||
		for (const Variant &K : keys) {
 | 
			
		||||
			p_constants->insert(K, constants[K]);
 | 
			
		||||
		for (const KeyValue<Variant, Variant> &kv : constants) {
 | 
			
		||||
			p_constants->insert(kv.key, kv.value);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	GDVIRTUAL0RC_REQUIRED(TypedArray<StringName>, _get_members)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,10 +67,8 @@ Vector<String> Translation::get_translated_message_list() const {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void Translation::_set_messages(const Dictionary &p_messages) {
 | 
			
		||||
	List<Variant> keys;
 | 
			
		||||
	p_messages.get_key_list(&keys);
 | 
			
		||||
	for (const Variant &E : keys) {
 | 
			
		||||
		translation_map[E] = p_messages[E];
 | 
			
		||||
	for (const KeyValue<Variant, Variant> &kv : p_messages) {
 | 
			
		||||
		translation_map[kv.key] = kv.value;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -86,20 +86,16 @@ Dictionary TranslationPO::_get_messages() const {
 | 
			
		|||
void TranslationPO::_set_messages(const Dictionary &p_messages) {
 | 
			
		||||
	// Construct translation_map from a Dictionary.
 | 
			
		||||
 | 
			
		||||
	List<Variant> context_l;
 | 
			
		||||
	p_messages.get_key_list(&context_l);
 | 
			
		||||
	for (const Variant &ctx : context_l) {
 | 
			
		||||
		const Dictionary &id_str_map = p_messages[ctx];
 | 
			
		||||
	for (const KeyValue<Variant, Variant> &kv : p_messages) {
 | 
			
		||||
		const Dictionary &id_str_map = kv.value;
 | 
			
		||||
 | 
			
		||||
		HashMap<StringName, Vector<StringName>> temp_map;
 | 
			
		||||
		List<Variant> id_l;
 | 
			
		||||
		id_str_map.get_key_list(&id_l);
 | 
			
		||||
		for (List<Variant>::Element *E2 = id_l.front(); E2; E2 = E2->next()) {
 | 
			
		||||
			StringName id = E2->get();
 | 
			
		||||
			temp_map[id] = id_str_map[id];
 | 
			
		||||
		for (const KeyValue<Variant, Variant> &kv_id : id_str_map) {
 | 
			
		||||
			StringName id = kv_id.key;
 | 
			
		||||
			temp_map[id] = kv_id.value;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		translation_map[ctx] = temp_map;
 | 
			
		||||
		translation_map[kv.key] = temp_map;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4024,11 +4024,9 @@ String String::format(const Variant &values, const String &placeholder) const {
 | 
			
		|||
		}
 | 
			
		||||
	} else if (values.get_type() == Variant::DICTIONARY) {
 | 
			
		||||
		Dictionary d = values;
 | 
			
		||||
		List<Variant> keys;
 | 
			
		||||
		d.get_key_list(&keys);
 | 
			
		||||
 | 
			
		||||
		for (const Variant &key : keys) {
 | 
			
		||||
			new_string = new_string.replace(placeholder.replace("_", key), d[key]);
 | 
			
		||||
		for (const KeyValue<Variant, Variant> &kv : d) {
 | 
			
		||||
			new_string = new_string.replace(placeholder.replace("_", kv.key), kv.value);
 | 
			
		||||
		}
 | 
			
		||||
	} else if (values.get_type() == Variant::OBJECT) {
 | 
			
		||||
		Object *obj = values.get_validated_object();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,6 +49,14 @@ struct DictionaryPrivate {
 | 
			
		|||
	Variant *typed_fallback = nullptr; // Allows a typed dictionary to return dummy values when attempting an invalid access.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Dictionary::ConstIterator Dictionary::begin() const {
 | 
			
		||||
	return _p->variant_map.begin();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Dictionary::ConstIterator Dictionary::end() const {
 | 
			
		||||
	return _p->variant_map.end();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Dictionary::get_key_list(List<Variant> *p_keys) const {
 | 
			
		||||
	if (_p->variant_map.is_empty()) {
 | 
			
		||||
		return;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,6 +31,7 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "core/string/ustring.h"
 | 
			
		||||
#include "core/templates/hash_map.h"
 | 
			
		||||
#include "core/templates/list.h"
 | 
			
		||||
#include "core/templates/pair.h"
 | 
			
		||||
#include "core/variant/array.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -39,6 +40,8 @@ class Variant;
 | 
			
		|||
 | 
			
		||||
struct ContainerType;
 | 
			
		||||
struct DictionaryPrivate;
 | 
			
		||||
struct StringLikeVariantComparator;
 | 
			
		||||
struct VariantHasher;
 | 
			
		||||
 | 
			
		||||
class Dictionary {
 | 
			
		||||
	mutable DictionaryPrivate *_p;
 | 
			
		||||
| 
						 | 
				
			
			@ -47,6 +50,11 @@ class Dictionary {
 | 
			
		|||
	void _unref() const;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	using ConstIterator = HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::ConstIterator;
 | 
			
		||||
 | 
			
		||||
	ConstIterator begin() const;
 | 
			
		||||
	ConstIterator end() const;
 | 
			
		||||
 | 
			
		||||
	void get_key_list(List<Variant> *p_keys) const;
 | 
			
		||||
	Variant get_key_at_index(int p_index) const;
 | 
			
		||||
	Variant get_value_at_index(int p_index) const;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1654,15 +1654,13 @@ String Variant::stringify(int recursion_count) const {
 | 
			
		|||
			// Add leading and trailing space to Dictionary printing. This distinguishes it
 | 
			
		||||
			// from array printing on fonts that have similar-looking {} and [] characters.
 | 
			
		||||
			String str("{ ");
 | 
			
		||||
			List<Variant> keys;
 | 
			
		||||
			d.get_key_list(&keys);
 | 
			
		||||
 | 
			
		||||
			Vector<_VariantStrPair> pairs;
 | 
			
		||||
 | 
			
		||||
			for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
 | 
			
		||||
			for (const KeyValue<Variant, Variant> &kv : d) {
 | 
			
		||||
				_VariantStrPair sp;
 | 
			
		||||
				sp.key = stringify_variant_clean(E->get(), recursion_count);
 | 
			
		||||
				sp.value = stringify_variant_clean(d[E->get()], recursion_count);
 | 
			
		||||
				sp.key = stringify_variant_clean(kv.key, recursion_count);
 | 
			
		||||
				sp.value = stringify_variant_clean(kv.value, recursion_count);
 | 
			
		||||
 | 
			
		||||
				pairs.push_back(sp);
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1286,11 +1286,9 @@ Variant Variant::get(const Variant &p_index, bool *r_valid, VariantGetError *err
 | 
			
		|||
void Variant::get_property_list(List<PropertyInfo> *p_list) const {
 | 
			
		||||
	if (type == DICTIONARY) {
 | 
			
		||||
		const Dictionary *dic = reinterpret_cast<const Dictionary *>(_data._mem);
 | 
			
		||||
		List<Variant> keys;
 | 
			
		||||
		dic->get_key_list(&keys);
 | 
			
		||||
		for (const Variant &E : keys) {
 | 
			
		||||
			if (E.is_string()) {
 | 
			
		||||
				p_list->push_back(PropertyInfo(dic->get_valid(E).get_type(), E));
 | 
			
		||||
		for (const KeyValue<Variant, Variant> &kv : *dic) {
 | 
			
		||||
			if (kv.key.is_string()) {
 | 
			
		||||
				p_list->push_back(PropertyInfo(dic->get_valid(kv.key).get_type(), kv.key));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else if (type == OBJECT) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -297,11 +297,9 @@ Error EditorBuildProfile::load_from_file(const String &p_path) {
 | 
			
		|||
 | 
			
		||||
	if (data.has("disabled_build_options")) {
 | 
			
		||||
		Dictionary disabled_build_options_arr = data["disabled_build_options"];
 | 
			
		||||
		List<Variant> keys;
 | 
			
		||||
		disabled_build_options_arr.get_key_list(&keys);
 | 
			
		||||
 | 
			
		||||
		for (const Variant &K : keys) {
 | 
			
		||||
			String key = K;
 | 
			
		||||
		for (const KeyValue<Variant, Variant> &kv : disabled_build_options_arr) {
 | 
			
		||||
			String key = kv.key;
 | 
			
		||||
 | 
			
		||||
			for (int i = 0; i < BUILD_OPTION_MAX; i++) {
 | 
			
		||||
				String f = build_option_identifiers[i];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -336,12 +336,8 @@ void EditorData::set_editor_plugin_states(const Dictionary &p_states) {
 | 
			
		|||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	List<Variant> keys;
 | 
			
		||||
	p_states.get_key_list(&keys);
 | 
			
		||||
 | 
			
		||||
	List<Variant>::Element *E = keys.front();
 | 
			
		||||
	for (; E; E = E->next()) {
 | 
			
		||||
		String name = E->get();
 | 
			
		||||
	for (const KeyValue<Variant, Variant> &kv : p_states) {
 | 
			
		||||
		String name = kv.key;
 | 
			
		||||
		int idx = -1;
 | 
			
		||||
		for (int i = 0; i < editor_plugins.size(); i++) {
 | 
			
		||||
			if (editor_plugins[i]->get_plugin_name() == name) {
 | 
			
		||||
| 
						 | 
				
			
			@ -353,7 +349,7 @@ void EditorData::set_editor_plugin_states(const Dictionary &p_states) {
 | 
			
		|||
		if (idx == -1) {
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		editor_plugins[idx]->set_state(p_states[name]);
 | 
			
		||||
		editor_plugins[idx]->set_state(kv.value);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1071,12 +1067,10 @@ void EditorData::script_class_load_icon_paths() {
 | 
			
		|||
#ifndef DISABLE_DEPRECATED
 | 
			
		||||
	if (ProjectSettings::get_singleton()->has_setting("_global_script_class_icons")) {
 | 
			
		||||
		Dictionary d = GLOBAL_GET("_global_script_class_icons");
 | 
			
		||||
		List<Variant> keys;
 | 
			
		||||
		d.get_key_list(&keys);
 | 
			
		||||
 | 
			
		||||
		for (const Variant &E : keys) {
 | 
			
		||||
			String name = E.operator String();
 | 
			
		||||
			_script_class_icon_paths[name] = d[name];
 | 
			
		||||
		for (const KeyValue<Variant, Variant> &kv : d) {
 | 
			
		||||
			String name = kv.key.operator String();
 | 
			
		||||
			_script_class_icon_paths[name] = kv.value;
 | 
			
		||||
 | 
			
		||||
			String path = ScriptServer::get_global_class_path(name);
 | 
			
		||||
			script_class_set_name(path, name);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2824,11 +2824,9 @@ Error EditorFileSystem::_reimport_file(const String &p_file, const HashMap<Strin
 | 
			
		|||
	if (load_default && ProjectSettings::get_singleton()->has_setting("importer_defaults/" + importer->get_importer_name())) {
 | 
			
		||||
		//use defaults if exist
 | 
			
		||||
		Dictionary d = GLOBAL_GET("importer_defaults/" + importer->get_importer_name());
 | 
			
		||||
		List<Variant> v;
 | 
			
		||||
		d.get_key_list(&v);
 | 
			
		||||
 | 
			
		||||
		for (const Variant &E : v) {
 | 
			
		||||
			params[E] = d[E];
 | 
			
		||||
		for (const KeyValue<Variant, Variant> &kv : d) {
 | 
			
		||||
			params[kv.key] = kv.value;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1593,10 +1593,8 @@ void EditorNode::_save_editor_states(const String &p_file, int p_idx) {
 | 
			
		|||
		md = editor_data.get_scene_editor_states(p_idx);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	List<Variant> keys;
 | 
			
		||||
	md.get_key_list(&keys);
 | 
			
		||||
	for (const Variant &E : keys) {
 | 
			
		||||
		cf->set_value("editor_states", E, md[E]);
 | 
			
		||||
	for (const KeyValue<Variant, Variant> &kv : md) {
 | 
			
		||||
		cf->set_value("editor_states", kv.key, kv.value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Save the currently selected nodes.
 | 
			
		||||
| 
						 | 
				
			
			@ -1670,11 +1668,8 @@ bool EditorNode::_find_and_save_edited_subresources(Object *obj, HashMap<Ref<Res
 | 
			
		|||
			} break;
 | 
			
		||||
			case Variant::DICTIONARY: {
 | 
			
		||||
				Dictionary d = obj->get(E.name);
 | 
			
		||||
				List<Variant> keys;
 | 
			
		||||
				d.get_key_list(&keys);
 | 
			
		||||
				for (const Variant &F : keys) {
 | 
			
		||||
					Variant v = d[F];
 | 
			
		||||
					Ref<Resource> res = v;
 | 
			
		||||
				for (const KeyValue<Variant, Variant> &kv : d) {
 | 
			
		||||
					Ref<Resource> res = kv.value;
 | 
			
		||||
					if (_find_and_save_resource(res, processed, flags)) {
 | 
			
		||||
						ret_changed = true;
 | 
			
		||||
					}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3036,15 +3036,14 @@ static bool _find_recursive_resources(const Variant &v, HashSet<Resource *> &res
 | 
			
		|||
		} break;
 | 
			
		||||
		case Variant::DICTIONARY: {
 | 
			
		||||
			Dictionary d = v;
 | 
			
		||||
			List<Variant> keys;
 | 
			
		||||
			d.get_key_list(&keys);
 | 
			
		||||
			for (const Variant &k : keys) {
 | 
			
		||||
			for (const KeyValue<Variant, Variant> &kv : d) {
 | 
			
		||||
				const Variant &k = kv.key;
 | 
			
		||||
				const Variant &v2 = kv.value;
 | 
			
		||||
				if (k.get_type() == Variant::ARRAY || k.get_type() == Variant::DICTIONARY || k.get_type() == Variant::OBJECT) {
 | 
			
		||||
					if (_find_recursive_resources(k, resources_found)) {
 | 
			
		||||
						return true;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				Variant v2 = d[k];
 | 
			
		||||
				if (v2.get_type() == Variant::ARRAY || v2.get_type() == Variant::DICTIONARY || v2.get_type() == Variant::OBJECT) {
 | 
			
		||||
					if (_find_recursive_resources(v2, resources_found)) {
 | 
			
		||||
						return true;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -205,10 +205,8 @@ bool EditorImportPlugin::can_import_threaded() const {
 | 
			
		|||
 | 
			
		||||
Error EditorImportPlugin::_append_import_external_resource(const String &p_file, const Dictionary &p_custom_options, const String &p_custom_importer, Variant p_generator_parameters) {
 | 
			
		||||
	HashMap<StringName, Variant> options;
 | 
			
		||||
	List<Variant> keys;
 | 
			
		||||
	p_custom_options.get_key_list(&keys);
 | 
			
		||||
	for (const Variant &K : keys) {
 | 
			
		||||
		options.insert(K, p_custom_options[K]);
 | 
			
		||||
	for (const KeyValue<Variant, Variant> &kv : p_custom_options) {
 | 
			
		||||
		options.insert(kv.key, kv.value);
 | 
			
		||||
	}
 | 
			
		||||
	return append_import_external_resource(p_file, options, p_custom_importer, p_generator_parameters);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -297,13 +297,11 @@ void ImportDock::set_edit_multiple_paths(const Vector<String> &p_paths) {
 | 
			
		|||
		if (value_frequency.has(E.option.name)) {
 | 
			
		||||
			Dictionary d = value_frequency[E.option.name];
 | 
			
		||||
			int freq = 0;
 | 
			
		||||
			List<Variant> v;
 | 
			
		||||
			d.get_key_list(&v);
 | 
			
		||||
			Variant value;
 | 
			
		||||
			for (const Variant &F : v) {
 | 
			
		||||
				int f = d[F];
 | 
			
		||||
			for (const KeyValue<Variant, Variant> &kv : d) {
 | 
			
		||||
				int f = kv.value;
 | 
			
		||||
				if (f > freq) {
 | 
			
		||||
					value = F;
 | 
			
		||||
					value = kv.key;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -456,16 +454,14 @@ void ImportDock::_preset_selected(int p_idx) {
 | 
			
		|||
			ERR_FAIL_COND(!ProjectSettings::get_singleton()->has_setting(setting_name));
 | 
			
		||||
 | 
			
		||||
			Dictionary import_settings = GLOBAL_GET(setting_name);
 | 
			
		||||
			List<Variant> keys;
 | 
			
		||||
			import_settings.get_key_list(&keys);
 | 
			
		||||
 | 
			
		||||
			if (params->checking) {
 | 
			
		||||
				params->checked.clear();
 | 
			
		||||
			}
 | 
			
		||||
			for (const Variant &E : keys) {
 | 
			
		||||
				params->values[E] = import_settings[E];
 | 
			
		||||
			for (const KeyValue<Variant, Variant> &kv : import_settings) {
 | 
			
		||||
				params->values[kv.key] = kv.value;
 | 
			
		||||
				if (params->checking) {
 | 
			
		||||
					params->checked.insert(E);
 | 
			
		||||
					params->checked.insert(kv.key);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			params->update();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -539,11 +539,9 @@ void LocalizationEditor::update_translations() {
 | 
			
		|||
 | 
			
		||||
	if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/translation_remaps")) {
 | 
			
		||||
		Dictionary remaps = GLOBAL_GET("internationalization/locale/translation_remaps");
 | 
			
		||||
		List<Variant> rk;
 | 
			
		||||
		remaps.get_key_list(&rk);
 | 
			
		||||
		Vector<String> keys;
 | 
			
		||||
		for (const Variant &E : rk) {
 | 
			
		||||
			keys.push_back(E);
 | 
			
		||||
		for (const KeyValue<Variant, Variant> &kv : remaps) {
 | 
			
		||||
			keys.push_back(kv.key);
 | 
			
		||||
		}
 | 
			
		||||
		keys.sort();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6619,17 +6619,15 @@ void Node3DEditor::set_state(const Dictionary &p_state) {
 | 
			
		|||
 | 
			
		||||
	if (d.has("gizmos_status")) {
 | 
			
		||||
		Dictionary gizmos_status = d["gizmos_status"];
 | 
			
		||||
		List<Variant> keys;
 | 
			
		||||
		gizmos_status.get_key_list(&keys);
 | 
			
		||||
 | 
			
		||||
		for (int j = 0; j < gizmo_plugins_by_name.size(); ++j) {
 | 
			
		||||
			if (!gizmo_plugins_by_name[j]->can_be_hidden()) {
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			int state = EditorNode3DGizmoPlugin::VISIBLE;
 | 
			
		||||
			for (const Variant &key : keys) {
 | 
			
		||||
				if (gizmo_plugins_by_name.write[j]->get_gizmo_name() == String(key)) {
 | 
			
		||||
					state = gizmos_status[key];
 | 
			
		||||
			for (const KeyValue<Variant, Variant> &kv : gizmos_status) {
 | 
			
		||||
				if (gizmo_plugins_by_name.write[j]->get_gizmo_name() == String(kv.key)) {
 | 
			
		||||
					state = kv.value;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -173,11 +173,9 @@ int AudioStreamInteractive::get_clip_auto_advance_next_clip(int p_clip) const {
 | 
			
		|||
// TRANSITIONS
 | 
			
		||||
 | 
			
		||||
void AudioStreamInteractive::_set_transitions(const Dictionary &p_transitions) {
 | 
			
		||||
	List<Variant> keys;
 | 
			
		||||
	p_transitions.get_key_list(&keys);
 | 
			
		||||
	for (const Variant &K : keys) {
 | 
			
		||||
		Vector2i k = K;
 | 
			
		||||
		Dictionary data = p_transitions[K];
 | 
			
		||||
	for (const KeyValue<Variant, Variant> &kv : p_transitions) {
 | 
			
		||||
		Vector2i k = kv.key;
 | 
			
		||||
		Dictionary data = kv.value;
 | 
			
		||||
		ERR_CONTINUE(!data.has("from_time"));
 | 
			
		||||
		ERR_CONTINUE(!data.has("to_time"));
 | 
			
		||||
		ERR_CONTINUE(!data.has("fade_mode"));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -77,11 +77,9 @@ bool AnimationMixer::_set(const StringName &p_name, const Variant &p_value) {
 | 
			
		|||
		while (animation_libraries.size()) {
 | 
			
		||||
			remove_animation_library(animation_libraries[0].name);
 | 
			
		||||
		}
 | 
			
		||||
		List<Variant> keys;
 | 
			
		||||
		d.get_key_list(&keys);
 | 
			
		||||
		for (const Variant &K : keys) {
 | 
			
		||||
			Ref<AnimationLibrary> lib = d[K];
 | 
			
		||||
			add_animation_library(K, lib);
 | 
			
		||||
		for (const KeyValue<Variant, Variant> &kv : d) {
 | 
			
		||||
			Ref<AnimationLibrary> lib = kv.value;
 | 
			
		||||
			add_animation_library(kv.key, lib);
 | 
			
		||||
		}
 | 
			
		||||
		emit_signal(SNAME("animation_libraries_updated"));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -121,12 +121,10 @@ AnimationNode::NodeTimeInfo AnimationNode::get_node_time_info() const {
 | 
			
		|||
void AnimationNode::get_child_nodes(List<ChildNode> *r_child_nodes) {
 | 
			
		||||
	Dictionary cn;
 | 
			
		||||
	if (GDVIRTUAL_CALL(_get_child_nodes, cn)) {
 | 
			
		||||
		List<Variant> keys;
 | 
			
		||||
		cn.get_key_list(&keys);
 | 
			
		||||
		for (const Variant &E : keys) {
 | 
			
		||||
		for (const KeyValue<Variant, Variant> &kv : cn) {
 | 
			
		||||
			ChildNode child;
 | 
			
		||||
			child.name = E;
 | 
			
		||||
			child.node = cn[E];
 | 
			
		||||
			child.name = kv.key;
 | 
			
		||||
			child.node = kv.value;
 | 
			
		||||
			r_child_nodes->push_back(child);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -91,13 +91,11 @@ void ImporterMesh::add_surface(Mesh::PrimitiveType p_primitive, const Array &p_a
 | 
			
		|||
		s.blend_shape_data.push_back(bs);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	List<Variant> lods;
 | 
			
		||||
	p_lods.get_key_list(&lods);
 | 
			
		||||
	for (const Variant &E : lods) {
 | 
			
		||||
		ERR_CONTINUE(!E.is_num());
 | 
			
		||||
	for (const KeyValue<Variant, Variant> &kv : p_lods) {
 | 
			
		||||
		ERR_CONTINUE(!kv.key.is_num());
 | 
			
		||||
		Surface::LOD lod;
 | 
			
		||||
		lod.distance = E;
 | 
			
		||||
		lod.indices = p_lods[E];
 | 
			
		||||
		lod.distance = kv.key;
 | 
			
		||||
		lod.indices = kv.value;
 | 
			
		||||
		ERR_CONTINUE(lod.indices.is_empty());
 | 
			
		||||
		s.lods.push_back(lod);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -134,10 +134,8 @@ void AnimationLibrary::_set_data(const Dictionary &p_data) {
 | 
			
		|||
		K.value->disconnect_changed(callable_mp(this, &AnimationLibrary::_animation_changed));
 | 
			
		||||
	}
 | 
			
		||||
	animations.clear();
 | 
			
		||||
	List<Variant> keys;
 | 
			
		||||
	p_data.get_key_list(&keys);
 | 
			
		||||
	for (const Variant &K : keys) {
 | 
			
		||||
		add_animation(K, p_data[K]);
 | 
			
		||||
	for (const KeyValue<Variant, Variant> &kv : p_data) {
 | 
			
		||||
		add_animation(kv.key, kv.value);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1674,14 +1674,11 @@ void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant,
 | 
			
		|||
			Dictionary d = p_variant;
 | 
			
		||||
			_find_resources(d.get_typed_key_script());
 | 
			
		||||
			_find_resources(d.get_typed_value_script());
 | 
			
		||||
			List<Variant> keys;
 | 
			
		||||
			d.get_key_list(&keys);
 | 
			
		||||
			for (const Variant &E : keys) {
 | 
			
		||||
			for (const KeyValue<Variant, Variant> &kv : d) {
 | 
			
		||||
				// Of course keys should also be cached, after all we can't prevent users from using resources as keys, right?
 | 
			
		||||
				// See also ResourceFormatSaverBinaryInstance::_find_resources (when p_variant is of type Variant::DICTIONARY)
 | 
			
		||||
				_find_resources(E);
 | 
			
		||||
				Variant v = d[E];
 | 
			
		||||
				_find_resources(v);
 | 
			
		||||
				_find_resources(kv.key);
 | 
			
		||||
				_find_resources(kv.value);
 | 
			
		||||
			}
 | 
			
		||||
		} break;
 | 
			
		||||
		case Variant::PACKED_BYTE_ARRAY: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -537,16 +537,13 @@ bool CodeHighlighter::has_color_region(const String &p_start_key) const {
 | 
			
		|||
void CodeHighlighter::set_color_regions(const Dictionary &p_color_regions) {
 | 
			
		||||
	color_regions.clear();
 | 
			
		||||
 | 
			
		||||
	List<Variant> keys;
 | 
			
		||||
	p_color_regions.get_key_list(&keys);
 | 
			
		||||
 | 
			
		||||
	for (const Variant &E : keys) {
 | 
			
		||||
		String key = E;
 | 
			
		||||
	for (const KeyValue<Variant, Variant> &kv : p_color_regions) {
 | 
			
		||||
		String key = kv.key;
 | 
			
		||||
 | 
			
		||||
		String start_key = key.get_slicec(' ', 0);
 | 
			
		||||
		String end_key = key.get_slice_count(" ") > 1 ? key.get_slicec(' ', 1) : String();
 | 
			
		||||
 | 
			
		||||
		add_color_region(start_key, end_key, p_color_regions[key], end_key.is_empty());
 | 
			
		||||
		add_color_region(start_key, end_key, kv.value, end_key.is_empty());
 | 
			
		||||
	}
 | 
			
		||||
	clear_highlighting_cache();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -425,11 +425,9 @@ protected:
 | 
			
		|||
	}
 | 
			
		||||
	void _set_versions(const Dictionary &p_versions) {
 | 
			
		||||
		versions.clear();
 | 
			
		||||
		List<Variant> keys;
 | 
			
		||||
		p_versions.get_key_list(&keys);
 | 
			
		||||
		for (const Variant &E : keys) {
 | 
			
		||||
			StringName vname = E;
 | 
			
		||||
			Ref<RDShaderSPIRV> bc = p_versions[E];
 | 
			
		||||
		for (const KeyValue<Variant, Variant> &kv : p_versions) {
 | 
			
		||||
			StringName vname = kv.key;
 | 
			
		||||
			Ref<RDShaderSPIRV> bc = kv.value;
 | 
			
		||||
			ERR_CONTINUE(bc.is_null());
 | 
			
		||||
			versions[vname] = bc;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -593,4 +593,21 @@ TEST_CASE("[Dictionary] Typed copying") {
 | 
			
		|||
	d6.clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("[Dictionary] Iteration") {
 | 
			
		||||
	Dictionary a1 = build_dictionary(1, 2, 3, 4, 5, 6);
 | 
			
		||||
	Dictionary a2 = build_dictionary(1, 2, 3, 4, 5, 6);
 | 
			
		||||
 | 
			
		||||
	int idx = 0;
 | 
			
		||||
 | 
			
		||||
	for (const KeyValue<Variant, Variant> &kv : (const Dictionary &)a1) {
 | 
			
		||||
		CHECK_EQ(int(a2[kv.key]), int(kv.value));
 | 
			
		||||
		idx++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	CHECK_EQ(idx, a1.size());
 | 
			
		||||
 | 
			
		||||
	a1.clear();
 | 
			
		||||
	a2.clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace TestDictionary
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue