summaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/cvtt/image_compress_cvtt.cpp2
-rw-r--r--modules/gdscript/config.py1
-rw-r--r--modules/gdscript/doc_classes/GDScriptSyntaxHighlighter.xml23
-rw-r--r--modules/gdscript/gdscript_parser.cpp52
-rw-r--r--modules/gdscript/gdscript_parser.h8
-rw-r--r--modules/gdscript/register_types.cpp7
-rw-r--r--modules/gdscript/tests/scripts/completion/argument_options/string_literals/argument_options_inside_string_literal.cfg5
-rw-r--r--modules/gdscript/tests/scripts/completion/argument_options/string_literals/argument_options_inside_string_literal.gd8
-rw-r--r--modules/gdscript/tests/scripts/completion/common/identifiers_in_call.cfg (renamed from modules/gdscript/tests/scripts/completion/common/identifiers.cfg)6
-rw-r--r--modules/gdscript/tests/scripts/completion/common/identifiers_in_call.gd18
-rw-r--r--modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.cfg25
-rw-r--r--modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.gd (renamed from modules/gdscript/tests/scripts/completion/common/identifiers.gd)4
-rw-r--r--modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.cfg25
-rw-r--r--modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.gd22
-rw-r--r--modules/gdscript/tests/scripts/completion/common/no_completion_in_string.cfg26
-rw-r--r--modules/gdscript/tests/scripts/completion/common/no_completion_in_string.gd19
-rw-r--r--modules/gdscript/tests/scripts/completion/common/self.gd1
-rw-r--r--modules/gdscript/tests/scripts/completion/filter/organized_export.gd3
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/local_infered/local_infered.cfg (renamed from modules/gdscript/tests/scripts/completion/get_node/local_interfered/local_interfered.cfg)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/local_infered/local_infered.gd (renamed from modules/gdscript/tests/scripts/completion/get_node/local_interfered/local_interfered.gd)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/class_local_infered_scene.cfg (renamed from modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/class_local_interfered_scene.cfg)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/class_local_infered_scene.gd (renamed from modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/class_local_interfered_scene.gd)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/native_local_infered_scene.cfg (renamed from modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/native_local_interfered_scene.cfg)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/native_local_infered_scene.gd (renamed from modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/native_local_interfered_scene.gd)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/member_infered/member_infered.cfg (renamed from modules/gdscript/tests/scripts/completion/get_node/member_interfered/member_interfered.cfg)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/member_infered/member_infered.gd (renamed from modules/gdscript/tests/scripts/completion/get_node/member_interfered/member_interfered.gd)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/class_member_infered_scene.cfg (renamed from modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/class_member_interfered_scene.cfg)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/class_member_infered_scene.gd (renamed from modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/class_member_interfered_scene.gd)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/native_member_infered_scene.cfg (renamed from modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/native_member_interfered_scene.cfg)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/native_member_infered_scene.gd (renamed from modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/native_member_interfered_scene.gd)0
-rw-r--r--modules/gdscript/tests/scripts/completion/types/local/infered.cfg (renamed from modules/gdscript/tests/scripts/completion/types/local/interfered.cfg)0
-rw-r--r--modules/gdscript/tests/scripts/completion/types/local/infered.gd (renamed from modules/gdscript/tests/scripts/completion/types/local/interfered.gd)0
-rw-r--r--modules/gdscript/tests/scripts/completion/types/member/infered.cfg (renamed from modules/gdscript/tests/scripts/completion/types/member/interfered.cfg)0
-rw-r--r--modules/gdscript/tests/scripts/completion/types/member/infered.gd (renamed from modules/gdscript/tests/scripts/completion/types/member/interfered.gd)0
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs10
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs17
-rw-r--r--modules/openxr/extensions/openxr_hand_tracking_extension.cpp77
-rw-r--r--modules/openxr/extensions/openxr_hand_tracking_extension.h3
38 files changed, 304 insertions, 58 deletions
diff --git a/modules/cvtt/image_compress_cvtt.cpp b/modules/cvtt/image_compress_cvtt.cpp
index 4938d8bff5..a0578bbd9d 100644
--- a/modules/cvtt/image_compress_cvtt.cpp
+++ b/modules/cvtt/image_compress_cvtt.cpp
@@ -149,7 +149,7 @@ void image_compress_cvtt(Image *p_image, Image::UsedChannels p_channels) {
int h = p_image->get_height();
bool is_ldr = (p_image->get_format() <= Image::FORMAT_RGBA8);
- bool is_hdr = (p_image->get_format() >= Image::FORMAT_RH) && (p_image->get_format() <= Image::FORMAT_RGBE9995);
+ bool is_hdr = (p_image->get_format() >= Image::FORMAT_RF) && (p_image->get_format() <= Image::FORMAT_RGBE9995);
if (!is_ldr && !is_hdr) {
return; // Not a usable source format
diff --git a/modules/gdscript/config.py b/modules/gdscript/config.py
index a7d5c406e9..ecd33a5dac 100644
--- a/modules/gdscript/config.py
+++ b/modules/gdscript/config.py
@@ -11,6 +11,7 @@ def get_doc_classes():
return [
"@GDScript",
"GDScript",
+ "GDScriptSyntaxHighlighter",
]
diff --git a/modules/gdscript/doc_classes/GDScriptSyntaxHighlighter.xml b/modules/gdscript/doc_classes/GDScriptSyntaxHighlighter.xml
new file mode 100644
index 0000000000..63a9222901
--- /dev/null
+++ b/modules/gdscript/doc_classes/GDScriptSyntaxHighlighter.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="GDScriptSyntaxHighlighter" inherits="EditorSyntaxHighlighter" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
+ <brief_description>
+ A GDScript syntax highlighter that can be used with [TextEdit] and [CodeEdit] nodes.
+ </brief_description>
+ <description>
+ [b]Note:[/b] This class can only be used for editor plugins because it relies on editor settings.
+ [codeblocks]
+ [gdscript]
+ var code_preview = TextEdit.new()
+ var highlighter = GDScriptSyntaxHighlighter.new()
+ code_preview.syntax_highlighter = highlighter
+ [/gdscript]
+ [csharp]
+ var codePreview = new TextEdit();
+ var highlighter = new GDScriptSyntaxHighlighter();
+ codePreview.SyntaxHighlighter = highlighter;
+ [/csharp]
+ [/codeblocks]
+ </description>
+ <tutorials>
+ </tutorials>
+</class>
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 54bb152f7f..ecef852b4b 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -245,8 +245,26 @@ void GDScriptParser::apply_pending_warnings() {
}
#endif
-void GDScriptParser::make_completion_context(CompletionType p_type, Node *p_node, int p_argument, bool p_force) {
- if (!for_completion || (!p_force && completion_context.type != COMPLETION_NONE)) {
+void GDScriptParser::override_completion_context(const Node *p_for_node, CompletionType p_type, Node *p_node, int p_argument) {
+ if (!for_completion) {
+ return;
+ }
+ if (completion_context.node != p_for_node) {
+ return;
+ }
+ CompletionContext context;
+ context.type = p_type;
+ context.current_class = current_class;
+ context.current_function = current_function;
+ context.current_suite = current_suite;
+ context.current_line = tokenizer->get_cursor_line();
+ context.current_argument = p_argument;
+ context.node = p_node;
+ completion_context = context;
+}
+
+void GDScriptParser::make_completion_context(CompletionType p_type, Node *p_node, int p_argument) {
+ if (!for_completion) {
return;
}
if (previous.cursor_place != GDScriptTokenizerText::CURSOR_MIDDLE && previous.cursor_place != GDScriptTokenizerText::CURSOR_END && current.cursor_place == GDScriptTokenizerText::CURSOR_NONE) {
@@ -264,8 +282,8 @@ void GDScriptParser::make_completion_context(CompletionType p_type, Node *p_node
completion_context = context;
}
-void GDScriptParser::make_completion_context(CompletionType p_type, Variant::Type p_builtin_type, bool p_force) {
- if (!for_completion || (!p_force && completion_context.type != COMPLETION_NONE)) {
+void GDScriptParser::make_completion_context(CompletionType p_type, Variant::Type p_builtin_type) {
+ if (!for_completion) {
return;
}
if (previous.cursor_place != GDScriptTokenizerText::CURSOR_MIDDLE && previous.cursor_place != GDScriptTokenizerText::CURSOR_END && current.cursor_place == GDScriptTokenizerText::CURSOR_NONE) {
@@ -1620,7 +1638,7 @@ GDScriptParser::AnnotationNode *GDScriptParser::parse_annotation(uint32_t p_vali
advance();
// Arguments.
push_completion_call(annotation);
- make_completion_context(COMPLETION_ANNOTATION_ARGUMENTS, annotation, 0, true);
+ make_completion_context(COMPLETION_ANNOTATION_ARGUMENTS, annotation, 0);
int argument_index = 0;
do {
if (check(GDScriptTokenizer::Token::PARENTHESIS_CLOSE)) {
@@ -1628,7 +1646,7 @@ GDScriptParser::AnnotationNode *GDScriptParser::parse_annotation(uint32_t p_vali
break;
}
- make_completion_context(COMPLETION_ANNOTATION_ARGUMENTS, annotation, argument_index, true);
+ make_completion_context(COMPLETION_ANNOTATION_ARGUMENTS, annotation, argument_index);
set_last_completion_call_arg(argument_index++);
ExpressionNode *argument = parse_expression(false);
if (argument == nullptr) {
@@ -2569,8 +2587,11 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_literal(ExpressionNode *p_
}
LiteralNode *literal = alloc_node<LiteralNode>();
- complete_extents(literal);
literal->value = previous.literal;
+ reset_extents(literal, p_previous_operand);
+ update_extents(literal);
+ make_completion_context(COMPLETION_NONE, literal, -1);
+ complete_extents(literal);
return literal;
}
@@ -3065,12 +3086,12 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_attribute(ExpressionNode *
const IdentifierNode *id = static_cast<const IdentifierNode *>(p_previous_operand);
Variant::Type builtin_type = get_builtin_type(id->name);
if (builtin_type < Variant::VARIANT_MAX) {
- make_completion_context(COMPLETION_BUILT_IN_TYPE_CONSTANT_OR_STATIC_METHOD, builtin_type, true);
+ make_completion_context(COMPLETION_BUILT_IN_TYPE_CONSTANT_OR_STATIC_METHOD, builtin_type);
is_builtin = true;
}
}
if (!is_builtin) {
- make_completion_context(COMPLETION_ATTRIBUTE, attribute, -1, true);
+ make_completion_context(COMPLETION_ATTRIBUTE, attribute, -1);
}
}
@@ -3195,23 +3216,24 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre
push_completion_call(call);
int argument_index = 0;
do {
- make_completion_context(ct, call, argument_index++, true);
+ make_completion_context(ct, call, argument_index);
if (check(GDScriptTokenizer::Token::PARENTHESIS_CLOSE)) {
// Allow for trailing comma.
break;
}
- bool use_identifier_completion = current.cursor_place == GDScriptTokenizerText::CURSOR_END || current.cursor_place == GDScriptTokenizerText::CURSOR_MIDDLE;
ExpressionNode *argument = parse_expression(false);
if (argument == nullptr) {
push_error(R"(Expected expression as the function argument.)");
} else {
call->arguments.push_back(argument);
- if (argument->type == Node::IDENTIFIER && use_identifier_completion) {
- completion_context.type = COMPLETION_IDENTIFIER;
+ if (argument->type == Node::LITERAL) {
+ override_completion_context(argument, ct, call, argument_index);
}
}
+
ct = COMPLETION_CALL_ARGUMENTS;
+ argument_index++;
} while (match(GDScriptTokenizer::Token::COMMA));
pop_completion_call();
@@ -3224,7 +3246,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre
GDScriptParser::ExpressionNode *GDScriptParser::parse_get_node(ExpressionNode *p_previous_operand, bool p_can_assign) {
// We want code completion after a DOLLAR even if the current code is invalid.
- make_completion_context(COMPLETION_GET_NODE, nullptr, -1, true);
+ make_completion_context(COMPLETION_GET_NODE, nullptr, -1);
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()));
@@ -3281,7 +3303,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_get_node(ExpressionNode *p
path_state = PATH_STATE_SLASH;
}
- make_completion_context(COMPLETION_GET_NODE, get_node, context_argument++, true);
+ make_completion_context(COMPLETION_GET_NODE, get_node, context_argument++);
if (match(GDScriptTokenizer::Token::LITERAL)) {
if (previous.literal.get_type() != Variant::STRING) {
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index 60ee477656..2999fb11e4 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -1455,9 +1455,11 @@ private:
}
void apply_pending_warnings();
#endif
-
- void make_completion_context(CompletionType p_type, Node *p_node, int p_argument = -1, bool p_force = false);
- void make_completion_context(CompletionType p_type, Variant::Type p_builtin_type, bool p_force = false);
+ void make_completion_context(CompletionType p_type, Node *p_node, int p_argument = -1);
+ void make_completion_context(CompletionType p_type, Variant::Type p_builtin_type);
+ // In some cases it might become necessary to alter the completion context after parsing a subexpression.
+ // For example to not override COMPLETE_CALL_ARGUMENTS with COMPLETION_NONE from string literals.
+ void override_completion_context(const Node *p_for_node, CompletionType p_type, Node *p_node, int p_argument = -1);
void push_completion_call(Node *p_call);
void pop_completion_call();
void set_last_completion_call_arg(int p_argument);
diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp
index 59e387eece..055f8e4110 100644
--- a/modules/gdscript/register_types.cpp
+++ b/modules/gdscript/register_types.cpp
@@ -165,6 +165,13 @@ void initialize_gdscript_module(ModuleInitializationLevel p_level) {
gdscript_translation_parser_plugin.instantiate();
EditorTranslationParser::get_singleton()->add_parser(gdscript_translation_parser_plugin, EditorTranslationParser::STANDARD);
+ } else if (p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) {
+ ClassDB::APIType prev_api = ClassDB::get_current_api();
+ ClassDB::set_current_api(ClassDB::API_EDITOR);
+
+ GDREGISTER_CLASS(GDScriptSyntaxHighlighter);
+
+ ClassDB::set_current_api(prev_api);
}
#endif // TOOLS_ENABLED
}
diff --git a/modules/gdscript/tests/scripts/completion/argument_options/string_literals/argument_options_inside_string_literal.cfg b/modules/gdscript/tests/scripts/completion/argument_options/string_literals/argument_options_inside_string_literal.cfg
new file mode 100644
index 0000000000..be9bd510e1
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/argument_options/string_literals/argument_options_inside_string_literal.cfg
@@ -0,0 +1,5 @@
+[output]
+include=[
+ {"insert_text": "\"property_of_a\""},
+ {"insert_text": "\"name\""},
+]
diff --git a/modules/gdscript/tests/scripts/completion/argument_options/string_literals/argument_options_inside_string_literal.gd b/modules/gdscript/tests/scripts/completion/argument_options/string_literals/argument_options_inside_string_literal.gd
new file mode 100644
index 0000000000..a8e04a62a7
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/argument_options/string_literals/argument_options_inside_string_literal.gd
@@ -0,0 +1,8 @@
+extends Node
+
+const A = preload ("res://completion/class_a.notest.gd")
+
+func _ready() -> void:
+ var a := A.new()
+ var tween := get_tree().create_tween()
+ tween.tween_property(a, "➡")
diff --git a/modules/gdscript/tests/scripts/completion/common/identifiers.cfg b/modules/gdscript/tests/scripts/completion/common/identifiers_in_call.cfg
index 871a404e3a..5f08f9c265 100644
--- a/modules/gdscript/tests/scripts/completion/common/identifiers.cfg
+++ b/modules/gdscript/tests/scripts/completion/common/identifiers_in_call.cfg
@@ -11,11 +11,15 @@ include=[
{"display": "func_of_a"},
{"display": "signal_of_a"},
- ; GDScript: self.gd
+ ; GDScript: identifiers.gd
{"display": "test_signal_1"},
{"display": "test_signal_2"},
{"display": "test_var_1"},
{"display": "test_var_2"},
{"display": "test_func_1"},
{"display": "test_func_2"},
+ {"display": "test_parameter_1"},
+ {"display": "test_parameter_2"},
+ {"display": "local_test_var_1"},
+ {"display": "local_test_var_2"},
]
diff --git a/modules/gdscript/tests/scripts/completion/common/identifiers_in_call.gd b/modules/gdscript/tests/scripts/completion/common/identifiers_in_call.gd
new file mode 100644
index 0000000000..91488c25aa
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/common/identifiers_in_call.gd
@@ -0,0 +1,18 @@
+extends "res://completion/class_a.notest.gd"
+
+signal test_signal_1(a)
+signal test_signal_2(a: int)
+
+var test_var_1
+var test_var_2: int
+
+func test_func_1(t):
+ pass
+
+func test_func_2(t: int) -> void:
+ pass
+
+func _init(test_parameter_1, test_parameter_2: String):
+ var local_test_var_1
+ var local_test_var_2: int
+ print(t➡)
diff --git a/modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.cfg b/modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.cfg
new file mode 100644
index 0000000000..5f08f9c265
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.cfg
@@ -0,0 +1,25 @@
+scene="res://completion/get_node/get_node.tscn"
+[output]
+include=[
+ ; Node
+ {"display": "add_child"},
+ {"display": "owner"},
+ {"display": "child_entered_tree"},
+
+ ; GDScript: class_a.notest.gd
+ {"display": "property_of_a"},
+ {"display": "func_of_a"},
+ {"display": "signal_of_a"},
+
+ ; GDScript: identifiers.gd
+ {"display": "test_signal_1"},
+ {"display": "test_signal_2"},
+ {"display": "test_var_1"},
+ {"display": "test_var_2"},
+ {"display": "test_func_1"},
+ {"display": "test_func_2"},
+ {"display": "test_parameter_1"},
+ {"display": "test_parameter_2"},
+ {"display": "local_test_var_1"},
+ {"display": "local_test_var_2"},
+]
diff --git a/modules/gdscript/tests/scripts/completion/common/identifiers.gd b/modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.gd
index efbafbee8e..a2f5b7bc23 100644
--- a/modules/gdscript/tests/scripts/completion/common/identifiers.gd
+++ b/modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.gd
@@ -12,5 +12,7 @@ func test_func_1(t):
func test_func_2(t: int) -> void:
pass
-func _init():
+func _init(test_parameter_1, test_parameter_2: String):
+ var local_test_var_1
+ var local_test_var_2: int
t➡
diff --git a/modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.cfg b/modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.cfg
new file mode 100644
index 0000000000..5f08f9c265
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.cfg
@@ -0,0 +1,25 @@
+scene="res://completion/get_node/get_node.tscn"
+[output]
+include=[
+ ; Node
+ {"display": "add_child"},
+ {"display": "owner"},
+ {"display": "child_entered_tree"},
+
+ ; GDScript: class_a.notest.gd
+ {"display": "property_of_a"},
+ {"display": "func_of_a"},
+ {"display": "signal_of_a"},
+
+ ; GDScript: identifiers.gd
+ {"display": "test_signal_1"},
+ {"display": "test_signal_2"},
+ {"display": "test_var_1"},
+ {"display": "test_var_2"},
+ {"display": "test_func_1"},
+ {"display": "test_func_2"},
+ {"display": "test_parameter_1"},
+ {"display": "test_parameter_2"},
+ {"display": "local_test_var_1"},
+ {"display": "local_test_var_2"},
+]
diff --git a/modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.gd b/modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.gd
new file mode 100644
index 0000000000..fed0b869c4
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.gd
@@ -0,0 +1,22 @@
+# godotengine/godot#92226
+extends "res://completion/class_a.notest.gd"
+
+signal test_signal_1(a)
+signal test_signal_2(a: int)
+
+var test_var_1
+var test_var_2: int
+
+func test_func_1(t):
+ pass
+
+func test_func_2(t: int) -> void:
+ pass
+
+func _init(test_parameter_1, test_parameter_2: String):
+ var local_test_var_1
+ var local_test_var_2: int
+ print(t➡
+
+ if true:
+ pass
diff --git a/modules/gdscript/tests/scripts/completion/common/no_completion_in_string.cfg b/modules/gdscript/tests/scripts/completion/common/no_completion_in_string.cfg
new file mode 100644
index 0000000000..462846c9b2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/common/no_completion_in_string.cfg
@@ -0,0 +1,26 @@
+scene="res://completion/get_node/get_node.tscn"
+[output]
+exclude=[
+ ; Node
+ {"display": "add_child"},
+ {"display": "owner"},
+ {"display": "child_entered_tree"},
+ {"display": "add_child"},
+
+ ; GDScript: class_a.notest.gd
+ {"display": "property_of_a"},
+ {"display": "func_of_a"},
+ {"display": "signal_of_a"},
+
+ ; GDScript: no_completion_in_string.gd
+ {"display": "test_signal_1"},
+ {"display": "test_signal_2"},
+ {"display": "test_var_1"},
+ {"display": "test_var_2"},
+ {"display": "test_func_1"},
+ {"display": "test_func_2"},
+ {"display": "test_parameter_1"},
+ {"display": "test_parameter_2"},
+ {"display": "local_test_var_1"},
+ {"display": "local_test_var_2"},
+]
diff --git a/modules/gdscript/tests/scripts/completion/common/no_completion_in_string.gd b/modules/gdscript/tests/scripts/completion/common/no_completion_in_string.gd
new file mode 100644
index 0000000000..da52af9fe3
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/common/no_completion_in_string.gd
@@ -0,0 +1,19 @@
+# godotengine/godot#62945
+extends "res://completion/class_a.notest.gd"
+
+signal test_signal_1(a)
+signal test_signal_2(a: int)
+
+var test_var_1
+var test_var_2: int
+
+func test_func_1(t):
+ pass
+
+func test_func_2(t: int) -> void:
+ pass
+
+func _init(test_parameter_1, test_parameter_2: String):
+ var local_test_var_1
+ var local_test_var_2: int
+ var a = "➡"
diff --git a/modules/gdscript/tests/scripts/completion/common/self.gd b/modules/gdscript/tests/scripts/completion/common/self.gd
index 9ad2fbea51..ed181af0c5 100644
--- a/modules/gdscript/tests/scripts/completion/common/self.gd
+++ b/modules/gdscript/tests/scripts/completion/common/self.gd
@@ -14,3 +14,4 @@ func test_func_2(t: int) -> void:
func _init():
self.➡
+ pass
diff --git a/modules/gdscript/tests/scripts/completion/filter/organized_export.gd b/modules/gdscript/tests/scripts/completion/filter/organized_export.gd
index 189608904c..9fa9618cee 100644
--- a/modules/gdscript/tests/scripts/completion/filter/organized_export.gd
+++ b/modules/gdscript/tests/scripts/completion/filter/organized_export.gd
@@ -5,4 +5,5 @@ extends CPUParticles2D
@export_subgroup("Test Subgroup")
func _init():
- ➡
+ t➡
+ pass
diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_interfered/local_interfered.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_infered/local_infered.cfg
index ae7d34d87d..ae7d34d87d 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/local_interfered/local_interfered.cfg
+++ b/modules/gdscript/tests/scripts/completion/get_node/local_infered/local_infered.cfg
diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_interfered/local_interfered.gd b/modules/gdscript/tests/scripts/completion/get_node/local_infered/local_infered.gd
index 7710c2d13b..7710c2d13b 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/local_interfered/local_interfered.gd
+++ b/modules/gdscript/tests/scripts/completion/get_node/local_infered/local_infered.gd
diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/class_local_interfered_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/class_local_infered_scene.cfg
index 9c580b711d..9c580b711d 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/class_local_interfered_scene.cfg
+++ b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/class_local_infered_scene.cfg
diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/class_local_interfered_scene.gd b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/class_local_infered_scene.gd
index 6b29bf5526..6b29bf5526 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/class_local_interfered_scene.gd
+++ b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/class_local_infered_scene.gd
diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/native_local_interfered_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/native_local_infered_scene.cfg
index 446198dd35..446198dd35 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/native_local_interfered_scene.cfg
+++ b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/native_local_infered_scene.cfg
diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/native_local_interfered_scene.gd b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/native_local_infered_scene.gd
index 7710c2d13b..7710c2d13b 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/native_local_interfered_scene.gd
+++ b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/native_local_infered_scene.gd
diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_interfered/member_interfered.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_infered/member_infered.cfg
index ae7d34d87d..ae7d34d87d 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/member_interfered/member_interfered.cfg
+++ b/modules/gdscript/tests/scripts/completion/get_node/member_infered/member_infered.cfg
diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_interfered/member_interfered.gd b/modules/gdscript/tests/scripts/completion/get_node/member_infered/member_infered.gd
index 97b288334e..97b288334e 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/member_interfered/member_interfered.gd
+++ b/modules/gdscript/tests/scripts/completion/get_node/member_infered/member_infered.gd
diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/class_member_interfered_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/class_member_infered_scene.cfg
index 9c580b711d..9c580b711d 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/class_member_interfered_scene.cfg
+++ b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/class_member_infered_scene.cfg
diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/class_member_interfered_scene.gd b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/class_member_infered_scene.gd
index 402fd1d275..402fd1d275 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/class_member_interfered_scene.gd
+++ b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/class_member_infered_scene.gd
diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/native_member_interfered_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/native_member_infered_scene.cfg
index 446198dd35..446198dd35 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/native_member_interfered_scene.cfg
+++ b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/native_member_infered_scene.cfg
diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/native_member_interfered_scene.gd b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/native_member_infered_scene.gd
index 97b288334e..97b288334e 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/native_member_interfered_scene.gd
+++ b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/native_member_infered_scene.gd
diff --git a/modules/gdscript/tests/scripts/completion/types/local/interfered.cfg b/modules/gdscript/tests/scripts/completion/types/local/infered.cfg
index 8b68d51a89..8b68d51a89 100644
--- a/modules/gdscript/tests/scripts/completion/types/local/interfered.cfg
+++ b/modules/gdscript/tests/scripts/completion/types/local/infered.cfg
diff --git a/modules/gdscript/tests/scripts/completion/types/local/interfered.gd b/modules/gdscript/tests/scripts/completion/types/local/infered.gd
index f003c366a4..f003c366a4 100644
--- a/modules/gdscript/tests/scripts/completion/types/local/interfered.gd
+++ b/modules/gdscript/tests/scripts/completion/types/local/infered.gd
diff --git a/modules/gdscript/tests/scripts/completion/types/member/interfered.cfg b/modules/gdscript/tests/scripts/completion/types/member/infered.cfg
index 8b68d51a89..8b68d51a89 100644
--- a/modules/gdscript/tests/scripts/completion/types/member/interfered.cfg
+++ b/modules/gdscript/tests/scripts/completion/types/member/infered.cfg
diff --git a/modules/gdscript/tests/scripts/completion/types/member/interfered.gd b/modules/gdscript/tests/scripts/completion/types/member/infered.gd
index 069abd7891..069abd7891 100644
--- a/modules/gdscript/tests/scripts/completion/types/member/interfered.gd
+++ b/modules/gdscript/tests/scripts/completion/types/member/infered.gd
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
index 5cc2a8026e..901700067d 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
@@ -241,11 +241,17 @@ namespace Godot.Bridge
if (outIconPath != null)
{
- var iconAttr = scriptType.GetCustomAttributes(inherit: false)
+ IconAttribute? iconAttr = scriptType.GetCustomAttributes(inherit: false)
.OfType<IconAttribute>()
.FirstOrDefault();
- *outIconPath = Marshaling.ConvertStringToNative(iconAttr?.Path);
+ if (!string.IsNullOrEmpty(iconAttr?.Path))
+ {
+ string iconPath = iconAttr.Path.IsAbsolutePath()
+ ? iconAttr.Path.SimplifyPath()
+ : scriptPathStr.GetBaseDir().PathJoin(iconAttr.Path).SimplifyPath();
+ *outIconPath = Marshaling.ConvertStringToNative(iconPath);
+ }
}
if (outBaseType != null)
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
index a5fa89d3bf..f943a3049d 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
@@ -47,7 +47,7 @@ namespace Godot
{
get
{
- real_t detSign = Mathf.Sign(BasisDeterminant());
+ real_t detSign = Mathf.Sign(Determinant());
return new Vector2(X.Length(), detSign * Y.Length());
}
}
@@ -59,7 +59,7 @@ namespace Godot
{
get
{
- real_t detSign = Mathf.Sign(BasisDeterminant());
+ real_t detSign = Mathf.Sign(Determinant());
return Mathf.Acos(X.Normalized().Dot(detSign * Y.Normalized())) - Mathf.Pi * 0.5f;
}
}
@@ -135,7 +135,7 @@ namespace Godot
/// <returns>The inverse transformation matrix.</returns>
public readonly Transform2D AffineInverse()
{
- real_t det = BasisDeterminant();
+ real_t det = Determinant();
if (det == 0)
throw new InvalidOperationException("Matrix determinant is zero and cannot be inverted.");
@@ -157,15 +157,16 @@ namespace Godot
/// <summary>
/// Returns the determinant of the basis matrix. If the basis is
- /// uniformly scaled, its determinant is the square of the scale.
+ /// uniformly scaled, then its determinant equals the square of the
+ /// scale factor.
///
- /// A negative determinant means the Y scale is negative.
- /// A zero determinant means the basis isn't invertible,
- /// and is usually considered invalid.
+ /// A negative determinant means the basis was flipped, so one part of
+ /// the scale is negative. A zero determinant means the basis isn't
+ /// invertible, and is usually considered invalid.
/// </summary>
/// <returns>The determinant of the basis matrix.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private readonly real_t BasisDeterminant()
+ public readonly real_t Determinant()
{
return (X.X * Y.Y) - (X.Y * Y.X);
}
diff --git a/modules/openxr/extensions/openxr_hand_tracking_extension.cpp b/modules/openxr/extensions/openxr_hand_tracking_extension.cpp
index d9a66aa827..6d6231f6fa 100644
--- a/modules/openxr/extensions/openxr_hand_tracking_extension.cpp
+++ b/modules/openxr/extensions/openxr_hand_tracking_extension.cpp
@@ -58,9 +58,14 @@ OpenXRHandTrackingExtension::~OpenXRHandTrackingExtension() {
HashMap<String, bool *> OpenXRHandTrackingExtension::get_requested_extensions() {
HashMap<String, bool *> request_extensions;
+ unobstructed_data_source = GLOBAL_GET("xr/openxr/extensions/hand_tracking_unobstructed_data_source");
+ controller_data_source = GLOBAL_GET("xr/openxr/extensions/hand_tracking_controller_data_source");
+
request_extensions[XR_EXT_HAND_TRACKING_EXTENSION_NAME] = &hand_tracking_ext;
request_extensions[XR_EXT_HAND_JOINTS_MOTION_RANGE_EXTENSION_NAME] = &hand_motion_range_ext;
- request_extensions[XR_EXT_HAND_TRACKING_DATA_SOURCE_EXTENSION_NAME] = &hand_tracking_source_ext;
+ if (unobstructed_data_source || controller_data_source) {
+ request_extensions[XR_EXT_HAND_TRACKING_DATA_SOURCE_EXTENSION_NAME] = &hand_tracking_source_ext;
+ }
return request_extensions;
}
@@ -141,10 +146,18 @@ void OpenXRHandTrackingExtension::on_process() {
void *next_pointer = nullptr;
// Originally not all XR runtimes supported hand tracking data sourced both from controllers and normal hand tracking.
- // With this extension we can indicate we accept input from both sources so hand tracking data is consistently provided
- // on runtimes that support this.
- XrHandTrackingDataSourceEXT data_sources[2] = { XR_HAND_TRACKING_DATA_SOURCE_UNOBSTRUCTED_EXT, XR_HAND_TRACKING_DATA_SOURCE_CONTROLLER_EXT };
- XrHandTrackingDataSourceInfoEXT data_source_info = { XR_TYPE_HAND_TRACKING_DATA_SOURCE_INFO_EXT, next_pointer, 2, data_sources };
+ // With this extension we can indicate we wish to accept input from either or both sources.
+ // This functionality is subject to the abilities of the XR runtime and requires the data source extension.
+ // Note: If the data source extension is not available, no guarantees can be made on what the XR runtime supports.
+ uint32_t data_source_count = 0;
+ XrHandTrackingDataSourceEXT data_sources[2];
+ if (unobstructed_data_source) {
+ data_sources[data_source_count++] = XR_HAND_TRACKING_DATA_SOURCE_UNOBSTRUCTED_EXT;
+ }
+ if (controller_data_source) {
+ data_sources[data_source_count++] = XR_HAND_TRACKING_DATA_SOURCE_CONTROLLER_EXT;
+ }
+ XrHandTrackingDataSourceInfoEXT data_source_info = { XR_TYPE_HAND_TRACKING_DATA_SOURCE_INFO_EXT, next_pointer, data_source_count, data_sources };
if (hand_tracking_source_ext) {
// If supported include this info
next_pointer = &data_source_info;
@@ -224,7 +237,9 @@ void OpenXRHandTrackingExtension::on_process() {
if (XR_FAILED(result)) {
// not successful? then we do nothing.
print_line("OpenXR: Failed to get tracking for hand", i, "[", OpenXRAPI::get_singleton()->get_error_string(result), "]");
+ godot_tracker->set_hand_tracking_source(XRHandTracker::HAND_TRACKING_SOURCE_UNKNOWN);
godot_tracker->set_has_tracking_data(false);
+ godot_tracker->invalidate_pose("default");
continue;
}
@@ -235,8 +250,6 @@ void OpenXRHandTrackingExtension::on_process() {
}
if (hand_trackers[i].locations.isActive) {
- godot_tracker->set_has_tracking_data(true);
-
// SKELETON_RIG_HUMANOID bone adjustment. This rotation performs:
// OpenXR Z+ -> Godot Humanoid Y- (Back along the bone)
// OpenXR Y+ -> Godot Humanoid Z- (Out the back of the hand)
@@ -245,7 +258,6 @@ void OpenXRHandTrackingExtension::on_process() {
for (int joint = 0; joint < XR_HAND_JOINT_COUNT_EXT; joint++) {
const XrHandJointLocationEXT &location = hand_trackers[i].joint_locations[joint];
const XrHandJointVelocityEXT &velocity = hand_trackers[i].joint_velocities[joint];
- const XrHandTrackingDataSourceStateEXT &data_source = hand_trackers[i].data_source;
const XrPosef &pose = location.pose;
Transform3D transform;
@@ -285,23 +297,35 @@ void OpenXRHandTrackingExtension::on_process() {
godot_tracker->set_hand_joint_radius((XRHandTracker::HandJoint)joint, location.radius);
if (joint == XR_HAND_JOINT_PALM_EXT) {
- XRHandTracker::HandTrackingSource source = XRHandTracker::HAND_TRACKING_SOURCE_UNKNOWN;
- if (data_source.dataSource == XR_HAND_TRACKING_DATA_SOURCE_UNOBSTRUCTED_EXT) {
- source = XRHandTracker::HAND_TRACKING_SOURCE_UNOBSTRUCTED;
- } else if (data_source.dataSource == XR_HAND_TRACKING_DATA_SOURCE_CONTROLLER_EXT) {
- source = XRHandTracker::HAND_TRACKING_SOURCE_CONTROLLER;
- }
-
- godot_tracker->set_hand_tracking_source(source);
if (location.locationFlags & XR_SPACE_LOCATION_POSITION_TRACKED_BIT) {
+ XrHandTrackingDataSourceStateEXT &data_source = hand_trackers[i].data_source;
+
+ XRHandTracker::HandTrackingSource source = XRHandTracker::HAND_TRACKING_SOURCE_UNKNOWN;
+ if (hand_tracking_source_ext) {
+ if (!data_source.isActive) {
+ source = XRHandTracker::HAND_TRACKING_SOURCE_NOT_TRACKED;
+ } else if (data_source.dataSource == XR_HAND_TRACKING_DATA_SOURCE_UNOBSTRUCTED_EXT) {
+ source = XRHandTracker::HAND_TRACKING_SOURCE_UNOBSTRUCTED;
+ } else if (data_source.dataSource == XR_HAND_TRACKING_DATA_SOURCE_CONTROLLER_EXT) {
+ source = XRHandTracker::HAND_TRACKING_SOURCE_CONTROLLER;
+ } else {
+ // Data source shouldn't be active, if new data sources are added to OpenXR we need to enable them.
+ WARN_PRINT_ONCE("Unknown active data source found!");
+ source = XRHandTracker::HAND_TRACKING_SOURCE_UNKNOWN;
+ }
+ }
+ godot_tracker->set_hand_tracking_source(source);
+ godot_tracker->set_has_tracking_data(true);
godot_tracker->set_pose("default", transform, linear_velocity, angular_velocity);
} else {
+ godot_tracker->set_hand_tracking_source(hand_tracking_source_ext ? XRHandTracker::HAND_TRACKING_SOURCE_NOT_TRACKED : XRHandTracker::HAND_TRACKING_SOURCE_UNKNOWN);
godot_tracker->set_has_tracking_data(false);
godot_tracker->invalidate_pose("default");
}
}
}
} else {
+ godot_tracker->set_hand_tracking_source(hand_tracking_source_ext ? XRHandTracker::HAND_TRACKING_SOURCE_NOT_TRACKED : XRHandTracker::HAND_TRACKING_SOURCE_UNKNOWN);
godot_tracker->set_has_tracking_data(false);
godot_tracker->invalidate_pose("default");
}
@@ -349,16 +373,17 @@ XrHandJointsMotionRangeEXT OpenXRHandTrackingExtension::get_motion_range(HandTra
OpenXRHandTrackingExtension::HandTrackedSource OpenXRHandTrackingExtension::get_hand_tracking_source(HandTrackedHands p_hand) const {
ERR_FAIL_UNSIGNED_INDEX_V(p_hand, OPENXR_MAX_TRACKED_HANDS, OPENXR_SOURCE_UNKNOWN);
- if (hand_tracking_source_ext && hand_trackers[p_hand].data_source.isActive) {
- switch (hand_trackers[p_hand].data_source.dataSource) {
- case XR_HAND_TRACKING_DATA_SOURCE_UNOBSTRUCTED_EXT:
- return OPENXR_SOURCE_UNOBSTRUCTED;
-
- case XR_HAND_TRACKING_DATA_SOURCE_CONTROLLER_EXT:
- return OPENXR_SOURCE_CONTROLLER;
-
- default:
- return OPENXR_SOURCE_UNKNOWN;
+ if (hand_tracking_source_ext) {
+ if (!hand_trackers[p_hand].data_source.isActive) {
+ return OPENXR_SOURCE_NOT_TRACKED;
+ } else if (hand_trackers[p_hand].data_source.dataSource == XR_HAND_TRACKING_DATA_SOURCE_UNOBSTRUCTED_EXT) {
+ return OPENXR_SOURCE_UNOBSTRUCTED;
+ } else if (hand_trackers[p_hand].data_source.dataSource == XR_HAND_TRACKING_DATA_SOURCE_CONTROLLER_EXT) {
+ return OPENXR_SOURCE_CONTROLLER;
+ } else {
+ // Data source shouldn't be active, if new data sources are added to OpenXR we need to enable them.
+ WARN_PRINT_ONCE("Unknown active data source found!");
+ return OPENXR_SOURCE_UNKNOWN;
}
}
diff --git a/modules/openxr/extensions/openxr_hand_tracking_extension.h b/modules/openxr/extensions/openxr_hand_tracking_extension.h
index f709bc05c2..2c34ff7f21 100644
--- a/modules/openxr/extensions/openxr_hand_tracking_extension.h
+++ b/modules/openxr/extensions/openxr_hand_tracking_extension.h
@@ -48,6 +48,7 @@ public:
OPENXR_SOURCE_UNKNOWN,
OPENXR_SOURCE_UNOBSTRUCTED,
OPENXR_SOURCE_CONTROLLER,
+ OPENXR_SOURCE_NOT_TRACKED,
OPENXR_SOURCE_MAX
};
@@ -110,6 +111,8 @@ private:
bool hand_tracking_ext = false;
bool hand_motion_range_ext = false;
bool hand_tracking_source_ext = false;
+ bool unobstructed_data_source = false;
+ bool controller_data_source = false;
// functions
void cleanup_hand_tracking();