Browse Source

Merge pull request #60881 from reduz/new-hash-map

Rémi Verschelde 3 years ago
parent
commit
edda6ee9f8
95 changed files with 1345 additions and 1785 deletions
  1. 5 5
      core/config/project_settings.cpp
  2. 3 3
      core/config/project_settings.h
  3. 8 8
      core/input/input.cpp
  4. 20 20
      core/input/input_map.cpp
  5. 7 7
      core/input/input_map.h
  6. 15 12
      core/io/config_file.cpp
  7. 2 2
      core/io/config_file.h
  8. 2 2
      core/io/missing_resource.cpp
  9. 1 1
      core/io/missing_resource.h
  10. 6 11
      core/io/resource.cpp
  11. 11 11
      core/io/resource_uid.cpp
  12. 2 2
      core/io/resource_uid.h
  13. 42 75
      core/object/class_db.cpp
  14. 29 33
      core/object/object.cpp
  15. 2 3
      core/object/object.h
  16. 2 3
      core/object/script_language.cpp
  17. 8 0
      core/os/memory.h
  18. 13 27
      core/string/translation_po.cpp
  19. 402 373
      core/templates/hash_map.h
  20. 85 0
      core/templates/hashfuncs.h
  21. 0 301
      core/templates/ordered_hash_map.h
  22. 7 1
      core/templates/paged_allocator.h
  23. 46 39
      core/variant/dictionary.cpp
  24. 0 1
      doc/classes/DirectionalLight3D.xml
  25. 1 1
      doc/classes/Light3D.xml
  26. 1 0
      doc/classes/OmniLight3D.xml
  27. 2 3
      drivers/gles3/storage/material_storage.cpp
  28. 46 36
      editor/debugger/editor_performance_profiler.cpp
  29. 2 2
      editor/debugger/editor_performance_profiler.h
  30. 16 20
      editor/editor_command_palette.cpp
  31. 3 6
      editor/editor_data.cpp
  32. 1 1
      editor/editor_help_search.h
  33. 13 10
      editor/editor_settings.cpp
  34. 7 8
      editor/editor_settings_dialog.cpp
  35. 1 1
      editor/editor_settings_dialog.h
  36. 4 4
      editor/import/resource_importer_scene.cpp
  37. 1 1
      editor/plugins/node_3d_editor_gizmos.h
  38. 3 3
      editor/plugins/script_editor_plugin.cpp
  39. 55 55
      editor/plugins/theme_editor_plugin.cpp
  40. 1 1
      editor/plugins/theme_editor_plugin.h
  41. 4 4
      editor/pot_generator.cpp
  42. 2 2
      editor/pot_generator.h
  43. 4 4
      editor/project_settings_editor.cpp
  44. 5 5
      main/main.cpp
  45. 2 2
      main/performance.cpp
  46. 2 2
      main/performance.h
  47. 2 3
      modules/gdscript/editor/gdscript_highlighter.cpp
  48. 3 5
      modules/gdscript/gdscript_analyzer.cpp
  49. 2 4
      modules/gdscript/gdscript_byte_codegen.cpp
  50. 1 1
      modules/gdscript/gdscript_compiler.cpp
  51. 12 16
      modules/gdscript/gdscript_editor.cpp
  52. 11 15
      modules/gdscript/gdscript_parser.cpp
  53. 1 1
      modules/gdscript/gdscript_parser.h
  54. 12 20
      modules/gdscript/language_server/gdscript_extend_parser.cpp
  55. 18 14
      modules/gdscript/language_server/gdscript_language_protocol.cpp
  56. 5 13
      modules/gdscript/language_server/gdscript_text_document.cpp
  57. 6 12
      modules/gdscript/language_server/gdscript_workspace.cpp
  58. 5 5
      modules/gdscript/tests/gdscript_test_runner.cpp
  59. 14 27
      modules/mono/class_db_api_json.cpp
  60. 4 4
      modules/mono/csharp_script.cpp
  61. 1 1
      modules/mono/csharp_script.h
  62. 20 22
      modules/mono/editor/bindings_generator.cpp
  63. 1 1
      modules/mono/editor/bindings_generator.h
  64. 3 3
      modules/mono/editor/code_completion.cpp
  65. 10 15
      modules/mono/mono_gd/gd_mono.cpp
  66. 8 11
      modules/mono/mono_gd/gd_mono_class.cpp
  67. 7 10
      modules/raycast/raycast_occlusion_cull.cpp
  68. 4 6
      modules/text_server_adv/text_server_adv.cpp
  69. 4 6
      modules/text_server_fb/text_server_fb.cpp
  70. 5 7
      modules/visual_script/editor/visual_script_editor.cpp
  71. 66 93
      modules/visual_script/visual_script.cpp
  72. 10 15
      platform/iphone/export/export_plugin.cpp
  73. 14 20
      scene/animation/animation_tree.cpp
  74. 3 1
      scene/gui/code_edit.cpp
  75. 11 11
      scene/gui/graph_edit.cpp
  76. 2 2
      scene/main/missing_node.cpp
  77. 1 1
      scene/main/missing_node.h
  78. 5 7
      scene/main/scene_tree.cpp
  79. 9 11
      scene/main/shader_globals_override.cpp
  80. 3 3
      scene/multiplayer/multiplayer_spawner.cpp
  81. 2 4
      scene/multiplayer/scene_cache_interface.cpp
  82. 2 3
      scene/multiplayer/scene_replication_interface.cpp
  83. 8 12
      scene/multiplayer/scene_replication_state.cpp
  84. 2 2
      scene/multiplayer/scene_replication_state.h
  85. 4 4
      scene/resources/packed_scene.cpp
  86. 1 1
      scene/resources/surface_tool.cpp
  87. 88 194
      scene/resources/theme.cpp
  88. 2 3
      servers/rendering/renderer_rd/storage_rd/material_storage.cpp
  89. 7 8
      servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
  90. 3 3
      servers/rendering/rendering_server_default.cpp
  91. 2 2
      servers/rendering/rendering_server_default.h
  92. 1 1
      servers/rendering/shader_types.h
  93. 13 16
      tests/core/object/test_class_db.h
  94. 32 34
      tests/core/templates/test_hash_map.h
  95. 1 1
      tests/test_main.cpp

+ 5 - 5
core/config/project_settings.cpp

@@ -1091,7 +1091,7 @@ bool ProjectSettings::has_custom_feature(const String &p_feature) const {
 	return custom_features.has(p_feature);
 	return custom_features.has(p_feature);
 }
 }
 
 
-OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> ProjectSettings::get_autoload_list() const {
+const HashMap<StringName, ProjectSettings::AutoloadInfo> &ProjectSettings::get_autoload_list() const {
 	return autoloads;
 	return autoloads;
 }
 }
 
 
@@ -1135,13 +1135,13 @@ void ProjectSettings::_bind_methods() {
 
 
 void ProjectSettings::_add_builtin_input_map() {
 void ProjectSettings::_add_builtin_input_map() {
 	if (InputMap::get_singleton()) {
 	if (InputMap::get_singleton()) {
-		OrderedHashMap<String, List<Ref<InputEvent>>> builtins = InputMap::get_singleton()->get_builtins();
+		HashMap<String, List<Ref<InputEvent>>> builtins = InputMap::get_singleton()->get_builtins();
 
 
-		for (OrderedHashMap<String, List<Ref<InputEvent>>>::Element E = builtins.front(); E; E = E.next()) {
+		for (KeyValue<String, List<Ref<InputEvent>>> &E : builtins) {
 			Array events;
 			Array events;
 
 
 			// Convert list of input events into array
 			// Convert list of input events into array
-			for (List<Ref<InputEvent>>::Element *I = E.get().front(); I; I = I->next()) {
+			for (List<Ref<InputEvent>>::Element *I = E.value.front(); I; I = I->next()) {
 				events.push_back(I->get());
 				events.push_back(I->get());
 			}
 			}
 
 
@@ -1149,7 +1149,7 @@ void ProjectSettings::_add_builtin_input_map() {
 			action["deadzone"] = Variant(0.5f);
 			action["deadzone"] = Variant(0.5f);
 			action["events"] = events;
 			action["events"] = events;
 
 
-			String action_name = "input/" + E.key();
+			String action_name = "input/" + E.key;
 			GLOBAL_DEF(action_name, action);
 			GLOBAL_DEF(action_name, action);
 			input_presets.push_back(action_name);
 			input_presets.push_back(action_name);
 		}
 		}

+ 3 - 3
core/config/project_settings.h

@@ -33,7 +33,7 @@
 
 
 #include "core/object/class_db.h"
 #include "core/object/class_db.h"
 #include "core/os/thread_safe.h"
 #include "core/os/thread_safe.h"
-#include "core/templates/ordered_hash_map.h"
+#include "core/templates/hash_map.h"
 #include "core/templates/set.h"
 #include "core/templates/set.h"
 
 
 class ProjectSettings : public Object {
 class ProjectSettings : public Object {
@@ -94,7 +94,7 @@ protected:
 	Set<String> custom_features;
 	Set<String> custom_features;
 	Map<StringName, StringName> feature_overrides;
 	Map<StringName, StringName> feature_overrides;
 
 
-	OrderedHashMap<StringName, AutoloadInfo> autoloads;
+	HashMap<StringName, AutoloadInfo> autoloads;
 
 
 	String project_data_dir_name;
 	String project_data_dir_name;
 
 
@@ -181,7 +181,7 @@ public:
 
 
 	bool has_custom_feature(const String &p_feature) const;
 	bool has_custom_feature(const String &p_feature) const;
 
 
-	OrderedHashMap<StringName, AutoloadInfo> get_autoload_list() const;
+	const HashMap<StringName, AutoloadInfo> &get_autoload_list() const;
 	void add_autoload(const AutoloadInfo &p_autoload);
 	void add_autoload(const AutoloadInfo &p_autoload);
 	void remove_autoload(const StringName &p_autoload);
 	void remove_autoload(const StringName &p_autoload);
 	bool has_autoload(const StringName &p_autoload) const;
 	bool has_autoload(const StringName &p_autoload) const;

+ 8 - 8
core/input/input.cpp

@@ -636,21 +636,21 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
 		}
 		}
 	}
 	}
 
 
-	for (OrderedHashMap<StringName, InputMap::Action>::ConstElement E = InputMap::get_singleton()->get_action_map().front(); E; E = E.next()) {
-		if (InputMap::get_singleton()->event_is_action(p_event, E.key())) {
+	for (const KeyValue<StringName, InputMap::Action> &E : InputMap::get_singleton()->get_action_map()) {
+		if (InputMap::get_singleton()->event_is_action(p_event, E.key)) {
 			// If not echo and action pressed state has changed
 			// If not echo and action pressed state has changed
-			if (!p_event->is_echo() && is_action_pressed(E.key(), false) != p_event->is_action_pressed(E.key())) {
+			if (!p_event->is_echo() && is_action_pressed(E.key, false) != p_event->is_action_pressed(E.key)) {
 				Action action;
 				Action action;
 				action.physics_frame = Engine::get_singleton()->get_physics_frames();
 				action.physics_frame = Engine::get_singleton()->get_physics_frames();
 				action.process_frame = Engine::get_singleton()->get_process_frames();
 				action.process_frame = Engine::get_singleton()->get_process_frames();
-				action.pressed = p_event->is_action_pressed(E.key());
+				action.pressed = p_event->is_action_pressed(E.key);
 				action.strength = 0.0f;
 				action.strength = 0.0f;
 				action.raw_strength = 0.0f;
 				action.raw_strength = 0.0f;
-				action.exact = InputMap::get_singleton()->event_is_action(p_event, E.key(), true);
-				action_state[E.key()] = action;
+				action.exact = InputMap::get_singleton()->event_is_action(p_event, E.key, true);
+				action_state[E.key] = action;
 			}
 			}
-			action_state[E.key()].strength = p_event->get_action_strength(E.key());
-			action_state[E.key()].raw_strength = p_event->get_action_raw_strength(E.key());
+			action_state[E.key].strength = p_event->get_action_strength(E.key);
+			action_state[E.key].raw_strength = p_event->get_action_raw_strength(E.key);
 		}
 		}
 	}
 	}
 
 

+ 20 - 20
core/input/input_map.cpp

@@ -119,8 +119,8 @@ List<StringName> InputMap::get_actions() const {
 		return actions;
 		return actions;
 	}
 	}
 
 
-	for (OrderedHashMap<StringName, Action>::Element E = input_map.front(); E; E = E.next()) {
-		actions.push_back(E.key());
+	for (const KeyValue<StringName, Action> &E : input_map) {
+		actions.push_back(E.key);
 	}
 	}
 
 
 	return actions;
 	return actions;
@@ -203,12 +203,12 @@ Array InputMap::_action_get_events(const StringName &p_action) {
 }
 }
 
 
 const List<Ref<InputEvent>> *InputMap::action_get_events(const StringName &p_action) {
 const List<Ref<InputEvent>> *InputMap::action_get_events(const StringName &p_action) {
-	const OrderedHashMap<StringName, Action>::Element E = input_map.find(p_action);
+	HashMap<StringName, Action>::Iterator E = input_map.find(p_action);
 	if (!E) {
 	if (!E) {
 		return nullptr;
 		return nullptr;
 	}
 	}
 
 
-	return &E.get().inputs;
+	return &E->value.inputs;
 }
 }
 
 
 bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match) const {
 bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match) const {
@@ -216,7 +216,7 @@ bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName
 }
 }
 
 
 bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match, bool *r_pressed, float *r_strength, float *r_raw_strength) const {
 bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match, bool *r_pressed, float *r_strength, float *r_raw_strength) const {
-	OrderedHashMap<StringName, Action>::Element E = input_map.find(p_action);
+	HashMap<StringName, Action>::Iterator E = input_map.find(p_action);
 	ERR_FAIL_COND_V_MSG(!E, false, suggest_actions(p_action));
 	ERR_FAIL_COND_V_MSG(!E, false, suggest_actions(p_action));
 
 
 	Ref<InputEventAction> input_event_action = p_event;
 	Ref<InputEventAction> input_event_action = p_event;
@@ -235,11 +235,11 @@ bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const Str
 		return input_event_action->get_action() == p_action;
 		return input_event_action->get_action() == p_action;
 	}
 	}
 
 
-	List<Ref<InputEvent>>::Element *event = _find_event(E.get(), p_event, p_exact_match, r_pressed, r_strength, r_raw_strength);
+	List<Ref<InputEvent>>::Element *event = _find_event(E->value, p_event, p_exact_match, r_pressed, r_strength, r_raw_strength);
 	return event != nullptr;
 	return event != nullptr;
 }
 }
 
 
-const OrderedHashMap<StringName, InputMap::Action> &InputMap::get_action_map() const {
+const HashMap<StringName, InputMap::Action> &InputMap::get_action_map() const {
 	return input_map;
 	return input_map;
 }
 }
 
 
@@ -360,7 +360,7 @@ String InputMap::get_builtin_display_name(const String &p_name) const {
 	return p_name;
 	return p_name;
 }
 }
 
 
-const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
+const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
 	// Return cache if it has already been built.
 	// Return cache if it has already been built.
 	if (default_builtin_cache.size()) {
 	if (default_builtin_cache.size()) {
 		return default_builtin_cache;
 		return default_builtin_cache;
@@ -686,19 +686,19 @@ const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
 	return default_builtin_cache;
 	return default_builtin_cache;
 }
 }
 
 
-const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins_with_feature_overrides_applied() {
+const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins_with_feature_overrides_applied() {
 	if (default_builtin_with_overrides_cache.size() > 0) {
 	if (default_builtin_with_overrides_cache.size() > 0) {
 		return default_builtin_with_overrides_cache;
 		return default_builtin_with_overrides_cache;
 	}
 	}
 
 
-	OrderedHashMap<String, List<Ref<InputEvent>>> builtins = get_builtins();
+	HashMap<String, List<Ref<InputEvent>>> builtins = get_builtins();
 
 
 	// Get a list of all built in inputs which are valid overrides for the OS
 	// Get a list of all built in inputs which are valid overrides for the OS
 	// Key = builtin name (e.g. ui_accept)
 	// Key = builtin name (e.g. ui_accept)
 	// Value = override/feature names (e.g. macos, if it was defined as "ui_accept.macos" and the platform supports that feature)
 	// Value = override/feature names (e.g. macos, if it was defined as "ui_accept.macos" and the platform supports that feature)
 	Map<String, Vector<String>> builtins_with_overrides;
 	Map<String, Vector<String>> builtins_with_overrides;
-	for (OrderedHashMap<String, List<Ref<InputEvent>>>::Element E = builtins.front(); E; E = E.next()) {
-		String fullname = E.key();
+	for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtins) {
+		String fullname = E.key;
 
 
 		Vector<String> split = fullname.split(".");
 		Vector<String> split = fullname.split(".");
 		String name = split[0];
 		String name = split[0];
@@ -709,8 +709,8 @@ const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins_with
 		}
 		}
 	}
 	}
 
 
-	for (OrderedHashMap<String, List<Ref<InputEvent>>>::Element E = builtins.front(); E; E = E.next()) {
-		String fullname = E.key();
+	for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtins) {
+		String fullname = E.key;
 
 
 		Vector<String> split = fullname.split(".");
 		Vector<String> split = fullname.split(".");
 		String name = split[0];
 		String name = split[0];
@@ -726,22 +726,22 @@ const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins_with
 			continue;
 			continue;
 		}
 		}
 
 
