diff options
56 files changed, 508 insertions, 329 deletions
diff --git a/SConstruct b/SConstruct index a06dfc1bde..4f411d6d0a 100644 --- a/SConstruct +++ b/SConstruct @@ -375,6 +375,8 @@ for name, path in modules_detected.items(): else: enabled = False + opts.Add(BoolVariable("module_" + name + "_enabled", "Enable module '%s'" % (name,), enabled)) + # Add module-specific options. try: for opt in config.get_opts(selected_platform): @@ -384,7 +386,6 @@ for name, path in modules_detected.items(): sys.path.remove(path) sys.modules.pop("config") - opts.Add(BoolVariable("module_" + name + "_enabled", "Enable module '%s'" % (name,), enabled)) methods.write_modules(modules_detected) diff --git a/core/extension/gdextension.cpp b/core/extension/gdextension.cpp index 28cad12ec9..7e280466a8 100644 --- a/core/extension/gdextension.cpp +++ b/core/extension/gdextension.cpp @@ -683,9 +683,45 @@ GDExtensionInterfaceFunctionPtr GDExtension::get_interface_function(StringName p } Error GDExtension::open_library(const String &p_path, const String &p_entry_symbol) { - Error err = OS::get_singleton()->open_dynamic_library(p_path, library, true, &library_path); + library_path = p_path; + + String abs_path = ProjectSettings::get_singleton()->globalize_path(p_path); +#if defined(WINDOWS_ENABLED) && defined(TOOLS_ENABLED) + // If running on the editor on Windows, we copy the library and open the copy. + // This is so the original file isn't locked and can be updated by a compiler. + if (Engine::get_singleton()->is_editor_hint()) { + if (!FileAccess::exists(abs_path)) { + ERR_PRINT("GDExtension library not found: " + library_path); + return ERR_FILE_NOT_FOUND; + } + + // Copy the file to the same directory as the original with a prefix in the name. + // This is so relative path to dependencies are satisfied. + String copy_path = abs_path.get_base_dir().path_join("~" + abs_path.get_file()); + + // If there's a left-over copy (possibly from a crash) then delete it first. + if (FileAccess::exists(copy_path)) { + DirAccess::remove_absolute(copy_path); + } + + Error copy_err = DirAccess::copy_absolute(abs_path, copy_path); + if (copy_err) { + ERR_PRINT("Error copying GDExtension library: " + library_path); + return ERR_CANT_CREATE; + } + FileAccess::set_hidden_attribute(copy_path, true); + + // Save the copied path so it can be deleted later. + temp_lib_path = copy_path; + + // Use the copy to open the library. + abs_path = copy_path; + } +#endif + + Error err = OS::get_singleton()->open_dynamic_library(abs_path, library, true); if (err != OK) { - ERR_PRINT("GDExtension dynamic library not found: " + p_path); + ERR_PRINT("GDExtension dynamic library not found: " + abs_path); return err; } @@ -694,7 +730,7 @@ Error GDExtension::open_library(const String &p_path, const String &p_entry_symb err = OS::get_singleton()->get_dynamic_library_symbol_handle(library, p_entry_symbol, entry_funcptr, false); if (err != OK) { - ERR_PRINT("GDExtension entry point '" + p_entry_symbol + "' not found in library " + p_path); + ERR_PRINT("GDExtension entry point '" + p_entry_symbol + "' not found in library " + abs_path); OS::get_singleton()->close_dynamic_library(library); return err; } @@ -884,41 +920,7 @@ Error GDExtensionResourceLoader::load_gdextension_resource(const String &p_path, FileAccess::get_modified_time(p_path))); #endif - String abs_path = ProjectSettings::get_singleton()->globalize_path(library_path); -#if defined(WINDOWS_ENABLED) && defined(TOOLS_ENABLED) - // If running on the editor on Windows, we copy the library and open the copy. - // This is so the original file isn't locked and can be updated by a compiler. - if (Engine::get_singleton()->is_editor_hint()) { - if (!FileAccess::exists(abs_path)) { - ERR_PRINT("GDExtension library not found: " + library_path); - return ERR_FILE_NOT_FOUND; - } - - // Copy the file to the same directory as the original with a prefix in the name. - // This is so relative path to dependencies are satisfied. - String copy_path = abs_path.get_base_dir().path_join("~" + abs_path.get_file()); - - // If there's a left-over copy (possibly from a crash) then delete it first. - if (FileAccess::exists(copy_path)) { - DirAccess::remove_absolute(copy_path); - } - - Error copy_err = DirAccess::copy_absolute(abs_path, copy_path); - if (copy_err) { - ERR_PRINT("Error copying GDExtension library: " + library_path); - return ERR_CANT_CREATE; - } - FileAccess::set_hidden_attribute(copy_path, true); - - // Save the copied path so it can be deleted later. - p_extension->set_temp_library_path(copy_path); - - // Use the copy to open the library. - abs_path = copy_path; - } -#endif - - err = p_extension->open_library(abs_path, entry_symbol); + err = p_extension->open_library(library_path, entry_symbol); if (err != OK) { #if defined(WINDOWS_ENABLED) && defined(TOOLS_ENABLED) // If the DLL fails to load, make sure that temporary DLL copies are cleaned up. diff --git a/core/extension/gdextension.h b/core/extension/gdextension.h index 2b42346478..2996100c9a 100644 --- a/core/extension/gdextension.h +++ b/core/extension/gdextension.h @@ -119,7 +119,6 @@ public: void close_library(); #if defined(WINDOWS_ENABLED) && defined(TOOLS_ENABLED) - void set_temp_library_path(const String &p_path) { temp_lib_path = p_path; } String get_temp_library_path() const { return temp_lib_path; } #endif diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 934c75b5d3..366ccca4cb 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -399,15 +399,20 @@ public: return d; } - static _ALWAYS_INLINE_ double lerp_angle(double p_from, double p_to, double p_weight) { + static _ALWAYS_INLINE_ double angle_difference(double p_from, double p_to) { double difference = fmod(p_to - p_from, Math_TAU); - double distance = fmod(2.0 * difference, Math_TAU) - difference; - return p_from + distance * p_weight; + return fmod(2.0 * difference, Math_TAU) - difference; } - static _ALWAYS_INLINE_ float lerp_angle(float p_from, float p_to, float p_weight) { + static _ALWAYS_INLINE_ float angle_difference(float p_from, float p_to) { float difference = fmod(p_to - p_from, (float)Math_TAU); - float distance = fmod(2.0f * difference, (float)Math_TAU) - difference; - return p_from + distance * p_weight; + return fmod(2.0f * difference, (float)Math_TAU) - difference; + } + + static _ALWAYS_INLINE_ double lerp_angle(double p_from, double p_to, double p_weight) { + return p_from + Math::angle_difference(p_from, p_to) * p_weight; + } + static _ALWAYS_INLINE_ float lerp_angle(float p_from, float p_to, float p_weight) { + return p_from + Math::angle_difference(p_from, p_to) * p_weight; } static _ALWAYS_INLINE_ double inverse_lerp(double p_from, double p_to, double p_value) { @@ -438,6 +443,7 @@ public: float s = CLAMP((p_s - p_from) / (p_to - p_from), 0.0f, 1.0f); return s * s * (3.0f - 2.0f * s); } + static _ALWAYS_INLINE_ double move_toward(double p_from, double p_to, double p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SIGN(p_to - p_from) * p_delta; } @@ -445,6 +451,19 @@ public: return abs(p_to - p_from) <= p_delta ? p_to : p_from + SIGN(p_to - p_from) * p_delta; } + static _ALWAYS_INLINE_ double rotate_toward(double p_from, double p_to, double p_delta) { + double difference = Math::angle_difference(p_from, p_to); + double abs_difference = Math::abs(difference); + // When `p_delta < 0` move no further than to PI radians away from `p_to` (as PI is the max possible angle distance). + return p_from + CLAMP(p_delta, abs_difference - Math_PI, abs_difference) * (difference >= 0.0 ? 1.0 : -1.0); + } + static _ALWAYS_INLINE_ float rotate_toward(float p_from, float p_to, float p_delta) { + float difference = Math::angle_difference(p_from, p_to); + float abs_difference = Math::abs(difference); + // When `p_delta < 0` move no further than to PI radians away from `p_to` (as PI is the max possible angle distance). + return p_from + CLAMP(p_delta, abs_difference - (float)Math_PI, abs_difference) * (difference >= 0.0f ? 1.0f : -1.0f); + } + static _ALWAYS_INLINE_ double linear_to_db(double p_linear) { return Math::log(p_linear) * 8.6858896380650365530225783783321; } diff --git a/core/object/object.cpp b/core/object/object.cpp index 0a6cd32f3c..f62b93d0ff 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -617,7 +617,7 @@ void Object::get_method_list(List<MethodInfo> *p_list) const { Variant Object::_call_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { if (p_argcount < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 0; + r_error.expected = 1; return Variant(); } @@ -636,7 +636,7 @@ Variant Object::_call_bind(const Variant **p_args, int p_argcount, Callable::Cal Variant Object::_call_deferred_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { if (p_argcount < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 0; + r_error.expected = 1; return Variant(); } @@ -715,12 +715,11 @@ Variant Object::callp(const StringName &p_method, const Variant **p_args, int p_ //free must be here, before anything, always ready #ifdef DEBUG_ENABLED if (p_argcount != 0) { - r_error.argument = 0; r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; + r_error.expected = 0; return Variant(); } if (Object::cast_to<RefCounted>(this)) { - r_error.argument = 0; r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; ERR_FAIL_V_MSG(Variant(), "Can't 'free' a reference."); } @@ -1036,14 +1035,17 @@ struct _ObjectSignalDisconnectData { }; Error Object::_emit_signal(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + if (unlikely(p_argcount < 1)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.expected = 1; + ERR_FAIL_V(Error::ERR_INVALID_PARAMETER); + } - ERR_FAIL_COND_V(p_argcount < 1, Error::ERR_INVALID_PARAMETER); - if (p_args[0]->get_type() != Variant::STRING_NAME && p_args[0]->get_type() != Variant::STRING) { + if (unlikely(p_args[0]->get_type() != Variant::STRING_NAME && p_args[0]->get_type() != Variant::STRING)) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::STRING_NAME; - ERR_FAIL_COND_V(p_args[0]->get_type() != Variant::STRING_NAME && p_args[0]->get_type() != Variant::STRING, Error::ERR_INVALID_PARAMETER); + ERR_FAIL_V(Error::ERR_INVALID_PARAMETER); } r_error.error = Callable::CallError::CALL_OK; diff --git a/core/os/os.cpp b/core/os/os.cpp index 38ea4a0fdd..991b179e1f 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -355,7 +355,7 @@ void OS::set_cmdline(const char *p_execpath, const List<String> &p_args, const L } String OS::get_unique_id() const { - ERR_FAIL_V(""); + return ""; } int OS::get_processor_count() const { diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h index 9f8fb7e95e..34b54f1d00 100644 --- a/core/variant/binder_common.h +++ b/core/variant/binder_common.h @@ -404,13 +404,13 @@ void call_with_variant_args(T *p_instance, void (T::*p_method)(P...), const Vari #ifdef DEBUG_METHODS_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } if ((size_t)p_argcount < sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -422,7 +422,7 @@ void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const V #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -433,7 +433,7 @@ void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const V #ifdef DEBUG_ENABLED if (missing > dvs) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -455,13 +455,13 @@ void call_with_variant_argsc(T *p_instance, void (T::*p_method)(P...) const, con #ifdef DEBUG_METHODS_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } if ((size_t)p_argcount < sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -473,7 +473,7 @@ void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const, #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -484,7 +484,7 @@ void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const, #ifdef DEBUG_ENABLED if (missing > dvs) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -506,7 +506,7 @@ void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -517,7 +517,7 @@ void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const #ifdef DEBUG_ENABLED if (missing > dvs) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -539,7 +539,7 @@ void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const, #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -550,7 +550,7 @@ void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const, #ifdef DEBUG_ENABLED if (missing > dvs) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -785,13 +785,13 @@ void call_with_variant_args_ret(T *p_instance, R (T::*p_method)(P...), const Var #ifdef DEBUG_METHODS_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } if ((size_t)p_argcount < sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -815,13 +815,13 @@ void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_ar #ifdef DEBUG_METHODS_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } if ((size_t)p_argcount < sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -833,13 +833,13 @@ void call_with_variant_args_static_ret(void (*p_method)(P...), const Variant **p #ifdef DEBUG_METHODS_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } if ((size_t)p_argcount < sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -851,13 +851,13 @@ void call_with_variant_args_retc(T *p_instance, R (T::*p_method)(P...) const, co #ifdef DEBUG_METHODS_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } if ((size_t)p_argcount < sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -882,7 +882,7 @@ void call_with_variant_args_retc_static_helper_dv(T *p_instance, R (*p_method)(T #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -893,7 +893,7 @@ void call_with_variant_args_retc_static_helper_dv(T *p_instance, R (*p_method)(T #ifdef DEBUG_ENABLED if (missing > dvs) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -928,7 +928,7 @@ void call_with_variant_args_static_helper_dv(T *p_instance, void (*p_method)(T * #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -939,7 +939,7 @@ void call_with_variant_args_static_helper_dv(T *p_instance, void (*p_method)(T * #ifdef DEBUG_ENABLED if (missing > dvs) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -961,7 +961,7 @@ void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const Variant **p #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -972,7 +972,7 @@ void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const Variant **p #ifdef DEBUG_ENABLED if (missing > dvs) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -994,7 +994,7 @@ void call_with_variant_args_static_dv(void (*p_method)(P...), const Variant **p_ #ifdef DEBUG_ENABLED if ((size_t)p_argcount > sizeof...(P)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif @@ -1005,7 +1005,7 @@ void call_with_variant_args_static_dv(void (*p_method)(P...), const Variant **p_ #ifdef DEBUG_ENABLED if (missing > dvs) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); + r_error.expected = sizeof...(P); return; } #endif diff --git a/core/variant/callable_bind.cpp b/core/variant/callable_bind.cpp index a5629d5d39..9a6380a55f 100644 --- a/core/variant/callable_bind.cpp +++ b/core/variant/callable_bind.cpp @@ -245,9 +245,8 @@ void CallableCustomUnbind::get_bound_arguments(Vector<Variant> &r_arguments, int } void CallableCustomUnbind::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const { - if (argcount > p_argcount) { + if (p_argcount < argcount) { r_call_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_call_error.argument = 0; r_call_error.expected = argcount; return; } @@ -255,9 +254,8 @@ void CallableCustomUnbind::call(const Variant **p_arguments, int p_argcount, Var } Error CallableCustomUnbind::rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const { - if (argcount > p_argcount) { + if (p_argcount < argcount) { r_call_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_call_error.argument = 0; r_call_error.expected = argcount; return ERR_UNCONFIGURED; } diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index b21e23b3ec..f041d2c95e 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1037,9 +1037,7 @@ struct _VariantCall { static void func_Callable_rpc_id(Variant *v, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { if (p_argcount == 0) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 0; r_error.expected = 1; - } else if (p_args[0]->get_type() != Variant::INT) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 0a63749ac5..d80bc473e5 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -337,6 +337,7 @@ Variant VariantUtilityFunctions::snapped(const Variant &x, const Variant &step, if (x.get_type() != step.get_type() && !((x.get_type() == Variant::INT && step.get_type() == Variant::FLOAT) || (x.get_type() == Variant::FLOAT && step.get_type() == Variant::INT))) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 1; + r_error.expected = x.get_type(); return Variant(); } @@ -384,8 +385,8 @@ Variant VariantUtilityFunctions::lerp(const Variant &from, const Variant &to, do r_error.error = Callable::CallError::CALL_OK; if (from.get_type() != to.get_type()) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.expected = from.get_type(); r_error.argument = 1; + r_error.expected = from.get_type(); return Variant(); } @@ -451,6 +452,10 @@ double VariantUtilityFunctions::bezier_derivative(double p_start, double p_contr return Math::bezier_derivative(p_start, p_control_1, p_control_2, p_end, p_t); } +double VariantUtilityFunctions::angle_difference(double from, double to) { + return Math::angle_difference(from, to); +} + double VariantUtilityFunctions::lerp_angle(double from, double to, double weight) { return Math::lerp_angle(from, to, weight); } @@ -471,6 +476,10 @@ double VariantUtilityFunctions::move_toward(double from, double to, double delta return Math::move_toward(from, to, delta); } +double VariantUtilityFunctions::rotate_toward(double from, double to, double delta) { + return Math::rotate_toward(from, to, delta); +} + double VariantUtilityFunctions::deg_to_rad(double angle_deg) { return Math::deg_to_rad(angle_deg); } @@ -492,7 +501,7 @@ Variant VariantUtilityFunctions::wrap(const Variant &p_x, const Variant &p_min, if (x_type != Variant::INT && x_type != Variant::FLOAT) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; - r_error.expected = x_type; + r_error.expected = Variant::FLOAT; return Variant(); } @@ -558,8 +567,8 @@ Variant VariantUtilityFunctions::max(const Variant **p_args, int p_argcount, Cal Variant::Type arg_type = p_args[i]->get_type(); if (arg_type != Variant::INT && arg_type != Variant::FLOAT) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.expected = Variant::FLOAT; r_error.argument = i; + r_error.expected = Variant::FLOAT; return Variant(); } if (i == 0) { @@ -569,8 +578,8 @@ Variant VariantUtilityFunctions::max(const Variant **p_args, int p_argcount, Cal Variant::evaluate(Variant::OP_LESS, base, *p_args[i], ret, valid); if (!valid) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.expected = base.get_type(); r_error.argument = i; + r_error.expected = base.get_type(); return Variant(); } if (ret.booleanize()) { @@ -602,8 +611,8 @@ Variant VariantUtilityFunctions::min(const Variant **p_args, int p_argcount, Cal Variant::Type arg_type = p_args[i]->get_type(); if (arg_type != Variant::INT && arg_type != Variant::FLOAT) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.expected = Variant::FLOAT; r_error.argument = i; + r_error.expected = Variant::FLOAT; return Variant(); } if (i == 0) { @@ -613,8 +622,8 @@ Variant VariantUtilityFunctions::min(const Variant **p_args, int p_argcount, Cal Variant::evaluate(Variant::OP_GREATER, base, *p_args[i], ret, valid); if (!valid) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.expected = base.get_type(); r_error.argument = i; + r_error.expected = base.get_type(); return Variant(); } if (ret.booleanize()) { @@ -642,8 +651,8 @@ Variant VariantUtilityFunctions::clamp(const Variant &x, const Variant &min, con Variant::evaluate(Variant::OP_LESS, value, min, ret, valid); if (!valid) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.expected = value.get_type(); r_error.argument = 1; + r_error.expected = value.get_type(); return Variant(); } if (ret.booleanize()) { @@ -652,8 +661,8 @@ Variant VariantUtilityFunctions::clamp(const Variant &x, const Variant &min, con Variant::evaluate(Variant::OP_GREATER, value, max, ret, valid); if (!valid) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.expected = value.get_type(); r_error.argument = 2; + r_error.expected = value.get_type(); return Variant(); } if (ret.booleanize()) { @@ -839,7 +848,7 @@ Variant VariantUtilityFunctions::type_convert(const Variant &p_variant, const Va String VariantUtilityFunctions::str(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { if (p_arg_count < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 1; + r_error.expected = 1; return String(); } String s; @@ -983,7 +992,7 @@ void VariantUtilityFunctions::printraw(const Variant **p_args, int p_arg_count, void VariantUtilityFunctions::push_error(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { if (p_arg_count < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 1; + r_error.expected = 1; } String s; for (int i = 0; i < p_arg_count; i++) { @@ -1003,7 +1012,7 @@ void VariantUtilityFunctions::push_error(const Variant **p_args, int p_arg_count void VariantUtilityFunctions::push_warning(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { if (p_arg_count < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 1; + r_error.expected = 1; } String s; for (int i = 0; i < p_arg_count; i++) { @@ -1653,12 +1662,14 @@ void Variant::_register_variant_utility_functions() { FUNCBINDR(cubic_interpolate_angle_in_time, sarray("from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(bezier_interpolate, sarray("start", "control_1", "control_2", "end", "t"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(bezier_derivative, sarray("start", "control_1", "control_2", "end", "t"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(angle_difference, sarray("from", "to"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(lerp_angle, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(inverse_lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(remap, sarray("value", "istart", "istop", "ostart", "ostop"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(smoothstep, sarray("from", "to", "x"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(move_toward, sarray("from", "to", "delta"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(rotate_toward, sarray("from", "to", "delta"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(deg_to_rad, sarray("deg"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(rad_to_deg, sarray("rad"), Variant::UTILITY_FUNC_TYPE_MATH); @@ -1749,14 +1760,12 @@ void Variant::call_utility_function(const StringName &p_name, Variant *r_ret, co if (unlikely(!bfi->is_vararg && p_argcount < bfi->argcount)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 0; r_error.expected = bfi->argcount; return; } if (unlikely(!bfi->is_vararg && p_argcount > bfi->argcount)) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = 0; r_error.expected = bfi->argcount; return; } diff --git a/core/variant/variant_utility.h b/core/variant/variant_utility.h index 66883fb140..8130f30881 100644 --- a/core/variant/variant_utility.h +++ b/core/variant/variant_utility.h @@ -90,11 +90,13 @@ struct VariantUtilityFunctions { double to_t, double pre_t, double post_t); static double bezier_interpolate(double p_start, double p_control_1, double p_control_2, double p_end, double p_t); static double bezier_derivative(double p_start, double p_control_1, double p_control_2, double p_end, double p_t); + static double angle_difference(double from, double to); static double lerp_angle(double from, double to, double weight); static double inverse_lerp(double from, double to, double weight); static double remap(double value, double istart, double istop, double ostart, double ostop); static double smoothstep(double from, double to, double val); static double move_toward(double from, double to, double delta); + static double rotate_toward(double from, double to, double delta); static double deg_to_rad(double angle_deg); static double rad_to_deg(double angle_rad); static double linear_to_db(double linear); diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 4ae3f96287..a077900a9c 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -85,6 +85,14 @@ [/codeblock] </description> </method> + <method name="angle_difference"> + <return type="float" /> + <param index="0" name="from" type="float" /> + <param index="1" name="to" type="float" /> + <description> + Returns the difference between the two angles, in the range of [code][-PI, +PI][/code]. When [param from] and [param to] are opposite, returns [code]-PI[/code] if [param from] is smaller than [param to], or [code]PI[/code] otherwise. + </description> + </method> <method name="asin"> <return type="float" /> <param index="0" name="x" type="float" /> @@ -1110,6 +1118,17 @@ Creates a RID from a [param base]. This is used mainly from native extensions to build servers. </description> </method> + <method name="rotate_toward"> + <return type="float" /> + <param index="0" name="from" type="float" /> + <param index="1" name="to" type="float" /> + <param index="2" name="delta" type="float" /> + <description> + Rotates [param from] toward [param to] by the [param delta] amount. Will not go past [param to]. + Similar to [method move_toward], but interpolates correctly when the angles wrap around [constant @GDScript.TAU]. + If [param delta] is negative, this function will rotate away from [param to], toward the opposite angle, and will not go past the opposite angle. + </description> + </method> <method name="round"> <return type="Variant" /> <param index="0" name="x" type="Variant" /> diff --git a/doc/classes/GraphEdit.xml b/doc/classes/GraphEdit.xml index baa591fd66..46cf05d578 100644 --- a/doc/classes/GraphEdit.xml +++ b/doc/classes/GraphEdit.xml @@ -5,7 +5,7 @@ </brief_description> <description> [GraphEdit] provides tools for creation, manipulation, and display of various graphs. Its main purpose in the engine is to power the visual programming systems, such as visual shaders, but it is also available for use in user projects. - [GraphEdit] by itself is only an empty container, representing an infinite grid where [GraphNode]s can be placed. Each [GraphNode] represents a node in the graph, a single unit of data in the connected scheme. [GraphEdit], in turn, helps to control various interactions with nodes and between nodes. When the user attempts to connect, disconnect, or close a [GraphNode], a signal is emitted in the [GraphEdit], but no action is taken by default. It is the responsibility of the programmer utilizing this control to implement the necessary logic to determine how each request should be handled. + [GraphEdit] by itself is only an empty container, representing an infinite grid where [GraphNode]s can be placed. Each [GraphNode] represents a node in the graph, a single unit of data in the connected scheme. [GraphEdit], in turn, helps to control various interactions with nodes and between nodes. When the user attempts to connect, disconnect, or delete a [GraphNode], a signal is emitted in the [GraphEdit], but no action is taken by default. It is the responsibility of the programmer utilizing this control to implement the necessary logic to determine how each request should be handled. [b]Performance:[/b] It is greatly advised to enable low-processor usage mode (see [member OS.low_processor_usage_mode]) when using GraphEdits. </description> <tutorials> @@ -289,12 +289,6 @@ Emitted at the beginning of a GraphNode movement. </description> </signal> - <signal name="close_nodes_request"> - <param index="0" name="nodes" type="StringName[]" /> - <description> - Emitted when attempting to remove a GraphNode from the GraphEdit. Provides a list of node names to be removed (all selected nodes, excluding nodes without closing button). - </description> - </signal> <signal name="connection_drag_ended"> <description> Emitted at the end of a connection drag. @@ -338,6 +332,12 @@ Emitted when the user presses [kbd]Ctrl + C[/kbd]. </description> </signal> + <signal name="delete_nodes_request"> + <param index="0" name="nodes" type="StringName[]" /> + <description> + Emitted when attempting to remove a GraphNode from the GraphEdit. Provides a list of node names to be removed (all selected nodes, excluding nodes without closing button). + </description> + </signal> <signal name="disconnection_request"> <param index="0" name="from_node" type="StringName" /> <param index="1" name="from_port" type="int" /> diff --git a/doc/classes/GraphElement.xml b/doc/classes/GraphElement.xml index 589b553cb6..dd2c7f3d3e 100644 --- a/doc/classes/GraphElement.xml +++ b/doc/classes/GraphElement.xml @@ -27,9 +27,9 @@ </member> </members> <signals> - <signal name="close_request"> + <signal name="delete_request"> <description> - Emitted when closing the GraphElement is requested. + Emitted when removing the GraphElement is requested. </description> </signal> <signal name="dragged"> diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index 2efe47a012..7cfbca1178 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -449,7 +449,7 @@ <description> Returns a string that is unique to the device. [b]Note:[/b] This string may change without notice if the user reinstalls/upgrades their operating system or changes their hardware. This means it should generally not be used to encrypt persistent data as the data saved before an unexpected ID change would become inaccessible. The returned string may also be falsified using external programs, so do not rely on the string returned by [method get_unique_id] for security purposes. - [b]Note:[/b] Returns an empty string on Web, as this method isn't implemented on this platform yet. + [b]Note:[/b] Returns an empty string and prints an error on Web, as this method cannot be implemented on this platform. </description> </method> <method name="get_user_data_dir" qualifiers="const"> diff --git a/editor/editor_undo_redo_manager.cpp b/editor/editor_undo_redo_manager.cpp index 2b059352a7..5b064c9ae3 100644 --- a/editor/editor_undo_redo_manager.cpp +++ b/editor/editor_undo_redo_manager.cpp @@ -156,7 +156,7 @@ void EditorUndoRedoManager::add_undo_methodp(Object *p_object, const StringName void EditorUndoRedoManager::_add_do_method(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { if (p_argcount < 2) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 0; + r_error.expected = 2; return; } @@ -185,7 +185,7 @@ void EditorUndoRedoManager::_add_do_method(const Variant **p_args, int p_argcoun void EditorUndoRedoManager::_add_undo_method(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { if (p_argcount < 2) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 0; + r_error.expected = 2; return; } diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index b80d3c1869..36f712dde8 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -1789,11 +1789,13 @@ void FileSystemDock::_rename_operation_confirm() { EditorSceneTabs::get_singleton()->set_current_tab(current_tab); + if (tree->has_focus()) { + current_path = new_path; + current_path_line_edit->set_text(current_path); + } + print_verbose("FileSystem: calling rescan."); _rescan(); - - current_path = new_path; - current_path_line_edit->set_text(current_path); } void FileSystemDock::_duplicate_operation_confirm() { diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp index 2ef5e89bf7..87b855052b 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/scene_import_settings.cpp @@ -550,7 +550,7 @@ void SceneImportSettings::_update_camera() { camera->set_orthogonal(camera_size * zoom, 0.0001, camera_size * 2); Transform3D xf; - xf.basis = Basis(Vector3(1, 0, 0), rot_x) * Basis(Vector3(0, 1, 0), rot_y); + xf.basis = Basis(Vector3(0, 1, 0), rot_y) * Basis(Vector3(1, 0, 0), rot_x); xf.origin = center; xf.translate_local(0, 0, camera_size); diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index dc3729393f..deb54176bb 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -170,7 +170,7 @@ void AnimationNodeBlendTreeEditor::update_graph() { name->connect("text_changed", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_rename_lineedit_changed), CONNECT_DEFERRED); base = 1; agnode->set_closable(true); - node->connect("close_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_close_request).bind(E), CONNECT_DEFERRED); + node->connect("delete_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_delete_node_request).bind(E), CONNECT_DEFERRED); } for (int i = 0; i < agnode->get_input_count(); i++) { @@ -494,7 +494,7 @@ void AnimationNodeBlendTreeEditor::_anim_selected(int p_index, Array p_options, undo_redo->commit_action(); } -void AnimationNodeBlendTreeEditor::_close_request(const String &p_which) { +void AnimationNodeBlendTreeEditor::_delete_node_request(const String &p_which) { if (read_only) { return; } @@ -518,7 +518,7 @@ void AnimationNodeBlendTreeEditor::_close_request(const String &p_which) { undo_redo->commit_action(); } -void AnimationNodeBlendTreeEditor::_close_nodes_request(const TypedArray<StringName> &p_nodes) { +void AnimationNodeBlendTreeEditor::_delete_nodes_request(const TypedArray<StringName> &p_nodes) { if (read_only) { return; } @@ -552,7 +552,7 @@ void AnimationNodeBlendTreeEditor::_close_nodes_request(const TypedArray<StringN undo_redo->create_action(TTR("Delete Node(s)")); for (const StringName &F : to_erase) { - _close_request(F); + _delete_node_request(F); } undo_redo->commit_action(); @@ -1057,7 +1057,7 @@ AnimationNodeBlendTreeEditor::AnimationNodeBlendTreeEditor() { graph->connect("disconnection_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_disconnection_request), CONNECT_DEFERRED); graph->connect("node_selected", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_selected)); graph->connect("scroll_offset_changed", callable_mp(this, &AnimationNodeBlendTreeEditor::_scroll_changed)); - graph->connect("close_nodes_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_close_nodes_request)); + graph->connect("delete_nodes_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_delete_nodes_request)); graph->connect("popup_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_popup_request)); graph->connect("connection_to_empty", callable_mp(this, &AnimationNodeBlendTreeEditor::_connection_to_empty)); graph->connect("connection_from_empty", callable_mp(this, &AnimationNodeBlendTreeEditor::_connection_from_empty)); diff --git a/editor/plugins/animation_blend_tree_editor_plugin.h b/editor/plugins/animation_blend_tree_editor_plugin.h index 12b709515f..1f7a33e02a 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.h +++ b/editor/plugins/animation_blend_tree_editor_plugin.h @@ -109,8 +109,8 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin { void _node_selected(Object *p_node); void _open_in_editor(const String &p_which); void _anim_selected(int p_index, Array p_options, const String &p_node); - void _close_request(const String &p_which); - void _close_nodes_request(const TypedArray<StringName> &p_nodes); + void _delete_node_request(const String &p_which); + void _delete_nodes_request(const TypedArray<StringName> &p_nodes); bool _update_filters(const Ref<AnimationNode> &anode); void _inspect_filters(const String &p_which); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index f2225fabad..7b48e6fbe9 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -2203,9 +2203,6 @@ AnimationPlayerEditorPlugin::~AnimationPlayerEditorPlugin() { if (dummy_player) { memdelete(dummy_player); } - if (player) { - memdelete(player); - } } // AnimationTrackKeyEditEditorPlugin diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 8b1053b79b..c706869823 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -453,7 +453,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool // All nodes are closable except the output node. if (p_id >= 2) { vsnode->set_closable(true); - node->connect("close_request", callable_mp(editor, &VisualShaderEditor::_close_node_request).bind(p_type, p_id), CONNECT_DEFERRED); + node->connect("delete_request", callable_mp(editor, &VisualShaderEditor::_delete_node_request).bind(p_type, p_id), CONNECT_DEFERRED); } graph->add_child(node); node->set_theme(vstheme); @@ -3852,7 +3852,7 @@ void VisualShaderEditor::_convert_constants_to_parameters(bool p_vice_versa) { undo_redo->commit_action(); } -void VisualShaderEditor::_close_node_request(int p_type, int p_node) { +void VisualShaderEditor::_delete_node_request(int p_type, int p_node) { Ref<VisualShaderNode> node = visual_shader->get_node((VisualShader::Type)p_type, p_node); if (!node->is_closable()) { return; @@ -3867,7 +3867,7 @@ void VisualShaderEditor::_close_node_request(int p_type, int p_node) { undo_redo->commit_action(); } -void VisualShaderEditor::_close_nodes_request(const TypedArray<StringName> &p_nodes) { +void VisualShaderEditor::_delete_nodes_request(const TypedArray<StringName> &p_nodes) { List<int> to_erase; if (p_nodes.is_empty()) { @@ -4898,7 +4898,7 @@ void VisualShaderEditor::_node_menu_id_pressed(int p_idx) { _paste_nodes(true, menu_point); break; case NodeMenuOptions::DELETE: - _close_nodes_request(TypedArray<StringName>()); + _delete_nodes_request(TypedArray<StringName>()); break; case NodeMenuOptions::DUPLICATE: _duplicate_nodes(); @@ -5198,7 +5198,7 @@ VisualShaderEditor::VisualShaderEditor() { graph->connect("duplicate_nodes_request", callable_mp(this, &VisualShaderEditor::_duplicate_nodes)); graph->connect("copy_nodes_request", callable_mp(this, &VisualShaderEditor::_copy_nodes).bind(false)); graph->connect("paste_nodes_request", callable_mp(this, &VisualShaderEditor::_paste_nodes).bind(false, Point2())); - graph->connect("close_nodes_request", callable_mp(this, &VisualShaderEditor::_close_nodes_request)); + graph->connect("delete_nodes_request", callable_mp(this, &VisualShaderEditor::_delete_nodes_request)); graph->connect("gui_input", callable_mp(this, &VisualShaderEditor::_graph_gui_input)); graph->connect("connection_to_empty", callable_mp(this, &VisualShaderEditor::_connection_to_empty)); graph->connect("connection_from_empty", callable_mp(this, &VisualShaderEditor::_connection_from_empty)); diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index 8629e64467..07a73b4e51 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -380,8 +380,8 @@ class VisualShaderEditor : public VBoxContainer { void _node_selected(Object *p_node); void _delete_nodes(int p_type, const List<int> &p_nodes); - void _close_node_request(int p_type, int p_node); - void _close_nodes_request(const TypedArray<StringName> &p_nodes); + void _delete_node_request(int p_type, int p_node); + void _delete_nodes_request(const TypedArray<StringName> &p_nodes); void _node_changed(int p_id); diff --git a/misc/extension_api_validation/4.1-stable.expected b/misc/extension_api_validation/4.1-stable.expected index 0aea0612ab..6720ee6b47 100644 --- a/misc/extension_api_validation/4.1-stable.expected +++ b/misc/extension_api_validation/4.1-stable.expected @@ -118,7 +118,6 @@ Excluded unexposed classes from extension_api.json. GH-79311 -------- -Validate extension JSON: API was removed: classes/GraphEdit/signals/delete_nodes_request Validate extension JSON: API was removed: classes/GraphNode/methods/get_connection_input_color Validate extension JSON: API was removed: classes/GraphNode/methods/get_connection_input_count Validate extension JSON: API was removed: classes/GraphNode/methods/get_connection_input_height diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index 3e13d1525d..372c212d2b 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -140,7 +140,7 @@ Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_ar if (p_argcount == 0) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 1; + r_error.expected = 1; return Variant(); } else if (p_argcount == 1) { //noooneee diff --git a/modules/gdscript/gdscript_utility_functions.cpp b/modules/gdscript/gdscript_utility_functions.cpp index d85b12b7fe..69a0b42d89 100644 --- a/modules/gdscript/gdscript_utility_functions.cpp +++ b/modules/gdscript/gdscript_utility_functions.cpp @@ -45,14 +45,12 @@ #define VALIDATE_ARG_COUNT(m_count) \ if (p_arg_count < m_count) { \ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; \ - r_error.argument = m_count; \ r_error.expected = m_count; \ *r_ret = Variant(); \ return; \ } \ if (p_arg_count > m_count) { \ r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; \ - r_error.argument = m_count; \ r_error.expected = m_count; \ *r_ret = Variant(); \ return; \ @@ -119,7 +117,6 @@ struct GDScriptUtilityFunctionsDefinitions { switch (p_arg_count) { case 0: { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 1; r_error.expected = 1; *r_ret = Variant(); } break; @@ -223,7 +220,6 @@ struct GDScriptUtilityFunctionsDefinitions { } break; default: { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = 3; r_error.expected = 3; *r_ret = Variant(); @@ -251,6 +247,7 @@ struct GDScriptUtilityFunctionsDefinitions { } else if (p_args[0]->get_type() != Variant::OBJECT) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; + r_error.expected = Variant::OBJECT; *r_ret = Variant(); } else { Object *obj = *p_args[0]; @@ -390,13 +387,13 @@ struct GDScriptUtilityFunctionsDefinitions { static inline void Color8(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { if (p_arg_count < 3) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 3; + r_error.expected = 3; *r_ret = Variant(); return; } if (p_arg_count > 4) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = 4; + r_error.expected = 4; *r_ret = Variant(); return; } diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index be18dee2cf..5ecae08f6c 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -519,7 +519,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a if (p_argcount > _argument_count) { r_err.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; r_err.expected = _argument_count; - call_depth--; return _get_default_variant_for_data_type(return_type); } else if (p_argcount < _argument_count - _default_arg_count) { diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp index 3787d0fe5e..cb45a6589e 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.cpp +++ b/modules/gltf/editor/editor_scene_importer_blend.cpp @@ -49,6 +49,67 @@ #include <shlwapi.h> #endif +static bool _get_blender_version(const String &p_path, int &r_major, int &r_minor, String *r_err = nullptr) { + String path = p_path; +#ifdef WINDOWS_ENABLED + path = path.path_join("blender.exe"); +#else + path = path.path_join("blender"); +#endif + +#if defined(MACOS_ENABLED) + if (!FileAccess::exists(path)) { + path = p_path.path_join("Blender"); + } +#endif + + if (!FileAccess::exists(path)) { + if (r_err) { + *r_err = TTR("Path does not contain a Blender installation."); + } + return false; + } + List<String> args; + args.push_back("--version"); + String pipe; + Error err = OS::get_singleton()->execute(path, args, &pipe); + if (err != OK) { + if (r_err) { + *r_err = TTR("Can't execute Blender binary."); + } + return false; + } + int bl = pipe.find("Blender "); + if (bl == -1) { + if (r_err) { + *r_err = vformat(TTR("Unexpected --version output from Blender binary at: %s."), path); + } + return false; + } + pipe = pipe.substr(bl); + pipe = pipe.replace_first("Blender ", ""); + int pp = pipe.find("."); + if (pp == -1) { + if (r_err) { + *r_err = TTR("Path supplied lacks a Blender binary."); + } + return false; + } + String v = pipe.substr(0, pp); + r_major = v.to_int(); + if (r_major < 3) { + if (r_err) { + *r_err = TTR("This Blender installation is too old for this importer (not 3.0+)."); + } + return false; + } + + int pp2 = pipe.find(".", pp + 1); + r_minor = pp2 > pp ? pipe.substr(pp + 1, pp2 - pp - 1).to_int() : 0; + + return true; +} + uint32_t EditorSceneFormatImporterBlend::get_import_flags() const { return ImportFlags::IMPORT_SCENE | ImportFlags::IMPORT_ANIMATION; } @@ -60,8 +121,13 @@ void EditorSceneFormatImporterBlend::get_extensions(List<String> *r_extensions) Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, List<String> *r_missing_deps, Error *r_err) { - // Get global paths for source and sink. + String blender_path = EDITOR_GET("filesystem/import/blender/blender3_path"); + if (blender_major_version == -1 || blender_minor_version == -1) { + _get_blender_version(blender_path, blender_major_version, blender_minor_version, nullptr); + } + + // Get global paths for source and sink. // Escape paths to be valid Python strings to embed in the script. const String source_global = ProjectSettings::get_singleton()->globalize_path(p_path).c_escape(); const String sink = ProjectSettings::get_singleton()->get_imported_files_path().path_join( @@ -153,9 +219,17 @@ Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_ parameters_map["export_tangents"] = false; } if (p_options.has(SNAME("blender/animation/group_tracks")) && p_options[SNAME("blender/animation/group_tracks")]) { - parameters_map["export_nla_strips"] = true; + if (blender_major_version > 3 || (blender_major_version == 3 && blender_minor_version >= 6)) { + parameters_map["export_animation_mode"] = "ACTIONS"; + } else { + parameters_map["export_nla_strips"] = true; + } } else { - parameters_map["export_nla_strips"] = false; + if (blender_major_version > 3 || (blender_major_version == 3 && blender_minor_version >= 6)) { + parameters_map["export_animation_mode"] = "ACTIVE_ACTIONS"; + } else { + parameters_map["export_nla_strips"] = false; + } } if (p_options.has(SNAME("blender/animation/limit_playback")) && p_options[SNAME("blender/animation/limit_playback")]) { parameters_map["export_frame_range"] = true; @@ -269,67 +343,8 @@ void EditorSceneFormatImporterBlend::get_import_options(const String &p_path, Li /////////////////////////// static bool _test_blender_path(const String &p_path, String *r_err = nullptr) { - String path = p_path; -#ifdef WINDOWS_ENABLED - path = path.path_join("blender.exe"); -#else - path = path.path_join("blender"); -#endif - -#if defined(MACOS_ENABLED) - if (!FileAccess::exists(path)) { - path = path.path_join("Blender"); - } -#endif - - if (!FileAccess::exists(path)) { - if (r_err) { - *r_err = TTR("Path does not contain a Blender installation."); - } - return false; - } - List<String> args; - args.push_back("--version"); - String pipe; - Error err = OS::get_singleton()->execute(path, args, &pipe); - if (err != OK) { - if (r_err) { - *r_err = TTR("Can't execute Blender binary."); - } - return false; - } - int bl = pipe.find("Blender "); - if (bl == -1) { - if (r_err) { - *r_err = vformat(TTR("Unexpected --version output from Blender binary at: %s"), path); - } - return false; - } - pipe = pipe.substr(bl); - pipe = pipe.replace_first("Blender ", ""); - int pp = pipe.find("."); - if (pp == -1) { - if (r_err) { - *r_err = TTR("Path supplied lacks a Blender binary."); - } - return false; - } - String v = pipe.substr(0, pp); - int version = v.to_int(); - if (version < 3) { - if (r_err) { - *r_err = TTR("This Blender installation is too old for this importer (not 3.0+)."); - } - return false; - } - if (version > 3) { - if (r_err) { - *r_err = TTR("This Blender installation is too new for this importer (not 3.x)."); - } - return false; - } - - return true; + int major, minor; + return _get_blender_version(p_path, major, minor, r_err); } bool EditorFileSystemImportFormatSupportQueryBlend::is_active() const { diff --git a/modules/gltf/editor/editor_scene_importer_blend.h b/modules/gltf/editor/editor_scene_importer_blend.h index c77a23f9f6..ec467db457 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.h +++ b/modules/gltf/editor/editor_scene_importer_blend.h @@ -43,6 +43,9 @@ class ConfirmationDialog; class EditorSceneFormatImporterBlend : public EditorSceneFormatImporter { GDCLASS(EditorSceneFormatImporterBlend, EditorSceneFormatImporter); + int blender_major_version = -1; + int blender_minor_version = -1; + public: enum { BLEND_VISIBLE_ALL, diff --git a/modules/minimp3/SCsub b/modules/minimp3/SCsub index 20e3165f38..09e84f71e9 100644 --- a/modules/minimp3/SCsub +++ b/modules/minimp3/SCsub @@ -13,5 +13,8 @@ if not env.msvc: else: env_minimp3.Prepend(CPPPATH=[thirdparty_dir]) +if not env["minimp3_extra_formats"]: + env_minimp3.Append(CPPDEFINES=["MINIMP3_ONLY_MP3"]) + # Godot source files env_minimp3.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/minimp3/audio_stream_mp3.cpp b/modules/minimp3/audio_stream_mp3.cpp index 6af86a96dc..4efa4d329e 100644 --- a/modules/minimp3/audio_stream_mp3.cpp +++ b/modules/minimp3/audio_stream_mp3.cpp @@ -28,7 +28,6 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#define MINIMP3_ONLY_MP3 #define MINIMP3_FLOAT_OUTPUT #define MINIMP3_IMPLEMENTATION #define MINIMP3_NO_STDIO diff --git a/modules/minimp3/config.py b/modules/minimp3/config.py index e6bdcb2a83..115b376fc8 100644 --- a/modules/minimp3/config.py +++ b/modules/minimp3/config.py @@ -2,6 +2,14 @@ def can_build(env, platform): return True +def get_opts(platform): + from SCons.Variables import BoolVariable + + return [ + BoolVariable("minimp3_extra_formats", "Build minimp3 with MP1/MP2 decoding support", False), + ] + + def configure(env): pass diff --git a/modules/minimp3/resource_importer_mp3.cpp b/modules/minimp3/resource_importer_mp3.cpp index 4e56120ec6..d60b979c3f 100644 --- a/modules/minimp3/resource_importer_mp3.cpp +++ b/modules/minimp3/resource_importer_mp3.cpp @@ -47,6 +47,10 @@ String ResourceImporterMP3::get_visible_name() const { } void ResourceImporterMP3::get_recognized_extensions(List<String> *p_extensions) const { +#ifndef MINIMP3_ONLY_MP3 + p_extensions->push_back("mp1"); + p_extensions->push_back("mp2"); +#endif p_extensions->push_back("mp3"); } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs index 81b2ffef34..09269508b7 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs @@ -134,6 +134,38 @@ namespace Godot } /// <summary> + /// Returns the difference between the two angles, + /// in range of -<see cref="Pi"/>, <see cref="Pi"/>. + /// When <paramref name="from"/> and <paramref name="to"/> are opposite, + /// returns -<see cref="Pi"/> if <paramref name="from"/> is smaller than <paramref name="to"/>, + /// or <see cref="Pi"/> otherwise. + /// </summary> + /// <param name="from">The start angle.</param> + /// <param name="to">The destination angle.</param> + /// <returns>The difference between the two angles.</returns> + public static float AngleDifference(float from, float to) + { + float difference = (to - from) % MathF.Tau; + return ((2.0f * difference) % MathF.Tau) - difference; + } + + /// <summary> + /// Returns the difference between the two angles, + /// in range of -<see cref="Pi"/>, <see cref="Pi"/>. + /// When <paramref name="from"/> and <paramref name="to"/> are opposite, + /// returns -<see cref="Pi"/> if <paramref name="from"/> is smaller than <paramref name="to"/>, + /// or <see cref="Pi"/> otherwise. + /// </summary> + /// <param name="from">The start angle.</param> + /// <param name="to">The destination angle.</param> + /// <returns>The difference between the two angles.</returns> + public static double AngleDifference(double from, double to) + { + double difference = (to - from) % Math.Tau; + return ((2.0 * difference) % Math.Tau) - difference; + } + + /// <summary> /// Returns the arc sine of <paramref name="s"/> in radians. /// Use to get the angle of sine <paramref name="s"/>. /// </summary> @@ -1093,9 +1125,7 @@ namespace Godot /// <returns>The resulting angle of the interpolation.</returns> public static float LerpAngle(float from, float to, float weight) { - float difference = (to - from) % MathF.Tau; - float distance = ((2 * difference) % MathF.Tau) - difference; - return from + (distance * weight); + return from + AngleDifference(from, to) * weight; } /// <summary> @@ -1110,9 +1140,7 @@ namespace Godot /// <returns>The resulting angle of the interpolation.</returns> public static double LerpAngle(double from, double to, double weight) { - double difference = (to - from) % Math.Tau; - double distance = ((2 * difference) % Math.Tau) - difference; - return from + (distance * weight); + return from + AngleDifference(from, to) * weight; } /// <summary> @@ -1429,6 +1457,38 @@ namespace Godot } /// <summary> + /// Rotates <paramref name="from"/> toward <paramref name="to"/> by the <paramref name="delta"/> amount. Will not go past <paramref name="to"/>. + /// Similar to <see cref="MoveToward(float, float, float)"/> but interpolates correctly when the angles wrap around <see cref="Tau"/>. + /// If <paramref name="delta"/> is negative, this function will rotate away from <paramref name="to"/>, toward the opposite angle, and will not go past the opposite angle. + /// </summary> + /// <param name="from">The start angle.</param> + /// <param name="to">The angle to move towards.</param> + /// <param name="delta">The amount to move by.</param> + /// <returns>The angle after moving.</returns> + public static float RotateToward(float from, float to, float delta) + { + float difference = AngleDifference(from, to); + float absDifference = Math.Abs(difference); + return from + Math.Clamp(delta, absDifference - MathF.PI, absDifference) * (difference >= 0.0f ? 1.0f : -1.0f); + } + + /// <summary> + /// Rotates <paramref name="from"/> toward <paramref name="to"/> by the <paramref name="delta"/> amount. Will not go past <paramref name="to"/>. + /// Similar to <see cref="MoveToward(double, double, double)"/> but interpolates correctly when the angles wrap around <see cref="Tau"/>. + /// If <paramref name="delta"/> is negative, this function will rotate away from <paramref name="to"/>, toward the opposite angle, and will not go past the opposite angle. + /// </summary> + /// <param name="from">The start angle.</param> + /// <param name="to">The angle to move towards.</param> + /// <param name="delta">The amount to move by.</param> + /// <returns>The angle after moving.</returns> + public static double RotateToward(double from, double to, double delta) + { + double difference = AngleDifference(from, to); + double absDifference = Math.Abs(difference); + return from + Math.Clamp(delta, absDifference - Math.PI, absDifference) * (difference >= 0.0 ? 1.0 : -1.0); + } + + /// <summary> /// Rounds <paramref name="s"/> to the nearest whole number, /// with halfway cases rounded towards the nearest multiple of two. /// </summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/ExceptionUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/ExceptionUtils.cs index a656c5de90..dc53e48bd0 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/ExceptionUtils.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/ExceptionUtils.cs @@ -206,7 +206,7 @@ namespace Godot.NativeInterop } case godot_variant_call_error_error.GODOT_CALL_ERROR_CALL_ERROR_TOO_MANY_ARGUMENTS: case godot_variant_call_error_error.GODOT_CALL_ERROR_CALL_ERROR_TOO_FEW_ARGUMENTS: - return $"Invalid call to {where}. Expected {error.Argument} arguments."; + return $"Invalid call to {where}. Expected {error.Expected} arguments."; case godot_variant_call_error_error.GODOT_CALL_ERROR_CALL_ERROR_INVALID_METHOD: return $"Invalid call. Nonexistent {where}."; case godot_variant_call_error_error.GODOT_CALL_ERROR_CALL_ERROR_INSTANCE_IS_NULL: diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp index edc934e927..d6455cbf1c 100644 --- a/platform/android/java_class_wrapper.cpp +++ b/platform/android/java_class_wrapper.cpp @@ -50,14 +50,14 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method, } int pc = E.param_types.size(); - if (pc > p_argcount) { + if (p_argcount < pc) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = pc; + r_error.expected = pc; continue; } - if (pc < p_argcount) { + if (p_argcount > pc) { r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = pc; + r_error.expected = pc; continue; } uint32_t *ptypes = E.param_types.ptrw(); diff --git a/platform/web/api/api.cpp b/platform/web/api/api.cpp index ab7154b0fb..a695091a04 100644 --- a/platform/web/api/api.cpp +++ b/platform/web/api/api.cpp @@ -96,7 +96,7 @@ Ref<JavaScriptObject> JavaScriptBridge::create_callback(const Callable &p_callab Variant JavaScriptBridge::_create_object_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { if (p_argcount < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 0; + r_error.expected = 1; return Ref<JavaScriptObject>(); } if (p_args[0]->get_type() != Variant::STRING) { diff --git a/platform/web/audio_driver_web.h b/platform/web/audio_driver_web.h index 7bfed834e1..12a61746c3 100644 --- a/platform/web/audio_driver_web.h +++ b/platform/web/audio_driver_web.h @@ -32,6 +32,7 @@ #define AUDIO_DRIVER_WEB_H #include "godot_audio.h" +#include "godot_js.h" #include "core/os/mutex.h" #include "core/os/thread.h" @@ -55,8 +56,8 @@ private: int mix_rate = 0; int channel_count = 0; - static void _state_change_callback(int p_state); - static void _latency_update_callback(float p_latency); + WASM_EXPORT static void _state_change_callback(int p_state); + WASM_EXPORT static void _latency_update_callback(float p_latency); static AudioDriverWeb *singleton; diff --git a/platform/web/display_server_web.h b/platform/web/display_server_web.h index a4fd75f33b..1653deff80 100644 --- a/platform/web/display_server_web.h +++ b/platform/web/display_server_web.h @@ -33,6 +33,8 @@ #include "servers/display_server.h" +#include "godot_js.h" + #include <emscripten.h> #include <emscripten/html5.h> @@ -88,28 +90,28 @@ private: static const char *godot2dom_cursor(DisplayServer::CursorShape p_shape); // events - static void fullscreen_change_callback(int p_fullscreen); - static int mouse_button_callback(int p_pressed, int p_button, double p_x, double p_y, int p_modifiers); - static void mouse_move_callback(double p_x, double p_y, double p_rel_x, double p_rel_y, int p_modifiers); - static int mouse_wheel_callback(double p_delta_x, double p_delta_y); - static void touch_callback(int p_type, int p_count); - static void key_callback(int p_pressed, int p_repeat, int p_modifiers); - static void vk_input_text_callback(const char *p_text, int p_cursor); - static void gamepad_callback(int p_index, int p_connected, const char *p_id, const char *p_guid); + WASM_EXPORT static void fullscreen_change_callback(int p_fullscreen); + WASM_EXPORT static int mouse_button_callback(int p_pressed, int p_button, double p_x, double p_y, int p_modifiers); + WASM_EXPORT static void mouse_move_callback(double p_x, double p_y, double p_rel_x, double p_rel_y, int p_modifiers); + WASM_EXPORT static int mouse_wheel_callback(double p_delta_x, double p_delta_y); + WASM_EXPORT static void touch_callback(int p_type, int p_count); + WASM_EXPORT static void key_callback(int p_pressed, int p_repeat, int p_modifiers); + WASM_EXPORT static void vk_input_text_callback(const char *p_text, int p_cursor); + WASM_EXPORT static void gamepad_callback(int p_index, int p_connected, const char *p_id, const char *p_guid); void process_joypads(); - static void _js_utterance_callback(int p_event, int p_id, int p_pos); + WASM_EXPORT static void _js_utterance_callback(int p_event, int p_id, int p_pos); static Vector<String> get_rendering_drivers_func(); static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_window_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error); static void _dispatch_input_event(const Ref<InputEvent> &p_event); - static void request_quit_callback(); - static void window_blur_callback(); - static void update_voices_callback(int p_size, const char **p_voice); - static void update_clipboard_callback(const char *p_text); - static void send_window_event_callback(int p_notification); - static void drop_files_js_callback(char **p_filev, int p_filec); + WASM_EXPORT static void request_quit_callback(); + WASM_EXPORT static void window_blur_callback(); + WASM_EXPORT static void update_voices_callback(int p_size, const char **p_voice); + WASM_EXPORT static void update_clipboard_callback(const char *p_text); + WASM_EXPORT static void send_window_event_callback(int p_notification); + WASM_EXPORT static void drop_files_js_callback(char **p_filev, int p_filec); protected: int get_current_video_driver() const; diff --git a/platform/web/godot_js.h b/platform/web/godot_js.h index 3341cf8a67..f172148bf9 100644 --- a/platform/web/godot_js.h +++ b/platform/web/godot_js.h @@ -31,6 +31,8 @@ #ifndef GODOT_JS_H #define GODOT_JS_H +#define WASM_EXPORT __attribute__((visibility("default"))) + #ifdef __cplusplus extern "C" { #endif diff --git a/platform/web/javascript_bridge_singleton.cpp b/platform/web/javascript_bridge_singleton.cpp index 45bce1b480..41206f14a5 100644 --- a/platform/web/javascript_bridge_singleton.cpp +++ b/platform/web/javascript_bridge_singleton.cpp @@ -68,11 +68,11 @@ private: int _js_id = 0; Callable _callable; - static int _variant2js(const void **p_args, int p_pos, godot_js_wrapper_ex *r_val, void **p_lock); - static void _free_lock(void **p_lock, int p_type); - static Variant _js2variant(int p_type, godot_js_wrapper_ex *p_val); - static void *_alloc_variants(int p_size); - static void _callback(void *p_ref, int p_arg_id, int p_argc); + WASM_EXPORT static int _variant2js(const void **p_args, int p_pos, godot_js_wrapper_ex *r_val, void **p_lock); + WASM_EXPORT static void _free_lock(void **p_lock, int p_type); + WASM_EXPORT static Variant _js2variant(int p_type, godot_js_wrapper_ex *p_val); + WASM_EXPORT static void *_alloc_variants(int p_size); + WASM_EXPORT static void _callback(void *p_ref, int p_arg_id, int p_argc); protected: bool _set(const StringName &p_name, const Variant &p_value) override; @@ -289,7 +289,7 @@ Ref<JavaScriptObject> JavaScriptBridge::get_interface(const String &p_interface) Variant JavaScriptBridge::_create_object_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { if (p_argcount < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 0; + r_error.expected = 1; return Ref<JavaScriptObject>(); } if (p_args[0]->get_type() != Variant::STRING) { diff --git a/platform/web/os_web.cpp b/platform/web/os_web.cpp index f038f0248a..186e4abf92 100644 --- a/platform/web/os_web.cpp +++ b/platform/web/os_web.cpp @@ -132,6 +132,10 @@ int OS_Web::get_processor_count() const { return godot_js_os_hw_concurrency_get(); } +String OS_Web::get_unique_id() const { + ERR_FAIL_V_MSG("", "OS::get_unique_id() is not available on the Web platform."); +} + bool OS_Web::_check_internal_feature_support(const String &p_feature) { if (p_feature == "web") { return true; diff --git a/platform/web/os_web.h b/platform/web/os_web.h index b9570f9ca1..f262337f00 100644 --- a/platform/web/os_web.h +++ b/platform/web/os_web.h @@ -33,6 +33,8 @@ #include "audio_driver_web.h" +#include "godot_js.h" + #include "core/input/input.h" #include "drivers/unix/os_unix.h" #include "servers/audio_server.h" @@ -48,11 +50,11 @@ class OS_Web : public OS_Unix { bool idb_needs_sync = false; bool pwa_is_waiting = false; - static void main_loop_callback(); + WASM_EXPORT static void main_loop_callback(); - static void file_access_close_callback(const String &p_file, int p_flags); - static void fs_sync_callback(); - static void update_pwa_state_callback(); + WASM_EXPORT static void file_access_close_callback(const String &p_file, int p_flags); + WASM_EXPORT static void fs_sync_callback(); + WASM_EXPORT static void update_pwa_state_callback(); protected: void initialize() override; @@ -83,6 +85,7 @@ public: int get_process_id() const override; bool is_process_running(const ProcessID &p_pid) const override; int get_processor_count() const override; + String get_unique_id() const override; int get_default_thread_pool_size() const override { return 1; } String get_executable_path() const override; diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index b6a36b2391..19063981bf 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -1014,7 +1014,7 @@ void RigidBody2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.01,1000,0.01,or_greater,exp,suffix:kg"), "set_mass", "get_mass"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-8,8,0.001,or_less,or_greater"), "set_gravity_scale", "get_gravity_scale"); ADD_GROUP("Mass Distribution", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "center_of_mass_mode", PROPERTY_HINT_ENUM, "Auto,Custom", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_center_of_mass_mode", "get_center_of_mass_mode"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "center_of_mass", PROPERTY_HINT_RANGE, "-10,10,0.01,or_less,or_greater,suffix:px"), "set_center_of_mass", "get_center_of_mass"); diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index 66895afb27..973d1cde58 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -1082,7 +1082,7 @@ void RigidBody3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.01,1000,0.01,or_greater,exp,suffix:kg"), "set_mass", "get_mass"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-8,8,0.001,or_less,or_greater"), "set_gravity_scale", "get_gravity_scale"); ADD_GROUP("Mass Distribution", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "center_of_mass_mode", PROPERTY_HINT_ENUM, "Auto,Custom", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_center_of_mass_mode", "get_center_of_mass_mode"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_of_mass", PROPERTY_HINT_RANGE, "-10,10,0.01,or_less,or_greater,suffix:m"), "set_center_of_mass", "get_center_of_mass"); @@ -3022,7 +3022,7 @@ void PhysicalBone3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.01,1000,0.01,or_greater,exp,suffix:kg"), "set_mass", "get_mass"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_friction", "get_friction"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_bounce", "get_bounce"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-10,10,0.01"), "set_gravity_scale", "get_gravity_scale"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-8,8,0.001,or_less,or_greater"), "set_gravity_scale", "get_gravity_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator"); ADD_PROPERTY(PropertyInfo(Variant::INT, "linear_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_linear_damp_mode", "get_linear_damp_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp"); diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 8e08653abd..a886831fdb 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -768,7 +768,7 @@ void AnimationPlayer::_bind_methods() { ADD_GROUP("Playback Options", "playback_"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "playback_default_blend_time", PROPERTY_HINT_RANGE, "0,4096,0.01,suffix:s"), "set_default_blend_time", "get_default_blend_time"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed_scale", PROPERTY_HINT_RANGE, "-64,64,0.01"), "set_speed_scale", "get_speed_scale"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed_scale", PROPERTY_HINT_RANGE, "-4,4,0.001,or_less,or_greater"), "set_speed_scale", "get_speed_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "movie_quit_on_finish"), "set_movie_quit_on_finish_enabled", "is_movie_quit_on_finish_enabled"); ADD_SIGNAL(MethodInfo(SNAME("current_animation_changed"), PropertyInfo(Variant::STRING, "name"))); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 53e8945933..c7ff5980cb 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -2533,7 +2533,7 @@ StringName Control::get_theme_type_variation() const { Ref<Texture2D> Control::get_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(Ref<Texture2D>()); if (!data.initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { @@ -2557,7 +2557,7 @@ Ref<Texture2D> Control::get_theme_icon(const StringName &p_name, const StringNam Ref<StyleBox> Control::get_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(Ref<StyleBox>()); if (!data.initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { @@ -2581,7 +2581,7 @@ Ref<StyleBox> Control::get_theme_stylebox(const StringName &p_name, const String Ref<Font> Control::get_theme_font(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(Ref<Font>()); if (!data.initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { @@ -2605,7 +2605,7 @@ Ref<Font> Control::get_theme_font(const StringName &p_name, const StringName &p_ int Control::get_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(0); if (!data.initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { @@ -2629,7 +2629,7 @@ int Control::get_theme_font_size(const StringName &p_name, const StringName &p_t Color Control::get_theme_color(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(Color()); if (!data.initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { @@ -2653,7 +2653,7 @@ Color Control::get_theme_color(const StringName &p_name, const StringName &p_the int Control::get_theme_constant(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(0); if (!data.initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { @@ -2704,7 +2704,7 @@ Ref<Texture2D> Control::get_editor_theme_icon(const StringName &p_name) const { bool Control::has_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(false); if (!data.initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { @@ -2721,7 +2721,7 @@ bool Control::has_theme_icon(const StringName &p_name, const StringName &p_theme bool Control::has_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(false); if (!data.initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { @@ -2738,7 +2738,7 @@ bool Control::has_theme_stylebox(const StringName &p_name, const StringName &p_t bool Control::has_theme_font(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(false); if (!data.initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { @@ -2755,7 +2755,7 @@ bool Control::has_theme_font(const StringName &p_name, const StringName &p_theme bool Control::has_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(false); if (!data.initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { @@ -2772,7 +2772,7 @@ bool Control::has_theme_font_size(const StringName &p_name, const StringName &p_ bool Control::has_theme_color(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(false); if (!data.initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { @@ -2789,7 +2789,7 @@ bool Control::has_theme_color(const StringName &p_name, const StringName &p_them bool Control::has_theme_constant(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(false); if (!data.initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 6e12e7f196..d522f40a4e 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -1384,7 +1384,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { } } - emit_signal(SNAME("close_nodes_request"), nodes); + emit_signal(SNAME("delete_nodes_request"), nodes); accept_event(); } } @@ -1890,20 +1890,24 @@ void GraphEdit::_bind_methods() { ADD_SIGNAL(MethodInfo("connection_request", PropertyInfo(Variant::STRING_NAME, "from_node"), PropertyInfo(Variant::INT, "from_port"), PropertyInfo(Variant::STRING_NAME, "to_node"), PropertyInfo(Variant::INT, "to_port"))); ADD_SIGNAL(MethodInfo("disconnection_request", PropertyInfo(Variant::STRING_NAME, "from_node"), PropertyInfo(Variant::INT, "from_port"), PropertyInfo(Variant::STRING_NAME, "to_node"), PropertyInfo(Variant::INT, "to_port"))); - ADD_SIGNAL(MethodInfo("popup_request", PropertyInfo(Variant::VECTOR2, "position"))); - ADD_SIGNAL(MethodInfo("duplicate_nodes_request")); + ADD_SIGNAL(MethodInfo("connection_to_empty", PropertyInfo(Variant::STRING_NAME, "from_node"), PropertyInfo(Variant::INT, "from_port"), PropertyInfo(Variant::VECTOR2, "release_position"))); + ADD_SIGNAL(MethodInfo("connection_from_empty", PropertyInfo(Variant::STRING_NAME, "to_node"), PropertyInfo(Variant::INT, "to_port"), PropertyInfo(Variant::VECTOR2, "release_position"))); + ADD_SIGNAL(MethodInfo("connection_drag_started", PropertyInfo(Variant::STRING_NAME, "from_node"), PropertyInfo(Variant::INT, "from_port"), PropertyInfo(Variant::BOOL, "is_output"))); + ADD_SIGNAL(MethodInfo("connection_drag_ended")); + ADD_SIGNAL(MethodInfo("copy_nodes_request")); ADD_SIGNAL(MethodInfo("paste_nodes_request")); + ADD_SIGNAL(MethodInfo("duplicate_nodes_request")); + ADD_SIGNAL(MethodInfo("delete_nodes_request", PropertyInfo(Variant::ARRAY, "nodes", PROPERTY_HINT_ARRAY_TYPE, "StringName"))); + ADD_SIGNAL(MethodInfo("node_selected", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("node_deselected", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); - ADD_SIGNAL(MethodInfo("connection_to_empty", PropertyInfo(Variant::STRING_NAME, "from_node"), PropertyInfo(Variant::INT, "from_port"), PropertyInfo(Variant::VECTOR2, "release_position"))); - ADD_SIGNAL(MethodInfo("connection_from_empty", PropertyInfo(Variant::STRING_NAME, "to_node"), PropertyInfo(Variant::INT, "to_port"), PropertyInfo(Variant::VECTOR2, "release_position"))); - ADD_SIGNAL(MethodInfo("close_nodes_request", PropertyInfo(Variant::ARRAY, "nodes", PROPERTY_HINT_ARRAY_TYPE, "StringName"))); + + ADD_SIGNAL(MethodInfo("popup_request", PropertyInfo(Variant::VECTOR2, "position"))); + ADD_SIGNAL(MethodInfo("begin_node_move")); ADD_SIGNAL(MethodInfo("end_node_move")); ADD_SIGNAL(MethodInfo("scroll_offset_changed", PropertyInfo(Variant::VECTOR2, "offset"))); - ADD_SIGNAL(MethodInfo("connection_drag_started", PropertyInfo(Variant::STRING_NAME, "from_node"), PropertyInfo(Variant::INT, "from_port"), PropertyInfo(Variant::BOOL, "is_output"))); - ADD_SIGNAL(MethodInfo("connection_drag_ended")); BIND_ENUM_CONSTANT(SCROLL_ZOOMS); BIND_ENUM_CONSTANT(SCROLL_PANS); diff --git a/scene/gui/graph_element.cpp b/scene/gui/graph_element.cpp index ac2cb8bd5d..5129fdd135 100644 --- a/scene/gui/graph_element.cpp +++ b/scene/gui/graph_element.cpp @@ -233,13 +233,15 @@ void GraphElement::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selectable"), "set_selectable", "is_selectable"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selected"), "set_selected", "is_selected"); - ADD_SIGNAL(MethodInfo("position_offset_changed")); ADD_SIGNAL(MethodInfo("node_selected")); ADD_SIGNAL(MethodInfo("node_deselected")); - ADD_SIGNAL(MethodInfo("dragged", PropertyInfo(Variant::VECTOR2, "from"), PropertyInfo(Variant::VECTOR2, "to"))); + ADD_SIGNAL(MethodInfo("raise_request")); - ADD_SIGNAL(MethodInfo("close_request")); + ADD_SIGNAL(MethodInfo("delete_request")); ADD_SIGNAL(MethodInfo("resize_request", PropertyInfo(Variant::VECTOR2, "new_minsize"))); + ADD_SIGNAL(MethodInfo("dragged", PropertyInfo(Variant::VECTOR2, "from"), PropertyInfo(Variant::VECTOR2, "to"))); + ADD_SIGNAL(MethodInfo("position_offset_changed")); + BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, GraphElement, resizer); } diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp index 9a915939c2..7e9b566438 100644 --- a/scene/gui/tab_bar.cpp +++ b/scene/gui/tab_bar.cpp @@ -851,11 +851,6 @@ bool TabBar::is_tab_hidden(int p_tab) const { void TabBar::set_tab_metadata(int p_tab, const Variant &p_metadata) { ERR_FAIL_INDEX(p_tab, tabs.size()); - - if (tabs[p_tab].metadata == p_metadata) { - return; - } - tabs.write[p_tab].metadata = p_metadata; } diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index e2b16cdd66..e78789edbd 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -1476,7 +1476,7 @@ Size2 TreeItem::get_minimum_size(int p_column) { void TreeItem::_call_recursive_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { if (p_argcount < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 0; + r_error.expected = 1; return; } @@ -3142,7 +3142,7 @@ void Tree::value_editor_changed(double p_value) { TreeItem::Cell &c = popup_edited_item->cells.write[popup_edited_item_col]; c.val = p_value; - text_editor->set_text(String::num(c.val, Math::range_step_decimals(c.step))); + line_editor->set_text(String::num(c.val, Math::range_step_decimals(c.step))); item_edited(popup_edited_item_col, popup_edited_item); queue_redraw(); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 5a107188fa..421760b23f 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -675,7 +675,7 @@ const Variant Node::get_node_rpc_config() const { Error Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { if (p_argcount < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 1; + r_error.expected = 1; return ERR_INVALID_PARAMETER; } @@ -697,7 +697,7 @@ Error Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallErro Error Node::_rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { if (p_argcount < 2) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 2; + r_error.expected = 2; return ERR_INVALID_PARAMETER; } @@ -3162,7 +3162,7 @@ void Node::unhandled_key_input(const Ref<InputEvent> &p_key_event) { Variant Node::_call_deferred_thread_group_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { if (p_argcount < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 0; + r_error.expected = 1; return Variant(); } @@ -3185,7 +3185,7 @@ Variant Node::_call_deferred_thread_group_bind(const Variant **p_args, int p_arg Variant Node::_call_thread_safe_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { if (p_argcount < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 0; + r_error.expected = 1; return Variant(); } diff --git a/scene/main/window.cpp b/scene/main/window.cpp index c345c3d179..f5468b29c5 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -829,16 +829,7 @@ void Window::set_visible(bool p_visible) { //update transient exclusive if (transient_parent) { - if (exclusive && visible) { - if (!is_in_edited_scene_root()) { - ERR_FAIL_COND_MSG(transient_parent->exclusive_child && transient_parent->exclusive_child != this, "Transient parent has another exclusive child."); - transient_parent->exclusive_child = this; - } - } else { - if (transient_parent->exclusive_child == this) { - transient_parent->exclusive_child = nullptr; - } - } + _set_transient_exclusive_child(true); } } @@ -878,15 +869,7 @@ void Window::_make_transient() { if (window) { transient_parent = window; window->transient_children.insert(this); - if (is_inside_tree() && is_visible() && exclusive) { - if (transient_parent->exclusive_child == nullptr) { - if (!is_in_edited_scene_root()) { - transient_parent->exclusive_child = this; - } - } else if (transient_parent->exclusive_child != this) { - ERR_PRINT("Making child transient exclusive, but parent has another exclusive child"); - } - } + _set_transient_exclusive_child(); } //see if we can make transient @@ -895,6 +878,22 @@ void Window::_make_transient() { } } +void Window::_set_transient_exclusive_child(bool p_clear_invalid) { + if (exclusive && visible && is_inside_tree()) { + if (!is_in_edited_scene_root()) { + // Transient parent has another exclusive child. + if (transient_parent->exclusive_child && transient_parent->exclusive_child != this) { + ERR_PRINT(vformat("Attempting to make child window exclusive, but the parent window already has another exclusive child. This window: %s, parent window: %s, current exclusive child window: %s", this->get_description(), transient_parent->get_description(), transient_parent->exclusive_child->get_description())); + } + transient_parent->exclusive_child = this; + } + } else if (p_clear_invalid) { + if (transient_parent->exclusive_child == this) { + transient_parent->exclusive_child = nullptr; + } + } +} + void Window::set_transient(bool p_transient) { ERR_MAIN_THREAD_GUARD; if (transient == p_transient) { @@ -936,16 +935,7 @@ void Window::set_exclusive(bool p_exclusive) { } if (transient_parent) { - if (p_exclusive && is_inside_tree() && is_visible()) { - ERR_FAIL_COND_MSG(transient_parent->exclusive_child && transient_parent->exclusive_child != this, "Transient parent has another exclusive child."); - if (!is_in_edited_scene_root()) { - transient_parent->exclusive_child = this; - } - } else { - if (transient_parent->exclusive_child == this) { - transient_parent->exclusive_child = nullptr; - } - } + _set_transient_exclusive_child(true); } } @@ -1999,7 +1989,7 @@ StringName Window::get_theme_type_variation() const { Ref<Texture2D> Window::get_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(Ref<Texture2D>()); if (!initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { @@ -2023,7 +2013,7 @@ Ref<Texture2D> Window::get_theme_icon(const StringName &p_name, const StringName Ref<StyleBox> Window::get_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(Ref<StyleBox>()); if (!initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { @@ -2047,7 +2037,7 @@ Ref<StyleBox> Window::get_theme_stylebox(const StringName &p_name, const StringN Ref<Font> Window::get_theme_font(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(Ref<Font>()); if (!initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { @@ -2071,7 +2061,7 @@ Ref<Font> Window::get_theme_font(const StringName &p_name, const StringName &p_t int Window::get_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(0); if (!initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { @@ -2095,7 +2085,7 @@ int Window::get_theme_font_size(const StringName &p_name, const StringName &p_th Color Window::get_theme_color(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(Color()); if (!initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { @@ -2119,7 +2109,7 @@ Color Window::get_theme_color(const StringName &p_name, const StringName &p_them int Window::get_theme_constant(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(0); if (!initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { @@ -2170,7 +2160,7 @@ Ref<Texture2D> Window::get_editor_theme_icon(const StringName &p_name) const { bool Window::has_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(false); if (!initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { @@ -2187,7 +2177,7 @@ bool Window::has_theme_icon(const StringName &p_name, const StringName &p_theme_ bool Window::has_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(false); if (!initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { @@ -2204,7 +2194,7 @@ bool Window::has_theme_stylebox(const StringName &p_name, const StringName &p_th bool Window::has_theme_font(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(false); if (!initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { @@ -2221,7 +2211,7 @@ bool Window::has_theme_font(const StringName &p_name, const StringName &p_theme_ bool Window::has_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(false); if (!initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { @@ -2238,7 +2228,7 @@ bool Window::has_theme_font_size(const StringName &p_name, const StringName &p_t bool Window::has_theme_color(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(false); if (!initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { @@ -2255,7 +2245,7 @@ bool Window::has_theme_color(const StringName &p_name, const StringName &p_theme bool Window::has_theme_constant(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(false); if (!initialized) { - WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + WARN_PRINT_ONCE(vformat("Attempting to access theme items too early in %s; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED", this->get_description())); } if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { diff --git a/scene/main/window.h b/scene/main/window.h index c1a7ed2e0b..db739cc304 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -163,12 +163,14 @@ private: void _update_window_callbacks(); - void _clear_transient(); - void _make_transient(); Window *transient_parent = nullptr; Window *exclusive_child = nullptr; HashSet<Window *> transient_children; + void _clear_transient(); + void _make_transient(); + void _set_transient_exclusive_child(bool p_clear_invalid = false); + ThemeOwner *theme_owner = nullptr; Ref<Theme> theme; StringName theme_type_variation; diff --git a/scene/resources/text_file.h b/scene/resources/text_file.h index f8dfd1a4c2..739ee083ce 100644 --- a/scene/resources/text_file.h +++ b/scene/resources/text_file.h @@ -41,6 +41,9 @@ private: String text; String path; +protected: + virtual bool editor_can_reload_from_file() override { return false; } + public: virtual bool has_text() const; virtual String get_text() const; diff --git a/tests/core/math/test_math_funcs.h b/tests/core/math/test_math_funcs.h index d046656b0f..5fbea4aece 100644 --- a/tests/core/math/test_math_funcs.h +++ b/tests/core/math/test_math_funcs.h @@ -360,6 +360,25 @@ TEST_CASE_TEMPLATE("[Math] remap", T, float, double) { CHECK(Math::remap((T)-250.0, (T)-100.0, (T)-200.0, (T)0.0, (T)-1000.0) == doctest::Approx((T)-1500.0)); } +TEST_CASE_TEMPLATE("[Math] angle_difference", T, float, double) { + // Loops around, should return 0.0. + CHECK(Math::angle_difference((T)0.0, (T)Math_TAU) == doctest::Approx((T)0.0)); + CHECK(Math::angle_difference((T)Math_PI, (T)-Math_PI) == doctest::Approx((T)0.0)); + CHECK(Math::angle_difference((T)0.0, (T)Math_TAU * (T)4.0) == doctest::Approx((T)0.0)); + + // Rotation is clockwise, so it should return -PI. + CHECK(Math::angle_difference((T)0.0, (T)Math_PI) == doctest::Approx((T)-Math_PI)); + CHECK(Math::angle_difference((T)0.0, (T)-Math_PI) == doctest::Approx((T)Math_PI)); + CHECK(Math::angle_difference((T)Math_PI, (T)0.0) == doctest::Approx((T)Math_PI)); + CHECK(Math::angle_difference((T)-Math_PI, (T)0.0) == doctest::Approx((T)-Math_PI)); + + CHECK(Math::angle_difference((T)0.0, (T)3.0) == doctest::Approx((T)3.0)); + CHECK(Math::angle_difference((T)1.0, (T)-2.0) == doctest::Approx((T)-3.0)); + CHECK(Math::angle_difference((T)-1.0, (T)2.0) == doctest::Approx((T)3.0)); + CHECK(Math::angle_difference((T)-2.0, (T)-4.5) == doctest::Approx((T)-2.5)); + CHECK(Math::angle_difference((T)100.0, (T)102.5) == doctest::Approx((T)2.5)); +} + TEST_CASE_TEMPLATE("[Math] lerp_angle", T, float, double) { // Counter-clockwise rotation. CHECK(Math::lerp_angle((T)0.24 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx((T)-0.005 * Math_TAU)); @@ -390,6 +409,23 @@ TEST_CASE_TEMPLATE("[Math] move_toward", T, float, double) { CHECK(Math::move_toward(-2.0, -5.0, 4.0) == doctest::Approx((T)-5.0)); } +TEST_CASE_TEMPLATE("[Math] rotate_toward", T, float, double) { + // Rotate toward. + CHECK(Math::rotate_toward((T)0.0, (T)Math_PI * (T)0.75, (T)1.5) == doctest::Approx((T)1.5)); + CHECK(Math::rotate_toward((T)-2.0, (T)1.0, (T)2.5) == doctest::Approx((T)0.5)); + CHECK(Math::rotate_toward((T)-2.0, (T)Math_PI, (T)Math_PI) == doctest::Approx((T)-Math_PI)); + CHECK(Math::rotate_toward((T)1.0, (T)Math_PI, (T)20.0) == doctest::Approx((T)Math_PI)); + + // Rotate away. + CHECK(Math::rotate_toward((T)0.0, (T)0.0, (T)-1.5) == doctest::Approx((T)-1.5)); + CHECK(Math::rotate_toward((T)0.0, (T)0.0, (T)-Math_PI) == doctest::Approx((T)-Math_PI)); + CHECK(Math::rotate_toward((T)3.0, (T)Math_PI, (T)-Math_PI) == doctest::Approx((T)0.0)); + CHECK(Math::rotate_toward((T)2.0, (T)Math_PI, (T)-1.5) == doctest::Approx((T)0.5)); + CHECK(Math::rotate_toward((T)1.0, (T)2.0, (T)-0.5) == doctest::Approx((T)0.5)); + CHECK(Math::rotate_toward((T)2.5, (T)2.0, (T)-0.5) == doctest::Approx((T)3.0)); + CHECK(Math::rotate_toward((T)-1.0, (T)1.0, (T)-1.0) == doctest::Approx((T)-2.0)); +} + TEST_CASE_TEMPLATE("[Math] smoothstep", T, float, double) { CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)-5.0) == doctest::Approx((T)0.0)); CHECK(Math::smoothstep((T)0.0, (T)2.0, (T)0.5) == doctest::Approx((T)0.15625)); |