diff options
Diffstat (limited to 'modules')
21 files changed, 160 insertions, 49 deletions
diff --git a/modules/fbx/fbx_document.cpp b/modules/fbx/fbx_document.cpp index 63766247ee..bde23289f4 100644 --- a/modules/fbx/fbx_document.cpp +++ b/modules/fbx/fbx_document.cpp @@ -990,8 +990,8 @@ Error FBXDocument::_parse_images(Ref<FBXState> p_state, const String &p_base_pat for (int texture_i = 0; texture_i < static_cast<int>(fbx_scene->texture_files.count); texture_i++) { const ufbx_texture_file &fbx_texture_file = fbx_scene->texture_files[texture_i]; String path = _as_string(fbx_texture_file.filename); - path = ProjectSettings::get_singleton()->localize_path(path); - if (path.is_absolute_path() && !path.is_resource_file()) { + // Use only filename for absolute paths to avoid portability issues. + if (path.is_absolute_path()) { path = path.get_file(); } if (!p_base_path.is_empty()) { @@ -2239,6 +2239,10 @@ Error FBXDocument::_parse_lights(Ref<FBXState> p_state) { } String FBXDocument::_get_texture_path(const String &p_base_dir, const String &p_source_file_path) const { + // Check if the original path exists first. + if (FileAccess::exists(p_source_file_path)) { + return p_source_file_path.strip_edges(); + } const String tex_file_name = p_source_file_path.get_file(); const Vector<String> subdirs = { "", "textures/", "Textures/", "images/", diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index b198338ff0..cd19887d82 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -1957,6 +1957,18 @@ void GDScriptAnalyzer::resolve_assignable(GDScriptParser::AssignableNode *p_assi } else { parser->push_warning(p_assignable, GDScriptWarning::UNTYPED_DECLARATION, declaration_type, p_assignable->identifier->name); } + } else if (specified_type.kind == GDScriptParser::DataType::ENUM && p_assignable->initializer == nullptr) { + // Warn about enum variables without default value. Unless the enum defines the "0" value, then it's fine. + bool has_zero_value = false; + for (const KeyValue<StringName, int64_t> &kv : specified_type.enum_values) { + if (kv.value == 0) { + has_zero_value = true; + break; + } + } + if (!has_zero_value) { + parser->push_warning(p_assignable, GDScriptWarning::ENUM_VARIABLE_WITHOUT_DEFAULT, p_assignable->identifier->name); + } } #endif diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index 2940af585d..5b1639e250 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -1455,10 +1455,11 @@ GDScriptTokenizer::Token GDScriptTokenizerText::scan() { if (_peek() != '\n') { return make_error("Expected new line after \"\\\"."); } - continuation_lines.push_back(line); _advance(); newline(false); line_continuation = true; + _skip_whitespace(); // Skip whitespace/comment lines after `\`. See GH-89403. + continuation_lines.push_back(line); return scan(); // Recurse to get next token. } diff --git a/modules/gdscript/gdscript_tokenizer_buffer.cpp b/modules/gdscript/gdscript_tokenizer_buffer.cpp index db523ea941..e53bc5bc41 100644 --- a/modules/gdscript/gdscript_tokenizer_buffer.cpp +++ b/modules/gdscript/gdscript_tokenizer_buffer.cpp @@ -285,9 +285,9 @@ Vector<uint8_t> GDScriptTokenizerBuffer::parse_code_string(const String &p_code, // Remove continuation lines from map. for (int line : tokenizer.get_continuation_lines()) { - if (rev_token_lines.has(line + 1)) { - token_lines.erase(rev_token_lines[line + 1]); - token_columns.erase(rev_token_lines[line + 1]); + if (rev_token_lines.has(line)) { + token_lines.erase(rev_token_lines[line]); + token_columns.erase(rev_token_lines[line]); } } diff --git a/modules/gdscript/gdscript_warning.cpp b/modules/gdscript/gdscript_warning.cpp index 708966a0a8..48a0abe617 100644 --- a/modules/gdscript/gdscript_warning.cpp +++ b/modules/gdscript/gdscript_warning.cpp @@ -126,6 +126,9 @@ String GDScriptWarning::get_message() const { case INT_AS_ENUM_WITHOUT_MATCH: CHECK_SYMBOLS(3); return vformat(R"(Cannot %s %s as Enum "%s": no enum member has matching value.)", symbols[0], symbols[1], symbols[2]); + case ENUM_VARIABLE_WITHOUT_DEFAULT: + CHECK_SYMBOLS(1); + return vformat(R"(The variable "%s" has an enum type and does not set an explicit default value. The default will be set to "0".)", symbols[0]); case EMPTY_FILE: return "Empty script file."; case DEPRECATED_KEYWORD: @@ -221,6 +224,7 @@ String GDScriptWarning::get_name_from_code(Code p_code) { "NARROWING_CONVERSION", "INT_AS_ENUM_WITHOUT_CAST", "INT_AS_ENUM_WITHOUT_MATCH", + "ENUM_VARIABLE_WITHOUT_DEFAULT", "EMPTY_FILE", "DEPRECATED_KEYWORD", "RENAMED_IN_GODOT_4_HINT", diff --git a/modules/gdscript/gdscript_warning.h b/modules/gdscript/gdscript_warning.h index 93c232a0f8..3ad9488138 100644 --- a/modules/gdscript/gdscript_warning.h +++ b/modules/gdscript/gdscript_warning.h @@ -78,6 +78,7 @@ public: NARROWING_CONVERSION, // Float value into an integer slot, precision is lost. INT_AS_ENUM_WITHOUT_CAST, // An integer value was used as an enum value without casting. INT_AS_ENUM_WITHOUT_MATCH, // An integer value was used as an enum value without matching enum member. + ENUM_VARIABLE_WITHOUT_DEFAULT, // A variable with an enum type does not have a default value. The default will be set to `0` instead of the first enum value. EMPTY_FILE, // A script file is empty. DEPRECATED_KEYWORD, // The keyword is deprecated and should be replaced. RENAMED_IN_GODOT_4_HINT, // A variable or function that could not be found has been renamed in Godot 4. @@ -129,6 +130,7 @@ public: WARN, // NARROWING_CONVERSION WARN, // INT_AS_ENUM_WITHOUT_CAST WARN, // INT_AS_ENUM_WITHOUT_MATCH + WARN, // ENUM_VARIABLE_WITHOUT_DEFAULT WARN, // EMPTY_FILE WARN, // DEPRECATED_KEYWORD WARN, // RENAMED_IN_GODOT_4_HINT diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp index a0329eb8d2..e3d16eaf42 100644 --- a/modules/gdscript/tests/gdscript_test_runner.cpp +++ b/modules/gdscript/tests/gdscript_test_runner.cpp @@ -300,14 +300,23 @@ bool GDScriptTestRunner::make_tests_for_dir(const String &p_dir) { #endif String out_file = next.get_basename() + ".out"; - if (!is_generating && !dir->file_exists(out_file)) { - ERR_FAIL_V_MSG(false, "Could not find output file for " + next); - } - GDScriptTest test(current_dir.path_join(next), current_dir.path_join(out_file), source_dir); - if (binary_tokens) { - test.set_tokenizer_mode(GDScriptTest::TOKENIZER_BUFFER); + ERR_FAIL_COND_V_MSG(!is_generating && !dir->file_exists(out_file), false, "Could not find output file for " + next); + + if (next.ends_with(".bin.gd")) { + // Test text mode first. + GDScriptTest text_test(current_dir.path_join(next), current_dir.path_join(out_file), source_dir); + tests.push_back(text_test); + // Test binary mode even without `--use-binary-tokens`. + GDScriptTest bin_test(current_dir.path_join(next), current_dir.path_join(out_file), source_dir); + bin_test.set_tokenizer_mode(GDScriptTest::TOKENIZER_BUFFER); + tests.push_back(bin_test); + } else { + GDScriptTest test(current_dir.path_join(next), current_dir.path_join(out_file), source_dir); + if (binary_tokens) { + test.set_tokenizer_mode(GDScriptTest::TOKENIZER_BUFFER); + } + tests.push_back(test); } - tests.push_back(test); } } diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/enum_without_default_value.gd b/modules/gdscript/tests/scripts/analyzer/warnings/enum_without_default_value.gd new file mode 100644 index 0000000000..13e3edf93f --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/warnings/enum_without_default_value.gd @@ -0,0 +1,9 @@ +enum HasZero { A = 0, B = 1 } +enum HasNoZero { A = 1, B = 2 } +var has_zero: HasZero # No warning, because the default `0` is valid. +var has_no_zero: HasNoZero # Warning, because there is no `0` in the enum. + + +func test(): + print(has_zero) + print(has_no_zero) diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/enum_without_default_value.out b/modules/gdscript/tests/scripts/analyzer/warnings/enum_without_default_value.out new file mode 100644 index 0000000000..ae40e0bc8c --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/warnings/enum_without_default_value.out @@ -0,0 +1,7 @@ +GDTEST_OK +>> WARNING +>> Line: 4 +>> ENUM_VARIABLE_WITHOUT_DEFAULT +>> The variable "has_no_zero" has an enum type and does not set an explicit default value. The default will be set to "0". +0 +0 diff --git a/modules/gdscript/tests/scripts/parser/features/continuation_lines_comments.bin.gd b/modules/gdscript/tests/scripts/parser/features/continuation_lines_comments.bin.gd new file mode 100644 index 0000000000..cb0bc94d2e --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/continuation_lines_comments.bin.gd @@ -0,0 +1,12 @@ +# GH-89403 + +func test(): + var x := 1 + if x == 0 \ + # Comment. + # Comment. + and (x < 1 or x > 2) \ + # Comment. + and x != 3: + pass + print("Ok") diff --git a/modules/gdscript/tests/scripts/parser/features/continuation_lines_comments.bin.out b/modules/gdscript/tests/scripts/parser/features/continuation_lines_comments.bin.out new file mode 100644 index 0000000000..0e9f482af4 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/features/continuation_lines_comments.bin.out @@ -0,0 +1,2 @@ +GDTEST_OK +Ok diff --git a/modules/gdscript/tests/scripts/runtime/features/member_info.gd b/modules/gdscript/tests/scripts/runtime/features/member_info.gd index d7485f49e6..42b29eee43 100644 --- a/modules/gdscript/tests/scripts/runtime/features/member_info.gd +++ b/modules/gdscript/tests/scripts/runtime/features/member_info.gd @@ -23,6 +23,7 @@ var test_var_hard_int: int var test_var_hard_variant_type: Variant.Type @export var test_var_hard_variant_type_exported: Variant.Type var test_var_hard_node_process_mode: Node.ProcessMode +@warning_ignore("enum_variable_without_default") var test_var_hard_my_enum: MyEnum var test_var_hard_array: Array var test_var_hard_array_int: Array[int] diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs index 9cd5498fa8..37f319b697 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs @@ -1208,39 +1208,39 @@ namespace Godot /// Do a simple expression match, where '*' matches zero or more /// arbitrary characters and '?' matches any single character except '.'. /// </summary> - /// <param name="instance">The string to check.</param> - /// <param name="expr">Expression to check.</param> + /// <param name="str">The string to check.</param> + /// <param name="pattern">Expression to check.</param> /// <param name="caseSensitive"> /// If <see langword="true"/>, the check will be case sensitive. /// </param> /// <returns>If the expression has any matches.</returns> - private static bool ExprMatch(this string instance, string expr, bool caseSensitive) + private static bool WildcardMatch(ReadOnlySpan<char> str, ReadOnlySpan<char> pattern, bool caseSensitive) { // case '\0': - if (expr.Length == 0) - return instance.Length == 0; + if (pattern.IsEmpty) + return str.IsEmpty; - switch (expr[0]) + switch (pattern[0]) { case '*': - return ExprMatch(instance, expr.Substring(1), caseSensitive) || (instance.Length > 0 && - ExprMatch(instance.Substring(1), expr, caseSensitive)); + return WildcardMatch(str, pattern.Slice(1), caseSensitive) + || (!str.IsEmpty && WildcardMatch(str.Slice(1), pattern, caseSensitive)); case '?': - return instance.Length > 0 && instance[0] != '.' && - ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive); + return !str.IsEmpty && str[0] != '.' && + WildcardMatch(str.Slice(1), pattern.Slice(1), caseSensitive); default: - if (instance.Length == 0) + if (str.IsEmpty) return false; - if (caseSensitive) - return instance[0] == expr[0]; - return (char.ToUpperInvariant(instance[0]) == char.ToUpperInvariant(expr[0])) && - ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive); + bool charMatches = caseSensitive ? + str[0] == pattern[0] : + char.ToUpperInvariant(str[0]) == char.ToUpperInvariant(pattern[0]); + return charMatches && + WildcardMatch(str.Slice(1), pattern.Slice(1), caseSensitive); } } /// <summary> - /// Do a simple case sensitive expression match, using ? and * wildcards - /// (see <see cref="ExprMatch(string, string, bool)"/>). + /// Do a simple case sensitive expression match, using ? and * wildcards. /// </summary> /// <seealso cref="MatchN(string, string)"/> /// <param name="instance">The string to check.</param> @@ -1254,12 +1254,11 @@ namespace Godot if (instance.Length == 0 || expr.Length == 0) return false; - return instance.ExprMatch(expr, caseSensitive); + return WildcardMatch(instance, expr, caseSensitive); } /// <summary> - /// Do a simple case insensitive expression match, using ? and * wildcards - /// (see <see cref="ExprMatch(string, string, bool)"/>). + /// Do a simple case insensitive expression match, using ? and * wildcards. /// </summary> /// <seealso cref="Match(string, string, bool)"/> /// <param name="instance">The string to check.</param> @@ -1270,7 +1269,7 @@ namespace Godot if (instance.Length == 0 || expr.Length == 0) return false; - return instance.ExprMatch(expr, caseSensitive: false); + return WildcardMatch(instance, expr, caseSensitive: false); } /// <summary> diff --git a/modules/navigation/2d/nav_mesh_generator_2d.cpp b/modules/navigation/2d/nav_mesh_generator_2d.cpp index d8f1170f6a..9000259524 100644 --- a/modules/navigation/2d/nav_mesh_generator_2d.cpp +++ b/modules/navigation/2d/nav_mesh_generator_2d.cpp @@ -43,9 +43,9 @@ #include "scene/resources/2d/circle_shape_2d.h" #include "scene/resources/2d/concave_polygon_shape_2d.h" #include "scene/resources/2d/convex_polygon_shape_2d.h" +#include "scene/resources/2d/navigation_mesh_source_geometry_data_2d.h" +#include "scene/resources/2d/navigation_polygon.h" #include "scene/resources/2d/rectangle_shape_2d.h" -#include "scene/resources/navigation_mesh_source_geometry_data_2d.h" -#include "scene/resources/navigation_polygon.h" #include "thirdparty/clipper2/include/clipper2/clipper.h" #include "thirdparty/misc/polypartition.h" diff --git a/modules/navigation/3d/nav_mesh_generator_3d.cpp b/modules/navigation/3d/nav_mesh_generator_3d.cpp index 3d3f4b4679..b1b3cbed5d 100644 --- a/modules/navigation/3d/nav_mesh_generator_3d.cpp +++ b/modules/navigation/3d/nav_mesh_generator_3d.cpp @@ -45,12 +45,12 @@ #include "scene/resources/3d/convex_polygon_shape_3d.h" #include "scene/resources/3d/cylinder_shape_3d.h" #include "scene/resources/3d/height_map_shape_3d.h" +#include "scene/resources/3d/navigation_mesh_source_geometry_data_3d.h" #include "scene/resources/3d/primitive_meshes.h" #include "scene/resources/3d/shape_3d.h" #include "scene/resources/3d/sphere_shape_3d.h" #include "scene/resources/3d/world_boundary_shape_3d.h" #include "scene/resources/navigation_mesh.h" -#include "scene/resources/navigation_mesh_source_geometry_data_3d.h" #include "modules/modules_enabled.gen.h" // For csg, gridmap. diff --git a/modules/navigation/3d/navigation_mesh_generator.cpp b/modules/navigation/3d/navigation_mesh_generator.cpp index 8393896db1..54df42e266 100644 --- a/modules/navigation/3d/navigation_mesh_generator.cpp +++ b/modules/navigation/3d/navigation_mesh_generator.cpp @@ -32,7 +32,7 @@ #include "navigation_mesh_generator.h" -#include "scene/resources/navigation_mesh_source_geometry_data_3d.h" +#include "scene/resources/3d/navigation_mesh_source_geometry_data_3d.h" #include "servers/navigation_server_3d.h" NavigationMeshGenerator *NavigationMeshGenerator::singleton = nullptr; diff --git a/modules/navigation/editor/navigation_mesh_editor_plugin.cpp b/modules/navigation/editor/navigation_mesh_editor_plugin.cpp index 352203f5aa..d7bf1cdd38 100644 --- a/modules/navigation/editor/navigation_mesh_editor_plugin.cpp +++ b/modules/navigation/editor/navigation_mesh_editor_plugin.cpp @@ -42,7 +42,6 @@ #include "scene/gui/button.h" #include "scene/gui/dialogs.h" #include "scene/gui/label.h" -#include "scene/resources/navigation_mesh_source_geometry_data_3d.h" void NavigationMeshEditor::_node_removed(Node *p_node) { if (p_node == node) { diff --git a/modules/openxr/doc_classes/OpenXRHand.xml b/modules/openxr/doc_classes/OpenXRHand.xml index 9cc548dd6f..23d932ddd7 100644 --- a/modules/openxr/doc_classes/OpenXRHand.xml +++ b/modules/openxr/doc_classes/OpenXRHand.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="OpenXRHand" inherits="SkeletonModifier3D" deprecated="Use [XRHandModifier3D] instead." xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> +<class name="OpenXRHand" inherits="Node3D" deprecated="Use [XRHandModifier3D] instead." xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> <brief_description> Node supporting hand and finger tracking in OpenXR. </brief_description> @@ -18,11 +18,14 @@ <member name="hand" type="int" setter="set_hand" getter="get_hand" enum="OpenXRHand.Hands" default="0"> Specifies whether this node tracks the left or right hand of the player. </member> + <member name="hand_skeleton" type="NodePath" setter="set_hand_skeleton" getter="get_hand_skeleton" default="NodePath("")"> + Set a [Skeleton3D] node for which the pose positions will be updated. + </member> <member name="motion_range" type="int" setter="set_motion_range" getter="get_motion_range" enum="OpenXRHand.MotionRange" default="0"> Set the motion range (if supported) limiting the hand motion. </member> <member name="skeleton_rig" type="int" setter="set_skeleton_rig" getter="get_skeleton_rig" enum="OpenXRHand.SkeletonRig" default="0"> - Set the type of skeleton rig the parent [Skeleton3D] is compliant with. + Set the type of skeleton rig the [member hand_skeleton] is compliant with. </member> </members> <constants> diff --git a/modules/openxr/scene/openxr_hand.cpp b/modules/openxr/scene/openxr_hand.cpp index f20d1f8e19..2a4104f6ee 100644 --- a/modules/openxr/scene/openxr_hand.cpp +++ b/modules/openxr/scene/openxr_hand.cpp @@ -40,6 +40,9 @@ void OpenXRHand::_bind_methods() { ClassDB::bind_method(D_METHOD("set_hand", "hand"), &OpenXRHand::set_hand); ClassDB::bind_method(D_METHOD("get_hand"), &OpenXRHand::get_hand); + ClassDB::bind_method(D_METHOD("set_hand_skeleton", "hand_skeleton"), &OpenXRHand::set_hand_skeleton); + ClassDB::bind_method(D_METHOD("get_hand_skeleton"), &OpenXRHand::get_hand_skeleton); + ClassDB::bind_method(D_METHOD("set_motion_range", "motion_range"), &OpenXRHand::set_motion_range); ClassDB::bind_method(D_METHOD("get_motion_range"), &OpenXRHand::get_motion_range); @@ -51,6 +54,7 @@ void OpenXRHand::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "hand", PROPERTY_HINT_ENUM, "Left,Right"), "set_hand", "get_hand"); ADD_PROPERTY(PropertyInfo(Variant::INT, "motion_range", PROPERTY_HINT_ENUM, "Unobstructed,Conform to controller"), "set_motion_range", "get_motion_range"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "hand_skeleton", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Skeleton3D"), "set_hand_skeleton", "get_hand_skeleton"); ADD_PROPERTY(PropertyInfo(Variant::INT, "skeleton_rig", PROPERTY_HINT_ENUM, "OpenXR,Humanoid"), "set_skeleton_rig", "get_skeleton_rig"); ADD_PROPERTY(PropertyInfo(Variant::INT, "bone_update", PROPERTY_HINT_ENUM, "Full,Rotation Only"), "set_bone_update", "get_bone_update"); @@ -86,6 +90,12 @@ OpenXRHand::Hands OpenXRHand::get_hand() const { return hand; } +void OpenXRHand::set_hand_skeleton(const NodePath &p_hand_skeleton) { + hand_skeleton = p_hand_skeleton; + + // TODO if inside tree call _get_bones() +} + void OpenXRHand::set_motion_range(MotionRange p_motion_range) { ERR_FAIL_INDEX(p_motion_range, MOTION_RANGE_MAX); motion_range = p_motion_range; @@ -97,6 +107,10 @@ OpenXRHand::MotionRange OpenXRHand::get_motion_range() const { return motion_range; } +NodePath OpenXRHand::get_hand_skeleton() const { + return hand_skeleton; +} + void OpenXRHand::_set_motion_range() { if (!hand_tracking_ext) { return; @@ -138,6 +152,20 @@ OpenXRHand::BoneUpdate OpenXRHand::get_bone_update() const { return bone_update; } +Skeleton3D *OpenXRHand::get_skeleton() { + if (!has_node(hand_skeleton)) { + return nullptr; + } + + Node *node = get_node(hand_skeleton); + if (!node) { + return nullptr; + } + + Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(node); + return skeleton; +} + void OpenXRHand::_get_joint_data() { // Table of bone names for different rig types. static const String bone_names[SKELETON_RIG_MAX][XR_HAND_JOINT_COUNT_EXT] = { @@ -262,7 +290,7 @@ void OpenXRHand::_get_joint_data() { } } -void OpenXRHand::_process_modification() { +void OpenXRHand::_update_skeleton() { if (openxr_api == nullptr || !openxr_api->is_initialized()) { return; } else if (hand_tracking_ext == nullptr || !hand_tracking_ext->get_active()) { @@ -367,14 +395,21 @@ void OpenXRHand::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { _get_joint_data(); + + set_process_internal(true); } break; case NOTIFICATION_EXIT_TREE: { + set_process_internal(false); + // reset for (int i = 0; i < XR_HAND_JOINT_COUNT_EXT; i++) { joints[i].bone = -1; joints[i].parent_joint = -1; } } break; + case NOTIFICATION_INTERNAL_PROCESS: { + _update_skeleton(); + } break; default: { } break; } diff --git a/modules/openxr/scene/openxr_hand.h b/modules/openxr/scene/openxr_hand.h index fc0a994f48..4c77e7277c 100644 --- a/modules/openxr/scene/openxr_hand.h +++ b/modules/openxr/scene/openxr_hand.h @@ -31,15 +31,16 @@ #ifndef OPENXR_HAND_H #define OPENXR_HAND_H -#include "scene/3d/skeleton_modifier_3d.h" +#include "scene/3d/node_3d.h" +#include "scene/3d/skeleton_3d.h" #include <openxr/openxr.h> class OpenXRAPI; class OpenXRHandTrackingExtension; -class OpenXRHand : public SkeletonModifier3D { - GDCLASS(OpenXRHand, SkeletonModifier3D); +class OpenXRHand : public Node3D { + GDCLASS(OpenXRHand, Node3D); public: enum Hands { // Deprecated, need to change this to OpenXRInterface::Hands. @@ -85,13 +86,13 @@ private: void _set_motion_range(); + Skeleton3D *get_skeleton(); void _get_joint_data(); + void _update_skeleton(); protected: static void _bind_methods(); - virtual void _process_modification() override; - public: OpenXRHand(); @@ -101,6 +102,9 @@ public: void set_motion_range(MotionRange p_motion_range); MotionRange get_motion_range() const; + void set_hand_skeleton(const NodePath &p_hand_skeleton); + NodePath get_hand_skeleton() const; + void set_skeleton_rig(SkeletonRig p_skeleton_rig); SkeletonRig get_skeleton_rig() const; diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp index affe163aeb..d903137195 100644 --- a/modules/svg/image_loader_svg.cpp +++ b/modules/svg/image_loader_svg.cpp @@ -173,9 +173,17 @@ void ImageLoaderSVG::get_recognized_extensions(List<String> *p_extensions) const } Error ImageLoaderSVG::load_image(Ref<Image> p_image, Ref<FileAccess> p_fileaccess, BitField<ImageFormatLoader::LoaderFlags> p_flags, float p_scale) { - String svg = p_fileaccess->get_as_utf8_string(); + const uint64_t len = p_fileaccess->get_length() - p_fileaccess->get_position(); + Vector<uint8_t> buffer; + buffer.resize(len); + p_fileaccess->get_buffer(buffer.ptrw(), buffer.size()); + + String svg; + Error err = svg.parse_utf8((const char *)buffer.ptr(), buffer.size()); + if (err != OK) { + return err; + } - Error err; if (p_flags & FLAG_CONVERT_COLORS) { err = create_image_from_string(p_image, svg, p_scale, false, forced_color_map); } else { |
