summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/csg/csg.cpp19
-rw-r--r--modules/csg/csg.h10
-rw-r--r--modules/csg/csg_shape.cpp48
-rw-r--r--modules/csg/csg_shape.h6
-rw-r--r--modules/csg/doc_classes/CSGPrimitive3D.xml4
-rw-r--r--modules/csg/editor/csg_gizmos.cpp8
-rw-r--r--modules/enet/enet_multiplayer_peer.h4
-rw-r--r--modules/freetype/SCsub3
-rw-r--r--modules/gdscript/doc_classes/@GDScript.xml29
-rw-r--r--modules/gdscript/editor/gdscript_highlighter.cpp9
-rw-r--r--modules/gdscript/editor/gdscript_highlighter.h2
-rw-r--r--modules/gdscript/editor/gdscript_translation_parser_plugin.h8
-rw-r--r--modules/gdscript/gdscript.cpp132
-rw-r--r--modules/gdscript/gdscript.h71
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp49
-rw-r--r--modules/gdscript/gdscript_analyzer.h2
-rw-r--r--modules/gdscript/gdscript_byte_codegen.cpp6
-rw-r--r--modules/gdscript/gdscript_byte_codegen.h42
-rw-r--r--modules/gdscript/gdscript_cache.cpp6
-rw-r--r--modules/gdscript/gdscript_cache.h4
-rw-r--r--modules/gdscript/gdscript_compiler.cpp79
-rw-r--r--modules/gdscript/gdscript_compiler.h14
-rw-r--r--modules/gdscript/gdscript_editor.cpp94
-rw-r--r--modules/gdscript/gdscript_function.cpp9
-rw-r--r--modules/gdscript/gdscript_function.h2
-rw-r--r--modules/gdscript/gdscript_parser.cpp245
-rw-r--r--modules/gdscript/gdscript_parser.h23
-rw-r--r--modules/gdscript/gdscript_tokenizer.cpp10
-rw-r--r--modules/gdscript/gdscript_tokenizer.h10
-rw-r--r--modules/gdscript/gdscript_vm.cpp56
-rw-r--r--modules/gdscript/gdscript_warning.cpp16
-rw-r--r--modules/gdscript/gdscript_warning.h10
-rw-r--r--modules/gdscript/language_server/gdscript_extend_parser.cpp36
-rw-r--r--modules/gdscript/language_server/gdscript_language_protocol.cpp32
-rw-r--r--modules/gdscript/language_server/gdscript_text_document.cpp26
-rw-r--r--modules/gdscript/language_server/gdscript_workspace.cpp76
-rw-r--r--modules/gdscript/language_server/gdscript_workspace.h6
-rw-r--r--modules/gdscript/language_server/lsp.hpp10
-rw-r--r--modules/gdscript/register_types.cpp2
-rw-r--r--modules/gdscript/tests/gdscript_test_runner.cpp14
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/await_with_signals_no_warning.gd12
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/await_with_signals_no_warning.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_default_dict_void.gd14
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_default_dict_void.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/typed_array_assignment.gd2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/typed_array_assignment.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/dollar-assignment-bug-53696.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/lambda_standalone.gd3
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/lambda_standalone.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.gd4
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/nothing_after_dollar.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar_slash.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/features/dollar_and_percent_get_node.gd49
-rw-r--r--modules/gdscript/tests/scripts/parser/features/dollar_and_percent_get_node.out19
-rw-r--r--modules/gdscript/tests/scripts/parser/features/if_after_lambda.gd7
-rw-r--r--modules/gdscript/tests/scripts/parser/features/if_after_lambda.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/features/lambda_default_parameter_capture.gd7
-rw-r--r--modules/gdscript/tests/scripts/parser/features/lambda_default_parameter_capture.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.gd6
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.out4
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/unreachable_code_after_return_bug_55154.gd16
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/unreachable_code_after_return_bug_55154.out2
-rw-r--r--modules/gltf/doc_classes/GLTFDocumentExtension.xml69
-rw-r--r--modules/gltf/doc_classes/GLTFState.xml2
-rw-r--r--modules/gltf/editor/editor_scene_importer_blend.cpp6
-rw-r--r--modules/gltf/editor/editor_scene_importer_blend.h4
-rw-r--r--modules/gltf/editor/editor_scene_importer_fbx.cpp6
-rw-r--r--modules/gltf/editor/editor_scene_importer_fbx.h4
-rw-r--r--modules/gltf/editor/editor_scene_importer_gltf.cpp3
-rw-r--r--modules/gltf/editor/editor_scene_importer_gltf.h5
-rw-r--r--modules/gltf/gltf_accessor.h1
-rw-r--r--modules/gltf/gltf_animation.cpp2
-rw-r--r--modules/gltf/gltf_animation.h4
-rw-r--r--modules/gltf/gltf_document.cpp164
-rw-r--r--modules/gltf/gltf_document.h25
-rw-r--r--modules/gltf/gltf_document_extension.cpp100
-rw-r--r--modules/gltf/gltf_document_extension.h38
-rw-r--r--modules/gltf/gltf_document_extension_convert_importer_mesh.cpp45
-rw-r--r--modules/gltf/gltf_document_extension_convert_importer_mesh.h8
-rw-r--r--modules/gltf/gltf_skeleton.cpp2
-rw-r--r--modules/gltf/gltf_skeleton.h8
-rw-r--r--modules/gltf/gltf_skin.cpp12
-rw-r--r--modules/gltf/gltf_skin.h4
-rw-r--r--modules/gltf/gltf_state.cpp13
-rw-r--r--modules/gltf/gltf_state.h29
-rw-r--r--modules/gridmap/editor/grid_map_editor_plugin.cpp3
-rw-r--r--modules/gridmap/grid_map.cpp33
-rw-r--r--modules/gridmap/grid_map.h21
-rw-r--r--modules/jsonrpc/jsonrpc.h2
-rw-r--r--modules/mbedtls/stream_peer_mbedtls.cpp4
-rw-r--r--modules/mbedtls/stream_peer_mbedtls.h1
-rw-r--r--modules/minimp3/resource_importer_mp3.cpp4
-rw-r--r--modules/minimp3/resource_importer_mp3.h4
-rw-r--r--modules/mono/class_db_api_json.cpp41
-rw-r--r--modules/mono/csharp_script.cpp66
-rw-r--r--modules/mono/csharp_script.h30
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs1
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs3
-rw-r--r--modules/mono/editor/bindings_generator.cpp155
-rw-r--r--modules/mono/editor/bindings_generator.h18
-rw-r--r--modules/mono/editor/code_completion.cpp6
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs5
-rw-r--r--modules/mono/glue/base_object_glue.cpp4
-rw-r--r--modules/mono/managed_callable.cpp2
-rw-r--r--modules/mono/managed_callable.h2
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp25
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.cpp4
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.h4
-rw-r--r--modules/mono/mono_gd/gd_mono_cache.cpp2
-rw-r--r--modules/mono/mono_gd/gd_mono_cache.h1
-rw-r--r--modules/mono/mono_gd/gd_mono_class.cpp39
-rw-r--r--modules/mono/mono_gd/gd_mono_class.h8
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp10
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h1
-rw-r--r--modules/mono/utils/osx_utils.cpp4
-rw-r--r--modules/navigation/godot_navigation_server.cpp38
-rw-r--r--modules/navigation/godot_navigation_server.h5
-rw-r--r--modules/navigation/nav_map.cpp4
-rw-r--r--modules/navigation/nav_map.h8
-rw-r--r--modules/navigation/nav_utils.h12
-rw-r--r--modules/navigation/navigation_mesh_generator.cpp28
-rw-r--r--modules/noise/fastnoise_lite.cpp53
-rw-r--r--modules/noise/fastnoise_lite.h3
-rw-r--r--modules/openxr/editor/openxr_action_editor.cpp3
-rw-r--r--modules/openxr/editor/openxr_action_map_editor.cpp1
-rw-r--r--modules/openxr/extensions/openxr_extension_wrapper.h6
-rw-r--r--modules/openxr/extensions/openxr_vulkan_extension.cpp9
-rw-r--r--modules/openxr/openxr_api.cpp24
-rw-r--r--modules/openxr/openxr_api.h6
-rw-r--r--modules/openxr/openxr_interface.cpp2
-rw-r--r--modules/raycast/lightmap_raycaster.cpp10
-rw-r--r--modules/raycast/lightmap_raycaster.h6
-rw-r--r--modules/raycast/raycast_occlusion_cull.cpp23
-rw-r--r--modules/raycast/raycast_occlusion_cull.h16
-rw-r--r--modules/raycast/static_raycaster.cpp10
-rw-r--r--modules/raycast/static_raycaster.h4
-rw-r--r--modules/regex/regex.cpp8
-rw-r--r--modules/regex/regex.h4
-rw-r--r--modules/svg/image_loader_svg.cpp2
-rw-r--r--modules/text_server_adv/SCsub2
-rw-r--r--modules/text_server_adv/gdextension_build/SConstruct12
-rw-r--r--modules/text_server_adv/text_server_adv.cpp45
-rw-r--r--modules/text_server_adv/text_server_adv.h21
-rw-r--r--modules/text_server_fb/gdextension_build/SConstruct10
-rw-r--r--modules/text_server_fb/text_server_fb.cpp39
-rw-r--r--modules/text_server_fb/text_server_fb.h16
-rw-r--r--modules/visual_script/editor/visual_script_editor.cpp188
-rw-r--r--modules/visual_script/editor/visual_script_editor.h22
-rw-r--r--modules/visual_script/editor/visual_script_property_selector.cpp37
-rw-r--r--modules/visual_script/editor/visual_script_property_selector.h10
-rw-r--r--modules/visual_script/visual_script.cpp315
-rw-r--r--modules/visual_script/visual_script.h33
-rw-r--r--modules/visual_script/visual_script_nodes.cpp2
-rw-r--r--modules/vorbis/audio_stream_ogg_vorbis.cpp3
-rw-r--r--modules/vorbis/resource_importer_ogg_vorbis.cpp4
-rw-r--r--modules/vorbis/resource_importer_ogg_vorbis.h4
-rw-r--r--modules/webrtc/webrtc_data_channel.h2
-rw-r--r--modules/webrtc/webrtc_multiplayer_peer.cpp36
-rw-r--r--modules/webrtc/webrtc_multiplayer_peer.h2
-rw-r--r--modules/websocket/websocket_multiplayer_peer.h2
-rw-r--r--modules/websocket/wsl_client.cpp2
-rw-r--r--modules/websocket/wsl_server.cpp2
164 files changed, 2070 insertions, 1480 deletions
diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp
index 760ee0846d..93533e1690 100644
--- a/modules/csg/csg.cpp
+++ b/modules/csg/csg.cpp
@@ -194,7 +194,7 @@ void CSGBrush::_regen_face_aabbs() {
}
}
-void CSGBrush::build_from_faces(const Vector<Vector3> &p_vertices, const Vector<Vector2> &p_uvs, const Vector<bool> &p_smooth, const Vector<Ref<Material>> &p_materials, const Vector<bool> &p_invert_faces) {
+void CSGBrush::build_from_faces(const Vector<Vector3> &p_vertices, const Vector<Vector2> &p_uvs, const Vector<bool> &p_smooth, const Vector<Ref<Material>> &p_materials, const Vector<bool> &p_flip_faces) {
faces.clear();
int vc = p_vertices.size();
@@ -208,10 +208,10 @@ void CSGBrush::build_from_faces(const Vector<Vector3> &p_vertices, const Vector<
const bool *rs = p_smooth.ptr();
int mc = p_materials.size();
const Ref<Material> *rm = p_materials.ptr();
- int ic = p_invert_faces.size();
- const bool *ri = p_invert_faces.ptr();
+ int ic = p_flip_faces.size();
+ const bool *ri = p_flip_faces.ptr();
- Map<Ref<Material>, int> material_map;
+ HashMap<Ref<Material>, int> material_map;
faces.resize(p_vertices.size() / 3);
@@ -242,10 +242,10 @@ void CSGBrush::build_from_faces(const Vector<Vector3> &p_vertices, const Vector<
if (mc == vc / 3) {
Ref<Material> mat = rm[i];
if (mat.is_valid()) {
- const Map<Ref<Material>, int>::Element *E = material_map.find(mat);
+ HashMap<Ref<Material>, int>::ConstIterator E = material_map.find(mat);
if (E) {
- f.material = E->get();
+ f.material = E->value;
} else {
f.material = material_map.size();
material_map[mat] = f.material;
@@ -1387,13 +1387,13 @@ void CSGBrushOperation::update_faces(const CSGBrush &p_brush_a, const int p_face
}
// Ensure B has points either side of or in the plane of A.
- int in_plane_count = 0, over_count = 0, under_count = 0;
+ int over_count = 0, under_count = 0;
Plane plane_a(vertices_a[0], vertices_a[1], vertices_a[2]);
ERR_FAIL_COND_MSG(plane_a.normal == Vector3(), "Couldn't form plane from Brush A face.");
for (int i = 0; i < 3; i++) {
if (plane_a.has_point(vertices_b[i])) {
- in_plane_count++;
+ // In plane.
} else if (plane_a.is_point_over(vertices_b[i])) {
over_count++;
} else {
@@ -1406,7 +1406,6 @@ void CSGBrushOperation::update_faces(const CSGBrush &p_brush_a, const int p_face
}
// Ensure A has points either side of or in the plane of B.
- in_plane_count = 0;
over_count = 0;
under_count = 0;
Plane plane_b(vertices_b[0], vertices_b[1], vertices_b[2]);
@@ -1414,7 +1413,7 @@ void CSGBrushOperation::update_faces(const CSGBrush &p_brush_a, const int p_face
for (int i = 0; i < 3; i++) {
if (plane_b.has_point(vertices_a[i])) {
- in_plane_count++;
+ // In plane.
} else if (plane_b.is_point_over(vertices_a[i])) {
over_count++;
} else {
diff --git a/modules/csg/csg.h b/modules/csg/csg.h
index 9ff7b13a44..53a9e5d722 100644
--- a/modules/csg/csg.h
+++ b/modules/csg/csg.h
@@ -38,8 +38,8 @@
#include "core/math/vector3.h"
#include "core/object/ref_counted.h"
#include "core/templates/list.h"
-#include "core/templates/map.h"
#include "core/templates/oa_hash_map.h"
+#include "core/templates/rb_map.h"
#include "core/templates/vector.h"
#include "scene/resources/material.h"
@@ -139,8 +139,8 @@ struct CSGBrushOperation {
Vector<Vector3> points;
Vector<Face> faces;
- Map<Ref<Material>, int> materials;
- Map<Vector3, int> vertex_map;
+ HashMap<Ref<Material>, int> materials;
+ HashMap<Vector3, int> vertex_map;
OAHashMap<VertexKey, int, VertexKeyHash> snap_cache;
float vertex_snap = 0.0;
@@ -184,8 +184,8 @@ struct CSGBrushOperation {
};
struct Build2DFaceCollection {
- Map<int, Build2DFaces> build2DFacesA;
- Map<int, Build2DFaces> build2DFacesB;
+ HashMap<int, Build2DFaces> build2DFacesA;
+ HashMap<int, Build2DFaces> build2DFacesB;
};
void update_faces(const CSGBrush &p_brush_a, const int p_face_idx_a, const CSGBrush &p_brush_b, const int p_face_idx_b, Build2DFaceCollection &p_collection, float p_vertex_snap);
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 0a2427e4e6..25772bebbe 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -682,7 +682,7 @@ CSGBrush *CSGPrimitive3D::_create_brush_from_arrays(const Vector<Vector3> &p_ver
int ic = invert.size();
bool *w = invert.ptrw();
for (int i = 0; i < ic; i++) {
- w[i] = invert_faces;
+ w[i] = flip_faces;
}
}
brush->build_from_faces(p_vertices, p_uv, p_smooth, p_materials, invert);
@@ -691,28 +691,28 @@ CSGBrush *CSGPrimitive3D::_create_brush_from_arrays(const Vector<Vector3> &p_ver
}
void CSGPrimitive3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_invert_faces", "invert_faces"), &CSGPrimitive3D::set_invert_faces);
- ClassDB::bind_method(D_METHOD("is_inverting_faces"), &CSGPrimitive3D::is_inverting_faces);
+ ClassDB::bind_method(D_METHOD("set_flip_faces", "flip_faces"), &CSGPrimitive3D::set_flip_faces);
+ ClassDB::bind_method(D_METHOD("get_flip_faces"), &CSGPrimitive3D::get_flip_faces);
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "invert_faces"), "set_invert_faces", "is_inverting_faces");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_faces"), "set_flip_faces", "get_flip_faces");
}
-void CSGPrimitive3D::set_invert_faces(bool p_invert) {
- if (invert_faces == p_invert) {
+void CSGPrimitive3D::set_flip_faces(bool p_invert) {
+ if (flip_faces == p_invert) {
return;
}
- invert_faces = p_invert;
+ flip_faces = p_invert;
_make_dirty();
}
-bool CSGPrimitive3D::is_inverting_faces() {
- return invert_faces;
+bool CSGPrimitive3D::get_flip_faces() {
+ return flip_faces;
}
CSGPrimitive3D::CSGPrimitive3D() {
- invert_faces = false;
+ flip_faces = false;
}
/////////////////////
@@ -921,7 +921,7 @@ CSGBrush *CSGSphere3D::_build_brush() {
int face_count = rings * radial_segments * 2 - radial_segments * 2;
- bool invert_val = is_inverting_faces();
+ bool invert_val = get_flip_faces();
Ref<Material> material = get_material();
Vector<Vector3> faces;
@@ -1052,7 +1052,7 @@ void CSGSphere3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGSphere3D::set_material);
ClassDB::bind_method(D_METHOD("get_material"), &CSGSphere3D::get_material);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001"), "set_radius", "get_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,suffix:m"), "set_radius", "get_radius");
ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1"), "set_radial_segments", "get_radial_segments");
ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1"), "set_rings", "get_rings");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smooth_faces"), "set_smooth_faces", "get_smooth_faces");
@@ -1125,7 +1125,7 @@ CSGBrush *CSGBox3D::_build_brush() {
int face_count = 12; //it's a cube..
- bool invert_val = is_inverting_faces();
+ bool invert_val = get_flip_faces();
Ref<Material> material = get_material();
Vector<Vector3> faces;
@@ -1225,7 +1225,7 @@ void CSGBox3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGBox3D::set_material);
ClassDB::bind_method(D_METHOD("get_material"), &CSGBox3D::get_material);
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size"), "set_size", "get_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size", PROPERTY_HINT_NONE, "suffix:m"), "set_size", "get_size");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial"), "set_material", "get_material");
}
@@ -1258,7 +1258,7 @@ CSGBrush *CSGCylinder3D::_build_brush() {
int face_count = sides * (cone ? 1 : 2) + sides + (cone ? 0 : sides);
- bool invert_val = is_inverting_faces();
+ bool invert_val = get_flip_faces();
Ref<Material> material = get_material();
Vector<Vector3> faces;
@@ -1405,8 +1405,8 @@ void CSGCylinder3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGCylinder3D::set_smooth_faces);
ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGCylinder3D::get_smooth_faces);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_radius", "get_radius");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_height", "get_height");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp,suffix:m"), "set_radius", "get_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp,suffix:m"), "set_height", "get_height");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sides", PROPERTY_HINT_RANGE, "3,64,1"), "set_sides", "get_sides");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cone"), "set_cone", "is_cone");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smooth_faces"), "set_smooth_faces", "get_smooth_faces");
@@ -1503,7 +1503,7 @@ CSGBrush *CSGTorus3D::_build_brush() {
int face_count = ring_sides * sides * 2;
- bool invert_val = is_inverting_faces();
+ bool invert_val = get_flip_faces();
Ref<Material> material = get_material();
Vector<Vector3> faces;
@@ -1630,8 +1630,8 @@ void CSGTorus3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_smooth_faces", "smooth_faces"), &CSGTorus3D::set_smooth_faces);
ClassDB::bind_method(D_METHOD("get_smooth_faces"), &CSGTorus3D::get_smooth_faces);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inner_radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_inner_radius", "get_inner_radius");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "outer_radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_outer_radius", "get_outer_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inner_radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp,suffix:m"), "set_inner_radius", "get_inner_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "outer_radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp,suffix:m"), "set_outer_radius", "get_outer_radius");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sides", PROPERTY_HINT_RANGE, "3,64,1"), "set_sides", "get_sides");
ADD_PROPERTY(PropertyInfo(Variant::INT, "ring_sides", PROPERTY_HINT_RANGE, "3,64,1"), "set_ring_sides", "get_ring_sides");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smooth_faces"), "set_smooth_faces", "get_smooth_faces");
@@ -1881,7 +1881,7 @@ CSGBrush *CSGPolygon3D::_build_brush() {
smoothw[face] = false;
materialsw[face] = material;
- invertw[face] = invert_faces;
+ invertw[face] = flip_faces;
face++;
}
}
@@ -1986,7 +1986,7 @@ CSGBrush *CSGPolygon3D::_build_brush() {
uvsw[face * 3 + 2] = u[2];
smoothw[face] = smooth_faces;
- invertw[face] = invert_faces;
+ invertw[face] = flip_faces;
materialsw[face] = material;
face++;
@@ -2001,7 +2001,7 @@ CSGBrush *CSGPolygon3D::_build_brush() {
uvsw[face * 3 + 2] = u[0];
smoothw[face] = smooth_faces;
- invertw[face] = invert_faces;
+ invertw[face] = flip_faces;
materialsw[face] = material;
face++;
@@ -2026,7 +2026,7 @@ CSGBrush *CSGPolygon3D::_build_brush() {
smoothw[face] = false;
materialsw[face] = material;
- invertw[face] = invert_faces;
+ invertw[face] = flip_faces;
face++;
}
}
diff --git a/modules/csg/csg_shape.h b/modules/csg/csg_shape.h
index b5d5f97cf3..0eaf5c3727 100644
--- a/modules/csg/csg_shape.h
+++ b/modules/csg/csg_shape.h
@@ -171,13 +171,13 @@ class CSGPrimitive3D : public CSGShape3D {
GDCLASS(CSGPrimitive3D, CSGShape3D);
protected:
- bool invert_faces;
+ bool flip_faces;
CSGBrush *_create_brush_from_arrays(const Vector<Vector3> &p_vertices, const Vector<Vector2> &p_uv, const Vector<bool> &p_smooth, const Vector<Ref<Material>> &p_materials);
static void _bind_methods();
public:
- void set_invert_faces(bool p_invert);
- bool is_inverting_faces();
+ void set_flip_faces(bool p_invert);
+ bool get_flip_faces();
CSGPrimitive3D();
};
diff --git a/modules/csg/doc_classes/CSGPrimitive3D.xml b/modules/csg/doc_classes/CSGPrimitive3D.xml
index 39f4fa320d..6ea413c991 100644
--- a/modules/csg/doc_classes/CSGPrimitive3D.xml
+++ b/modules/csg/doc_classes/CSGPrimitive3D.xml
@@ -11,8 +11,8 @@
<link title="Prototyping levels with CSG">$DOCS_URL/tutorials/3d/csg_tools.html</link>
</tutorials>
<members>
- <member name="invert_faces" type="bool" setter="set_invert_faces" getter="is_inverting_faces" default="false">
- Invert the faces of the mesh.
+ <member name="flip_faces" type="bool" setter="set_flip_faces" getter="get_flip_faces" default="false">
+ If set, the order of the vertices in each triangle are reversed resulting in the backside of the mesh being drawn.
</member>
</members>
</class>
diff --git a/modules/csg/editor/csg_gizmos.cpp b/modules/csg/editor/csg_gizmos.cpp
index 4d972e46c6..6442ff71fc 100644
--- a/modules/csg/editor/csg_gizmos.cpp
+++ b/modules/csg/editor/csg_gizmos.cpp
@@ -349,9 +349,11 @@ void CSGShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
if (cs->is_root_shape()) {
Array csg_meshes = cs->get_meshes();
- Ref<Mesh> csg_mesh = csg_meshes[1];
- if (csg_mesh.is_valid()) {
- p_gizmo->add_collision_triangles(csg_mesh->generate_triangle_mesh());
+ if (csg_meshes.size() == 2) {
+ Ref<Mesh> csg_mesh = csg_meshes[1];
+ if (csg_mesh.is_valid()) {
+ p_gizmo->add_collision_triangles(csg_mesh->generate_triangle_mesh());
+ }
}
}
diff --git a/modules/enet/enet_multiplayer_peer.h b/modules/enet/enet_multiplayer_peer.h
index e7b61169fb..18eca18e51 100644
--- a/modules/enet/enet_multiplayer_peer.h
+++ b/modules/enet/enet_multiplayer_peer.h
@@ -70,8 +70,8 @@ private:
ConnectionStatus connection_status = CONNECTION_DISCONNECTED;
- Map<int, Ref<ENetConnection>> hosts;
- Map<int, Ref<ENetPacketPeer>> peers;
+ HashMap<int, Ref<ENetConnection>> hosts;
+ HashMap<int, Ref<ENetPacketPeer>> peers;
struct Packet {
ENetPacket *packet = nullptr;
diff --git a/modules/freetype/SCsub b/modules/freetype/SCsub
index d23c4b637c..4b2ea6faa5 100644
--- a/modules/freetype/SCsub
+++ b/modules/freetype/SCsub
@@ -49,6 +49,7 @@ if env["builtin_freetype"]:
"src/psnames/psnames.c",
"src/raster/raster.c",
"src/sdf/sdf.c",
+ "src/svg/svg.c",
"src/smooth/smooth.c",
"src/truetype/truetype.c",
"src/type1/type1.c",
@@ -87,7 +88,7 @@ if env["builtin_freetype"]:
# Also needed in main env for scene/
env.Prepend(CPPPATH=[thirdparty_dir + "/include"])
- env_freetype.Append(CPPDEFINES=["FT2_BUILD_LIBRARY", "FT_CONFIG_OPTION_USE_PNG"])
+ env_freetype.Append(CPPDEFINES=["FT2_BUILD_LIBRARY", "FT_CONFIG_OPTION_USE_PNG", "FT_CONFIG_OPTION_SYSTEM_ZLIB"])
if env["target"] == "debug":
env_freetype.Append(CPPDEFINES=["ZLIB_DEBUG"])
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index d0926d317b..70151c4d21 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -184,27 +184,24 @@
<method name="range" qualifiers="vararg">
<return type="Array" />
<description>
- Returns an array with the given range. Range can be 1 argument [code]N[/code] (0 to [code]N[/code] - 1), two arguments ([code]initial[/code], [code]final - 1[/code]) or three arguments ([code]initial[/code], [code]final - 1[/code], [code]increment[/code]). Returns an empty array if the range isn't valid (e.g. [code]range(2, 5, -1)[/code] or [code]range(5, 5, 1)[/code]).
- Returns an array with the given range. [code]range()[/code] can have 1 argument N ([code]0[/code] to [code]N - 1[/code]), two arguments ([code]initial[/code], [code]final - 1[/code]) or three arguments ([code]initial[/code], [code]final - 1[/code], [code]increment[/code]). [code]increment[/code] can be negative. If [code]increment[/code] is negative, [code]final - 1[/code] will become [code]final + 1[/code]. Also, the initial value must be greater than the final value for the loop to run.
- [code]range()[/code] converts all arguments to [int] before processing.
+ Returns an array with the given range. [method range] can be called in three ways:
+ [code]range(n: int)[/code]: Starts from 0, increases by steps of 1, and stops [i]before[/i] [code]n[/code]. The argument [code]n[/code] is [b]exclusive[/b].
+ [code]range(b: int, n: int)[/code]: Starts from [code]b[/code], increases by steps of 1, and stops [i]before[/i] [code]n[/code]. The arguments [code]b[/code] and [code]n[/code] are [b]inclusive[/b] and [b]exclusive[/b], respectively.
+ [code]range(b: int, n: int, s: int)[/code]: Starts from [code]b[/code], increases/decreases by steps of [code]s[/code], and stops [i]before[/i] [code]n[/code]. The arguments [code]b[/code] and [code]n[/code] are [b]inclusive[/b] and [b]exclusive[/b], respectively. The argument [code]s[/code] [b]can[/b] be negative, but not [code]0[/code]. If [code]s[/code] is [code]0[/code], an error message is printed.
+ [method range] converts all arguments to [int] before processing.
+ [b]Note:[/b] Returns an empty array if no value meets the value constraint (e.g. [code]range(2, 5, -1)[/code] or [code]range(5, 5, 1)[/code]).
+ Examples:
[codeblock]
- print(range(4))
- print(range(2, 5))
- print(range(0, 6, 2))
- [/codeblock]
- Output:
- [codeblock]
- [0, 1, 2, 3]
- [2, 3, 4]
- [0, 2, 4]
+ print(range(4)) # Prints [0, 1, 2, 3]
+ print(range(2, 5)) # Prints [2, 3, 4]
+ print(range(0, 6, 2)) # Prints [0, 2, 4]
+ print(range(4, 1, -1)) # Prints [4, 3, 2]
[/codeblock]
To iterate over an [Array] backwards, use:
[codeblock]
var array = [3, 6, 9]
- var i := array.size() - 1
- while i &gt;= 0:
- print(array[i])
- i -= 1
+ for i in range(array.size(), 0, -1):
+ print(array[i - 1])
[/codeblock]
Output:
[codeblock]
diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp
index e3f0ddfc35..b86e9b386d 100644
--- a/modules/gdscript/editor/gdscript_highlighter.cpp
+++ b/modules/gdscript/editor/gdscript_highlighter.cpp
@@ -387,9 +387,9 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
in_member_variable = false;
}
- if (!in_node_path && in_region == -1 && str[j] == '$') {
+ if (!in_node_path && in_region == -1 && (str[j] == '$' || str[j] == '%')) {
in_node_path = true;
- } else if (in_region != -1 || (is_a_symbol && str[j] != '/')) {
+ } else if (in_region != -1 || (is_a_symbol && str[j] != '/' && str[j] != '%')) {
in_node_path = false;
}
@@ -510,9 +510,8 @@ void GDScriptSyntaxHighlighter::_update_cache() {
}
/* 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) {
keywords[info.name] = usertype_color;
}
diff --git a/modules/gdscript/editor/gdscript_highlighter.h b/modules/gdscript/editor/gdscript_highlighter.h
index 1ae0d72896..92764e3891 100644
--- a/modules/gdscript/editor/gdscript_highlighter.h
+++ b/modules/gdscript/editor/gdscript_highlighter.h
@@ -45,7 +45,7 @@ private:
bool line_only = false;
};
Vector<ColorRegion> color_regions;
- Map<int, int> color_region_cache;
+ HashMap<int, int> color_region_cache;
HashMap<StringName, Color> keywords;
HashMap<StringName, Color> member_keywords;
diff --git a/modules/gdscript/editor/gdscript_translation_parser_plugin.h b/modules/gdscript/editor/gdscript_translation_parser_plugin.h
index e7b40aa367..969a50f48c 100644
--- a/modules/gdscript/editor/gdscript_translation_parser_plugin.h
+++ b/modules/gdscript/editor/gdscript_translation_parser_plugin.h
@@ -31,7 +31,7 @@
#ifndef GDSCRIPT_TRANSLATION_PARSER_PLUGIN_H
#define GDSCRIPT_TRANSLATION_PARSER_PLUGIN_H
-#include "core/templates/set.h"
+#include "core/templates/hash_set.h"
#include "editor/editor_translation_parser.h"
#include "modules/gdscript/gdscript_parser.h"
@@ -44,9 +44,9 @@ class GDScriptEditorTranslationParserPlugin : public EditorTranslationParserPlug
// List of patterns used for extracting translation strings.
StringName tr_func = "tr";
StringName trn_func = "tr_n";
- Set<StringName> assignment_patterns;
- Set<StringName> first_arg_patterns;
- Set<StringName> second_arg_patterns;
+ HashSet<StringName> assignment_patterns;
+ HashSet<StringName> first_arg_patterns;
+ HashSet<StringName> second_arg_patterns;
// FileDialog patterns.
StringName fd_add_filter = "add_filter";
StringName fd_set_filter = "set_filters";
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 1b4711804c..55a7e39dec 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -340,14 +340,14 @@ bool GDScript::has_method(const StringName &p_method) const {
}
MethodInfo GDScript::get_method_info(const StringName &p_method) const {
- const Map<StringName, GDScriptFunction *>::Element *E = member_functions.find(p_method);
+ HashMap<StringName, GDScriptFunction *>::ConstIterator E = member_functions.find(p_method);
if (!E) {
return MethodInfo();
}
- GDScriptFunction *func = E->get();
+ GDScriptFunction *func = E->value;
MethodInfo mi;
- mi.name = E->key();
+ mi.name = E->key;
for (int i = 0; i < func->get_argument_count(); i++) {
mi.arguments.push_back(func->get_argument_type(i));
}
@@ -359,9 +359,9 @@ MethodInfo GDScript::get_method_info(const StringName &p_method) const {
bool GDScript::get_property_default_value(const StringName &p_property, Variant &r_value) const {
#ifdef TOOLS_ENABLED
- const Map<StringName, Variant>::Element *E = member_default_values_cache.find(p_property);
+ HashMap<StringName, Variant>::ConstIterator E = member_default_values_cache.find(p_property);
if (E) {
- r_value = E->get();
+ r_value = E->value;
return true;
}
@@ -427,7 +427,7 @@ void GDScript::set_source_code(const String &p_code) {
}
#ifdef TOOLS_ENABLED
-void GDScript::_update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames) {
+void GDScript::_update_exports_values(HashMap<StringName, Variant> &values, List<PropertyInfo> &propnames) {
if (base_cache.is_valid()) {
base_cache->_update_exports_values(values, propnames);
}
@@ -759,13 +759,13 @@ bool GDScript::_update_exports(bool *r_err, bool p_recursive_call, PlaceHolderSc
if ((changed || p_instance_to_update) && placeholders.size()) { //hm :(
// update placeholders if any
- Map<StringName, Variant> values;
+ HashMap<StringName, Variant> values;
List<PropertyInfo> propnames;
_update_exports_values(values, propnames);
if (changed) {
- for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
- E->get()->update(propnames, values);
+ for (PlaceHolderScriptInstance *E : placeholders) {
+ E->update(propnames, values);
}
} else {
p_instance_to_update->update(propnames, values);
@@ -788,10 +788,10 @@ void GDScript::update_exports() {
return;
}
- Set<ObjectID> copy = inheriters_cache; //might get modified
+ HashSet<ObjectID> copy = inheriters_cache; //might get modified
- for (Set<ObjectID>::Element *E = copy.front(); E; E = E->next()) {
- Object *id = ObjectDB::get_instance(E->get());
+ for (const ObjectID &E : copy) {
+ Object *id = ObjectDB::get_instance(E);
GDScript *s = Object::cast_to<GDScript>(id);
if (!s) {
continue;
@@ -929,7 +929,7 @@ ScriptLanguage *GDScript::get_language() const {
return GDScriptLanguage::get_singleton();
}
-void GDScript::get_constants(Map<StringName, Variant> *p_constants) {
+void GDScript::get_constants(HashMap<StringName, Variant> *p_constants) {
if (p_constants) {
for (const KeyValue<StringName, Variant> &E : constants) {
(*p_constants)[E.key] = E.value;
@@ -937,10 +937,10 @@ void GDScript::get_constants(Map<StringName, Variant> *p_constants) {
}
}
-void GDScript::get_members(Set<StringName> *p_members) {
+void GDScript::get_members(HashSet<StringName> *p_members) {
if (p_members) {
- for (Set<StringName>::Element *E = members.front(); E; E = E->next()) {
- p_members->insert(E->get());
+ for (const StringName &E : members) {
+ p_members->insert(E);
}
}
}
@@ -952,11 +952,11 @@ const Vector<Multiplayer::RPCConfig> GDScript::get_rpc_methods() const {
Variant GDScript::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
GDScript *top = this;
while (top) {
- Map<StringName, GDScriptFunction *>::Element *E = top->member_functions.find(p_method);
+ HashMap<StringName, GDScriptFunction *>::Iterator E = top->member_functions.find(p_method);
if (E) {
- ERR_FAIL_COND_V_MSG(!E->get()->is_static(), Variant(), "Can't call non-static function '" + String(p_method) + "' in script.");
+ ERR_FAIL_COND_V_MSG(!E->value->is_static(), Variant(), "Can't call non-static function '" + String(p_method) + "' in script.");
- return E->get()->call(nullptr, p_args, p_argcount, r_error);
+ return E->value->call(nullptr, p_args, p_argcount, r_error);
}
top = top->_base;
}
@@ -971,17 +971,17 @@ bool GDScript::_get(const StringName &p_name, Variant &r_ret) const {
const GDScript *top = this;
while (top) {
{
- const Map<StringName, Variant>::Element *E = top->constants.find(p_name);
+ HashMap<StringName, Variant>::ConstIterator E = top->constants.find(p_name);
if (E) {
- r_ret = E->get();
+ r_ret = E->value;
return true;
}
}
{
- const Map<StringName, Ref<GDScript>>::Element *E = subclasses.find(p_name);
+ HashMap<StringName, Ref<GDScript>>::ConstIterator E = subclasses.find(p_name);
if (E) {
- r_ret = E->get();
+ r_ret = E->value;
return true;
}
}
@@ -1061,7 +1061,7 @@ Error GDScript::load_source_code(const String &p_path) {
return OK;
}
-const Map<StringName, GDScriptFunction *> &GDScript::debug_get_member_functions() const {
+const HashMap<StringName, GDScriptFunction *> &GDScript::debug_get_member_functions() const {
return member_functions;
}
@@ -1209,7 +1209,7 @@ void GDScript::_init_rpc_methods_properties() {
}
GDScript *cscript = this;
- Map<StringName, Ref<GDScript>>::Element *sub_E = subclasses.front();
+ HashMap<StringName, Ref<GDScript>>::Iterator sub_E = subclasses.begin();
while (cscript) {
// RPC Methods
for (KeyValue<StringName, GDScriptFunction *> &E : cscript->member_functions) {
@@ -1223,11 +1223,11 @@ void GDScript::_init_rpc_methods_properties() {
}
if (cscript != this) {
- sub_E = sub_E->next();
+ ++sub_E;
}
if (sub_E) {
- cscript = sub_E->get().ptr();
+ cscript = sub_E->value.ptr();
} else {
cscript = nullptr;
}
@@ -1282,9 +1282,9 @@ GDScript::~GDScript() {
bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) {
//member
{
- const Map<StringName, GDScript::MemberInfo>::Element *E = script->member_indices.find(p_name);
+ HashMap<StringName, GDScript::MemberInfo>::Iterator E = script->member_indices.find(p_name);
if (E) {
- const GDScript::MemberInfo *member = &E->get();
+ const GDScript::MemberInfo *member = &E->value;
if (member->setter) {
const Variant *val = &p_value;
Callable::CallError err;
@@ -1325,13 +1325,13 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) {
GDScript *sptr = script.ptr();
while (sptr) {
- Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._set);
+ HashMap<StringName, GDScriptFunction *>::Iterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._set);
if (E) {
Variant name = p_name;
const Variant *args[2] = { &name, &p_value };
Callable::CallError err;
- Variant ret = E->get()->call(this, (const Variant **)args, 2, err);
+ Variant ret = E->value->call(this, (const Variant **)args, 2, err);
if (err.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::BOOL && ret.operator bool()) {
return true;
}
@@ -1346,16 +1346,16 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
const GDScript *sptr = script.ptr();
while (sptr) {
{
- const Map<StringName, GDScript::MemberInfo>::Element *E = script->member_indices.find(p_name);
+ HashMap<StringName, GDScript::MemberInfo>::ConstIterator E = script->member_indices.find(p_name);
if (E) {
- if (E->get().getter) {
+ if (E->value.getter) {
Callable::CallError err;
- r_ret = const_cast<GDScriptInstance *>(this)->callp(E->get().getter, nullptr, 0, err);
+ r_ret = const_cast<GDScriptInstance *>(this)->callp(E->value.getter, nullptr, 0, err);
if (err.error == Callable::CallError::CALL_OK) {
return true;
}
}
- r_ret = members[E->get().index];
+ r_ret = members[E->value.index];
return true; //index found
}
}
@@ -1363,9 +1363,9 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
{
const GDScript *sl = sptr;
while (sl) {
- const Map<StringName, Variant>::Element *E = sl->constants.find(p_name);
+ HashMap<StringName, Variant>::ConstIterator E = sl->constants.find(p_name);
if (E) {
- r_ret = E->get();
+ r_ret = E->value;
return true; //index found
}
sl = sl->_base;
@@ -1376,9 +1376,9 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
// Signals.
const GDScript *sl = sptr;
while (sl) {
- const Map<StringName, Vector<StringName>>::Element *E = sl->_signals.find(p_name);
+ HashMap<StringName, Vector<StringName>>::ConstIterator E = sl->_signals.find(p_name);
if (E) {
- r_ret = Signal(this->owner, E->key());
+ r_ret = Signal(this->owner, E->key);
return true; //index found
}
sl = sl->_base;
@@ -1389,14 +1389,14 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
// Methods.
const GDScript *sl = sptr;
while (sl) {
- const Map<StringName, GDScriptFunction *>::Element *E = sl->member_functions.find(p_name);
+ HashMap<StringName, GDScriptFunction *>::ConstIterator E = sl->member_functions.find(p_name);
if (E) {
Multiplayer::RPCConfig config;
config.name = p_name;
if (sptr->rpc_functions.find(config) != -1) {
- r_ret = Callable(memnew(GDScriptRPCCallable(this->owner, E->key())));
+ r_ret = Callable(memnew(GDScriptRPCCallable(this->owner, E->key)));
} else {
- r_ret = Callable(this->owner, E->key());
+ r_ret = Callable(this->owner, E->key);
}
return true; //index found
}
@@ -1405,13 +1405,13 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
}
{
- const Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get);
+ HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get);
if (E) {
Variant name = p_name;
const Variant *args[1] = { &name };
Callable::CallError err;
- Variant ret = const_cast<GDScriptFunction *>(E->get())->call(const_cast<GDScriptInstance *>(this), (const Variant **)args, 1, err);
+ Variant ret = const_cast<GDScriptFunction *>(E->value)->call(const_cast<GDScriptInstance *>(this), (const Variant **)args, 1, err);
if (err.error == Callable::CallError::CALL_OK && ret.get_type() != Variant::NIL) {
r_ret = ret;
return true;
@@ -1449,10 +1449,10 @@ void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const
List<PropertyInfo> props;
while (sptr) {
- const Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get_property_list);
+ HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get_property_list);
if (E) {
Callable::CallError err;
- Variant ret = const_cast<GDScriptFunction *>(E->get())->call(const_cast<GDScriptInstance *>(this), nullptr, 0, err);
+ Variant ret = const_cast<GDScriptFunction *>(E->value)->call(const_cast<GDScriptInstance *>(this), nullptr, 0, err);
if (err.error == Callable::CallError::CALL_OK) {
ERR_FAIL_COND_MSG(ret.get_type() != Variant::ARRAY, "Wrong type for _get_property_list, must be an array of dictionaries.");
@@ -1525,7 +1525,7 @@ void GDScriptInstance::get_method_list(List<MethodInfo> *p_list) const {
bool GDScriptInstance::has_method(const StringName &p_method) const {
const GDScript *sptr = script.ptr();
while (sptr) {
- const Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(p_method);
+ HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(p_method);
if (E) {
return true;
}
@@ -1538,9 +1538,9 @@ bool GDScriptInstance::has_method(const StringName &p_method) const {
Variant GDScriptInstance::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
GDScript *sptr = script.ptr();
while (sptr) {
- Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(p_method);
+ HashMap<StringName, GDScriptFunction *>::Iterator E = sptr->member_functions.find(p_method);
if (E) {
- return E->get()->call(this, p_args, p_argcount, r_error);
+ return E->value->call(this, p_args, p_argcount, r_error);
}
sptr = sptr->_base;
}
@@ -1555,10 +1555,10 @@ void GDScriptInstance::notification(int p_notification) {
GDScript *sptr = script.ptr();
while (sptr) {
- Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._notification);
+ HashMap<StringName, GDScriptFunction *>::Iterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._notification);
if (E) {
Callable::CallError err;
- E->get()->call(this, args, 1, err);
+ E->value->call(this, args, 1, err);
if (err.error != Callable::CallError::CALL_OK) {
//print error about notification call
}
@@ -1882,7 +1882,7 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so
//when someone asks you why dynamically typed languages are easier to write....
- Map<Ref<GDScript>, Map<ObjectID, List<Pair<StringName, Variant>>>> to_reload;
+ HashMap<Ref<GDScript>, HashMap<ObjectID, List<Pair<StringName, Variant>>>> to_reload;
//as scripts are going to be reloaded, must proceed without locking here
@@ -1895,11 +1895,11 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so
continue;
}
- to_reload.insert(script, Map<ObjectID, List<Pair<StringName, Variant>>>());
+ to_reload.insert(script, HashMap<ObjectID, List<Pair<StringName, Variant>>>());
if (!p_soft_reload) {
//save state and remove script from instances
- Map<ObjectID, List<Pair<StringName, Variant>>> &map = to_reload[script];
+ HashMap<ObjectID, List<Pair<StringName, Variant>>> &map = to_reload[script];
while (script->instances.front()) {
Object *obj = script->instances.front()->get();
@@ -1916,7 +1916,7 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so
#ifdef TOOLS_ENABLED
while (script->placeholders.size()) {
- Object *obj = script->placeholders.front()->get()->get_owner();
+ Object *obj = (*script->placeholders.begin())->get_owner();
//save instance info
if (obj->get_script_instance()) {
@@ -1926,7 +1926,7 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so
obj->set_script(Variant());
} else {
// no instance found. Let's remove it so we don't loop forever
- script->placeholders.erase(script->placeholders.front()->get());
+ script->placeholders.erase(*script->placeholders.begin());
}
}
@@ -1938,7 +1938,7 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so
}
}
- for (KeyValue<Ref<GDScript>, Map<ObjectID, List<Pair<StringName, Variant>>>> &E : to_reload) {
+ for (KeyValue<Ref<GDScript>, HashMap<ObjectID, List<Pair<StringName, Variant>>>> &E : to_reload) {
Ref<GDScript> scr = E.key;
scr->reload(p_soft_reload);
@@ -2232,9 +2232,13 @@ GDScriptLanguage::GDScriptLanguage() {
GLOBAL_DEF("debug/gdscript/warnings/treat_warnings_as_errors", false);
GLOBAL_DEF("debug/gdscript/warnings/exclude_addons", true);
for (int i = 0; i < (int)GDScriptWarning::WARNING_MAX; i++) {
- String warning = GDScriptWarning::get_name_from_code((GDScriptWarning::Code)i).to_lower();
- bool default_enabled = !warning.begins_with("unsafe_");
- GLOBAL_DEF("debug/gdscript/warnings/" + warning, default_enabled);
+ GDScriptWarning::Code code = (GDScriptWarning::Code)i;
+ Variant default_enabled = GDScriptWarning::get_default_value(code);
+ String path = GDScriptWarning::get_settings_path_from_code(code);
+ GLOBAL_DEF(path, default_enabled);
+
+ PropertyInfo property_info = GDScriptWarning::get_property_info(code);
+ ProjectSettings::get_singleton()->set_custom_property_info(path, property_info);
}
#endif // DEBUG_ENABLED
}
@@ -2277,13 +2281,13 @@ void GDScriptLanguage::add_orphan_subclass(const String &p_qualified_name, const
}
Ref<GDScript> GDScriptLanguage::get_orphan_subclass(const String &p_qualified_name) {
- Map<String, ObjectID>::Element *orphan_subclass_element = orphan_subclasses.find(p_qualified_name);
+ HashMap<String, ObjectID>::Iterator orphan_subclass_element = orphan_subclasses.find(p_qualified_name);
if (!orphan_subclass_element) {
return Ref<GDScript>();
}
- ObjectID orphan_subclass = orphan_subclass_element->get();
+ ObjectID orphan_subclass = orphan_subclass_element->value;
Object *obj = ObjectDB::get_instance(orphan_subclass);
- orphan_subclasses.erase(orphan_subclass_element);
+ orphan_subclasses.remove(orphan_subclass_element);
if (!obj) {
return Ref<GDScript>();
}
@@ -2372,7 +2376,7 @@ Error ResourceFormatSaverGDScript::save(const String &p_path, const Ref<Resource
}
if (ScriptServer::is_reload_scripts_on_save_enabled()) {
- GDScriptLanguage::get_singleton()->reload_tool_script(p_resource, false);
+ GDScriptLanguage::get_singleton()->reload_tool_script(p_resource, true);
}
return OK;
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index a20f3b2fca..80f187a375 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -37,6 +37,7 @@
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
#include "core/object/script_language.h"
+#include "core/templates/rb_set.h"
#include "gdscript_function.h"
class GDScriptNativeClass : public RefCounted {
@@ -80,48 +81,48 @@ class GDScript : public Script {
GDScript *_base = nullptr; //fast pointer access
GDScript *_owner = nullptr; //for subclasses
- Set<StringName> members; //members are just indices to the instantiated script.
- Map<StringName, Variant> constants;
- Map<StringName, GDScriptFunction *> member_functions;
- Map<StringName, MemberInfo> member_indices; //members are just indices to the instantiated script.
- Map<StringName, Ref<GDScript>> subclasses;
- Map<StringName, Vector<StringName>> _signals;
+ HashSet<StringName> members; //members are just indices to the instantiated script.
+ HashMap<StringName, Variant> constants;
+ HashMap<StringName, GDScriptFunction *> member_functions;
+ HashMap<StringName, MemberInfo> member_indices; //members are just indices to the instantiated script.
+ HashMap<StringName, Ref<GDScript>> subclasses;
+ HashMap<StringName, Vector<StringName>> _signals;
Vector<Multiplayer::RPCConfig> rpc_functions;
#ifdef TOOLS_ENABLED
- Map<StringName, int> member_lines;
- Map<StringName, Variant> member_default_values;
+ HashMap<StringName, int> member_lines;
+ HashMap<StringName, Variant> member_default_values;
List<PropertyInfo> members_cache;
- Map<StringName, Variant> member_default_values_cache;
+ HashMap<StringName, Variant> member_default_values_cache;
Ref<GDScript> base_cache;
- Set<ObjectID> inheriters_cache;
+ HashSet<ObjectID> inheriters_cache;
bool source_changed_cache = false;
bool placeholder_fallback_enabled = false;
- void _update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames);
+ void _update_exports_values(HashMap<StringName, Variant> &values, List<PropertyInfo> &propnames);
DocData::ClassDoc doc;
Vector<DocData::ClassDoc> docs;
String doc_brief_description;
String doc_description;
Vector<DocData::TutorialDoc> doc_tutorials;
- Map<String, String> doc_functions;
- Map<String, String> doc_variables;
- Map<String, String> doc_constants;
- Map<String, String> doc_signals;
- Map<String, DocData::EnumDoc> doc_enums;
+ HashMap<String, String> doc_functions;
+ HashMap<String, String> doc_variables;
+ HashMap<String, String> doc_constants;
+ HashMap<String, String> doc_signals;
+ HashMap<String, DocData::EnumDoc> doc_enums;
void _clear_doc();
void _update_doc();
void _add_doc(const DocData::ClassDoc &p_inner_class);
#endif
- Map<StringName, PropertyInfo> member_info;
+ HashMap<StringName, PropertyInfo> member_info;
GDScriptFunction *implicit_initializer = nullptr;
GDScriptFunction *initializer = nullptr; //direct pointer to new , faster to locate
int subclass_count = 0;
- Set<Object *> instances;
+ RBSet<Object *> instances;
//exported members
String source;
String path;
@@ -139,14 +140,14 @@ class GDScript : public Script {
String _get_debug_path() const;
#ifdef TOOLS_ENABLED
- Set<PlaceHolderScriptInstance *> placeholders;
+ HashSet<PlaceHolderScriptInstance *> placeholders;
//void _update_placeholder(PlaceHolderScriptInstance *p_placeholder);
virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder) override;
#endif
#ifdef DEBUG_ENABLED
- Map<ObjectID, List<Pair<StringName, Variant>>> pending_reload_state;
+ HashMap<ObjectID, List<Pair<StringName, Variant>>> pending_reload_state;
#endif
@@ -176,14 +177,14 @@ public:
bool inherits_script(const Ref<Script> &p_script) const override;
- const Map<StringName, Ref<GDScript>> &get_subclasses() const { return subclasses; }
- const Map<StringName, Variant> &get_constants() const { return constants; }
- const Set<StringName> &get_members() const { return members; }
+ const HashMap<StringName, Ref<GDScript>> &get_subclasses() const { return subclasses; }
+ const HashMap<StringName, Variant> &get_constants() const { return constants; }
+ const HashSet<StringName> &get_members() const { return members; }
const GDScriptDataType &get_member_type(const StringName &p_member) const {
CRASH_COND(!member_indices.has(p_member));
return member_indices[p_member].data_type;
}
- const Map<StringName, GDScriptFunction *> &get_member_functions() const { return member_functions; }
+ const HashMap<StringName, GDScriptFunction *> &get_member_functions() const { return member_functions; }
const Ref<GDScriptNativeClass> &get_native() const { return native; }
const String &get_script_class_name() const { return name; }
@@ -193,8 +194,8 @@ public:
bool is_tool() const override { return tool; }
Ref<GDScript> get_base() const;
- const Map<StringName, MemberInfo> &debug_get_member_indices() const { return member_indices; }
- const Map<StringName, GDScriptFunction *> &debug_get_member_functions() const; //this is debug only
+ const HashMap<StringName, MemberInfo> &debug_get_member_indices() const { return member_indices; }
+ const HashMap<StringName, GDScriptFunction *> &debug_get_member_functions() const; //this is debug only
StringName debug_get_member_by_index(int p_idx) const;
Variant _new(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
@@ -245,8 +246,8 @@ public:
return -1;
}
- virtual void get_constants(Map<StringName, Variant> *p_constants) override;
- virtual void get_members(Set<StringName> *p_members) override;
+ virtual void get_constants(HashMap<StringName, Variant> *p_constants) override;
+ virtual void get_members(HashSet<StringName> *p_members) override;
virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override;
@@ -270,7 +271,7 @@ class GDScriptInstance : public ScriptInstance {
Object *owner = nullptr;
Ref<GDScript> script;
#ifdef DEBUG_ENABLED
- Map<StringName, int> member_indices_cache; //used only for hot script reloading
+ HashMap<StringName, int> member_indices_cache; //used only for hot script reloading
#endif
Vector<Variant> members;
bool base_ref_counted;
@@ -315,8 +316,8 @@ class GDScriptLanguage : public ScriptLanguage {
Variant *_global_array = nullptr;
Vector<Variant> global_array;
- Map<StringName, int> globals;
- Map<StringName, Variant> named_globals;
+ HashMap<StringName, int> globals;
+ HashMap<StringName, Variant> named_globals;
struct CallLevel {
Variant *stack = nullptr;
@@ -348,7 +349,7 @@ class GDScriptLanguage : public ScriptLanguage {
bool profiling;
uint64_t script_frame_time;
- Map<String, ObjectID> orphan_subclasses;
+ HashMap<String, ObjectID> orphan_subclasses;
public:
int calls;
@@ -427,8 +428,8 @@ public:
_FORCE_INLINE_ int get_global_array_size() const { return global_array.size(); }
_FORCE_INLINE_ Variant *get_global_array() { return _global_array; }
- _FORCE_INLINE_ const Map<StringName, int> &get_global_map() const { return globals; }
- _FORCE_INLINE_ const Map<StringName, Variant> &get_named_globals_map() const { return named_globals; }
+ _FORCE_INLINE_ const HashMap<StringName, int> &get_global_map() const { return globals; }
+ _FORCE_INLINE_ const HashMap<StringName, Variant> &get_named_globals_map() const { return named_globals; }
_FORCE_INLINE_ static GDScriptLanguage *get_singleton() { return singleton; }
@@ -449,7 +450,7 @@ public:
virtual bool is_using_templates() override;
virtual Ref<Script> make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const override;
virtual Vector<ScriptTemplate> get_built_in_templates(StringName p_object) override;
- virtual bool validate(const String &p_script, const String &p_path = "", List<String> *r_functions = nullptr, List<ScriptLanguage::ScriptError> *r_errors = nullptr, List<ScriptLanguage::Warning> *r_warnings = nullptr, Set<int> *r_safe_lines = nullptr) const override;
+ virtual bool validate(const String &p_script, const String &p_path = "", List<String> *r_functions = nullptr, List<ScriptLanguage::ScriptError> *r_errors = nullptr, List<ScriptLanguage::Warning> *r_warnings = nullptr, HashSet<int> *r_safe_lines = nullptr) const override;
virtual Script *create_script() const override;
virtual bool has_named_classes() const override;
virtual bool supports_builtin_mode() const override;
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index d346264933..9fa518ca0b 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -898,7 +898,7 @@ void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class) {
}
#ifdef DEBUG_ENABLED
- Set<uint32_t> previously_ignored = parser->ignored_warning_codes;
+ HashSet<uint32_t> previously_ignored = parser->ignored_warning_codes;
for (uint32_t ignored_warning : member.function->ignored_warnings) {
parser->ignored_warning_codes.insert(ignored_warning);
}
@@ -947,7 +947,7 @@ void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class) {
GDScriptParser::ClassNode::Member member = p_class->members[i];
if (member.type == GDScriptParser::ClassNode::Member::VARIABLE) {
#ifdef DEBUG_ENABLED
- Set<uint32_t> previously_ignored = parser->ignored_warning_codes;
+ HashSet<uint32_t> previously_ignored = parser->ignored_warning_codes;
for (uint32_t ignored_warning : member.function->ignored_warnings) {
parser->ignored_warning_codes.insert(ignored_warning);
}
@@ -1160,8 +1160,16 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *
}
}
} else {
- GDScriptParser::DataType return_type = resolve_datatype(p_function->return_type);
- p_function->set_datatype(return_type);
+ if (p_function->return_type != nullptr) {
+ p_function->set_datatype(resolve_datatype(p_function->return_type));
+ } else {
+ // In case the function is not typed, we can safely assume it's a Variant, so it's okay to mark as "inferred" here.
+ // It's not "undetected" to not mix up with unknown functions.
+ GDScriptParser::DataType return_type;
+ return_type.type_source = GDScriptParser::DataType::INFERRED;
+ return_type.kind = GDScriptParser::DataType::VARIANT;
+ p_function->set_datatype(return_type);
+ }
#ifdef TOOLS_ENABLED
// Check if the function signature matches the parent. If not it's an error since it breaks polymorphism.
@@ -1231,7 +1239,7 @@ void GDScriptAnalyzer::resolve_function_body(GDScriptParser::FunctionNode *p_fun
GDScriptParser::DataType return_type = p_function->body->get_datatype();
- if (p_function->get_datatype().has_no_type() && return_type.is_set()) {
+ if (!p_function->get_datatype().is_hard_type() && return_type.is_set()) {
// Use the suite inferred type if return isn't explicitly set.
return_type.type_source = GDScriptParser::DataType::INFERRED;
p_function->set_datatype(p_function->body->get_datatype());
@@ -1279,7 +1287,7 @@ void GDScriptAnalyzer::resolve_suite(GDScriptParser::SuiteNode *p_suite) {
}
#ifdef DEBUG_ENABLED
- Set<uint32_t> previously_ignored = parser->ignored_warning_codes;
+ HashSet<uint32_t> previously_ignored = parser->ignored_warning_codes;
for (uint32_t ignored_warning : stmt->ignored_warnings) {
parser->ignored_warning_codes.insert(ignored_warning);
}
@@ -1514,10 +1522,22 @@ void GDScriptAnalyzer::resolve_variable(GDScriptParser::VariableNode *p_variable
void GDScriptAnalyzer::resolve_constant(GDScriptParser::ConstantNode *p_constant) {
GDScriptParser::DataType type;
+ GDScriptParser::DataType explicit_type;
+ if (p_constant->datatype_specifier != nullptr) {
+ explicit_type = resolve_datatype(p_constant->datatype_specifier);
+ explicit_type.is_meta_type = false;
+ }
+
if (p_constant->initializer != nullptr) {
reduce_expression(p_constant->initializer);
if (p_constant->initializer->type == GDScriptParser::Node::ARRAY) {
- const_fold_array(static_cast<GDScriptParser::ArrayNode *>(p_constant->initializer));
+ GDScriptParser::ArrayNode *array = static_cast<GDScriptParser::ArrayNode *>(p_constant->initializer);
+ const_fold_array(array);
+
+ // Can only infer typed array if it has elements.
+ if (array->elements.size() > 0 || (p_constant->datatype_specifier != nullptr && explicit_type.has_container_element_type())) {
+ update_array_literal_element_type(explicit_type, array);
+ }
} else if (p_constant->initializer->type == GDScriptParser::Node::DICTIONARY) {
const_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(p_constant->initializer));
}
@@ -1536,8 +1556,6 @@ void GDScriptAnalyzer::resolve_constant(GDScriptParser::ConstantNode *p_constant
}
if (p_constant->datatype_specifier != nullptr) {
- GDScriptParser::DataType explicit_type = resolve_datatype(p_constant->datatype_specifier);
- explicit_type.is_meta_type = false;
if (!is_type_compatible(explicit_type, type)) {
push_error(vformat(R"(Assigned value for constant "%s" has type %s which is not compatible with defined type %s.)", p_constant->identifier->name, type.to_string(), explicit_type.to_string()), p_constant->initializer);
#ifdef DEBUG_ENABLED
@@ -2057,7 +2075,8 @@ void GDScriptAnalyzer::reduce_await(GDScriptParser::AwaitNode *p_await) {
p_await->set_datatype(awaiting_type);
#ifdef DEBUG_ENABLED
- if (!awaiting_type.is_coroutine && awaiting_type.builtin_type != Variant::SIGNAL) {
+ awaiting_type = p_await->to_await->get_datatype();
+ if (!(awaiting_type.has_no_type() || awaiting_type.is_coroutine || awaiting_type.builtin_type == Variant::SIGNAL)) {
parser->push_warning(p_await, GDScriptWarning::REDUNDANT_AWAIT);
}
#endif
@@ -2174,7 +2193,7 @@ void GDScriptAnalyzer::reduce_binary_op(GDScriptParser::BinaryOpNode *p_binary_o
void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_await, bool p_is_root) {
bool all_is_constant = true;
- Map<int, GDScriptParser::ArrayNode *> arrays; // For array literal to potentially type when passing.
+ HashMap<int, GDScriptParser::ArrayNode *> arrays; // For array literal to potentially type when passing.
for (int i = 0; i < p_call->arguments.size(); i++) {
reduce_expression(p_call->arguments[i]);
if (p_call->arguments[i]->type == GDScriptParser::Node::ARRAY) {
@@ -4218,13 +4237,11 @@ Error GDScriptAnalyzer::resolve_program() {
resolve_class_interface(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;
}
- depended_parsers[E]->raise_status(GDScriptParserRef::FULLY_SOLVED);
+ K.value->raise_status(GDScriptParserRef::FULLY_SOLVED);
}
return parser->errors.is_empty() ? OK : ERR_PARSE_ERROR;
}
diff --git a/modules/gdscript/gdscript_analyzer.h b/modules/gdscript/gdscript_analyzer.h
index 519e1975c4..3966b81b6e 100644
--- a/modules/gdscript/gdscript_analyzer.h
+++ b/modules/gdscript/gdscript_analyzer.h
@@ -33,7 +33,7 @@
#include "core/object/object.h"
#include "core/object/ref_counted.h"
-#include "core/templates/set.h"
+#include "core/templates/hash_set.h"
#include "gdscript_cache.h"
#include "gdscript_parser.h"
diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp
index e72069bcd5..3d5a39bf38 100644
--- a/modules/gdscript/gdscript_byte_codegen.cpp
+++ b/modules/gdscript/gdscript_byte_codegen.cpp
@@ -196,10 +196,8 @@ GDScriptFunction *GDScriptByteCodeGenerator::write_end() {
function->_constant_count = constant_map.size();
function->constants.resize(constant_map.size());
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 {
function->_constants_ptr = nullptr;
diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h
index 0503f66161..6ee8fda533 100644
--- a/modules/gdscript/gdscript_byte_codegen.h
+++ b/modules/gdscript/gdscript_byte_codegen.h
@@ -53,19 +53,19 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
bool debug_stack = false;
Vector<int> opcodes;
- List<Map<StringName, int>> stack_id_stack;
- Map<StringName, int> stack_identifiers;
+ List<RBMap<StringName, int>> stack_id_stack;
+ RBMap<StringName, int> stack_identifiers;
List<int> stack_identifiers_counts;
- Map<StringName, int> local_constants;
+ RBMap<StringName, int> local_constants;
Vector<StackSlot> locals;
Vector<StackSlot> temporaries;
List<int> used_temporaries;
- Map<Variant::Type, List<int>> temporaries_pool;
+ RBMap<Variant::Type, List<int>> temporaries_pool;
List<GDScriptFunction::StackDebug> stack_debug;
- List<Map<StringName, int>> block_identifier_stack;
- Map<StringName, int> block_identifiers;
+ List<RBMap<StringName, int>> block_identifier_stack;
+ RBMap<StringName, int> block_identifiers;
int max_locals = 0;
int current_line = 0;
@@ -77,23 +77,23 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
#endif
HashMap<Variant, int, VariantHasher, VariantComparator> constant_map;
- Map<StringName, int> name_map;
+ RBMap<StringName, int> name_map;
#ifdef TOOLS_ENABLED
Vector<StringName> named_globals;
#endif
- Map<Variant::ValidatedOperatorEvaluator, int> operator_func_map;
- Map<Variant::ValidatedSetter, int> setters_map;
- Map<Variant::ValidatedGetter, int> getters_map;
- Map<Variant::ValidatedKeyedSetter, int> keyed_setters_map;
- Map<Variant::ValidatedKeyedGetter, int> keyed_getters_map;
- Map<Variant::ValidatedIndexedSetter, int> indexed_setters_map;
- Map<Variant::ValidatedIndexedGetter, int> indexed_getters_map;
- Map<Variant::ValidatedBuiltInMethod, int> builtin_method_map;
- Map<Variant::ValidatedConstructor, int> constructors_map;
- Map<Variant::ValidatedUtilityFunction, int> utilities_map;
- Map<GDScriptUtilityFunctions::FunctionPtr, int> gds_utilities_map;
- Map<MethodBind *, int> method_bind_map;
- Map<GDScriptFunction *, int> lambdas_map;
+ RBMap<Variant::ValidatedOperatorEvaluator, int> operator_func_map;
+ RBMap<Variant::ValidatedSetter, int> setters_map;
+ RBMap<Variant::ValidatedGetter, int> getters_map;
+ RBMap<Variant::ValidatedKeyedSetter, int> keyed_setters_map;
+ RBMap<Variant::ValidatedKeyedGetter, int> keyed_getters_map;
+ RBMap<Variant::ValidatedIndexedSetter, int> indexed_setters_map;
+ RBMap<Variant::ValidatedIndexedGetter, int> indexed_getters_map;
+ RBMap<Variant::ValidatedBuiltInMethod, int> builtin_method_map;
+ RBMap<Variant::ValidatedConstructor, int> constructors_map;
+ RBMap<Variant::ValidatedUtilityFunction, int> utilities_map;
+ RBMap<GDScriptUtilityFunctions::FunctionPtr, int> gds_utilities_map;
+ RBMap<MethodBind *, int> method_bind_map;
+ RBMap<GDScriptFunction *, int> lambdas_map;
// Lists since these can be nested.
List<int> if_jmp_addrs;
@@ -135,7 +135,7 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
stack_identifiers_counts.push_back(locals.size());
stack_id_stack.push_back(stack_identifiers);
if (debug_stack) {
- Map<StringName, int> block_ids(block_identifiers);
+ RBMap<StringName, int> block_ids(block_identifiers);
block_identifier_stack.push_back(block_ids);
block_identifiers.clear();
}
diff --git a/modules/gdscript/gdscript_cache.cpp b/modules/gdscript/gdscript_cache.cpp
index 8c198345c2..4c15fca91e 100644
--- a/modules/gdscript/gdscript_cache.cpp
+++ b/modules/gdscript/gdscript_cache.cpp
@@ -223,13 +223,13 @@ Error GDScriptCache::finish_compiling(const String &p_owner) {
singleton->full_gdscript_cache[p_owner] = script.ptr();
singleton->shallow_gdscript_cache.erase(p_owner);
- Set<String> depends = singleton->dependencies[p_owner];
+ HashSet<String> depends = singleton->dependencies[p_owner];
Error err = OK;
- for (const Set<String>::Element *E = depends.front(); E != nullptr; E = E->next()) {
+ for (const String &E : depends) {
Error this_err = OK;
// No need to save the script. We assume it's already referenced in the owner.
- get_full_script(E->get(), this_err);
+ get_full_script(E, this_err);
if (this_err != OK) {
err = this_err;
diff --git a/modules/gdscript/gdscript_cache.h b/modules/gdscript/gdscript_cache.h
index 3ce976ee14..b971bdd984 100644
--- a/modules/gdscript/gdscript_cache.h
+++ b/modules/gdscript/gdscript_cache.h
@@ -34,7 +34,7 @@
#include "core/object/ref_counted.h"
#include "core/os/mutex.h"
#include "core/templates/hash_map.h"
-#include "core/templates/set.h"
+#include "core/templates/hash_set.h"
#include "gdscript.h"
class GDScriptAnalyzer;
@@ -74,7 +74,7 @@ class GDScriptCache {
HashMap<String, GDScriptParserRef *> parser_map;
HashMap<String, GDScript *> shallow_gdscript_cache;
HashMap<String, GDScript *> full_gdscript_cache;
- HashMap<String, Set<String>> dependencies;
+ HashMap<String, HashSet<String>> dependencies;
friend class GDScript;
friend class GDScriptParserRef;
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 37a988ee4c..910f94a936 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -108,11 +108,15 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
result.native_type = result.script_type->get_instance_base_type();
} break;
case GDScriptParser::DataType::CLASS: {
- // Locate class by constructing the path to it and following that path
+ // Locate class by constructing the path to it and following that path.
GDScriptParser::ClassNode *class_type = p_datatype.class_type;
if (class_type) {
- const bool is_inner_by_path = (!main_script->path.is_empty()) && (class_type->fqcn.split("::")[0] == main_script->path);
- const bool is_inner_by_name = (!main_script->name.is_empty()) && (class_type->fqcn.split("::")[0] == main_script->name);
+ result.kind = GDScriptDataType::GDSCRIPT;
+ result.builtin_type = p_datatype.builtin_type;
+
+ String class_name = class_type->fqcn.split("::")[0];
+ const bool is_inner_by_path = (!main_script->path.is_empty()) && (class_name == main_script->path);
+ const bool is_inner_by_name = (!main_script->name.is_empty()) && (class_name == main_script->name);
if (is_inner_by_path || is_inner_by_name) {
// Local class.
List<StringName> names;
@@ -131,16 +135,41 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
script = script->subclasses[names.back()->get()];
names.pop_back();
}
- result.kind = GDScriptDataType::GDSCRIPT;
result.script_type = script.ptr();
result.native_type = script->get_instance_base_type();
- result.builtin_type = p_datatype.builtin_type;
} else {
- result.kind = GDScriptDataType::GDSCRIPT;
- result.script_type_ref = GDScriptCache::get_shallow_script(p_datatype.script_path, main_script->path);
+ // Inner class.
+ PackedStringArray classes = class_type->fqcn.split("::");
+ if (!classes.is_empty()) {
+ for (GDScript *script : parsed_classes) {
+ // Checking of inheritance structure of inner class to find a correct script link.
+ if (script->name == classes[classes.size() - 1]) {
+ PackedStringArray classes2 = script->fully_qualified_name.split("::");
+ bool valid = true;
+ if (classes.size() != classes2.size()) {
+ valid = false;
+ } else {
+ for (int i = 0; i < classes.size(); i++) {
+ if (classes[i] != classes2[i]) {
+ valid = false;
+ break;
+ }
+ }
+ }
+ if (!valid) {
+ continue;
+ }
+ result.script_type_ref = Ref<GDScript>(script);
+ break;
+ }
+ }
+ }
+ if (result.script_type_ref.is_null()) {
+ result.script_type_ref = GDScriptCache::get_shallow_script(p_datatype.script_path, main_script->path);
+ }
+
result.script_type = result.script_type_ref.ptr();
result.native_type = p_datatype.native_type;
- result.builtin_type = p_datatype.builtin_type;
}
}
} break;
@@ -336,7 +365,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
if (GDScriptLanguage::get_singleton()->get_global_map().has(identifier)) {
// 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.
- 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) {
GDScriptCodeGenerator::Address global = codegen.add_temporary(_gdtype_from_datatype(in->get_datatype()));
int idx = GDScriptLanguage::get_singleton()->get_global_map()[identifier];
@@ -638,20 +667,8 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
case GDScriptParser::Node::GET_NODE: {
const GDScriptParser::GetNodeNode *get_node = static_cast<const GDScriptParser::GetNodeNode *>(p_expression);
- String node_name;
- if (get_node->string != nullptr) {
- node_name += String(get_node->string->value);
- } else {
- for (int i = 0; i < get_node->chain.size(); i++) {
- if (i > 0) {
- node_name += "/";
- }
- node_name += get_node->chain[i]->name;
- }
- }
-
Vector<GDScriptCodeGenerator::Address> args;
- args.push_back(codegen.add_constant(NodePath(node_name)));
+ args.push_back(codegen.add_constant(NodePath(get_node->full_path)));
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(get_node->get_datatype()));
@@ -703,10 +720,10 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
} else if (subscript->is_attribute) {
if (subscript->base->type == GDScriptParser::Node::SELF && codegen.script) {
GDScriptParser::IdentifierNode *identifier = subscript->attribute;
- const Map<StringName, GDScript::MemberInfo>::Element *MI = codegen.script->member_indices.find(identifier->name);
+ HashMap<StringName, GDScript::MemberInfo>::Iterator MI = codegen.script->member_indices.find(identifier->name);
#ifdef DEBUG_ENABLED
- if (MI && MI->get().getter == codegen.function_name) {
+ if (MI && MI->value.getter == codegen.function_name) {
String n = identifier->name;
_set_error("Must use '" + n + "' instead of 'self." + n + "' in getter.", identifier);
r_error = ERR_COMPILATION_FAILED;
@@ -714,11 +731,11 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
}
#endif
- if (MI && MI->get().getter == "") {
+ if (MI && MI->value.getter == "") {
// Remove result temp as we don't need it.
gen->pop_temporary();
// Faster than indexing self (as if no self. had been used).
- return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::MEMBER, MI->get().index, _gdtype_from_datatype(subscript->get_datatype()));
+ return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::MEMBER, MI->value.index, _gdtype_from_datatype(subscript->get_datatype()));
}
}
@@ -894,8 +911,8 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
const GDScriptParser::SubscriptNode *subscript = static_cast<GDScriptParser::SubscriptNode *>(assignment->assignee);
#ifdef DEBUG_ENABLED
if (subscript->is_attribute && subscript->base->type == GDScriptParser::Node::SELF && codegen.script) {
- const Map<StringName, GDScript::MemberInfo>::Element *MI = codegen.script->member_indices.find(subscript->attribute->name);
- if (MI && MI->get().setter == codegen.function_name) {
+ HashMap<StringName, GDScript::MemberInfo>::Iterator MI = codegen.script->member_indices.find(subscript->attribute->name);
+ if (MI && MI->value.setter == codegen.function_name) {
String n = subscript->attribute->name;
_set_error("Must use '" + n + "' instead of 'self." + n + "' in setter.", subscript);
r_error = ERR_COMPILATION_FAILED;
@@ -2500,8 +2517,8 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa
//validate instances if keeping state
if (p_keep_state) {
- for (Set<Object *>::Element *E = p_script->instances.front(); E;) {
- Set<Object *>::Element *N = E->next();
+ for (RBSet<Object *>::Element *E = p_script->instances.front(); E;) {
+ RBSet<Object *>::Element *N = E->next();
ScriptInstance *si = E->get()->get_script_instance();
if (si->is_placeholder()) {
@@ -2563,7 +2580,7 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa
}
void GDScriptCompiler::_make_scripts(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
- Map<StringName, Ref<GDScript>> old_subclasses;
+ HashMap<StringName, Ref<GDScript>> old_subclasses;
if (p_keep_state) {
old_subclasses = p_script->subclasses;
diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h
index 8d71437344..4841884e2d 100644
--- a/modules/gdscript/gdscript_compiler.h
+++ b/modules/gdscript/gdscript_compiler.h
@@ -31,7 +31,7 @@
#ifndef GDSCRIPT_COMPILER_H
#define GDSCRIPT_COMPILER_H
-#include "core/templates/set.h"
+#include "core/templates/hash_set.h"
#include "gdscript.h"
#include "gdscript_codegen.h"
#include "gdscript_function.h"
@@ -39,8 +39,8 @@
class GDScriptCompiler {
const GDScriptParser *parser = nullptr;
- Set<GDScript *> parsed_classes;
- Set<GDScript *> parsing_classes;
+ HashSet<GDScript *> parsed_classes;
+ HashSet<GDScript *> parsing_classes;
GDScript *main_script = nullptr;
struct CodeGen {
@@ -49,9 +49,9 @@ class GDScriptCompiler {
const GDScriptParser::FunctionNode *function_node = nullptr;
StringName function_name;
GDScriptCodeGenerator *generator = nullptr;
- Map<StringName, GDScriptCodeGenerator::Address> parameters;
- Map<StringName, GDScriptCodeGenerator::Address> locals;
- List<Map<StringName, GDScriptCodeGenerator::Address>> locals_stack;
+ HashMap<StringName, GDScriptCodeGenerator::Address> parameters;
+ HashMap<StringName, GDScriptCodeGenerator::Address> locals;
+ List<HashMap<StringName, GDScriptCodeGenerator::Address>> locals_stack;
GDScriptCodeGenerator::Address add_local(const StringName &p_name, const GDScriptDataType &p_type) {
uint32_t addr = generator->add_local(p_name, p_type);
@@ -101,7 +101,7 @@ class GDScriptCompiler {
}
void start_block() {
- Map<StringName, GDScriptCodeGenerator::Address> old_locals = locals;
+ HashMap<StringName, GDScriptCodeGenerator::Address> old_locals = locals;
locals_stack.push_back(old_locals);
generator->start_block();
}
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 0197bf9ea3..202d1dcdf4 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -98,7 +98,7 @@ Vector<ScriptLanguage::ScriptTemplate> GDScriptLanguage::get_built_in_templates(
return templates;
}
-static void get_function_names_recursively(const GDScriptParser::ClassNode *p_class, const String &p_prefix, Map<int, String> &r_funcs) {
+static void get_function_names_recursively(const GDScriptParser::ClassNode *p_class, const String &p_prefix, HashMap<int, String> &r_funcs) {
for (int i = 0; i < p_class->members.size(); i++) {
if (p_class->members[i].type == GDScriptParser::ClassNode::Member::FUNCTION) {
const GDScriptParser::FunctionNode *function = p_class->members[i].function;
@@ -110,7 +110,7 @@ static void get_function_names_recursively(const GDScriptParser::ClassNode *p_cl
}
}
-bool GDScriptLanguage::validate(const String &p_script, const String &p_path, List<String> *r_functions, List<ScriptLanguage::ScriptError> *r_errors, List<ScriptLanguage::Warning> *r_warnings, Set<int> *r_safe_lines) const {
+bool GDScriptLanguage::validate(const String &p_script, const String &p_path, List<String> *r_functions, List<ScriptLanguage::ScriptError> *r_errors, List<ScriptLanguage::Warning> *r_warnings, HashSet<int> *r_safe_lines) const {
GDScriptParser parser;
GDScriptAnalyzer analyzer(&parser);
@@ -148,7 +148,7 @@ bool GDScriptLanguage::validate(const String &p_script, const String &p_path, Li
return false;
} else {
const GDScriptParser::ClassNode *cl = parser.get_tree();
- Map<int, String> funcs;
+ HashMap<int, String> funcs;
get_function_names_recursively(cl, "", funcs);
@@ -159,7 +159,7 @@ bool GDScriptLanguage::validate(const String &p_script, const String &p_path, Li
#ifdef DEBUG_ENABLED
if (r_safe_lines) {
- const Set<int> &unsafe_lines = parser.get_unsafe_lines();
+ const HashSet<int> &unsafe_lines = parser.get_unsafe_lines();
for (int i = 1; i <= parser.get_last_line_number(); i++) {
if (!unsafe_lines.has(i)) {
r_safe_lines->insert(i);
@@ -321,7 +321,7 @@ void GDScriptLanguage::debug_get_stack_level_members(int p_level, List<String> *
Ref<GDScript> script = instance->get_script();
ERR_FAIL_COND(script.is_null());
- const Map<StringName, GDScript::MemberInfo> &mi = script->debug_get_member_indices();
+ const HashMap<StringName, GDScript::MemberInfo> &mi = script->debug_get_member_indices();
for (const KeyValue<StringName, GDScript::MemberInfo> &E : mi) {
p_members->push_back(E.key);
@@ -343,7 +343,7 @@ ScriptInstance *GDScriptLanguage::debug_get_stack_level_instance(int p_level) {
}
void GDScriptLanguage::debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {
- const Map<StringName, int> &name_idx = GDScriptLanguage::get_singleton()->get_global_map();
+ const HashMap<StringName, int> &name_idx = GDScriptLanguage::get_singleton()->get_global_map();
const Variant *globals = GDScriptLanguage::get_singleton()->get_global_array();
List<Pair<String, Variant>> cinfo;
@@ -722,7 +722,7 @@ static String _make_arguments_hint(const GDScriptParser::FunctionNode *p_functio
return arghint;
}
-static void _get_directory_contents(EditorFileSystemDirectory *p_dir, Map<String, ScriptLanguage::CodeCompletionOption> &r_list) {
+static void _get_directory_contents(EditorFileSystemDirectory *p_dir, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_list) {
const String quote_style = EDITOR_GET("text_editor/completion/use_single_quotes") ? "'" : "\"";
for (int i = 0; i < p_dir->get_file_count(); i++) {
@@ -736,7 +736,7 @@ static void _get_directory_contents(EditorFileSystemDirectory *p_dir, Map<String
}
}
-static void _find_annotation_arguments(const GDScriptParser::AnnotationNode *p_annotation, int p_argument, const String p_quote_style, Map<String, ScriptLanguage::CodeCompletionOption> &r_result) {
+static void _find_annotation_arguments(const GDScriptParser::AnnotationNode *p_annotation, int p_argument, const String p_quote_style, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result) {
if (p_annotation->name == SNAME("@export_range")) {
if (p_argument == 3 || p_argument == 4) {
// Slider hint.
@@ -777,7 +777,7 @@ static void _find_annotation_arguments(const GDScriptParser::AnnotationNode *p_a
}
}
-static void _find_built_in_variants(Map<String, ScriptLanguage::CodeCompletionOption> &r_result, bool exclude_nil = false) {
+static void _find_built_in_variants(HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, bool exclude_nil = false) {
for (int i = 0; i < Variant::VARIANT_MAX; i++) {
if (!exclude_nil && Variant::Type(i) == Variant::Type::NIL) {
ScriptLanguage::CodeCompletionOption option("null", ScriptLanguage::CODE_COMPLETION_KIND_CLASS);
@@ -789,7 +789,7 @@ static void _find_built_in_variants(Map<String, ScriptLanguage::CodeCompletionOp
}
}
-static void _list_available_types(bool p_inherit_only, GDScriptParser::CompletionContext &p_context, Map<String, ScriptLanguage::CodeCompletionOption> &r_result) {
+static void _list_available_types(bool p_inherit_only, GDScriptParser::CompletionContext &p_context, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result) {
// Built-in Variant Types
_find_built_in_variants(r_result, true);
@@ -851,9 +851,10 @@ static void _list_available_types(bool p_inherit_only, GDScriptParser::Completio
}
// 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") {
continue;
}
@@ -862,7 +863,7 @@ static void _list_available_types(bool p_inherit_only, GDScriptParser::Completio
}
}
-static void _find_identifiers_in_suite(const GDScriptParser::SuiteNode *p_suite, Map<String, ScriptLanguage::CodeCompletionOption> &r_result) {
+static void _find_identifiers_in_suite(const GDScriptParser::SuiteNode *p_suite, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result) {
for (int i = 0; i < p_suite->locals.size(); i++) {
ScriptLanguage::CodeCompletionOption option;
if (p_suite->locals[i].type == GDScriptParser::SuiteNode::Local::CONSTANT) {
@@ -878,9 +879,9 @@ static void _find_identifiers_in_suite(const GDScriptParser::SuiteNode *p_suite,
}
}
-static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base, bool p_only_functions, Map<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth);
+static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base, bool p_only_functions, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth);
-static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class, bool p_only_functions, bool p_static, bool p_parent_only, Map<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth) {
+static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class, bool p_only_functions, bool p_static, bool p_parent_only, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth) {
ERR_FAIL_COND(p_recursion_depth > COMPLETION_RECURSION_LIMIT);
if (!p_parent_only) {
@@ -965,7 +966,7 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class,
_find_identifiers_in_base(base_type, p_only_functions, r_result, p_recursion_depth + 1);
}
-static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base, bool p_only_functions, Map<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth) {
+static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base, bool p_only_functions, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth) {
ERR_FAIL_COND(p_recursion_depth > COMPLETION_RECURSION_LIMIT);
GDScriptParser::DataType base_type = p_base.type;
@@ -997,7 +998,7 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
r_result.insert(option.display, option);
}
}
- Map<StringName, Variant> constants;
+ HashMap<StringName, Variant> constants;
scr->get_constants(&constants);
for (const KeyValue<StringName, Variant> &E : constants) {
int location = p_recursion_depth + _get_constant_location(scr->get_class_name(), E.key);
@@ -1056,6 +1057,14 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
r_result.insert(option.display, option);
}
+ List<MethodInfo> signals;
+ ClassDB::get_signal_list(type, &signals);
+ for (const MethodInfo &E : signals) {
+ int location = p_recursion_depth + _get_signal_location(type, StringName(E.name));
+ ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_SIGNAL, location);
+ r_result.insert(option.display, option);
+ }
+
if (!_static || Engine::get_singleton()->has_singleton(type)) {
List<PropertyInfo> pinfo;
ClassDB::get_property_list(type, &pinfo);
@@ -1140,7 +1149,7 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
}
}
-static void _find_identifiers(const GDScriptParser::CompletionContext &p_context, bool p_only_functions, Map<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth) {
+static void _find_identifiers(const GDScriptParser::CompletionContext &p_context, bool p_only_functions, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, int p_recursion_depth) {
if (!p_only_functions && p_context.current_suite) {
// This includes function parameters, since they are also locals.
_find_identifiers_in_suite(p_context.current_suite, r_result);
@@ -1219,12 +1228,11 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context
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;
}
- 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);
}
@@ -1517,12 +1525,10 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context,
r_type = _type_from_variant(GDScriptLanguage::get_singleton()->get_named_globals_map()[which]);
found = true;
} 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) {
- String script = E.value().path;
+ String script = E.value.path;
if (!script.begins_with("res://")) {
script = "res://" + script;
@@ -2083,7 +2089,7 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext &
case GDScriptParser::DataType::SCRIPT: {
Ref<Script> scr = base_type.script_type;
if (scr.is_valid()) {
- Map<StringName, Variant> constants;
+ HashMap<StringName, Variant> constants;
scr->get_constants(&constants);
if (constants.has(p_identifier)) {
r_type = _type_from_variant(constants[p_identifier]);
@@ -2312,7 +2318,7 @@ static bool _guess_method_return_type_from_base(GDScriptParser::CompletionContex
return false;
}
-static void _find_enumeration_candidates(GDScriptParser::CompletionContext &p_context, const String &p_enum_hint, Map<String, ScriptLanguage::CodeCompletionOption> &r_result) {
+static void _find_enumeration_candidates(GDScriptParser::CompletionContext &p_context, const String &p_enum_hint, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result) {
if (!p_enum_hint.contains(".")) {
// Global constant or in the current class.
StringName current_enum = p_enum_hint;
@@ -2349,7 +2355,7 @@ static void _find_enumeration_candidates(GDScriptParser::CompletionContext &p_co
}
}
-static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_method, int p_argidx, bool p_static, Map<String, ScriptLanguage::CodeCompletionOption> &r_result, String &r_arghint) {
+static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_method, int p_argidx, bool p_static, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, String &r_arghint) {
Variant base = p_base.value;
GDScriptParser::DataType base_type = p_base.type;
@@ -2468,7 +2474,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
}
}
-static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, const GDScriptParser::Node *p_call, int p_argidx, Map<String, ScriptLanguage::CodeCompletionOption> &r_result, bool &r_forced, String &r_arghint) {
+static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, const GDScriptParser::Node *p_call, int p_argidx, HashMap<String, ScriptLanguage::CodeCompletionOption> &r_result, bool &r_forced, String &r_arghint) {
if (p_call->type == GDScriptParser::Node::PRELOAD) {
if (p_argidx == 0 && bool(EditorSettings::get_singleton()->get("text_editor/completion/complete_file_paths"))) {
_get_directory_contents(EditorFileSystem::get_singleton()->get_filesystem(), r_result);
@@ -2583,7 +2589,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
analyzer.analyze();
r_forced = false;
- Map<String, ScriptLanguage::CodeCompletionOption> options;
+ HashMap<String, ScriptLanguage::CodeCompletionOption> options;
GDScriptParser::CompletionContext completion_context = parser.get_completion_context();
completion_context.base = p_owner;
@@ -2882,10 +2888,8 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
}
// 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);
options.insert(option.display, option);
}
@@ -3062,6 +3066,13 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
}
}
+ if (ClassDB::has_signal(class_name, p_symbol, true)) {
+ r_result.type = ScriptLanguage::LOOKUP_RESULT_CLASS_SIGNAL;
+ r_result.class_name = base_type.native_type;
+ r_result.class_member = p_symbol;
+ return OK;
+ }
+
StringName enum_name = ClassDB::get_integer_constant_enum(class_name, p_symbol, true);
if (enum_name != StringName()) {
r_result.type = ScriptLanguage::LOOKUP_RESULT_CLASS_ENUM;
@@ -3144,7 +3155,7 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
}
::Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol, const String &p_path, Object *p_owner, LookupResult &r_result) {
- // Before parsing, try the usual stuff
+ // Before parsing, try the usual stuff.
if (ClassDB::class_exists(p_symbol)) {
r_result.type = ScriptLanguage::LOOKUP_RESULT_CLASS;
r_result.class_name = p_symbol;
@@ -3160,7 +3171,9 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
}
}
- if (GDScriptUtilityFunctions::function_exists(p_symbol)) {
+ // Need special checks for assert and preload as they are technically
+ // keywords, so are not registered in GDScriptUtilityFunctions.
+ if (GDScriptUtilityFunctions::function_exists(p_symbol) || "assert" == p_symbol || "preload" == p_symbol) {
r_result.type = ScriptLanguage::LOOKUP_RESULT_CLASS_METHOD;
r_result.class_name = "@GDScript";
r_result.class_member = p_symbol;
@@ -3216,6 +3229,7 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
is_function = true;
[[fallthrough]];
}
+ case GDScriptParser::COMPLETION_ASSIGN:
case GDScriptParser::COMPLETION_CALL_ARGUMENTS:
case GDScriptParser::COMPLETION_IDENTIFIER: {
GDScriptParser::DataType base_type;
@@ -3268,7 +3282,7 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
}
// Global.
- Map<StringName, int> classes = GDScriptLanguage::get_singleton()->get_global_map();
+ HashMap<StringName, int> classes = GDScriptLanguage::get_singleton()->get_global_map();
if (classes.has(p_symbol)) {
Variant value = GDScriptLanguage::get_singleton()->get_global_array()[classes[p_symbol]];
if (value.get_type() == Variant::OBJECT) {
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index 3d708955ed..cd3b7d69c5 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -93,7 +93,7 @@ struct _GDFKCS {
void GDScriptFunction::debug_get_stack_member_state(int p_line, List<Pair<StringName, int>> *r_stackvars) const {
int oc = 0;
- Map<StringName, _GDFKC> sdmap;
+ HashMap<StringName, _GDFKC> sdmap;
for (const StackDebug &sd : stack_debug) {
if (sd.line >= p_line) {
break;
@@ -270,6 +270,8 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) {
if (EngineDebugger::is_active()) {
GDScriptLanguage::get_singleton()->exit_function();
}
+
+ _clear_stack();
#endif
}
@@ -279,7 +281,8 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) {
void GDScriptFunctionState::_clear_stack() {
if (state.stack_size) {
Variant *stack = (Variant *)state.stack.ptr();
- for (int i = 0; i < state.stack_size; i++) {
+ // The first 3 are special addresses and not copied to the state, so we skip them here.
+ for (int i = 3; i < state.stack_size; i++) {
stack[i].~Variant();
}
state.stack_size = 0;
@@ -300,8 +303,6 @@ GDScriptFunctionState::GDScriptFunctionState() :
}
GDScriptFunctionState::~GDScriptFunctionState() {
- _clear_stack();
-
{
MutexLock lock(GDScriptLanguage::singleton->lock);
scripts_list.remove_from_list();
diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index ba0d51c5cc..d2ca795977 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -495,7 +495,7 @@ private:
Vector<GDScriptDataType> argument_types;
GDScriptDataType return_type;
- Map<int, Variant::Type> temporary_slots;
+ HashMap<int, Variant::Type> temporary_slots;
#ifdef TOOLS_ENABLED
Vector<StringName> arg_names;
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 67f6b61f14..bc225850c9 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -100,10 +100,8 @@ void GDScriptParser::cleanup() {
}
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);
}
}
@@ -205,7 +203,8 @@ void GDScriptParser::push_warning(const Node *p_source, GDScriptWarning::Code p_
if (ignored_warnings.has(warn_name)) {
return;
}
- if (!GLOBAL_GET("debug/gdscript/warnings/" + warn_name)) {
+ int warn_level = (int)GLOBAL_GET(GDScriptWarning::get_settings_path_from_code(p_code));
+ if (!warn_level) {
return;
}
@@ -217,6 +216,11 @@ void GDScriptParser::push_warning(const Node *p_source, GDScriptWarning::Code p_
warning.leftmost_column = p_source->leftmost_column;
warning.rightmost_column = p_source->rightmost_column;
+ if (warn_level == GDScriptWarning::WarnLevel::ERROR) {
+ push_error(warning.get_message(), p_source);
+ return;
+ }
+
List<GDScriptWarning>::Element *before = nullptr;
for (List<GDScriptWarning>::Element *E = warnings.front(); E; E = E->next()) {
if (E->get().start_line > warning.start_line) {
@@ -1626,6 +1630,10 @@ GDScriptParser::Node *GDScriptParser::parse_statement() {
case Node::AWAIT:
// Fine.
break;
+ case Node::LAMBDA:
+ // Standalone lambdas can't be used, so make this an error.
+ push_error("Standalone lambdas cannot be accessed. Consider assigning it to a variable.", expression);
+ break;
default:
push_warning(expression, GDScriptWarning::STANDALONE_EXPRESSION);
}
@@ -1810,7 +1818,6 @@ GDScriptParser::MatchNode *GDScriptParser::parse_match() {
#ifdef DEBUG_ENABLED
bool all_have_return = true;
bool have_wildcard = false;
- bool wildcard_has_return = false;
bool have_wildcard_without_continue = false;
#endif
@@ -1828,9 +1835,6 @@ GDScriptParser::MatchNode *GDScriptParser::parse_match() {
if (branch->has_wildcard) {
have_wildcard = true;
- if (branch->block->has_return) {
- wildcard_has_return = true;
- }
if (!branch->block->has_continue) {
have_wildcard_without_continue = true;
}
@@ -1845,7 +1849,7 @@ GDScriptParser::MatchNode *GDScriptParser::parse_match() {
consume(GDScriptTokenizer::Token::DEDENT, R"(Expected an indented block after "match" statement.)");
#ifdef DEBUG_ENABLED
- if (wildcard_has_return || (all_have_return && have_wildcard)) {
+ if (all_have_return && have_wildcard) {
current_suite->has_return = true;
}
#endif
@@ -1863,7 +1867,7 @@ GDScriptParser::MatchBranchNode *GDScriptParser::parse_match_branch() {
if (pattern == nullptr) {
continue;
}
- if (pattern->pattern_type == PatternNode::PT_BIND) {
+ if (pattern->binds.size() > 0) {
has_bind = true;
}
if (branch->patterns.size() > 0 && has_bind) {
@@ -1894,11 +1898,9 @@ GDScriptParser::MatchBranchNode *GDScriptParser::parse_match_branch() {
SuiteNode *suite = alloc_node<SuiteNode>();
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;
suite->add_local(local);
}
}
@@ -2107,7 +2109,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_precedence(Precedence p_pr
ExpressionNode *previous_operand = (this->*prefix_rule)(nullptr, p_can_assign);
while (p_precedence <= get_rule(current.type)->precedence) {
- if (previous_operand == nullptr || (p_stop_on_assign && current.type == GDScriptTokenizer::Token::EQUAL)) {
+ if (previous_operand == nullptr || (p_stop_on_assign && current.type == GDScriptTokenizer::Token::EQUAL) || (previous_operand->type == Node::LAMBDA && lambda_ended)) {
return previous_operand;
}
// Also switch multiline mode on here for infix operators.
@@ -2319,6 +2321,10 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_binary_operator(Expression
operation->operation = BinaryOpNode::OP_MODULO;
operation->variant_op = Variant::OP_MODULE;
break;
+ case GDScriptTokenizer::Token::STAR_STAR:
+ operation->operation = BinaryOpNode::OP_POWER;
+ operation->variant_op = Variant::OP_POWER;
+ break;
case GDScriptTokenizer::Token::LESS_LESS:
operation->operation = BinaryOpNode::OP_BIT_LEFT_SHIFT;
operation->variant_op = Variant::OP_SHIFT_LEFT;
@@ -2482,6 +2488,10 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_assignment(ExpressionNode
assignment->operation = AssignmentNode::OP_MULTIPLICATION;
assignment->variant_op = Variant::OP_MULTIPLY;
break;
+ case GDScriptTokenizer::Token::STAR_STAR_EQUAL:
+ assignment->operation = AssignmentNode::OP_POWER;
+ assignment->variant_op = Variant::OP_POWER;
+ break;
case GDScriptTokenizer::Token::SLASH_EQUAL:
assignment->operation = AssignmentNode::OP_DIVISION;
assignment->variant_op = Variant::OP_DIVIDE;
@@ -2820,51 +2830,97 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre
}
GDScriptParser::ExpressionNode *GDScriptParser::parse_get_node(ExpressionNode *p_previous_operand, bool p_can_assign) {
- if (match(GDScriptTokenizer::Token::LITERAL)) {
- if (previous.literal.get_type() != Variant::STRING) {
- push_error(R"(Expect node path as string or identifier after "$".)");
+ if (!current.is_node_name() && !check(GDScriptTokenizer::Token::LITERAL) && !check(GDScriptTokenizer::Token::SLASH) && !check(GDScriptTokenizer::Token::PERCENT)) {
+ push_error(vformat(R"(Expected node path as string or identifier after "%s".)", previous.get_name()));
+ return nullptr;
+ }
+
+ if (check(GDScriptTokenizer::Token::LITERAL)) {
+ if (current.literal.get_type() != Variant::STRING) {
+ push_error(vformat(R"(Expected node path as string or identifier after "%s".)", previous.get_name()));
return nullptr;
}
- GetNodeNode *get_node = alloc_node<GetNodeNode>();
- make_completion_context(COMPLETION_GET_NODE, get_node);
- get_node->string = parse_literal();
- return get_node;
- } else if (current.is_node_name()) {
- GetNodeNode *get_node = alloc_node<GetNodeNode>();
- int chain_position = 0;
- do {
- make_completion_context(COMPLETION_GET_NODE, get_node, chain_position++);
- if (!current.is_node_name()) {
- push_error(R"(Expect node path after "/".)");
+ }
+
+ GetNodeNode *get_node = alloc_node<GetNodeNode>();
+
+ // Store the last item in the path so the parser knows what to expect.
+ // Allow allows more specific error messages.
+ enum PathState {
+ PATH_STATE_START,
+ PATH_STATE_SLASH,
+ PATH_STATE_PERCENT,
+ PATH_STATE_NODE_NAME,
+ } path_state = PATH_STATE_START;
+
+ if (previous.type == GDScriptTokenizer::Token::DOLLAR) {
+ // Detect initial slash, which will be handled in the loop if it matches.
+ match(GDScriptTokenizer::Token::SLASH);
+#ifdef DEBUG_ENABLED
+ } else {
+ get_node->use_dollar = false;
+#endif
+ }
+
+ int context_argument = 0;
+
+ do {
+ if (previous.type == GDScriptTokenizer::Token::PERCENT) {
+ if (path_state != PATH_STATE_START && path_state != PATH_STATE_SLASH) {
+ push_error(R"("%" is only valid in the beginning of a node name (either after "$" or after "/"))");
return nullptr;
}
- advance();
- IdentifierNode *identifier = alloc_node<IdentifierNode>();
- identifier->name = previous.get_identifier();
- get_node->chain.push_back(identifier);
- } while (match(GDScriptTokenizer::Token::SLASH));
- return get_node;
- } else if (match(GDScriptTokenizer::Token::SLASH)) {
- GetNodeNode *get_node = alloc_node<GetNodeNode>();
- IdentifierNode *identifier_root = alloc_node<IdentifierNode>();
- get_node->chain.push_back(identifier_root);
- int chain_position = 0;
- do {
- make_completion_context(COMPLETION_GET_NODE, get_node, chain_position++);
- if (!current.is_node_name()) {
- push_error(R"(Expect node path after "/".)");
+ get_node->full_path += "%";
+
+ path_state = PATH_STATE_PERCENT;
+ } else if (previous.type == GDScriptTokenizer::Token::SLASH) {
+ if (path_state != PATH_STATE_START && path_state != PATH_STATE_NODE_NAME) {
+ push_error(R"("/" is only valid at the beginning of the path or after a node name.)");
return nullptr;
}
+
+ get_node->full_path += "/";
+
+ path_state = PATH_STATE_SLASH;
+ }
+
+ make_completion_context(COMPLETION_GET_NODE, get_node, context_argument++);
+
+ if (match(GDScriptTokenizer::Token::LITERAL)) {
+ if (previous.literal.get_type() != Variant::STRING) {
+ String previous_token;
+ switch (path_state) {
+ case PATH_STATE_START:
+ previous_token = "$";
+ break;
+ case PATH_STATE_PERCENT:
+ previous_token = "%";
+ break;
+ case PATH_STATE_SLASH:
+ previous_token = "/";
+ break;
+ default:
+ break;
+ }
+ push_error(vformat(R"(Expected node path as string or identifier after "%s".)", previous_token));
+ return nullptr;
+ }
+
+ get_node->full_path += previous.literal.operator String();
+
+ path_state = PATH_STATE_NODE_NAME;
+ } else if (current.is_node_name()) {
advance();
- IdentifierNode *identifier = alloc_node<IdentifierNode>();
- identifier->name = previous.get_identifier();
- get_node->chain.push_back(identifier);
- } while (match(GDScriptTokenizer::Token::SLASH));
- return get_node;
- } else {
- push_error(R"(Expect node path as string or identifier after "$".)");
- return nullptr;
- }
+ get_node->full_path += previous.get_identifier();
+
+ path_state = PATH_STATE_NODE_NAME;
+ } else if (!check(GDScriptTokenizer::Token::SLASH) && !check(GDScriptTokenizer::Token::PERCENT)) {
+ push_error(vformat(R"(Unexpected "%s" in node path.)", current.get_name()));
+ return nullptr;
+ }
+ } while (match(GDScriptTokenizer::Token::SLASH) || match(GDScriptTokenizer::Token::PERCENT));
+
+ return get_node;
}
GDScriptParser::ExpressionNode *GDScriptParser::parse_preload(ExpressionNode *p_previous_operand, bool p_can_assign) {
@@ -2922,6 +2978,9 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_lambda(ExpressionNode *p_p
current_function = function;
SuiteNode *body = alloc_node<SuiteNode>();
+ body->parent_function = current_function;
+ body->parent_block = current_suite;
+
SuiteNode *previous_suite = current_suite;
current_suite = body;
@@ -3049,7 +3108,7 @@ bool GDScriptParser::has_comment(int p_line) {
}
String GDScriptParser::get_doc_comment(int p_line, bool p_single_line) {
- const Map<int, GDScriptTokenizer::CommentData> &comments = tokenizer.get_comments();
+ const HashMap<int, GDScriptTokenizer::CommentData> &comments = tokenizer.get_comments();
ERR_FAIL_COND_V(!comments.has(p_line), String());
if (p_single_line) {
@@ -3101,7 +3160,7 @@ String GDScriptParser::get_doc_comment(int p_line, bool p_single_line) {
}
void GDScriptParser::get_class_doc_comment(int p_line, String &p_brief, String &p_desc, Vector<Pair<String, String>> &p_tutorials, bool p_inner_class) {
- const Map<int, GDScriptTokenizer::CommentData> &comments = tokenizer.get_comments();
+ const HashMap<int, GDScriptTokenizer::CommentData> &comments = tokenizer.get_comments();
if (!comments.has(p_line)) {
return;
}
@@ -3134,24 +3193,23 @@ void GDScriptParser::get_class_doc_comment(int p_line, String &p_brief, String &
String title, link; // For tutorials.
String doc_line = comments[line++].comment.trim_prefix("##");
- String striped_line = doc_line.strip_edges();
+ String stripped_line = doc_line.strip_edges();
// Set the read mode.
- if (striped_line.begins_with("@desc:") && p_desc.is_empty()) {
+ if (stripped_line.is_empty() && mode == BRIEF && !p_brief.is_empty()) {
mode = DESC;
- striped_line = striped_line.trim_prefix("@desc:");
- in_codeblock = _in_codeblock(doc_line, in_codeblock);
+ continue;
- } else if (striped_line.begins_with("@tutorial")) {
+ } else if (stripped_line.begins_with("@tutorial")) {
int begin_scan = String("@tutorial").length();
- if (begin_scan >= striped_line.length()) {
+ if (begin_scan >= stripped_line.length()) {
continue; // invalid syntax.
}
- if (striped_line[begin_scan] == ':') { // No title.
+ if (stripped_line[begin_scan] == ':') { // No title.
// Syntax: ## @tutorial: https://godotengine.org/ // The title argument is optional.
title = "";
- link = striped_line.trim_prefix("@tutorial:").strip_edges();
+ link = stripped_line.trim_prefix("@tutorial:").strip_edges();
} else {
/* Syntax:
@@ -3159,35 +3217,35 @@ void GDScriptParser::get_class_doc_comment(int p_line, String &p_brief, String &
* ^ open ^ close ^ colon ^ url
*/
int open_bracket_pos = begin_scan, close_bracket_pos = 0;
- while (open_bracket_pos < striped_line.length() && (striped_line[open_bracket_pos] == ' ' || striped_line[open_bracket_pos] == '\t')) {
+ while (open_bracket_pos < stripped_line.length() && (stripped_line[open_bracket_pos] == ' ' || stripped_line[open_bracket_pos] == '\t')) {
open_bracket_pos++;
}
- if (open_bracket_pos == striped_line.length() || striped_line[open_bracket_pos++] != '(') {
+ if (open_bracket_pos == stripped_line.length() || stripped_line[open_bracket_pos++] != '(') {
continue; // invalid syntax.
}
close_bracket_pos = open_bracket_pos;
- while (close_bracket_pos < striped_line.length() && striped_line[close_bracket_pos] != ')') {
+ while (close_bracket_pos < stripped_line.length() && stripped_line[close_bracket_pos] != ')') {
close_bracket_pos++;
}
- if (close_bracket_pos == striped_line.length()) {
+ if (close_bracket_pos == stripped_line.length()) {
continue; // invalid syntax.
}
int colon_pos = close_bracket_pos + 1;
- while (colon_pos < striped_line.length() && (striped_line[colon_pos] == ' ' || striped_line[colon_pos] == '\t')) {
+ while (colon_pos < stripped_line.length() && (stripped_line[colon_pos] == ' ' || stripped_line[colon_pos] == '\t')) {
colon_pos++;
}
- if (colon_pos == striped_line.length() || striped_line[colon_pos++] != ':') {
+ if (colon_pos == stripped_line.length() || stripped_line[colon_pos++] != ':') {
continue; // invalid syntax.
}
- title = striped_line.substr(open_bracket_pos, close_bracket_pos - open_bracket_pos).strip_edges();
- link = striped_line.substr(colon_pos).strip_edges();
+ title = stripped_line.substr(open_bracket_pos, close_bracket_pos - open_bracket_pos).strip_edges();
+ link = stripped_line.substr(colon_pos).strip_edges();
}
mode = TUTORIALS;
in_codeblock = false;
- } else if (striped_line.is_empty()) {
+ } else if (stripped_line.is_empty()) {
continue;
} else {
// Tutorial docs are single line, we need a @tag after it.
@@ -3207,7 +3265,7 @@ void GDScriptParser::get_class_doc_comment(int p_line, String &p_brief, String &
}
doc_line = doc_line.substr(i);
} else {
- doc_line = striped_line;
+ doc_line = stripped_line;
}
String line_join = (in_codeblock) ? "\n" : " ";
@@ -3264,13 +3322,15 @@ GDScriptParser::ParseRule *GDScriptParser::get_rule(GDScriptTokenizer::Token::Ty
{ &GDScriptParser::parse_unary_operator, &GDScriptParser::parse_binary_operator, PREC_ADDITION_SUBTRACTION }, // PLUS,
{ &GDScriptParser::parse_unary_operator, &GDScriptParser::parse_binary_operator, PREC_ADDITION_SUBTRACTION }, // MINUS,
{ nullptr, &GDScriptParser::parse_binary_operator, PREC_FACTOR }, // STAR,
+ { nullptr, &GDScriptParser::parse_binary_operator, PREC_POWER }, // STAR_STAR,
{ nullptr, &GDScriptParser::parse_binary_operator, PREC_FACTOR }, // SLASH,
- { nullptr, &GDScriptParser::parse_binary_operator, PREC_FACTOR }, // PERCENT,
+ { &GDScriptParser::parse_get_node, &GDScriptParser::parse_binary_operator, PREC_FACTOR }, // PERCENT,
// Assignment
{ nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // EQUAL,
{ nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // PLUS_EQUAL,
{ nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // MINUS_EQUAL,
{ nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // STAR_EQUAL,
+ { nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // STAR_STAR_EQUAL,
{ nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // SLASH_EQUAL,
{ nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // PERCENT_EQUAL,
{ nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // LESS_LESS_EQUAL,
@@ -3555,14 +3615,16 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
variable->export_info.hint = PROPERTY_HINT_ENUM;
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 += ",";
+ } else {
+ 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;
@@ -3895,6 +3957,9 @@ void GDScriptParser::TreePrinter::print_assignment(AssignmentNode *p_assignment)
case AssignmentNode::OP_MODULO:
push_text("%");
break;
+ case AssignmentNode::OP_POWER:
+ push_text("**");
+ break;
case AssignmentNode::OP_BIT_SHIFT_LEFT:
push_text("<<");
break;
@@ -3943,6 +4008,9 @@ void GDScriptParser::TreePrinter::print_binary_op(BinaryOpNode *p_binary_op) {
case BinaryOpNode::OP_MODULO:
push_text(" % ");
break;
+ case BinaryOpNode::OP_POWER:
+ push_text(" ** ");
+ break;
case BinaryOpNode::OP_BIT_LEFT_SHIFT:
push_text(" << ");
break;
@@ -4236,17 +4304,10 @@ void GDScriptParser::TreePrinter::print_function(FunctionNode *p_function, const
}
void GDScriptParser::TreePrinter::print_get_node(GetNodeNode *p_get_node) {
- push_text("$");
- if (p_get_node->string != nullptr) {
- print_literal(p_get_node->string);
- } else {
- for (int i = 0; i < p_get_node->chain.size(); i++) {
- if (i > 0) {
- push_text("/");
- }
- print_identifier(p_get_node->chain[i]);
- }
+ if (p_get_node->use_dollar) {
+ push_text("$");
}
+ push_text(p_get_node->full_path);
}
void GDScriptParser::TreePrinter::print_identifier(IdentifierNode *p_identifier) {
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index 10474db02f..e3f8d4b8ba 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -39,7 +39,7 @@
#include "core/string/ustring.h"
#include "core/templates/hash_map.h"
#include "core/templates/list.h"
-#include "core/templates/map.h"
+#include "core/templates/rb_map.h"
#include "core/templates/vector.h"
#include "core/variant/variant.h"
#include "gdscript_cache.h"
@@ -132,7 +132,7 @@ public:
ClassNode *class_type = nullptr;
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 has_no_type() const { return type_source == UNDETECTED; }
@@ -360,6 +360,7 @@ public:
OP_MULTIPLICATION,
OP_DIVISION,
OP_MODULO,
+ OP_POWER,
OP_BIT_SHIFT_LEFT,
OP_BIT_SHIFT_RIGHT,
OP_BIT_AND,
@@ -393,6 +394,7 @@ public:
OP_MULTIPLICATION,
OP_DIVISION,
OP_MODULO,
+ OP_POWER,
OP_BIT_LEFT_SHIFT,
OP_BIT_RIGHT_SHIFT,
OP_BIT_AND,
@@ -747,8 +749,10 @@ public:
};
struct GetNodeNode : public ExpressionNode {
- LiteralNode *string = nullptr;
- Vector<IdentifierNode *> chain;
+ String full_path;
+#ifdef DEBUG_ENABLED
+ bool use_dollar = true;
+#endif
GetNodeNode() {
type = GET_NODE;
@@ -800,7 +804,7 @@ public:
FunctionNode *function = nullptr;
FunctionNode *parent_function = nullptr;
Vector<IdentifierNode *> captures;
- Map<StringName, int> captures_indices;
+ HashMap<StringName, int> captures_indices;
bool use_self = false;
bool has_name() const {
@@ -1203,9 +1207,9 @@ private:
List<ParserError> errors;
#ifdef DEBUG_ENABLED
List<GDScriptWarning> warnings;
- Set<String> ignored_warnings;
- Set<uint32_t> ignored_warning_codes;
- Set<int> unsafe_lines;
+ HashSet<String> ignored_warnings;
+ HashSet<uint32_t> ignored_warning_codes;
+ HashSet<int> unsafe_lines;
#endif
GDScriptTokenizer tokenizer;
@@ -1263,6 +1267,7 @@ private:
PREC_FACTOR,
PREC_SIGN,
PREC_BIT_NOT,
+ PREC_POWER,
PREC_TYPE_TEST,
PREC_AWAIT,
PREC_CALL,
@@ -1416,7 +1421,7 @@ public:
}
#ifdef DEBUG_ENABLED
const List<GDScriptWarning> &get_warnings() const { return warnings; }
- const Set<int> &get_unsafe_lines() const { return unsafe_lines; }
+ const HashSet<int> &get_unsafe_lines() const { return unsafe_lines; }
int get_last_line_number() const { return current.end_line; }
#endif
diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp
index 63fad0d9bb..6c17afe939 100644
--- a/modules/gdscript/gdscript_tokenizer.cpp
+++ b/modules/gdscript/gdscript_tokenizer.cpp
@@ -67,6 +67,7 @@ static const char *token_names[] = {
"+", // PLUS,
"-", // MINUS,
"*", // STAR,
+ "**", // STAR_STAR,
"/", // SLASH,
"%", // PERCENT,
// Assignment
@@ -74,6 +75,7 @@ static const char *token_names[] = {
"+=", // PLUS_EQUAL,
"-=", // MINUS_EQUAL,
"*=", // STAR_EQUAL,
+ "**=", // STAR_STAR_EQUAL,
"/=", // SLASH_EQUAL,
"%=", // PERCENT_EQUAL,
"<<=", // LESS_LESS_EQUAL,
@@ -1403,6 +1405,14 @@ GDScriptTokenizer::Token GDScriptTokenizer::scan() {
if (_peek() == '=') {
_advance();
return make_token(Token::STAR_EQUAL);
+ } else if (_peek() == '*') {
+ if (_peek(1) == '=') {
+ _advance();
+ _advance(); // Advance both '*' and '='
+ return make_token(Token::STAR_STAR_EQUAL);
+ }
+ _advance();
+ return make_token(Token::STAR_STAR);
} else {
return make_token(Token::STAR);
}
diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h
index abd090e381..7fb715f2c8 100644
--- a/modules/gdscript/gdscript_tokenizer.h
+++ b/modules/gdscript/gdscript_tokenizer.h
@@ -31,9 +31,9 @@
#ifndef GDSCRIPT_TOKENIZER_H
#define GDSCRIPT_TOKENIZER_H
+#include "core/templates/hash_map.h"
+#include "core/templates/hash_set.h"
#include "core/templates/list.h"
-#include "core/templates/map.h"
-#include "core/templates/set.h"
#include "core/templates/vector.h"
#include "core/variant/variant.h"
@@ -78,6 +78,7 @@ public:
PLUS,
MINUS,
STAR,
+ STAR_STAR,
SLASH,
PERCENT,
// Assignment
@@ -85,6 +86,7 @@ public:
PLUS_EQUAL,
MINUS_EQUAL,
STAR_EQUAL,
+ STAR_STAR_EQUAL,
SLASH_EQUAL,
PERCENT_EQUAL,
LESS_LESS_EQUAL,
@@ -191,7 +193,7 @@ public:
new_line = p_new_line;
}
};
- const Map<int, CommentData> &get_comments() const {
+ const HashMap<int, CommentData> &get_comments() const {
return comments;
}
#endif // TOOLS_ENABLED
@@ -224,7 +226,7 @@ private:
int length = 0;
#ifdef TOOLS_ENABLED
- Map<int, CommentData> comments;
+ HashMap<int, CommentData> comments;
#endif // TOOLS_ENABLED
_FORCE_INLINE_ bool _is_at_end() { return position >= length; }
diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp
index e28dd26c28..55f4ebb1c5 100644
--- a/modules/gdscript/gdscript_vm.cpp
+++ b/modules/gdscript/gdscript_vm.cpp
@@ -546,33 +546,32 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
memnew_placement(&stack[i], Variant);
}
- memnew_placement(&stack[ADDR_STACK_NIL], Variant);
-
if (_instruction_args_size) {
instruction_args = (Variant **)&aptr[sizeof(Variant) * _stack_size];
} else {
instruction_args = nullptr;
}
- if (p_instance) {
- memnew_placement(&stack[ADDR_STACK_SELF], Variant(p_instance->owner));
- script = p_instance->script.ptr();
- } else {
- memnew_placement(&stack[ADDR_STACK_SELF], Variant);
- script = _script;
+ for (const KeyValue<int, Variant::Type> &E : temporary_slots) {
+ type_init_function_table[E.value](&stack[E.key]);
}
}
+
if (_ptrcall_args_size) {
call_args_ptr = (const void **)alloca(_ptrcall_args_size * sizeof(void *));
} else {
call_args_ptr = nullptr;
}
- memnew_placement(&stack[ADDR_STACK_CLASS], Variant(script));
-
- for (const KeyValue<int, Variant::Type> &E : temporary_slots) {
- type_init_function_table[E.value](&stack[E.key]);
+ if (p_instance) {
+ memnew_placement(&stack[ADDR_STACK_SELF], Variant(p_instance->owner));
+ script = p_instance->script.ptr();
+ } else {
+ memnew_placement(&stack[ADDR_STACK_SELF], Variant);
+ script = _script;
}
+ memnew_placement(&stack[ADDR_STACK_CLASS], Variant(script));
+ memnew_placement(&stack[ADDR_STACK_NIL], Variant);
String err_text;
@@ -2104,7 +2103,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
const GDScript *gds = _script;
- const Map<StringName, GDScriptFunction *>::Element *E = nullptr;
+ HashMap<StringName, GDScriptFunction *>::ConstIterator E;
while (gds->base.ptr()) {
gds = gds->base.ptr();
E = gds->member_functions.find(*methodname);
@@ -2116,7 +2115,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
Callable::CallError err;
if (E) {
- *dst = E->get()->call(p_instance, (const Variant **)argptrs, argc, err);
+ *dst = E->value->call(p_instance, (const Variant **)argptrs, argc, err);
} else if (gds->native.ptr()) {
if (*methodname != GDScriptLanguage::get_singleton()->strings._init) {
MethodBind *mb = ClassDB::get_method(gds->native->get_name(), *methodname);
@@ -2171,8 +2170,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
// Is this even possible to be null at this point?
if (obj) {
if (obj->is_class_ptr(GDScriptFunctionState::get_class_ptr_static())) {
- static StringName completed = _scs_create("completed");
- result = Signal(obj, completed);
+ result = Signal(obj, "completed");
}
}
}
@@ -2193,8 +2191,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
gdfs->function = this;
gdfs->state.stack.resize(alloca_size);
- //copy variant stack
- for (int i = 0; i < _stack_size; i++) {
+
+ // First 3 stack addresses are special, so we just skip them here.
+ for (int i = 3; i < _stack_size; i++) {
memnew_placement(&gdfs->state.stack.write[sizeof(Variant) * i], Variant(stack[i]));
}
gdfs->state.stack_size = _stack_size;
@@ -3451,26 +3450,27 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
GDScriptLanguage::get_singleton()->script_frame_time += time_taken - function_call_time;
}
- // Check if this is the last time the function is resuming from await
- // Will be true if never awaited as well
- // When it's the last resume it will postpone the exit from stack,
- // so the debugger knows which function triggered the resume of the next function (if any)
+ // Check if this is not the last time it was interrupted by `await` or if it's the first time executing.
+ // If that is the case then we exit the function as normal. Otherwise we postpone it until the last `await` is completed.
+ // This ensures the call stack can be properly shown when using `await`, showing what resumed the function.
if (!p_state || awaited) {
if (EngineDebugger::is_active()) {
GDScriptLanguage::get_singleton()->exit_function();
}
#endif
- if (_stack_size) {
- //free stack
- for (int i = 0; i < _stack_size; i++) {
- stack[i].~Variant();
- }
+ // Free stack, except reserved addresses.
+ for (int i = 3; i < _stack_size; i++) {
+ stack[i].~Variant();
}
-
#ifdef DEBUG_ENABLED
}
#endif
+ // Always free reserved addresses, since they are never copied.
+ for (int i = 0; i < 3; i++) {
+ stack[i].~Variant();
+ }
+
return retvalue;
}
diff --git a/modules/gdscript/gdscript_warning.cpp b/modules/gdscript/gdscript_warning.cpp
index ad96e36640..1cae7bdfac 100644
--- a/modules/gdscript/gdscript_warning.cpp
+++ b/modules/gdscript/gdscript_warning.cpp
@@ -163,6 +163,18 @@ String GDScriptWarning::get_message() const {
#undef CHECK_SYMBOLS
}
+int GDScriptWarning::get_default_value(Code p_code) {
+ if (get_name_from_code(p_code).to_lower().begins_with("unsafe_")) {
+ return WarnLevel::IGNORE;
+ }
+ return WarnLevel::WARN;
+}
+
+PropertyInfo GDScriptWarning::get_property_info(Code p_code) {
+ // Making this a separate function in case a warning needs different PropertyInfo in the future.
+ return PropertyInfo(Variant::INT, get_settings_path_from_code(p_code), PROPERTY_HINT_ENUM, "Ignore,Warn,Error");
+}
+
String GDScriptWarning::get_name() const {
return get_name_from_code(code);
}
@@ -210,6 +222,10 @@ String GDScriptWarning::get_name_from_code(Code p_code) {
return names[(int)p_code];
}
+String GDScriptWarning::get_settings_path_from_code(Code p_code) {
+ return "debug/gdscript/warnings/" + get_name_from_code(p_code).to_lower();
+}
+
GDScriptWarning::Code GDScriptWarning::get_code_from_name(const String &p_name) {
for (int i = 0; i < WARNING_MAX; i++) {
if (get_name_from_code((Code)i) == p_name) {
diff --git a/modules/gdscript/gdscript_warning.h b/modules/gdscript/gdscript_warning.h
index 82efe3568f..f47f31aedf 100644
--- a/modules/gdscript/gdscript_warning.h
+++ b/modules/gdscript/gdscript_warning.h
@@ -33,11 +33,18 @@
#ifdef DEBUG_ENABLED
+#include "core/object/object.h"
#include "core/string/ustring.h"
#include "core/templates/vector.h"
class GDScriptWarning {
public:
+ enum WarnLevel {
+ IGNORE,
+ WARN,
+ ERROR
+ };
+
enum Code {
UNASSIGNED_VARIABLE, // Variable used but never assigned.
UNASSIGNED_VARIABLE_OP_ASSIGN, // Variable never assigned but used in an assignment operation (+=, *=, etc).
@@ -81,7 +88,10 @@ public:
String get_name() const;
String get_message() const;
+ static int get_default_value(Code p_code);
+ static PropertyInfo get_property_info(Code p_code);
static String get_name_from_code(Code p_code);
+ static String get_settings_path_from_code(Code p_code);
static Code get_code_from_name(const String &p_name);
};
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp
index 5516f59fe9..d3c5fed95a 100644
--- a/modules/gdscript/language_server/gdscript_extend_parser.cpp
+++ b/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++) {
const lsp::DocumentSymbol &symbol = class_symbol.children[i];
- members.set(symbol.name, &symbol);
+ members.insert(symbol.name, &symbol);
// cache level one inner classes
if (symbol.kind == lsp::SymbolKind::Class) {
ClassMembers inner_class;
for (int j = 0; j < symbol.children.size(); 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);
}
}
}
@@ -216,8 +216,8 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
if (res.is_valid() && !res->get_path().is_empty()) {
value_text = "preload(\"" + res->get_path() + "\")";
if (symbol.documentation.is_empty()) {
- if (Map<String, ExtendGDScriptParser *>::Element *S = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(res->get_path())) {
- symbol.documentation = S->get()->class_symbol.documentation;
+ if (HashMap<String, ExtendGDScriptParser *>::Iterator S = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(res->get_path())) {
+ symbol.documentation = S->value->class_symbol.documentation;
}
}
} else {
@@ -661,30 +661,22 @@ const List<lsp::DocumentLink> &ExtendGDScriptParser::get_document_links() const
const Array &ExtendGDScriptParser::get_member_completions() {
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();
- item.data = JOIN_SYMBOLS(path, *name);
+ item.data = JOIN_SYMBOLS(path, E.key);
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();
- 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_name = inner_class->next(member_name);
}
-
- _class = inner_classes.next(_class);
}
}
diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp
index cdddab319d..7460f8edff 100644
--- a/modules/gdscript/language_server/gdscript_language_protocol.cpp
+++ b/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");
Ref<LSPeer> peer = memnew(LSPeer);
peer->connection = tcp_peer;
- clients.set(next_client_id, peer);
+ clients.insert(next_client_id, peer);
next_client_id++;
EditorNode::get_log()->add_message("[LSP] Connection Taken", EditorLog::MSG_TYPE_EDITOR);
return OK;
@@ -229,28 +229,33 @@ void GDScriptLanguageProtocol::poll() {
if (server->is_connection_available()) {
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();
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 {
if (peer->connection->get_available_bytes() > 0) {
- latest_client_id = *id;
+ latest_client_id = E->key;
Error err = peer->handle_data();
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();
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() {
- 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();
}
diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp
index c42bd58aeb..d763701911 100644
--- a/modules/gdscript/language_server/gdscript_text_document.cpp
+++ b/modules/gdscript/language_server/gdscript_text_document.cpp
@@ -109,23 +109,15 @@ void GDScriptTextDocument::notify_client_show_symbol(const lsp::DocumentSymbol *
void GDScriptTextDocument::initialize() {
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();
- 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());
-
- name = members.next(name);
}
-
- class_ptr = native_members.next(class_ptr);
}
}
}
@@ -149,9 +141,9 @@ Array GDScriptTextDocument::documentSymbol(const Dictionary &p_params) {
String uri = params["uri"];
String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(uri);
Array arr;
- if (const Map<String, ExtendGDScriptParser *>::Element *parser = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(path)) {
+ if (HashMap<String, ExtendGDScriptParser *>::ConstIterator parser = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(path)) {
Vector<lsp::DocumentedSymbolInformation> list;
- parser->get()->get_symbols().symbol_tree_as_list(uri, list);
+ parser->value->get_symbols().symbol_tree_as_list(uri, list);
for (int i = 0; i < list.size(); i++) {
arr.push_back(list[i].to_json());
}
@@ -275,8 +267,8 @@ Dictionary GDScriptTextDocument::resolve(const Dictionary &p_params) {
}
if (!symbol) {
- if (const Map<String, ExtendGDScriptParser *>::Element *E = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(class_name)) {
- symbol = E->get()->get_member_symbol(member_name, inner_class_name);
+ if (HashMap<String, ExtendGDScriptParser *>::ConstIterator E = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(class_name)) {
+ symbol = E->value->get_member_symbol(member_name, inner_class_name);
}
}
}
diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp
index 89ee6b35e5..8d484a43b3 100644
--- a/modules/gdscript/language_server/gdscript_workspace.cpp
+++ b/modules/gdscript/language_server/gdscript_workspace.cpp
@@ -116,22 +116,22 @@ void GDScriptWorkspace::did_delete_files(const Dictionary &p_params) {
}
void GDScriptWorkspace::remove_cache_parser(const String &p_path) {
- Map<String, ExtendGDScriptParser *>::Element *parser = parse_results.find(p_path);
- Map<String, ExtendGDScriptParser *>::Element *script = scripts.find(p_path);
+ HashMap<String, ExtendGDScriptParser *>::Iterator parser = parse_results.find(p_path);
+ HashMap<String, ExtendGDScriptParser *>::Iterator script = scripts.find(p_path);
if (parser && script) {
- if (script->get() && script->get() == parser->get()) {
- memdelete(script->get());
+ if (script->value && script->value == parser->value) {
+ memdelete(script->value);
} else {
- memdelete(script->get());
- memdelete(parser->get());
+ memdelete(script->value);
+ memdelete(parser->value);
}
parse_results.erase(p_path);
scripts.erase(p_path);
} else if (parser) {
- memdelete(parser->get());
+ memdelete(parser->value);
parse_results.erase(p_path);
} else if (script) {
- memdelete(script->get());
+ memdelete(script->value);
scripts.erase(p_path);
}
}
@@ -141,8 +141,8 @@ const lsp::DocumentSymbol *GDScriptWorkspace::get_native_symbol(const String &p_
StringName empty;
while (class_name != empty) {
- if (const Map<StringName, lsp::DocumentSymbol>::Element *E = native_symbols.find(class_name)) {
- const lsp::DocumentSymbol &class_symbol = E->value();
+ if (HashMap<StringName, lsp::DocumentSymbol>::ConstIterator E = native_symbols.find(class_name)) {
+ const lsp::DocumentSymbol &class_symbol = E->value;
if (p_member.is_empty()) {
return &class_symbol;
@@ -162,9 +162,9 @@ const lsp::DocumentSymbol *GDScriptWorkspace::get_native_symbol(const String &p_
}
const lsp::DocumentSymbol *GDScriptWorkspace::get_script_symbol(const String &p_path) const {
- const Map<String, ExtendGDScriptParser *>::Element *S = scripts.find(p_path);
+ HashMap<String, ExtendGDScriptParser *>::ConstIterator S = scripts.find(p_path);
if (S) {
- return &(S->get()->get_symbols());
+ return &(S->value->get_symbols());
}
return nullptr;
}
@@ -209,10 +209,10 @@ void GDScriptWorkspace::reload_all_workspace_scripts() {
err = parse_script(path, content);
if (err != OK) {
- Map<String, ExtendGDScriptParser *>::Element *S = parse_results.find(path);
+ HashMap<String, ExtendGDScriptParser *>::Iterator S = parse_results.find(path);
String err_msg = "Failed parse script " + path;
if (S) {
- err_msg += "\n" + S->get()->get_errors()[0].message;
+ err_msg += "\n" + S->value->get_errors()[0].message;
}
ERR_CONTINUE_MSG(err != OK, err_msg);
}
@@ -238,25 +238,25 @@ void GDScriptWorkspace::list_script_files(const String &p_root_dir, List<String>
}
ExtendGDScriptParser *GDScriptWorkspace::get_parse_successed_script(const String &p_path) {
- const Map<String, ExtendGDScriptParser *>::Element *S = scripts.find(p_path);
+ HashMap<String, ExtendGDScriptParser *>::Iterator S = scripts.find(p_path);
if (!S) {
parse_local_script(p_path);
S = scripts.find(p_path);
}
if (S) {
- return S->get();
+ return S->value;
}
return nullptr;
}
ExtendGDScriptParser *GDScriptWorkspace::get_parse_result(const String &p_path) {
- const Map<String, ExtendGDScriptParser *>::Element *S = parse_results.find(p_path);
+ HashMap<String, ExtendGDScriptParser *>::Iterator S = parse_results.find(p_path);
if (!S) {
parse_local_script(p_path);
S = parse_results.find(p_path);
}
if (S) {
- return S->get();
+ return S->value;
}
return nullptr;
}
@@ -404,9 +404,9 @@ Error GDScriptWorkspace::initialize() {
const lsp::DocumentSymbol &class_symbol = E.value;
for (int i = 0; i < class_symbol.children.size(); 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
@@ -424,8 +424,8 @@ Error GDScriptWorkspace::initialize() {
Error GDScriptWorkspace::parse_script(const String &p_path, const String &p_content) {
ExtendGDScriptParser *parser = memnew(ExtendGDScriptParser);
Error err = parser->parse(p_content, p_path);
- Map<String, ExtendGDScriptParser *>::Element *last_parser = parse_results.find(p_path);
- Map<String, ExtendGDScriptParser *>::Element *last_script = scripts.find(p_path);
+ HashMap<String, ExtendGDScriptParser *>::Iterator last_parser = parse_results.find(p_path);
+ HashMap<String, ExtendGDScriptParser *>::Iterator last_script = scripts.find(p_path);
if (err == OK) {
remove_cache_parser(p_path);
@@ -433,8 +433,8 @@ Error GDScriptWorkspace::parse_script(const String &p_path, const String &p_cont
scripts[p_path] = parser;
} else {
- if (last_parser && last_script && last_parser->get() != last_script->get()) {
- memdelete(last_parser->get());
+ if (last_parser && last_script && last_parser->value != last_script->value) {
+ memdelete(last_parser->value);
}
parse_results[p_path] = parser;
}
@@ -513,9 +513,9 @@ String GDScriptWorkspace::get_file_uri(const String &p_path) const {
void GDScriptWorkspace::publish_diagnostics(const String &p_path) {
Dictionary params;
Array errors;
- const Map<String, ExtendGDScriptParser *>::Element *ele = parse_results.find(p_path);
+ HashMap<String, ExtendGDScriptParser *>::ConstIterator ele = parse_results.find(p_path);
if (ele) {
- const Vector<lsp::Diagnostic> &list = ele->get()->get_diagnostics();
+ const Vector<lsp::Diagnostic> &list = ele->value->get_diagnostics();
errors.resize(list.size());
for (int i = 0; i < list.size(); ++i) {
errors[i] = list[i].to_json();
@@ -682,13 +682,11 @@ void GDScriptWorkspace::resolve_related_symbols(const lsp::TextDocumentPositionP
Vector2i 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)) {
r_list.push_back(*symbol);
}
- class_ptr = native_members.next(class_ptr);
}
for (const KeyValue<String, ExtendGDScriptParser *> &E : scripts) {
@@ -698,23 +696,19 @@ void GDScriptWorkspace::resolve_related_symbols(const lsp::TextDocumentPositionP
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)) {
r_list.push_back(*symbol);
}
-
- _class = inner_classes.next(_class);
}
}
}
}
const lsp::DocumentSymbol *GDScriptWorkspace::resolve_native_symbol(const lsp::NativeSymbolInspectParams &p_params) {
- if (Map<StringName, lsp::DocumentSymbol>::Element *E = native_symbols.find(p_params.native_class)) {
- const lsp::DocumentSymbol &symbol = E->get();
+ if (HashMap<StringName, lsp::DocumentSymbol>::Iterator E = native_symbols.find(p_params.native_class)) {
+ const lsp::DocumentSymbol &symbol = E->value;
if (p_params.symbol_name.is_empty() || p_params.symbol_name == symbol.name) {
return &symbol;
}
@@ -790,7 +784,7 @@ GDScriptWorkspace::GDScriptWorkspace() {
}
GDScriptWorkspace::~GDScriptWorkspace() {
- Set<String> cached_parsers;
+ HashSet<String> cached_parsers;
for (const KeyValue<String, ExtendGDScriptParser *> &E : parse_results) {
cached_parsers.insert(E.key);
@@ -800,7 +794,7 @@ GDScriptWorkspace::~GDScriptWorkspace() {
cached_parsers.insert(E.key);
}
- for (Set<String>::Element *E = cached_parsers.front(); E; E = E->next()) {
- remove_cache_parser(E->get());
+ for (const String &E : cached_parsers) {
+ remove_cache_parser(E);
}
}
diff --git a/modules/gdscript/language_server/gdscript_workspace.h b/modules/gdscript/language_server/gdscript_workspace.h
index 92e78f8992..7bff5db81f 100644
--- a/modules/gdscript/language_server/gdscript_workspace.h
+++ b/modules/gdscript/language_server/gdscript_workspace.h
@@ -48,7 +48,7 @@ protected:
static void _bind_methods();
void remove_cache_parser(const String &p_path);
bool initialized = false;
- Map<StringName, lsp::DocumentSymbol> native_symbols;
+ HashMap<StringName, lsp::DocumentSymbol> native_symbols;
const lsp::DocumentSymbol *get_native_symbol(const String &p_class, const String &p_member = "") const;
const lsp::DocumentSymbol *get_script_symbol(const String &p_path) const;
@@ -68,8 +68,8 @@ public:
String root;
String root_uri;
- Map<String, ExtendGDScriptParser *> scripts;
- Map<String, ExtendGDScriptParser *> parse_results;
+ HashMap<String, ExtendGDScriptParser *> scripts;
+ HashMap<String, ExtendGDScriptParser *> parse_results;
HashMap<StringName, ClassMembers> native_members;
public:
diff --git a/modules/gdscript/language_server/lsp.hpp b/modules/gdscript/language_server/lsp.hpp
index a63f9df918..d4aa207972 100644
--- a/modules/gdscript/language_server/lsp.hpp
+++ b/modules/gdscript/language_server/lsp.hpp
@@ -261,7 +261,7 @@ struct WorkspaceEdit {
/**
* Holds changes to existing resources.
*/
- Map<String, Vector<TextEdit>> changes;
+ HashMap<String, Vector<TextEdit>> changes;
_FORCE_INLINE_ void add_edit(const String &uri, const TextEdit &edit) {
if (changes.has(uri)) {
@@ -293,8 +293,8 @@ struct WorkspaceEdit {
}
_FORCE_INLINE_ void add_change(const String &uri, const int &line, const int &start_character, const int &end_character, const String &new_text) {
- if (Map<String, Vector<TextEdit>>::Element *E = changes.find(uri)) {
- Vector<TextEdit> edit_list = E->value();
+ if (HashMap<String, Vector<TextEdit>>::Iterator E = changes.find(uri)) {
+ Vector<TextEdit> edit_list = E->value;
for (int i = 0; i < edit_list.size(); ++i) {
TextEdit edit = edit_list[i];
if (edit.range.start.character == start_character) {
@@ -310,8 +310,8 @@ struct WorkspaceEdit {
new_edit.range.end.line = line;
new_edit.range.end.character = end_character;
- if (Map<String, Vector<TextEdit>>::Element *E = changes.find(uri)) {
- E->value().push_back(new_edit);
+ if (HashMap<String, Vector<TextEdit>>::Iterator E = changes.find(uri)) {
+ E->value.push_back(new_edit);
} else {
Vector<TextEdit> edit_list;
edit_list.push_back(new_edit);
diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp
index 59acb1c064..b230c6ba36 100644
--- a/modules/gdscript/register_types.cpp
+++ b/modules/gdscript/register_types.cpp
@@ -70,7 +70,7 @@ class EditorExportGDScript : public EditorExportPlugin {
GDCLASS(EditorExportGDScript, EditorExportPlugin);
public:
- virtual void _export_file(const String &p_path, const String &p_type, const Set<String> &p_features) override {
+ virtual void _export_file(const String &p_path, const String &p_type, const HashSet<String> &p_features) override {
int script_mode = EditorExportPreset::MODE_SCRIPT_COMPILED;
String script_key;
diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp
index ea51990237..de5cd10e7c 100644
--- a/modules/gdscript/tests/gdscript_test_runner.cpp
+++ b/modules/gdscript/tests/gdscript_test_runner.cpp
@@ -48,11 +48,11 @@
namespace GDScriptTests {
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.
- 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) {
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
@@ -62,8 +62,8 @@ void init_autoloads() {
}
// 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) {
// Skip non-singletons since we don't have a scene tree here anyway.
@@ -543,8 +543,8 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) {
return result;
}
// Test running.
- const Map<StringName, GDScriptFunction *>::Element *test_function_element = script->get_member_functions().find(GDScriptTestRunner::test_function_name);
- if (test_function_element == nullptr) {
+ const HashMap<StringName, GDScriptFunction *>::ConstIterator test_function_element = script->get_member_functions().find(GDScriptTestRunner::test_function_name);
+ if (!test_function_element) {
enable_stdout();
result.status = GDTEST_LOAD_ERROR;
result.output = "";
diff --git a/modules/gdscript/tests/scripts/analyzer/features/await_with_signals_no_warning.gd b/modules/gdscript/tests/scripts/analyzer/features/await_with_signals_no_warning.gd
new file mode 100644
index 0000000000..9a7c6a8250
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/await_with_signals_no_warning.gd
@@ -0,0 +1,12 @@
+# https://github.com/godotengine/godot/issues/54589
+# https://github.com/godotengine/godot/issues/56265
+
+extends Resource
+
+func test():
+ print("okay")
+ await self.changed
+ await unknown(self)
+
+func unknown(arg):
+ await arg.changed
diff --git a/modules/gdscript/tests/scripts/analyzer/features/await_with_signals_no_warning.out b/modules/gdscript/tests/scripts/analyzer/features/await_with_signals_no_warning.out
new file mode 100644
index 0000000000..2dc04a363e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/await_with_signals_no_warning.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+okay
diff --git a/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_default_dict_void.gd b/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_default_dict_void.gd
new file mode 100644
index 0000000000..631e7be5ce
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_default_dict_void.gd
@@ -0,0 +1,14 @@
+func test():
+ var instance := Parent.new()
+ instance.my_function({"a": 1})
+ instance = Child.new()
+ instance.my_function({"a": 1})
+ print("No failure")
+
+class Parent:
+ func my_function(_par1: Dictionary = {}) -> void:
+ pass
+
+class Child extends Parent:
+ func my_function(_par1: Dictionary = {}) -> void:
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_default_dict_void.out b/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_default_dict_void.out
new file mode 100644
index 0000000000..67f0045867
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_default_dict_void.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+No failure
diff --git a/modules/gdscript/tests/scripts/analyzer/typed_array_assignment.gd b/modules/gdscript/tests/scripts/analyzer/typed_array_assignment.gd
new file mode 100644
index 0000000000..9f86d0531c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/typed_array_assignment.gd
@@ -0,0 +1,2 @@
+func test():
+ const arr: Array[int] = ["Hello", "World"]
diff --git a/modules/gdscript/tests/scripts/analyzer/typed_array_assignment.out b/modules/gdscript/tests/scripts/analyzer/typed_array_assignment.out
new file mode 100644
index 0000000000..26b6e13d4f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/typed_array_assignment.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Assigned value for constant "arr" has type Array[String] which is not compatible with defined type Array[int].
diff --git a/modules/gdscript/tests/scripts/parser/errors/dollar-assignment-bug-53696.out b/modules/gdscript/tests/scripts/parser/errors/dollar-assignment-bug-53696.out
index b3dc181a22..9fafcb5a64 100644
--- a/modules/gdscript/tests/scripts/parser/errors/dollar-assignment-bug-53696.out
+++ b/modules/gdscript/tests/scripts/parser/errors/dollar-assignment-bug-53696.out
@@ -1,2 +1,2 @@
GDTEST_PARSER_ERROR
-Expect node path as string or identifier after "$".
+Expected node path as string or identifier after "$".
diff --git a/modules/gdscript/tests/scripts/parser/errors/lambda_standalone.gd b/modules/gdscript/tests/scripts/parser/errors/lambda_standalone.gd
new file mode 100644
index 0000000000..fa0a43094e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/errors/lambda_standalone.gd
@@ -0,0 +1,3 @@
+func test():
+ func standalone():
+ print("can't be accessed")
diff --git a/modules/gdscript/tests/scripts/parser/errors/lambda_standalone.out b/modules/gdscript/tests/scripts/parser/errors/lambda_standalone.out
new file mode 100644
index 0000000000..c6830c8258
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/errors/lambda_standalone.out
@@ -0,0 +1,2 @@
+GDTEST_PARSER_ERROR
+Standalone lambdas cannot be accessed. Consider assigning it to a variable.
diff --git a/modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.gd b/modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.gd
new file mode 100644
index 0000000000..4608c778aa
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.gd
@@ -0,0 +1,4 @@
+func test():
+ match 1:
+ [[[var a]]], 2:
+ pass
diff --git a/modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.out b/modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.out
new file mode 100644
index 0000000000..1cdc24683b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.out
@@ -0,0 +1,2 @@
+GDTEST_PARSER_ERROR
+Cannot use a variable bind with multiple patterns.
diff --git a/modules/gdscript/tests/scripts/parser/errors/nothing_after_dollar.out b/modules/gdscript/tests/scripts/parser/errors/nothing_after_dollar.out
index b3dc181a22..9fafcb5a64 100644
--- a/modules/gdscript/tests/scripts/parser/errors/nothing_after_dollar.out
+++ b/modules/gdscript/tests/scripts/parser/errors/nothing_after_dollar.out
@@ -1,2 +1,2 @@
GDTEST_PARSER_ERROR
-Expect node path as string or identifier after "$".
+Expected node path as string or identifier after "$".
diff --git a/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar.out b/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar.out
index b3dc181a22..9fafcb5a64 100644
--- a/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar.out
+++ b/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar.out
@@ -1,2 +1,2 @@
GDTEST_PARSER_ERROR
-Expect node path as string or identifier after "$".
+Expected node path as string or identifier after "$".
diff --git a/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar_slash.out b/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar_slash.out
index dcb4ccecb0..3062f0be70 100644
--- a/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar_slash.out
+++ b/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar_slash.out
@@ -1,2 +1,2 @@
GDTEST_PARSER_ERROR
-Expect node path after "/".
+Expected node path as string or identifier after "/".
diff --git a/modules/gdscript/tests/scripts/parser/features/dollar_and_percent_get_node.gd b/modules/gdscript/tests/scripts/parser/features/dollar_and_percent_get_node.gd
new file mode 100644
index 0000000000..f04f4de08d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/dollar_and_percent_get_node.gd
@@ -0,0 +1,49 @@
+extends Node
+
+func test():
+ var child = Node.new()
+ child.name = "Child"
+ add_child(child)
+ child.owner = self
+
+ var hey = Node.new()
+ hey.name = "Hey"
+ child.add_child(hey)
+ hey.owner = self
+ hey.unique_name_in_owner = true
+
+ var fake_hey = Node.new()
+ fake_hey.name = "Hey"
+ add_child(fake_hey)
+ fake_hey.owner = self
+
+ var sub_child = Node.new()
+ sub_child.name = "SubChild"
+ hey.add_child(sub_child)
+ sub_child.owner = self
+
+ var howdy = Node.new()
+ howdy.name = "Howdy"
+ sub_child.add_child(howdy)
+ howdy.owner = self
+ howdy.unique_name_in_owner = true
+
+ print(hey == $Child/Hey)
+ print(howdy == $Child/Hey/SubChild/Howdy)
+
+ print(%Hey == hey)
+ print($%Hey == hey)
+ print(%"Hey" == hey)
+ print($"%Hey" == hey)
+ print($%"Hey" == hey)
+ print(%Hey/%Howdy == howdy)
+ print($%Hey/%Howdy == howdy)
+ print($"%Hey/%Howdy" == howdy)
+ print($"%Hey"/"%Howdy" == howdy)
+ print(%"Hey"/"%Howdy" == howdy)
+ print($%"Hey"/"%Howdy" == howdy)
+ print($"%Hey"/%"Howdy" == howdy)
+ print(%"Hey"/%"Howdy" == howdy)
+ print($%"Hey"/%"Howdy" == howdy)
+ print(%"Hey/%Howdy" == howdy)
+ print($%"Hey/%Howdy" == howdy)
diff --git a/modules/gdscript/tests/scripts/parser/features/dollar_and_percent_get_node.out b/modules/gdscript/tests/scripts/parser/features/dollar_and_percent_get_node.out
new file mode 100644
index 0000000000..041c4439b0
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/dollar_and_percent_get_node.out
@@ -0,0 +1,19 @@
+GDTEST_OK
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
diff --git a/modules/gdscript/tests/scripts/parser/features/if_after_lambda.gd b/modules/gdscript/tests/scripts/parser/features/if_after_lambda.gd
new file mode 100644
index 0000000000..f5e26ab1ab
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/if_after_lambda.gd
@@ -0,0 +1,7 @@
+# https://github.com/godotengine/godot/issues/61231
+
+func test():
+ var my_lambda = func():
+ print("hello")
+ if 0 == 0:
+ my_lambda.call()
diff --git a/modules/gdscript/tests/scripts/parser/features/if_after_lambda.out b/modules/gdscript/tests/scripts/parser/features/if_after_lambda.out
new file mode 100644
index 0000000000..58774d2d3f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/if_after_lambda.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+hello
diff --git a/modules/gdscript/tests/scripts/parser/features/lambda_default_parameter_capture.gd b/modules/gdscript/tests/scripts/parser/features/lambda_default_parameter_capture.gd
new file mode 100644
index 0000000000..2140b6923e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/lambda_default_parameter_capture.gd
@@ -0,0 +1,7 @@
+# https://github.com/godotengine/godot/issues/56751
+
+func test():
+ var x = "local"
+ var lambda = func(param = x):
+ print(param)
+ lambda.call()
diff --git a/modules/gdscript/tests/scripts/parser/features/lambda_default_parameter_capture.out b/modules/gdscript/tests/scripts/parser/features/lambda_default_parameter_capture.out
new file mode 100644
index 0000000000..ce3241b94d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/lambda_default_parameter_capture.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+local
diff --git a/modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.gd b/modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.gd
new file mode 100644
index 0000000000..a0ae7fb17c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.gd
@@ -0,0 +1,6 @@
+func test():
+ match [1, 2, 3]:
+ [var a, var b, var c]:
+ print(a == 1)
+ print(b == 2)
+ print(c == 3)
diff --git a/modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.out b/modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.out
new file mode 100644
index 0000000000..316db6d748
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.out
@@ -0,0 +1,4 @@
+GDTEST_OK
+true
+true
+true
diff --git a/modules/gdscript/tests/scripts/parser/warnings/unreachable_code_after_return_bug_55154.gd b/modules/gdscript/tests/scripts/parser/warnings/unreachable_code_after_return_bug_55154.gd
new file mode 100644
index 0000000000..d00d483a73
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/warnings/unreachable_code_after_return_bug_55154.gd
@@ -0,0 +1,16 @@
+func test():
+ var foo := "bar"
+ match foo:
+ "baz":
+ return
+ _:
+ pass
+ match foo:
+ "baz":
+ return
+ match foo:
+ "bar":
+ pass
+ _:
+ return
+ print("reached")
diff --git a/modules/gdscript/tests/scripts/parser/warnings/unreachable_code_after_return_bug_55154.out b/modules/gdscript/tests/scripts/parser/warnings/unreachable_code_after_return_bug_55154.out
new file mode 100644
index 0000000000..47db6b631b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/warnings/unreachable_code_after_return_bug_55154.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+reached
diff --git a/modules/gltf/doc_classes/GLTFDocumentExtension.xml b/modules/gltf/doc_classes/GLTFDocumentExtension.xml
index 03b4380ff4..3c28546ad7 100644
--- a/modules/gltf/doc_classes/GLTFDocumentExtension.xml
+++ b/modules/gltf/doc_classes/GLTFDocumentExtension.xml
@@ -7,65 +7,52 @@
<tutorials>
</tutorials>
<methods>
- <method name="export_post">
- <return type="int" enum="Error" />
- <argument index="0" name="document" type="GLTFDocument" />
+ <method name="_export_node" qualifiers="virtual">
+ <return type="int" />
+ <argument index="0" name="state" type="GLTFState" />
+ <argument index="1" name="gltf_node" type="GLTFNode" />
+ <argument index="2" name="json" type="Dictionary" />
+ <argument index="3" name="node" type="Node" />
<description>
</description>
</method>
- <method name="export_preflight">
- <return type="int" enum="Error" />
- <argument index="0" name="document" type="GLTFDocument" />
- <argument index="1" name="node" type="Node" />
+ <method name="_export_post" qualifiers="virtual">
+ <return type="int" />
+ <argument index="0" name="state" type="GLTFState" />
<description>
</description>
</method>
- <method name="get_export_setting" qualifiers="const">
- <return type="Variant" />
- <argument index="0" name="key" type="StringName" />
+ <method name="_export_preflight" qualifiers="virtual">
+ <return type="int" />
+ <argument index="0" name="root" type="Node" />
<description>
</description>
</method>
- <method name="get_export_setting_keys" qualifiers="const">
- <return type="Array" />
+ <method name="_import_node" qualifiers="virtual">
+ <return type="int" />
+ <argument index="0" name="state" type="GLTFState" />
+ <argument index="1" name="gltf_node" type="GLTFNode" />
+ <argument index="2" name="json" type="Dictionary" />
+ <argument index="3" name="node" type="Node" />
<description>
</description>
</method>
- <method name="get_import_setting" qualifiers="const">
- <return type="Variant" />
- <argument index="0" name="key" type="StringName" />
+ <method name="_import_post" qualifiers="virtual">
+ <return type="int" />
+ <argument index="0" name="state" type="GLTFState" />
+ <argument index="1" name="root" type="Node" />
<description>
</description>
</method>
- <method name="get_import_setting_keys" qualifiers="const">
- <return type="Array" />
+ <method name="_import_post_parse" qualifiers="virtual">
+ <return type="int" />
+ <argument index="0" name="state" type="GLTFState" />
<description>
</description>
</method>
- <method name="import_post">
- <return type="int" enum="Error" />
- <argument index="0" name="document" type="GLTFDocument" />
- <argument index="1" name="node" type="Node" />
- <description>
- </description>
- </method>
- <method name="import_preflight">
- <return type="int" enum="Error" />
- <argument index="0" name="document" type="GLTFDocument" />
- <description>
- </description>
- </method>
- <method name="set_export_setting">
- <return type="void" />
- <argument index="0" name="key" type="StringName" />
- <argument index="1" name="value" type="Variant" />
- <description>
- </description>
- </method>
- <method name="set_import_setting">
- <return type="void" />
- <argument index="0" name="key" type="StringName" />
- <argument index="1" name="value" type="Variant" />
+ <method name="_import_preflight" qualifiers="virtual">
+ <return type="int" />
+ <argument index="0" name="state" type="GLTFState" />
<description>
</description>
</method>
diff --git a/modules/gltf/doc_classes/GLTFState.xml b/modules/gltf/doc_classes/GLTFState.xml
index a59fa900bc..44a1723563 100644
--- a/modules/gltf/doc_classes/GLTFState.xml
+++ b/modules/gltf/doc_classes/GLTFState.xml
@@ -192,6 +192,8 @@
</method>
</methods>
<members>
+ <member name="base_path" type="String" setter="set_base_path" getter="get_base_path" default="&quot;&quot;">
+ </member>
<member name="buffers" type="Array" setter="set_buffers" getter="get_buffers" default="[]">
</member>
<member name="glb_data" type="PackedByteArray" setter="set_glb_data" getter="get_glb_data" default="PackedByteArray()">
diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp
index 173d5131cf..676862ea5a 100644
--- a/modules/gltf/editor/editor_scene_importer_blend.cpp
+++ b/modules/gltf/editor/editor_scene_importer_blend.cpp
@@ -58,7 +58,7 @@ void EditorSceneFormatImporterBlend::get_extensions(List<String> *r_extensions)
}
Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_t p_flags,
- const Map<StringName, Variant> &p_options, int p_bake_fps,
+ const HashMap<StringName, Variant> &p_options, int p_bake_fps,
List<String> *r_missing_deps, Error *r_err) {
// Get global paths for source and sink.
@@ -239,7 +239,7 @@ Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_
}
Variant EditorSceneFormatImporterBlend::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option,
- const Map<StringName, Variant> &p_options) {
+ const HashMap<StringName, Variant> &p_options) {
if (p_path.get_extension().to_lower() != "blend") {
return true;
}
@@ -310,7 +310,7 @@ static bool _test_blender_path(const String &p_path, String *r_err = nullptr) {
Error err = OS::get_singleton()->execute(path, args, &pipe);
if (err != OK) {
if (r_err) {
- *r_err = TTR("Can't excecute Blender binary.");
+ *r_err = TTR("Can't execute Blender binary.");
}
return false;
}
diff --git a/modules/gltf/editor/editor_scene_importer_blend.h b/modules/gltf/editor/editor_scene_importer_blend.h
index 0925333a28..dd1c1b9889 100644
--- a/modules/gltf/editor/editor_scene_importer_blend.h
+++ b/modules/gltf/editor/editor_scene_importer_blend.h
@@ -66,12 +66,12 @@ public:
virtual uint32_t get_import_flags() const override;
virtual void get_extensions(List<String> *r_extensions) const override;
virtual Node *import_scene(const String &p_path, uint32_t p_flags,
- const Map<StringName, Variant> &p_options, int p_bake_fps,
+ const HashMap<StringName, Variant> &p_options, int p_bake_fps,
List<String> *r_missing_deps, Error *r_err = nullptr) override;
virtual void get_import_options(const String &p_path,
List<ResourceImporter::ImportOption> *r_options) override;
virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option,
- const Map<StringName, Variant> &p_options) override;
+ const HashMap<StringName, Variant> &p_options) override;
};
class LineEdit;
diff --git a/modules/gltf/editor/editor_scene_importer_fbx.cpp b/modules/gltf/editor/editor_scene_importer_fbx.cpp
index 893d2efcec..faad2d315d 100644
--- a/modules/gltf/editor/editor_scene_importer_fbx.cpp
+++ b/modules/gltf/editor/editor_scene_importer_fbx.cpp
@@ -30,7 +30,7 @@
#include "editor_scene_importer_fbx.h"
-#if TOOLS_ENABLED
+#ifdef TOOLS_ENABLED
#include "../gltf_document.h"
#include "../gltf_state.h"
@@ -49,7 +49,7 @@ void EditorSceneFormatImporterFBX::get_extensions(List<String> *r_extensions) co
}
Node *EditorSceneFormatImporterFBX::import_scene(const String &p_path, uint32_t p_flags,
- const Map<StringName, Variant> &p_options, int p_bake_fps,
+ const HashMap<StringName, Variant> &p_options, int p_bake_fps,
List<String> *r_missing_deps, Error *r_err) {
// Get global paths for source and sink.
@@ -106,7 +106,7 @@ Node *EditorSceneFormatImporterFBX::import_scene(const String &p_path, uint32_t
}
Variant EditorSceneFormatImporterFBX::get_option_visibility(const String &p_path, bool p_for_animation,
- const String &p_option, const Map<StringName, Variant> &p_options) {
+ const String &p_option, const HashMap<StringName, Variant> &p_options) {
return true;
}
diff --git a/modules/gltf/editor/editor_scene_importer_fbx.h b/modules/gltf/editor/editor_scene_importer_fbx.h
index 84de7fd1cc..b0039b1c8f 100644
--- a/modules/gltf/editor/editor_scene_importer_fbx.h
+++ b/modules/gltf/editor/editor_scene_importer_fbx.h
@@ -45,12 +45,12 @@ public:
virtual uint32_t get_import_flags() const override;
virtual void get_extensions(List<String> *r_extensions) const override;
virtual Node *import_scene(const String &p_path, uint32_t p_flags,
- const Map<StringName, Variant> &p_options, int p_bake_fps,
+ const HashMap<StringName, Variant> &p_options, int p_bake_fps,
List<String> *r_missing_deps, Error *r_err = nullptr) override;
virtual void get_import_options(const String &p_path,
List<ResourceImporter::ImportOption> *r_options) override;
virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option,
- const Map<StringName, Variant> &p_options) override;
+ const HashMap<StringName, Variant> &p_options) override;
};
#endif // TOOLS_ENABLED
diff --git a/modules/gltf/editor/editor_scene_importer_gltf.cpp b/modules/gltf/editor/editor_scene_importer_gltf.cpp
index 5e7811ad2b..3fadec5167 100644
--- a/modules/gltf/editor/editor_scene_importer_gltf.cpp
+++ b/modules/gltf/editor/editor_scene_importer_gltf.cpp
@@ -35,7 +35,6 @@
#include "../gltf_document.h"
#include "../gltf_state.h"
-#include "scene/main/node.h"
#include "scene/resources/animation.h"
uint32_t EditorSceneFormatImporterGLTF::get_import_flags() const {
@@ -48,7 +47,7 @@ void EditorSceneFormatImporterGLTF::get_extensions(List<String> *r_extensions) c
}
Node *EditorSceneFormatImporterGLTF::import_scene(const String &p_path, uint32_t p_flags,
- const Map<StringName, Variant> &p_options, int p_bake_fps,
+ const HashMap<StringName, Variant> &p_options, int p_bake_fps,
List<String> *r_missing_deps, Error *r_err) {
Ref<GLTFDocument> doc;
doc.instantiate();
diff --git a/modules/gltf/editor/editor_scene_importer_gltf.h b/modules/gltf/editor/editor_scene_importer_gltf.h
index b714ada124..b17a1e4eaa 100644
--- a/modules/gltf/editor/editor_scene_importer_gltf.h
+++ b/modules/gltf/editor/editor_scene_importer_gltf.h
@@ -33,6 +33,9 @@
#ifdef TOOLS_ENABLED
+#include "../gltf_document_extension.h"
+#include "../gltf_state.h"
+
#include "editor/import/resource_importer_scene.h"
class Animation;
@@ -45,7 +48,7 @@ public:
virtual uint32_t get_import_flags() const override;
virtual void get_extensions(List<String> *r_extensions) const override;
virtual Node *import_scene(const String &p_path, uint32_t p_flags,
- const Map<StringName, Variant> &p_options, int p_bake_fps,
+ const HashMap<StringName, Variant> &p_options, int p_bake_fps,
List<String> *r_missing_deps, Error *r_err = nullptr) override;
};
diff --git a/modules/gltf/gltf_accessor.h b/modules/gltf/gltf_accessor.h
index 6bf1bf543a..f412dc2c7f 100644
--- a/modules/gltf/gltf_accessor.h
+++ b/modules/gltf/gltf_accessor.h
@@ -34,7 +34,6 @@
#include "core/io/resource.h"
#include "gltf_document.h"
-#include "gltf_document_extension.h"
struct GLTFAccessor : public Resource {
GDCLASS(GLTFAccessor, Resource);
diff --git a/modules/gltf/gltf_animation.cpp b/modules/gltf/gltf_animation.cpp
index c857be4b2c..e598c870ab 100644
--- a/modules/gltf/gltf_animation.cpp
+++ b/modules/gltf/gltf_animation.cpp
@@ -45,7 +45,7 @@ void GLTFAnimation::set_loop(bool p_val) {
loop = p_val;
}
-Map<int, GLTFAnimation::Track> &GLTFAnimation::get_tracks() {
+HashMap<int, GLTFAnimation::Track> &GLTFAnimation::get_tracks() {
return tracks;
}
diff --git a/modules/gltf/gltf_animation.h b/modules/gltf/gltf_animation.h
index ba8ae8a273..8688ddb937 100644
--- a/modules/gltf/gltf_animation.h
+++ b/modules/gltf/gltf_animation.h
@@ -64,11 +64,11 @@ public:
public:
bool get_loop() const;
void set_loop(bool p_val);
- Map<int, GLTFAnimation::Track> &get_tracks();
+ HashMap<int, GLTFAnimation::Track> &get_tracks();
GLTFAnimation();
private:
bool loop = false;
- Map<int, Track> tracks;
+ HashMap<int, Track> tracks;
};
#endif // GLTF_ANIMATION_H
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index 082b4ce1ec..2017355717 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -128,10 +128,10 @@ Error GLTFDocument::_serialize(Ref<GLTFState> state, const String &p_path) {
state->buffers.push_back(Vector<uint8_t>());
}
- /* STEP 1 CONVERT MESH INSTANCES */
+ /* STEP CONVERT MESH INSTANCES */
_convert_mesh_instances(state);
- /* STEP 2 SERIALIZE CAMERAS */
+ /* STEP SERIALIZE CAMERAS */
Error err = _serialize_cameras(state);
if (err != OK) {
return Error::FAILED;
@@ -143,37 +143,37 @@ Error GLTFDocument::_serialize(Ref<GLTFState> state, const String &p_path) {
return Error::FAILED;
}
- /* STEP 5 SERIALIZE MESHES (we have enough info now) */
+ /* STEP SERIALIZE MESHES (we have enough info now) */
err = _serialize_meshes(state);
if (err != OK) {
return Error::FAILED;
}
- /* STEP 6 SERIALIZE TEXTURES */
+ /* STEP SERIALIZE TEXTURES */
err = _serialize_materials(state);
if (err != OK) {
return Error::FAILED;
}
- /* STEP 7 SERIALIZE ANIMATIONS */
+ /* STEP SERIALIZE ANIMATIONS */
err = _serialize_animations(state);
if (err != OK) {
return Error::FAILED;
}
- /* STEP 8 SERIALIZE ACCESSORS */
+ /* STEP SERIALIZE ACCESSORS */
err = _encode_accessors(state);
if (err != OK) {
return Error::FAILED;
}
- /* STEP 9 SERIALIZE IMAGES */
+ /* STEP SERIALIZE IMAGES */
err = _serialize_images(state, p_path);
if (err != OK) {
return Error::FAILED;
}
- /* STEP 10 SERIALIZE TEXTURES */
+ /* STEP SERIALIZE TEXTURES */
err = _serialize_textures(state);
if (err != OK) {
return Error::FAILED;
@@ -183,42 +183,49 @@ Error GLTFDocument::_serialize(Ref<GLTFState> state, const String &p_path) {
state->buffer_views.write[i]->buffer = 0;
}
- /* STEP 11 SERIALIZE BUFFER VIEWS */
+ /* STEP SERIALIZE BUFFER VIEWS */
err = _encode_buffer_views(state);
if (err != OK) {
return Error::FAILED;
}
- /* STEP 12 SERIALIZE NODES */
+ /* STEP SERIALIZE NODES */
err = _serialize_nodes(state);
if (err != OK) {
return Error::FAILED;
}
- /* STEP 13 SERIALIZE SCENE */
+ /* STEP SERIALIZE SCENE */
err = _serialize_scenes(state);
if (err != OK) {
return Error::FAILED;
}
- /* STEP 14 SERIALIZE SCENE */
+ /* STEP SERIALIZE SCENE */
err = _serialize_lights(state);
if (err != OK) {
return Error::FAILED;
}
- /* STEP 15 SERIALIZE EXTENSIONS */
+ /* STEP SERIALIZE EXTENSIONS */
err = _serialize_extensions(state);
if (err != OK) {
return Error::FAILED;
}
- /* STEP 16 SERIALIZE VERSION */
+ /* STEP SERIALIZE VERSION */
err = _serialize_version(state);
if (err != OK) {
return Error::FAILED;
}
+ for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
+ Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ ERR_CONTINUE(ext.is_null());
+ err = ext->export_post(state);
+ ERR_FAIL_COND_V(err != OK, err);
+ }
+
return OK;
}
@@ -442,6 +449,15 @@ Error GLTFDocument::_serialize_nodes(Ref<GLTFState> state) {
}
node["children"] = children;
}
+
+ for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
+ Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ ERR_CONTINUE(ext.is_null());
+ ERR_CONTINUE(!state->scene_nodes.find(i));
+ Error err = ext->export_node(state, n, state->json, state->scene_nodes[i]);
+ ERR_CONTINUE(err != OK);
+ }
+
nodes.push_back(node);
}
state->json["nodes"] = nodes;
@@ -2294,7 +2310,7 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
attributes["COLOR_0"] = _encode_accessor_as_color(state, a, true);
}
}
- Map<int, int> joint_i_to_bone_i;
+ HashMap<int, int> joint_i_to_bone_i;
for (GLTFNodeIndex node_i = 0; node_i < state->nodes.size(); node_i++) {
GLTFSkinIndex skin_i = -1;
if (state->nodes[node_i]->mesh == gltf_mesh_i) {
@@ -2468,9 +2484,9 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
mat = import_mesh->get_surface_material(surface_i);
}
if (mat.is_valid()) {
- Map<Ref<BaseMaterial3D>, GLTFMaterialIndex>::Element *material_cache_i = state->material_cache.find(mat);
- if (material_cache_i && material_cache_i->get() != -1) {
- primitive["material"] = material_cache_i->get();
+ HashMap<Ref<BaseMaterial3D>, GLTFMaterialIndex>::Iterator material_cache_i = state->material_cache.find(mat);
+ if (material_cache_i && material_cache_i->value != -1) {
+ primitive["material"] = material_cache_i->value;
} else {
GLTFMaterialIndex mat_i = state->materials.size();
state->materials.push_back(mat);
@@ -5658,7 +5674,7 @@ void GLTFDocument::_generate_scene_node(Ref<GLTFState> state, Node *scene_parent
if (!current_node) {
current_node = _generate_spatial(state, node_index);
}
- scene_parent->add_child(current_node);
+ scene_parent->add_child(current_node, true);
if (current_node != scene_root) {
current_node->set_owner(scene_root);
}
@@ -5904,9 +5920,9 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
Node *root = ap->get_parent();
ERR_FAIL_COND(root == nullptr);
- Map<GLTFNodeIndex, Node *>::Element *node_element = state->scene_nodes.find(node_index);
- ERR_CONTINUE_MSG(node_element == nullptr, vformat("Unable to find node %d for animation", node_index));
- node_path = root->get_path_to(node_element->get());
+ HashMap<GLTFNodeIndex, Node *>::Iterator node_element = state->scene_nodes.find(node_index);
+ ERR_CONTINUE_MSG(!node_element, vformat("Unable to find node %d for animation", node_index));
+ node_path = root->get_path_to(node_element->value);
if (gltf_node->skeleton >= 0) {
const Skeleton3D *sk = state->skeletons[gltf_node->skeleton]->godot_skeleton;
@@ -6116,11 +6132,11 @@ void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> state) {
if (node->mesh < 0) {
continue;
}
- Map<GLTFNodeIndex, Node *>::Element *mi_element = state->scene_nodes.find(mi_node_i);
+ HashMap<GLTFNodeIndex, Node *>::Iterator mi_element = state->scene_nodes.find(mi_node_i);
if (!mi_element) {
continue;
}
- MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(mi_element->get());
+ MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(mi_element->value);
if (!mi) {
continue;
}
@@ -6250,11 +6266,11 @@ void GLTFDocument::_process_mesh_instances(Ref<GLTFState> state, Node *scene_roo
if (node->skin >= 0 && node->mesh >= 0) {
const GLTFSkinIndex skin_i = node->skin;
- Map<GLTFNodeIndex, Node *>::Element *mi_element = state->scene_nodes.find(node_i);
- ERR_CONTINUE_MSG(mi_element == nullptr, vformat("Unable to find node %d", node_i));
+ HashMap<GLTFNodeIndex, Node *>::Iterator mi_element = state->scene_nodes.find(node_i);
+ ERR_CONTINUE_MSG(!mi_element, vformat("Unable to find node %d", node_i));
- ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(mi_element->get());
- ERR_CONTINUE_MSG(mi == nullptr, vformat("Unable to cast node %d of type %s to ImporterMeshInstance3D", node_i, mi_element->get()->get_class_name()));
+ ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(mi_element->value);
+ ERR_CONTINUE_MSG(mi == nullptr, vformat("Unable to cast node %d of type %s to ImporterMeshInstance3D", node_i, mi_element->value->get_class_name()));
const GLTFSkeletonIndex skel_i = state->skins.write[node->skin]->skeleton;
Ref<GLTFSkeleton> gltf_skeleton = state->skeletons.write[skel_i];
@@ -6436,10 +6452,10 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
for (const KeyValue<GLTFNodeIndex, Node *> &position_scene_node_i : state->scene_nodes) {
if (position_scene_node_i.value == node) {
GLTFNodeIndex node_index = position_scene_node_i.key;
- Map<int, GLTFAnimation::Track>::Element *position_track_i = gltf_animation->get_tracks().find(node_index);
+ HashMap<int, GLTFAnimation::Track>::Iterator position_track_i = gltf_animation->get_tracks().find(node_index);
GLTFAnimation::Track track;
if (position_track_i) {
- track = position_track_i->get();
+ track = position_track_i->value;
}
track = _convert_animation_track(state, track, animation, track_i, node_index);
gltf_animation->get_tracks().insert(node_index, track);
@@ -6452,10 +6468,10 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
for (const KeyValue<GLTFNodeIndex, Node *> &rotation_degree_scene_node_i : state->scene_nodes) {
if (rotation_degree_scene_node_i.value == node) {
GLTFNodeIndex node_index = rotation_degree_scene_node_i.key;
- Map<int, GLTFAnimation::Track>::Element *rotation_degree_track_i = gltf_animation->get_tracks().find(node_index);
+ HashMap<int, GLTFAnimation::Track>::Iterator rotation_degree_track_i = gltf_animation->get_tracks().find(node_index);
GLTFAnimation::Track track;
if (rotation_degree_track_i) {
- track = rotation_degree_track_i->get();
+ track = rotation_degree_track_i->value;
}
track = _convert_animation_track(state, track, animation, track_i, node_index);
gltf_animation->get_tracks().insert(node_index, track);
@@ -6468,10 +6484,10 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
for (const KeyValue<GLTFNodeIndex, Node *> &scale_scene_node_i : state->scene_nodes) {
if (scale_scene_node_i.value == node) {
GLTFNodeIndex node_index = scale_scene_node_i.key;
- Map<int, GLTFAnimation::Track>::Element *scale_track_i = gltf_animation->get_tracks().find(node_index);
+ HashMap<int, GLTFAnimation::Track>::Iterator scale_track_i = gltf_animation->get_tracks().find(node_index);
GLTFAnimation::Track track;
if (scale_track_i) {
- track = scale_track_i->get();
+ track = scale_track_i->value;
}
track = _convert_animation_track(state, track, animation, track_i, node_index);
gltf_animation->get_tracks().insert(node_index, track);
@@ -6503,7 +6519,7 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
}
}
ERR_CONTINUE(mesh_index == -1);
- Map<int, GLTFAnimation::Track> &tracks = gltf_animation->get_tracks();
+ HashMap<int, GLTFAnimation::Track> &tracks = gltf_animation->get_tracks();
GLTFAnimation::Track track = gltf_animation->get_tracks().has(mesh_index) ? gltf_animation->get_tracks()[mesh_index] : GLTFAnimation::Track();
if (!tracks.has(mesh_index)) {
for (int32_t shape_i = 0; shape_i < mesh->get_blend_shape_count(); shape_i++) {
@@ -6565,10 +6581,10 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
continue;
}
GLTFNodeIndex node_i = skeleton_gltf->godot_bone_node[bone];
- Map<int, GLTFAnimation::Track>::Element *property_track_i = gltf_animation->get_tracks().find(node_i);
+ HashMap<int, GLTFAnimation::Track>::Iterator property_track_i = gltf_animation->get_tracks().find(node_i);
GLTFAnimation::Track track;
if (property_track_i) {
- track = property_track_i->get();
+ track = property_track_i->value;
}
track = _convert_animation_track(state, track, animation, track_i, node_i);
gltf_animation->get_tracks()[node_i] = track;
@@ -6580,10 +6596,10 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
for (const KeyValue<GLTFNodeIndex, Node *> &scene_node_i : state->scene_nodes) {
if (scene_node_i.value == godot_node) {
GLTFNodeIndex node_i = scene_node_i.key;
- Map<int, GLTFAnimation::Track>::Element *node_track_i = gltf_animation->get_tracks().find(node_i);
+ HashMap<int, GLTFAnimation::Track>::Iterator node_track_i = gltf_animation->get_tracks().find(node_i);
GLTFAnimation::Track track;
if (node_track_i) {
- track = node_track_i->get();
+ track = node_track_i->value;
}
track = _convert_animation_track(state, track, animation, track_i, node_i);
gltf_animation->get_tracks()[node_i] = track;
@@ -6642,8 +6658,8 @@ Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, Ref<FileAccess>
for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
ERR_CONTINUE(ext.is_null());
- err = ext->import_preflight(this);
- ERR_FAIL_COND_V(err != OK, FAILED);
+ err = ext->import_preflight(state);
+ ERR_FAIL_COND_V(err != OK, err);
}
err = _parse_gltf_state(state, p_path, p_bake_fps);
ERR_FAIL_COND_V(err != OK, err);
@@ -6870,12 +6886,10 @@ PackedByteArray GLTFDocument::generate_buffer(Ref<GLTFState> state) {
Error GLTFDocument::write_to_filesystem(Ref<GLTFState> state, const String &p_path) {
ERR_FAIL_NULL_V(state, ERR_INVALID_PARAMETER);
-
Error err = _serialize(state, p_path);
if (err != OK) {
return err;
}
-
err = _serialize_file(state, p_path);
if (err != OK) {
return Error::FAILED;
@@ -6886,6 +6900,7 @@ Error GLTFDocument::write_to_filesystem(Ref<GLTFState> state, const String &p_pa
Node *GLTFDocument::generate_scene(Ref<GLTFState> state, int32_t p_bake_fps) {
ERR_FAIL_NULL_V(state, nullptr);
ERR_FAIL_INDEX_V(0, state->root_nodes.size(), nullptr);
+ Error err = OK;
GLTFNodeIndex gltf_root = state->root_nodes.write[0];
Node *gltf_root_node = state->get_scene_node(gltf_root);
Node *root = gltf_root_node->get_parent();
@@ -6899,12 +6914,26 @@ Node *GLTFDocument::generate_scene(Ref<GLTFState> state, int32_t p_bake_fps) {
_import_animation(state, ap, i, p_bake_fps);
}
}
-
+ for (KeyValue<GLTFNodeIndex, Node *> E : state->scene_nodes) {
+ ERR_CONTINUE(!E.value);
+ for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
+ Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ ERR_CONTINUE(ext.is_null());
+ ERR_CONTINUE(!state->json.has("nodes"));
+ Array nodes = state->json["nodes"];
+ ERR_CONTINUE(E.key >= nodes.size());
+ ERR_CONTINUE(E.key < 0);
+ Dictionary node_json = nodes[E.key];
+ Ref<GLTFNode> gltf_node = state->nodes[E.key];
+ err = ext->import_node(state, gltf_node, node_json, E.value);
+ ERR_CONTINUE(err != OK);
+ }
+ }
for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
ERR_CONTINUE(ext.is_null());
- Error err = ext->import_post(this, root);
- ERR_FAIL_COND_V(err != OK, nullptr);
+ err = ext->import_post(state, root);
+ ERR_CONTINUE(err != OK);
}
ERR_FAIL_NULL_V(root, nullptr);
return root;
@@ -6919,13 +6948,23 @@ Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> state, uint32
if (!state->buffers.size()) {
state->buffers.push_back(Vector<uint8_t>());
}
+ for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
+ Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ ERR_CONTINUE(ext.is_null());
+ }
- /* STEP 1 CONVERT MESH INSTANCES */
- _convert_mesh_instances(state);
+ for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
+ Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ ERR_CONTINUE(ext.is_null());
+ Error err = ext->export_preflight(p_node);
+ ERR_FAIL_COND_V(err != OK, FAILED);
+ }
+ _convert_scene_node(state, p_node, -1, -1);
+ if (!state->buffers.size()) {
+ state->buffers.push_back(Vector<uint8_t>());
+ }
- /* STEP 2 CREATE SKINS */
- Error err = _serialize_skins(state);
- return err;
+ return OK;
}
Error GLTFDocument::append_from_buffer(PackedByteArray p_bytes, String p_base_path, Ref<GLTFState> state, uint32_t p_flags, int32_t p_bake_fps) {
@@ -6938,8 +6977,15 @@ Error GLTFDocument::append_from_buffer(PackedByteArray p_bytes, String p_base_pa
Ref<FileAccessMemory> file_access;
file_access.instantiate();
file_access->open_custom(p_bytes.ptr(), p_bytes.size());
- err = _parse(state, p_base_path.get_base_dir(), file_access, p_bake_fps);
- ERR_FAIL_COND_V(err != OK, FAILED);
+ state->base_path = p_base_path.get_base_dir();
+ err = _parse(state, state->base_path, file_access, p_bake_fps);
+ ERR_FAIL_COND_V(err != OK, err);
+ for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
+ Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ ERR_CONTINUE(ext.is_null());
+ err = ext->import_post_parse(state);
+ ERR_FAIL_COND_V(err != OK, err);
+ }
return OK;
}
@@ -7030,6 +7076,7 @@ Error GLTFDocument::_parse_gltf_state(Ref<GLTFState> state, const String &p_sear
for (int32_t root_i = 0; root_i < state->root_nodes.size(); root_i++) {
_generate_scene_node(state, root, root, state->root_nodes[root_i]);
}
+
return OK;
}
@@ -7049,9 +7096,16 @@ Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> r_state, uint
if (base_path.is_empty()) {
base_path = p_path.get_base_dir();
}
+ r_state->base_path = base_path;
err = _parse(r_state, base_path, f, p_bake_fps);
- ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
- return err;
+ ERR_FAIL_COND_V(err != OK, err);
+ for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
+ Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
+ ERR_CONTINUE(ext.is_null());
+ err = ext->import_post_parse(r_state);
+ ERR_FAIL_COND_V(err != OK, err);
+ }
+ return OK;
}
Error GLTFDocument::_parse_gltf_extensions(Ref<GLTFState> state) {
diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h
index 19bc507a8d..2f61210ff9 100644
--- a/modules/gltf/gltf_document.h
+++ b/modules/gltf/gltf_document.h
@@ -33,19 +33,12 @@
#include "gltf_animation.h"
-#include "core/error/error_list.h"
-#include "core/variant/dictionary.h"
-#include "core/variant/variant.h"
-#include "gltf_document_extension_convert_importer_mesh.h"
#include "scene/3d/bone_attachment_3d.h"
#include "scene/3d/importer_mesh_instance_3d.h"
#include "scene/3d/light_3d.h"
#include "scene/3d/mesh_instance_3d.h"
-#include "scene/3d/node_3d.h"
-#include "scene/3d/skeleton_3d.h"
#include "scene/animation/animation_player.h"
#include "scene/resources/material.h"
-#include "scene/resources/texture.h"
#include "modules/modules_enabled.gen.h" // For csg, gridmap.
@@ -135,12 +128,12 @@ private:
}
template <class T>
- static Array to_array(const Set<T> &p_inp) {
+ static Array to_array(const HashSet<T> &p_inp) {
Array ret;
- typename Set<T>::Element *elem = p_inp.front();
+ typename HashSet<T>::Iterator elem = p_inp.begin();
while (elem) {
- ret.push_back(elem->get());
- elem = elem->next();
+ ret.push_back(*elem);
+ ++elem;
}
return ret;
}
@@ -154,23 +147,23 @@ private:
}
template <class T>
- static void set_from_array(Set<T> &r_out, const Array &p_inp) {
+ static void set_from_array(HashSet<T> &r_out, const Array &p_inp) {
r_out.clear();
for (int i = 0; i < p_inp.size(); i++) {
r_out.insert(p_inp[i]);
}
}
template <class K, class V>
- static Dictionary to_dict(const Map<K, V> &p_inp) {
+ static Dictionary to_dict(const HashMap<K, V> &p_inp) {
Dictionary ret;
- for (typename Map<K, V>::Element *E = p_inp.front(); E; E = E->next()) {
- ret[E->key()] = E->value();
+ for (const KeyValue<K, V> &E : p_inp) {
+ ret[E.key] = E.value;
}
return ret;
}
template <class K, class V>
- static void set_from_dict(Map<K, V> &r_out, const Dictionary &p_inp) {
+ static void set_from_dict(HashMap<K, V> &r_out, const Dictionary &p_inp) {
r_out.clear();
Array keys = p_inp.keys();
for (int i = 0; i < keys.size(); i++) {
diff --git a/modules/gltf/gltf_document_extension.cpp b/modules/gltf/gltf_document_extension.cpp
index 192a1d347c..d0bd7651e0 100644
--- a/modules/gltf/gltf_document_extension.cpp
+++ b/modules/gltf/gltf_document_extension.cpp
@@ -30,59 +30,79 @@
#include "gltf_document_extension.h"
-#include "gltf_document.h"
-
void GLTFDocumentExtension::_bind_methods() {
- // Import
- ClassDB::bind_method(D_METHOD("get_import_setting_keys"),
- &GLTFDocumentExtension::get_import_setting_keys);
- ClassDB::bind_method(D_METHOD("import_preflight", "document"),
- &GLTFDocumentExtension::import_preflight);
- ClassDB::bind_method(D_METHOD("get_import_setting", "key"),
- &GLTFDocumentExtension::get_import_setting);
- ClassDB::bind_method(D_METHOD("set_import_setting", "key", "value"),
- &GLTFDocumentExtension::set_import_setting);
- ClassDB::bind_method(D_METHOD("import_post", "document", "node"),
- &GLTFDocumentExtension::import_post);
- // Export
- ClassDB::bind_method(D_METHOD("get_export_setting_keys"),
- &GLTFDocumentExtension::get_export_setting_keys);
- ClassDB::bind_method(D_METHOD("get_export_setting", "key"),
- &GLTFDocumentExtension::get_export_setting);
- ClassDB::bind_method(D_METHOD("set_export_setting", "key", "value"),
- &GLTFDocumentExtension::set_export_setting);
- ClassDB::bind_method(D_METHOD("export_preflight", "document", "node"),
- &GLTFDocumentExtension::export_preflight);
- ClassDB::bind_method(D_METHOD("export_post", "document"),
- &GLTFDocumentExtension::export_post);
+ GDVIRTUAL_BIND(_import_preflight, "state");
+ GDVIRTUAL_BIND(_import_post_parse, "state");
+ GDVIRTUAL_BIND(_import_node, "state", "gltf_node", "json", "node");
+ GDVIRTUAL_BIND(_import_post, "state", "root");
+ GDVIRTUAL_BIND(_export_preflight, "root");
+ GDVIRTUAL_BIND(_export_node, "state", "gltf_node", "json", "node");
+ GDVIRTUAL_BIND(_export_post, "state");
}
-Array GLTFDocumentExtension::get_import_setting_keys() const {
- return import_settings.keys();
+Error GLTFDocumentExtension::import_post(Ref<GLTFState> p_state, Node *p_root) {
+ ERR_FAIL_NULL_V(p_root, ERR_INVALID_PARAMETER);
+ ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
+ int err = OK;
+ if (GDVIRTUAL_CALL(_import_post, p_state, p_root, err)) {
+ return Error(err);
+ }
+ return OK;
}
-Variant GLTFDocumentExtension::get_import_setting(const StringName &p_key) const {
- if (!import_settings.has(p_key)) {
- return Variant();
+Error GLTFDocumentExtension::import_preflight(Ref<GLTFState> p_state) {
+ ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
+ int err = OK;
+ if (GDVIRTUAL_CALL(_import_preflight, p_state, err)) {
+ return Error(err);
}
- return import_settings[p_key];
+ return OK;
}
-void GLTFDocumentExtension::set_import_setting(const StringName &p_key, Variant p_var) {
- import_settings[p_key] = p_var;
+Error GLTFDocumentExtension::import_post_parse(Ref<GLTFState> p_state) {
+ ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
+ int err = OK;
+ if (GDVIRTUAL_CALL(_import_post_parse, p_state, err)) {
+ return Error(err);
+ }
+ return OK;
}
-Array GLTFDocumentExtension::get_export_setting_keys() const {
- return import_settings.keys();
+Error GLTFDocumentExtension::export_post(Ref<GLTFState> p_state) {
+ ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
+ int err = OK;
+ if (GDVIRTUAL_CALL(_export_post, p_state, err)) {
+ return Error(err);
+ }
+ return OK;
+}
+Error GLTFDocumentExtension::export_preflight(Node *p_root) {
+ ERR_FAIL_NULL_V(p_root, ERR_INVALID_PARAMETER);
+ int err = OK;
+ if (GDVIRTUAL_CALL(_export_preflight, p_root, err)) {
+ return Error(err);
+ }
+ return OK;
}
-Variant GLTFDocumentExtension::get_export_setting(const StringName &p_key) const {
- if (!import_settings.has(p_key)) {
- return Variant();
+Error GLTFDocumentExtension::import_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_dict, Node *p_node) {
+ ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
+ ERR_FAIL_NULL_V(p_gltf_node, ERR_INVALID_PARAMETER);
+ ERR_FAIL_NULL_V(p_node, ERR_INVALID_PARAMETER);
+ int err = OK;
+ if (GDVIRTUAL_CALL(_import_node, p_state, p_gltf_node, r_dict, p_node, err)) {
+ return Error(err);
}
- return import_settings[p_key];
+ return OK;
}
-void GLTFDocumentExtension::set_export_setting(const StringName &p_key, Variant p_var) {
- import_settings[p_key] = p_var;
+Error GLTFDocumentExtension::export_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_dict, Node *p_node) {
+ ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
+ ERR_FAIL_NULL_V(p_gltf_node, ERR_INVALID_PARAMETER);
+ ERR_FAIL_NULL_V(p_node, ERR_INVALID_PARAMETER);
+ int err = OK;
+ if (GDVIRTUAL_CALL(_export_node, p_state, p_gltf_node, r_dict, p_node, err)) {
+ return Error(err);
+ }
+ return OK;
}
diff --git a/modules/gltf/gltf_document_extension.h b/modules/gltf/gltf_document_extension.h
index f7a3531282..556f79e887 100644
--- a/modules/gltf/gltf_document_extension.h
+++ b/modules/gltf/gltf_document_extension.h
@@ -31,33 +31,31 @@
#ifndef GLTF_DOCUMENT_EXTENSION_H
#define GLTF_DOCUMENT_EXTENSION_H
-#include "core/io/resource.h"
-#include "core/variant/dictionary.h"
-#include "core/variant/typed_array.h"
-#include "core/variant/variant.h"
-class GLTFDocument;
+#include "gltf_accessor.h"
+#include "gltf_node.h"
+#include "gltf_state.h"
+
class GLTFDocumentExtension : public Resource {
GDCLASS(GLTFDocumentExtension, Resource);
- Dictionary import_settings;
- Dictionary export_settings;
-
protected:
static void _bind_methods();
public:
- virtual Array get_import_setting_keys() const;
- virtual Variant get_import_setting(const StringName &p_key) const;
- virtual void set_import_setting(const StringName &p_key, Variant p_var);
- virtual Error import_preflight(Ref<GLTFDocument> p_document) { return OK; }
- virtual Error import_post(Ref<GLTFDocument> p_document, Node *p_node) { return OK; }
-
-public:
- virtual Array get_export_setting_keys() const;
- virtual Variant get_export_setting(const StringName &p_key) const;
- virtual void set_export_setting(const StringName &p_key, Variant p_var);
- virtual Error export_preflight(Ref<GLTFDocument> p_document, Node *p_node) { return OK; }
- virtual Error export_post(Ref<GLTFDocument> p_document) { return OK; }
+ virtual Error import_preflight(Ref<GLTFState> p_state);
+ virtual Error import_post_parse(Ref<GLTFState> p_state);
+ virtual Error export_post(Ref<GLTFState> p_state);
+ virtual Error import_post(Ref<GLTFState> p_state, Node *p_node);
+ virtual Error export_preflight(Node *p_state);
+ virtual Error import_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_json, Node *p_node);
+ virtual Error export_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_json, Node *p_node);
+ GDVIRTUAL1R(int, _import_preflight, Ref<GLTFState>);
+ GDVIRTUAL1R(int, _import_post_parse, Ref<GLTFState>);
+ GDVIRTUAL4R(int, _import_node, Ref<GLTFState>, Ref<GLTFNode>, Dictionary, Node *);
+ GDVIRTUAL2R(int, _import_post, Ref<GLTFState>, Node *);
+ GDVIRTUAL1R(int, _export_preflight, Node *);
+ GDVIRTUAL4R(int, _export_node, Ref<GLTFState>, Ref<GLTFNode>, Dictionary, Node *);
+ GDVIRTUAL1R(int, _export_post, Ref<GLTFState>);
};
#endif // GLTF_DOCUMENT_EXTENSION_H
diff --git a/modules/gltf/gltf_document_extension_convert_importer_mesh.cpp b/modules/gltf/gltf_document_extension_convert_importer_mesh.cpp
index 47a3e5598f..1620900a04 100644
--- a/modules/gltf/gltf_document_extension_convert_importer_mesh.cpp
+++ b/modules/gltf/gltf_document_extension_convert_importer_mesh.cpp
@@ -29,41 +29,40 @@
/*************************************************************************/
#include "gltf_document_extension_convert_importer_mesh.h"
+
+#include "gltf_state.h"
+
#include "core/error/error_macros.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/resources/importer_mesh.h"
-#include <cstddef>
-
void GLTFDocumentExtensionConvertImporterMesh::_bind_methods() {
}
-Error GLTFDocumentExtensionConvertImporterMesh::import_post(Ref<GLTFDocument> p_document, Node *p_node) {
- ERR_FAIL_NULL_V(p_document, ERR_INVALID_PARAMETER);
- ERR_FAIL_NULL_V(p_node, ERR_INVALID_PARAMETER);
+Error GLTFDocumentExtensionConvertImporterMesh::import_post(Ref<GLTFState> p_state, Node *p_root) {
+ ERR_FAIL_NULL_V(p_root, ERR_INVALID_PARAMETER);
+ ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
List<Node *> queue;
- queue.push_back(p_node);
+ queue.push_back(p_root);
List<Node *> delete_queue;
while (!queue.is_empty()) {
List<Node *>::Element *E = queue.front();
Node *node = E->get();
- {
- ImporterMeshInstance3D *mesh_3d = cast_to<ImporterMeshInstance3D>(node);
- if (mesh_3d) {
- MeshInstance3D *mesh_instance_node_3d = memnew(MeshInstance3D);
- Ref<ImporterMesh> mesh = mesh_3d->get_mesh();
- if (mesh.is_valid()) {
- Ref<ArrayMesh> array_mesh = mesh->get_mesh();
- mesh_instance_node_3d->set_name(node->get_name());
- mesh_instance_node_3d->set_transform(mesh_3d->get_transform());
- mesh_instance_node_3d->set_mesh(array_mesh);
- mesh_instance_node_3d->set_skin(mesh_3d->get_skin());
- mesh_instance_node_3d->set_skeleton_path(mesh_3d->get_skeleton_path());
- node->replace_by(mesh_instance_node_3d);
- delete_queue.push_back(node);
- } else {
- memdelete(mesh_instance_node_3d);
- }
+ ImporterMeshInstance3D *mesh_3d = cast_to<ImporterMeshInstance3D>(node);
+ if (mesh_3d) {
+ MeshInstance3D *mesh_instance_node_3d = memnew(MeshInstance3D);
+ Ref<ImporterMesh> mesh = mesh_3d->get_mesh();
+ if (mesh.is_valid()) {
+ Ref<ArrayMesh> array_mesh = mesh->get_mesh();
+ mesh_instance_node_3d->set_name(node->get_name());
+ mesh_instance_node_3d->set_transform(mesh_3d->get_transform());
+ mesh_instance_node_3d->set_mesh(array_mesh);
+ mesh_instance_node_3d->set_skin(mesh_3d->get_skin());
+ mesh_instance_node_3d->set_skeleton_path(mesh_3d->get_skeleton_path());
+ node->replace_by(mesh_instance_node_3d);
+ delete_queue.push_back(node);
+ } else {
+ memdelete(mesh_instance_node_3d);
}
}
int child_count = node->get_child_count();
diff --git a/modules/gltf/gltf_document_extension_convert_importer_mesh.h b/modules/gltf/gltf_document_extension_convert_importer_mesh.h
index 2d51143140..4c9e42a00f 100644
--- a/modules/gltf/gltf_document_extension_convert_importer_mesh.h
+++ b/modules/gltf/gltf_document_extension_convert_importer_mesh.h
@@ -31,14 +31,10 @@
#ifndef GLTF_EXTENSION_EDITOR_H
#define GLTF_EXTENSION_EDITOR_H
-#include "core/io/resource.h"
-#include "core/variant/dictionary.h"
-
-#include "gltf_document.h"
#include "gltf_document_extension.h"
+
#include "scene/3d/importer_mesh_instance_3d.h"
#include "scene/3d/mesh_instance_3d.h"
-#include "scene/main/node.h"
#include "scene/resources/importer_mesh.h"
class GLTFDocumentExtension;
@@ -50,6 +46,6 @@ protected:
static void _bind_methods();
public:
- Error import_post(Ref<GLTFDocument> p_document, Node *p_node) override;
+ Error import_post(Ref<GLTFState> p_state, Node *p_root) override;
};
#endif // GLTF_EXTENSION_EDITOR_H
diff --git a/modules/gltf/gltf_skeleton.cpp b/modules/gltf/gltf_skeleton.cpp
index e80376f130..b813f39a27 100644
--- a/modules/gltf/gltf_skeleton.cpp
+++ b/modules/gltf/gltf_skeleton.cpp
@@ -46,7 +46,7 @@ void GLTFSkeleton::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "joints"), "set_joints", "get_joints"); // Vector<GLTFNodeIndex>
ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "roots"), "set_roots", "get_roots"); // Vector<GLTFNodeIndex>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "unique_names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_unique_names", "get_unique_names"); // Set<String>
- ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "godot_bone_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_godot_bone_node", "get_godot_bone_node"); // Map<int32_t,
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "godot_bone_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_godot_bone_node", "get_godot_bone_node"); // RBMap<int32_t,
}
Vector<GLTFNodeIndex> GLTFSkeleton::get_joints() {
diff --git a/modules/gltf/gltf_skeleton.h b/modules/gltf/gltf_skeleton.h
index 7d07d528cb..92ee6e6234 100644
--- a/modules/gltf/gltf_skeleton.h
+++ b/modules/gltf/gltf_skeleton.h
@@ -50,9 +50,9 @@ private:
Skeleton3D *godot_skeleton = nullptr;
// Set of unique bone names for the skeleton
- Set<String> unique_names;
+ HashSet<String> unique_names;
- Map<int32_t, GLTFNodeIndex> godot_bone_node;
+ HashMap<int32_t, GLTFNodeIndex> godot_bone_node;
Vector<BoneAttachment3D *> bone_attachments;
@@ -78,10 +78,10 @@ public:
Array get_unique_names();
void set_unique_names(Array p_unique_names);
- //Map<int32_t, GLTFNodeIndex> get_godot_bone_node() {
+ //RBMap<int32_t, GLTFNodeIndex> get_godot_bone_node() {
// return this->godot_bone_node;
//}
- //void set_godot_bone_node(Map<int32_t, GLTFNodeIndex> p_godot_bone_node) {
+ //void set_godot_bone_node(RBMap<int32_t, GLTFNodeIndex> p_godot_bone_node) {
// this->godot_bone_node = p_godot_bone_node;
//}
Dictionary get_godot_bone_node();
diff --git a/modules/gltf/gltf_skin.cpp b/modules/gltf/gltf_skin.cpp
index 283fc34ff5..e8005aa0c1 100644
--- a/modules/gltf/gltf_skin.cpp
+++ b/modules/gltf/gltf_skin.cpp
@@ -59,8 +59,8 @@ void GLTFSkin::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "non_joints"), "set_non_joints", "get_non_joints"); // Vector<GLTFNodeIndex>
ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "roots"), "set_roots", "get_roots"); // Vector<GLTFNodeIndex>
ADD_PROPERTY(PropertyInfo(Variant::INT, "skeleton"), "set_skeleton", "get_skeleton"); // int
- ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "joint_i_to_bone_i", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL), "set_joint_i_to_bone_i", "get_joint_i_to_bone_i"); // Map<int,
- ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "joint_i_to_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL), "set_joint_i_to_name", "get_joint_i_to_name"); // Map<int,
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "joint_i_to_bone_i", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL), "set_joint_i_to_bone_i", "get_joint_i_to_bone_i"); // RBMap<int,
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "joint_i_to_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL), "set_joint_i_to_name", "get_joint_i_to_name"); // RBMap<int,
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "godot_skin"), "set_godot_skin", "get_godot_skin"); // Ref<Skin>
}
@@ -130,16 +130,16 @@ void GLTFSkin::set_joint_i_to_bone_i(Dictionary p_joint_i_to_bone_i) {
Dictionary GLTFSkin::get_joint_i_to_name() {
Dictionary ret;
- Map<int, StringName>::Element *elem = joint_i_to_name.front();
+ HashMap<int, StringName>::Iterator elem = joint_i_to_name.begin();
while (elem) {
- ret[elem->key()] = String(elem->value());
- elem = elem->next();
+ ret[elem->key] = String(elem->value);
+ ++elem;
}
return ret;
}
void GLTFSkin::set_joint_i_to_name(Dictionary p_joint_i_to_name) {
- joint_i_to_name = Map<int, StringName>();
+ joint_i_to_name = HashMap<int, StringName>();
Array keys = p_joint_i_to_name.keys();
for (int i = 0; i < keys.size(); i++) {
joint_i_to_name[keys[i]] = p_joint_i_to_name[keys[i]];
diff --git a/modules/gltf/gltf_skin.h b/modules/gltf/gltf_skin.h
index 31cb892f19..d946324756 100644
--- a/modules/gltf/gltf_skin.h
+++ b/modules/gltf/gltf_skin.h
@@ -65,8 +65,8 @@ private:
// A mapping from the joint indices (in the order of joints_original) to the
// Godot Skeleton's bone_indices
- Map<int, int> joint_i_to_bone_i;
- Map<int, StringName> joint_i_to_name;
+ HashMap<int, int> joint_i_to_bone_i;
+ HashMap<int, StringName> joint_i_to_name;
// The Actual Skin that will be created as a mapping between the IBM's of
// this skin to the generated skeleton for the mesh instances.
diff --git a/modules/gltf/gltf_state.cpp b/modules/gltf/gltf_state.cpp
index 6ead2f69c3..989fa476c2 100644
--- a/modules/gltf/gltf_state.cpp
+++ b/modules/gltf/gltf_state.cpp
@@ -57,6 +57,8 @@ void GLTFState::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_materials", "materials"), &GLTFState::set_materials);
ClassDB::bind_method(D_METHOD("get_scene_name"), &GLTFState::get_scene_name);
ClassDB::bind_method(D_METHOD("set_scene_name", "scene_name"), &GLTFState::set_scene_name);
+ ClassDB::bind_method(D_METHOD("get_base_path"), &GLTFState::get_base_path);
+ ClassDB::bind_method(D_METHOD("set_base_path", "base_path"), &GLTFState::set_base_path);
ClassDB::bind_method(D_METHOD("get_root_nodes"), &GLTFState::get_root_nodes);
ClassDB::bind_method(D_METHOD("set_root_nodes", "root_nodes"), &GLTFState::set_root_nodes);
ClassDB::bind_method(D_METHOD("get_textures"), &GLTFState::get_textures);
@@ -93,6 +95,7 @@ void GLTFState::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "meshes", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_meshes", "get_meshes"); // Vector<Ref<GLTFMesh>>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "materials", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_materials", "get_materials"); // Vector<Ref<Material>
ADD_PROPERTY(PropertyInfo(Variant::STRING, "scene_name"), "set_scene_name", "get_scene_name"); // String
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_path"), "set_base_path", "get_base_path"); // String
ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "root_nodes"), "set_root_nodes", "get_root_nodes"); // Vector<int>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "textures", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_textures", "get_textures"); // Vector<Ref<GLTFTexture>>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "images", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_images", "get_images"); // Vector<Ref<Texture>
@@ -102,7 +105,7 @@ void GLTFState::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "unique_names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_unique_names", "get_unique_names"); // Set<String>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "unique_animation_names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_unique_animation_names", "get_unique_animation_names"); // Set<String>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "skeletons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skeletons", "get_skeletons"); // Vector<Ref<GLTFSkeleton>>
- ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "skeleton_to_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skeleton_to_node", "get_skeleton_to_node"); // Map<GLTFSkeletonIndex,
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "skeleton_to_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skeleton_to_node", "get_skeleton_to_node"); // RBMap<GLTFSkeletonIndex,
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animations", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_animations", "get_animations"); // Vector<Ref<GLTFAnimation>>
}
@@ -313,3 +316,11 @@ void GLTFState::set_discard_meshes_and_materials(bool p_discard_meshes_and_mater
bool GLTFState::get_discard_meshes_and_materials() {
return discard_meshes_and_materials;
}
+
+String GLTFState::get_base_path() {
+ return base_path;
+}
+
+void GLTFState::set_base_path(String p_base_path) {
+ base_path = p_base_path;
+}
diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h
index 42ca079f1c..2fdef19038 100644
--- a/modules/gltf/gltf_state.h
+++ b/modules/gltf/gltf_state.h
@@ -44,10 +44,7 @@
#include "gltf_skin.h"
#include "gltf_texture.h"
-#include "core/io/resource.h"
-#include "core/templates/map.h"
-#include "core/templates/pair.h"
-#include "core/templates/vector.h"
+#include "core/templates/rb_map.h"
#include "scene/animation/animation_player.h"
#include "scene/resources/texture.h"
@@ -56,6 +53,7 @@ class GLTFState : public Resource {
friend class GLTFDocument;
String filename;
+ String base_path;
Dictionary json;
int major_version = 0;
int minor_version = 0;
@@ -72,7 +70,7 @@ class GLTFState : public Resource {
Vector<Ref<GLTFMesh>> meshes; // meshes are loaded directly, no reason not to.
Vector<AnimationPlayer *> animation_players;
- Map<Ref<BaseMaterial3D>, GLTFMaterialIndex> material_cache;
+ HashMap<Ref<BaseMaterial3D>, GLTFMaterialIndex> material_cache;
Vector<Ref<BaseMaterial3D>> materials;
String scene_name;
@@ -83,16 +81,16 @@ class GLTFState : public Resource {
Vector<Ref<GLTFSkin>> skins;
Vector<Ref<GLTFCamera>> cameras;
Vector<Ref<GLTFLight>> lights;
- Set<String> unique_names;
- Set<String> unique_animation_names;
+ HashSet<String> unique_names;
+ HashSet<String> unique_animation_names;
Vector<Ref<GLTFSkeleton>> skeletons;
- Map<GLTFSkeletonIndex, GLTFNodeIndex> skeleton_to_node;
+ HashMap<GLTFSkeletonIndex, GLTFNodeIndex> skeleton_to_node;
Vector<Ref<GLTFAnimation>> animations;
- Map<GLTFNodeIndex, Node *> scene_nodes;
+ HashMap<GLTFNodeIndex, Node *> scene_nodes;
- Map<ObjectID, GLTFSkeletonIndex> skeleton3d_to_gltf_skeleton;
- Map<ObjectID, Map<ObjectID, GLTFSkinIndex>> skin_and_skeleton3d_to_gltf_skin;
+ HashMap<ObjectID, GLTFSkeletonIndex> skeleton3d_to_gltf_skeleton;
+ HashMap<ObjectID, HashMap<ObjectID, GLTFSkinIndex>> skin_and_skeleton3d_to_gltf_skin;
protected:
static void _bind_methods();
@@ -137,6 +135,9 @@ public:
String get_scene_name();
void set_scene_name(String p_scene_name);
+ String get_base_path();
+ void set_base_path(String p_base_path);
+
Array get_root_nodes();
void set_root_nodes(Array p_root_nodes);
@@ -176,7 +177,7 @@ public:
AnimationPlayer *get_animation_player(int idx);
- //void set_scene_nodes(Map<GLTFNodeIndex, Node *> p_scene_nodes) {
+ //void set_scene_nodes(RBMap<GLTFNodeIndex, Node *> p_scene_nodes) {
// this->scene_nodes = p_scene_nodes;
//}
@@ -184,10 +185,10 @@ public:
// this->animation_players = p_animation_players;
//}
- //Map<Ref<Material>, GLTFMaterialIndex> get_material_cache() {
+ //RBMap<Ref<Material>, GLTFMaterialIndex> get_material_cache() {
// return this->material_cache;
//}
- //void set_material_cache(Map<Ref<Material>, GLTFMaterialIndex> p_material_cache) {
+ //void set_material_cache(RBMap<Ref<Material>, GLTFMaterialIndex> p_material_cache) {
// this->material_cache = p_material_cache;
//}
};
diff --git a/modules/gridmap/editor/grid_map_editor_plugin.cpp b/modules/gridmap/editor/grid_map_editor_plugin.cpp
index 2f613768ee..cfff5c61de 100644
--- a/modules/gridmap/editor/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/editor/grid_map_editor_plugin.cpp
@@ -930,6 +930,7 @@ void GridMapEditor::edit(GridMap *p_gridmap) {
}
update_palette();
+ _update_cursor_instance();
set_process(true);
@@ -1220,7 +1221,7 @@ GridMapEditor::GridMapEditor() {
search_box = memnew(LineEdit);
search_box->set_h_size_flags(SIZE_EXPAND_FILL);
- search_box->set_placeholder(TTR("Filter meshes"));
+ search_box->set_placeholder(TTR("Filter Meshes"));
hb->add_child(search_box);
search_box->connect("text_changed", callable_mp(this, &GridMapEditor::_text_changed));
search_box->connect("gui_input", callable_mp(this, &GridMapEditor::_sbox_input));
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index 3c7bd5eb70..dcdb520d11 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -103,9 +103,10 @@ bool GridMap::_get(const StringName &p_name, Variant &r_ret) const {
{
int *w = cells.ptrw();
int i = 0;
- for (Map<IndexKey, Cell>::Element *E = cell_map.front(); E; E = E->next(), i++) {
- encode_uint64(E->key().key, (uint8_t *)&w[i * 3]);
- encode_uint32(E->get().cell, (uint8_t *)&w[i * 3 + 2]);
+ for (const KeyValue<IndexKey, Cell> &E : cell_map) {
+ encode_uint64(E.key.key, (uint8_t *)&w[i * 3]);
+ encode_uint32(E.value.cell, (uint8_t *)&w[i * 3 + 2]);
+ i++;
}
}
@@ -480,17 +481,17 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
* and set said multimesh bounding box to one containing all cells which have this item
*/
- Map<int, List<Pair<Transform3D, IndexKey>>> multimesh_items;
+ HashMap<int, List<Pair<Transform3D, IndexKey>>> multimesh_items;
- for (Set<IndexKey>::Element *E = g.cells.front(); E; E = E->next()) {
- ERR_CONTINUE(!cell_map.has(E->get()));
- const Cell &c = cell_map[E->get()];
+ for (const IndexKey &E : g.cells) {
+ ERR_CONTINUE(!cell_map.has(E));
+ const Cell &c = cell_map[E];
if (!mesh_library.is_valid() || !mesh_library->has_item(c.item)) {
continue;
}
- Vector3 cellpos = Vector3(E->get().x, E->get().y, E->get().z);
+ Vector3 cellpos = Vector3(E.x, E.y, E.z);
Vector3 ofs = _get_offset();
Transform3D xform;
@@ -506,7 +507,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
Pair<Transform3D, IndexKey> p;
p.first = xform * mesh_library->get_item_mesh_transform(c.item);
- p.second = E->get();
+ p.second = E;
multimesh_items[c.item].push_back(p);
}
}
@@ -539,7 +540,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
nm.region = region;
}
- g.navmesh_ids[E->get()] = nm;
+ g.navmesh_ids[E] = nm;
}
}
@@ -770,7 +771,7 @@ void GridMap::_queue_octants_dirty() {
void GridMap::_recreate_octant_data() {
recreating_octants = true;
- Map<IndexKey, Cell> cell_copy = cell_map;
+ HashMap<IndexKey, Cell, IndexKey> cell_copy = cell_map;
_clear_internal();
for (const KeyValue<IndexKey, Cell> &E : cell_copy) {
set_cell_item(Vector3i(E.key), E.value.item, E.value.rot);
@@ -969,7 +970,7 @@ Array GridMap::get_meshes() const {
xform.set_origin(cellpos * cell_size + ofs);
xform.basis.scale(Vector3(cell_scale, cell_scale, cell_scale));
- meshes.push_back(xform);
+ meshes.push_back(xform * mesh_library->get_item_mesh_transform(id));
meshes.push_back(mesh);
}
@@ -998,7 +999,7 @@ void GridMap::make_baked_meshes(bool p_gen_lightmap_uv, float p_lightmap_uv_texe
}
//generate
- Map<OctantKey, Map<Ref<Material>, Ref<SurfaceTool>>> surface_map;
+ HashMap<OctantKey, HashMap<Ref<Material>, Ref<SurfaceTool>>, OctantKey> surface_map;
for (KeyValue<IndexKey, Cell> &E : cell_map) {
IndexKey key = E.key;
@@ -1028,10 +1029,10 @@ void GridMap::make_baked_meshes(bool p_gen_lightmap_uv, float p_lightmap_uv_texe
ok.z = key.z / octant_size;
if (!surface_map.has(ok)) {
- surface_map[ok] = Map<Ref<Material>, Ref<SurfaceTool>>();
+ surface_map[ok] = HashMap<Ref<Material>, Ref<SurfaceTool>>();
}
- Map<Ref<Material>, Ref<SurfaceTool>> &mat_map = surface_map[ok];
+ HashMap<Ref<Material>, Ref<SurfaceTool>> &mat_map = surface_map[ok];
for (int i = 0; i < mesh->get_surface_count(); i++) {
if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) {
@@ -1051,7 +1052,7 @@ void GridMap::make_baked_meshes(bool p_gen_lightmap_uv, float p_lightmap_uv_texe
}
}
- for (KeyValue<OctantKey, Map<Ref<Material>, Ref<SurfaceTool>>> &E : surface_map) {
+ for (KeyValue<OctantKey, HashMap<Ref<Material>, Ref<SurfaceTool>>> &E : surface_map) {
Ref<ArrayMesh> mesh;
mesh.instantiate();
for (KeyValue<Ref<Material>, Ref<SurfaceTool>> &F : E.value) {
diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h
index 5e367e149d..d0872a839b 100644
--- a/modules/gridmap/grid_map.h
+++ b/modules/gridmap/grid_map.h
@@ -56,9 +56,15 @@ class GridMap : public Node3D {
};
uint64_t key = 0;
+ static uint32_t hash(const IndexKey &p_key) {
+ return hash_one_uint64(p_key.key);
+ }
_FORCE_INLINE_ bool operator<(const IndexKey &p_key) const {
return key < p_key.key;
}
+ _FORCE_INLINE_ bool operator==(const IndexKey &p_key) const {
+ return key == p_key.key;
+ }
_FORCE_INLINE_ operator Vector3i() const {
return Vector3i(x, y, z);
@@ -107,13 +113,13 @@ class GridMap : public Node3D {
};
Vector<MultimeshInstance> multimesh_instances;
- Set<IndexKey> cells;
+ HashSet<IndexKey> cells;
RID collision_debug;
RID collision_debug_instance;
bool dirty = false;
RID static_body;
- Map<IndexKey, NavMesh> navmesh_ids;
+ HashMap<IndexKey, NavMesh> navmesh_ids;
};
union OctantKey {
@@ -126,8 +132,11 @@ class GridMap : public Node3D {
uint64_t key = 0;
- _FORCE_INLINE_ bool operator<(const OctantKey &p_key) const {
- return key < p_key.key;
+ static uint32_t hash(const OctantKey &p_key) {
+ return hash_one_uint64(p_key.key);
+ }
+ _FORCE_INLINE_ bool operator==(const OctantKey &p_key) const {
+ return key == p_key.key;
}
//OctantKey(const IndexKey& p_k, int p_item) { indexkey=p_k.key; item=p_item; }
@@ -154,8 +163,8 @@ class GridMap : public Node3D {
Ref<MeshLibrary> mesh_library;
- Map<OctantKey, Octant *> octant_map;
- Map<IndexKey, Cell> cell_map;
+ HashMap<OctantKey, Octant *, OctantKey> octant_map;
+ HashMap<IndexKey, Cell, IndexKey> cell_map;
void _recreate_octant_data();
diff --git a/modules/jsonrpc/jsonrpc.h b/modules/jsonrpc/jsonrpc.h
index 3144746f6d..f57d6aef42 100644
--- a/modules/jsonrpc/jsonrpc.h
+++ b/modules/jsonrpc/jsonrpc.h
@@ -37,7 +37,7 @@
class JSONRPC : public Object {
GDCLASS(JSONRPC, Object)
- Map<String, Object *> method_scopes;
+ HashMap<String, Object *> method_scopes;
protected:
static void _bind_methods();
diff --git a/modules/mbedtls/stream_peer_mbedtls.cpp b/modules/mbedtls/stream_peer_mbedtls.cpp
index 1818048877..92590fbcf6 100644
--- a/modules/mbedtls/stream_peer_mbedtls.cpp
+++ b/modules/mbedtls/stream_peer_mbedtls.cpp
@@ -298,6 +298,10 @@ StreamPeerMbedTLS::Status StreamPeerMbedTLS::get_status() const {
return status;
}
+Ref<StreamPeer> StreamPeerMbedTLS::get_stream() const {
+ return base;
+}
+
StreamPeerSSL *StreamPeerMbedTLS::_create_func() {
return memnew(StreamPeerMbedTLS);
}
diff --git a/modules/mbedtls/stream_peer_mbedtls.h b/modules/mbedtls/stream_peer_mbedtls.h
index 98b91e65ab..7660410e04 100644
--- a/modules/mbedtls/stream_peer_mbedtls.h
+++ b/modules/mbedtls/stream_peer_mbedtls.h
@@ -57,6 +57,7 @@ public:
virtual Error accept_stream(Ref<StreamPeer> p_base, Ref<CryptoKey> p_key, Ref<X509Certificate> p_cert, Ref<X509Certificate> p_ca_chain = Ref<X509Certificate>());
virtual Error connect_to_stream(Ref<StreamPeer> p_base, bool p_validate_certs = false, const String &p_for_hostname = String(), Ref<X509Certificate> p_valid_cert = Ref<X509Certificate>());
virtual Status get_status() const;
+ virtual Ref<StreamPeer> get_stream() const;
virtual void disconnect_from_stream();
diff --git a/modules/minimp3/resource_importer_mp3.cpp b/modules/minimp3/resource_importer_mp3.cpp
index 6cd710e792..e03940f963 100644
--- a/modules/minimp3/resource_importer_mp3.cpp
+++ b/modules/minimp3/resource_importer_mp3.cpp
@@ -54,7 +54,7 @@ String ResourceImporterMP3::get_resource_type() const {
return "AudioStreamMP3";
}
-bool ResourceImporterMP3::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const {
+bool ResourceImporterMP3::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const {
return true;
}
@@ -71,7 +71,7 @@ void ResourceImporterMP3::get_import_options(const String &p_path, List<ImportOp
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "loop_offset"), 0));
}
-Error ResourceImporterMP3::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
+Error ResourceImporterMP3::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
bool loop = p_options["loop"];
float loop_offset = p_options["loop_offset"];
diff --git a/modules/minimp3/resource_importer_mp3.h b/modules/minimp3/resource_importer_mp3.h
index 75890228b9..678a3773bb 100644
--- a/modules/minimp3/resource_importer_mp3.h
+++ b/modules/minimp3/resource_importer_mp3.h
@@ -48,9 +48,9 @@ public:
virtual String get_preset_name(int p_idx) const override;
virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override;
- virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override;
+ virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override;
- virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override;
+ virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override;
ResourceImporterMP3();
};
diff --git a/modules/mono/class_db_api_json.cpp b/modules/mono/class_db_api_json.cpp
index 9253f105bb..3afde1e8d3 100644
--- a/modules/mono/class_db_api_json.cpp
+++ b/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) {
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);
ERR_FAIL_COND(!t);
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;
- 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());
@@ -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
}
- snames.push_back(*k);
+ snames.push_back(F.key);
}
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;
- 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>();
@@ -158,10 +149,8 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
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>();
@@ -193,10 +182,8 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
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>();
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 5875a0fbd4..622838b308 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -686,10 +686,10 @@ void CSharpLanguage::pre_unsafe_unreference(Object *p_obj) {
#ifdef DEBUG_ENABLED
MutexLock lock(unsafe_object_references_lock);
ObjectID id = p_obj->get_instance_id();
- Map<ObjectID, int>::Element *elem = unsafe_object_references.find(id);
+ HashMap<ObjectID, int>::Iterator elem = unsafe_object_references.find(id);
ERR_FAIL_NULL(elem);
- if (--elem->value() == 0) {
- unsafe_object_references.erase(elem);
+ if (--elem->value == 0) {
+ unsafe_object_references.remove(elem);
}
#endif
}
@@ -875,7 +875,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
// Script::instances are deleted during managed object disposal, which happens on domain finalize.
// Only placeholders are kept. Therefore we need to keep a copy before that happens.
- for (Object *&obj : script->instances) {
+ for (Object *obj : script->instances) {
script->pending_reload_instances.insert(obj->get_instance_id());
RefCounted *rc = Object::cast_to<RefCounted>(obj);
@@ -885,7 +885,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
}
#ifdef TOOLS_ENABLED
- for (PlaceHolderScriptInstance *&script_instance : script->placeholders) {
+ for (PlaceHolderScriptInstance *script_instance : script->placeholders) {
Object *obj = script_instance->get_owner();
script->pending_reload_instances.insert(obj->get_instance_id());
@@ -897,9 +897,9 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
#endif
// Save state and remove script from instances
- Map<ObjectID, CSharpScript::StateBackup> &owners_map = script->pending_reload_state;
+ RBMap<ObjectID, CSharpScript::StateBackup> &owners_map = script->pending_reload_state;
- for (Object *&obj : script->instances) {
+ for (Object *obj : script->instances) {
ERR_CONTINUE(!obj->get_script_instance());
CSharpInstance *csi = static_cast<CSharpInstance *>(obj->get_script_instance());
@@ -922,8 +922,8 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
// After the state of all instances is saved, clear scripts and script instances
for (Ref<CSharpScript> &script : scripts) {
- while (script->instances.front()) {
- Object *obj = script->instances.front()->get();
+ while (script->instances.begin()) {
+ Object *obj = *script->instances.begin();
obj->set_script(Ref<RefCounted>()); // Remove script and existing script instances (placeholder are not removed before domain reload)
}
@@ -1099,14 +1099,14 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
const StringName &name = G.first;
const Array &serialized_data = G.second;
- Map<StringName, CSharpScript::EventSignal>::Element *match = script->event_signals.find(name);
+ HashMap<StringName, CSharpScript::EventSignal>::Iterator match = script->event_signals.find(name);
if (!match) {
// The event or its signal attribute were removed
continue;
}
- const CSharpScript::EventSignal &event_signal = match->value();
+ const CSharpScript::EventSignal &event_signal = match->value;
MonoObject *managed_serialized_data = GDMonoMarshal::variant_to_mono_object(serialized_data);
MonoDelegate *delegate = nullptr;
@@ -1428,7 +1428,7 @@ bool CSharpLanguage::setup_csharp_script_binding(CSharpScriptBinding &r_script_b
return true;
}
-Map<Object *, CSharpScriptBinding>::Element *CSharpLanguage::insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding) {
+RBMap<Object *, CSharpScriptBinding>::Element *CSharpLanguage::insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding) {
return script_bindings.insert(p_object, p_script_binding);
}
@@ -1437,7 +1437,7 @@ void *CSharpLanguage::_instance_binding_create_callback(void *, void *p_instance
MutexLock lock(csharp_lang->language_bind_mutex);
- Map<Object *, CSharpScriptBinding>::Element *match = csharp_lang->script_bindings.find((Object *)p_instance);
+ RBMap<Object *, CSharpScriptBinding>::Element *match = csharp_lang->script_bindings.find((Object *)p_instance);
if (match) {
return (void *)match;
}
@@ -1467,7 +1467,7 @@ void CSharpLanguage::_instance_binding_free_callback(void *, void *, void *p_bin
{
MutexLock lock(csharp_lang->language_bind_mutex);
- Map<Object *, CSharpScriptBinding>::Element *data = (Map<Object *, CSharpScriptBinding>::Element *)p_binding;
+ RBMap<Object *, CSharpScriptBinding>::Element *data = (RBMap<Object *, CSharpScriptBinding>::Element *)p_binding;
CSharpScriptBinding &script_binding = data->value();
@@ -1488,7 +1488,7 @@ void CSharpLanguage::_instance_binding_free_callback(void *, void *, void *p_bin
GDNativeBool CSharpLanguage::_instance_binding_reference_callback(void *p_token, void *p_binding, GDNativeBool p_reference) {
CRASH_COND(!p_binding);
- CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)p_binding)->get();
+ CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)p_binding)->get();
RefCounted *rc_owner = Object::cast_to<RefCounted>(script_binding.owner);
@@ -1558,7 +1558,7 @@ void *CSharpLanguage::get_instance_binding(Object *p_object) {
// `setup_csharp_script_binding` may call `reference()`. It was moved here outside to fix that.
if (binding) {
- CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)binding)->value();
+ CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)binding)->value();
if (!script_binding.inited) {
MutexLock lock(CSharpLanguage::get_singleton()->get_language_bind_mutex());
@@ -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 {
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
@@ -2301,7 +2301,7 @@ CSharpInstance::~CSharpInstance() {
void *data = CSharpLanguage::get_instance_binding(owner);
CRASH_COND(data == nullptr);
- CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
+ CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)data)->get();
CRASH_COND(!script_binding.inited);
#ifdef DEBUG_ENABLED
@@ -2315,9 +2315,9 @@ CSharpInstance::~CSharpInstance() {
#ifdef DEBUG_ENABLED
// CSharpInstance must not be created unless it's going to be added to the list for sure
- Set<Object *>::Element *match = script->instances.find(owner);
+ HashSet<Object *>::Iterator match = script->instances.find(owner);
CRASH_COND(!match);
- script->instances.erase(match);
+ script->instances.remove(match);
#else
script->instances.erase(owner);
#endif
@@ -2331,7 +2331,7 @@ void CSharpScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder)
#endif
#ifdef TOOLS_ENABLED
-void CSharpScript::_update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames) {
+void CSharpScript::_update_exports_values(HashMap<StringName, Variant> &values, List<PropertyInfo> &propnames) {
if (base_cache.is_valid()) {
base_cache->_update_exports_values(values, propnames);
}
@@ -2567,12 +2567,12 @@ bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_upda
if ((changed || p_instance_to_update) && placeholders.size()) {
// Update placeholders if any
- Map<StringName, Variant> values;
+ HashMap<StringName, Variant> values;
List<PropertyInfo> propnames;
_update_exports_values(values, propnames);
if (changed) {
- for (PlaceHolderScriptInstance *&script_instance : placeholders) {
+ for (PlaceHolderScriptInstance *script_instance : placeholders) {
script_instance->update(propnames, values);
}
} else {
@@ -2807,7 +2807,8 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage
GD_MONO_ASSERT_THREAD_ATTACHED;
if (p_variant_type == Variant::INT && p_type.type_encoding == MONO_TYPE_VALUETYPE && mono_class_is_enum(p_type.type_class->get_mono_ptr())) {
- r_hint = PROPERTY_HINT_ENUM;
+ MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), p_type.type_class->get_mono_type());
+ r_hint = GDMonoUtils::Marshal::type_has_flags_attribute(reftype) ? PROPERTY_HINT_FLAGS : PROPERTY_HINT_ENUM;
Vector<MonoClassField *> fields = p_type.type_class->get_enum_fields();
@@ -2844,7 +2845,8 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage
uint64_t val = GDMonoUtils::unbox_enum_value(val_obj, enum_basetype, r_error);
ERR_FAIL_COND_V_MSG(r_error, -1, "Failed to unbox '" + enum_field_name + "' constant enum value.");
- if (val != (unsigned int)i) {
+ unsigned int expected_val = r_hint == PROPERTY_HINT_FLAGS ? 1 << i : i;
+ if (val != expected_val) {
uses_default_values = false;
}
@@ -3144,7 +3146,7 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg
void *data = CSharpLanguage::get_existing_instance_binding(p_owner);
CRASH_COND(data == nullptr);
- CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
+ CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)data)->get();
if (script_binding.inited && !script_binding.gchandle.is_released()) {
MonoObject *mono_object = script_binding.gchandle.get_target();
if (mono_object) {
@@ -3401,9 +3403,9 @@ ScriptLanguage *CSharpScript::get_language() const {
bool CSharpScript::get_property_default_value(const StringName &p_property, Variant &r_value) const {
#ifdef TOOLS_ENABLED
- const Map<StringName, Variant>::Element *E = exported_members_defval_cache.find(p_property);
+ HashMap<StringName, Variant>::ConstIterator E = exported_members_defval_cache.find(p_property);
if (E) {
- r_value = E->get();
+ r_value = E->value;
return true;
}
@@ -3491,8 +3493,8 @@ Ref<Script> CSharpScript::get_base_script() const {
void CSharpScript::get_script_property_list(List<PropertyInfo> *r_list) const {
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) {
@@ -3574,7 +3576,7 @@ CSharpScript::~CSharpScript() {
#endif
}
-void CSharpScript::get_members(Set<StringName> *p_members) {
+void CSharpScript::get_members(HashSet<StringName> *p_members) {
#if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED)
if (p_members) {
for (const StringName &member_name : exported_members_names) {
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 41b54248a3..69bd8703aa 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -110,7 +110,7 @@ private:
Ref<CSharpScript> base_cache; // TODO what's this for?
- Set<Object *> instances;
+ HashSet<Object *> instances;
#ifdef GD_MONO_HOT_RELOAD
struct StateBackup {
@@ -121,8 +121,8 @@ private:
List<Pair<StringName, Array>> event_signals;
};
- Set<ObjectID> pending_reload_instances;
- Map<ObjectID, StateBackup> pending_reload_state;
+ HashSet<ObjectID> pending_reload_instances;
+ RBMap<ObjectID, StateBackup> pending_reload_state;
StringName tied_class_name_for_reload;
StringName tied_class_namespace_for_reload;
#endif
@@ -132,29 +132,29 @@ private:
SelfList<CSharpScript> script_list = this;
- Map<StringName, Vector<SignalParameter>> _signals;
- Map<StringName, EventSignal> event_signals;
+ HashMap<StringName, Vector<SignalParameter>> _signals;
+ HashMap<StringName, EventSignal> event_signals;
bool signals_invalidated = true;
Vector<Multiplayer::RPCConfig> rpc_functions;
#ifdef TOOLS_ENABLED
List<PropertyInfo> exported_members_cache; // members_cache
- Map<StringName, Variant> exported_members_defval_cache; // member_default_values_cache
- Set<PlaceHolderScriptInstance *> placeholders;
+ HashMap<StringName, Variant> exported_members_defval_cache; // member_default_values_cache
+ HashSet<PlaceHolderScriptInstance *> placeholders;
bool source_changed_cache = false;
bool placeholder_fallback_enabled = false;
bool exports_invalidated = true;
- void _update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames);
+ void _update_exports_values(HashMap<StringName, Variant> &values, List<PropertyInfo> &propnames);
void _update_member_info_no_exports();
void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder) override;
#endif
#if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED)
- Set<StringName> exported_members_names;
+ HashSet<StringName> exported_members_names;
#endif
- OrderedHashMap<StringName, PropertyInfo> member_info;
+ HashMap<StringName, PropertyInfo> member_info;
void _clear();
@@ -218,7 +218,7 @@ public:
void get_script_property_list(List<PropertyInfo> *r_list) const override;
void update_exports() override;
- void get_members(Set<StringName> *p_members) override;
+ void get_members(HashSet<StringName> *p_members) override;
bool is_tool() const override { return tool; }
bool is_valid() const override { return valid; }
@@ -356,11 +356,11 @@ class CSharpLanguage : public ScriptLanguage {
Mutex script_gchandle_release_mutex;
Mutex language_bind_mutex;
- Map<Object *, CSharpScriptBinding> script_bindings;
+ RBMap<Object *, CSharpScriptBinding> script_bindings;
#ifdef DEBUG_ENABLED
// List of unsafe object references
- Map<ObjectID, int> unsafe_object_references;
+ HashMap<ObjectID, int> unsafe_object_references;
Mutex unsafe_object_references_lock;
#endif
@@ -467,7 +467,7 @@ public:
virtual Ref<Script> make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const override;
virtual Vector<ScriptTemplate> get_built_in_templates(StringName p_object) override;
/* TODO */ bool validate(const String &p_script, const String &p_path, List<String> *r_functions,
- List<ScriptLanguage::ScriptError> *r_errors = nullptr, List<ScriptLanguage::Warning> *r_warnings = nullptr, Set<int> *r_safe_lines = nullptr) const override {
+ List<ScriptLanguage::ScriptError> *r_errors = nullptr, List<ScriptLanguage::Warning> *r_warnings = nullptr, HashSet<int> *r_safe_lines = nullptr) const override {
return true;
}
String validate_path(const String &p_path) const override;
@@ -518,7 +518,7 @@ public:
void thread_enter() override;
void thread_exit() override;
- Map<Object *, CSharpScriptBinding>::Element *insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding);
+ RBMap<Object *, CSharpScriptBinding>::Element *insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding);
bool setup_csharp_script_binding(CSharpScriptBinding &r_script_binding, Object *p_object);
#ifdef DEBUG_ENABLED
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs
index bac7a2e6db..02e9d98647 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs
@@ -63,6 +63,7 @@ namespace GodotTools.Build
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = false;
+ startInfo.CreateNoWindow = true;
if (UsingMonoMsBuildOnWindows)
{
diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs
index 93a1360cb6..2db549c623 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs
@@ -184,7 +184,8 @@ namespace GodotTools.Utils
{
RedirectStandardOutput = true,
RedirectStandardError = true,
- UseShellExecute = false
+ UseShellExecute = false,
+ CreateNoWindow = true
};
using (Process process = Process.Start(startInfo))
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 54c65c21e8..960d2fe27c 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -604,14 +604,14 @@ void BindingsGenerator::_append_xml_signal(StringBuilder &p_xml_output, const Ty
void BindingsGenerator::_append_xml_enum(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts) {
const StringName search_cname = !p_target_itype ? p_target_cname : StringName(p_target_itype->name + "." + (String)p_target_cname);
- const Map<StringName, TypeInterface>::Element *enum_match = enum_types.find(search_cname);
+ HashMap<StringName, TypeInterface>::ConstIterator enum_match = enum_types.find(search_cname);
if (!enum_match && search_cname != p_target_cname) {
enum_match = enum_types.find(p_target_cname);
}
if (enum_match) {
- const TypeInterface &target_enum_itype = enum_match->value();
+ const TypeInterface &target_enum_itype = enum_match->value;
p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
p_xml_output.append(target_enum_itype.proxy_name); // Includes nesting class if any
@@ -1078,8 +1078,8 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) {
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) {
continue;
@@ -1187,8 +1187,8 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) {
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) {
continue;
@@ -1573,9 +1573,9 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
// Search it in base types too
const TypeInterface *current_type = &p_itype;
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 + "'.");
- current_type = &base_match.get();
+ current_type = &base_match->value;
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
current_type = &p_itype;
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 + "'.");
- current_type = &base_match.get();
+ current_type = &base_match->value;
getter = current_type->find_method_by_name(p_iprop.getter);
}
@@ -1652,7 +1652,9 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
p_output.append("static ");
}
- p_output.append(prop_itype->cs_type);
+ String prop_cs_type = prop_itype->cs_type + _get_generic_type_parameters(*prop_itype, proptype_name.generic_type_parameters);
+
+ p_output.append(prop_cs_type);
p_output.append(" ");
p_output.append(p_iprop.proxy_name);
p_output.append("\n" INDENT2 OPEN_BLOCK);
@@ -1762,6 +1764,8 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
"Invalid default value for parameter '" + iarg.name + "' of method '" + p_itype.name + "." + p_imethod.name + "'.");
}
+ String arg_cs_type = arg_type->cs_type + _get_generic_type_parameters(*arg_type, iarg.type.generic_type_parameters);
+
// Add the current arguments to the signature
// If the argument has a default value which is not a constant, we will make it Nullable
{
@@ -1773,7 +1777,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
arguments_sig += "Nullable<";
}
- arguments_sig += arg_type->cs_type;
+ arguments_sig += arg_cs_type;
if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) {
arguments_sig += "> ";
@@ -1800,7 +1804,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
String arg_in = iarg.name;
arg_in += "_in";
- cs_in_statements += arg_type->cs_type;
+ cs_in_statements += arg_cs_type;
cs_in_statements += " ";
cs_in_statements += arg_in;
cs_in_statements += " = ";
@@ -1820,7 +1824,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
cs_in_statements += " : ";
}
- String cs_type = arg_type->cs_type;
+ String cs_type = arg_cs_type;
if (cs_type.ends_with("[]")) {
cs_type = cs_type.substr(0, cs_type.length() - 2);
}
@@ -1837,7 +1841,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
// Escape < and > in the attribute default value
String param_def_arg = def_arg.replacen("<", "&lt;").replacen(">", "&gt;");
- default_args_doc.append(MEMBER_BEGIN "/// <param name=\"" + param_tag_name + "\">If the parameter is null, then the default value is " + param_def_arg + "</param>");
+ default_args_doc.append(MEMBER_BEGIN "/// <param name=\"" + param_tag_name + "\">If the parameter is null, then the default value is <c>" + param_def_arg + "</c>.</param>");
} else {
icall_params += arg_type->cs_in.is_empty() ? iarg.name : sformat(arg_type->cs_in, iarg.name);
}
@@ -1903,7 +1907,9 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
p_output.append("virtual ");
}
- p_output.append(return_type->cs_type + " ");
+ String return_cs_type = return_type->cs_type + _get_generic_type_parameters(*return_type, p_imethod.return_type.generic_type_parameters);
+
+ p_output.append(return_cs_type + " ");
p_output.append(p_imethod.proxy_name + "(");
p_output.append(arguments_sig + ")\n" OPEN_BLOCK_L2);
@@ -1914,7 +1920,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
p_output.append("return;\n" CLOSE_BLOCK_L2);
} else {
p_output.append("return default(");
- p_output.append(return_type->cs_type);
+ p_output.append(return_cs_type);
p_output.append(");\n" CLOSE_BLOCK_L2);
}
@@ -1938,10 +1944,10 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
return OK; // Won't increment method bind count
}
- const Map<const MethodInterface *, const InternalCall *>::Element *match = method_icalls_map.find(&p_imethod);
+ HashMap<const MethodInterface *, const InternalCall *>::ConstIterator match = method_icalls_map.find(&p_imethod);
ERR_FAIL_NULL_V(match, ERR_BUG);
- const InternalCall *im_icall = match->value();
+ const InternalCall *im_icall = match->value;
String im_call = im_icall->editor_only ? BINDINGS_CLASS_NATIVECALLS_EDITOR : BINDINGS_CLASS_NATIVECALLS;
im_call += ".";
@@ -1956,7 +1962,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
} else if (return_type->cs_out.is_empty()) {
p_output.append("return " + im_call + "(" + icall_params + ");\n");
} else {
- p_output.append(sformat(return_type->cs_out, im_call, icall_params, return_type->cs_type, return_type->im_type_out));
+ p_output.append(sformat(return_type->cs_out, im_call, icall_params, return_cs_type, return_type->im_type_out));
p_output.append("\n");
}
@@ -2096,8 +2102,8 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
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();
@@ -2322,10 +2328,10 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
i++;
}
- const Map<const MethodInterface *, const InternalCall *>::Element *match = method_icalls_map.find(&p_imethod);
+ HashMap<const MethodInterface *, const InternalCall *>::ConstIterator match = method_icalls_map.find(&p_imethod);
ERR_FAIL_NULL_V(match, ERR_BUG);
- const InternalCall *im_icall = match->value();
+ const InternalCall *im_icall = match->value;
String icall_method = im_icall->name;
if (!generated_icall_funcs.find(im_icall)) {
@@ -2468,29 +2474,29 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
}
const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_or_null(const TypeReference &p_typeref) {
- const Map<StringName, TypeInterface>::Element *builtin_type_match = builtin_types.find(p_typeref.cname);
+ HashMap<StringName, TypeInterface>::ConstIterator builtin_type_match = builtin_types.find(p_typeref.cname);
if (builtin_type_match) {
- return &builtin_type_match->get();
+ return &builtin_type_match->value;
}
- const OrderedHashMap<StringName, TypeInterface>::Element obj_type_match = obj_types.find(p_typeref.cname);
+ HashMap<StringName, TypeInterface>::ConstIterator obj_type_match = obj_types.find(p_typeref.cname);
if (obj_type_match) {
- return &obj_type_match.get();
+ return &obj_type_match->value;
}
if (p_typeref.is_enum) {
- const Map<StringName, TypeInterface>::Element *enum_match = enum_types.find(p_typeref.cname);
+ HashMap<StringName, TypeInterface>::ConstIterator enum_match = enum_types.find(p_typeref.cname);
if (enum_match) {
- return &enum_match->get();
+ return &enum_match->value;
}
// Enum not found. Most likely because none of its constants were bound, so it's empty. That's fine. Use int instead.
- const Map<StringName, TypeInterface>::Element *int_match = builtin_types.find(name_cache.type_int);
+ HashMap<StringName, TypeInterface>::ConstIterator int_match = builtin_types.find(name_cache.type_int);
ERR_FAIL_NULL_V(int_match, nullptr);
- return &int_match->get();
+ return &int_match->value;
}
return nullptr;
@@ -2505,16 +2511,52 @@ const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_or_placehol
ERR_PRINT(String() + "Type not found. Creating placeholder: '" + p_typeref.cname.operator String() + "'.");
- const Map<StringName, TypeInterface>::Element *match = placeholder_types.find(p_typeref.cname);
+ HashMap<StringName, TypeInterface>::ConstIterator match = placeholder_types.find(p_typeref.cname);
if (match) {
- return &match->get();
+ return &match->value;
}
TypeInterface placeholder;
TypeInterface::create_placeholder_type(placeholder, p_typeref.cname);
- return &placeholder_types.insert(placeholder.cname, placeholder)->get();
+ return &placeholder_types.insert(placeholder.cname, placeholder)->value;
+}
+
+const String BindingsGenerator::_get_generic_type_parameters(const TypeInterface &p_itype, const List<TypeReference> &p_generic_type_parameters) {
+ if (p_generic_type_parameters.is_empty()) {
+ return "";
+ }
+
+ ERR_FAIL_COND_V_MSG(p_itype.type_parameter_count != p_generic_type_parameters.size(), "",
+ "Generic type parameter count mismatch for type '" + p_itype.name + "'." +
+ " Found " + itos(p_generic_type_parameters.size()) + ", but requires " +
+ itos(p_itype.type_parameter_count) + ".");
+
+ int i = 0;
+ String params = "<";
+ for (const TypeReference &param_type : p_generic_type_parameters) {
+ const TypeInterface *param_itype = _get_type_or_placeholder(param_type);
+
+ ERR_FAIL_COND_V_MSG(param_itype->is_singleton, "",
+ "Generic type parameter is a singleton: '" + param_itype->name + "'.");
+
+ if (p_itype.api_type == ClassDB::API_CORE) {
+ ERR_FAIL_COND_V_MSG(param_itype->api_type == ClassDB::API_EDITOR, "",
+ "Generic type parameter '" + param_itype->name + "' has type from the editor API." +
+ " Core API cannot have dependencies on the editor API.");
+ }
+
+ params += param_itype->cs_type;
+ if (i < p_generic_type_parameters.size() - 1) {
+ params += ", ";
+ }
+
+ i++;
+ }
+ params += ">";
+
+ return params;
}
StringName BindingsGenerator::_get_int_type_name_from_meta(GodotTypeInfo::Metadata p_meta) {
@@ -2708,7 +2750,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
List<PropertyInfo> property_list;
ClassDB::get_property_list(type_cname, &property_list, true);
- Map<StringName, StringName> accessor_methods;
+ HashMap<StringName, StringName> accessor_methods;
for (const PropertyInfo &property : property_list) {
if (property.usage & PROPERTY_USAGE_GROUP || property.usage & PROPERTY_USAGE_SUBGROUP || property.usage & PROPERTY_USAGE_CATEGORY || (property.type == Variant::NIL && property.usage & PROPERTY_USAGE_ARRAY)) {
@@ -2832,6 +2874,9 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
ERR_FAIL_COND_V_MSG(bad_reference_hint, false,
String() + "Return type is reference but hint is not '" _STR(PROPERTY_HINT_RESOURCE_TYPE) "'." +
" Are you returning a reference type by pointer? Method: '" + itype.name + "." + imethod.name + "'.");
+ } else if (return_info.type == Variant::ARRAY && return_info.hint == PROPERTY_HINT_ARRAY_TYPE) {
+ imethod.return_type.cname = Variant::get_type_name(return_info.type);
+ imethod.return_type.generic_type_parameters.push_back(TypeReference(return_info.hint_string));
} else if (return_info.hint == PROPERTY_HINT_RESOURCE_TYPE) {
imethod.return_type.cname = return_info.hint_string;
} else if (return_info.type == Variant::NIL && return_info.usage & PROPERTY_USAGE_NIL_IS_VARIANT) {
@@ -2861,6 +2906,9 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
iarg.type.is_enum = true;
} else if (arginfo.class_name != StringName()) {
iarg.type.cname = arginfo.class_name;
+ } else if (arginfo.type == Variant::ARRAY && arginfo.hint == PROPERTY_HINT_ARRAY_TYPE) {
+ iarg.type.cname = Variant::get_type_name(arginfo.type);
+ iarg.type.generic_type_parameters.push_back(TypeReference(arginfo.hint_string));
} else if (arginfo.hint == PROPERTY_HINT_RESOURCE_TYPE) {
iarg.type.cname = arginfo.hint_string;
} else if (arginfo.type == Variant::NIL) {
@@ -2903,9 +2951,9 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
imethod.proxy_name += "_";
}
- Map<StringName, StringName>::Element *accessor = accessor_methods.find(imethod.cname);
+ HashMap<StringName, StringName>::Iterator accessor = accessor_methods.find(imethod.cname);
if (accessor) {
- const PropertyInterface *accessor_property = itype.find_property_by_name(accessor->value());
+ const PropertyInterface *accessor_property = itype.find_property_by_name(accessor->value);
// We only deprecate an accessor method if it's in the same class as the property. It's easier this way, but also
// we don't know if an accessor method in a different class could have other purposes, so better leave those untouched.
@@ -2942,12 +2990,11 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
// Populate signals
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;
- const MethodInfo &method_info = signal_map.get(*k);
+ const MethodInfo &method_info = E.value;
isignal.name = method_info.name;
isignal.cname = method_info.name;
@@ -2967,6 +3014,9 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
iarg.type.is_enum = true;
} else if (arginfo.class_name != StringName()) {
iarg.type.cname = arginfo.class_name;
+ } else if (arginfo.type == Variant::ARRAY && arginfo.hint == PROPERTY_HINT_ARRAY_TYPE) {
+ iarg.type.cname = Variant::get_type_name(arginfo.type);
+ iarg.type.generic_type_parameters.push_back(TypeReference(arginfo.hint_string));
} else if (arginfo.hint == PROPERTY_HINT_RESOURCE_TYPE) {
iarg.type.cname = arginfo.hint_string;
} else if (arginfo.type == Variant::NIL) {
@@ -3024,10 +3074,9 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
ClassDB::get_integer_constant_list(type_cname, &constants, true);
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();
if (itype.find_property_by_proxy_name(enum_proxy_cname)) {
// We have several conflicts between enums and PascalCase properties,
@@ -3036,7 +3085,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
enum_proxy_cname = StringName(enum_proxy_name);
}
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) {
String constant_name = constant_cname.operator String();
int *value = class_info->constant_map.getptr(constant_cname);
@@ -3066,7 +3115,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
TypeInterface enum_itype;
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.proxy_name = itype.proxy_name + "." + enum_proxy_name;
TypeInterface::postsetup_enum_type(enum_itype);
@@ -3551,13 +3600,14 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.name = "Array";
itype.cname = itype.name;
itype.proxy_name = itype.name;
+ itype.type_parameter_count = 1;
itype.c_out = "\treturn memnew(Array(%1));\n";
itype.c_type = itype.name;
itype.c_type_in = itype.c_type + "*";
itype.c_type_out = itype.c_type + "*";
itype.cs_type = BINDINGS_NAMESPACE_COLLECTIONS "." + itype.proxy_name;
itype.cs_in = "%0." CS_SMETHOD_GETINSTANCE "()";
- itype.cs_out = "return new " + itype.cs_type + "(%0(%1));";
+ itype.cs_out = "return new %2(%0(%1));";
itype.im_type_in = "IntPtr";
itype.im_type_out = "IntPtr";
builtin_types.insert(itype.cname, itype);
@@ -3567,13 +3617,14 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.name = "Dictionary";
itype.cname = itype.name;
itype.proxy_name = itype.name;
+ itype.type_parameter_count = 2;
itype.c_out = "\treturn memnew(Dictionary(%1));\n";
itype.c_type = itype.name;
itype.c_type_in = itype.c_type + "*";
itype.c_type_out = itype.c_type + "*";
itype.cs_type = BINDINGS_NAMESPACE_COLLECTIONS "." + itype.proxy_name;
itype.cs_in = "%0." CS_SMETHOD_GETINSTANCE "()";
- itype.cs_out = "return new " + itype.cs_type + "(%0(%1));";
+ itype.cs_out = "return new %2(%0(%1));";
itype.im_type_in = "IntPtr";
itype.im_type_out = "IntPtr";
builtin_types.insert(itype.cname, itype);
@@ -3596,11 +3647,11 @@ void BindingsGenerator::_populate_global_constants() {
int global_constants_count = CoreConstants::get_global_constant_count();
if (global_constants_count > 0) {
- Map<String, DocData::ClassDoc>::Element *match = EditorHelp::get_doc_data()->class_list.find("@GlobalScope");
+ HashMap<String, DocData::ClassDoc>::Iterator match = EditorHelp::get_doc_data()->class_list.find("@GlobalScope");
CRASH_COND_MSG(!match, "Could not find '@GlobalScope' in DocData.");
- const DocData::ClassDoc &global_scope_doc = match->value();
+ const DocData::ClassDoc &global_scope_doc = match->value;
for (int i = 0; i < global_constants_count; i++) {
String constant_name = CoreConstants::get_global_constant_name(i);
@@ -3715,8 +3766,8 @@ void BindingsGenerator::_initialize() {
core_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;
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index dec4fae8cd..f0ba2b18e4 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -87,6 +87,8 @@ class BindingsGenerator {
StringName cname;
bool is_enum = false;
+ List<TypeReference> generic_type_parameters;
+
TypeReference() {}
TypeReference(const StringName &p_cname) :
@@ -206,6 +208,8 @@ class BindingsGenerator {
String name;
StringName cname;
+ int type_parameter_count;
+
/**
* Identifier name of the base class.
*/
@@ -533,24 +537,24 @@ class BindingsGenerator {
bool log_print_enabled = true;
bool initialized = false;
- OrderedHashMap<StringName, TypeInterface> obj_types;
+ HashMap<StringName, TypeInterface> obj_types;
- Map<StringName, TypeInterface> placeholder_types;
- Map<StringName, TypeInterface> builtin_types;
- Map<StringName, TypeInterface> enum_types;
+ HashMap<StringName, TypeInterface> placeholder_types;
+ HashMap<StringName, TypeInterface> builtin_types;
+ HashMap<StringName, TypeInterface> enum_types;
List<EnumInterface> global_enums;
List<ConstantInterface> global_constants;
List<InternalCall> method_icalls;
- Map<const MethodInterface *, const InternalCall *> method_icalls_map;
+ HashMap<const MethodInterface *, const InternalCall *> method_icalls_map;
List<const InternalCall *> generated_icall_funcs;
List<InternalCall> core_custom_icalls;
List<InternalCall> editor_custom_icalls;
- Map<StringName, List<StringName>> blacklisted_methods;
+ HashMap<StringName, List<StringName>> blacklisted_methods;
void _initialize_blacklisted_methods();
@@ -679,6 +683,8 @@ class BindingsGenerator {
const TypeInterface *_get_type_or_null(const TypeReference &p_typeref);
const TypeInterface *_get_type_or_placeholder(const TypeReference &p_typeref);
+ const String _get_generic_type_parameters(const TypeInterface &p_itype, const List<TypeReference> &p_generic_type_parameters);
+
StringName _get_int_type_name_from_meta(GodotTypeInfo::Metadata p_meta);
StringName _get_float_type_name_from_meta(GodotTypeInfo::Metadata p_meta);
diff --git a/modules/mono/editor/code_completion.cpp b/modules/mono/editor/code_completion.cpp
index 79015686c3..a1789412f4 100644
--- a/modules/mono/editor/code_completion.cpp
+++ b/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: {
{
// 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)));
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs
index ee4d0eed08..50ae2eb112 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs
@@ -80,6 +80,11 @@ namespace Godot
private static bool TypeIsGenericIDictionary(Type type) => type.GetGenericTypeDefinition() == typeof(IDictionary<,>);
/// <summary>
+ /// Returns <see langword="true"/> if the <see cref="FlagsAttribute"/> is applied to the given type.
+ /// </summary>
+ private static bool TypeHasFlagsAttribute(Type type) => type.IsDefined(typeof(FlagsAttribute), false);
+
+ /// <summary>
/// Returns the generic type definition of <paramref name="type"/>.
/// </summary>
/// <exception cref="InvalidOperationException">
diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp
index b10d78c593..7b9dbc87cf 100644
--- a/modules/mono/glue/base_object_glue.cpp
+++ b/modules/mono/glue/base_object_glue.cpp
@@ -68,7 +68,7 @@ void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) {
void *data = CSharpLanguage::get_existing_instance_binding(p_ptr);
if (data) {
- CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
+ CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)data)->get();
if (script_binding.inited) {
MonoGCHandleData &gchandle = script_binding.gchandle;
if (!gchandle.is_released()) {
@@ -115,7 +115,7 @@ void godot_icall_RefCounted_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoole
void *data = CSharpLanguage::get_existing_instance_binding(rc);
if (data) {
- CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
+ CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)data)->get();
if (script_binding.inited) {
MonoGCHandleData &gchandle = script_binding.gchandle;
if (!gchandle.is_released()) {
diff --git a/modules/mono/managed_callable.cpp b/modules/mono/managed_callable.cpp
index 8ed21c323f..4f7783b765 100644
--- a/modules/mono/managed_callable.cpp
+++ b/modules/mono/managed_callable.cpp
@@ -36,7 +36,7 @@
#ifdef GD_MONO_HOT_RELOAD
SelfList<ManagedCallable>::List ManagedCallable::instances;
-Map<ManagedCallable *, Array> ManagedCallable::instances_pending_reload;
+RBMap<ManagedCallable *, Array> ManagedCallable::instances_pending_reload;
Mutex ManagedCallable::instances_mutex;
#endif
diff --git a/modules/mono/managed_callable.h b/modules/mono/managed_callable.h
index d50a8a7b08..11bee6cf60 100644
--- a/modules/mono/managed_callable.h
+++ b/modules/mono/managed_callable.h
@@ -48,7 +48,7 @@ class ManagedCallable : public CallableCustom {
#ifdef GD_MONO_HOT_RELOAD
SelfList<ManagedCallable> self_instance = this;
static SelfList<ManagedCallable>::List instances;
- static Map<ManagedCallable *, Array> instances_pending_reload;
+ static RBMap<ManagedCallable *, Array> instances_pending_reload;
static Mutex instances_mutex;
#endif
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index e98ce8f6c1..39a8ef22b7 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/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());
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) {
GDMonoClass *klass = assembly->get_class(p_raw_class);
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());
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);
if (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) {
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);
@@ -1298,13 +1295,11 @@ GDMono::~GDMono() {
// Leave the rest to 'mono_jit_cleanup'
#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();
diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp
index 3991b14612..42c6b6305f 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.cpp
+++ b/modules/mono/mono_gd/gd_mono_assembly.cpp
@@ -412,10 +412,10 @@ GDMonoClass *GDMonoAssembly::get_class(const StringName &p_namespace, const Stri
GDMonoClass *GDMonoAssembly::get_class(MonoClass *p_mono_class) {
ERR_FAIL_NULL_V(image, nullptr);
- Map<MonoClass *, GDMonoClass *>::Element *match = cached_raw.find(p_mono_class);
+ HashMap<MonoClass *, GDMonoClass *>::Iterator match = cached_raw.find(p_mono_class);
if (match) {
- return match->value();
+ return match->value;
}
StringName namespace_name = String::utf8(mono_class_get_namespace(p_mono_class));
diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h
index a96357b082..0a3ae6c4fe 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.h
+++ b/modules/mono/mono_gd/gd_mono_assembly.h
@@ -36,7 +36,7 @@
#include "core/string/ustring.h"
#include "core/templates/hash_map.h"
-#include "core/templates/map.h"
+#include "core/templates/rb_map.h"
#include "gd_mono_utils.h"
class GDMonoAssembly {
@@ -79,7 +79,7 @@ class GDMonoAssembly {
#endif
HashMap<ClassKey, GDMonoClass *, ClassKey::Hasher> cached_classes;
- Map<MonoClass *, GDMonoClass *> cached_raw;
+ HashMap<MonoClass *, GDMonoClass *> cached_raw;
static Vector<String> search_dirs;
diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp
index d8fd244067..44a8e26b8f 100644
--- a/modules/mono/mono_gd/gd_mono_cache.cpp
+++ b/modules/mono/mono_gd/gd_mono_cache.cpp
@@ -176,6 +176,7 @@ void CachedData::clear_godot_api_cache() {
methodthunk_MarshalUtils_TypeIsGenericIEnumerable.nullify();
methodthunk_MarshalUtils_TypeIsGenericICollection.nullify();
methodthunk_MarshalUtils_TypeIsGenericIDictionary.nullify();
+ methodthunk_MarshalUtils_TypeHasFlagsAttribute.nullify();
methodthunk_MarshalUtils_GetGenericTypeDefinition.nullify();
@@ -300,6 +301,7 @@ void update_godot_api_cache() {
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericIEnumerable, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericIEnumerable", 1));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericICollection, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericICollection", 1));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericIDictionary, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericIDictionary", 1));
+ CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeHasFlagsAttribute, GODOT_API_CLASS(MarshalUtils)->get_method("TypeHasFlagsAttribute", 1));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GetGenericTypeDefinition, GODOT_API_CLASS(MarshalUtils)->get_method("GetGenericTypeDefinition", 2));
diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h
index 4000342c94..92136e1f41 100644
--- a/modules/mono/mono_gd/gd_mono_cache.h
+++ b/modules/mono/mono_gd/gd_mono_cache.h
@@ -147,6 +147,7 @@ struct CachedData {
GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericIEnumerable;
GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericICollection;
GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericIDictionary;
+ GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeHasFlagsAttribute;
GDMonoMethodThunk<MonoReflectionType *, MonoReflectionType **> methodthunk_MarshalUtils_GetGenericTypeDefinition;
diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp
index 3fc0f16e05..51c5aa3542 100644
--- a/modules/mono/mono_gd/gd_mono_class.cpp
+++ b/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) {
memdelete(*existing_method); // Must delete old one
}
- methods.set(key, method);
+ methods.insert(key, method);
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) {
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) {
GDMonoMethod *method = memnew(GDMonoMethod(p_name, raw_method));
- methods.set(key, method);
+ methods.insert(key, 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));
- methods.set(key, method);
+ methods.insert(key, method);
return method;
}
@@ -362,10 +360,10 @@ GDMonoMethod *GDMonoClass::get_method_with_desc(const String &p_description, boo
}
GDMonoField *GDMonoClass::get_field(const StringName &p_name) {
- Map<StringName, GDMonoField *>::Element *result = fields.find(p_name);
+ HashMap<StringName, GDMonoField *>::Iterator result = fields.find(p_name);
if (result) {
- return result->value();
+ return result->value;
}
if (fields_fetched) {
@@ -394,10 +392,10 @@ const Vector<GDMonoField *> &GDMonoClass::get_all_fields() {
while ((raw_field = mono_class_get_fields(mono_class, &iter)) != nullptr) {
StringName name = String::utf8(mono_field_get_name(raw_field));
- Map<StringName, GDMonoField *>::Element *match = fields.find(name);
+ HashMap<StringName, GDMonoField *>::Iterator match = fields.find(name);
if (match) {
- fields_list.push_back(match->get());
+ fields_list.push_back(match->value);
} else {
GDMonoField *field = memnew(GDMonoField(raw_field, this));
fields.insert(name, field);
@@ -411,10 +409,10 @@ const Vector<GDMonoField *> &GDMonoClass::get_all_fields() {
}
GDMonoProperty *GDMonoClass::get_property(const StringName &p_name) {
- Map<StringName, GDMonoProperty *>::Element *result = properties.find(p_name);
+ HashMap<StringName, GDMonoProperty *>::Iterator result = properties.find(p_name);
if (result) {
- return result->value();
+ return result->value;
}
if (properties_fetched) {
@@ -443,10 +441,10 @@ const Vector<GDMonoProperty *> &GDMonoClass::get_all_properties() {
while ((raw_property = mono_class_get_properties(mono_class, &iter)) != nullptr) {
StringName name = String::utf8(mono_property_get_name(raw_property));
- Map<StringName, GDMonoProperty *>::Element *match = properties.find(name);
+ HashMap<StringName, GDMonoProperty *>::Iterator match = properties.find(name);
if (match) {
- properties_list.push_back(match->get());
+ properties_list.push_back(match->value);
} else {
GDMonoProperty *property = memnew(GDMonoProperty(raw_property, this));
properties.insert(name, property);
@@ -479,10 +477,10 @@ const Vector<GDMonoClass *> &GDMonoClass::get_all_delegates() {
if (mono_class_is_delegate(raw_class)) {
StringName name = String::utf8(mono_class_get_name(raw_class));
- Map<StringName, GDMonoClass *>::Element *match = delegates.find(name);
+ HashMap<StringName, GDMonoClass *>::Iterator match = delegates.find(name);
if (match) {
- delegates_list.push_back(match->get());
+ delegates_list.push_back(match->value);
} else {
GDMonoClass *delegate = memnew(GDMonoClass(String::utf8(mono_class_get_namespace(raw_class)), String::utf8(mono_class_get_name(raw_class)), raw_class, assembly));
delegates.insert(name, delegate);
@@ -549,9 +547,8 @@ GDMonoClass::~GDMonoClass() {
Vector<GDMonoMethod *> deleted_methods;
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) {
for (int i = 0; i < offset; i++) {
diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h
index b32d561f61..6b35da30f9 100644
--- a/modules/mono/mono_gd/gd_mono_class.h
+++ b/modules/mono/mono_gd/gd_mono_class.h
@@ -32,7 +32,7 @@
#define GD_MONO_CLASS_H
#include "core/string/ustring.h"
-#include "core/templates/map.h"
+#include "core/templates/rb_map.h"
#include "gd_mono_field.h"
#include "gd_mono_header.h"
@@ -85,15 +85,15 @@ class GDMonoClass {
Vector<GDMonoMethod *> method_list;
bool fields_fetched;
- Map<StringName, GDMonoField *> fields;
+ HashMap<StringName, GDMonoField *> fields;
Vector<GDMonoField *> fields_list;
bool properties_fetched;
- Map<StringName, GDMonoProperty *> properties;
+ HashMap<StringName, GDMonoProperty *> properties;
Vector<GDMonoProperty *> properties_list;
bool delegates_fetched;
- Map<StringName, GDMonoClass *> delegates;
+ HashMap<StringName, GDMonoClass *> delegates;
Vector<GDMonoClass *> delegates_list;
friend class GDMonoAssembly;
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index a884bf4da0..1983d6ebe2 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -70,7 +70,7 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) {
void *data = CSharpLanguage::get_instance_binding(unmanaged);
ERR_FAIL_NULL_V(data, nullptr);
- CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->value();
+ CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)data)->value();
ERR_FAIL_COND_V(!script_binding.inited, nullptr);
MonoGCHandleData &gchandle = script_binding.gchandle;
@@ -614,6 +614,14 @@ bool type_is_generic_idictionary(MonoReflectionType *p_reftype) {
return (bool)res;
}
+bool type_has_flags_attribute(MonoReflectionType *p_reftype) {
+ NO_GLUE_RET(false);
+ MonoException *exc = nullptr;
+ MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeHasFlagsAttribute).invoke(p_reftype, &exc);
+ UNHANDLED_EXCEPTION(exc);
+ return (bool)res;
+}
+
void get_generic_type_definition(MonoReflectionType *p_reftype, MonoReflectionType **r_generic_reftype) {
MonoException *exc = nullptr;
CACHED_METHOD_THUNK(MarshalUtils, GetGenericTypeDefinition).invoke(p_reftype, r_generic_reftype, &exc);
diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h
index 4c2c2c93c2..246a1cd31e 100644
--- a/modules/mono/mono_gd/gd_mono_utils.h
+++ b/modules/mono/mono_gd/gd_mono_utils.h
@@ -61,6 +61,7 @@ bool type_is_system_generic_dictionary(MonoReflectionType *p_reftype);
bool type_is_generic_ienumerable(MonoReflectionType *p_reftype);
bool type_is_generic_icollection(MonoReflectionType *p_reftype);
bool type_is_generic_idictionary(MonoReflectionType *p_reftype);
+bool type_has_flags_attribute(MonoReflectionType *p_reftype);
void get_generic_type_definition(MonoReflectionType *p_reftype, MonoReflectionType **r_generic_reftype);
diff --git a/modules/mono/utils/osx_utils.cpp b/modules/mono/utils/osx_utils.cpp
index 835c611709..abb59420eb 100644
--- a/modules/mono/utils/osx_utils.cpp
+++ b/modules/mono/utils/osx_utils.cpp
@@ -34,8 +34,8 @@
#include "core/string/print_string.h"
-#include <CoreFoundation/CoreFoundation.h>
-#include <CoreServices/CoreServices.h>
+#import <CoreFoundation/CoreFoundation.h>
+#import <CoreServices/CoreServices.h>
bool osx_is_app_bundle_installed(const String &p_bundle_id) {
CFStringRef bundle_id = CFStringCreateWithCString(nullptr, p_bundle_id.utf8(), kCFStringEncodingUTF8);
diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp
index d16d41b438..cc9d05da47 100644
--- a/modules/navigation/godot_navigation_server.cpp
+++ b/modules/navigation/godot_navigation_server.cpp
@@ -233,6 +233,44 @@ RID GodotNavigationServer::map_get_closest_point_owner(RID p_map, const Vector3
return map->get_closest_point_owner(p_point);
}
+Array GodotNavigationServer::map_get_regions(RID p_map) const {
+ Array regions_rids;
+ const NavMap *map = map_owner.get_or_null(p_map);
+ ERR_FAIL_COND_V(map == nullptr, regions_rids);
+ for (NavRegion *region : map->get_regions()) {
+ regions_rids.push_back(region->get_self());
+ }
+ return regions_rids;
+}
+
+Array GodotNavigationServer::map_get_agents(RID p_map) const {
+ Array agents_rids;
+ const NavMap *map = map_owner.get_or_null(p_map);
+ ERR_FAIL_COND_V(map == nullptr, agents_rids);
+ for (RvoAgent *agent : map->get_agents()) {
+ agents_rids.push_back(agent->get_self());
+ }
+ return agents_rids;
+}
+
+RID GodotNavigationServer::region_get_map(RID p_region) const {
+ NavRegion *region = region_owner.get_or_null(p_region);
+ ERR_FAIL_COND_V(region == nullptr, RID());
+ if (region->get_map()) {
+ return region->get_map()->get_self();
+ }
+ return RID();
+}
+
+RID GodotNavigationServer::agent_get_map(RID p_agent) const {
+ RvoAgent *agent = agent_owner.get_or_null(p_agent);
+ ERR_FAIL_COND_V(agent == nullptr, RID());
+ if (agent->get_map()) {
+ return agent->get_map()->get_self();
+ }
+ return RID();
+}
+
RID GodotNavigationServer::region_create() const {
GodotNavigationServer *mut_this = const_cast<GodotNavigationServer *>(this);
MutexLock lock(mut_this->operations_mutex);
diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h
index 7ad5e2d501..89e7311e51 100644
--- a/modules/navigation/godot_navigation_server.h
+++ b/modules/navigation/godot_navigation_server.h
@@ -105,8 +105,12 @@ public:
virtual Vector3 map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const override;
virtual RID map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const override;
+ virtual Array map_get_regions(RID p_map) const override;
+ virtual Array map_get_agents(RID p_map) const override;
+
virtual RID region_create() const override;
COMMAND_2(region_set_map, RID, p_region, RID, p_map);
+ virtual RID region_get_map(RID p_region) const override;
COMMAND_2(region_set_layers, RID, p_region, uint32_t, p_layers);
virtual uint32_t region_get_layers(RID p_region) const override;
COMMAND_2(region_set_transform, RID, p_region, Transform3D, p_transform);
@@ -118,6 +122,7 @@ public:
virtual RID agent_create() const override;
COMMAND_2(agent_set_map, RID, p_agent, RID, p_map);
+ virtual RID agent_get_map(RID p_agent) const override;
COMMAND_2(agent_set_neighbor_dist, RID, p_agent, real_t, p_dist);
COMMAND_2(agent_set_max_neighbors, RID, p_agent, int, p_count);
COMMAND_2(agent_set_time_horizon, RID, p_agent, real_t, p_time);
diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp
index cbc0adc574..344475fb37 100644
--- a/modules/navigation/nav_map.cpp
+++ b/modules/navigation/nav_map.cpp
@@ -541,7 +541,7 @@ void NavMap::sync() {
}
// Group all edges per key.
- Map<gd::EdgeKey, Vector<gd::Edge::Connection>> connections;
+ HashMap<gd::EdgeKey, Vector<gd::Edge::Connection>, gd::EdgeKey> connections;
for (size_t poly_id(0); poly_id < polygons.size(); poly_id++) {
gd::Polygon &poly(polygons[poly_id]);
@@ -549,7 +549,7 @@ void NavMap::sync() {
int next_point = (p + 1) % poly.points.size();
gd::EdgeKey ek(poly.points[p].key, poly.points[next_point].key);
- Map<gd::EdgeKey, Vector<gd::Edge::Connection>>::Element *connection = connections.find(ek);
+ HashMap<gd::EdgeKey, Vector<gd::Edge::Connection>, gd::EdgeKey>::Iterator connection = connections.find(ek);
if (!connection) {
connections[ek] = Vector<gd::Edge::Connection>();
}
diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h
index 5232e42bed..f58a78d4ca 100644
--- a/modules/navigation/nav_map.h
+++ b/modules/navigation/nav_map.h
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RVO_SPACE_H
-#define RVO_SPACE_H
+#ifndef NAV_MAP_H
+#define NAV_MAP_H
#include "nav_rid.h"
#include "core/math/math_defs.h"
-#include "core/templates/map.h"
+#include "core/templates/rb_map.h"
#include "core/templates/thread_work_pool.h"
#include "nav_utils.h"
@@ -141,4 +141,4 @@ private:
void clip_path(const std::vector<gd::NavigationPoly> &p_navigation_polys, Vector<Vector3> &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly) const;
};
-#endif // RVO_SPACE_H
+#endif // NAV_MAP_H
diff --git a/modules/navigation/nav_utils.h b/modules/navigation/nav_utils.h
index 5b6c695ca4..a9f4e0e2fc 100644
--- a/modules/navigation/nav_utils.h
+++ b/modules/navigation/nav_utils.h
@@ -32,8 +32,9 @@
#define NAV_UTILS_H
#include "core/math/vector3.h"
+#include "core/templates/hash_map.h"
+#include "core/templates/hashfuncs.h"
#include "core/templates/vector.h"
-
#include <vector>
class NavRegion;
@@ -49,15 +50,18 @@ union PointKey {
};
uint64_t key = 0;
- bool operator<(const PointKey &p_key) const { return key < p_key.key; }
};
struct EdgeKey {
PointKey a;
PointKey b;
- bool operator<(const EdgeKey &p_key) const {
- return (a.key == p_key.a.key) ? (b.key < p_key.b.key) : (a.key < p_key.a.key);
+ static uint32_t hash(const EdgeKey &p_val) {
+ return hash_one_uint64(p_val.a.key) ^ hash_one_uint64(p_val.b.key);
+ }
+
+ bool operator==(const EdgeKey &p_key) const {
+ return (a.key == p_key.a.key) && (b.key == p_key.b.key);
}
EdgeKey(const PointKey &p_a = PointKey(), const PointKey &p_b = PointKey()) :
diff --git a/modules/navigation/navigation_mesh_generator.cpp b/modules/navigation/navigation_mesh_generator.cpp
index 2d6c78f704..1bc7cd7cdc 100644
--- a/modules/navigation/navigation_mesh_generator.cpp
+++ b/modules/navigation/navigation_mesh_generator.cpp
@@ -172,14 +172,16 @@ void NavigationMeshGenerator::_parse_geometry(const Transform3D &p_navmesh_trans
if (Object::cast_to<MultiMeshInstance3D>(p_node) && p_generate_from != NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS) {
MultiMeshInstance3D *multimesh_instance = Object::cast_to<MultiMeshInstance3D>(p_node);
Ref<MultiMesh> multimesh = multimesh_instance->get_multimesh();
- Ref<Mesh> mesh = multimesh->get_mesh();
- if (mesh.is_valid()) {
- int n = multimesh->get_visible_instance_count();
- if (n == -1) {
- n = multimesh->get_instance_count();
- }
- for (int i = 0; i < n; i++) {
- _add_mesh(mesh, p_navmesh_transform * multimesh_instance->get_global_transform() * multimesh->get_instance_transform(i), p_vertices, p_indices);
+ if (multimesh.is_valid()) {
+ Ref<Mesh> mesh = multimesh->get_mesh();
+ if (mesh.is_valid()) {
+ int n = multimesh->get_visible_instance_count();
+ if (n == -1) {
+ n = multimesh->get_instance_count();
+ }
+ for (int i = 0; i < n; i++) {
+ _add_mesh(mesh, p_navmesh_transform * multimesh_instance->get_global_transform() * multimesh->get_instance_transform(i), p_vertices, p_indices);
+ }
}
}
}
@@ -445,7 +447,7 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh(
cfg.minRegionArea = (int)(p_nav_mesh->get_region_min_size() * p_nav_mesh->get_region_min_size());
cfg.mergeRegionArea = (int)(p_nav_mesh->get_region_merge_size() * p_nav_mesh->get_region_merge_size());
cfg.maxVertsPerPoly = (int)p_nav_mesh->get_verts_per_poly();
- cfg.detailSampleDist = p_nav_mesh->get_detail_sample_distance() < 0.9f ? 0 : p_nav_mesh->get_cell_size() * p_nav_mesh->get_detail_sample_distance();
+ cfg.detailSampleDist = MAX(p_nav_mesh->get_cell_size() * p_nav_mesh->get_detail_sample_distance(), 0.1f);
cfg.detailSampleMaxError = p_nav_mesh->get_cell_height() * p_nav_mesh->get_detail_sample_max_error();
cfg.bmin[0] = bmin[0];
@@ -462,6 +464,14 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh(
#endif
rcCalcGridSize(cfg.bmin, cfg.bmax, cfg.cs, &cfg.width, &cfg.height);
+ // ~30000000 seems to be around sweetspot where Editor baking breaks
+ if ((cfg.width * cfg.height) > 30000000) {
+ WARN_PRINT("NavigationMesh baking process will likely fail."
+ "\nSource geometry is suspiciously big for the current Cell Size and Cell Height in the NavMesh Resource bake settings."
+ "\nIf baking does not fail, the resulting NavigationMesh will create serious pathfinding performance issues."
+ "\nIt is advised to increase Cell Size and/or Cell Height in the NavMesh Resource bake settings or reduce the size / scale of the source geometry.");
+ }
+
#ifdef TOOLS_ENABLED
if (ep) {
ep->step(TTR("Creating heightfield..."), 3);
diff --git a/modules/noise/fastnoise_lite.cpp b/modules/noise/fastnoise_lite.cpp
index a8d38dee62..b21e3247d7 100644
--- a/modules/noise/fastnoise_lite.cpp
+++ b/modules/noise/fastnoise_lite.cpp
@@ -30,6 +30,24 @@
#include "fastnoise_lite.h"
+_FastNoiseLite::FractalType FastNoiseLite::_convert_domain_warp_fractal_type_enum(DomainWarpFractalType p_domain_warp_fractal_type) {
+ _FastNoiseLite::FractalType type;
+ switch (p_domain_warp_fractal_type) {
+ case DOMAIN_WARP_FRACTAL_NONE:
+ type = _FastNoiseLite::FractalType_None;
+ break;
+ case DOMAIN_WARP_FRACTAL_PROGRESSIVE:
+ type = _FastNoiseLite::FractalType_DomainWarpProgressive;
+ break;
+ case DOMAIN_WARP_FRACTAL_INDEPENDENT:
+ type = _FastNoiseLite::FractalType_DomainWarpIndependent;
+ break;
+ default:
+ type = _FastNoiseLite::FractalType_None;
+ }
+ return type;
+}
+
FastNoiseLite::FastNoiseLite() {
_noise.SetNoiseType((_FastNoiseLite::NoiseType)noise_type);
_noise.SetSeed(seed);
@@ -50,7 +68,7 @@ FastNoiseLite::FastNoiseLite() {
_domain_warp_noise.SetSeed(seed);
_domain_warp_noise.SetDomainWarpAmp(domain_warp_amplitude);
_domain_warp_noise.SetFrequency(domain_warp_frequency);
- _domain_warp_noise.SetFractalType(_FastNoiseLite::FractalType_None);
+ _domain_warp_noise.SetFractalType(_convert_domain_warp_fractal_type_enum(domain_warp_fractal_type));
_domain_warp_noise.SetFractalOctaves(domain_warp_fractal_octaves);
_domain_warp_noise.SetFractalLacunarity(domain_warp_fractal_lacunarity);
_domain_warp_noise.SetFractalGain(domain_warp_fractal_gain);
@@ -241,23 +259,7 @@ real_t FastNoiseLite::get_domain_warp_frequency() const {
void FastNoiseLite::set_domain_warp_fractal_type(DomainWarpFractalType p_domain_warp_fractal_type) {
domain_warp_fractal_type = p_domain_warp_fractal_type;
- // This needs manual conversion because Godots Inspector property API does not support discontiguous enum indices.
- _FastNoiseLite::FractalType type;
- switch (p_domain_warp_fractal_type) {
- case DOMAIN_WARP_FRACTAL_NONE:
- type = _FastNoiseLite::FractalType_None;
- break;
- case DOMAIN_WARP_FRACTAL_PROGRESSIVE:
- type = _FastNoiseLite::FractalType_DomainWarpProgressive;
- break;
- case DOMAIN_WARP_FRACTAL_INDEPENDENT:
- type = _FastNoiseLite::FractalType_DomainWarpIndependent;
- break;
- default:
- type = _FastNoiseLite::FractalType_None;
- }
-
- _domain_warp_noise.SetFractalType(type);
+ _domain_warp_noise.SetFractalType(_convert_domain_warp_fractal_type_enum(p_domain_warp_fractal_type));
emit_changed();
}
@@ -298,6 +300,12 @@ real_t FastNoiseLite::get_domain_warp_fractal_gain() const {
// Noise interface functions.
real_t FastNoiseLite::get_noise_1d(real_t p_x) const {
+ p_x += offset.x;
+ if (domain_warp_enabled) {
+ // Needed since DomainWarp expects a reference.
+ real_t y_dummy = 0;
+ _domain_warp_noise.DomainWarp(p_x, y_dummy);
+ }
return get_noise_2d(p_x, 0.0);
}
@@ -306,10 +314,12 @@ real_t FastNoiseLite::get_noise_2dv(Vector2 p_v) const {
}
real_t FastNoiseLite::get_noise_2d(real_t p_x, real_t p_y) const {
+ p_x += offset.x;
+ p_y += offset.y;
if (domain_warp_enabled) {
_domain_warp_noise.DomainWarp(p_x, p_y);
}
- return _noise.GetNoise(p_x + offset.x, p_y + offset.y);
+ return _noise.GetNoise(p_x, p_y);
}
real_t FastNoiseLite::get_noise_3dv(Vector3 p_v) const {
@@ -317,10 +327,13 @@ real_t FastNoiseLite::get_noise_3dv(Vector3 p_v) const {
}
real_t FastNoiseLite::get_noise_3d(real_t p_x, real_t p_y, real_t p_z) const {
+ p_x += offset.x;
+ p_y += offset.y;
+ p_z += offset.z;
if (domain_warp_enabled) {
_domain_warp_noise.DomainWarp(p_x, p_y, p_z);
}
- return _noise.GetNoise(p_x + offset.x, p_y + offset.y, p_z + offset.z);
+ return _noise.GetNoise(p_x, p_y, p_z);
}
void FastNoiseLite::_changed() {
diff --git a/modules/noise/fastnoise_lite.h b/modules/noise/fastnoise_lite.h
index 0a4251868b..fe8cd7ce6e 100644
--- a/modules/noise/fastnoise_lite.h
+++ b/modules/noise/fastnoise_lite.h
@@ -127,6 +127,9 @@ private:
real_t domain_warp_fractal_lacunarity = 6;
real_t domain_warp_fractal_gain = 0.5;
+ // This needs manual conversion because Godots Inspector property API does not support discontiguous enum indices.
+ _FastNoiseLite::FractalType _convert_domain_warp_fractal_type_enum(DomainWarpFractalType p_domain_warp_fractal_type);
+
public:
FastNoiseLite();
~FastNoiseLite();
diff --git a/modules/openxr/editor/openxr_action_editor.cpp b/modules/openxr/editor/openxr_action_editor.cpp
index e2a4f67f16..41c6465f43 100644
--- a/modules/openxr/editor/openxr_action_editor.cpp
+++ b/modules/openxr/editor/openxr_action_editor.cpp
@@ -63,8 +63,7 @@ void OpenXRActionEditor::_on_action_localized_name_changed(const String p_new_te
}
void OpenXRActionEditor::_on_item_selected(int p_idx) {
- ERR_FAIL_COND(p_idx < 0);
- ERR_FAIL_COND(p_idx >= OpenXRAction::OPENXR_ACTION_MAX);
+ ERR_FAIL_INDEX(p_idx, OpenXRAction::OPENXR_ACTION_MAX);
action->set_action_type(OpenXRAction::ActionType(p_idx));
}
diff --git a/modules/openxr/editor/openxr_action_map_editor.cpp b/modules/openxr/editor/openxr_action_map_editor.cpp
index 6e9a2e1b61..87b7f50224 100644
--- a/modules/openxr/editor/openxr_action_map_editor.cpp
+++ b/modules/openxr/editor/openxr_action_map_editor.cpp
@@ -344,6 +344,7 @@ OpenXRActionMapEditor::OpenXRActionMapEditor() {
tabs = memnew(TabContainer);
tabs->set_h_size_flags(SIZE_EXPAND_FILL);
tabs->set_v_size_flags(SIZE_EXPAND_FILL);
+ tabs->set_theme_type_variation("TabContainerOdd");
tabs->connect("tab_changed", callable_mp(this, &OpenXRActionMapEditor::_on_tabs_tab_changed));
tabs->connect("tab_button_pressed", callable_mp(this, &OpenXRActionMapEditor::_on_tab_button_pressed));
add_child(tabs);
diff --git a/modules/openxr/extensions/openxr_extension_wrapper.h b/modules/openxr/extensions/openxr_extension_wrapper.h
index f3064041b8..0f7c0ba0bc 100644
--- a/modules/openxr/extensions/openxr_extension_wrapper.h
+++ b/modules/openxr/extensions/openxr_extension_wrapper.h
@@ -33,7 +33,7 @@
#include "core/error/error_macros.h"
#include "core/math/camera_matrix.h"
-#include "core/templates/map.h"
+#include "core/templates/hash_map.h"
#include "core/templates/rid.h"
#include "thirdparty/openxr/src/common/xr_linear.h"
@@ -49,10 +49,10 @@ protected:
// Store extension we require.
// If bool pointer is a nullptr this means this extension is mandatory and initialisation will fail if it is not available
// If bool pointer is set, value will be set to true or false depending on whether extension is available
- Map<const char *, bool *> request_extensions;
+ HashMap<String, bool *> request_extensions;
public:
- virtual Map<const char *, bool *> get_request_extensions() {
+ virtual HashMap<String, bool *> get_request_extensions() {
return request_extensions;
}
diff --git a/modules/openxr/extensions/openxr_vulkan_extension.cpp b/modules/openxr/extensions/openxr_vulkan_extension.cpp
index 1eb7635a82..2ddf3b8a7d 100644
--- a/modules/openxr/extensions/openxr_vulkan_extension.cpp
+++ b/modules/openxr/extensions/openxr_vulkan_extension.cpp
@@ -33,6 +33,7 @@
#include "../extensions/openxr_vulkan_extension.h"
#include "../openxr_api.h"
#include "../openxr_util.h"
+#include "servers/rendering/renderer_rd/effects/copy_effects.h"
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_globals.h"
@@ -450,11 +451,9 @@ bool OpenXRVulkanExtension::copy_render_target_to_image(RID p_from_render_target
ERR_FAIL_COND_V(fb.is_null(), false);
// Our vulkan extension can only be used in conjunction with our vulkan renderer.
- // We need access to the effects object in order to have access to our copy logic.
- // Breaking all the rules but there is no nice way to do this.
- EffectsRD *effects = RendererStorageRD::base_singleton->get_effects();
- ERR_FAIL_NULL_V(effects, false);
- effects->copy_to_fb_rect(source_image, fb, Rect2i(), false, false, false, false, depth_image, data->is_multiview);
+ RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
+ ERR_FAIL_NULL_V(copy_effects, false);
+ copy_effects->copy_to_fb_rect(source_image, fb, Rect2i(), false, false, false, false, depth_image, data->is_multiview);
return true;
}
diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp
index 2e9be48f01..f42af0492f 100644
--- a/modules/openxr/openxr_api.cpp
+++ b/modules/openxr/openxr_api.cpp
@@ -170,9 +170,9 @@ bool OpenXRAPI::load_supported_extensions() {
return true;
}
-bool OpenXRAPI::is_extension_supported(const char *p_extension) const {
+bool OpenXRAPI::is_extension_supported(const String &p_extension) const {
for (uint32_t i = 0; i < num_supported_extensions; i++) {
- if (strcmp(supported_extensions[i].extensionName, p_extension) == 0) {
+ if (supported_extensions[i].extensionName == p_extension) {
#ifdef DEBUG
print_line("OpenXR: requested extension", p_extension, "is supported");
#endif
@@ -204,9 +204,9 @@ bool OpenXRAPI::create_instance() {
// Create our OpenXR instance, this will query any registered extension wrappers for extensions we need to enable.
// Append the extensions requested by the registered extension wrappers.
- Map<const char *, bool *> requested_extensions;
+ HashMap<String, bool *> requested_extensions;
for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) {
- Map<const char *, bool *> wrapper_request_extensions = wrapper->get_request_extensions();
+ const HashMap<String, bool *> &wrapper_request_extensions = wrapper->get_request_extensions();
// requested_extensions.insert(wrapper_request_extensions.begin(), wrapper_request_extensions.end());
for (auto &requested_extension : wrapper_request_extensions) {
@@ -224,6 +224,7 @@ bool OpenXRAPI::create_instance() {
// Check which extensions are supported
enabled_extensions.clear();
+
for (auto &requested_extension : requested_extensions) {
if (!is_extension_supported(requested_extension.key)) {
if (requested_extension.value == nullptr) {
@@ -238,13 +239,18 @@ bool OpenXRAPI::create_instance() {
*requested_extension.value = true;
// and record that we want to enable it
- enabled_extensions.push_back(requested_extension.key);
+ enabled_extensions.push_back(requested_extension.key.ascii());
} else {
// record that we want to enable this
- enabled_extensions.push_back(requested_extension.key);
+ enabled_extensions.push_back(requested_extension.key.ascii());
}
}
+ Vector<const char *> extension_ptrs;
+ for (int i = 0; i < enabled_extensions.size(); i++) {
+ extension_ptrs.push_back(enabled_extensions[i].get_data());
+ }
+
// Get our project name
String project_name = GLOBAL_GET("application/config/name");
@@ -264,8 +270,8 @@ bool OpenXRAPI::create_instance() {
application_info, // applicationInfo
0, // enabledApiLayerCount, need to find out if we need support for this?
nullptr, // enabledApiLayerNames
- uint32_t(enabled_extensions.size()), // enabledExtensionCount
- enabled_extensions.ptr() // enabledExtensionNames
+ uint32_t(extension_ptrs.size()), // enabledExtensionCount
+ extension_ptrs.ptr() // enabledExtensionNames
};
copy_string_to_char_buffer(project_name, instance_create_info.applicationInfo.applicationName, XR_MAX_APPLICATION_NAME_SIZE);
@@ -1001,7 +1007,7 @@ bool OpenXRAPI::initialize(const String &p_rendering_driver) {
ERR_FAIL_V(false);
#endif
} else if (p_rendering_driver == "opengl3") {
-#ifdef OPENGL3_ENABLED
+#ifdef GLES3_ENABLED
// graphics_extension = memnew(OpenXROpenGLExtension(this));
// register_extension_wrapper(graphics_extension);
ERR_FAIL_V_MSG(false, "OpenXR: OpenGL is not supported at this time.");
diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h
index 702f6b9b1d..bd71f0e1c2 100644
--- a/modules/openxr/openxr_api.h
+++ b/modules/openxr/openxr_api.h
@@ -37,7 +37,7 @@
#include "core/math/vector2.h"
#include "core/os/memory.h"
#include "core/string/ustring.h"
-#include "core/templates/map.h"
+#include "core/templates/rb_map.h"
#include "core/templates/rid_owner.h"
#include "core/templates/vector.h"
#include "servers/xr/xr_pose.h"
@@ -73,7 +73,7 @@ private:
uint32_t num_supported_extensions = 0;
XrExtensionProperties *supported_extensions = nullptr;
Vector<OpenXRExtensionWrapper *> registered_extension_wrappers;
- Vector<const char *> enabled_extensions;
+ Vector<CharString> enabled_extensions;
bool ext_hp_mixed_reality_available = false;
bool ext_samsung_odyssey_available = false;
@@ -132,7 +132,7 @@ private:
bool load_layer_properties();
bool load_supported_extensions();
- bool is_extension_supported(const char *p_extension) const;
+ bool is_extension_supported(const String &p_extension) const;
// instance
bool create_instance();
diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp
index 41ce8c019e..ab06583932 100644
--- a/modules/openxr/openxr_interface.cpp
+++ b/modules/openxr/openxr_interface.cpp
@@ -113,7 +113,7 @@ void OpenXRInterface::_load_action_map() {
// process our action map
if (action_map.is_valid()) {
- Map<Ref<OpenXRAction>, Action *> xr_actions;
+ HashMap<Ref<OpenXRAction>, Action *> xr_actions;
Array action_sets = action_map->get_action_sets();
for (int i = 0; i < action_sets.size(); i++) {
diff --git a/modules/raycast/lightmap_raycaster.cpp b/modules/raycast/lightmap_raycaster.cpp
index ecc256bff9..9b35b5616e 100644
--- a/modules/raycast/lightmap_raycaster.cpp
+++ b/modules/raycast/lightmap_raycaster.cpp
@@ -152,17 +152,17 @@ void LightmapRaycasterEmbree::commit() {
rtcCommitScene(embree_scene);
}
-void LightmapRaycasterEmbree::set_mesh_filter(const Set<int> &p_mesh_ids) {
- for (Set<int>::Element *E = p_mesh_ids.front(); E; E = E->next()) {
- rtcDisableGeometry(rtcGetGeometry(embree_scene, E->get()));
+void LightmapRaycasterEmbree::set_mesh_filter(const HashSet<int> &p_mesh_ids) {
+ for (const int &E : p_mesh_ids) {
+ rtcDisableGeometry(rtcGetGeometry(embree_scene, E));
}
rtcCommitScene(embree_scene);
filter_meshes = p_mesh_ids;
}
void LightmapRaycasterEmbree::clear_mesh_filter() {
- for (Set<int>::Element *E = filter_meshes.front(); E; E = E->next()) {
- rtcEnableGeometry(rtcGetGeometry(embree_scene, E->get()));
+ for (const int &E : filter_meshes) {
+ rtcEnableGeometry(rtcGetGeometry(embree_scene, E));
}
rtcCommitScene(embree_scene);
filter_meshes.clear();
diff --git a/modules/raycast/lightmap_raycaster.h b/modules/raycast/lightmap_raycaster.h
index c420e617e5..4266b46ea8 100644
--- a/modules/raycast/lightmap_raycaster.h
+++ b/modules/raycast/lightmap_raycaster.h
@@ -52,8 +52,8 @@ private:
static void filter_function(const struct RTCFilterFunctionNArguments *p_args);
- Map<unsigned int, AlphaTextureData> alpha_textures;
- Set<int> filter_meshes;
+ HashMap<unsigned int, AlphaTextureData> alpha_textures;
+ HashSet<int> filter_meshes;
public:
virtual bool intersect(Ray &p_ray) override;
@@ -64,7 +64,7 @@ public:
virtual void set_mesh_alpha_texture(Ref<Image> p_alpha_texture, unsigned int p_id) override;
virtual void commit() override;
- virtual void set_mesh_filter(const Set<int> &p_mesh_ids) override;
+ virtual void set_mesh_filter(const HashSet<int> &p_mesh_ids) override;
virtual void clear_mesh_filter() override;
static LightmapRaycaster *create_embree_raycaster();
diff --git a/modules/raycast/raycast_occlusion_cull.cpp b/modules/raycast/raycast_occlusion_cull.cpp
index 1550f0ef8b..89e75f774e 100644
--- a/modules/raycast/raycast_occlusion_cull.cpp
+++ b/modules/raycast/raycast_occlusion_cull.cpp
@@ -223,9 +223,9 @@ void RaycastOcclusionCull::occluder_set_mesh(RID p_occluder, const PackedVector3
occluder->vertices = p_vertices;
occluder->indices = p_indices;
- for (Set<InstanceID>::Element *E = occluder->users.front(); E; E = E->next()) {
- RID scenario_rid = E->get().scenario;
- RID instance_rid = E->get().instance;
+ for (const InstanceID &E : occluder->users) {
+ RID scenario_rid = E.scenario;
+ RID instance_rid = E.instance;
ERR_CONTINUE(!scenarios.has(scenario_rid));
Scenario &scenario = scenarios[scenario_rid];
ERR_CONTINUE(!scenario.instances.has(instance_rid));
@@ -454,10 +454,9 @@ bool RaycastOcclusionCull::Scenario::update(ThreadWorkPool &p_thread_pool) {
next_scene = rtcNewScene(raycast_singleton->ebr_device);
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) {
continue;
@@ -573,9 +572,8 @@ void RaycastOcclusionCull::set_build_quality(RS::ViewportOcclusionCullingBuildQu
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() {
- 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) {
scenario.commit_thread->wait_to_finish();
memdelete(scenario.commit_thread);
diff --git a/modules/raycast/raycast_occlusion_cull.h b/modules/raycast/raycast_occlusion_cull.h
index 8453c5341d..4474031991 100644
--- a/modules/raycast/raycast_occlusion_cull.h
+++ b/modules/raycast/raycast_occlusion_cull.h
@@ -86,11 +86,13 @@ private:
RID scenario;
RID instance;
- bool operator<(const InstanceID &rhs) const {
- if (instance == rhs.instance) {
- return rhs.scenario < scenario;
- }
- return instance < rhs.instance;
+ static uint32_t hash(const InstanceID &p_ins) {
+ uint32_t h = hash_djb2_one_64(p_ins.scenario.get_id());
+ return hash_djb2_one_64(p_ins.instance.get_id(), h);
+ }
+ bool operator==(const InstanceID &rhs) const {
+ return instance == rhs.instance && rhs.scenario == scenario;
+ ;
}
InstanceID() {}
@@ -101,7 +103,7 @@ private:
struct Occluder {
PackedVector3Array vertices;
PackedInt32Array indices;
- Set<InstanceID> users;
+ HashSet<InstanceID, InstanceID> users;
};
struct OccluderInstance {
@@ -136,7 +138,7 @@ private:
int current_scene_idx = 0;
HashMap<RID, OccluderInstance> instances;
- Set<RID> dirty_instances; // To avoid duplicates
+ HashSet<RID> dirty_instances; // To avoid duplicates
LocalVector<RID> dirty_instances_array; // To iterate and split into threads
LocalVector<RID> removed_instances;
diff --git a/modules/raycast/static_raycaster.cpp b/modules/raycast/static_raycaster.cpp
index 9df6d5ff43..7659eea27f 100644
--- a/modules/raycast/static_raycaster.cpp
+++ b/modules/raycast/static_raycaster.cpp
@@ -94,17 +94,17 @@ void StaticRaycasterEmbree::commit() {
rtcCommitScene(embree_scene);
}
-void StaticRaycasterEmbree::set_mesh_filter(const Set<int> &p_mesh_ids) {
- for (Set<int>::Element *E = p_mesh_ids.front(); E; E = E->next()) {
- rtcDisableGeometry(rtcGetGeometry(embree_scene, E->get()));
+void StaticRaycasterEmbree::set_mesh_filter(const HashSet<int> &p_mesh_ids) {
+ for (const int &E : p_mesh_ids) {
+ rtcDisableGeometry(rtcGetGeometry(embree_scene, E));
}
rtcCommitScene(embree_scene);
filter_meshes = p_mesh_ids;
}
void StaticRaycasterEmbree::clear_mesh_filter() {
- for (Set<int>::Element *E = filter_meshes.front(); E; E = E->next()) {
- rtcEnableGeometry(rtcGetGeometry(embree_scene, E->get()));
+ for (const int &E : filter_meshes) {
+ rtcEnableGeometry(rtcGetGeometry(embree_scene, E));
}
rtcCommitScene(embree_scene);
filter_meshes.clear();
diff --git a/modules/raycast/static_raycaster.h b/modules/raycast/static_raycaster.h
index cce19ba60d..e2909f9b56 100644
--- a/modules/raycast/static_raycaster.h
+++ b/modules/raycast/static_raycaster.h
@@ -41,7 +41,7 @@ private:
static RTCDevice embree_device;
RTCScene embree_scene;
- Set<int> filter_meshes;
+ HashSet<int> filter_meshes;
public:
virtual bool intersect(Ray &p_ray) override;
@@ -50,7 +50,7 @@ public:
virtual void add_mesh(const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices, unsigned int p_id) override;
virtual void commit() override;
- virtual void set_mesh_filter(const Set<int> &p_mesh_ids) override;
+ virtual void set_mesh_filter(const HashSet<int> &p_mesh_ids) override;
virtual void clear_mesh_filter() override;
static StaticRaycaster *create_embree_raycaster();
diff --git a/modules/regex/regex.cpp b/modules/regex/regex.cpp
index ee1137b71f..bbe92139e0 100644
--- a/modules/regex/regex.cpp
+++ b/modules/regex/regex.cpp
@@ -52,9 +52,9 @@ int RegExMatch::_find(const Variant &p_name) const {
return i;
} else if (p_name.get_type() == Variant::STRING) {
- const Map<String, int>::Element *found = names.find((String)p_name);
+ HashMap<String, int>::ConstIterator found = names.find((String)p_name);
if (found) {
- return found->value();
+ return found->value;
}
}
@@ -75,8 +75,8 @@ int RegExMatch::get_group_count() const {
Dictionary RegExMatch::get_names() const {
Dictionary result;
- for (const Map<String, int>::Element *i = names.front(); i != nullptr; i = i->next()) {
- result[i->key()] = i->value();
+ for (const KeyValue<String, int> &E : names) {
+ result[E.key] = E.value;
}
return result;
diff --git a/modules/regex/regex.h b/modules/regex/regex.h
index e7221f4070..1455188670 100644
--- a/modules/regex/regex.h
+++ b/modules/regex/regex.h
@@ -33,7 +33,7 @@
#include "core/object/ref_counted.h"
#include "core/string/ustring.h"
-#include "core/templates/map.h"
+#include "core/templates/rb_map.h"
#include "core/templates/vector.h"
#include "core/variant/array.h"
#include "core/variant/dictionary.h"
@@ -48,7 +48,7 @@ class RegExMatch : public RefCounted {
String subject;
Vector<Range> data;
- Map<String, int> names;
+ HashMap<String, int> names;
friend class RegEx;
diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp
index 7fe2e589b1..dcb1f1d744 100644
--- a/modules/svg/image_loader_svg.cpp
+++ b/modules/svg/image_loader_svg.cpp
@@ -94,7 +94,7 @@ void ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, String p_strin
ERR_FAIL_MSG("ImageLoaderSVG can't create image.");
}
- res = sw_canvas->push(move(picture));
+ res = sw_canvas->push(std::move(picture));
if (res != tvg::Result::Success) {
memfree(buffer);
ERR_FAIL_MSG("ImageLoaderSVG can't create image.");
diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub
index 525d4d3efb..a46f17311a 100644
--- a/modules/text_server_adv/SCsub
+++ b/modules/text_server_adv/SCsub
@@ -442,7 +442,7 @@ if env["builtin_icu"]:
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
- icu_data_name = "icudt70l.dat"
+ icu_data_name = "icudt71l.dat"
if env_icu["tools"]:
env_icu.Depends("#thirdparty/icu4c/icudata.gen.h", "#thirdparty/icu4c/" + icu_data_name)
diff --git a/modules/text_server_adv/gdextension_build/SConstruct b/modules/text_server_adv/gdextension_build/SConstruct
index 1c38398c88..0e36ef6805 100644
--- a/modules/text_server_adv/gdextension_build/SConstruct
+++ b/modules/text_server_adv/gdextension_build/SConstruct
@@ -116,6 +116,7 @@ if env["freetype_enabled"]:
"src/psnames/psnames.c",
"src/raster/raster.c",
"src/sdf/sdf.c",
+ "src/svg/svg.c",
"src/smooth/smooth.c",
"src/truetype/truetype.c",
"src/type1/type1.c",
@@ -164,7 +165,14 @@ if env["freetype_enabled"]:
env_freetype.Append(CPPPATH=[thirdparty_freetype_dir + "/include", thirdparty_zlib_dir, thirdparty_png_dir])
env.Append(CPPPATH=[thirdparty_freetype_dir + "/include"])
- env_freetype.Append(CPPDEFINES=["FT2_BUILD_LIBRARY", "FT_CONFIG_OPTION_USE_PNG", ("PNG_ARM_NEON_OPT", 0)])
+ env_freetype.Append(
+ CPPDEFINES=[
+ "FT2_BUILD_LIBRARY",
+ "FT_CONFIG_OPTION_USE_PNG",
+ ("PNG_ARM_NEON_OPT", 0),
+ "FT_CONFIG_OPTION_SYSTEM_ZLIB",
+ ]
+ )
if env["target"] == "debug":
env_freetype.Append(CPPDEFINES=["ZLIB_DEBUG"])
@@ -564,7 +572,7 @@ thirdparty_icu_sources = [
]
thirdparty_icu_sources = [thirdparty_icu_dir + file for file in thirdparty_icu_sources]
-icu_data_name = "icudt70l.dat"
+icu_data_name = "icudt71l.dat"
if env["static_icu_data"]:
env_icu.Depends("../../../thirdparty/icu4c/icudata.gen.h", "../../../thirdparty/icu4c/" + icu_data_name)
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index ba249aff7a..598ccd1238 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -1691,6 +1691,8 @@ hb_font_t *TextServerAdvanced::_font_get_hb_handle(const RID &p_font_rid, int64_
}
RID TextServerAdvanced::create_font() {
+ _THREAD_SAFE_METHOD_
+
FontDataAdvanced *fd = memnew(FontDataAdvanced);
return font_owner.make_rid(fd);
@@ -2172,6 +2174,11 @@ void TextServerAdvanced::font_set_scale(const RID &p_font_rid, int64_t p_size, d
Vector2i size = _get_size(fd, p_size);
ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
+#ifdef MODULE_FREETYPE_ENABLED
+ if (fd->cache[size]->face) {
+ return; // Do not override scale for dynamic fonts, it's calculated automatically.
+ }
+#endif
fd->cache[size]->scale = p_scale;
}
@@ -2366,9 +2373,8 @@ Array TextServerAdvanced::font_get_glyph_list(const RID &p_font_rid, const Vecto
Array ret;
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;
}
@@ -2684,13 +2690,22 @@ Dictionary TextServerAdvanced::font_get_glyph_contours(const RID &p_font_rid, in
int error = FT_Load_Glyph(fd->cache[size]->face, index, FT_LOAD_NO_BITMAP | (fd->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0));
ERR_FAIL_COND_V(error, Dictionary());
- double h = fd->cache[size]->ascent;
+ if (fd->embolden != 0.f) {
+ FT_Pos strength = fd->embolden * p_size * 4; // 26.6 fractional units (1 / 64).
+ FT_Outline_Embolden(&fd->cache[size]->face->glyph->outline, strength);
+ }
+
+ if (fd->transform != Transform2D()) {
+ FT_Matrix mat = { FT_Fixed(fd->transform[0][0] * 65536), FT_Fixed(fd->transform[0][1] * 65536), FT_Fixed(fd->transform[1][0] * 65536), FT_Fixed(fd->transform[1][1] * 65536) }; // 16.16 fractional units (1 / 65536).
+ FT_Outline_Transform(&fd->cache[size]->face->glyph->outline, &mat);
+ }
+
double scale = (1.0 / 64.0) / fd->cache[size]->oversampling * fd->cache[size]->scale;
if (fd->msdf) {
scale = scale * (double)p_size / (double)fd->msdf_source_size;
}
for (short i = 0; i < fd->cache[size]->face->glyph->outline.n_points; i++) {
- points.push_back(Vector3(fd->cache[size]->face->glyph->outline.points[i].x * scale, h - fd->cache[size]->face->glyph->outline.points[i].y * scale, FT_CURVE_TAG(fd->cache[size]->face->glyph->outline.tags[i])));
+ points.push_back(Vector3(fd->cache[size]->face->glyph->outline.points[i].x * scale, -fd->cache[size]->face->glyph->outline.points[i].y * scale, FT_CURVE_TAG(fd->cache[size]->face->glyph->outline.tags[i])));
}
for (short i = 0; i < fd->cache[size]->face->glyph->outline.n_contours; i++) {
contours.push_back(fd->cache[size]->face->glyph->outline.contours[i]);
@@ -2765,7 +2780,7 @@ Vector2 TextServerAdvanced::font_get_kerning(const RID &p_font_rid, int64_t p_si
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2());
- const Map<Vector2i, Vector2> &kern = fd->cache[size]->kerning_map;
+ const HashMap<Vector2i, Vector2, VariantHasher, VariantComparator> &kern = fd->cache[size]->kerning_map;
if (kern.has(p_glyph_pair)) {
if (fd->msdf) {
@@ -2823,7 +2838,7 @@ bool TextServerAdvanced::font_has_char(const RID &p_font_rid, int64_t p_char) co
if (fd->cache.is_empty()) {
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, fd->msdf ? Vector2i(fd->msdf_source_size, 0) : Vector2i(16, 0)), false);
}
- FontDataForSizeAdvanced *at_size = fd->cache.front()->get();
+ FontDataForSizeAdvanced *at_size = fd->cache.begin()->value;
#ifdef MODULE_FREETYPE_ENABLED
if (at_size && at_size->face) {
@@ -2841,7 +2856,7 @@ String TextServerAdvanced::font_get_supported_chars(const RID &p_font_rid) const
if (fd->cache.is_empty()) {
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, fd->msdf ? Vector2i(fd->msdf_source_size, 0) : Vector2i(16, 0)), String());
}
- FontDataForSizeAdvanced *at_size = fd->cache.front()->get();
+ FontDataForSizeAdvanced *at_size = fd->cache.begin()->value;
String chars;
#ifdef MODULE_FREETYPE_ENABLED
@@ -2859,9 +2874,8 @@ String TextServerAdvanced::font_get_supported_chars(const RID &p_font_rid) const
#endif
if (at_size) {
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;
@@ -3347,6 +3361,7 @@ void TextServerAdvanced::full_copy(ShapedTextDataAdvanced *p_shaped) {
RID TextServerAdvanced::create_shaped_text(TextServer::Direction p_direction, TextServer::Orientation p_orientation) {
_THREAD_SAFE_METHOD_
+
ShapedTextDataAdvanced *sd = memnew(ShapedTextDataAdvanced);
sd->hb_buffer = hb_buffer_create();
sd->direction = p_direction;
@@ -3736,6 +3751,8 @@ void TextServerAdvanced::_realign(ShapedTextDataAdvanced *p_sd) const {
}
RID TextServerAdvanced::shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const {
+ _THREAD_SAFE_METHOD_
+
const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, RID());
@@ -4572,7 +4589,7 @@ bool TextServerAdvanced::shaped_text_update_justification_ops(const RID &p_shape
Glyph *sd_glyphs = sd->glyphs.ptrw();
int sd_size = sd->glyphs.size();
- if (sd->jstops.size() > 0) {
+ if (!sd->jstops.is_empty()) {
for (int i = 0; i < sd_size; i++) {
if (sd_glyphs[i].count > 0) {
char32_t c = sd->text[sd_glyphs[i].start - sd->start];
@@ -5572,7 +5589,7 @@ PackedInt32Array TextServerAdvanced::string_get_word_breaks(const String &p_stri
// Convert to UTF-16.
Char16String utf16 = p_string.utf16();
- Set<int> breaks;
+ HashSet<int> breaks;
UErrorCode err = U_ZERO_ERROR;
UBreakIterator *bi = ubrk_open(UBRK_LINE, p_language.ascii().get_data(), (const UChar *)utf16.ptr(), utf16.length(), &err);
if (U_FAILURE(err)) {
@@ -5623,8 +5640,10 @@ TextServerAdvanced::TextServerAdvanced() {
TextServerAdvanced::~TextServerAdvanced() {
_bmp_free_font_funcs();
+#ifdef MODULE_FREETYPE_ENABLED
if (ft_library != nullptr) {
FT_Done_FreeType(ft_library);
}
+#endif
u_cleanup();
}
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index 1b4293aa72..fe1d4bdcbf 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -67,7 +67,6 @@
#include <godot_cpp/classes/ref.hpp>
#include <godot_cpp/templates/hash_map.hpp>
-#include <godot_cpp/templates/map.hpp>
#include <godot_cpp/templates/rid_owner.hpp>
#include <godot_cpp/templates/set.hpp>
#include <godot_cpp/templates/thread_work_pool.hpp>
@@ -78,6 +77,7 @@ using namespace godot;
#else
// Headers for building as built-in module.
+#include "core/templates/hash_map.h"
#include "core/templates/rid_owner.h"
#include "core/templates/thread_work_pool.h"
#include "scene/resources/texture.h"
@@ -126,15 +126,15 @@ class TextServerAdvanced : public TextServerExtension {
_THREAD_SAFE_CLASS_
struct NumSystemData {
- Set<StringName> lang;
+ HashSet<StringName> lang;
String digits;
String percent_sign;
String exp;
};
Vector<NumSystemData> num_systems;
- Map<StringName, int32_t> feature_sets;
- Map<int32_t, StringName> feature_sets_inv;
+ HashMap<StringName, int32_t> feature_sets;
+ HashMap<int32_t, StringName> feature_sets_inv;
void _insert_num_systems_lang();
void _insert_feature_sets();
@@ -191,8 +191,7 @@ class TextServerAdvanced : public TextServerExtension {
Vector<FontTexture> textures;
HashMap<int32_t, FontGlyph> glyph_map;
- Map<Vector2i, Vector2> kerning_map;
-
+ HashMap<Vector2i, Vector2, VariantHasher, VariantComparator> kerning_map;
hb_font_t *hb_handle = nullptr;
#ifdef MODULE_FREETYPE_ENABLED
@@ -233,17 +232,17 @@ class TextServerAdvanced : public TextServerExtension {
String font_name;
String style_name;
- Map<Vector2i, FontDataForSizeAdvanced *> cache;
+ HashMap<Vector2i, FontDataForSizeAdvanced *, VariantHasher, VariantComparator> cache;
bool face_init = false;
- Set<uint32_t> supported_scripts;
+ HashSet<uint32_t> supported_scripts;
Dictionary supported_features;
Dictionary supported_varaitions;
Dictionary feature_overrides;
// Language/script support override.
- Map<String, bool> language_support_overrides;
- Map<String, bool> script_support_overrides;
+ HashMap<String, bool> language_support_overrides;
+ HashMap<String, bool> script_support_overrides;
PackedByteArray data;
const uint8_t *data_ptr;
@@ -334,7 +333,7 @@ class TextServerAdvanced : public TextServerExtension {
InlineAlignment inline_align = INLINE_ALIGNMENT_CENTER;
Rect2 rect;
};
- Map<Variant, EmbeddedObject> objects;
+ HashMap<Variant, EmbeddedObject, VariantHasher, VariantComparator> objects;
/* Shaped data */
TextServer::Direction para_direction = DIRECTION_LTR; // Detected text direction.
diff --git a/modules/text_server_fb/gdextension_build/SConstruct b/modules/text_server_fb/gdextension_build/SConstruct
index 1753bc8b86..6c9e10db18 100644
--- a/modules/text_server_fb/gdextension_build/SConstruct
+++ b/modules/text_server_fb/gdextension_build/SConstruct
@@ -111,6 +111,7 @@ if env["freetype_enabled"]:
"src/psnames/psnames.c",
"src/raster/raster.c",
"src/sdf/sdf.c",
+ "src/svg/svg.c",
"src/smooth/smooth.c",
"src/truetype/truetype.c",
"src/type1/type1.c",
@@ -159,7 +160,14 @@ if env["freetype_enabled"]:
env_freetype.Append(CPPPATH=[thirdparty_freetype_dir + "/include", thirdparty_zlib_dir, thirdparty_png_dir])
env.Append(CPPPATH=[thirdparty_freetype_dir + "/include"])
- env_freetype.Append(CPPDEFINES=["FT2_BUILD_LIBRARY", "FT_CONFIG_OPTION_USE_PNG", ("PNG_ARM_NEON_OPT", 0)])
+ env_freetype.Append(
+ CPPDEFINES=[
+ "FT2_BUILD_LIBRARY",
+ "FT_CONFIG_OPTION_USE_PNG",
+ ("PNG_ARM_NEON_OPT", 0),
+ "FT_CONFIG_OPTION_SYSTEM_ZLIB",
+ ]
+ )
if env["target"] == "debug":
env_freetype.Append(CPPDEFINES=["ZLIB_DEBUG"])
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index 8ae56aa64d..498b58175e 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -853,6 +853,8 @@ _FORCE_INLINE_ void TextServerFallback::_font_clear_cache(FontDataFallback *p_fo
}
RID TextServerFallback::create_font() {
+ _THREAD_SAFE_METHOD_
+
FontDataFallback *fd = memnew(FontDataFallback);
return font_owner.make_rid(fd);
@@ -1334,6 +1336,11 @@ void TextServerFallback::font_set_scale(const RID &p_font_rid, int64_t p_size, d
Vector2i size = _get_size(fd, p_size);
ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
+#ifdef MODULE_FREETYPE_ENABLED
+ if (fd->cache[size]->face) {
+ return; // Do not override scale for dynamic fonts, it's calculated automatically.
+ }
+#endif
fd->cache[size]->scale = p_scale;
}
@@ -1528,9 +1535,8 @@ Array TextServerFallback::font_get_glyph_list(const RID &p_font_rid, const Vecto
Array ret;
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;
}
@@ -1832,13 +1838,22 @@ Dictionary TextServerFallback::font_get_glyph_contours(const RID &p_font_rid, in
int error = FT_Load_Glyph(fd->cache[size]->face, FT_Get_Char_Index(fd->cache[size]->face, index), FT_LOAD_NO_BITMAP | (fd->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0));
ERR_FAIL_COND_V(error, Dictionary());
- double h = fd->cache[size]->ascent;
+ if (fd->embolden != 0.f) {
+ FT_Pos strength = fd->embolden * p_size * 4; // 26.6 fractional units (1 / 64).
+ FT_Outline_Embolden(&fd->cache[size]->face->glyph->outline, strength);
+ }
+
+ if (fd->transform != Transform2D()) {
+ FT_Matrix mat = { FT_Fixed(fd->transform[0][0] * 65536), FT_Fixed(fd->transform[0][1] * 65536), FT_Fixed(fd->transform[1][0] * 65536), FT_Fixed(fd->transform[1][1] * 65536) }; // 16.16 fractional units (1 / 65536).
+ FT_Outline_Transform(&fd->cache[size]->face->glyph->outline, &mat);
+ }
+
double scale = (1.0 / 64.0) / fd->cache[size]->oversampling * fd->cache[size]->scale;
if (fd->msdf) {
scale = scale * (double)p_size / (double)fd->msdf_source_size;
}
for (short i = 0; i < fd->cache[size]->face->glyph->outline.n_points; i++) {
- points.push_back(Vector3(fd->cache[size]->face->glyph->outline.points[i].x * scale, h - fd->cache[size]->face->glyph->outline.points[i].y * scale, FT_CURVE_TAG(fd->cache[size]->face->glyph->outline.tags[i])));
+ points.push_back(Vector3(fd->cache[size]->face->glyph->outline.points[i].x * scale, -fd->cache[size]->face->glyph->outline.points[i].y * scale, FT_CURVE_TAG(fd->cache[size]->face->glyph->outline.tags[i])));
}
for (short i = 0; i < fd->cache[size]->face->glyph->outline.n_contours; i++) {
contours.push_back(fd->cache[size]->face->glyph->outline.contours[i]);
@@ -1913,7 +1928,7 @@ Vector2 TextServerFallback::font_get_kerning(const RID &p_font_rid, int64_t p_si
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2());
- const Map<Vector2i, Vector2> &kern = fd->cache[size]->kerning_map;
+ const HashMap<Vector2i, Vector2, VariantHasher, VariantComparator> &kern = fd->cache[size]->kerning_map;
if (kern.has(p_glyph_pair)) {
if (fd->msdf) {
@@ -1953,7 +1968,7 @@ bool TextServerFallback::font_has_char(const RID &p_font_rid, int64_t p_char) co
if (fd->cache.is_empty()) {
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, fd->msdf ? Vector2i(fd->msdf_source_size, 0) : Vector2i(16, 0)), false);
}
- FontDataForSizeFallback *at_size = fd->cache.front()->get();
+ FontDataForSizeFallback *at_size = fd->cache.begin()->value;
#ifdef MODULE_FREETYPE_ENABLED
if (at_size && at_size->face) {
@@ -1971,7 +1986,7 @@ String TextServerFallback::font_get_supported_chars(const RID &p_font_rid) const
if (fd->cache.is_empty()) {
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, fd->msdf ? Vector2i(fd->msdf_source_size, 0) : Vector2i(16, 0)), String());
}
- FontDataForSizeFallback *at_size = fd->cache.front()->get();
+ FontDataForSizeFallback *at_size = fd->cache.begin()->value;
String chars;
#ifdef MODULE_FREETYPE_ENABLED
@@ -1989,9 +2004,8 @@ String TextServerFallback::font_get_supported_chars(const RID &p_font_rid) const
#endif
if (at_size) {
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;
@@ -2417,6 +2431,7 @@ void TextServerFallback::full_copy(ShapedTextDataFallback *p_shaped) {
RID TextServerFallback::create_shaped_text(TextServer::Direction p_direction, TextServer::Orientation p_orientation) {
_THREAD_SAFE_METHOD_
+
ShapedTextDataFallback *sd = memnew(ShapedTextDataFallback);
sd->direction = p_direction;
sd->orientation = p_orientation;
@@ -2795,6 +2810,8 @@ void TextServerFallback::_realign(ShapedTextDataFallback *p_sd) const {
}
RID TextServerFallback::shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const {
+ _THREAD_SAFE_METHOD_
+
const ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, RID());
diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h
index c837029623..0d2fc2628d 100644
--- a/modules/text_server_fb/text_server_fb.h
+++ b/modules/text_server_fb/text_server_fb.h
@@ -67,7 +67,6 @@
#include <godot_cpp/classes/ref.hpp>
#include <godot_cpp/templates/hash_map.hpp>
-#include <godot_cpp/templates/map.hpp>
#include <godot_cpp/templates/rid_owner.hpp>
#include <godot_cpp/templates/set.hpp>
#include <godot_cpp/templates/thread_work_pool.hpp>
@@ -80,6 +79,7 @@ using namespace godot;
#include "servers/text/text_server_extension.h"
+#include "core/templates/hash_map.h"
#include "core/templates/rid_owner.h"
#include "core/templates/thread_work_pool.h"
#include "scene/resources/texture.h"
@@ -106,8 +106,8 @@ class TextServerFallback : public TextServerExtension {
GDCLASS(TextServerFallback, TextServerExtension);
_THREAD_SAFE_CLASS_
- Map<StringName, int32_t> feature_sets;
- Map<int32_t, StringName> feature_sets_inv;
+ HashMap<StringName, int32_t> feature_sets;
+ HashMap<int32_t, StringName> feature_sets_inv;
void _insert_feature_sets();
_FORCE_INLINE_ void _insert_feature(const StringName &p_name, int32_t p_tag);
@@ -159,7 +159,7 @@ class TextServerFallback : public TextServerExtension {
Vector<FontTexture> textures;
HashMap<int32_t, FontGlyph> glyph_map;
- Map<Vector2i, Vector2> kerning_map;
+ HashMap<Vector2i, Vector2, VariantHasher, VariantComparator> kerning_map;
#ifdef MODULE_FREETYPE_ENABLED
FT_Face face = nullptr;
@@ -196,15 +196,15 @@ class TextServerFallback : public TextServerExtension {
String font_name;
String style_name;
- Map<Vector2i, FontDataForSizeFallback *> cache;
+ HashMap<Vector2i, FontDataForSizeFallback *, VariantHasher, VariantComparator> cache;
bool face_init = false;
Dictionary supported_varaitions;
Dictionary feature_overrides;
// Language/script support override.
- Map<String, bool> language_support_overrides;
- Map<String, bool> script_support_overrides;
+ HashMap<String, bool> language_support_overrides;
+ HashMap<String, bool> script_support_overrides;
PackedByteArray data;
const uint8_t *data_ptr;
@@ -294,7 +294,7 @@ class TextServerFallback : public TextServerExtension {
InlineAlignment inline_align = INLINE_ALIGNMENT_CENTER;
Rect2 rect;
};
- Map<Variant, EmbeddedObject> objects;
+ HashMap<Variant, EmbeddedObject, VariantHasher, VariantComparator> objects;
/* Shaped data */
TextServer::Direction para_direction = DIRECTION_LTR; // Detected text direction.
diff --git a/modules/visual_script/editor/visual_script_editor.cpp b/modules/visual_script/editor/visual_script_editor.cpp
index 3e6680d8d8..4741c7f887 100644
--- a/modules/visual_script/editor/visual_script_editor.cpp
+++ b/modules/visual_script/editor/visual_script_editor.cpp
@@ -647,6 +647,14 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
Control::get_theme_icon(SNAME("PackedColorArray"), SNAME("EditorIcons"))
};
+ // Visual script specific theme for MSDF font.
+ Ref<Theme> vstheme;
+ vstheme.instantiate();
+ Ref<Font> label_font = EditorNode::get_singleton()->get_editor_theme()->get_font("main_msdf", "EditorFonts");
+ vstheme->set_font("font", "Label", label_font);
+ vstheme->set_font("font", "LineEdit", label_font);
+ vstheme->set_font("font", "Button", label_font);
+
Ref<Texture2D> seq_port = Control::get_theme_icon(SNAME("VisualShaderPort"), SNAME("EditorIcons"));
List<int> node_ids;
script->get_node_list(&node_ids);
@@ -881,7 +889,49 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
EditorResourcePreview::get_singleton()->queue_edited_resource_preview(res, this, "_button_resource_previewed", arr);
} else if (pi.type == Variant::INT && pi.hint == PROPERTY_HINT_ENUM) {
- button->set_text(pi.hint_string.get_slice(",", value));
+ bool found = false;
+ const Vector<String> options = pi.hint_string.split(",");
+ int64_t current_val = 0;
+ for (const String &option : options) {
+ Vector<String> text_split = option.split(":");
+ if (text_split.size() != 1) {
+ current_val = text_split[1].to_int();
+ }
+ if (value.operator int() == current_val) {
+ button->set_text(text_split[0]);
+ found = true;
+ break;
+ }
+ current_val += 1;
+ }
+ if (!found) {
+ button->set_text(value);
+ }
+ } else if (pi.type == Variant::INT && pi.hint == PROPERTY_HINT_FLAGS) {
+ Vector<String> value_texts;
+ const Vector<String> options = pi.hint_string.split(",");
+ uint32_t v = value;
+ for (const String &option : options) {
+ uint32_t current_val;
+ Vector<String> text_split = option.split(":");
+ if (text_split.size() != -1) {
+ current_val = text_split[1].to_int();
+ } else {
+ current_val = 1 << i;
+ }
+ if ((v & current_val) == current_val) {
+ value_texts.push_back(text_split[0]);
+ }
+ }
+ if (value_texts.size() != 0) {
+ String value_text = value_texts[0];
+ for (const String &text : value_texts) {
+ value_text += " | " + text;
+ }
+ button->set_text(value_text);
+ } else {
+ button->set_text(value);
+ }
} else {
button->set_text(value);
}
@@ -960,9 +1010,8 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
slot_idx++;
}
-
graph->add_child(gnode);
-
+ gnode->set_theme(vstheme);
if (gnode->is_comment()) {
graph->move_child(gnode, 0);
}
@@ -973,6 +1022,9 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
float graph_minimap_opacity = EditorSettings::get_singleton()->get("editors/visual_editors/minimap_opacity");
graph->set_minimap_opacity(graph_minimap_opacity);
+ float graph_lines_curvature = EditorSettings::get_singleton()->get("editors/visual_editors/lines_curvature");
+ graph->set_connection_lines_curvature(graph_lines_curvature);
+
// Use default_func instead of default_func for now I think that should be good stop gap solution to ensure not breaking anything.
graph->call_deferred(SNAME("set_scroll_ofs"), script->get_scroll() * EDSCALE);
updating_graph = false;
@@ -1433,7 +1485,11 @@ void VisualScriptEditor::_deselect_input_names() {
}
}
-void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_button) {
+void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_button, MouseButton p_mouse_button) {
+ if (p_mouse_button != MouseButton::LEFT) {
+ return;
+ }
+
TreeItem *ti = Object::cast_to<TreeItem>(p_item);
TreeItem *root = members->get_root();
@@ -1603,12 +1659,12 @@ void VisualScriptEditor::_remove_output_port(int p_id, int p_port) {
List<VisualScript::DataConnection> data_connections;
script->get_data_connection_list(&data_connections);
- HashMap<int, Set<int>> conn_map;
+ HashMap<int, RBSet<int>> conn_map;
for (const VisualScript::DataConnection &E : data_connections) {
if (E.from_node == p_id && E.from_port == p_port) {
// Push into the connections map.
if (!conn_map.has(E.to_node)) {
- conn_map.set(E.to_node, Set<int>());
+ conn_map.insert(E.to_node, RBSet<int>());
}
conn_map[E.to_node].insert(E.to_port);
}
@@ -1617,11 +1673,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(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, RBSet<int>> &E : conn_map) {
+ for (const int &F : E.value) {
+ undo_redo->add_undo_method(script.ptr(), "data_connect", p_id, p_port, E.key, F);
}
}
@@ -1762,14 +1816,14 @@ void VisualScriptEditor::_on_nodes_paste() {
return;
}
- Map<int, int> remap;
+ HashMap<int, int> remap;
undo_redo->create_action(TTR("Paste VisualScript Nodes"));
int idc = script->get_available_id() + 1;
- Set<int> to_select;
+ RBSet<int> to_select;
- Set<Vector2> existing_positions;
+ RBSet<Vector2> existing_positions;
{
List<int> nodes;
@@ -1808,14 +1862,14 @@ void VisualScriptEditor::_on_nodes_paste() {
undo_redo->add_undo_method(script.ptr(), "remove_node", new_id);
}
- for (Set<VisualScript::SequenceConnection>::Element *E = clipboard->sequence_connections.front(); E; E = E->next()) {
- undo_redo->add_do_method(script.ptr(), "sequence_connect", remap[E->get().from_node], E->get().from_output, remap[E->get().to_node]);
- undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", remap[E->get().from_node], E->get().from_output, remap[E->get().to_node]);
+ for (const VisualScript::SequenceConnection &E : clipboard->sequence_connections) {
+ undo_redo->add_do_method(script.ptr(), "sequence_connect", remap[E.from_node], E.from_output, remap[E.to_node]);
+ undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", remap[E.from_node], E.from_output, remap[E.to_node]);
}
- for (Set<VisualScript::DataConnection>::Element *E = clipboard->data_connections.front(); E; E = E->next()) {
- undo_redo->add_do_method(script.ptr(), "data_connect", remap[E->get().from_node], E->get().from_port, remap[E->get().to_node], E->get().to_port);
- undo_redo->add_undo_method(script.ptr(), "data_disconnect", remap[E->get().from_node], E->get().from_port, remap[E->get().to_node], E->get().to_port);
+ for (const VisualScript::DataConnection &E : clipboard->data_connections) {
+ undo_redo->add_do_method(script.ptr(), "data_connect", remap[E.from_node], E.from_port, remap[E.to_node], E.to_port);
+ undo_redo->add_undo_method(script.ptr(), "data_disconnect", remap[E.from_node], E.from_port, remap[E.to_node], E.to_port);
}
undo_redo->add_do_method(this, "_update_graph");
@@ -1883,7 +1937,7 @@ void VisualScriptEditor::_on_nodes_delete() {
}
void VisualScriptEditor::_on_nodes_duplicate() {
- Set<int> to_duplicate;
+ RBSet<int> to_duplicate;
for (int i = 0; i < graph->get_child_count(); i++) {
GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i));
@@ -1902,20 +1956,20 @@ void VisualScriptEditor::_on_nodes_duplicate() {
undo_redo->create_action(TTR("Duplicate VisualScript Nodes"));
int idc = script->get_available_id() + 1;
- Set<int> to_select;
+ RBSet<int> to_select;
HashMap<int, int> remap;
- for (Set<int>::Element *F = to_duplicate.front(); F; F = F->next()) {
+ for (const int &F : to_duplicate) {
// Duplicate from the specific function but place it into the default func as it would lack the connections.
- Ref<VisualScriptNode> node = script->get_node(F->get());
+ Ref<VisualScriptNode> node = script->get_node(F);
Ref<VisualScriptNode> dupe = node->duplicate(true);
int new_id = idc++;
- remap.set(F->get(), new_id);
+ remap.insert(F, 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) + Vector2(20, 20));
undo_redo->add_undo_method(script.ptr(), "remove_node", new_id);
}
@@ -1961,15 +2015,6 @@ void VisualScriptEditor::_generic_search(Vector2 pos, bool node_centered) {
}
new_connect_node_select->select_from_visual_script(script, false); // do not reset text
-
- // Ensure that the dialog fits inside the graph.
- Size2 bounds = graph->get_global_position() + graph->get_size() - new_connect_node_select->get_size();
- pos.x = pos.x > bounds.x ? bounds.x : pos.x;
- pos.y = pos.y > bounds.y ? bounds.y : pos.y;
-
- if (pos != Vector2()) {
- new_connect_node_select->set_position(pos);
- }
}
void VisualScriptEditor::input(const Ref<InputEvent> &p_event) {
@@ -3177,7 +3222,7 @@ void VisualScriptEditor::_graph_connect_to_empty(const String &p_from, int p_fro
}
}
-VisualScriptNode::TypeGuess VisualScriptEditor::_guess_output_type(int p_port_action_node, int p_port_action_output, Set<int> &visited_nodes) {
+VisualScriptNode::TypeGuess VisualScriptEditor::_guess_output_type(int p_port_action_node, int p_port_action_output, RBSet<int> &visited_nodes) {
VisualScriptNode::TypeGuess tg;
tg.type = Variant::NIL;
@@ -3228,7 +3273,7 @@ VisualScriptNode::TypeGuess VisualScriptEditor::_guess_output_type(int p_port_ac
}
void VisualScriptEditor::_port_action_menu(int p_option) {
- Set<int> vn;
+ RBSet<int> vn;
switch (p_option) {
case CREATE_CALL_SET_GET: {
@@ -3340,7 +3385,7 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri
#endif
Vector2 pos = _get_pos_in_graph(port_action_pos);
- Set<int> vn;
+ RBSet<int> vn;
bool port_node_exists = true;
if (drop_position != Vector2()) {
@@ -4096,8 +4141,8 @@ void VisualScriptEditor::_menu_option(int p_what) {
} break;
case EDIT_CREATE_FUNCTION: {
// Create Function.
- Map<int, Ref<VisualScriptNode>> nodes;
- Set<int> selections;
+ HashMap<int, Ref<VisualScriptNode>> nodes;
+ RBSet<int> selections;
for (int i = 0; i < graph->get_child_count(); i++) {
GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i));
if (gn) {
@@ -4120,18 +4165,18 @@ void VisualScriptEditor::_menu_option(int p_what) {
return; // nothing to be done if there are no valid nodes selected
}
- Set<VisualScript::SequenceConnection> seqmove;
- Set<VisualScript::DataConnection> datamove;
+ RBSet<VisualScript::SequenceConnection> seqmove;
+ RBSet<VisualScript::DataConnection> datamove;
- Set<VisualScript::SequenceConnection> seqext;
- Set<VisualScript::DataConnection> dataext;
+ RBSet<VisualScript::SequenceConnection> seqext;
+ RBSet<VisualScript::DataConnection> dataext;
int start_node = -1;
- Set<int> end_nodes;
+ RBSet<int> end_nodes;
if (nodes.size() == 1) {
- Ref<VisualScriptNode> nd = script->get_node(nodes.front()->key());
+ Ref<VisualScriptNode> nd = script->get_node(nodes.begin()->key);
if (nd.is_valid() && nd->has_input_sequence_port()) {
- start_node = nodes.front()->key();
+ start_node = nodes.begin()->key;
} else {
EditorNode::get_singleton()->show_warning(TTR("Select at least one node with sequence port."));
return;
@@ -4169,8 +4214,8 @@ void VisualScriptEditor::_menu_option(int p_what) {
}
} else {
// Pick the node with input sequence.
- Set<int> nodes_from;
- Set<int> nodes_to;
+ RBSet<int> nodes_from;
+ RBSet<int> nodes_to;
for (const VisualScript::SequenceConnection &E : seqs) {
if (nodes.has(E.from_node) && nodes.has(E.to_node)) {
seqmove.insert(E);
@@ -4196,9 +4241,9 @@ void VisualScriptEditor::_menu_option(int p_what) {
// If we still don't have a start node then,
// run through the nodes and select the first tree node,
// i.e. node without any input sequence but output sequence.
- for (Set<int>::Element *E = nodes_from.front(); E; E = E->next()) {
- if (!nodes_to.has(E->get())) {
- start_node = E->get();
+ for (const int &E : nodes_from) {
+ if (!nodes_to.has(E)) {
+ start_node = E;
}
}
}
@@ -4267,13 +4312,13 @@ void VisualScriptEditor::_menu_option(int p_what) {
// Move the nodes.
// Handles reconnection of sequence connections on undo, start here in case of issues.
- for (Set<VisualScript::SequenceConnection>::Element *E = seqext.front(); E; E = E->next()) {
- undo_redo->add_do_method(script.ptr(), "sequence_disconnect", E->get().from_node, E->get().from_output, E->get().to_node);
- undo_redo->add_undo_method(script.ptr(), "sequence_connect", E->get().from_node, E->get().from_output, E->get().to_node);
+ for (const VisualScript::SequenceConnection &E : seqext) {
+ undo_redo->add_do_method(script.ptr(), "sequence_disconnect", E.from_node, E.from_output, E.to_node);
+ undo_redo->add_undo_method(script.ptr(), "sequence_connect", E.from_node, E.from_output, E.to_node);
}
- for (Set<VisualScript::DataConnection>::Element *E = dataext.front(); E; E = E->next()) {
- undo_redo->add_do_method(script.ptr(), "data_disconnect", E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
- undo_redo->add_undo_method(script.ptr(), "data_connect", E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
+ for (const VisualScript::DataConnection &E : dataext) {
+ undo_redo->add_do_method(script.ptr(), "data_disconnect", E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_undo_method(script.ptr(), "data_connect", E.from_node, E.from_port, E.to_node, E.to_port);
}
// I don't really think we need support for non sequenced functions at this moment.
@@ -4281,24 +4326,24 @@ void VisualScriptEditor::_menu_option(int p_what) {
// Could fail with the new changes, start here when searching for bugs in create function shortcut.
int m = 1;
- for (Set<int>::Element *G = end_nodes.front(); G; G = G->next()) {
+ for (const int &G : end_nodes) {
Ref<VisualScriptReturn> ret_node;
ret_node.instantiate();
int ret_id = fn_id + (m++);
selections.insert(ret_id);
- Vector2 posi = _get_available_pos(false, script->get_node_position(G->get()) + Vector2(80, -100));
+ Vector2 posi = _get_available_pos(false, script->get_node_position(G) + Vector2(80, -100));
undo_redo->add_do_method(script.ptr(), "add_node", ret_id, ret_node, posi);
undo_redo->add_undo_method(script.ptr(), "remove_node", ret_id);
- undo_redo->add_do_method(script.ptr(), "sequence_connect", G->get(), 0, ret_id);
+ undo_redo->add_do_method(script.ptr(), "sequence_connect", G, 0, ret_id);
// Add data outputs from each of the end_nodes.
- Ref<VisualScriptNode> vsn = script->get_node(G->get());
+ Ref<VisualScriptNode> vsn = script->get_node(G);
if (vsn.is_valid() && vsn->get_output_value_port_count() > 0) {
ret_node->set_enable_return_value(true);
// Use the zeroth data port cause that's the likely one that is planned to be used.
ret_node->set_return_type(vsn->get_output_value_port_info(0).type);
- undo_redo->add_do_method(script.ptr(), "data_connect", G->get(), 0, ret_id, 0);
+ undo_redo->add_do_method(script.ptr(), "data_connect", G, 0, ret_id, 0);
}
}
@@ -4333,7 +4378,7 @@ void VisualScriptEditor::_menu_option(int p_what) {
// This is likely going to be very slow and I am not sure if I should keep it,
// but I hope that it will not be a problem considering that we won't be creating functions so frequently,
// and cyclic connections would be a problem but hopefully we won't let them get to this point.
-void VisualScriptEditor::_get_ends(int p_node, const List<VisualScript::SequenceConnection> &p_seqs, const Set<int> &p_selected, Set<int> &r_end_nodes) {
+void VisualScriptEditor::_get_ends(int p_node, const List<VisualScript::SequenceConnection> &p_seqs, const RBSet<int> &p_selected, RBSet<int> &r_end_nodes) {
for (const VisualScript::SequenceConnection &E : p_seqs) {
int from = E.from_node;
int to = E.to_node;
@@ -4347,7 +4392,11 @@ void VisualScriptEditor::_get_ends(int p_node, const List<VisualScript::Sequence
}
}
-void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos) {
+void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos, MouseButton p_button) {
+ if (p_button != MouseButton::RIGHT) {
+ return;
+ }
+
TreeItem *ti = members->get_selected();
ERR_FAIL_COND(!ti);
@@ -4548,11 +4597,11 @@ VisualScriptEditor::VisualScriptEditor() {
members_section->add_margin_child(TTR("Members:"), members, true);
members->set_custom_minimum_size(Size2(0, 50 * EDSCALE));
members->set_hide_root(true);
- members->connect("button_pressed", callable_mp(this, &VisualScriptEditor::_member_button));
+ members->connect("button_clicked", callable_mp(this, &VisualScriptEditor::_member_button));
members->connect("item_edited", callable_mp(this, &VisualScriptEditor::_member_edited));
members->connect("cell_selected", callable_mp(this, &VisualScriptEditor::_member_selected), varray(), CONNECT_DEFERRED);
members->connect("gui_input", callable_mp(this, &VisualScriptEditor::_members_gui_input));
- members->connect("item_rmb_selected", callable_mp(this, &VisualScriptEditor::_member_rmb_selected));
+ members->connect("item_mouse_selected", callable_mp(this, &VisualScriptEditor::_member_rmb_selected));
members->set_allow_rmb_select(true);
members->set_allow_reselect(true);
members->set_hide_folding(true);
@@ -4577,6 +4626,7 @@ VisualScriptEditor::VisualScriptEditor() {
add_child(graph);
graph->set_v_size_flags(Control::SIZE_EXPAND_FILL);
graph->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
+ graph->set_show_zoom_label(true);
graph->connect("node_selected", callable_mp(this, &VisualScriptEditor::_node_selected));
graph->connect("begin_node_move", callable_mp(this, &VisualScriptEditor::_begin_node_move));
graph->connect("end_node_move", callable_mp(this, &VisualScriptEditor::_end_node_move));
@@ -4588,6 +4638,8 @@ VisualScriptEditor::VisualScriptEditor() {
graph->set_drag_forwarding(this);
float graph_minimap_opacity = EditorSettings::get_singleton()->get("editors/visual_editors/minimap_opacity");
graph->set_minimap_opacity(graph_minimap_opacity);
+ float graph_lines_curvature = EditorSettings::get_singleton()->get("editors/visual_editors/lines_curvature");
+ graph->set_connection_lines_curvature(graph_lines_curvature);
graph->hide();
graph->connect("scroll_offset_changed", callable_mp(this, &VisualScriptEditor::_graph_ofs_changed));
@@ -4839,7 +4891,7 @@ Ref<VisualScriptNode> VisualScriptCustomNodes::create_node_custom(const String &
}
VisualScriptCustomNodes *VisualScriptCustomNodes::singleton = nullptr;
-Map<String, Ref<RefCounted>> VisualScriptCustomNodes::custom_nodes;
+HashMap<String, Ref<RefCounted>> VisualScriptCustomNodes::custom_nodes;
VisualScriptCustomNodes::VisualScriptCustomNodes() {
singleton = this;
diff --git a/modules/visual_script/editor/visual_script_editor.h b/modules/visual_script/editor/visual_script_editor.h
index e63539ac5b..fd59d22cbe 100644
--- a/modules/visual_script/editor/visual_script_editor.h
+++ b/modules/visual_script/editor/visual_script_editor.h
@@ -142,9 +142,9 @@ class VisualScriptEditor : public ScriptEditorBase {
Vector<Pair<Variant::Type, String>> args;
};
- Map<StringName, Color> node_colors;
+ HashMap<StringName, Color> node_colors;
HashMap<StringName, Ref<StyleBox>> node_styles;
- Map<StringName, Variant::Type> base_type_map;
+ HashMap<StringName, Variant::Type> base_type_map;
void _update_graph_connections();
void _update_graph(int p_only_id = -1);
@@ -159,11 +159,11 @@ class VisualScriptEditor : public ScriptEditorBase {
String _validate_name(const String &p_name) const;
struct Clipboard {
- Map<int, Ref<VisualScriptNode>> nodes;
- Map<int, Vector2> nodes_positions;
+ HashMap<int, Ref<VisualScriptNode>> nodes;
+ HashMap<int, Vector2> nodes_positions;
- Set<VisualScript::SequenceConnection> sequence_connections;
- Set<VisualScript::DataConnection> data_connections;
+ RBSet<VisualScript::SequenceConnection> sequence_connections;
+ RBSet<VisualScript::DataConnection> data_connections;
};
static Clipboard *clipboard;
@@ -213,7 +213,7 @@ class VisualScriptEditor : public ScriptEditorBase {
void _end_node_move();
void _move_node(int p_id, const Vector2 &p_to);
- void _get_ends(int p_node, const List<VisualScript::SequenceConnection> &p_seqs, const Set<int> &p_selected, Set<int> &r_end_nodes);
+ void _get_ends(int p_node, const List<VisualScript::SequenceConnection> &p_seqs, const RBSet<int> &p_selected, RBSet<int> &r_end_nodes);
void _node_moved(Vector2 p_from, Vector2 p_to, int p_id);
void _remove_node(int p_id);
@@ -226,7 +226,7 @@ class VisualScriptEditor : public ScriptEditorBase {
void _update_available_nodes();
- void _member_button(Object *p_item, int p_column, int p_button);
+ void _member_button(Object *p_item, int p_column, int p_button, MouseButton p_mouse_button);
void _expression_text_changed(const String &p_text, int p_id);
void _add_input_port(int p_id);
@@ -287,9 +287,9 @@ class VisualScriptEditor : public ScriptEditorBase {
void _draw_color_over_button(Object *obj, Color p_color);
void _button_resource_previewed(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, Variant p_ud);
- VisualScriptNode::TypeGuess _guess_output_type(int p_port_action_node, int p_port_action_output, Set<int> &p_visited_nodes);
+ VisualScriptNode::TypeGuess _guess_output_type(int p_port_action_node, int p_port_action_output, RBSet<int> &p_visited_nodes);
- void _member_rmb_selected(const Vector2 &p_pos);
+ void _member_rmb_selected(const Vector2 &p_pos, MouseButton p_button);
void _member_option(int p_option);
void _toggle_scripts_pressed();
@@ -359,7 +359,7 @@ protected:
static void _bind_methods();
static VisualScriptCustomNodes *singleton;
- static Map<String, Ref<RefCounted>> custom_nodes;
+ static HashMap<String, Ref<RefCounted>> custom_nodes;
static Ref<VisualScriptNode> create_node_custom(const String &p_name);
public:
diff --git a/modules/visual_script/editor/visual_script_property_selector.cpp b/modules/visual_script/editor/visual_script_property_selector.cpp
index c8549ddb53..ae30655301 100644
--- a/modules/visual_script/editor/visual_script_property_selector.cpp
+++ b/modules/visual_script/editor/visual_script_property_selector.cpp
@@ -182,7 +182,7 @@ void VisualScriptPropertySelector::select_method_from_base_type(const String &p_
void VisualScriptPropertySelector::select_from_base_type(const String &p_base, const String &p_base_script, bool p_virtuals_only, const bool p_connecting, bool clear_text) {
set_title(TTR("Select from base type"));
base_type = p_base;
- base_script = p_base_script.lstrip("res://").quote(); // filepath to EditorHelp::get_doc_data().name
+ base_script = p_base_script.trim_prefix("res://").quote(); // filepath to EditorHelp::get_doc_data().name
type = Variant::NIL;
connecting = p_connecting;
@@ -217,7 +217,7 @@ void VisualScriptPropertySelector::select_from_script(const Ref<Script> &p_scrip
ERR_FAIL_COND(p_script.is_null());
base_type = p_script->get_instance_base_type();
- base_script = p_script->get_path().lstrip("res://").quote(); // filepath to EditorHelp::get_doc_data().name
+ base_script = p_script->get_path().trim_prefix("res://").quote(); // filepath to EditorHelp::get_doc_data().name
type = Variant::NIL;
script = p_script->get_instance_id();
connecting = p_connecting;
@@ -312,7 +312,7 @@ void VisualScriptPropertySelector::select_from_instance(Object *p_instance, cons
if (p_script == nullptr) {
base_script = "";
} else {
- base_script = p_script->get_path().lstrip("res://").quote(); // filepath to EditorHelp::get_doc_data().name
+ base_script = p_script->get_path().trim_prefix("res://").quote(); // filepath to EditorHelp::get_doc_data().name
}
type = Variant::NIL;
@@ -346,7 +346,7 @@ void VisualScriptPropertySelector::select_from_visual_script(const Ref<Script> &
if (p_script == nullptr) {
base_script = "";
} else {
- base_script = p_script->get_path().lstrip("res://").quote(); // filepath to EditorHelp::get_doc_data().name
+ base_script = p_script->get_path().trim_prefix("res://").quote(); // filepath to EditorHelp::get_doc_data().name
}
type = Variant::NIL;
connecting = false;
@@ -521,8 +521,17 @@ VisualScriptPropertySelector::VisualScriptPropertySelector() {
results_tree->connect("item_selected", callable_mp(this, &VisualScriptPropertySelector::_item_selected));
vbox->add_child(results_tree);
+ ScrollContainer *scroller = memnew(ScrollContainer);
+ scroller->set_horizontal_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
+ scroller->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ scroller->set_custom_minimum_size(Size2(600, 400) * EDSCALE);
+ vbox->add_child(scroller);
+
help_bit = memnew(EditorHelpBit);
- vbox->add_child(help_bit);
+ help_bit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ help_bit->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ scroller->add_child(help_bit);
+
help_bit->connect("request_hide", callable_mp(this, &VisualScriptPropertySelector::_hide_requested));
get_ok_button()->set_text(TTR("Open"));
get_ok_button()->set_disabled(true);
@@ -726,7 +735,7 @@ bool VisualScriptPropertySelector::SearchRunner::_phase_match_classes_init() {
combined_docs.insert(class_doc.name, class_doc);
}
}
- iterator_doc = combined_docs.front();
+ iterator_doc = combined_docs.begin();
return true;
}
@@ -787,7 +796,7 @@ bool VisualScriptPropertySelector::SearchRunner::_phase_node_classes_build() {
}
bool VisualScriptPropertySelector::SearchRunner::_phase_match_classes() {
- DocData::ClassDoc &class_doc = iterator_doc->value();
+ DocData::ClassDoc &class_doc = iterator_doc->value;
if (
(!_is_class_disabled_by_feature_profile(class_doc.name) && !_is_class_disabled_by_scope(class_doc.name)) ||
_match_visual_script(class_doc)) {
@@ -909,13 +918,13 @@ bool VisualScriptPropertySelector::SearchRunner::_phase_match_classes() {
}
}
- iterator_doc = iterator_doc->next();
+ ++iterator_doc;
return !iterator_doc;
}
bool VisualScriptPropertySelector::SearchRunner::_phase_class_items_init() {
results_tree->clear();
- iterator_match = matches.front();
+ iterator_match = matches.begin();
root_item = results_tree->create_item();
class_items.clear();
@@ -928,7 +937,7 @@ bool VisualScriptPropertySelector::SearchRunner::_phase_class_items() {
return true;
}
- ClassMatch &match = iterator_match->value();
+ ClassMatch &match = iterator_match->value;
if (search_flags & SEARCH_SHOW_HIERARCHY) {
if (match.required()) {
@@ -940,12 +949,12 @@ bool VisualScriptPropertySelector::SearchRunner::_phase_class_items() {
}
}
- iterator_match = iterator_match->next();
+ ++iterator_match;
return !iterator_match;
}
bool VisualScriptPropertySelector::SearchRunner::_phase_member_items_init() {
- iterator_match = matches.front();
+ iterator_match = matches.begin();
return true;
}
@@ -955,7 +964,7 @@ bool VisualScriptPropertySelector::SearchRunner::_phase_member_items() {
return true;
}
- ClassMatch &match = iterator_match->value();
+ ClassMatch &match = iterator_match->value;
TreeItem *parent = (search_flags & SEARCH_SHOW_HIERARCHY) ? class_items[match.doc->name] : root_item;
bool constructor_created = false;
@@ -986,7 +995,7 @@ bool VisualScriptPropertySelector::SearchRunner::_phase_member_items() {
_create_theme_property_item(parent, match.doc, match.theme_properties[i]);
}
- iterator_match = iterator_match->next();
+ ++iterator_match;
return !iterator_match;
}
diff --git a/modules/visual_script/editor/visual_script_property_selector.h b/modules/visual_script/editor/visual_script_property_selector.h
index 90a6265ab7..91d81bba47 100644
--- a/modules/visual_script/editor/visual_script_property_selector.h
+++ b/modules/visual_script/editor/visual_script_property_selector.h
@@ -179,15 +179,15 @@ class VisualScriptPropertySelector::SearchRunner : public RefCounted {
Ref<Texture2D> empty_icon;
Color disabled_color;
- Map<String, DocData::ClassDoc>::Element *iterator_doc = nullptr;
- Map<String, ClassMatch> matches;
- Map<String, ClassMatch>::Element *iterator_match = nullptr;
+ HashMap<String, DocData::ClassDoc>::Iterator iterator_doc;
+ HashMap<String, ClassMatch> matches;
+ HashMap<String, ClassMatch>::Iterator iterator_match;
TreeItem *root_item = nullptr;
- Map<String, TreeItem *> class_items;
+ HashMap<String, TreeItem *> class_items;
TreeItem *matched_item = nullptr;
float match_highest_score = 0;
- Map<String, DocData::ClassDoc> combined_docs;
+ HashMap<String, DocData::ClassDoc> combined_docs;
List<String> vs_nodes;
bool _is_class_disabled_by_feature_profile(const StringName &p_class);
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index 7028fead9a..24bb22960e 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/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 {
- 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 {
@@ -229,12 +230,12 @@ void VisualScript::_node_ports_changed(int p_id) {
{
List<SequenceConnection> to_remove;
- for (Set<SequenceConnection>::Element *E = sequence_connections.front(); E; E = E->next()) {
- if (E->get().from_node == p_id && E->get().from_output >= vsn->get_output_sequence_port_count()) {
- to_remove.push_back(E->get());
+ for (const SequenceConnection &E : sequence_connections) {
+ if (E.from_node == p_id && E.from_output >= vsn->get_output_sequence_port_count()) {
+ to_remove.push_back(E);
}
- if (E->get().to_node == p_id && !vsn->has_input_sequence_port()) {
- to_remove.push_back(E->get());
+ if (E.to_node == p_id && !vsn->has_input_sequence_port()) {
+ to_remove.push_back(E);
}
}
@@ -247,12 +248,12 @@ void VisualScript::_node_ports_changed(int p_id) {
{
List<DataConnection> to_remove;
- for (Set<DataConnection>::Element *E = data_connections.front(); E; E = E->next()) {
- if (E->get().from_node == p_id && E->get().from_port >= vsn->get_output_value_port_count()) {
- to_remove.push_back(E->get());
+ for (const DataConnection &E : data_connections) {
+ if (E.from_node == p_id && E.from_port >= vsn->get_output_value_port_count()) {
+ to_remove.push_back(E);
}
- if (E->get().to_node == p_id && E->get().to_port >= vsn->get_input_value_port_count()) {
- to_remove.push_back(E->get());
+ if (E.to_node == p_id && E.to_port >= vsn->get_input_value_port_count()) {
+ to_remove.push_back(E);
}
}
@@ -291,9 +292,9 @@ void VisualScript::remove_node(int p_id) {
{
List<SequenceConnection> to_remove;
- for (Set<SequenceConnection>::Element *E = sequence_connections.front(); E; E = E->next()) {
- if (E->get().from_node == p_id || E->get().to_node == p_id) {
- to_remove.push_back(E->get());
+ for (const SequenceConnection &E : sequence_connections) {
+ if (E.from_node == p_id || E.to_node == p_id) {
+ to_remove.push_back(E);
}
}
@@ -306,9 +307,9 @@ void VisualScript::remove_node(int p_id) {
{
List<DataConnection> to_remove;
- for (Set<DataConnection>::Element *E = data_connections.front(); E; E = E->next()) {
- if (E->get().from_node == p_id || E->get().to_node == p_id) {
- to_remove.push_back(E->get());
+ for (const DataConnection &E : data_connections) {
+ if (E.from_node == p_id || E.to_node == p_id) {
+ to_remove.push_back(E);
}
}
@@ -346,7 +347,9 @@ Point2 VisualScript::get_node_position(int p_id) 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) {
@@ -381,8 +384,8 @@ bool VisualScript::has_sequence_connection(int p_from_node, int p_from_output, i
}
void VisualScript::get_sequence_connection_list(List<SequenceConnection> *r_connection) const {
- for (const Set<SequenceConnection>::Element *E = sequence_connections.front(); E; E = E->next()) {
- r_connection->push_back(E->get());
+ for (const SequenceConnection &E : sequence_connections) {
+ r_connection->push_back(E);
}
}
@@ -423,8 +426,8 @@ bool VisualScript::has_data_connection(int p_from_node, int p_from_port, int p_t
}
bool VisualScript::is_input_value_port_connected(int p_node, int p_port) const {
- for (const Set<DataConnection>::Element *E = data_connections.front(); E; E = E->next()) {
- if (E->get().to_node == p_node && E->get().to_port == p_port) {
+ for (const DataConnection &E : data_connections) {
+ if (E.to_node == p_node && E.to_port == p_port) {
return true;
}
}
@@ -432,10 +435,10 @@ bool VisualScript::is_input_value_port_connected(int p_node, int p_port) const {
}
bool VisualScript::get_input_value_port_connection_source(int p_node, int p_port, int *r_node, int *r_port) const {
- for (const Set<DataConnection>::Element *E = data_connections.front(); E; E = E->next()) {
- if (E->get().to_node == p_node && E->get().to_port == p_port) {
- *r_node = E->get().from_node;
- *r_port = E->get().from_port;
+ for (const DataConnection &E : data_connections) {
+ if (E.to_node == p_node && E.to_port == p_port) {
+ *r_node = E.from_node;
+ *r_port = E.from_port;
return true;
}
}
@@ -443,8 +446,8 @@ bool VisualScript::get_input_value_port_connection_source(int p_node, int p_port
}
void VisualScript::get_data_connection_list(List<DataConnection> *r_connection) const {
- for (const Set<DataConnection>::Element *E = data_connections.front(); E; E = E->next()) {
- r_connection->push_back(E->get());
+ for (const DataConnection &E : data_connections) {
+ r_connection->push_back(E);
}
}
@@ -563,8 +566,9 @@ Dictionary VisualScript::_get_variable_info(const StringName &p_name) 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) {
@@ -713,12 +717,11 @@ int VisualScript::get_available_id() const {
// This is infinitely increasing,
// 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.
- List<int> nds;
- nodes.get_key_list(&nds);
+
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);
@@ -748,24 +751,21 @@ void VisualScript::_update_placeholders() {
return; // No bother if no placeholders.
}
List<PropertyInfo> pinfo;
- Map<StringName, Variant> values;
-
- List<StringName> keys;
- variables.get_key_list(&keys);
+ HashMap<StringName, Variant> values;
- for (const StringName &E : keys) {
- if (!variables[E]._export) {
+ for (const KeyValue<StringName, Variable> &E : variables) {
+ if (!variables[E.key]._export) {
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);
- 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()) {
- E->get()->update(pinfo, values);
+ for (PlaceHolderScriptInstance *E : placeholders) {
+ E->update(pinfo, values);
}
}
@@ -779,20 +779,17 @@ ScriptInstance *VisualScript::instance_create(Object *p_this) {
placeholders.insert(sins);
List<PropertyInfo> pinfo;
- Map<StringName, Variant> values;
+ HashMap<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;
}
- PropertyInfo p = variables[E].info;
- p.name = String(E);
+ PropertyInfo p = variables[E.key].info;
+ p.name = String(E.key);
pinfo.push_back(p);
- values[p.name] = variables[E].default_value;
+ values[p.name] = variables[E.key].default_value;
}
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 {
- List<StringName> funcs;
- functions.get_key_list(&funcs);
-
- for (const StringName &E : funcs) {
+ for (const KeyValue<StringName, Function> &E : functions) {
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()) {
for (int i = 0; i < func->get_argument_count(); i++) {
PropertyInfo arg;
@@ -945,10 +939,8 @@ int VisualScript::get_member_line(const StringName &p_member) const {
#ifdef TOOLS_ENABLED
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;
}
}
@@ -1017,15 +1009,13 @@ void VisualScript::_set_data(const Dictionary &p_data) {
// Takes all the rpc methods.
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->get_rpc_mode() != Multiplayer::RPC_MODE_DISABLED) {
Multiplayer::RPCConfig nd;
- nd.name = E;
+ nd.name = E.key;
nd.rpc_mode = vsf->get_rpc_mode();
nd.transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE; // TODO
if (rpc_functions.find(nd) == -1) {
@@ -1045,13 +1035,11 @@ Dictionary VisualScript::_get_data() const {
d["base_type"] = base_type;
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);
}
d["variables"] = vars;
@@ -1073,40 +1061,36 @@ Dictionary VisualScript::_get_data() const {
d["signals"] = sigs;
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;
- 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);
}
d["functions"] = funcs;
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;
Array seqconns;
- for (const Set<SequenceConnection>::Element *F = sequence_connections.front(); F; F = F->next()) {
- seqconns.push_back(F->get().from_node);
- seqconns.push_back(F->get().from_output);
- seqconns.push_back(F->get().to_node);
+ for (const SequenceConnection &F : sequence_connections) {
+ seqconns.push_back(F.from_node);
+ seqconns.push_back(F.from_output);
+ seqconns.push_back(F.to_node);
}
d["sequence_connections"] = seqconns;
Array dataconns;
- for (const Set<DataConnection>::Element *F = data_connections.front(); F; F = F->next()) {
- dataconns.push_back(F->get().from_node);
- dataconns.push_back(F->get().from_port);
- dataconns.push_back(F->get().to_node);
- dataconns.push_back(F->get().to_port);
+ for (const DataConnection &F : data_connections) {
+ dataconns.push_back(F.from_node);
+ dataconns.push_back(F.from_port);
+ dataconns.push_back(F.to_node);
+ dataconns.push_back(F.to_port);
}
d["data_connections"] = dataconns;
@@ -1184,10 +1168,10 @@ bool VisualScript::inherits_script(const Ref<Script> &p_script) const {
return this == p_script.ptr(); // There is no inheritance in visual scripts, so this is enough.
}
-Set<int> VisualScript::get_output_sequence_ports_connected(int from_node) {
+RBSet<int> VisualScript::get_output_sequence_ports_connected(int from_node) {
List<VisualScript::SequenceConnection> *sc = memnew(List<VisualScript::SequenceConnection>);
get_sequence_connection_list(sc);
- Set<int> connected;
+ RBSet<int> connected;
for (List<VisualScript::SequenceConnection>::Element *E = sc->front(); E; E = E->next()) {
if (E->get().from_node == from_node) {
connected.insert(E->get().from_output);
@@ -1199,45 +1183,41 @@ Set<int> VisualScript::get_output_sequence_ports_connected(int from_node) {
VisualScript::~VisualScript() {
// 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);
}
}
////////////////////////////////////////////
bool VisualScriptInstance::set(const StringName &p_name, const Variant &p_value) {
- Map<StringName, Variant>::Element *E = variables.find(p_name);
+ HashMap<StringName, Variant>::Iterator E = variables.find(p_name);
if (!E) {
return false;
}
- E->get() = p_value;
+ E->value = p_value;
return true;
}
bool VisualScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
- const Map<StringName, Variant>::Element *E = variables.find(p_name);
+ HashMap<StringName, Variant>::ConstIterator E = variables.find(p_name);
if (!E) {
return false;
}
- r_ret = E->get();
+ r_ret = E->value;
return true;
}
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;
}
- 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_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 {
- 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;
- 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()) {
for (int i = 0; i < vsf->get_argument_count(); i++) {
PropertyInfo arg;
@@ -1337,9 +1315,9 @@ void VisualScriptInstance::_dependency_step(VisualScriptNodeInstance *node, int
}
Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p_stack, int p_stack_size, VisualScriptNodeInstance *p_node, int p_flow_stack_pos, int p_pass, bool p_resuming_yield, Callable::CallError &r_error) {
- Map<StringName, Function>::Element *F = functions.find(p_method);
+ HashMap<StringName, Function>::Iterator F = functions.find(p_method);
ERR_FAIL_COND_V(!F, Variant());
- Function *f = &F->get();
+ Function *f = &F->value;
// This call goes separate, so it can be yielded and suspended.
Variant *variant_stack = (Variant *)p_stack;
@@ -1711,7 +1689,7 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p
Variant VisualScriptInstance::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
r_error.error = Callable::CallError::CALL_OK; //ok by default
- Map<StringName, Function>::Element *F = functions.find(p_method);
+ HashMap<StringName, Function>::Iterator F = functions.find(p_method);
if (!F) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
return Variant();
@@ -1719,7 +1697,7 @@ Variant VisualScriptInstance::callp(const StringName &p_method, const Variant **
VSDEBUG("CALLING: " + String(p_method));
- Function *f = &F->get();
+ Function *f = &F->value;
int total_stack_size = 0;
@@ -1753,14 +1731,14 @@ Variant VisualScriptInstance::callp(const StringName &p_method, const Variant **
memset(pass_stack, 0, f->pass_stack_size * sizeof(int));
- Map<int, VisualScriptNodeInstance *>::Element *E = instances.find(f->node);
+ HashMap<int, VisualScriptNodeInstance *>::Iterator E = instances.find(f->node);
if (!E) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
ERR_FAIL_V_MSG(Variant(), "No VisualScriptFunction node in function.");
}
- VisualScriptNodeInstance *node = E->get();
+ VisualScriptNodeInstance *node = E->value;
if (flow_stack) {
flow_stack[0] = node->get_id();
@@ -1845,19 +1823,15 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
// 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.
{
- 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.node = vsfn.func_id;
function.max_stack = 0;
@@ -1865,10 +1839,10 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
function.pass_stack_size = 0;
function.node_count = 0;
- Map<StringName, int> local_var_indices;
+ HashMap<StringName, int> local_var_indices;
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);
}
@@ -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);
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());
@@ -1887,42 +1861,41 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
max_input_args = MAX(max_input_args, function.argument_count);
}
// Function nodes graphs.
- Set<VisualScript::SequenceConnection> seqconns;
- Set<VisualScript::DataConnection> dataconns;
- Set<int> node_ids;
+ RBSet<VisualScript::SequenceConnection> seqconns;
+ RBSet<VisualScript::DataConnection> dataconns;
+ RBSet<int> node_ids;
node_ids.insert(function.node);
{
List<int> nd_queue;
nd_queue.push_back(function.node);
while (!nd_queue.is_empty()) {
- for (const Set<VisualScript::SequenceConnection>::Element *F = script->sequence_connections.front(); F; F = F->next()) {
- if (nd_queue.front()->get() == F->get().from_node && !node_ids.has(F->get().to_node)) {
- nd_queue.push_back(F->get().to_node);
- node_ids.insert(F->get().to_node);
+ for (const VisualScript::SequenceConnection &F : script->sequence_connections) {
+ if (nd_queue.front()->get() == F.from_node && !node_ids.has(F.to_node)) {
+ nd_queue.push_back(F.to_node);
+ node_ids.insert(F.to_node);
}
- if (nd_queue.front()->get() == F->get().from_node && !seqconns.has(F->get())) {
- seqconns.insert(F->get());
+ if (nd_queue.front()->get() == F.from_node && !seqconns.has(F)) {
+ seqconns.insert(F);
}
}
nd_queue.pop_front();
}
HashMap<int, HashMap<int, Pair<int, int>>> dc_lut; // :: to -> to_port -> (from, from_port)
- for (const Set<VisualScript::DataConnection>::Element *F = script->data_connections.front(); F; F = F->next()) {
- dc_lut[F->get().to_node][F->get().to_port] = Pair<int, int>(F->get().from_node, F->get().from_port);
+ for (const VisualScript::DataConnection &F : script->data_connections) {
+ dc_lut[F.to_node][F.to_port] = Pair<int, int>(F.from_node, F.from_port);
}
- for (const Set<int>::Element *F = node_ids.front(); F; F = F->next()) {
- nd_queue.push_back(F->get());
+ for (const int &F : node_ids) {
+ nd_queue.push_back(F);
}
List<int> dc_keys;
while (!nd_queue.is_empty()) {
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;
- 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_port = F;
+ dc.to_port = F.key;
dataconns.insert(dc);
nd_queue.push_back(dc.from_node);
node_ids.insert(dc.from_node);
@@ -1934,15 +1907,15 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
//Multiple passes are required to set up this complex thing..
//First create the nodes.
- for (const Set<int>::Element *F = node_ids.front(); F; F = F->next()) {
- Ref<VisualScriptNode> node = script->nodes[F->get()].node;
+ for (const int &F : node_ids) {
+ Ref<VisualScriptNode> node = script->nodes[F].node;
VisualScriptNodeInstance *instance = node->instantiate(this); // Create instance.
ERR_FAIL_COND(!instance);
instance->base = node.ptr();
- instance->id = F->get();
+ instance->id = F;
instance->input_port_count = node->get_input_value_port_count();
instance->input_ports = nullptr;
instance->output_port_count = node->get_output_value_port_count();
@@ -2002,14 +1975,14 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
max_input_args = MAX(max_input_args, instance->input_port_count);
max_output_args = MAX(max_output_args, instance->output_port_count);
- instances[F->get()] = instance;
+ instances[F] = instance;
}
function.trash_pos = function.max_stack++; // create pos for trash
// Second pass, do data connections.
- for (const Set<VisualScript::DataConnection>::Element *F = dataconns.front(); F; F = F->next()) {
- VisualScript::DataConnection dc = F->get();
+ for (const VisualScript::DataConnection &F : dataconns) {
+ VisualScript::DataConnection dc = F;
ERR_CONTINUE(!instances.has(dc.from_node));
VisualScriptNodeInstance *from = instances[dc.from_node];
ERR_CONTINUE(!instances.has(dc.to_node));
@@ -2035,8 +2008,8 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
}
// Third pass, do sequence connections.
- for (const Set<VisualScript::SequenceConnection>::Element *F = seqconns.front(); F; F = F->next()) {
- VisualScript::SequenceConnection sc = F->get();
+ for (const VisualScript::SequenceConnection &F : seqconns) {
+ VisualScript::SequenceConnection sc = F;
ERR_CONTINUE(!instances.has(sc.from_node));
VisualScriptNodeInstance *from = instances[sc.from_node];
ERR_CONTINUE(!instances.has(sc.to_node));
@@ -2049,11 +2022,11 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
//fourth pass:
// 1) unassigned input ports to default values
// 2) connect unassigned output ports to trash
- for (const Set<int>::Element *F = node_ids.front(); F; F = F->next()) {
- ERR_CONTINUE(!instances.has(F->get()));
+ for (const int &F : node_ids) {
+ ERR_CONTINUE(!instances.has(F));
- Ref<VisualScriptNode> node = script->nodes[F->get()].node;
- VisualScriptNodeInstance *instance = instances[F->get()];
+ Ref<VisualScriptNode> node = script->nodes[F].node;
+ VisualScriptNodeInstance *instance = instances[F];
// Connect to default values.
for (int i = 0; i < instance->input_port_count; i++) {
@@ -2072,7 +2045,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
}
}
- functions[E] = function;
+ functions[E.key] = function;
}
}
}
@@ -2250,7 +2223,7 @@ Ref<Script> VisualScriptLanguage::make_template(const String &p_template, const
return script;
}
-bool VisualScriptLanguage::validate(const String &p_script, const String &p_path, List<String> *r_functions, List<ScriptLanguage::ScriptError> *r_errors, List<ScriptLanguage::Warning> *r_warnings, Set<int> *r_safe_lines) const {
+bool VisualScriptLanguage::validate(const String &p_script, const String &p_path, List<String> *r_functions, List<ScriptLanguage::ScriptError> *r_errors, List<ScriptLanguage::Warning> *r_warnings, HashSet<int> *r_safe_lines) const {
return false;
}
diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h
index 6b27af15f6..0f3b8de3fc 100644
--- a/modules/visual_script/visual_script.h
+++ b/modules/visual_script/visual_script.h
@@ -36,6 +36,7 @@
#include "core/doc_data.h"
#include "core/object/script_language.h"
#include "core/os/thread.h"
+#include "core/templates/rb_set.h"
class VisualScriptInstance;
class VisualScriptNodeInstance;
@@ -214,8 +215,8 @@ private:
HashMap<int, NodeData> nodes; // Can be a sparse map.
- Set<SequenceConnection> sequence_connections;
- Set<DataConnection> data_connections;
+ RBSet<SequenceConnection> sequence_connections;
+ RBSet<DataConnection> data_connections;
Vector2 scroll;
@@ -233,15 +234,15 @@ private:
HashMap<StringName, Function> functions;
HashMap<StringName, Variable> variables;
- Map<StringName, Vector<Argument>> custom_signals;
+ HashMap<StringName, Vector<Argument>> custom_signals;
Vector<Multiplayer::RPCConfig> rpc_functions;
- Map<Object *, VisualScriptInstance *> instances;
+ HashMap<Object *, VisualScriptInstance *> instances;
bool is_tool_script;
#ifdef TOOLS_ENABLED
- Set<PlaceHolderScriptInstance *> placeholders;
+ RBSet<PlaceHolderScriptInstance *> placeholders;
// void _update_placeholder(PlaceHolderScriptInstance *p_placeholder);
virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder) override;
void _update_placeholders();
@@ -283,7 +284,7 @@ public:
void sequence_disconnect(int p_from_node, int p_from_output, int p_to_node);
bool has_sequence_connection(int p_from_node, int p_from_output, int p_to_node) const;
void get_sequence_connection_list(List<SequenceConnection> *r_connection) const;
- Set<int> get_output_sequence_ports_connected(int from_node);
+ RBSet<int> get_output_sequence_ports_connected(int from_node);
void data_connect(int p_from_node, int p_from_port, int p_to_node, int p_to_port);
void data_disconnect(int p_from_node, int p_from_port, int p_to_node, int p_to_port);
@@ -317,7 +318,7 @@ public:
void custom_signal_swap_argument(const StringName &p_func, int p_argidx, int p_with_argidx);
void remove_custom_signal(const StringName &p_name);
void rename_custom_signal(const StringName &p_name, const StringName &p_new_name);
- Set<int> get_output_sequence_ports_connected(const String &edited_func, int from_node);
+ RBSet<int> get_output_sequence_ports_connected(const String &edited_func, int from_node);
void get_custom_signal_list(List<StringName> *r_custom_signals) const;
@@ -376,8 +377,8 @@ class VisualScriptInstance : public ScriptInstance {
Object *owner = nullptr;
Ref<VisualScript> script;
- Map<StringName, Variant> variables; // Using variable path, not script.
- Map<int, VisualScriptNodeInstance *> instances;
+ HashMap<StringName, Variant> variables; // Using variable path, not script.
+ HashMap<int, VisualScriptNodeInstance *> instances;
struct Function {
int node = 0;
@@ -389,7 +390,7 @@ class VisualScriptInstance : public ScriptInstance {
int argument_count = 0;
};
- Map<StringName, Function> functions;
+ HashMap<StringName, Function> functions;
Vector<Variant> default_values;
int max_input_args = 0;
@@ -415,22 +416,22 @@ public:
String to_string(bool *r_valid);
bool set_variable(const StringName &p_variable, const Variant &p_value) {
- Map<StringName, Variant>::Element *E = variables.find(p_variable);
+ HashMap<StringName, Variant>::Iterator E = variables.find(p_variable);
if (!E) {
return false;
}
- E->get() = p_value;
+ E->value = p_value;
return true;
}
bool get_variable(const StringName &p_variable, Variant *r_variable) const {
- const Map<StringName, Variant>::Element *E = variables.find(p_variable);
+ HashMap<StringName, Variant>::ConstIterator E = variables.find(p_variable);
if (!E) {
return false;
}
- *r_variable = E->get();
+ *r_variable = E->value;
return true;
}
@@ -480,7 +481,7 @@ public:
typedef Ref<VisualScriptNode> (*VisualScriptNodeRegisterFunc)(const String &p_type);
class VisualScriptLanguage : public ScriptLanguage {
- Map<String, VisualScriptNodeRegisterFunc> register_funcs;
+ HashMap<String, VisualScriptNodeRegisterFunc> register_funcs;
struct CallLevel {
Variant *stack = nullptr;
@@ -570,7 +571,7 @@ public:
virtual void get_string_delimiters(List<String> *p_delimiters) const override;
virtual bool is_using_templates() override;
virtual Ref<Script> make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const override;
- virtual bool validate(const String &p_script, const String &p_path = "", List<String> *r_functions = nullptr, List<ScriptLanguage::ScriptError> *r_errors = nullptr, List<ScriptLanguage::Warning> *r_warnings = nullptr, Set<int> *r_safe_lines = nullptr) const override;
+ virtual bool validate(const String &p_script, const String &p_path = "", List<String> *r_functions = nullptr, List<ScriptLanguage::ScriptError> *r_errors = nullptr, List<ScriptLanguage::Warning> *r_warnings = nullptr, HashSet<int> *r_safe_lines = nullptr) const override;
virtual Script *create_script() const override;
virtual bool has_named_classes() const override;
virtual bool supports_builtin_mode() const override;
diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp
index dbbe74f3d5..ac33526ddc 100644
--- a/modules/visual_script/visual_script_nodes.cpp
+++ b/modules/visual_script/visual_script_nodes.cpp
@@ -3416,7 +3416,7 @@ VisualScriptConstructor::VisualScriptConstructor() {
type = Variant::NIL;
}
-static Map<String, Pair<Variant::Type, MethodInfo>> constructor_map;
+static HashMap<String, Pair<Variant::Type, MethodInfo>> constructor_map;
static Ref<VisualScriptNode> create_constructor_node(const String &p_name) {
ERR_FAIL_COND_V(!constructor_map.has(p_name), Ref<VisualScriptNode>());
diff --git a/modules/vorbis/audio_stream_ogg_vorbis.cpp b/modules/vorbis/audio_stream_ogg_vorbis.cpp
index 5ff5b2339c..b645a48c88 100644
--- a/modules/vorbis/audio_stream_ogg_vorbis.cpp
+++ b/modules/vorbis/audio_stream_ogg_vorbis.cpp
@@ -350,7 +350,6 @@ void AudioStreamOGGVorbis::maybe_update_info() {
vorbis_info_init(&info);
vorbis_comment_init(&comment);
- int packet_count = 0;
Ref<OGGPacketSequencePlayback> packet_sequence_playback = packet_sequence->instance_playback();
for (int i = 0; i < 3; i++) {
@@ -369,8 +368,6 @@ void AudioStreamOGGVorbis::maybe_update_info() {
err = vorbis_synthesis_headerin(&info, &comment, packet);
ERR_FAIL_COND_MSG(err != 0, "Error parsing header packet " + itos(i) + ": " + itos(err));
-
- packet_count++;
}
packet_sequence->set_sampling_rate(info.rate);
diff --git a/modules/vorbis/resource_importer_ogg_vorbis.cpp b/modules/vorbis/resource_importer_ogg_vorbis.cpp
index 03e145216a..7ee6446313 100644
--- a/modules/vorbis/resource_importer_ogg_vorbis.cpp
+++ b/modules/vorbis/resource_importer_ogg_vorbis.cpp
@@ -57,7 +57,7 @@ String ResourceImporterOGGVorbis::get_resource_type() const {
return "AudioStreamOGGVorbis";
}
-bool ResourceImporterOGGVorbis::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const {
+bool ResourceImporterOGGVorbis::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const {
return true;
}
@@ -74,7 +74,7 @@ void ResourceImporterOGGVorbis::get_import_options(const String &p_path, List<Im
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "loop_offset"), 0));
}
-Error ResourceImporterOGGVorbis::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
+Error ResourceImporterOGGVorbis::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
bool loop = p_options["loop"];
float loop_offset = p_options["loop_offset"];
diff --git a/modules/vorbis/resource_importer_ogg_vorbis.h b/modules/vorbis/resource_importer_ogg_vorbis.h
index 07291803a1..3b4a68a1fd 100644
--- a/modules/vorbis/resource_importer_ogg_vorbis.h
+++ b/modules/vorbis/resource_importer_ogg_vorbis.h
@@ -52,9 +52,9 @@ public:
virtual int get_preset_count() const override;
virtual String get_preset_name(int p_idx) const override;
virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override;
- virtual bool get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const override;
+ virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override;
- virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override;
+ virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override;
ResourceImporterOGGVorbis();
};
diff --git a/modules/webrtc/webrtc_data_channel.h b/modules/webrtc/webrtc_data_channel.h
index eac8f85a84..75e29283ec 100644
--- a/modules/webrtc/webrtc_data_channel.h
+++ b/modules/webrtc/webrtc_data_channel.h
@@ -33,7 +33,7 @@
#include "core/io/packet_peer.h"
-#define WRTC_IN_BUF "network/limits/webrtc/max_channel_in_buffer_kb"
+#define WRTC_IN_BUF PNAME("network/limits/webrtc/max_channel_in_buffer_kb")
class WebRTCDataChannel : public PacketPeer {
GDCLASS(WebRTCDataChannel, PacketPeer);
diff --git a/modules/webrtc/webrtc_multiplayer_peer.cpp b/modules/webrtc/webrtc_multiplayer_peer.cpp
index 0bc42b104c..6f68b84ad3 100644
--- a/modules/webrtc/webrtc_multiplayer_peer.cpp
+++ b/modules/webrtc/webrtc_multiplayer_peer.cpp
@@ -140,41 +140,41 @@ void WebRTCMultiplayerPeer::poll() {
}
void WebRTCMultiplayerPeer::_find_next_peer() {
- Map<int, Ref<ConnectedPeer>>::Element *E = peer_map.find(next_packet_peer);
+ HashMap<int, Ref<ConnectedPeer>>::Iterator E = peer_map.find(next_packet_peer);
if (E) {
- E = E->next();
+ ++E;
}
// After last.
while (E) {
- if (!E->get()->connected) {
- E = E->next();
+ if (!E->value->connected) {
+ ++E;
continue;
}
- for (const Ref<WebRTCDataChannel> &F : E->get()->channels) {
+ for (const Ref<WebRTCDataChannel> &F : E->value->channels) {
if (F->get_available_packet_count()) {
- next_packet_peer = E->key();
+ next_packet_peer = E->key;
return;
}
}
- E = E->next();
+ ++E;
}
- E = peer_map.front();
+ E = peer_map.begin();
// Before last
while (E) {
- if (!E->get()->connected) {
- E = E->next();
+ if (!E->value->connected) {
+ ++E;
continue;
}
- for (const Ref<WebRTCDataChannel> &F : E->get()->channels) {
+ for (const Ref<WebRTCDataChannel> &F : E->value->channels) {
if (F->get_available_packet_count()) {
- next_packet_peer = E->key();
+ next_packet_peer = E->key;
return;
}
}
- if (E->key() == (int)next_packet_peer) {
+ if (E->key == (int)next_packet_peer) {
break;
}
- E = E->next();
+ ++E;
}
// No packet found
next_packet_peer = 0;
@@ -354,12 +354,12 @@ Error WebRTCMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer_si
}
if (target_peer > 0) {
- Map<int, Ref<ConnectedPeer>>::Element *E = peer_map.find(target_peer);
+ HashMap<int, Ref<ConnectedPeer>>::Iterator E = peer_map.find(target_peer);
ERR_FAIL_COND_V_MSG(!E, ERR_INVALID_PARAMETER, "Invalid target peer: " + itos(target_peer) + ".");
- ERR_FAIL_COND_V_MSG(E->value()->channels.size() <= ch, ERR_INVALID_PARAMETER, vformat("Unable to send packet on channel %d, max channels: %d", ch, E->value()->channels.size()));
- ERR_FAIL_COND_V(E->value()->channels[ch].is_null(), ERR_BUG);
- return E->value()->channels[ch]->put_packet(p_buffer, p_buffer_size);
+ ERR_FAIL_COND_V_MSG(E->value->channels.size() <= ch, ERR_INVALID_PARAMETER, vformat("Unable to send packet on channel %d, max channels: %d", ch, E->value->channels.size()));
+ ERR_FAIL_COND_V(E->value->channels[ch].is_null(), ERR_BUG);
+ return E->value->channels[ch]->put_packet(p_buffer, p_buffer_size);
} else {
int exclude = -target_peer;
diff --git a/modules/webrtc/webrtc_multiplayer_peer.h b/modules/webrtc/webrtc_multiplayer_peer.h
index 6675c67867..97550a3e9d 100644
--- a/modules/webrtc/webrtc_multiplayer_peer.h
+++ b/modules/webrtc/webrtc_multiplayer_peer.h
@@ -69,7 +69,7 @@ private:
int next_packet_peer = 0;
bool server_compat = false;
- Map<int, Ref<ConnectedPeer>> peer_map;
+ HashMap<int, Ref<ConnectedPeer>> peer_map;
List<Dictionary> channels_config;
void _peer_to_dict(Ref<ConnectedPeer> p_connected_peer, Dictionary &r_dict);
diff --git a/modules/websocket/websocket_multiplayer_peer.h b/modules/websocket/websocket_multiplayer_peer.h
index 43d9d59f38..db529a669d 100644
--- a/modules/websocket/websocket_multiplayer_peer.h
+++ b/modules/websocket/websocket_multiplayer_peer.h
@@ -62,7 +62,7 @@ protected:
};
List<Packet> _incoming_packets;
- Map<int, Ref<WebSocketPeer>> _peer_map;
+ HashMap<int, Ref<WebSocketPeer>> _peer_map;
Packet _current_packet;
bool _is_multiplayer = false;
diff --git a/modules/websocket/wsl_client.cpp b/modules/websocket/wsl_client.cpp
index 894ba7766f..478dbb9d47 100644
--- a/modules/websocket/wsl_client.cpp
+++ b/modules/websocket/wsl_client.cpp
@@ -113,7 +113,7 @@ bool WSLClient::_verify_headers(String &r_protocol) {
ERR_FAIL_COND_V_MSG(req[0] != "HTTP/1.1", false, "Invalid protocol. Got: '" + req[0] + "', expected 'HTTP/1.1'.");
ERR_FAIL_COND_V_MSG(req[1] != "101", false, "Invalid status code. Got: '" + req[1] + "', expected '101'.");
- Map<String, String> headers;
+ HashMap<String, String> headers;
for (int i = 1; i < len; i++) {
Vector<String> header = psa[i].split(":", false, 1);
ERR_FAIL_COND_V_MSG(header.size() != 2, false, "Invalid header -> " + psa[i] + ".");
diff --git a/modules/websocket/wsl_server.cpp b/modules/websocket/wsl_server.cpp
index b58b2e4724..517b9643f8 100644
--- a/modules/websocket/wsl_server.cpp
+++ b/modules/websocket/wsl_server.cpp
@@ -46,7 +46,7 @@ bool WSLServer::PendingPeer::_parse_request(const Vector<String> p_protocols, St
ERR_FAIL_COND_V_MSG(req[0] != "GET" || req[2] != "HTTP/1.1", false, "Invalid method or HTTP version.");
r_resource_name = req[1];
- Map<String, String> headers;
+ HashMap<String, String> headers;
for (int i = 1; i < len; i++) {
Vector<String> header = psa[i].split(":", false, 1);
ERR_FAIL_COND_V_MSG(header.size() != 2, false, "Invalid header -> " + psa[i]);