-		default_builtin_with_overrides_cache.insert(name, E.value());
+		default_builtin_with_overrides_cache.insert(name, E.value);
 	}
 	}
 
 
 	return default_builtin_with_overrides_cache;
 	return default_builtin_with_overrides_cache;
 }
 }
 
 
 void InputMap::load_default() {
 void InputMap::load_default() {
-	OrderedHashMap<String, List<Ref<InputEvent>>> builtins = get_builtins_with_feature_overrides_applied();
+	HashMap<String, List<Ref<InputEvent>>> builtins = get_builtins_with_feature_overrides_applied();
 
 
-	for (OrderedHashMap<String, List<Ref<InputEvent>>>::Element E = builtins.front(); E; E = E.next()) {
-		String name = E.key();
+	for (const KeyValue<String, List<Ref<InputEvent>>> &E : builtins) {
+		String name = E.key;
 
 
 		add_action(name);
 		add_action(name);
 
 
-		List<Ref<InputEvent>> inputs = E.get();
-		for (List<Ref<InputEvent>>::Element *I = inputs.front(); I; I = I->next()) {
+		const List<Ref<InputEvent>> &inputs = E.value;
+		for (const List<Ref<InputEvent>>::Element *I = inputs.front(); I; I = I->next()) {
 			Ref<InputEventKey> iek = I->get();
 			Ref<InputEventKey> iek = I->get();
 
 
 			// For the editor, only add keyboard actions.
 			// For the editor, only add keyboard actions.

+ 7 - 7
core/input/input_map.h

@@ -34,7 +34,7 @@
 #include "core/input/input_event.h"
 #include "core/input/input_event.h"
 #include "core/object/class_db.h"
 #include "core/object/class_db.h"
 #include "core/object/object.h"
 #include "core/object/object.h"
-#include "core/templates/ordered_hash_map.h"
+#include "core/templates/hash_map.h"
 
 
 class InputMap : public Object {
 class InputMap : public Object {
 	GDCLASS(InputMap, Object);
 	GDCLASS(InputMap, Object);
@@ -54,9 +54,9 @@ public:
 private:
 private:
 	static InputMap *singleton;
 	static InputMap *singleton;
 
 
-	mutable OrderedHashMap<StringName, Action> input_map;
-	OrderedHashMap<String, List<Ref<InputEvent>>> default_builtin_cache;
-	OrderedHashMap<String, List<Ref<InputEvent>>> default_builtin_with_overrides_cache;
+	mutable HashMap<StringName, Action> input_map;
+	HashMap<String, List<Ref<InputEvent>>> default_builtin_cache;
+	HashMap<String, List<Ref<InputEvent>>> default_builtin_with_overrides_cache;
 
 
 	List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match = false, bool *r_pressed = nullptr, float *r_strength = nullptr, float *r_raw_strength = nullptr) const;
 	List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match = false, bool *r_pressed = nullptr, float *r_strength = nullptr, float *r_raw_strength = nullptr) const;
 
 
@@ -85,7 +85,7 @@ public:
 	bool event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false) const;
 	bool event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false) const;
 	bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false, bool *r_pressed = nullptr, float *r_strength = nullptr, float *r_raw_strength = nullptr) const;
 	bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false, bool *r_pressed = nullptr, float *r_strength = nullptr, float *r_raw_strength = nullptr) const;
 
 
-	const OrderedHashMap<StringName, Action> &get_action_map() const;
+	const HashMap<StringName, Action> &get_action_map() const;
 	void load_from_project_settings();
 	void load_from_project_settings();
 	void load_default();
 	void load_default();
 
 
@@ -93,8 +93,8 @@ public:
 
 
 	String get_builtin_display_name(const String &p_name) const;
 	String get_builtin_display_name(const String &p_name) const;
 	// Use an Ordered Map so insertion order is preserved. We want the elements to be 'grouped' somewhat.
 	// Use an Ordered Map so insertion order is preserved. We want the elements to be 'grouped' somewhat.
-	const OrderedHashMap<String, List<Ref<InputEvent>>> &get_builtins();
-	const OrderedHashMap<String, List<Ref<InputEvent>>> &get_builtins_with_feature_overrides_applied();
+	const HashMap<String, List<Ref<InputEvent>>> &get_builtins();
+	const HashMap<String, List<Ref<InputEvent>>> &get_builtins_with_feature_overrides_applied();
 
 
 	InputMap();
 	InputMap();
 	~InputMap();
 	~InputMap();

+ 15 - 12
core/io/config_file.cpp

@@ -73,7 +73,7 @@ void ConfigFile::set_value(const String &p_section, const String &p_key, const V
 
 
 	} else {
 	} else {
 		if (!values.has(p_section)) {
 		if (!values.has(p_section)) {
-			values[p_section] = OrderedHashMap<String, Variant>();
+			values[p_section] = HashMap<String, Variant>();
 		}
 		}
 
 
 		values[p_section][p_key] = p_value;
 		values[p_section][p_key] = p_value;
@@ -102,16 +102,16 @@ bool ConfigFile::has_section_key(const String &p_section, const String &p_key) c
 }
 }
 
 
 void ConfigFile::get_sections(List<String> *r_sections) const {
 void ConfigFile::get_sections(List<String> *r_sections) const {
-	for (OrderedHashMap<String, OrderedHashMap<String, Variant>>::ConstElement E = values.front(); E; E = E.next()) {
-		r_sections->push_back(E.key());
+	for (const KeyValue<String, HashMap<String, Variant>> &E : values) {
+		r_sections->push_back(E.key);
 	}
 	}
 }
 }
 
 
 void ConfigFile::get_section_keys(const String &p_section, List<String> *r_keys) const {
 void ConfigFile::get_section_keys(const String &p_section, List<String> *r_keys) const {
 	ERR_FAIL_COND_MSG(!values.has(p_section), vformat("Cannot get keys from nonexistent section \"%s\".", p_section));
 	ERR_FAIL_COND_MSG(!values.has(p_section), vformat("Cannot get keys from nonexistent section \"%s\".", p_section));
 
 
-	for (OrderedHashMap<String, Variant>::ConstElement E = values[p_section].front(); E; E = E.next()) {
-		r_keys->push_back(E.key());
+	for (const KeyValue<String, Variant> &E : values[p_section]) {
+		r_keys->push_back(E.key);
 	}
 	}
 }
 }
 
 
@@ -174,18 +174,21 @@ Error ConfigFile::save_encrypted_pass(const String &p_path, const String &p_pass
 }
 }
 
 
 Error ConfigFile::_internal_save(Ref<FileAccess> file) {
 Error ConfigFile::_internal_save(Ref<FileAccess> file) {
-	for (OrderedHashMap<String, OrderedHashMap<String, Variant>>::Element E = values.front(); E; E = E.next()) {
-		if (E != values.front()) {
+	bool first = true;
+	for (const KeyValue<String, HashMap<String, Variant>> &E : values) {
+		if (first) {
+			first = false;
+		} else {
 			file->store_string("\n");
 			file->store_string("\n");
 		}
 		}
-		if (!E.key().is_empty()) {
-			file->store_string("[" + E.key() + "]\n\n");
+		if (!E.key.is_empty()) {
+			file->store_string("[" + E.key + "]\n\n");
 		}
 		}
 
 
-		for (OrderedHashMap<String, Variant>::Element F = E.get().front(); F; F = F.next()) {
+		for (const KeyValue<String, Variant> &F : E.value) {
 			String vstr;
 			String vstr;
-			VariantWriter::write_to_string(F.get(), vstr);
-			file->store_string(F.key().property_name_encode() + "=" + vstr + "\n");
+			VariantWriter::write_to_string(F.value, vstr);
+			file->store_string(F.key.property_name_encode() + "=" + vstr + "\n");
 		}
 		}
 	}
 	}
 
 

+ 2 - 2
core/io/config_file.h

@@ -33,13 +33,13 @@
 
 
 #include "core/io/file_access.h"
 #include "core/io/file_access.h"
 #include "core/object/ref_counted.h"
 #include "core/object/ref_counted.h"
-#include "core/templates/ordered_hash_map.h"
+#include "core/templates/hash_map.h"
 #include "core/variant/variant_parser.h"
 #include "core/variant/variant_parser.h"
 
 
 class ConfigFile : public RefCounted {
 class ConfigFile : public RefCounted {
 	GDCLASS(ConfigFile, RefCounted);
 	GDCLASS(ConfigFile, RefCounted);
 
 
-	OrderedHashMap<String, OrderedHashMap<String, Variant>> values;
+	HashMap<String, HashMap<String, Variant>> values;
 
 
 	PackedStringArray _get_sections() const;
 	PackedStringArray _get_sections() const;
 	PackedStringArray _get_section_keys(const String &p_section) const;
 	PackedStringArray _get_section_keys(const String &p_section) const;

+ 2 - 2
core/io/missing_resource.cpp

@@ -53,8 +53,8 @@ bool MissingResource::_get(const StringName &p_name, Variant &r_ret) const {
 }
 }
 
 
 void MissingResource::_get_property_list(List<PropertyInfo> *p_list) const {
 void MissingResource::_get_property_list(List<PropertyInfo> *p_list) const {
-	for (OrderedHashMap<StringName, Variant>::ConstElement E = properties.front(); E; E = E.next()) {
-		p_list->push_back(PropertyInfo(E.value().get_type(), E.key()));
+	for (const KeyValue<StringName, Variant> &E : properties) {
+		p_list->push_back(PropertyInfo(E.value.get_type(), E.key));
 	}
 	}
 }
 }
 
 

+ 1 - 1
core/io/missing_resource.h

@@ -38,7 +38,7 @@
 
 
 class MissingResource : public Resource {
 class MissingResource : public Resource {
 	GDCLASS(MissingResource, Resource)
 	GDCLASS(MissingResource, Resource)
-	OrderedHashMap<StringName, Variant> properties;
+	HashMap<StringName, Variant> properties;
 
 
 	String original_class;
 	String original_class;
 	bool recording_properties = false;
 	bool recording_properties = false;

+ 6 - 11
core/io/resource.cpp

@@ -478,10 +478,8 @@ void ResourceCache::clear() {
 	if (resources.size()) {
 	if (resources.size()) {
 		ERR_PRINT("Resources still in use at exit (run with --verbose for details).");
 		ERR_PRINT("Resources still in use at exit (run with --verbose for details).");
 		if (OS::get_singleton()->is_stdout_verbose()) {
 		if (OS::get_singleton()->is_stdout_verbose()) {
-			const String *K = nullptr;
-			while ((K = resources.next(K))) {
-				Resource *r = resources[*K];
-				print_line(vformat("Resource still in use: %s (%s)", *K, r->get_class()));
+			for (const KeyValue<String, Resource *> &E : resources) {
+				print_line(vformat("Resource still in use: %s (%s)", E.key, E.value->get_class()));
 			}
 			}
 		}
 		}
 	}
 	}
@@ -516,10 +514,8 @@ Resource *ResourceCache::get(const String &p_path) {
 
 
 void ResourceCache::get_cached_resources(List<Ref<Resource>> *p_resources) {
 void ResourceCache::get_cached_resources(List<Ref<Resource>> *p_resources) {
 	lock.read_lock();
 	lock.read_lock();
-	const String *K = nullptr;
-	while ((K = resources.next(K))) {
-		Resource *r = resources[*K];
-		p_resources->push_back(Ref<Resource>(r));
+	for (KeyValue<String, Resource *> &E : resources) {
+		p_resources->push_back(Ref<Resource>(E.value));
 	}
 	}
 	lock.read_unlock();
 	lock.read_unlock();
 }
 }
@@ -544,9 +540,8 @@ void ResourceCache::dump(const char *p_file, bool p_short) {
 		ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file at path '" + String::utf8(p_file) + "'.");
 		ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file at path '" + String::utf8(p_file) + "'.");
 	}
 	}
 
 
-	const String *K = nullptr;
-	while ((K = resources.next(K))) {
-		Resource *r = resources[*K];
+	for (KeyValue<String, Resource *> &E : resources) {
+		Resource *r = E.value;
 
 
 		if (!type_count.has(r->get_class())) {
 		if (!type_count.has(r->get_class())) {
 			type_count[r->get_class()] = 0;
 			type_count[r->get_class()] = 0;

+ 11 - 11
core/io/resource_uid.cpp

@@ -149,12 +149,12 @@ Error ResourceUID::save_to_cache() {
 
 
 	cache_entries = 0;
 	cache_entries = 0;
 
 
-	for (OrderedHashMap<ID, Cache>::Element E = unique_ids.front(); E; E = E.next()) {
-		f->store_64(E.key());
-		uint32_t s = E.get().cs.length();
+	for (KeyValue<ID, Cache> &E : unique_ids) {
+		f->store_64(E.key);
+		uint32_t s = E.value.cs.length();
 		f->store_32(s);
 		f->store_32(s);
-		f->store_buffer((const uint8_t *)E.get().cs.ptr(), s);
-		E.get().saved_to_cache = true;
+		f->store_buffer((const uint8_t *)E.value.cs.ptr(), s);
+		E.value.saved_to_cache = true;
 		cache_entries++;
 		cache_entries++;
 	}
 	}
 
 
@@ -202,8 +202,8 @@ Error ResourceUID::update_cache() {
 	MutexLock l(mutex);
 	MutexLock l(mutex);
 
 
 	Ref<FileAccess> f;
 	Ref<FileAccess> f;
-	for (OrderedHashMap<ID, Cache>::Element E = unique_ids.front(); E; E = E.next()) {
-		if (!E.get().saved_to_cache) {
+	for (KeyValue<ID, Cache> &E : unique_ids) {
+		if (!E.value.saved_to_cache) {
 			if (f.is_null()) {
 			if (f.is_null()) {
 				f = FileAccess::open(get_cache_file(), FileAccess::READ_WRITE); //append
 				f = FileAccess::open(get_cache_file(), FileAccess::READ_WRITE); //append
 				if (f.is_null()) {
 				if (f.is_null()) {
@@ -211,11 +211,11 @@ Error ResourceUID::update_cache() {
 				}
 				}
 				f->seek_end();
 				f->seek_end();
 			}
 			}
-			f->store_64(E.key());
-			uint32_t s = E.get().cs.length();
+			f->store_64(E.key);
+			uint32_t s = E.value.cs.length();
 			f->store_32(s);
 			f->store_32(s);
-			f->store_buffer((const uint8_t *)E.get().cs.ptr(), s);
-			E.get().saved_to_cache = true;
+			f->store_buffer((const uint8_t *)E.value.cs.ptr(), s);
+			E.value.saved_to_cache = true;
 			cache_entries++;
 			cache_entries++;
 		}
 		}
 	}
 	}

+ 2 - 2
core/io/resource_uid.h

@@ -33,7 +33,7 @@
 
 
 #include "core/object/ref_counted.h"
 #include "core/object/ref_counted.h"
 #include "core/string/string_name.h"
 #include "core/string/string_name.h"
-#include "core/templates/ordered_hash_map.h"
+#include "core/templates/hash_map.h"
 
 
 class ResourceUID : public Object {
 class ResourceUID : public Object {
 	GDCLASS(ResourceUID, Object)
 	GDCLASS(ResourceUID, Object)
@@ -53,7 +53,7 @@ private:
 		bool saved_to_cache = false;
 		bool saved_to_cache = false;
 	};
 	};
 
 
-	OrderedHashMap<ID, Cache> unique_ids; //unique IDs and utf8 paths (less memory used)
+	HashMap<ID, Cache> unique_ids; //unique IDs and utf8 paths (less memory used)
 	static ResourceUID *singleton;
 	static ResourceUID *singleton;
 
 
 	uint32_t cache_entries = 0;
 	uint32_t cache_entries = 0;

+ 42 - 75
core/object/class_db.cpp

@@ -90,10 +90,8 @@ bool ClassDB::is_parent_class(const StringName &p_class, const StringName &p_inh
 void ClassDB::get_class_list(List<StringName> *p_classes) {
 void ClassDB::get_class_list(List<StringName> *p_classes) {
 	OBJTYPE_RLOCK;
 	OBJTYPE_RLOCK;
 
 
-	const StringName *k = nullptr;
-
-	while ((k = classes.next(k))) {
-		p_classes->push_back(*k);
+	for (const KeyValue<StringName, ClassInfo> &E : classes) {
+		p_classes->push_back(E.key);
 	}
 	}
 
 
 	p_classes->sort();
 	p_classes->sort();
@@ -102,11 +100,9 @@ void ClassDB::get_class_list(List<StringName> *p_classes) {
 void ClassDB::get_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes) {
 void ClassDB::get_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes) {
 	OBJTYPE_RLOCK;
 	OBJTYPE_RLOCK;
 
 
-	const StringName *k = nullptr;
-
-	while ((k = classes.next(k))) {
-		if (*k != p_class && _is_parent_class(*k, p_class)) {
-			p_classes->push_back(*k);
+	for (const KeyValue<StringName, ClassInfo> &E : classes) {
+		if (E.key != p_class && _is_parent_class(E.key, p_class)) {
+			p_classes->push_back(E.key);
 		}
 		}
 	}
 	}
 }
 }
@@ -114,11 +110,9 @@ void ClassDB::get_inheriters_from_class(const StringName &p_class, List<StringNa
 void ClassDB::get_direct_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes) {
 void ClassDB::get_direct_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes) {
 	OBJTYPE_RLOCK;
 	OBJTYPE_RLOCK;
 
 
-	const StringName *k = nullptr;
-
-	while ((k = classes.next(k))) {
-		if (*k != p_class && _get_parent_class(*k) == p_class) {
-			p_classes->push_back(*k);
+	for (const KeyValue<StringName, ClassInfo> &E : classes) {
+		if (E.key != p_class && _get_parent_class(E.key) == p_class) {
+			p_classes->push_back(E.key);
 		}
 		}
 	}
 	}
 }
 }
@@ -172,17 +166,12 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
 
 
 	uint64_t hash = hash_djb2_one_64(HashMapHasherDefault::hash(VERSION_FULL_CONFIG));
 	uint64_t hash = hash_djb2_one_64(HashMapHasherDefault::hash(VERSION_FULL_CONFIG));
 
 
-	List<StringName> names;
-
-	const StringName *k = nullptr;
+	List<StringName> class_list;
+	ClassDB::get_class_list(&class_list);
+	// Must be alphabetically sorted for hash to compute.
+	class_list.sort_custom<StringName::AlphCompare>();
 
 
-	while ((k = classes.next(k))) {
-		names.push_back(*k);
-	}
-	//must be alphabetically sorted for hash to compute
-	names.sort_custom<StringName::AlphCompare>();
-
-	for (const StringName &E : names) {
+	for (const StringName &E : class_list) {
 		ClassInfo *t = classes.getptr(E);
 		ClassInfo *t = classes.getptr(E);
 		ERR_FAIL_COND_V_MSG(!t, 0, "Cannot get class '" + String(E) + "'.");
 		ERR_FAIL_COND_V_MSG(!t, 0, "Cannot get class '" + String(E) + "'.");
 		if (t->api != p_api || !t->exposed) {
 		if (t->api != p_api || !t->exposed) {
@@ -195,10 +184,8 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
 
 
 			List<StringName> snames;
 			List<StringName> snames;
 
 
-			k = nullptr;
-
-			while ((k = t->method_map.next(k))) {
-				String name = k->operator String();
+			for (const KeyValue<StringName, MethodBind *> &F : t->method_map) {
+				String name = F.key.operator String();
 
 
 				ERR_CONTINUE(name.is_empty());
 				ERR_CONTINUE(name.is_empty());
 
 
@@ -206,7 +193,7 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
 					continue; // Ignore non-virtual methods that start with an underscore
 					continue; // Ignore non-virtual methods that start with an underscore
 				}
 				}
 
 
-				snames.push_back(*k);
+				snames.push_back(F.key);
 			}
 			}
 
 
 			snames.sort_custom<StringName::AlphCompare>();
 			snames.sort_custom<StringName::AlphCompare>();
@@ -241,10 +228,8 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
 
 
 			List<StringName> snames;
 			List<StringName> snames;
 
 
-			k = nullptr;
-
-			while ((k = t->constant_map.next(k))) {
-				snames.push_back(*k);
+			for (const KeyValue<StringName, int> &F : t->constant_map) {
+				snames.push_back(F.key);
 			}
 			}
 
 
 			snames.sort_custom<StringName::AlphCompare>();
 			snames.sort_custom<StringName::AlphCompare>();
@@ -259,10 +244,8 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
 
 
 			List<StringName> snames;
 			List<StringName> snames;
 
 
-			k = nullptr;
-
-			while ((k = t->signal_map.next(k))) {
-				snames.push_back(*k);
+			for (const KeyValue<StringName, MethodInfo> &F : t->signal_map) {
+				snames.push_back(F.key);
 			}
 			}
 
 
 			snames.sort_custom<StringName::AlphCompare>();
 			snames.sort_custom<StringName::AlphCompare>();
@@ -280,10 +263,8 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
 
 
 			List<StringName> snames;
 			List<StringName> snames;
 
 
-			k = nullptr;
-
-			while ((k = t->property_setget.next(k))) {
-				snames.push_back(*k);
+			for (const KeyValue<StringName, PropertySetGet> &F : t->property_setget) {
+				snames.push_back(F.key);
 			}
 			}
 
 
 			snames.sort_custom<StringName::AlphCompare>();
 			snames.sort_custom<StringName::AlphCompare>();
@@ -474,10 +455,8 @@ void ClassDB::get_method_list(const StringName &p_class, List<MethodInfo> *p_met
 
 
 #else
 #else
 
 
-		const StringName *K = nullptr;
-
-		while ((K = type->method_map.next(K))) {
-			MethodBind *m = type->method_map[*K];
+		for (KeyValue<StringName, MethodBind *> &E : type->method_map) {
+			MethodBind *m = E.value;
 			MethodInfo minfo = info_from_bind(m);
 			MethodInfo minfo = info_from_bind(m);
 			p_methods->push_back(minfo);
 			p_methods->push_back(minfo);
 		}
 		}
@@ -603,10 +582,9 @@ void ClassDB::get_integer_constant_list(const StringName &p_class, List<String>
 			p_constants->push_back(E);
 			p_constants->push_back(E);
 		}
 		}
 #else
 #else
-		const StringName *K = nullptr;
 
 
-		while ((K = type->constant_map.next(K))) {
-			p_constants->push_back(*K);
+		for (const KeyValue<StringName, int> &E : type->constant_map) {
+			p_constants->push_back(E.key);
 		}
 		}
 
 
 #endif
 #endif
@@ -667,12 +645,11 @@ StringName ClassDB::get_integer_constant_enum(const StringName &p_class, const S
 	ClassInfo *type = classes.getptr(p_class);
 	ClassInfo *type = classes.getptr(p_class);
 
 
 	while (type) {
 	while (type) {
-		const StringName *k = nullptr;
-		while ((k = type->enum_map.next(k))) {
-			List<StringName> &constants_list = type->enum_map.get(*k);
+		for (KeyValue<StringName, List<StringName>> &E : type->enum_map) {
+			List<StringName> &constants_list = E.value;
 			const List<StringName>::Element *found = constants_list.find(p_name);
 			const List<StringName>::Element *found = constants_list.find(p_name);
 			if (found) {
 			if (found) {
-				return *k;
+				return E.key;
 			}
 			}
 		}
 		}
 
 
@@ -692,9 +669,8 @@ void ClassDB::get_enum_list(const StringName &p_class, List<StringName> *p_enums
 	ClassInfo *type = classes.getptr(p_class);
 	ClassInfo *type = classes.getptr(p_class);
 
 
 	while (type) {
 	while (type) {
-		const StringName *k = nullptr;
-		while ((k = type->enum_map.next(k))) {
-			p_enums->push_back(*k);
+		for (KeyValue<StringName, List<StringName>> &E : type->enum_map) {
+			p_enums->push_back(E.key);
 		}
 		}
 
 
 		if (p_no_inheritance) {
 		if (p_no_inheritance) {
@@ -800,9 +776,8 @@ void ClassDB::get_signal_list(const StringName &p_class, List<MethodInfo> *p_sig
 	ClassInfo *check = type;
 	ClassInfo *check = type;
 
 
 	while (check) {
 	while (check) {
-		const StringName *S = nullptr;
-		while ((S = check->signal_map.next(S))) {
-			p_signals->push_back(check->signal_map[*S]);
+		for (KeyValue<StringName, MethodInfo> &E : check->signal_map) {
+			p_signals->push_back(E.value);
 		}
 		}
 
 
 		if (p_no_inheritance) {
 		if (p_no_inheritance) {
@@ -1397,10 +1372,8 @@ void ClassDB::add_resource_base_extension(const StringName &p_extension, const S
 }
 }
 
 
 void ClassDB::get_resource_base_extensions(List<String> *p_extensions) {
 void ClassDB::get_resource_base_extensions(List<String> *p_extensions) {
-	const StringName *K = nullptr;
-
-	while ((K = resource_base_extensions.next(K))) {
-		p_extensions->push_back(*K);
+	for (const KeyValue<StringName, StringName> &E : resource_base_extensions) {
+		p_extensions->push_back(E.key);
 	}
 	}
 }
 }
 
 
@@ -1409,12 +1382,9 @@ bool ClassDB::is_resource_extension(const StringName &p_extension) {
 }
 }
 
 
 void ClassDB::get_extensions_for_type(const StringName &p_class, List<String> *p_extensions) {
 void ClassDB::get_extensions_for_type(const StringName &p_class, List<String> *p_extensions) {
-	const StringName *K = nullptr;
-
-	while ((K = resource_base_extensions.next(K))) {
-		StringName cmp = resource_base_extensions[*K];
-		if (is_parent_class(p_class, cmp) || is_parent_class(cmp, p_class)) {
-			p_extensions->push_back(*K);
+	for (const KeyValue<StringName, StringName> &E : resource_base_extensions) {
+		if (is_parent_class(p_class, E.value) || is_parent_class(E.value, p_class)) {
+			p_extensions->push_back(E.key);
 		}
 		}
 	}
 	}
 }
 }
@@ -1556,14 +1526,11 @@ void ClassDB::cleanup_defaults() {
 void ClassDB::cleanup() {
 void ClassDB::cleanup() {
 	//OBJTYPE_LOCK; hah not here
 	//OBJTYPE_LOCK; hah not here
 
 
-	const StringName *k = nullptr;
-
-	while ((k = classes.next(k))) {
-		ClassInfo &ti = classes[*k];
+	for (KeyValue<StringName, ClassInfo> &E : classes) {
+		ClassInfo &ti = E.value;
 
 
-		const StringName *m = nullptr;
-		while ((m = ti.method_map.next(m))) {
-			memdelete(ti.method_map[*m]);
+		for (KeyValue<StringName, MethodBind *> &F : ti.method_map) {
+			memdelete(F.value);
 		}
 		}
 	}
 	}
 	classes.clear();
 	classes.clear();

+ 29 - 33
core/object/object.cpp

@@ -417,9 +417,9 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid
 		return;
 		return;
 
 
 	} else {
 	} else {
-		OrderedHashMap<StringName, Variant>::Element *E = metadata_properties.getptr(p_name);
-		if (E) {
-			E->get() = p_value;
+		Variant **V = metadata_properties.getptr(p_name);
+		if (V) {
+			**V = p_value;
 			if (r_valid) {
 			if (r_valid) {
 				*r_valid = true;
 				*r_valid = true;
 			}
 			}
@@ -508,10 +508,10 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const {
 		return ret;
 		return ret;
 	}
 	}
 
 
-	const OrderedHashMap<StringName, Variant>::Element *E = metadata_properties.getptr(p_name);
+	const Variant *const *V = metadata_properties.getptr(p_name);
 
 
-	if (E) {
-		ret = E->get();
+	if (V) {
+		ret = **V;
 		if (r_valid) {
 		if (r_valid) {
 			*r_valid = true;
 			*r_valid = true;
 		}
 		}
@@ -666,9 +666,9 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
 		script_instance->get_property_list(p_list);
 		script_instance->get_property_list(p_list);
 	}
 	}
 
 
-	for (OrderedHashMap<StringName, Variant>::ConstElement K = metadata.front(); K; K = K.next()) {
-		PropertyInfo pi = PropertyInfo(K.value().get_type(), "metadata/" + K.key().operator String());
-		if (K.value().get_type() == Variant::OBJECT) {
+	for (const KeyValue<StringName, Variant> &K : metadata) {
+		PropertyInfo pi = PropertyInfo(K.value.get_type(), "metadata/" + K.key.operator String());
+		if (K.value.get_type() == Variant::OBJECT) {
 			pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
 			pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
 			pi.hint_string = "Resource";
 			pi.hint_string = "Resource";
 		}
 		}
@@ -944,13 +944,13 @@ void Object::set_meta(const StringName &p_name, const Variant &p_value) {
 		return;
 		return;
 	}
 	}
 
 
-	OrderedHashMap<StringName, Variant>::Element E = metadata.find(p_name);
+	HashMap<StringName, Variant>::Iterator E = metadata.find(p_name);
 	if (E) {
 	if (E) {
-		E.value() = p_value;
+		E->value = p_value;
 	} else {
 	} else {
 		ERR_FAIL_COND(!p_name.operator String().is_valid_identifier());
 		ERR_FAIL_COND(!p_name.operator String().is_valid_identifier());
-		E = metadata.insert(p_name, p_value);
-		metadata_properties["metadata/" + p_name.operator String()] = E;
+		Variant *V = &metadata.insert(p_name, p_value)->value;
+		metadata_properties["metadata/" + p_name.operator String()] = V;
 		notify_property_list_changed();
 		notify_property_list_changed();
 	}
 	}
 }
 }
@@ -993,16 +993,16 @@ Array Object::_get_method_list_bind() const {
 Vector<StringName> Object::_get_meta_list_bind() const {
 Vector<StringName> Object::_get_meta_list_bind() const {
 	Vector<StringName> _metaret;
 	Vector<StringName> _metaret;
 
 
-	for (OrderedHashMap<StringName, Variant>::ConstElement K = metadata.front(); K; K = K.next()) {
-		_metaret.push_back(K.key());
+	for (const KeyValue<StringName, Variant> &K : metadata) {
+		_metaret.push_back(K.key);
 	}
 	}
 
 
 	return _metaret;
 	return _metaret;
 }
 }
 
 
 void Object::get_meta_list(List<StringName> *p_list) const {
 void Object::get_meta_list(List<StringName> *p_list) const {
-	for (OrderedHashMap<StringName, Variant>::ConstElement K = metadata.front(); K; K = K.next()) {
-		p_list->push_back(K.key());
+	for (const KeyValue<StringName, Variant> &K : metadata) {
+		p_list->push_back(K.key);
 	}
 	}
 }
 }
 
 
@@ -1250,21 +1250,18 @@ void Object::get_signal_list(List<MethodInfo> *p_signals) const {
 
 
 	ClassDB::get_signal_list(get_class_name(), p_signals);
 	ClassDB::get_signal_list(get_class_name(), p_signals);
 	//find maybe usersignals?
 	//find maybe usersignals?
-	const StringName *S = nullptr;
 
 
-	while ((S = signal_map.next(S))) {
-		if (!signal_map[*S].user.name.is_empty()) {
+	for (const KeyValue<StringName, SignalData> &E : signal_map) {
+		if (!E.value.user.name.is_empty()) {
 			//user signal
 			//user signal
-			p_signals->push_back(signal_map[*S].user);
+			p_signals->push_back(E.value.user);
 		}
 		}
 	}
 	}
 }
 }
 
 
 void Object::get_all_signal_connections(List<Connection> *p_connections) const {
 void Object::get_all_signal_connections(List<Connection> *p_connections) const {
-	const StringName *S = nullptr;
-
-	while ((S = signal_map.next(S))) {
-		const SignalData *s = &signal_map[*S];
+	for (const KeyValue<StringName, SignalData> &E : signal_map) {
+		const SignalData *s = &E.value;
 
 
 		for (int i = 0; i < s->slot_map.size(); i++) {
 		for (int i = 0; i < s->slot_map.size(); i++) {
 			p_connections->push_back(s->slot_map.getv(i).conn);
 			p_connections->push_back(s->slot_map.getv(i).conn);
@@ -1285,10 +1282,9 @@ void Object::get_signal_connection_list(const StringName &p_signal, List<Connect
 
 
 int Object::get_persistent_signal_connection_count() const {
 int Object::get_persistent_signal_connection_count() const {
 	int count = 0;
 	int count = 0;
-	const StringName *S = nullptr;
 
 
-	while ((S = signal_map.next(S))) {
-		const SignalData *s = &signal_map[*S];
+	for (const KeyValue<StringName, SignalData> &E : signal_map) {
+		const SignalData *s = &E.value;
 
 
 		for (int i = 0; i < s->slot_map.size(); i++) {
 		for (int i = 0; i < s->slot_map.size(); i++) {
 			if (s->slot_map.getv(i).conn.flags & CONNECT_PERSIST) {
 			if (s->slot_map.getv(i).conn.flags & CONNECT_PERSIST) {
@@ -1866,15 +1862,15 @@ Object::~Object() {
 		_extension_instance = nullptr;
 		_extension_instance = nullptr;
 	}
 	}
 
 
-	const StringName *S = nullptr;
-
 	if (_emitting) {
 	if (_emitting) {
 		//@todo this may need to actually reach the debugger prioritarily somehow because it may crash before
 		//@todo this may need to actually reach the debugger prioritarily somehow because it may crash before
 		ERR_PRINT("Object " + to_string() + " was freed or unreferenced while a signal is being emitted from it. Try connecting to the signal using 'CONNECT_DEFERRED' flag, or use queue_free() to free the object (if this object is a Node) to avoid this error and potential crashes.");
 		ERR_PRINT("Object " + to_string() + " was freed or unreferenced while a signal is being emitted from it. Try connecting to the signal using 'CONNECT_DEFERRED' flag, or use queue_free() to free the object (if this object is a Node) to avoid this error and potential crashes.");
 	}
 	}
 
 
-	while ((S = signal_map.next(nullptr))) {
-		SignalData *s = &signal_map[*S];
+	while (signal_map.size()) {
+		// Avoid regular iteration so erasing is safe.
+		KeyValue<StringName, SignalData> &E = *signal_map.begin();
+		SignalData *s = &E.value;
 
 
 		//brute force disconnect for performance
 		//brute force disconnect for performance
 		int slot_count = s->slot_map.size();
 		int slot_count = s->slot_map.size();
@@ -1884,7 +1880,7 @@ Object::~Object() {
 			slot_list[i].value.conn.callable.get_object()->connections.erase(slot_list[i].value.cE);
 			slot_list[i].value.conn.callable.get_object()->connections.erase(slot_list[i].value.cE);
 		}
 		}
 
 
-		signal_map.erase(*S);
+		signal_map.erase(E.key);
 	}
 	}
 
 
 	//signals from nodes that connect to this node
 	//signals from nodes that connect to this node

+ 2 - 3
core/object/object.h

@@ -39,7 +39,6 @@
 #include "core/templates/hash_map.h"
 #include "core/templates/hash_map.h"
 #include "core/templates/list.h"
 #include "core/templates/list.h"
 #include "core/templates/map.h"
 #include "core/templates/map.h"
-#include "core/templates/ordered_hash_map.h"
 #include "core/templates/safe_refcount.h"
 #include "core/templates/safe_refcount.h"
 #include "core/templates/set.h"
 #include "core/templates/set.h"
 #include "core/templates/vmap.h"
 #include "core/templates/vmap.h"
@@ -515,8 +514,8 @@ private:
 #endif
 #endif
 	ScriptInstance *script_instance = nullptr;
 	ScriptInstance *script_instance = nullptr;
 	Variant script; // Reference does not exist yet, store it in a Variant.
 	Variant script; // Reference does not exist yet, store it in a Variant.
-	OrderedHashMap<StringName, Variant> metadata;
-	HashMap<StringName, OrderedHashMap<StringName, Variant>::Element> metadata_properties;
+	HashMap<StringName, Variant> metadata;
+	HashMap<StringName, Variant *> metadata_properties;
 	mutable StringName _class_name;
 	mutable StringName _class_name;
 	mutable const StringName *_class_ptr = nullptr;
 	mutable const StringName *_class_ptr = nullptr;
 
 

+ 2 - 3
core/object/script_language.cpp

@@ -253,10 +253,9 @@ StringName ScriptServer::get_global_class_native_base(const String &p_class) {
 }
 }
 
 
 void ScriptServer::get_global_class_list(List<StringName> *r_global_classes) {
 void ScriptServer::get_global_class_list(List<StringName> *r_global_classes) {
-	const StringName *K = nullptr;
 	List<StringName> classes;
 	List<StringName> classes;
-	while ((K = global_classes.next(K))) {
-		classes.push_back(*K);
+	for (const KeyValue<StringName, GlobalScriptClass> &E : global_classes) {
+		classes.push_back(E.key);
 	}
 	}
 	classes.sort_custom<StringName::AlphCompare>();
 	classes.sort_custom<StringName::AlphCompare>();
 	for (const StringName &E : classes) {
 	for (const StringName &E : classes) {

+ 8 - 0
core/os/memory.h

@@ -197,4 +197,12 @@ struct _GlobalNilClass {
 	static _GlobalNil _nil;
 	static _GlobalNil _nil;
 };
 };
 
 
+template <class T>
+class DefaultTypedAllocator {
+public:
+	template <class... Args>
+	_FORCE_INLINE_ T *new_allocation(const Args &&...p_args) { return memnew(T(p_args...)); }
+	_FORCE_INLINE_ void delete_allocation(T *p_allocation) { memdelete(p_allocation); }
+};
+
 #endif // MEMORY_H
 #endif // MEMORY_H

+ 13 - 27
core/string/translation_po.cpp

@@ -70,21 +70,14 @@ Dictionary TranslationPO::_get_messages() const {
 
 
 	Dictionary d;
 	Dictionary d;
 
 
-	List<StringName> context_l;
-	translation_map.get_key_list(&context_l);
-	for (const StringName &ctx : context_l) {
-		const HashMap<StringName, Vector<StringName>> &id_str_map = translation_map[ctx];
-
+	for (const KeyValue<StringName, HashMap<StringName, Vector<StringName>>> &E : translation_map) {
 		Dictionary d2;
 		Dictionary d2;
-		List<StringName> id_l;
-		id_str_map.get_key_list(&id_l);
-		// Save list of id and strs associated with a context in a temporary dictionary.
-		for (List<StringName>::Element *E2 = id_l.front(); E2; E2 = E2->next()) {
-			StringName id = E2->get();
-			d2[id] = id_str_map[id];
+
+		for (const KeyValue<StringName, Vector<StringName>> &E2 : E.value) {
+			d2[E2.key] = E2.value;
 		}
 		}
 
 
-		d[ctx] = d2;
+		d[E.key] = d2;
 	}
 	}
 
 
 	return d;
 	return d;
@@ -274,31 +267,24 @@ void TranslationPO::get_message_list(List<StringName> *r_messages) const {
 	// OptimizedTranslation uses this function to get the list of msgid.
 	// OptimizedTranslation uses this function to get the list of msgid.
 	// Return all the keys of translation_map under "" context.
 	// Return all the keys of translation_map under "" context.
 
 
-	List<StringName> context_l;
-	translation_map.get_key_list(&context_l);
-
-	for (const StringName &E : context_l) {
-		if (String(E) != "") {
+	for (const KeyValue<StringName, HashMap<StringName, Vector<StringName>>> &E : translation_map) {
+		if (E.key != StringName()) {
 			continue;
 			continue;
 		}
 		}
 
 
-		List<StringName> msgid_l;
-		translation_map[E].get_key_list(&msgid_l);
-
-		for (List<StringName>::Element *E2 = msgid_l.front(); E2; E2 = E2->next()) {
-			r_messages->push_back(E2->get());
+		for (const KeyValue<StringName, Vector<StringName>> &E2 : E.value) {
+			r_messages->push_back(E2.key);
 		}
 		}
 	}
 	}
 }
 }
 
 
 int TranslationPO::get_message_count() const {
 int TranslationPO::get_message_count() const {
-	List<StringName> context_l;
-	translation_map.get_key_list(&context_l);
-
 	int count = 0;
 	int count = 0;
-	for (const StringName &E : context_l) {
-		count += translation_map[E].size();
+
+	for (const KeyValue<StringName, HashMap<StringName, Vector<StringName>>> &E : translation_map) {
+		count += E.value.size();
 	}
 	}
+
 	return count;
 	return count;
 }
 }
 
 

+ 402 - 373
core/templates/hash_map.h

@@ -31,524 +31,553 @@
 #ifndef HASH_MAP_H
 #ifndef HASH_MAP_H
 #define HASH_MAP_H
 #define HASH_MAP_H
 
 
-#include "core/error/error_macros.h"
 #include "core/math/math_funcs.h"
 #include "core/math/math_funcs.h"
 #include "core/os/memory.h"
 #include "core/os/memory.h"
-#include "core/string/ustring.h"
 #include "core/templates/hashfuncs.h"
 #include "core/templates/hashfuncs.h"
-#include "core/templates/list.h"
+#include "core/templates/paged_allocator.h"
+#include "core/templates/pair.h"
 
 
 /**
 /**
- * @class HashMap
+ * A HashMap implementation that uses open addressing with Robin Hood hashing.
+ * Robin Hood hashing swaps out entries that have a smaller probing distance
+ * than the to-be-inserted entry, that evens out the average probing distance
+ * and enables faster lookups. Backward shift deletion is employed to further
+ * improve the performance and to avoid infinite loops in rare cases.
  *
  *
- * Implementation of a standard Hashing HashMap, for quick lookups of Data associated with a Key.
- * The implementation provides hashers for the default types, if you need a special kind of hasher, provide
- * your own.
- * @param TKey  Key, search is based on it, needs to be hasheable. It is unique in this container.
- * @param TData Data, data associated with the key
- * @param Hasher Hasher object, needs to provide a valid static hash function for TKey
- * @param Comparator comparator object, needs to be able to safely compare two TKey values.
- * It needs to ensure that x == x for any items inserted in the map. Bear in mind that nan != nan when implementing an equality check.
- * @param MIN_HASH_TABLE_POWER Miminum size of the hash table, as a power of two. You rarely need to change this parameter.
- * @param RELATIONSHIP Relationship at which the hash table is resized. if amount of elements is RELATIONSHIP
- * times bigger than the hash table, table is resized to solve this condition. if RELATIONSHIP is zero, table is always MIN_HASH_TABLE_POWER.
+ * Keys and values are stored in a double linked list by insertion order. This
+ * has a slight performance overhead on lookup, which can be mostly compensated
+ * using a paged allocator if required.
  *
  *
+ * The assignment operator copy the pairs from one map to the other.
  */
  */
 
 
-template <class TKey, class TData, class Hasher = HashMapHasherDefault, class Comparator = HashMapComparatorDefault<TKey>, uint8_t MIN_HASH_TABLE_POWER = 3, uint8_t RELATIONSHIP = 8>
+template <class TKey, class TValue>
+struct HashMapElement {
+	HashMapElement *next = nullptr;
+	HashMapElement *prev = nullptr;
+	KeyValue<TKey, TValue> data;
+	HashMapElement() {}
+	HashMapElement(const TKey &p_key, const TValue &p_value) :
+			data(p_key, p_value) {}
+};
+
+template <class TKey, class TValue,
+		class Hasher = HashMapHasherDefault,
+		class Comparator = HashMapComparatorDefault<TKey>,
+		class Allocator = DefaultTypedAllocator<HashMapElement<TKey, TValue>>>
 class HashMap {
 class HashMap {
 public:
 public:
-	struct Pair {
-		TKey key;
-		TData data;
+	const uint32_t MIN_CAPACITY_INDEX = 2; // Use a prime.
+	const float MAX_OCCUPANCY = 0.75;
+	const uint32_t EMPTY_HASH = 0;
 
 
-		Pair(const TKey &p_key) :
-				key(p_key),
-				data() {}
-		Pair(const TKey &p_key, const TData &p_data) :
-				key(p_key),
-				data(p_data) {
-		}
-	};
+private:
+	Allocator element_alloc;
+	HashMapElement<TKey, TValue> **elements = nullptr;
+	uint32_t *hashes = nullptr;
+	HashMapElement<TKey, TValue> *head_element = nullptr;
+	HashMapElement<TKey, TValue> *tail_element = nullptr;
 
 
-	struct Element {
-	private:
-		friend class HashMap;
+	uint32_t capacity_index = 0;
+	uint32_t num_elements = 0;
 
 
-		uint32_t hash = 0;
-		Element *next = nullptr;
-		Element() {}
-		Pair pair;
+	_FORCE_INLINE_ uint32_t _hash(const TKey &p_key) const {
+		uint32_t hash = Hasher::hash(p_key);
 
 
-	public:
-		const TKey &key() const {
-			return pair.key;
+		if (unlikely(hash == EMPTY_HASH)) {
+			hash = EMPTY_HASH + 1;
 		}
 		}
 
 
-		TData &value() {
-			return pair.data;
-		}
+		return hash;
+	}
 
 
-		const TData &value() const {
-			return pair.value();
+	_FORCE_INLINE_ uint32_t _get_probe_length(uint32_t p_pos, uint32_t p_hash, uint32_t p_capacity) const {
+		uint32_t original_pos = p_hash % p_capacity;
+		return (p_pos - original_pos + p_capacity) % p_capacity;
+	}
+
+	bool _lookup_pos(const TKey &p_key, uint32_t &r_pos) const {
+		if (elements == nullptr) {
+			return false; // Failed lookups, no elements
 		}
 		}
 
 
-		Element(const TKey &p_key) :
-				pair(p_key) {}
-		Element(const Element &p_other) :
-				hash(p_other.hash),
-				pair(p_other.pair.key, p_other.pair.data) {}
-	};
+		uint32_t capacity = hash_table_size_primes[capacity_index];
+		uint32_t hash = _hash(p_key);
+		uint32_t pos = hash % capacity;
+		uint32_t distance = 0;
 
 
-private:
-	Element **hash_table = nullptr;
-	uint8_t hash_table_power = 0;
-	uint32_t elements = 0;
+		while (true) {
+			if (hashes[pos] == EMPTY_HASH) {
+				return false;
+			}
 
 
-	void make_hash_table() {
-		ERR_FAIL_COND(hash_table);
+			if (distance > _get_probe_length(pos, hashes[pos], capacity)) {
+				return false;
+			}
 
 
-		hash_table = memnew_arr(Element *, (1 << MIN_HASH_TABLE_POWER));
+			if (hashes[pos] == hash && Comparator::compare(elements[pos]->data.key, p_key)) {
+				r_pos = pos;
+				return true;
+			}
 
 
-		hash_table_power = MIN_HASH_TABLE_POWER;
-		elements = 0;
-		for (int i = 0; i < (1 << MIN_HASH_TABLE_POWER); i++) {
-			hash_table[i] = nullptr;
+			pos = (pos + 1) % capacity;
+			distance++;
 		}
 		}
 	}
 	}
 
 
-	void erase_hash_table() {
-		ERR_FAIL_COND_MSG(elements, "Cannot erase hash table if there are still elements inside.");
+	void _insert_with_hash(uint32_t p_hash, HashMapElement<TKey, TValue> *p_value) {
+		uint32_t capacity = hash_table_size_primes[capacity_index];
+		uint32_t hash = p_hash;
+		HashMapElement<TKey, TValue> *value = p_value;
+		uint32_t distance = 0;
+		uint32_t pos = hash % capacity;
 
 
-		memdelete_arr(hash_table);
-		hash_table = nullptr;
-		hash_table_power = 0;
-		elements = 0;
-	}
+		while (true) {
+			if (hashes[pos] == EMPTY_HASH) {
+				elements[pos] = value;
+				hashes[pos] = hash;
 
 
-	void check_hash_table() {
-		int new_hash_table_power = -1;
+				num_elements++;
 
 
-		if ((int)elements > ((1 << hash_table_power) * RELATIONSHIP)) {
-			/* rehash up */
-			new_hash_table_power = hash_table_power + 1;
-
-			while ((int)elements > ((1 << new_hash_table_power) * RELATIONSHIP)) {
-				new_hash_table_power++;
+				return;
 			}
 			}
 
 
-		} else if ((hash_table_power > (int)MIN_HASH_TABLE_POWER) && ((int)elements < ((1 << (hash_table_power - 1)) * RELATIONSHIP))) {
-			/* rehash down */
-			new_hash_table_power = hash_table_power - 1;
-
-			while ((int)elements < ((1 << (new_hash_table_power - 1)) * RELATIONSHIP)) {
-				new_hash_table_power--;
+			// Not an empty slot, let's check the probing length of the existing one.
+			uint32_t existing_probe_len = _get_probe_length(pos, hashes[pos], capacity);
+			if (existing_probe_len < distance) {
+				SWAP(hash, hashes[pos]);
+				SWAP(value, elements[pos]);
+				distance = existing_probe_len;
 			}
 			}
 
 
-			if (new_hash_table_power < (int)MIN_HASH_TABLE_POWER) {
-				new_hash_table_power = MIN_HASH_TABLE_POWER;
-			}
+			pos = (pos + 1) % capacity;
+			distance++;
 		}
 		}
+	}
 
 
-		if (new_hash_table_power == -1) {
-			return;
-		}
+	void _resize_and_rehash(uint32_t p_new_capacity_index) {
+		uint32_t old_capacity = hash_table_size_primes[capacity_index];
 
 
-		Element **new_hash_table = memnew_arr(Element *, ((uint64_t)1 << new_hash_table_power));
-		ERR_FAIL_COND_MSG(!new_hash_table, "Out of memory.");
+		// Capacity can't be 0.
+		capacity_index = MAX((uint32_t)MIN_CAPACITY_INDEX, p_new_capacity_index);
 
 
-		for (int i = 0; i < (1 << new_hash_table_power); i++) {
-			new_hash_table[i] = nullptr;
-		}
+		uint32_t capacity = hash_table_size_primes[capacity_index];
 
 
-		if (hash_table) {
-			for (int i = 0; i < (1 << hash_table_power); i++) {
-				while (hash_table[i]) {
-					Element *se = hash_table[i];
-					hash_table[i] = se->next;
-					int new_pos = se->hash & ((1 << new_hash_table_power) - 1);
-					se->next = new_hash_table[new_pos];
-					new_hash_table[new_pos] = se;
-				}
-			}
+		HashMapElement<TKey, TValue> **old_elements = elements;
+		uint32_t *old_hashes = hashes;
 
 
-			memdelete_arr(hash_table);
-		}
-		hash_table = new_hash_table;
-		hash_table_power = new_hash_table_power;
-	}
+		num_elements = 0;
+		hashes = reinterpret_cast<uint32_t *>(Memory::alloc_static(sizeof(uint32_t) * capacity));
+		elements = reinterpret_cast<HashMapElement<TKey, TValue> **>(Memory::alloc_static(sizeof(HashMapElement<TKey, TValue> *) * capacity));
 
 
-	/* I want to have only one function.. */
-	_FORCE_INLINE_ const Element *get_element(const TKey &p_key) const {
-		uint32_t hash = Hasher::hash(p_key);
-		uint32_t index = hash & ((1 << hash_table_power) - 1);
+		for (uint32_t i = 0; i < capacity; i++) {
+			hashes[i] = 0;
+			elements[i] = nullptr;
+		}
 
 
-		Element *e = hash_table[index];
+		if (old_capacity == 0) {
+			// Nothing to do.
+			return;
+		}
 
 
-		while (e) {
-			/* checking hash first avoids comparing key, which may take longer */
-			if (e->hash == hash && Comparator::compare(e->pair.key, p_key)) {
-				/* the pair exists in this hashtable, so just update data */
-				return e;
+		for (uint32_t i = 0; i < old_capacity; i++) {
+			if (old_hashes[i] == EMPTY_HASH) {
+				continue;
 			}
 			}
 
 
-			e = e->next;
+			_insert_with_hash(old_hashes[i], old_elements[i]);
 		}
 		}
 
 
-		return nullptr;
-	}
-
-	Element *create_element(const TKey &p_key) {
-		/* if element doesn't exist, create it */
-		Element *e = memnew(Element(p_key));
-		ERR_FAIL_COND_V_MSG(!e, nullptr, "Out of memory.");
-		uint32_t hash = Hasher::hash(p_key);
-		uint32_t index = hash & ((1 << hash_table_power) - 1);
-		e->next = hash_table[index];
-		e->hash = hash;
-
-		hash_table[index] = e;
-		elements++;
-
-		return e;
+		Memory::free_static(old_elements);
+		Memory::free_static(old_hashes);
 	}
 	}
 
 
-	void copy_from(const HashMap &p_t) {
-		if (&p_t == this) {
-			return; /* much less bother with that */
-		}
+	_FORCE_INLINE_ HashMapElement<TKey, TValue> *_insert(const TKey &p_key, const TValue &p_value, bool p_front_insert = false) {
+		uint32_t capacity = hash_table_size_primes[capacity_index];
+		if (unlikely(elements == nullptr)) {
+			// Allocate on demand to save memory.
 
 
-		clear();
+			hashes = reinterpret_cast<uint32_t *>(Memory::alloc_static(sizeof(uint32_t) * capacity));
+			elements = reinterpret_cast<HashMapElement<TKey, TValue> **>(Memory::alloc_static(sizeof(HashMapElement<TKey, TValue> *) * capacity));
 
 
-		if (!p_t.hash_table || p_t.hash_table_power == 0) {
-			return; /* not copying from empty table */
+			for (uint32_t i = 0; i < capacity; i++) {
+				hashes[i] = EMPTY_HASH;
+				elements[i] = nullptr;
+			}
 		}
 		}
 
 
-		hash_table = memnew_arr(Element *, (uint64_t)1 << p_t.hash_table_power);
-		hash_table_power = p_t.hash_table_power;
-		elements = p_t.elements;
-
-		for (int i = 0; i < (1 << p_t.hash_table_power); i++) {
-			hash_table[i] = nullptr;
+		uint32_t pos = 0;
+		bool exists = _lookup_pos(p_key, pos);
 
 
-			const Element *e = p_t.hash_table[i];
-
-			while (e) {
-				Element *le = memnew(Element(*e)); /* local element */
+		if (exists) {
+			elements[pos]->data.value = p_value;
+			return elements[pos];
+		} else {
+			if (num_elements + 1 > MAX_OCCUPANCY * capacity) {
+				ERR_FAIL_COND_V_MSG(capacity_index + 1 == HASH_TABLE_SIZE_MAX, nullptr, "Hash table maximum capacity reached, aborting insertion.");
+				_resize_and_rehash(capacity_index + 1);
+			}
 
 
-				/* add to list and reassign pointers */
-				le->next = hash_table[i];
-				hash_table[i] = le;
+			HashMapElement<TKey, TValue> *elem = element_alloc.new_allocation(HashMapElement<TKey, TValue>(p_key, p_value));
 
 
-				e = e->next;
+			if (tail_element == nullptr) {
+				head_element = elem;
+				tail_element = elem;
+			} else if (p_front_insert) {
+				head_element->prev = elem;
+				elem->next = head_element;
+				head_element = elem;
+			} else {
+				tail_element->next = elem;
+				elem->prev = tail_element;
+				tail_element = elem;
 			}
 			}
+
+			uint32_t hash = _hash(p_key);
+			_insert_with_hash(hash, elem);
+			return elem;
 		}
 		}
 	}
 	}
 
 
 public:
 public:
-	Element *set(const TKey &p_key, const TData &p_data) {
-		return set(Pair(p_key, p_data));
-	}
+	_FORCE_INLINE_ uint32_t get_capacity() const { return hash_table_size_primes[capacity_index]; }
+	_FORCE_INLINE_ uint32_t size() const { return num_elements; }
 
 
-	Element *set(const Pair &p_pair) {
-		Element *e = nullptr;
-		if (!hash_table) {
-			make_hash_table(); // if no table, make one
-		} else {
-			e = const_cast<Element *>(get_element(p_pair.key));
-		}
+	/* Standard Godot Container API */
 
 
-		/* if we made it up to here, the pair doesn't exist, create and assign */
+	bool is_empty() const {
+		return num_elements == 0;
+	}
 
 
-		if (!e) {
-			e = create_element(p_pair.key);
-			if (!e) {
-				return nullptr;
-			}
-			check_hash_table(); // perform mantenience routine
+	void clear() {
+		if (elements == nullptr) {
+			return;
 		}
 		}
+		uint32_t capacity = hash_table_size_primes[capacity_index];
+		for (uint32_t i = 0; i < capacity; i++) {
+			if (hashes[i] == EMPTY_HASH) {
+				continue;
+			}
 
 
-		e->pair.data = p_pair.data;
-		return e;
-	}
+			hashes[i] = EMPTY_HASH;
+			element_alloc.delete_allocation(elements[i]);
+			elements[i] = nullptr;
+		}
 
 
-	bool has(const TKey &p_key) const {
-		return getptr(p_key) != nullptr;
+		tail_element = nullptr;
+		head_element = nullptr;
+		num_elements = 0;
 	}
 	}
 
 
-	/**
-	 * Get a key from data, return a const reference.
-	 * WARNING: this doesn't check errors, use either getptr and check nullptr, or check
-	 * first with has(key)
-	 */
-
-	const TData &get(const TKey &p_key) const {
-		const TData *res = getptr(p_key);
-		CRASH_COND_MSG(!res, "Map key not found.");
-		return *res;
+	TValue &get(const TKey &p_key) {
+		uint32_t pos = 0;
+		bool exists = _lookup_pos(p_key, pos);
+		CRASH_COND_MSG(!exists, "HashMap key not found.");
+		return elements[pos]->data.value;
 	}
 	}
 
 
-	TData &get(const TKey &p_key) {
-		TData *res = getptr(p_key);
-		CRASH_COND_MSG(!res, "Map key not found.");
-		return *res;
+	const TValue &get(const TKey &p_key) const {
+		uint32_t pos = 0;
+		bool exists = _lookup_pos(p_key, pos);
+		CRASH_COND_MSG(!exists, "HashMap key not found.");
+		return elements[pos]->data.value;
 	}
 	}
 
 
-	/**
-	 * Same as get, except it can return nullptr when item was not found.
-	 * This is mainly used for speed purposes.
-	 */
+	const TValue *getptr(const TKey &p_key) const {
+		uint32_t pos = 0;
+		bool exists = _lookup_pos(p_key, pos);
 
 
-	_FORCE_INLINE_ TData *getptr(const TKey &p_key) {
-		if (unlikely(!hash_table)) {
-			return nullptr;
+		if (exists) {
+			return &elements[pos]->data.value;
 		}
 		}
+		return nullptr;
+	}
 
 
-		Element *e = const_cast<Element *>(get_element(p_key));
+	TValue *getptr(const TKey &p_key) {
+		uint32_t pos = 0;
+		bool exists = _lookup_pos(p_key, pos);
 
 
-		if (e) {
-			return &e->pair.data;
+		if (exists) {
+			return &elements[pos]->data.value;
 		}
 		}
-
 		return nullptr;
 		return nullptr;
 	}
 	}
 
 
-	_FORCE_INLINE_ const TData *getptr(const TKey &p_key) const {
-		if (unlikely(!hash_table)) {
-			return nullptr;
-		}
+	_FORCE_INLINE_ bool has(const TKey &p_key) const {
+		uint32_t _pos = 0;
+		return _lookup_pos(p_key, _pos);
+	}
 
 
-		const Element *e = const_cast<Element *>(get_element(p_key));
+	bool erase(const TKey &p_key) {
+		uint32_t pos = 0;
+		bool exists = _lookup_pos(p_key, pos);
 
 
-		if (e) {
-			return &e->pair.data;
+		if (!exists) {
+			return false;
 		}
 		}
 
 
-		return nullptr;
-	}
+		uint32_t capacity = hash_table_size_primes[capacity_index];
+		uint32_t next_pos = (pos + 1) % capacity;
+		while (hashes[next_pos] != EMPTY_HASH && _get_probe_length(next_pos, hashes[next_pos], capacity) != 0) {
+			SWAP(hashes[next_pos], hashes[pos]);
+			SWAP(elements[next_pos], elements[pos]);
+			pos = next_pos;
+			next_pos = (pos + 1) % capacity;
+		}
 
 
-	/**
-	 * Same as get, except it can return nullptr when item was not found.
-	 * This version is custom, will take a hash and a custom key (that should support operator==()
-	 */
+		hashes[pos] = EMPTY_HASH;
 
 
-	template <class C>
-	_FORCE_INLINE_ TData *custom_getptr(C p_custom_key, uint32_t p_custom_hash) {
-		if (unlikely(!hash_table)) {
-			return nullptr;
+		if (head_element == elements[pos]) {
+			head_element = elements[pos]->next;
 		}
 		}
 
 
-		uint32_t hash = p_custom_hash;
-		uint32_t index = hash & ((1 << hash_table_power) - 1);
-
-		Element *e = hash_table[index];
+		if (tail_element == elements[pos]) {
+			tail_element = elements[pos]->prev;
+		}
 
 
-		while (e) {
-			/* checking hash first avoids comparing key, which may take longer */
-			if (e->hash == hash && Comparator::compare(e->pair.key, p_custom_key)) {
-				/* the pair exists in this hashtable, so just update data */
-				return &e->pair.data;
-			}
+		if (elements[pos]->prev) {
+			elements[pos]->prev->next = elements[pos]->next;
+		}
 
 
-			e = e->next;
+		if (elements[pos]->next) {
+			elements[pos]->next->prev = elements[pos]->prev;
 		}
 		}
 
 
-		return nullptr;
+		element_alloc.delete_allocation(elements[pos]);
+		elements[pos] = nullptr;
+
+		num_elements--;
+		return true;
 	}
 	}
 
 
-	template <class C>
-	_FORCE_INLINE_ const TData *custom_getptr(C p_custom_key, uint32_t p_custom_hash) const {
-		if (unlikely(!hash_table)) {
-			return nullptr;
+	// Reserves space for a number of elements, useful to avoid many resizes and rehashes.
+	// If adding a known (possibly large) number of elements at once, must be larger than old capacity.
+	void reserve(uint32_t p_new_capacity) {
+		uint32_t new_index = capacity_index;
+
+		while (hash_table_size_primes[new_index] < p_new_capacity) {
+			ERR_FAIL_COND_MSG(new_index + 1 == (uint32_t)HASH_TABLE_SIZE_MAX, nullptr);
+			new_index++;
 		}
 		}
 
 
-		uint32_t hash = p_custom_hash;
-		uint32_t index = hash & ((1 << hash_table_power) - 1);
+		if (new_index == capacity_index) {
+			return;
+		}
+
+		if (elements == nullptr) {
+			capacity_index = new_index;
+			return; // Unallocated yet.
+		}
+		_resize_and_rehash(new_index);
+	}
 
 
-		const Element *e = hash_table[index];
+	/** Iterator API **/
 
 
-		while (e) {
-			/* checking hash first avoids comparing key, which may take longer */
-			if (e->hash == hash && Comparator::compare(e->pair.key, p_custom_key)) {
-				/* the pair exists in this hashtable, so just update data */
-				return &e->pair.data;
+	struct Iterator {
+		_FORCE_INLINE_ KeyValue<TKey, TValue> &operator*() const {
+			return E->data;
+		}
+		_FORCE_INLINE_ KeyValue<TKey, TValue> *operator->() const { return &E->data; }
+		_FORCE_INLINE_ Iterator &operator++() {
+			if (E) {
+				E = E->next;
 			}
 			}
-
-			e = e->next;
+			return *this;
+		}
+		_FORCE_INLINE_ Iterator &operator--() {
+			if (E) {
+				E = E->prev;
+			}
+			return *this;
 		}
 		}
 
 
-		return nullptr;
-	}
+		_FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; }
+		_FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; }
 
 
-	/**
-	 * Erase an item, return true if erasing was successful
-	 */
+		_FORCE_INLINE_ operator bool() const {
+			return E != nullptr;
+		}
 
 
-	bool erase(const TKey &p_key) {
-		if (unlikely(!hash_table)) {
-			return false;
+		_FORCE_INLINE_ Iterator(HashMapElement<TKey, TValue> *p_E) { E = p_E; }
+		_FORCE_INLINE_ Iterator() {}
+		_FORCE_INLINE_ Iterator(const Iterator &p_it) { E = p_it.E; }
+		_FORCE_INLINE_ void operator=(const Iterator &p_it) {
+			E = p_it.E;
 		}
 		}
 
 
-		uint32_t hash = Hasher::hash(p_key);
-		uint32_t index = hash & ((1 << hash_table_power) - 1);
-
-		Element *e = hash_table[index];
-		Element *p = nullptr;
-		while (e) {
-			/* checking hash first avoids comparing key, which may take longer */
-			if (e->hash == hash && Comparator::compare(e->pair.key, p_key)) {
-				if (p) {
-					p->next = e->next;
-				} else {
-					//begin of list
-					hash_table[index] = e->next;
-				}
-
-				memdelete(e);
-				elements--;
-
-				if (elements == 0) {
-					erase_hash_table();
-				} else {
-					check_hash_table();
-				}
-				return true;
+	private:
+		HashMapElement<TKey, TValue> *E = nullptr;
+	};
+
+	struct ConstIterator {
+		_FORCE_INLINE_ const KeyValue<TKey, TValue> &operator*() const {
+			return E->data;
+		}
+		_FORCE_INLINE_ const KeyValue<TKey, TValue> *operator->() const { return &E->data; }
+		_FORCE_INLINE_ ConstIterator &operator++() {
+			if (E) {
+				E = E->next;
+			}
+			return *this;
+		}
+		_FORCE_INLINE_ ConstIterator &operator--() {
+			if (E) {
+				E = E->prev;
 			}
 			}
+			return *this;
+		}
+
+		_FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return E == b.E; }
+		_FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return E != b.E; }
 
 
-			p = e;
-			e = e->next;
+		_FORCE_INLINE_ operator bool() const {
+			return E != nullptr;
 		}
 		}
 
 
-		return false;
-	}
+		_FORCE_INLINE_ ConstIterator(const HashMapElement<TKey, TValue> *p_E) { E = p_E; }
+		_FORCE_INLINE_ ConstIterator() {}
+		_FORCE_INLINE_ ConstIterator(const ConstIterator &p_it) { E = p_it.E; }
+		_FORCE_INLINE_ void operator=(const ConstIterator &p_it) {
+			E = p_it.E;
+		}
 
 
-	inline const TData &operator[](const TKey &p_key) const { //constref
+	private:
+		const HashMapElement<TKey, TValue> *E = nullptr;
+	};
 
 
-		return get(p_key);
+	_FORCE_INLINE_ Iterator begin() {
+		return Iterator(head_element);
+	}
+	_FORCE_INLINE_ Iterator end() {
+		return Iterator(nullptr);
+	}
+	_FORCE_INLINE_ Iterator last() {
+		return Iterator(tail_element);
 	}
 	}
-	inline TData &operator[](const TKey &p_key) { //assignment
 
 
-		Element *e = nullptr;
-		if (!hash_table) {
-			make_hash_table(); // if no table, make one
-		} else {
-			e = const_cast<Element *>(get_element(p_key));
+	_FORCE_INLINE_ Iterator find(const TKey &p_key) {
+		uint32_t pos = 0;
+		bool exists = _lookup_pos(p_key, pos);
+		if (!exists) {
+			return end();
 		}
 		}
+		return Iterator(elements[pos]);
+	}
 
 
-		/* if we made it up to here, the pair doesn't exist, create */
-		if (!e) {
-			e = create_element(p_key);
-			CRASH_COND(!e);
-			check_hash_table(); // perform mantenience routine
+	_FORCE_INLINE_ void remove(const Iterator &p_iter) {
+		if (p_iter) {
+			erase(p_iter->key);
 		}
 		}
+	}
 
 
-		return e->pair.data;
+	_FORCE_INLINE_ ConstIterator begin() const {
+		return ConstIterator(head_element);
+	}
+	_FORCE_INLINE_ ConstIterator end() const {
+		return ConstIterator(nullptr);
+	}
+	_FORCE_INLINE_ ConstIterator last() const {
+		return ConstIterator(tail_element);
 	}
 	}
 
 
-	/**
-	 * Get the next key to p_key, and the first key if p_key is null.
-	 * Returns a pointer to the next key if found, nullptr otherwise.
-	 * Adding/Removing elements while iterating will, of course, have unexpected results, don't do it.
-	 *
-	 * Example:
-	 *
-	 * 	const TKey *k=nullptr;
-	 *
-	 * 	while( (k=table.next(k)) ) {
-	 *
-	 * 		print( *k );
-	 * 	}
-	 *
-	 */
-	const TKey *next(const TKey *p_key) const {
-		if (unlikely(!hash_table)) {
-			return nullptr;
+	_FORCE_INLINE_ ConstIterator find(const TKey &p_key) const {
+		uint32_t pos = 0;
+		bool exists = _lookup_pos(p_key, pos);
+		if (!exists) {
+			return end();
 		}
 		}
+		return ConstIterator(elements[pos]);
+	}
 
 
-		if (!p_key) { /* get the first key */
-
-			for (int i = 0; i < (1 << hash_table_power); i++) {
-				if (hash_table[i]) {
-					return &hash_table[i]->pair.key;
-				}
-			}
-
-		} else { /* get the next key */
+	/* Indexing */
 
 
-			const Element *e = get_element(*p_key);
-			ERR_FAIL_COND_V_MSG(!e, nullptr, "Invalid key supplied.");
-			if (e->next) {
-				/* if there is a "next" in the list, return that */
-				return &e->next->pair.key;
-			} else {
-				/* go to next elements */
-				uint32_t index = e->hash & ((1 << hash_table_power) - 1);
-				index++;
-				for (int i = index; i < (1 << hash_table_power); i++) {
-					if (hash_table[i]) {
-						return &hash_table[i]->pair.key;
-					}
-				}
-			}
+	const TValue &operator[](const TKey &p_key) const {
+		uint32_t pos = 0;
+		bool exists = _lookup_pos(p_key, pos);
+		CRASH_COND(!exists);
+		return elements[pos]->data.value;
+	}
 
 
-			/* nothing found, was at end */
+	TValue &operator[](const TKey &p_key) {
+		uint32_t pos = 0;
+		bool exists = _lookup_pos(p_key, pos);
+		if (!exists) {
+			return _insert(p_key, TValue())->data.value;
+		} else {
+			return elements[pos]->data.value;
 		}
 		}
-
-		return nullptr; /* nothing found */
 	}
 	}
 
 
-	inline unsigned int size() const {
-		return elements;
-	}
+	/* Insert */
 
 
-	inline bool is_empty() const {
-		return elements == 0;
+	Iterator insert(const TKey &p_key, const TValue &p_value, bool p_front_insert = false) {
+		return Iterator(_insert(p_key, p_value, p_front_insert));
 	}
 	}
 
 
-	void clear() {
-		/* clean up */
-		if (hash_table) {
-			for (int i = 0; i < (1 << hash_table_power); i++) {
-				while (hash_table[i]) {
-					Element *e = hash_table[i];
-					hash_table[i] = e->next;
-					memdelete(e);
-				}
-			}
+	/* Constructors */
 
 
-			memdelete_arr(hash_table);
+	HashMap(const HashMap &p_other) {
+		reserve(hash_table_size_primes[p_other.capacity_index]);
+
+		if (p_other.num_elements == 0) {
+			return;
 		}
 		}
 
 
-		hash_table = nullptr;
-		hash_table_power = 0;
-		elements = 0;
+		for (const KeyValue<TKey, TValue> &E : p_other) {
+			insert(E.key, E.value);
+		}
 	}
 	}
 
 
-	void operator=(const HashMap &p_table) {
-		copy_from(p_table);
-	}
+	void operator=(const HashMap &p_other) {
+		if (this == &p_other) {
+			return; // Ignore self assignment.
+		}
+		if (num_elements != 0) {
+			clear();
+		}
 
 
-	void get_key_list(List<TKey> *r_keys) const {
-		if (unlikely(!hash_table)) {
-			return;
+		reserve(hash_table_size_primes[p_other.capacity_index]);
+
+		if (p_other.elements == nullptr) {
+			return; // Nothing to copy.
 		}
 		}
-		for (int i = 0; i < (1 << hash_table_power); i++) {
-			Element *e = hash_table[i];
-			while (e) {
-				r_keys->push_back(e->pair.key);
-				e = e->next;
-			}
+
+		for (const KeyValue<TKey, TValue> &E : p_other) {
+			insert(E.key, E.value);
 		}
 		}
 	}
 	}
 
 
-	HashMap() {}
+	HashMap(uint32_t p_initial_capacity) {
+		// Capacity can't be 0.
+		capacity_index = 0;
+		reserve(p_initial_capacity);
+	}
+	HashMap() {
+		capacity_index = MIN_CAPACITY_INDEX;
+	}
 
 
-	HashMap(const HashMap &p_table) {
-		copy_from(p_table);
+	uint32_t debug_get_hash(uint32_t p_index) {
+		if (num_elements == 0) {
+			return 0;
+		}
+		ERR_FAIL_INDEX_V(p_index, get_capacity(), 0);
+		return hashes[p_index];
+	}
+	Iterator debug_get_element(uint32_t p_index) {
+		if (num_elements == 0) {
+			return Iterator();
+		}
+		ERR_FAIL_INDEX_V(p_index, get_capacity(), Iterator());
+		return Iterator(elements[p_index]);
 	}
 	}
 
 
 	~HashMap() {
 	~HashMap() {
 		clear();
 		clear();
+
+		if (elements != nullptr) {
+			Memory::free_static(elements);
+			Memory::free_static(hashes);
+		}
 	}
 	}
 };
 };
 
 

+ 85 - 0
core/templates/hashfuncs.h

@@ -31,14 +31,22 @@
 #ifndef HASHFUNCS_H
 #ifndef HASHFUNCS_H
 #define HASHFUNCS_H
 #define HASHFUNCS_H
 
 
+#include "core/math/aabb.h"
 #include "core/math/math_defs.h"
 #include "core/math/math_defs.h"
 #include "core/math/math_funcs.h"
 #include "core/math/math_funcs.h"
+#include "core/math/rect2.h"
+#include "core/math/rect2i.h"
+#include "core/math/vector2.h"
+#include "core/math/vector2i.h"
+#include "core/math/vector3.h"
+#include "core/math/vector3i.h"
 #include "core/object/object_id.h"
 #include "core/object/object_id.h"
 #include "core/string/node_path.h"
 #include "core/string/node_path.h"
 #include "core/string/string_name.h"
 #include "core/string/string_name.h"
 #include "core/string/ustring.h"
 #include "core/string/ustring.h"
 #include "core/templates/rid.h"
 #include "core/templates/rid.h"
 #include "core/typedefs.h"
 #include "core/typedefs.h"
+
 /**
 /**
  * Hashing functions
  * Hashing functions
  */
  */
@@ -178,6 +186,49 @@ struct HashMapHasherDefault {
 	static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); }
 	static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); }
 	static _FORCE_INLINE_ uint32_t hash(const NodePath &p_path) { return p_path.hash(); }
 	static _FORCE_INLINE_ uint32_t hash(const NodePath &p_path) { return p_path.hash(); }
 
 
+	static _FORCE_INLINE_ uint32_t hash(const Vector2i &p_vec) {
+		uint32_t h = hash_djb2_one_32(p_vec.x);
+		return hash_djb2_one_32(p_vec.y, h);
+	}
+	static _FORCE_INLINE_ uint32_t hash(const Vector3i &p_vec) {
+		uint32_t h = hash_djb2_one_32(p_vec.x);
+		h = hash_djb2_one_32(p_vec.y, h);
+		return hash_djb2_one_32(p_vec.z, h);
+	}
+
+	static _FORCE_INLINE_ uint32_t hash(const Vector2 &p_vec) {
+		uint32_t h = hash_djb2_one_float(p_vec.x);
+		return hash_djb2_one_float(p_vec.y, h);
+	}
+	static _FORCE_INLINE_ uint32_t hash(const Vector3 &p_vec) {
+		uint32_t h = hash_djb2_one_float(p_vec.x);
+		h = hash_djb2_one_float(p_vec.y, h);
+		return hash_djb2_one_float(p_vec.z, h);
+	}
+
+	static _FORCE_INLINE_ uint32_t hash(const Rect2i &p_rect) {
+		uint32_t h = hash_djb2_one_32(p_rect.position.x);
+		h = hash_djb2_one_32(p_rect.position.y, h);
+		h = hash_djb2_one_32(p_rect.size.x, h);
+		return hash_djb2_one_32(p_rect.size.y, h);
+	}
+
+	static _FORCE_INLINE_ uint32_t hash(const Rect2 &p_rect) {
+		uint32_t h = hash_djb2_one_float(p_rect.position.x);
+		h = hash_djb2_one_float(p_rect.position.y, h);
+		h = hash_djb2_one_float(p_rect.size.x, h);
+		return hash_djb2_one_float(p_rect.size.y, h);
+	}
+
+	static _FORCE_INLINE_ uint32_t hash(const AABB &p_aabb) {
+		uint32_t h = hash_djb2_one_float(p_aabb.position.x);
+		h = hash_djb2_one_float(p_aabb.position.y, h);
+		h = hash_djb2_one_float(p_aabb.position.z, h);
+		h = hash_djb2_one_float(p_aabb.size.x, h);
+		h = hash_djb2_one_float(p_aabb.size.y, h);
+		return hash_djb2_one_float(p_aabb.size.z, h);
+	}
+
 	//static _FORCE_INLINE_ uint32_t hash(const void* p_ptr)  { return uint32_t(uint64_t(p_ptr))*(0x9e3779b1L); }
 	//static _FORCE_INLINE_ uint32_t hash(const void* p_ptr)  { return uint32_t(uint64_t(p_ptr))*(0x9e3779b1L); }
 };
 };
 
 
@@ -196,4 +247,38 @@ struct HashMapComparatorDefault {
 	}
 	}
 };
 };
 
 
+constexpr uint32_t HASH_TABLE_SIZE_MAX = 29;
+
+const uint32_t hash_table_size_primes[HASH_TABLE_SIZE_MAX] = {
+	5,
+	13,
+	23,
+	47,
+	97,
+	193,
+	389,
+	769,
+	1543,
+	3079,
+	6151,
+	12289,
+	24593,
+	49157,
+	98317,
+	196613,
+	393241,
+	786433,
+	1572869,
+	3145739,
+	6291469,
+	12582917,
+	25165843,
+	50331653,
+	100663319,
+	201326611,
+	402653189,
+	805306457,
+	1610612741,
+};
+
 #endif // HASHFUNCS_H
 #endif // HASHFUNCS_H

+ 0 - 301
core/templates/ordered_hash_map.h

@@ -1,301 +0,0 @@
-/*************************************************************************/
-/*  ordered_hash_map.h                                                   */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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.                */
-/*************************************************************************/
-
-#ifndef ORDERED_HASH_MAP_H
-#define ORDERED_HASH_MAP_H
-
-#include "core/templates/hash_map.h"
-#include "core/templates/list.h"
-#include "core/templates/pair.h"
-
-/**
- * A hash map which allows to iterate elements in insertion order.
- * Insertion, lookup, deletion have O(1) complexity.
- * The API aims to be consistent with Map rather than HashMap, because the
- * former is more frequently used and is more coherent with the rest of the
- * codebase.
- * Deletion during iteration is safe and will preserve the order.
- */
-template <class K, class V, class Hasher = HashMapHasherDefault, class Comparator = HashMapComparatorDefault<K>, uint8_t MIN_HASH_TABLE_POWER = 3, uint8_t RELATIONSHIP = 8>
-class OrderedHashMap {
-	typedef List<Pair<const K *, V>> InternalList;
-	typedef HashMap<K, typename InternalList::Element *, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP> InternalMap;
-
-	InternalList list;
-	InternalMap map;
-
-public:
-	class Element {
-		friend class OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>;
-
-		typename InternalList::Element *list_element = nullptr;
-		typename InternalList::Element *prev_element = nullptr;
-		typename InternalList::Element *next_element = nullptr;
-
-		Element(typename InternalList::Element *p_element) {
-			list_element = p_element;
-
-			if (list_element) {
-				next_element = list_element->next();
-				prev_element = list_element->prev();
-			}
-		}
-
-	public:
-		_FORCE_INLINE_ Element() {}
-
-		Element next() const {
-			return Element(next_element);
-		}
-
-		Element prev() const {
-			return Element(prev_element);
-		}
-
-		Element(const Element &other) :
-				list_element(other.list_element),
-				prev_element(other.prev_element),
-				next_element(other.next_element) {
-		}
-
-		void operator=(const Element &other) {
-			list_element = other.list_element;
-			next_element = other.next_element;
-			prev_element = other.prev_element;
-		}
-
-		_FORCE_INLINE_ bool operator==(const Element &p_other) const {
-			return this->list_element == p_other.list_element;
-		}
-		_FORCE_INLINE_ bool operator!=(const Element &p_other) const {
-			return this->list_element != p_other.list_element;
-		}
-
-		operator bool() const {
-			return (list_element != nullptr);
-		}
-
-		const K &key() const {
-			CRASH_COND(!list_element);
-			return *(list_element->get().first);
-		}
-
-		V &value() {
-			CRASH_COND(!list_element);
-			return list_element->get().second;
-		}
-
-		const V &value() const {
-			CRASH_COND(!list_element);
-			return list_element->get().second;
-		}
-
-		V &get() {
-			CRASH_COND(!list_element);
-			return list_element->get().second;
-		}
-
-		const V &get() const {
-			CRASH_COND(!list_element);
-			return list_element->get().second;
-		}
-	};
-
-	class ConstElement {
-		friend class OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>;
-
-		const typename InternalList::Element *list_element = nullptr;
-
-		ConstElement(const typename InternalList::Element *p_element) :
-				list_element(p_element) {
-		}
-
-	public:
-		_FORCE_INLINE_ ConstElement() {}
-
-		ConstElement(const ConstElement &other) :
-				list_element(other.list_element) {
-		}
-
-		void operator=(const ConstElement &other) {
-			list_element = other.list_element;
-		}
-
-		ConstElement next() const {
-			return ConstElement(list_element ? list_element->next() : nullptr);
-		}
-
-		ConstElement prev() const {
-			return ConstElement(list_element ? list_element->prev() : nullptr);
-		}
-
-		_FORCE_INLINE_ bool operator==(const ConstElement &p_other) const {
-			return this->list_element == p_other.list_element;
-		}
-		_FORCE_INLINE_ bool operator!=(const ConstElement &p_other) const {
-			return this->list_element != p_other.list_element;
-		}
-
-		operator bool() const {
-			return (list_element != nullptr);
-		}
-
-		const K &key() const {
-			CRASH_COND(!list_element);
-			return *(list_element->get().first);
-		}
-
-		const V &value() const {
-			CRASH_COND(!list_element);
-			return list_element->get().second;
-		}
-
-		const V &get() const {
-			CRASH_COND(!list_element);
-			return list_element->get().second;
-		}
-	};
-
-	ConstElement find(const K &p_key) const {
-		typename InternalList::Element *const *list_element = map.getptr(p_key);
-		if (list_element) {
-			return ConstElement(*list_element);
-		}
-		return ConstElement(nullptr);
-	}
-
-	Element find(const K &p_key) {
-		typename InternalList::Element **list_element = map.getptr(p_key);
-		if (list_element) {
-			return Element(*list_element);
-		}
-		return Element(nullptr);
-	}
-
-	Element insert(const K &p_key, const V &p_value) {
-		typename InternalList::Element **list_element = map.getptr(p_key);
-		if (list_element) {
-			(*list_element)->get().second = p_value;
-			return Element(*list_element);
-		}
-		// Incorrectly set the first value of the pair with a value that will
-		// be invalid as soon as we leave this function...
-		typename InternalList::Element *new_element = list.push_back(Pair<const K *, V>(&p_key, p_value));
-		// ...this is needed here in case the hashmap recursively reference itself...
-		typename InternalMap::Element *e = map.set(p_key, new_element);
-		// ...now we can set the right value !
-		new_element->get().first = &e->key();
-
-		return Element(new_element);
-	}
-
-	void erase(Element &p_element) {
-		map.erase(p_element.key());
-		list.erase(p_element.list_element);
-		p_element.list_element = nullptr;
-	}
-
-	bool erase(const K &p_key) {
-		typename InternalList::Element **list_element = map.getptr(p_key);
-		if (list_element) {
-			list.erase(*list_element);
-			map.erase(p_key);
-			return true;
-		}
-		return false;
-	}
-
-	inline bool has(const K &p_key) const {
-		return map.has(p_key);
-	}
-
-	const V &operator[](const K &p_key) const {
-		ConstElement e = find(p_key);
-		CRASH_COND(!e);
-		return e.value();
-	}
-
-	V &operator[](const K &p_key) {
-		Element e = find(p_key);
-		if (!e) {
-			// consistent with Map behaviour
-			e = insert(p_key, V());
-		}
-		return e.value();
-	}
-
-	inline Element front() {
-		return Element(list.front());
-	}
-
-	inline Element back() {
-		return Element(list.back());
-	}
-
-	inline ConstElement front() const {
-		return ConstElement(list.front());
-	}
-
-	inline ConstElement back() const {
-		return ConstElement(list.back());
-	}
-
-	inline bool is_empty() const { return list.is_empty(); }
-	inline int size() const { return list.size(); }
-
-	const void *id() const {
-		return list.id();
-	}
-
-	void clear() {
-		map.clear();
-		list.clear();
-	}
-
-private:
-	void _copy_from(const OrderedHashMap &p_map) {
-		for (ConstElement E = p_map.front(); E; E = E.next()) {
-			insert(E.key(), E.value());
-		}
-	}
-
-public:
-	void operator=(const OrderedHashMap &p_map) {
-		_copy_from(p_map);
-	}
-
-	OrderedHashMap(const OrderedHashMap &p_map) {
-		_copy_from(p_map);
-	}
-
-	_FORCE_INLINE_ OrderedHashMap() {}
-};
-
-#endif // ORDERED_HASH_MAP_H

+ 7 - 1
core/templates/paged_allocator.h

@@ -50,6 +50,10 @@ class PagedAllocator {
 	SpinLock spin_lock;
 	SpinLock spin_lock;
 
 
 public:
 public:
+	enum {
+		DEFAULT_PAGE_SIZE = 4096
+	};
+
 	template <class... Args>
 	template <class... Args>
 	T *alloc(const Args &&...p_args) {
 	T *alloc(const Args &&...p_args) {
 		if (thread_safe) {
 		if (thread_safe) {
@@ -121,7 +125,9 @@ public:
 		page_shift = get_shift_from_power_of_2(page_size);
 		page_shift = get_shift_from_power_of_2(page_size);
 	}
 	}
 
 
-	PagedAllocator(uint32_t p_page_size = 4096) { // power of 2 recommended because of alignment with OS page sizes. Even if element is bigger, its still a multiple and get rounded amount of pages
+	// Power of 2 recommended because of alignment with OS page sizes.
+	// Even if element is bigger, it's still a multiple and gets rounded to amount of pages.
+	PagedAllocator(uint32_t p_page_size = DEFAULT_PAGE_SIZE) {
 		configure(p_page_size);
 		configure(p_page_size);
 	}
 	}
 
 

+ 46 - 39
core/variant/dictionary.cpp

@@ -30,7 +30,7 @@
 
 
 #include "dictionary.h"
 #include "dictionary.h"
 
 
-#include "core/templates/ordered_hash_map.h"
+#include "core/templates/hash_map.h"
 #include "core/templates/safe_refcount.h"
 #include "core/templates/safe_refcount.h"
 #include "core/variant/variant.h"
 #include "core/variant/variant.h"
 // required in this order by VariantInternal, do not remove this comment.
 // required in this order by VariantInternal, do not remove this comment.
@@ -41,7 +41,7 @@
 
 
 struct DictionaryPrivate {
 struct DictionaryPrivate {
 	SafeRefCount refcount;
 	SafeRefCount refcount;
-	OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> variant_map;
+	HashMap<Variant, Variant, VariantHasher, VariantComparator> variant_map;
 };
 };
 
 
 void Dictionary::get_key_list(List<Variant> *p_keys) const {
 void Dictionary::get_key_list(List<Variant> *p_keys) const {
@@ -49,16 +49,16 @@ void Dictionary::get_key_list(List<Variant> *p_keys) const {
 		return;
 		return;
 	}
 	}
 
 
-	for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
-		p_keys->push_back(E.key());
+	for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
+		p_keys->push_back(E.key);
 	}
 	}
 }
 }
 
 
 Variant Dictionary::get_key_at_index(int p_index) const {
 Variant Dictionary::get_key_at_index(int p_index) const {
 	int index = 0;
 	int index = 0;
-	for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
+	for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
 		if (index == p_index) {
 		if (index == p_index) {
-			return E.key();
+			return E.key;
 		}
 		}
 		index++;
 		index++;
 	}
 	}
@@ -68,9 +68,9 @@ Variant Dictionary::get_key_at_index(int p_index) const {
 
 
 Variant Dictionary::get_value_at_index(int p_index) const {
 Variant Dictionary::get_value_at_index(int p_index) const {
 	int index = 0;
 	int index = 0;
-	for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
+	for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
 		if (index == p_index) {
 		if (index == p_index) {
-			return E.value();
+			return E.value;
 		}
 		}
 		index++;
 		index++;
 	}
 	}
@@ -97,50 +97,50 @@ const Variant &Dictionary::operator[](const Variant &p_key) const {
 }
 }
 
 
 const Variant *Dictionary::getptr(const Variant &p_key) const {
 const Variant *Dictionary::getptr(const Variant &p_key) const {
-	OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E;
+	HashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstIterator E;
 
 
 	if (p_key.get_type() == Variant::STRING_NAME) {
 	if (p_key.get_type() == Variant::STRING_NAME) {
 		const StringName *sn = VariantInternal::get_string_name(&p_key);
 		const StringName *sn = VariantInternal::get_string_name(&p_key);
-		E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
+		E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
 	} else {
 	} else {
-		E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
+		E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
 	}
 	}
 
 
 	if (!E) {
 	if (!E) {
 		return nullptr;
 		return nullptr;
 	}
 	}
-	return &E.get();
+	return &E->value;
 }
 }
 
 
 Variant *Dictionary::getptr(const Variant &p_key) {
 Variant *Dictionary::getptr(const Variant &p_key) {
-	OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E;
+	HashMap<Variant, Variant, VariantHasher, VariantComparator>::Iterator E;
 
 
 	if (p_key.get_type() == Variant::STRING_NAME) {
 	if (p_key.get_type() == Variant::STRING_NAME) {
 		const StringName *sn = VariantInternal::get_string_name(&p_key);
 		const StringName *sn = VariantInternal::get_string_name(&p_key);
-		E = ((OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
+		E = ((HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
 	} else {
 	} else {
-		E = ((OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
+		E = ((HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
 	}
 	}
 	if (!E) {
 	if (!E) {
 		return nullptr;
 		return nullptr;
 	}
 	}
-	return &E.get();
+	return &E->value;
 }
 }
 
 
 Variant Dictionary::get_valid(const Variant &p_key) const {
 Variant Dictionary::get_valid(const Variant &p_key) const {
-	OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E;
+	HashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstIterator E;
 
 
 	if (p_key.get_type() == Variant::STRING_NAME) {
 	if (p_key.get_type() == Variant::STRING_NAME) {
 		const StringName *sn = VariantInternal::get_string_name(&p_key);
 		const StringName *sn = VariantInternal::get_string_name(&p_key);
-		E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
+		E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(sn->operator String());
 	} else {
 	} else {
-		E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
+		E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key);
 	}
 	}
 
 
 	if (!E) {
 	if (!E) {
 		return Variant();
 		return Variant();
 	}
 	}
-	return E.get();
+	return E->value;
 }
 }
 
 
 Variant Dictionary::get(const Variant &p_key, const Variant &p_default) const {
 Variant Dictionary::get(const Variant &p_key, const Variant &p_default) const {
@@ -210,9 +210,9 @@ bool Dictionary::recursive_equal(const Dictionary &p_dictionary, int recursion_c
 		return true;
 		return true;
 	}
 	}
 	recursion_count++;
 	recursion_count++;
-	for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement this_E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->front(); this_E; this_E = this_E.next()) {
-		OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement other_E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&p_dictionary._p->variant_map)->find(this_E.key());
-		if (!other_E || !this_E.value().hash_compare(other_E.value(), recursion_count)) {
+	for (const KeyValue<Variant, Variant> &this_E : _p->variant_map) {
+		HashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstIterator other_E = ((const HashMap<Variant, Variant, VariantHasher, VariantComparator> *)&p_dictionary._p->variant_map)->find(this_E.key);
+		if (!other_E || !this_E.value.hash_compare(other_E->value, recursion_count)) {
 			return false;
 			return false;
 		}
 		}
 	}
 	}
@@ -261,9 +261,9 @@ uint32_t Dictionary::recursive_hash(int recursion_count) const {
 	uint32_t h = hash_djb2_one_32(Variant::DICTIONARY);
 	uint32_t h = hash_djb2_one_32(Variant::DICTIONARY);
 
 
 	recursion_count++;
 	recursion_count++;
-	for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
-		h = hash_djb2_one_32(E.key().recursive_hash(recursion_count), h);
-		h = hash_djb2_one_32(E.value().recursive_hash(recursion_count), h);
+	for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
+		h = hash_djb2_one_32(E.key.recursive_hash(recursion_count), h);
+		h = hash_djb2_one_32(E.value.recursive_hash(recursion_count), h);
 	}
 	}
 
 
 	return h;
 	return h;
@@ -278,8 +278,8 @@ Array Dictionary::keys() const {
 	varr.resize(size());
 	varr.resize(size());
 
 
 	int i = 0;
 	int i = 0;
-	for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
-		varr[i] = E.key();
+	for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
+		varr[i] = E.key;
 		i++;
 		i++;
 	}
 	}
 
 
@@ -295,8 +295,8 @@ Array Dictionary::values() const {
 	varr.resize(size());
 	varr.resize(size());
 
 
 	int i = 0;
 	int i = 0;
-	for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
-		varr[i] = E.get();
+	for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
+		varr[i] = E.value;
 		i++;
 		i++;
 	}
 	}
 
 
@@ -306,16 +306,23 @@ Array Dictionary::values() const {
 const Variant *Dictionary::next(const Variant *p_key) const {
 const Variant *Dictionary::next(const Variant *p_key) const {
 	if (p_key == nullptr) {
 	if (p_key == nullptr) {
 		// caller wants to get the first element
 		// caller wants to get the first element
-		if (_p->variant_map.front()) {
-			return &_p->variant_map.front().key();
+		if (_p->variant_map.begin()) {
+			return &_p->variant_map.begin()->key;
 		}
 		}
 		return nullptr;
 		return nullptr;
 	}
 	}
-	OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.find(*p_key);
+	HashMap<Variant, Variant, VariantHasher, VariantComparator>::Iterator E = _p->variant_map.find(*p_key);
 
 
-	if (E && E.next()) {
-		return &E.next().key();
+	if (!E) {
+		return nullptr;
+	}
+
+	++E;
+
+	if (E) {
+		return &E->key;
 	}
 	}
+
 	return nullptr;
 	return nullptr;
 }
 }
 
 
@@ -333,12 +340,12 @@ Dictionary Dictionary::recursive_duplicate(bool p_deep, int recursion_count) con
 
 
 	if (p_deep) {
 	if (p_deep) {
 		recursion_count++;
 		recursion_count++;
-		for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
-			n[E.key().recursive_duplicate(true, recursion_count)] = E.value().recursive_duplicate(true, recursion_count);
+		for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
+			n[E.key.recursive_duplicate(true, recursion_count)] = E.value.recursive_duplicate(true, recursion_count);
 		}
 		}
 	} else {
 	} else {
-		for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
-			n[E.key()] = E.value();
+		for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
+			n[E.key] = E.value;
 		}
 		}
 	}
 	}
 
 

+ 0 - 1
doc/classes/DirectionalLight3D.xml

@@ -34,7 +34,6 @@
 		<member name="directional_shadow_split_3" type="float" setter="set_param" getter="get_param" default="0.5">
 		<member name="directional_shadow_split_3" type="float" setter="set_param" getter="get_param" default="0.5">
 			The distance from shadow split 2 to split 3. Relative to [member directional_shadow_max_distance]. Only used when [member directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS].
 			The distance from shadow split 2 to split 3. Relative to [member directional_shadow_max_distance]. Only used when [member directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS].
 		</member>
 		</member>
-		<member name="shadow_bias" type="float" setter="set_param" getter="get_param" overrides="Light3D" default="0.1" />
 		<member name="sky_mode" type="int" setter="set_sky_mode" getter="get_sky_mode" enum="DirectionalLight3D.SkyMode" default="0">
 		<member name="sky_mode" type="int" setter="set_sky_mode" getter="get_sky_mode" enum="DirectionalLight3D.SkyMode" default="0">
 			Set whether this [DirectionalLight3D] is visible in the sky, in the scene, or both in the sky and in the scene. See [enum SkyMode] for options.
 			Set whether this [DirectionalLight3D] is visible in the sky, in the scene, or both in the sky and in the scene. See [enum SkyMode] for options.
 		</member>
 		</member>

+ 1 - 1
doc/classes/Light3D.xml

@@ -80,7 +80,7 @@
 		<member name="light_specular" type="float" setter="set_param" getter="get_param" default="0.5">
 		<member name="light_specular" type="float" setter="set_param" getter="get_param" default="0.5">
 			The intensity of the specular blob in objects affected by the light. At [code]0[/code], the light becomes a pure diffuse light. When not baking emission, this can be used to avoid unrealistic reflections when placing lights above an emissive surface.
 			The intensity of the specular blob in objects affected by the light. At [code]0[/code], the light becomes a pure diffuse light. When not baking emission, this can be used to avoid unrealistic reflections when placing lights above an emissive surface.
 		</member>
 		</member>
-		<member name="shadow_bias" type="float" setter="set_param" getter="get_param" default="0.2">
+		<member name="shadow_bias" type="float" setter="set_param" getter="get_param" default="0.1">
 			Used to adjust shadow appearance. Too small a value results in self-shadowing ("shadow acne"), while too large a value causes shadows to separate from casters ("peter-panning"). Adjust as needed.
 			Used to adjust shadow appearance. Too small a value results in self-shadowing ("shadow acne"), while too large a value causes shadows to separate from casters ("peter-panning"). Adjust as needed.
 		</member>
 		</member>
 		<member name="shadow_blur" type="float" setter="set_param" getter="get_param" default="1.0">
 		<member name="shadow_blur" type="float" setter="set_param" getter="get_param" default="1.0">

+ 1 - 0
doc/classes/OmniLight3D.xml

@@ -19,6 +19,7 @@
 		<member name="omni_shadow_mode" type="int" setter="set_shadow_mode" getter="get_shadow_mode" enum="OmniLight3D.ShadowMode" default="1">
 		<member name="omni_shadow_mode" type="int" setter="set_shadow_mode" getter="get_shadow_mode" enum="OmniLight3D.ShadowMode" default="1">
 			See [enum ShadowMode].
 			See [enum ShadowMode].
 		</member>
 		</member>
+		<member name="shadow_bias" type="float" setter="set_param" getter="get_param" overrides="Light3D" default="0.2" />
 	</members>
 	</members>
 	<constants>
 	<constants>
 		<constant name="SHADOW_DUAL_PARABOLOID" value="0" enum="ShadowMode">
 		<constant name="SHADOW_DUAL_PARABOLOID" value="0" enum="ShadowMode">

+ 2 - 3
drivers/gles3/storage/material_storage.cpp

@@ -2077,10 +2077,9 @@ Vector<StringName> MaterialStorage::global_variable_get_list() const {
 		ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance.");
 		ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance.");
 	}
 	}
 
 
-	const StringName *K = nullptr;
 	Vector<StringName> names;
 	Vector<StringName> names;
-	while ((K = global_variables.variables.next(K))) {
-		names.push_back(*K);
+	for (const KeyValue<StringName, GlobalVariables::Variable> &E : global_variables.variables) {
+		names.push_back(E.key);
 	}
 	}
 	names.sort_custom<StringName::AlphCompare>();
 	names.sort_custom<StringName::AlphCompare>();
 	return names;
 	return names;

+ 46 - 36
editor/debugger/editor_performance_profiler.cpp

@@ -97,9 +97,9 @@ void EditorPerformanceProfiler::_monitor_select() {
 
 
 void EditorPerformanceProfiler::_monitor_draw() {
 void EditorPerformanceProfiler::_monitor_draw() {
 	Vector<StringName> active;
 	Vector<StringName> active;
-	for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) {
-		if (i.value().item->is_checked(0)) {
-			active.push_back(i.key());
+	for (const KeyValue<StringName, Monitor> &E : monitors) {
+		if (E.value.item->is_checked(0)) {
+			active.push_back(E.key);
 		}
 		}
 	}
 	}
 
 
@@ -204,22 +204,22 @@ void EditorPerformanceProfiler::_monitor_draw() {
 
 
 void EditorPerformanceProfiler::_build_monitor_tree() {
 void EditorPerformanceProfiler::_build_monitor_tree() {
 	Set<StringName> monitor_checked;
 	Set<StringName> monitor_checked;
-	for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) {
-		if (i.value().item && i.value().item->is_checked(0)) {
-			monitor_checked.insert(i.key());
+	for (KeyValue<StringName, Monitor> &E : monitors) {
+		if (E.value.item && E.value.item->is_checked(0)) {
+			monitor_checked.insert(E.key);
 		}
 		}
 	}
 	}
 
 
 	base_map.clear();
 	base_map.clear();
 	monitor_tree->get_root()->clear_children();
 	monitor_tree->get_root()->clear_children();
 
 
-	for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) {
-		TreeItem *base = _get_monitor_base(i.value().base);
-		TreeItem *item = _create_monitor_item(i.value().name, base);
-		item->set_checked(0, monitor_checked.has(i.key()));
-		i.value().item = item;
-		if (!i.value().history.is_empty()) {
-			i.value().update_value(i.value().history.front()->get());
+	for (KeyValue<StringName, Monitor> &E : monitors) {
+		TreeItem *base = _get_monitor_base(E.value.base);
+		TreeItem *item = _create_monitor_item(E.value.name, base);
+		item->set_checked(0, monitor_checked.has(E.key));
+		E.value.item = item;
+		if (!E.value.history.is_empty()) {
+			E.value.update_value(E.value.history.front()->get());
 		}
 		}
 	}
 	}
 }
 }
@@ -252,9 +252,9 @@ void EditorPerformanceProfiler::_marker_input(const Ref<InputEvent> &p_event) {
 	Ref<InputEventMouseButton> mb = p_event;
 	Ref<InputEventMouseButton> mb = p_event;
 	if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) {
 	if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) {
 		Vector<StringName> active;
 		Vector<StringName> active;
-		for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) {
-			if (i.value().item->is_checked(0)) {
-				active.push_back(i.key());
+		for (KeyValue<StringName, Monitor> &E : monitors) {
+			if (E.value.item->is_checked(0)) {
+				active.push_back(E.key);
 			}
 			}
 		}
 		}
 		if (active.size() > 0) {
 		if (active.size() > 0) {
@@ -293,12 +293,16 @@ void EditorPerformanceProfiler::_marker_input(const Ref<InputEvent> &p_event) {
 }
 }
 
 
 void EditorPerformanceProfiler::reset() {
 void EditorPerformanceProfiler::reset() {
-	for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) {
-		if (String(i.key()).begins_with("custom:")) {
-			monitors.erase(i);
+	HashMap<StringName, Monitor>::Iterator E = monitors.begin();
+	while (E != monitors.end()) {
+		HashMap<StringName, Monitor>::Iterator N = E;
+		++N;
+		if (String(E->key).begins_with("custom:")) {
+			monitors.remove(E);
 		} else {
 		} else {
-			i.value().reset();
+			E->value.reset();
 		}
 		}
+		E = N;
 	}
 	}
 
 
 	_build_monitor_tree();
 	_build_monitor_tree();
@@ -308,43 +312,49 @@ void EditorPerformanceProfiler::reset() {
 }
 }
 
 
 void EditorPerformanceProfiler::update_monitors(const Vector<StringName> &p_names) {
 void EditorPerformanceProfiler::update_monitors(const Vector<StringName> &p_names) {
-	OrderedHashMap<StringName, int> names;
+	HashMap<StringName, int> names;
 	for (int i = 0; i < p_names.size(); i++) {
 	for (int i = 0; i < p_names.size(); i++) {
 		names.insert("custom:" + p_names[i], Performance::MONITOR_MAX + i);
 		names.insert("custom:" + p_names[i], Performance::MONITOR_MAX + i);
 	}
 	}
 
 
-	for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) {
-		if (String(i.key()).begins_with("custom:")) {
-			if (!names.has(i.key())) {
-				monitors.erase(i);
-			} else {
-				i.value().frame_index = names[i.key()];
-				names.erase(i.key());
+	{
+		HashMap<StringName, Monitor>::Iterator E = monitors.begin();
+		while (E != monitors.end()) {
+			HashMap<StringName, Monitor>::Iterator N = E;
+			++N;
+			if (String(E->key).begins_with("custom:")) {
+				if (!names.has(E->key)) {
+					monitors.remove(E);
+				} else {
+					E->value.frame_index = names[E->key];
+					names.erase(E->key);
+				}
 			}
 			}
+			E = N;
 		}
 		}
 	}
 	}
 
 
-	for (OrderedHashMap<StringName, int>::Element i = names.front(); i; i = i.next()) {
-		String name = String(i.key()).replace_first("custom:", "");
+	for (const KeyValue<StringName, int> &E : names) {
+		String name = String(E.key).replace_first("custom:", "");
 		String base = "Custom";
 		String base = "Custom";
 		if (name.get_slice_count("/") == 2) {
 		if (name.get_slice_count("/") == 2) {
 			base = name.get_slicec('/', 0);
 			base = name.get_slicec('/', 0);
 			name = name.get_slicec('/', 1);
 			name = name.get_slicec('/', 1);
 		}
 		}
-		monitors.insert(i.key(), Monitor(name, base, i.value(), Performance::MONITOR_TYPE_QUANTITY, nullptr));
+		monitors.insert(E.key, Monitor(name, base, E.value, Performance::MONITOR_TYPE_QUANTITY, nullptr));
 	}
 	}
 
 
 	_build_monitor_tree();
 	_build_monitor_tree();
 }
 }
 
 
 void EditorPerformanceProfiler::add_profile_frame(const Vector<float> &p_values) {
 void EditorPerformanceProfiler::add_profile_frame(const Vector<float> &p_values) {
-	for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) {
+	for (KeyValue<StringName, Monitor> &E : monitors) {
 		float data = 0.0f;
 		float data = 0.0f;
-		if (i.value().frame_index >= 0 && i.value().frame_index < p_values.size()) {
-			data = p_values[i.value().frame_index];
+		if (E.value.frame_index >= 0 && E.value.frame_index < p_values.size()) {
+			data = p_values[E.value.frame_index];
 		}
 		}
-		i.value().history.push_front(data);
-		i.value().update_value(data);
+		E.value.history.push_front(data);
+		E.value.update_value(data);
 	}
 	}
 	marker_frame++;
 	marker_frame++;
 	monitor_draw->update();
 	monitor_draw->update();

+ 2 - 2
editor/debugger/editor_performance_profiler.h

@@ -31,8 +31,8 @@
 #ifndef EDITOR_PERFORMANCE_PROFILER_H
 #ifndef EDITOR_PERFORMANCE_PROFILER_H
 #define EDITOR_PERFORMANCE_PROFILER_H
 #define EDITOR_PERFORMANCE_PROFILER_H
 
 
+#include "core/templates/hash_map.h"
 #include "core/templates/map.h"
 #include "core/templates/map.h"
-#include "core/templates/ordered_hash_map.h"
 #include "main/performance.h"
 #include "main/performance.h"
 #include "scene/gui/control.h"
 #include "scene/gui/control.h"
 #include "scene/gui/label.h"
 #include "scene/gui/label.h"
@@ -59,7 +59,7 @@ private:
 		void reset();
 		void reset();
 	};
 	};
 
 
-	OrderedHashMap<StringName, Monitor> monitors;
+	HashMap<StringName, Monitor> monitors;
 
 
 	Map<StringName, TreeItem *> base_map;
 	Map<StringName, TreeItem *> base_map;
 	Tree *monitor_tree = nullptr;
 	Tree *monitor_tree = nullptr;

+ 16 - 20
editor/editor_command_palette.cpp

@@ -57,20 +57,19 @@ float EditorCommandPalette::_score_path(const String &p_search, const String &p_
 }
 }
 
 
 void EditorCommandPalette::_update_command_search(const String &search_text) {
 void EditorCommandPalette::_update_command_search(const String &search_text) {
-	commands.get_key_list(&command_keys);
-	ERR_FAIL_COND(command_keys.is_empty());
+	ERR_FAIL_COND(commands.size() == 0);
 
 
 	Map<String, TreeItem *> sections;
 	Map<String, TreeItem *> sections;
 	TreeItem *first_section = nullptr;
 	TreeItem *first_section = nullptr;
 
 
 	// Filter possible candidates.
 	// Filter possible candidates.
 	Vector<CommandEntry> entries;
 	Vector<CommandEntry> entries;
-	for (int i = 0; i < command_keys.size(); i++) {
+	for (const KeyValue<String, Command> &E : commands) {
 		CommandEntry r;
 		CommandEntry r;
-		r.key_name = command_keys[i];
-		r.display_name = commands[r.key_name].name;
-		r.shortcut_text = commands[r.key_name].shortcut;
-		r.last_used = commands[r.key_name].last_used;
+		r.key_name = E.key;
+		r.display_name = E.value.name;
+		r.shortcut_text = E.value.shortcut;
+		r.last_used = E.value.last_used;
 
 
 		if (search_text.is_subsequence_ofn(r.display_name)) {
 		if (search_text.is_subsequence_ofn(r.display_name)) {
 			if (!search_text.is_empty()) {
 			if (!search_text.is_empty()) {
@@ -180,7 +179,9 @@ void EditorCommandPalette::open_popup() {
 }
 }
 
 
 void EditorCommandPalette::get_actions_list(List<String> *p_list) const {
 void EditorCommandPalette::get_actions_list(List<String> *p_list) const {
-	commands.get_key_list(p_list);
+	for (const KeyValue<String, Command> &E : commands) {
+		p_list->push_back(E.key);
+	}
 }
 }
 
 
 void EditorCommandPalette::remove_command(String p_key_name) {
 void EditorCommandPalette::remove_command(String p_key_name) {
@@ -229,17 +230,14 @@ void EditorCommandPalette::execute_command(String &p_command_key) {
 }
 }
 
 
 void EditorCommandPalette::register_shortcuts_as_command() {
 void EditorCommandPalette::register_shortcuts_as_command() {
-	const String *key = nullptr;
-	key = unregistered_shortcuts.next(key);
-	while (key != nullptr) {
-		String command_name = unregistered_shortcuts[*key].first;
-		Ref<Shortcut> shortcut = unregistered_shortcuts[*key].second;
+	for (const KeyValue<String, Pair<String, Ref<Shortcut>>> &E : unregistered_shortcuts) {
+		String command_name = E.value.first;
+		Ref<Shortcut> shortcut = E.value.second;
 		Ref<InputEventShortcut> ev;
 		Ref<InputEventShortcut> ev;
 		ev.instantiate();
 		ev.instantiate();
 		ev->set_shortcut(shortcut);
 		ev->set_shortcut(shortcut);
 		String shortcut_text = String(shortcut->get_as_text());
 		String shortcut_text = String(shortcut->get_as_text());
-		add_command(command_name, *key, callable_mp(EditorNode::get_singleton()->get_viewport(), &Viewport::push_unhandled_input), varray(ev, false), shortcut_text);
-		key = unregistered_shortcuts.next(key);
+		add_command(command_name, E.key, callable_mp(EditorNode::get_singleton()->get_viewport(), &Viewport::push_unhandled_input), varray(ev, false), shortcut_text);
 	}
 	}
 	unregistered_shortcuts.clear();
 	unregistered_shortcuts.clear();
 
 
@@ -276,12 +274,10 @@ void EditorCommandPalette::_theme_changed() {
 
 
 void EditorCommandPalette::_save_history() const {
 void EditorCommandPalette::_save_history() const {
 	Dictionary command_history;
 	Dictionary command_history;
-	List<String> command_keys;
-	commands.get_key_list(&command_keys);
 
 
-	for (const String &key : command_keys) {
-		if (commands[key].last_used > 0) {
-			command_history[key] = commands[key].last_used;
+	for (const KeyValue<String, Command> &E : commands) {
+		if (E.value.last_used > 0) {
+			command_history[E.key] = E.value.last_used;
 		}
 		}
 	}
 	}
 	EditorSettings::get_singleton()->set_project_metadata("command_palette", "command_history", command_history);
 	EditorSettings::get_singleton()->set_project_metadata("command_palette", "command_history", command_history);

+ 3 - 6
editor/editor_data.cpp

@@ -945,13 +945,10 @@ void EditorData::script_class_set_name(const String &p_path, const StringName &p
 }
 }
 
 
 void EditorData::script_class_save_icon_paths() {
 void EditorData::script_class_save_icon_paths() {
-	List<StringName> keys;
-	_script_class_icon_paths.get_key_list(&keys);
-
 	Dictionary d;
 	Dictionary d;
-	for (const StringName &E : keys) {
-		if (ScriptServer::is_global_class(E)) {
-			d[E] = _script_class_icon_paths[E];
+	for (const KeyValue<StringName, String> &E : _script_class_icon_paths) {
+		if (ScriptServer::is_global_class(E.key)) {
+			d[E.key] = E.value;
 		}
 		}
 	}
 	}
 
 

+ 1 - 1
editor/editor_help_search.h

@@ -31,7 +31,7 @@
 #ifndef EDITOR_HELP_SEARCH_H
 #ifndef EDITOR_HELP_SEARCH_H
 #define EDITOR_HELP_SEARCH_H
 #define EDITOR_HELP_SEARCH_H
 
 
-#include "core/templates/ordered_hash_map.h"
+#include "core/templates/map.h"
 #include "editor/code_editor.h"
 #include "editor/code_editor.h"
 #include "editor/editor_help.h"
 #include "editor/editor_help.h"
 #include "editor/editor_plugin.h"
 #include "editor/editor_plugin.h"

+ 13 - 10
editor/editor_settings.cpp

@@ -141,7 +141,7 @@ bool EditorSettings::_get(const StringName &p_name, Variant &r_ret) const {
 
 
 	if (p_name == "shortcuts") {
 	if (p_name == "shortcuts") {
 		Array save_array;
 		Array save_array;
-		const OrderedHashMap<String, List<Ref<InputEvent>>> &builtin_list = InputMap::get_singleton()->get_builtins();
+		const HashMap<String, List<Ref<InputEvent>>> &builtin_list = InputMap::get_singleton()->get_builtins();
 		for (const KeyValue<String, Ref<Shortcut>> &shortcut_definition : shortcuts) {
 		for (const KeyValue<String, Ref<Shortcut>> &shortcut_definition : shortcuts) {
 			Ref<Shortcut> sc = shortcut_definition.value;
 			Ref<Shortcut> sc = shortcut_definition.value;
 
 
@@ -244,18 +244,17 @@ struct _EVCSort {
 void EditorSettings::_get_property_list(List<PropertyInfo> *p_list) const {
 void EditorSettings::_get_property_list(List<PropertyInfo> *p_list) const {
 	_THREAD_SAFE_METHOD_
 	_THREAD_SAFE_METHOD_
 
 
-	const String *k = nullptr;
 	Set<_EVCSort> vclist;
 	Set<_EVCSort> vclist;
 
 
-	while ((k = props.next(k))) {
-		const VariantContainer *v = props.getptr(*k);
+	for (const KeyValue<String, VariantContainer> &E : props) {
+		const VariantContainer *v = &E.value;
 
 
 		if (v->hide_from_editor) {
 		if (v->hide_from_editor) {
 			continue;
 			continue;
 		}
 		}
 
 
 		_EVCSort vc;
 		_EVCSort vc;
-		vc.name = *k;
+		vc.name = E.key;
 		vc.order = v->order;
 		vc.order = v->order;
 		vc.type = v->variant.get_type();
 		vc.type = v->variant.get_type();
 		vc.save = v->save;
 		vc.save = v->save;
@@ -789,7 +788,11 @@ bool EditorSettings::_save_text_editor_theme(String p_file) {
 	Ref<ConfigFile> cf = memnew(ConfigFile); // hex is better?
 	Ref<ConfigFile> cf = memnew(ConfigFile); // hex is better?
 
 
 	List<String> keys;
 	List<String> keys;
-	props.get_key_list(&keys);
+
+	for (const KeyValue<String, VariantContainer> &E : props) {
+		keys.push_back(E.key);
+	}
+
 	keys.sort();
 	keys.sort();
 
 
 	for (const String &key : keys) {
 	for (const String &key : keys) {
@@ -1421,10 +1424,10 @@ Ref<Shortcut> EditorSettings::get_shortcut(const String &p_name) const {
 
 
 	// If there was no override, check the default builtins to see if it has an InputEvent for the provided name.
 	// If there was no override, check the default builtins to see if it has an InputEvent for the provided name.
 	if (sc.is_null()) {
 	if (sc.is_null()) {
-		const OrderedHashMap<String, List<Ref<InputEvent>>>::ConstElement builtin_default = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied().find(p_name);
+		const HashMap<String, List<Ref<InputEvent>>>::ConstIterator builtin_default = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied().find(p_name);
 		if (builtin_default) {
 		if (builtin_default) {
 			sc.instantiate();
 			sc.instantiate();
-			sc->set_events_list(&builtin_default.get());
+			sc->set_events_list(&builtin_default->value);
 			sc->set_name(InputMap::get_singleton()->get_builtin_display_name(p_name));
 			sc->set_name(InputMap::get_singleton()->get_builtin_display_name(p_name));
 		}
 		}
 	}
 	}
@@ -1562,9 +1565,9 @@ void EditorSettings::set_builtin_action_override(const String &p_name, const Arr
 	// Check if the provided event array is same as built-in. If it is, it does not need to be added to the overrides.
 	// Check if the provided event array is same as built-in. If it is, it does not need to be added to the overrides.
 	// Note that event order must also be the same.
 	// Note that event order must also be the same.
 	bool same_as_builtin = true;
 	bool same_as_builtin = true;
-	OrderedHashMap<String, List<Ref<InputEvent>>>::ConstElement builtin_default = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied().find(p_name);
+	HashMap<String, List<Ref<InputEvent>>>::ConstIterator builtin_default = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied().find(p_name);
 	if (builtin_default) {
 	if (builtin_default) {
-		List<Ref<InputEvent>> builtin_events = builtin_default.get();
+		const List<Ref<InputEvent>> &builtin_events = builtin_default->value;
 
 
 		// In the editor we only care about key events.
 		// In the editor we only care about key events.
 		List<Ref<InputEventKey>> builtin_key_events;
 		List<Ref<InputEventKey>> builtin_key_events;

+ 7 - 8
editor/editor_settings_dialog.cpp

@@ -248,11 +248,11 @@ void EditorSettingsDialog::_update_shortcut_events(const String &p_path, const A
 	undo_redo->commit_action();
 	undo_redo->commit_action();
 }
 }
 
 
-Array EditorSettingsDialog::_event_list_to_array_helper(List<Ref<InputEvent>> &p_events) {
+Array EditorSettingsDialog::_event_list_to_array_helper(const List<Ref<InputEvent>> &p_events) {
 	Array events;
 	Array events;
 
 
 	// Convert the list to an array, and only keep key events as this is for the editor.
 	// Convert the list to an array, and only keep key events as this is for the editor.
-	for (List<Ref<InputEvent>>::Element *E = p_events.front(); E; E = E->next()) {
+	for (const List<Ref<InputEvent>>::Element *E = p_events.front(); E; E = E->next()) {
 		Ref<InputEventKey> k = E->get();
 		Ref<InputEventKey> k = E->get();
 		if (k.is_valid()) {
 		if (k.is_valid()) {
 			events.append(E->get());
 			events.append(E->get());
@@ -374,10 +374,9 @@ void EditorSettingsDialog::_update_shortcuts() {
 	common_section->set_custom_bg_color(1, shortcuts->get_theme_color(SNAME("prop_subsection"), SNAME("Editor")));
 	common_section->set_custom_bg_color(1, shortcuts->get_theme_color(SNAME("prop_subsection"), SNAME("Editor")));
 
 
 	// Get the action map for the editor, and add each item to the "Common" section.
 	// Get the action map for the editor, and add each item to the "Common" section.
-	OrderedHashMap<StringName, InputMap::Action> action_map = InputMap::get_singleton()->get_action_map();
-	for (OrderedHashMap<StringName, InputMap::Action>::Element E = action_map.front(); E; E = E.next()) {
-		String action_name = E.key();
-		InputMap::Action action = E.get();
+	for (const KeyValue<StringName, InputMap::Action> &E : InputMap::get_singleton()->get_action_map()) {
+		const String &action_name = E.key;
+		const InputMap::Action &action = E.value;
 
 
 		Array events; // Need to get the list of events into an array so it can be set as metadata on the item.
 		Array events; // Need to get the list of events into an array so it can be set as metadata on the item.
 		Vector<String> event_strings;
 		Vector<String> event_strings;
@@ -387,10 +386,10 @@ void EditorSettingsDialog::_update_shortcuts() {
 			continue;
 			continue;
 		}
 		}
 
 
-		List<Ref<InputEvent>> all_default_events = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied().find(action_name).value();
+		const List<Ref<InputEvent>> &all_default_events = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied().find(action_name)->value;
 		List<Ref<InputEventKey>> key_default_events;
 		List<Ref<InputEventKey>> key_default_events;
 		// Remove all non-key events from the defaults. Only check keys, since we are in the editor.
 		// Remove all non-key events from the defaults. Only check keys, since we are in the editor.
-		for (List<Ref<InputEvent>>::Element *I = all_default_events.front(); I; I = I->next()) {
+		for (const List<Ref<InputEvent>>::Element *I = all_default_events.front(); I; I = I->next()) {
 			Ref<InputEventKey> k = I->get();
 			Ref<InputEventKey> k = I->get();
 			if (k.is_valid()) {
 			if (k.is_valid()) {
 				key_default_events.push_back(k);
 				key_default_events.push_back(k);

+ 1 - 1
editor/editor_settings_dialog.h

@@ -89,7 +89,7 @@ class EditorSettingsDialog : public AcceptDialog {
 	void _event_config_confirmed();
 	void _event_config_confirmed();
 
 
 	void _create_shortcut_treeitem(TreeItem *p_parent, const String &p_shortcut_identifier, const String &p_display, Array &p_events, bool p_allow_revert, bool p_is_common, bool p_is_collapsed);
 	void _create_shortcut_treeitem(TreeItem *p_parent, const String &p_shortcut_identifier, const String &p_display, Array &p_events, bool p_allow_revert, bool p_is_common, bool p_is_collapsed);
-	Array _event_list_to_array_helper(List<Ref<InputEvent>> &p_events);
+	Array _event_list_to_array_helper(const List<Ref<InputEvent>> &p_events);
 	void _update_builtin_action(const String &p_name, const Array &p_events);
 	void _update_builtin_action(const String &p_name, const Array &p_events);
 	void _update_shortcut_events(const String &p_path, const Array &p_events);
 	void _update_shortcut_events(const String &p_path, const Array &p_events);
 
 

+ 4 - 4
editor/import/resource_importer_scene.cpp

@@ -1737,7 +1737,7 @@ void ResourceImporterScene::_optimize_track_usage(AnimationPlayer *p_player, Ani
 	p_player->get_animation_list(&anims);
 	p_player->get_animation_list(&anims);
 	Node *parent = p_player->get_parent();
 	Node *parent = p_player->get_parent();
 	ERR_FAIL_COND(parent == nullptr);
 	ERR_FAIL_COND(parent == nullptr);
-	OrderedHashMap<NodePath, uint32_t> used_tracks[TRACK_CHANNEL_MAX];
+	HashMap<NodePath, uint32_t> used_tracks[TRACK_CHANNEL_MAX];
 	bool tracks_to_add = false;
 	bool tracks_to_add = false;
 	static const Animation::TrackType track_types[TRACK_CHANNEL_MAX] = { Animation::TYPE_POSITION_3D, Animation::TYPE_ROTATION_3D, Animation::TYPE_SCALE_3D, Animation::TYPE_BLEND_SHAPE };
 	static const Animation::TrackType track_types[TRACK_CHANNEL_MAX] = { Animation::TYPE_POSITION_3D, Animation::TYPE_ROTATION_3D, Animation::TYPE_SCALE_3D, Animation::TYPE_BLEND_SHAPE };
 	for (const StringName &I : anims) {
 	for (const StringName &I : anims) {
@@ -1790,12 +1790,12 @@ void ResourceImporterScene::_optimize_track_usage(AnimationPlayer *p_player, Ani
 				used_tracks[j][path] = pass;
 				used_tracks[j][path] = pass;
 			}
 			}
 
 
-			for (OrderedHashMap<NodePath, uint32_t>::Element J = used_tracks[j].front(); J; J = J.next()) {
-				if (J.get() == pass) {
+			for (const KeyValue<NodePath, uint32_t> &J : used_tracks[j]) {
+				if (J.value == pass) {
 					continue;
 					continue;
 				}
 				}
 
 
-				NodePath path = J.key();
+				NodePath path = J.key;
 				Node *n = parent->get_node(path);
 				Node *n = parent->get_node(path);
 
 
 				if (j == TRACK_CHANNEL_BLEND_SHAPE) {
 				if (j == TRACK_CHANNEL_BLEND_SHAPE) {

+ 1 - 1
editor/plugins/node_3d_editor_gizmos.h

@@ -31,8 +31,8 @@
 #ifndef NODE_3D_EDITOR_GIZMOS_H
 #ifndef NODE_3D_EDITOR_GIZMOS_H
 #define NODE_3D_EDITOR_GIZMOS_H
 #define NODE_3D_EDITOR_GIZMOS_H
 
 
+#include "core/templates/hash_map.h"
 #include "core/templates/local_vector.h"
 #include "core/templates/local_vector.h"
-#include "core/templates/ordered_hash_map.h"
 #include "scene/3d/camera_3d.h"
 #include "scene/3d/camera_3d.h"
 #include "scene/3d/node_3d.h"
 #include "scene/3d/node_3d.h"
 #include "scene/3d/skeleton_3d.h"
 #include "scene/3d/skeleton_3d.h"

+ 3 - 3
editor/plugins/script_editor_plugin.cpp

@@ -119,9 +119,9 @@ void EditorStandardSyntaxHighlighter::_update_cache() {
 	}
 	}
 
 
 	/* Autoloads. */
 	/* Autoloads. */
-	OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
-	for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) {
-		const ProjectSettings::AutoloadInfo &info = E.value();
+	HashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
+	for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : autoloads) {
+		const ProjectSettings::AutoloadInfo &info = E.value;
 		if (info.is_singleton) {
 		if (info.is_singleton) {
 			highlighter->add_keyword_color(info.name, usertype_color);
 			highlighter->add_keyword_color(info.name, usertype_color);
 		}
 		}

+ 55 - 55
editor/plugins/theme_editor_plugin.cpp

@@ -2339,8 +2339,8 @@ void ThemeTypeEditor::_update_type_list_debounced() {
 	update_debounce_timer->start();
 	update_debounce_timer->start();
 }
 }
 
 
-OrderedHashMap<StringName, bool> ThemeTypeEditor::_get_type_items(String p_type_name, void (Theme::*get_list_func)(StringName, List<StringName> *) const, bool include_default) {
-	OrderedHashMap<StringName, bool> items;
+HashMap<StringName, bool> ThemeTypeEditor::_get_type_items(String p_type_name, void (Theme::*get_list_func)(StringName, List<StringName> *) const, bool include_default) {
+	HashMap<StringName, bool> items;
 	List<StringName> names;
 	List<StringName> names;
 
 
 	if (include_default) {
 	if (include_default) {
@@ -2367,12 +2367,12 @@ OrderedHashMap<StringName, bool> ThemeTypeEditor::_get_type_items(String p_type_
 	}
 	}
 
 
 	List<StringName> keys;
 	List<StringName> keys;
-	for (OrderedHashMap<StringName, bool>::Element E = items.front(); E; E = E.next()) {
-		keys.push_back(E.key());
+	for (const KeyValue<StringName, bool> &E : items) {
+		keys.push_back(E.key);
 	}
 	}
 	keys.sort_custom<StringName::AlphCompare>();
 	keys.sort_custom<StringName::AlphCompare>();
 
 
-	OrderedHashMap<StringName, bool> ordered_items;
+	HashMap<StringName, bool> ordered_items;
 	for (const StringName &E : keys) {
 	for (const StringName &E : keys) {
 		ordered_items[E] = items[E];
 		ordered_items[E] = items[E];
 	}
 	}
@@ -2464,18 +2464,18 @@ void ThemeTypeEditor::_update_type_items() {
 			color_items_list->remove_child(node);
 			color_items_list->remove_child(node);
 		}
 		}
 
 
-		OrderedHashMap<StringName, bool> color_items = _get_type_items(edited_type, &Theme::get_color_list, show_default);
-		for (OrderedHashMap<StringName, bool>::Element E = color_items.front(); E; E = E.next()) {
-			HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_COLOR, E.key(), E.get());
+		HashMap<StringName, bool> color_items = _get_type_items(edited_type, &Theme::get_color_list, show_default);
+		for (const KeyValue<StringName, bool> &E : color_items) {
+			HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_COLOR, E.key, E.value);
 			ColorPickerButton *item_editor = memnew(ColorPickerButton);
 			ColorPickerButton *item_editor = memnew(ColorPickerButton);
 			item_editor->set_h_size_flags(SIZE_EXPAND_FILL);
 			item_editor->set_h_size_flags(SIZE_EXPAND_FILL);
 			item_control->add_child(item_editor);
 			item_control->add_child(item_editor);
 
 
-			if (E.get()) {
-				item_editor->set_pick_color(edited_theme->get_color(E.key(), edited_type));
-				item_editor->connect("color_changed", callable_mp(this, &ThemeTypeEditor::_color_item_changed), varray(E.key()));
+			if (E.value) {
+				item_editor->set_pick_color(edited_theme->get_color(E.key, edited_type));
+				item_editor->connect("color_changed", callable_mp(this, &ThemeTypeEditor::_color_item_changed), varray(E.key));
 			} else {
 			} else {
-				item_editor->set_pick_color(Theme::get_default()->get_color(E.key(), edited_type));
+				item_editor->set_pick_color(Theme::get_default()->get_color(E.key, edited_type));
 				item_editor->set_disabled(true);
 				item_editor->set_disabled(true);
 			}
 			}
 
 
@@ -2492,9 +2492,9 @@ void ThemeTypeEditor::_update_type_items() {
 			constant_items_list->remove_child(node);
 			constant_items_list->remove_child(node);
 		}
 		}
 
 
-		OrderedHashMap<StringName, bool> constant_items = _get_type_items(edited_type, &Theme::get_constant_list, show_default);
-		for (OrderedHashMap<StringName, bool>::Element E = constant_items.front(); E; E = E.next()) {
-			HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_CONSTANT, E.key(), E.get());
+		HashMap<StringName, bool> constant_items = _get_type_items(edited_type, &Theme::get_constant_list, show_default);
+		for (const KeyValue<StringName, bool> &E : constant_items) {
+			HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_CONSTANT, E.key, E.value);
 			SpinBox *item_editor = memnew(SpinBox);
 			SpinBox *item_editor = memnew(SpinBox);
 			item_editor->set_h_size_flags(SIZE_EXPAND_FILL);
 			item_editor->set_h_size_flags(SIZE_EXPAND_FILL);
 			item_editor->set_min(-100000);
 			item_editor->set_min(-100000);
@@ -2504,11 +2504,11 @@ void ThemeTypeEditor::_update_type_items() {
 			item_editor->set_allow_greater(true);
 			item_editor->set_allow_greater(true);
 			item_control->add_child(item_editor);
 			item_control->add_child(item_editor);
 
 
-			if (E.get()) {
-				item_editor->set_value(edited_theme->get_constant(E.key(), edited_type));
-				item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_constant_item_changed), varray(E.key()));
+			if (E.value) {
+				item_editor->set_value(edited_theme->get_constant(E.key, edited_type));
+				item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_constant_item_changed), varray(E.key));
 			} else {
 			} else {
-				item_editor->set_value(Theme::get_default()->get_constant(E.key(), edited_type));
+				item_editor->set_value(Theme::get_default()->get_constant(E.key, edited_type));
 				item_editor->set_editable(false);
 				item_editor->set_editable(false);
 			}
 			}
 
 
@@ -2525,25 +2525,25 @@ void ThemeTypeEditor::_update_type_items() {
 			font_items_list->remove_child(node);
 			font_items_list->remove_child(node);
 		}
 		}
 
 
-		OrderedHashMap<StringName, bool> font_items = _get_type_items(edited_type, &Theme::get_font_list, show_default);
-		for (OrderedHashMap<StringName, bool>::Element E = font_items.front(); E; E = E.next()) {
-			HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_FONT, E.key(), E.get());
+		HashMap<StringName, bool> font_items = _get_type_items(edited_type, &Theme::get_font_list, show_default);
+		for (const KeyValue<StringName, bool> &E : font_items) {
+			HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_FONT, E.key, E.value);
 			EditorResourcePicker *item_editor = memnew(EditorResourcePicker);
 			EditorResourcePicker *item_editor = memnew(EditorResourcePicker);
 			item_editor->set_h_size_flags(SIZE_EXPAND_FILL);
 			item_editor->set_h_size_flags(SIZE_EXPAND_FILL);
 			item_editor->set_base_type("Font");
 			item_editor->set_base_type("Font");
 			item_control->add_child(item_editor);
 			item_control->add_child(item_editor);
 
 
-			if (E.get()) {
-				if (edited_theme->has_font(E.key(), edited_type)) {
-					item_editor->set_edited_resource(edited_theme->get_font(E.key(), edited_type));
+			if (E.value) {
+				if (edited_theme->has_font(E.key, edited_type)) {
+					item_editor->set_edited_resource(edited_theme->get_font(E.key, edited_type));
 				} else {
 				} else {
 					item_editor->set_edited_resource(Ref<Resource>());
 					item_editor->set_edited_resource(Ref<Resource>());
 				}
 				}
 				item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item));
 				item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item));
-				item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_font_item_changed), varray(E.key()));
+				item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_font_item_changed), varray(E.key));
 			} else {
 			} else {
-				if (Theme::get_default()->has_font(E.key(), edited_type)) {
-					item_editor->set_edited_resource(Theme::get_default()->get_font(E.key(), edited_type));
+				if (Theme::get_default()->has_font(E.key, edited_type)) {
+					item_editor->set_edited_resource(Theme::get_default()->get_font(E.key, edited_type));
 				} else {
 				} else {
 					item_editor->set_edited_resource(Ref<Resource>());
 					item_editor->set_edited_resource(Ref<Resource>());
 				}
 				}
@@ -2563,9 +2563,9 @@ void ThemeTypeEditor::_update_type_items() {
 			font_size_items_list->remove_child(node);
 			font_size_items_list->remove_child(node);
 		}
 		}
 
 
-		OrderedHashMap<StringName, bool> font_size_items = _get_type_items(edited_type, &Theme::get_font_size_list, show_default);
-		for (OrderedHashMap<StringName, bool>::Element E = font_size_items.front(); E; E = E.next()) {
-			HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_FONT_SIZE, E.key(), E.get());
+		HashMap<StringName, bool> font_size_items = _get_type_items(edited_type, &Theme::get_font_size_list, show_default);
+		for (const KeyValue<StringName, bool> &E : font_size_items) {
+			HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_FONT_SIZE, E.key, E.value);
 			SpinBox *item_editor = memnew(SpinBox);
 			SpinBox *item_editor = memnew(SpinBox);
 			item_editor->set_h_size_flags(SIZE_EXPAND_FILL);
 			item_editor->set_h_size_flags(SIZE_EXPAND_FILL);
 			item_editor->set_min(-100000);
 			item_editor->set_min(-100000);
@@ -2575,11 +2575,11 @@ void ThemeTypeEditor::_update_type_items() {
 			item_editor->set_allow_greater(true);
 			item_editor->set_allow_greater(true);
 			item_control->add_child(item_editor);
 			item_control->add_child(item_editor);
 
 
-			if (E.get()) {
-				item_editor->set_value(edited_theme->get_font_size(E.key(), edited_type));
-				item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_font_size_item_changed), varray(E.key()));
+			if (E.value) {
+				item_editor->set_value(edited_theme->get_font_size(E.key, edited_type));
+				item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_font_size_item_changed), varray(E.key));
 			} else {
 			} else {
-				item_editor->set_value(Theme::get_default()->get_font_size(E.key(), edited_type));
+				item_editor->set_value(Theme::get_default()->get_font_size(E.key, edited_type));
 				item_editor->set_editable(false);
 				item_editor->set_editable(false);
 			}
 			}
 
 
@@ -2596,25 +2596,25 @@ void ThemeTypeEditor::_update_type_items() {
 			icon_items_list->remove_child(node);
 			icon_items_list->remove_child(node);
 		}
 		}
 
 
-		OrderedHashMap<StringName, bool> icon_items = _get_type_items(edited_type, &Theme::get_icon_list, show_default);
-		for (OrderedHashMap<StringName, bool>::Element E = icon_items.front(); E; E = E.next()) {
-			HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_ICON, E.key(), E.get());
+		HashMap<StringName, bool> icon_items = _get_type_items(edited_type, &Theme::get_icon_list, show_default);
+		for (const KeyValue<StringName, bool> &E : icon_items) {
+			HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_ICON, E.key, E.value);
 			EditorResourcePicker *item_editor = memnew(EditorResourcePicker);
 			EditorResourcePicker *item_editor = memnew(EditorResourcePicker);
 			item_editor->set_h_size_flags(SIZE_EXPAND_FILL);
 			item_editor->set_h_size_flags(SIZE_EXPAND_FILL);
 			item_editor->set_base_type("Texture2D");
 			item_editor->set_base_type("Texture2D");
 			item_control->add_child(item_editor);
 			item_control->add_child(item_editor);
 
 
-			if (E.get()) {
-				if (edited_theme->has_icon(E.key(), edited_type)) {
-					item_editor->set_edited_resource(edited_theme->get_icon(E.key(), edited_type));
+			if (E.value) {
+				if (edited_theme->has_icon(E.key, edited_type)) {
+					item_editor->set_edited_resource(edited_theme->get_icon(E.key, edited_type));
 				} else {
 				} else {
 					item_editor->set_edited_resource(Ref<Resource>());
 					item_editor->set_edited_resource(Ref<Resource>());
 				}
 				}
 				item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item));
 				item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item));
-				item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_icon_item_changed), varray(E.key()));
+				item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_icon_item_changed), varray(E.key));
 			} else {
 			} else {
-				if (Theme::get_default()->has_icon(E.key(), edited_type)) {
-					item_editor->set_edited_resource(Theme::get_default()->get_icon(E.key(), edited_type));
+				if (Theme::get_default()->has_icon(E.key, edited_type)) {
+					item_editor->set_edited_resource(Theme::get_default()->get_icon(E.key, edited_type));
 				} else {
 				} else {
 					item_editor->set_edited_resource(Ref<Resource>());
 					item_editor->set_edited_resource(Ref<Resource>());
 				}
 				}
@@ -2664,26 +2664,26 @@ void ThemeTypeEditor::_update_type_items() {
 			stylebox_items_list->add_child(memnew(HSeparator));
 			stylebox_items_list->add_child(memnew(HSeparator));
 		}
 		}
 
 
-		OrderedHashMap<StringName, bool> stylebox_items = _get_type_items(edited_type, &Theme::get_stylebox_list, show_default);
-		for (OrderedHashMap<StringName, bool>::Element E = stylebox_items.front(); E; E = E.next()) {
-			if (leading_stylebox.pinned && leading_stylebox.item_name == E.key()) {
+		HashMap<StringName, bool> stylebox_items = _get_type_items(edited_type, &Theme::get_stylebox_list, show_default);
+		for (const KeyValue<StringName, bool> &E : stylebox_items) {
+			if (leading_stylebox.pinned && leading_stylebox.item_name == E.key) {
 				continue;
 				continue;
 			}
 			}
 
 
-			HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_STYLEBOX, E.key(), E.get());
+			HBoxContainer *item_control = _create_property_control(Theme::DATA_TYPE_STYLEBOX, E.key, E.value);
 			EditorResourcePicker *item_editor = memnew(EditorResourcePicker);
 			EditorResourcePicker *item_editor = memnew(EditorResourcePicker);
 			item_editor->set_h_size_flags(SIZE_EXPAND_FILL);
 			item_editor->set_h_size_flags(SIZE_EXPAND_FILL);
 			item_editor->set_stretch_ratio(1.5);
 			item_editor->set_stretch_ratio(1.5);
 			item_editor->set_base_type("StyleBox");
 			item_editor->set_base_type("StyleBox");
 
 
-			if (E.get()) {
-				if (edited_theme->has_stylebox(E.key(), edited_type)) {
-					item_editor->set_edited_resource(edited_theme->get_stylebox(E.key(), edited_type));
+			if (E.value) {
+				if (edited_theme->has_stylebox(E.key, edited_type)) {
+					item_editor->set_edited_resource(edited_theme->get_stylebox(E.key, edited_type));
 				} else {
 				} else {
 					item_editor->set_edited_resource(Ref<Resource>());
 					item_editor->set_edited_resource(Ref<Resource>());
 				}
 				}
 				item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item));
 				item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item));
-				item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_stylebox_item_changed), varray(E.key()));
+				item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_stylebox_item_changed), varray(E.key));
 
 
 				Button *pin_leader_button = memnew(Button);
 				Button *pin_leader_button = memnew(Button);
 				pin_leader_button->set_flat(true);
 				pin_leader_button->set_flat(true);
@@ -2691,10 +2691,10 @@ void ThemeTypeEditor::_update_type_items() {
 				pin_leader_button->set_icon(get_theme_icon(SNAME("Pin"), SNAME("EditorIcons")));
 				pin_leader_button->set_icon(get_theme_icon(SNAME("Pin"), SNAME("EditorIcons")));
 				pin_leader_button->set_tooltip(TTR("Pin this StyleBox as a main style. Editing its properties will update the same properties in all other StyleBoxes of this type."));
 				pin_leader_button->set_tooltip(TTR("Pin this StyleBox as a main style. Editing its properties will update the same properties in all other StyleBoxes of this type."));
 				item_control->add_child(pin_leader_button);
 				item_control->add_child(pin_leader_button);
-				pin_leader_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_on_pin_leader_button_pressed), varray(item_editor, E.key()));
+				pin_leader_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_on_pin_leader_button_pressed), varray(item_editor, E.key));
 			} else {
 			} else {
-				if (Theme::get_default()->has_stylebox(E.key(), edited_type)) {
-					item_editor->set_edited_resource(Theme::get_default()->get_stylebox(E.key(), edited_type));
+				if (Theme::get_default()->has_stylebox(E.key, edited_type)) {
+					item_editor->set_edited_resource(Theme::get_default()->get_stylebox(E.key, edited_type));
 				} else {
 				} else {
 					item_editor->set_edited_resource(Ref<Resource>());
 					item_editor->set_edited_resource(Ref<Resource>());
 				}
 				}

+ 1 - 1
editor/plugins/theme_editor_plugin.h

@@ -363,7 +363,7 @@ class ThemeTypeEditor : public MarginContainer {
 	VBoxContainer *_create_item_list(Theme::DataType p_data_type);
 	VBoxContainer *_create_item_list(Theme::DataType p_data_type);
 	void _update_type_list();
 	void _update_type_list();
 	void _update_type_list_debounced();
 	void _update_type_list_debounced();
-	OrderedHashMap<StringName, bool> _get_type_items(String p_type_name, void (Theme::*get_list_func)(StringName, List<StringName> *) const, bool include_default);
+	HashMap<StringName, bool> _get_type_items(String p_type_name, void (Theme::*get_list_func)(StringName, List<StringName> *) const, bool include_default);
 	HBoxContainer *_create_property_control(Theme::DataType p_data_type, String p_item_name, bool p_editable);
 	HBoxContainer *_create_property_control(Theme::DataType p_data_type, String p_item_name, bool p_editable);
 	void _add_focusable(Control *p_control);
 	void _add_focusable(Control *p_control);
 	void _update_type_items();
 	void _update_type_items();

+ 4 - 4
editor/pot_generator.cpp

@@ -39,7 +39,7 @@ POTGenerator *POTGenerator::singleton = nullptr;
 
 
 #ifdef DEBUG_POT
 #ifdef DEBUG_POT
 void POTGenerator::_print_all_translation_strings() {
 void POTGenerator::_print_all_translation_strings() {
-	for (OrderedHashMap<String, Vector<POTGenerator::MsgidData>>::Element E = all_translation_strings.front(); E; E = E.next()) {
+	for (HashMap<String, Vector<POTGenerator::MsgidData>>::Element E = all_translation_strings.front(); E; E = E.next()) {
 		Vector<MsgidData> v_md = all_translation_strings[E.key()];
 		Vector<MsgidData> v_md = all_translation_strings[E.key()];
 		for (int i = 0; i < v_md.size(); i++) {
 		for (int i = 0; i < v_md.size(); i++) {
 			print_line("++++++");
 			print_line("++++++");
@@ -121,9 +121,9 @@ void POTGenerator::_write_to_pot(const String &p_file) {
 
 
 	file->store_string(header);
 	file->store_string(header);
 
 
-	for (OrderedHashMap<String, Vector<MsgidData>>::Element E_pair = all_translation_strings.front(); E_pair; E_pair = E_pair.next()) {
-		String msgid = E_pair.key();
-		Vector<MsgidData> v_msgid_data = E_pair.value();
+	for (const KeyValue<String, Vector<MsgidData>> &E_pair : all_translation_strings) {
+		String msgid = E_pair.key;
+		const Vector<MsgidData> &v_msgid_data = E_pair.value;
 		for (int i = 0; i < v_msgid_data.size(); i++) {
 		for (int i = 0; i < v_msgid_data.size(); i++) {
 			String context = v_msgid_data[i].ctx;
 			String context = v_msgid_data[i].ctx;
 			String plural = v_msgid_data[i].plural;
 			String plural = v_msgid_data[i].plural;

+ 2 - 2
editor/pot_generator.h

@@ -32,7 +32,7 @@
 #define POT_GENERATOR_H
 #define POT_GENERATOR_H
 
 
 #include "core/io/file_access.h"
 #include "core/io/file_access.h"
-#include "core/templates/ordered_hash_map.h"
+#include "core/templates/hash_map.h"
 #include "core/templates/set.h"
 #include "core/templates/set.h"
 
 
 //#define DEBUG_POT
 //#define DEBUG_POT
@@ -46,7 +46,7 @@ class POTGenerator {
 		Set<String> locations;
 		Set<String> locations;
 	};
 	};
 	// Store msgid as key and the additional data around the msgid - if it's under a context, has plurals and its file locations.
 	// Store msgid as key and the additional data around the msgid - if it's under a context, has plurals and its file locations.
-	OrderedHashMap<String, Vector<MsgidData>> all_translation_strings;
+	HashMap<String, Vector<MsgidData>> all_translation_strings;
 
 
 	void _write_to_pot(const String &p_file);
 	void _write_to_pot(const String &p_file);
 	void _write_msgid(Ref<FileAccess> r_file, const String &p_id, bool p_plural);
 	void _write_msgid(Ref<FileAccess> r_file, const String &p_id, bool p_plural);

+ 4 - 4
editor/project_settings_editor.cpp

@@ -420,7 +420,7 @@ void ProjectSettingsEditor::_action_reordered(const String &p_action_name, const
 	Variant target_value = ps->get(target_name);
 	Variant target_value = ps->get(target_name);
 
 
 	List<PropertyInfo> props;
 	List<PropertyInfo> props;
-	OrderedHashMap<String, Variant> action_values;
+	HashMap<String, Variant> action_values;
 	ProjectSettings::get_singleton()->get_property_list(&props);
 	ProjectSettings::get_singleton()->get_property_list(&props);
 
 
 	undo_redo->create_action(TTR("Update Input Action Order"));
 	undo_redo->create_action(TTR("Update Input Action Order"));
@@ -437,9 +437,9 @@ void ProjectSettingsEditor::_action_reordered(const String &p_action_name, const
 		undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", prop.name);
 		undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", prop.name);
 	}
 	}
 
 
-	for (OrderedHashMap<String, Variant>::Element E = action_values.front(); E; E = E.next()) {
-		String name = E.key();
-		Variant value = E.get();
+	for (const KeyValue<String, Variant> &E : action_values) {
+		String name = E.key;
+		const Variant &value = E.value;
 
 
 		if (name == target_name) {
 		if (name == target_name) {
 			if (p_before) {
 			if (p_before) {

+ 5 - 5
main/main.cpp

@@ -2329,11 +2329,11 @@ bool Main::start() {
 		if (!project_manager && !editor) { // game
 		if (!project_manager && !editor) { // game
 			if (!game_path.is_empty() || !script.is_empty()) {
 			if (!game_path.is_empty() || !script.is_empty()) {
 				//autoload
 				//autoload
-				OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
+				HashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
 
 
 				//first pass, add the constants so they exist before any script is loaded
 				//first pass, add the constants so they exist before any script is loaded
-				for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) {
-					const ProjectSettings::AutoloadInfo &info = E.get();
+				for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : autoloads) {
+					const ProjectSettings::AutoloadInfo &info = E.value;
 
 
 					if (info.is_singleton) {
 					if (info.is_singleton) {
 						for (int i = 0; i < ScriptServer::get_language_count(); i++) {
 						for (int i = 0; i < ScriptServer::get_language_count(); i++) {
@@ -2344,8 +2344,8 @@ bool Main::start() {
 
 
 				//second pass, load into global constants
 				//second pass, load into global constants
 				List<Node *> to_add;
 				List<Node *> to_add;
-				for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) {
-					const ProjectSettings::AutoloadInfo &info = E.get();
+				for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : autoloads) {
+					const ProjectSettings::AutoloadInfo &info = E.value;
 
 
 					Ref<Resource> res = ResourceLoader::load(info.path);
 					Ref<Resource> res = ResourceLoader::load(info.path);
 					ERR_CONTINUE_MSG(res.is_null(), "Can't autoload: " + info.path);
 					ERR_CONTINUE_MSG(res.is_null(), "Can't autoload: " + info.path);

+ 2 - 2
main/performance.cpp

@@ -247,8 +247,8 @@ Array Performance::get_custom_monitor_names() {
 	Array return_array;
 	Array return_array;
 	return_array.resize(_monitor_map.size());
 	return_array.resize(_monitor_map.size());
 	int index = 0;
 	int index = 0;
-	for (OrderedHashMap<StringName, MonitorCall>::Element i = _monitor_map.front(); i; i = i.next()) {
-		return_array.set(index, i.key());
+	for (KeyValue<StringName, MonitorCall> i : _monitor_map) {
+		return_array.set(index, i.key);
 		index++;
 		index++;
 	}
 	}
 	return return_array;
 	return return_array;

+ 2 - 2
main/performance.h

@@ -32,7 +32,7 @@
 #define PERFORMANCE_H
 #define PERFORMANCE_H
 
 
 #include "core/object/class_db.h"
 #include "core/object/class_db.h"
-#include "core/templates/ordered_hash_map.h"
+#include "core/templates/hash_map.h"
 
 
 #define PERF_WARN_OFFLINE_FUNCTION
 #define PERF_WARN_OFFLINE_FUNCTION
 #define PERF_WARN_PROCESS_SYNC
 #define PERF_WARN_PROCESS_SYNC
@@ -58,7 +58,7 @@ class Performance : public Object {
 		Variant call(bool &r_error, String &r_error_message);
 		Variant call(bool &r_error, String &r_error_message);
 	};
 	};
 
 
-	OrderedHashMap<StringName, MonitorCall> _monitor_map;
+	HashMap<StringName, MonitorCall> _monitor_map;
 	uint64_t _monitor_modification_time;
 	uint64_t _monitor_modification_time;
 
 
 public:
 public:

+ 2 - 3
modules/gdscript/editor/gdscript_highlighter.cpp

@@ -510,9 +510,8 @@ void GDScriptSyntaxHighlighter::_update_cache() {
 	}
 	}
 
 
 	/* Autoloads. */
 	/* Autoloads. */
-	OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
-	for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) {
-		const ProjectSettings::AutoloadInfo &info = E.value();
+	for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : ProjectSettings::get_singleton()->get_autoload_list()) {
+		const ProjectSettings::AutoloadInfo &info = E.value;
 		if (info.is_singleton) {
 		if (info.is_singleton) {
 			keywords[info.name] = usertype_color;
 			keywords[info.name] = usertype_color;
 		}
 		}

+ 3 - 5
modules/gdscript/gdscript_analyzer.cpp

@@ -4218,13 +4218,11 @@ Error GDScriptAnalyzer::resolve_program() {
 	resolve_class_interface(parser->head);
 	resolve_class_interface(parser->head);
 	resolve_class_body(parser->head);
 	resolve_class_body(parser->head);
 
 
-	List<String> parser_keys;
-	depended_parsers.get_key_list(&parser_keys);
-	for (const String &E : parser_keys) {
-		if (depended_parsers[E].is_null()) {
+	for (KeyValue<String, Ref<GDScriptParserRef>> &K : depended_parsers) {
+		if (K.value.is_null()) {
 			return ERR_PARSE_ERROR;
 			return ERR_PARSE_ERROR;
 		}
 		}
-		depended_parsers[E]->raise_status(GDScriptParserRef::FULLY_SOLVED);
+		K.value->raise_status(GDScriptParserRef::FULLY_SOLVED);
 	}
 	}
 	return parser->errors.is_empty() ? OK : ERR_PARSE_ERROR;
 	return parser->errors.is_empty() ? OK : ERR_PARSE_ERROR;
 }
 }

+ 2 - 4
modules/gdscript/gdscript_byte_codegen.cpp

@@ -196,10 +196,8 @@ GDScriptFunction *GDScriptByteCodeGenerator::write_end() {
 		function->_constant_count = constant_map.size();
 		function->_constant_count = constant_map.size();
 		function->constants.resize(constant_map.size());
 		function->constants.resize(constant_map.size());
 		function->_constants_ptr = function->constants.ptrw();
 		function->_constants_ptr = function->constants.ptrw();
-		const Variant *K = nullptr;
-		while ((K = constant_map.next(K))) {
-			int idx = constant_map[*K];
-			function->constants.write[idx] = *K;
+		for (const KeyValue<Variant, int> &K : constant_map) {
+			function->constants.write[K.value] = K.key;
 		}
 		}
 	} else {
 	} else {
 		function->_constants_ptr = nullptr;
 		function->_constants_ptr = nullptr;

+ 1 - 1
modules/gdscript/gdscript_compiler.cpp

@@ -336,7 +336,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
 			if (GDScriptLanguage::get_singleton()->get_global_map().has(identifier)) {
 			if (GDScriptLanguage::get_singleton()->get_global_map().has(identifier)) {
 				// If it's an autoload singleton, we postpone to load it at runtime.
 				// If it's an autoload singleton, we postpone to load it at runtime.
 				// This is so one autoload doesn't try to load another before it's compiled.
 				// This is so one autoload doesn't try to load another before it's compiled.
-				OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
+				HashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
 				if (autoloads.has(identifier) && autoloads[identifier].is_singleton) {
 				if (autoloads.has(identifier) && autoloads[identifier].is_singleton) {
 					GDScriptCodeGenerator::Address global = codegen.add_temporary(_gdtype_from_datatype(in->get_datatype()));
 					GDScriptCodeGenerator::Address global = codegen.add_temporary(_gdtype_from_datatype(in->get_datatype()));
 					int idx = GDScriptLanguage::get_singleton()->get_global_map()[identifier];
 					int idx = GDScriptLanguage::get_singleton()->get_global_map()[identifier];

+ 12 - 16
modules/gdscript/gdscript_editor.cpp

@@ -851,9 +851,10 @@ static void _list_available_types(bool p_inherit_only, GDScriptParser::Completio
 	}
 	}
 
 
 	// Autoload singletons
 	// Autoload singletons
-	OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
-	for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) {
-		const ProjectSettings::AutoloadInfo &info = E.get();
+	HashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
+
+	for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : autoloads) {
+		const ProjectSettings::AutoloadInfo &info = E.value;
 		if (!info.is_singleton || info.path.get_extension().to_lower() != "gd") {
 		if (!info.is_singleton || info.path.get_extension().to_lower() != "gd") {
 			continue;
 			continue;
 		}
 		}
@@ -1219,12 +1220,11 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context
 		r_result.insert(option.display, option);
 		r_result.insert(option.display, option);
 	}
 	}
 
 
-	OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
-	for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) {
-		if (!E.value().is_singleton) {
+	for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : ProjectSettings::get_singleton()->get_autoload_list()) {
+		if (!E.value.is_singleton) {
 			continue;
 			continue;
 		}
 		}
-		ScriptLanguage::CodeCompletionOption option(E.key(), ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT);
+		ScriptLanguage::CodeCompletionOption option(E.key, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT);
 		r_result.insert(option.display, option);
 		r_result.insert(option.display, option);
 	}
 	}
 
 
@@ -1517,12 +1517,10 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context,
 												r_type = _type_from_variant(GDScriptLanguage::get_singleton()->get_named_globals_map()[which]);
 												r_type = _type_from_variant(GDScriptLanguage::get_singleton()->get_named_globals_map()[which]);
 												found = true;
 												found = true;
 											} else {
 											} else {
-												OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
-
-												for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) {
-													String name = E.key();
+												for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : ProjectSettings::get_singleton()->get_autoload_list()) {
+													String name = E.key;
 													if (name == which) {
 													if (name == which) {
-														String script = E.value().path;
+														String script = E.value.path;
 
 
 														if (!script.begins_with("res://")) {
 														if (!script.begins_with("res://")) {
 															script = "res://" + script;
 															script = "res://" + script;
@@ -2882,10 +2880,8 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
 				}
 				}
 
 
 				// Get autoloads.
 				// Get autoloads.
-				OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
-
-				for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) {
-					String path = "/root/" + E.key();
+				for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : ProjectSettings::get_singleton()->get_autoload_list()) {
+					String path = "/root/" + E.key;
 					ScriptLanguage::CodeCompletionOption option(path.quote(quote_style), ScriptLanguage::CODE_COMPLETION_KIND_NODE_PATH);
 					ScriptLanguage::CodeCompletionOption option(path.quote(quote_style), ScriptLanguage::CODE_COMPLETION_KIND_NODE_PATH);
 					options.insert(option.display, option);
 					options.insert(option.display, option);
 				}
 				}

+ 11 - 15
modules/gdscript/gdscript_parser.cpp

@@ -100,10 +100,8 @@ void GDScriptParser::cleanup() {
 }
 }
 
 
 void GDScriptParser::get_annotation_list(List<MethodInfo> *r_annotations) const {
 void GDScriptParser::get_annotation_list(List<MethodInfo> *r_annotations) const {
-	List<StringName> keys;
-	valid_annotations.get_key_list(&keys);
-	for (const StringName &E : keys) {
-		r_annotations->push_back(valid_annotations[E].info);
+	for (const KeyValue<StringName, AnnotationInfo> &E : valid_annotations) {
+		r_annotations->push_back(E.value.info);
 	}
 	}
 }
 }
 
 
@@ -1894,11 +1892,8 @@ GDScriptParser::MatchBranchNode *GDScriptParser::parse_match_branch() {
 
 
 	SuiteNode *suite = alloc_node<SuiteNode>();
 	SuiteNode *suite = alloc_node<SuiteNode>();
 	if (branch->patterns.size() > 0) {
 	if (branch->patterns.size() > 0) {
-		List<StringName> binds;
-		branch->patterns[0]->binds.get_key_list(&binds);
-
-		for (const StringName &E : binds) {
-			SuiteNode::Local local(branch->patterns[0]->binds[E], current_function);
+		for (const KeyValue<StringName, IdentifierNode *> &E : branch->patterns[0]->binds) {
+			SuiteNode::Local local(E.value, current_function);
 			local.type = SuiteNode::Local::PATTERN_BIND;
 			local.type = SuiteNode::Local::PATTERN_BIND;
 			suite->add_local(local);
 			suite->add_local(local);
 		}
 		}
@@ -3566,14 +3561,15 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
 				variable->export_info.hint = PROPERTY_HINT_ENUM;
 				variable->export_info.hint = PROPERTY_HINT_ENUM;
 
 
 				String enum_hint_string;
 				String enum_hint_string;
-				for (OrderedHashMap<StringName, int>::Element E = export_type.enum_values.front(); E; E = E.next()) {
-					enum_hint_string += E.key().operator String().capitalize().xml_escape();
-					enum_hint_string += ":";
-					enum_hint_string += String::num_int64(E.value()).xml_escape();
-
-					if (E.next()) {
+				bool first = true;
+				for (const KeyValue<StringName, int> &E : export_type.enum_values) {
+					if (!first) {
 						enum_hint_string += ",";
 						enum_hint_string += ",";
+						first = false;
 					}
 					}
+					enum_hint_string += E.key.operator String().capitalize().xml_escape();
+					enum_hint_string += ":";
+					enum_hint_string += String::num_int64(E.value).xml_escape();
 				}
 				}
 
 
 				variable->export_info.hint_string = enum_hint_string;
 				variable->export_info.hint_string = enum_hint_string;

+ 1 - 1
modules/gdscript/gdscript_parser.h

@@ -132,7 +132,7 @@ public:
 		ClassNode *class_type = nullptr;
 		ClassNode *class_type = nullptr;
 
 
 		MethodInfo method_info; // For callable/signals.
 		MethodInfo method_info; // For callable/signals.
-		OrderedHashMap<StringName, int> enum_values; // For enums.
+		HashMap<StringName, int> enum_values; // For enums.
 
 
 		_FORCE_INLINE_ bool is_set() const { return kind != UNRESOLVED; }
 		_FORCE_INLINE_ bool is_set() const { return kind != UNRESOLVED; }
 		_FORCE_INLINE_ bool has_no_type() const { return type_source == UNDETECTED; }
 		_FORCE_INLINE_ bool has_no_type() const { return type_source == UNDETECTED; }

+ 12 - 20
modules/gdscript/language_server/gdscript_extend_parser.cpp

@@ -89,16 +89,16 @@ void ExtendGDScriptParser::update_symbols() {
 
 
 		for (int i = 0; i < class_symbol.children.size(); i++) {
 		for (int i = 0; i < class_symbol.children.size(); i++) {
 			const lsp::DocumentSymbol &symbol = class_symbol.children[i];
 			const lsp::DocumentSymbol &symbol = class_symbol.children[i];
-			members.set(symbol.name, &symbol);
+			members.insert(symbol.name, &symbol);
 
 
 			// cache level one inner classes
 			// cache level one inner classes
 			if (symbol.kind == lsp::SymbolKind::Class) {
 			if (symbol.kind == lsp::SymbolKind::Class) {
 				ClassMembers inner_class;
 				ClassMembers inner_class;
 				for (int j = 0; j < symbol.children.size(); j++) {
 				for (int j = 0; j < symbol.children.size(); j++) {
 					const lsp::DocumentSymbol &s = symbol.children[j];
 					const lsp::DocumentSymbol &s = symbol.children[j];
-					inner_class.set(s.name, &s);
+					inner_class.insert(s.name, &s);
 				}
 				}
-				inner_classes.set(symbol.name, inner_class);
+				inner_classes.insert(symbol.name, inner_class);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -661,30 +661,22 @@ const List<lsp::DocumentLink> &ExtendGDScriptParser::get_document_links() const
 
 
 const Array &ExtendGDScriptParser::get_member_completions() {
 const Array &ExtendGDScriptParser::get_member_completions() {
 	if (member_completions.is_empty()) {
 	if (member_completions.is_empty()) {
-		const String *name = members.next(nullptr);
-		while (name) {
-			const lsp::DocumentSymbol *symbol = members.get(*name);
+		for (const KeyValue<String, const lsp::DocumentSymbol *> &E : members) {
+			const lsp::DocumentSymbol *symbol = E.value;
 			lsp::CompletionItem item = symbol->make_completion_item();
 			lsp::CompletionItem item = symbol->make_completion_item();
-			item.data = JOIN_SYMBOLS(path, *name);
+			item.data = JOIN_SYMBOLS(path, E.key);
 			member_completions.push_back(item.to_json());
 			member_completions.push_back(item.to_json());
-
-			name = members.next(name);
 		}
 		}
 
 
-		const String *_class = inner_classes.next(nullptr);
-		while (_class) {
-			const ClassMembers *inner_class = inner_classes.getptr(*_class);
-			const String *member_name = inner_class->next(nullptr);
-			while (member_name) {
-				const lsp::DocumentSymbol *symbol = inner_class->get(*member_name);
+		for (const KeyValue<String, ClassMembers> &E : inner_classes) {
+			const ClassMembers *inner_class = &E.value;
+
+			for (const KeyValue<String, const lsp::DocumentSymbol *> &F : *inner_class) {
+				const lsp::DocumentSymbol *symbol = F.value;
 				lsp::CompletionItem item = symbol->make_completion_item();
 				lsp::CompletionItem item = symbol->make_completion_item();
-				item.data = JOIN_SYMBOLS(path, JOIN_SYMBOLS(*_class, *member_name));
+				item.data = JOIN_SYMBOLS(path, JOIN_SYMBOLS(E.key, F.key));
 				member_completions.push_back(item.to_json());
 				member_completions.push_back(item.to_json());
-
-				member_name = inner_class->next(member_name);
 			}
 			}
-
-			_class = inner_classes.next(_class);
 		}
 		}
 	}
 	}
 
 

+ 18 - 14
modules/gdscript/language_server/gdscript_language_protocol.cpp

@@ -126,7 +126,7 @@ Error GDScriptLanguageProtocol::on_client_connected() {
 	ERR_FAIL_COND_V_MSG(clients.size() >= LSP_MAX_CLIENTS, FAILED, "Max client limits reached");
 	ERR_FAIL_COND_V_MSG(clients.size() >= LSP_MAX_CLIENTS, FAILED, "Max client limits reached");
 	Ref<LSPeer> peer = memnew(LSPeer);
 	Ref<LSPeer> peer = memnew(LSPeer);
 	peer->connection = tcp_peer;
 	peer->connection = tcp_peer;
-	clients.set(next_client_id, peer);
+	clients.insert(next_client_id, peer);
 	next_client_id++;
 	next_client_id++;
 	EditorNode::get_log()->add_message("[LSP] Connection Taken", EditorLog::MSG_TYPE_EDITOR);
 	EditorNode::get_log()->add_message("[LSP] Connection Taken", EditorLog::MSG_TYPE_EDITOR);
 	return OK;
 	return OK;
@@ -229,28 +229,33 @@ void GDScriptLanguageProtocol::poll() {
 	if (server->is_connection_available()) {
 	if (server->is_connection_available()) {
 		on_client_connected();
 		on_client_connected();
 	}
 	}
-	const int *id = nullptr;
-	while ((id = clients.next(id))) {
-		Ref<LSPeer> peer = clients.get(*id);
+
+	HashMap<int, Ref<LSPeer>>::Iterator E = clients.begin();
+	while (E != clients.end()) {
+		Ref<LSPeer> peer = E->value;
 		StreamPeerTCP::Status status = peer->connection->get_status();
 		StreamPeerTCP::Status status = peer->connection->get_status();
 		if (status == StreamPeerTCP::STATUS_NONE || status == StreamPeerTCP::STATUS_ERROR) {
 		if (status == StreamPeerTCP::STATUS_NONE || status == StreamPeerTCP::STATUS_ERROR) {
-			on_client_disconnected(*id);
-			id = nullptr;
+			on_client_disconnected(E->key);
+			E = clients.begin();
+			continue;
 		} else {
 		} else {
 			if (peer->connection->get_available_bytes() > 0) {
 			if (peer->connection->get_available_bytes() > 0) {
-				latest_client_id = *id;
+				latest_client_id = E->key;
 				Error err = peer->handle_data();
 				Error err = peer->handle_data();
 				if (err != OK && err != ERR_BUSY) {
 				if (err != OK && err != ERR_BUSY) {
-					on_client_disconnected(*id);
-					id = nullptr;
+					on_client_disconnected(E->key);
+					E = clients.begin();
+					continue;
 				}
 				}
 			}
 			}
 			Error err = peer->send_data();
 			Error err = peer->send_data();
 			if (err != OK && err != ERR_BUSY) {
 			if (err != OK && err != ERR_BUSY) {
-				on_client_disconnected(*id);
-				id = nullptr;
+				on_client_disconnected(E->key);
+				E = clients.begin();
+				continue;
 			}
 			}
 		}
 		}
+		++E;
 	}
 	}
 }
 }
 
 
@@ -259,9 +264,8 @@ Error GDScriptLanguageProtocol::start(int p_port, const IPAddress &p_bind_ip) {
 }
 }
 
 
 void GDScriptLanguageProtocol::stop() {
 void GDScriptLanguageProtocol::stop() {
-	const int *id = nullptr;
-	while ((id = clients.next(id))) {
-		Ref<LSPeer> peer = clients.get(*id);
+	for (const KeyValue<int, Ref<LSPeer>> &E : clients) {
+		Ref<LSPeer> peer = clients.get(E.key);
 		peer->connection->disconnect_from_host();
 		peer->connection->disconnect_from_host();
 	}
 	}
 
 

+ 5 - 13
modules/gdscript/language_server/gdscript_text_document.cpp

@@ -109,23 +109,15 @@ void GDScriptTextDocument::notify_client_show_symbol(const lsp::DocumentSymbol *
 
 
 void GDScriptTextDocument::initialize() {
 void GDScriptTextDocument::initialize() {
 	if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) {
 	if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) {
-		const HashMap<StringName, ClassMembers> &native_members = GDScriptLanguageProtocol::get_singleton()->get_workspace()->native_members;
+		for (const KeyValue<StringName, ClassMembers> &E : GDScriptLanguageProtocol::get_singleton()->get_workspace()->native_members) {
+			const ClassMembers &members = E.value;
 
 
-		const StringName *class_ptr = native_members.next(nullptr);
-		while (class_ptr) {
-			const ClassMembers &members = native_members.get(*class_ptr);
-
-			const String *name = members.next(nullptr);
-			while (name) {
-				const lsp::DocumentSymbol *symbol = members.get(*name);
+			for (const KeyValue<String, const lsp::DocumentSymbol *> &F : members) {
+				const lsp::DocumentSymbol *symbol = members.get(F.key);
 				lsp::CompletionItem item = symbol->make_completion_item();
 				lsp::CompletionItem item = symbol->make_completion_item();
-				item.data = JOIN_SYMBOLS(String(*class_ptr), *name);
+				item.data = JOIN_SYMBOLS(String(E.key), F.key);
 				native_member_completions.push_back(item.to_json());
 				native_member_completions.push_back(item.to_json());
-
-				name = members.next(name);
 			}
 			}
-
-			class_ptr = native_members.next(class_ptr);
 		}
 		}
 	}
 	}
 }
 }

+ 6 - 12
modules/gdscript/language_server/gdscript_workspace.cpp

@@ -404,9 +404,9 @@ Error GDScriptWorkspace::initialize() {
 			const lsp::DocumentSymbol &class_symbol = E.value;
 			const lsp::DocumentSymbol &class_symbol = E.value;
 			for (int i = 0; i < class_symbol.children.size(); i++) {
 			for (int i = 0; i < class_symbol.children.size(); i++) {
 				const lsp::DocumentSymbol &symbol = class_symbol.children[i];
 				const lsp::DocumentSymbol &symbol = class_symbol.children[i];
-				members.set(symbol.name, &symbol);
+				members.insert(symbol.name, &symbol);
 			}
 			}
-			native_members.set(E.key, members);
+			native_members.insert(E.key, members);
 		}
 		}
 
 
 		// cache member completions
 		// cache member completions
@@ -682,13 +682,11 @@ void GDScriptWorkspace::resolve_related_symbols(const lsp::TextDocumentPositionP
 		Vector2i offset;
 		Vector2i offset;
 		symbol_identifier = parser->get_identifier_under_position(p_doc_pos.position, offset);
 		symbol_identifier = parser->get_identifier_under_position(p_doc_pos.position, offset);
 
 
-		const StringName *class_ptr = native_members.next(nullptr);
-		while (class_ptr) {
-			const ClassMembers &members = native_members.get(*class_ptr);
+		for (const KeyValue<StringName, ClassMembers> &E : native_members) {
+			const ClassMembers &members = native_members.get(E.key);
 			if (const lsp::DocumentSymbol *const *symbol = members.getptr(symbol_identifier)) {
 			if (const lsp::DocumentSymbol *const *symbol = members.getptr(symbol_identifier)) {
 				r_list.push_back(*symbol);
 				r_list.push_back(*symbol);
 			}
 			}
-			class_ptr = native_members.next(class_ptr);
 		}
 		}
 
 
 		for (const KeyValue<String, ExtendGDScriptParser *> &E : scripts) {
 		for (const KeyValue<String, ExtendGDScriptParser *> &E : scripts) {
@@ -698,15 +696,11 @@ void GDScriptWorkspace::resolve_related_symbols(const lsp::TextDocumentPositionP
 				r_list.push_back(*symbol);
 				r_list.push_back(*symbol);
 			}
 			}
 
 
-			const HashMap<String, ClassMembers> &inner_classes = script->get_inner_classes();
-			const String *_class = inner_classes.next(nullptr);
-			while (_class) {
-				const ClassMembers *inner_class = inner_classes.getptr(*_class);
+			for (const KeyValue<String, ClassMembers> &F : script->get_inner_classes()) {
+				const ClassMembers *inner_class = &F.value;
 				if (const lsp::DocumentSymbol *const *symbol = inner_class->getptr(symbol_identifier)) {
 				if (const lsp::DocumentSymbol *const *symbol = inner_class->getptr(symbol_identifier)) {
 					r_list.push_back(*symbol);
 					r_list.push_back(*symbol);
 				}
 				}
-
-				_class = inner_classes.next(_class);
 			}
 			}
 		}
 		}
 	}
 	}

+ 5 - 5
modules/gdscript/tests/gdscript_test_runner.cpp

@@ -48,11 +48,11 @@
 namespace GDScriptTests {
 namespace GDScriptTests {
 
 
 void init_autoloads() {
 void init_autoloads() {
-	OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
+	HashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
 
 
 	// First pass, add the constants so they exist before any script is loaded.
 	// First pass, add the constants so they exist before any script is loaded.
-	for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) {
-		const ProjectSettings::AutoloadInfo &info = E.get();
+	for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : ProjectSettings::get_singleton()->get_autoload_list()) {
+		const ProjectSettings::AutoloadInfo &info = E.value;
 
 
 		if (info.is_singleton) {
 		if (info.is_singleton) {
 			for (int i = 0; i < ScriptServer::get_language_count(); i++) {
 			for (int i = 0; i < ScriptServer::get_language_count(); i++) {
@@ -62,8 +62,8 @@ void init_autoloads() {
 	}
 	}
 
 
 	// Second pass, load into global constants.
 	// Second pass, load into global constants.
-	for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) {
-		const ProjectSettings::AutoloadInfo &info = E.get();
+	for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : ProjectSettings::get_singleton()->get_autoload_list()) {
+		const ProjectSettings::AutoloadInfo &info = E.value;
 
 
 		if (!info.is_singleton) {
 		if (!info.is_singleton) {
 			// Skip non-singletons since we don't have a scene tree here anyway.
 			// Skip non-singletons since we don't have a scene tree here anyway.

+ 14 - 27
modules/mono/class_db_api_json.cpp

@@ -40,17 +40,12 @@
 void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
 void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
 	Dictionary classes_dict;
 	Dictionary classes_dict;
 
 
-	List<StringName> names;
+	List<StringName> class_list;
+	ClassDB::get_class_list(&class_list);
+	// Must be alphabetically sorted for hash to compute.
+	class_list.sort_custom<StringName::AlphCompare>();
 
 
-	const StringName *k = nullptr;
-
-	while ((k = ClassDB::classes.next(k))) {
-		names.push_back(*k);
-	}
-	//must be alphabetically sorted for hash to compute
-	names.sort_custom<StringName::AlphCompare>();
-
-	for (const StringName &E : names) {
+	for (const StringName &E : class_list) {
 		ClassDB::ClassInfo *t = ClassDB::classes.getptr(E);
 		ClassDB::ClassInfo *t = ClassDB::classes.getptr(E);
 		ERR_FAIL_COND(!t);
 		ERR_FAIL_COND(!t);
 		if (t->api != p_api || !t->exposed) {
 		if (t->api != p_api || !t->exposed) {
@@ -66,10 +61,8 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
 
 
 			List<StringName> snames;
 			List<StringName> snames;
 
 
-			k = nullptr;
-
-			while ((k = t->method_map.next(k))) {
-				String name = k->operator String();
+			for (const KeyValue<StringName, MethodBind *> &F : t->method_map) {
+				String name = F.key.operator String();
 
 
 				ERR_CONTINUE(name.is_empty());
 				ERR_CONTINUE(name.is_empty());
 
 
@@ -77,7 +70,7 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
 					continue; // Ignore non-virtual methods that start with an underscore
 					continue; // Ignore non-virtual methods that start with an underscore
 				}
 				}
 
 
-				snames.push_back(*k);
+				snames.push_back(F.key);
 			}
 			}
 
 
 			snames.sort_custom<StringName::AlphCompare>();
 			snames.sort_custom<StringName::AlphCompare>();
@@ -131,10 +124,8 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
 
 
 			List<StringName> snames;
 			List<StringName> snames;
 
 
-			k = nullptr;
-
-			while ((k = t->constant_map.next(k))) {
-				snames.push_back(*k);
+			for (const KeyValue<StringName, int> &F : t->constant_map) {
+				snames.push_back(F.key);
 			}
 			}
 
 
 			snames.sort_custom<StringName::AlphCompare>();
 			snames.sort_custom<StringName::AlphCompare>();
@@ -158,10 +149,8 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
 
 
 			List<StringName> snames;
 			List<StringName> snames;
 
 
-			k = nullptr;
-
-			while ((k = t->signal_map.next(k))) {
-				snames.push_back(*k);
+			for (const KeyValue<StringName, MethodInfo> &F : t->signal_map) {
+				snames.push_back(F.key);
 			}
 			}
 
 
 			snames.sort_custom<StringName::AlphCompare>();
 			snames.sort_custom<StringName::AlphCompare>();
@@ -193,10 +182,8 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
 
 
 			List<StringName> snames;
 			List<StringName> snames;
 
 
-			k = nullptr;
-
-			while ((k = t->property_setget.next(k))) {
-				snames.push_back(*k);
+			for (const KeyValue<StringName, ClassDB::PropertySetGet> &F : t->property_setget) {
+				snames.push_back(F.key);
 			}
 			}
 
 
 			snames.sort_custom<StringName::AlphCompare>();
 			snames.sort_custom<StringName::AlphCompare>();

+ 4 - 4
modules/mono/csharp_script.cpp

@@ -1798,8 +1798,8 @@ void CSharpInstance::get_event_signals_state_for_reloading(List<Pair<StringName,
 
 
 void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const {
 void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const {
 	List<PropertyInfo> props;
 	List<PropertyInfo> props;
-	for (OrderedHashMap<StringName, PropertyInfo>::ConstElement E = script->member_info.front(); E; E = E.next()) {
-		props.push_front(E.value());
+	for (const KeyValue<StringName, PropertyInfo> &E : script->member_info) {
+		props.push_front(E.value);
 	}
 	}
 
 
 	// Call _get_property_list
 	// Call _get_property_list
@@ -3491,8 +3491,8 @@ Ref<Script> CSharpScript::get_base_script() const {
 void CSharpScript::get_script_property_list(List<PropertyInfo> *r_list) const {
 void CSharpScript::get_script_property_list(List<PropertyInfo> *r_list) const {
 	List<PropertyInfo> props;
 	List<PropertyInfo> props;
 
 
-	for (OrderedHashMap<StringName, PropertyInfo>::ConstElement E = member_info.front(); E; E = E.next()) {
-		props.push_front(E.value());
+	for (const KeyValue<StringName, PropertyInfo> &E : member_info) {
+		props.push_front(E.value);
 	}
 	}
 
 
 	for (const PropertyInfo &prop : props) {
 	for (const PropertyInfo &prop : props) {

+ 1 - 1
modules/mono/csharp_script.h

@@ -154,7 +154,7 @@ private:
 	Set<StringName> exported_members_names;
 	Set<StringName> exported_members_names;
 #endif
 #endif
 
 
-	OrderedHashMap<StringName, PropertyInfo> member_info;
+	HashMap<StringName, PropertyInfo> member_info;
 
 
 	void _clear();
 	void _clear();
 
 

+ 20 - 22
modules/mono/editor/bindings_generator.cpp

@@ -1078,8 +1078,8 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) {
 		compile_items.push_back(output_file);
 		compile_items.push_back(output_file);
 	}
 	}
 
 
-	for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) {
-		const TypeInterface &itype = E.get();
+	for (const KeyValue<StringName, TypeInterface> &E : obj_types) {
+		const TypeInterface &itype = E.value;
 
 
 		if (itype.api_type == ClassDB::API_EDITOR) {
 		if (itype.api_type == ClassDB::API_EDITOR) {
 			continue;
 			continue;
@@ -1187,8 +1187,8 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) {
 
 
 	Vector<String> compile_items;
 	Vector<String> compile_items;
 
 
-	for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) {
-		const TypeInterface &itype = E.get();
+	for (const KeyValue<StringName, TypeInterface> &E : obj_types) {
+		const TypeInterface &itype = E.value;
 
 
 		if (itype.api_type != ClassDB::API_EDITOR) {
 		if (itype.api_type != ClassDB::API_EDITOR) {
 			continue;
 			continue;
@@ -1573,9 +1573,9 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
 	// Search it in base types too
 	// Search it in base types too
 	const TypeInterface *current_type = &p_itype;
 	const TypeInterface *current_type = &p_itype;
 	while (!setter && current_type->base_name != StringName()) {
 	while (!setter && current_type->base_name != StringName()) {
-		OrderedHashMap<StringName, TypeInterface>::Element base_match = obj_types.find(current_type->base_name);
+		HashMap<StringName, TypeInterface>::Iterator base_match = obj_types.find(current_type->base_name);
 		ERR_FAIL_COND_V_MSG(!base_match, ERR_BUG, "Type not found '" + current_type->base_name + "'. Inherited by '" + current_type->name + "'.");
 		ERR_FAIL_COND_V_MSG(!base_match, ERR_BUG, "Type not found '" + current_type->base_name + "'. Inherited by '" + current_type->name + "'.");
-		current_type = &base_match.get();
+		current_type = &base_match->value;
 		setter = current_type->find_method_by_name(p_iprop.setter);
 		setter = current_type->find_method_by_name(p_iprop.setter);
 	}
 	}
 
 
@@ -1584,9 +1584,9 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
 	// Search it in base types too
 	// Search it in base types too
 	current_type = &p_itype;
 	current_type = &p_itype;
 	while (!getter && current_type->base_name != StringName()) {
 	while (!getter && current_type->base_name != StringName()) {
-		OrderedHashMap<StringName, TypeInterface>::Element base_match = obj_types.find(current_type->base_name);
+		HashMap<StringName, TypeInterface>::Iterator base_match = obj_types.find(current_type->base_name);
 		ERR_FAIL_COND_V_MSG(!base_match, ERR_BUG, "Type not found '" + current_type->base_name + "'. Inherited by '" + current_type->name + "'.");
 		ERR_FAIL_COND_V_MSG(!base_match, ERR_BUG, "Type not found '" + current_type->base_name + "'. Inherited by '" + current_type->name + "'.");
-		current_type = &base_match.get();
+		current_type = &base_match->value;
 		getter = current_type->find_method_by_name(p_iprop.getter);
 		getter = current_type->find_method_by_name(p_iprop.getter);
 	}
 	}
 
 
@@ -2096,8 +2096,8 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
 
 
 	generated_icall_funcs.clear();
 	generated_icall_funcs.clear();
 
 
-	for (OrderedHashMap<StringName, TypeInterface>::Element type_elem = obj_types.front(); type_elem; type_elem = type_elem.next()) {
-		const TypeInterface &itype = type_elem.get();
+	for (const KeyValue<StringName, TypeInterface> &type_elem : obj_types) {
+		const TypeInterface &itype = type_elem.value;
 
 
 		bool is_derived_type = itype.base_name != StringName();
 		bool is_derived_type = itype.base_name != StringName();
 
 
@@ -2474,10 +2474,10 @@ const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_or_null(con
 		return &builtin_type_match->get();
 		return &builtin_type_match->get();
 	}
 	}
 
 
-	const OrderedHashMap<StringName, TypeInterface>::Element obj_type_match = obj_types.find(p_typeref.cname);
+	const HashMap<StringName, TypeInterface>::Iterator obj_type_match = obj_types.find(p_typeref.cname);
 
 
 	if (obj_type_match) {
 	if (obj_type_match) {
-		return &obj_type_match.get();
+		return &obj_type_match->value;
 	}
 	}
 
 
 	if (p_typeref.is_enum) {
 	if (p_typeref.is_enum) {
@@ -2942,12 +2942,11 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
 		// Populate signals
 		// Populate signals
 
 
 		const HashMap<StringName, MethodInfo> &signal_map = class_info->signal_map;
 		const HashMap<StringName, MethodInfo> &signal_map = class_info->signal_map;
-		const StringName *k = nullptr;
 
 
-		while ((k = signal_map.next(k))) {
+		for (const KeyValue<StringName, MethodInfo> &E : signal_map) {
 			SignalInterface isignal;
 			SignalInterface isignal;
 
 
-			const MethodInfo &method_info = signal_map.get(*k);
+			const MethodInfo &method_info = E.value;
 
 
 			isignal.name = method_info.name;
 			isignal.name = method_info.name;
 			isignal.cname = method_info.name;
 			isignal.cname = method_info.name;
@@ -3024,10 +3023,9 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
 		ClassDB::get_integer_constant_list(type_cname, &constants, true);
 		ClassDB::get_integer_constant_list(type_cname, &constants, true);
 
 
 		const HashMap<StringName, List<StringName>> &enum_map = class_info->enum_map;
 		const HashMap<StringName, List<StringName>> &enum_map = class_info->enum_map;
-		k = nullptr;
 
 
-		while ((k = enum_map.next(k))) {
-			StringName enum_proxy_cname = *k;
+		for (const KeyValue<StringName, List<StringName>> &E : enum_map) {
+			StringName enum_proxy_cname = E.key;
 			String enum_proxy_name = enum_proxy_cname.operator String();
 			String enum_proxy_name = enum_proxy_cname.operator String();
 			if (itype.find_property_by_proxy_name(enum_proxy_cname)) {
 			if (itype.find_property_by_proxy_name(enum_proxy_cname)) {
 				// We have several conflicts between enums and PascalCase properties,
 				// We have several conflicts between enums and PascalCase properties,
@@ -3036,7 +3034,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
 				enum_proxy_cname = StringName(enum_proxy_name);
 				enum_proxy_cname = StringName(enum_proxy_name);
 			}
 			}
 			EnumInterface ienum(enum_proxy_cname);
 			EnumInterface ienum(enum_proxy_cname);
-			const List<StringName> &enum_constants = enum_map.get(*k);
+			const List<StringName> &enum_constants = E.value;
 			for (const StringName &constant_cname : enum_constants) {
 			for (const StringName &constant_cname : enum_constants) {
 				String constant_name = constant_cname.operator String();
 				String constant_name = constant_cname.operator String();
 				int *value = class_info->constant_map.getptr(constant_cname);
 				int *value = class_info->constant_map.getptr(constant_cname);
@@ -3066,7 +3064,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
 
 
 			TypeInterface enum_itype;
 			TypeInterface enum_itype;
 			enum_itype.is_enum = true;
 			enum_itype.is_enum = true;
-			enum_itype.name = itype.name + "." + String(*k);
+			enum_itype.name = itype.name + "." + String(E.key);
 			enum_itype.cname = StringName(enum_itype.name);
 			enum_itype.cname = StringName(enum_itype.name);
 			enum_itype.proxy_name = itype.proxy_name + "." + enum_proxy_name;
 			enum_itype.proxy_name = itype.proxy_name + "." + enum_proxy_name;
 			TypeInterface::postsetup_enum_type(enum_itype);
 			TypeInterface::postsetup_enum_type(enum_itype);
@@ -3715,8 +3713,8 @@ void BindingsGenerator::_initialize() {
 	core_custom_icalls.clear();
 	core_custom_icalls.clear();
 	editor_custom_icalls.clear();
 	editor_custom_icalls.clear();
 
 
-	for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) {
-		_generate_method_icalls(E.get());
+	for (const KeyValue<StringName, TypeInterface> &E : obj_types) {
+		_generate_method_icalls(E.value);
 	}
 	}
 
 
 	initialized = true;
 	initialized = true;

+ 1 - 1
modules/mono/editor/bindings_generator.h

@@ -533,7 +533,7 @@ class BindingsGenerator {
 	bool log_print_enabled = true;
 	bool log_print_enabled = true;
 	bool initialized = false;
 	bool initialized = false;
 
 
-	OrderedHashMap<StringName, TypeInterface> obj_types;
+	HashMap<StringName, TypeInterface> obj_types;
 
 
 	Map<StringName, TypeInterface> placeholder_types;
 	Map<StringName, TypeInterface> placeholder_types;
 	Map<StringName, TypeInterface> builtin_types;
 	Map<StringName, TypeInterface> builtin_types;

+ 3 - 3
modules/mono/editor/code_completion.cpp

@@ -121,10 +121,10 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
 		case CompletionKind::NODE_PATHS: {
 		case CompletionKind::NODE_PATHS: {
 			{
 			{
 				// Autoloads.
 				// Autoloads.
-				OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
+				HashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
 
 
-				for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) {
-					const ProjectSettings::AutoloadInfo &info = E.value();
+				for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : autoloads) {
+					const ProjectSettings::AutoloadInfo &info = E.value;
 					suggestions.push_back(quoted("/root/" + String(info.name)));
 					suggestions.push_back(quoted("/root/" + String(info.name)));
 				}
 				}
 			}
 			}

+ 10 - 15
modules/mono/mono_gd/gd_mono.cpp

@@ -1167,9 +1167,8 @@ GDMonoClass *GDMono::get_class(MonoClass *p_raw_class) {
 	int32_t domain_id = mono_domain_get_id(mono_domain_get());
 	int32_t domain_id = mono_domain_get_id(mono_domain_get());
 	HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[domain_id];
 	HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[domain_id];
 
 
-	const String *k = nullptr;
-	while ((k = domain_assemblies.next(k))) {
-		GDMonoAssembly *assembly = domain_assemblies.get(*k);
+	for (const KeyValue<String, GDMonoAssembly *> &E : domain_assemblies) {
+		GDMonoAssembly *assembly = E.value;
 		if (assembly->get_image() == image) {
 		if (assembly->get_image() == image) {
 			GDMonoClass *klass = assembly->get_class(p_raw_class);
 			GDMonoClass *klass = assembly->get_class(p_raw_class);
 			if (klass) {
 			if (klass) {
@@ -1190,9 +1189,8 @@ GDMonoClass *GDMono::get_class(const StringName &p_namespace, const StringName &
 	int32_t domain_id = mono_domain_get_id(mono_domain_get());
 	int32_t domain_id = mono_domain_get_id(mono_domain_get());
 	HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[domain_id];
 	HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[domain_id];
 
 
-	const String *k = nullptr;
-	while ((k = domain_assemblies.next(k))) {
-		GDMonoAssembly *assembly = domain_assemblies.get(*k);
+	for (const KeyValue<String, GDMonoAssembly *> &E : domain_assemblies) {
+		GDMonoAssembly *assembly = E.value;
 		klass = assembly->get_class(p_namespace, p_name);
 		klass = assembly->get_class(p_namespace, p_name);
 		if (klass) {
 		if (klass) {
 			return klass;
 			return klass;
@@ -1205,9 +1203,8 @@ GDMonoClass *GDMono::get_class(const StringName &p_namespace, const StringName &
 void GDMono::_domain_assemblies_cleanup(int32_t p_domain_id) {
 void GDMono::_domain_assemblies_cleanup(int32_t p_domain_id) {
 	HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[p_domain_id];
 	HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[p_domain_id];
 
 
-	const String *k = nullptr;
-	while ((k = domain_assemblies.next(k))) {
-		memdelete(domain_assemblies.get(*k));
+	for (const KeyValue<String, GDMonoAssembly *> &E : domain_assemblies) {
+		memdelete(E.value);
 	}
 	}
 
 
 	assemblies.erase(p_domain_id);
 	assemblies.erase(p_domain_id);
@@ -1298,13 +1295,11 @@ GDMono::~GDMono() {
 		// Leave the rest to 'mono_jit_cleanup'
 		// Leave the rest to 'mono_jit_cleanup'
 #endif
 #endif
 
 
-		const int32_t *k = nullptr;
-		while ((k = assemblies.next(k))) {
-			HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies.get(*k);
+		for (const KeyValue<int32_t, HashMap<String, GDMonoAssembly *>> &E : assemblies) {
+			const HashMap<String, GDMonoAssembly *> &domain_assemblies = E.value;
 
 
-			const String *kk = nullptr;
-			while ((kk = domain_assemblies.next(kk))) {
-				memdelete(domain_assemblies.get(*kk));
+			for (const KeyValue<String, GDMonoAssembly *> &F : domain_assemblies) {
+				memdelete(F.value);
 			}
 			}
 		}
 		}
 		assemblies.clear();
 		assemblies.clear();

+ 8 - 11
modules/mono/mono_gd/gd_mono_class.cpp

@@ -247,7 +247,7 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base
 				if (existing_method) {
 				if (existing_method) {
 					memdelete(*existing_method); // Must delete old one
 					memdelete(*existing_method); // Must delete old one
 				}
 				}
-				methods.set(key, method);
+				methods.insert(key, method);
 
 
 				break;
 				break;
 			}
 			}
@@ -266,11 +266,9 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base
 GDMonoMethod *GDMonoClass::get_fetched_method_unknown_params(const StringName &p_name) {
 GDMonoMethod *GDMonoClass::get_fetched_method_unknown_params(const StringName &p_name) {
 	ERR_FAIL_COND_V(!methods_fetched, nullptr);
 	ERR_FAIL_COND_V(!methods_fetched, nullptr);
 
 
-	const MethodKey *k = nullptr;
-
-	while ((k = methods.next(k))) {
-		if (k->name == p_name) {
-			return methods.get(*k);
+	for (const KeyValue<MethodKey, GDMonoMethod *> &E : methods) {
+		if (E.key.name == p_name) {
+			return E.value;
 		}
 		}
 	}
 	}
 
 
@@ -307,7 +305,7 @@ GDMonoMethod *GDMonoClass::get_method(const StringName &p_name, uint16_t p_param
 
 
 	if (raw_method) {
 	if (raw_method) {
 		GDMonoMethod *method = memnew(GDMonoMethod(p_name, raw_method));
 		GDMonoMethod *method = memnew(GDMonoMethod(p_name, raw_method));
-		methods.set(key, method);
+		methods.insert(key, method);
 
 
 		return method;
 		return method;
 	}
 	}
@@ -342,7 +340,7 @@ GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method, const StringName
 	}
 	}
 
 
 	GDMonoMethod *method = memnew(GDMonoMethod(p_name, p_raw_method));
 	GDMonoMethod *method = memnew(GDMonoMethod(p_name, p_raw_method));
-	methods.set(key, method);
+	methods.insert(key, method);
 
 
 	return method;
 	return method;
 }
 }
@@ -549,9 +547,8 @@ GDMonoClass::~GDMonoClass() {
 		Vector<GDMonoMethod *> deleted_methods;
 		Vector<GDMonoMethod *> deleted_methods;
 		deleted_methods.resize(methods.size());
 		deleted_methods.resize(methods.size());
 
 
-		const MethodKey *k = nullptr;
-		while ((k = methods.next(k))) {
-			GDMonoMethod *method = methods.get(*k);
+		for (const KeyValue<MethodKey, GDMonoMethod *> &E : methods) {
+			GDMonoMethod *method = E.value;
 
 
 			if (method) {
 			if (method) {
 				for (int i = 0; i < offset; i++) {
 				for (int i = 0; i < offset; i++) {

+ 7 - 10
modules/raycast/raycast_occlusion_cull.cpp

@@ -454,10 +454,9 @@ bool RaycastOcclusionCull::Scenario::update(ThreadWorkPool &p_thread_pool) {
 	next_scene = rtcNewScene(raycast_singleton->ebr_device);
 	next_scene = rtcNewScene(raycast_singleton->ebr_device);
 	rtcSetSceneBuildQuality(next_scene, RTCBuildQuality(raycast_singleton->build_quality));
 	rtcSetSceneBuildQuality(next_scene, RTCBuildQuality(raycast_singleton->build_quality));
 
 
-	const RID *inst_rid = nullptr;
-	while ((inst_rid = instances.next(inst_rid))) {
-		OccluderInstance *occ_inst = instances.getptr(*inst_rid);
-		Occluder *occ = raycast_singleton->occluder_owner.get_or_null(occ_inst->occluder);
+	for (const KeyValue<RID, OccluderInstance> &E : instances) {
+		const OccluderInstance *occ_inst = &E.value;
+		const Occluder *occ = raycast_singleton->occluder_owner.get_or_null(occ_inst->occluder);
 
 
 		if (!occ || !occ_inst->enabled) {
 		if (!occ || !occ_inst->enabled) {
 			continue;
 			continue;
@@ -573,9 +572,8 @@ void RaycastOcclusionCull::set_build_quality(RS::ViewportOcclusionCullingBuildQu
 
 
 	build_quality = p_quality;
 	build_quality = p_quality;
 
 
-	const RID *scenario_rid = nullptr;
-	while ((scenario_rid = scenarios.next(scenario_rid))) {
-		scenarios[*scenario_rid].dirty = true;
+	for (KeyValue<RID, Scenario> &K : scenarios) {
+		K.value.dirty = true;
 	}
 	}
 }
 }
 
 
@@ -596,9 +594,8 @@ RaycastOcclusionCull::RaycastOcclusionCull() {
 }
 }
 
 
 RaycastOcclusionCull::~RaycastOcclusionCull() {
 RaycastOcclusionCull::~RaycastOcclusionCull() {
-	const RID *scenario_rid = nullptr;
-	while ((scenario_rid = scenarios.next(scenario_rid))) {
-		Scenario &scenario = scenarios[*scenario_rid];
+	for (KeyValue<RID, Scenario> &K : scenarios) {
+		Scenario &scenario = K.value;
 		if (scenario.commit_thread) {
 		if (scenario.commit_thread) {
 			scenario.commit_thread->wait_to_finish();
 			scenario.commit_thread->wait_to_finish();
 			memdelete(scenario.commit_thread);
 			memdelete(scenario.commit_thread);

+ 4 - 6
modules/text_server_adv/text_server_adv.cpp

@@ -2371,9 +2371,8 @@ Array TextServerAdvanced::font_get_glyph_list(const RID &p_font_rid, const Vecto
 
 
 	Array ret;
 	Array ret;
 	const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map;
 	const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map;
-	const int32_t *E = nullptr;
-	while ((E = gl.next(E))) {
-		ret.push_back(*E);
+	for (const KeyValue<int32_t, FontGlyph> &E : gl) {
+		ret.push_back(E.key);
 	}
 	}
 	return ret;
 	return ret;
 }
 }
@@ -2864,9 +2863,8 @@ String TextServerAdvanced::font_get_supported_chars(const RID &p_font_rid) const
 #endif
 #endif
 	if (at_size) {
 	if (at_size) {
 		const HashMap<int32_t, FontGlyph> &gl = at_size->glyph_map;
 		const HashMap<int32_t, FontGlyph> &gl = at_size->glyph_map;
-		const int32_t *E = nullptr;
-		while ((E = gl.next(E))) {
-			chars = chars + String::chr(*E);
+		for (const KeyValue<int32_t, FontGlyph> &E : gl) {
+			chars = chars + String::chr(E.key);
 		}
 		}
 	}
 	}
 	return chars;
 	return chars;

+ 4 - 6
modules/text_server_fb/text_server_fb.cpp

@@ -1533,9 +1533,8 @@ Array TextServerFallback::font_get_glyph_list(const RID &p_font_rid, const Vecto
 
 
 	Array ret;
 	Array ret;
 	const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map;
 	const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map;
-	const int32_t *E = nullptr;
-	while ((E = gl.next(E))) {
-		ret.push_back(*E);
+	for (const KeyValue<int32_t, FontGlyph> &E : gl) {
+		ret.push_back(E.key);
 	}
 	}
 	return ret;
 	return ret;
 }
 }
@@ -1994,9 +1993,8 @@ String TextServerFallback::font_get_supported_chars(const RID &p_font_rid) const
 #endif
 #endif
 	if (at_size) {
 	if (at_size) {
 		const HashMap<int32_t, FontGlyph> &gl = at_size->glyph_map;
 		const HashMap<int32_t, FontGlyph> &gl = at_size->glyph_map;
-		const int32_t *E = nullptr;
-		while ((E = gl.next(E))) {
-			chars = chars + String::chr(*E);
+		for (const KeyValue<int32_t, FontGlyph> &E : gl) {
+			chars = chars + String::chr(E.key);
 		}
 		}
 	}
 	}
 	return chars;
 	return chars;

+ 5 - 7
modules/visual_script/editor/visual_script_editor.cpp

@@ -1608,7 +1608,7 @@ void VisualScriptEditor::_remove_output_port(int p_id, int p_port) {
 		if (E.from_node == p_id && E.from_port == p_port) {
 		if (E.from_node == p_id && E.from_port == p_port) {
 			// Push into the connections map.
 			// Push into the connections map.
 			if (!conn_map.has(E.to_node)) {
 			if (!conn_map.has(E.to_node)) {
-				conn_map.set(E.to_node, Set<int>());
+				conn_map.insert(E.to_node, Set<int>());
 			}
 			}
 			conn_map[E.to_node].insert(E.to_port);
 			conn_map[E.to_node].insert(E.to_port);
 		}
 		}
@@ -1617,11 +1617,9 @@ void VisualScriptEditor::_remove_output_port(int p_id, int p_port) {
 	undo_redo->add_do_method(vsn.ptr(), "remove_output_data_port", p_port);
 	undo_redo->add_do_method(vsn.ptr(), "remove_output_data_port", p_port);
 	undo_redo->add_do_method(this, "_update_graph", p_id);
 	undo_redo->add_do_method(this, "_update_graph", p_id);
 
 
-	List<int> keys;
-	conn_map.get_key_list(&keys);
-	for (const int &E : keys) {
-		for (const Set<int>::Element *F = conn_map[E].front(); F; F = F->next()) {
-			undo_redo->add_undo_method(script.ptr(), "data_connect", p_id, p_port, E, F->get());
+	for (const KeyValue<int, Set<int>> &E : conn_map) {
+		for (const Set<int>::Element *F = E.value.front(); F; F = F->next()) {
+			undo_redo->add_undo_method(script.ptr(), "data_connect", p_id, p_port, E.key, F->get());
 		}
 		}
 	}
 	}
 
 
@@ -1912,7 +1910,7 @@ void VisualScriptEditor::_on_nodes_duplicate() {
 		Ref<VisualScriptNode> dupe = node->duplicate(true);
 		Ref<VisualScriptNode> dupe = node->duplicate(true);
 
 
 		int new_id = idc++;
 		int new_id = idc++;
-		remap.set(F->get(), new_id);
+		remap.insert(F->get(), new_id);
 
 
 		to_select.insert(new_id);
 		to_select.insert(new_id);
 		undo_redo->add_do_method(script.ptr(), "add_node", new_id, dupe, script->get_node_position(F->get()) + Vector2(20, 20));
 		undo_redo->add_do_method(script.ptr(), "add_node", new_id, dupe, script->get_node_position(F->get()) + Vector2(20, 20));

+ 66 - 93
modules/visual_script/visual_script.cpp

@@ -209,8 +209,9 @@ Vector2 VisualScript::get_scroll() const {
 }
 }
 
 
 void VisualScript::get_function_list(List<StringName> *r_functions) const {
 void VisualScript::get_function_list(List<StringName> *r_functions) const {
-	functions.get_key_list(r_functions);
-	// r_functions->sort_custom<StringName::AlphCompare>(); // Don't force sorting.
+	for (const KeyValue<StringName, Function> &E : functions) {
+		r_functions->push_back(E.key);
+	}
 }
 }
 
 
 int VisualScript::get_function_node_id(const StringName &p_name) const {
 int VisualScript::get_function_node_id(const StringName &p_name) const {
@@ -346,7 +347,9 @@ Point2 VisualScript::get_node_position(int p_id) const {
 }
 }
 
 
 void VisualScript::get_node_list(List<int> *r_nodes) const {
 void VisualScript::get_node_list(List<int> *r_nodes) const {
-	nodes.get_key_list(r_nodes);
+	for (const KeyValue<int, NodeData> &E : nodes) {
+		r_nodes->push_back(E.key);
+	}
 }
 }
 
 
 void VisualScript::sequence_connect(int p_from_node, int p_from_output, int p_to_node) {
 void VisualScript::sequence_connect(int p_from_node, int p_from_output, int p_to_node) {
@@ -563,8 +566,9 @@ Dictionary VisualScript::_get_variable_info(const StringName &p_name) const {
 }
 }
 
 
 void VisualScript::get_variable_list(List<StringName> *r_variables) const {
 void VisualScript::get_variable_list(List<StringName> *r_variables) const {
-	variables.get_key_list(r_variables);
-	// r_variables->sort_custom<StringName::AlphCompare>(); // Don't force it.
+	for (const KeyValue<StringName, Variable> &E : variables) {
+		r_variables->push_back(E.key);
+	}
 }
 }
 
 
 void VisualScript::set_instance_base_type(const StringName &p_type) {
 void VisualScript::set_instance_base_type(const StringName &p_type) {
@@ -713,12 +717,11 @@ int VisualScript::get_available_id() const {
 	// This is infinitely increasing,
 	// This is infinitely increasing,
 	// so one might want to implement a better solution,
 	// so one might want to implement a better solution,
 	// if the there is a case for huge number of nodes to be added to visual script.
 	// if the there is a case for huge number of nodes to be added to visual script.
-	List<int> nds;
-	nodes.get_key_list(&nds);
+
 	int max = -1;
 	int max = -1;
-	for (const int &E : nds) {
-		if (E > max) {
-			max = E;
+	for (const KeyValue<int, NodeData> &E : nodes) {
+		if (E.key > max) {
+			max = E.key;
 		}
 		}
 	}
 	}
 	return (max + 1);
 	return (max + 1);
@@ -750,18 +753,15 @@ void VisualScript::_update_placeholders() {
 	List<PropertyInfo> pinfo;
 	List<PropertyInfo> pinfo;
 	Map<StringName, Variant> values;
 	Map<StringName, Variant> values;
 
 
-	List<StringName> keys;
-	variables.get_key_list(&keys);
-
-	for (const StringName &E : keys) {
-		if (!variables[E]._export) {
+	for (const KeyValue<StringName, Variable> &E : variables) {
+		if (!variables[E.key]._export) {
 			continue;
 			continue;
 		}
 		}
 
 
-		PropertyInfo p = variables[E].info;
-		p.name = String(E);
+		PropertyInfo p = variables[E.key].info;
+		p.name = String(E.key);
 		pinfo.push_back(p);
 		pinfo.push_back(p);
-		values[p.name] = variables[E].default_value;
+		values[p.name] = variables[E.key].default_value;
 	}
 	}
 
 
 	for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
 	for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
@@ -781,18 +781,15 @@ ScriptInstance *VisualScript::instance_create(Object *p_this) {
 		List<PropertyInfo> pinfo;
 		List<PropertyInfo> pinfo;
 		Map<StringName, Variant> values;
 		Map<StringName, Variant> values;
 
 
-		List<StringName> keys;
-		variables.get_key_list(&keys);
-
-		for (const StringName &E : keys) {
-			if (!variables[E]._export) {
+		for (const KeyValue<StringName, Variable> &E : variables) {
+			if (!variables[E.key]._export) {
 				continue;
 				continue;
 			}
 			}
 
 
-			PropertyInfo p = variables[E].info;
-			p.name = String(E);
+			PropertyInfo p = variables[E.key].info;
+			p.name = String(E.key);
 			pinfo.push_back(p);
 			pinfo.push_back(p);
-			values[p.name] = variables[E].default_value;
+			values[p.name] = variables[E.key].default_value;
 		}
 		}
 		sins->update(pinfo, values);
 		sins->update(pinfo, values);
 
 
@@ -872,14 +869,11 @@ bool VisualScript::get_property_default_value(const StringName &p_property, Vari
 }
 }
 
 
 void VisualScript::get_script_method_list(List<MethodInfo> *p_list) const {
 void VisualScript::get_script_method_list(List<MethodInfo> *p_list) const {
-	List<StringName> funcs;
-	functions.get_key_list(&funcs);
-
-	for (const StringName &E : funcs) {
+	for (const KeyValue<StringName, Function> &E : functions) {
 		MethodInfo mi;
 		MethodInfo mi;
-		mi.name = E;
-		if (functions[E].func_id >= 0) {
-			Ref<VisualScriptFunction> func = nodes[functions[E].func_id].node;
+		mi.name = E.key;
+		if (functions[E.key].func_id >= 0) {
+			Ref<VisualScriptFunction> func = nodes[functions[E.key].func_id].node;
 			if (func.is_valid()) {
 			if (func.is_valid()) {
 				for (int i = 0; i < func->get_argument_count(); i++) {
 				for (int i = 0; i < func->get_argument_count(); i++) {
 					PropertyInfo arg;
 					PropertyInfo arg;
@@ -945,10 +939,8 @@ int VisualScript::get_member_line(const StringName &p_member) const {
 
 
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
 bool VisualScript::are_subnodes_edited() const {
 bool VisualScript::are_subnodes_edited() const {
-	List<int> keys;
-	nodes.get_key_list(&keys);
-	for (const int &F : keys) {
-		if (nodes[F].node->is_edited()) {
+	for (const KeyValue<int, NodeData> &F : nodes) {
+		if (F.value.node->is_edited()) {
 			return true;
 			return true;
 		}
 		}
 	}
 	}
@@ -1017,15 +1009,13 @@ void VisualScript::_set_data(const Dictionary &p_data) {
 
 
 	// Takes all the rpc methods.
 	// Takes all the rpc methods.
 	rpc_functions.clear();
 	rpc_functions.clear();
-	List<StringName> fns;
-	functions.get_key_list(&fns);
-	for (const StringName &E : fns) {
-		if (functions[E].func_id >= 0 && nodes.has(functions[E].func_id)) {
-			Ref<VisualScriptFunction> vsf = nodes[functions[E].func_id].node;
+	for (const KeyValue<StringName, Function> &E : functions) {
+		if (E.value.func_id >= 0 && nodes.has(E.value.func_id)) {
+			Ref<VisualScriptFunction> vsf = nodes[E.value.func_id].node;
 			if (vsf.is_valid()) {
 			if (vsf.is_valid()) {
 				if (vsf->get_rpc_mode() != Multiplayer::RPC_MODE_DISABLED) {
 				if (vsf->get_rpc_mode() != Multiplayer::RPC_MODE_DISABLED) {
 					Multiplayer::RPCConfig nd;
 					Multiplayer::RPCConfig nd;
-					nd.name = E;
+					nd.name = E.key;
 					nd.rpc_mode = vsf->get_rpc_mode();
 					nd.rpc_mode = vsf->get_rpc_mode();
 					nd.transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE; // TODO
 					nd.transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE; // TODO
 					if (rpc_functions.find(nd) == -1) {
 					if (rpc_functions.find(nd) == -1) {
@@ -1045,13 +1035,11 @@ Dictionary VisualScript::_get_data() const {
 	d["base_type"] = base_type;
 	d["base_type"] = base_type;
 
 
 	Array vars;
 	Array vars;
-	List<StringName> var_names;
-	variables.get_key_list(&var_names);
-	for (const StringName &E : var_names) {
-		Dictionary var = _get_variable_info(E);
-		var["name"] = E; // Make sure it's the right one.
-		var["default_value"] = variables[E].default_value;
-		var["export"] = variables[E]._export;
+	for (const KeyValue<StringName, Variable> &E : variables) {
+		Dictionary var = _get_variable_info(E.key);
+		var["name"] = E.key; // Make sure it's the right one.
+		var["default_value"] = E.value.default_value;
+		var["export"] = E.value._export;
 		vars.push_back(var);
 		vars.push_back(var);
 	}
 	}
 	d["variables"] = vars;
 	d["variables"] = vars;
@@ -1073,23 +1061,19 @@ Dictionary VisualScript::_get_data() const {
 	d["signals"] = sigs;
 	d["signals"] = sigs;
 
 
 	Array funcs;
 	Array funcs;
-	List<StringName> func_names;
-	functions.get_key_list(&func_names);
-	for (const StringName &E : func_names) {
+	for (const KeyValue<StringName, Function> &E : functions) {
 		Dictionary func;
 		Dictionary func;
-		func["name"] = E;
-		func["function_id"] = functions[E].func_id;
+		func["name"] = E.key;
+		func["function_id"] = E.value.func_id;
 		funcs.push_back(func);
 		funcs.push_back(func);
 	}
 	}
 	d["functions"] = funcs;
 	d["functions"] = funcs;
 
 
 	Array nds;
 	Array nds;
-	List<int> node_ids;
-	nodes.get_key_list(&node_ids);
-	for (const int &F : node_ids) {
-		nds.push_back(F);
-		nds.push_back(nodes[F].pos);
-		nds.push_back(nodes[F].node);
+	for (const KeyValue<int, NodeData> &F : nodes) {
+		nds.push_back(F.key);
+		nds.push_back(F.value.pos);
+		nds.push_back(F.value.node);
 	}
 	}
 	d["nodes"] = nds;
 	d["nodes"] = nds;
 
 
@@ -1199,10 +1183,8 @@ Set<int> VisualScript::get_output_sequence_ports_connected(int from_node) {
 
 
 VisualScript::~VisualScript() {
 VisualScript::~VisualScript() {
 	// Remove all nodes and stuff that hold data refs.
 	// Remove all nodes and stuff that hold data refs.
-	List<int> nds;
-	nodes.get_key_list(&nds);
-	for (const int &E : nds) {
-		remove_node(E);
+	for (const KeyValue<int, NodeData> &E : nodes) {
+		remove_node(E.key);
 	}
 	}
 }
 }
 
 
@@ -1230,14 +1212,12 @@ bool VisualScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
 }
 }
 
 
 void VisualScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const {
 void VisualScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const {
-	List<StringName> vars;
-	script->variables.get_key_list(&vars);
-	for (const StringName &E : vars) {
-		if (!script->variables[E]._export) {
+	for (const KeyValue<StringName, VisualScript::Variable> &E : script->variables) {
+		if (!E.value._export) {
 			continue;
 			continue;
 		}
 		}
-		PropertyInfo p = script->variables[E].info;
-		p.name = String(E);
+		PropertyInfo p = E.value.info;
+		p.name = String(E.key);
 		p.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE;
 		p.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE;
 		p_properties->push_back(p);
 		p_properties->push_back(p);
 	}
 	}
@@ -1259,13 +1239,11 @@ Variant::Type VisualScriptInstance::get_property_type(const StringName &p_name,
 }
 }
 
 
 void VisualScriptInstance::get_method_list(List<MethodInfo> *p_list) const {
 void VisualScriptInstance::get_method_list(List<MethodInfo> *p_list) const {
-	List<StringName> fns;
-	script->functions.get_key_list(&fns);
-	for (const StringName &E : fns) {
+	for (const KeyValue<StringName, VisualScript::Function> &E : script->functions) {
 		MethodInfo mi;
 		MethodInfo mi;
-		mi.name = E;
-		if (script->functions[E].func_id >= 0 && script->nodes.has(script->functions[E].func_id)) {
-			Ref<VisualScriptFunction> vsf = script->nodes[script->functions[E].func_id].node;
+		mi.name = E.key;
+		if (E.value.func_id >= 0 && script->nodes.has(E.value.func_id)) {
+			Ref<VisualScriptFunction> vsf = script->nodes[E.value.func_id].node;
 			if (vsf.is_valid()) {
 			if (vsf.is_valid()) {
 				for (int i = 0; i < vsf->get_argument_count(); i++) {
 				for (int i = 0; i < vsf->get_argument_count(); i++) {
 					PropertyInfo arg;
 					PropertyInfo arg;
@@ -1845,19 +1823,15 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
 
 
 	// Setup variables.
 	// Setup variables.
 	{
 	{
-		List<StringName> keys;
-		script->variables.get_key_list(&keys);
-		for (const StringName &E : keys) {
-			variables[E] = script->variables[E].default_value;
+		for (const KeyValue<StringName, VisualScript::Variable> &E : script->variables) {
+			variables[E.key] = E.value.default_value;
 		}
 		}
 	}
 	}
 
 
 	// Setup functions from sequence trees.
 	// Setup functions from sequence trees.
 	{
 	{
-		List<StringName> keys;
-		script->functions.get_key_list(&keys);
-		for (const StringName &E : keys) {
-			const VisualScript::Function vsfn = p_script->functions[E];
+		for (const KeyValue<StringName, VisualScript::Function> &E : script->functions) {
+			const VisualScript::Function &vsfn = E.value;
 			Function function;
 			Function function;
 			function.node = vsfn.func_id;
 			function.node = vsfn.func_id;
 			function.max_stack = 0;
 			function.max_stack = 0;
@@ -1868,7 +1842,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
 			Map<StringName, int> local_var_indices;
 			Map<StringName, int> local_var_indices;
 
 
 			if (function.node < 0) {
 			if (function.node < 0) {
-				VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(), 0, "No start node in function: " + String(E));
+				VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(), 0, "No start node in function: " + String(E.key));
 				ERR_CONTINUE(function.node < 0);
 				ERR_CONTINUE(function.node < 0);
 			}
 			}
 
 
@@ -1876,7 +1850,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
 				Ref<VisualScriptFunction> func_node = script->get_node(vsfn.func_id);
 				Ref<VisualScriptFunction> func_node = script->get_node(vsfn.func_id);
 
 
 				if (func_node.is_null()) {
 				if (func_node.is_null()) {
-					VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(), 0, "No VisualScriptFunction typed start node in function: " + String(E));
+					VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(), 0, "No VisualScriptFunction typed start node in function: " + String(E.key));
 				}
 				}
 
 
 				ERR_CONTINUE(!func_node.is_valid());
 				ERR_CONTINUE(!func_node.is_valid());
@@ -1916,13 +1890,12 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
 				List<int> dc_keys;
 				List<int> dc_keys;
 				while (!nd_queue.is_empty()) {
 				while (!nd_queue.is_empty()) {
 					int ky = nd_queue.front()->get();
 					int ky = nd_queue.front()->get();
-					dc_lut[ky].get_key_list(&dc_keys);
-					for (const int &F : dc_keys) {
+					for (const KeyValue<int, Pair<int, int>> &F : dc_lut[ky]) {
 						VisualScript::DataConnection dc;
 						VisualScript::DataConnection dc;
-						dc.from_node = dc_lut[ky][F].first;
-						dc.from_port = dc_lut[ky][F].second;
+						dc.from_node = F.value.first;
+						dc.from_port = F.value.second;
 						dc.to_node = ky;
 						dc.to_node = ky;
-						dc.to_port = F;
+						dc.to_port = F.key;
 						dataconns.insert(dc);
 						dataconns.insert(dc);
 						nd_queue.push_back(dc.from_node);
 						nd_queue.push_back(dc.from_node);
 						node_ids.insert(dc.from_node);
 						node_ids.insert(dc.from_node);
@@ -2072,7 +2045,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
 				}
 				}
 			}
 			}
 
 
-			functions[E] = function;
+			functions[E.key] = function;
 		}
 		}
 	}
 	}
 }
 }

+ 10 - 15
platform/iphone/export/export_plugin.cpp

@@ -107,16 +107,13 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
 	for (int i = 0; i < found_plugins.size(); i++) {
 	for (int i = 0; i < found_plugins.size(); i++) {
 		// Editable plugin plist values
 		// Editable plugin plist values
 		PluginConfigIOS plugin = found_plugins[i];
 		PluginConfigIOS plugin = found_plugins[i];
-		const String *K = nullptr;
 
 
-		while ((K = plugin.plist.next(K))) {
-			String key = *K;
-			PluginConfigIOS::PlistItem item = plugin.plist[key];
-			switch (item.type) {
+		for (const KeyValue<String, PluginConfigIOS::PlistItem> &E : plugin.plist) {
+			switch (E.value.type) {
 				case PluginConfigIOS::PlistItemType::STRING_INPUT: {
 				case PluginConfigIOS::PlistItemType::STRING_INPUT: {
-					String preset_name = "plugins_plist/" + key;
+					String preset_name = "plugins_plist/" + E.key;
 					if (!plist_keys.has(preset_name)) {
 					if (!plist_keys.has(preset_name)) {
-						r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, preset_name), item.value));
+						r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, preset_name), E.value.value));
 						plist_keys.insert(preset_name);
 						plist_keys.insert(preset_name);
 					}
 					}
 				} break;
 				} break;
@@ -1258,11 +1255,10 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset>
 
 
 		// Plist
 		// Plist
 		// Using hash map container to remove duplicates
 		// Using hash map container to remove duplicates
-		const String *K = nullptr;
 
 
-		while ((K = plugin.plist.next(K))) {
-			String key = *K;
-			PluginConfigIOS::PlistItem item = plugin.plist[key];
+		for (const KeyValue<String, PluginConfigIOS::PlistItem> &E : plugin.plist) {
+			String key = E.key;
+			const PluginConfigIOS::PlistItem &item = E.value;
 
 
 			String value;
 			String value;
 
 
@@ -1301,10 +1297,9 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref<EditorExportPreset>
 
 
 	// Updating `Info.plist`
 	// Updating `Info.plist`
 	{
 	{
-		const String *K = nullptr;
-		while ((K = plist_values.next(K))) {
-			String key = *K;
-			String value = plist_values[key];
+		for (const KeyValue<String, String> &E : plist_values) {
+			String key = E.key;
+			String value = E.value;
 
 
 			if (key.is_empty() || value.is_empty()) {
 			if (key.is_empty() || value.is_empty()) {
 				continue;
 				continue;

+ 14 - 20
scene/animation/animation_tree.cpp

@@ -198,12 +198,11 @@ double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<Stri
 			blendw[i] = 0.0; //all to zero by default
 			blendw[i] = 0.0; //all to zero by default
 		}
 		}
 
 
-		const NodePath *K = nullptr;
-		while ((K = filter.next(K))) {
-			if (!state->track_map.has(*K)) {
+		for (const KeyValue<NodePath, bool> &E : filter) {
+			if (!state->track_map.has(E.key)) {
 				continue;
 				continue;
 			}
 			}
-			int idx = state->track_map[*K];
+			int idx = state->track_map[E.key];
 			blendw[idx] = 1.0; //filtered goes to one
 			blendw[idx] = 1.0; //filtered goes to one
 		}
 		}
 
 
@@ -374,9 +373,8 @@ bool AnimationNode::has_filter() const {
 Array AnimationNode::_get_filters() const {
 Array AnimationNode::_get_filters() const {
 	Array paths;
 	Array paths;
 
 
-	const NodePath *K = nullptr;
-	while ((K = filter.next(K))) {
-		paths.push_back(String(*K)); //use strings, so sorting is possible
+	for (const KeyValue<NodePath, bool> &E : filter) {
+		paths.push_back(String(E.key)); //use strings, so sorting is possible
 	}
 	}
 	paths.sort(); //done so every time the scene is saved, it does not change
 	paths.sort(); //done so every time the scene is saved, it does not change
 
 
@@ -803,11 +801,10 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
 
 
 	List<NodePath> to_delete;
 	List<NodePath> to_delete;
 
 
-	const NodePath *K = nullptr;
-	while ((K = track_cache.next(K))) {
-		TrackCache *tc = track_cache[*K];
+	for (const KeyValue<NodePath, TrackCache *> &K : track_cache) {
+		TrackCache *tc = track_cache[K.key];
 		if (tc->setup_pass != setup_pass) {
 		if (tc->setup_pass != setup_pass) {
-			to_delete.push_back(*K);
+			to_delete.push_back(K.key);
 		}
 		}
 	}
 	}
 
 
@@ -820,10 +817,9 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
 
 
 	state.track_map.clear();
 	state.track_map.clear();
 
 
-	K = nullptr;
 	int idx = 0;
 	int idx = 0;
-	while ((K = track_cache.next(K))) {
-		state.track_map[*K] = idx;
+	for (const KeyValue<NodePath, TrackCache *> &K : track_cache) {
+		state.track_map[K.key] = idx;
 		idx++;
 		idx++;
 	}
 	}
 
 
@@ -835,9 +831,8 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
 }
 }
 
 
 void AnimationTree::_clear_caches() {
 void AnimationTree::_clear_caches() {
-	const NodePath *K = nullptr;
-	while ((K = track_cache.next(K))) {
-		memdelete(track_cache[*K]);
+	for (KeyValue<NodePath, TrackCache *> &K : track_cache) {
+		memdelete(K.value);
 	}
 	}
 	playing_caches.clear();
 	playing_caches.clear();
 
 
@@ -1569,9 +1564,8 @@ void AnimationTree::_process_graph(double p_delta) {
 
 
 	{
 	{
 		// finally, set the tracks
 		// finally, set the tracks
-		const NodePath *K = nullptr;
-		while ((K = track_cache.next(K))) {
-			TrackCache *track = track_cache[*K];
+		for (const KeyValue<NodePath, TrackCache *> &K : track_cache) {
+			TrackCache *track = K.value;
 			if (track->process_pass != process_pass) {
 			if (track->process_pass != process_pass) {
 				continue; //not processed, ignore
 				continue; //not processed, ignore
 			}
 			}

+ 3 - 1
scene/gui/code_edit.cpp

@@ -3036,7 +3036,9 @@ void CodeEdit::_text_changed() {
 
 
 	lc = get_line_count();
 	lc = get_line_count();
 	List<int> breakpoints;
 	List<int> breakpoints;
-	breakpointed_lines.get_key_list(&breakpoints);
+	for (const KeyValue<int, bool> &E : breakpointed_lines) {
+		breakpoints.push_back(E.key);
+	}
 	for (const int &line : breakpoints) {
 	for (const int &line : breakpoints) {
 		if (line < lines_edited_from || (line < lc && is_line_breakpointed(line))) {
 		if (line < lines_edited_from || (line < lc && is_line_breakpointed(line))) {
 			continue;
 			continue;

+ 11 - 11
scene/gui/graph_edit.cpp

@@ -523,7 +523,7 @@ void GraphEdit::_update_comment_enclosed_nodes_list(GraphNode *p_node, HashMap<S
 		}
 		}
 	}
 	}
 
 
-	p_comment_enclosed_nodes.set(p_node->get_name(), enclosed_nodes);
+	p_comment_enclosed_nodes.insert(p_node->get_name(), enclosed_nodes);
 }
 }
 
 
 void GraphEdit::_set_drag_comment_enclosed_nodes(GraphNode *p_node, HashMap<StringName, Vector<GraphNode *>> &p_comment_enclosed_nodes, bool p_drag) {
 void GraphEdit::_set_drag_comment_enclosed_nodes(GraphNode *p_node, HashMap<StringName, Vector<GraphNode *>> &p_comment_enclosed_nodes, bool p_drag) {
@@ -1742,11 +1742,11 @@ HashMap<int, Vector<StringName>> GraphEdit::_layering(const Set<StringName> &r_s
 				Vector<StringName> t;
 				Vector<StringName> t;
 				t.push_back(E->get());
 				t.push_back(E->get());
 				if (!l.has(current_layer)) {
 				if (!l.has(current_layer)) {
-					l.set(current_layer, Vector<StringName>{});
+					l.insert(current_layer, Vector<StringName>{});
 				}
 				}
 				selected = true;
 				selected = true;
 				t.append_array(l[current_layer]);
 				t.append_array(l[current_layer]);
-				l.set(current_layer, t);
+				l.insert(current_layer, t);
 				Set<StringName> V;
 				Set<StringName> V;
 				V.insert(E->get());
 				V.insert(E->get());
 				_set_operations(GraphEdit::UNION, u, V);
 				_set_operations(GraphEdit::UNION, u, V);
@@ -1860,10 +1860,10 @@ void GraphEdit::_crossing_minimisation(HashMap<int, Vector<StringName>> &r_layer
 				}
 				}
 				d[q] = crossings;
 				d[q] = crossings;
 			}
 			}
-			c.set(p, d);
+			c.insert(p, d);
 		}
 		}
 
 
-		r_layers.set(i, _split(lower_layer, c));
+		r_layers.insert(i, _split(lower_layer, c));
 	}
 	}
 }
 }
 
 
@@ -2026,7 +2026,7 @@ void GraphEdit::_place_block(StringName p_v, float p_delta, const HashMap<int, V
 			threshold = _calculate_threshold(p_v, w, r_node_name, r_layers, r_root, r_align, r_inner_shift, threshold, r_node_positions);
 			threshold = _calculate_threshold(p_v, w, r_node_name, r_layers, r_root, r_align, r_inner_shift, threshold, r_node_positions);
 			w = r_align[w];
 			w = r_align[w];
 		} while (w != p_v);
 		} while (w != p_v);
-		r_node_positions.set(p_v, pos);
+		r_node_positions.insert(p_v, pos);
 	}
 	}
 
 
 #undef PRED
 #undef PRED
@@ -2082,10 +2082,10 @@ void GraphEdit::arrange_nodes() {
 							ports = p_ports;
 							ports = p_ports;
 						}
 						}
 					}
 					}
-					port_info.set(_connection, ports);
+					port_info.insert(_connection, ports);
 				}
 				}
 			}
 			}
-			upper_neighbours.set(gn->get_name(), s);
+			upper_neighbours.insert(gn->get_name(), s);
 		}
 		}
 	}
 	}
 
 
@@ -2109,7 +2109,7 @@ void GraphEdit::arrange_nodes() {
 		inner_shift[E->get()] = 0.0f;
 		inner_shift[E->get()] = 0.0f;
 		sink[E->get()] = E->get();
 		sink[E->get()] = E->get();
 		shift[E->get()] = FLT_MAX;
 		shift[E->get()] = FLT_MAX;
-		new_positions.set(E->get(), default_position);
+		new_positions.insert(E->get(), default_position);
 		if ((StringName)root[E->get()] == E->get()) {
 		if ((StringName)root[E->get()] == E->get()) {
 			block_heads.insert(E->get());
 			block_heads.insert(E->get());
 		}
 		}
@@ -2129,7 +2129,7 @@ void GraphEdit::arrange_nodes() {
 		do {
 		do {
 			Vector2 cal_pos;
 			Vector2 cal_pos;
 			cal_pos.y = start_from + (real_t)inner_shift[u];
 			cal_pos.y = start_from + (real_t)inner_shift[u];
-			new_positions.set(u, cal_pos);
+			new_positions.insert(u, cal_pos);
 			u = align[u];
 			u = align[u];
 		} while (u != E->get());
 		} while (u != E->get());
 	}
 	}
@@ -2161,7 +2161,7 @@ void GraphEdit::arrange_nodes() {
 				}
 				}
 				cal_pos.x = current_node_start_pos;
 				cal_pos.x = current_node_start_pos;
 			}
 			}
-			new_positions.set(layer[j], cal_pos);
+			new_positions.insert(layer[j], cal_pos);
 		}
 		}
 
 
 		start_from += largest_node_size + gap_h;
 		start_from += largest_node_size + gap_h;

+ 2 - 2
scene/main/missing_node.cpp

@@ -53,8 +53,8 @@ bool MissingNode::_get(const StringName &p_name, Variant &r_ret) const {
 }
 }
 
 
 void MissingNode::_get_property_list(List<PropertyInfo> *p_list) const {
 void MissingNode::_get_property_list(List<PropertyInfo> *p_list) const {
-	for (OrderedHashMap<StringName, Variant>::ConstElement E = properties.front(); E; E = E.next()) {
-		p_list->push_back(PropertyInfo(E.value().get_type(), E.key()));
+	for (const KeyValue<StringName, Variant> &E : properties) {
+		p_list->push_back(PropertyInfo(E.value.get_type(), E.key));
 	}
 	}
 }
 }
 
 

+ 1 - 1
scene/main/missing_node.h

@@ -36,7 +36,7 @@
 
 
 class MissingNode : public Node {
 class MissingNode : public Node {
 	GDCLASS(MissingNode, Node)
 	GDCLASS(MissingNode, Node)
-	OrderedHashMap<StringName, Variant> properties;
+	HashMap<StringName, Variant> properties;
 
 
 	String original_class;
 	String original_class;
 	bool recording_properties = false;
 	bool recording_properties = false;

+ 5 - 7
scene/main/scene_tree.cpp

@@ -438,9 +438,8 @@ bool SceneTree::process(double p_time) {
 
 
 	if (multiplayer_poll) {
 	if (multiplayer_poll) {
 		multiplayer->poll();
 		multiplayer->poll();
-		const NodePath *rpath = nullptr;
-		while ((rpath = custom_multiplayers.next(rpath))) {
-			custom_multiplayers[*rpath]->poll();
+		for (KeyValue<NodePath, Ref<MultiplayerAPI>> &E : custom_multiplayers) {
+			E.value->poll();
 		}
 		}
 	}
 	}
 
 
@@ -1137,9 +1136,8 @@ Array SceneTree::get_processed_tweens() {
 
 
 Ref<MultiplayerAPI> SceneTree::get_multiplayer(const NodePath &p_for_path) const {
 Ref<MultiplayerAPI> SceneTree::get_multiplayer(const NodePath &p_for_path) const {
 	Ref<MultiplayerAPI> out = multiplayer;
 	Ref<MultiplayerAPI> out = multiplayer;
-	const NodePath *spath = nullptr;
-	while ((spath = custom_multiplayers.next(spath))) {
-		const Vector<StringName> snames = (*spath).get_names();
+	for (const KeyValue<NodePath, Ref<MultiplayerAPI>> &E : custom_multiplayers) {
+		const Vector<StringName> snames = E.key.get_names();
 		const Vector<StringName> tnames = p_for_path.get_names();
 		const Vector<StringName> tnames = p_for_path.get_names();
 		if (tnames.size() < snames.size()) {
 		if (tnames.size() < snames.size()) {
 			continue;
 			continue;
@@ -1154,7 +1152,7 @@ Ref<MultiplayerAPI> SceneTree::get_multiplayer(const NodePath &p_for_path) const
 			}
 			}
 		}
 		}
 		if (valid) {
 		if (valid) {
-			out = custom_multiplayers[*spath];
+			out = E.value;
 			break;
 			break;
 		}
 		}
 	}
 	}

+ 9 - 11
scene/main/shader_globals_override.cpp

@@ -229,20 +229,19 @@ void ShaderGlobalsOverride::_activate() {
 		active = true;
 		active = true;
 		add_to_group(SceneStringNames::get_singleton()->shader_overrides_group_active);
 		add_to_group(SceneStringNames::get_singleton()->shader_overrides_group_active);
 
 
-		const StringName *K = nullptr;
-		while ((K = overrides.next(K))) {
-			Override *o = overrides.getptr(*K);
+		for (const KeyValue<StringName, Override> &E : overrides) {
+			const Override *o = &E.value;
 			if (o->in_use && o->override.get_type() != Variant::NIL) {
 			if (o->in_use && o->override.get_type() != Variant::NIL) {
 				if (o->override.get_type() == Variant::OBJECT) {
 				if (o->override.get_type() == Variant::OBJECT) {
 					RID tex_rid = o->override;
 					RID tex_rid = o->override;
-					RS::get_singleton()->global_variable_set_override(*K, tex_rid);
+					RS::get_singleton()->global_variable_set_override(E.key, tex_rid);
 				} else {
 				} else {
-					RS::get_singleton()->global_variable_set_override(*K, o->override);
+					RS::get_singleton()->global_variable_set_override(E.key, o->override);
 				}
 				}
 			}
 			}
-		}
 
 
-		update_configuration_warnings(); //may have activated
+			update_configuration_warnings(); //may have activated
+		}
 	}
 	}
 }
 }
 
 
@@ -256,11 +255,10 @@ void ShaderGlobalsOverride::_notification(int p_what) {
 		case Node3D::NOTIFICATION_EXIT_TREE: {
 		case Node3D::NOTIFICATION_EXIT_TREE: {
 			if (active) {
 			if (active) {
 				//remove overrides
 				//remove overrides
-				const StringName *K = nullptr;
-				while ((K = overrides.next(K))) {
-					Override *o = overrides.getptr(*K);
+				for (const KeyValue<StringName, Override> &E : overrides) {
+					const Override *o = &E.value;
 					if (o->in_use) {
 					if (o->in_use) {
-						RS::get_singleton()->global_variable_set_override(*K, Variant());
+						RS::get_singleton()->global_variable_set_override(E.key, Variant());
 					}
 					}
 				}
 				}
 			}
 			}

+ 3 - 3
scene/multiplayer/multiplayer_spawner.cpp

@@ -91,9 +91,9 @@ void MultiplayerSpawner::_notification(int p_what) {
 
 
 		case NOTIFICATION_EXIT_TREE: {
 		case NOTIFICATION_EXIT_TREE: {
 			_update_spawn_node();
 			_update_spawn_node();
-			const ObjectID *oid = nullptr;
-			while ((oid = tracked_nodes.next(oid))) {
-				Node *node = Object::cast_to<Node>(ObjectDB::get_instance(*oid));
+
+			for (const KeyValue<ObjectID, SpawnInfo> &E : tracked_nodes) {
+				Node *node = Object::cast_to<Node>(ObjectDB::get_instance(E.key));
 				ERR_CONTINUE(!node);
 				ERR_CONTINUE(!node);
 				node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &MultiplayerSpawner::_node_exit));
 				node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &MultiplayerSpawner::_node_exit));
 				// This is unlikely, but might still crash the engine.
 				// This is unlikely, but might still crash the engine.

+ 2 - 4
scene/multiplayer/scene_cache_interface.cpp

@@ -50,10 +50,8 @@ void SceneCacheInterface::on_peer_change(int p_id, bool p_connected) {
 		path_get_cache.erase(p_id);
 		path_get_cache.erase(p_id);
 		// Cleanup sent cache.
 		// Cleanup sent cache.
 		// Some refactoring is needed to make this faster and do paths GC.
 		// Some refactoring is needed to make this faster and do paths GC.
-		List<NodePath> keys;
-		path_send_cache.get_key_list(&keys);
-		for (const NodePath &E : keys) {
-			PathSentCache *psc = path_send_cache.getptr(E);
+		for (const KeyValue<NodePath, PathSentCache> &E : path_send_cache) {
+			PathSentCache *psc = path_send_cache.getptr(E.key);
 			psc->confirmed_peers.erase(p_id);
 			psc->confirmed_peers.erase(p_id);
 		}
 		}
 	}
 	}

+ 2 - 3
scene/multiplayer/scene_replication_interface.cpp

@@ -49,9 +49,8 @@ void SceneReplicationInterface::make_default() {
 
 
 void SceneReplicationInterface::_free_remotes(int p_id) {
 void SceneReplicationInterface::_free_remotes(int p_id) {
 	const HashMap<uint32_t, ObjectID> remotes = rep_state->peer_get_remotes(p_id);
 	const HashMap<uint32_t, ObjectID> remotes = rep_state->peer_get_remotes(p_id);
-	const uint32_t *k = nullptr;
-	while ((k = remotes.next(k))) {
-		Node *node = rep_state->get_node(remotes.get(*k));
+	for (const KeyValue<uint32_t, ObjectID> &E : remotes) {
+		Node *node = rep_state->get_node(E.value);
 		ERR_CONTINUE(!node);
 		ERR_CONTINUE(!node);
 		node->queue_delete();
 		node->queue_delete();
 	}
 	}

+ 8 - 12
scene/multiplayer/scene_replication_state.cpp

@@ -55,9 +55,8 @@ void SceneReplicationState::_untrack(const ObjectID &p_id) {
 		}
 		}
 		// If we spawned or synced it, we need to remove it from any peer it was sent to.
 		// If we spawned or synced it, we need to remove it from any peer it was sent to.
 		if (net_id || peer == 0) {
 		if (net_id || peer == 0) {
-			const int *k = nullptr;
-			while ((k = peers_info.next(k))) {
-				peers_info.get(*k).known_nodes.erase(p_id);
+			for (KeyValue<int, PeerInfo> &E : peers_info) {
+				E.value.known_nodes.erase(p_id);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -134,9 +133,8 @@ void SceneReplicationState::reset() {
 	peers_info.clear();
 	peers_info.clear();
 	known_peers.clear();
 	known_peers.clear();
 	// Tracked nodes are cleared on deletion, here we only reset the ids so they can be later re-assigned.
 	// Tracked nodes are cleared on deletion, here we only reset the ids so they can be later re-assigned.
-	const ObjectID *oid = nullptr;
-	while ((oid = tracked_nodes.next(oid))) {
-		TrackedNode &tobj = tracked_nodes[*oid];
+	for (KeyValue<ObjectID, TrackedNode> &E : tracked_nodes) {
+		TrackedNode &tobj = E.value;
 		tobj.net_id = 0;
 		tobj.net_id = 0;
 		tobj.remote_peer = 0;
 		tobj.remote_peer = 0;
 		tobj.last_sync = 0;
 		tobj.last_sync = 0;
@@ -195,9 +193,8 @@ Error SceneReplicationState::peer_add_node(int p_peer, const ObjectID &p_id) {
 		ERR_FAIL_COND_V(!peers_info.has(p_peer), ERR_INVALID_PARAMETER);
 		ERR_FAIL_COND_V(!peers_info.has(p_peer), ERR_INVALID_PARAMETER);
 		peers_info[p_peer].known_nodes.insert(p_id);
 		peers_info[p_peer].known_nodes.insert(p_id);
 	} else {
 	} else {
-		const int *pid = nullptr;
-		while ((pid = peers_info.next(pid))) {
-			peers_info.get(*pid).known_nodes.insert(p_id);
+		for (KeyValue<int, PeerInfo> &E : peers_info) {
+			E.value.known_nodes.insert(p_id);
 		}
 		}
 	}
 	}
 	return OK;
 	return OK;
@@ -208,9 +205,8 @@ Error SceneReplicationState::peer_del_node(int p_peer, const ObjectID &p_id) {
 		ERR_FAIL_COND_V(!peers_info.has(p_peer), ERR_INVALID_PARAMETER);
 		ERR_FAIL_COND_V(!peers_info.has(p_peer), ERR_INVALID_PARAMETER);
 		peers_info[p_peer].known_nodes.erase(p_id);
 		peers_info[p_peer].known_nodes.erase(p_id);
 	} else {
 	} else {
-		const int *pid = nullptr;
-		while ((pid = peers_info.next(pid))) {
-			peers_info.get(*pid).known_nodes.erase(p_id);
+		for (KeyValue<int, PeerInfo> &E : peers_info) {
+			E.value.known_nodes.erase(p_id);
 		}
 		}
 	}
 	}
 	return OK;
 	return OK;

+ 2 - 2
scene/multiplayer/scene_replication_state.h

@@ -81,8 +81,8 @@ private:
 
 
 public:
 public:
 	const Set<int> get_peers() const { return known_peers; }
 	const Set<int> get_peers() const { return known_peers; }
-	const Set<ObjectID> get_spawned_nodes() const { return spawned_nodes; }
-	const Set<ObjectID> get_path_only_nodes() const { return path_only_nodes; }
+	const Set<ObjectID> &get_spawned_nodes() const { return spawned_nodes; }
+	const Set<ObjectID> &get_path_only_nodes() const { return path_only_nodes; }
 
 
 	MultiplayerSynchronizer *get_synchronizer(const ObjectID &p_id) { return tracked_nodes.has(p_id) ? tracked_nodes[p_id].get_synchronizer() : nullptr; }
 	MultiplayerSynchronizer *get_synchronizer(const ObjectID &p_id) { return tracked_nodes.has(p_id) ? tracked_nodes[p_id].get_synchronizer() : nullptr; }
 	MultiplayerSpawner *get_spawner(const ObjectID &p_id) { return tracked_nodes.has(p_id) ? tracked_nodes[p_id].get_spawner() : nullptr; }
 	MultiplayerSpawner *get_spawner(const ObjectID &p_id) { return tracked_nodes.has(p_id) ? tracked_nodes[p_id].get_spawner() : nullptr; }

+ 4 - 4
scene/resources/packed_scene.cpp

@@ -913,10 +913,10 @@ Error SceneState::pack(Node *p_scene) {
 	}
 	}
 
 
 	variants.resize(variant_map.size());
 	variants.resize(variant_map.size());
-	const Variant *K = nullptr;
-	while ((K = variant_map.next(K))) {
-		int idx = variant_map[*K];
-		variants.write[idx] = *K;
+
+	for (const KeyValue<Variant, int> &E : variant_map) {
+		int idx = E.value;
+		variants.write[idx] = E.key;
 	}
 	}
 
 
 	node_paths.resize(nodepath_map.size());
 	node_paths.resize(nodepath_map.size());

+ 1 - 1
scene/resources/surface_tool.cpp

@@ -1165,7 +1165,7 @@ void SurfaceTool::generate_normals(bool p_flip) {
 		for (int i = 0; i < 3; i++) {
 		for (int i = 0; i < 3; i++) {
 			Vector3 *lv = vertex_hash.getptr(v[i]);
 			Vector3 *lv = vertex_hash.getptr(v[i]);
 			if (!lv) {
 			if (!lv) {
-				vertex_hash.set(v[i], normal);
+				vertex_hash.insert(v[i], normal);
 			} else {
 			} else {
 				(*lv) += normal;
 				(*lv) += normal;
 			}
 			}

+ 88 - 194
scene/resources/theme.cpp

@@ -123,76 +123,50 @@ bool Theme::_get(const StringName &p_name, Variant &r_ret) const {
 void Theme::_get_property_list(List<PropertyInfo> *p_list) const {
 void Theme::_get_property_list(List<PropertyInfo> *p_list) const {
 	List<PropertyInfo> list;
 	List<PropertyInfo> list;
 
 
-	const StringName *key = nullptr;
-
 	// Type variations.
 	// Type variations.
-	while ((key = variation_map.next(key))) {
-		list.push_back(PropertyInfo(Variant::STRING_NAME, String() + *key + "/base_type"));
+	for (const KeyValue<StringName, StringName> &E : variation_map) {
+		list.push_back(PropertyInfo(Variant::STRING_NAME, String() + E.key + "/base_type"));
 	}
 	}
 
 
-	key = nullptr;
-
 	// Icons.
 	// Icons.
-	while ((key = icon_map.next(key))) {
-		const StringName *key2 = nullptr;
-
-		while ((key2 = icon_map[*key].next(key2))) {
-			list.push_back(PropertyInfo(Variant::OBJECT, String() + *key + "/icons/" + *key2, PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL));
+	for (const KeyValue<StringName, HashMap<StringName, Ref<Texture2D>>> &E : icon_map) {
+		for (const KeyValue<StringName, Ref<Texture2D>> &F : E.value) {
+			list.push_back(PropertyInfo(Variant::OBJECT, String() + E.key + "/icons/" + F.key, PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL));
 		}
 		}
 	}
 	}
 
 
-	key = nullptr;
-
 	// Styles.
 	// Styles.
-	while ((key = style_map.next(key))) {
-		const StringName *key2 = nullptr;
-
-		while ((key2 = style_map[*key].next(key2))) {
-			list.push_back(PropertyInfo(Variant::OBJECT, String() + *key + "/styles/" + *key2, PROPERTY_HINT_RESOURCE_TYPE, "StyleBox", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL));
+	for (const KeyValue<StringName, HashMap<StringName, Ref<StyleBox>>> &E : style_map) {
+		for (const KeyValue<StringName, Ref<StyleBox>> &F : E.value) {
+			list.push_back(PropertyInfo(Variant::OBJECT, String() + E.key + "/styles/" + F.key, PROPERTY_HINT_RESOURCE_TYPE, "StyleBox", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL));
 		}
 		}
 	}
 	}
 
 
-	key = nullptr;
-
 	// Fonts.
 	// Fonts.
-	while ((key = font_map.next(key))) {
-		const StringName *key2 = nullptr;
-
-		while ((key2 = font_map[*key].next(key2))) {
-			list.push_back(PropertyInfo(Variant::OBJECT, String() + *key + "/fonts/" + *key2, PROPERTY_HINT_RESOURCE_TYPE, "Font", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL));
+	for (const KeyValue<StringName, HashMap<StringName, Ref<Font>>> &E : font_map) {
+		for (const KeyValue<StringName, Ref<Font>> &F : E.value) {
+			list.push_back(PropertyInfo(Variant::OBJECT, String() + E.key + "/fonts/" + F.key, PROPERTY_HINT_RESOURCE_TYPE, "Font", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL));
 		}
 		}
 	}
 	}
 
 
-	key = nullptr;
-
 	// Font sizes.
 	// Font sizes.
-	while ((key = font_size_map.next(key))) {
-		const StringName *key2 = nullptr;
-
-		while ((key2 = font_size_map[*key].next(key2))) {
-			list.push_back(PropertyInfo(Variant::INT, String() + *key + "/font_sizes/" + *key2, PROPERTY_HINT_RANGE, "0,256,1,or_greater"));
+	for (const KeyValue<StringName, HashMap<StringName, int>> &E : font_size_map) {
+		for (const KeyValue<StringName, int> &F : E.value) {
+			list.push_back(PropertyInfo(Variant::INT, String() + E.key + "/font_sizes/" + F.key, PROPERTY_HINT_RANGE, "0,256,1,or_greater"));
 		}
 		}
 	}
 	}
 
 
-	key = nullptr;
-
 	// Colors.
 	// Colors.
-	while ((key = color_map.next(key))) {
-		const StringName *key2 = nullptr;
-
-		while ((key2 = color_map[*key].next(key2))) {
-			list.push_back(PropertyInfo(Variant::COLOR, String() + *key + "/colors/" + *key2));
+	for (const KeyValue<StringName, HashMap<StringName, Color>> &E : color_map) {
+		for (const KeyValue<StringName, Color> &F : E.value) {
+			list.push_back(PropertyInfo(Variant::INT, String() + E.key + "/colors/" + F.key));
 		}
 		}
 	}
 	}
 
 
-	key = nullptr;
-
 	// Constants.
 	// Constants.
-	while ((key = constant_map.next(key))) {
-		const StringName *key2 = nullptr;
-
-		while ((key2 = constant_map[*key].next(key2))) {
-			list.push_back(PropertyInfo(Variant::INT, String() + *key + "/constants/" + *key2));
+	for (const KeyValue<StringName, HashMap<StringName, int>> &E : constant_map) {
+		for (const KeyValue<StringName, int> &F : E.value) {
+			list.push_back(PropertyInfo(Variant::INT, String() + E.key + "/constants/" + F.key));
 		}
 		}
 	}
 	}
 
 
@@ -414,10 +388,8 @@ void Theme::get_icon_list(StringName p_theme_type, List<StringName> *p_list) con
 		return;
 		return;
 	}
 	}
 
 
-	const StringName *key = nullptr;
-
-	while ((key = icon_map[p_theme_type].next(key))) {
-		p_list->push_back(*key);
+	for (const KeyValue<StringName, Ref<Texture2D>> &E : icon_map[p_theme_type]) {
+		p_list->push_back(E.key);
 	}
 	}
 }
 }
 
 
@@ -437,9 +409,8 @@ void Theme::remove_icon_type(const StringName &p_theme_type) {
 
 
 	_freeze_change_propagation();
 	_freeze_change_propagation();
 
 
-	const StringName *L = nullptr;
-	while ((L = icon_map[p_theme_type].next(L))) {
-		Ref<Texture2D> icon = icon_map[p_theme_type][*L];
+	for (const KeyValue<StringName, Ref<Texture2D>> &E : icon_map[p_theme_type]) {
+		Ref<Texture2D> icon = E.value;
 		if (icon.is_valid()) {
 		if (icon.is_valid()) {
 			icon->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
 			icon->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
 		}
 		}
@@ -453,9 +424,8 @@ void Theme::remove_icon_type(const StringName &p_theme_type) {
 void Theme::get_icon_type_list(List<StringName> *p_list) const {
 void Theme::get_icon_type_list(List<StringName> *p_list) const {
 	ERR_FAIL_NULL(p_list);
 	ERR_FAIL_NULL(p_list);
 
 
-	const StringName *key = nullptr;
-	while ((key = icon_map.next(key))) {
-		p_list->push_back(*key);
+	for (const KeyValue<StringName, HashMap<StringName, Ref<Texture2D>>> &E : icon_map) {
+		p_list->push_back(E.key);
 	}
 	}
 }
 }
 
 
@@ -528,10 +498,8 @@ void Theme::get_stylebox_list(StringName p_theme_type, List<StringName> *p_list)
 		return;
 		return;
 	}
 	}
 
 
-	const StringName *key = nullptr;
-
-	while ((key = style_map[p_theme_type].next(key))) {
-		p_list->push_back(*key);
+	for (const KeyValue<StringName, Ref<StyleBox>> &E : style_map[p_theme_type]) {
+		p_list->push_back(E.key);
 	}
 	}
 }
 }
 
 
@@ -551,9 +519,8 @@ void Theme::remove_stylebox_type(const StringName &p_theme_type) {
 
 
 	_freeze_change_propagation();
 	_freeze_change_propagation();
 
 
-	const StringName *L = nullptr;
-	while ((L = style_map[p_theme_type].next(L))) {
-		Ref<StyleBox> style = style_map[p_theme_type][*L];
+	for (const KeyValue<StringName, Ref<StyleBox>> &E : style_map[p_theme_type]) {
+		Ref<StyleBox> style = E.value;
 		if (style.is_valid()) {
 		if (style.is_valid()) {
 			style->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
 			style->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
 		}
 		}
@@ -567,9 +534,8 @@ void Theme::remove_stylebox_type(const StringName &p_theme_type) {
 void Theme::get_stylebox_type_list(List<StringName> *p_list) const {
 void Theme::get_stylebox_type_list(List<StringName> *p_list) const {
 	ERR_FAIL_NULL(p_list);
 	ERR_FAIL_NULL(p_list);
 
 
-	const StringName *key = nullptr;
-	while ((key = style_map.next(key))) {
-		p_list->push_back(*key);
+	for (const KeyValue<StringName, HashMap<StringName, Ref<StyleBox>>> &E : style_map) {
+		p_list->push_back(E.key);
 	}
 	}
 }
 }
 
 
@@ -644,10 +610,8 @@ void Theme::get_font_list(StringName p_theme_type, List<StringName> *p_list) con
 		return;
 		return;
 	}
 	}
 
 
-	const StringName *key = nullptr;
-
-	while ((key = font_map[p_theme_type].next(key))) {
-		p_list->push_back(*key);
+	for (const KeyValue<StringName, Ref<Font>> &E : font_map[p_theme_type]) {
+		p_list->push_back(E.key);
 	}
 	}
 }
 }
 
 
@@ -667,9 +631,8 @@ void Theme::remove_font_type(const StringName &p_theme_type) {
 
 
 	_freeze_change_propagation();
 	_freeze_change_propagation();
 
 
-	const StringName *L = nullptr;
-	while ((L = font_map[p_theme_type].next(L))) {
-		Ref<Font> font = font_map[p_theme_type][*L];
+	for (const KeyValue<StringName, Ref<Font>> &E : font_map[p_theme_type]) {
+		Ref<Font> font = E.value;
 		if (font.is_valid()) {
 		if (font.is_valid()) {
 			font->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
 			font->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
 		}
 		}
@@ -683,9 +646,8 @@ void Theme::remove_font_type(const StringName &p_theme_type) {
 void Theme::get_font_type_list(List<StringName> *p_list) const {
 void Theme::get_font_type_list(List<StringName> *p_list) const {
 	ERR_FAIL_NULL(p_list);
 	ERR_FAIL_NULL(p_list);
 
 
-	const StringName *key = nullptr;
-	while ((key = font_map.next(key))) {
-		p_list->push_back(*key);
+	for (const KeyValue<StringName, HashMap<StringName, Ref<Font>>> &E : font_map) {
+		p_list->push_back(E.key);
 	}
 	}
 }
 }
 
 
@@ -747,10 +709,8 @@ void Theme::get_font_size_list(StringName p_theme_type, List<StringName> *p_list
 		return;
 		return;
 	}
 	}
 
 
-	const StringName *key = nullptr;
-
-	while ((key = font_size_map[p_theme_type].next(key))) {
-		p_list->push_back(*key);
+	for (const KeyValue<StringName, int> &E : font_size_map[p_theme_type]) {
+		p_list->push_back(E.key);
 	}
 	}
 }
 }
 
 
@@ -774,9 +734,8 @@ void Theme::remove_font_size_type(const StringName &p_theme_type) {
 void Theme::get_font_size_type_list(List<StringName> *p_list) const {
 void Theme::get_font_size_type_list(List<StringName> *p_list) const {
 	ERR_FAIL_NULL(p_list);
 	ERR_FAIL_NULL(p_list);
 
 
-	const StringName *key = nullptr;
-	while ((key = font_size_map.next(key))) {
-		p_list->push_back(*key);
+	for (const KeyValue<StringName, HashMap<StringName, int>> &E : font_size_map) {
+		p_list->push_back(E.key);
 	}
 	}
 }
 }
 
 
@@ -836,10 +795,8 @@ void Theme::get_color_list(StringName p_theme_type, List<StringName> *p_list) co
 		return;
 		return;
 	}
 	}
 
 
-	const StringName *key = nullptr;
-
-	while ((key = color_map[p_theme_type].next(key))) {
-		p_list->push_back(*key);
+	for (const KeyValue<StringName, Color> &E : color_map[p_theme_type]) {
+		p_list->push_back(E.key);
 	}
 	}
 }
 }
 
 
@@ -863,9 +820,8 @@ void Theme::remove_color_type(const StringName &p_theme_type) {
 void Theme::get_color_type_list(List<StringName> *p_list) const {
 void Theme::get_color_type_list(List<StringName> *p_list) const {
 	ERR_FAIL_NULL(p_list);
 	ERR_FAIL_NULL(p_list);
 
 
-	const StringName *key = nullptr;
-	while ((key = color_map.next(key))) {
-		p_list->push_back(*key);
+	for (const KeyValue<StringName, HashMap<StringName, Color>> &E : color_map) {
+		p_list->push_back(E.key);
 	}
 	}
 }
 }
 
 
@@ -925,10 +881,8 @@ void Theme::get_constant_list(StringName p_theme_type, List<StringName> *p_list)
 		return;
 		return;
 	}
 	}
 
 
-	const StringName *key = nullptr;
-
-	while ((key = constant_map[p_theme_type].next(key))) {
-		p_list->push_back(*key);
+	for (const KeyValue<StringName, int> &E : constant_map[p_theme_type]) {
+		p_list->push_back(E.key);
 	}
 	}
 }
 }
 
 
@@ -952,9 +906,8 @@ void Theme::remove_constant_type(const StringName &p_theme_type) {
 void Theme::get_constant_type_list(List<StringName> *p_list) const {
 void Theme::get_constant_type_list(List<StringName> *p_list) const {
 	ERR_FAIL_NULL(p_list);
 	ERR_FAIL_NULL(p_list);
 
 
-	const StringName *key = nullptr;
-	while ((key = constant_map.next(key))) {
-		p_list->push_back(*key);
+	for (const KeyValue<StringName, HashMap<StringName, int>> &E : constant_map) {
+		p_list->push_back(E.key);
 	}
 	}
 }
 }
 
 
@@ -1311,52 +1264,12 @@ void Theme::remove_type(const StringName &p_theme_type) {
 void Theme::get_type_list(List<StringName> *p_list) const {
 void Theme::get_type_list(List<StringName> *p_list) const {
 	ERR_FAIL_NULL(p_list);
 	ERR_FAIL_NULL(p_list);
 
 
-	Set<StringName> types;
-	const StringName *key = nullptr;
-
-	// Icons.
-	while ((key = icon_map.next(key))) {
-		types.insert(*key);
-	}
-
-	key = nullptr;
-
-	// StyleBoxes.
-	while ((key = style_map.next(key))) {
-		types.insert(*key);
-	}
-
-	key = nullptr;
-
-	// Fonts.
-	while ((key = font_map.next(key))) {
-		types.insert(*key);
-	}
-
-	key = nullptr;
-
-	// Font sizes.
-	while ((key = font_size_map.next(key))) {
-		types.insert(*key);
-	}
-
-	key = nullptr;
-
-	// Colors.
-	while ((key = color_map.next(key))) {
-		types.insert(*key);
-	}
-
-	key = nullptr;
-
-	// Constants.
-	while ((key = constant_map.next(key))) {
-		types.insert(*key);
-	}
-
-	for (Set<StringName>::Element *E = types.front(); E; E = E->next()) {
-		p_list->push_back(E->get());
-	}
+	get_icon_type_list(p_list);
+	get_stylebox_type_list(p_list);
+	get_font_type_list(p_list);
+	get_font_size_type_list(p_list);
+	get_color_type_list(p_list);
+	get_constant_type_list(p_list);
 }
 }
 
 
 void Theme::get_type_dependencies(const StringName &p_base_type, const StringName &p_type_variation, List<StringName> *p_list) {
 void Theme::get_type_dependencies(const StringName &p_base_type, const StringName &p_type_variation, List<StringName> *p_list) {
@@ -1667,75 +1580,62 @@ void Theme::merge_with(const Ref<Theme> &p_other) {
 
 
 	// Colors.
 	// Colors.
 	{
 	{
-		const StringName *K = nullptr;
-		while ((K = p_other->color_map.next(K))) {
-			const StringName *L = nullptr;
-			while ((L = p_other->color_map[*K].next(L))) {
-				set_color(*L, *K, p_other->color_map[*K][*L]);
+		for (const KeyValue<StringName, HashMap<StringName, Color>> &E : p_other->color_map) {
+			for (const KeyValue<StringName, Color> &F : E.value) {
+				set_color(F.key, E.key, F.value);
 			}
 			}
 		}
 		}
 	}
 	}
 
 
 	// Constants.
 	// Constants.
 	{
 	{
-		const StringName *K = nullptr;
-		while ((K = p_other->constant_map.next(K))) {
-			const StringName *L = nullptr;
-			while ((L = p_other->constant_map[*K].next(L))) {
-				set_constant(*L, *K, p_other->constant_map[*K][*L]);
+		for (const KeyValue<StringName, HashMap<StringName, int>> &E : p_other->constant_map) {
+			for (const KeyValue<StringName, int> &F : E.value) {
+				set_constant(F.key, E.key, F.value);
 			}
 			}
 		}
 		}
 	}
 	}
 
 
 	// Fonts.
 	// Fonts.
 	{
 	{
-		const StringName *K = nullptr;
-		while ((K = p_other->font_map.next(K))) {
-			const StringName *L = nullptr;
-			while ((L = p_other->font_map[*K].next(L))) {
-				set_font(*L, *K, p_other->font_map[*K][*L]);
+		for (const KeyValue<StringName, HashMap<StringName, Ref<Font>>> &E : p_other->font_map) {
+			for (const KeyValue<StringName, Ref<Font>> &F : E.value) {
+				set_font(F.key, E.key, F.value);
 			}
 			}
 		}
 		}
 	}
 	}
 
 
 	// Font sizes.
 	// Font sizes.
 	{
 	{
-		const StringName *K = nullptr;
-		while ((K = p_other->font_size_map.next(K))) {
-			const StringName *L = nullptr;
-			while ((L = p_other->font_size_map[*K].next(L))) {
-				set_font_size(*L, *K, p_other->font_size_map[*K][*L]);
+		for (const KeyValue<StringName, HashMap<StringName, int>> &E : p_other->font_size_map) {
+			for (const KeyValue<StringName, int> &F : E.value) {
+				set_font_size(F.key, E.key, F.value);
 			}
 			}
 		}
 		}
 	}
 	}
 
 
 	// Icons.
 	// Icons.
 	{
 	{
-		const StringName *K = nullptr;
-		while ((K = p_other->icon_map.next(K))) {
-			const StringName *L = nullptr;
-			while ((L = p_other->icon_map[*K].next(L))) {
-				set_icon(*L, *K, p_other->icon_map[*K][*L]);
+		for (const KeyValue<StringName, HashMap<StringName, Ref<Texture2D>>> &E : p_other->icon_map) {
+			for (const KeyValue<StringName, Ref<Texture2D>> &F : E.value) {
+				set_icon(F.key, E.key, F.value);
 			}
 			}
 		}
 		}
 	}
 	}
 
 
 	// Styleboxes.
 	// Styleboxes.
 	{
 	{
-		const StringName *K = nullptr;
-		while ((K = p_other->style_map.next(K))) {
-			const StringName *L = nullptr;
-			while ((L = p_other->style_map[*K].next(L))) {
-				set_stylebox(*L, *K, p_other->style_map[*K][*L]);
+		for (const KeyValue<StringName, HashMap<StringName, Ref<StyleBox>>> &E : p_other->style_map) {
+			for (const KeyValue<StringName, Ref<StyleBox>> &F : E.value) {
+				set_stylebox(F.key, E.key, F.value);
 			}
 			}
 		}
 		}
 	}
 	}
 
 
 	// Type variations.
 	// Type variations.
 	{
 	{
-		const StringName *K = nullptr;
-		while ((K = p_other->variation_map.next(K))) {
-			set_type_variation(*K, p_other->variation_map[*K]);
+		for (const KeyValue<StringName, StringName> &E : p_other->variation_map) {
+			set_type_variation(E.key, E.value);
 		}
 		}
 	}
 	}
 
 
@@ -1745,12 +1645,10 @@ void Theme::merge_with(const Ref<Theme> &p_other) {
 void Theme::clear() {
 void Theme::clear() {
 	// These items need disconnecting.
 	// These items need disconnecting.
 	{
 	{
-		const StringName *K = nullptr;
-		while ((K = icon_map.next(K))) {
-			const StringName *L = nullptr;
-			while ((L = icon_map[*K].next(L))) {
-				Ref<Texture2D> icon = icon_map[*K][*L];
-				if (icon.is_valid()) {
+		for (const KeyValue<StringName, HashMap<StringName, Ref<Texture2D>>> &E : icon_map) {
+			for (const KeyValue<StringName, Ref<Texture2D>> &F : E.value) {
+				if (F.value.is_valid()) {
+					Ref<Texture2D> icon = F.value;
 					icon->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
 					icon->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
 				}
 				}
 			}
 			}
@@ -1758,12 +1656,10 @@ void Theme::clear() {
 	}
 	}
 
 
 	{
 	{
-		const StringName *K = nullptr;
-		while ((K = style_map.next(K))) {
-			const StringName *L = nullptr;
-			while ((L = style_map[*K].next(L))) {
-				Ref<StyleBox> style = style_map[*K][*L];
-				if (style.is_valid()) {
+		for (const KeyValue<StringName, HashMap<StringName, Ref<StyleBox>>> &E : style_map) {
+			for (const KeyValue<StringName, Ref<StyleBox>> &F : E.value) {
+				if (F.value.is_valid()) {
+					Ref<StyleBox> style = F.value;
 					style->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
 					style->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
 				}
 				}
 			}
 			}
@@ -1771,12 +1667,10 @@ void Theme::clear() {
 	}
 	}
 
 
 	{
 	{
-		const StringName *K = nullptr;
-		while ((K = font_map.next(K))) {
-			const StringName *L = nullptr;
-			while ((L = font_map[*K].next(L))) {
-				Ref<Font> font = font_map[*K][*L];
-				if (font.is_valid()) {
+		for (const KeyValue<StringName, HashMap<StringName, Ref<Font>>> &E : font_map) {
+			for (const KeyValue<StringName, Ref<Font>> &F : E.value) {
+				if (F.value.is_valid()) {
+					Ref<Font> font = F.value;
 					font->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
 					font->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed));
 				}
 				}
 			}
 			}

+ 2 - 3
servers/rendering/renderer_rd/storage_rd/material_storage.cpp

@@ -1959,10 +1959,9 @@ Vector<StringName> MaterialStorage::global_variable_get_list() const {
 		ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance.");
 		ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance.");
 	}
 	}
 
 
-	const StringName *K = nullptr;
 	Vector<StringName> names;
 	Vector<StringName> names;
-	while ((K = global_variables.variables.next(K))) {
-		names.push_back(*K);
+	for (const KeyValue<StringName, GlobalVariables::Variable> &E : global_variables.variables) {
+		names.push_back(E.key);
 	}
 	}
 	names.sort_custom<StringName::AlphCompare>();
 	names.sort_custom<StringName::AlphCompare>();
 	return names;
 	return names;

+ 7 - 8
servers/rendering/renderer_rd/storage_rd/texture_storage.cpp

@@ -1831,13 +1831,13 @@ void TextureStorage::update_decal_atlas() {
 		Vector<DecalAtlas::SortItem> itemsv;
 		Vector<DecalAtlas::SortItem> itemsv;
 		itemsv.resize(decal_atlas.textures.size());
 		itemsv.resize(decal_atlas.textures.size());
 		int base_size = 8;
 		int base_size = 8;
-		const RID *K = nullptr;
 
 
 		int idx = 0;
 		int idx = 0;
-		while ((K = decal_atlas.textures.next(K))) {
+
+		for (const KeyValue<RID, DecalAtlas::Texture> &E : decal_atlas.textures) {
 			DecalAtlas::SortItem &si = itemsv.write[idx];
 			DecalAtlas::SortItem &si = itemsv.write[idx];
 
 
-			Texture *src_tex = get_texture(*K);
+			Texture *src_tex = get_texture(E.key);
 
 
 			si.size.width = (src_tex->width / border) + 1;
 			si.size.width = (src_tex->width / border) + 1;
 			si.size.height = (src_tex->height / border) + 1;
 			si.size.height = (src_tex->height / border) + 1;
@@ -1847,7 +1847,7 @@ void TextureStorage::update_decal_atlas() {
 				base_size = nearest_power_of_2_templated(si.size.width);
 				base_size = nearest_power_of_2_templated(si.size.width);
 			}
 			}
 
 
-			si.texture = *K;
+			si.texture = E.key;
 			idx++;
 			idx++;
 		}
 		}
 
 
@@ -1983,10 +1983,9 @@ void TextureStorage::update_decal_atlas() {
 
 
 				RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(mm.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, cc);
 				RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(mm.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, cc);
 
 
-				const RID *K = nullptr;
-				while ((K = decal_atlas.textures.next(K))) {
-					DecalAtlas::Texture *t = decal_atlas.textures.getptr(*K);
-					Texture *src_tex = get_texture(*K);
+				for (const KeyValue<RID, DecalAtlas::Texture> &E : decal_atlas.textures) {
+					DecalAtlas::Texture *t = decal_atlas.textures.getptr(E.key);
+					Texture *src_tex = get_texture(E.key);
 					copy_effects->copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0);
 					copy_effects->copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0);
 				}
 				}
 
 

+ 3 - 3
servers/rendering/rendering_server_default.cpp

@@ -179,10 +179,10 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
 			print_line("GPU PROFILE (total " + rtos(total_time) + "ms): ");
 			print_line("GPU PROFILE (total " + rtos(total_time) + "ms): ");
 
 
 			float print_threshold = 0.01;
 			float print_threshold = 0.01;
-			for (OrderedHashMap<String, float>::Element E = print_gpu_profile_task_time.front(); E; E = E.next()) {
-				double time = E.value() / double(print_frame_profile_frame_count);
+			for (const KeyValue<String, float> &E : print_gpu_profile_task_time) {
+				double time = E.value / double(print_frame_profile_frame_count);
 				if (time > print_threshold) {
 				if (time > print_threshold) {
-					print_line("\t-" + E.key() + ": " + rtos(time) + "ms");
+					print_line("\t-" + E.key + ": " + rtos(time) + "ms");
 				}
 				}
 			}
 			}
 			print_gpu_profile_task_time.clear();
 			print_gpu_profile_task_time.clear();

+ 2 - 2
servers/rendering/rendering_server_default.h

@@ -33,7 +33,7 @@
 
 
 #include "core/math/octree.h"
 #include "core/math/octree.h"
 #include "core/templates/command_queue_mt.h"
 #include "core/templates/command_queue_mt.h"
-#include "core/templates/ordered_hash_map.h"
+#include "core/templates/hash_map.h"
 #include "renderer_canvas_cull.h"
 #include "renderer_canvas_cull.h"
 #include "renderer_scene_cull.h"
 #include "renderer_scene_cull.h"
 #include "renderer_viewport.h"
 #include "renderer_viewport.h"
@@ -69,7 +69,7 @@ class RenderingServerDefault : public RenderingServer {
 
 
 	//for printing
 	//for printing
 	bool print_gpu_profile = false;
 	bool print_gpu_profile = false;
-	OrderedHashMap<String, float> print_gpu_profile_task_time;
+	HashMap<String, float> print_gpu_profile_task_time;
 	uint64_t print_frame_profile_ticks_from = 0;
 	uint64_t print_frame_profile_ticks_from = 0;
 	uint32_t print_frame_profile_frame_count = 0;
 	uint32_t print_frame_profile_frame_count = 0;
 
 

+ 1 - 1
servers/rendering/shader_types.h

@@ -31,7 +31,7 @@
 #ifndef SHADERTYPES_H
 #ifndef SHADERTYPES_H
 #define SHADERTYPES_H
 #define SHADERTYPES_H
 
 
-#include "core/templates/ordered_hash_map.h"
+#include "core/templates/map.h"
 #include "servers/rendering_server.h"
 #include "servers/rendering_server.h"
 #include "shader_language.h"
 #include "shader_language.h"
 
 

+ 13 - 16
tests/core/object/test_class_db.h

@@ -173,7 +173,7 @@ struct NamesCache {
 	}
 	}
 };
 };
 
 
-typedef OrderedHashMap<StringName, ExposedClass> ExposedClasses;
+typedef HashMap<StringName, ExposedClass> ExposedClasses;
 
 
 struct Context {
 struct Context {
 	Vector<StringName> enum_types;
 	Vector<StringName> enum_types;
@@ -183,13 +183,13 @@ struct Context {
 	NamesCache names_cache;
 	NamesCache names_cache;
 
 
 	const ExposedClass *find_exposed_class(const StringName &p_name) const {
 	const ExposedClass *find_exposed_class(const StringName &p_name) const {
-		ExposedClasses::ConstElement elem = exposed_classes.find(p_name);
-		return elem ? &elem.value() : nullptr;
+		ExposedClasses::ConstIterator elem = exposed_classes.find(p_name);
+		return elem ? &elem->value : nullptr;
 	}
 	}
 
 
 	const ExposedClass *find_exposed_class(const TypeReference &p_type_ref) const {
 	const ExposedClass *find_exposed_class(const TypeReference &p_type_ref) const {
-		ExposedClasses::ConstElement elem = exposed_classes.find(p_type_ref.name);
-		return elem ? &elem.value() : nullptr;
+		ExposedClasses::ConstIterator elem = exposed_classes.find(p_type_ref.name);
+		return elem ? &elem->value : nullptr;
 	}
 	}
 
 
 	bool has_type(const TypeReference &p_type_ref) const {
 	bool has_type(const TypeReference &p_type_ref) const {
@@ -676,12 +676,11 @@ void add_exposed_classes(Context &r_context) {
 		// Add signals
 		// Add signals
 
 
 		const HashMap<StringName, MethodInfo> &signal_map = class_info->signal_map;
 		const HashMap<StringName, MethodInfo> &signal_map = class_info->signal_map;
-		const StringName *k = nullptr;
 
 
-		while ((k = signal_map.next(k))) {
+		for (const KeyValue<StringName, MethodInfo> &K : signal_map) {
 			SignalData signal;
 			SignalData signal;
 
 
-			const MethodInfo &method_info = signal_map.get(*k);
+			const MethodInfo &method_info = signal_map.get(K.key);
 
 
 			signal.name = method_info.name;
 			signal.name = method_info.name;
 
 
@@ -734,14 +733,12 @@ void add_exposed_classes(Context &r_context) {
 		ClassDB::get_integer_constant_list(class_name, &constants, true);
 		ClassDB::get_integer_constant_list(class_name, &constants, true);
 
 
 		const HashMap<StringName, List<StringName>> &enum_map = class_info->enum_map;
 		const HashMap<StringName, List<StringName>> &enum_map = class_info->enum_map;
-		k = nullptr;
 
 
-		while ((k = enum_map.next(k))) {
+		for (const KeyValue<StringName, List<StringName>> &K : enum_map) {
 			EnumData enum_;
 			EnumData enum_;
-			enum_.name = *k;
+			enum_.name = K.key;
 
 
-			const List<StringName> &enum_constants = enum_map.get(*k);
-			for (const StringName &E : enum_constants) {
+			for (const StringName &E : K.value) {
 				const StringName &constant_name = E;
 				const StringName &constant_name = E;
 				TEST_FAIL_COND(String(constant_name).find("::") != -1,
 				TEST_FAIL_COND(String(constant_name).find("::") != -1,
 						"Enum constant contains '::', check bindings to remove the scope: '",
 						"Enum constant contains '::', check bindings to remove the scope: '",
@@ -760,7 +757,7 @@ void add_exposed_classes(Context &r_context) {
 
 
 			exposed_class.enums.push_back(enum_);
 			exposed_class.enums.push_back(enum_);
 
 
-			r_context.enum_types.push_back(String(class_name) + "." + String(*k));
+			r_context.enum_types.push_back(String(class_name) + "." + String(K.key));
 		}
 		}
 
 
 		for (const String &E : constants) {
 		for (const String &E : constants) {
@@ -850,8 +847,8 @@ TEST_SUITE("[ClassDB]") {
 			TEST_FAIL_COND(object_class->base != StringName(),
 			TEST_FAIL_COND(object_class->base != StringName(),
 					"Object class derives from another class: '", object_class->base, "'.");
 					"Object class derives from another class: '", object_class->base, "'.");
 
 
-			for (ExposedClasses::Element E = context.exposed_classes.front(); E; E = E.next()) {
-				validate_class(context, E.value());
+			for (const KeyValue<StringName, ExposedClass> &E : context.exposed_classes) {
+				validate_class(context, E.value);
 			}
 			}
 		}
 		}
 	}
 	}

+ 32 - 34
tests/core/templates/test_ordered_hash_map.h → tests/core/templates/test_hash_map.h

@@ -1,5 +1,5 @@
 /*************************************************************************/
 /*************************************************************************/
-/*  test_ordered_hash_map.h                                              */
+/*  test_hash_map.h                                                      */
 /*************************************************************************/
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
 /*                           GODOT ENGINE                                */
@@ -28,56 +28,53 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 /*************************************************************************/
 
 
-#ifndef TEST_ORDERED_HASH_MAP_H
-#define TEST_ORDERED_HASH_MAP_H
+#ifndef TEST_HASH_MAP_H
+#define TEST_HASH_MAP_H
 
 
-#include "core/templates/ordered_hash_map.h"
+#include "core/templates/hash_map.h"
 
 
 #include "tests/test_macros.h"
 #include "tests/test_macros.h"
 
 
-namespace TestOrderedHashMap {
+namespace TestHashMap {
 
 
-TEST_CASE("[OrderedHashMap] Insert element") {
-	OrderedHashMap<int, int> map;
-	OrderedHashMap<int, int>::Element e = map.insert(42, 84);
+TEST_CASE("[HashMap] Insert element") {
+	HashMap<int, int> map;
+	HashMap<int, int>::Iterator e = map.insert(42, 84);
 
 
 	CHECK(e);
 	CHECK(e);
-	CHECK(e.key() == 42);
-	CHECK(e.get() == 84);
-	CHECK(e.value() == 84);
+	CHECK(e->key == 42);
+	CHECK(e->value == 84);
 	CHECK(map[42] == 84);
 	CHECK(map[42] == 84);
 	CHECK(map.has(42));
 	CHECK(map.has(42));
 	CHECK(map.find(42));
 	CHECK(map.find(42));
 }
 }
 
 
-TEST_CASE("[OrderedHashMap] Overwrite element") {
-	OrderedHashMap<int, int> map;
+TEST_CASE("[HashMap] Overwrite element") {
+	HashMap<int, int> map;
 	map.insert(42, 84);
 	map.insert(42, 84);
 	map.insert(42, 1234);
 	map.insert(42, 1234);
 
 
 	CHECK(map[42] == 1234);
 	CHECK(map[42] == 1234);
 }
 }
 
 
-TEST_CASE("[OrderedHashMap] Erase via element") {
-	OrderedHashMap<int, int> map;
-	OrderedHashMap<int, int>::Element e = map.insert(42, 84);
-
-	map.erase(e);
-	CHECK(!e);
+TEST_CASE("[HashMap] Erase via element") {
+	HashMap<int, int> map;
+	HashMap<int, int>::Iterator e = map.insert(42, 84);
+	map.remove(e);
 	CHECK(!map.has(42));
 	CHECK(!map.has(42));
 	CHECK(!map.find(42));
 	CHECK(!map.find(42));
 }
 }
 
 
-TEST_CASE("[OrderedHashMap] Erase via key") {
-	OrderedHashMap<int, int> map;
+TEST_CASE("[HashMap] Erase via key") {
+	HashMap<int, int> map;
 	map.insert(42, 84);
 	map.insert(42, 84);
 	map.erase(42);
 	map.erase(42);
 	CHECK(!map.has(42));
 	CHECK(!map.has(42));
 	CHECK(!map.find(42));
 	CHECK(!map.find(42));
 }
 }
 
 
-TEST_CASE("[OrderedHashMap] Size") {
-	OrderedHashMap<int, int> map;
+TEST_CASE("[HashMap] Size") {
+	HashMap<int, int> map;
 	map.insert(42, 84);
 	map.insert(42, 84);
 	map.insert(123, 84);
 	map.insert(123, 84);
 	map.insert(123, 84);
 	map.insert(123, 84);
@@ -87,8 +84,8 @@ TEST_CASE("[OrderedHashMap] Size") {
 	CHECK(map.size() == 4);
 	CHECK(map.size() == 4);
 }
 }
 
 
-TEST_CASE("[OrderedHashMap] Iteration") {
-	OrderedHashMap<int, int> map;
+TEST_CASE("[HashMap] Iteration") {
+	HashMap<int, int> map;
 	map.insert(42, 84);
 	map.insert(42, 84);
 	map.insert(123, 12385);
 	map.insert(123, 12385);
 	map.insert(0, 12934);
 	map.insert(0, 12934);
@@ -102,34 +99,35 @@ TEST_CASE("[OrderedHashMap] Iteration") {
 	expected.push_back(Pair<int, int>(123485, 1238888));
 	expected.push_back(Pair<int, int>(123485, 1238888));
 
 
 	int idx = 0;
 	int idx = 0;
-	for (OrderedHashMap<int, int>::Element E = map.front(); E; E = E.next()) {
-		CHECK(expected[idx] == Pair<int, int>(E.key(), E.value()));
+	for (const KeyValue<int, int> &E : map) {
+		CHECK(expected[idx] == Pair<int, int>(E.key, E.value));
 		++idx;
 		++idx;
 	}
 	}
 }
 }
 
 
-TEST_CASE("[OrderedHashMap] Const iteration") {
-	OrderedHashMap<int, int> map;
+TEST_CASE("[HashMap] Const iteration") {
+	HashMap<int, int> map;
 	map.insert(42, 84);
 	map.insert(42, 84);
 	map.insert(123, 12385);
 	map.insert(123, 12385);
 	map.insert(0, 12934);
 	map.insert(0, 12934);
 	map.insert(123485, 1238888);
 	map.insert(123485, 1238888);
 	map.insert(123, 111111);
 	map.insert(123, 111111);
 
 
-	const OrderedHashMap<int, int> const_map = map;
+	const HashMap<int, int> const_map = map;
 
 
 	Vector<Pair<int, int>> expected;
 	Vector<Pair<int, int>> expected;
 	expected.push_back(Pair<int, int>(42, 84));
 	expected.push_back(Pair<int, int>(42, 84));
 	expected.push_back(Pair<int, int>(123, 111111));
 	expected.push_back(Pair<int, int>(123, 111111));
 	expected.push_back(Pair<int, int>(0, 12934));
 	expected.push_back(Pair<int, int>(0, 12934));
 	expected.push_back(Pair<int, int>(123485, 1238888));
 	expected.push_back(Pair<int, int>(123485, 1238888));
+	expected.push_back(Pair<int, int>(123, 111111));
 
 
 	int idx = 0;
 	int idx = 0;
-	for (OrderedHashMap<int, int>::ConstElement E = const_map.front(); E; E = E.next()) {
-		CHECK(expected[idx] == Pair<int, int>(E.key(), E.value()));
+	for (const KeyValue<int, int> &E : const_map) {
+		CHECK(expected[idx] == Pair<int, int>(E.key, E.value));
 		++idx;
 		++idx;
 	}
 	}
 }
 }
-} // namespace TestOrderedHashMap
+} // namespace TestHashMap
 
 
-#endif // TEST_ORDERED_HASH_MAP_H
+#endif // TEST_HASH_MAP_H

+ 1 - 1
tests/test_main.cpp

@@ -59,10 +59,10 @@
 #include "tests/core/string/test_string.h"
 #include "tests/core/string/test_string.h"
 #include "tests/core/string/test_translation.h"
 #include "tests/core/string/test_translation.h"
 #include "tests/core/templates/test_command_queue.h"
 #include "tests/core/templates/test_command_queue.h"
+#include "tests/core/templates/test_hash_map.h"
 #include "tests/core/templates/test_list.h"
 #include "tests/core/templates/test_list.h"
 #include "tests/core/templates/test_local_vector.h"
 #include "tests/core/templates/test_local_vector.h"
 #include "tests/core/templates/test_lru.h"
 #include "tests/core/templates/test_lru.h"
-#include "tests/core/templates/test_ordered_hash_map.h"
 #include "tests/core/templates/test_paged_array.h"
 #include "tests/core/templates/test_paged_array.h"
 #include "tests/core/templates/test_vector.h"
 #include "tests/core/templates/test_vector.h"
 #include "tests/core/test_crypto.h"
 #include "tests/core/test_crypto.h"