diff options
Diffstat (limited to 'modules')
46 files changed, 514 insertions, 20 deletions
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index ec20811385..279be65f03 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -3030,6 +3030,7 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a case Variant::PACKED_VECTOR2_ARRAY: case Variant::PACKED_VECTOR3_ARRAY: case Variant::PACKED_COLOR_ARRAY: + case Variant::PACKED_VECTOR4_ARRAY: safe_to_fold = false; break; default: @@ -4425,7 +4426,6 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri switch (base_type.builtin_type) { // Expect int or real as index. case Variant::PACKED_BYTE_ARRAY: - case Variant::PACKED_COLOR_ARRAY: case Variant::PACKED_FLOAT32_ARRAY: case Variant::PACKED_FLOAT64_ARRAY: case Variant::PACKED_INT32_ARRAY: @@ -4433,6 +4433,8 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri case Variant::PACKED_STRING_ARRAY: case Variant::PACKED_VECTOR2_ARRAY: case Variant::PACKED_VECTOR3_ARRAY: + case Variant::PACKED_COLOR_ARRAY: + case Variant::PACKED_VECTOR4_ARRAY: case Variant::ARRAY: case Variant::STRING: error = index_type.builtin_type != Variant::INT && index_type.builtin_type != Variant::FLOAT; @@ -4531,10 +4533,6 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri case Variant::QUATERNION: result_type.builtin_type = Variant::FLOAT; break; - // Return Color. - case Variant::PACKED_COLOR_ARRAY: - result_type.builtin_type = Variant::COLOR; - break; // Return String. case Variant::PACKED_STRING_ARRAY: case Variant::STRING: @@ -4556,6 +4554,14 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri case Variant::BASIS: result_type.builtin_type = Variant::VECTOR3; break; + // Return Color. + case Variant::PACKED_COLOR_ARRAY: + result_type.builtin_type = Variant::COLOR; + break; + // Return Vector4. + case Variant::PACKED_VECTOR4_ARRAY: + result_type.builtin_type = Variant::VECTOR4; + break; // Depends on the index. case Variant::TRANSFORM3D: case Variant::PROJECTION: diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp index 5a50bd8648..4cda3d3037 100644 --- a/modules/gdscript/gdscript_byte_codegen.cpp +++ b/modules/gdscript/gdscript_byte_codegen.cpp @@ -109,6 +109,7 @@ uint32_t GDScriptByteCodeGenerator::add_temporary(const GDScriptDataType &p_type case Variant::PACKED_VECTOR2_ARRAY: case Variant::PACKED_VECTOR3_ARRAY: case Variant::PACKED_COLOR_ARRAY: + case Variant::PACKED_VECTOR4_ARRAY: case Variant::VARIANT_MAX: // Arrays, dictionaries, and objects are reference counted, so we don't use the pool for them. temp_type = Variant::NIL; @@ -543,6 +544,9 @@ void GDScriptByteCodeGenerator::write_type_adjust(const Address &p_target, Varia case Variant::PACKED_COLOR_ARRAY: append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_COLOR_ARRAY); break; + case Variant::PACKED_VECTOR4_ARRAY: + append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_VECTOR4_ARRAY); + break; case Variant::NIL: case Variant::VARIANT_MAX: return; @@ -1573,6 +1577,10 @@ void GDScriptByteCodeGenerator::write_for(const Address &p_variable, bool p_use_ begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_COLOR_ARRAY; iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_COLOR_ARRAY; break; + case Variant::PACKED_VECTOR4_ARRAY: + begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_VECTOR4_ARRAY; + iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_VECTOR4_ARRAY; + break; default: break; } diff --git a/modules/gdscript/gdscript_disassembler.cpp b/modules/gdscript/gdscript_disassembler.cpp index 8dd04c76dd..0331045078 100644 --- a/modules/gdscript/gdscript_disassembler.cpp +++ b/modules/gdscript/gdscript_disassembler.cpp @@ -1046,6 +1046,7 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { m_macro(PACKED_VECTOR2_ARRAY); \ m_macro(PACKED_VECTOR3_ARRAY); \ m_macro(PACKED_COLOR_ARRAY); \ + m_macro(PACKED_VECTOR4_ARRAY); \ m_macro(OBJECT) case OPCODE_ITERATE_BEGIN: { @@ -1150,6 +1151,7 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { DISASSEMBLE_TYPE_ADJUST(PACKED_VECTOR2_ARRAY); DISASSEMBLE_TYPE_ADJUST(PACKED_VECTOR3_ARRAY); DISASSEMBLE_TYPE_ADJUST(PACKED_COLOR_ARRAY); + DISASSEMBLE_TYPE_ADJUST(PACKED_VECTOR4_ARRAY); case OPCODE_ASSERT: { text += "assert ("; diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index 430b96115b..759e92d68c 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -301,6 +301,7 @@ public: OPCODE_ITERATE_BEGIN_PACKED_VECTOR2_ARRAY, OPCODE_ITERATE_BEGIN_PACKED_VECTOR3_ARRAY, OPCODE_ITERATE_BEGIN_PACKED_COLOR_ARRAY, + OPCODE_ITERATE_BEGIN_PACKED_VECTOR4_ARRAY, OPCODE_ITERATE_BEGIN_OBJECT, OPCODE_ITERATE, OPCODE_ITERATE_INT, @@ -321,6 +322,7 @@ public: OPCODE_ITERATE_PACKED_VECTOR2_ARRAY, OPCODE_ITERATE_PACKED_VECTOR3_ARRAY, OPCODE_ITERATE_PACKED_COLOR_ARRAY, + OPCODE_ITERATE_PACKED_VECTOR4_ARRAY, OPCODE_ITERATE_OBJECT, OPCODE_STORE_GLOBAL, OPCODE_STORE_NAMED_GLOBAL, @@ -361,6 +363,7 @@ public: OPCODE_TYPE_ADJUST_PACKED_VECTOR2_ARRAY, OPCODE_TYPE_ADJUST_PACKED_VECTOR3_ARRAY, OPCODE_TYPE_ADJUST_PACKED_COLOR_ARRAY, + OPCODE_TYPE_ADJUST_PACKED_VECTOR4_ARRAY, OPCODE_ASSERT, OPCODE_BREAKPOINT, OPCODE_LINE, diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 9799c6e610..634d4fc867 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -4129,6 +4129,9 @@ static String _get_annotation_error_string(const StringName &p_annotation_name, case Variant::COLOR: types.push_back("PackedColorArray"); break; + case Variant::VECTOR4: + types.push_back("PackedVector4Array"); + break; default: break; } @@ -4827,6 +4830,8 @@ static Variant::Type _variant_type_to_typed_array_element_type(Variant::Type p_t return Variant::VECTOR3; case Variant::PACKED_COLOR_ARRAY: return Variant::COLOR; + case Variant::PACKED_VECTOR4_ARRAY: + return Variant::VECTOR4; default: return Variant::NIL; } diff --git a/modules/gdscript/gdscript_utility_functions.cpp b/modules/gdscript/gdscript_utility_functions.cpp index e5b0f55df8..f0816650b9 100644 --- a/modules/gdscript/gdscript_utility_functions.cpp +++ b/modules/gdscript/gdscript_utility_functions.cpp @@ -519,6 +519,10 @@ struct GDScriptUtilityFunctionsDefinitions { Vector<Color> d = *p_args[0]; *r_ret = d.size(); } break; + case Variant::PACKED_VECTOR4_ARRAY: { + Vector<Vector4> d = *p_args[0]; + *r_ret = d.size(); + } break; default: { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index 4e76965889..11bd1d224a 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -208,6 +208,7 @@ void (*type_init_function_table[])(Variant *) = { &VariantInitializer<PackedVector2Array>::init, // PACKED_VECTOR2_ARRAY. &VariantInitializer<PackedVector3Array>::init, // PACKED_VECTOR3_ARRAY. &VariantInitializer<PackedColorArray>::init, // PACKED_COLOR_ARRAY. + &VariantInitializer<PackedVector4Array>::init, // PACKED_VECTOR4_ARRAY. }; #if defined(__GNUC__) @@ -298,6 +299,7 @@ void (*type_init_function_table[])(Variant *) = { &&OPCODE_ITERATE_BEGIN_PACKED_VECTOR2_ARRAY, \ &&OPCODE_ITERATE_BEGIN_PACKED_VECTOR3_ARRAY, \ &&OPCODE_ITERATE_BEGIN_PACKED_COLOR_ARRAY, \ + &&OPCODE_ITERATE_BEGIN_PACKED_VECTOR4_ARRAY, \ &&OPCODE_ITERATE_BEGIN_OBJECT, \ &&OPCODE_ITERATE, \ &&OPCODE_ITERATE_INT, \ @@ -318,6 +320,7 @@ void (*type_init_function_table[])(Variant *) = { &&OPCODE_ITERATE_PACKED_VECTOR2_ARRAY, \ &&OPCODE_ITERATE_PACKED_VECTOR3_ARRAY, \ &&OPCODE_ITERATE_PACKED_COLOR_ARRAY, \ + &&OPCODE_ITERATE_PACKED_VECTOR4_ARRAY, \ &&OPCODE_ITERATE_OBJECT, \ &&OPCODE_STORE_GLOBAL, \ &&OPCODE_STORE_NAMED_GLOBAL, \ @@ -358,6 +361,7 @@ void (*type_init_function_table[])(Variant *) = { &&OPCODE_TYPE_ADJUST_PACKED_VECTOR2_ARRAY, \ &&OPCODE_TYPE_ADJUST_PACKED_VECTOR3_ARRAY, \ &&OPCODE_TYPE_ADJUST_PACKED_COLOR_ARRAY, \ + &&OPCODE_TYPE_ADJUST_PACKED_VECTOR4_ARRAY, \ &&OPCODE_ASSERT, \ &&OPCODE_BREAKPOINT, \ &&OPCODE_LINE, \ @@ -430,6 +434,7 @@ void (*type_init_function_table[])(Variant *) = { #define OP_GET_PACKED_VECTOR2_ARRAY get_vector2_array #define OP_GET_PACKED_VECTOR3_ARRAY get_vector3_array #define OP_GET_PACKED_COLOR_ARRAY get_color_array +#define OP_GET_PACKED_VECTOR4_ARRAY get_vector4_array #define OP_GET_TRANSFORM3D get_transform #define OP_GET_TRANSFORM2D get_transform2d #define OP_GET_PROJECTION get_projection @@ -3059,6 +3064,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE_ITERATE_BEGIN_PACKED_ARRAY(VECTOR2, Vector2, get_vector2_array, VECTOR2, Vector2, get_vector2); OPCODE_ITERATE_BEGIN_PACKED_ARRAY(VECTOR3, Vector3, get_vector3_array, VECTOR3, Vector3, get_vector3); OPCODE_ITERATE_BEGIN_PACKED_ARRAY(COLOR, Color, get_color_array, COLOR, Color, get_color); + OPCODE_ITERATE_BEGIN_PACKED_ARRAY(VECTOR4, Vector4, get_vector4_array, VECTOR4, Vector4, get_vector4); OPCODE(OPCODE_ITERATE_BEGIN_OBJECT) { CHECK_SPACE(4); @@ -3394,6 +3400,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE_ITERATE_PACKED_ARRAY(VECTOR2, Vector2, get_vector2_array, get_vector2); OPCODE_ITERATE_PACKED_ARRAY(VECTOR3, Vector3, get_vector3_array, get_vector3); OPCODE_ITERATE_PACKED_ARRAY(COLOR, Color, get_color_array, get_color); + OPCODE_ITERATE_PACKED_ARRAY(VECTOR4, Vector4, get_vector4_array, get_vector4); OPCODE(OPCODE_ITERATE_OBJECT) { CHECK_SPACE(4); @@ -3525,6 +3532,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE_TYPE_ADJUST(PACKED_VECTOR2_ARRAY, PackedVector2Array); OPCODE_TYPE_ADJUST(PACKED_VECTOR3_ARRAY, PackedVector3Array); OPCODE_TYPE_ADJUST(PACKED_COLOR_ARRAY, PackedColorArray); + OPCODE_TYPE_ADJUST(PACKED_VECTOR4_ARRAY, PackedVector4Array); OPCODE(OPCODE_ASSERT) { CHECK_SPACE(3); diff --git a/modules/gdscript/tests/scripts/analyzer/features/boolean_operators_for_all_types.gd b/modules/gdscript/tests/scripts/analyzer/features/boolean_operators_for_all_types.gd index 73d0f9096c..18675e5725 100644 --- a/modules/gdscript/tests/scripts/analyzer/features/boolean_operators_for_all_types.gd +++ b/modules/gdscript/tests/scripts/analyzer/features/boolean_operators_for_all_types.gd @@ -345,3 +345,12 @@ func test(): prints(x and true) prints(x or false) prints(x or true) + + # TYPE_PACKED_VECTOR4_ARRAY + x = PackedVector4Array([Vector4.ONE]) + prints("TYPE_PACKED_VECTOR4_ARRAY") + prints(not x) + prints(x and false) + prints(x and true) + prints(x or false) + prints(x or true) diff --git a/modules/gdscript/tests/scripts/analyzer/features/boolean_operators_for_all_types.out b/modules/gdscript/tests/scripts/analyzer/features/boolean_operators_for_all_types.out index e2945c910a..47f9d7548b 100644 --- a/modules/gdscript/tests/scripts/analyzer/features/boolean_operators_for_all_types.out +++ b/modules/gdscript/tests/scripts/analyzer/features/boolean_operators_for_all_types.out @@ -227,3 +227,9 @@ false true true true +TYPE_PACKED_VECTOR4_ARRAY +false +false +true +true +true diff --git a/modules/gdscript/tests/scripts/parser/features/export_arrays.gd b/modules/gdscript/tests/scripts/parser/features/export_arrays.gd index ddfb186aa4..0d97135a7b 100644 --- a/modules/gdscript/tests/scripts/parser/features/export_arrays.gd +++ b/modules/gdscript/tests/scripts/parser/features/export_arrays.gd @@ -63,6 +63,7 @@ var temp_packed_float64_array: PackedFloat64Array var temp_packed_color_array: PackedColorArray var temp_packed_vector2_array: PackedVector2Array var temp_packed_vector3_array: PackedVector3Array +var temp_packed_vector4_array: PackedVector4Array @export var test_weak_packed_byte_array = temp_packed_byte_array @export var test_weak_packed_int32_array = temp_packed_int32_array @@ -72,6 +73,7 @@ var temp_packed_vector3_array: PackedVector3Array @export var test_weak_packed_color_array = temp_packed_color_array @export var test_weak_packed_vector2_array = temp_packed_vector2_array @export var test_weak_packed_vector3_array = temp_packed_vector3_array +@export var test_weak_packed_vector4_array = temp_packed_vector4_array @export_range(1, 10) var test_range_weak_packed_byte_array = temp_packed_byte_array @export_range(1, 10) var test_range_weak_packed_int32_array = temp_packed_int32_array diff --git a/modules/gdscript/tests/scripts/parser/features/export_arrays.out b/modules/gdscript/tests/scripts/parser/features/export_arrays.out index 00e75fcc43..acbf389645 100644 --- a/modules/gdscript/tests/scripts/parser/features/export_arrays.out +++ b/modules/gdscript/tests/scripts/parser/features/export_arrays.out @@ -123,6 +123,8 @@ var test_weak_packed_vector2_array: PackedVector2Array hint=TYPE_STRING hint_string="Vector2:Vector2" usage=DEFAULT|SCRIPT_VARIABLE var test_weak_packed_vector3_array: PackedVector3Array hint=TYPE_STRING hint_string="Vector3:Vector3" usage=DEFAULT|SCRIPT_VARIABLE +var test_weak_packed_vector4_array: PackedVector4Array + hint=TYPE_STRING hint_string="Vector4:Vector4" usage=DEFAULT|SCRIPT_VARIABLE var test_range_weak_packed_byte_array: PackedByteArray hint=TYPE_STRING hint_string="int/RANGE:1,10" usage=DEFAULT|SCRIPT_VARIABLE var test_range_weak_packed_int32_array: PackedInt32Array diff --git a/modules/gdscript/tests/scripts/runtime/features/compare_builtin_equals_null.gd b/modules/gdscript/tests/scripts/runtime/features/compare_builtin_equals_null.gd index 809d0d28a9..5d8dafc4a1 100644 --- a/modules/gdscript/tests/scripts/runtime/features/compare_builtin_equals_null.gd +++ b/modules/gdscript/tests/scripts/runtime/features/compare_builtin_equals_null.gd @@ -140,3 +140,7 @@ func test(): # PackedColorArray value = PackedColorArray() print(value == null) + + # PackedVector4Array + value = PackedVector4Array() + print(value == null) diff --git a/modules/gdscript/tests/scripts/runtime/features/compare_builtin_equals_null.out b/modules/gdscript/tests/scripts/runtime/features/compare_builtin_equals_null.out index 27423ab8e7..e0e222eccc 100644 --- a/modules/gdscript/tests/scripts/runtime/features/compare_builtin_equals_null.out +++ b/modules/gdscript/tests/scripts/runtime/features/compare_builtin_equals_null.out @@ -34,3 +34,4 @@ false false false false +false diff --git a/modules/gdscript/tests/scripts/runtime/features/compare_builtin_not_equals_null.gd b/modules/gdscript/tests/scripts/runtime/features/compare_builtin_not_equals_null.gd index f46afb0f18..88286ede03 100644 --- a/modules/gdscript/tests/scripts/runtime/features/compare_builtin_not_equals_null.gd +++ b/modules/gdscript/tests/scripts/runtime/features/compare_builtin_not_equals_null.gd @@ -140,3 +140,7 @@ func test(): # PackedColorArray value = PackedColorArray() print(value != null) + + # PackedVector4Array + value = PackedVector4Array() + print(value != null) diff --git a/modules/gdscript/tests/scripts/runtime/features/compare_builtin_not_equals_null.out b/modules/gdscript/tests/scripts/runtime/features/compare_builtin_not_equals_null.out index a11c47854a..f6e72aedd5 100644 --- a/modules/gdscript/tests/scripts/runtime/features/compare_builtin_not_equals_null.out +++ b/modules/gdscript/tests/scripts/runtime/features/compare_builtin_not_equals_null.out @@ -34,3 +34,4 @@ true true true true +true diff --git a/modules/gdscript/tests/scripts/runtime/features/compare_null_equals_builtin.gd b/modules/gdscript/tests/scripts/runtime/features/compare_null_equals_builtin.gd index 7649062fda..6ca1b3e490 100644 --- a/modules/gdscript/tests/scripts/runtime/features/compare_null_equals_builtin.gd +++ b/modules/gdscript/tests/scripts/runtime/features/compare_null_equals_builtin.gd @@ -136,3 +136,7 @@ func test(): # PackedColorArray value = PackedColorArray() print(null == value) + + # PackedVector4Array + value = PackedVector4Array() + print(null == value) diff --git a/modules/gdscript/tests/scripts/runtime/features/compare_null_equals_builtin.out b/modules/gdscript/tests/scripts/runtime/features/compare_null_equals_builtin.out index 639f6027b9..27423ab8e7 100644 --- a/modules/gdscript/tests/scripts/runtime/features/compare_null_equals_builtin.out +++ b/modules/gdscript/tests/scripts/runtime/features/compare_null_equals_builtin.out @@ -33,3 +33,4 @@ false false false false +false diff --git a/modules/gdscript/tests/scripts/runtime/features/compare_null_not_equals_builtin.gd b/modules/gdscript/tests/scripts/runtime/features/compare_null_not_equals_builtin.gd index 8d5f9df1b8..d7addfa390 100644 --- a/modules/gdscript/tests/scripts/runtime/features/compare_null_not_equals_builtin.gd +++ b/modules/gdscript/tests/scripts/runtime/features/compare_null_not_equals_builtin.gd @@ -136,3 +136,7 @@ func test(): # PackedColorArray value = PackedColorArray() print(null != value) + + # PackedVector4Array + value = PackedVector4Array() + print(null != value) diff --git a/modules/gdscript/tests/scripts/runtime/features/compare_null_not_equals_builtin.out b/modules/gdscript/tests/scripts/runtime/features/compare_null_not_equals_builtin.out index d1e332afba..a11c47854a 100644 --- a/modules/gdscript/tests/scripts/runtime/features/compare_null_not_equals_builtin.out +++ b/modules/gdscript/tests/scripts/runtime/features/compare_null_not_equals_builtin.out @@ -33,3 +33,4 @@ true true true true +true diff --git a/modules/gdscript/tests/scripts/runtime/features/stringify.gd b/modules/gdscript/tests/scripts/runtime/features/stringify.gd index 0dbb252b0e..8579baf876 100644 --- a/modules/gdscript/tests/scripts/runtime/features/stringify.gd +++ b/modules/gdscript/tests/scripts/runtime/features/stringify.gd @@ -40,3 +40,4 @@ func test(): print(PackedVector2Array([Vector2.ONE, Vector2.ZERO])) print(PackedVector3Array([Vector3.ONE, Vector3.ZERO])) print(PackedColorArray([Color.RED, Color.BLUE, Color.GREEN])) + print(PackedVector4Array([Vector4.ONE, Vector4.ZERO])) diff --git a/modules/gdscript/tests/scripts/runtime/features/stringify.out b/modules/gdscript/tests/scripts/runtime/features/stringify.out index 1f33de00cc..7833b6e213 100644 --- a/modules/gdscript/tests/scripts/runtime/features/stringify.out +++ b/modules/gdscript/tests/scripts/runtime/features/stringify.out @@ -32,3 +32,4 @@ Node::[signal]property_list_changed [(1, 1), (0, 0)] [(1, 1, 1), (0, 0, 0)] [(1, 0, 0, 1), (0, 0, 1, 1), (0, 1, 0, 1)] +[(1, 1, 1, 1), (0, 0, 0, 0)] diff --git a/modules/mobile_vr/doc_classes/MobileVRInterface.xml b/modules/mobile_vr/doc_classes/MobileVRInterface.xml index 8338054142..0dbe06d220 100644 --- a/modules/mobile_vr/doc_classes/MobileVRInterface.xml +++ b/modules/mobile_vr/doc_classes/MobileVRInterface.xml @@ -40,6 +40,14 @@ <member name="oversample" type="float" setter="set_oversample" getter="get_oversample" default="1.5"> The oversample setting. Because of the lens distortion we have to render our buffers at a higher resolution then the screen can natively handle. A value between 1.5 and 2.0 often provides good results but at the cost of performance. </member> + <member name="vrs_min_radius" type="float" setter="set_vrs_min_radius" getter="get_vrs_min_radius" default="20.0"> + The minimum radius around the focal point where full quality is guaranteed if VRS is used as a percentage of screen size. + [b]Note:[/b] Mobile and Forward+ renderers only. Requires [member Viewport.vrs_mode] to be set to [constant Viewport.VRS_XR]. + </member> + <member name="vrs_strength" type="float" setter="set_vrs_strength" getter="get_vrs_strength" default="1.0"> + The strength used to calculate the VRS density map. The greater this value, the more noticeable VRS is. This improves performance at the cost of quality. + [b]Note:[/b] Mobile and Forward+ renderers only. Requires [member Viewport.vrs_mode] to be set to [constant Viewport.VRS_XR]. + </member> <member name="xr_play_area_mode" type="int" setter="set_play_area_mode" getter="get_play_area_mode" overrides="XRInterface" enum="XRInterface.PlayAreaMode" default="1" /> </members> </class> diff --git a/modules/mobile_vr/mobile_vr_interface.cpp b/modules/mobile_vr/mobile_vr_interface.cpp index d23edcd1d1..f27281866a 100644 --- a/modules/mobile_vr/mobile_vr_interface.cpp +++ b/modules/mobile_vr/mobile_vr_interface.cpp @@ -250,6 +250,16 @@ void MobileVRInterface::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "oversample", PROPERTY_HINT_RANGE, "1.0,2.0,0.1"), "set_oversample", "get_oversample"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "k1", PROPERTY_HINT_RANGE, "0.1,10.0,0.0001"), "set_k1", "get_k1"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "k2", PROPERTY_HINT_RANGE, "0.1,10.0,0.0001"), "set_k2", "get_k2"); + + ClassDB::bind_method(D_METHOD("get_vrs_min_radius"), &MobileVRInterface::get_vrs_min_radius); + ClassDB::bind_method(D_METHOD("set_vrs_min_radius", "radius"), &MobileVRInterface::set_vrs_min_radius); + + ClassDB::bind_method(D_METHOD("get_vrs_strength"), &MobileVRInterface::get_vrs_strength); + ClassDB::bind_method(D_METHOD("set_vrs_strength", "strength"), &MobileVRInterface::set_vrs_strength); + + ADD_GROUP("Vulkan VRS", "vrs_"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "vrs_min_radius", PROPERTY_HINT_RANGE, "1.0,100.0,1.0"), "set_vrs_min_radius", "get_vrs_min_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "vrs_strength", PROPERTY_HINT_RANGE, "0.1,10.0,0.1"), "set_vrs_strength", "get_vrs_strength"); } void MobileVRInterface::set_eye_height(const double p_eye_height) { @@ -316,6 +326,22 @@ double MobileVRInterface::get_k2() const { return k2; }; +float MobileVRInterface::get_vrs_min_radius() const { + return xr_vrs.get_vrs_min_radius(); +} + +void MobileVRInterface::set_vrs_min_radius(float p_vrs_min_radius) { + xr_vrs.set_vrs_min_radius(p_vrs_min_radius); +} + +float MobileVRInterface::get_vrs_strength() const { + return xr_vrs.get_vrs_strength(); +} + +void MobileVRInterface::set_vrs_strength(float p_vrs_strength) { + xr_vrs.set_vrs_strength(p_vrs_strength); +} + uint32_t MobileVRInterface::get_view_count() { // needs stereo... return 2; @@ -489,11 +515,16 @@ Vector<BlitToScreen> MobileVRInterface::post_draw_viewport(RID p_render_target, Vector<BlitToScreen> blit_to_screen; - // We must have a valid render target + // We must have a valid render target. ERR_FAIL_COND_V(!p_render_target.is_valid(), blit_to_screen); - // Because we are rendering to our device we must use our main viewport! - ERR_FAIL_COND_V(p_screen_rect == Rect2(), blit_to_screen); + // We will only output to screen if this is our main viewport. + if (p_screen_rect == Rect2()) { + // Warn the developer once, it's up to the developer to output to screen. + WARN_PRINT_ONCE("SubViewport used with MobileVRInterface, no output to screen"); + + return blit_to_screen; + } Rect2 modified_screen_rect = Rect2(p_screen_rect.position + offset_rect.position * p_screen_rect.size, p_screen_rect.size * offset_rect.size); @@ -542,6 +573,23 @@ void MobileVRInterface::process() { }; }; +RID MobileVRInterface::get_vrs_texture() { + PackedVector2Array eye_foci; + + Size2 target_size = get_render_target_size(); + real_t aspect_ratio = target_size.x / target_size.y; + uint32_t view_count = get_view_count(); + + for (uint32_t v = 0; v < view_count; v++) { + Projection cm = get_projection_for_view(v, aspect_ratio, 0.1, 1000.0); + Vector3 center = cm.xform(Vector3(0.0, 0.0, 999.0)); + + eye_foci.push_back(Vector2(center.x, center.y)); + } + + return xr_vrs.make_vrs_texture(target_size, eye_foci); +} + MobileVRInterface::MobileVRInterface() {} MobileVRInterface::~MobileVRInterface() { diff --git a/modules/mobile_vr/mobile_vr_interface.h b/modules/mobile_vr/mobile_vr_interface.h index e1d43fff74..490b1c393c 100644 --- a/modules/mobile_vr/mobile_vr_interface.h +++ b/modules/mobile_vr/mobile_vr_interface.h @@ -33,6 +33,7 @@ #include "servers/xr/xr_interface.h" #include "servers/xr/xr_positional_tracker.h" +#include "servers/xr/xr_vrs.h" /** The mobile interface is a native VR interface that can be used on Android and iOS phones. @@ -72,6 +73,8 @@ private: Ref<XRPositionalTracker> head; Transform3D head_transform; + XRVRS xr_vrs; + /* logic for processing our sensor data, this was originally in our positional tracker logic but I think that doesn't make sense in hindsight. It only makes marginally more sense to park it here for now, @@ -138,6 +141,12 @@ public: void set_k2(const double p_k2); double get_k2() const; + float get_vrs_min_radius() const; + void set_vrs_min_radius(float p_vrs_min_radius); + + float get_vrs_strength() const; + void set_vrs_strength(float p_vrs_strength); + virtual StringName get_name() const override; virtual uint32_t get_capabilities() const override; @@ -161,6 +170,8 @@ public: virtual void process() override; + virtual RID get_vrs_texture() override; + MobileVRInterface(); ~MobileVRInterface(); }; diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs index 834beaa131..4cf6a9f431 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs @@ -44,7 +44,8 @@ namespace Godot.SourceGenerators PackedVector2Array = 35, PackedVector3Array = 36, PackedColorArray = 37, - Max = 38 + PackedVector4Array = 38, + Max = 39 } internal enum PropertyHint diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs index be6af117eb..bfb735e72f 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs @@ -51,6 +51,7 @@ namespace Godot.SourceGenerators StringArray, Vector2Array, Vector3Array, + Vector4Array, ColorArray, GodotObjectOrDerivedArray, SystemArrayOfStringName, diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs index 0258f53062..d272832950 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs @@ -66,6 +66,7 @@ namespace Godot.SourceGenerators MarshalType.StringArray => VariantType.PackedStringArray, MarshalType.Vector2Array => VariantType.PackedVector2Array, MarshalType.Vector3Array => VariantType.PackedVector3Array, + MarshalType.Vector4Array => VariantType.PackedVector4Array, MarshalType.ColorArray => VariantType.PackedColorArray, MarshalType.GodotObjectOrDerivedArray => VariantType.Array, MarshalType.SystemArrayOfStringName => VariantType.Array, @@ -190,6 +191,8 @@ namespace Godot.SourceGenerators return MarshalType.Vector2Array; case { Name: "Vector3" }: return MarshalType.Vector3Array; + case { Name: "Vector4" }: + return MarshalType.Vector4Array; case { Name: "Color" }: return MarshalType.ColorArray; case { Name: "StringName" }: diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index e1ce41edd5..db86693a58 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -330,6 +330,8 @@ String BindingsGenerator::bbcode_to_text(const String &p_bbcode, const TypeInter output.append("'" BINDINGS_NAMESPACE ".Vector3[]'"); } else if (tag == "PackedColorArray") { output.append("'" BINDINGS_NAMESPACE ".Color[]'"); + } else if (tag == "PackedVector4Array") { + output.append("'" BINDINGS_NAMESPACE ".Vector4[]'"); } else { const TypeInterface *target_itype = _get_type_or_null(TypeReference(tag)); @@ -646,6 +648,8 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".Vector3\"/>[]"); } else if (tag == "PackedColorArray") { xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".Color\"/>[]"); + } else if (tag == "PackedVector4Array") { + xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".Vector4\"/>[]"); } else { const TypeInterface *target_itype = _get_type_or_null(TypeReference(tag)); @@ -3516,6 +3520,7 @@ bool BindingsGenerator::_arg_default_value_is_assignable_to_type(const Variant & case Variant::PACKED_STRING_ARRAY: case Variant::PACKED_VECTOR2_ARRAY: case Variant::PACKED_VECTOR3_ARRAY: + case Variant::PACKED_VECTOR4_ARRAY: case Variant::PACKED_COLOR_ARRAY: case Variant::CALLABLE: case Variant::SIGNAL: @@ -4246,6 +4251,7 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar case Variant::PACKED_STRING_ARRAY: case Variant::PACKED_VECTOR2_ARRAY: case Variant::PACKED_VECTOR3_ARRAY: + case Variant::PACKED_VECTOR4_ARRAY: case Variant::PACKED_COLOR_ARRAY: r_iarg.default_argument = "Array.Empty<%s>()"; r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF; @@ -4585,6 +4591,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { INSERT_ARRAY(PackedColorArray, godot_packed_color_array, Color); INSERT_ARRAY(PackedVector2Array, godot_packed_vector2_array, Vector2); INSERT_ARRAY(PackedVector3Array, godot_packed_vector3_array, Vector3); + INSERT_ARRAY(PackedVector4Array, godot_packed_vector4_array, Vector4); #undef INSERT_ARRAY diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h index a397dcb026..556d287af4 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -705,7 +705,7 @@ class BindingsGenerator { StringName type_Vector4i = StaticCString::create("Vector4i"); // Object not included as it must be checked for all derived classes - static constexpr int nullable_types_count = 18; + static constexpr int nullable_types_count = 19; StringName nullable_types[nullable_types_count] = { type_String, type_StringName, @@ -727,6 +727,7 @@ class BindingsGenerator { StaticCString::create(_STR(PackedVector2Array)), StaticCString::create(_STR(PackedVector3Array)), StaticCString::create(_STR(PackedColorArray)), + StaticCString::create(_STR(PackedVector4Array)), }; bool is_nullable_type(const StringName &p_type) const { diff --git a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs index f3f6759e1d..08e293afcc 100644 --- a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs +++ b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/UnmanagedCallbacksGenerator.cs @@ -468,6 +468,7 @@ using Godot.NativeInterop; "Godot.NativeInterop.godot_packed_string_array", "Godot.NativeInterop.godot_packed_vector2_array", "Godot.NativeInterop.godot_packed_vector3_array", + "Godot.NativeInterop.godot_packed_vector4_array", "Godot.NativeInterop.godot_packed_color_array", }; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/CustomUnsafe.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/CustomUnsafe.cs index afef20a7f2..171cf86edb 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/CustomUnsafe.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/CustomUnsafe.cs @@ -296,6 +296,22 @@ public static class CustomUnsafe => ref *ReadOnlyRefAsPointer(in source); [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe godot_packed_vector4_array* AsPointer(ref godot_packed_vector4_array value) + => value.GetUnsafeAddress(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe godot_packed_vector4_array* ReadOnlyRefAsPointer(in godot_packed_vector4_array value) + => value.GetUnsafeAddress(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe ref godot_packed_vector4_array AsRef(godot_packed_vector4_array* source) + => ref *source; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe ref godot_packed_vector4_array AsRef(in godot_packed_vector4_array source) + => ref *ReadOnlyRefAsPointer(in source); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe godot_packed_color_array* AsPointer(ref godot_packed_color_array value) => value.GetUnsafeAddress(); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs index a019dd3513..7e5c01d0f8 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs @@ -1134,6 +1134,39 @@ namespace Godot.NativeInterop } [StructLayout(LayoutKind.Sequential)] + // ReSharper disable once InconsistentNaming + public ref struct godot_packed_vector4_array + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal readonly unsafe godot_packed_vector4_array* GetUnsafeAddress() + => (godot_packed_vector4_array*)Unsafe.AsPointer(ref Unsafe.AsRef(in _writeProxy)); + + private IntPtr _writeProxy; + private unsafe Vector4* _ptr; + + public unsafe void Dispose() + { + if (_ptr == null) + return; + NativeFuncs.godotsharp_packed_vector4_array_destroy(ref this); + _ptr = null; + } + + public readonly unsafe Vector4* Buffer + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => _ptr; + } + + public readonly unsafe int Size + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => _ptr != null ? (int)(*((ulong*)_ptr - 1)) : 0; + } + } + + [StructLayout(LayoutKind.Sequential)] + // ReSharper disable once InconsistentNaming public ref struct godot_packed_color_array { [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs index 9f7fa53e24..15b7ce7c73 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs @@ -133,6 +133,9 @@ namespace Godot.NativeInterop if (type == typeof(Vector3[])) return Variant.Type.PackedVector3Array; + if (type == typeof(Vector4[])) + return Variant.Type.PackedVector4Array; + if (type == typeof(Color[])) return Variant.Type.PackedColorArray; @@ -574,6 +577,30 @@ namespace Godot.NativeInterop return NativeFuncs.godotsharp_packed_vector3_array_new_mem_copy(src, p_array.Length); } + // PackedVector4Array + + public static unsafe Vector4[] ConvertNativePackedVector4ArrayToSystemArray(godot_packed_vector4_array p_array) + { + Vector4* buffer = p_array.Buffer; + int size = p_array.Size; + if (size == 0) + return Array.Empty<Vector4>(); + int sizeInBytes = size * sizeof(Vector4); + var array = new Vector4[size]; + fixed (Vector4* dest = array) + Buffer.MemoryCopy(buffer, dest, sizeInBytes, sizeInBytes); + return array; + } + + public static unsafe godot_packed_vector4_array ConvertSystemArrayToNativePackedVector4Array( + Span<Vector4> p_array) + { + if (p_array.IsEmpty) + return new godot_packed_vector4_array(); + fixed (Vector4* src = p_array) + return NativeFuncs.godotsharp_packed_vector4_array_new_mem_copy(src, p_array.Length); + } + // PackedColorArray public static unsafe Color[] ConvertNativePackedColorArrayToSystemArray(godot_packed_color_array p_array) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs index fef21fae46..c4fd639cce 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs @@ -144,6 +144,9 @@ namespace Godot.NativeInterop public static partial godot_packed_vector3_array godotsharp_packed_vector3_array_new_mem_copy(Vector3* p_src, int p_length); + public static partial godot_packed_vector4_array godotsharp_packed_vector4_array_new_mem_copy(Vector4* p_src, + int p_length); + public static partial godot_packed_color_array godotsharp_packed_color_array_new_mem_copy(Color* p_src, int p_length); @@ -224,6 +227,9 @@ namespace Godot.NativeInterop public static partial void godotsharp_variant_new_packed_vector3_array(out godot_variant r_dest, in godot_packed_vector3_array p_pv3a); + public static partial void godotsharp_variant_new_packed_vector4_array(out godot_variant r_dest, + in godot_packed_vector4_array p_pv4a); + public static partial void godotsharp_variant_new_packed_color_array(out godot_variant r_dest, in godot_packed_color_array p_pca); @@ -302,6 +308,9 @@ namespace Godot.NativeInterop public static partial godot_packed_vector3_array godotsharp_variant_as_packed_vector3_array( in godot_variant p_self); + public static partial godot_packed_vector4_array godotsharp_variant_as_packed_vector4_array( + in godot_variant p_self); + public static partial godot_packed_color_array godotsharp_variant_as_packed_color_array(in godot_variant p_self); public static partial godot_bool godotsharp_variant_equals(in godot_variant p_a, in godot_variant p_b); @@ -352,6 +361,8 @@ namespace Godot.NativeInterop public static partial void godotsharp_packed_vector3_array_destroy(ref godot_packed_vector3_array p_self); + public static partial void godotsharp_packed_vector4_array_destroy(ref godot_packed_vector4_array p_self); + public static partial void godotsharp_packed_color_array_destroy(ref godot_packed_color_array p_self); public static partial void godotsharp_variant_destroy(ref godot_variant p_self); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs index 94609984ac..dc151e2c3e 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs @@ -165,6 +165,12 @@ namespace Godot.NativeInterop return ret; } + public static godot_variant CreateFromPackedVector4Array(in godot_packed_vector4_array from) + { + NativeFuncs.godotsharp_variant_new_packed_vector4_array(out godot_variant ret, from); + return ret; + } + public static godot_variant CreateFromPackedColorArray(in godot_packed_color_array from) { NativeFuncs.godotsharp_variant_new_packed_color_array(out godot_variant ret, from); @@ -228,6 +234,13 @@ namespace Godot.NativeInterop } [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static godot_variant CreateFromPackedVector4Array(Span<Vector4> from) + { + using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedVector4Array(from); + return CreateFromPackedVector4Array(nativePackedArray); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static godot_variant CreateFromPackedColorArray(Span<Color> from) { using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedColorArray(from); @@ -605,6 +618,12 @@ namespace Godot.NativeInterop return Marshaling.ConvertNativePackedVector3ArrayToSystemArray(packedArray); } + public static Vector4[] ConvertAsPackedVector4ArrayToSystemArray(in godot_variant p_var) + { + using var packedArray = NativeFuncs.godotsharp_variant_as_packed_vector4_array(p_var); + return Marshaling.ConvertNativePackedVector4ArrayToSystemArray(packedArray); + } + public static Color[] ConvertAsPackedColorArrayToSystemArray(in godot_variant p_var) { using var packedArray = NativeFuncs.godotsharp_variant_as_packed_color_array(p_var); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs index d8f7214c2f..2897cc4199 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs @@ -155,6 +155,9 @@ public partial class VariantUtils if (typeof(T) == typeof(Vector3[])) return CreateFromPackedVector3Array(UnsafeAs<Vector3[]>(from)); + if (typeof(T) == typeof(Vector4[])) + return CreateFromPackedVector4Array(UnsafeAs<Vector4[]>(from)); + if (typeof(T) == typeof(Color[])) return CreateFromPackedColorArray(UnsafeAs<Color[]>(from)); @@ -343,6 +346,9 @@ public partial class VariantUtils if (typeof(T) == typeof(Vector3[])) return UnsafeAsT(ConvertAsPackedVector3ArrayToSystemArray(variant)); + if (typeof(T) == typeof(Vector4[])) + return UnsafeAsT(ConvertAsPackedVector4ArrayToSystemArray(variant)); + if (typeof(T) == typeof(Color[])) return UnsafeAsT(ConvertAsPackedColorArrayToSystemArray(variant)); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs index c2d3050adc..b40f524859 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs @@ -149,6 +149,7 @@ public partial struct Variant : IDisposable Type.PackedStringArray => AsStringArray(), Type.PackedVector2Array => AsVector2Array(), Type.PackedVector3Array => AsVector3Array(), + Type.PackedVector4Array => AsVector4Array(), Type.PackedColorArray => AsColorArray(), Type.Nil => null, Type.Max or _ => @@ -320,6 +321,10 @@ public partial struct Variant : IDisposable VariantUtils.ConvertAsPackedVector3ArrayToSystemArray((godot_variant)NativeVar); [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4[] AsVector4Array() => + VariantUtils.ConvertAsPackedVector4ArrayToSystemArray((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] public Color[] AsColorArray() => VariantUtils.ConvertAsPackedColorArrayToSystemArray((godot_variant)NativeVar); @@ -492,6 +497,9 @@ public partial struct Variant : IDisposable public static explicit operator Vector3[](Variant from) => from.AsVector3Array(); [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Vector4[](Variant from) => from.AsVector4Array(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static explicit operator Color[](Variant from) => from.AsColorArray(); [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -642,6 +650,9 @@ public partial struct Variant : IDisposable public static Variant CreateFrom(Span<Vector3> from) => from; [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Variant CreateFrom(Span<Vector4> from) => from; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Variant CreateFrom(Span<Color> from) => from; [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -841,6 +852,10 @@ public partial struct Variant : IDisposable (Variant)from.AsSpan(); [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Vector4[] from) => + (Variant)from.AsSpan(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator Variant(Color[] from) => (Variant)from.AsSpan(); @@ -893,6 +908,10 @@ public partial struct Variant : IDisposable CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromPackedVector3Array(from)); [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Span<Vector4> from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromPackedVector4Array(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator Variant(Span<Color> from) => CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromPackedColorArray(from)); diff --git a/modules/mono/glue/runtime_interop.cpp b/modules/mono/glue/runtime_interop.cpp index 4bb324c0ee..1af462dafd 100644 --- a/modules/mono/glue/runtime_interop.cpp +++ b/modules/mono/glue/runtime_interop.cpp @@ -461,6 +461,16 @@ godot_packed_array godotsharp_packed_vector3_array_new_mem_copy(const Vector3 *p return ret; } +godot_packed_array godotsharp_packed_vector4_array_new_mem_copy(const Vector4 *p_src, int32_t p_length) { + godot_packed_array ret; + memnew_placement(&ret, PackedVector4Array); + PackedVector4Array *array = reinterpret_cast<PackedVector4Array *>(&ret); + array->resize(p_length); + Vector4 *dst = array->ptrw(); + memcpy(dst, p_src, p_length * sizeof(Vector4)); + return ret; +} + godot_packed_array godotsharp_packed_color_array_new_mem_copy(const Color *p_src, int32_t p_length) { godot_packed_array ret; memnew_placement(&ret, PackedColorArray); @@ -646,6 +656,10 @@ void godotsharp_variant_new_packed_vector3_array(godot_variant *r_dest, const Pa memnew_placement(r_dest, Variant(*p_pv3a)); } +void godotsharp_variant_new_packed_vector4_array(godot_variant *r_dest, const PackedVector4Array *p_pv4a) { + memnew_placement(r_dest, Variant(*p_pv4a)); +} + void godotsharp_variant_new_packed_color_array(godot_variant *r_dest, const PackedColorArray *p_pca) { memnew_placement(r_dest, Variant(*p_pca)); } @@ -886,6 +900,13 @@ godot_packed_array godotsharp_variant_as_packed_vector3_array(const Variant *p_s return raw_dest; } +godot_packed_array godotsharp_variant_as_packed_vector4_array(const Variant *p_self) { + godot_packed_array raw_dest; + PackedVector4Array *dest = (PackedVector4Array *)&raw_dest; + memnew_placement(dest, PackedVector4Array(p_self->operator PackedVector4Array())); + return raw_dest; +} + godot_packed_array godotsharp_variant_as_packed_color_array(const Variant *p_self) { godot_packed_array raw_dest; PackedColorArray *dest = (PackedColorArray *)&raw_dest; @@ -974,6 +995,10 @@ void godotsharp_packed_vector3_array_destroy(PackedVector3Array *p_self) { p_self->~PackedVector3Array(); } +void godotsharp_packed_vector4_array_destroy(PackedVector4Array *p_self) { + p_self->~PackedVector4Array(); +} + void godotsharp_packed_color_array_destroy(PackedColorArray *p_self) { p_self->~PackedColorArray(); } @@ -1456,6 +1481,7 @@ static const void *unmanaged_callbacks[]{ (void *)godotsharp_packed_float64_array_new_mem_copy, (void *)godotsharp_packed_vector2_array_new_mem_copy, (void *)godotsharp_packed_vector3_array_new_mem_copy, + (void *)godotsharp_packed_vector4_array_new_mem_copy, (void *)godotsharp_packed_color_array_new_mem_copy, (void *)godotsharp_packed_string_array_add, (void *)godotsharp_callable_new_with_delegate, @@ -1484,6 +1510,7 @@ static const void *unmanaged_callbacks[]{ (void *)godotsharp_variant_new_packed_string_array, (void *)godotsharp_variant_new_packed_vector2_array, (void *)godotsharp_variant_new_packed_vector3_array, + (void *)godotsharp_variant_new_packed_vector4_array, (void *)godotsharp_variant_new_packed_color_array, (void *)godotsharp_variant_as_bool, (void *)godotsharp_variant_as_int, @@ -1520,6 +1547,7 @@ static const void *unmanaged_callbacks[]{ (void *)godotsharp_variant_as_packed_string_array, (void *)godotsharp_variant_as_packed_vector2_array, (void *)godotsharp_variant_as_packed_vector3_array, + (void *)godotsharp_variant_as_packed_vector4_array, (void *)godotsharp_variant_as_packed_color_array, (void *)godotsharp_variant_equals, (void *)godotsharp_string_new_with_utf16_chars, @@ -1538,6 +1566,7 @@ static const void *unmanaged_callbacks[]{ (void *)godotsharp_packed_string_array_destroy, (void *)godotsharp_packed_vector2_array_destroy, (void *)godotsharp_packed_vector3_array_destroy, + (void *)godotsharp_packed_vector4_array_destroy, (void *)godotsharp_packed_color_array_destroy, (void *)godotsharp_variant_destroy, (void *)godotsharp_string_destroy, diff --git a/modules/multiplayer/editor/replication_editor.cpp b/modules/multiplayer/editor/replication_editor.cpp index 8453a41473..73e53a6a07 100644 --- a/modules/multiplayer/editor/replication_editor.cpp +++ b/modules/multiplayer/editor/replication_editor.cpp @@ -234,7 +234,8 @@ ReplicationEditor::ReplicationEditor() { Variant::PACKED_STRING_ARRAY, Variant::PACKED_VECTOR2_ARRAY, Variant::PACKED_VECTOR3_ARRAY, - Variant::PACKED_COLOR_ARRAY + Variant::PACKED_COLOR_ARRAY, + Variant::PACKED_VECTOR4_ARRAY, }; prop_selector->set_type_filter(types); prop_selector->connect("selected", callable_mp(this, &ReplicationEditor::_pick_node_property_selected)); diff --git a/modules/openxr/doc_classes/OpenXRInterface.xml b/modules/openxr/doc_classes/OpenXRInterface.xml index 86ba1416c8..309cbe0d72 100644 --- a/modules/openxr/doc_classes/OpenXRInterface.xml +++ b/modules/openxr/doc_classes/OpenXRInterface.xml @@ -152,6 +152,14 @@ <member name="render_target_size_multiplier" type="float" setter="set_render_target_size_multiplier" getter="get_render_target_size_multiplier" default="1.0"> The render size multiplier for the current HMD. Must be set before the interface has been initialized. </member> + <member name="vrs_min_radius" type="float" setter="set_vrs_min_radius" getter="get_vrs_min_radius" default="20.0"> + The minimum radius around the focal point where full quality is guaranteed if VRS is used as a percentage of screen size. + [b]Note:[/b] Mobile and Forward+ renderers only. Requires [member Viewport.vrs_mode] to be set to [constant Viewport.VRS_XR]. + </member> + <member name="vrs_strength" type="float" setter="set_vrs_strength" getter="get_vrs_strength" default="1.0"> + The strength used to calculate the VRS density map. The greater this value, the more noticeable VRS is. This improves performance at the cost of quality. + [b]Note:[/b] Mobile and Forward+ renderers only. Requires [member Viewport.vrs_mode] to be set to [constant Viewport.VRS_XR]. + </member> </members> <signals> <signal name="instance_exiting"> diff --git a/modules/openxr/extensions/openxr_eye_gaze_interaction.cpp b/modules/openxr/extensions/openxr_eye_gaze_interaction.cpp index 477a1c2609..eea996edd9 100644 --- a/modules/openxr/extensions/openxr_eye_gaze_interaction.cpp +++ b/modules/openxr/extensions/openxr_eye_gaze_interaction.cpp @@ -34,6 +34,7 @@ #include "core/os/os.h" #include "../action_map/openxr_interaction_profile_metadata.h" +#include "../openxr_api.h" OpenXREyeGazeInteractionExtension *OpenXREyeGazeInteractionExtension::singleton = nullptr; @@ -106,3 +107,38 @@ void OpenXREyeGazeInteractionExtension::on_register_metadata() { metadata->register_interaction_profile("Eye gaze", "/interaction_profiles/ext/eye_gaze_interaction", XR_EXT_EYE_GAZE_INTERACTION_EXTENSION_NAME); metadata->register_io_path("/interaction_profiles/ext/eye_gaze_interaction", "Gaze pose", "/user/eyes_ext", "/user/eyes_ext/input/gaze_ext/pose", "", OpenXRAction::OPENXR_ACTION_POSE); } + +bool OpenXREyeGazeInteractionExtension::get_eye_gaze_pose(double p_dist, Vector3 &r_eye_pose) { + OpenXRAPI *openxr_api = OpenXRAPI::get_singleton(); + ERR_FAIL_NULL_V(openxr_api, false); + + if (!init_eye_gaze_pose) { + init_eye_gaze_pose = true; + + eye_tracker = openxr_api->find_tracker("/user/eyes_ext"); + if (eye_tracker.is_null()) { + WARN_PRINT("Couldn't obtain eye tracker"); + } + + eye_action = openxr_api->find_action("eye_gaze_pose"); + if (eye_action.is_null()) { + WARN_PRINT("Couldn't obtain pose action for `eye_gaze_pose`, make sure to add this to your action map."); + } + } + + if (eye_tracker.is_null() || eye_action.is_null()) { + return false; + } + + Transform3D eye_transform; + Vector3 linear_velocity; + Vector3 angular_velocity; + XRPose::TrackingConfidence confidence = openxr_api->get_action_pose(eye_action, eye_tracker, eye_transform, linear_velocity, angular_velocity); + if (confidence == XRPose::XR_TRACKING_CONFIDENCE_NONE) { + return false; + } + + r_eye_pose = eye_transform.origin + eye_transform.basis[2] * p_dist; + + return true; +} diff --git a/modules/openxr/extensions/openxr_eye_gaze_interaction.h b/modules/openxr/extensions/openxr_eye_gaze_interaction.h index 2b99f8edff..114c1aacc7 100644 --- a/modules/openxr/extensions/openxr_eye_gaze_interaction.h +++ b/modules/openxr/extensions/openxr_eye_gaze_interaction.h @@ -50,11 +50,17 @@ public: virtual void on_register_metadata() override; + bool get_eye_gaze_pose(double p_dist, Vector3 &r_eye_pose); + private: static OpenXREyeGazeInteractionExtension *singleton; bool available = false; XrSystemEyeGazeInteractionPropertiesEXT properties; + + bool init_eye_gaze_pose = false; + RID eye_tracker; + RID eye_action; }; #endif // OPENXR_EYE_GAZE_INTERACTION_H diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp index 40e3ecfefc..8731a36865 100644 --- a/modules/openxr/openxr_api.cpp +++ b/modules/openxr/openxr_api.cpp @@ -54,6 +54,7 @@ #endif #include "extensions/openxr_composition_layer_depth_extension.h" +#include "extensions/openxr_eye_gaze_interaction.h" #include "extensions/openxr_fb_display_refresh_rate_extension.h" #include "extensions/openxr_fb_foveation_extension.h" #include "extensions/openxr_fb_update_swapchain_extension.h" @@ -1826,6 +1827,46 @@ bool OpenXRAPI::get_view_projection(uint32_t p_view, double p_z_near, double p_z return graphics_extension->create_projection_fov(render_state.views[p_view].fov, p_z_near, p_z_far, p_camera_matrix); } +Vector2 OpenXRAPI::get_eye_focus(uint32_t p_view, float p_aspect) { + ERR_FAIL_NULL_V(graphics_extension, Vector2()); + + if (!render_state.running) { + return Vector2(); + } + + // xrWaitFrame not run yet + if (render_state.predicted_display_time == 0) { + return Vector2(); + } + + // we don't have valid view info + if (render_state.views == nullptr || !render_state.view_pose_valid) { + return Vector2(); + } + + Projection cm; + if (!graphics_extension->create_projection_fov(render_state.views[p_view].fov, 0.1, 1000.0, cm)) { + return Vector2(); + } + + // Default focus to center... + Vector3 focus = cm.xform(Vector3(0.0, 0.0, 999.9)); + + // Lets check for eye tracking... + OpenXREyeGazeInteractionExtension *eye_gaze_interaction = OpenXREyeGazeInteractionExtension::get_singleton(); + if (eye_gaze_interaction && eye_gaze_interaction->supports_eye_gaze_interaction()) { + Vector3 eye_gaze_pose; + if (eye_gaze_interaction->get_eye_gaze_pose(1.0, eye_gaze_pose)) { + Transform3D view_transform = transform_from_pose(render_state.views[p_view].pose); + + eye_gaze_pose = view_transform.xform_inv(eye_gaze_pose); + focus = cm.xform(eye_gaze_pose); + } + } + + return Vector2(focus.x, focus.y); +} + bool OpenXRAPI::poll_events() { ERR_FAIL_COND_V(instance == XR_NULL_HANDLE, false); @@ -2633,10 +2674,23 @@ bool OpenXRAPI::xr_result(XrResult result, const char *format, Array args) const RID OpenXRAPI::get_tracker_rid(XrPath p_path) { List<RID> current; tracker_owner.get_owned_list(¤t); - for (int i = 0; i < current.size(); i++) { - Tracker *tracker = tracker_owner.get_or_null(current[i]); + for (const RID &E : current) { + Tracker *tracker = tracker_owner.get_or_null(E); if (tracker && tracker->toplevel_path == p_path) { - return current[i]; + return E; + } + } + + return RID(); +} + +RID OpenXRAPI::find_tracker(const String &p_name) { + List<RID> current; + tracker_owner.get_owned_list(¤t); + for (const RID &E : current) { + Tracker *tracker = tracker_owner.get_or_null(E); + if (tracker && tracker->name == p_name) { + return E; } } @@ -2827,10 +2881,23 @@ void OpenXRAPI::action_set_free(RID p_action_set) { RID OpenXRAPI::get_action_rid(XrAction p_action) { List<RID> current; action_owner.get_owned_list(¤t); - for (int i = 0; i < current.size(); i++) { - Action *action = action_owner.get_or_null(current[i]); + for (const RID &E : current) { + Action *action = action_owner.get_or_null(E); if (action && action->handle == p_action) { - return current[i]; + return E; + } + } + + return RID(); +} + +RID OpenXRAPI::find_action(const String &p_name) { + List<RID> current; + action_owner.get_owned_list(¤t); + for (const RID &E : current) { + Action *action = action_owner.get_or_null(E); + if (action && action->name == p_name) { + return E; } } @@ -2931,10 +2998,10 @@ void OpenXRAPI::action_free(RID p_action) { RID OpenXRAPI::get_interaction_profile_rid(XrPath p_path) { List<RID> current; interaction_profile_owner.get_owned_list(¤t); - for (int i = 0; i < current.size(); i++) { - InteractionProfile *ip = interaction_profile_owner.get_or_null(current[i]); + for (const RID &E : current) { + InteractionProfile *ip = interaction_profile_owner.get_or_null(E); if (ip && ip->path == p_path) { - return current[i]; + return E; } } diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h index c95867810c..f9d2e60148 100644 --- a/modules/openxr/openxr_api.h +++ b/modules/openxr/openxr_api.h @@ -456,6 +456,7 @@ public: XRPose::TrackingConfidence get_head_center(Transform3D &r_transform, Vector3 &r_linear_velocity, Vector3 &r_angular_velocity); bool get_view_transform(uint32_t p_view, Transform3D &r_transform); bool get_view_projection(uint32_t p_view, double p_z_near, double p_z_far, Projection &p_camera_matrix); + Vector2 get_eye_focus(uint32_t p_view, float p_aspect); bool process(); void pre_render(); @@ -515,6 +516,9 @@ public: bool interaction_profile_suggest_bindings(RID p_interaction_profile); void interaction_profile_free(RID p_interaction_profile); + RID find_tracker(const String &p_name); + RID find_action(const String &p_name); + bool sync_action_sets(const Vector<RID> p_active_sets); bool get_action_bool(RID p_action, RID p_tracker); float get_action_float(RID p_action, RID p_tracker); diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp index 39a61d1b4d..b92d1edb90 100644 --- a/modules/openxr/openxr_interface.cpp +++ b/modules/openxr/openxr_interface.cpp @@ -97,6 +97,16 @@ void OpenXRInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("is_hand_interaction_supported"), &OpenXRInterface::is_hand_interaction_supported); ClassDB::bind_method(D_METHOD("is_eye_gaze_interaction_supported"), &OpenXRInterface::is_eye_gaze_interaction_supported); + // VRS + ClassDB::bind_method(D_METHOD("get_vrs_min_radius"), &OpenXRInterface::get_vrs_min_radius); + ClassDB::bind_method(D_METHOD("set_vrs_min_radius", "radius"), &OpenXRInterface::set_vrs_min_radius); + ClassDB::bind_method(D_METHOD("get_vrs_strength"), &OpenXRInterface::get_vrs_strength); + ClassDB::bind_method(D_METHOD("set_vrs_strength", "strength"), &OpenXRInterface::set_vrs_strength); + + ADD_GROUP("Vulkan VRS", "vrs_"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "vrs_min_radius", PROPERTY_HINT_RANGE, "1.0,100.0,1.0"), "set_vrs_min_radius", "get_vrs_min_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "vrs_strength", PROPERTY_HINT_RANGE, "0.1,10.0,0.1"), "set_vrs_strength", "get_vrs_strength"); + BIND_ENUM_CONSTANT(HAND_LEFT); BIND_ENUM_CONSTANT(HAND_RIGHT); BIND_ENUM_CONSTANT(HAND_MAX); @@ -872,6 +882,22 @@ Array OpenXRInterface::get_action_sets() const { return arr; } +float OpenXRInterface::get_vrs_min_radius() const { + return xr_vrs.get_vrs_min_radius(); +} + +void OpenXRInterface::set_vrs_min_radius(float p_vrs_min_radius) { + xr_vrs.set_vrs_min_radius(p_vrs_min_radius); +} + +float OpenXRInterface::get_vrs_strength() const { + return xr_vrs.get_vrs_strength(); +} + +void OpenXRInterface::set_vrs_strength(float p_vrs_strength) { + xr_vrs.set_vrs_strength(p_vrs_strength); +} + double OpenXRInterface::get_render_target_size_multiplier() const { if (openxr_api == nullptr) { return 1.0; @@ -1435,6 +1461,24 @@ Vector3 OpenXRInterface::get_hand_joint_angular_velocity(Hand p_hand, HandJoints return Vector3(); } +RID OpenXRInterface::get_vrs_texture() { + if (!openxr_api) { + return RID(); + } + + PackedVector2Array eye_foci; + + Size2 target_size = get_render_target_size(); + real_t aspect_ratio = target_size.x / target_size.y; + uint32_t view_count = get_view_count(); + + for (uint32_t v = 0; v < view_count; v++) { + eye_foci.push_back(openxr_api->get_eye_focus(v, aspect_ratio)); + } + + return xr_vrs.make_vrs_texture(target_size, eye_foci); +} + OpenXRInterface::OpenXRInterface() { openxr_api = OpenXRAPI::get_singleton(); if (openxr_api) { diff --git a/modules/openxr/openxr_interface.h b/modules/openxr/openxr_interface.h index ac33304757..f0ee0dc3c4 100644 --- a/modules/openxr/openxr_interface.h +++ b/modules/openxr/openxr_interface.h @@ -80,6 +80,8 @@ private: XRPose::TrackingConfidence head_confidence; Transform3D transform_for_view[2]; // We currently assume 2, but could be 4 for VARJO which we do not support yet + XRVRS xr_vrs; + void _load_action_map(); struct Action { // An action we've registered with OpenXR @@ -168,6 +170,12 @@ public: bool get_foveation_dynamic() const; void set_foveation_dynamic(bool p_foveation_dynamic); + float get_vrs_min_radius() const; + void set_vrs_min_radius(float p_vrs_min_radius); + + float get_vrs_strength() const; + void set_vrs_strength(float p_vrs_strength); + virtual Size2 get_render_target_size() override; virtual uint32_t get_view_count() override; virtual Transform3D get_camera_transform() override; @@ -276,6 +284,8 @@ public: Vector3 get_hand_joint_linear_velocity(Hand p_hand, HandJoints p_joint) const; Vector3 get_hand_joint_angular_velocity(Hand p_hand, HandJoints p_joint) const; + virtual RID get_vrs_texture() override; + OpenXRInterface(); ~OpenXRInterface(); }; |
