summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/config/project_settings.cpp3
-rw-r--r--core/extension/gdextension.cpp6
-rw-r--r--core/math/a_star.cpp56
-rw-r--r--core/object/script_language_extension.cpp2
-rw-r--r--core/variant/variant.h1
-rw-r--r--core/variant/variant_call.cpp85
-rw-r--r--core/variant/variant_callable.cpp81
-rw-r--r--core/variant/variant_callable.h58
-rw-r--r--core/variant/variant_setget.cpp53
-rw-r--r--doc/classes/BaseMaterial3D.xml2
-rw-r--r--doc/classes/Basis.xml2
-rw-r--r--doc/classes/Callable.xml11
-rw-r--r--doc/classes/CameraAttributesPractical.xml2
-rw-r--r--doc/classes/CompressedCubemap.xml2
-rw-r--r--doc/classes/CompressedCubemapArray.xml2
-rw-r--r--doc/classes/CompressedTexture2DArray.xml2
-rw-r--r--doc/classes/EditorPlugin.xml2
-rw-r--r--doc/classes/InputEventMIDI.xml2
-rw-r--r--doc/classes/Object.xml2
-rw-r--r--doc/classes/ProjectSettings.xml6
-rw-r--r--doc/classes/ScriptLanguageExtension.xml5
-rw-r--r--doc/classes/Texture2D.xml1
-rw-r--r--doc/classes/Transform2D.xml2
-rw-r--r--doc/classes/Transform3D.xml2
-rw-r--r--doc/classes/VehicleWheel3D.xml2
-rw-r--r--drivers/d3d12/d3d12_context.cpp60
-rw-r--r--drivers/d3d12/d3d12_context.h2
-rw-r--r--drivers/unix/os_unix.cpp2
-rw-r--r--editor/animation_track_editor.cpp129
-rw-r--r--editor/animation_track_editor.h2
-rw-r--r--editor/editor_file_system.cpp8
-rw-r--r--editor/project_converter_3_to_4.cpp9
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp4
-rw-r--r--modules/gdscript/gdscript_compiler.cpp8
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/builtin_method_as_callable.gd6
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/builtin_method_as_callable.out3
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/static_method_as_callable.gd8
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/static_method_as_callable.out2
-rw-r--r--modules/gltf/gltf_document.cpp4
-rw-r--r--platform/android/os_android.cpp2
-rw-r--r--platform/ios/os_ios.mm2
-rw-r--r--platform/macos/os_macos.mm2
-rw-r--r--platform/windows/os_windows.cpp6
-rw-r--r--scene/gui/popup_menu.cpp42
-rw-r--r--scene/gui/popup_menu.h1
-rw-r--r--scene/main/viewport.cpp2
-rw-r--r--scene/resources/animation.cpp269
-rw-r--r--scene/resources/animation.h1
-rw-r--r--servers/audio_server.cpp1
-rw-r--r--servers/physics_server_2d_wrap_mt.cpp2
-rw-r--r--servers/physics_server_2d_wrap_mt.h1
-rw-r--r--servers/physics_server_3d_wrap_mt.cpp2
-rw-r--r--servers/physics_server_3d_wrap_mt.h1
-rw-r--r--thirdparty/linuxbsd_headers/README.md19
54 files changed, 684 insertions, 308 deletions
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 56e041be1b..59d1f45e9c 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -1462,7 +1462,6 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("debug/settings/crash_handler/message.editor",
String("Please include this when reporting the bug on: https://github.com/godotengine/godot/issues"));
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/occlusion_culling/bvh_build_quality", PROPERTY_HINT_ENUM, "Low,Medium,High"), 2);
- GLOBAL_DEF(PropertyInfo(Variant::INT, "memory/limits/multithreaded_server/rid_pool_prealloc", PROPERTY_HINT_RANGE, "0,500,1"), 60); // No negative and limit to 500 due to crashes.
GLOBAL_DEF_RST("internationalization/rendering/force_right_to_left_layout_direction", false);
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "internationalization/rendering/root_node_layout_direction", PROPERTY_HINT_ENUM, "Based on Application Locale,Left-to-Right,Right-to-Left,Based on System Locale"), 0);
@@ -1484,6 +1483,8 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF_RST("rendering/rendering_device/d3d12/max_misc_descriptors_per_frame", 512);
custom_prop_info["rendering/rendering_device/d3d12/max_misc_descriptors_per_frame"] = PropertyInfo(Variant::INT, "rendering/rendering_device/d3d12/max_misc_descriptors_per_frame", PROPERTY_HINT_RANGE, "32,4096");
+ GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/rendering_device/d3d12/agility_sdk_version"), 610);
+
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Linear Mipmap,Nearest Mipmap"), 1);
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_repeat", PROPERTY_HINT_ENUM, "Disable,Enable,Mirror"), 0);
diff --git a/core/extension/gdextension.cpp b/core/extension/gdextension.cpp
index 2bac1f6592..19ffe96a09 100644
--- a/core/extension/gdextension.cpp
+++ b/core/extension/gdextension.cpp
@@ -715,10 +715,8 @@ Error GDExtension::open_library(const String &p_path, const String &p_entry_symb
#endif
Error err = OS::get_singleton()->open_dynamic_library(abs_path, library, true, &library_path);
- if (err != OK) {
- ERR_PRINT("GDExtension dynamic library not found: " + abs_path);
- return err;
- }
+ ERR_FAIL_COND_V_MSG(err == ERR_FILE_NOT_FOUND, err, "GDExtension dynamic library not found: " + abs_path);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Can't open GDExtension dynamic library: " + abs_path);
#if defined(WINDOWS_ENABLED) && defined(TOOLS_ENABLED)
// If we copied the file, let's change the library path to point at the original,
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp
index f0f160940d..fb54058bd9 100644
--- a/core/math/a_star.cpp
+++ b/core/math/a_star.cpp
@@ -69,7 +69,7 @@ void AStar3D::add_point(int64_t p_id, const Vector3 &p_pos, real_t p_weight_scal
}
Vector3 AStar3D::get_point_position(int64_t p_id) const {
- Point *p;
+ Point *p = nullptr;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_V_MSG(!p_exists, Vector3(), vformat("Can't get point's position. Point with id: %d doesn't exist.", p_id));
@@ -77,7 +77,7 @@ Vector3 AStar3D::get_point_position(int64_t p_id) const {
}
void AStar3D::set_point_position(int64_t p_id, const Vector3 &p_pos) {
- Point *p;
+ Point *p = nullptr;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_MSG(!p_exists, vformat("Can't set point's position. Point with id: %d doesn't exist.", p_id));
@@ -85,7 +85,7 @@ void AStar3D::set_point_position(int64_t p_id, const Vector3 &p_pos) {
}
real_t AStar3D::get_point_weight_scale(int64_t p_id) const {
- Point *p;
+ Point *p = nullptr;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_V_MSG(!p_exists, 0, vformat("Can't get point's weight scale. Point with id: %d doesn't exist.", p_id));
@@ -93,7 +93,7 @@ real_t AStar3D::get_point_weight_scale(int64_t p_id) const {
}
void AStar3D::set_point_weight_scale(int64_t p_id, real_t p_weight_scale) {
- Point *p;
+ Point *p = nullptr;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_MSG(!p_exists, vformat("Can't set point's weight scale. Point with id: %d doesn't exist.", p_id));
ERR_FAIL_COND_MSG(p_weight_scale < 0.0, vformat("Can't set point's weight scale less than 0.0: %f.", p_weight_scale));
@@ -102,7 +102,7 @@ void AStar3D::set_point_weight_scale(int64_t p_id, real_t p_weight_scale) {
}
void AStar3D::remove_point(int64_t p_id) {
- Point *p;
+ Point *p = nullptr;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_MSG(!p_exists, vformat("Can't remove point. Point with id: %d doesn't exist.", p_id));
@@ -130,11 +130,11 @@ void AStar3D::remove_point(int64_t p_id) {
void AStar3D::connect_points(int64_t p_id, int64_t p_with_id, bool bidirectional) {
ERR_FAIL_COND_MSG(p_id == p_with_id, vformat("Can't connect point with id: %d to itself.", p_id));
- Point *a;
+ Point *a = nullptr;
bool from_exists = points.lookup(p_id, a);
ERR_FAIL_COND_MSG(!from_exists, vformat("Can't connect points. Point with id: %d doesn't exist.", p_id));
- Point *b;
+ Point *b = nullptr;
bool to_exists = points.lookup(p_with_id, b);
ERR_FAIL_COND_MSG(!to_exists, vformat("Can't connect points. Point with id: %d doesn't exist.", p_with_id));
@@ -166,11 +166,11 @@ void AStar3D::connect_points(int64_t p_id, int64_t p_with_id, bool bidirectional
}
void AStar3D::disconnect_points(int64_t p_id, int64_t p_with_id, bool bidirectional) {
- Point *a;
+ Point *a = nullptr;
bool a_exists = points.lookup(p_id, a);
ERR_FAIL_COND_MSG(!a_exists, vformat("Can't disconnect points. Point with id: %d doesn't exist.", p_id));
- Point *b;
+ Point *b = nullptr;
bool b_exists = points.lookup(p_with_id, b);
ERR_FAIL_COND_MSG(!b_exists, vformat("Can't disconnect points. Point with id: %d doesn't exist.", p_with_id));
@@ -220,7 +220,7 @@ PackedInt64Array AStar3D::get_point_ids() {
}
Vector<int64_t> AStar3D::get_point_connections(int64_t p_id) {
- Point *p;
+ Point *p = nullptr;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_V_MSG(!p_exists, Vector<int64_t>(), vformat("Can't get point's connections. Point with id: %d doesn't exist.", p_id));
@@ -386,11 +386,11 @@ real_t AStar3D::_estimate_cost(int64_t p_from_id, int64_t p_to_id) {
return scost;
}
- Point *from_point;
+ Point *from_point = nullptr;
bool from_exists = points.lookup(p_from_id, from_point);
ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_from_id));
- Point *to_point;
+ Point *to_point = nullptr;
bool to_exists = points.lookup(p_to_id, to_point);
ERR_FAIL_COND_V_MSG(!to_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_to_id));
@@ -403,11 +403,11 @@ real_t AStar3D::_compute_cost(int64_t p_from_id, int64_t p_to_id) {
return scost;
}
- Point *from_point;
+ Point *from_point = nullptr;
bool from_exists = points.lookup(p_from_id, from_point);
ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_from_id));
- Point *to_point;
+ Point *to_point = nullptr;
bool to_exists = points.lookup(p_to_id, to_point);
ERR_FAIL_COND_V_MSG(!to_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_to_id));
@@ -415,11 +415,11 @@ real_t AStar3D::_compute_cost(int64_t p_from_id, int64_t p_to_id) {
}
Vector<Vector3> AStar3D::get_point_path(int64_t p_from_id, int64_t p_to_id) {
- Point *a;
+ Point *a = nullptr;
bool from_exists = points.lookup(p_from_id, a);
ERR_FAIL_COND_V_MSG(!from_exists, Vector<Vector3>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_from_id));
- Point *b;
+ Point *b = nullptr;
bool to_exists = points.lookup(p_to_id, b);
ERR_FAIL_COND_V_MSG(!to_exists, Vector<Vector3>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_to_id));
@@ -464,11 +464,11 @@ Vector<Vector3> AStar3D::get_point_path(int64_t p_from_id, int64_t p_to_id) {
}
Vector<int64_t> AStar3D::get_id_path(int64_t p_from_id, int64_t p_to_id) {
- Point *a;
+ Point *a = nullptr;
bool from_exists = points.lookup(p_from_id, a);
ERR_FAIL_COND_V_MSG(!from_exists, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_from_id));
- Point *b;
+ Point *b = nullptr;
bool to_exists = points.lookup(p_to_id, b);
ERR_FAIL_COND_V_MSG(!to_exists, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_to_id));
@@ -513,7 +513,7 @@ Vector<int64_t> AStar3D::get_id_path(int64_t p_from_id, int64_t p_to_id) {
}
void AStar3D::set_point_disabled(int64_t p_id, bool p_disabled) {
- Point *p;
+ Point *p = nullptr;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_MSG(!p_exists, vformat("Can't set if point is disabled. Point with id: %d doesn't exist.", p_id));
@@ -521,7 +521,7 @@ void AStar3D::set_point_disabled(int64_t p_id, bool p_disabled) {
}
bool AStar3D::is_point_disabled(int64_t p_id) const {
- Point *p;
+ Point *p = nullptr;
bool p_exists = points.lookup(p_id, p);
ERR_FAIL_COND_V_MSG(!p_exists, false, vformat("Can't get if point is disabled. Point with id: %d doesn't exist.", p_id));
@@ -660,11 +660,11 @@ real_t AStar2D::_estimate_cost(int64_t p_from_id, int64_t p_to_id) {
return scost;
}
- AStar3D::Point *from_point;
+ AStar3D::Point *from_point = nullptr;
bool from_exists = astar.points.lookup(p_from_id, from_point);
ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_from_id));
- AStar3D::Point *to_point;
+ AStar3D::Point *to_point = nullptr;
bool to_exists = astar.points.lookup(p_to_id, to_point);
ERR_FAIL_COND_V_MSG(!to_exists, 0, vformat("Can't estimate cost. Point with id: %d doesn't exist.", p_to_id));
@@ -677,11 +677,11 @@ real_t AStar2D::_compute_cost(int64_t p_from_id, int64_t p_to_id) {
return scost;
}
- AStar3D::Point *from_point;
+ AStar3D::Point *from_point = nullptr;
bool from_exists = astar.points.lookup(p_from_id, from_point);
ERR_FAIL_COND_V_MSG(!from_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_from_id));
- AStar3D::Point *to_point;
+ AStar3D::Point *to_point = nullptr;
bool to_exists = astar.points.lookup(p_to_id, to_point);
ERR_FAIL_COND_V_MSG(!to_exists, 0, vformat("Can't compute cost. Point with id: %d doesn't exist.", p_to_id));
@@ -689,11 +689,11 @@ real_t AStar2D::_compute_cost(int64_t p_from_id, int64_t p_to_id) {
}
Vector<Vector2> AStar2D::get_point_path(int64_t p_from_id, int64_t p_to_id) {
- AStar3D::Point *a;
+ AStar3D::Point *a = nullptr;
bool from_exists = astar.points.lookup(p_from_id, a);
ERR_FAIL_COND_V_MSG(!from_exists, Vector<Vector2>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_from_id));
- AStar3D::Point *b;
+ AStar3D::Point *b = nullptr;
bool to_exists = astar.points.lookup(p_to_id, b);
ERR_FAIL_COND_V_MSG(!to_exists, Vector<Vector2>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_to_id));
@@ -737,11 +737,11 @@ Vector<Vector2> AStar2D::get_point_path(int64_t p_from_id, int64_t p_to_id) {
}
Vector<int64_t> AStar2D::get_id_path(int64_t p_from_id, int64_t p_to_id) {
- AStar3D::Point *a;
+ AStar3D::Point *a = nullptr;
bool from_exists = astar.points.lookup(p_from_id, a);
ERR_FAIL_COND_V_MSG(!from_exists, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_from_id));
- AStar3D::Point *b;
+ AStar3D::Point *b = nullptr;
bool to_exists = astar.points.lookup(p_to_id, b);
ERR_FAIL_COND_V_MSG(!to_exists, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_to_id));
diff --git a/core/object/script_language_extension.cpp b/core/object/script_language_extension.cpp
index 79f39cb626..be62cabe25 100644
--- a/core/object/script_language_extension.cpp
+++ b/core/object/script_language_extension.cpp
@@ -107,7 +107,7 @@ void ScriptLanguageExtension::_bind_methods() {
GDVIRTUAL_BIND(_supports_builtin_mode);
GDVIRTUAL_BIND(_supports_documentation);
GDVIRTUAL_BIND(_can_inherit_from_file);
- GDVIRTUAL_BIND(_find_function, "class_name", "function_name");
+ GDVIRTUAL_BIND(_find_function, "function", "code");
GDVIRTUAL_BIND(_make_function, "class_name", "function_name", "function_args");
GDVIRTUAL_BIND(_open_in_external_editor, "script", "line", "column");
GDVIRTUAL_BIND(_overrides_external_editor);
diff --git a/core/variant/variant.h b/core/variant/variant.h
index 480f21df98..e93733040a 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -572,6 +572,7 @@ public:
static ValidatedBuiltInMethod get_validated_builtin_method(Variant::Type p_type, const StringName &p_method);
static PTRBuiltInMethod get_ptr_builtin_method(Variant::Type p_type, const StringName &p_method);
+ static MethodInfo get_builtin_method_info(Variant::Type p_type, const StringName &p_method);
static int get_builtin_method_argument_count(Variant::Type p_type, const StringName &p_method);
static Variant::Type get_builtin_method_argument_type(Variant::Type p_type, const StringName &p_method, int p_argument);
static String get_builtin_method_argument_name(Variant::Type p_type, const StringName &p_method, int p_argument);
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 7121b4da96..dd793dbcd4 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -1114,6 +1114,46 @@ struct VariantBuiltInMethodInfo {
Variant::Type return_type;
int argument_count = 0;
Variant::Type (*get_argument_type)(int p_arg) = nullptr;
+
+ MethodInfo get_method_info(const StringName &p_name) const {
+ MethodInfo mi;
+ mi.name = p_name;
+
+ if (has_return_type) {
+ mi.return_val.type = return_type;
+ if (mi.return_val.type == Variant::NIL) {
+ mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
+ }
+ }
+
+ if (is_const) {
+ mi.flags |= METHOD_FLAG_CONST;
+ }
+ if (is_vararg) {
+ mi.flags |= METHOD_FLAG_VARARG;
+ }
+ if (is_static) {
+ mi.flags |= METHOD_FLAG_STATIC;
+ }
+
+ for (int i = 0; i < argument_count; i++) {
+ PropertyInfo pi;
+#ifdef DEBUG_METHODS_ENABLED
+ pi.name = argument_names[i];
+#else
+ pi.name = "arg" + itos(i + 1);
+#endif
+ pi.type = (*get_argument_type)(i);
+ if (pi.type == Variant::NIL) {
+ pi.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
+ }
+ mi.arguments.push_back(pi);
+ }
+
+ mi.default_arguments = default_arguments;
+
+ return mi;
+ }
};
typedef OAHashMap<StringName, VariantBuiltInMethodInfo> BuiltinMethodMap;
@@ -1268,6 +1308,13 @@ Variant::PTRBuiltInMethod Variant::get_ptr_builtin_method(Variant::Type p_type,
return method->ptrcall;
}
+MethodInfo Variant::get_builtin_method_info(Variant::Type p_type, const StringName &p_method) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, MethodInfo());
+ const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
+ ERR_FAIL_NULL_V(method, MethodInfo());
+ return method->get_method_info(p_method);
+}
+
int Variant::get_builtin_method_argument_count(Variant::Type p_type, const StringName &p_method) {
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, 0);
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
@@ -1378,43 +1425,7 @@ void Variant::get_method_list(List<MethodInfo> *p_list) const {
for (const StringName &E : builtin_method_names[type]) {
const VariantBuiltInMethodInfo *method = builtin_method_info[type].lookup_ptr(E);
ERR_CONTINUE(!method);
-
- MethodInfo mi;
- mi.name = E;
-
- //return type
- if (method->has_return_type) {
- mi.return_val.type = method->return_type;
- if (mi.return_val.type == Variant::NIL) {
- mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
- }
- }
-
- if (method->is_const) {
- mi.flags |= METHOD_FLAG_CONST;
- }
- if (method->is_vararg) {
- mi.flags |= METHOD_FLAG_VARARG;
- }
- if (method->is_static) {
- mi.flags |= METHOD_FLAG_STATIC;
- }
- for (int i = 0; i < method->argument_count; i++) {
- PropertyInfo pi;
-#ifdef DEBUG_METHODS_ENABLED
- pi.name = method->argument_names[i];
-#else
- pi.name = "arg" + itos(i + 1);
-#endif
- pi.type = method->get_argument_type(i);
- if (pi.type == Variant::NIL) {
- pi.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
- }
- mi.arguments.push_back(pi);
- }
-
- mi.default_arguments = method->default_arguments;
- p_list->push_back(mi);
+ p_list->push_back(method->get_method_info(E));
}
}
}
diff --git a/core/variant/variant_callable.cpp b/core/variant/variant_callable.cpp
new file mode 100644
index 0000000000..dc31b6d1ac
--- /dev/null
+++ b/core/variant/variant_callable.cpp
@@ -0,0 +1,81 @@
+/**************************************************************************/
+/* variant_callable.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "variant_callable.h"
+
+#include "core/templates/hashfuncs.h"
+
+bool VariantCallable::compare_equal(const CallableCustom *p_a, const CallableCustom *p_b) {
+ return p_a->hash() == p_b->hash();
+}
+
+bool VariantCallable::compare_less(const CallableCustom *p_a, const CallableCustom *p_b) {
+ return p_a->hash() < p_b->hash();
+}
+
+uint32_t VariantCallable::hash() const {
+ return h;
+}
+
+String VariantCallable::get_as_text() const {
+ return vformat("%s::%s (Callable)", Variant::get_type_name(variant.get_type()), method);
+}
+
+CallableCustom::CompareEqualFunc VariantCallable::get_compare_equal_func() const {
+ return compare_equal;
+}
+
+CallableCustom::CompareLessFunc VariantCallable::get_compare_less_func() const {
+ return compare_less;
+}
+
+bool VariantCallable::is_valid() const {
+ return Variant::has_builtin_method(variant.get_type(), method);
+}
+
+StringName VariantCallable::get_method() const {
+ return method;
+}
+
+ObjectID VariantCallable::get_object() const {
+ return ObjectID();
+}
+
+void VariantCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
+ Variant v = variant;
+ v.callp(method, p_arguments, p_argcount, r_return_value, r_call_error);
+}
+
+VariantCallable::VariantCallable(const Variant &p_variant, const StringName &p_method) {
+ variant = p_variant;
+ method = p_method;
+ h = variant.hash();
+ h = hash_murmur3_one_64(Variant::get_builtin_method_hash(variant.get_type(), method), h);
+}
diff --git a/core/variant/variant_callable.h b/core/variant/variant_callable.h
new file mode 100644
index 0000000000..3f2b058aaf
--- /dev/null
+++ b/core/variant/variant_callable.h
@@ -0,0 +1,58 @@
+/**************************************************************************/
+/* variant_callable.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef VARIANT_CALLABLE_H
+#define VARIANT_CALLABLE_H
+
+#include "core/variant/callable.h"
+#include "core/variant/variant.h"
+
+class VariantCallable : public CallableCustom {
+ Variant variant;
+ StringName method;
+ uint32_t h = 0;
+
+ static bool compare_equal(const CallableCustom *p_a, const CallableCustom *p_b);
+ static bool compare_less(const CallableCustom *p_a, const CallableCustom *p_b);
+
+public:
+ uint32_t hash() const override;
+ String get_as_text() const override;
+ CompareEqualFunc get_compare_equal_func() const override;
+ CompareLessFunc get_compare_less_func() const override;
+ bool is_valid() const override;
+ StringName get_method() const override;
+ ObjectID get_object() const override;
+ void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
+
+ VariantCallable(const Variant &p_variant, const StringName &p_method);
+};
+
+#endif // VARIANT_CALLABLE_H
diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp
index 05f7abf32c..b0e0a885f4 100644
--- a/core/variant/variant_setget.cpp
+++ b/core/variant/variant_setget.cpp
@@ -30,6 +30,8 @@
#include "variant_setget.h"
+#include "variant_callable.h"
+
struct VariantSetterGetterInfo {
void (*setter)(Variant *base, const Variant *value, bool &valid);
void (*getter)(const Variant *base, Variant *value);
@@ -264,42 +266,45 @@ void Variant::set_named(const StringName &p_member, const Variant &p_value, bool
}
Variant Variant::get_named(const StringName &p_member, bool &r_valid) const {
- Variant ret;
uint32_t s = variant_setters_getters[type].size();
if (s) {
for (uint32_t i = 0; i < s; i++) {
if (variant_setters_getters_names[type][i] == p_member) {
+ Variant ret;
variant_setters_getters[type][i].getter(this, &ret);
r_valid = true;
return ret;
}
}
+ }
- r_valid = false;
-
- } else if (type == Variant::OBJECT) {
- Object *obj = get_validated_object();
- if (!obj) {
- r_valid = false;
- return "Instance base is null.";
- } else {
- return obj->get(p_member, &r_valid);
- }
- } else if (type == Variant::DICTIONARY) {
- const Variant *v = VariantGetInternalPtr<Dictionary>::get_ptr(this)->getptr(p_member);
- if (v) {
- r_valid = true;
-
- return *v;
- } else {
- r_valid = false;
- }
-
- } else {
- r_valid = false;
+ switch (type) {
+ case Variant::OBJECT: {
+ Object *obj = get_validated_object();
+ if (!obj) {
+ r_valid = false;
+ return "Instance base is null.";
+ } else {
+ return obj->get(p_member, &r_valid);
+ }
+ } break;
+ case Variant::DICTIONARY: {
+ const Variant *v = VariantGetInternalPtr<Dictionary>::get_ptr(this)->getptr(p_member);
+ if (v) {
+ r_valid = true;
+ return *v;
+ }
+ } break;
+ default: {
+ if (Variant::has_builtin_method(type, p_member)) {
+ r_valid = true;
+ return Callable(memnew(VariantCallable(*this, p_member)));
+ }
+ } break;
}
- return ret;
+ r_valid = false;
+ return Variant();
}
/**** INDEXED SETTERS AND GETTERS ****/
diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml
index 653397ebc3..e3a7eda563 100644
--- a/doc/classes/BaseMaterial3D.xml
+++ b/doc/classes/BaseMaterial3D.xml
@@ -383,7 +383,7 @@
If [code]true[/code], enables subsurface scattering transmittance. Only effective if [member subsurf_scatter_enabled] is [code]true[/code]. See also [member backlight_enabled].
</member>
<member name="subsurf_scatter_transmittance_texture" type="Texture2D" setter="set_texture" getter="get_texture">
- The texture to use for multiplying the intensity of the subsurface scattering transmitteance intensity. See also [member subsurf_scatter_texture]. Ignored if [member subsurf_scatter_skin_mode] is [code]true[/code].
+ The texture to use for multiplying the intensity of the subsurface scattering transmittance intensity. See also [member subsurf_scatter_texture]. Ignored if [member subsurf_scatter_skin_mode] is [code]true[/code].
</member>
<member name="texture_filter" type="int" setter="set_texture_filter" getter="get_texture_filter" enum="BaseMaterial3D.TextureFilter" default="3">
Filter flags for the texture. See [enum TextureFilter] for options.
diff --git a/doc/classes/Basis.xml b/doc/classes/Basis.xml
index f98c207a6e..fb6cf5a258 100644
--- a/doc/classes/Basis.xml
+++ b/doc/classes/Basis.xml
@@ -7,7 +7,7 @@
A 3×3 matrix used for representing 3D rotation and scale. Usually used as an orthogonal basis for a [Transform3D].
Contains 3 vector fields X, Y and Z as its columns, which are typically interpreted as the local basis vectors of a transformation. For such use, it is composed of a scaling and a rotation matrix, in that order (M = R.S).
Basis can also be accessed as an array of 3D vectors. These vectors are usually orthogonal to each other, but are not necessarily normalized (due to scaling).
- For more information, read the "Matrices and transforms" documentation article.
+ For a general introduction, see the [url=$DOCS_URL/tutorials/math/matrices_and_transforms.html]Matrices and transforms[/url] tutorial.
</description>
<tutorials>
<link title="Math documentation index">$DOCS_URL/tutorials/math/index.html</link>
diff --git a/doc/classes/Callable.xml b/doc/classes/Callable.xml
index b903e98319..3550a6b7bd 100644
--- a/doc/classes/Callable.xml
+++ b/doc/classes/Callable.xml
@@ -46,17 +46,6 @@
# Prints "Attack!", when the button_pressed signal is emitted.
button_pressed.connect(func(): print("Attack!"))
[/codeblock]
- [b]Note:[/b] Methods of native types such as [Signal], [Array], or [Dictionary] are not of type [Callable] in order to avoid unnecessary overhead. If you need to pass those methods as [Callable], use a lambda function as a wrapper.
- [codeblock]
- func _init():
- var my_dictionary = { "hello": "world" }
-
- # This will not work, `clear` is not a callable.
- create_tween().tween_callback(my_dictionary.clear)
-
- # This will work, as lambdas are custom callables.
- create_tween().tween_callback(func(): my_dictionary.clear())
- [/codeblock]
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/CameraAttributesPractical.xml b/doc/classes/CameraAttributesPractical.xml
index 8a5956cc87..893bc27f91 100644
--- a/doc/classes/CameraAttributesPractical.xml
+++ b/doc/classes/CameraAttributesPractical.xml
@@ -17,7 +17,7 @@
The minimum sensitivity (in ISO) used when calculating auto exposure. When calculating scene average luminance, color values will be clamped to at least this value. This limits the auto-exposure from exposing above a certain brightness, resulting in a cut off point where the scene will remain dark.
</member>
<member name="dof_blur_amount" type="float" setter="set_dof_blur_amount" getter="get_dof_blur_amount" default="0.1">
- Sets the maximum amount of blur. When using physically-based blur amounts, will instead act as a multiplier. High values lead to an increased amount of bluriness, but can be much more expensive to calculate. It is best to keep this as low as possible for a given art style.
+ Sets the maximum amount of blur. When using physically-based blur amounts, will instead act as a multiplier. High values lead to an increased amount of blurriness, but can be much more expensive to calculate. It is best to keep this as low as possible for a given art style.
</member>
<member name="dof_blur_far_distance" type="float" setter="set_dof_blur_far_distance" getter="get_dof_blur_far_distance" default="10.0">
Objects further from the [Camera3D] by this amount will be blurred by the depth of field effect. Measured in meters.
diff --git a/doc/classes/CompressedCubemap.xml b/doc/classes/CompressedCubemap.xml
index 6ab0cc5d88..406ab4909a 100644
--- a/doc/classes/CompressedCubemap.xml
+++ b/doc/classes/CompressedCubemap.xml
@@ -4,7 +4,7 @@
An optionally compressed [Cubemap].
</brief_description>
<description>
- A cubemap that is loaded from a [code].ccube[/code] file. This file format is internal to Godot; it is created by importing other image formats with the import system. [CompressedCubemap] can use one of 4 compresson methods:
+ A cubemap that is loaded from a [code].ccube[/code] file. This file format is internal to Godot; it is created by importing other image formats with the import system. [CompressedCubemap] can use one of 4 compression methods:
- Lossless (WebP or PNG, uncompressed on the GPU)
- Lossy (WebP, uncompressed on the GPU)
- VRAM Compressed (compressed on the GPU)
diff --git a/doc/classes/CompressedCubemapArray.xml b/doc/classes/CompressedCubemapArray.xml
index 32687229ed..195449ee99 100644
--- a/doc/classes/CompressedCubemapArray.xml
+++ b/doc/classes/CompressedCubemapArray.xml
@@ -4,7 +4,7 @@
An optionally compressed [CubemapArray].
</brief_description>
<description>
- A cubemap array that is loaded from a [code].ccubearray[/code] file. This file format is internal to Godot; it is created by importing other image formats with the import system. [CompressedCubemapArray] can use one of 4 compresson methods:
+ A cubemap array that is loaded from a [code].ccubearray[/code] file. This file format is internal to Godot; it is created by importing other image formats with the import system. [CompressedCubemapArray] can use one of 4 compression methods:
- Lossless (WebP or PNG, uncompressed on the GPU)
- Lossy (WebP, uncompressed on the GPU)
- VRAM Compressed (compressed on the GPU)
diff --git a/doc/classes/CompressedTexture2DArray.xml b/doc/classes/CompressedTexture2DArray.xml
index ab0684fa06..6570e8f931 100644
--- a/doc/classes/CompressedTexture2DArray.xml
+++ b/doc/classes/CompressedTexture2DArray.xml
@@ -4,7 +4,7 @@
Array of 2-dimensional textures, optionally compressed.
</brief_description>
<description>
- A texture array that is loaded from a [code].ctexarray[/code] file. This file format is internal to Godot; it is created by importing other image formats with the import system. [CompressedTexture2DArray] can use one of 4 compresson methods:
+ A texture array that is loaded from a [code].ctexarray[/code] file. This file format is internal to Godot; it is created by importing other image formats with the import system. [CompressedTexture2DArray] can use one of 4 compression methods:
- Lossless (WebP or PNG, uncompressed on the GPU)
- Lossy (WebP, uncompressed on the GPU)
- VRAM Compressed (compressed on the GPU)
diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml
index 50709f9ef5..148a6541a2 100644
--- a/doc/classes/EditorPlugin.xml
+++ b/doc/classes/EditorPlugin.xml
@@ -327,7 +327,7 @@
<param index="0" name="object" type="Object" />
<description>
Implement this function if your plugin edits a specific type of object (Resource or Node). If you return [code]true[/code], then you will get the functions [method _edit] and [method _make_visible] called when the editor requests them. If you have declared the methods [method _forward_canvas_gui_input] and [method _forward_3d_gui_input] these will be called too.
- [b]Note:[/b] Each plugin should handle only one type of objects at a time. If a plugin handes more types of objects and they are edited at the same time, it will result in errors.
+ [b]Note:[/b] Each plugin should handle only one type of objects at a time. If a plugin handles more types of objects and they are edited at the same time, it will result in errors.
</description>
</method>
<method name="_has_main_screen" qualifiers="virtual const">
diff --git a/doc/classes/InputEventMIDI.xml b/doc/classes/InputEventMIDI.xml
index d685fdfa41..8e2ad52801 100644
--- a/doc/classes/InputEventMIDI.xml
+++ b/doc/classes/InputEventMIDI.xml
@@ -75,7 +75,7 @@
If the message is [constant MIDI_MESSAGE_CONTROL_CHANGE], this indicates the controller value, otherwise this is zero. Controllers include devices such as pedals and levers.
</member>
<member name="instrument" type="int" setter="set_instrument" getter="get_instrument" default="0">
- The instrument of this input event. This value ranges from 0 to 127. Refer to the instrument list on the General MIDI wikipedia article to see a list of instruments, except that this value is 0-index, so subtract one from every number on that chart. A standard piano will have an instrument number of 0.
+ The instrument of this input event. This value ranges from 0 to 127. Refer to the instrument list for [url=https://en.wikipedia.org/wiki/General_MIDI#Program_change_events]General MIDI[/url] to see a list of instruments, except that this value is 0-index, so subtract one from every number on that chart. A standard piano will have an instrument number of 0.
</member>
<member name="message" type="int" setter="set_message" getter="get_message" enum="MIDIMessage" default="0">
Returns a value indicating the type of message for this MIDI signal. This is a member of the [enum MIDIMessage] enum.
diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml
index 2ffb02096d..e4f4d7682b 100644
--- a/doc/classes/Object.xml
+++ b/doc/classes/Object.xml
@@ -314,7 +314,7 @@
{
if (property["name"].AsStringName() == PropertyName.Number &amp;&amp; IsNumberEditable)
{
- var usage = property["usage"].As&gt;PropertyUsageFlags&lt;() | PropertyUsageFlags.ReadOnly;
+ var usage = property["usage"].As&lt;PropertyUsageFlags&gt;() | PropertyUsageFlags.ReadOnly;
property["usage"] = (int)usage;
}
}
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index ab92916320..cb36d28a41 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -1993,9 +1993,6 @@
<member name="memory/limits/message_queue/max_size_mb" type="int" setter="" getter="" default="32">
Godot uses a message queue to defer some function calls. If you run out of space on it (you will see an error), you can increase the size here.
</member>
- <member name="memory/limits/multithreaded_server/rid_pool_prealloc" type="int" setter="" getter="" default="60">
- This is used by servers when used in multi-threading mode (servers and visual). RIDs are preallocated to avoid stalling the server requesting them on threads. If servers get stalled too often when loading resources in a thread, increase this number.
- </member>
<member name="navigation/2d/default_cell_size" type="float" setter="" getter="" default="1.0">
Default cell size for 2D navigation maps. See [method NavigationServer2D.map_set_cell_size].
</member>
@@ -2616,6 +2613,9 @@
<member name="rendering/renderer/rendering_method.web" type="String" setter="" getter="" default="&quot;gl_compatibility&quot;">
Override for [member rendering/renderer/rendering_method] on web.
</member>
+ <member name="rendering/rendering_device/d3d12/agility_sdk_version" type="int" setter="" getter="" default="610">
+ Version code of the Direct3D 12 Agility SDK to use ([code]D3D12SDKVersion[/code]).
+ </member>
<member name="rendering/rendering_device/d3d12/max_misc_descriptors_per_frame" type="int" setter="" getter="" default="512">
The number of entries in the miscellaneous descriptors heap the Direct3D 12 rendering driver uses each frame, used for various operations like clearing a texture.
Depending on the complexity of scenes, this value may be lowered or may need to be raised.
diff --git a/doc/classes/ScriptLanguageExtension.xml b/doc/classes/ScriptLanguageExtension.xml
index b4e2f40612..c5248f4888 100644
--- a/doc/classes/ScriptLanguageExtension.xml
+++ b/doc/classes/ScriptLanguageExtension.xml
@@ -114,9 +114,10 @@
</method>
<method name="_find_function" qualifiers="virtual const">
<return type="int" />
- <param index="0" name="class_name" type="String" />
- <param index="1" name="function_name" type="String" />
+ <param index="0" name="function" type="String" />
+ <param index="1" name="code" type="String" />
<description>
+ Returns the line where the function is defined in the code, or [code]-1[/code] if the function is not present.
</description>
</method>
<method name="_finish" qualifiers="virtual">
diff --git a/doc/classes/Texture2D.xml b/doc/classes/Texture2D.xml
index 087f3a70f8..7254a92e36 100644
--- a/doc/classes/Texture2D.xml
+++ b/doc/classes/Texture2D.xml
@@ -123,6 +123,7 @@
<return type="Image" />
<description>
Returns an [Image] that is a copy of data from this [Texture2D] (a new [Image] is created each time). [Image]s can be accessed and manipulated directly.
+ [b]Note:[/b] This will return [code]null[/code] if this [Texture2D] is invalid.
[b]Note:[/b] This will fetch the texture data from the GPU, which might cause performance problems when overused.
</description>
</method>
diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml
index aee70f6b59..19a4973f4a 100644
--- a/doc/classes/Transform2D.xml
+++ b/doc/classes/Transform2D.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
A 2×3 matrix (2 rows, 3 columns) used for 2D linear transformations. It can represent transformations such as translation, rotation, and scaling. It consists of three [Vector2] values: [member x], [member y], and the [member origin].
- For more information, read the "Matrices and transforms" documentation article.
+ For a general introduction, see the [url=$DOCS_URL/tutorials/math/matrices_and_transforms.html]Matrices and transforms[/url] tutorial.
</description>
<tutorials>
<link title="Math documentation index">$DOCS_URL/tutorials/math/index.html</link>
diff --git a/doc/classes/Transform3D.xml b/doc/classes/Transform3D.xml
index 85da629d70..91ece6943c 100644
--- a/doc/classes/Transform3D.xml
+++ b/doc/classes/Transform3D.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
A 3×4 matrix (3 rows, 4 columns) used for 3D linear transformations. It can represent transformations such as translation, rotation, and scaling. It consists of a [member basis] (first 3 columns) and a [Vector3] for the [member origin] (last column).
- For more information, read the "Matrices and transforms" documentation article.
+ For a general introduction, see the [url=$DOCS_URL/tutorials/math/matrices_and_transforms.html]Matrices and transforms[/url] tutorial.
</description>
<tutorials>
<link title="Math documentation index">$DOCS_URL/tutorials/math/index.html</link>
diff --git a/doc/classes/VehicleWheel3D.xml b/doc/classes/VehicleWheel3D.xml
index 9c7ba58534..77cb5ca9f8 100644
--- a/doc/classes/VehicleWheel3D.xml
+++ b/doc/classes/VehicleWheel3D.xml
@@ -81,7 +81,7 @@
This is the distance in meters the wheel is lowered from its origin point. Don't set this to 0.0 and move the wheel into position, instead move the origin point of your wheel (the gizmo in Godot) to the position the wheel will take when bottoming out, then use the rest length to move the wheel down to the position it should be in when the car is in rest.
</member>
<member name="wheel_roll_influence" type="float" setter="set_roll_influence" getter="get_roll_influence" default="0.1">
- This value affects the roll of your vehicle. If set to 1.0 for all wheels, your vehicle will be prone to rolling over, while a value of 0.0 will resist body roll.
+ This value affects the roll of your vehicle. If set to 1.0 for all wheels, your vehicle will resist body roll, while a value of 0.0 will be prone to rolling over.
</member>
</members>
</class>
diff --git a/drivers/d3d12/d3d12_context.cpp b/drivers/d3d12/d3d12_context.cpp
index 36492b198b..97f5d91f3a 100644
--- a/drivers/d3d12/d3d12_context.cpp
+++ b/drivers/d3d12/d3d12_context.cpp
@@ -55,27 +55,14 @@
#include <guiddef.h>
#include <dxguids.h>
+#ifndef CLSID_D3D12DeviceFactory
+// Note: symbol is not available in MinGW import library.
+const CLSID CLSID_D3D12DeviceFactory = __uuidof(ID3D12DeviceFactory);
+#endif
#endif
extern "C" {
char godot_nir_arch_name[32];
-
-#ifdef AGILITY_SDK_ENABLED
-__declspec(dllexport) extern const UINT D3D12SDKVersion = 610;
-#ifdef AGILITY_SDK_MULTIARCH_ENABLED
-#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
-__declspec(dllexport) extern const char *D3D12SDKPath = "\\.\\arm64";
-#elif defined(__arm__) || defined(_M_ARM)
-__declspec(dllexport) extern const char *D3D12SDKPath = "\\.\\arm32";
-#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(_M_X64)
-__declspec(dllexport) extern const char *D3D12SDKPath = "\\.\\x86_64";
-#elif defined(__i386) || defined(__i386__) || defined(_M_IX86)
-__declspec(dllexport) extern const char *D3D12SDKPath = "\\.\\x86_32";
-#endif
-#else
-__declspec(dllexport) extern const char *D3D12SDKPath = "\\.";
-#endif // AGILITY_SDK_MULTIARCH
-#endif // AGILITY_SDK_ENABLED
}
#ifdef PIX_ENABLED
@@ -295,7 +282,12 @@ Error D3D12Context::_check_capabilities() {
Error D3D12Context::_initialize_debug_layers() {
ComPtr<ID3D12Debug> debug_controller;
- HRESULT res = D3D12GetDebugInterface(IID_PPV_ARGS(&debug_controller));
+ HRESULT res;
+ if (device_factory) {
+ res = device_factory->GetConfigurationInterface(CLSID_D3D12Debug, IID_PPV_ARGS(&debug_controller));
+ } else {
+ res = D3D12GetDebugInterface(IID_PPV_ARGS(&debug_controller));
+ }
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_QUERY_FAILED);
debug_controller->EnableDebugLayer();
return OK;
@@ -501,7 +493,12 @@ void D3D12Context::_dump_adapter_info(int p_index) {
}
Error D3D12Context::_create_device(DeviceBasics &r_basics) {
- HRESULT res = D3D12CreateDevice(gpu.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(r_basics.device.GetAddressOf()));
+ HRESULT res;
+ if (device_factory) {
+ res = device_factory->CreateDevice(gpu.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(r_basics.device.GetAddressOf()));
+ } else {
+ res = D3D12CreateDevice(gpu.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(r_basics.device.GetAddressOf()));
+ }
ERR_FAIL_COND_V_MSG(!SUCCEEDED(res), ERR_CANT_CREATE, "D3D12CreateDevice failed with error " + vformat("0x%08ux", (uint64_t)res) + ".");
// Create direct command queue.
@@ -808,7 +805,32 @@ Error D3D12Context::_update_swap_chain(Window *window) {
return OK;
}
+void D3D12Context::_init_device_factory() {
+ uint32_t agility_sdk_version = GLOBAL_GET("rendering/rendering_device/d3d12/agility_sdk_version");
+ String agility_sdk_path = String(".\\") + Engine::get_singleton()->get_architecture_name();
+
+ // Note: symbol is not available in MinGW import library.
+ PFN_D3D12_GET_INTERFACE d3d_D3D12GetInterface = (PFN_D3D12_GET_INTERFACE)GetProcAddress(LoadLibraryW(L"D3D12.dll"), "D3D12GetInterface");
+ ERR_FAIL_COND(!d3d_D3D12GetInterface);
+
+ ID3D12SDKConfiguration *sdk_config = nullptr;
+ if (SUCCEEDED(d3d_D3D12GetInterface(CLSID_D3D12SDKConfiguration, IID_PPV_ARGS(&sdk_config)))) {
+ ID3D12SDKConfiguration1 *sdk_config1 = nullptr;
+ if (SUCCEEDED(sdk_config->QueryInterface(&sdk_config1))) {
+ if (SUCCEEDED(sdk_config1->CreateDeviceFactory(agility_sdk_version, agility_sdk_path.ascii().get_data(), IID_PPV_ARGS(device_factory.GetAddressOf())))) {
+ d3d_D3D12GetInterface(CLSID_D3D12DeviceFactory, IID_PPV_ARGS(device_factory.GetAddressOf()));
+ } else if (SUCCEEDED(sdk_config1->CreateDeviceFactory(agility_sdk_version, ".\\", IID_PPV_ARGS(device_factory.GetAddressOf())))) {
+ d3d_D3D12GetInterface(CLSID_D3D12DeviceFactory, IID_PPV_ARGS(device_factory.GetAddressOf()));
+ }
+ sdk_config1->Release();
+ }
+ sdk_config->Release();
+ }
+}
+
Error D3D12Context::initialize() {
+ _init_device_factory();
+
if (_use_validation_layers()) {
Error err = _initialize_debug_layers();
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
diff --git a/drivers/d3d12/d3d12_context.h b/drivers/d3d12/d3d12_context.h
index ec4bc832b6..27ec93bb7d 100644
--- a/drivers/d3d12/d3d12_context.h
+++ b/drivers/d3d12/d3d12_context.h
@@ -110,6 +110,7 @@ private:
IMAGE_COUNT = FRAME_LAG + 1,
};
+ ComPtr<ID3D12DeviceFactory> device_factory;
ComPtr<IDXGIFactory2> dxgi_factory;
ComPtr<IDXGIAdapter> gpu;
DeviceLimits gpu_limits = {};
@@ -181,6 +182,7 @@ private:
void *p_context);
Error _initialize_debug_layers();
+ void _init_device_factory();
Error _select_adapter(int &r_index);
void _dump_adapter_info(int p_index);
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 9a77930d75..50abd5af42 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -656,6 +656,8 @@ Error OS_Unix::open_dynamic_library(const String p_path, void *&p_library_handle
path = get_executable_path().get_base_dir().path_join("../lib").path_join(p_path.get_file());
}
+ ERR_FAIL_COND_V(!FileAccess::exists(path), ERR_FILE_NOT_FOUND);
+
p_library_handle = dlopen(path.utf8().get_data(), GODOT_DLOPEN_MODE);
ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 8268cf10ae..d9d28e5c09 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -2718,9 +2718,9 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
PropertyInfo prop_info;
ClassDB::get_property_info(nd->get_class(), prop, &prop_info);
#ifdef DISABLE_DEPRECATED
- bool is_angle = prop_info.type == Variant::FLOAT && prop_info.hint_string.find("radians_as_degrees") != -1;
+ bool is_angle = prop_info.type == Variant::FLOAT && prop_info.hint_string.contains("radians_as_degrees");
#else
- bool is_angle = prop_info.type == Variant::FLOAT && prop_info.hint_string.find("radians") != -1;
+ bool is_angle = prop_info.type == Variant::FLOAT && prop_info.hint_string.contains("radians");
#endif // DISABLE_DEPRECATED
if (is_angle) {
menu->add_icon_item(get_editor_theme_icon(SNAME("InterpLinearAngle")), TTR("Linear Angle"), MENU_INTERPOLATION_LINEAR_ANGLE);
@@ -4190,27 +4190,11 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD
bool create_reset_track = p_reset_wanted && track_type_is_resettable(p_id.type);
Animation::UpdateMode update_mode = Animation::UPDATE_DISCRETE;
+ Animation::InterpolationType interp_type = Animation::INTERPOLATION_LINEAR;
+ bool loop_wrap = true;
if (create_normal_track || create_reset_track) {
if (p_id.type == Animation::TYPE_VALUE || p_id.type == Animation::TYPE_BEZIER) {
- // Hack.
- NodePath np;
- animation->add_track(p_id.type);
- animation->track_set_path(animation->get_track_count() - 1, p_id.path);
- PropertyInfo h = _find_hint_for_track(animation->get_track_count() - 1, np);
- animation->remove_track(animation->get_track_count() - 1); // Hack.
-
- if (h.type == Variant::FLOAT ||
- h.type == Variant::VECTOR2 ||
- h.type == Variant::RECT2 ||
- h.type == Variant::VECTOR3 ||
- h.type == Variant::AABB ||
- h.type == Variant::QUATERNION ||
- h.type == Variant::COLOR ||
- h.type == Variant::PLANE ||
- h.type == Variant::TRANSFORM2D ||
- h.type == Variant::TRANSFORM3D) {
- update_mode = Animation::UPDATE_CONTINUOUS;
- }
+ _fetch_value_track_options(p_id.path, &update_mode, &interp_type, &loop_wrap);
}
}
@@ -4237,6 +4221,8 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD
undo_redo->add_do_method(animation.ptr(), "add_track", p_id.type);
undo_redo->add_do_method(animation.ptr(), "track_set_path", p_id.track_idx, p_id.path);
+ undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_type", p_id.track_idx, interp_type);
+ undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_loop_wrap", p_id.track_idx, loop_wrap);
if (p_id.type == Animation::TYPE_VALUE) {
undo_redo->add_do_method(animation.ptr(), "value_track_set_update_mode", p_id.track_idx, update_mode);
}
@@ -4824,36 +4810,82 @@ void AnimationTrackEditor::_add_track(int p_type) {
pick_track->get_filter_line_edit()->grab_focus();
}
+void AnimationTrackEditor::_fetch_value_track_options(const NodePath &p_path, Animation::UpdateMode *r_update_mode, Animation::InterpolationType *r_interpolation_type, bool *r_loop_wrap) {
+ AnimationPlayer *player = AnimationPlayerEditor::get_singleton()->get_player();
+ if (player->has_animation(SceneStringNames::get_singleton()->RESET)) {
+ Ref<Animation> reset_anim = player->get_animation(SceneStringNames::get_singleton()->RESET);
+ int rt = reset_anim->find_track(p_path, Animation::TrackType::TYPE_VALUE);
+ if (rt >= 0) {
+ *r_update_mode = reset_anim->value_track_get_update_mode(rt);
+ *r_interpolation_type = reset_anim->track_get_interpolation_type(rt);
+ *r_loop_wrap = reset_anim->track_get_interpolation_loop_wrap(rt);
+ return;
+ }
+ rt = reset_anim->find_track(p_path, Animation::TrackType::TYPE_BEZIER);
+ if (rt >= 0) {
+ *r_interpolation_type = reset_anim->track_get_interpolation_type(rt);
+ *r_loop_wrap = reset_anim->track_get_interpolation_loop_wrap(rt);
+ return;
+ }
+ }
+
+ // Hack.
+ NodePath np;
+ animation->add_track(Animation::TYPE_VALUE);
+ animation->track_set_path(animation->get_track_count() - 1, p_path);
+ PropertyInfo h = _find_hint_for_track(animation->get_track_count() - 1, np);
+ animation->remove_track(animation->get_track_count() - 1); // Hack.
+ switch (h.type) {
+ case Variant::FLOAT: {
+#ifdef DISABLE_DEPRECATED
+ bool is_angle = h.type == Variant::FLOAT && h.hint_string.contains("radians_as_degrees");
+#else
+ bool is_angle = h.type == Variant::FLOAT && h.hint_string.contains("radians");
+#endif // DISABLE_DEPRECATED
+ if (is_angle) {
+ *r_interpolation_type = Animation::INTERPOLATION_LINEAR_ANGLE;
+ }
+ [[fallthrough]];
+ }
+ case Variant::VECTOR2:
+ case Variant::RECT2:
+ case Variant::VECTOR3:
+ case Variant::TRANSFORM2D:
+ case Variant::VECTOR4:
+ case Variant::PLANE:
+ case Variant::QUATERNION:
+ case Variant::AABB:
+ case Variant::BASIS:
+ case Variant::TRANSFORM3D:
+ case Variant::PROJECTION:
+ case Variant::COLOR:
+ case Variant::PACKED_FLOAT32_ARRAY:
+ case Variant::PACKED_FLOAT64_ARRAY:
+ case Variant::PACKED_VECTOR2_ARRAY:
+ case Variant::PACKED_VECTOR3_ARRAY:
+ case Variant::PACKED_COLOR_ARRAY: {
+ *r_update_mode = Animation::UPDATE_CONTINUOUS;
+ } break;
+ default: {
+ }
+ }
+}
+
void AnimationTrackEditor::_new_track_property_selected(String p_name) {
String full_path = String(adding_track_path) + ":" + p_name;
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
- if (adding_track_type == Animation::TYPE_VALUE) {
- Animation::UpdateMode update_mode = Animation::UPDATE_DISCRETE;
- {
- // Hack.
- NodePath np;
- animation->add_track(Animation::TYPE_VALUE);
- animation->track_set_path(animation->get_track_count() - 1, full_path);
- PropertyInfo h = _find_hint_for_track(animation->get_track_count() - 1, np);
- animation->remove_track(animation->get_track_count() - 1); // Hack.
- if (h.type == Variant::FLOAT ||
- h.type == Variant::VECTOR2 ||
- h.type == Variant::RECT2 ||
- h.type == Variant::VECTOR3 ||
- h.type == Variant::AABB ||
- h.type == Variant::QUATERNION ||
- h.type == Variant::COLOR ||
- h.type == Variant::PLANE ||
- h.type == Variant::TRANSFORM2D ||
- h.type == Variant::TRANSFORM3D) {
- update_mode = Animation::UPDATE_CONTINUOUS;
- }
- }
+ Animation::UpdateMode update_mode = Animation::UPDATE_DISCRETE;
+ Animation::InterpolationType interp_type = Animation::INTERPOLATION_LINEAR;
+ bool loop_wrap = true;
+ _fetch_value_track_options(full_path, &update_mode, &interp_type, &loop_wrap);
+ if (adding_track_type == Animation::TYPE_VALUE) {
undo_redo->create_action(TTR("Add Track"));
undo_redo->add_do_method(animation.ptr(), "add_track", adding_track_type);
undo_redo->add_do_method(animation.ptr(), "track_set_path", animation->get_track_count(), full_path);
+ undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_type", animation->get_track_count(), interp_type);
+ undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_loop_wrap", animation->get_track_count(), loop_wrap);
undo_redo->add_do_method(animation.ptr(), "value_track_set_update_mode", animation->get_track_count(), update_mode);
undo_redo->add_undo_method(animation.ptr(), "remove_track", animation->get_track_count());
undo_redo->commit_action();
@@ -4877,8 +4909,11 @@ void AnimationTrackEditor::_new_track_property_selected(String p_name) {
undo_redo->create_action(TTR("Add Bezier Track"));
int base_track = animation->get_track_count();
for (int i = 0; i < subindices.size(); i++) {
+ int track_idx = base_track + i;
undo_redo->add_do_method(animation.ptr(), "add_track", adding_track_type);
- undo_redo->add_do_method(animation.ptr(), "track_set_path", base_track + i, full_path + subindices[i]);
+ undo_redo->add_do_method(animation.ptr(), "track_set_path", track_idx, full_path + subindices[i]);
+ undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_type", track_idx, interp_type);
+ undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_loop_wrap", track_idx, loop_wrap);
undo_redo->add_undo_method(animation.ptr(), "remove_track", base_track);
}
undo_redo->commit_action();
@@ -6038,6 +6073,12 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
existing_idx = reset->track_find_key(dst_track, 0, Animation::FIND_MODE_APPROX);
}
+ if (animation->track_get_type(sk.track) == Animation::TYPE_VALUE) {
+ undo_redo->add_do_method(reset.ptr(), "value_track_set_update_mode", dst_track, animation->value_track_get_update_mode(sk.track));
+ undo_redo->add_do_method(reset.ptr(), "track_set_interpolation_type", dst_track, animation->track_get_interpolation_type(sk.track));
+ undo_redo->add_do_method(reset.ptr(), "track_set_interpolation_loop_wrap", dst_track, animation->track_get_interpolation_loop_wrap(sk.track));
+ }
+
undo_redo->add_do_method(reset.ptr(), "track_insert_key", dst_track, 0, animation->track_get_key_value(sk.track, sk.key), animation->track_get_key_transition(sk.track, sk.key));
undo_redo->add_undo_method(reset.ptr(), "track_remove_key_at_time", dst_track, 0);
diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h
index 4b9849b26c..0667b8e80e 100644
--- a/editor/animation_track_editor.h
+++ b/editor/animation_track_editor.h
@@ -481,6 +481,8 @@ class AnimationTrackEditor : public VBoxContainer {
void _insert_key_from_track(float p_ofs, int p_track);
void _add_method_key(const String &p_method);
+ void _fetch_value_track_options(const NodePath &p_path, Animation::UpdateMode *r_update_mode, Animation::InterpolationType *r_interpolation_type, bool *r_loop_wrap);
+
void _clear_selection_for_anim(const Ref<Animation> &p_anim);
void _select_at_anim(const Ref<Animation> &p_anim, int p_track, float p_pos);
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index 807f0c8eb7..ad11f6135c 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -2436,7 +2436,13 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) {
Error EditorFileSystem::reimport_append(const String &p_file, const HashMap<StringName, Variant> &p_custom_options, const String &p_custom_importer, Variant p_generator_parameters) {
ERR_FAIL_COND_V_MSG(!importing, ERR_INVALID_PARAMETER, "Can only append files to import during a current reimport process.");
- return _reimport_file(p_file, p_custom_options, p_custom_importer, &p_generator_parameters);
+ Error ret = _reimport_file(p_file, p_custom_options, p_custom_importer, &p_generator_parameters);
+
+ // Emit the resource_reimported signal for the single file we just reimported.
+ Vector<String> reloads;
+ reloads.append(p_file);
+ emit_signal(SNAME("resources_reimported"), reloads);
+ return ret;
}
Error EditorFileSystem::_resource_import(const String &p_path) {
diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp
index bea865af13..46d9a02e94 100644
--- a/editor/project_converter_3_to_4.cpp
+++ b/editor/project_converter_3_to_4.cpp
@@ -68,10 +68,10 @@ public:
RegEx reg_json_parse = RegEx("([\t ]{0,})([^\n]+)parse_json\\(([^\n]+)");
RegEx reg_json_non_new = RegEx("([\t ]{0,})([^\n]+)JSON\\.parse\\(([^\n]+)");
RegEx reg_json_print = RegEx("\\bJSON\\b\\.print\\(");
- RegEx reg_export_simple = RegEx("export\\(([a-zA-Z0-9_]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)");
- RegEx reg_export_typed = RegEx("export\\(([a-zA-Z0-9_]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)[ ]*:[ ]*[a-zA-Z0-9_]+");
- RegEx reg_export_inferred_type = RegEx("export\\([a-zA-Z0-9_]+\\)[ ]+var[ ]+([a-zA-Z0-9_]+)[ ]*:[ ]*=");
- RegEx reg_export_advanced = RegEx("export\\(([^)^\n]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)([^\n]+)");
+ RegEx reg_export_simple = RegEx("export[ ]*\\(([a-zA-Z0-9_]+)\\)[ ]*var[ ]+([a-zA-Z0-9_]+)");
+ RegEx reg_export_typed = RegEx("export[ ]*\\(([a-zA-Z0-9_]+)\\)[ ]*var[ ]+([a-zA-Z0-9_]+)[ ]*:[ ]*[a-zA-Z0-9_]+");
+ RegEx reg_export_inferred_type = RegEx("export[ ]*\\([a-zA-Z0-9_]+\\)[ ]*var[ ]+([a-zA-Z0-9_]+)[ ]*:[ ]*=");
+ RegEx reg_export_advanced = RegEx("export[ ]*\\(([^)^\n]+)\\)[ ]*var[ ]+([a-zA-Z0-9_]+)([^\n]+)");
RegEx reg_setget_setget = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+?)[ \t]*setget[ \t]+([a-zA-Z0-9_]+)[ \t]*,[ \t]*([a-zA-Z0-9_]+)");
RegEx reg_setget_set = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+?)[ \t]*setget[ \t]+([a-zA-Z0-9_]+)[ \t]*[,]*[^\n]*$");
RegEx reg_setget_get = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+?)[ \t]*setget[ \t]+,[ \t]*([a-zA-Z0-9_]+)[ \t]*$");
@@ -931,6 +931,7 @@ bool ProjectConverter3To4::test_conversion(RegExContainer &reg_container) {
valid = valid && test_conversion_gdscript_builtin(" Transform.xform_inv(Vector3(a,b,c) + Vector3.UP) ", " (Vector3(a,b,c) + Vector3.UP) * Transform ", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
valid = valid && test_conversion_gdscript_builtin("export(float) var lifetime = 3.0", "export var lifetime: float = 3.0", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
+ valid = valid && test_conversion_gdscript_builtin("export (int)var spaces=1", "export var spaces: int=1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
valid = valid && test_conversion_gdscript_builtin("export(String, 'AnonymousPro', 'CourierPrime') var _font_name = 'AnonymousPro'", "export var _font_name = 'AnonymousPro' # (String, 'AnonymousPro', 'CourierPrime')", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); // TODO, this is only a workaround
valid = valid && test_conversion_gdscript_builtin("export(PackedScene) var mob_scene", "export var mob_scene: PackedScene", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
valid = valid && test_conversion_gdscript_builtin("export(float) var lifetime: float = 3.0", "export var lifetime: float = 3.0", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 5478a46bbc..cf537bde16 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -3658,6 +3658,10 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
return;
}
}
+ if (Variant::has_builtin_method(base.builtin_type, name)) {
+ p_identifier->set_datatype(make_callable_type(Variant::get_builtin_method_info(base.builtin_type, name)));
+ return;
+ }
if (base.is_hard_type()) {
#ifdef SUGGEST_GODOT4_RENAMES
String rename_hint = String();
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 9560f670e6..ee360e581b 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -322,9 +322,13 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
if (member.type == GDScriptParser::ClassNode::Member::FUNCTION || member.type == GDScriptParser::ClassNode::Member::SIGNAL) {
// Get like it was a property.
GDScriptCodeGenerator::Address temp = codegen.add_temporary(); // TODO: Get type here.
- GDScriptCodeGenerator::Address self(GDScriptCodeGenerator::Address::SELF);
- gen->write_get_named(temp, identifier, self);
+ GDScriptCodeGenerator::Address base(GDScriptCodeGenerator::Address::SELF);
+ if (member.type == GDScriptParser::ClassNode::Member::FUNCTION && member.function->is_static) {
+ base = GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::CLASS);
+ }
+
+ gen->write_get_named(temp, identifier, base);
return temp;
}
}
diff --git a/modules/gdscript/tests/scripts/runtime/features/builtin_method_as_callable.gd b/modules/gdscript/tests/scripts/runtime/features/builtin_method_as_callable.gd
new file mode 100644
index 0000000000..e4016c0119
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/builtin_method_as_callable.gd
@@ -0,0 +1,6 @@
+func test():
+ var array: Array = [1, 2, 3]
+ print(array)
+ var callable: Callable = array.clear
+ callable.call()
+ print(array)
diff --git a/modules/gdscript/tests/scripts/runtime/features/builtin_method_as_callable.out b/modules/gdscript/tests/scripts/runtime/features/builtin_method_as_callable.out
new file mode 100644
index 0000000000..c4182b38e9
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/builtin_method_as_callable.out
@@ -0,0 +1,3 @@
+GDTEST_OK
+[1, 2, 3]
+[]
diff --git a/modules/gdscript/tests/scripts/runtime/features/static_method_as_callable.gd b/modules/gdscript/tests/scripts/runtime/features/static_method_as_callable.gd
index f6aa58737f..97e9da3b26 100644
--- a/modules/gdscript/tests/scripts/runtime/features/static_method_as_callable.gd
+++ b/modules/gdscript/tests/scripts/runtime/features/static_method_as_callable.gd
@@ -1,12 +1,18 @@
-# GH-79521
+# GH-79521, GH-86032
class_name TestStaticMethodAsCallable
static func static_func() -> String:
return "Test"
+static func another_static_func():
+ prints("another_static_func:", static_func.call(), static_func.is_valid())
+
func test():
var a: Callable = TestStaticMethodAsCallable.static_func
var b: Callable = static_func
prints(a.call(), a.is_valid())
prints(b.call(), b.is_valid())
+ @warning_ignore("static_called_on_instance")
+ another_static_func()
+ TestStaticMethodAsCallable.another_static_func()
diff --git a/modules/gdscript/tests/scripts/runtime/features/static_method_as_callable.out b/modules/gdscript/tests/scripts/runtime/features/static_method_as_callable.out
index e6d461b8f9..2b773ce8ee 100644
--- a/modules/gdscript/tests/scripts/runtime/features/static_method_as_callable.out
+++ b/modules/gdscript/tests/scripts/runtime/features/static_method_as_callable.out
@@ -1,3 +1,5 @@
GDTEST_OK
Test true
Test true
+another_static_func: Test true
+another_static_func: Test true
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index 030c3f88b0..e3824562bf 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -3218,7 +3218,7 @@ void GLTFDocument::_parse_image_save_image(Ref<GLTFState> p_state, const Vector<
bool must_import = true;
Vector<uint8_t> img_data = p_image->get_data();
Dictionary generator_parameters;
- String file_path = p_state->get_base_path() + "/" + p_state->filename.get_basename() + "_" + p_image->get_name();
+ String file_path = p_state->get_base_path().path_join(p_state->filename.get_basename() + "_" + p_image->get_name());
file_path += p_file_extension.is_empty() ? ".png" : p_file_extension;
if (FileAccess::exists(file_path + ".import")) {
Ref<ConfigFile> config;
@@ -3230,6 +3230,8 @@ void GLTFDocument::_parse_image_save_image(Ref<GLTFState> p_state, const Vector<
if (!generator_parameters.has("md5")) {
must_import = false; // Didn't come from a gltf document; don't overwrite.
}
+ }
+ if (must_import) {
String existing_md5 = generator_parameters["md5"];
unsigned char md5_hash[16];
CryptoCore::md5(img_data.ptr(), img_data.size(), md5_hash);
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 0d82bec75d..35d4222152 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -170,6 +170,8 @@ Error OS_Android::open_dynamic_library(const String p_path, void *&p_library_han
so_file_exists = false;
}
+ ERR_FAIL_COND_V(!FileAccess::exists(path), ERR_FILE_NOT_FOUND);
+
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
if (!p_library_handle && so_file_exists) {
// The library may be on the sdcard and thus inaccessible. Try to copy it to the internal
diff --git a/platform/ios/os_ios.mm b/platform/ios/os_ios.mm
index a646705305..80f1f4a5c2 100644
--- a/platform/ios/os_ios.mm
+++ b/platform/ios/os_ios.mm
@@ -257,6 +257,8 @@ Error OS_IOS::open_dynamic_library(const String p_path, void *&p_library_handle,
path = get_framework_executable(get_executable_path().get_base_dir().path_join("Frameworks").path_join(p_path.get_file().get_basename() + ".framework"));
}
+ ERR_FAIL_COND_V(!FileAccess::exists(path), ERR_FILE_NOT_FOUND);
+
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
diff --git a/platform/macos/os_macos.mm b/platform/macos/os_macos.mm
index 29dff683d5..b8496d72fb 100644
--- a/platform/macos/os_macos.mm
+++ b/platform/macos/os_macos.mm
@@ -230,6 +230,8 @@ Error OS_MacOS::open_dynamic_library(const String p_path, void *&p_library_handl
path = get_framework_executable(get_executable_path().get_base_dir().path_join("../Frameworks").path_join(p_path.get_file()));
}
+ ERR_FAIL_COND_V(!FileAccess::exists(path), ERR_FILE_NOT_FOUND);
+
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 1d3b80e21e..6ad616da85 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -360,6 +360,8 @@ Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_han
path = get_executable_path().get_base_dir().path_join(p_path.get_file());
}
+ ERR_FAIL_COND_V(!FileAccess::exists(path), ERR_FILE_NOT_FOUND);
+
typedef DLL_DIRECTORY_COOKIE(WINAPI * PAddDllDirectory)(PCWSTR);
typedef BOOL(WINAPI * PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE);
@@ -1183,7 +1185,7 @@ Vector<String> OS_Windows::get_system_font_path_for_text(const String &p_font_na
if (FAILED(hr)) {
continue;
}
- String fpath = String::utf16((const char16_t *)&file_path[0]);
+ String fpath = String::utf16((const char16_t *)&file_path[0]).replace("\\", "/");
WIN32_FIND_DATAW d;
HANDLE fnd = FindFirstFileW((LPCWSTR)&file_path[0], &d);
@@ -1262,7 +1264,7 @@ String OS_Windows::get_system_font_path(const String &p_font_name, int p_weight,
if (FAILED(hr)) {
continue;
}
- String fpath = String::utf16((const char16_t *)&file_path[0]);
+ String fpath = String::utf16((const char16_t *)&file_path[0]).replace("\\", "/");
WIN32_FIND_DATAW d;
HANDLE fnd = FindFirstFileW((LPCWSTR)&file_path[0], &d);
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index d9c633b238..3d61744786 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -42,6 +42,21 @@
HashMap<String, PopupMenu *> PopupMenu::system_menus;
+bool PopupMenu::_set_item_accelerator(int p_index, const Ref<InputEventKey> &p_ie) {
+ DisplayServer *ds = DisplayServer::get_singleton();
+ if (p_ie->get_physical_keycode() == Key::NONE && p_ie->get_keycode() == Key::NONE && p_ie->get_key_label() != Key::NONE) {
+ ds->global_menu_set_item_accelerator(global_menu_name, p_index, p_ie->get_key_label_with_modifiers());
+ return true;
+ } else if (p_ie->get_keycode() != Key::NONE) {
+ ds->global_menu_set_item_accelerator(global_menu_name, p_index, p_ie->get_keycode_with_modifiers());
+ return true;
+ } else if (p_ie->get_physical_keycode() != Key::NONE) {
+ ds->global_menu_set_item_accelerator(global_menu_name, p_index, ds->keyboard_get_keycode_from_physical(p_ie->get_physical_keycode_with_modifiers()));
+ return true;
+ }
+ return false;
+}
+
String PopupMenu::bind_global_menu() {
#ifdef TOOLS_ENABLED
if (is_part_of_edited_scene()) {
@@ -101,8 +116,7 @@ String PopupMenu::bind_global_menu() {
Array events = item.shortcut->get_events();
for (int j = 0; j < events.size(); j++) {
Ref<InputEventKey> ie = events[j];
- if (ie.is_valid()) {
- ds->global_menu_set_item_accelerator(global_menu_name, index, ie->get_keycode_with_modifiers());
+ if (ie.is_valid() && _set_item_accelerator(index, ie)) {
break;
}
}
@@ -1368,8 +1382,7 @@ void PopupMenu::add_shortcut(const Ref<Shortcut> &p_shortcut, int p_id, bool p_g
Array events = item.shortcut->get_events();
for (int j = 0; j < events.size(); j++) {
Ref<InputEventKey> ie = events[j];
- if (ie.is_valid()) {
- ds->global_menu_set_item_accelerator(global_menu_name, index, ie->get_keycode_with_modifiers());
+ if (ie.is_valid() && _set_item_accelerator(index, ie)) {
break;
}
}
@@ -1397,8 +1410,7 @@ void PopupMenu::add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<Shortc
Array events = item.shortcut->get_events();
for (int j = 0; j < events.size(); j++) {
Ref<InputEventKey> ie = events[j];
- if (ie.is_valid()) {
- ds->global_menu_set_item_accelerator(global_menu_name, index, ie->get_keycode_with_modifiers());
+ if (ie.is_valid() && _set_item_accelerator(index, ie)) {
break;
}
}
@@ -1427,8 +1439,7 @@ void PopupMenu::add_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_id, bo
Array events = item.shortcut->get_events();
for (int j = 0; j < events.size(); j++) {
Ref<InputEventKey> ie = events[j];
- if (ie.is_valid()) {
- ds->global_menu_set_item_accelerator(global_menu_name, index, ie->get_keycode_with_modifiers());
+ if (ie.is_valid() && _set_item_accelerator(index, ie)) {
break;
}
}
@@ -1458,8 +1469,7 @@ void PopupMenu::add_icon_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<
Array events = item.shortcut->get_events();
for (int j = 0; j < events.size(); j++) {
Ref<InputEventKey> ie = events[j];
- if (ie.is_valid()) {
- ds->global_menu_set_item_accelerator(global_menu_name, index, ie->get_keycode_with_modifiers());
+ if (ie.is_valid() && _set_item_accelerator(index, ie)) {
break;
}
}
@@ -1489,8 +1499,7 @@ void PopupMenu::add_radio_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_
Array events = item.shortcut->get_events();
for (int j = 0; j < events.size(); j++) {
Ref<InputEventKey> ie = events[j];
- if (ie.is_valid()) {
- ds->global_menu_set_item_accelerator(global_menu_name, index, ie->get_keycode_with_modifiers());
+ if (ie.is_valid() && _set_item_accelerator(index, ie)) {
break;
}
}
@@ -1520,8 +1529,7 @@ void PopupMenu::add_icon_radio_check_shortcut(const Ref<Texture2D> &p_icon, cons
Array events = item.shortcut->get_events();
for (int j = 0; j < events.size(); j++) {
Ref<InputEventKey> ie = events[j];
- if (ie.is_valid()) {
- ds->global_menu_set_item_accelerator(global_menu_name, index, ie->get_keycode_with_modifiers());
+ if (ie.is_valid() && _set_item_accelerator(index, ie)) {
break;
}
}
@@ -2045,8 +2053,7 @@ void PopupMenu::set_item_shortcut(int p_idx, const Ref<Shortcut> &p_shortcut, bo
Array events = items[p_idx].shortcut->get_events();
for (int j = 0; j < events.size(); j++) {
Ref<InputEventKey> ie = events[j];
- if (ie.is_valid()) {
- ds->global_menu_set_item_accelerator(global_menu_name, p_idx, ie->get_keycode_with_modifiers());
+ if (ie.is_valid() && _set_item_accelerator(p_idx, ie)) {
break;
}
}
@@ -2116,8 +2123,7 @@ void PopupMenu::set_item_shortcut_disabled(int p_idx, bool p_disabled) {
Array events = items[p_idx].shortcut->get_events();
for (int j = 0; j < events.size(); j++) {
Ref<InputEventKey> ie = events[j];
- if (ie.is_valid()) {
- ds->global_menu_set_item_accelerator(global_menu_name, p_idx, ie->get_keycode_with_modifiers());
+ if (ie.is_valid() && _set_item_accelerator(p_idx, ie)) {
break;
}
}
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index c1ab9544ea..9783f9d57b 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -194,6 +194,7 @@ class PopupMenu : public Popup {
void _close_pressed();
void _menu_changed();
void _input_from_window_internal(const Ref<InputEvent> &p_event);
+ bool _set_item_accelerator(int p_index, const Ref<InputEventKey> &p_ie);
protected:
virtual void add_child_notify(Node *p_child) override;
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 89ec5636ab..2f0cfda898 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -2073,7 +2073,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Window *w = Object::cast_to<Window>(ObjectDB::get_instance(object_under));
if (w) {
viewport_under = w;
- viewport_pos = screen_mouse_pos - w->get_position();
+ viewport_pos = w->get_final_transform().affine_inverse().xform(screen_mouse_pos - w->get_position());
}
}
}
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 52850cac4a..1ab11cfdf0 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -2394,79 +2394,7 @@ Quaternion Animation::_cubic_interpolate_in_time(const Quaternion &p_pre_a, cons
}
Variant Animation::_cubic_interpolate_in_time(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const {
- Variant::Type type_a = p_a.get_type();
- Variant::Type type_b = p_b.get_type();
- Variant::Type type_pa = p_pre_a.get_type();
- Variant::Type type_pb = p_post_b.get_type();
-
- //make int and real play along
-
- uint32_t vformat = 1 << type_a;
- vformat |= 1 << type_b;
- vformat |= 1 << type_pa;
- vformat |= 1 << type_pb;
-
- if (vformat == ((1 << Variant::INT) | (1 << Variant::FLOAT)) || vformat == (1 << Variant::FLOAT)) {
- //mix of real and int
- real_t a = p_a;
- real_t b = p_b;
- real_t pa = p_pre_a;
- real_t pb = p_post_b;
-
- return Math::cubic_interpolate_in_time(a, b, pa, pb, p_c, p_b_t, p_pre_a_t, p_post_b_t);
- } else if ((vformat & (vformat - 1))) {
- return p_a; //can't interpolate, mix of types
- }
-
- switch (type_a) {
- case Variant::VECTOR2: {
- Vector2 a = p_a;
- Vector2 b = p_b;
- Vector2 pa = p_pre_a;
- Vector2 pb = p_post_b;
-
- return a.cubic_interpolate_in_time(b, pa, pb, p_c, p_b_t, p_pre_a_t, p_post_b_t);
- }
- case Variant::RECT2: {
- Rect2 a = p_a;
- Rect2 b = p_b;
- Rect2 pa = p_pre_a;
- Rect2 pb = p_post_b;
-
- return Rect2(
- a.position.cubic_interpolate_in_time(b.position, pa.position, pb.position, p_c, p_b_t, p_pre_a_t, p_post_b_t),
- a.size.cubic_interpolate_in_time(b.size, pa.size, pb.size, p_c, p_b_t, p_pre_a_t, p_post_b_t));
- }
- case Variant::VECTOR3: {
- Vector3 a = p_a;
- Vector3 b = p_b;
- Vector3 pa = p_pre_a;
- Vector3 pb = p_post_b;
-
- return a.cubic_interpolate_in_time(b, pa, pb, p_c, p_b_t, p_pre_a_t, p_post_b_t);
- }
- case Variant::QUATERNION: {
- Quaternion a = p_a;
- Quaternion b = p_b;
- Quaternion pa = p_pre_a;
- Quaternion pb = p_post_b;
-
- return a.spherical_cubic_interpolate_in_time(b, pa, pb, p_c, p_b_t, p_pre_a_t, p_post_b_t);
- }
- case Variant::AABB: {
- AABB a = p_a;
- AABB b = p_b;
- AABB pa = p_pre_a;
- AABB pb = p_post_b;
-
- return AABB(
- a.position.cubic_interpolate_in_time(b.position, pa.position, pb.position, p_c, p_b_t, p_pre_a_t, p_post_b_t),
- a.size.cubic_interpolate_in_time(b.size, pa.size, pb.size, p_c, p_b_t, p_pre_a_t, p_post_b_t));
- }
- default: {
- return _interpolate(p_a, p_b, p_c);
- }
- }
+ return cubic_interpolate_in_time_variant(p_pre_a, p_a, p_b, p_post_b, p_c, p_pre_a_t, p_b_t, p_post_b_t);
}
real_t Animation::_cubic_interpolate_in_time(const real_t &p_pre_a, const real_t &p_a, const real_t &p_b, const real_t &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const {
@@ -2489,7 +2417,7 @@ Variant Animation::_cubic_interpolate_angle_in_time(const Variant &p_pre_a, cons
real_t pb = p_post_b;
return Math::fposmod((float)Math::cubic_interpolate_angle_in_time(a, b, pa, pb, p_c, p_b_t, p_pre_a_t, p_post_b_t), (float)Math_TAU);
}
- return _interpolate(p_a, p_b, p_c);
+ return _cubic_interpolate_in_time(p_pre_a, p_a, p_b, p_post_b, p_c, p_pre_a_t, p_b_t, p_post_b_t);
}
template <class T>
@@ -5972,8 +5900,7 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float
return Variant();
} break;
case Variant::FLOAT: {
- const double va = a.operator double();
- return va + ((b.operator double()) - va) * c;
+ return Math::lerp(a.operator double(), b.operator double(), (double)c);
} break;
case Variant::VECTOR2: {
return (a.operator Vector2()).lerp(b.operator Vector2(), c);
@@ -5992,7 +5919,7 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float
case Variant::PLANE: {
const Plane pa = a.operator Plane();
const Plane pb = b.operator Plane();
- return Plane(pa.normal.lerp(pb.normal, c), pa.d + (pb.d - pa.d) * c);
+ return Plane(pa.normal.lerp(pb.normal, c), Math::lerp((double)pa.d, (double)pb.d, (double)c));
} break;
case Variant::COLOR: {
return (a.operator Color()).lerp(b.operator Color(), c);
@@ -6102,6 +6029,194 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float
return c < 0.5 ? a : b;
}
+Variant Animation::cubic_interpolate_in_time_variant(const Variant &pre_a, const Variant &a, const Variant &b, const Variant &post_b, float c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t, bool p_snap_array_element) {
+ if (pre_a.get_type() != a.get_type() || pre_a.get_type() != b.get_type() || pre_a.get_type() != post_b.get_type()) {
+ if (pre_a.is_num() && a.is_num() && b.is_num() && post_b.is_num()) {
+ return cubic_interpolate_in_time_variant(cast_to_blendwise(pre_a), cast_to_blendwise(a), cast_to_blendwise(b), cast_to_blendwise(post_b), c, p_pre_a_t, p_b_t, p_post_b_t, p_snap_array_element);
+ } else if (!a.is_array()) {
+ return a;
+ }
+ }
+
+ switch (a.get_type()) {
+ case Variant::NIL: {
+ return Variant();
+ } break;
+ case Variant::FLOAT: {
+ return Math::cubic_interpolate_in_time(a.operator double(), b.operator double(), pre_a.operator double(), post_b.operator double(), (double)c, (double)p_pre_a_t, (double)p_b_t, (double)p_post_b_t);
+ } break;
+ case Variant::VECTOR2: {
+ return (a.operator Vector2()).cubic_interpolate_in_time(b.operator Vector2(), pre_a.operator Vector2(), post_b.operator Vector2(), c, p_b_t, p_pre_a_t, p_post_b_t);
+ } break;
+ case Variant::RECT2: {
+ const Rect2 rpa = pre_a.operator Rect2();
+ const Rect2 ra = a.operator Rect2();
+ const Rect2 rb = b.operator Rect2();
+ const Rect2 rpb = post_b.operator Rect2();
+ return Rect2(
+ ra.position.cubic_interpolate_in_time(rb.position, rpa.position, rpb.position, c, p_b_t, p_pre_a_t, p_post_b_t),
+ ra.size.cubic_interpolate_in_time(rb.size, rpa.size, rpb.size, c, p_b_t, p_pre_a_t, p_post_b_t));
+ } break;
+ case Variant::VECTOR3: {
+ return (a.operator Vector3()).cubic_interpolate_in_time(b.operator Vector3(), pre_a.operator Vector3(), post_b.operator Vector3(), c, p_b_t, p_pre_a_t, p_post_b_t);
+ } break;
+ case Variant::VECTOR4: {
+ return (a.operator Vector4()).cubic_interpolate_in_time(b.operator Vector4(), pre_a.operator Vector4(), post_b.operator Vector4(), c, p_b_t, p_pre_a_t, p_post_b_t);
+ } break;
+ case Variant::PLANE: {
+ const Plane ppa = pre_a.operator Plane();
+ const Plane pa = a.operator Plane();
+ const Plane pb = b.operator Plane();
+ const Plane ppb = post_b.operator Plane();
+ return Plane(
+ pa.normal.cubic_interpolate_in_time(pb.normal, ppa.normal, ppb.normal, c, p_b_t, p_pre_a_t, p_post_b_t),
+ Math::cubic_interpolate_in_time((double)pa.d, (double)pb.d, (double)ppa.d, (double)ppb.d, (double)c, (double)p_b_t, (double)p_pre_a_t, (double)p_post_b_t));
+ } break;
+ case Variant::COLOR: {
+ const Color cpa = pre_a.operator Color();
+ const Color ca = a.operator Color();
+ const Color cb = b.operator Color();
+ const Color cpb = post_b.operator Color();
+ return Color(
+ Math::cubic_interpolate_in_time((double)ca.r, (double)cb.r, (double)cpa.r, (double)cpb.r, (double)c, (double)p_pre_a_t, (double)p_b_t, (double)p_post_b_t),
+ Math::cubic_interpolate_in_time((double)ca.g, (double)cb.g, (double)cpa.g, (double)cpb.g, (double)c, (double)p_pre_a_t, (double)p_b_t, (double)p_post_b_t),
+ Math::cubic_interpolate_in_time((double)ca.b, (double)cb.b, (double)cpa.b, (double)cpb.b, (double)c, (double)p_pre_a_t, (double)p_b_t, (double)p_post_b_t),
+ Math::cubic_interpolate_in_time((double)ca.a, (double)cb.a, (double)cpa.a, (double)cpb.a, (double)c, (double)p_pre_a_t, (double)p_b_t, (double)p_post_b_t));
+ } break;
+ case Variant::AABB: {
+ const ::AABB apa = pre_a.operator ::AABB();
+ const ::AABB aa = a.operator ::AABB();
+ const ::AABB ab = b.operator ::AABB();
+ const ::AABB apb = post_b.operator ::AABB();
+ return AABB(
+ aa.position.cubic_interpolate_in_time(ab.position, apa.position, apb.position, c, p_b_t, p_pre_a_t, p_post_b_t),
+ aa.size.cubic_interpolate_in_time(ab.size, apa.size, apb.size, c, p_b_t, p_pre_a_t, p_post_b_t));
+ } break;
+ case Variant::BASIS: {
+ const Basis bpa = pre_a.operator Basis();
+ const Basis ba = a.operator Basis();
+ const Basis bb = b.operator Basis();
+ const Basis bpb = post_b.operator Basis();
+ return Basis(
+ ba.rows[0].cubic_interpolate_in_time(bb.rows[0], bpa.rows[0], bpb.rows[0], c, p_pre_a_t, p_b_t, p_post_b_t),
+ ba.rows[1].cubic_interpolate_in_time(bb.rows[1], bpa.rows[1], bpb.rows[1], c, p_pre_a_t, p_b_t, p_post_b_t),
+ ba.rows[2].cubic_interpolate_in_time(bb.rows[2], bpa.rows[2], bpb.rows[2], c, p_pre_a_t, p_b_t, p_post_b_t));
+ } break;
+ case Variant::QUATERNION: {
+ return (a.operator Quaternion()).spherical_cubic_interpolate_in_time(b.operator Quaternion(), pre_a.operator Quaternion(), post_b.operator Quaternion(), c, p_b_t, p_pre_a_t, p_post_b_t);
+ } break;
+ case Variant::TRANSFORM2D: {
+ const Transform2D tpa = pre_a.operator Transform2D();
+ const Transform2D ta = a.operator Transform2D();
+ const Transform2D tb = b.operator Transform2D();
+ const Transform2D tpb = post_b.operator Transform2D();
+ // TODO: May cause unintended skew, we needs spherical_cubic_interpolate_in_time() for angle and Transform2D::cubic_interpolate_with().
+ return Transform2D(
+ ta[0].cubic_interpolate_in_time(tb[0], tpa[0], tpb[0], c, p_pre_a_t, p_b_t, p_post_b_t),
+ ta[1].cubic_interpolate_in_time(tb[1], tpa[1], tpb[1], c, p_pre_a_t, p_b_t, p_post_b_t),
+ ta[2].cubic_interpolate_in_time(tb[2], tpa[2], tpb[2], c, p_pre_a_t, p_b_t, p_post_b_t));
+ } break;
+ case Variant::TRANSFORM3D: {
+ const Transform3D tpa = pre_a.operator Transform3D();
+ const Transform3D ta = a.operator Transform3D();
+ const Transform3D tb = b.operator Transform3D();
+ const Transform3D tpb = post_b.operator Transform3D();
+ // TODO: May cause unintended skew, we needs Transform3D::cubic_interpolate_with().
+ return Transform3D(
+ ta.basis.rows[0].cubic_interpolate_in_time(tb.basis.rows[0], tpa.basis.rows[0], tpb.basis.rows[0], c, p_pre_a_t, p_b_t, p_post_b_t),
+ ta.basis.rows[1].cubic_interpolate_in_time(tb.basis.rows[1], tpa.basis.rows[1], tpb.basis.rows[1], c, p_pre_a_t, p_b_t, p_post_b_t),
+ ta.basis.rows[2].cubic_interpolate_in_time(tb.basis.rows[2], tpa.basis.rows[2], tpb.basis.rows[2], c, p_pre_a_t, p_b_t, p_post_b_t),
+ ta.origin.cubic_interpolate_in_time(tb.origin, tpa.origin, tpb.origin, c, p_pre_a_t, p_b_t, p_post_b_t));
+ } break;
+ case Variant::BOOL:
+ case Variant::INT:
+ case Variant::RECT2I:
+ case Variant::VECTOR2I:
+ case Variant::VECTOR3I:
+ case Variant::VECTOR4I:
+ case Variant::PACKED_INT32_ARRAY:
+ case Variant::PACKED_INT64_ARRAY: {
+ // Fallback the interpolatable value which needs casting.
+ return cast_from_blendwise(cubic_interpolate_in_time_variant(cast_to_blendwise(pre_a), cast_to_blendwise(a), cast_to_blendwise(b), cast_to_blendwise(post_b), c, p_pre_a_t, p_b_t, p_post_b_t, p_snap_array_element), a.get_type());
+ } break;
+ case Variant::STRING:
+ case Variant::STRING_NAME: {
+ // TODO:
+ // String interpolation works on both the character array size and the character code, to apply cubic interpolation neatly,
+ // we need to figure out how to interpolate well in cases where there are fewer than 4 keys. So, for now, fallback to linear interpolation.
+ return interpolate_variant(a, b, c);
+ } break;
+ case Variant::PACKED_BYTE_ARRAY: {
+ // Skip.
+ } break;
+ default: {
+ if (a.is_array()) {
+ const Array arr_pa = pre_a.operator Array();
+ const Array arr_a = a.operator Array();
+ const Array arr_b = b.operator Array();
+ const Array arr_pb = post_b.operator Array();
+
+ int min_size = arr_a.size();
+ int max_size = arr_b.size();
+ bool is_a_larger = inform_variant_array(min_size, max_size);
+
+ Array result;
+ result.set_typed(MAX(arr_a.get_typed_builtin(), arr_b.get_typed_builtin()), StringName(), Variant());
+ result.resize(min_size);
+
+ if (min_size == 0 && max_size == 0) {
+ return result;
+ }
+
+ Variant vz;
+ if (is_a_larger) {
+ vz = arr_a[0];
+ } else {
+ vz = arr_b[0];
+ }
+ vz.zero();
+ Variant pre_last = arr_pa.size() ? arr_pa[arr_pa.size() - 1] : vz;
+ Variant post_last = arr_pb.size() ? arr_pb[arr_pb.size() - 1] : vz;
+
+ int i = 0;
+ for (; i < min_size; i++) {
+ result[i] = cubic_interpolate_in_time_variant(i >= arr_pa.size() ? pre_last : arr_pa[i], arr_a[i], arr_b[i], i >= arr_pb.size() ? post_last : arr_pb[i], c, p_pre_a_t, p_b_t, p_post_b_t);
+ }
+ if (min_size != max_size) {
+ // Process with last element of the lesser array.
+ // This is pretty funny and bizarre, but artists like to use it for polygon animation.
+ Variant lesser_last = vz;
+ if (is_a_larger && !Math::is_equal_approx(c, 1.0f)) {
+ result.resize(max_size);
+ if (p_snap_array_element) {
+ c = 0;
+ }
+ if (i > 0) {
+ lesser_last = arr_b[i - 1];
+ }
+ for (; i < max_size; i++) {
+ result[i] = cubic_interpolate_in_time_variant(i >= arr_pa.size() ? pre_last : arr_pa[i], arr_a[i], lesser_last, i >= arr_pb.size() ? post_last : arr_pb[i], c, p_pre_a_t, p_b_t, p_post_b_t);
+ }
+ } else if (!is_a_larger && !Math::is_zero_approx(c)) {
+ result.resize(max_size);
+ if (p_snap_array_element) {
+ c = 1;
+ }
+ if (i > 0) {
+ lesser_last = arr_a[i - 1];
+ }
+ for (; i < max_size; i++) {
+ result[i] = cubic_interpolate_in_time_variant(i >= arr_pa.size() ? pre_last : arr_pa[i], lesser_last, arr_b[i], i >= arr_pb.size() ? post_last : arr_pb[i], c, p_pre_a_t, p_b_t, p_post_b_t);
+ }
+ }
+ }
+ return result;
+ }
+ } break;
+ }
+ return c < 0.5 ? a : b;
+}
+
bool Animation::inform_variant_array(int &r_min, int &r_max) {
if (r_min <= r_max) {
return false;
diff --git a/scene/resources/animation.h b/scene/resources/animation.h
index 2579b6c8ce..54a78fffa4 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -502,6 +502,7 @@ public:
static Variant subtract_variant(const Variant &a, const Variant &b);
static Variant blend_variant(const Variant &a, const Variant &b, float c);
static Variant interpolate_variant(const Variant &a, const Variant &b, float c, bool p_snap_array_element = false);
+ static Variant cubic_interpolate_in_time_variant(const Variant &pre_a, const Variant &a, const Variant &b, const Variant &post_b, float c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t, bool p_snap_array_element = false);
Animation();
~Animation();
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 511a8b3122..f1848b0b94 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -1147,6 +1147,7 @@ void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, Has
for (int channel_idx = 0; channel_idx < MAX_CHANNELS_PER_BUS; channel_idx++) {
new_bus_details->volume[idx][channel_idx] = pair.value[channel_idx];
}
+ idx++;
}
playback_node->bus_details = new_bus_details;
playback_node->prev_bus_details = new AudioStreamPlaybackBusDetails();
diff --git a/servers/physics_server_2d_wrap_mt.cpp b/servers/physics_server_2d_wrap_mt.cpp
index f4682b7c14..a23bb5e701 100644
--- a/servers/physics_server_2d_wrap_mt.cpp
+++ b/servers/physics_server_2d_wrap_mt.cpp
@@ -120,8 +120,6 @@ PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool
physics_server_2d = p_contained;
create_thread = p_create_thread;
- pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
-
if (!p_create_thread) {
server_thread = Thread::get_caller_id();
} else {
diff --git a/servers/physics_server_2d_wrap_mt.h b/servers/physics_server_2d_wrap_mt.h
index 0ae004da19..3bebe5df85 100644
--- a/servers/physics_server_2d_wrap_mt.h
+++ b/servers/physics_server_2d_wrap_mt.h
@@ -66,7 +66,6 @@ class PhysicsServer2DWrapMT : public PhysicsServer2D {
bool first_frame = true;
Mutex alloc_mutex;
- int pool_max_size = 0;
public:
#define ServerName PhysicsServer2D
diff --git a/servers/physics_server_3d_wrap_mt.cpp b/servers/physics_server_3d_wrap_mt.cpp
index 59db4617d0..feb17cad84 100644
--- a/servers/physics_server_3d_wrap_mt.cpp
+++ b/servers/physics_server_3d_wrap_mt.cpp
@@ -120,8 +120,6 @@ PhysicsServer3DWrapMT::PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool
physics_server_3d = p_contained;
create_thread = p_create_thread;
- pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
-
if (!p_create_thread) {
server_thread = Thread::get_caller_id();
} else {
diff --git a/servers/physics_server_3d_wrap_mt.h b/servers/physics_server_3d_wrap_mt.h
index 99179d8248..fc8930977d 100644
--- a/servers/physics_server_3d_wrap_mt.h
+++ b/servers/physics_server_3d_wrap_mt.h
@@ -65,7 +65,6 @@ class PhysicsServer3DWrapMT : public PhysicsServer3D {
bool first_frame = true;
Mutex alloc_mutex;
- int pool_max_size = 0;
public:
#define ServerName PhysicsServer3D
diff --git a/thirdparty/linuxbsd_headers/README.md b/thirdparty/linuxbsd_headers/README.md
index af902aa97a..225dd62ad0 100644
--- a/thirdparty/linuxbsd_headers/README.md
+++ b/thirdparty/linuxbsd_headers/README.md
@@ -9,20 +9,21 @@ readability.
- Upstream: https://www.alsa-project.org/
- Version: 1.1.3-5
-- License: LPGL-2.1+
+- License: LGPL-2.1+
Patches in the `patches` directory should be re-applied after updates.
+
## dbus
-- Upstream: https://www.freedesktop.org/wiki/software/dbus/
+- Upstream: https://www.freedesktop.org/wiki/Software/dbus/
- Version: 1.12.2
- License: AFL-2.1
## fontconfig
-- Upstream: https://www.freedesktop.org/wiki/software/fontconfig/
+- Upstream: https://www.freedesktop.org/wiki/Software/fontconfig/
- Version: 2.12.6
- License: fontconfig
@@ -31,21 +32,21 @@ Patches in the `patches` directory should be re-applied after updates.
- Upstream: http://pulseaudio.org/
- Version: 1.11.1
-- License: LPGL-2.1+
+- License: LGPL-2.1+
-# speechd
+## speechd
- Upstream: https://www.freebsoft.org/pub/projects/speechd/
- Version: 0.8.8
-- License: LPGL-2.1+
+- License: LGPL-2.1+
-# udev
+## udev
-- Upstream: https://www.freedesktop.org/wiki/software/systemd/
+- Upstream: https://www.freedesktop.org/wiki/Software/systemd/
- Version: 237
-- License: LPGL-2.1+
+- License: LGPL-2.1+
## X11