diff options
104 files changed, 1654 insertions, 669 deletions
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 7a10390d72..4d2006d42a 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -619,7 +619,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bool p_upwards, bool p_ignore_override) { Error err = _setup(p_path, p_main_pack, p_upwards, p_ignore_override); if (err == OK) { - String custom_settings = GLOBAL_DEF("application/config/project_settings_override", ""); + String custom_settings = GLOBAL_GET("application/config/project_settings_override"); if (!custom_settings.is_empty()) { _load_settings_text(custom_settings); } @@ -1276,6 +1276,7 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF("physics/2d/run_on_separate_thread", false); GLOBAL_DEF("physics/3d/run_on_separate_thread", false); + GLOBAL_DEF("debug/disable_touch", false); GLOBAL_DEF("debug/settings/profiler/max_functions", 16384); custom_prop_info["debug/settings/profiler/max_functions"] = PropertyInfo(Variant::INT, "debug/settings/profiler/max_functions", PROPERTY_HINT_RANGE, "128,65535,1"); @@ -1292,6 +1293,22 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF("compression/formats/gzip/compression_level", Compression::gzip_level); custom_prop_info["compression/formats/gzip/compression_level"] = PropertyInfo(Variant::INT, "compression/formats/gzip/compression_level", PROPERTY_HINT_RANGE, "-1,9,1"); + GLOBAL_DEF("debug/settings/crash_handler/message", + String("Please include this when reporting the bug to the project developer.")); + GLOBAL_DEF("debug/settings/crash_handler/message.editor", + String("Please include this when reporting the bug on: https://github.com/godotengine/godot/issues")); + GLOBAL_DEF_RST("rendering/occlusion_culling/bvh_build_quality", 2); + GLOBAL_DEF("memory/limits/multithreaded_server/rid_pool_prealloc", 60); + GLOBAL_DEF_RST("internationalization/rendering/force_right_to_left_layout_direction", false); + + GLOBAL_DEF("gui/timers/incremental_search_max_interval_msec", 2000); + ProjectSettings::get_singleton()->set_custom_property_info("gui/timers/incremental_search_max_interval_msec", PropertyInfo(Variant::INT, "gui/timers/incremental_search_max_interval_msec", PROPERTY_HINT_RANGE, "0,10000,1,or_greater")); // No negative numbers. + + GLOBAL_DEF("rendering/rendering_device/staging_buffer/block_size_kb", 256); + GLOBAL_DEF("rendering/rendering_device/staging_buffer/max_size_mb", 128); + GLOBAL_DEF("rendering/rendering_device/staging_buffer/texture_upload_region_size_px", 64); + GLOBAL_DEF("rendering/rendering_device/vulkan/max_descriptors_per_pool", 64); + // These properties will not show up in the dialog nor in the documentation. If you want to exclude whole groups, see _get_property_list() method. GLOBAL_DEF_INTERNAL("application/config/features", PackedStringArray()); GLOBAL_DEF_INTERNAL("internationalization/locale/translation_remaps", PackedStringArray()); diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp index 96b396caa9..a2c507e350 100644 --- a/core/extension/extension_api_dump.cpp +++ b/core/extension/extension_api_dump.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "extension_api_dump.h" + #include "core/config/engine.h" #include "core/core_constants.h" #include "core/io/file_access.h" @@ -938,9 +939,9 @@ void NativeExtensionAPIDump::generate_extension_json_file(const String &p_path) Ref<JSON> json; json.instantiate(); - String text = json->stringify(api, "\t", false); + String text = json->stringify(api, "\t", false) + "\n"; Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::WRITE); - CharString cs = text.ascii(); - fa->store_buffer((const uint8_t *)cs.ptr(), cs.length()); + fa->store_string(text); } -#endif + +#endif // TOOLS_ENABLED diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp index 193fcb8916..864f2fa86b 100644 --- a/core/extension/gdnative_interface.cpp +++ b/core/extension/gdnative_interface.cpp @@ -61,8 +61,9 @@ static void gdnative_print_script_error(const char *p_description, const char *p _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_SCRIPT); } -uint64_t gdnative_get_native_struct_size(const char *p_name) { - return ClassDB::get_native_struct_size(p_name); +uint64_t gdnative_get_native_struct_size(const GDNativeStringNamePtr p_name) { + const StringName name = *reinterpret_cast<const StringName *>(p_name); + return ClassDB::get_native_struct_size(name); } // Variant functions @@ -81,11 +82,11 @@ static void gdnative_variant_destroy(GDNativeVariantPtr p_self) { static void gdnative_variant_call(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argcount, GDNativeVariantPtr r_return, GDNativeCallError *r_error) { Variant *self = (Variant *)p_self; - const StringName *method = (const StringName *)p_method; + const StringName method = *reinterpret_cast<const StringName *>(p_method); const Variant **args = (const Variant **)p_args; Variant ret; Callable::CallError error; - self->callp(*method, args, p_argcount, ret, error); + self->callp(method, args, p_argcount, ret, error); memnew_placement(r_return, Variant(ret)); if (r_error) { @@ -97,11 +98,11 @@ static void gdnative_variant_call(GDNativeVariantPtr p_self, const GDNativeStrin static void gdnative_variant_call_static(GDNativeVariantType p_type, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argcount, GDNativeVariantPtr r_return, GDNativeCallError *r_error) { Variant::Type type = (Variant::Type)p_type; - const StringName *method = (const StringName *)p_method; + const StringName method = *reinterpret_cast<const StringName *>(p_method); const Variant **args = (const Variant **)p_args; Variant ret; Callable::CallError error; - Variant::call_static(type, *method, args, p_argcount, ret, error); + Variant::call_static(type, method, args, p_argcount, ret, error); memnew_placement(r_return, Variant(ret)); if (r_error) { @@ -469,11 +470,11 @@ static GDNativeTypeFromVariantConstructorFunc gdnative_get_type_from_variant_con static GDNativePtrOperatorEvaluator gdnative_variant_get_ptr_operator_evaluator(GDNativeVariantOperator p_operator, GDNativeVariantType p_type_a, GDNativeVariantType p_type_b) { return (GDNativePtrOperatorEvaluator)Variant::get_ptr_operator_evaluator(Variant::Operator(p_operator), Variant::Type(p_type_a), Variant::Type(p_type_b)); } -static GDNativePtrBuiltInMethod gdnative_variant_get_ptr_builtin_method(GDNativeVariantType p_type, const char *p_method, GDNativeInt p_hash) { - StringName method = p_method; +static GDNativePtrBuiltInMethod gdnative_variant_get_ptr_builtin_method(GDNativeVariantType p_type, const GDNativeStringNamePtr p_method, GDNativeInt p_hash) { + const StringName method = *reinterpret_cast<const StringName *>(p_method); uint32_t hash = Variant::get_builtin_method_hash(Variant::Type(p_type), method); if (hash != p_hash) { - ERR_PRINT_ONCE("Error getting method " + String(method) + ", hash mismatch."); + ERR_PRINT_ONCE("Error getting method " + method + ", hash mismatch."); return nullptr; } @@ -497,11 +498,13 @@ static void gdnative_variant_construct(GDNativeVariantType p_type, GDNativeVaria r_error->expected = error.expected; } } -static GDNativePtrSetter gdnative_variant_get_ptr_setter(GDNativeVariantType p_type, const char *p_member) { - return (GDNativePtrSetter)Variant::get_member_ptr_setter(Variant::Type(p_type), p_member); +static GDNativePtrSetter gdnative_variant_get_ptr_setter(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member) { + const StringName member = *reinterpret_cast<const StringName *>(p_member); + return (GDNativePtrSetter)Variant::get_member_ptr_setter(Variant::Type(p_type), member); } -static GDNativePtrGetter gdnative_variant_get_ptr_getter(GDNativeVariantType p_type, const char *p_member) { - return (GDNativePtrGetter)Variant::get_member_ptr_getter(Variant::Type(p_type), p_member); +static GDNativePtrGetter gdnative_variant_get_ptr_getter(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member) { + const StringName member = *reinterpret_cast<const StringName *>(p_member); + return (GDNativePtrGetter)Variant::get_member_ptr_getter(Variant::Type(p_type), member); } static GDNativePtrIndexedSetter gdnative_variant_get_ptr_indexed_setter(GDNativeVariantType p_type) { return (GDNativePtrIndexedSetter)Variant::get_member_ptr_indexed_setter(Variant::Type(p_type)); @@ -518,14 +521,15 @@ static GDNativePtrKeyedGetter gdnative_variant_get_ptr_keyed_getter(GDNativeVari static GDNativePtrKeyedChecker gdnative_variant_get_ptr_keyed_checker(GDNativeVariantType p_type) { return (GDNativePtrKeyedChecker)Variant::get_member_ptr_keyed_checker(Variant::Type(p_type)); } -static void gdnative_variant_get_constant_value(GDNativeVariantType p_type, const char *p_constant, GDNativeVariantPtr r_ret) { - memnew_placement(r_ret, Variant(Variant::get_constant_value(Variant::Type(p_type), p_constant))); +static void gdnative_variant_get_constant_value(GDNativeVariantType p_type, const GDNativeStringNamePtr p_constant, GDNativeVariantPtr r_ret) { + StringName constant = *reinterpret_cast<const StringName *>(p_constant); + memnew_placement(r_ret, Variant(Variant::get_constant_value(Variant::Type(p_type), constant))); } -static GDNativePtrUtilityFunction gdnative_variant_get_ptr_utility_function(const char *p_function, GDNativeInt p_hash) { - StringName function = p_function; +static GDNativePtrUtilityFunction gdnative_variant_get_ptr_utility_function(const GDNativeStringNamePtr p_function, GDNativeInt p_hash) { + StringName function = *reinterpret_cast<const StringName *>(p_function); uint32_t hash = Variant::get_utility_function_hash(function); if (hash != p_hash) { - ERR_PRINT_ONCE("Error getting utility function " + String(function) + ", hash mismatch."); + ERR_PRINT_ONCE("Error getting utility function " + function + ", hash mismatch."); return nullptr; } return (GDNativePtrUtilityFunction)Variant::get_ptr_utility_function(function); @@ -836,8 +840,9 @@ static void gdnative_object_destroy(GDNativeObjectPtr p_o) { memdelete((Object *)p_o); } -static GDNativeObjectPtr gdnative_global_get_singleton(const char *p_name) { - return (GDNativeObjectPtr)Engine::get_singleton()->get_singleton_object(String(p_name)); +static GDNativeObjectPtr gdnative_global_get_singleton(const GDNativeStringNamePtr p_name) { + const StringName name = *reinterpret_cast<const StringName *>(p_name); + return (GDNativeObjectPtr)Engine::get_singleton()->get_singleton_object(name); } static void *gdnative_object_get_instance_binding(GDNativeObjectPtr p_object, void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks) { @@ -850,9 +855,10 @@ static void gdnative_object_set_instance_binding(GDNativeObjectPtr p_object, voi o->set_instance_binding(p_token, p_binding, p_callbacks); } -static void gdnative_object_set_instance(GDNativeObjectPtr p_object, const char *p_classname, GDExtensionClassInstancePtr p_instance) { +static void gdnative_object_set_instance(GDNativeObjectPtr p_object, const GDNativeStringNamePtr p_classname, GDExtensionClassInstancePtr p_instance) { + const StringName classname = *reinterpret_cast<const StringName *>(p_classname); Object *o = (Object *)p_object; - ClassDB::set_object_extension_instance(o, p_classname, p_instance); + ClassDB::set_object_extension_instance(o, classname, p_instance); } static GDNativeObjectPtr gdnative_object_get_instance_from_id(GDObjectInstanceID p_instance_id) { @@ -880,23 +886,26 @@ static GDNativeScriptInstancePtr gdnative_script_instance_create(const GDNativeE return reinterpret_cast<GDNativeScriptInstancePtr>(script_instance_extension); } -static GDNativeMethodBindPtr gdnative_classdb_get_method_bind(const char *p_classname, const char *p_methodname, GDNativeInt p_hash) { - MethodBind *mb = ClassDB::get_method(StringName(p_classname), StringName(p_methodname)); +static GDNativeMethodBindPtr gdnative_classdb_get_method_bind(const GDNativeStringNamePtr p_classname, const GDNativeStringNamePtr p_methodname, GDNativeInt p_hash) { + const StringName classname = *reinterpret_cast<const StringName *>(p_classname); + const StringName methodname = *reinterpret_cast<const StringName *>(p_methodname); + MethodBind *mb = ClassDB::get_method(classname, methodname); ERR_FAIL_COND_V(!mb, nullptr); if (mb->get_hash() != p_hash) { - ERR_PRINT("Hash mismatch for method '" + String(p_classname) + "." + String(p_methodname) + "'."); + ERR_PRINT("Hash mismatch for method '" + classname + "." + methodname + "'."); return nullptr; } - // MethodBind *mb = ClassDB::get_method("Node", "get_name"); return (GDNativeMethodBindPtr)mb; } -static GDNativeObjectPtr gdnative_classdb_construct_object(const char *p_classname) { - return (GDNativeObjectPtr)ClassDB::instantiate(p_classname); +static GDNativeObjectPtr gdnative_classdb_construct_object(const GDNativeStringNamePtr p_classname) { + const StringName classname = *reinterpret_cast<const StringName *>(p_classname); + return (GDNativeObjectPtr)ClassDB::instantiate(classname); } -static void *gdnative_classdb_get_class_tag(const char *p_classname) { - ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(p_classname); +static void *gdnative_classdb_get_class_tag(const GDNativeStringNamePtr p_classname) { + const StringName classname = *reinterpret_cast<const StringName *>(p_classname); + ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(classname); return class_info ? class_info->class_ptr : nullptr; } diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h index 1ce50bc186..68eed5a161 100644 --- a/core/extension/gdnative_interface.h +++ b/core/extension/gdnative_interface.h @@ -202,21 +202,21 @@ typedef uint64_t (*GDNativeExtensionClassGetRID)(GDExtensionClassInstancePtr p_i typedef struct { GDNativeVariantType type; - const char *name; - const char *class_name; + GDNativeStringNamePtr name; + GDNativeStringNamePtr class_name; uint32_t hint; // Bitfield of `PropertyHint` (defined in `extension_api.json`) - const char *hint_string; + GDNativeStringPtr hint_string; uint32_t usage; // Bitfield of `PropertyUsageFlags` (defined in `extension_api.json`) } GDNativePropertyInfo; typedef struct { - const char *name; + GDNativeStringNamePtr name; GDNativePropertyInfo return_value; uint32_t flags; // Bitfield of `GDNativeExtensionClassMethodFlags` int32_t id; - GDNativePropertyInfo *arguments; + GDNativePropertyInfo *arguments; // array of `argument_count` size uint32_t argument_count; - GDNativeVariantPtr default_arguments; + GDNativeVariantPtr *default_arguments; // array of `default_argument_count` size uint32_t default_argument_count; } GDNativeMethodInfo; @@ -225,13 +225,13 @@ typedef void (*GDNativeExtensionClassFreePropertyList)(GDExtensionClassInstanceP typedef GDNativeBool (*GDNativeExtensionClassPropertyCanRevert)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name); typedef GDNativeBool (*GDNativeExtensionClassPropertyGetRevert)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret); typedef void (*GDNativeExtensionClassNotification)(GDExtensionClassInstancePtr p_instance, int32_t p_what); -typedef void (*GDNativeExtensionClassToString)(GDExtensionClassInstancePtr p_instance, GDNativeStringPtr p_out); +typedef void (*GDNativeExtensionClassToString)(GDExtensionClassInstancePtr p_instance, GDNativeBool *r_is_valid, GDNativeStringPtr p_out); typedef void (*GDNativeExtensionClassReference)(GDExtensionClassInstancePtr p_instance); typedef void (*GDNativeExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance); typedef void (*GDNativeExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret); typedef GDNativeObjectPtr (*GDNativeExtensionClassCreateInstance)(void *p_userdata); typedef void (*GDNativeExtensionClassFreeInstance)(void *p_userdata, GDExtensionClassInstancePtr p_instance); -typedef GDNativeExtensionClassCallVirtual (*GDNativeExtensionClassGetVirtual)(void *p_userdata, const char *p_name); +typedef GDNativeExtensionClassCallVirtual (*GDNativeExtensionClassGetVirtual)(void *p_userdata, const GDNativeStringNamePtr p_name); typedef struct { GDNativeBool is_virtual; @@ -284,24 +284,21 @@ typedef enum { typedef void (*GDNativeExtensionClassMethodCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error); typedef void (*GDNativeExtensionClassMethodPtrCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret); -/* passing -1 as argument in the following functions refers to the return type */ -typedef GDNativeVariantType (*GDNativeExtensionClassMethodGetArgumentType)(void *p_method_userdata, int32_t p_argument); -typedef void (*GDNativeExtensionClassMethodGetArgumentInfo)(void *p_method_userdata, int32_t p_argument, GDNativePropertyInfo *r_info); -typedef GDNativeExtensionClassMethodArgumentMetadata (*GDNativeExtensionClassMethodGetArgumentMetadata)(void *p_method_userdata, int32_t p_argument); - typedef struct { - const char *name; + GDNativeStringNamePtr name; void *method_userdata; GDNativeExtensionClassMethodCall call_func; GDNativeExtensionClassMethodPtrCall ptrcall_func; uint32_t method_flags; // Bitfield of `GDNativeExtensionClassMethodFlags` uint32_t argument_count; GDNativeBool has_return_value; - GDNativeExtensionClassMethodGetArgumentType get_argument_type_func; - GDNativeExtensionClassMethodGetArgumentInfo get_argument_info_func; /* name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. */ - GDNativeExtensionClassMethodGetArgumentMetadata get_argument_metadata_func; + GDNativePropertyInfo *return_value_info; // Ignored if `has_return_value` is false + GDNativeExtensionClassMethodArgumentMetadata return_value_metadata; // Ignored if `has_return_value` is false + /* name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. */ + GDNativePropertyInfo *aguments_info; // array of `argument_count` size + GDNativeExtensionClassMethodArgumentMetadata *aguments_metadata; // array of `argument_count` size uint32_t default_argument_count; - GDNativeVariantPtr *default_arguments; + GDNativeVariantPtr *default_arguments; // array of `default_argument_count` size } GDNativeExtensionClassMethodInfo; /* SCRIPT INSTANCE EXTENSION */ @@ -312,7 +309,6 @@ typedef GDNativeBool (*GDNativeExtensionScriptInstanceSet)(GDNativeExtensionScri typedef GDNativeBool (*GDNativeExtensionScriptInstanceGet)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret); typedef const GDNativePropertyInfo *(*GDNativeExtensionScriptInstanceGetPropertyList)(GDNativeExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count); typedef void (*GDNativeExtensionScriptInstanceFreePropertyList)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativePropertyInfo *p_list); -typedef GDNativeVariantType (*GDNativeExtensionScriptInstanceGetPropertyType)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeBool *r_is_valid); typedef GDNativeBool (*GDNativeExtensionScriptInstancePropertyCanRevert)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name); typedef GDNativeBool (*GDNativeExtensionScriptInstancePropertyGetRevert)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret); @@ -328,7 +324,7 @@ typedef GDNativeBool (*GDNativeExtensionScriptInstanceHasMethod)(GDNativeExtensi typedef void (*GDNativeExtensionScriptInstanceCall)(GDNativeExtensionScriptInstanceDataPtr p_self, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error); typedef void (*GDNativeExtensionScriptInstanceNotification)(GDNativeExtensionScriptInstanceDataPtr p_instance, int32_t p_what); -typedef const char *(*GDNativeExtensionScriptInstanceToString)(GDNativeExtensionScriptInstanceDataPtr p_instance, GDNativeBool *r_is_valid); +typedef void (*GDNativeExtensionScriptInstanceToString)(GDNativeExtensionScriptInstanceDataPtr p_instance, GDNativeBool *r_is_valid, GDNativeStringPtr r_out); typedef void (*GDNativeExtensionScriptInstanceRefCountIncremented)(GDNativeExtensionScriptInstanceDataPtr p_instance); typedef GDNativeBool (*GDNativeExtensionScriptInstanceRefCountDecremented)(GDNativeExtensionScriptInstanceDataPtr p_instance); @@ -349,7 +345,6 @@ typedef struct { GDNativeExtensionScriptInstanceGet get_func; GDNativeExtensionScriptInstanceGetPropertyList get_property_list_func; GDNativeExtensionScriptInstanceFreePropertyList free_property_list_func; - GDNativeExtensionScriptInstanceGetPropertyType get_property_type_func; GDNativeExtensionScriptInstancePropertyCanRevert property_can_revert_func; GDNativeExtensionScriptInstancePropertyGetRevert property_get_revert_func; @@ -400,7 +395,7 @@ typedef struct { void (*print_warning)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line); void (*print_script_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line); - uint64_t (*get_native_struct_size)(const char *p_name); + uint64_t (*get_native_struct_size)(const GDNativeStringNamePtr p_name); /* GODOT VARIANT */ @@ -443,19 +438,19 @@ typedef struct { GDNativeVariantFromTypeConstructorFunc (*get_variant_from_type_constructor)(GDNativeVariantType p_type); GDNativeTypeFromVariantConstructorFunc (*get_variant_to_type_constructor)(GDNativeVariantType p_type); GDNativePtrOperatorEvaluator (*variant_get_ptr_operator_evaluator)(GDNativeVariantOperator p_operator, GDNativeVariantType p_type_a, GDNativeVariantType p_type_b); - GDNativePtrBuiltInMethod (*variant_get_ptr_builtin_method)(GDNativeVariantType p_type, const char *p_method, GDNativeInt p_hash); + GDNativePtrBuiltInMethod (*variant_get_ptr_builtin_method)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_method, GDNativeInt p_hash); GDNativePtrConstructor (*variant_get_ptr_constructor)(GDNativeVariantType p_type, int32_t p_constructor); GDNativePtrDestructor (*variant_get_ptr_destructor)(GDNativeVariantType p_type); void (*variant_construct)(GDNativeVariantType p_type, GDNativeVariantPtr p_base, const GDNativeVariantPtr *p_args, int32_t p_argument_count, GDNativeCallError *r_error); - GDNativePtrSetter (*variant_get_ptr_setter)(GDNativeVariantType p_type, const char *p_member); - GDNativePtrGetter (*variant_get_ptr_getter)(GDNativeVariantType p_type, const char *p_member); + GDNativePtrSetter (*variant_get_ptr_setter)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member); + GDNativePtrGetter (*variant_get_ptr_getter)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member); GDNativePtrIndexedSetter (*variant_get_ptr_indexed_setter)(GDNativeVariantType p_type); GDNativePtrIndexedGetter (*variant_get_ptr_indexed_getter)(GDNativeVariantType p_type); GDNativePtrKeyedSetter (*variant_get_ptr_keyed_setter)(GDNativeVariantType p_type); GDNativePtrKeyedGetter (*variant_get_ptr_keyed_getter)(GDNativeVariantType p_type); GDNativePtrKeyedChecker (*variant_get_ptr_keyed_checker)(GDNativeVariantType p_type); - void (*variant_get_constant_value)(GDNativeVariantType p_type, const char *p_constant, GDNativeVariantPtr r_ret); - GDNativePtrUtilityFunction (*variant_get_ptr_utility_function)(const char *p_function, GDNativeInt p_hash); + void (*variant_get_constant_value)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_constant, GDNativeVariantPtr r_ret); + GDNativePtrUtilityFunction (*variant_get_ptr_utility_function)(const GDNativeStringNamePtr p_function, GDNativeInt p_hash); /* extra utilities */ @@ -524,12 +519,12 @@ typedef struct { void (*object_method_bind_call)(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeVariantPtr *p_args, GDNativeInt p_arg_count, GDNativeVariantPtr r_ret, GDNativeCallError *r_error); void (*object_method_bind_ptrcall)(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret); void (*object_destroy)(GDNativeObjectPtr p_o); - GDNativeObjectPtr (*global_get_singleton)(const char *p_name); + GDNativeObjectPtr (*global_get_singleton)(const GDNativeStringNamePtr p_name); void *(*object_get_instance_binding)(GDNativeObjectPtr p_o, void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks); void (*object_set_instance_binding)(GDNativeObjectPtr p_o, void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks); - void (*object_set_instance)(GDNativeObjectPtr p_o, const char *p_classname, GDExtensionClassInstancePtr p_instance); /* p_classname should be a registered extension class and should extend the p_o object's class. */ + void (*object_set_instance)(GDNativeObjectPtr p_o, const GDNativeStringNamePtr p_classname, GDExtensionClassInstancePtr p_instance); /* p_classname should be a registered extension class and should extend the p_o object's class. */ GDNativeObjectPtr (*object_cast_to)(const GDNativeObjectPtr p_object, void *p_class_tag); GDNativeObjectPtr (*object_get_instance_from_id)(GDObjectInstanceID p_instance_id); @@ -540,20 +535,21 @@ typedef struct { GDNativeScriptInstancePtr (*script_instance_create)(const GDNativeExtensionScriptInstanceInfo *p_info, GDNativeExtensionScriptInstanceDataPtr p_instance_data); /* CLASSDB */ - GDNativeObjectPtr (*classdb_construct_object)(const char *p_classname); /* The passed class must be a built-in godot class, or an already-registered extension class. In both case, object_set_instance should be called to fully initialize the object. */ - GDNativeMethodBindPtr (*classdb_get_method_bind)(const char *p_classname, const char *p_methodname, GDNativeInt p_hash); - void *(*classdb_get_class_tag)(const char *p_classname); + GDNativeObjectPtr (*classdb_construct_object)(const GDNativeStringNamePtr p_classname); /* The passed class must be a built-in godot class, or an already-registered extension class. In both case, object_set_instance should be called to fully initialize the object. */ + GDNativeMethodBindPtr (*classdb_get_method_bind)(const GDNativeStringNamePtr p_classname, const GDNativeStringNamePtr p_methodname, GDNativeInt p_hash); + void *(*classdb_get_class_tag)(const GDNativeStringNamePtr p_classname); /* CLASSDB EXTENSION */ - void (*classdb_register_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs); - void (*classdb_register_extension_class_method)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info); - void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield); - void (*classdb_register_extension_class_property)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter); - void (*classdb_register_extension_class_property_group)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix); - void (*classdb_register_extension_class_property_subgroup)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix); - void (*classdb_register_extension_class_signal)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count); - void (*classdb_unregister_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name); /* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first. */ + // Provided parameters for `classdb_register_extension_*` can be safely freed once the function returns + void (*classdb_register_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs); + void (*classdb_register_extension_class_method)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info); + void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_enum_name, const GDNativeStringNamePtr p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield); + void (*classdb_register_extension_class_property)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativePropertyInfo *p_info, const GDNativeStringNamePtr p_setter, const GDNativeStringNamePtr p_getter); + void (*classdb_register_extension_class_property_group)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringPtr p_group_name, const GDNativeStringPtr p_prefix); + void (*classdb_register_extension_class_property_subgroup)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringPtr p_subgroup_name, const GDNativeStringPtr p_prefix); + void (*classdb_register_extension_class_signal)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count); + void (*classdb_unregister_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name); /* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first. */ void (*get_library_path)(const GDNativeExtensionClassLibraryPtr p_library, GDNativeStringPtr r_path); diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp index cc019584a5..8bbb72fd82 100644 --- a/core/extension/native_extension.cpp +++ b/core/extension/native_extension.cpp @@ -42,26 +42,37 @@ String NativeExtension::get_extension_list_config_file() { class NativeExtensionMethodBind : public MethodBind { GDNativeExtensionClassMethodCall call_func; GDNativeExtensionClassMethodPtrCall ptrcall_func; - GDNativeExtensionClassMethodGetArgumentType get_argument_type_func; - GDNativeExtensionClassMethodGetArgumentInfo get_argument_info_func; - GDNativeExtensionClassMethodGetArgumentMetadata get_argument_metadata_func; void *method_userdata; bool vararg; + PropertyInfo return_value_info; + GodotTypeInfo::Metadata return_value_metadata; + List<PropertyInfo> arguments_info; + List<GodotTypeInfo::Metadata> arguments_metadata; protected: virtual Variant::Type _gen_argument_type(int p_arg) const override { - return Variant::Type(get_argument_type_func(method_userdata, p_arg)); + if (p_arg < 0) { + return return_value_info.type; + } else { + return arguments_info[p_arg].type; + } } virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { - GDNativePropertyInfo pinfo; - get_argument_info_func(method_userdata, p_arg, &pinfo); - return PropertyInfo(pinfo); + if (p_arg < 0) { + return return_value_info; + } else { + return arguments_info[p_arg]; + } } public: #ifdef DEBUG_METHODS_ENABLED virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override { - return GodotTypeInfo::Metadata(get_argument_metadata_func(method_userdata, p_arg)); + if (p_arg < 0) { + return return_value_metadata; + } else { + return arguments_metadata[p_arg]; + } } #endif @@ -89,10 +100,17 @@ public: method_userdata = p_method_info->method_userdata; call_func = p_method_info->call_func; ptrcall_func = p_method_info->ptrcall_func; - get_argument_type_func = p_method_info->get_argument_type_func; - get_argument_info_func = p_method_info->get_argument_info_func; - get_argument_metadata_func = p_method_info->get_argument_metadata_func; - set_name(p_method_info->name); + set_name(*reinterpret_cast<StringName *>(p_method_info->name)); + + if (p_method_info->has_return_value) { + return_value_info = PropertyInfo(*p_method_info->return_value_info); + return_value_metadata = GodotTypeInfo::Metadata(p_method_info->return_value_metadata); + } + + for (uint32_t i = 0; i < p_method_info->argument_count; i++) { + arguments_info.push_back(PropertyInfo(p_method_info->aguments_info[i])); + arguments_metadata.push_back(GodotTypeInfo::Metadata(p_method_info->aguments_metadata[i])); + } set_hint_flags(p_method_info->method_flags); @@ -117,15 +135,15 @@ public: static GDNativeInterface gdnative_interface; -void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs) { +void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs) { NativeExtension *self = static_cast<NativeExtension *>(p_library); - StringName class_name = p_class_name; + StringName class_name = *reinterpret_cast<StringName *>(p_class_name); + StringName parent_class_name = *reinterpret_cast<StringName *>(p_parent_class_name); ERR_FAIL_COND_MSG(!String(class_name).is_valid_identifier(), "Attempt to register extension class '" + class_name + "', which is not a valid class identifier."); ERR_FAIL_COND_MSG(ClassDB::class_exists(class_name), "Attempt to register extension class '" + class_name + "', which appears to be already registered."); Extension *parent_extension = nullptr; - StringName parent_class_name = p_parent_class_name; if (self->extension_classes.has(parent_class_name)) { parent_extension = &self->extension_classes[parent_class_name]; @@ -172,11 +190,11 @@ void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibr ClassDB::register_extension_class(&extension->native_extension); } -void NativeExtension::_register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info) { +void NativeExtension::_register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info) { NativeExtension *self = static_cast<NativeExtension *>(p_library); - StringName class_name = p_class_name; - StringName method_name = p_method_info->name; + StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); + StringName method_name = *reinterpret_cast<const StringName *>(p_method_info->name); ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension method '" + String(method_name) + "' for unexisting class '" + class_name + "'."); //Extension *extension = &self->extension_classes[class_name]; @@ -186,56 +204,63 @@ void NativeExtension::_register_extension_class_method(const GDNativeExtensionCl ClassDB::bind_method_custom(class_name, method); } -void NativeExtension::_register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield) { +void NativeExtension::_register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_enum_name, const GDNativeStringNamePtr p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield) { NativeExtension *self = static_cast<NativeExtension *>(p_library); - StringName class_name = p_class_name; - ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension constant '" + String(p_constant_name) + "' for unexisting class '" + class_name + "'."); - - //Extension *extension = &self->extension_classes[class_name]; + StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); + StringName enum_name = *reinterpret_cast<const StringName *>(p_enum_name); + StringName constant_name = *reinterpret_cast<const StringName *>(p_constant_name); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension constant '" + constant_name + "' for unexisting class '" + class_name + "'."); - ClassDB::bind_integer_constant(class_name, p_enum_name, p_constant_name, p_constant_value, p_is_bitfield); + ClassDB::bind_integer_constant(class_name, enum_name, constant_name, p_constant_value, p_is_bitfield); } -void NativeExtension::_register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter) { +void NativeExtension::_register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativePropertyInfo *p_info, const GDNativeStringNamePtr p_setter, const GDNativeStringNamePtr p_getter) { NativeExtension *self = static_cast<NativeExtension *>(p_library); - StringName class_name = p_class_name; - String property_name = p_info->name; + StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); + StringName setter = *reinterpret_cast<const StringName *>(p_setter); + StringName getter = *reinterpret_cast<const StringName *>(p_getter); + String property_name = *reinterpret_cast<const StringName *>(p_info->name); ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property '" + property_name + "' for unexisting class '" + class_name + "'."); //Extension *extension = &self->extension_classes[class_name]; PropertyInfo pinfo(*p_info); - ClassDB::add_property(class_name, pinfo, p_setter, p_getter); + ClassDB::add_property(class_name, pinfo, setter, getter); } -void NativeExtension::_register_extension_class_property_group(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix) { +void NativeExtension::_register_extension_class_property_group(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringPtr p_group_name, const GDNativeStringPtr p_prefix) { NativeExtension *self = static_cast<NativeExtension *>(p_library); - StringName class_name = p_class_name; - ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property group '" + String(p_group_name) + "' for unexisting class '" + class_name + "'."); + StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); + String group_name = *reinterpret_cast<const String *>(p_group_name); + String prefix = *reinterpret_cast<const String *>(p_prefix); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property group '" + group_name + "' for unexisting class '" + class_name + "'."); - ClassDB::add_property_group(class_name, p_group_name, p_prefix); + ClassDB::add_property_group(class_name, group_name, prefix); } -void NativeExtension::_register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix) { +void NativeExtension::_register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringPtr p_subgroup_name, const GDNativeStringPtr p_prefix) { NativeExtension *self = static_cast<NativeExtension *>(p_library); - StringName class_name = p_class_name; - ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property subgroup '" + String(p_subgroup_name) + "' for unexisting class '" + class_name + "'."); + StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); + String subgroup_name = *reinterpret_cast<const String *>(p_subgroup_name); + String prefix = *reinterpret_cast<const String *>(p_prefix); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property subgroup '" + subgroup_name + "' for unexisting class '" + class_name + "'."); - ClassDB::add_property_subgroup(class_name, p_subgroup_name, p_prefix); + ClassDB::add_property_subgroup(class_name, subgroup_name, prefix); } -void NativeExtension::_register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count) { +void NativeExtension::_register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count) { NativeExtension *self = static_cast<NativeExtension *>(p_library); - StringName class_name = p_class_name; - ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class signal '" + String(p_signal_name) + "' for unexisting class '" + class_name + "'."); + StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); + StringName signal_name = *reinterpret_cast<const StringName *>(p_signal_name); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class signal '" + signal_name + "' for unexisting class '" + class_name + "'."); MethodInfo s; - s.name = p_signal_name; + s.name = signal_name; for (int i = 0; i < p_argument_count; i++) { PropertyInfo arg(p_argument_info[i]); s.arguments.push_back(arg); @@ -243,10 +268,10 @@ void NativeExtension::_register_extension_class_signal(const GDNativeExtensionCl ClassDB::add_signal(class_name, s); } -void NativeExtension::_unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name) { +void NativeExtension::_unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name) { NativeExtension *self = static_cast<NativeExtension *>(p_library); - StringName class_name = p_class_name; + StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to unregister unexisting extension class '" + class_name + "'."); Extension *ext = &self->extension_classes[class_name]; ERR_FAIL_COND_MSG(ext->native_extension.children.size(), "Attempt to unregister class '" + class_name + "' while other extension classes inherit from it."); diff --git a/core/extension/native_extension.h b/core/extension/native_extension.h index b7238d2899..70f6f9f039 100644 --- a/core/extension/native_extension.h +++ b/core/extension/native_extension.h @@ -47,14 +47,14 @@ class NativeExtension : public Resource { HashMap<StringName, Extension> extension_classes; - static void _register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs); - static void _register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info); - static void _register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield); - static void _register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter); - static void _register_extension_class_property_group(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix); - static void _register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix); - static void _register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count); - static void _unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name); + static void _register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs); + static void _register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info); + static void _register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_enum_name, const GDNativeStringNamePtr p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield); + static void _register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativePropertyInfo *p_info, const GDNativeStringNamePtr p_setter, const GDNativeStringNamePtr p_getter); + static void _register_extension_class_property_group(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_group_name, const GDNativeStringNamePtr p_prefix); + static void _register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_subgroup_name, const GDNativeStringNamePtr p_prefix); + static void _register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count); + static void _unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name); static void _get_library_path(const GDNativeExtensionClassLibraryPtr p_library, GDNativeStringPtr r_path); GDNativeInitialization initialization; diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp index 0863dea053..afde6863a3 100644 --- a/core/object/class_db.cpp +++ b/core/object/class_db.cpp @@ -1460,7 +1460,7 @@ Variant ClassDB::class_get_default_property_value(const StringName &p_class, con if (Engine::get_singleton()->has_singleton(p_class)) { c = Engine::get_singleton()->get_singleton_object(p_class); cleanup_c = false; - } else if (ClassDB::can_instantiate(p_class) && !ClassDB::is_virtual(p_class)) { + } else if (ClassDB::can_instantiate(p_class)) { // Keep this condition in sync with doc_tools.cpp get_documentation_default_value. c = ClassDB::instantiate(p_class); cleanup_c = true; } diff --git a/core/object/make_virtuals.py b/core/object/make_virtuals.py index 326a9277ff..61bf6d900a 100644 --- a/core/object/make_virtuals.py +++ b/core/object/make_virtuals.py @@ -16,7 +16,8 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\ } \\ }\\ if (unlikely(_get_extension() && !_gdvirtual_##m_name##_initialized)) {\\ - _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, #m_name) : (GDNativeExtensionClassCallVirtual) nullptr;\\ + /* TODO: C-style cast because GDNativeStringNamePtr's const qualifier is broken (see https://github.com/godotengine/godot/pull/67751) */\\ + _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, (GDNativeStringNamePtr)&_gdvirtual_##m_name##_sn) : (GDNativeExtensionClassCallVirtual) nullptr;\\ _gdvirtual_##m_name##_initialized = true;\\ }\\ if (_gdvirtual_##m_name) {\\ @@ -40,7 +41,8 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_overridden() const { \\ return _script_instance->has_method(_gdvirtual_##m_name##_sn);\\ }\\ if (unlikely(_get_extension() && !_gdvirtual_##m_name##_initialized)) {\\ - _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, #m_name) : (GDNativeExtensionClassCallVirtual) nullptr;\\ + /* TODO: C-style cast because GDNativeStringNamePtr's const qualifier is broken (see https://github.com/godotengine/godot/pull/67751) */\\ + _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, (GDNativeStringNamePtr)&_gdvirtual_##m_name##_sn) : (GDNativeExtensionClassCallVirtual) nullptr;\\ _gdvirtual_##m_name##_initialized = true;\\ }\\ if (_gdvirtual_##m_name) {\\ diff --git a/core/object/object.cpp b/core/object/object.cpp index 540b9a8f19..d27e0d7621 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -808,7 +808,8 @@ String Object::to_string() { } if (_extension && _extension->to_string) { String ret; - _extension->to_string(_extension_instance, &ret); + GDNativeBool is_valid; + _extension->to_string(_extension_instance, &is_valid, &ret); return ret; } return "<" + get_class() + "#" + itos(get_instance_id()) + ">"; diff --git a/core/object/object.h b/core/object/object.h index 8c647cda40..7bb88998a2 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -192,10 +192,10 @@ struct PropertyInfo { explicit PropertyInfo(const GDNativePropertyInfo &pinfo) : type((Variant::Type)pinfo.type), - name(pinfo.name), - class_name(pinfo.class_name), // can be null + name(*reinterpret_cast<StringName *>(pinfo.name)), + class_name(*reinterpret_cast<StringName *>(pinfo.class_name)), hint((PropertyHint)pinfo.hint), - hint_string(pinfo.hint_string), // can be null + hint_string(*reinterpret_cast<String *>(pinfo.hint_string)), usage(pinfo.usage) {} bool operator==(const PropertyInfo &p_info) const { @@ -242,6 +242,20 @@ struct MethodInfo { MethodInfo() {} + explicit MethodInfo(const GDNativeMethodInfo &pinfo) : + name(*reinterpret_cast<StringName *>(pinfo.name)), + return_val(PropertyInfo(pinfo.return_value)), + flags(pinfo.flags), + id(pinfo.id) { + for (uint32_t j = 0; j < pinfo.argument_count; j++) { + arguments.push_back(PropertyInfo(pinfo.arguments[j])); + } + const Variant *def_values = (const Variant *)pinfo.default_arguments; + for (uint32_t j = 0; j < pinfo.default_argument_count; j++) { + default_arguments.push_back(def_values[j]); + } + } + void _push_params(const PropertyInfo &p_param) { arguments.push_back(p_param); } diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h index c32fb9d85b..c287a6f71a 100644 --- a/core/object/script_language_extension.h +++ b/core/object/script_language_extension.h @@ -681,16 +681,21 @@ public: } } virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = nullptr) const override { - if (native_info->get_property_type_func) { - GDNativeBool is_valid = 0; - GDNativeVariantType type = native_info->get_property_type_func(instance, (const GDNativeStringNamePtr)&p_name, &is_valid); - if (r_is_valid) { - *r_is_valid = is_valid != 0; + Variant::Type type = Variant::Type::NIL; + if (native_info->get_property_list_func) { + uint32_t pcount; + const GDNativePropertyInfo *pinfo = native_info->get_property_list_func(instance, &pcount); + for (uint32_t i = 0; i < pcount; i++) { + if (p_name == *reinterpret_cast<StringName *>(pinfo->name)) { + type = Variant::Type(pinfo->type); + break; + } + } + if (native_info->free_property_list_func) { + native_info->free_property_list_func(instance, pinfo); } - - return Variant::Type(type); } - return Variant::NIL; + return type; } virtual bool property_can_revert(const StringName &p_name) const override { @@ -727,19 +732,7 @@ public: uint32_t mcount; const GDNativeMethodInfo *minfo = native_info->get_method_list_func(instance, &mcount); for (uint32_t i = 0; i < mcount; i++) { - MethodInfo m; - m.name = minfo[i].name; - m.flags = minfo[i].flags; - m.id = minfo[i].id; - m.return_val = PropertyInfo(minfo[i].return_value); - for (uint32_t j = 0; j < minfo[i].argument_count; j++) { - m.arguments.push_back(PropertyInfo(minfo[i].arguments[j])); - } - const Variant *def_values = (const Variant *)minfo[i].default_arguments; - for (uint32_t j = 0; j < minfo[i].default_argument_count; j++) { - m.default_arguments.push_back(def_values[j]); - } - p_list->push_back(m); + p_list->push_back(MethodInfo(minfo[i])); } if (native_info->free_method_list_func) { native_info->free_method_list_func(instance, minfo); @@ -773,7 +766,8 @@ public: virtual String to_string(bool *r_valid) override { if (native_info->to_string_func) { GDNativeBool valid; - String ret = native_info->to_string_func(instance, &valid); + String ret; + native_info->to_string_func(instance, &valid, reinterpret_cast<GDNativeStringPtr>(&ret)); if (r_valid) { *r_valid = valid != 0; } diff --git a/doc/classes/BaseButton.xml b/doc/classes/BaseButton.xml index 638934bc9e..c92e39e08a 100644 --- a/doc/classes/BaseButton.xml +++ b/doc/classes/BaseButton.xml @@ -44,37 +44,38 @@ </method> </methods> <members> - <member name="action_mode" type="int" setter="set_action_mode" getter="get_action_mode" enum="BaseButton.ActionMode"> + <member name="action_mode" type="int" setter="set_action_mode" getter="get_action_mode" enum="BaseButton.ActionMode" default="1"> Determines when the button is considered clicked, one of the [enum ActionMode] constants. </member> <member name="button_group" type="ButtonGroup" setter="set_button_group" getter="get_button_group"> The [ButtonGroup] associated with the button. Not to be confused with node groups. </member> - <member name="button_mask" type="int" setter="set_button_mask" getter="get_button_mask" enum="MouseButton"> + <member name="button_mask" type="int" setter="set_button_mask" getter="get_button_mask" enum="MouseButton" default="1"> Binary mask to choose which mouse buttons this button will respond to. To allow both left-click and right-click, use [code]MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_RIGHT[/code]. </member> - <member name="button_pressed" type="bool" setter="set_pressed" getter="is_pressed"> + <member name="button_pressed" type="bool" setter="set_pressed" getter="is_pressed" default="false"> If [code]true[/code], the button's state is pressed. Means the button is pressed down or toggled (if [member toggle_mode] is active). Only works if [member toggle_mode] is [code]true[/code]. [b]Note:[/b] Setting [member button_pressed] will result in [signal toggled] to be emitted. If you want to change the pressed state without emitting that signal, use [method set_pressed_no_signal]. </member> - <member name="disabled" type="bool" setter="set_disabled" getter="is_disabled"> + <member name="disabled" type="bool" setter="set_disabled" getter="is_disabled" default="false"> If [code]true[/code], the button is in disabled state and can't be clicked or toggled. </member> - <member name="keep_pressed_outside" type="bool" setter="set_keep_pressed_outside" getter="is_keep_pressed_outside"> + <member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" overrides="Control" enum="Control.FocusMode" default="2" /> + <member name="keep_pressed_outside" type="bool" setter="set_keep_pressed_outside" getter="is_keep_pressed_outside" default="false"> If [code]true[/code], the button stays pressed when moving the cursor outside the button while pressing it. [b]Note:[/b] This property only affects the button's visual appearance. Signals will be emitted at the same moment regardless of this property's value. </member> <member name="shortcut" type="Shortcut" setter="set_shortcut" getter="get_shortcut"> [Shortcut] associated to the button. </member> - <member name="shortcut_feedback" type="bool" setter="set_shortcut_feedback" getter="is_shortcut_feedback"> + <member name="shortcut_feedback" type="bool" setter="set_shortcut_feedback" getter="is_shortcut_feedback" default="true"> If [code]true[/code], the button will appear pressed when its shortcut is activated. If [code]false[/code] and [member toggle_mode] is [code]false[/code], the shortcut will activate the button without appearing to press the button. </member> - <member name="shortcut_in_tooltip" type="bool" setter="set_shortcut_in_tooltip" getter="is_shortcut_in_tooltip_enabled"> + <member name="shortcut_in_tooltip" type="bool" setter="set_shortcut_in_tooltip" getter="is_shortcut_in_tooltip_enabled" default="true"> If [code]true[/code], the button will add information about its shortcut in the tooltip. </member> - <member name="toggle_mode" type="bool" setter="set_toggle_mode" getter="is_toggle_mode"> + <member name="toggle_mode" type="bool" setter="set_toggle_mode" getter="is_toggle_mode" default="false"> If [code]true[/code], the button is in toggle mode. Makes the button flip state between pressed and unpressed each time its area is clicked. </member> </members> diff --git a/doc/classes/CameraAttributes.xml b/doc/classes/CameraAttributes.xml index a741728c14..23dc212069 100644 --- a/doc/classes/CameraAttributes.xml +++ b/doc/classes/CameraAttributes.xml @@ -12,19 +12,19 @@ <tutorials> </tutorials> <members> - <member name="auto_exposure_enabled" type="bool" setter="set_auto_exposure_enabled" getter="is_auto_exposure_enabled"> + <member name="auto_exposure_enabled" type="bool" setter="set_auto_exposure_enabled" getter="is_auto_exposure_enabled" default="false"> If [code]true[/code], enables the tonemapping auto exposure mode of the scene renderer. If [code]true[/code], the renderer will automatically determine the exposure setting to adapt to the scene's illumination and the observed light. </member> - <member name="auto_exposure_scale" type="float" setter="set_auto_exposure_scale" getter="get_auto_exposure_scale"> + <member name="auto_exposure_scale" type="float" setter="set_auto_exposure_scale" getter="get_auto_exposure_scale" default="0.4"> The scale of the auto exposure effect. Affects the intensity of auto exposure. </member> - <member name="auto_exposure_speed" type="float" setter="set_auto_exposure_speed" getter="get_auto_exposure_speed"> + <member name="auto_exposure_speed" type="float" setter="set_auto_exposure_speed" getter="get_auto_exposure_speed" default="0.5"> The speed of the auto exposure effect. Affects the time needed for the camera to perform auto exposure. </member> - <member name="exposure_multiplier" type="float" setter="set_exposure_multiplier" getter="get_exposure_multiplier"> + <member name="exposure_multiplier" type="float" setter="set_exposure_multiplier" getter="get_exposure_multiplier" default="1.0"> Multiplier for the exposure amount. A higher value results in a brighter image. </member> - <member name="exposure_sensitivity" type="float" setter="set_exposure_sensitivity" getter="get_exposure_sensitivity"> + <member name="exposure_sensitivity" type="float" setter="set_exposure_sensitivity" getter="get_exposure_sensitivity" default="100.0"> Sensitivity of camera sensors, measured in ISO. A higher sensitivity results in a brighter image. Only available when [member ProjectSettings.rendering/lights_and_shadows/use_physical_light_units] is enabled. When [member auto_exposure_enabled] this can be used as a method of exposure compensation, doubling the value will increase the exposure value (measured in EV100) by 1 stop. </member> </members> diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index 113987bb52..76c67fd704 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -1725,9 +1725,17 @@ </constant> <constant name="WINDOW_VIEW" value="2" enum="HandleType"> Window view: + - Windows: [code]HDC[/code] for the window (only with the GL Compatibility renderer). - macOS: [code]NSView*[/code] for the window main view. - iOS: [code]UIView*[/code] for the window main view. </constant> + <constant name="OPENGL_CONTEXT" value="3" enum="HandleType"> + OpenGL context (only with the GL Compatibility renderer): + - Windows: [code]HGLRC[/code] for the window. + - Linux: [code]GLXContext*[/code] for the window. + - MacOS: [code]NSOpenGLContext*[/code] for the window. + - Android: [code]EGLContext[/code] for the window. + </constant> <constant name="TTS_UTTERANCE_STARTED" value="0" enum="TTSUtteranceEvent"> Utterance has begun to be spoken. </constant> diff --git a/doc/classes/EditorFeatureProfile.xml b/doc/classes/EditorFeatureProfile.xml index 99e97fc25f..27f61f1bd8 100644 --- a/doc/classes/EditorFeatureProfile.xml +++ b/doc/classes/EditorFeatureProfile.xml @@ -116,7 +116,10 @@ <constant name="FEATURE_IMPORT_DOCK" value="6" enum="Feature"> The Import dock. If this feature is disabled, the Import dock won't be visible. </constant> - <constant name="FEATURE_MAX" value="7" enum="Feature"> + <constant name="FEATURE_HISTORY_DOCK" value="7" enum="Feature"> + The History dock. If this feature is disabled, the History dock won't be visible. + </constant> + <constant name="FEATURE_MAX" value="8" enum="Feature"> Represents the size of the [enum Feature] enum. </constant> </constants> diff --git a/doc/classes/EditorSpinSlider.xml b/doc/classes/EditorSpinSlider.xml index 9961e11f7d..784a3c1214 100644 --- a/doc/classes/EditorSpinSlider.xml +++ b/doc/classes/EditorSpinSlider.xml @@ -12,6 +12,7 @@ <member name="flat" type="bool" setter="set_flat" getter="is_flat" default="false"> If [code]true[/code], the slider will not draw background. </member> + <member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" overrides="Control" enum="Control.FocusMode" default="2" /> <member name="hide_slider" type="bool" setter="set_hide_slider" getter="is_hiding_slider" default="false"> If [code]true[/code], the slider is hidden. </member> diff --git a/doc/classes/GPUParticles2D.xml b/doc/classes/GPUParticles2D.xml index 4916171900..c7d10078e8 100644 --- a/doc/classes/GPUParticles2D.xml +++ b/doc/classes/GPUParticles2D.xml @@ -89,12 +89,17 @@ Particle texture. If [code]null[/code], particles will be squares. </member> <member name="trail_enabled" type="bool" setter="set_trail_enabled" getter="is_trail_enabled" default="false"> + If [code]true[/code], enables particle trails using a mesh skinning system. + [b]Note:[/b] Unlike [GPUParticles3D], the number of trail sections and subdivisions is set with the [member trail_sections] and [member trail_section_subdivisions] properties. </member> - <member name="trail_length_secs" type="float" setter="set_trail_length" getter="get_trail_length" default="0.3"> + <member name="trail_lifetime" type="float" setter="set_trail_lifetime" getter="get_trail_lifetime" default="0.3"> + The amount of time the particle's trail should represent (in seconds). Only effective if [member trail_enabled] is [code]true[/code]. </member> <member name="trail_section_subdivisions" type="int" setter="set_trail_section_subdivisions" getter="get_trail_section_subdivisions" default="4"> + The number of subdivisions to use for the particle trail rendering. Higher values can result in smoother trail curves, at the cost of performance due to increased mesh complexity. See also [member trail_sections]. Only effective if [member trail_enabled] is [code]true[/code]. </member> <member name="trail_sections" type="int" setter="set_trail_sections" getter="get_trail_sections" default="8"> + The number of sections to use for the particle trail rendering. Higher values can result in smoother trail curves, at the cost of performance due to increased mesh complexity. See also [member trail_section_subdivisions]. Only effective if [member trail_enabled] is [code]true[/code]. </member> <member name="visibility_rect" type="Rect2" setter="set_visibility_rect" getter="get_visibility_rect" default="Rect2(-100, -100, 200, 200)"> The [Rect2] that determines the node's region which needs to be visible on screen for the particle system to be active. diff --git a/doc/classes/GPUParticles3D.xml b/doc/classes/GPUParticles3D.xml index d0be4d784a..ea53c5b4b5 100644 --- a/doc/classes/GPUParticles3D.xml +++ b/doc/classes/GPUParticles3D.xml @@ -116,8 +116,12 @@ <member name="sub_emitter" type="NodePath" setter="set_sub_emitter" getter="get_sub_emitter" default="NodePath("")"> </member> <member name="trail_enabled" type="bool" setter="set_trail_enabled" getter="is_trail_enabled" default="false"> + If [code]true[/code], enables particle trails using a mesh skinning system. Designed to work with [RibbonTrailMesh] and [TubeTrailMesh]. + [b]Note:[/b] [member BaseMaterial3D.use_particle_trails] must also be enabled on the particle mesh's material. Otherwise, setting [member trail_enabled] to [code]true[/code] will have no effect. + [b]Note:[/b] Unlike [GPUParticles2D], the number of trail sections and subdivisions is set in the [RibbonTrailMesh] or the [TubeTrailMesh]'s properties. </member> - <member name="trail_length_secs" type="float" setter="set_trail_length" getter="get_trail_length" default="0.3"> + <member name="trail_lifetime" type="float" setter="set_trail_lifetime" getter="get_trail_lifetime" default="0.3"> + The amount of time the particle's trail should represent (in seconds). Only effective if [member trail_enabled] is [code]true[/code]. </member> <member name="transform_align" type="int" setter="set_transform_align" getter="get_transform_align" enum="GPUParticles3D.TransformAlign" default="0"> </member> diff --git a/doc/classes/GeometryInstance3D.xml b/doc/classes/GeometryInstance3D.xml index 4d8ab91718..86d52ae9be 100644 --- a/doc/classes/GeometryInstance3D.xml +++ b/doc/classes/GeometryInstance3D.xml @@ -31,22 +31,22 @@ </method> </methods> <members> - <member name="cast_shadow" type="int" setter="set_cast_shadows_setting" getter="get_cast_shadows_setting" enum="GeometryInstance3D.ShadowCastingSetting"> + <member name="cast_shadow" type="int" setter="set_cast_shadows_setting" getter="get_cast_shadows_setting" enum="GeometryInstance3D.ShadowCastingSetting" default="1"> The selected shadow casting flag. See [enum ShadowCastingSetting] for possible values. </member> - <member name="extra_cull_margin" type="float" setter="set_extra_cull_margin" getter="get_extra_cull_margin"> + <member name="extra_cull_margin" type="float" setter="set_extra_cull_margin" getter="get_extra_cull_margin" default="0.0"> The extra distance added to the GeometryInstance3D's bounding box ([AABB]) to increase its cull box. </member> - <member name="gi_lightmap_scale" type="int" setter="set_lightmap_scale" getter="get_lightmap_scale" enum="GeometryInstance3D.LightmapScale"> + <member name="gi_lightmap_scale" type="int" setter="set_lightmap_scale" getter="get_lightmap_scale" enum="GeometryInstance3D.LightmapScale" default="0"> The texel density to use for lightmapping in [LightmapGI]. Greater scale values provide higher resolution in the lightmap, which can result in sharper shadows for lights that have both direct and indirect light baked. However, greater scale values will also increase the space taken by the mesh in the lightmap texture, which increases the memory, storage, and bake time requirements. When using a single mesh at different scales, consider adjusting this value to keep the lightmap texel density consistent across meshes. </member> - <member name="gi_mode" type="int" setter="set_gi_mode" getter="get_gi_mode" enum="GeometryInstance3D.GIMode"> + <member name="gi_mode" type="int" setter="set_gi_mode" getter="get_gi_mode" enum="GeometryInstance3D.GIMode" default="1"> The global illumination mode to use for the whole geometry. To avoid inconsistent results, use a mode that matches the purpose of the mesh during gameplay (static/dynamic). [b]Note:[/b] Lights' bake mode will also affect the global illumination rendering. See [member Light3D.light_bake_mode]. </member> - <member name="ignore_occlusion_culling" type="bool" setter="set_ignore_occlusion_culling" getter="is_ignoring_occlusion_culling"> + <member name="ignore_occlusion_culling" type="bool" setter="set_ignore_occlusion_culling" getter="is_ignoring_occlusion_culling" default="false"> </member> - <member name="lod_bias" type="float" setter="set_lod_bias" getter="get_lod_bias"> + <member name="lod_bias" type="float" setter="set_lod_bias" getter="get_lod_bias" default="1.0"> </member> <member name="material_overlay" type="Material" setter="set_material_overlay" getter="get_material_overlay"> The material overlay for the whole geometry. @@ -56,26 +56,26 @@ The material override for the whole geometry. If a material is assigned to this property, it will be used instead of any material set in any material slot of the mesh. </member> - <member name="transparency" type="float" setter="set_transparency" getter="get_transparency"> + <member name="transparency" type="float" setter="set_transparency" getter="get_transparency" default="0.0"> The transparency applied to the whole geometry (as a multiplier of the materials' existing transparency). [code]0.0[/code] is fully opaque, while [code]1.0[/code] is fully transparent. Values greater than [code]0.0[/code] (exclusive) will force the geometry's materials to go through the transparent pipeline, which is slower to render and can exhibit rendering issues due to incorrect transparency sorting. However, unlike using a transparent material, setting [member transparency] to a value greater than [code]0.0[/code] (exclusive) will [i]not[/i] disable shadow rendering. In spatial shaders, [code]1.0 - transparency[/code] is set as the default value of the [code]ALPHA[/code] built-in. [b]Note:[/b] [member transparency] is clamped between [code]0.0[/code] and [code]1.0[/code], so this property cannot be used to make transparent materials more opaque than they originally are. </member> - <member name="visibility_range_begin" type="float" setter="set_visibility_range_begin" getter="get_visibility_range_begin"> + <member name="visibility_range_begin" type="float" setter="set_visibility_range_begin" getter="get_visibility_range_begin" default="0.0"> Starting distance from which the GeometryInstance3D will be visible, taking [member visibility_range_begin_margin] into account as well. The default value of 0 is used to disable the range check. </member> - <member name="visibility_range_begin_margin" type="float" setter="set_visibility_range_begin_margin" getter="get_visibility_range_begin_margin"> + <member name="visibility_range_begin_margin" type="float" setter="set_visibility_range_begin_margin" getter="get_visibility_range_begin_margin" default="0.0"> Margin for the [member visibility_range_begin] threshold. The GeometryInstance3D will only change its visibility state when it goes over or under the [member visibility_range_begin] threshold by this amount. If [member visibility_range_fade_mode] is [constant VISIBILITY_RANGE_FADE_DISABLED], this acts as an hysteresis distance. If [member visibility_range_fade_mode] is [constant VISIBILITY_RANGE_FADE_SELF] or [constant VISIBILITY_RANGE_FADE_DEPENDENCIES], this acts as a fade transition distance and must be set to a value greater than [code]0.0[/code] for the effect to be noticeable. </member> - <member name="visibility_range_end" type="float" setter="set_visibility_range_end" getter="get_visibility_range_end"> + <member name="visibility_range_end" type="float" setter="set_visibility_range_end" getter="get_visibility_range_end" default="0.0"> Distance from which the GeometryInstance3D will be hidden, taking [member visibility_range_end_margin] into account as well. The default value of 0 is used to disable the range check. </member> - <member name="visibility_range_end_margin" type="float" setter="set_visibility_range_end_margin" getter="get_visibility_range_end_margin"> + <member name="visibility_range_end_margin" type="float" setter="set_visibility_range_end_margin" getter="get_visibility_range_end_margin" default="0.0"> Margin for the [member visibility_range_end] threshold. The GeometryInstance3D will only change its visibility state when it goes over or under the [member visibility_range_end] threshold by this amount. If [member visibility_range_fade_mode] is [constant VISIBILITY_RANGE_FADE_DISABLED], this acts as an hysteresis distance. If [member visibility_range_fade_mode] is [constant VISIBILITY_RANGE_FADE_SELF] or [constant VISIBILITY_RANGE_FADE_DEPENDENCIES], this acts as a fade transition distance and must be set to a value greater than [code]0.0[/code] for the effect to be noticeable. </member> - <member name="visibility_range_fade_mode" type="int" setter="set_visibility_range_fade_mode" getter="get_visibility_range_fade_mode" enum="GeometryInstance3D.VisibilityRangeFadeMode"> + <member name="visibility_range_fade_mode" type="int" setter="set_visibility_range_fade_mode" getter="get_visibility_range_fade_mode" enum="GeometryInstance3D.VisibilityRangeFadeMode" default="0"> Controls which instances will be faded when approaching the limits of the visibility range. See [enum VisibilityRangeFadeMode] for possible values. </member> </members> diff --git a/doc/classes/Label3D.xml b/doc/classes/Label3D.xml index b741dc6e64..0cbca2224e 100644 --- a/doc/classes/Label3D.xml +++ b/doc/classes/Label3D.xml @@ -44,6 +44,7 @@ <member name="billboard" type="int" setter="set_billboard_mode" getter="get_billboard_mode" enum="BaseMaterial3D.BillboardMode" default="0"> The billboard mode to use for the label. See [enum BaseMaterial3D.BillboardMode] for possible values. </member> + <member name="cast_shadow" type="int" setter="set_cast_shadows_setting" getter="get_cast_shadows_setting" overrides="GeometryInstance3D" enum="GeometryInstance3D.ShadowCastingSetting" default="0" /> <member name="double_sided" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="true"> If [code]true[/code], text can be seen from the back as well, if [code]false[/code], it is invisible when looking at it from behind. </member> @@ -57,6 +58,7 @@ Font size of the [Label3D]'s text. To make the font look more detailed when up close, increase [member font_size] while decreasing [member pixel_size] at the same time. Higher font sizes require more time to render new characters, which can cause stuttering during gameplay. </member> + <member name="gi_mode" type="int" setter="set_gi_mode" getter="get_gi_mode" overrides="GeometryInstance3D" enum="GeometryInstance3D.GIMode" default="0" /> <member name="horizontal_alignment" type="int" setter="set_horizontal_alignment" getter="get_horizontal_alignment" enum="HorizontalAlignment" default="1"> Controls the text's horizontal alignment. Supports left, center, right, and fill, or justify. Set it to one of the [enum HorizontalAlignment] constants. </member> diff --git a/doc/classes/LinkButton.xml b/doc/classes/LinkButton.xml index 7c6ff2d4e1..d7701ea184 100644 --- a/doc/classes/LinkButton.xml +++ b/doc/classes/LinkButton.xml @@ -10,9 +10,11 @@ <tutorials> </tutorials> <members> + <member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" overrides="Control" enum="Control.FocusMode" default="0" /> <member name="language" type="String" setter="set_language" getter="get_language" default=""""> Language code used for line-breaking and text shaping algorithms, if left empty current locale is used instead. </member> + <member name="mouse_default_cursor_shape" type="int" setter="set_default_cursor_shape" getter="get_default_cursor_shape" overrides="Control" enum="Control.CursorShape" default="2" /> <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="TextServer.StructuredTextParser" default="0"> Set BiDi algorithm override for the structured text. </member> diff --git a/doc/classes/Mesh.xml b/doc/classes/Mesh.xml index facbe5fd0f..640fa9efec 100644 --- a/doc/classes/Mesh.xml +++ b/doc/classes/Mesh.xml @@ -176,7 +176,7 @@ </method> </methods> <members> - <member name="lightmap_size_hint" type="Vector2i" setter="set_lightmap_size_hint" getter="get_lightmap_size_hint"> + <member name="lightmap_size_hint" type="Vector2i" setter="set_lightmap_size_hint" getter="get_lightmap_size_hint" default="Vector2i(0, 0)"> Sets a hint to be used for lightmap resolution. </member> </members> diff --git a/doc/classes/PhysicsDirectBodyState2D.xml b/doc/classes/PhysicsDirectBodyState2D.xml index fdc3a44e9d..e8062f3e94 100644 --- a/doc/classes/PhysicsDirectBodyState2D.xml +++ b/doc/classes/PhysicsDirectBodyState2D.xml @@ -76,6 +76,7 @@ <param index="0" name="torque" type="float" /> <description> Applies a rotational force without affecting position. A force is time dependent and meant to be applied every physics update. + [b]Note:[/b] [member inverse_inertia] is required for this to work. To have [member inverse_inertia], an active [CollisionShape2D] must be a child of the node, or you can manually set [member inverse_inertia]. </description> </method> <method name="apply_torque_impulse"> @@ -84,6 +85,7 @@ <description> Applies a rotational impulse to the body without affecting the position. An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise). + [b]Note:[/b] [member inverse_inertia] is required for this to work. To have [member inverse_inertia], an active [CollisionShape2D] must be a child of the node, or you can manually set [member inverse_inertia]. </description> </method> <method name="get_constant_force" qualifiers="const"> @@ -207,40 +209,40 @@ </method> </methods> <members> - <member name="angular_velocity" type="float" setter="set_angular_velocity" getter="get_angular_velocity"> + <member name="angular_velocity" type="float" setter="set_angular_velocity" getter="get_angular_velocity" default="0.0"> The body's rotational velocity in [i]radians[/i] per second. </member> - <member name="center_of_mass" type="Vector2" setter="" getter="get_center_of_mass"> + <member name="center_of_mass" type="Vector2" setter="" getter="get_center_of_mass" default="Vector2(0, 0)"> The body's center of mass position relative to the body's center in the global coordinate system. </member> - <member name="center_of_mass_local" type="Vector2" setter="" getter="get_center_of_mass_local"> + <member name="center_of_mass_local" type="Vector2" setter="" getter="get_center_of_mass_local" default="Vector2(0, 0)"> The body's center of mass position in the body's local coordinate system. </member> - <member name="inverse_inertia" type="float" setter="" getter="get_inverse_inertia"> + <member name="inverse_inertia" type="float" setter="" getter="get_inverse_inertia" default="0.0"> The inverse of the inertia of the body. </member> - <member name="inverse_mass" type="float" setter="" getter="get_inverse_mass"> + <member name="inverse_mass" type="float" setter="" getter="get_inverse_mass" default="0.0"> The inverse of the mass of the body. </member> - <member name="linear_velocity" type="Vector2" setter="set_linear_velocity" getter="get_linear_velocity"> + <member name="linear_velocity" type="Vector2" setter="set_linear_velocity" getter="get_linear_velocity" default="Vector2(0, 0)"> The body's linear velocity in pixels per second. </member> - <member name="sleeping" type="bool" setter="set_sleep_state" getter="is_sleeping"> + <member name="sleeping" type="bool" setter="set_sleep_state" getter="is_sleeping" default="false"> If [code]true[/code], this body is currently sleeping (not active). </member> - <member name="step" type="float" setter="" getter="get_step"> + <member name="step" type="float" setter="" getter="get_step" default="0.0"> The timestep (delta) used for the simulation. </member> - <member name="total_angular_damp" type="float" setter="" getter="get_total_angular_damp"> + <member name="total_angular_damp" type="float" setter="" getter="get_total_angular_damp" default="0.0"> The rate at which the body stops rotating, if there are not any other forces moving it. </member> - <member name="total_gravity" type="Vector2" setter="" getter="get_total_gravity"> + <member name="total_gravity" type="Vector2" setter="" getter="get_total_gravity" default="Vector2(0, 0)"> The total gravity vector being currently applied to this body. </member> - <member name="total_linear_damp" type="float" setter="" getter="get_total_linear_damp"> + <member name="total_linear_damp" type="float" setter="" getter="get_total_linear_damp" default="0.0"> The rate at which the body stops moving, if there are not any other forces moving it. </member> - <member name="transform" type="Transform2D" setter="set_transform" getter="get_transform"> + <member name="transform" type="Transform2D" setter="set_transform" getter="get_transform" default="Transform2D(1, 0, 0, 1, 0, 0)"> The body's transformation matrix. </member> </members> diff --git a/doc/classes/PhysicsDirectBodyState3D.xml b/doc/classes/PhysicsDirectBodyState3D.xml index 04087cbfb6..4c6d51c85a 100644 --- a/doc/classes/PhysicsDirectBodyState3D.xml +++ b/doc/classes/PhysicsDirectBodyState3D.xml @@ -76,6 +76,7 @@ <param index="0" name="torque" type="Vector3" /> <description> Applies a rotational force without affecting position. A force is time dependent and meant to be applied every physics update. + [b]Note:[/b] [member inverse_inertia] is required for this to work. To have [member inverse_inertia], an active [CollisionShape3D] must be a child of the node, or you can manually set [member inverse_inertia]. </description> </method> <method name="apply_torque_impulse"> @@ -84,6 +85,7 @@ <description> Applies a rotational impulse to the body without affecting the position. An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise). + [b]Note:[/b] [member inverse_inertia] is required for this to work. To have [member inverse_inertia], an active [CollisionShape3D] must be a child of the node, or you can manually set [member inverse_inertia]. </description> </method> <method name="get_constant_force" qualifiers="const"> @@ -214,45 +216,45 @@ </method> </methods> <members> - <member name="angular_velocity" type="Vector3" setter="set_angular_velocity" getter="get_angular_velocity"> + <member name="angular_velocity" type="Vector3" setter="set_angular_velocity" getter="get_angular_velocity" default="Vector3(0, 0, 0)"> The body's rotational velocity in [i]radians[/i] per second. </member> - <member name="center_of_mass" type="Vector3" setter="" getter="get_center_of_mass"> + <member name="center_of_mass" type="Vector3" setter="" getter="get_center_of_mass" default="Vector3(0, 0, 0)"> The body's center of mass position relative to the body's center in the global coordinate system. </member> - <member name="center_of_mass_local" type="Vector3" setter="" getter="get_center_of_mass_local"> + <member name="center_of_mass_local" type="Vector3" setter="" getter="get_center_of_mass_local" default="Vector3(0, 0, 0)"> The body's center of mass position in the body's local coordinate system. </member> - <member name="inverse_inertia" type="Vector3" setter="" getter="get_inverse_inertia"> + <member name="inverse_inertia" type="Vector3" setter="" getter="get_inverse_inertia" default="Vector3(0, 0, 0)"> The inverse of the inertia of the body. </member> - <member name="inverse_inertia_tensor" type="Basis" setter="" getter="get_inverse_inertia_tensor"> + <member name="inverse_inertia_tensor" type="Basis" setter="" getter="get_inverse_inertia_tensor" default="Basis(1, 0, 0, 0, 1, 0, 0, 0, 1)"> The inverse of the inertia tensor of the body. </member> - <member name="inverse_mass" type="float" setter="" getter="get_inverse_mass"> + <member name="inverse_mass" type="float" setter="" getter="get_inverse_mass" default="0.0"> The inverse of the mass of the body. </member> - <member name="linear_velocity" type="Vector3" setter="set_linear_velocity" getter="get_linear_velocity"> + <member name="linear_velocity" type="Vector3" setter="set_linear_velocity" getter="get_linear_velocity" default="Vector3(0, 0, 0)"> The body's linear velocity in units per second. </member> - <member name="principal_inertia_axes" type="Basis" setter="" getter="get_principal_inertia_axes"> + <member name="principal_inertia_axes" type="Basis" setter="" getter="get_principal_inertia_axes" default="Basis(1, 0, 0, 0, 1, 0, 0, 0, 1)"> </member> - <member name="sleeping" type="bool" setter="set_sleep_state" getter="is_sleeping"> + <member name="sleeping" type="bool" setter="set_sleep_state" getter="is_sleeping" default="false"> If [code]true[/code], this body is currently sleeping (not active). </member> - <member name="step" type="float" setter="" getter="get_step"> + <member name="step" type="float" setter="" getter="get_step" default="0.0"> The timestep (delta) used for the simulation. </member> - <member name="total_angular_damp" type="float" setter="" getter="get_total_angular_damp"> + <member name="total_angular_damp" type="float" setter="" getter="get_total_angular_damp" default="0.0"> The rate at which the body stops rotating, if there are not any other forces moving it. </member> - <member name="total_gravity" type="Vector3" setter="" getter="get_total_gravity"> + <member name="total_gravity" type="Vector3" setter="" getter="get_total_gravity" default="Vector3(0, 0, 0)"> The total gravity vector being currently applied to this body. </member> - <member name="total_linear_damp" type="float" setter="" getter="get_total_linear_damp"> + <member name="total_linear_damp" type="float" setter="" getter="get_total_linear_damp" default="0.0"> The rate at which the body stops moving, if there are not any other forces moving it. </member> - <member name="transform" type="Transform3D" setter="set_transform" getter="get_transform"> + <member name="transform" type="Transform3D" setter="set_transform" getter="get_transform" default="Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)"> The body's transformation matrix. </member> </members> diff --git a/doc/classes/PrimitiveMesh.xml b/doc/classes/PrimitiveMesh.xml index 1b9ecdbfa0..7a411b27ac 100644 --- a/doc/classes/PrimitiveMesh.xml +++ b/doc/classes/PrimitiveMesh.xml @@ -34,10 +34,10 @@ </method> </methods> <members> - <member name="custom_aabb" type="AABB" setter="set_custom_aabb" getter="get_custom_aabb"> + <member name="custom_aabb" type="AABB" setter="set_custom_aabb" getter="get_custom_aabb" default="AABB(0, 0, 0, 0, 0, 0)"> Overrides the [AABB] with one defined by user for use with frustum culling. Especially useful to avoid unexpected culling when using a shader to offset vertices. </member> - <member name="flip_faces" type="bool" setter="set_flip_faces" getter="get_flip_faces"> + <member name="flip_faces" type="bool" setter="set_flip_faces" getter="get_flip_faces" default="false"> If set, the order of the vertices in each triangle are reversed resulting in the backside of the mesh being drawn. This gives the same result as using [constant BaseMaterial3D.CULL_FRONT] in [member BaseMaterial3D.cull_mode]. </member> diff --git a/doc/classes/ProgressBar.xml b/doc/classes/ProgressBar.xml index 510b8d5bd1..f8c5dc0e1f 100644 --- a/doc/classes/ProgressBar.xml +++ b/doc/classes/ProgressBar.xml @@ -15,6 +15,8 @@ <member name="show_percentage" type="bool" setter="set_show_percentage" getter="is_percentage_shown" default="true"> If [code]true[/code], the fill percentage is displayed on the bar. </member> + <member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" default="0" /> + <member name="step" type="float" setter="set_step" getter="get_step" overrides="Range" default="0.01" /> </members> <constants> <constant name="FILL_BEGIN_TO_END" value="0" enum="FillMode"> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index fae88a401b..4699131c41 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -341,6 +341,9 @@ <member name="compression/formats/zstd/window_log_size" type="int" setter="" getter="" default="27"> Largest size limit (in power of 2) allowed when compressing using long-distance matching with Zstandard. Higher values can result in better compression, but will require more memory when compressing and decompressing. </member> + <member name="debug/disable_touch" type="bool" setter="" getter="" default="false"> + Disable touch input. Only has effect on iOS. + </member> <member name="debug/file_logging/enable_file_logging" type="bool" setter="" getter="" default="false"> If [code]true[/code], logs all output to files. </member> diff --git a/doc/classes/Range.xml b/doc/classes/Range.xml index 9764318ee4..8aa89015c6 100644 --- a/doc/classes/Range.xml +++ b/doc/classes/Range.xml @@ -38,34 +38,34 @@ </method> </methods> <members> - <member name="allow_greater" type="bool" setter="set_allow_greater" getter="is_greater_allowed"> + <member name="allow_greater" type="bool" setter="set_allow_greater" getter="is_greater_allowed" default="false"> If [code]true[/code], [member value] may be greater than [member max_value]. </member> - <member name="allow_lesser" type="bool" setter="set_allow_lesser" getter="is_lesser_allowed"> + <member name="allow_lesser" type="bool" setter="set_allow_lesser" getter="is_lesser_allowed" default="false"> If [code]true[/code], [member value] may be less than [member min_value]. </member> - <member name="exp_edit" type="bool" setter="set_exp_ratio" getter="is_ratio_exp"> + <member name="exp_edit" type="bool" setter="set_exp_ratio" getter="is_ratio_exp" default="false"> If [code]true[/code], and [code]min_value[/code] is greater than 0, [code]value[/code] will be represented exponentially rather than linearly. </member> - <member name="max_value" type="float" setter="set_max" getter="get_max"> + <member name="max_value" type="float" setter="set_max" getter="get_max" default="100.0"> Maximum value. Range is clamped if [code]value[/code] is greater than [code]max_value[/code]. </member> - <member name="min_value" type="float" setter="set_min" getter="get_min"> + <member name="min_value" type="float" setter="set_min" getter="get_min" default="0.0"> Minimum value. Range is clamped if [code]value[/code] is less than [code]min_value[/code]. </member> - <member name="page" type="float" setter="set_page" getter="get_page"> + <member name="page" type="float" setter="set_page" getter="get_page" default="0.0"> Page size. Used mainly for [ScrollBar]. ScrollBar's length is its size multiplied by [code]page[/code] over the difference between [code]min_value[/code] and [code]max_value[/code]. </member> <member name="ratio" type="float" setter="set_as_ratio" getter="get_as_ratio"> The value mapped between 0 and 1. </member> - <member name="rounded" type="bool" setter="set_use_rounded_values" getter="is_using_rounded_values"> + <member name="rounded" type="bool" setter="set_use_rounded_values" getter="is_using_rounded_values" default="false"> If [code]true[/code], [code]value[/code] will always be rounded to the nearest integer. </member> - <member name="step" type="float" setter="set_step" getter="get_step"> + <member name="step" type="float" setter="set_step" getter="get_step" default="1.0"> If greater than 0, [code]value[/code] will always be rounded to a multiple of [code]step[/code]. If [code]rounded[/code] is also [code]true[/code], [code]value[/code] will first be rounded to a multiple of [code]step[/code] then rounded to the nearest integer. </member> - <member name="value" type="float" setter="set_value" getter="get_value"> + <member name="value" type="float" setter="set_value" getter="get_value" default="0.0"> Range's current value. Changing this property (even via code) will trigger [signal value_changed] signal. Use [method set_value_no_signal] if you want to avoid it. </member> </members> diff --git a/doc/classes/RigidBody2D.xml b/doc/classes/RigidBody2D.xml index 9eedc3a24c..6e3535f14a 100644 --- a/doc/classes/RigidBody2D.xml +++ b/doc/classes/RigidBody2D.xml @@ -87,6 +87,7 @@ <param index="0" name="torque" type="float" /> <description> Applies a rotational force without affecting position. A force is time dependent and meant to be applied every physics update. + [b]Note:[/b] [member inertia] is required for this to work. To have [member inertia], an active [CollisionShape2D] must be a child of the node, or you can manually set [member inertia]. </description> </method> <method name="apply_torque_impulse"> @@ -95,6 +96,7 @@ <description> Applies a rotational impulse to the body without affecting the position. An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise). + [b]Note:[/b] [member inertia] is required for this to work. To have [member inertia], an active [CollisionShape2D] must be a child of the node, or you can manually set [member inertia]. </description> </method> <method name="get_colliding_bodies" qualifiers="const"> diff --git a/doc/classes/RigidBody3D.xml b/doc/classes/RigidBody3D.xml index 3ee3f25df1..8380d56de3 100644 --- a/doc/classes/RigidBody3D.xml +++ b/doc/classes/RigidBody3D.xml @@ -87,6 +87,7 @@ <param index="0" name="torque" type="Vector3" /> <description> Applies a rotational force without affecting position. A force is time dependent and meant to be applied every physics update. + [b]Note:[/b] [member inertia] is required for this to work. To have [member inertia], an active [CollisionShape3D] must be a child of the node, or you can manually set [member inertia]. </description> </method> <method name="apply_torque_impulse"> @@ -95,6 +96,7 @@ <description> Applies a rotational impulse to the body without affecting the position. An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise). + [b]Note:[/b] [member inertia] is required for this to work. To have [member inertia], an active [CollisionShape3D] must be a child of the node, or you can manually set [member inertia]. </description> </method> <method name="get_colliding_bodies" qualifiers="const"> diff --git a/doc/classes/ScrollBar.xml b/doc/classes/ScrollBar.xml index d0dd69408e..266787c9c8 100644 --- a/doc/classes/ScrollBar.xml +++ b/doc/classes/ScrollBar.xml @@ -12,6 +12,8 @@ <member name="custom_step" type="float" setter="set_custom_step" getter="get_custom_step" default="-1.0"> Overrides the step used when clicking increment and decrement buttons or when using arrow keys when the [ScrollBar] is focused. </member> + <member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" default="0" /> + <member name="step" type="float" setter="set_step" getter="get_step" overrides="Range" default="0.0" /> </members> <signals> <signal name="scrolling"> diff --git a/doc/classes/Slider.xml b/doc/classes/Slider.xml index c3dbd69e59..0e626842bd 100644 --- a/doc/classes/Slider.xml +++ b/doc/classes/Slider.xml @@ -13,9 +13,11 @@ <member name="editable" type="bool" setter="set_editable" getter="is_editable" default="true"> If [code]true[/code], the slider can be interacted with. If [code]false[/code], the value can be changed only by code. </member> + <member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" overrides="Control" enum="Control.FocusMode" default="2" /> <member name="scrollable" type="bool" setter="set_scrollable" getter="is_scrollable" default="true"> If [code]true[/code], the value can be changed using the mouse wheel. </member> + <member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" default="0" /> <member name="tick_count" type="int" setter="set_ticks" getter="get_ticks" default="0"> Number of ticks displayed on the slider, including border ticks. Ticks are uniformly-distributed value markers. </member> diff --git a/doc/classes/StyleBox.xml b/doc/classes/StyleBox.xml index 8656cde4a0..ff6d4d8821 100644 --- a/doc/classes/StyleBox.xml +++ b/doc/classes/StyleBox.xml @@ -114,21 +114,21 @@ </method> </methods> <members> - <member name="content_margin_bottom" type="float" setter="set_default_margin" getter="get_default_margin"> + <member name="content_margin_bottom" type="float" setter="set_default_margin" getter="get_default_margin" default="-1.0"> The bottom margin for the contents of this style box. Increasing this value reduces the space available to the contents from the bottom. If this value is negative, it is ignored and a child-specific margin is used instead. For example for [StyleBoxFlat] the border thickness (if any) is used instead. It is up to the code using this style box to decide what these contents are: for example, a [Button] respects this content margin for the textual contents of the button. [method get_margin] should be used to fetch this value as consumer instead of reading these properties directly. This is because it correctly respects negative values and the fallback mentioned above. </member> - <member name="content_margin_left" type="float" setter="set_default_margin" getter="get_default_margin"> + <member name="content_margin_left" type="float" setter="set_default_margin" getter="get_default_margin" default="-1.0"> The left margin for the contents of this style box. Increasing this value reduces the space available to the contents from the left. Refer to [member content_margin_bottom] for extra considerations. </member> - <member name="content_margin_right" type="float" setter="set_default_margin" getter="get_default_margin"> + <member name="content_margin_right" type="float" setter="set_default_margin" getter="get_default_margin" default="-1.0"> The right margin for the contents of this style box. Increasing this value reduces the space available to the contents from the right. Refer to [member content_margin_bottom] for extra considerations. </member> - <member name="content_margin_top" type="float" setter="set_default_margin" getter="get_default_margin"> + <member name="content_margin_top" type="float" setter="set_default_margin" getter="get_default_margin" default="-1.0"> The top margin for the contents of this style box. Increasing this value reduces the space available to the contents from the top. Refer to [member content_margin_bottom] for extra considerations. </member> diff --git a/doc/classes/TextureProgressBar.xml b/doc/classes/TextureProgressBar.xml index fcdb18e10d..ded4dac7da 100644 --- a/doc/classes/TextureProgressBar.xml +++ b/doc/classes/TextureProgressBar.xml @@ -27,6 +27,7 @@ <member name="fill_mode" type="int" setter="set_fill_mode" getter="get_fill_mode" default="0"> The fill direction. See [enum FillMode] for possible values. </member> + <member name="mouse_filter" type="int" setter="set_mouse_filter" getter="get_mouse_filter" overrides="Control" enum="Control.MouseFilter" default="1" /> <member name="nine_patch_stretch" type="bool" setter="set_nine_patch_stretch" getter="get_nine_patch_stretch" default="false"> If [code]true[/code], Godot treats the bar's textures like in [NinePatchRect]. Use the [code]stretch_margin_*[/code] properties like [member stretch_margin_bottom] to set up the nine patch's 3×3 grid. When using a radial [member fill_mode], this setting will enable stretching. </member> diff --git a/doc/classes/ViewportTexture.xml b/doc/classes/ViewportTexture.xml index 6bd64a50bb..955f054cea 100644 --- a/doc/classes/ViewportTexture.xml +++ b/doc/classes/ViewportTexture.xml @@ -15,6 +15,7 @@ <link title="3D Viewport Scaling Demo">https://godotengine.org/asset-library/asset/586</link> </tutorials> <members> + <member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="true" /> <member name="viewport_path" type="NodePath" setter="set_viewport_path_in_scene" getter="get_viewport_path_in_scene" default="NodePath("")"> The path to the [Viewport] node to display. This is relative to the scene root, not to the node which uses the texture. </member> diff --git a/doc/classes/VisualInstance3D.xml b/doc/classes/VisualInstance3D.xml index 94e8c25660..31811f817b 100644 --- a/doc/classes/VisualInstance3D.xml +++ b/doc/classes/VisualInstance3D.xml @@ -56,7 +56,7 @@ </method> </methods> <members> - <member name="layers" type="int" setter="set_layer_mask" getter="get_layer_mask"> + <member name="layers" type="int" setter="set_layer_mask" getter="get_layer_mask" default="1"> The render layer(s) this [VisualInstance3D] is drawn on. This object will only be visible for [Camera3D]s whose cull mask includes the render object this [VisualInstance3D] is set to. For [Light3D]s, this can be used to control which [VisualInstance3D]s are affected by a specific light. For [GPUParticles3D], this can be used to control which particles are effected by a specific attractor. For [Decal]s, this can be used to control which [VisualInstance3D]s are affected by a specific decal. diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 2e8c95fe61..734911ccdb 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1642,6 +1642,9 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_ ERR_FAIL_COND(rb.is_null()); } + GLES3::RenderTarget *rt = texture_storage->get_render_target(rb->render_target); + ERR_FAIL_COND(!rt); + // Assign render data // Use the format from rendererRD RenderDataGLES3 render_data; @@ -1729,8 +1732,20 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_ scene_state.ubo.emissive_exposure_normalization = -1.0; // Use default exposure normalization. + bool flip_y = !render_data.reflection_probe.is_valid(); + + if (rt->overridden.color.is_valid()) { + // If we've overridden the render target's color texture, then don't render upside down. + // We're probably rendering directly to an XR device. + flip_y = false; + } + if (!flip_y) { + // If we're rendering right-side up, then we need to change the winding order. + glFrontFace(GL_CW); + } + _setup_lights(&render_data, false, render_data.directional_light_count, render_data.omni_light_count, render_data.spot_light_count); - _setup_environment(&render_data, render_data.reflection_probe.is_valid(), screen_size, !render_data.reflection_probe.is_valid(), clear_color, false); + _setup_environment(&render_data, render_data.reflection_probe.is_valid(), screen_size, flip_y, clear_color, false); _fill_render_list(RENDER_LIST_OPAQUE, &render_data, PASS_MODE_COLOR); render_list[RENDER_LIST_OPAQUE].sort_by_key(); @@ -1811,7 +1826,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_ } } - glBindFramebuffer(GL_FRAMEBUFFER, rb->framebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo); glViewport(0, 0, rb->width, rb->height); // Do depth prepass if it's explicitly enabled @@ -1917,6 +1932,11 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_ _render_list_template<PASS_MODE_COLOR_TRANSPARENT>(&render_list_params_alpha, &render_data, 0, render_list[RENDER_LIST_ALPHA].elements.size(), true); + if (!flip_y) { + // Restore the default winding order. + glFrontFace(GL_CCW); + } + if (rb.is_valid()) { _render_buffers_debug_draw(rb, p_shadow_atlas, p_occluder_debug_tex); } @@ -1973,6 +1993,8 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, } } + bool should_request_redraw = false; + for (uint32_t i = p_from_element; i < p_to_element; i++) { const GeometryInstanceSurface *surf = p_params->elements[i]; GeometryInstanceGLES3 *inst = surf->owner; @@ -2003,6 +2025,11 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, continue; } + //request a redraw if one of the shaders uses TIME + if (shader->uses_time) { + should_request_redraw = true; + } + if constexpr (p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) { if (scene_state.current_depth_test != shader->depth_test) { if (shader->depth_test == GLES3::SceneShaderData::DEPTH_TEST_DISABLED) { @@ -2227,6 +2254,11 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, glDisableVertexAttribArray(15); } } + + // Make the actual redraw request + if (should_request_redraw) { + RenderingServerDefault::redraw_request(); + } } void RasterizerSceneGLES3::render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { diff --git a/drivers/gles3/storage/render_scene_buffers_gles3.cpp b/drivers/gles3/storage/render_scene_buffers_gles3.cpp index b8e4530f56..e0e78de728 100644 --- a/drivers/gles3/storage/render_scene_buffers_gles3.cpp +++ b/drivers/gles3/storage/render_scene_buffers_gles3.cpp @@ -33,17 +33,12 @@ #include "render_scene_buffers_gles3.h" #include "texture_storage.h" -#ifdef ANDROID_ENABLED -#define glFramebufferTextureMultiviewOVR GLES3::Config::get_singleton()->eglFramebufferTextureMultiviewOVR -#endif - RenderSceneBuffersGLES3::~RenderSceneBuffersGLES3() { free_render_buffer_data(); } void RenderSceneBuffersGLES3::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) { GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); - GLES3::Config *config = GLES3::Config::get_singleton(); //internal_size.x = p_internal_size.x; // ignore for now //internal_size.y = p_internal_size.y; @@ -62,66 +57,9 @@ void RenderSceneBuffersGLES3::configure(RID p_render_target, const Size2i p_inte GLES3::RenderTarget *rt = texture_storage->get_render_target(p_render_target); is_transparent = rt->is_transparent; - - // framebuffer - glGenFramebuffers(1, &framebuffer); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - - if (view_count > 1 && config->multiview_supported) { - glBindTexture(GL_TEXTURE_2D_ARRAY, rt->color); - glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, rt->color, 0, 0, view_count); - } else { - glBindTexture(GL_TEXTURE_2D, rt->color); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0); - } - - glGenTextures(1, &depth_texture); - if (view_count > 1 && config->multiview_supported) { - glBindTexture(GL_TEXTURE_2D_ARRAY, depth_texture); - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, view_count, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); - - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } else { - glBindTexture(GL_TEXTURE_2D, depth_texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } - - if (view_count > 1 && config->multiview_supported) { - glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depth_texture, 0, 0, view_count); - } else { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_texture, 0); - } - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - - glBindTexture(GL_TEXTURE_2D, 0); - glBindTexture(GL_TEXTURE_2D_ARRAY, 0); - glBindFramebuffer(GL_FRAMEBUFFER, texture_storage->system_fbo); - - if (status != GL_FRAMEBUFFER_COMPLETE) { - free_render_buffer_data(); - WARN_PRINT("Could not create 3D renderbuffer, status: " + texture_storage->get_framebuffer_error(status)); - return; - } } void RenderSceneBuffersGLES3::free_render_buffer_data() { - if (depth_texture) { - glDeleteTextures(1, &depth_texture); - depth_texture = 0; - } - if (framebuffer) { - glDeleteFramebuffers(1, &framebuffer); - framebuffer = 0; - } } #endif // GLES3_ENABLED diff --git a/drivers/gles3/storage/render_scene_buffers_gles3.h b/drivers/gles3/storage/render_scene_buffers_gles3.h index dbedbd22c3..092c14e1b8 100644 --- a/drivers/gles3/storage/render_scene_buffers_gles3.h +++ b/drivers/gles3/storage/render_scene_buffers_gles3.h @@ -61,9 +61,6 @@ public: bool is_transparent = false; RID render_target; - GLuint internal_texture = 0; // Used for rendering when post effects are enabled - GLuint depth_texture = 0; // Main depth texture - GLuint framebuffer = 0; // Main framebuffer, contains internal_texture and depth_texture or render_target->color and depth_texture //built-in textures used for ping pong image processing and blurring struct Blur { diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index 11151c4100..e0457a8d28 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -614,7 +614,9 @@ void TextureStorage::texture_free(RID p_texture) { } if (t->tex_id != 0) { - glDeleteTextures(1, &t->tex_id); + if (!t->is_external) { + glDeleteTextures(1, &t->tex_id); + } t->tex_id = 0; } @@ -680,6 +682,35 @@ void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) { texture_owner.initialize_rid(p_texture, proxy_tex); } +RID TextureStorage::texture_create_external(Texture::Type p_type, Image::Format p_format, unsigned int p_image, int p_width, int p_height, int p_depth, int p_layers, RS::TextureLayeredType p_layered_type) { + Texture texture; + texture.active = true; + texture.is_external = true; + texture.type = p_type; + + switch (p_type) { + case Texture::TYPE_2D: { + texture.target = GL_TEXTURE_2D; + } break; + case Texture::TYPE_3D: { + texture.target = GL_TEXTURE_3D; + } break; + case Texture::TYPE_LAYERED: { + texture.target = GL_TEXTURE_2D_ARRAY; + } break; + } + + texture.real_format = texture.format = p_format; + texture.tex_id = p_image; + texture.alloc_width = texture.width = p_width; + texture.alloc_height = texture.height = p_height; + texture.depth = p_depth; + texture.layers = p_layers; + texture.layered_type = p_layered_type; + + return texture_owner.make_rid(texture); +} + void TextureStorage::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) { texture_set_data(p_texture, p_image, p_layer); #ifdef TOOLS_ENABLED @@ -1459,43 +1490,74 @@ void TextureStorage::_update_render_target(RenderTarget *rt) { glDepthMask(GL_FALSE); { - /* Front FBO */ + Texture *texture; + bool use_multiview = rt->view_count > 1 && config->multiview_supported; + GLenum texture_target = use_multiview ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D; - Texture *texture = get_texture(rt->texture); - ERR_FAIL_COND(!texture); + /* Front FBO */ - // framebuffer glGenFramebuffers(1, &rt->fbo); glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo); // color - glGenTextures(1, &rt->color); - if (rt->view_count > 1 && config->multiview_supported) { - glBindTexture(GL_TEXTURE_2D_ARRAY, rt->color); - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, rt->color_internal_format, rt->size.x, rt->size.y, rt->view_count, 0, rt->color_format, rt->color_type, nullptr); - - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (rt->overridden.color.is_valid()) { + texture = get_texture(rt->overridden.color); + ERR_FAIL_COND(!texture); + + rt->color = texture->tex_id; + rt->size = Size2i(texture->width, texture->height); } else { - glBindTexture(GL_TEXTURE_2D, rt->color); - glTexImage2D(GL_TEXTURE_2D, 0, rt->color_internal_format, rt->size.x, rt->size.y, 0, rt->color_format, rt->color_type, nullptr); + texture = get_texture(rt->texture); + ERR_FAIL_COND(!texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } + glGenTextures(1, &rt->color); + glBindTexture(texture_target, rt->color); + + if (use_multiview) { + glTexImage3D(texture_target, 0, rt->color_internal_format, rt->size.x, rt->size.y, rt->view_count, 0, rt->color_format, rt->color_type, nullptr); + } else { + glTexImage2D(texture_target, 0, rt->color_internal_format, rt->size.x, rt->size.y, 0, rt->color_format, rt->color_type, nullptr); + } - if (rt->view_count > 1 && config->multiview_supported) { + glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + if (use_multiview) { glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, rt->color, 0, 0, rt->view_count); } else { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0); } - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + // depth + if (rt->overridden.depth.is_valid()) { + texture = get_texture(rt->overridden.depth); + ERR_FAIL_COND(!texture); + rt->depth = texture->tex_id; + } else { + glGenTextures(1, &rt->depth); + glBindTexture(texture_target, rt->depth); + + if (use_multiview) { + glTexImage3D(texture_target, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, rt->view_count, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); + } else { + glTexImage2D(texture_target, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); + } + + glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + if (use_multiview) { + glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, rt->depth, 0, 0, rt->view_count); + } else { + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0); + } + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { glDeleteFramebuffers(1, &rt->fbo); glDeleteTextures(1, &rt->color); @@ -1503,32 +1565,38 @@ void TextureStorage::_update_render_target(RenderTarget *rt) { rt->size.x = 0; rt->size.y = 0; rt->color = 0; - texture->tex_id = 0; - texture->active = false; + rt->depth = 0; + if (rt->overridden.color.is_null()) { + texture->tex_id = 0; + texture->active = false; + } WARN_PRINT("Could not create render target, status: " + get_framebuffer_error(status)); return; } - texture->format = rt->image_format; - texture->real_format = rt->image_format; - if (rt->view_count > 1 && config->multiview_supported) { - texture->type = Texture::TYPE_LAYERED; - texture->target = GL_TEXTURE_2D_ARRAY; - texture->layers = rt->view_count; + if (rt->overridden.color.is_valid()) { + texture->is_render_target = true; } else { - texture->type = Texture::TYPE_2D; - texture->target = GL_TEXTURE_2D; - texture->layers = 1; + texture->format = rt->image_format; + texture->real_format = rt->image_format; + texture->target = texture_target; + if (rt->view_count > 1 && config->multiview_supported) { + texture->type = Texture::TYPE_LAYERED; + texture->layers = rt->view_count; + } else { + texture->type = Texture::TYPE_2D; + texture->layers = 1; + } + texture->gl_format_cache = rt->color_format; + texture->gl_type_cache = GL_UNSIGNED_BYTE; + texture->gl_internal_format_cache = rt->color_internal_format; + texture->tex_id = rt->color; + texture->width = rt->size.x; + texture->alloc_width = rt->size.x; + texture->height = rt->size.y; + texture->alloc_height = rt->size.y; + texture->active = true; } - texture->gl_format_cache = rt->color_format; - texture->gl_type_cache = GL_UNSIGNED_BYTE; - texture->gl_internal_format_cache = rt->color_internal_format; - texture->tex_id = rt->color; - texture->width = rt->size.x; - texture->alloc_width = rt->size.x; - texture->height = rt->size.y; - texture->alloc_height = rt->size.y; - texture->active = true; } glClearColor(0, 0, 0, 0); @@ -1596,17 +1664,32 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) { if (rt->fbo) { glDeleteFramebuffers(1, &rt->fbo); - glDeleteTextures(1, &rt->color); rt->fbo = 0; + } + + if (rt->overridden.color.is_null()) { + glDeleteTextures(1, &rt->color); rt->color = 0; } - Texture *tex = get_texture(rt->texture); - tex->alloc_height = 0; - tex->alloc_width = 0; - tex->width = 0; - tex->height = 0; - tex->active = false; + if (rt->overridden.depth.is_null()) { + glDeleteTextures(1, &rt->depth); + rt->depth = 0; + } + + if (rt->texture.is_valid()) { + Texture *tex = get_texture(rt->texture); + tex->alloc_height = 0; + tex->alloc_width = 0; + tex->width = 0; + tex->height = 0; + tex->active = false; + } + + if (rt->overridden.color.is_valid()) { + Texture *tex = get_texture(rt->overridden.color); + tex->is_render_target = false; + } if (rt->backbuffer_fbo != 0) { glDeleteFramebuffers(1, &rt->backbuffer_fbo); @@ -1617,6 +1700,15 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) { _render_target_clear_sdf(rt); } +void TextureStorage::_clear_render_target_overridden_fbo_cache(RenderTarget *rt) { + // Dispose of the cached fbo's and the allocated textures + for (KeyValue<uint32_t, RenderTarget::RTOverridden::FBOCacheEntry> &E : rt->overridden.fbo_cache) { + glDeleteTextures(E.value.allocated_textures.size(), E.value.allocated_textures.ptr()); + glDeleteFramebuffers(1, &E.value.fbo); + } + rt->overridden.fbo_cache.clear(); +} + RID TextureStorage::render_target_create() { RenderTarget render_target; //render_target.was_used = false; @@ -1635,11 +1727,14 @@ RID TextureStorage::render_target_create() { void TextureStorage::render_target_free(RID p_rid) { RenderTarget *rt = render_target_owner.get_or_null(p_rid); _clear_render_target(rt); + _clear_render_target_overridden_fbo_cache(rt); Texture *t = get_texture(rt->texture); if (t) { t->is_render_target = false; - texture_free(rt->texture); + if (rt->overridden.color.is_null()) { + texture_free(rt->texture); + } //memdelete(t); } render_target_owner.free(p_rid); @@ -1666,6 +1761,9 @@ void TextureStorage::render_target_set_size(RID p_render_target, int p_width, in if (p_width == rt->size.x && p_height == rt->size.y && p_view_count == rt->view_count) { return; } + if (rt->overridden.color.is_valid()) { + return; + } _clear_render_target(rt); @@ -1683,10 +1781,91 @@ Size2i TextureStorage::render_target_get_size(RID p_render_target) const { return rt->size; } +void TextureStorage::render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND(!rt); + ERR_FAIL_COND(rt->direct_to_screen); + + rt->overridden.velocity = p_velocity_texture; + + if (rt->overridden.color == p_color_texture && rt->overridden.depth == p_depth_texture) { + return; + } + + if (p_color_texture.is_null() && p_depth_texture.is_null()) { + _clear_render_target(rt); + rt->overridden.is_overridden = false; + rt->overridden.color = RID(); + rt->overridden.depth = RID(); + rt->size = Size2i(); + _clear_render_target_overridden_fbo_cache(rt); + return; + } + + if (!rt->overridden.is_overridden) { + _clear_render_target(rt); + } + + rt->overridden.color = p_color_texture; + rt->overridden.depth = p_depth_texture; + rt->overridden.is_overridden = true; + + uint32_t hash_key = hash_murmur3_one_64(p_color_texture.get_id()); + hash_key = hash_murmur3_one_64(p_depth_texture.get_id(), hash_key); + hash_key = hash_fmix32(hash_key); + + RBMap<uint32_t, RenderTarget::RTOverridden::FBOCacheEntry>::Element *cache; + if ((cache = rt->overridden.fbo_cache.find(hash_key)) != nullptr) { + rt->fbo = cache->get().fbo; + rt->size = cache->get().size; + rt->texture = p_color_texture; + return; + } + + _update_render_target(rt); + + RenderTarget::RTOverridden::FBOCacheEntry new_entry; + new_entry.fbo = rt->fbo; + new_entry.size = rt->size; + // Keep track of any textures we had to allocate because they weren't overridden. + if (p_color_texture.is_null()) { + new_entry.allocated_textures.push_back(rt->color); + } + if (p_depth_texture.is_null()) { + new_entry.allocated_textures.push_back(rt->depth); + } + rt->overridden.fbo_cache.insert(hash_key, new_entry); +} + +RID TextureStorage::render_target_get_override_color(RID p_render_target) const { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + + return rt->overridden.color; +} + +RID TextureStorage::render_target_get_override_depth(RID p_render_target) const { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + + return rt->overridden.depth; +} + +RID TextureStorage::render_target_get_override_velocity(RID p_render_target) const { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + + return rt->overridden.velocity; +} + RID TextureStorage::render_target_get_texture(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND_V(!rt, RID()); + if (rt->overridden.color.is_valid()) { + return rt->overridden.color; + } + return rt->texture; } @@ -1696,8 +1875,10 @@ void TextureStorage::render_target_set_transparent(RID p_render_target, bool p_t rt->is_transparent = p_transparent; - _clear_render_target(rt); - _update_render_target(rt); + if (rt->overridden.color.is_null()) { + _clear_render_target(rt); + _update_render_target(rt); + } } bool TextureStorage::render_target_get_transparent(RID p_render_target) const { @@ -1718,6 +1899,11 @@ void TextureStorage::render_target_set_direct_to_screen(RID p_render_target, boo // those functions change how they operate depending on the value of DIRECT_TO_SCREEN _clear_render_target(rt); rt->direct_to_screen = p_direct_to_screen; + if (rt->direct_to_screen) { + rt->overridden.color = RID(); + rt->overridden.depth = RID(); + rt->overridden.velocity = RID(); + } _update_render_target(rt); } @@ -1750,6 +1936,7 @@ void TextureStorage::render_target_set_msaa(RID p_render_target, RS::ViewportMSA } WARN_PRINT("2D MSAA is not yet supported for GLES3."); + _clear_render_target(rt); rt->msaa = p_msaa; _update_render_target(rt); diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h index 35fa16c894..5dff768bd7 100644 --- a/drivers/gles3/storage/texture_storage.h +++ b/drivers/gles3/storage/texture_storage.h @@ -126,6 +126,7 @@ struct Texture { RID self; bool is_proxy = false; + bool is_external = false; bool is_render_target = false; RID proxy_to = RID(); @@ -187,6 +188,7 @@ struct Texture { void copy_from(const Texture &o) { proxy_to = o.proxy_to; is_proxy = o.is_proxy; + is_external = o.is_external; width = o.width; height = o.height; alloc_width = o.alloc_width; @@ -310,6 +312,7 @@ struct RenderTarget { RID self; GLuint fbo = 0; GLuint color = 0; + GLuint depth = 0; GLuint backbuffer_fbo = 0; GLuint backbuffer = 0; @@ -333,6 +336,20 @@ struct RenderTarget { bool used_in_frame = false; RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED; + struct RTOverridden { + bool is_overridden = false; + RID color; + RID depth; + RID velocity; + + struct FBOCacheEntry { + GLuint fbo; + Size2i size; + Vector<GLuint> allocated_textures; + }; + RBMap<uint32_t, FBOCacheEntry> fbo_cache; + } overridden; + RID texture; Color clear_color = Color(1, 1, 1, 1); @@ -395,6 +412,7 @@ private: mutable RID_Owner<RenderTarget> render_target_owner; void _clear_render_target(RenderTarget *rt); + void _clear_render_target_overridden_fbo_cache(RenderTarget *rt); void _update_render_target(RenderTarget *rt); void _create_render_target_backbuffer(RenderTarget *rt); void _render_target_allocate_sdf(RenderTarget *rt); @@ -454,6 +472,8 @@ public: virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override; virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent + RID texture_create_external(Texture::Type p_type, Image::Format p_format, unsigned int p_image, int p_width, int p_height, int p_depth, int p_layers, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY); + virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override; virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override{}; virtual void texture_proxy_update(RID p_proxy, RID p_base) override; @@ -593,10 +613,10 @@ public: virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override {} virtual RID render_target_get_vrs_texture(RID p_render_target) const override { return RID(); } - virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) override {} - virtual RID render_target_get_override_color(RID p_render_target) const override { return RID(); } - virtual RID render_target_get_override_depth(RID p_render_target) const override { return RID(); } - virtual RID render_target_get_override_velocity(RID p_render_target) const override { return RID(); } + virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) override; + virtual RID render_target_get_override_color(RID p_render_target) const override; + virtual RID render_target_get_override_depth(RID p_render_target) const override; + virtual RID render_target_get_override_velocity(RID p_render_target) const override; virtual RID render_target_get_texture(RID p_render_target) override; diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 66754932ad..0ff4ca31e6 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -9387,12 +9387,10 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de } } - // NOTE: If adding new project settings here, also duplicate their definition in - // rendering_server.cpp for headless doctool. - staging_buffer_block_size = GLOBAL_DEF("rendering/rendering_device/staging_buffer/block_size_kb", 256); + staging_buffer_block_size = GLOBAL_GET("rendering/rendering_device/staging_buffer/block_size_kb"); staging_buffer_block_size = MAX(4u, staging_buffer_block_size); staging_buffer_block_size *= 1024; // Kb -> bytes. - staging_buffer_max_size = GLOBAL_DEF("rendering/rendering_device/staging_buffer/max_size_mb", 128); + staging_buffer_max_size = GLOBAL_GET("rendering/rendering_device/staging_buffer/max_size_mb"); staging_buffer_max_size = MAX(1u, staging_buffer_max_size); staging_buffer_max_size *= 1024 * 1024; @@ -9400,7 +9398,7 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de // Validate enough blocks. staging_buffer_max_size = staging_buffer_block_size * 4; } - texture_upload_region_size_px = GLOBAL_DEF("rendering/rendering_device/staging_buffer/texture_upload_region_size_px", 64); + texture_upload_region_size_px = GLOBAL_GET("rendering/rendering_device/staging_buffer/texture_upload_region_size_px"); texture_upload_region_size_px = nearest_power_of_2_templated(texture_upload_region_size_px); frames_drawn = frame_count; // Start from frame count, so everything else is immediately old. @@ -9415,7 +9413,7 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de ERR_CONTINUE(err != OK); } - max_descriptors_per_pool = GLOBAL_DEF("rendering/rendering_device/vulkan/max_descriptors_per_pool", 64); + max_descriptors_per_pool = GLOBAL_GET("rendering/rendering_device/vulkan/max_descriptors_per_pool"); // Check to make sure DescriptorPoolKey is good. static_assert(sizeof(uint64_t) * 3 >= UNIFORM_TYPE_MAX * sizeof(uint16_t)); diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp index 7d6eb186dc..6e6416e3ca 100644 --- a/editor/doc_tools.cpp +++ b/editor/doc_tools.cpp @@ -335,7 +335,7 @@ static Variant get_documentation_default_value(const StringName &p_class_name, c Variant default_value = Variant(); r_default_value_valid = false; - if (ClassDB::can_instantiate(p_class_name)) { + if (ClassDB::can_instantiate(p_class_name)) { // Keep this condition in sync with ClassDB::class_get_default_property_value. default_value = ClassDB::class_get_default_property_value(p_class_name, p_property_name, &r_default_value_valid); } else { // Cannot get default value of classes that can't be instantiated diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp index 9549ffb09b..49fb16a095 100644 --- a/editor/editor_feature_profile.cpp +++ b/editor/editor_feature_profile.cpp @@ -47,6 +47,7 @@ const char *EditorFeatureProfile::feature_names[FEATURE_MAX] = { TTRC("Node Dock"), TTRC("FileSystem Dock"), TTRC("Import Dock"), + TTRC("History Dock"), }; const char *EditorFeatureProfile::feature_descriptions[FEATURE_MAX] = { @@ -57,6 +58,7 @@ const char *EditorFeatureProfile::feature_descriptions[FEATURE_MAX] = { TTRC("Allows to work with signals and groups of the node selected in the Scene dock."), TTRC("Allows to browse the local file system via a dedicated dock."), TTRC("Allows to configure import settings for individual assets. Requires the FileSystem dock to function."), + TTRC("Provides an overview of the editor's and each scene's undo history."), }; const char *EditorFeatureProfile::feature_identifiers[FEATURE_MAX] = { @@ -67,6 +69,7 @@ const char *EditorFeatureProfile::feature_identifiers[FEATURE_MAX] = { "node_dock", "filesystem_dock", "import_dock", + "history_dock", }; void EditorFeatureProfile::set_disable_class(const StringName &p_class, bool p_disabled) { @@ -302,6 +305,7 @@ void EditorFeatureProfile::_bind_methods() { BIND_ENUM_CONSTANT(FEATURE_NODE_DOCK); BIND_ENUM_CONSTANT(FEATURE_FILESYSTEM_DOCK); BIND_ENUM_CONSTANT(FEATURE_IMPORT_DOCK); + BIND_ENUM_CONSTANT(FEATURE_HISTORY_DOCK); BIND_ENUM_CONSTANT(FEATURE_MAX); } diff --git a/editor/editor_feature_profile.h b/editor/editor_feature_profile.h index dab6c951e4..6868c54146 100644 --- a/editor/editor_feature_profile.h +++ b/editor/editor_feature_profile.h @@ -52,6 +52,7 @@ public: FEATURE_NODE_DOCK, FEATURE_FILESYSTEM_DOCK, FEATURE_IMPORT_DOCK, + FEATURE_HISTORY_DOCK, FEATURE_MAX }; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 716e0b454f..1bca1b3c87 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -244,15 +244,11 @@ void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vecto String full_path = p_full_paths[set_idx]; // Get rid of file extensions and res:// prefixes. - if (scene_name.rfind(".") >= 0) { - scene_name = scene_name.substr(0, scene_name.rfind(".")); - } + scene_name = scene_name.get_basename(); if (full_path.begins_with("res://")) { full_path = full_path.substr(6); } - if (full_path.rfind(".") >= 0) { - full_path = full_path.substr(0, full_path.rfind(".")); - } + full_path = full_path.get_basename(); // Normalize trailing slashes when normalizing directory names. scene_name = scene_name.trim_suffix("/"); @@ -270,7 +266,7 @@ void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vecto String parent = full_path.substr(0, difference); int slash_idx = parent.rfind("/"); slash_idx = parent.rfind("/", slash_idx - 1); - parent = slash_idx >= 0 ? parent.substr(slash_idx + 1) : parent; + parent = (slash_idx >= 0 && parent.length() > 1) ? parent.substr(slash_idx + 1) : parent; r_filenames.write[set_idx] = parent + r_filenames[set_idx]; } } @@ -302,15 +298,11 @@ void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vecto String path = p_full_paths[E->get()]; // Get rid of file extensions and res:// prefixes. - if (scene_name.rfind(".") >= 0) { - scene_name = scene_name.substr(0, scene_name.rfind(".")); - } + scene_name = scene_name.get_basename(); if (path.begins_with("res://")) { path = path.substr(6); } - if (path.rfind(".") >= 0) { - path = path.substr(0, path.rfind(".")); - } + path = path.get_basename(); // Normalize trailing slashes when normalizing directory names. scene_name = scene_name.trim_suffix("/"); @@ -544,7 +536,7 @@ void EditorNode::_update_from_settings() { RS::get_singleton()->environment_set_volumetric_fog_filter_active(bool(GLOBAL_GET("rendering/environment/volumetric_fog/use_filter"))); RS::get_singleton()->canvas_set_shadow_texture_size(GLOBAL_GET("rendering/2d/shadow_atlas/size")); - bool use_half_res_gi = GLOBAL_DEF("rendering/global_illumination/gi/use_half_resolution", false); + bool use_half_res_gi = GLOBAL_GET("rendering/global_illumination/gi/use_half_resolution"); RS::get_singleton()->gi_set_use_half_resolution(use_half_res_gi); bool snap_2d_transforms = GLOBAL_GET("rendering/2d/snap/snap_2d_transforms_to_pixel"); @@ -5142,7 +5134,7 @@ bool EditorNode::has_scenes_in_session() { bool EditorNode::ensure_main_scene(bool p_from_native) { pick_main_scene->set_meta("from_native", p_from_native); // Whether from play button or native run. - String main_scene = GLOBAL_DEF_BASIC("application/run/main_scene", ""); + String main_scene = GLOBAL_GET("application/run/main_scene"); if (main_scene.is_empty()) { current_menu_option = -1; @@ -5209,7 +5201,7 @@ bool EditorNode::is_run_playing() const { String EditorNode::get_run_playing_scene() const { String run_filename = editor_run.get_running_scene(); if (run_filename.is_empty() && is_run_playing()) { - run_filename = GLOBAL_DEF_BASIC("application/run/main_scene", ""); // Must be the main scene then. + run_filename = GLOBAL_GET("application/run/main_scene"); // Must be the main scene then. } return run_filename; @@ -5976,12 +5968,14 @@ void EditorNode::_feature_profile_changed() { TabContainer *import_tabs = cast_to<TabContainer>(ImportDock::get_singleton()->get_parent()); TabContainer *node_tabs = cast_to<TabContainer>(NodeDock::get_singleton()->get_parent()); TabContainer *fs_tabs = cast_to<TabContainer>(FileSystemDock::get_singleton()->get_parent()); + TabContainer *history_tabs = cast_to<TabContainer>(history_dock->get_parent()); if (profile.is_valid()) { node_tabs->set_tab_hidden(node_tabs->get_tab_idx_from_control(NodeDock::get_singleton()), profile->is_feature_disabled(EditorFeatureProfile::FEATURE_NODE_DOCK)); // The Import dock is useless without the FileSystem dock. Ensure the configuration is valid. bool fs_dock_disabled = profile->is_feature_disabled(EditorFeatureProfile::FEATURE_FILESYSTEM_DOCK); fs_tabs->set_tab_hidden(fs_tabs->get_tab_idx_from_control(FileSystemDock::get_singleton()), fs_dock_disabled); import_tabs->set_tab_hidden(import_tabs->get_tab_idx_from_control(ImportDock::get_singleton()), fs_dock_disabled || profile->is_feature_disabled(EditorFeatureProfile::FEATURE_IMPORT_DOCK)); + history_tabs->set_tab_hidden(history_tabs->get_tab_idx_from_control(history_dock), profile->is_feature_disabled(EditorFeatureProfile::FEATURE_HISTORY_DOCK)); main_editor_buttons[EDITOR_3D]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D)); main_editor_buttons[EDITOR_SCRIPT]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_SCRIPT)); @@ -5997,6 +5991,8 @@ void EditorNode::_feature_profile_changed() { import_tabs->set_tab_hidden(import_tabs->get_tab_idx_from_control(ImportDock::get_singleton()), false); node_tabs->set_tab_hidden(node_tabs->get_tab_idx_from_control(NodeDock::get_singleton()), false); fs_tabs->set_tab_hidden(fs_tabs->get_tab_idx_from_control(FileSystemDock::get_singleton()), false); + history_tabs->set_tab_hidden(history_tabs->get_tab_idx_from_control(history_dock), false); + history_dock->set_visible(true); ImportDock::get_singleton()->set_visible(true); NodeDock::get_singleton()->set_visible(true); FileSystemDock::get_singleton()->set_visible(true); @@ -7108,7 +7104,7 @@ EditorNode::EditorNode() { filesystem_dock->connect("display_mode_changed", callable_mp(this, &EditorNode::_save_docks)); get_project_settings()->connect_filesystem_dock_signals(filesystem_dock); - HistoryDock *hd = memnew(HistoryDock); + history_dock = memnew(HistoryDock); // Scene: Top left. dock_slot[DOCK_SLOT_LEFT_UR]->add_child(SceneTreeDock::get_singleton()); @@ -7131,8 +7127,8 @@ EditorNode::EditorNode() { dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(dock_slot[DOCK_SLOT_RIGHT_UL]->get_tab_idx_from_control(NodeDock::get_singleton()), TTR("Node")); // History: Full height right, behind Node. - dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(hd); - dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(dock_slot[DOCK_SLOT_RIGHT_UL]->get_tab_idx_from_control(hd), TTR("History")); + dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(history_dock); + dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(dock_slot[DOCK_SLOT_RIGHT_UL]->get_tab_idx_from_control(history_dock), TTR("History")); // Hide unused dock slots and vsplits. dock_slot[DOCK_SLOT_LEFT_UL]->hide(); diff --git a/editor/editor_node.h b/editor/editor_node.h index 9c8d564057..f27fe429b9 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -77,6 +77,7 @@ class EditorUndoRedoManager; class ExportTemplateManager; class FileDialog; class FileSystemDock; +class HistoryDock; class HSplitContainer; class ImportDock; class LinkButton; @@ -274,6 +275,7 @@ private: EditorRunNative *run_native = nullptr; EditorSelection *editor_selection = nullptr; EditorSettingsDialog *editor_settings_dialog = nullptr; + HistoryDock *history_dock = nullptr; ProjectExportDialog *project_export = nullptr; ProjectSettingsEditor *project_settings_editor = nullptr; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index e6e32f882f..baf335f5b4 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -928,9 +928,7 @@ void CanvasItemEditor::_add_node_pressed(int p_result) { [[fallthrough]]; } case ADD_MOVE: { - if (p_result == ADD_MOVE) { - nodes_to_move = EditorNode::get_singleton()->get_editor_selection()->get_selected_node_list(); - } + nodes_to_move = EditorNode::get_singleton()->get_editor_selection()->get_selected_node_list(); if (nodes_to_move.is_empty()) { return; } @@ -1731,22 +1729,16 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) { drag_to = transform.affine_inverse().xform(m->get_position()); - Transform2D xform = ci->get_global_transform_with_canvas().affine_inverse(); + Transform2D xform = ci->get_global_transform_with_canvas(); Point2 drag_to_snapped_begin; Point2 drag_to_snapped_end; - // last call decides which snapping lines are drawn - if (drag_type == DRAG_LEFT || drag_type == DRAG_TOP || drag_type == DRAG_TOP_LEFT) { - drag_to_snapped_end = snap_point(xform.affine_inverse().xform(current_end) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, ci); - drag_to_snapped_begin = snap_point(xform.affine_inverse().xform(current_begin) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, ci); - } else { - drag_to_snapped_begin = snap_point(xform.affine_inverse().xform(current_begin) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, ci); - drag_to_snapped_end = snap_point(xform.affine_inverse().xform(current_end) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, ci); - } + drag_to_snapped_end = snap_point(xform.xform(current_end) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, ci); + drag_to_snapped_begin = snap_point(xform.xform(current_begin) + (drag_to - drag_from), SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, ci); - Point2 drag_begin = xform.xform(drag_to_snapped_begin); - Point2 drag_end = xform.xform(drag_to_snapped_end); + Point2 drag_begin = xform.affine_inverse().xform(drag_to_snapped_begin); + Point2 drag_end = xform.affine_inverse().xform(drag_to_snapped_end); // Horizontal resize if (drag_type == DRAG_LEFT || drag_type == DRAG_TOP_LEFT || drag_type == DRAG_BOTTOM_LEFT) { diff --git a/editor/plugins/control_editor_plugin.cpp b/editor/plugins/control_editor_plugin.cpp index bb6092755e..1791f7b420 100644 --- a/editor/plugins/control_editor_plugin.cpp +++ b/editor/plugins/control_editor_plugin.cpp @@ -810,19 +810,6 @@ void ControlEditorToolbar::_container_flags_selected(int p_flags, bool p_vertica undo_redo->commit_action(); } -Vector2 ControlEditorToolbar::_anchor_to_position(const Control *p_control, Vector2 anchor) { - ERR_FAIL_COND_V(!p_control, Vector2()); - - Transform2D parent_transform = p_control->get_transform().affine_inverse(); - Rect2 parent_rect = p_control->get_parent_anchorable_rect(); - - if (p_control->is_layout_rtl()) { - return parent_transform.xform(parent_rect.position + Vector2(parent_rect.size.x - parent_rect.size.x * anchor.x, parent_rect.size.y * anchor.y)); - } else { - return parent_transform.xform(parent_rect.position + Vector2(parent_rect.size.x * anchor.x, parent_rect.size.y * anchor.y)); - } -} - Vector2 ControlEditorToolbar::_position_to_anchor(const Control *p_control, Vector2 position) { ERR_FAIL_COND_V(!p_control, Vector2()); diff --git a/editor/plugins/control_editor_plugin.h b/editor/plugins/control_editor_plugin.h index 22267cbc04..d78773a509 100644 --- a/editor/plugins/control_editor_plugin.h +++ b/editor/plugins/control_editor_plugin.h @@ -222,7 +222,6 @@ class ControlEditorToolbar : public HBoxContainer { void _anchor_mode_toggled(bool p_status); void _container_flags_selected(int p_flags, bool p_vertical); - Vector2 _anchor_to_position(const Control *p_control, Vector2 anchor); Vector2 _position_to_anchor(const Control *p_control, Vector2 position); bool _is_node_locked(const Node *p_node); List<Control *> _get_edited_controls(); diff --git a/editor/plugins/gdextension_export_plugin.h b/editor/plugins/gdextension_export_plugin.h index e1d68d97b5..c5f7d2a047 100644 --- a/editor/plugins/gdextension_export_plugin.h +++ b/editor/plugins/gdextension_export_plugin.h @@ -107,7 +107,7 @@ void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p for (const String &E : p_features) { tags.append(E); } - ERR_FAIL_MSG(vformat("Couldn't export extension: %s. No suitable library found for export flags: %s", p_path, String(", ").join(tags))); + ERR_FAIL_MSG(vformat("No suitable library found. The libraries' tags referred to an invalid feature flag. Possible feature flags for your platform: %s", p_path, String(", ").join(tags))); } List<String> dependencies; diff --git a/editor/plugins/gradient_texture_2d_editor_plugin.cpp b/editor/plugins/gradient_texture_2d_editor_plugin.cpp index dc01a52bb3..561dca4fc6 100644 --- a/editor/plugins/gradient_texture_2d_editor_plugin.cpp +++ b/editor/plugins/gradient_texture_2d_editor_plugin.cpp @@ -121,13 +121,12 @@ void GradientTexture2DEditorRect::_notification(int p_what) { Size2 rect_size = get_size(); // Get the size and position to draw the texture and handles at. - size = Size2(texture->get_width() * rect_size.height / texture->get_height(), rect_size.height); - if (size.width > rect_size.width) { - size.width = rect_size.width; - size.height = texture->get_height() * size.width / texture->get_width(); - } - offset = ((rect_size - size + handle_size) / 2).round(); - size -= handle_size; + // Subtract handle sizes so they stay inside the preview, but keep the texture's aspect ratio. + Size2 available_size = rect_size - handle_size; + Size2 ratio = available_size / texture->get_size(); + size = MIN(ratio.x, ratio.y) * texture->get_size(); + offset = ((rect_size - size) / 2).round(); + checkerboard->set_rect(Rect2(offset, size)); draw_set_transform(offset); @@ -180,8 +179,9 @@ GradientTexture2DEditorRect::GradientTexture2DEditorRect() { checkerboard = memnew(TextureRect); checkerboard->set_stretch_mode(TextureRect::STRETCH_TILE); + checkerboard->set_ignore_texture_size(true); checkerboard->set_draw_behind_parent(true); - add_child(checkerboard); + add_child(checkerboard, false, INTERNAL_MODE_FRONT); set_custom_minimum_size(Size2(0, 250 * EDSCALE)); } diff --git a/main/main.cpp b/main/main.cpp index 5b998d98ce..0fce8e3d94 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -443,11 +443,7 @@ Error Main::test_setup() { globals = memnew(ProjectSettings); - GLOBAL_DEF("debug/settings/crash_handler/message", - String("Please include this when reporting the bug on https://github.com/godotengine/godot/issues")); - GLOBAL_DEF_RST("rendering/occlusion_culling/bvh_build_quality", 2); - - register_core_settings(); //here globals are present + register_core_settings(); // Here globals are present. translation_server = memnew(TranslationServer); tsman = memnew(TextServerManager); @@ -665,11 +661,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph GLOBAL_DEF_RST("application/run/flush_stdout_on_print", false); GLOBAL_DEF_RST("application/run/flush_stdout_on_print.debug", true); - GLOBAL_DEF("debug/settings/crash_handler/message", - String("Please include this when reporting the bug to the project developer.")); - GLOBAL_DEF("debug/settings/crash_handler/message.editor", - String("Please include this when reporting the bug on: https://github.com/godotengine/godot/issues")); - MAIN_PRINT("Main: Parse CMDLine"); /* argument parsing and main creation */ @@ -1358,7 +1349,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph ResourceUID::get_singleton()->load_from_cache(); // load UUIDs from cache. - GLOBAL_DEF("memory/limits/multithreaded_server/rid_pool_prealloc", 60); ProjectSettings::get_singleton()->set_custom_property_info("memory/limits/multithreaded_server/rid_pool_prealloc", PropertyInfo(Variant::INT, "memory/limits/multithreaded_server/rid_pool_prealloc", @@ -1715,7 +1705,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph window_mode = (DisplayServer::WindowMode)(GLOBAL_GET("display/window/size/mode").operator int()); } - GLOBAL_DEF_RST("internationalization/rendering/force_right_to_left_layout_direction", false); GLOBAL_DEF("internationalization/locale/include_text_server_data", false); OS::get_singleton()->_allow_hidpi = GLOBAL_DEF("display/window/dpi/allow_hidpi", true); @@ -2165,12 +2154,12 @@ Error Main::setup2(Thread::ID p_main_tid_override) { boot_logo->set_pixel(0, 0, Color(0, 0, 0, 0)); } + Color boot_bg_color = GLOBAL_DEF_BASIC("application/boot_splash/bg_color", boot_splash_bg_color); + #if defined(TOOLS_ENABLED) && !defined(NO_EDITOR_SPLASH) - const Color boot_bg_color = + boot_bg_color = GLOBAL_DEF_BASIC("application/boot_splash/bg_color", (editor || project_manager) ? boot_splash_editor_bg_color : boot_splash_bg_color); -#else - const Color boot_bg_color = GLOBAL_DEF_BASIC("application/boot_splash/bg_color", boot_splash_bg_color); #endif if (boot_logo.is_valid()) { RenderingServer::get_singleton()->set_boot_image(boot_logo, boot_bg_color, boot_logo_scale, @@ -2202,7 +2191,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) { MAIN_PRINT("Main: DCC"); RenderingServer::get_singleton()->set_default_clear_color( - GLOBAL_DEF_BASIC("rendering/environment/defaults/default_clear_color", Color(0.3, 0.3, 0.3))); + GLOBAL_GET("rendering/environment/defaults/default_clear_color")); GLOBAL_DEF("application/config/icon", String()); ProjectSettings::get_singleton()->set_custom_property_info("application/config/icon", @@ -2805,15 +2794,48 @@ bool Main::start() { startup_benchmark_file = String(); } #endif + GLOBAL_DEF_BASIC("display/window/stretch/mode", "disabled"); + ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/mode", + PropertyInfo(Variant::STRING, + "display/window/stretch/mode", + PROPERTY_HINT_ENUM, + "disabled,canvas_items,viewport")); + GLOBAL_DEF_BASIC("display/window/stretch/aspect", "keep"); + ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/aspect", + PropertyInfo(Variant::STRING, + "display/window/stretch/aspect", + PROPERTY_HINT_ENUM, + "ignore,keep,keep_width,keep_height,expand")); + GLOBAL_DEF_BASIC("display/window/stretch/scale", 1.0); + ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/scale", + PropertyInfo(Variant::FLOAT, + "display/window/stretch/scale", + PROPERTY_HINT_RANGE, + "0.5,8.0,0.01")); + sml->set_auto_accept_quit(GLOBAL_DEF("application/config/auto_accept_quit", true)); + sml->set_quit_on_go_back(GLOBAL_DEF("application/config/quit_on_go_back", true)); + GLOBAL_DEF_BASIC("gui/common/snap_controls_to_pixels", true); + GLOBAL_DEF_BASIC("gui/fonts/dynamic_fonts/use_oversampling", true); + + GLOBAL_DEF_BASIC("rendering/textures/canvas_textures/default_texture_filter", 1); + ProjectSettings::get_singleton()->set_custom_property_info( + "rendering/textures/canvas_textures/default_texture_filter", + PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_filter", PROPERTY_HINT_ENUM, + "Nearest,Linear,Linear Mipmap,Nearest Mipmap")); + GLOBAL_DEF_BASIC("rendering/textures/canvas_textures/default_texture_repeat", 0); + ProjectSettings::get_singleton()->set_custom_property_info( + "rendering/textures/canvas_textures/default_texture_repeat", + PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_repeat", PROPERTY_HINT_ENUM, + "Disable,Enable,Mirror")); if (!editor && !project_manager) { //standard helpers that can be changed from main config - String stretch_mode = GLOBAL_DEF_BASIC("display/window/stretch/mode", "disabled"); - String stretch_aspect = GLOBAL_DEF_BASIC("display/window/stretch/aspect", "keep"); - Size2i stretch_size = Size2i(GLOBAL_DEF_BASIC("display/window/size/viewport_width", 0), - GLOBAL_DEF_BASIC("display/window/size/viewport_height", 0)); - real_t stretch_scale = GLOBAL_DEF_BASIC("display/window/stretch/scale", 1.0); + String stretch_mode = GLOBAL_GET("display/window/stretch/mode"); + String stretch_aspect = GLOBAL_GET("display/window/stretch/aspect"); + Size2i stretch_size = Size2i(GLOBAL_GET("display/window/size/viewport_width"), + GLOBAL_GET("display/window/size/viewport_height")); + real_t stretch_scale = GLOBAL_GET("display/window/stretch/scale"); Window::ContentScaleMode cs_sm = Window::CONTENT_SCALE_MODE_DISABLED; if (stretch_mode == "canvas_items") { @@ -2838,8 +2860,8 @@ bool Main::start() { sml->get_root()->set_content_scale_size(stretch_size); sml->get_root()->set_content_scale_factor(stretch_scale); - sml->set_auto_accept_quit(GLOBAL_DEF("application/config/auto_accept_quit", true)); - sml->set_quit_on_go_back(GLOBAL_DEF("application/config/quit_on_go_back", true)); + sml->set_auto_accept_quit(GLOBAL_GET("application/config/auto_accept_quit")); + sml->set_quit_on_go_back(GLOBAL_GET("application/config/quit_on_go_back")); String appname = GLOBAL_GET("application/config/name"); appname = TranslationServer::get_singleton()->translate(appname); #ifdef DEBUG_ENABLED @@ -2855,53 +2877,18 @@ bool Main::start() { // It can still be overridden by the user in a script. DisplayServer::get_singleton()->window_set_min_size(Size2i(64, 64)); - bool snap_controls = GLOBAL_DEF("gui/common/snap_controls_to_pixels", true); + bool snap_controls = GLOBAL_GET("gui/common/snap_controls_to_pixels"); sml->get_root()->set_snap_controls_to_pixels(snap_controls); - bool font_oversampling = GLOBAL_DEF("gui/fonts/dynamic_fonts/use_oversampling", true); + bool font_oversampling = GLOBAL_GET("gui/fonts/dynamic_fonts/use_oversampling"); sml->get_root()->set_use_font_oversampling(font_oversampling); - int texture_filter = GLOBAL_DEF("rendering/textures/canvas_textures/default_texture_filter", 1); - int texture_repeat = GLOBAL_DEF("rendering/textures/canvas_textures/default_texture_repeat", 0); + int texture_filter = GLOBAL_GET("rendering/textures/canvas_textures/default_texture_filter"); + int texture_repeat = GLOBAL_GET("rendering/textures/canvas_textures/default_texture_repeat"); sml->get_root()->set_default_canvas_item_texture_filter( Viewport::DefaultCanvasItemTextureFilter(texture_filter)); sml->get_root()->set_default_canvas_item_texture_repeat( Viewport::DefaultCanvasItemTextureRepeat(texture_repeat)); - - } else { - GLOBAL_DEF_BASIC("display/window/stretch/mode", "disabled"); - ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/mode", - PropertyInfo(Variant::STRING, - "display/window/stretch/mode", - PROPERTY_HINT_ENUM, - "disabled,canvas_items,viewport")); - GLOBAL_DEF_BASIC("display/window/stretch/aspect", "keep"); - ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/aspect", - PropertyInfo(Variant::STRING, - "display/window/stretch/aspect", - PROPERTY_HINT_ENUM, - "ignore,keep,keep_width,keep_height,expand")); - GLOBAL_DEF_BASIC("display/window/stretch/scale", 1.0); - ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/scale", - PropertyInfo(Variant::FLOAT, - "display/window/stretch/scale", - PROPERTY_HINT_RANGE, - "0.5,8.0,0.01")); - sml->set_auto_accept_quit(GLOBAL_DEF("application/config/auto_accept_quit", true)); - sml->set_quit_on_go_back(GLOBAL_DEF("application/config/quit_on_go_back", true)); - GLOBAL_DEF_BASIC("gui/common/snap_controls_to_pixels", true); - GLOBAL_DEF_BASIC("gui/fonts/dynamic_fonts/use_oversampling", true); - - GLOBAL_DEF_BASIC("rendering/textures/canvas_textures/default_texture_filter", 1); - ProjectSettings::get_singleton()->set_custom_property_info( - "rendering/textures/canvas_textures/default_texture_filter", - PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_filter", PROPERTY_HINT_ENUM, - "Nearest,Linear,Linear Mipmap,Nearest Mipmap")); - GLOBAL_DEF_BASIC("rendering/textures/canvas_textures/default_texture_repeat", 0); - ProjectSettings::get_singleton()->set_custom_property_info( - "rendering/textures/canvas_textures/default_texture_repeat", - PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_repeat", PROPERTY_HINT_ENUM, - "Disable,Enable,Mirror")); } #ifdef TOOLS_ENABLED @@ -2970,7 +2957,7 @@ bool Main::start() { Engine::get_singleton()->startup_benchmark_begin_measure("game_load"); // Load SSL Certificates from Project Settings (or builtin). - Crypto::load_default_certificates(GLOBAL_DEF("network/tls/certificate_bundle_override", "")); + Crypto::load_default_certificates(GLOBAL_GET("network/tls/certificate_bundle_override")); if (!game_path.is_empty()) { Node *scene = nullptr; @@ -2983,7 +2970,7 @@ bool Main::start() { sml->add_current_scene(scene); #ifdef MACOS_ENABLED - String mac_iconpath = GLOBAL_DEF("application/config/macos_native_icon", "Variant()"); + String mac_iconpath = GLOBAL_GET("application/config/macos_native_icon"); if (!mac_iconpath.is_empty()) { DisplayServer::get_singleton()->set_native_icon(mac_iconpath); hasicon = true; @@ -2991,14 +2978,14 @@ bool Main::start() { #endif #ifdef WINDOWS_ENABLED - String win_iconpath = GLOBAL_DEF("application/config/windows_native_icon", "Variant()"); + String win_iconpath = GLOBAL_GET("application/config/windows_native_icon"); if (!win_iconpath.is_empty()) { DisplayServer::get_singleton()->set_native_icon(win_iconpath); hasicon = true; } #endif - String iconpath = GLOBAL_DEF("application/config/icon", "Variant()"); + String iconpath = GLOBAL_GET("application/config/icon"); if ((!iconpath.is_empty()) && (!hasicon)) { Ref<Image> icon; icon.instantiate(); diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 7acd1cdb96..fd13edc4cf 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -2432,9 +2432,8 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar // TODO: Make enums not be just a dictionary? Dictionary new_enum; for (int j = 0; j < enum_n->values.size(); j++) { - int value = enum_n->values[j].value; // Needs to be string because Variant::get will convert to String. - new_enum[String(enum_n->values[j].identifier->name)] = value; + new_enum[String(enum_n->values[j].identifier->name)] = enum_n->values[j].value; } p_script->constants.insert(enum_n->identifier->name, new_enum); diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 4279edf394..6842a1ff49 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -3802,7 +3802,7 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node String enum_hint_string; bool first = true; - for (const KeyValue<StringName, int> &E : export_type.enum_values) { + for (const KeyValue<StringName, int64_t> &E : export_type.enum_values) { if (!first) { enum_hint_string += ","; } else { diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index f40887ddb8..d8f5b866aa 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -131,7 +131,7 @@ public: ClassNode *class_type = nullptr; MethodInfo method_info; // For callable/signals. - HashMap<StringName, int> enum_values; // For enums. + HashMap<StringName, int64_t> enum_values; // For enums. _FORCE_INLINE_ bool is_set() const { return kind != UNRESOLVED; } _FORCE_INLINE_ bool has_no_type() const { return type_source == UNDETECTED; } diff --git a/modules/openxr/SCsub b/modules/openxr/SCsub index b5978ab134..84542be3b9 100644 --- a/modules/openxr/SCsub +++ b/modules/openxr/SCsub @@ -90,6 +90,8 @@ if env["platform"] == "android": env_openxr.add_source_files(module_obj, "extensions/openxr_android_extension.cpp") if env["vulkan"]: env_openxr.add_source_files(module_obj, "extensions/openxr_vulkan_extension.cpp") +if env["opengl3"]: + env_openxr.add_source_files(module_obj, "extensions/openxr_opengl_extension.cpp") env_openxr.add_source_files(module_obj, "extensions/openxr_palm_pose_extension.cpp") env_openxr.add_source_files(module_obj, "extensions/openxr_composition_layer_depth_extension.cpp") diff --git a/modules/openxr/extensions/openxr_opengl_extension.cpp b/modules/openxr/extensions/openxr_opengl_extension.cpp new file mode 100644 index 0000000000..a25727f885 --- /dev/null +++ b/modules/openxr/extensions/openxr_opengl_extension.cpp @@ -0,0 +1,479 @@ +/*************************************************************************/ +/* openxr_opengl_extension.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifdef GLES3_ENABLED + +#include "../extensions/openxr_opengl_extension.h" +#include "../openxr_util.h" +#include "drivers/gles3/effects/copy_effects.h" +#include "drivers/gles3/storage/texture_storage.h" +#include "servers/rendering/rendering_server_globals.h" +#include "servers/rendering_server.h" + +OpenXROpenGLExtension::OpenXROpenGLExtension(OpenXRAPI *p_openxr_api) : + OpenXRGraphicsExtensionWrapper(p_openxr_api) { +#ifdef ANDROID_ENABLED + request_extensions[XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME] = nullptr; +#else + request_extensions[XR_KHR_OPENGL_ENABLE_EXTENSION_NAME] = nullptr; +#endif + + ERR_FAIL_NULL(openxr_api); +} + +OpenXROpenGLExtension::~OpenXROpenGLExtension() { +} + +void OpenXROpenGLExtension::on_instance_created(const XrInstance p_instance) { + ERR_FAIL_NULL(openxr_api); + + // Obtain pointers to functions we're accessing here. + +#ifdef ANDROID_ENABLED + EXT_INIT_XR_FUNC(xrGetOpenGLESGraphicsRequirementsKHR); +#else + EXT_INIT_XR_FUNC(xrGetOpenGLGraphicsRequirementsKHR); +#endif + EXT_INIT_XR_FUNC(xrEnumerateSwapchainImages); +} + +bool OpenXROpenGLExtension::check_graphics_api_support(XrVersion p_desired_version) { + ERR_FAIL_NULL_V(openxr_api, false); + + XrSystemId system_id = openxr_api->get_system_id(); + XrInstance instance = openxr_api->get_instance(); + +#ifdef ANDROID_ENABLED + XrGraphicsRequirementsOpenGLESKHR opengl_requirements; + opengl_requirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR; + opengl_requirements.next = nullptr; + + XrResult result = xrGetOpenGLESGraphicsRequirementsKHR(instance, system_id, &opengl_requirements); + if (!openxr_api->xr_result(result, "Failed to get OpenGL graphics requirements!")) { + return false; + } +#else + XrGraphicsRequirementsOpenGLKHR opengl_requirements; + opengl_requirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR; + opengl_requirements.next = nullptr; + + XrResult result = xrGetOpenGLGraphicsRequirementsKHR(instance, system_id, &opengl_requirements); + if (!openxr_api->xr_result(result, "Failed to get OpenGL graphics requirements!")) { + return false; + } +#endif + + if (p_desired_version < opengl_requirements.minApiVersionSupported) { + print_line("OpenXR: Requested OpenGL version does not meet the minimum version this runtime supports."); + print_line("- desired_version ", OpenXRUtil::make_xr_version_string(p_desired_version)); + print_line("- minApiVersionSupported ", OpenXRUtil::make_xr_version_string(opengl_requirements.minApiVersionSupported)); + print_line("- maxApiVersionSupported ", OpenXRUtil::make_xr_version_string(opengl_requirements.maxApiVersionSupported)); + return false; + } + + if (p_desired_version > opengl_requirements.maxApiVersionSupported) { + print_line("OpenXR: Requested OpenGL version exceeds the maximum version this runtime has been tested on and is known to support."); + print_line("- desired_version ", OpenXRUtil::make_xr_version_string(p_desired_version)); + print_line("- minApiVersionSupported ", OpenXRUtil::make_xr_version_string(opengl_requirements.minApiVersionSupported)); + print_line("- maxApiVersionSupported ", OpenXRUtil::make_xr_version_string(opengl_requirements.maxApiVersionSupported)); + } + + return true; +} + +#ifdef WIN32 +XrGraphicsBindingOpenGLWin32KHR OpenXROpenGLExtension::graphics_binding_gl; +#elif ANDROID_ENABLED +XrGraphicsBindingOpenGLESAndroidKHR OpenXROpenGLExtension::graphics_binding_gl; +#else +XrGraphicsBindingOpenGLXlibKHR OpenXROpenGLExtension::graphics_binding_gl; +#endif + +void *OpenXROpenGLExtension::set_session_create_and_get_next_pointer(void *p_next_pointer) { + XrVersion desired_version = XR_MAKE_VERSION(3, 3, 0); + + if (!check_graphics_api_support(desired_version)) { + print_line("OpenXR: Trying to initialize with OpenGL anyway..."); + //return p_next_pointer; + } + + DisplayServer *display_server = DisplayServer::get_singleton(); + +#ifdef WIN32 + graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR, + graphics_binding_gl.next = p_next_pointer; + + graphics_binding_gl.hDC = (HDC)display_server->window_get_native_handle(DisplayServer::WINDOW_VIEW); + graphics_binding_gl.hGLRC = (HGLRC)display_server->window_get_native_handle(DisplayServer::OPENGL_CONTEXT); +#elif ANDROID_ENABLED + graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR; + graphics_binding_gl.next = p_next_pointer; + + graphics_binding_gl.display = eglGetCurrentDisplay(); + graphics_binding_gl.config = (EGLConfig)0; // https://github.com/KhronosGroup/OpenXR-SDK-Source/blob/master/src/tests/hello_xr/graphicsplugin_opengles.cpp#L122 + graphics_binding_gl.context = eglGetCurrentContext(); +#else + graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR; + graphics_binding_gl.next = p_next_pointer; + + void *display_handle = (void *)display_server->window_get_native_handle(DisplayServer::DISPLAY_HANDLE); + void *glxcontext_handle = (void *)display_server->window_get_native_handle(DisplayServer::OPENGL_CONTEXT); + void *glxdrawable_handle = (void *)display_server->window_get_native_handle(DisplayServer::WINDOW_HANDLE); + + graphics_binding_gl.xDisplay = (Display *)display_handle; + graphics_binding_gl.glxContext = (GLXContext)glxcontext_handle; + graphics_binding_gl.glxDrawable = (GLXDrawable)glxdrawable_handle; + + if (graphics_binding_gl.xDisplay == nullptr) { + print_line("OpenXR Failed to get xDisplay from Godot, using XOpenDisplay(nullptr)"); + graphics_binding_gl.xDisplay = XOpenDisplay(nullptr); + } + if (graphics_binding_gl.glxContext == nullptr) { + print_line("OpenXR Failed to get glxContext from Godot, using glXGetCurrentContext()"); + graphics_binding_gl.glxContext = glXGetCurrentContext(); + } + if (graphics_binding_gl.glxDrawable == 0) { + print_line("OpenXR Failed to get glxDrawable from Godot, using glXGetCurrentDrawable()"); + graphics_binding_gl.glxDrawable = glXGetCurrentDrawable(); + } + + // spec says to use proper values but runtimes don't care + graphics_binding_gl.visualid = 0; + graphics_binding_gl.glxFBConfig = 0; +#endif + + return &graphics_binding_gl; +} + +void OpenXROpenGLExtension::get_usable_swapchain_formats(Vector<int64_t> &p_usable_swap_chains) { +#ifdef WIN32 + p_usable_swap_chains.push_back(GL_SRGB8_ALPHA8); + p_usable_swap_chains.push_back(GL_RGBA8); +#elif ANDROID_ENABLED + p_usable_swap_chains.push_back(GL_SRGB8_ALPHA8); + p_usable_swap_chains.push_back(GL_RGBA8); +#else + p_usable_swap_chains.push_back(GL_SRGB8_ALPHA8_EXT); + p_usable_swap_chains.push_back(GL_RGBA8_EXT); +#endif +} + +void OpenXROpenGLExtension::get_usable_depth_formats(Vector<int64_t> &p_usable_depth_formats) { + p_usable_depth_formats.push_back(GL_DEPTH_COMPONENT32F); + p_usable_depth_formats.push_back(GL_DEPTH24_STENCIL8); + p_usable_depth_formats.push_back(GL_DEPTH32F_STENCIL8); +} + +bool OpenXROpenGLExtension::get_swapchain_image_data(XrSwapchain p_swapchain, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size, void **r_swapchain_graphics_data) { + GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); + ERR_FAIL_NULL_V(texture_storage, false); + + uint32_t swapchain_length; + XrResult result = xrEnumerateSwapchainImages(p_swapchain, 0, &swapchain_length, nullptr); + if (XR_FAILED(result)) { + print_line("OpenXR: Failed to get swapchaim image count [", openxr_api->get_error_string(result), "]"); + return false; + } + +#ifdef ANDROID_ENABLED + XrSwapchainImageOpenGLESKHR *images = (XrSwapchainImageOpenGLESKHR *)memalloc(sizeof(XrSwapchainImageOpenGLESKHR) * swapchain_length); +#else + XrSwapchainImageOpenGLKHR *images = (XrSwapchainImageOpenGLKHR *)memalloc(sizeof(XrSwapchainImageOpenGLKHR) * swapchain_length); +#endif + ERR_FAIL_NULL_V_MSG(images, false, "OpenXR Couldn't allocate memory for swap chain image"); + + for (uint64_t i = 0; i < swapchain_length; i++) { +#ifdef ANDROID_ENABLED + images[i].type = XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR; +#else + images[i].type = XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR; +#endif + images[i].next = nullptr; + images[i].image = 0; + } + + result = xrEnumerateSwapchainImages(p_swapchain, swapchain_length, &swapchain_length, (XrSwapchainImageBaseHeader *)images); + if (XR_FAILED(result)) { + print_line("OpenXR: Failed to get swapchaim images [", openxr_api->get_error_string(result), "]"); + memfree(images); + return false; + } + + SwapchainGraphicsData *data = memnew(SwapchainGraphicsData); + if (data == nullptr) { + print_line("OpenXR: Failed to allocate memory for swapchain data"); + memfree(images); + return false; + } + *r_swapchain_graphics_data = data; + data->is_multiview = (p_array_size > 1); + + Image::Format format = Image::FORMAT_RGBA8; + + Vector<RID> texture_rids; + + for (uint64_t i = 0; i < swapchain_length; i++) { + RID texture_rid = texture_storage->texture_create_external( + p_array_size == 1 ? GLES3::Texture::TYPE_2D : GLES3::Texture::TYPE_LAYERED, + format, + images[i].image, + p_width, + p_height, + 1, + p_array_size); + + texture_rids.push_back(texture_rid); + } + + data->texture_rids = texture_rids; + + memfree(images); + + return true; +} + +bool OpenXROpenGLExtension::create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, Projection &r_camera_matrix) { + XrMatrix4x4f matrix; + XrMatrix4x4f_CreateProjectionFov(&matrix, GRAPHICS_OPENGL, p_fov, (float)p_z_near, (float)p_z_far); + + for (int j = 0; j < 4; j++) { + for (int i = 0; i < 4; i++) { + r_camera_matrix.columns[j][i] = matrix.m[j * 4 + i]; + } + } + + return true; +} + +RID OpenXROpenGLExtension::get_texture(void *p_swapchain_graphics_data, int p_image_index) { + SwapchainGraphicsData *data = (SwapchainGraphicsData *)p_swapchain_graphics_data; + ERR_FAIL_NULL_V(data, RID()); + + ERR_FAIL_INDEX_V(p_image_index, data->texture_rids.size(), RID()); + return data->texture_rids[p_image_index]; +} + +void OpenXROpenGLExtension::cleanup_swapchain_graphics_data(void **p_swapchain_graphics_data) { + if (*p_swapchain_graphics_data == nullptr) { + return; + } + + GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton(); + ERR_FAIL_NULL(texture_storage); + + SwapchainGraphicsData *data = (SwapchainGraphicsData *)*p_swapchain_graphics_data; + + for (int i = 0; i < data->texture_rids.size(); i++) { + texture_storage->texture_free(data->texture_rids[i]); + } + data->texture_rids.clear(); + + memdelete(data); + *p_swapchain_graphics_data = nullptr; +} + +#define ENUM_TO_STRING_CASE(e) \ + case e: { \ + return String(#e); \ + } break; + +String OpenXROpenGLExtension::get_swapchain_format_name(int64_t p_swapchain_format) const { + // These are somewhat different per platform, will need to weed some stuff out... + switch (p_swapchain_format) { +#ifdef WIN32 + // using definitions from GLAD + ENUM_TO_STRING_CASE(GL_R8_SNORM) + ENUM_TO_STRING_CASE(GL_RG8_SNORM) + ENUM_TO_STRING_CASE(GL_RGB8_SNORM) + ENUM_TO_STRING_CASE(GL_RGBA8_SNORM) + ENUM_TO_STRING_CASE(GL_R16_SNORM) + ENUM_TO_STRING_CASE(GL_RG16_SNORM) + ENUM_TO_STRING_CASE(GL_RGB16_SNORM) + ENUM_TO_STRING_CASE(GL_RGBA16_SNORM) + ENUM_TO_STRING_CASE(GL_RGB4) + ENUM_TO_STRING_CASE(GL_RGB5) + ENUM_TO_STRING_CASE(GL_RGB8) + ENUM_TO_STRING_CASE(GL_RGB10) + ENUM_TO_STRING_CASE(GL_RGB12) + ENUM_TO_STRING_CASE(GL_RGB16) + ENUM_TO_STRING_CASE(GL_RGBA2) + ENUM_TO_STRING_CASE(GL_RGBA4) + ENUM_TO_STRING_CASE(GL_RGB5_A1) + ENUM_TO_STRING_CASE(GL_RGBA8) + ENUM_TO_STRING_CASE(GL_RGB10_A2) + ENUM_TO_STRING_CASE(GL_RGBA12) + ENUM_TO_STRING_CASE(GL_RGBA16) + ENUM_TO_STRING_CASE(GL_RGBA32F) + ENUM_TO_STRING_CASE(GL_RGB32F) + ENUM_TO_STRING_CASE(GL_RGBA16F) + ENUM_TO_STRING_CASE(GL_RGB16F) + ENUM_TO_STRING_CASE(GL_RGBA32UI) + ENUM_TO_STRING_CASE(GL_RGB32UI) + ENUM_TO_STRING_CASE(GL_RGBA16UI) + ENUM_TO_STRING_CASE(GL_RGB16UI) + ENUM_TO_STRING_CASE(GL_RGBA8UI) + ENUM_TO_STRING_CASE(GL_RGB8UI) + ENUM_TO_STRING_CASE(GL_RGBA32I) + ENUM_TO_STRING_CASE(GL_RGB32I) + ENUM_TO_STRING_CASE(GL_RGBA16I) + ENUM_TO_STRING_CASE(GL_RGB16I) + ENUM_TO_STRING_CASE(GL_RGBA8I) + ENUM_TO_STRING_CASE(GL_RGB8I) + ENUM_TO_STRING_CASE(GL_RGB10_A2UI) + ENUM_TO_STRING_CASE(GL_SRGB) + ENUM_TO_STRING_CASE(GL_SRGB8) + ENUM_TO_STRING_CASE(GL_SRGB_ALPHA) + ENUM_TO_STRING_CASE(GL_SRGB8_ALPHA8) + ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT16) + ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT24) + ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT32) + ENUM_TO_STRING_CASE(GL_DEPTH24_STENCIL8) + ENUM_TO_STRING_CASE(GL_R11F_G11F_B10F) + ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT32F) + ENUM_TO_STRING_CASE(GL_DEPTH32F_STENCIL8) + +#elif ANDROID_ENABLED + // using definitions from GLES3/gl3.h + + ENUM_TO_STRING_CASE(GL_RGBA4) + ENUM_TO_STRING_CASE(GL_RGB5_A1) + ENUM_TO_STRING_CASE(GL_RGB565) + ENUM_TO_STRING_CASE(GL_RGB8) + ENUM_TO_STRING_CASE(GL_RGBA8) + ENUM_TO_STRING_CASE(GL_RGB10_A2) + ENUM_TO_STRING_CASE(GL_RGBA32F) + ENUM_TO_STRING_CASE(GL_RGB32F) + ENUM_TO_STRING_CASE(GL_RGBA16F) + ENUM_TO_STRING_CASE(GL_RGB16F) + ENUM_TO_STRING_CASE(GL_R11F_G11F_B10F) + ENUM_TO_STRING_CASE(GL_UNSIGNED_INT_10F_11F_11F_REV) + ENUM_TO_STRING_CASE(GL_RGB9_E5) + ENUM_TO_STRING_CASE(GL_UNSIGNED_INT_5_9_9_9_REV) + ENUM_TO_STRING_CASE(GL_RGBA32UI) + ENUM_TO_STRING_CASE(GL_RGB32UI) + ENUM_TO_STRING_CASE(GL_RGBA16UI) + ENUM_TO_STRING_CASE(GL_RGB16UI) + ENUM_TO_STRING_CASE(GL_RGBA8UI) + ENUM_TO_STRING_CASE(GL_RGB8UI) + ENUM_TO_STRING_CASE(GL_RGBA32I) + ENUM_TO_STRING_CASE(GL_RGB32I) + ENUM_TO_STRING_CASE(GL_RGBA16I) + ENUM_TO_STRING_CASE(GL_RGB16I) + ENUM_TO_STRING_CASE(GL_RGBA8I) + ENUM_TO_STRING_CASE(GL_RGB8I) + ENUM_TO_STRING_CASE(GL_RG) + ENUM_TO_STRING_CASE(GL_RG_INTEGER) + ENUM_TO_STRING_CASE(GL_R8) + ENUM_TO_STRING_CASE(GL_RG8) + ENUM_TO_STRING_CASE(GL_R16F) + ENUM_TO_STRING_CASE(GL_R32F) + ENUM_TO_STRING_CASE(GL_RG16F) + ENUM_TO_STRING_CASE(GL_RG32F) + ENUM_TO_STRING_CASE(GL_R8I) + ENUM_TO_STRING_CASE(GL_R8UI) + ENUM_TO_STRING_CASE(GL_R16I) + ENUM_TO_STRING_CASE(GL_R16UI) + ENUM_TO_STRING_CASE(GL_R32I) + ENUM_TO_STRING_CASE(GL_R32UI) + ENUM_TO_STRING_CASE(GL_RG8I) + ENUM_TO_STRING_CASE(GL_RG8UI) + ENUM_TO_STRING_CASE(GL_RG16I) + ENUM_TO_STRING_CASE(GL_RG16UI) + ENUM_TO_STRING_CASE(GL_RG32I) + ENUM_TO_STRING_CASE(GL_RG32UI) + ENUM_TO_STRING_CASE(GL_R8_SNORM) + ENUM_TO_STRING_CASE(GL_RG8_SNORM) + ENUM_TO_STRING_CASE(GL_RGB8_SNORM) + ENUM_TO_STRING_CASE(GL_RGBA8_SNORM) + ENUM_TO_STRING_CASE(GL_RGB10_A2UI) + ENUM_TO_STRING_CASE(GL_SRGB) + ENUM_TO_STRING_CASE(GL_SRGB8) + ENUM_TO_STRING_CASE(GL_SRGB8_ALPHA8) + ENUM_TO_STRING_CASE(GL_COMPRESSED_R11_EAC) + ENUM_TO_STRING_CASE(GL_COMPRESSED_SIGNED_R11_EAC) + ENUM_TO_STRING_CASE(GL_COMPRESSED_RG11_EAC) + ENUM_TO_STRING_CASE(GL_COMPRESSED_SIGNED_RG11_EAC) + ENUM_TO_STRING_CASE(GL_COMPRESSED_RGB8_ETC2) + ENUM_TO_STRING_CASE(GL_COMPRESSED_SRGB8_ETC2) + ENUM_TO_STRING_CASE(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2) + ENUM_TO_STRING_CASE(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2) + ENUM_TO_STRING_CASE(GL_COMPRESSED_RGBA8_ETC2_EAC) + ENUM_TO_STRING_CASE(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC) + ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT16) + ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT24) + ENUM_TO_STRING_CASE(GL_DEPTH24_STENCIL8) + +#else + // using definitions from GL/gl.h + ENUM_TO_STRING_CASE(GL_ALPHA4_EXT) + ENUM_TO_STRING_CASE(GL_ALPHA8_EXT) + ENUM_TO_STRING_CASE(GL_ALPHA12_EXT) + ENUM_TO_STRING_CASE(GL_ALPHA16_EXT) + ENUM_TO_STRING_CASE(GL_LUMINANCE4_EXT) + ENUM_TO_STRING_CASE(GL_LUMINANCE8_EXT) + ENUM_TO_STRING_CASE(GL_LUMINANCE12_EXT) + ENUM_TO_STRING_CASE(GL_LUMINANCE16_EXT) + ENUM_TO_STRING_CASE(GL_LUMINANCE4_ALPHA4_EXT) + ENUM_TO_STRING_CASE(GL_LUMINANCE6_ALPHA2_EXT) + ENUM_TO_STRING_CASE(GL_LUMINANCE8_ALPHA8_EXT) + ENUM_TO_STRING_CASE(GL_LUMINANCE12_ALPHA4_EXT) + ENUM_TO_STRING_CASE(GL_LUMINANCE12_ALPHA12_EXT) + ENUM_TO_STRING_CASE(GL_LUMINANCE16_ALPHA16_EXT) + ENUM_TO_STRING_CASE(GL_INTENSITY_EXT) + ENUM_TO_STRING_CASE(GL_INTENSITY4_EXT) + ENUM_TO_STRING_CASE(GL_INTENSITY8_EXT) + ENUM_TO_STRING_CASE(GL_INTENSITY12_EXT) + ENUM_TO_STRING_CASE(GL_INTENSITY16_EXT) + ENUM_TO_STRING_CASE(GL_RGB2_EXT) + ENUM_TO_STRING_CASE(GL_RGB4_EXT) + ENUM_TO_STRING_CASE(GL_RGB5_EXT) + ENUM_TO_STRING_CASE(GL_RGB8_EXT) + ENUM_TO_STRING_CASE(GL_RGB10_EXT) + ENUM_TO_STRING_CASE(GL_RGB12_EXT) + ENUM_TO_STRING_CASE(GL_RGB16_EXT) + ENUM_TO_STRING_CASE(GL_RGBA2_EXT) + ENUM_TO_STRING_CASE(GL_RGBA4_EXT) + ENUM_TO_STRING_CASE(GL_RGB5_A1_EXT) + ENUM_TO_STRING_CASE(GL_RGBA8_EXT) + ENUM_TO_STRING_CASE(GL_RGB10_A2_EXT) + ENUM_TO_STRING_CASE(GL_RGBA12_EXT) + ENUM_TO_STRING_CASE(GL_RGBA16_EXT) + ENUM_TO_STRING_CASE(GL_SRGB_EXT) + ENUM_TO_STRING_CASE(GL_SRGB8_EXT) + ENUM_TO_STRING_CASE(GL_SRGB_ALPHA_EXT) + ENUM_TO_STRING_CASE(GL_SRGB8_ALPHA8_EXT) +#endif + default: { + return String("Swapchain format 0x") + String::num_int64(p_swapchain_format, 16); + } break; + } +} + +#endif // GLES3_ENABLED diff --git a/modules/openxr/extensions/openxr_opengl_extension.h b/modules/openxr/extensions/openxr_opengl_extension.h new file mode 100644 index 0000000000..b666653c8e --- /dev/null +++ b/modules/openxr/extensions/openxr_opengl_extension.h @@ -0,0 +1,120 @@ +/*************************************************************************/ +/* openxr_opengl_extension.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef OPENXR_OPENGL_EXTENSION_H +#define OPENXR_OPENGL_EXTENSION_H + +#ifdef GLES3_ENABLED + +#include "core/templates/vector.h" +#include "openxr_extension_wrapper.h" + +#include "../openxr_api.h" +#include "../util.h" + +#ifdef ANDROID_ENABLED +#define XR_USE_GRAPHICS_API_OPENGL_ES +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <GLES3/gl3.h> +#include <GLES3/gl3ext.h> +#else +#define XR_USE_GRAPHICS_API_OPENGL +#endif + +#ifdef WINDOWS_ENABLED +// Including windows.h here is absolutely evil, we shouldn't be doing this outside of platform +// however due to the way the openxr headers are put together, we have no choice. +#include <windows.h> +#endif + +#ifdef X11_ENABLED +#include OPENGL_INCLUDE_H +#define GL_GLEXT_PROTOTYPES 1 +#define GL3_PROTOTYPES 1 +#include <GL/gl.h> +#include <GL/glext.h> +#include <GL/glx.h> +#include <X11/Xlib.h> +#endif + +#ifdef ANDROID_ENABLED +// The jobject type from jni.h is used by openxr_platform.h on Android. +#include <jni.h> +#endif + +// include platform dependent structs +#include <openxr/openxr_platform.h> + +class OpenXROpenGLExtension : public OpenXRGraphicsExtensionWrapper { +public: + OpenXROpenGLExtension(OpenXRAPI *p_openxr_api); + virtual ~OpenXROpenGLExtension() override; + + virtual void on_instance_created(const XrInstance p_instance) override; + virtual void *set_session_create_and_get_next_pointer(void *p_next_pointer) override; + + virtual void get_usable_swapchain_formats(Vector<int64_t> &p_usable_swap_chains) override; + virtual void get_usable_depth_formats(Vector<int64_t> &p_usable_swap_chains) override; + virtual String get_swapchain_format_name(int64_t p_swapchain_format) const override; + virtual bool get_swapchain_image_data(XrSwapchain p_swapchain, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size, void **r_swapchain_graphics_data) override; + virtual void cleanup_swapchain_graphics_data(void **p_swapchain_graphics_data) override; + virtual bool create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, Projection &r_camera_matrix) override; + virtual RID get_texture(void *p_swapchain_graphics_data, int p_image_index) override; + +private: + static OpenXROpenGLExtension *singleton; + +#ifdef WIN32 + static XrGraphicsBindingOpenGLWin32KHR graphics_binding_gl; +#elif ANDROID_ENABLED + static XrGraphicsBindingOpenGLESAndroidKHR graphics_binding_gl; +#else + static XrGraphicsBindingOpenGLXlibKHR graphics_binding_gl; +#endif + + struct SwapchainGraphicsData { + bool is_multiview; + Vector<RID> texture_rids; + }; + + bool check_graphics_api_support(XrVersion p_desired_version); + +#ifdef ANDROID_ENABLED + EXT_PROTO_XRRESULT_FUNC3(xrGetOpenGLESGraphicsRequirementsKHR, (XrInstance), p_instance, (XrSystemId), p_system_id, (XrGraphicsRequirementsOpenGLESKHR *), p_graphics_requirements) +#else + EXT_PROTO_XRRESULT_FUNC3(xrGetOpenGLGraphicsRequirementsKHR, (XrInstance), p_instance, (XrSystemId), p_system_id, (XrGraphicsRequirementsOpenGLKHR *), p_graphics_requirements) +#endif + EXT_PROTO_XRRESULT_FUNC4(xrEnumerateSwapchainImages, (XrSwapchain), p_swapchain, (uint32_t), p_image_capacity_input, (uint32_t *), p_image_count_output, (XrSwapchainImageBaseHeader *), p_images) +}; + +#endif // GLES3_ENABLED + +#endif // OPENXR_OPENGL_EXTENSION_H diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp index 8b189cf027..88111afede 100644 --- a/modules/openxr/openxr_api.cpp +++ b/modules/openxr/openxr_api.cpp @@ -45,10 +45,40 @@ #include "extensions/openxr_android_extension.h" #endif +// We need to have all the graphics API defines before the Vulkan or OpenGL +// extensions are included, otherwise we'll only get one graphics API. +#ifdef VULKAN_ENABLED +#define XR_USE_GRAPHICS_API_VULKAN +#endif +#ifdef GLES3_ENABLED +#ifdef ANDROID +#define XR_USE_GRAPHICS_API_OPENGL_ES +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <GLES3/gl3.h> +#include <GLES3/gl3ext.h> +#else +#define XR_USE_GRAPHICS_API_OPENGL +#endif // ANDROID +#ifdef X11_ENABLED +#include OPENGL_INCLUDE_H +#define GL_GLEXT_PROTOTYPES 1 +#define GL3_PROTOTYPES 1 +#include <GL/gl.h> +#include <GL/glext.h> +#include <GL/glx.h> +#include <X11/Xlib.h> +#endif // X11_ENABLED +#endif // GLES_ENABLED + #ifdef VULKAN_ENABLED #include "extensions/openxr_vulkan_extension.h" #endif +#ifdef GLES3_ENABLED +#include "extensions/openxr_opengl_extension.h" +#endif + #include "extensions/openxr_composition_layer_depth_extension.h" #include "extensions/openxr_fb_display_refresh_rate_extension.h" #include "extensions/openxr_fb_passthrough_extension_wrapper.h" @@ -1142,9 +1172,8 @@ bool OpenXRAPI::initialize(const String &p_rendering_driver) { #endif } else if (p_rendering_driver == "opengl3") { #ifdef GLES3_ENABLED - // graphics_extension = memnew(OpenXROpenGLExtension(this)); - // register_extension_wrapper(graphics_extension); - ERR_FAIL_V_MSG(false, "OpenXR: OpenGL is not supported at this time."); + graphics_extension = memnew(OpenXROpenGLExtension(this)); + register_extension_wrapper(graphics_extension); #else // shouldn't be possible... ERR_FAIL_V(false); diff --git a/modules/websocket/emws_peer.cpp b/modules/websocket/emws_peer.cpp index 3bd132bc73..eea015e486 100644 --- a/modules/websocket/emws_peer.cpp +++ b/modules/websocket/emws_peer.cpp @@ -95,6 +95,10 @@ Error EMWSPeer::connect_to_url(const String &p_url, bool p_verify_tls, Ref<X509C requested_url += ":" + String::num(port); } + if (!path.is_empty()) { + requested_url += path; + } + peer_sock = godot_js_websocket_create(this, requested_url.utf8().get_data(), proto_string.utf8().get_data(), &_esws_on_connect, &_esws_on_message, &_esws_on_error, &_esws_on_close); if (peer_sock == -1) { return FAILED; diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index 08369e735d..967f5c7dae 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -321,6 +321,11 @@ int64_t DisplayServerAndroid::window_get_native_handle(HandleType p_handle_type, case WINDOW_VIEW: { return 0; // Not supported. } +#ifdef GLES3_ENABLED + case OPENGL_CONTEXT: { + return eglGetCurrentContext(); + } +#endif default: { return 0; } diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index 3bfdd3b881..9919268375 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -585,12 +585,13 @@ zip_fileinfo EditorExportPlatformAndroid::get_zip_fileinfo() { return zipfi; } -Vector<String> EditorExportPlatformAndroid::get_abis() { - Vector<String> abis; - abis.push_back("armeabi-v7a"); - abis.push_back("arm64-v8a"); - abis.push_back("x86"); - abis.push_back("x86_64"); +Vector<EditorExportPlatformAndroid::ABI> EditorExportPlatformAndroid::get_abis() { + // Should have the same order and size as get_archs. + Vector<ABI> abis; + abis.push_back(ABI("armeabi-v7a", "arm32")); + abis.push_back(ABI("arm64-v8a", "arm64")); + abis.push_back(ABI("x86", "x86_32")); + abis.push_back(ABI("x86_64", "x86_64")); return abis; } @@ -687,14 +688,20 @@ Error EditorExportPlatformAndroid::save_apk_so(void *p_userdata, const SharedObj return FAILED; } APKExportData *ed = static_cast<APKExportData *>(p_userdata); - Vector<String> abis = get_abis(); + Vector<ABI> abis = get_abis(); bool exported = false; for (int i = 0; i < p_so.tags.size(); ++i) { // shared objects can be fat (compatible with multiple ABIs) - int abi_index = abis.find(p_so.tags[i]); + int abi_index = -1; + for (int j = 0; j < abis.size(); ++j) { + if (abis[j].abi == p_so.tags[i] || abis[j].arch == p_so.tags[i]) { + abi_index = j; + break; + } + } if (abi_index != -1) { exported = true; - String abi = abis[abi_index]; + String abi = abis[abi_index].abi; String dst_path = String("lib").path_join(abi).path_join(p_so.path.get_file()); Vector<uint8_t> array = FileAccess::get_file_as_array(p_so.path); Error store_err = store_in_apk(ed, dst_path, array); @@ -702,9 +709,7 @@ Error EditorExportPlatformAndroid::save_apk_so(void *p_userdata, const SharedObj } } if (!exported) { - String abis_string = String(" ").join(abis); - String err = "Cannot determine ABI for library \"" + p_so.path + "\". One of the supported ABIs must be used as a tag: " + abis_string; - ERR_PRINT(err); + ERR_PRINT("Cannot determine architecture for library \"" + p_so.path + "\". One of the supported architectures must be used as a tag: " + join_abis(abis, " ", true)); return FAILED; } return OK; @@ -725,16 +730,22 @@ Error EditorExportPlatformAndroid::ignore_apk_file(void *p_userdata, const Strin Error EditorExportPlatformAndroid::copy_gradle_so(void *p_userdata, const SharedObject &p_so) { ERR_FAIL_COND_V_MSG(!p_so.path.get_file().begins_with("lib"), FAILED, "Android .so file names must start with \"lib\", but got: " + p_so.path); - Vector<String> abis = get_abis(); + Vector<ABI> abis = get_abis(); CustomExportData *export_data = static_cast<CustomExportData *>(p_userdata); bool exported = false; for (int i = 0; i < p_so.tags.size(); ++i) { - int abi_index = abis.find(p_so.tags[i]); + int abi_index = -1; + for (int j = 0; j < abis.size(); ++j) { + if (abis[j].abi == p_so.tags[i] || abis[j].arch == p_so.tags[i]) { + abi_index = j; + break; + } + } if (abi_index != -1) { exported = true; String base = "res://android/build/libs"; String type = export_data->debug ? "debug" : "release"; - String abi = abis[abi_index]; + String abi = abis[abi_index].abi; String filename = p_so.path.get_file(); String dst_path = base.path_join(type).path_join(abi).path_join(filename); Vector<uint8_t> data = FileAccess::get_file_as_array(p_so.path); @@ -745,7 +756,7 @@ Error EditorExportPlatformAndroid::copy_gradle_so(void *p_userdata, const Shared } } ERR_FAIL_COND_V_MSG(!exported, FAILED, - "Cannot determine ABI for library \"" + p_so.path + "\". One of the supported ABIs must be used as a tag: " + String(" ").join(abis)); + "Cannot determine architecture for library \"" + p_so.path + "\". One of the supported architectures must be used as a tag:" + join_abis(abis, " ", true)); return OK; } @@ -1656,11 +1667,11 @@ void EditorExportPlatformAndroid::_copy_icons_to_gradle_project(const Ref<Editor } } -Vector<String> EditorExportPlatformAndroid::get_enabled_abis(const Ref<EditorExportPreset> &p_preset) { - Vector<String> abis = get_abis(); - Vector<String> enabled_abis; +Vector<EditorExportPlatformAndroid::ABI> EditorExportPlatformAndroid::get_enabled_abis(const Ref<EditorExportPreset> &p_preset) { + Vector<ABI> abis = get_abis(); + Vector<ABI> enabled_abis; for (int i = 0; i < abis.size(); ++i) { - bool is_enabled = p_preset->get("architectures/" + abis[i]); + bool is_enabled = p_preset->get("architectures/" + abis[i].abi); if (is_enabled) { enabled_abis.push_back(abis[i]); } @@ -1671,9 +1682,10 @@ Vector<String> EditorExportPlatformAndroid::get_enabled_abis(const Ref<EditorExp void EditorExportPlatformAndroid::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const { r_features->push_back("etc2"); - Vector<String> abis = get_enabled_abis(p_preset); + Vector<ABI> abis = get_enabled_abis(p_preset); for (int i = 0; i < abis.size(); ++i) { - r_features->push_back(abis[i]); + r_features->push_back(abis[i].arch); + r_features->push_back(abis[i].abi); } } @@ -1697,9 +1709,9 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio // Android supports multiple architectures in an app bundle, so // we expose each option as a checkbox in the export dialog. - const Vector<String> abis = get_abis(); + const Vector<ABI> abis = get_abis(); for (int i = 0; i < abis.size(); ++i) { - const String abi = abis[i]; + const String abi = abis[i].abi; // All Android devices supporting Vulkan run 64-bit Android, // so there is usually no point in exporting for 32-bit Android. const bool is_default = abi == "arm64-v8a"; @@ -2516,13 +2528,24 @@ void EditorExportPlatformAndroid::_remove_copied_libs() { da->remove(GDNATIVE_LIBS_PATH); } -String EditorExportPlatformAndroid::join_list(List<String> parts, const String &separator) const { +String EditorExportPlatformAndroid::join_list(const List<String> &p_parts, const String &p_separator) { + String ret; + for (int i = 0; i < p_parts.size(); ++i) { + if (i > 0) { + ret += p_separator; + } + ret += p_parts[i]; + } + return ret; +} + +String EditorExportPlatformAndroid::join_abis(const Vector<EditorExportPlatformAndroid::ABI> &p_parts, const String &p_separator, bool p_use_arch) { String ret; - for (int i = 0; i < parts.size(); ++i) { + for (int i = 0; i < p_parts.size(); ++i) { if (i > 0) { - ret += separator; + ret += p_separator; } - ret += parts[i]; + ret += (p_use_arch) ? p_parts[i].arch : p_parts[i].abi; } return ret; } @@ -2544,7 +2567,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP bool use_custom_build = bool(p_preset->get("custom_build/use_custom_build")); bool p_give_internet = p_flags & (DEBUG_FLAG_DUMB_CLIENT | DEBUG_FLAG_REMOTE_DEBUG); bool apk_expansion = p_preset->get("apk_expansion/enable"); - Vector<String> enabled_abis = get_enabled_abis(p_preset); + Vector<ABI> enabled_abis = get_enabled_abis(p_preset); print_verbose("Exporting for Android..."); print_verbose("- debug build: " + bool_to_string(p_debug)); @@ -2553,7 +2576,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP print_verbose("- sign build: " + bool_to_string(should_sign)); print_verbose("- custom build enabled: " + bool_to_string(use_custom_build)); print_verbose("- apk expansion enabled: " + bool_to_string(apk_expansion)); - print_verbose("- enabled abis: " + String(",").join(enabled_abis)); + print_verbose("- enabled abis: " + join_abis(enabled_abis, ",", false)); print_verbose("- export filter: " + itos(p_preset->get_export_filter())); print_verbose("- include filter: " + p_preset->get_include_filter()); print_verbose("- exclude filter: " + p_preset->get_exclude_filter()); @@ -2676,7 +2699,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP if (!target_sdk_version.is_valid_int()) { target_sdk_version = itos(DEFAULT_TARGET_SDK_VERSION); } - String enabled_abi_string = String("|").join(enabled_abis); + String enabled_abi_string = join_abis(enabled_abis, "|", false); String sign_flag = should_sign ? "true" : "false"; String zipalign_flag = "true"; @@ -2861,7 +2884,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP String apk_expansion_pkey = p_preset->get("apk_expansion/public_key"); - Vector<String> invalid_abis(enabled_abis); + Vector<ABI> invalid_abis(enabled_abis); while (ret == UNZ_OK) { //get filename unz_file_info info; @@ -2924,7 +2947,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP if (file.ends_with(".so")) { bool enabled = false; for (int i = 0; i < enabled_abis.size(); ++i) { - if (file.begins_with("lib/" + enabled_abis[i] + "/")) { + if (file.begins_with("lib/" + enabled_abis[i].abi + "/")) { invalid_abis.erase(enabled_abis[i]); enabled = true; break; @@ -2966,8 +2989,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP } if (!invalid_abis.is_empty()) { - String unsupported_arch = String(", ").join(invalid_abis); - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Missing libraries in the export template for the selected architectures: %s. Please build a template with all required libraries, or uncheck the missing architectures in the export preset."), unsupported_arch)); + add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Missing libraries in the export template for the selected architectures: %s. Please build a template with all required libraries, or uncheck the missing architectures in the export preset."), join_abis(invalid_abis, ", ", false))); CLEANUP_AND_RETURN(ERR_FILE_NOT_FOUND); } diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h index 46012bd46c..c8fcb761fe 100644 --- a/platform/android/export/export_plugin.h +++ b/platform/android/export/export_plugin.h @@ -99,7 +99,22 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { static zip_fileinfo get_zip_fileinfo(); - static Vector<String> get_abis(); + struct ABI { + String abi; + String arch; + + bool operator==(const ABI &p_a) const { + return p_a.abi == abi; + } + + ABI(const String &p_abi, const String &p_arch) { + abi = p_abi; + arch = p_arch; + } + ABI() {} + }; + + static Vector<ABI> get_abis(); /// List the gdap files in the directory specified by the p_path parameter. static Vector<String> list_gdap_files(const String &p_path); @@ -152,7 +167,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { const Ref<Image> &foreground, const Ref<Image> &background); - static Vector<String> get_enabled_abis(const Ref<EditorExportPreset> &p_preset); + static Vector<ABI> get_enabled_abis(const Ref<EditorExportPreset> &p_preset); public: typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); @@ -228,7 +243,8 @@ public: void _remove_copied_libs(); - String join_list(List<String> parts, const String &separator) const; + static String join_list(const List<String> &p_parts, const String &p_separator); + static String join_abis(const Vector<ABI> &p_parts, const String &p_separator, bool p_use_arch); virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override; diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java index 7925b54fc4..804dbaf165 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java @@ -127,7 +127,9 @@ public class GodotEditText extends EditText { edit.setText(""); edit.append(text); if (msg.arg2 != -1) { - edit.setSelection(msg.arg1, msg.arg2); + int selectionStart = Math.min(msg.arg1, edit.length()); + int selectionEnd = Math.min(msg.arg2, edit.length()); + edit.setSelection(selectionStart, selectionEnd); edit.mInputWrapper.setSelection(true); } else { edit.mInputWrapper.setSelection(false); diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.kt b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.kt index a7a57621de..cde8d7cdae 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.kt @@ -77,7 +77,7 @@ internal class GodotGestureHandler : SimpleOnGestureListener(), OnScaleGestureLi } private fun contextClickRouter(event: MotionEvent) { - if (scaleInProgress) { + if (scaleInProgress || nextDownIsDoubleTap) { return } @@ -134,40 +134,24 @@ internal class GodotGestureHandler : SimpleOnGestureListener(), OnScaleGestureLi } private fun onActionUp(event: MotionEvent): Boolean { + if (event.actionMasked == MotionEvent.ACTION_CANCEL && pointerCaptureInProgress) { + // Don't dispatch the ACTION_CANCEL while a capture is in progress + return true + } + val sourceMouseRelative = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { event.isFromSource(InputDevice.SOURCE_MOUSE_RELATIVE) } else { false } - when { - pointerCaptureInProgress -> { - return if (event.actionMasked == MotionEvent.ACTION_CANCEL) { - // Don't dispatch the ACTION_CANCEL while a capture is in progress - true - } else { - GodotInputHandler.handleMouseEvent( - MotionEvent.ACTION_UP, - event.buttonState, - event.x, - event.y, - 0f, - 0f, - false, - sourceMouseRelative - ) - pointerCaptureInProgress = false - true - } - } - dragInProgress -> { - GodotInputHandler.handleMotionEvent(event) - dragInProgress = false - return true - } - contextClickInProgress -> { + + if (pointerCaptureInProgress || dragInProgress || contextClickInProgress) { + if (contextClickInProgress || GodotInputHandler.isMouseEvent(event)) { + // This may be an ACTION_BUTTON_RELEASE event which we don't handle, + // so we convert it to an ACTION_UP event. GodotInputHandler.handleMouseEvent( - event.actionMasked, - 0, + MotionEvent.ACTION_UP, + event.buttonState, event.x, event.y, 0f, @@ -175,11 +159,16 @@ internal class GodotGestureHandler : SimpleOnGestureListener(), OnScaleGestureLi false, sourceMouseRelative ) - contextClickInProgress = false - return true + } else { + GodotInputHandler.handleTouchEvent(event) } - else -> return false + pointerCaptureInProgress = false + dragInProgress = false + contextClickInProgress = false + return true } + + return false } private fun onActionMove(event: MotionEvent): Boolean { @@ -242,7 +231,7 @@ internal class GodotGestureHandler : SimpleOnGestureListener(), OnScaleGestureLi val x = terminusEvent.x val y = terminusEvent.y - if (terminusEvent.pointerCount >= 2 && panningAndScalingEnabled) { + if (terminusEvent.pointerCount >= 2 && panningAndScalingEnabled && !pointerCaptureInProgress) { GodotLib.pan(x, y, distanceX / 5f, distanceY / 5f) } else { GodotInputHandler.handleMotionEvent(terminusEvent) @@ -251,7 +240,7 @@ internal class GodotGestureHandler : SimpleOnGestureListener(), OnScaleGestureLi } override fun onScale(detector: ScaleGestureDetector?): Boolean { - if (detector == null || !panningAndScalingEnabled) { + if (detector == null || !panningAndScalingEnabled || pointerCaptureInProgress) { return false } GodotLib.magnify( @@ -263,7 +252,7 @@ internal class GodotGestureHandler : SimpleOnGestureListener(), OnScaleGestureLi } override fun onScaleBegin(detector: ScaleGestureDetector?): Boolean { - if (detector == null || !panningAndScalingEnabled) { + if (detector == null || !panningAndScalingEnabled || pointerCaptureInProgress) { return false } scaleInProgress = true diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java index d2f3c5aed2..2f26497cc8 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java @@ -245,7 +245,7 @@ public class GodotInputHandler implements InputManager.InputDeviceListener { } return true; } - } else if (isMouseEvent(event)) { + } else { return handleMouseEvent(event); } @@ -473,6 +473,9 @@ public class GodotInputHandler implements InputManager.InputDeviceListener { } static boolean handleMouseEvent(int eventAction, int buttonsMask, float x, float y, float deltaX, float deltaY, boolean doubleClick, boolean sourceMouseRelative) { + // We don't handle ACTION_BUTTON_PRESS and ACTION_BUTTON_RELEASE events as they typically + // follow ACTION_DOWN and ACTION_UP events. As such, handling them would result in duplicate + // stream of events to the engine. switch (eventAction) { case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: diff --git a/platform/android/java_godot_view_wrapper.cpp b/platform/android/java_godot_view_wrapper.cpp index 762840a4b1..378a467772 100644 --- a/platform/android/java_godot_view_wrapper.cpp +++ b/platform/android/java_godot_view_wrapper.cpp @@ -68,7 +68,7 @@ void GodotJavaViewWrapper::request_pointer_capture() { } void GodotJavaViewWrapper::release_pointer_capture() { - if (_request_pointer_capture != nullptr) { + if (_release_pointer_capture != nullptr) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL(env); diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 4469c7a0f7..97fa90b1d2 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -162,11 +162,16 @@ Vector<String> OS_Android::get_granted_permissions() const { } Error OS_Android::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) { - p_library_handle = dlopen(p_path.utf8().get_data(), RTLD_NOW); + String path = p_path; + if (!FileAccess::exists(path)) { + path = p_path.get_file(); + } + + p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW); ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + p_path + ", error: " + dlerror() + "."); if (r_resolved_path != nullptr) { - *r_resolved_path = p_path; + *r_resolved_path = path; } return OK; diff --git a/platform/ios/display_server_ios.mm b/platform/ios/display_server_ios.mm index 8808d8e842..6793b40dd4 100644 --- a/platform/ios/display_server_ios.mm +++ b/platform/ios/display_server_ios.mm @@ -227,7 +227,7 @@ void DisplayServerIOS::_window_callback(const Callable &p_callable, const Varian // MARK: Touches void DisplayServerIOS::touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_double_click) { - if (!GLOBAL_DEF("debug/disable_touch", false)) { + if (!GLOBAL_GET("debug/disable_touch")) { Ref<InputEventScreenTouch> ev; ev.instantiate(); @@ -240,7 +240,7 @@ void DisplayServerIOS::touch_press(int p_idx, int p_x, int p_y, bool p_pressed, } void DisplayServerIOS::touch_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y) { - if (!GLOBAL_DEF("debug/disable_touch", false)) { + if (!GLOBAL_GET("debug/disable_touch")) { Ref<InputEventScreenDrag> ev; ev.instantiate(); ev->set_index(p_idx); diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index f477787771..c3a86c69e1 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -1309,6 +1309,11 @@ int64_t DisplayServerX11::window_get_native_handle(HandleType p_handle_type, Win case WINDOW_VIEW: { return 0; // Not supported. } +#ifdef GLES3_ENABLED + case OPENGL_CONTEXT: { + return (int64_t)gl_manager->get_glx_context(p_window); + } +#endif default: { return 0; } diff --git a/platform/linuxbsd/x11/gl_manager_x11.cpp b/platform/linuxbsd/x11/gl_manager_x11.cpp index f586c57dda..893a22e75e 100644 --- a/platform/linuxbsd/x11/gl_manager_x11.cpp +++ b/platform/linuxbsd/x11/gl_manager_x11.cpp @@ -376,6 +376,17 @@ bool GLManager_X11::is_using_vsync() const { return use_vsync; } +void *GLManager_X11::get_glx_context(DisplayServer::WindowID p_window_id) { + if (p_window_id == -1) { + return nullptr; + } + + const GLWindow &win = _windows[p_window_id]; + const GLDisplay &disp = get_display(win.gldisplay_id); + + return (void *)disp.context->glx_context; +} + GLManager_X11::GLManager_X11(const Vector2i &p_size, ContextType p_context_type) { context_type = p_context_type; diff --git a/platform/linuxbsd/x11/gl_manager_x11.h b/platform/linuxbsd/x11/gl_manager_x11.h index 4f78c45c88..1594c82801 100644 --- a/platform/linuxbsd/x11/gl_manager_x11.h +++ b/platform/linuxbsd/x11/gl_manager_x11.h @@ -116,6 +116,8 @@ public: void set_use_vsync(bool p_use); bool is_using_vsync() const; + void *get_glx_context(DisplayServer::WindowID p_window_id); + GLManager_X11(const Vector2i &p_size, ContextType p_context_type); ~GLManager_X11(); }; diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index 4478a635a8..33d8a8dd14 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -2932,6 +2932,11 @@ int64_t DisplayServerMacOS::window_get_native_handle(HandleType p_handle_type, W case WINDOW_VIEW: { return (int64_t)windows[p_window].window_view; } +#ifdef GLES3_ENABLED + case OPENGL_CONTEXT: { + return (int64_t)gl_manager->get_context(p_window); + } +#endif default: { return 0; } diff --git a/platform/macos/gl_manager_macos_legacy.h b/platform/macos/gl_manager_macos_legacy.h index 8752086551..d7ad5b1197 100644 --- a/platform/macos/gl_manager_macos_legacy.h +++ b/platform/macos/gl_manager_macos_legacy.h @@ -89,6 +89,8 @@ public: void set_use_vsync(bool p_use); bool is_using_vsync() const; + NSOpenGLContext *get_context(DisplayServer::WindowID p_window_id); + GLManager_MacOS(ContextType p_context_type); ~GLManager_MacOS(); }; diff --git a/platform/macos/gl_manager_macos_legacy.mm b/platform/macos/gl_manager_macos_legacy.mm index dec4821b86..ea5c36da6c 100644 --- a/platform/macos/gl_manager_macos_legacy.mm +++ b/platform/macos/gl_manager_macos_legacy.mm @@ -215,6 +215,15 @@ bool GLManager_MacOS::is_using_vsync() const { return use_vsync; } +NSOpenGLContext *GLManager_MacOS::get_context(DisplayServer::WindowID p_window_id) { + if (!windows.has(p_window_id)) { + return nullptr; + } + + GLWindow &win = windows[p_window_id]; + return win.context; +} + GLManager_MacOS::GLManager_MacOS(ContextType p_context_type) { context_type = p_context_type; } diff --git a/platform/web/display_server_web.cpp b/platform/web/display_server_web.cpp index 5a1a56b9da..f704124704 100644 --- a/platform/web/display_server_web.cpp +++ b/platform/web/display_server_web.cpp @@ -54,7 +54,15 @@ DisplayServerWeb *DisplayServerWeb::get_singleton() { // Window (canvas) bool DisplayServerWeb::check_size_force_redraw() { - return godot_js_display_size_update() != 0; + bool size_changed = godot_js_display_size_update() != 0; + if (size_changed && !rect_changed_callback.is_null()) { + Variant size = Rect2i(Point2i(), window_get_size()); // TODO use window_get_position if implemented. + Variant *vp = &size; + Variant ret; + Callable::CallError ce; + rect_changed_callback.callp((const Variant **)&vp, 1, ret, ce); + } + return size_changed; } void DisplayServerWeb::fullscreen_change_callback(int p_fullscreen) { @@ -903,7 +911,7 @@ ObjectID DisplayServerWeb::window_get_attached_instance_id(WindowID p_window) co } void DisplayServerWeb::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) { - // Not supported. + rect_changed_callback = p_callable; } void DisplayServerWeb::window_set_window_event_callback(const Callable &p_callable, WindowID p_window) { diff --git a/platform/web/display_server_web.h b/platform/web/display_server_web.h index 3222e2483e..1919736802 100644 --- a/platform/web/display_server_web.h +++ b/platform/web/display_server_web.h @@ -60,6 +60,7 @@ private: WindowMode window_mode = WINDOW_MODE_WINDOWED; ObjectID window_attached_instance_id = {}; + Callable rect_changed_callback; Callable window_event_callback; Callable input_event_callback; Callable input_text_callback; diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index d6ee712a31..2c8058fdc5 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -741,9 +741,14 @@ int64_t DisplayServerWindows::window_get_native_handle(HandleType p_handle_type, case WINDOW_HANDLE: { return (int64_t)windows[p_window].hWnd; } +#if defined(GLES3_ENABLED) case WINDOW_VIEW: { - return 0; // Not supported. + return (int64_t)gl_manager->get_hdc(p_window); } + case OPENGL_CONTEXT: { + return (int64_t)gl_manager->get_hglrc(p_window); + } +#endif default: { return 0; } diff --git a/platform/windows/gl_manager_windows.cpp b/platform/windows/gl_manager_windows.cpp index 7689751f1b..900bca8258 100644 --- a/platform/windows/gl_manager_windows.cpp +++ b/platform/windows/gl_manager_windows.cpp @@ -339,6 +339,16 @@ bool GLManager_Windows::is_using_vsync() const { return use_vsync; } +HDC GLManager_Windows::get_hdc(DisplayServer::WindowID p_window_id) { + return get_window(p_window_id).hDC; +} + +HGLRC GLManager_Windows::get_hglrc(DisplayServer::WindowID p_window_id) { + const GLWindow &win = get_window(p_window_id); + const GLDisplay &disp = get_display(win.gldisplay_id); + return disp.hRC; +} + GLManager_Windows::GLManager_Windows(ContextType p_context_type) { context_type = p_context_type; diff --git a/platform/windows/gl_manager_windows.h b/platform/windows/gl_manager_windows.h index 5e43a3de2a..c6d5f9f855 100644 --- a/platform/windows/gl_manager_windows.h +++ b/platform/windows/gl_manager_windows.h @@ -113,6 +113,9 @@ public: void set_use_vsync(bool p_use); bool is_using_vsync() const; + HDC get_hdc(DisplayServer::WindowID p_window_id); + HGLRC get_hglrc(DisplayServer::WindowID p_window_id); + GLManager_Windows(ContextType p_context_type); ~GLManager_Windows(); }; diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp index 9786b01058..e18f2bd1a1 100644 --- a/scene/2d/gpu_particles_2d.cpp +++ b/scene/2d/gpu_particles_2d.cpp @@ -141,16 +141,16 @@ void GPUParticles2D::set_process_material(const Ref<Material> &p_material) { void GPUParticles2D::set_trail_enabled(bool p_enabled) { trail_enabled = p_enabled; - RS::get_singleton()->particles_set_trails(particles, trail_enabled, trail_length); + RS::get_singleton()->particles_set_trails(particles, trail_enabled, trail_lifetime); queue_redraw(); RS::get_singleton()->particles_set_transform_align(particles, p_enabled ? RS::PARTICLES_TRANSFORM_ALIGN_Y_TO_VELOCITY : RS::PARTICLES_TRANSFORM_ALIGN_DISABLED); } -void GPUParticles2D::set_trail_length(double p_seconds) { +void GPUParticles2D::set_trail_lifetime(double p_seconds) { ERR_FAIL_COND(p_seconds < 0.001); - trail_length = p_seconds; - RS::get_singleton()->particles_set_trails(particles, trail_enabled, trail_length); + trail_lifetime = p_seconds; + RS::get_singleton()->particles_set_trails(particles, trail_enabled, trail_lifetime); queue_redraw(); } @@ -181,8 +181,8 @@ bool GPUParticles2D::is_trail_enabled() const { return trail_enabled; } -double GPUParticles2D::get_trail_length() const { - return trail_length; +double GPUParticles2D::get_trail_lifetime() const { + return trail_lifetime; } void GPUParticles2D::_update_collision_size() { @@ -614,10 +614,10 @@ void GPUParticles2D::_bind_methods() { ClassDB::bind_method(D_METHOD("emit_particle", "xform", "velocity", "color", "custom", "flags"), &GPUParticles2D::emit_particle); ClassDB::bind_method(D_METHOD("set_trail_enabled", "enabled"), &GPUParticles2D::set_trail_enabled); - ClassDB::bind_method(D_METHOD("set_trail_length", "secs"), &GPUParticles2D::set_trail_length); + ClassDB::bind_method(D_METHOD("set_trail_lifetime", "secs"), &GPUParticles2D::set_trail_lifetime); ClassDB::bind_method(D_METHOD("is_trail_enabled"), &GPUParticles2D::is_trail_enabled); - ClassDB::bind_method(D_METHOD("get_trail_length"), &GPUParticles2D::get_trail_length); + ClassDB::bind_method(D_METHOD("get_trail_lifetime"), &GPUParticles2D::get_trail_lifetime); ClassDB::bind_method(D_METHOD("set_trail_sections", "sections"), &GPUParticles2D::set_trail_sections); ClassDB::bind_method(D_METHOD("get_trail_sections"), &GPUParticles2D::get_trail_sections); @@ -647,7 +647,7 @@ void GPUParticles2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime,Reverse Lifetime"), "set_draw_order", "get_draw_order"); ADD_GROUP("Trails", "trail_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "trail_enabled"), "set_trail_enabled", "is_trail_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "trail_length_secs", PROPERTY_HINT_RANGE, "0.01,10,0.01,suffix:s"), "set_trail_length", "get_trail_length"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "trail_lifetime", PROPERTY_HINT_RANGE, "0.01,10,0.01,or_greater,suffix:s"), "set_trail_lifetime", "get_trail_lifetime"); ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_sections", PROPERTY_HINT_RANGE, "2,128,1"), "set_trail_sections", "get_trail_sections"); ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_section_subdivisions", PROPERTY_HINT_RANGE, "1,1024,1"), "set_trail_section_subdivisions", "get_trail_section_subdivisions"); ADD_GROUP("Process Material", "process_"); diff --git a/scene/2d/gpu_particles_2d.h b/scene/2d/gpu_particles_2d.h index d613b4ef51..7fba174357 100644 --- a/scene/2d/gpu_particles_2d.h +++ b/scene/2d/gpu_particles_2d.h @@ -74,7 +74,7 @@ private: real_t collision_base_size = 1.0; bool trail_enabled = false; - double trail_length = 0.3; + double trail_lifetime = 0.3; int trail_sections = 8; int trail_section_subdivisions = 4; @@ -104,7 +104,7 @@ public: void set_speed_scale(double p_scale); void set_collision_base_size(real_t p_ratio); void set_trail_enabled(bool p_enabled); - void set_trail_length(double p_seconds); + void set_trail_lifetime(double p_seconds); void set_trail_sections(int p_sections); void set_trail_section_subdivisions(int p_subdivisions); @@ -126,7 +126,7 @@ public: real_t get_collision_base_size() const; bool is_trail_enabled() const; - double get_trail_length() const; + double get_trail_lifetime() const; int get_trail_sections() const; int get_trail_section_subdivisions() const; diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp index dbbf196f7a..9d04202c2d 100644 --- a/scene/3d/gpu_particles_3d.cpp +++ b/scene/3d/gpu_particles_3d.cpp @@ -176,22 +176,22 @@ void GPUParticles3D::set_draw_order(DrawOrder p_order) { void GPUParticles3D::set_trail_enabled(bool p_enabled) { trail_enabled = p_enabled; - RS::get_singleton()->particles_set_trails(particles, trail_enabled, trail_length); + RS::get_singleton()->particles_set_trails(particles, trail_enabled, trail_lifetime); update_configuration_warnings(); } -void GPUParticles3D::set_trail_length(double p_seconds) { +void GPUParticles3D::set_trail_lifetime(double p_seconds) { ERR_FAIL_COND(p_seconds < 0.001); - trail_length = p_seconds; - RS::get_singleton()->particles_set_trails(particles, trail_enabled, trail_length); + trail_lifetime = p_seconds; + RS::get_singleton()->particles_set_trails(particles, trail_enabled, trail_lifetime); } bool GPUParticles3D::is_trail_enabled() const { return trail_enabled; } -double GPUParticles3D::get_trail_length() const { - return trail_length; +double GPUParticles3D::get_trail_lifetime() const { + return trail_lifetime; } GPUParticles3D::DrawOrder GPUParticles3D::get_draw_order() const { @@ -552,10 +552,10 @@ void GPUParticles3D::_bind_methods() { ClassDB::bind_method(D_METHOD("emit_particle", "xform", "velocity", "color", "custom", "flags"), &GPUParticles3D::emit_particle); ClassDB::bind_method(D_METHOD("set_trail_enabled", "enabled"), &GPUParticles3D::set_trail_enabled); - ClassDB::bind_method(D_METHOD("set_trail_length", "secs"), &GPUParticles3D::set_trail_length); + ClassDB::bind_method(D_METHOD("set_trail_lifetime", "secs"), &GPUParticles3D::set_trail_lifetime); ClassDB::bind_method(D_METHOD("is_trail_enabled"), &GPUParticles3D::is_trail_enabled); - ClassDB::bind_method(D_METHOD("get_trail_length"), &GPUParticles3D::get_trail_length); + ClassDB::bind_method(D_METHOD("get_trail_lifetime"), &GPUParticles3D::get_trail_lifetime); ClassDB::bind_method(D_METHOD("set_transform_align", "align"), &GPUParticles3D::set_transform_align); ClassDB::bind_method(D_METHOD("get_transform_align"), &GPUParticles3D::get_transform_align); @@ -583,7 +583,7 @@ void GPUParticles3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "transform_align", PROPERTY_HINT_ENUM, "Disabled,Z-Billboard,Y to Velocity,Z-Billboard + Y to Velocity"), "set_transform_align", "get_transform_align"); ADD_GROUP("Trails", "trail_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "trail_enabled"), "set_trail_enabled", "is_trail_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "trail_length_secs", PROPERTY_HINT_RANGE, "0.01,10,0.01,suffix:s"), "set_trail_length", "get_trail_length"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "trail_lifetime", PROPERTY_HINT_RANGE, "0.01,10,0.01,or_greater,suffix:s"), "set_trail_lifetime", "get_trail_lifetime"); ADD_GROUP("Process Material", ""); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,ParticleProcessMaterial"), "set_process_material", "get_process_material"); ADD_GROUP("Draw Passes", "draw_"); @@ -627,7 +627,7 @@ GPUParticles3D::GPUParticles3D() { set_pre_process_time(0); set_explosiveness_ratio(0); set_randomness_ratio(0); - set_trail_length(0.3); + set_trail_lifetime(0.3); set_visibility_aabb(AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8))); set_use_local_coordinates(false); set_draw_passes(1); diff --git a/scene/3d/gpu_particles_3d.h b/scene/3d/gpu_particles_3d.h index ef92218e4d..835d71862a 100644 --- a/scene/3d/gpu_particles_3d.h +++ b/scene/3d/gpu_particles_3d.h @@ -76,7 +76,7 @@ private: real_t collision_base_size = 0.01; bool trail_enabled = false; - double trail_length = 0.3; + double trail_lifetime = 0.3; TransformAlign transform_align = TRANSFORM_ALIGN_DISABLED; @@ -112,7 +112,7 @@ public: void set_speed_scale(double p_scale); void set_collision_base_size(real_t p_ratio); void set_trail_enabled(bool p_enabled); - void set_trail_length(double p_seconds); + void set_trail_lifetime(double p_seconds); bool is_emitting() const; int get_amount() const; @@ -127,7 +127,7 @@ public: double get_speed_scale() const; real_t get_collision_base_size() const; bool is_trail_enabled() const; - double get_trail_length() const; + double get_trail_lifetime() const; void set_fixed_fps(int p_count); int get_fixed_fps() const; diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp index f5d30c584f..ca7d1dfc1d 100644 --- a/scene/3d/xr_nodes.cpp +++ b/scene/3d/xr_nodes.cpp @@ -644,6 +644,12 @@ void XROrigin3D::set_current(bool p_enabled) { origin_nodes[i]->set_current(false); } } + + // update XRServer with our current position + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL(xr_server); + + xr_server->set_world_origin(get_global_transform()); } else { bool found = false; // We no longer have a current origin so find the first one we can make current diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index d6b5557a3f..82f089735d 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -896,7 +896,7 @@ void ItemList::gui_input(const Ref<InputEvent> &p_event) { if (k.is_valid() && k->get_unicode()) { uint64_t now = OS::get_singleton()->get_ticks_msec(); uint64_t diff = now - search_time_msec; - uint64_t max_interval = uint64_t(GLOBAL_DEF("gui/timers/incremental_search_max_interval_msec", 2000)); + uint64_t max_interval = uint64_t(GLOBAL_GET("gui/timers/incremental_search_max_interval_msec")); search_time_msec = now; if (diff > max_interval) { @@ -1831,9 +1831,6 @@ void ItemList::_bind_methods() { ADD_SIGNAL(MethodInfo("item_clicked", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::VECTOR2, "at_position"), PropertyInfo(Variant::INT, "mouse_button_index"))); ADD_SIGNAL(MethodInfo("multi_selected", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "selected"))); ADD_SIGNAL(MethodInfo("item_activated", PropertyInfo(Variant::INT, "index"))); - - GLOBAL_DEF("gui/timers/incremental_search_max_interval_msec", 2000); - ProjectSettings::get_singleton()->set_custom_property_info("gui/timers/incremental_search_max_interval_msec", PropertyInfo(Variant::INT, "gui/timers/incremental_search_max_interval_msec", PROPERTY_HINT_RANGE, "0,10000,1,or_greater")); // No negative numbers } ItemList::ItemList() { diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 9a411ef7ed..82f56a56c9 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -472,7 +472,7 @@ void PopupMenu::gui_input(const Ref<InputEvent> &p_event) { if (allow_search && k.is_valid() && k->get_unicode() && k->is_pressed()) { uint64_t now = OS::get_singleton()->get_ticks_msec(); uint64_t diff = now - search_time_msec; - uint64_t max_interval = uint64_t(GLOBAL_DEF("gui/timers/incremental_search_max_interval_msec", 2000)); + uint64_t max_interval = uint64_t(GLOBAL_GET("gui/timers/incremental_search_max_interval_msec")); search_time_msec = now; if (diff > max_interval) { diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index ec34a8d26d..531226f938 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -182,14 +182,12 @@ void ScrollContainer::gui_input(const Ref<InputEvent> &p_gui_input) { drag_accum = Vector2(); last_drag_accum = Vector2(); drag_from = Vector2(prev_h_scroll, prev_v_scroll); - drag_touching = screen_is_touchscreen; + drag_touching = true; drag_touching_deaccel = false; beyond_deadzone = false; time_since_motion = 0; - if (drag_touching) { - set_physics_process_internal(true); - time_since_motion = 0; - } + set_physics_process_internal(true); + time_since_motion = 0; } else { if (drag_touching) { diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 1b8444abf4..56f7281721 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1854,6 +1854,12 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { } else { if (mb->get_button_index() == MouseButton::LEFT) { if (selection_drag_attempt && is_mouse_over_selection()) { + remove_secondary_carets(); + + Point2i pos = get_line_column_at_pos(get_local_mouse_pos()); + set_caret_line(pos.y, false, true, 0, 0); + set_caret_column(pos.x, true, 0); + deselect(); } dragging_minimap = false; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 6f9a9a5141..1c96858da7 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -4818,7 +4818,7 @@ TreeItem *Tree::get_item_with_text(const String &p_find) const { void Tree::_do_incr_search(const String &p_add) { uint64_t time = OS::get_singleton()->get_ticks_usec() / 1000; // convert to msec uint64_t diff = time - last_keypress; - if (diff > uint64_t(GLOBAL_DEF("gui/timers/incremental_search_max_interval_msec", 2000))) { + if (diff > uint64_t(GLOBAL_GET("gui/timers/incremental_search_max_interval_msec"))) { incr_search = p_add; } else if (incr_search != p_add) { incr_search += p_add; diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index dfd9c6eb2f..1eb78f0160 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -5851,18 +5851,18 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float return dst; } case Variant::PACKED_INT32_ARRAY: { - const Vector<int32_t> *arr_a = Object::cast_to<Vector<int32_t>>(a); - const Vector<int32_t> *arr_b = Object::cast_to<Vector<int32_t>>(b); - int32_t sz = arr_a->size(); - if (sz == 0 || arr_b->size() != sz) { + const Vector<int32_t> arr_a = a; + const Vector<int32_t> arr_b = b; + int32_t sz = arr_a.size(); + if (sz == 0 || arr_b.size() != sz) { return a; } else { Vector<int32_t> v; v.resize(sz); { int32_t *vw = v.ptrw(); - const int32_t *ar = arr_a->ptr(); - const int32_t *br = arr_b->ptr(); + const int32_t *ar = arr_a.ptr(); + const int32_t *br = arr_b.ptr(); Variant va; for (int32_t i = 0; i < sz; i++) { @@ -5874,18 +5874,18 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float } } case Variant::PACKED_INT64_ARRAY: { - const Vector<int64_t> *arr_a = Object::cast_to<Vector<int64_t>>(a); - const Vector<int64_t> *arr_b = Object::cast_to<Vector<int64_t>>(b); - int64_t sz = arr_a->size(); - if (sz == 0 || arr_b->size() != sz) { + const Vector<int64_t> arr_a = a; + const Vector<int64_t> arr_b = b; + int64_t sz = arr_a.size(); + if (sz == 0 || arr_b.size() != sz) { return a; } else { Vector<int64_t> v; v.resize(sz); { int64_t *vw = v.ptrw(); - const int64_t *ar = arr_a->ptr(); - const int64_t *br = arr_b->ptr(); + const int64_t *ar = arr_a.ptr(); + const int64_t *br = arr_b.ptr(); Variant va; for (int64_t i = 0; i < sz; i++) { @@ -5897,18 +5897,18 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float } } case Variant::PACKED_FLOAT32_ARRAY: { - const Vector<float> *arr_a = Object::cast_to<Vector<float>>(a); - const Vector<float> *arr_b = Object::cast_to<Vector<float>>(b); - int sz = arr_a->size(); - if (sz == 0 || arr_b->size() != sz) { + const Vector<float> arr_a = a; + const Vector<float> arr_b = b; + int sz = arr_a.size(); + if (sz == 0 || arr_b.size() != sz) { return a; } else { Vector<float> v; v.resize(sz); { float *vw = v.ptrw(); - const float *ar = arr_a->ptr(); - const float *br = arr_b->ptr(); + const float *ar = arr_a.ptr(); + const float *br = arr_b.ptr(); Variant va; for (int i = 0; i < sz; i++) { @@ -5920,18 +5920,18 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float } } case Variant::PACKED_FLOAT64_ARRAY: { - const Vector<double> *arr_a = Object::cast_to<Vector<double>>(a); - const Vector<double> *arr_b = Object::cast_to<Vector<double>>(b); - int sz = arr_a->size(); - if (sz == 0 || arr_b->size() != sz) { + const Vector<double> arr_a = a; + const Vector<double> arr_b = b; + int sz = arr_a.size(); + if (sz == 0 || arr_b.size() != sz) { return a; } else { Vector<double> v; v.resize(sz); { double *vw = v.ptrw(); - const double *ar = arr_a->ptr(); - const double *br = arr_b->ptr(); + const double *ar = arr_a.ptr(); + const double *br = arr_b.ptr(); Variant va; for (int i = 0; i < sz; i++) { @@ -5943,18 +5943,18 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float } } case Variant::PACKED_VECTOR2_ARRAY: { - const Vector<Vector2> *arr_a = Object::cast_to<Vector<Vector2>>(a); - const Vector<Vector2> *arr_b = Object::cast_to<Vector<Vector2>>(b); - int sz = arr_a->size(); - if (sz == 0 || arr_b->size() != sz) { + const Vector<Vector2> arr_a = a; + const Vector<Vector2> arr_b = b; + int sz = arr_a.size(); + if (sz == 0 || arr_b.size() != sz) { return a; } else { Vector<Vector2> v; v.resize(sz); { Vector2 *vw = v.ptrw(); - const Vector2 *ar = arr_a->ptr(); - const Vector2 *br = arr_b->ptr(); + const Vector2 *ar = arr_a.ptr(); + const Vector2 *br = arr_b.ptr(); for (int i = 0; i < sz; i++) { vw[i] = ar[i].lerp(br[i], c); @@ -5964,18 +5964,18 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float } } case Variant::PACKED_VECTOR3_ARRAY: { - const Vector<Vector3> *arr_a = Object::cast_to<Vector<Vector3>>(a); - const Vector<Vector3> *arr_b = Object::cast_to<Vector<Vector3>>(b); - int sz = arr_a->size(); - if (sz == 0 || arr_b->size() != sz) { + const Vector<Vector3> arr_a = a; + const Vector<Vector3> arr_b = b; + int sz = arr_a.size(); + if (sz == 0 || arr_b.size() != sz) { return a; } else { Vector<Vector3> v; v.resize(sz); { Vector3 *vw = v.ptrw(); - const Vector3 *ar = arr_a->ptr(); - const Vector3 *br = arr_b->ptr(); + const Vector3 *ar = arr_a.ptr(); + const Vector3 *br = arr_b.ptr(); for (int i = 0; i < sz; i++) { vw[i] = ar[i].lerp(br[i], c); @@ -5985,18 +5985,18 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float } } case Variant::PACKED_COLOR_ARRAY: { - const Vector<Color> *arr_a = Object::cast_to<Vector<Color>>(a); - const Vector<Color> *arr_b = Object::cast_to<Vector<Color>>(b); - int sz = arr_a->size(); - if (sz == 0 || arr_b->size() != sz) { + const Vector<Color> arr_a = a; + const Vector<Color> arr_b = b; + int sz = arr_a.size(); + if (sz == 0 || arr_b.size() != sz) { return a; } else { Vector<Color> v; v.resize(sz); { Color *vw = v.ptrw(); - const Color *ar = arr_a->ptr(); - const Color *br = arr_b->ptr(); + const Color *ar = arr_a.ptr(); + const Color *br = arr_b.ptr(); for (int i = 0; i < sz; i++) { vw[i] = ar[i].lerp(br[i], c); diff --git a/scene/resources/shape_2d.cpp b/scene/resources/shape_2d.cpp index 61daf801e8..af84144591 100644 --- a/scene/resources/shape_2d.cpp +++ b/scene/resources/shape_2d.cpp @@ -116,7 +116,7 @@ bool Shape2D::is_collision_outline_enabled() { return true; } #endif - return GLOBAL_DEF("debug/shapes/collision/draw_2d_outlines", true); + return GLOBAL_GET("debug/shapes/collision/draw_2d_outlines"); } Shape2D::Shape2D(const RID &p_rid) { diff --git a/scene/resources/text_line.cpp b/scene/resources/text_line.cpp index ca1cd54349..afab44834d 100644 --- a/scene/resources/text_line.cpp +++ b/scene/resources/text_line.cpp @@ -317,11 +317,7 @@ float TextLine::get_width() const { Size2 TextLine::get_size() const { const_cast<TextLine *>(this)->_shape(); - if (TS->shaped_text_get_orientation(rid) == TextServer::ORIENTATION_HORIZONTAL) { - return Size2(TS->shaped_text_get_size(rid).x, TS->shaped_text_get_size(rid).y); - } else { - return Size2(TS->shaped_text_get_size(rid).x, TS->shaped_text_get_size(rid).y); - } + return TS->shaped_text_get_size(rid); } float TextLine::get_line_ascent() const { diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 1897612562..52d7f66203 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -826,6 +826,7 @@ void DisplayServer::_bind_methods() { BIND_ENUM_CONSTANT(DISPLAY_HANDLE); BIND_ENUM_CONSTANT(WINDOW_HANDLE); BIND_ENUM_CONSTANT(WINDOW_VIEW); + BIND_ENUM_CONSTANT(OPENGL_CONTEXT); BIND_ENUM_CONSTANT(TTS_UTTERANCE_STARTED); BIND_ENUM_CONSTANT(TTS_UTTERANCE_ENDED); diff --git a/servers/display_server.h b/servers/display_server.h index 55e9fb55dc..a796377f88 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -70,6 +70,7 @@ public: DISPLAY_HANDLE, WINDOW_HANDLE, WINDOW_VIEW, + OPENGL_CONTEXT, }; typedef DisplayServer *(*CreateFunction)(const String &, WindowMode, VSyncMode, uint32_t, const Point2i *, const Size2i &, Error &r_error); diff --git a/servers/physics_2d/godot_space_2d.cpp b/servers/physics_2d/godot_space_2d.cpp index a82d7dbbc4..89afb0e2a0 100644 --- a/servers/physics_2d/godot_space_2d.cpp +++ b/servers/physics_2d/godot_space_2d.cpp @@ -1225,7 +1225,7 @@ GodotSpace2D::GodotSpace2D() { ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/solver/solver_iterations", PropertyInfo(Variant::INT, "physics/2d/solver/solver_iterations", PROPERTY_HINT_RANGE, "1,32,1,or_greater")); contact_recycle_radius = GLOBAL_DEF("physics/2d/solver/contact_recycle_radius", 1.0); - ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/solver/contact_recycle_radius", PropertyInfo(Variant::FLOAT, "physics/2d/solver/contact_max_separation", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater")); + ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/solver/contact_recycle_radius", PropertyInfo(Variant::FLOAT, "physics/2d/solver/contact_recycle_radius", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater")); contact_max_separation = GLOBAL_DEF("physics/2d/solver/contact_max_separation", 1.5); ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/solver/contact_max_separation", PropertyInfo(Variant::FLOAT, "physics/2d/solver/contact_max_separation", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater")); diff --git a/servers/physics_3d/godot_space_3d.cpp b/servers/physics_3d/godot_space_3d.cpp index c23485279d..c98409e2c4 100644 --- a/servers/physics_3d/godot_space_3d.cpp +++ b/servers/physics_3d/godot_space_3d.cpp @@ -1258,7 +1258,7 @@ GodotSpace3D::GodotSpace3D() { ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/solver/solver_iterations", PropertyInfo(Variant::INT, "physics/3d/solver/solver_iterations", PROPERTY_HINT_RANGE, "1,32,1,or_greater")); contact_recycle_radius = GLOBAL_DEF("physics/3d/solver/contact_recycle_radius", 0.01); - ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/solver/contact_recycle_radius", PropertyInfo(Variant::FLOAT, "physics/3d/solver/contact_max_separation", PROPERTY_HINT_RANGE, "0,0.1,0.01,or_greater")); + ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/solver/contact_recycle_radius", PropertyInfo(Variant::FLOAT, "physics/3d/solver/contact_recycle_radius", PROPERTY_HINT_RANGE, "0,0.1,0.01,or_greater")); contact_max_separation = GLOBAL_DEF("physics/3d/solver/contact_max_separation", 0.05); ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/solver/contact_max_separation", PropertyInfo(Variant::FLOAT, "physics/3d/solver/contact_max_separation", PROPERTY_HINT_RANGE, "0,0.1,0.01,or_greater")); diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h index b0914e70e4..4399f4ab66 100644 --- a/servers/rendering/dummy/storage/mesh_storage.h +++ b/servers/rendering/dummy/storage/mesh_storage.h @@ -81,6 +81,7 @@ public: s->vertex_count = p_surface.vertex_count; s->index_data = p_surface.index_data; s->index_count = p_surface.index_count; + s->aabb = p_surface.aabb; s->skin_data = p_surface.skin_data; } diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index f76d016ae7..898521ca4d 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -2004,6 +2004,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr RID prev_index_array_rd; RID prev_pipeline_rd; RID prev_xforms_uniform_set; + bool should_request_redraw = false; bool shadow_pass = (p_params->pass_mode == PASS_MODE_SHADOW) || (p_params->pass_mode == PASS_MODE_SHADOW_DP); @@ -2090,6 +2091,11 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr continue; } + //request a redraw if one of the shaders uses TIME + if (shader->uses_time) { + should_request_redraw = true; + } + //find cull variant SceneShaderForwardMobile::ShaderData::CullVariant cull_variant; @@ -2191,6 +2197,11 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instance_count); } + + // Make the actual redraw request + if (should_request_redraw) { + RenderingServerDefault::redraw_request(); + } } /* Geometry instance */ diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index 7fa0bb64a3..854976692e 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -425,7 +425,7 @@ void ParticlesStorage::particles_set_trails(RID p_particles, bool p_enable, doub p_length = MIN(10.0, p_length); particles->trails_enabled = p_enable; - particles->trail_length = p_length; + particles->trail_lifetime = p_length; _particles_free_data(particles); @@ -1351,7 +1351,7 @@ void ParticlesStorage::update_particles() { int history_size = 1; int trail_steps = 1; if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { - history_size = MAX(1, int(particles->trail_length * fixed_fps)); + history_size = MAX(1, int(particles->trail_lifetime * fixed_fps)); trail_steps = particles->trail_bind_poses.size(); } diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h index 017844626f..6478e2b5dc 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h @@ -232,7 +232,7 @@ private: Dependency dependency; - double trail_length = 1.0; + double trail_lifetime = 0.3; bool trails_enabled = false; LocalVector<ParticlesFrameParams> frame_history; LocalVector<ParticlesFrameParams> trail_params; diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index cf30d377b7..0c4d641a6f 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2871,14 +2871,6 @@ void RenderingServer::init() { GLOBAL_DEF("rendering/2d/shadow_atlas/size", 2048); - // Already defined in some RenderingDevice*::initialize, which run before this code. - // We re-define them here just for doctool's sake. Make sure to keep default values in sync. - GLOBAL_DEF("rendering/rendering_device/staging_buffer/block_size_kb", 256); - GLOBAL_DEF("rendering/rendering_device/staging_buffer/max_size_mb", 128); - GLOBAL_DEF("rendering/rendering_device/staging_buffer/texture_upload_region_size_px", 64); - // Vulkan-specific. - GLOBAL_DEF("rendering/rendering_device/vulkan/max_descriptors_per_pool", 64); - // Number of commands that can be drawn per frame. GLOBAL_DEF_RST("rendering/gl_compatibility/item_buffer_size", 16384); ProjectSettings::get_singleton()->set_custom_property_info("rendering/gl_compatibility/item_buffer_size", PropertyInfo(Variant::INT, "rendering/gl_compatibility/item_buffer_size", PROPERTY_HINT_RANGE, "1024,1048576,1")); @@ -2981,7 +2973,6 @@ void RenderingServer::init() { ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/light_projectors/filter", PropertyInfo(Variant::INT, "rendering/textures/light_projectors/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Linear (Fast),Nearest Mipmap (Fast),Linear Mipmap (Fast),Nearest Mipmap Anisotropic (Average),Linear Mipmap Anisotropic (Average)")); GLOBAL_DEF_RST("rendering/occlusion_culling/occlusion_rays_per_thread", 512); - GLOBAL_DEF_RST("rendering/occlusion_culling/bvh_build_quality", 2); ProjectSettings::get_singleton()->set_custom_property_info("rendering/occlusion_culling/bvh_build_quality", PropertyInfo(Variant::INT, "rendering/occlusion_culling/bvh_build_quality", PROPERTY_HINT_ENUM, "Low,Medium,High")); GLOBAL_DEF("rendering/environment/glow/upscale_mode", 1); diff --git a/tests/test_main.cpp b/tests/test_main.cpp index cee110414e..d58c19ac32 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -192,11 +192,8 @@ struct GodotTestCaseListener : public doctest::IReporter { String name = String(p_in.m_name); if (name.find("[SceneTree]") != -1) { - GLOBAL_DEF("memory/limits/multithreaded_server/rid_pool_prealloc", 60); memnew(MessageQueue); - GLOBAL_DEF("internationalization/rendering/force_right_to_left_layout_direction", false); - memnew(Input); Error err = OK; |