summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConstruct2
-rw-r--r--core/core_bind.cpp10
-rw-r--r--core/core_bind.h2
-rw-r--r--core/extension/gdnative_interface.cpp24
-rw-r--r--core/extension/gdnative_interface.h3
-rw-r--r--core/io/json.cpp86
-rw-r--r--core/io/json.h20
-rw-r--r--core/os/os.h2
-rw-r--r--core/register_core_types.cpp14
-rw-r--r--core/variant/variant.h3
-rw-r--r--core/variant/variant_setget.cpp566
-rw-r--r--doc/classes/AnimatedSprite2D.xml11
-rw-r--r--doc/classes/AnimatedSprite3D.xml13
-rw-r--r--doc/classes/BaseMaterial3D.xml2
-rw-r--r--doc/classes/Cubemap.xml4
-rw-r--r--doc/classes/CubemapArray.xml5
-rw-r--r--doc/classes/Environment.xml18
-rw-r--r--doc/classes/FogMaterial.xml13
-rw-r--r--doc/classes/FogVolume.xml9
-rw-r--r--doc/classes/ImageTextureLayered.xml6
-rw-r--r--doc/classes/JSON.xml18
-rw-r--r--doc/classes/LightmapGI.xml6
-rw-r--r--doc/classes/OS.xml21
-rw-r--r--doc/classes/PanoramaSkyMaterial.xml4
-rw-r--r--doc/classes/ProjectSettings.xml2
-rw-r--r--doc/classes/Texture2DArray.xml3
-rw-r--r--doc/classes/TextureLayered.xml11
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp18
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h13
-rw-r--r--drivers/unix/os_unix.cpp8
-rw-r--r--drivers/unix/os_unix.h2
-rw-r--r--editor/animation_track_editor.cpp9
-rw-r--r--editor/editor_command_palette.cpp2
-rw-r--r--editor/editor_file_system.cpp5
-rw-r--r--editor/editor_file_system.h1
-rw-r--r--editor/editor_inspector.cpp64
-rw-r--r--editor/editor_inspector.h2
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp12
-rw-r--r--editor/plugins/node_3d_editor_plugin.h2
-rw-r--r--editor/plugins/shader_editor_plugin.cpp1
-rw-r--r--methods.py93
-rwxr-xr-xmodules/mono/build_scripts/build_assemblies.py4
-rw-r--r--modules/openxr/openxr_api.cpp2
-rw-r--r--platform/android/os_android.cpp74
-rw-r--r--platform/android/os_android.h4
-rw-r--r--platform/ios/os_ios.h2
-rw-r--r--platform/ios/os_ios.mm9
-rw-r--r--platform/linuxbsd/display_server_x11.cpp26
-rw-r--r--platform/linuxbsd/display_server_x11.h2
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp37
-rw-r--r--platform/linuxbsd/os_linuxbsd.h4
-rw-r--r--platform/macos/display_server_macos.h2
-rw-r--r--platform/macos/display_server_macos.mm21
-rw-r--r--platform/macos/os_macos.h2
-rw-r--r--platform/macos/os_macos.mm9
-rw-r--r--platform/uwp/os_uwp.cpp10
-rw-r--r--platform/uwp/os_uwp.h2
-rw-r--r--platform/windows/display_server_windows.cpp62
-rw-r--r--platform/windows/display_server_windows.h2
-rw-r--r--platform/windows/os_windows.cpp18
-rw-r--r--platform/windows/os_windows.h2
-rw-r--r--scene/2d/animated_sprite_2d.cpp54
-rw-r--r--scene/2d/animated_sprite_2d.h3
-rw-r--r--scene/3d/lightmap_gi.cpp5
-rw-r--r--scene/3d/lightmap_gi.h8
-rw-r--r--scene/3d/sprite_3d.cpp52
-rw-r--r--scene/3d/sprite_3d.h3
-rw-r--r--scene/animation/animation_player.cpp7
-rw-r--r--scene/animation/animation_tree.cpp15
-rw-r--r--scene/animation/tween.cpp272
-rw-r--r--scene/animation/tween.h1
-rw-r--r--scene/gui/rich_text_label.cpp55
-rw-r--r--scene/gui/rich_text_label.h11
-rw-r--r--scene/main/viewport.cpp47
-rw-r--r--scene/main/viewport.h2
-rw-r--r--scene/main/window.cpp18
-rw-r--r--scene/main/window.h2
-rw-r--r--scene/resources/animation.cpp464
-rw-r--r--scene/resources/animation.h6
-rw-r--r--scene/resources/material.cpp30
-rw-r--r--scene/resources/material.h11
-rw-r--r--scene/resources/skeleton_profile.cpp4
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp2
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp7
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h15
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h15
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp21
-rw-r--r--servers/rendering/renderer_viewport.cpp75
-rw-r--r--servers/rendering/renderer_viewport.h5
-rw-r--r--thirdparty/README.md2
-rw-r--r--thirdparty/libpng/LICENSE4
-rw-r--r--thirdparty/libpng/arm/arm_init.c28
-rw-r--r--thirdparty/libpng/arm/filter_neon_intrinsics.c2
-rw-r--r--thirdparty/libpng/arm/palette_neon_intrinsics.c14
-rw-r--r--thirdparty/libpng/png.c14
-rw-r--r--thirdparty/libpng/png.h121
-rw-r--r--thirdparty/libpng/pngconf.h8
-rw-r--r--thirdparty/libpng/pngget.c176
-rw-r--r--thirdparty/libpng/pnginfo.h13
-rw-r--r--thirdparty/libpng/pnglibconf.h4
-rw-r--r--thirdparty/libpng/pngpread.c199
-rw-r--r--thirdparty/libpng/pngpriv.h120
-rw-r--r--thirdparty/libpng/pngread.c83
-rw-r--r--thirdparty/libpng/pngrtran.c2
-rw-r--r--thirdparty/libpng/pngrutil.c326
-rw-r--r--thirdparty/libpng/pngset.c159
-rw-r--r--thirdparty/libpng/pngstruct.h33
-rw-r--r--thirdparty/libpng/pngwrite.c58
-rw-r--r--thirdparty/libpng/pngwutil.c139
109 files changed, 1533 insertions, 2586 deletions
diff --git a/SConstruct b/SConstruct
index f7504f72e1..891f1116e1 100644
--- a/SConstruct
+++ b/SConstruct
@@ -737,7 +737,7 @@ if selected_platform in platform_list:
env.module_list = modules_enabled
methods.sort_module_list(env)
- methods.update_version(env.module_version_string)
+ methods.generate_version_header(env.module_version_string)
env["PROGSUFFIX"] = suffix + env.module_version_string + env["PROGSUFFIX"]
env["OBJSUFFIX"] = suffix + env["OBJSUFFIX"]
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index 9daf58cb71..ba48adff6a 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -322,6 +322,14 @@ String OS::get_name() const {
return ::OS::get_singleton()->get_name();
}
+String OS::get_distribution_name() const {
+ return ::OS::get_singleton()->get_distribution_name();
+}
+
+String OS::get_version() const {
+ return ::OS::get_singleton()->get_version();
+}
+
Vector<String> OS::get_cmdline_args() {
List<String> cmdline = ::OS::get_singleton()->get_cmdline_args();
Vector<String> cmdlinev;
@@ -535,6 +543,8 @@ void OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_environment", "variable"), &OS::has_environment);
ClassDB::bind_method(D_METHOD("get_name"), &OS::get_name);
+ ClassDB::bind_method(D_METHOD("get_distribution_name"), &OS::get_distribution_name);
+ ClassDB::bind_method(D_METHOD("get_version"), &OS::get_version);
ClassDB::bind_method(D_METHOD("get_cmdline_args"), &OS::get_cmdline_args);
ClassDB::bind_method(D_METHOD("get_cmdline_user_args"), &OS::get_cmdline_user_args);
diff --git a/core/core_bind.h b/core/core_bind.h
index cd382d2915..0f85e473a5 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -193,6 +193,8 @@ public:
bool set_environment(const String &p_var, const String &p_value) const;
String get_name() const;
+ String get_distribution_name() const;
+ String get_version() const;
Vector<String> get_cmdline_args();
Vector<String> get_cmdline_user_args();
diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp
index ef0b590030..6c680e82c9 100644
--- a/core/extension/gdnative_interface.cpp
+++ b/core/extension/gdnative_interface.cpp
@@ -251,27 +251,6 @@ static GDNativeBool gdnative_variant_booleanize(const GDNativeVariantPtr p_self)
return self->booleanize();
}
-static void gdnative_variant_sub(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_dst) {
- const Variant *a = (const Variant *)p_a;
- const Variant *b = (const Variant *)p_b;
- memnew_placement(r_dst, Variant);
- Variant::sub(*a, *b, *(Variant *)r_dst);
-}
-
-static void gdnative_variant_blend(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst) {
- const Variant *a = (const Variant *)p_a;
- const Variant *b = (const Variant *)p_b;
- memnew_placement(r_dst, Variant);
- Variant::blend(*a, *b, p_c, *(Variant *)r_dst);
-}
-
-static void gdnative_variant_interpolate(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst) {
- const Variant *a = (const Variant *)p_a;
- const Variant *b = (const Variant *)p_b;
- memnew_placement(r_dst, Variant);
- Variant::interpolate(*a, *b, p_c, *(Variant *)r_dst);
-}
-
static void gdnative_variant_duplicate(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_ret, GDNativeBool p_deep) {
const Variant *self = (const Variant *)p_self;
memnew_placement(r_ret, Variant(self->duplicate(p_deep)));
@@ -970,9 +949,6 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) {
gdni.variant_recursive_hash = gdnative_variant_recursive_hash;
gdni.variant_hash_compare = gdnative_variant_hash_compare;
gdni.variant_booleanize = gdnative_variant_booleanize;
- gdni.variant_sub = gdnative_variant_sub;
- gdni.variant_blend = gdnative_variant_blend;
- gdni.variant_interpolate = gdnative_variant_interpolate;
gdni.variant_duplicate = gdnative_variant_duplicate;
gdni.variant_stringify = gdnative_variant_stringify;
diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h
index cb2adcb562..39378d8261 100644
--- a/core/extension/gdnative_interface.h
+++ b/core/extension/gdnative_interface.h
@@ -427,9 +427,6 @@ typedef struct {
GDNativeInt (*variant_recursive_hash)(const GDNativeVariantPtr p_self, GDNativeInt p_recursion_count);
GDNativeBool (*variant_hash_compare)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_other);
GDNativeBool (*variant_booleanize)(const GDNativeVariantPtr p_self);
- void (*variant_sub)(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_dst);
- void (*variant_blend)(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst);
- void (*variant_interpolate)(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst);
void (*variant_duplicate)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_ret, GDNativeBool p_deep);
void (*variant_stringify)(const GDNativeVariantPtr p_self, GDNativeStringPtr r_ret);
diff --git a/core/io/json.cpp b/core/io/json.cpp
index 91500ff3d5..a685fcb718 100644
--- a/core/io/json.cpp
+++ b/core/io/json.cpp
@@ -497,6 +497,10 @@ Error JSON::_parse_object(Dictionary &object, const char32_t *p_str, int &index,
return ERR_PARSE_ERROR;
}
+void JSON::set_data(const Variant &p_data) {
+ data = p_data;
+}
+
Error JSON::_parse_string(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line) {
const char32_t *str = p_json.ptr();
int idx = 0;
@@ -557,6 +561,88 @@ void JSON::_bind_methods() {
ClassDB::bind_method(D_METHOD("parse", "json_string"), &JSON::parse);
ClassDB::bind_method(D_METHOD("get_data"), &JSON::get_data);
+ ClassDB::bind_method(D_METHOD("set_data", "data"), &JSON::set_data);
ClassDB::bind_method(D_METHOD("get_error_line"), &JSON::get_error_line);
ClassDB::bind_method(D_METHOD("get_error_message"), &JSON::get_error_message);
+
+ ADD_PROPERTY(PropertyInfo(Variant::NIL, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT), "set_data", "get_data"); // Ensures that it can be serialized as binary.
+}
+
+////
+
+////////////
+
+Ref<Resource> ResourceFormatLoaderJSON::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
+ if (r_error) {
+ *r_error = ERR_FILE_CANT_OPEN;
+ }
+
+ if (!FileAccess::exists(p_path)) {
+ *r_error = ERR_FILE_NOT_FOUND;
+ return Ref<Resource>();
+ }
+
+ Ref<JSON> json;
+ json.instantiate();
+
+ Error err = json->parse(FileAccess::get_file_as_string(p_path));
+ if (err != OK) {
+ if (r_error) {
+ *r_error = err;
+ }
+ ERR_PRINT("Error parsing JSON file at '" + p_path + "', on line " + itos(json->get_error_line()) + ": " + json->get_error_message());
+ return Ref<Resource>();
+ }
+
+ if (r_error) {
+ *r_error = OK;
+ }
+
+ return json;
+}
+
+void ResourceFormatLoaderJSON::get_recognized_extensions(List<String> *p_extensions) const {
+ p_extensions->push_back("json");
+}
+
+bool ResourceFormatLoaderJSON::handles_type(const String &p_type) const {
+ return (p_type == "JSON");
+}
+
+String ResourceFormatLoaderJSON::get_resource_type(const String &p_path) const {
+ String el = p_path.get_extension().to_lower();
+ if (el == "json") {
+ return "JSON";
+ }
+ return "";
+}
+
+Error ResourceFormatSaverJSON::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) {
+ Ref<JSON> json = p_resource;
+ ERR_FAIL_COND_V(json.is_null(), ERR_INVALID_PARAMETER);
+
+ String source = JSON::stringify(json->get_data(), "\t", false, true);
+
+ Error err;
+ Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
+
+ ERR_FAIL_COND_V_MSG(err, err, "Cannot save json '" + p_path + "'.");
+
+ file->store_string(source);
+ if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
+ return ERR_CANT_CREATE;
+ }
+
+ return OK;
+}
+
+void ResourceFormatSaverJSON::get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const {
+ Ref<JSON> json = p_resource;
+ if (json.is_valid()) {
+ p_extensions->push_back("json");
+ }
+}
+
+bool ResourceFormatSaverJSON::recognize(const Ref<Resource> &p_resource) const {
+ return p_resource->get_class_name() == "JSON"; //only json, not inherited
}
diff --git a/core/io/json.h b/core/io/json.h
index 840b1cc08a..208d4ad625 100644
--- a/core/io/json.h
+++ b/core/io/json.h
@@ -31,7 +31,9 @@
#ifndef JSON_H
#define JSON_H
-#include "core/object/ref_counted.h"
+#include "core/io/resource.h"
+#include "core/io/resource_loader.h"
+#include "core/io/resource_saver.h"
#include "core/variant/variant.h"
class JSON : public RefCounted {
@@ -86,8 +88,24 @@ public:
static Variant parse_string(const String &p_json_string);
inline Variant get_data() const { return data; }
+ void set_data(const Variant &p_data);
inline int get_error_line() const { return err_line; }
inline String get_error_message() const { return err_str; }
};
+class ResourceFormatLoaderJSON : public ResourceFormatLoader {
+public:
+ virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual bool handles_type(const String &p_type) const;
+ virtual String get_resource_type(const String &p_path) const;
+};
+
+class ResourceFormatSaverJSON : public ResourceFormatSaver {
+public:
+ virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0);
+ virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const;
+ virtual bool recognize(const Ref<Resource> &p_resource) const;
+};
+
#endif // JSON_H
diff --git a/core/os/os.h b/core/os/os.h
index 363697ea30..6944d29eeb 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -161,6 +161,8 @@ public:
virtual bool set_environment(const String &p_var, const String &p_value) const = 0;
virtual String get_name() const = 0;
+ virtual String get_distribution_name() const = 0;
+ virtual String get_version() const = 0;
virtual List<String> get_cmdline_args() const { return _cmdline; }
virtual List<String> get_cmdline_user_args() const { return _user_args; }
virtual List<String> get_cmdline_platform_args() const { return List<String>(); }
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 6650d9be23..6dfb0f82e0 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -87,6 +87,8 @@ static Ref<TranslationLoaderPO> resource_format_po;
static Ref<ResourceFormatSaverCrypto> resource_format_saver_crypto;
static Ref<ResourceFormatLoaderCrypto> resource_format_loader_crypto;
static Ref<NativeExtensionResourceLoader> resource_loader_native_extension;
+static Ref<ResourceFormatSaverJSON> resource_saver_json;
+static Ref<ResourceFormatLoaderJSON> resource_loader_json;
static core_bind::ResourceLoader *_resource_loader = nullptr;
static core_bind::ResourceSaver *_resource_saver = nullptr;
@@ -211,6 +213,12 @@ void register_core_types() {
resource_format_loader_crypto.instantiate();
ResourceLoader::add_resource_format_loader(resource_format_loader_crypto);
+ resource_loader_json.instantiate();
+ ResourceLoader::add_resource_format_loader(resource_loader_json);
+
+ resource_saver_json.instantiate();
+ ResourceSaver::add_resource_format_saver(resource_saver_json);
+
GDREGISTER_CLASS(MainLoop);
GDREGISTER_CLASS(Translation);
GDREGISTER_CLASS(OptimizedTranslation);
@@ -387,6 +395,12 @@ void unregister_core_types() {
ResourceLoader::remove_resource_format_loader(resource_format_loader_crypto);
resource_format_loader_crypto.unref();
+ ResourceSaver::remove_resource_format_saver(resource_saver_json);
+ resource_saver_json.unref();
+
+ ResourceLoader::remove_resource_format_loader(resource_loader_json);
+ resource_loader_json.unref();
+
if (ip) {
memdelete(ip);
}
diff --git a/core/variant/variant.h b/core/variant/variant.h
index 9b213a7682..b0738e7d44 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -552,9 +552,6 @@ public:
void zero();
Variant duplicate(bool p_deep = false) const;
Variant recursive_duplicate(bool p_deep, int recursion_count) const;
- static void blend(const Variant &a, const Variant &b, float c, Variant &r_dst);
- static void interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst);
- static void sub(const Variant &a, const Variant &b, Variant &r_dst);
/* Built-In Methods */
diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp
index 57b953f7f0..ff67b187ef 100644
--- a/core/variant/variant_setget.cpp
+++ b/core/variant/variant_setget.cpp
@@ -1911,572 +1911,6 @@ Variant Variant::recursive_duplicate(bool p_deep, int recursion_count) const {
}
}
-void Variant::sub(const Variant &a, const Variant &b, Variant &r_dst) {
- if (a.type != b.type) {
- return;
- }
-
- switch (a.type) {
- case NIL: {
- r_dst = Variant();
- }
- return;
- case INT: {
- int64_t va = a._data._int;
- int64_t vb = b._data._int;
- r_dst = int(va - vb);
- }
- return;
- case FLOAT: {
- double ra = a._data._float;
- double rb = b._data._float;
- r_dst = ra - rb;
- }
- return;
- case VECTOR2: {
- r_dst = *reinterpret_cast<const Vector2 *>(a._data._mem) - *reinterpret_cast<const Vector2 *>(b._data._mem);
- }
- return;
- case VECTOR2I: {
- int32_t vax = reinterpret_cast<const Vector2i *>(a._data._mem)->x;
- int32_t vbx = reinterpret_cast<const Vector2i *>(b._data._mem)->x;
- int32_t vay = reinterpret_cast<const Vector2i *>(a._data._mem)->y;
- int32_t vby = reinterpret_cast<const Vector2i *>(b._data._mem)->y;
- r_dst = Vector2i(int32_t(vax - vbx), int32_t(vay - vby));
- }
- return;
- case RECT2: {
- const Rect2 *ra = reinterpret_cast<const Rect2 *>(a._data._mem);
- const Rect2 *rb = reinterpret_cast<const Rect2 *>(b._data._mem);
- r_dst = Rect2(ra->position - rb->position, ra->size - rb->size);
- }
- return;
- case RECT2I: {
- const Rect2i *ra = reinterpret_cast<const Rect2i *>(a._data._mem);
- const Rect2i *rb = reinterpret_cast<const Rect2i *>(b._data._mem);
-
- int32_t vax = ra->position.x;
- int32_t vay = ra->position.y;
- int32_t vbx = ra->size.x;
- int32_t vby = ra->size.y;
- int32_t vcx = rb->position.x;
- int32_t vcy = rb->position.y;
- int32_t vdx = rb->size.x;
- int32_t vdy = rb->size.y;
-
- r_dst = Rect2i(int32_t(vax - vbx), int32_t(vay - vby), int32_t(vcx - vdx), int32_t(vcy - vdy));
- }
- return;
- case VECTOR3: {
- r_dst = *reinterpret_cast<const Vector3 *>(a._data._mem) - *reinterpret_cast<const Vector3 *>(b._data._mem);
- }
- return;
- case VECTOR3I: {
- int32_t vax = reinterpret_cast<const Vector3i *>(a._data._mem)->x;
- int32_t vbx = reinterpret_cast<const Vector3i *>(b._data._mem)->x;
- int32_t vay = reinterpret_cast<const Vector3i *>(a._data._mem)->y;
- int32_t vby = reinterpret_cast<const Vector3i *>(b._data._mem)->y;
- int32_t vaz = reinterpret_cast<const Vector3i *>(a._data._mem)->z;
- int32_t vbz = reinterpret_cast<const Vector3i *>(b._data._mem)->z;
- r_dst = Vector3i(int32_t(vax - vbx), int32_t(vay - vby), int32_t(vaz - vbz));
- }
- return;
- case AABB: {
- const ::AABB *ra = reinterpret_cast<const ::AABB *>(a._data._mem);
- const ::AABB *rb = reinterpret_cast<const ::AABB *>(b._data._mem);
- r_dst = ::AABB(ra->position - rb->position, ra->size - rb->size);
- }
- return;
- case QUATERNION: {
- Quaternion empty_rot;
- const Quaternion *qa = reinterpret_cast<const Quaternion *>(a._data._mem);
- const Quaternion *qb = reinterpret_cast<const Quaternion *>(b._data._mem);
- r_dst = (*qb).inverse() * *qa;
- }
- return;
- case COLOR: {
- const Color *ca = reinterpret_cast<const Color *>(a._data._mem);
- const Color *cb = reinterpret_cast<const Color *>(b._data._mem);
- float new_r = ca->r - cb->r;
- float new_g = ca->g - cb->g;
- float new_b = ca->b - cb->b;
- float new_a = ca->a - cb->a;
- new_r = new_r > 1.0 ? 1.0 : new_r;
- new_g = new_g > 1.0 ? 1.0 : new_g;
- new_b = new_b > 1.0 ? 1.0 : new_b;
- new_a = new_a > 1.0 ? 1.0 : new_a;
- r_dst = Color(new_r, new_g, new_b, new_a);
- }
- return;
- default: {
- r_dst = a;
- }
- return;
- }
-}
-
-void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst) {
- if (a.type != b.type) {
- if (a.is_num() && b.is_num()) {
- real_t va = a;
- real_t vb = b;
- r_dst = va + vb * c;
- } else {
- r_dst = a;
- }
- return;
- }
-
- switch (a.type) {
- case NIL: {
- r_dst = Variant();
- }
- return;
- case INT: {
- int64_t va = a._data._int;
- int64_t vb = b._data._int;
- r_dst = int(va + vb * c + 0.5);
- }
- return;
- case FLOAT: {
- double ra = a._data._float;
- double rb = b._data._float;
- r_dst = ra + rb * c;
- }
- return;
- case VECTOR2: {
- r_dst = *reinterpret_cast<const Vector2 *>(a._data._mem) + *reinterpret_cast<const Vector2 *>(b._data._mem) * c;
- }
- return;
- case VECTOR2I: {
- int32_t vax = reinterpret_cast<const Vector2i *>(a._data._mem)->x;
- int32_t vbx = reinterpret_cast<const Vector2i *>(b._data._mem)->x;
- int32_t vay = reinterpret_cast<const Vector2i *>(a._data._mem)->y;
- int32_t vby = reinterpret_cast<const Vector2i *>(b._data._mem)->y;
- r_dst = Vector2i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5));
- }
- return;
- case RECT2: {
- const Rect2 *ra = reinterpret_cast<const Rect2 *>(a._data._mem);
- const Rect2 *rb = reinterpret_cast<const Rect2 *>(b._data._mem);
- r_dst = Rect2(ra->position + rb->position * c, ra->size + rb->size * c);
- }
- return;
- case RECT2I: {
- const Rect2i *ra = reinterpret_cast<const Rect2i *>(a._data._mem);
- const Rect2i *rb = reinterpret_cast<const Rect2i *>(b._data._mem);
-
- int32_t vax = ra->position.x;
- int32_t vay = ra->position.y;
- int32_t vbx = ra->size.x;
- int32_t vby = ra->size.y;
- int32_t vcx = rb->position.x;
- int32_t vcy = rb->position.y;
- int32_t vdx = rb->size.x;
- int32_t vdy = rb->size.y;
-
- r_dst = Rect2i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vcx + vdx * c + 0.5), int32_t(vcy + vdy * c + 0.5));
- }
- return;
- case VECTOR3: {
- r_dst = *reinterpret_cast<const Vector3 *>(a._data._mem) + *reinterpret_cast<const Vector3 *>(b._data._mem) * c;
- }
- return;
- case VECTOR3I: {
- int32_t vax = reinterpret_cast<const Vector3i *>(a._data._mem)->x;
- int32_t vbx = reinterpret_cast<const Vector3i *>(b._data._mem)->x;
- int32_t vay = reinterpret_cast<const Vector3i *>(a._data._mem)->y;
- int32_t vby = reinterpret_cast<const Vector3i *>(b._data._mem)->y;
- int32_t vaz = reinterpret_cast<const Vector3i *>(a._data._mem)->z;
- int32_t vbz = reinterpret_cast<const Vector3i *>(b._data._mem)->z;
- r_dst = Vector3i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vaz + vbz * c + 0.5));
- }
- return;
- case AABB: {
- const ::AABB *ra = reinterpret_cast<const ::AABB *>(a._data._mem);
- const ::AABB *rb = reinterpret_cast<const ::AABB *>(b._data._mem);
- r_dst = ::AABB(ra->position + rb->position * c, ra->size + rb->size * c);
- }
- return;
- case QUATERNION: {
- Quaternion empty_rot;
- const Quaternion *qa = reinterpret_cast<const Quaternion *>(a._data._mem);
- const Quaternion *qb = reinterpret_cast<const Quaternion *>(b._data._mem);
- r_dst = *qa * empty_rot.slerp(*qb, c);
- }
- return;
- case COLOR: {
- const Color *ca = reinterpret_cast<const Color *>(a._data._mem);
- const Color *cb = reinterpret_cast<const Color *>(b._data._mem);
- float new_r = ca->r + cb->r * c;
- float new_g = ca->g + cb->g * c;
- float new_b = ca->b + cb->b * c;
- float new_a = ca->a + cb->a * c;
- new_r = new_r > 1.0 ? 1.0 : new_r;
- new_g = new_g > 1.0 ? 1.0 : new_g;
- new_b = new_b > 1.0 ? 1.0 : new_b;
- new_a = new_a > 1.0 ? 1.0 : new_a;
- r_dst = Color(new_r, new_g, new_b, new_a);
- }
- return;
- default: {
- r_dst = c < 0.5 ? a : b;
- }
- return;
- }
-}
-
-void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst) {
- if (a.type != b.type) {
- if (a.is_num() && b.is_num()) {
- //not as efficient but..
- real_t va = a;
- real_t vb = b;
- r_dst = va + (vb - va) * c;
-
- } else {
- r_dst = a;
- }
- return;
- }
-
- switch (a.type) {
- case NIL: {
- r_dst = Variant();
- }
- return;
- case BOOL: {
- r_dst = a;
- }
- return;
- case INT: {
- int64_t va = a._data._int;
- int64_t vb = b._data._int;
- r_dst = int(va + (vb - va) * c);
- }
- return;
- case FLOAT: {
- real_t va = a._data._float;
- real_t vb = b._data._float;
- r_dst = va + (vb - va) * c;
- }
- return;
- case STRING: {
- //this is pretty funny and bizarre, but artists like to use it for typewriter effects
- String sa = *reinterpret_cast<const String *>(a._data._mem);
- String sb = *reinterpret_cast<const String *>(b._data._mem);
- String dst;
- int sa_len = sa.length();
- int sb_len = sb.length();
- int csize = sa_len + (sb_len - sa_len) * c;
- if (csize == 0) {
- r_dst = "";
- return;
- }
- dst.resize(csize + 1);
- dst[csize] = 0;
- int split = csize / 2;
-
- for (int i = 0; i < csize; i++) {
- char32_t chr = ' ';
-
- if (i < split) {
- if (i < sa.length()) {
- chr = sa[i];
- } else if (i < sb.length()) {
- chr = sb[i];
- }
-
- } else {
- if (i < sb.length()) {
- chr = sb[i];
- } else if (i < sa.length()) {
- chr = sa[i];
- }
- }
-
- dst[i] = chr;
- }
-
- r_dst = dst;
- }
- return;
- case VECTOR2: {
- r_dst = reinterpret_cast<const Vector2 *>(a._data._mem)->lerp(*reinterpret_cast<const Vector2 *>(b._data._mem), c);
- }
- return;
- case VECTOR2I: {
- int32_t vax = reinterpret_cast<const Vector2i *>(a._data._mem)->x;
- int32_t vbx = reinterpret_cast<const Vector2i *>(b._data._mem)->x;
- int32_t vay = reinterpret_cast<const Vector2i *>(a._data._mem)->y;
- int32_t vby = reinterpret_cast<const Vector2i *>(b._data._mem)->y;
- r_dst = Vector2i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5));
- }
- return;
-
- case RECT2: {
- r_dst = Rect2(reinterpret_cast<const Rect2 *>(a._data._mem)->position.lerp(reinterpret_cast<const Rect2 *>(b._data._mem)->position, c), reinterpret_cast<const Rect2 *>(a._data._mem)->size.lerp(reinterpret_cast<const Rect2 *>(b._data._mem)->size, c));
- }
- return;
- case RECT2I: {
- const Rect2i *ra = reinterpret_cast<const Rect2i *>(a._data._mem);
- const Rect2i *rb = reinterpret_cast<const Rect2i *>(b._data._mem);
-
- int32_t vax = ra->position.x;
- int32_t vay = ra->position.y;
- int32_t vbx = ra->size.x;
- int32_t vby = ra->size.y;
- int32_t vcx = rb->position.x;
- int32_t vcy = rb->position.y;
- int32_t vdx = rb->size.x;
- int32_t vdy = rb->size.y;
-
- r_dst = Rect2i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vcx + vdx * c + 0.5), int32_t(vcy + vdy * c + 0.5));
- }
- return;
-
- case VECTOR3: {
- r_dst = reinterpret_cast<const Vector3 *>(a._data._mem)->lerp(*reinterpret_cast<const Vector3 *>(b._data._mem), c);
- }
- return;
- case VECTOR3I: {
- int32_t vax = reinterpret_cast<const Vector3i *>(a._data._mem)->x;
- int32_t vbx = reinterpret_cast<const Vector3i *>(b._data._mem)->x;
- int32_t vay = reinterpret_cast<const Vector3i *>(a._data._mem)->y;
- int32_t vby = reinterpret_cast<const Vector3i *>(b._data._mem)->y;
- int32_t vaz = reinterpret_cast<const Vector3i *>(a._data._mem)->z;
- int32_t vbz = reinterpret_cast<const Vector3i *>(b._data._mem)->z;
- r_dst = Vector3i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vaz + vbz * c + 0.5));
- }
- return;
-
- case TRANSFORM2D: {
- r_dst = a._data._transform2d->interpolate_with(*b._data._transform2d, c);
- }
- return;
- case PLANE: {
- r_dst = a;
- }
- return;
- case QUATERNION: {
- r_dst = reinterpret_cast<const Quaternion *>(a._data._mem)->slerp(*reinterpret_cast<const Quaternion *>(b._data._mem), c);
- }
- return;
- case AABB: {
- r_dst = ::AABB(a._data._aabb->position.lerp(b._data._aabb->position, c), a._data._aabb->size.lerp(b._data._aabb->size, c));
- }
- return;
- case BASIS: {
- r_dst = a._data._basis->lerp(*b._data._basis, c);
- }
- return;
- case TRANSFORM3D: {
- r_dst = a._data._transform3d->interpolate_with(*b._data._transform3d, c);
- }
- return;
- case COLOR: {
- r_dst = reinterpret_cast<const Color *>(a._data._mem)->lerp(*reinterpret_cast<const Color *>(b._data._mem), c);
- }
- return;
- case STRING_NAME: {
- r_dst = a;
- }
- return;
- case NODE_PATH: {
- r_dst = a;
- }
- return;
- case RID: {
- r_dst = a;
- }
- return;
- case OBJECT: {
- r_dst = a;
- }
- return;
- case DICTIONARY: {
- }
- return;
- case ARRAY: {
- r_dst = a;
- }
- return;
- case PACKED_BYTE_ARRAY: {
- r_dst = a;
- }
- return;
- case PACKED_INT32_ARRAY: {
- const Vector<int32_t> *arr_a = &PackedArrayRef<int32_t>::get_array(a._data.packed_array);
- const Vector<int32_t> *arr_b = &PackedArrayRef<int32_t>::get_array(b._data.packed_array);
- int32_t sz = arr_a->size();
- if (sz == 0 || arr_b->size() != sz) {
- r_dst = a;
- } else {
- Vector<int32_t> v;
- v.resize(sz);
- {
- int32_t *vw = v.ptrw();
- const int32_t *ar = arr_a->ptr();
- const int32_t *br = arr_b->ptr();
-
- Variant va;
- for (int32_t i = 0; i < sz; i++) {
- Variant::interpolate(ar[i], br[i], c, va);
- vw[i] = va;
- }
- }
- r_dst = v;
- }
- }
- return;
- case PACKED_INT64_ARRAY: {
- const Vector<int64_t> *arr_a = &PackedArrayRef<int64_t>::get_array(a._data.packed_array);
- const Vector<int64_t> *arr_b = &PackedArrayRef<int64_t>::get_array(b._data.packed_array);
- int64_t sz = arr_a->size();
- if (sz == 0 || arr_b->size() != sz) {
- r_dst = a;
- } else {
- Vector<int64_t> v;
- v.resize(sz);
- {
- int64_t *vw = v.ptrw();
- const int64_t *ar = arr_a->ptr();
- const int64_t *br = arr_b->ptr();
-
- Variant va;
- for (int64_t i = 0; i < sz; i++) {
- Variant::interpolate(ar[i], br[i], c, va);
- vw[i] = va;
- }
- }
- r_dst = v;
- }
- }
- return;
- case PACKED_FLOAT32_ARRAY: {
- const Vector<float> *arr_a = &PackedArrayRef<float>::get_array(a._data.packed_array);
- const Vector<float> *arr_b = &PackedArrayRef<float>::get_array(b._data.packed_array);
- int sz = arr_a->size();
- if (sz == 0 || arr_b->size() != sz) {
- r_dst = a;
- } else {
- Vector<float> v;
- v.resize(sz);
- {
- float *vw = v.ptrw();
- const float *ar = arr_a->ptr();
- const float *br = arr_b->ptr();
-
- Variant va;
- for (int i = 0; i < sz; i++) {
- Variant::interpolate(ar[i], br[i], c, va);
- vw[i] = va;
- }
- }
- r_dst = v;
- }
- }
- return;
- case PACKED_FLOAT64_ARRAY: {
- const Vector<double> *arr_a = &PackedArrayRef<double>::get_array(a._data.packed_array);
- const Vector<double> *arr_b = &PackedArrayRef<double>::get_array(b._data.packed_array);
- int sz = arr_a->size();
- if (sz == 0 || arr_b->size() != sz) {
- r_dst = a;
- } else {
- Vector<double> v;
- v.resize(sz);
- {
- double *vw = v.ptrw();
- const double *ar = arr_a->ptr();
- const double *br = arr_b->ptr();
-
- Variant va;
- for (int i = 0; i < sz; i++) {
- Variant::interpolate(ar[i], br[i], c, va);
- vw[i] = va;
- }
- }
- r_dst = v;
- }
- }
- return;
- case PACKED_STRING_ARRAY: {
- r_dst = a;
- }
- return;
- case PACKED_VECTOR2_ARRAY: {
- const Vector<Vector2> *arr_a = &PackedArrayRef<Vector2>::get_array(a._data.packed_array);
- const Vector<Vector2> *arr_b = &PackedArrayRef<Vector2>::get_array(b._data.packed_array);
- int sz = arr_a->size();
- if (sz == 0 || arr_b->size() != sz) {
- r_dst = a;
- } else {
- Vector<Vector2> v;
- v.resize(sz);
- {
- Vector2 *vw = v.ptrw();
- const Vector2 *ar = arr_a->ptr();
- const Vector2 *br = arr_b->ptr();
-
- for (int i = 0; i < sz; i++) {
- vw[i] = ar[i].lerp(br[i], c);
- }
- }
- r_dst = v;
- }
- }
- return;
- case PACKED_VECTOR3_ARRAY: {
- const Vector<Vector3> *arr_a = &PackedArrayRef<Vector3>::get_array(a._data.packed_array);
- const Vector<Vector3> *arr_b = &PackedArrayRef<Vector3>::get_array(b._data.packed_array);
- int sz = arr_a->size();
- if (sz == 0 || arr_b->size() != sz) {
- r_dst = a;
- } else {
- Vector<Vector3> v;
- v.resize(sz);
- {
- Vector3 *vw = v.ptrw();
- const Vector3 *ar = arr_a->ptr();
- const Vector3 *br = arr_b->ptr();
-
- for (int i = 0; i < sz; i++) {
- vw[i] = ar[i].lerp(br[i], c);
- }
- }
- r_dst = v;
- }
- }
- return;
- case PACKED_COLOR_ARRAY: {
- const Vector<Color> *arr_a = &PackedArrayRef<Color>::get_array(a._data.packed_array);
- const Vector<Color> *arr_b = &PackedArrayRef<Color>::get_array(b._data.packed_array);
- int sz = arr_a->size();
- if (sz == 0 || arr_b->size() != sz) {
- r_dst = a;
- } else {
- Vector<Color> v;
- v.resize(sz);
- {
- Color *vw = v.ptrw();
- const Color *ar = arr_a->ptr();
- const Color *br = arr_b->ptr();
-
- for (int i = 0; i < sz; i++) {
- vw[i] = ar[i].lerp(br[i], c);
- }
- }
- r_dst = v;
- }
- }
- return;
- default: {
- r_dst = a;
- }
- }
-}
-
void Variant::_register_variant_setters_getters() {
register_named_setters_getters();
register_indexed_setters_getters();
diff --git a/doc/classes/AnimatedSprite2D.xml b/doc/classes/AnimatedSprite2D.xml
index b207eda27f..afbe34816a 100644
--- a/doc/classes/AnimatedSprite2D.xml
+++ b/doc/classes/AnimatedSprite2D.xml
@@ -5,6 +5,8 @@
</brief_description>
<description>
[AnimatedSprite2D] is similar to the [Sprite2D] node, except it carries multiple textures as animation frames. Animations are created using a [SpriteFrames] resource, which allows you to import image files (or a folder containing said files) to provide the animation frames for the sprite. The [SpriteFrames] resource can be configured in the editor via the SpriteFrames bottom panel.
+ After setting up [member frames], [method play] may be called. It's also possible to select an [member animation] and toggle [member playing], even within the editor.
+ To pause the current animation, call [method stop] or set [member playing] to [code]false[/code]. Alternatively, setting [member speed_scale] to [code]0[/code] also preserves the current frame's elapsed time.
[b]Note:[/b] You can associate a set of normal or specular maps by creating additional [SpriteFrames] resources with a [code]_normal[/code] or [code]_specular[/code] suffix. For example, having 3 [SpriteFrames] resources [code]run[/code], [code]run_normal[/code], and [code]run_specular[/code] will make it so the [code]run[/code] animation uses normal and specular maps.
</description>
<tutorials>
@@ -17,13 +19,14 @@
<param index="0" name="anim" type="StringName" default="&amp;&quot;&quot;" />
<param index="1" name="backwards" type="bool" default="false" />
<description>
- Plays the animation named [param anim]. If no [param anim] is provided, the current animation is played. If [code]backwards[/code] is [code]true[/code], the animation will be played in reverse.
+ Plays the animation named [param anim]. If no [param anim] is provided, the current animation is played. If [param backwards] is [code]true[/code], the animation is played in reverse.
</description>
</method>
<method name="stop">
<return type="void" />
<description>
- Stops the current animation (does not reset the frame counter).
+ Stops the current [member animation] at the current [member frame].
+ [b]Note:[/b] This method resets the current frame's elapsed time. If this behavior is undesired, consider setting [member speed_scale] to [code]0[/code], instead.
</description>
</method>
</methods>
@@ -50,10 +53,10 @@
The texture's drawing offset.
</member>
<member name="playing" type="bool" setter="set_playing" getter="is_playing" default="false">
- If [code]true[/code], the [member animation] is currently playing.
+ If [code]true[/code], the [member animation] is currently playing. Setting this property to [code]false[/code] is the equivalent of calling [method stop].
</member>
<member name="speed_scale" type="float" setter="set_speed_scale" getter="get_speed_scale" default="1.0">
- The animation speed is multiplied by this value.
+ The animation speed is multiplied by this value. If set to a negative value, the animation is played in reverse. If set to [code]0[/code], the animation is paused, preserving the current frame's elapsed time.
</member>
</members>
<signals>
diff --git a/doc/classes/AnimatedSprite3D.xml b/doc/classes/AnimatedSprite3D.xml
index 58d3ca6ad3..09baf882fb 100644
--- a/doc/classes/AnimatedSprite3D.xml
+++ b/doc/classes/AnimatedSprite3D.xml
@@ -4,7 +4,9 @@
2D sprite node in 3D world, that can use multiple 2D textures for animation.
</brief_description>
<description>
- Animations are created using a [SpriteFrames] resource, which can be configured in the editor via the SpriteFrames panel.
+ [AnimatedSprite3D] is similar to the [Sprite3D] node, except it carries multiple textures as animation [member frames]. Animations are created using a [SpriteFrames] resource, which allows you to import image files (or a folder containing said files) to provide the animation frames for the sprite. The [SpriteFrames] resource can be configured in the editor via the SpriteFrames bottom panel.
+ After setting up [member frames], [method play] may be called. It's also possible to select an [member animation] and toggle [member playing], even within the editor.
+ To pause the current animation, call [method stop] or set [member playing] to [code]false[/code]. Alternatively, setting [member speed_scale] to [code]0[/code] also preserves the current frame's elapsed time.
</description>
<tutorials>
<link title="2D Sprite animation (also applies to 3D)">$DOCS_URL/tutorials/2d/2d_sprite_animation.html</link>
@@ -15,13 +17,14 @@
<param index="0" name="anim" type="StringName" default="&amp;&quot;&quot;" />
<param index="1" name="backwards" type="bool" default="false" />
<description>
- Plays the animation named [param anim]. If no [param anim] is provided, the current animation is played. If [param backwards] is [code]true[/code], the animation will be played in reverse.
+ Plays the animation named [param anim]. If no [param anim] is provided, the current animation is played. If [param backwards] is [code]true[/code], the animation is played in reverse.
</description>
</method>
<method name="stop">
<return type="void" />
<description>
- Stops the current animation (does not reset the frame counter).
+ Stops the current [member animation] at the current [member frame].
+ [b]Note:[/b] This method resets the current frame's elapsed time. If this behavior is undesired, consider setting [member speed_scale] to [code]0[/code], instead.
</description>
</method>
</methods>
@@ -36,10 +39,10 @@
The [SpriteFrames] resource containing the animation(s).
</member>
<member name="playing" type="bool" setter="set_playing" getter="is_playing" default="false">
- If [code]true[/code], the [member animation] is currently playing.
+ If [code]true[/code], the [member animation] is currently playing. Setting this property to [code]false[/code] is the equivalent of calling [method stop].
</member>
<member name="speed_scale" type="float" setter="set_speed_scale" getter="get_speed_scale" default="1.0">
- The animation speed is multiplied by this value.
+ The animation speed is multiplied by this value. If set to a negative value, the animation is played in reverse. If set to [code]0[/code], the animation is paused, preserving the current frame's elapsed time.
</member>
</members>
<signals>
diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml
index ee28675d89..cbb58a3e1e 100644
--- a/doc/classes/BaseMaterial3D.xml
+++ b/doc/classes/BaseMaterial3D.xml
@@ -28,7 +28,7 @@
<return type="Texture2D" />
<param index="0" name="param" type="int" enum="BaseMaterial3D.TextureParam" />
<description>
- Returns the [Texture] associated with the specified [enum TextureParam].
+ Returns the [Texture2D] associated with the specified [enum TextureParam].
</description>
</method>
<method name="set_feature">
diff --git a/doc/classes/Cubemap.xml b/doc/classes/Cubemap.xml
index 7173388027..0cdebeda95 100644
--- a/doc/classes/Cubemap.xml
+++ b/doc/classes/Cubemap.xml
@@ -4,9 +4,9 @@
6-sided texture typically used in 3D rendering.
</brief_description>
<description>
- A cubemap is a 6-sided texture typically used for faking reflections in 3D rendering. It can be used to make an object look as if it's reflecting its surroundings. This usually delivers much better performance than other reflection methods.
+ A cubemap is made of 6 textures organized in layers. They are typically used for faking reflections (see [ReflectionProbe]) in 3D rendering. It can be used to make an object look as if it's reflecting its surroundings. This usually delivers much better performance than other reflection methods.
This resource is typically used as a uniform in custom shaders. Few core Godot methods make use of Cubemap resources.
- [b]Note:[/b] Godot doesn't support using cubemaps as a [PanoramaSkyMaterial]. You can use [url=https://danilw.github.io/GLSL-howto/cubemap_to_panorama_js/cubemap_to_panorama.html]this tool[/url] to convert a cube map to an equirectangular sky map.
+ [b]Note:[/b] Godot doesn't support using cubemaps in a [PanoramaSkyMaterial]. You can use [url=https://danilw.github.io/GLSL-howto/cubemap_to_panorama_js/cubemap_to_panorama.html]this tool[/url] to convert a cubemap to an equirectangular sky map.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/CubemapArray.xml b/doc/classes/CubemapArray.xml
index 4fca842b5a..7f001155e4 100644
--- a/doc/classes/CubemapArray.xml
+++ b/doc/classes/CubemapArray.xml
@@ -1,8 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CubemapArray" inherits="ImageTextureLayered" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ A single composite texture resource which consists of multiple [Cubemap]s.
</brief_description>
<description>
+ [CubemapArray]s are made of an array of [Cubemap]s. Accordingly, like [Cubemap]s they are made of multiple textures the amount of which must be divisible by 6 (one image for each face of the cube). The primary benefit of [CubemapArray]s is that they can be accessed in shader code using a single texture reference. In other words, you can pass multiple [Cubemap]s into a shader using a single [CubemapArray].
+ Generally, [CubemapArray]s provide a more efficent way for storing multiple [Cubemap]s, than storing multiple [Cubemap]s themselves in an array.
+ Internally Godot, uses [CubemapArray]s for many effects including the [Sky], if you set [member ProjectSettings.rendering/reflections/sky_reflections/texture_array_reflections] to [code]true[/code].
+ [b]Note:[/b] [CubemapArray] is not supported in the OpenGL 3 rendering backend.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml
index 695f2cbc66..34a639d2de 100644
--- a/doc/classes/Environment.xml
+++ b/doc/classes/Environment.xml
@@ -86,7 +86,7 @@
This is useful to simulate [url=https://en.wikipedia.org/wiki/Aerial_perspective]aerial perspective[/url] in large scenes with low density fog. However, it is not very useful for high-density fog, as the sky will shine through. When set to [code]1.0[/code], the fog color comes completely from the [Sky]. If set to [code]0.0[/code], aerial perspective is disabled.
</member>
<member name="fog_density" type="float" setter="set_fog_density" getter="get_fog_density" default="0.01">
- The exponential fog density to use. Higher values result in a more dense fog.
+ The [i]exponential[/i] fog density to use. Higher values result in a more dense fog. Fog rendering is exponential as in real life.
</member>
<member name="fog_enabled" type="bool" setter="set_fog_enabled" getter="is_fog_enabled" default="false">
If [code]true[/code], fog effects are enabled.
@@ -292,13 +292,15 @@
The [Color] of the volumetric fog when interacting with lights. Mist and fog have an albedo close to [code]Color(1, 1, 1, 1)[/code] while smoke has a darker albedo.
</member>
<member name="volumetric_fog_ambient_inject" type="float" setter="set_volumetric_fog_ambient_inject" getter="get_volumetric_fog_ambient_inject" default="0.0">
- Scales the strength of ambient light used in the volumetric fog. A value of [code]0[/code] means that ambient light will not impact the volumetric fog.
+ Scales the strength of ambient light used in the volumetric fog. A value of [code]0.0[/code] means that ambient light will not impact the volumetric fog. [member volumetric_fog_ambient_inject] has a small performance cost when set above [code]0.0[/code].
+ [b]Note:[/b] This has no visible effect if [member volumetric_fog_density] is [code]0.0[/code] or if [member volumetric_fog_albedo] is a fully black color.
</member>
<member name="volumetric_fog_anisotropy" type="float" setter="set_volumetric_fog_anisotropy" getter="get_volumetric_fog_anisotropy" default="0.2">
- The direction of scattered light as it goes through the volumetric fog. A value close [code]1[/code] means almost all light is scattered forward. A value close to [code]0[/code] means light is scattered equally in all directions. A value close to [code]-1[/code] means light is scattered mostly backward. Fog and mist scatter light slightly forward, while smoke scatters light equally in all directions.
+ The direction of scattered light as it goes through the volumetric fog. A value close to [code]1.0[/code] means almost all light is scattered forward. A value close to [code]0.0[/code] means light is scattered equally in all directions. A value close to [code]-1.0[/code] means light is scattered mostly backward. Fog and mist scatter light slightly forward, while smoke scatters light equally in all directions.
</member>
<member name="volumetric_fog_density" type="float" setter="set_volumetric_fog_density" getter="get_volumetric_fog_density" default="0.05">
- The base density of the volumetric fog. Set this to the lowest density you want to have globally.
+ The base [i]exponential[/i] density of the volumetric fog. Set this to the lowest density you want to have globally. [FogVolume]s can be used to add to or subtract from this density in specific areas. Fog rendering is exponential as in real life.
+ A value of [code]0.0[/code] disables global volumetric fog while allowing [FogVolume]s to display volumetric fog in specific areas.
</member>
<member name="volumetric_fog_detail_spread" type="float" setter="set_volumetric_fog_detail_spread" getter="get_volumetric_fog_detail_spread" default="2.0">
The distribution of size down the length of the froxel buffer. A higher value compresses the froxels closer to the camera and places more detail closer to the camera.
@@ -313,20 +315,22 @@
Enables the volumetric fog effect. Volumetric fog uses a screen-aligned froxel buffer to calculate accurate volumetric scattering in the short to medium range. Volumetric fog interacts with [FogVolume]s and lights to calculate localized and global fog. Volumetric fog uses a PBR single-scattering model based on extinction, scattering, and emission which it exposes to users as density, albedo, and emission.
</member>
<member name="volumetric_fog_gi_inject" type="float" setter="set_volumetric_fog_gi_inject" getter="get_volumetric_fog_gi_inject" default="1.0">
- Scales the strength of Global Illumination used in the volumetric fog. A value of [code]0.0[/code] means that Global Illumination will not impact the volumetric fog.
+ Scales the strength of Global Illumination used in the volumetric fog's albedo color. A value of [code]0.0[/code] means that Global Illumination will not impact the volumetric fog. [member volumetric_fog_gi_inject] has a small performance cost when set above [code]0.0[/code].
+ [b]Note:[/b] This has no visible effect if [member volumetric_fog_density] is [code]0.0[/code] or if [member volumetric_fog_albedo] is a fully black color.
[b]Note:[/b] Only [VoxelGI] and SDFGI ([member Environment.sdfgi_enabled]) are taken into account when using [member volumetric_fog_gi_inject]. Global illumination from [LightmapGI], [ReflectionProbe] and SSIL (see [member ssil_enabled]) will be ignored by volumetric fog.
</member>
<member name="volumetric_fog_length" type="float" setter="set_volumetric_fog_length" getter="get_volumetric_fog_length" default="64.0">
- The distance over which the volumetric fog is computed. Increase to compute fog over a greater range, decrease to add more detail when a long range is not needed. For best quality fog, keep this as low as possible.
+ The distance over which the volumetric fog is computed. Increase to compute fog over a greater range, decrease to add more detail when a long range is not needed. For best quality fog, keep this as low as possible. See also [member ProjectSettings.rendering/environment/volumetric_fog/volume_depth].
</member>
<member name="volumetric_fog_sky_affect" type="float" setter="set_volumetric_fog_sky_affect" getter="get_volumetric_fog_sky_affect" default="1.0">
The factor to use when affecting the sky with volumetric fog. [code]1.0[/code] means that volumetric fog can fully obscure the sky. Lower values reduce the impact of volumetric fog on sky rendering, with [code]0.0[/code] not affecting sky rendering at all.
+ [b]Note:[/b] [member volumetric_fog_sky_affect] also affects [FogVolume]s, even if [member volumetric_fog_density] is [code]0.0[/code]. If you notice [FogVolume]s are disappearing when looking towards the sky, set [member volumetric_fog_sky_affect] to [code]1.0[/code].
</member>
<member name="volumetric_fog_temporal_reprojection_amount" type="float" setter="set_volumetric_fog_temporal_reprojection_amount" getter="get_volumetric_fog_temporal_reprojection_amount" default="0.9">
The amount by which to blend the last frame with the current frame. A higher number results in smoother volumetric fog, but makes "ghosting" much worse. A lower value reduces ghosting but can result in the per-frame temporal jitter becoming visible.
</member>
<member name="volumetric_fog_temporal_reprojection_enabled" type="bool" setter="set_volumetric_fog_temporal_reprojection_enabled" getter="is_volumetric_fog_temporal_reprojection_enabled" default="true">
- Enables temporal reprojection in the volumetric fog. Temporal reprojection blends the current frame's volumetric fog with the last frame's volumetric fog to smooth out jagged edges. The performance cost is minimal, however it does lead to moving [FogVolume]s and [Light3D]s "ghosting" and leaving a trail behind them. When temporal reprojection is enabled, try to avoid moving [FogVolume]s or [Light3D]s too fast.
+ Enables temporal reprojection in the volumetric fog. Temporal reprojection blends the current frame's volumetric fog with the last frame's volumetric fog to smooth out jagged edges. The performance cost is minimal; however, it leads to moving [FogVolume]s and [Light3D]s "ghosting" and leaving a trail behind them. When temporal reprojection is enabled, try to avoid moving [FogVolume]s or [Light3D]s too fast. Short-lived dynamic lighting effects should have [member Light3D.light_volumetric_fog_energy] set to [code]0.0[/code] to avoid ghosting.
</member>
</members>
<constants>
diff --git a/doc/classes/FogMaterial.xml b/doc/classes/FogMaterial.xml
index e63d4ddf3e..7428d6169a 100644
--- a/doc/classes/FogMaterial.xml
+++ b/doc/classes/FogMaterial.xml
@@ -5,27 +5,28 @@
</brief_description>
<description>
A [Material] resource that can be used by [FogVolume]s to draw volumetric effects.
+ If you need more advanced effects, use a custom [url=$DOCS_URL/tutorials/shaders/shader_reference/fog_shader.html]fog shader[/url].
</description>
<tutorials>
</tutorials>
<members>
<member name="albedo" type="Color" setter="set_albedo" getter="get_albedo" default="Color(1, 1, 1, 1)">
- Sets the single-scattering [Color] of the [FogVolume]. Internally [member albedo] is converted into single-scattering which is additively blended with other [FogVolume]s and the [member Environment.volumetric_fog_albedo].
+ The single-scattering [Color] of the [FogVolume]. Internally, [member albedo] is converted into single-scattering, which is additively blended with other [FogVolume]s and the [member Environment.volumetric_fog_albedo].
</member>
<member name="density" type="float" setter="set_density" getter="get_density" default="1.0">
- Sets the density of the [FogVolume]. Denser objects are more opaque, but may suffer from under-sampling artifacts that look like stripes.
+ The density of the [FogVolume]. Denser objects are more opaque, but may suffer from under-sampling artifacts that look like stripes. Negative values can be used to subtract fog from other [FogVolume]s or global volumetric fog.
</member>
<member name="density_texture" type="Texture3D" setter="set_density_texture" getter="get_density_texture">
- Sets a 3D texture that is used to scale the [member density] of the [FogVolume].
+ The 3D texture that is used to scale the [member density] of the [FogVolume]. This can be used to vary fog density within the [FogVolume] with any kind of static pattern. For animated effects, consider using a custom [url=$DOCS_URL/tutorials/shaders/shader_reference/fog_shader.html]fog shader[/url].
</member>
<member name="edge_fade" type="float" setter="set_edge_fade" getter="get_edge_fade" default="0.1">
- Sets the hardness of the edges of the [FogVolume]. A higher number will result in softer edges while a lower number will result in harder edges.
+ The hardness of the edges of the [FogVolume]. A higher value will result in softer edges, while a lower value will result in harder edges.
</member>
<member name="emission" type="Color" setter="set_emission" getter="get_emission" default="Color(0, 0, 0, 1)">
- Sets the [Color] of the light emitted by the [FogVolume]. Emitted light will not cast light or shadows on other objects, but can be useful for modulating the [Color] of the [FogVolume] independently from light sources.
+ The [Color] of the light emitted by the [FogVolume]. Emitted light will not cast light or shadows on other objects, but can be useful for modulating the [Color] of the [FogVolume] independently from light sources.
</member>
<member name="height_falloff" type="float" setter="set_height_falloff" getter="get_height_falloff" default="0.0">
- Sets the rate by which the height-based fog decreases in density as height increases in world space. A high falloff will result in a sharp transition, while a low falloff will result in a smoother transition. A value of [code]0[/code] results in uniform-density fog. The height threshold is determined by the height of the associated [FogVolume].
+ The rate by which the height-based fog decreases in density as height increases in world space. A high falloff will result in a sharp transition, while a low falloff will result in a smoother transition. A value of [code]0.0[/code] results in uniform-density fog. The height threshold is determined by the height of the associated [FogVolume].
</member>
</members>
</class>
diff --git a/doc/classes/FogVolume.xml b/doc/classes/FogVolume.xml
index 3f2ee3035c..d9fa2e6ebb 100644
--- a/doc/classes/FogVolume.xml
+++ b/doc/classes/FogVolume.xml
@@ -4,22 +4,23 @@
A node used to add local fog with the volumetric fog effect.
</brief_description>
<description>
- [FogVolume]s are used to add localized fog into the global volumetric fog effect.
+ [FogVolume]s are used to add localized fog into the global volumetric fog effect. [FogVolume]s can also remove volumetric fog from specific areas if using a [FogMaterial] with a negative [member FogMaterial.density].
Performance of [FogVolume]s is directly related to their relative size on the screen and the complexity of their attached [FogMaterial]. It is best to keep [FogVolume]s relatively small and simple where possible.
+ [b]Note:[/b] [FogVolume]s only have a visible effect if [member Environment.volumetric_fog_enabled] is [code]true[/code]. If you don't want fog to be globally visible (but only within [FogVolume] nodes), set [member Environment.volumetric_fog_density] to [code]0.0[/code].
</description>
<tutorials>
</tutorials>
<members>
<member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(1, 1, 1)">
- Sets the size of the [FogVolume] when [member shape] is [constant RenderingServer.FOG_VOLUME_SHAPE_ELLIPSOID], [constant RenderingServer.FOG_VOLUME_SHAPE_CONE], [constant RenderingServer.FOG_VOLUME_SHAPE_CYLINDER] or [constant RenderingServer.FOG_VOLUME_SHAPE_BOX].
+ The size of the [FogVolume] when [member shape] is [constant RenderingServer.FOG_VOLUME_SHAPE_ELLIPSOID], [constant RenderingServer.FOG_VOLUME_SHAPE_CONE], [constant RenderingServer.FOG_VOLUME_SHAPE_CYLINDER] or [constant RenderingServer.FOG_VOLUME_SHAPE_BOX].
[b]Note:[/b] Thin fog volumes may appear to flicker when the camera moves or rotates. This can be alleviated by increasing [member ProjectSettings.rendering/environment/volumetric_fog/volume_depth] (at a performance cost) or by decreasing [member Environment.volumetric_fog_length] (at no performance cost, but at the cost of lower fog range). Alternatively, the [FogVolume] can be made thicker and use a lower density in the [member material].
[b]Note:[/b] If [member shape] is [constant RenderingServer.FOG_VOLUME_SHAPE_CONE] or [constant RenderingServer.FOG_VOLUME_SHAPE_CYLINDER], the cone/cylinder will be adjusted to fit within the extents. Non-uniform scaling of cone/cylinder shapes via the [member extents] property is not supported, but you can scale the [FogVolume] node instead.
</member>
<member name="material" type="Material" setter="set_material" getter="get_material">
- Sets the [Material] to be used by the [FogVolume]. Can be either a [FogMaterial] or a custom [ShaderMaterial].
+ The [Material] used by the [FogVolume]. Can be either a built-in [FogMaterial] or a custom [ShaderMaterial].
</member>
<member name="shape" type="int" setter="set_shape" getter="get_shape" enum="RenderingServer.FogVolumeShape" default="3">
- Sets the shape of the [FogVolume] to either [constant RenderingServer.FOG_VOLUME_SHAPE_ELLIPSOID], [constant RenderingServer.FOG_VOLUME_SHAPE_CONE], [constant RenderingServer.FOG_VOLUME_SHAPE_CYLINDER], [constant RenderingServer.FOG_VOLUME_SHAPE_BOX] or [constant RenderingServer.FOG_VOLUME_SHAPE_WORLD].
+ The shape of the [FogVolume]. This can be set to either [constant RenderingServer.FOG_VOLUME_SHAPE_ELLIPSOID], [constant RenderingServer.FOG_VOLUME_SHAPE_CONE], [constant RenderingServer.FOG_VOLUME_SHAPE_CYLINDER], [constant RenderingServer.FOG_VOLUME_SHAPE_BOX] or [constant RenderingServer.FOG_VOLUME_SHAPE_WORLD].
</member>
</members>
</class>
diff --git a/doc/classes/ImageTextureLayered.xml b/doc/classes/ImageTextureLayered.xml
index f5b338542b..f5786f070a 100644
--- a/doc/classes/ImageTextureLayered.xml
+++ b/doc/classes/ImageTextureLayered.xml
@@ -11,6 +11,8 @@
<return type="int" enum="Error" />
<param index="0" name="images" type="Image[]" />
<description>
+ Creates an [ImageTextureLayered] from an array of [Image]s. The first image decides the width, height, image format and mipmapping setting. The other images must have the same width, height, image format and mipmapping setting.
+ Each [Image] represents one [code]layer[/code].
</description>
</method>
<method name="update_layer">
@@ -18,6 +20,10 @@
<param index="0" name="image" type="Image" />
<param index="1" name="layer" type="int" />
<description>
+ Replaces the existing [Image] data at the given [code]layer[/code] with this new image.
+ The given [Image] must have the same width, height, image format and mipmapping setting (a [code]bool[/code] value) as the rest of the referenced images.
+ If the image format is unsupported, it will be decompressed and converted to a similar and supported [enum Image.Format].
+ The update is immediate: synced with the draw.
</description>
</method>
</methods>
diff --git a/doc/classes/JSON.xml b/doc/classes/JSON.xml
index 46e46cc164..38ddca2727 100644
--- a/doc/classes/JSON.xml
+++ b/doc/classes/JSON.xml
@@ -6,7 +6,7 @@
<description>
The [JSON] enables all data types to be converted to and from a JSON string. This useful for serializing data to save to a file or send over the network.
[method stringify] is used to convert any data type into a JSON string.
- [method parse] is used to convert any existing JSON data into a [Variant] that can be used within Godot. If successfully parsed, use [method get_data] to retrieve the [Variant], and use [code]typeof[/code] to check if the Variant's type is what you expect. JSON Objects are converted into a [Dictionary], but JSON data can be used to store [Array]s, numbers, [String]s and even just a boolean.
+ [method parse] is used to convert any existing JSON data into a [Variant] that can be used within Godot. If successfully parsed, use [member data] to retrieve the [Variant], and use [code]typeof[/code] to check if the Variant's type is what you expect. JSON Objects are converted into a [Dictionary], but JSON data can be used to store [Array]s, numbers, [String]s and even just a boolean.
[b]Example[/b]
[codeblock]
var data_to_send = ["a", "b", "c"]
@@ -16,7 +16,7 @@
# Retrieve data
var error = json.parse(json_string)
if error == OK:
- var data_received = json.get_data()
+ var data_received = json.data
if typeof(data_received) == TYPE_ARRAY:
print(data_received) # Prints array
else:
@@ -32,13 +32,6 @@
<tutorials>
</tutorials>
<methods>
- <method name="get_data" qualifiers="const">
- <return type="Variant" />
- <description>
- Returns the [Variant] containing the data of a successful [method parse].
- [b]Note:[/b] It will return [code]Null[/code] if the last call to parse was unsuccessful or [method parse] has not yet been called.
- </description>
- </method>
<method name="get_error_line" qualifiers="const">
<return type="int" />
<description>
@@ -56,7 +49,7 @@
<param index="0" name="json_string" type="String" />
<description>
Attempts to parse the [param json_string] provided.
- Returns an [enum Error]. If the parse was successful, it returns [code]OK[/code] and the result can be retrieved using [method get_data]. If unsuccessful, use [method get_error_line] and [method get_error_message] for identifying the source of the failure.
+ Returns an [enum Error]. If the parse was successful, it returns [code]OK[/code] and the result can be retrieved using [member data]. If unsuccessful, use [method get_error_line] and [method get_error_message] for identifying the source of the failure.
Non-static variant of [method parse_string], if you want custom error handling.
</description>
</method>
@@ -118,4 +111,9 @@
</description>
</method>
</methods>
+ <members>
+ <member name="data" type="Variant" setter="set_data" getter="get_data" default="null">
+ Contains the parsed JSON data in [Variant] form.
+ </member>
+ </members>
</class>
diff --git a/doc/classes/LightmapGI.xml b/doc/classes/LightmapGI.xml
index dd8c7be489..53dae1a8e6 100644
--- a/doc/classes/LightmapGI.xml
+++ b/doc/classes/LightmapGI.xml
@@ -17,7 +17,7 @@
<member name="bias" type="float" setter="set_bias" getter="get_bias" default="0.0005">
The bias to use when computing shadows. Increasing [member bias] can fix shadow acne on the resulting baked lightmap, but can introduce peter-panning (shadows not connecting to their casters). Real-time [Light3D] shadows are not affected by this [member bias] property.
</member>
- <member name="bounces" type="int" setter="set_bounces" getter="get_bounces" default="1">
+ <member name="bounces" type="int" setter="set_bounces" getter="get_bounces" default="3">
Number of light bounces that are taken into account during baking. Higher values result in brighter, more realistic lighting, at the cost of longer bake times. If set to [code]0[/code], only environment lighting, direct light and emissive lighting is baked.
</member>
<member name="camera_attributes" type="CameraAttributes" setter="set_camera_attributes" getter="get_camera_attributes">
@@ -36,10 +36,10 @@
<member name="environment_custom_sky" type="Sky" setter="set_environment_custom_sky" getter="get_environment_custom_sky">
The sky to use as a source of environment lighting. Only effective if [member environment_mode] is [constant ENVIRONMENT_MODE_CUSTOM_SKY].
</member>
- <member name="environment_mode" type="int" setter="set_environment_mode" getter="get_environment_mode" enum="LightmapGI.EnvironmentMode" default="0">
+ <member name="environment_mode" type="int" setter="set_environment_mode" getter="get_environment_mode" enum="LightmapGI.EnvironmentMode" default="1">
The environment mode to use when baking lightmaps.
</member>
- <member name="generate_probes_subdiv" type="int" setter="set_generate_probes" getter="get_generate_probes" enum="LightmapGI.GenerateProbes" default="0">
+ <member name="generate_probes_subdiv" type="int" setter="set_generate_probes" getter="get_generate_probes" enum="LightmapGI.GenerateProbes" default="2">
The level of subdivision to use when automatically generating [LightmapProbe]s for dynamic object lighting. Higher values result in more accurate indirect lighting on dynamic objects, at the cost of longer bake times and larger file sizes.
[b]Note:[/b] Automatically generated [LightmapProbe]s are not visible as nodes in the Scene tree dock, and cannot be modified this way after they are generated.
[b]Note:[/b] Regardless of [member generate_probes_subdiv], direct lighting on dynamic objects is always applied using [Light3D] nodes in real-time.
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index 059766656f..54f31d7918 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -216,6 +216,15 @@
Not to be confused with [method get_user_data_dir], which returns the [i]project-specific[/i] user data path.
</description>
</method>
+ <method name="get_distribution_name" qualifiers="const">
+ <return type="String" />
+ <description>
+ Returns the name of the distribution for Linux and BSD platforms (e.g. Ubuntu, Manjaro, OpenBSD, etc.).
+ Returns the same value as [method get_name] for stock Android ROMs, but attempts to return the custom ROM name for popular Android derivatives such as LineageOS.
+ Returns the same value as [method get_name] for other platforms.
+ [b]Note:[/b] This method is not supported on the web platform. It returns an empty string.
+ </description>
+ </method>
<method name="get_environment" qualifiers="const">
<return type="String" />
<param index="0" name="variable" type="String" />
@@ -430,6 +439,18 @@
Not to be confused with [method get_data_dir], which returns the [i]global[/i] (non-project-specific) user home directory.
</description>
</method>
+ <method name="get_version" qualifiers="const">
+ <return type="String" />
+ <description>
+ Returns the exact production and build version of the operating system. This is different from the branded version used in marketing. This helps to distinguish between different releases of operating systems, including minor versions, and insider and custom builds.
+ For Windows, the major and minor version are returned, as well as the build number. For example, the returned string can look like [code]10.0.9926[/code] for a build of Windows 10, and it can look like [code]6.1.7601[/code] for a build of Windows 7 SP1.
+ For rolling distributions, such as Arch Linux, an empty string is returned.
+ For macOS and iOS, the major and minor version are returned, as well as the patch number.
+ For UWP, the device family version is returned.
+ For Android, the SDK version and the incremental build number are returned. If it's a custom ROM, it attempts to return its version instead.
+ [b]Note:[/b] This method is not supported on the web platform. It returns an empty string.
+ </description>
+ </method>
<method name="has_environment" qualifiers="const">
<return type="bool" />
<param index="0" name="variable" type="String" />
diff --git a/doc/classes/PanoramaSkyMaterial.xml b/doc/classes/PanoramaSkyMaterial.xml
index 21c7f29585..0c27037f28 100644
--- a/doc/classes/PanoramaSkyMaterial.xml
+++ b/doc/classes/PanoramaSkyMaterial.xml
@@ -4,9 +4,9 @@
A [Material] used with [Sky] to draw a background texture.
</brief_description>
<description>
- A resource referenced in a [Sky] that is used to draw a background. The Panorama sky material functions similar to skyboxes in other engines, except it uses an equirectangular sky map instead of a cube map.
+ A resource referenced in a [Sky] that is used to draw a background. The Panorama sky material functions similar to skyboxes in other engines, except it uses an equirectangular sky map instead of a cubemap.
Using an HDR panorama is strongly recommended for accurate, high-quality reflections. Godot supports the Radiance HDR ([code].hdr[/code]) and OpenEXR ([code].exr[/code]) image formats for this purpose.
- You can use [url=https://danilw.github.io/GLSL-howto/cubemap_to_panorama_js/cubemap_to_panorama.html]this tool[/url] to convert a cube map to an equirectangular sky map.
+ You can use [url=https://danilw.github.io/GLSL-howto/cubemap_to_panorama_js/cubemap_to_panorama.html]this tool[/url] to convert a cubemap to an equirectangular sky map.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 1f07a13c94..ffd3dbaf80 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -1782,7 +1782,7 @@
Enables filtering of the volumetric fog effect prior to integration. This substantially blurs the fog which reduces fine details but also smooths out harsh edges and aliasing artifacts. Disable when more detail is required.
</member>
<member name="rendering/environment/volumetric_fog/volume_depth" type="int" setter="" getter="" default="64">
- Number of slices to use along the depth of the froxel buffer for volumetric fog. A lower number will be more efficient but may result in artifacts appearing during camera movement.
+ Number of slices to use along the depth of the froxel buffer for volumetric fog. A lower number will be more efficient but may result in artifacts appearing during camera movement. See also [member Environment.volumetric_fog_length].
</member>
<member name="rendering/environment/volumetric_fog/volume_size" type="int" setter="" getter="" default="64">
Base size used to determine size of froxel buffer in the camera X-axis and Y-axis. The final size is scaled by the aspect ratio of the screen, so actual values may differ from what is set. Set a larger size for more detailed fog, set a smaller size for better performance.
diff --git a/doc/classes/Texture2DArray.xml b/doc/classes/Texture2DArray.xml
index 6f059b5fbf..113f37f974 100644
--- a/doc/classes/Texture2DArray.xml
+++ b/doc/classes/Texture2DArray.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Texture2DArray" inherits="ImageTextureLayered" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
+ A single texture resource which consists of multiple, separate images. Each image has the same dimensions and number of mipmap levels.
</brief_description>
<description>
+ A Texture2DArray is different from a Texture3D: The Texture2DArray does not support trilinear interpolation between the [Image]s, i.e. no blending.
+ A Texture2DArray is also different from an [AtlasTexture]: In a Texture2DArray, all images are treated separately. In an atlas, the regions (i.e. the single images) can be of different sizes. Furthermore, you usually need to add a padding around the regions, to prevent accidental UV mapping to more than one region. The same goes for mipmapping: Mipmap chains are handled separately for each layer. In an atlas, the slicing has to be done manually in the fragment shader.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/TextureLayered.xml b/doc/classes/TextureLayered.xml
index 7b528e2082..5e6afcbc5c 100644
--- a/doc/classes/TextureLayered.xml
+++ b/doc/classes/TextureLayered.xml
@@ -1,10 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="TextureLayered" inherits="Texture" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
- Base class for 3D texture types.
+ Base class for texture types which contain the data of multiple [Image]s. Each image is of the same size and format.
</brief_description>
<description>
- Base class for [Texture2DArray], [Cubemap] and [CubemapArray]. Cannot be used directly, but contains all the functions necessary for accessing the derived resource types. Data is set on a per-layer basis. For [Texture2DArray]s, the layer specifies the array layer.
+ Base class for [Texture2DArray], [Cubemap] and [CubemapArray]. Cannot be used directly, but contains all the functions necessary for accessing the derived resource types.
+ Data is set on a per-layer basis. For [Texture2DArray]s, the layer specifies the array layer.
+ All images need to have the same width, height and number of mipmap levels.
+ A [TextureLayered] can be loaded with [code]method ResourceFormatLoader.load[/code].
+ To create such a texture file yourself, re-import your image files using the Godot Editor import presets.
+ Internally, Godot maps these files to their respective counterparts in the target rendering driver (GLES3, Vulkan).
</description>
<tutorials>
</tutorials>
@@ -72,6 +77,7 @@
<method name="get_layers" qualifiers="const">
<return type="int" />
<description>
+ Returns the number of referenced [Image]s.
</description>
</method>
<method name="get_width" qualifiers="const">
@@ -83,6 +89,7 @@
<method name="has_mipmaps" qualifiers="const">
<return type="bool" />
<description>
+ Returns [code]true[/code] if the layers have generated mipmaps.
</description>
</method>
</methods>
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 8d4954136e..0ffede0992 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -198,7 +198,8 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
int item_count = 0;
bool backbuffer_cleared = false;
bool time_used = false;
- bool material_screen_texture_found = false;
+ bool material_screen_texture_cached = false;
+ bool material_screen_texture_mipmaps_cached = false;
Rect2 back_buffer_rect;
bool backbuffer_copy = false;
bool backbuffer_gen_mipmaps = false;
@@ -223,10 +224,12 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
GLES3::CanvasMaterialData *md = static_cast<GLES3::CanvasMaterialData *>(material_storage->material_get_data(material, RS::SHADER_CANVAS_ITEM));
if (md && md->shader_data->valid) {
if (md->shader_data->uses_screen_texture && canvas_group_owner == nullptr) {
- if (!material_screen_texture_found) {
+ if (!material_screen_texture_cached) {
backbuffer_copy = true;
back_buffer_rect = Rect2();
backbuffer_gen_mipmaps = md->shader_data->uses_screen_texture_mipmaps;
+ } else if (!material_screen_texture_mipmaps_cached) {
+ backbuffer_gen_mipmaps = md->shader_data->uses_screen_texture_mipmaps;
}
}
@@ -287,7 +290,16 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, backbuffer_gen_mipmaps);
backbuffer_copy = false;
- material_screen_texture_found = true; //after a backbuffer copy, screen texture makes no further copies
+ backbuffer_gen_mipmaps = false;
+ material_screen_texture_cached = true; // After a backbuffer copy, screen texture makes no further copies.
+ material_screen_texture_mipmaps_cached = backbuffer_gen_mipmaps;
+ }
+
+ if (backbuffer_gen_mipmaps) {
+ texture_storage->render_target_gen_back_buffer_mipmaps(p_to_render_target, back_buffer_rect);
+
+ backbuffer_gen_mipmaps = false;
+ material_screen_texture_mipmaps_cached = true;
}
// just add all items for now
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index 881fc5615c..d264284ef7 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -304,12 +304,13 @@ private:
};
enum {
- INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 5,
- INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 6,
- INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8,
- INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 9,
- INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 10,
- INSTANCE_DATA_FLAG_USE_VOXEL_GI = 1 << 11,
+ INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 4,
+ INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 5,
+ INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 7,
+ INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 8,
+ INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 9,
+ INSTANCE_DATA_FLAG_USE_VOXEL_GI = 1 << 10,
+ INSTANCE_DATA_FLAG_PARTICLES = 1 << 11,
INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12,
INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13,
INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14,
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index beb2812999..ab298a0e49 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -194,6 +194,14 @@ String OS_Unix::get_name() const {
return "Unix";
}
+String OS_Unix::get_distribution_name() const {
+ return "";
+}
+
+String OS_Unix::get_version() const {
+ return "";
+}
+
double OS_Unix::get_unix_time() const {
struct timeval tv_now;
gettimeofday(&tv_now, nullptr);
diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h
index b4c844bfef..8ef650f28b 100644
--- a/drivers/unix/os_unix.h
+++ b/drivers/unix/os_unix.h
@@ -62,6 +62,8 @@ public:
virtual Error set_cwd(const String &p_cwd) override;
virtual String get_name() const override;
+ virtual String get_distribution_name() const override;
+ virtual String get_version() const override;
virtual DateTime get_datetime(bool p_utc) const override;
virtual TimeZoneInfo get_time_zone_info() const override;
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 70b5501692..8919d23982 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -1445,7 +1445,9 @@ void AnimationTimelineEdit::_anim_loop_pressed() {
default:
break;
}
+ undo_redo->add_do_method(this, "update_values");
undo_redo->add_undo_method(animation.ptr(), "set_loop_mode", animation->get_loop_mode());
+ undo_redo->add_undo_method(this, "update_values");
undo_redo->commit_action();
} else {
String base_path = animation->get_path();
@@ -1913,6 +1915,8 @@ void AnimationTimelineEdit::_bind_methods() {
ADD_SIGNAL(MethodInfo("timeline_changed", PropertyInfo(Variant::FLOAT, "position"), PropertyInfo(Variant::BOOL, "drag"), PropertyInfo(Variant::BOOL, "timeline_only")));
ADD_SIGNAL(MethodInfo("track_added", PropertyInfo(Variant::INT, "track")));
ADD_SIGNAL(MethodInfo("length_changed", PropertyInfo(Variant::FLOAT, "size")));
+
+ ClassDB::bind_method(D_METHOD("update_values"), &AnimationTimelineEdit::update_values);
}
AnimationTimelineEdit::AnimationTimelineEdit() {
@@ -6050,10 +6054,9 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
real_t to_diff = fmod(b - a, Math_TAU);
to_v = a + fmod(2.0 * to_diff, Math_TAU) - to_diff;
}
- Variant delta_v;
- Variant::sub(to_v, from_v, delta_v);
+ Variant delta_v = Animation::subtract_variant(to_v, from_v);
double duration = to_t - from_t;
- double fixed_duration = duration - 0.01; // Prevent to overwrap keys...
+ double fixed_duration = duration - UNIT_EPSILON; // Prevent to overwrap keys...
for (double delta_t = dur_step; delta_t < fixed_duration; delta_t += dur_step) {
Pair<real_t, Variant> keydata;
keydata.first = from_t + delta_t;
diff --git a/editor/editor_command_palette.cpp b/editor/editor_command_palette.cpp
index ba1f2fd6af..a0913265eb 100644
--- a/editor/editor_command_palette.cpp
+++ b/editor/editor_command_palette.cpp
@@ -130,7 +130,7 @@ void EditorCommandPalette::_update_command_search(const String &search_text) {
ti->set_metadata(0, entries[i].key_name);
ti->set_text_alignment(1, HORIZONTAL_ALIGNMENT_RIGHT);
ti->set_text(1, shortcut_text);
- Color c = Color(1, 1, 1, 0.5);
+ Color c = get_theme_color(SNAME("font_color"), SNAME("Editor")) * Color(1, 1, 1, 0.5);
ti->set_custom_color(1, c);
}
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index 177bc6d2b2..b89bd23859 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -690,7 +690,6 @@ void EditorFileSystem::scan() {
_update_extensions();
- abort_scan = false;
if (!use_threads) {
scanning = true;
scan_total = 0;
@@ -1162,8 +1161,6 @@ void EditorFileSystem::scan_changes() {
scanning_changes = true;
scanning_changes_done = false;
- abort_scan = false;
-
if (!use_threads) {
if (filesystem) {
EditorProgressBG pr("sources", TTR("ScanSources"), 1000);
@@ -1195,8 +1192,6 @@ void EditorFileSystem::_notification(int p_what) {
case NOTIFICATION_EXIT_TREE: {
Thread &active_thread = thread.is_started() ? thread : thread_sources;
if (use_threads && active_thread.is_started()) {
- //abort thread if in progress
- abort_scan = true;
while (scanning) {
OS::get_singleton()->delay_usec(1000);
}
diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h
index f4e69b95e7..e06c6e4593 100644
--- a/editor/editor_file_system.h
+++ b/editor/editor_file_system.h
@@ -168,7 +168,6 @@ class EditorFileSystem : public Node {
EditorFileSystemDirectory *new_filesystem = nullptr;
- bool abort_scan = false;
bool scanning = false;
bool importing = false;
bool first_scan = true;
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index 9e7314bf50..413eb52556 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -458,7 +458,7 @@ StringName EditorProperty::_get_revert_property() const {
return property;
}
-void EditorProperty::update_revert_and_pin_status() {
+void EditorProperty::update_editor_property_status() {
if (property == StringName()) {
return; //no property, so nothing to do
}
@@ -469,15 +469,26 @@ void EditorProperty::update_revert_and_pin_status() {
CRASH_COND(!node);
new_pinned = node->is_property_pinned(property);
}
+
Variant current = object->get(_get_revert_property());
bool new_can_revert = EditorPropertyRevert::can_property_revert(object, property, &current) && !is_read_only();
- if (new_can_revert != can_revert || new_pinned != pinned) {
+ bool new_checked = checked;
+ if (checkable) { // for properties like theme overrides.
+ bool valid = false;
+ Variant value = object->get(property, &valid);
+ if (valid) {
+ new_checked = value.get_type() != Variant::NIL;
+ }
+ }
+
+ if (new_can_revert != can_revert || new_pinned != pinned || new_checked != checked) {
if (new_can_revert != can_revert) {
emit_signal(SNAME("property_can_revert_changed"), property, new_can_revert);
}
can_revert = new_can_revert;
pinned = new_pinned;
+ checked = new_checked;
queue_redraw();
}
}
@@ -974,7 +985,7 @@ void EditorProperty::_bind_methods() {
ADD_SIGNAL(MethodInfo("selected", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::INT, "focusable_idx")));
GDVIRTUAL_BIND(_update_property)
- ClassDB::bind_method(D_METHOD("_update_revert_and_pin_status"), &EditorProperty::update_revert_and_pin_status);
+ ClassDB::bind_method(D_METHOD("_update_editor_property_status"), &EditorProperty::update_editor_property_status);
}
EditorProperty::EditorProperty() {
@@ -2552,7 +2563,7 @@ void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, EditorIn
ep->set_read_only(read_only);
ep->update_property();
ep->_update_pin_flags();
- ep->update_revert_and_pin_status();
+ ep->update_editor_property_status();
ep->set_deletable(deletable_properties);
ep->update_cache();
}
@@ -3038,7 +3049,7 @@ void EditorInspector::update_tree() {
bool movable = true;
bool numbered = false;
bool foldable = use_folding;
- String add_button_text;
+ String add_button_text = TTR("Add Element");
String swap_method;
for (int i = (p.type == Variant::NIL ? 1 : 2); i < class_name_components.size(); i++) {
if (class_name_components[i].begins_with("page_size") && class_name_components[i].get_slice_count("=") == 2) {
@@ -3211,6 +3222,7 @@ void EditorInspector::update_tree() {
// Use the existing one.
ep->set_label(property_label_string);
}
+
for (int j = 0; j < properties.size(); j++) {
String prop = properties[j];
@@ -3258,7 +3270,7 @@ void EditorInspector::update_tree() {
ep->set_doc_path(doc_info.path);
ep->update_property();
ep->_update_pin_flags();
- ep->update_revert_and_pin_status();
+ ep->update_editor_property_status();
ep->update_cache();
if (current_selected && ep->property == current_selected) {
@@ -3297,7 +3309,7 @@ void EditorInspector::update_property(const String &p_prop) {
for (EditorProperty *E : editor_property_map[p_prop]) {
E->update_property();
- E->update_revert_and_pin_status();
+ E->update_editor_property_status();
E->update_cache();
}
}
@@ -3640,7 +3652,7 @@ void EditorInspector::_edit_set(const String &p_name, const Variant &p_value, bo
if (editor_property_map.has(p_name)) {
for (EditorProperty *E : editor_property_map[p_name]) {
- E->update_revert_and_pin_status();
+ E->update_editor_property_status();
}
}
}
@@ -3754,7 +3766,7 @@ void EditorInspector::_property_checked(const String &p_path, bool p_checked) {
for (EditorProperty *E : editor_property_map[p_path]) {
E->set_checked(p_checked);
E->update_property();
- E->update_revert_and_pin_status();
+ E->update_editor_property_status();
E->update_cache();
}
}
@@ -3778,8 +3790,8 @@ void EditorInspector::_property_pinned(const String &p_path, bool p_pinned) {
undo_redo->add_undo_method(node, "_set_property_pinned", p_path, !p_pinned);
if (editor_property_map.has(p_path)) {
for (List<EditorProperty *>::Element *E = editor_property_map[p_path].front(); E; E = E->next()) {
- undo_redo->add_do_method(E->get(), "_update_revert_and_pin_status");
- undo_redo->add_undo_method(E->get(), "_update_revert_and_pin_status");
+ undo_redo->add_do_method(E->get(), "_update_editor_property_status");
+ undo_redo->add_undo_method(E->get(), "_update_editor_property_status");
}
}
undo_redo->commit_action();
@@ -3787,7 +3799,7 @@ void EditorInspector::_property_pinned(const String &p_path, bool p_pinned) {
node->set_property_pinned(p_path, p_pinned);
if (editor_property_map.has(p_path)) {
for (List<EditorProperty *>::Element *E = editor_property_map[p_path].front(); E; E = E->next()) {
- E->get()->update_revert_and_pin_status();
+ E->get()->update_editor_property_status();
}
}
}
@@ -3868,7 +3880,7 @@ void EditorInspector::_notification(int p_what) {
for (EditorProperty *E : F.value) {
if (E && !E->is_cache_valid()) {
E->update_property();
- E->update_revert_and_pin_status();
+ E->update_editor_property_status();
E->update_cache();
}
}
@@ -3890,7 +3902,7 @@ void EditorInspector::_notification(int p_what) {
if (editor_property_map.has(prop)) {
for (EditorProperty *E : editor_property_map[prop]) {
E->update_property();
- E->update_revert_and_pin_status();
+ E->update_editor_property_status();
E->update_cache();
}
}
@@ -3983,13 +3995,7 @@ void EditorInspector::_check_meta_name(const String &p_name) {
} else if (!p_name.is_valid_identifier()) {
error = TTR("Metadata name must be a valid identifier.");
} else if (object->has_meta(p_name)) {
- Node *node = Object::cast_to<Node>(object);
- if (node) {
- error = vformat(TTR("Metadata with name \"%s\" already exists on \"%s\"."), p_name, node->get_name());
- } else {
- // This should normally never be reached, but the error is set just in case.
- error = vformat(TTR("Metadata with name \"%s\" already exists."), p_name, node->get_name());
- }
+ error = vformat(TTR("Metadata with name \"%s\" already exists."), p_name);
} else if (p_name[0] == '_') {
error = TTR("Names starting with _ are reserved for editor-only metadata.");
}
@@ -4009,14 +4015,6 @@ void EditorInspector::_show_add_meta_dialog() {
if (!add_meta_dialog) {
add_meta_dialog = memnew(ConfirmationDialog);
- Node *node = Object::cast_to<Node>(object);
- if (node) {
- add_meta_dialog->set_title(vformat(TTR("Add Metadata Property for \"%s\""), node->get_name()));
- } else {
- // This should normally never be reached, but the title is set just in case.
- add_meta_dialog->set_title(vformat(TTR("Add Metadata Property"), node->get_name()));
- }
-
VBoxContainer *vbc = memnew(VBoxContainer);
add_meta_dialog->add_child(vbc);
HBoxContainer *hbc = memnew(HBoxContainer);
@@ -4046,6 +4044,14 @@ void EditorInspector::_show_add_meta_dialog() {
add_meta_name->connect("text_changed", callable_mp(this, &EditorInspector::_check_meta_name));
}
+ Node *node = Object::cast_to<Node>(object);
+ if (node) {
+ add_meta_dialog->set_title(vformat(TTR("Add Metadata Property for \"%s\""), node->get_name()));
+ } else {
+ // This should normally be reached when the object is derived from Resource.
+ add_meta_dialog->set_title(vformat(TTR("Add Metadata Property for \"%s\""), object->get_class()));
+ }
+
add_meta_dialog->popup_centered();
add_meta_name->set_text("");
_check_meta_name("");
diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h
index 70378d8cf2..b7df5a8037 100644
--- a/editor/editor_inspector.h
+++ b/editor/editor_inspector.h
@@ -151,7 +151,7 @@ public:
void set_doc_path(const String &p_doc_path);
virtual void update_property();
- void update_revert_and_pin_status();
+ void update_editor_property_status();
virtual bool use_keying_next() const;
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index c8b49678d2..33aad0ac61 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -7645,6 +7645,7 @@ void Node3DEditor::_update_preview_environment() {
preview_sun->get_parent()->remove_child(preview_sun);
sun_state->show();
sun_vb->hide();
+ preview_sun_dangling = true;
}
if (directional_light_count > 0) {
@@ -7658,6 +7659,7 @@ void Node3DEditor::_update_preview_environment() {
add_child(preview_sun, true);
sun_state->hide();
sun_vb->show();
+ preview_sun_dangling = false;
}
}
@@ -7673,6 +7675,7 @@ void Node3DEditor::_update_preview_environment() {
preview_environment->get_parent()->remove_child(preview_environment);
environ_state->show();
environ_vb->hide();
+ preview_env_dangling = true;
}
if (world_env_count > 0) {
environ_state->set_text(TTR("Scene contains\nWorldEnvironment.\nPreview disabled."));
@@ -7685,6 +7688,7 @@ void Node3DEditor::_update_preview_environment() {
add_child(preview_environment);
environ_state->hide();
environ_vb->show();
+ preview_env_dangling = false;
}
}
}
@@ -7854,7 +7858,6 @@ Node3DEditor::Node3DEditor() {
sun_button->set_toggle_mode(true);
sun_button->set_flat(true);
sun_button->connect("pressed", callable_mp(this, &Node3DEditor::_update_preview_environment), CONNECT_DEFERRED);
- sun_button->set_disabled(true);
// Preview is enabled by default - ensure this applies on editor startup when there is no state yet.
sun_button->set_pressed(true);
@@ -7865,7 +7868,6 @@ Node3DEditor::Node3DEditor() {
environ_button->set_toggle_mode(true);
environ_button->set_flat(true);
environ_button->connect("pressed", callable_mp(this, &Node3DEditor::_update_preview_environment), CONNECT_DEFERRED);
- environ_button->set_disabled(true);
// Preview is enabled by default - ensure this applies on editor startup when there is no state yet.
environ_button->set_pressed(true);
@@ -8333,6 +8335,12 @@ void fragment() {
}
Node3DEditor::~Node3DEditor() {
memdelete(preview_node);
+ if (preview_sun_dangling && preview_sun) {
+ memdelete(preview_sun);
+ }
+ if (preview_env_dangling && preview_environment) {
+ memdelete(preview_environment);
+ }
}
void Node3DEditorPlugin::make_visible(bool p_visible) {
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index 580cb878ce..c76f534c22 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -763,7 +763,9 @@ private:
Button *sun_environ_settings = nullptr;
DirectionalLight3D *preview_sun = nullptr;
+ bool preview_sun_dangling = false;
WorldEnvironment *preview_environment = nullptr;
+ bool preview_env_dangling = false;
Ref<Environment> environment;
Ref<CameraAttributesPhysical> camera_attributes;
Ref<ProceduralSkyMaterial> sky_material;
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 246bc4b183..815a61f8ac 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -1366,6 +1366,7 @@ void ShaderEditorPlugin::_shader_selected(int p_index) {
edited_shaders[p_index].shader_editor->validate_script();
}
shader_tabs->set_current_tab(p_index);
+ shader_list->select(p_index);
}
void ShaderEditorPlugin::_shader_list_clicked(int p_item, Vector2 p_local_mouse_pos, MouseButton p_mouse_button_index) {
diff --git a/methods.py b/methods.py
index 1f49da7ace..78ec9b8674 100644
--- a/methods.py
+++ b/methods.py
@@ -77,44 +77,37 @@ def add_module_version_string(self, s):
self.module_version_string += "." + s
-def update_version(module_version_string=""):
+def get_version_info(module_version_string="", silent=False):
build_name = "custom_build"
if os.getenv("BUILD_NAME") != None:
build_name = str(os.getenv("BUILD_NAME"))
- print("Using custom build name: " + build_name)
+ if not silent:
+ print(f"Using custom build name: '{build_name}'.")
import version
- # NOTE: It is safe to generate this file here, since this is still executed serially
- f = open("core/version_generated.gen.h", "w")
- f.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
- f.write("#ifndef VERSION_GENERATED_GEN_H\n")
- f.write("#define VERSION_GENERATED_GEN_H\n")
- f.write('#define VERSION_SHORT_NAME "' + str(version.short_name) + '"\n')
- f.write('#define VERSION_NAME "' + str(version.name) + '"\n')
- f.write("#define VERSION_MAJOR " + str(version.major) + "\n")
- f.write("#define VERSION_MINOR " + str(version.minor) + "\n")
- f.write("#define VERSION_PATCH " + str(version.patch) + "\n")
+ version_info = {
+ "short_name": str(version.short_name),
+ "name": str(version.name),
+ "major": int(version.major),
+ "minor": int(version.minor),
+ "patch": int(version.patch),
+ "status": str(version.status),
+ "build": str(build_name),
+ "module_config": str(version.module_config) + module_version_string,
+ "year": int(version.year),
+ "website": str(version.website),
+ "docs_branch": str(version.docs),
+ }
+
# For dev snapshots (alpha, beta, RC, etc.) we do not commit status change to Git,
# so this define provides a way to override it without having to modify the source.
- godot_status = str(version.status)
if os.getenv("GODOT_VERSION_STATUS") != None:
- godot_status = str(os.getenv("GODOT_VERSION_STATUS"))
- print("Using version status '{}', overriding the original '{}'.".format(godot_status, str(version.status)))
- f.write('#define VERSION_STATUS "' + godot_status + '"\n')
- f.write('#define VERSION_BUILD "' + str(build_name) + '"\n')
- f.write('#define VERSION_MODULE_CONFIG "' + str(version.module_config) + module_version_string + '"\n')
- f.write("#define VERSION_YEAR " + str(version.year) + "\n")
- f.write('#define VERSION_WEBSITE "' + str(version.website) + '"\n')
- f.write('#define VERSION_DOCS_BRANCH "' + str(version.docs) + '"\n')
- f.write('#define VERSION_DOCS_URL "https://docs.godotengine.org/en/" VERSION_DOCS_BRANCH\n')
- f.write("#endif // VERSION_GENERATED_GEN_H\n")
- f.close()
+ version_info["status"] = str(os.getenv("GODOT_VERSION_STATUS"))
+ if not silent:
+ print(f"Using version status '{version_info.status}', overriding the original '{version.status}'.")
- # NOTE: It is safe to generate this file here, since this is still executed serially
- fhash = open("core/version_hash.gen.cpp", "w")
- fhash.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
- fhash.write('#include "core/version.h"\n')
+ # Parse Git hash if we're in a Git repo.
githash = ""
gitfolder = ".git"
@@ -144,7 +137,49 @@ def update_version(module_version_string=""):
else:
githash = head
- fhash.write('const char *const VERSION_HASH = "' + githash + '";\n')
+ version_info["git_hash"] = githash
+
+ return version_info
+
+
+def generate_version_header(module_version_string=""):
+ version_info = get_version_info(module_version_string)
+
+ # NOTE: It is safe to generate these files here, since this is still executed serially.
+
+ f = open("core/version_generated.gen.h", "w")
+ f.write(
+ """/* THIS FILE IS GENERATED DO NOT EDIT */
+#ifndef VERSION_GENERATED_GEN_H
+#define VERSION_GENERATED_GEN_H
+#define VERSION_SHORT_NAME "{short_name}"
+#define VERSION_NAME "{name}"
+#define VERSION_MAJOR {major}
+#define VERSION_MINOR {minor}
+#define VERSION_PATCH {patch}
+#define VERSION_STATUS "{status}"
+#define VERSION_BUILD "{build}"
+#define VERSION_MODULE_CONFIG "{module_config}"
+#define VERSION_YEAR {year}
+#define VERSION_WEBSITE "{website}"
+#define VERSION_DOCS_BRANCH "{docs_branch}"
+#define VERSION_DOCS_URL "https://docs.godotengine.org/en/" VERSION_DOCS_BRANCH
+#endif // VERSION_GENERATED_GEN_H
+""".format(
+ **version_info
+ )
+ )
+ f.close()
+
+ fhash = open("core/version_hash.gen.cpp", "w")
+ fhash.write(
+ """/* THIS FILE IS GENERATED DO NOT EDIT */
+#include "core/version.h"
+const char *const VERSION_HASH = "{git_hash}";
+""".format(
+ **version_info
+ )
+ )
fhash.close()
diff --git a/modules/mono/build_scripts/build_assemblies.py b/modules/mono/build_scripts/build_assemblies.py
index 6f66ce9efa..d78a9c7db8 100755
--- a/modules/mono/build_scripts/build_assemblies.py
+++ b/modules/mono/build_scripts/build_assemblies.py
@@ -315,6 +315,8 @@ def main():
output_dir = os.path.abspath(args.godot_output_dir)
+ push_nupkgs_local = os.path.abspath(args.push_nupkgs_local) if args.push_nupkgs_local else None
+
msbuild_tool = find_any_msbuild_tool(args.mono_prefix)
if msbuild_tool is None:
@@ -327,7 +329,7 @@ def main():
output_dir,
args.godot_platform,
args.dev_debug,
- args.push_nupkgs_local,
+ push_nupkgs_local,
args.float,
)
sys.exit(exit_code)
diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp
index 92d074cb75..94095eb61c 100644
--- a/modules/openxr/openxr_api.cpp
+++ b/modules/openxr/openxr_api.cpp
@@ -1557,7 +1557,7 @@ void OpenXRAPI::end_frame() {
XrCompositionLayerProjection projection_layer = {
XR_TYPE_COMPOSITION_LAYER_PROJECTION, // type
nullptr, // next
- layers_list.size() > 1 ? XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT | XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT : XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT, // layerFlags
+ layers_list.size() > 0 ? XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT | XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT : XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT, // layerFlags
play_space, // space
view_count, // viewCount
projection_views, // views
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 142dc54c45..4469c7a0f7 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -44,6 +44,7 @@
#include "net_socket_android.h"
#include <dlfcn.h>
+#include <sys/system_properties.h>
#include "java_godot_io_wrapper.h"
#include "java_godot_wrapper.h"
@@ -175,6 +176,79 @@ String OS_Android::get_name() const {
return "Android";
}
+String OS_Android::get_system_property(const char *key) const {
+ static String value;
+ char value_str[PROP_VALUE_MAX];
+ if (__system_property_get(key, value_str)) {
+ value = String(value_str);
+ }
+ return value;
+}
+
+String OS_Android::get_distribution_name() const {
+ if (!get_system_property("ro.havoc.version").is_empty()) {
+ return "Havoc OS";
+ } else if (!get_system_property("org.pex.version").is_empty()) { // Putting before "Pixel Experience", because it's derivating from it.
+ return "Pixel Extended";
+ } else if (!get_system_property("org.pixelexperience.version").is_empty()) {
+ return "Pixel Experience";
+ } else if (!get_system_property("ro.potato.version").is_empty()) {
+ return "POSP";
+ } else if (!get_system_property("ro.xtended.version").is_empty()) {
+ return "Project-Xtended";
+ } else if (!get_system_property("org.evolution.version").is_empty()) {
+ return "Evolution X";
+ } else if (!get_system_property("ro.corvus.version").is_empty()) {
+ return "Corvus-Q";
+ } else if (!get_system_property("ro.pa.version").is_empty()) {
+ return "Paranoid Android";
+ } else if (!get_system_property("ro.crdroid.version").is_empty()) {
+ return "crDroid Android";
+ } else if (!get_system_property("ro.syberia.version").is_empty()) {
+ return "Syberia Project";
+ } else if (!get_system_property("ro.arrow.version").is_empty()) {
+ return "ArrowOS";
+ } else if (!get_system_property("ro.lineage.version").is_empty()) { // Putting LineageOS last, just in case any derivative writes to "ro.lineage.version".
+ return "LineageOS";
+ }
+
+ if (!get_system_property("ro.modversion").is_empty()) { // Handles other Android custom ROMs.
+ return vformat("%s %s", get_name(), "Custom ROM");
+ }
+
+ // Handles stock Android.
+ return get_name();
+}
+
+String OS_Android::get_version() const {
+ const Vector<const char *> roms = { "ro.havoc.version", "org.pex.version", "org.pixelexperience.version",
+ "ro.potato.version", "ro.xtended.version", "org.evolution.version", "ro.corvus.version", "ro.pa.version",
+ "ro.crdroid.version", "ro.syberia.version", "ro.arrow.version", "ro.lineage.version" };
+ for (int i = 0; i < roms.size(); i++) {
+ static String rom_version = get_system_property(roms[i]);
+ if (!rom_version.is_empty()) {
+ return rom_version;
+ }
+ }
+
+ static String mod_version = get_system_property("ro.modversion"); // Handles other Android custom ROMs.
+ if (!mod_version.is_empty()) {
+ return mod_version;
+ }
+
+ // Handles stock Android.
+ static String sdk_version = get_system_property("ro.build.version.sdk_int");
+ static String build = get_system_property("ro.build.version.incremental");
+ if (!sdk_version.is_empty()) {
+ if (!build.is_empty()) {
+ return vformat("%s.%s", sdk_version, build);
+ }
+ return sdk_version;
+ }
+
+ return "";
+}
+
MainLoop *OS_Android::get_main_loop() const {
return main_loop;
}
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index 96c06d715c..d6546a3507 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -65,6 +65,8 @@ private:
GodotJavaWrapper *godot_java = nullptr;
GodotIOJavaWrapper *godot_io_java = nullptr;
+ String get_system_property(const char *key) const;
+
public:
static const char *ANDROID_EXEC_PATH;
@@ -93,6 +95,8 @@ public:
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr) override;
virtual String get_name() const override;
+ virtual String get_distribution_name() const override;
+ virtual String get_version() const override;
virtual MainLoop *get_main_loop() const override;
void main_loop_begin();
diff --git a/platform/ios/os_ios.h b/platform/ios/os_ios.h
index 3b88f53b6a..00d91da771 100644
--- a/platform/ios/os_ios.h
+++ b/platform/ios/os_ios.h
@@ -100,6 +100,8 @@ public:
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) override;
virtual String get_name() const override;
+ virtual String get_distribution_name() const override;
+ virtual String get_version() const override;
virtual String get_model_name() const override;
virtual Error shell_open(String p_uri) override;
diff --git a/platform/ios/os_ios.mm b/platform/ios/os_ios.mm
index b9d186f355..a674498620 100644
--- a/platform/ios/os_ios.mm
+++ b/platform/ios/os_ios.mm
@@ -240,6 +240,15 @@ String OS_IOS::get_name() const {
return "iOS";
}
+String OS_IOS::get_distribution_name() const {
+ return get_name();
+}
+
+String OS_IOS::get_version() const {
+ NSOperatingSystemVersion ver = [NSProcessInfo processInfo].operatingSystemVersion;
+ return vformat("%d.%d.%d", (int64_t)ver.majorVersion, (int64_t)ver.minorVersion, (int64_t)ver.patchVersion);
+}
+
String OS_IOS::get_model_name() const {
String model = ios->get_model();
if (model != "") {
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index 0236e134fb..66dea6cf1b 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/display_server_x11.cpp
@@ -397,7 +397,10 @@ void DisplayServerX11::mouse_set_mode(MouseMode p_mode) {
if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) {
//flush pending motion events
_flush_mouse_motion();
- WindowID window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID;
+ WindowID window_id = _get_focused_window_or_popup();
+ if (!windows.has(window_id)) {
+ window_id = MAIN_WINDOW_ID;
+ }
WindowData &window = windows[window_id];
if (XGrabPointer(
@@ -433,7 +436,11 @@ void DisplayServerX11::warp_mouse(const Point2i &p_position) {
if (mouse_mode == MOUSE_MODE_CAPTURED) {
last_mouse_pos = p_position;
} else {
- WindowID window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID;
+ WindowID window_id = _get_focused_window_or_popup();
+ if (!windows.has(window_id)) {
+ window_id = MAIN_WINDOW_ID;
+ }
+
XWarpPointer(x11_display, None, windows[window_id].x11_window,
0, 0, 0, 0, (int)p_position.x, (int)p_position.y);
}
@@ -3181,6 +3188,15 @@ void DisplayServerX11::_window_changed(XEvent *event) {
}
}
+DisplayServer::WindowID DisplayServerX11::_get_focused_window_or_popup() const {
+ const List<WindowID>::Element *E = popup_list.back();
+ if (E) {
+ return E->get();
+ }
+
+ return last_focused_window;
+}
+
void DisplayServerX11::_dispatch_input_events(const Ref<InputEvent> &p_event) {
static_cast<DisplayServerX11 *>(get_singleton())->_dispatch_input_event(p_event);
}
@@ -3936,7 +3952,11 @@ void DisplayServerX11::process_events() {
// The X11 API requires filtering one-by-one through the motion
// notify events, in order to figure out which event is the one
// generated by warping the mouse pointer.
- WindowID focused_window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID;
+ WindowID focused_window_id = _get_focused_window_or_popup();
+ if (!windows.has(focused_window_id)) {
+ focused_window_id = MAIN_WINDOW_ID;
+ }
+
while (true) {
if (mouse_mode == MOUSE_MODE_CAPTURED && event.xmotion.x == windows[focused_window_id].size.width / 2 && event.xmotion.y == windows[focused_window_id].size.height / 2) {
//this is likely the warp event since it was warped here
diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h
index ea03b2328c..a5fa7613bc 100644
--- a/platform/linuxbsd/display_server_x11.h
+++ b/platform/linuxbsd/display_server_x11.h
@@ -284,6 +284,8 @@ class DisplayServerX11 : public DisplayServer {
Context context = CONTEXT_ENGINE;
+ WindowID _get_focused_window_or_popup() const;
+
void _send_window_event(const WindowData &wd, WindowEvent p_event);
static void _dispatch_input_events(const Ref<InputEvent> &p_event);
void _dispatch_input_event(const Ref<InputEvent> &p_event);
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index f0d7b6ede5..f4e94f1a91 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -50,6 +50,7 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/utsname.h>
#include <unistd.h>
#ifdef FONTCONFIG_ENABLED
@@ -205,6 +206,42 @@ String OS_LinuxBSD::get_name() const {
#endif
}
+String OS_LinuxBSD::get_systemd_os_release_info_value(const String &key) const {
+ static String info;
+ if (info.is_empty()) {
+ Ref<FileAccess> f = FileAccess::open("/etc/os-release", FileAccess::READ);
+ if (f.is_valid()) {
+ while (!f->eof_reached()) {
+ const String line = f->get_line();
+ if (line.find(key) != -1) {
+ return line.split("=")[1].strip_edges();
+ }
+ }
+ }
+ }
+ return info;
+}
+
+String OS_LinuxBSD::get_distribution_name() const {
+ static String systemd_name = get_systemd_os_release_info_value("NAME"); // returns a value for systemd users, otherwise an empty string.
+ if (!systemd_name.is_empty()) {
+ return systemd_name;
+ }
+ struct utsname uts; // returns a decent value for BSD family.
+ uname(&uts);
+ return uts.sysname;
+}
+
+String OS_LinuxBSD::get_version() const {
+ static String systemd_version = get_systemd_os_release_info_value("VERSION"); // returns a value for systemd users, otherwise an empty string.
+ if (!systemd_version.is_empty()) {
+ return systemd_version;
+ }
+ struct utsname uts; // returns a decent value for BSD family.
+ uname(&uts);
+ return uts.version;
+}
+
Error OS_LinuxBSD::shell_open(String p_uri) {
Error ok;
int err_code;
diff --git a/platform/linuxbsd/os_linuxbsd.h b/platform/linuxbsd/os_linuxbsd.h
index d5b2321316..722d83ba19 100644
--- a/platform/linuxbsd/os_linuxbsd.h
+++ b/platform/linuxbsd/os_linuxbsd.h
@@ -67,6 +67,8 @@ class OS_LinuxBSD : public OS_Unix {
MainLoop *main_loop = nullptr;
+ String get_systemd_os_release_info_value(const String &key) const;
+
protected:
virtual void initialize() override;
virtual void finalize() override;
@@ -77,6 +79,8 @@ protected:
public:
virtual String get_name() const override;
+ virtual String get_distribution_name() const override;
+ virtual String get_version() const override;
virtual MainLoop *get_main_loop() const override;
diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h
index bb5dce641a..da377c9171 100644
--- a/platform/macos/display_server_macos.h
+++ b/platform/macos/display_server_macos.h
@@ -189,6 +189,8 @@ private:
Point2i _get_native_screen_position(int p_screen) const;
static void _displays_arrangement_changed(CGDirectDisplayID display_id, CGDisplayChangeSummaryFlags flags, void *user_info);
+ WindowID _get_focused_window_or_popup() const;
+
static void _dispatch_input_events(const Ref<InputEvent> &p_event);
void _dispatch_input_event(const Ref<InputEvent> &p_event);
void _push_input(const Ref<InputEvent> &p_event);
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index 91c6da5d13..05f89c70aa 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -317,6 +317,15 @@ void DisplayServerMacOS::_displays_arrangement_changed(CGDirectDisplayID display
}
}
+DisplayServer::WindowID DisplayServerMacOS::_get_focused_window_or_popup() const {
+ const List<WindowID>::Element *E = popup_list.back();
+ if (E) {
+ return E->get();
+ }
+
+ return last_focused_window;
+}
+
void DisplayServerMacOS::_dispatch_input_events(const Ref<InputEvent> &p_event) {
((DisplayServerMacOS *)(get_singleton()))->_dispatch_input_event(p_event);
}
@@ -1828,7 +1837,10 @@ void DisplayServerMacOS::mouse_set_mode(MouseMode p_mode) {
return;
}
- WindowID window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID;
+ WindowID window_id = _get_focused_window_or_popup();
+ if (!windows.has(window_id)) {
+ window_id = MAIN_WINDOW_ID;
+ }
WindowData &wd = windows[window_id];
if (p_mode == MOUSE_MODE_CAPTURED) {
// Apple Docs state that the display parameter is not used.
@@ -1943,7 +1955,10 @@ void DisplayServerMacOS::warp_mouse(const Point2i &p_position) {
_THREAD_SAFE_METHOD_
if (mouse_mode != MOUSE_MODE_CAPTURED) {
- WindowID window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID;
+ WindowID window_id = _get_focused_window_or_popup();
+ if (!windows.has(window_id)) {
+ window_id = MAIN_WINDOW_ID;
+ }
WindowData &wd = windows[window_id];
// Local point in window coords.
@@ -3537,7 +3552,7 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM
[apple_menu addItem:[NSMenuItem separatorItem]];
- title = [NSString stringWithFormat:NSLocalizedString(@"\t\tQuit %@", nil), nsappname];
+ title = [NSString stringWithFormat:NSLocalizedString(@"Quit %@", nil), nsappname];
[apple_menu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
// Add items to the menu bar.
diff --git a/platform/macos/os_macos.h b/platform/macos/os_macos.h
index 61db99689c..46e7c17ebe 100644
--- a/platform/macos/os_macos.h
+++ b/platform/macos/os_macos.h
@@ -75,6 +75,8 @@ public:
virtual List<String> get_cmdline_platform_args() const override;
virtual String get_name() const override;
+ virtual String get_distribution_name() const override;
+ virtual String get_version() const override;
virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
diff --git a/platform/macos/os_macos.mm b/platform/macos/os_macos.mm
index c250a9d71a..ae8534f6ab 100644
--- a/platform/macos/os_macos.mm
+++ b/platform/macos/os_macos.mm
@@ -134,6 +134,15 @@ String OS_MacOS::get_name() const {
return "macOS";
}
+String OS_MacOS::get_distribution_name() const {
+ return get_name();
+}
+
+String OS_MacOS::get_version() const {
+ NSOperatingSystemVersion ver = [NSProcessInfo processInfo].operatingSystemVersion;
+ return vformat("%d.%d.%d", (int64_t)ver.majorVersion, (int64_t)ver.minorVersion, (int64_t)ver.patchVersion);
+}
+
void OS_MacOS::alert(const String &p_alert, const String &p_title) {
NSAlert *window = [[NSAlert alloc] init];
NSString *ns_title = [NSString stringWithUTF8String:p_title.utf8().get_data()];
diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp
index 791328964b..8050d299f0 100644
--- a/platform/uwp/os_uwp.cpp
+++ b/platform/uwp/os_uwp.cpp
@@ -444,6 +444,16 @@ String OS_UWP::get_name() const {
return "UWP";
}
+String OS_UWP::get_distribution_name() const {
+ return get_name();
+}
+
+String OS_UWP::get_version() const {
+ winrt::hstring df_version = VersionInfo().DeviceFamilyVersion();
+ static String version = String(winrt::to_string(df_version).c_str());
+ return version;
+}
+
OS::DateTime OS_UWP::get_datetime(bool p_utc) const {
SYSTEMTIME systemtime;
if (p_utc) {
diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h
index 7d4224cf74..0c1c4a793a 100644
--- a/platform/uwp/os_uwp.h
+++ b/platform/uwp/os_uwp.h
@@ -183,6 +183,8 @@ public:
virtual MainLoop *get_main_loop() const;
virtual String get_name() const;
+ virtual String get_distribution_name() const;
+ virtual String get_version() const;
virtual DateTime get_datetime(bool p_utc) const;
virtual TimeZoneInfo get_time_zone_info() const;
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index 237215c198..4553f31480 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -104,7 +104,10 @@ void DisplayServerWindows::_set_mouse_mode_impl(MouseMode p_mode) {
if (windows.has(MAIN_WINDOW_ID) && (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED || p_mode == MOUSE_MODE_CONFINED_HIDDEN)) {
// Mouse is grabbed (captured or confined).
- WindowID window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID;
+ WindowID window_id = _get_focused_window_or_popup();
+ if (!windows.has(window_id)) {
+ window_id = MAIN_WINDOW_ID;
+ }
WindowData &wd = windows[window_id];
@@ -119,11 +122,15 @@ void DisplayServerWindows::_set_mouse_mode_impl(MouseMode p_mode) {
ClientToScreen(wd.hWnd, &pos);
SetCursorPos(pos.x, pos.y);
SetCapture(wd.hWnd);
+
+ _register_raw_input_devices(window_id);
}
} else {
// Mouse is free to move around (not captured or confined).
ReleaseCapture();
ClipCursor(nullptr);
+
+ _register_raw_input_devices(INVALID_WINDOW_ID);
}
if (p_mode == MOUSE_MODE_HIDDEN || p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED_HIDDEN) {
@@ -139,6 +146,37 @@ void DisplayServerWindows::_set_mouse_mode_impl(MouseMode p_mode) {
}
}
+DisplayServer::WindowID DisplayServerWindows::_get_focused_window_or_popup() const {
+ const List<WindowID>::Element *E = popup_list.back();
+ if (E) {
+ return E->get();
+ }
+
+ return last_focused_window;
+}
+
+void DisplayServerWindows::_register_raw_input_devices(WindowID p_target_window) {
+ use_raw_input = true;
+
+ RAWINPUTDEVICE rid[1] = {};
+ rid[0].usUsagePage = 0x01;
+ rid[0].usUsage = 0x02;
+ rid[0].dwFlags = 0;
+
+ if (p_target_window != INVALID_WINDOW_ID && windows.has(p_target_window)) {
+ // Follow the defined window
+ rid[0].hwndTarget = windows[p_target_window].hWnd;
+ } else {
+ // Follow the keyboard focus
+ rid[0].hwndTarget = 0;
+ }
+
+ if (RegisterRawInputDevices(rid, 1, sizeof(rid[0])) == FALSE) {
+ // Registration failed.
+ use_raw_input = false;
+ }
+}
+
bool DisplayServerWindows::tts_is_speaking() const {
ERR_FAIL_COND_V(!tts, false);
return tts->is_speaking();
@@ -194,7 +232,9 @@ DisplayServer::MouseMode DisplayServerWindows::mouse_get_mode() const {
void DisplayServerWindows::warp_mouse(const Point2i &p_position) {
_THREAD_SAFE_METHOD_
- if (!windows.has(last_focused_window)) {
+ WindowID window_id = _get_focused_window_or_popup();
+
+ if (!windows.has(window_id)) {
return; // No focused window?
}
@@ -205,7 +245,7 @@ void DisplayServerWindows::warp_mouse(const Point2i &p_position) {
POINT p;
p.x = p_position.x;
p.y = p_position.y;
- ClientToScreen(windows[last_focused_window].hWnd, &p);
+ ClientToScreen(windows[window_id].hWnd, &p);
SetCursorPos(p.x, p.y);
}
@@ -2483,7 +2523,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
old_y = coords.y;
}
- if (windows[window_id].window_has_focus && mm->get_relative() != Vector2()) {
+ if ((windows[window_id].window_has_focus || windows[window_id].is_popup) && mm->get_relative() != Vector2()) {
Input::get_singleton()->parse_input_event(mm);
}
}
@@ -3773,19 +3813,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
return;
}
- use_raw_input = true;
-
- RAWINPUTDEVICE Rid[1];
-
- Rid[0].usUsagePage = 0x01;
- Rid[0].usUsage = 0x02;
- Rid[0].dwFlags = 0;
- Rid[0].hwndTarget = 0;
-
- if (RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])) == FALSE) {
- // Registration failed.
- use_raw_input = false;
- }
+ _register_raw_input_devices(INVALID_WINDOW_ID);
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index fd64a02020..d85d6364bd 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -466,6 +466,8 @@ class DisplayServerWindows : public DisplayServer {
void _update_real_mouse_position(WindowID p_window);
void _set_mouse_mode_impl(MouseMode p_mode);
+ WindowID _get_focused_window_or_popup() const;
+ void _register_raw_input_devices(WindowID p_target_window);
void _process_activate_event(WindowID p_window_id, WPARAM wParam, LPARAM lParam);
void _process_key_events();
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 2c268ff3d5..1978ec5ab6 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -290,6 +290,24 @@ String OS_Windows::get_name() const {
return "Windows";
}
+String OS_Windows::get_distribution_name() const {
+ return get_name();
+}
+
+String OS_Windows::get_version() const {
+ typedef LONG NTSTATUS, *PNTSTATUS;
+ typedef NTSTATUS(WINAPI * RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
+ RtlGetVersionPtr version_ptr = (RtlGetVersionPtr)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlGetVersion");
+ if (version_ptr != nullptr) {
+ RTL_OSVERSIONINFOW fow = { 0 };
+ fow.dwOSVersionInfoSize = sizeof(fow);
+ if (version_ptr(&fow) == 0x00000000) {
+ return vformat("%d.%d.%d", (int64_t)fow.dwMajorVersion, (int64_t)fow.dwMinorVersion, (int64_t)fow.dwBuildNumber);
+ }
+ }
+ return "";
+}
+
OS::DateTime OS_Windows::get_datetime(bool p_utc) const {
SYSTEMTIME systemtime;
if (p_utc) {
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 53451b780e..491de2266f 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -143,6 +143,8 @@ public:
virtual MainLoop *get_main_loop() const override;
virtual String get_name() const override;
+ virtual String get_distribution_name() const override;
+ virtual String get_version() const override;
virtual void initialize_joypads() override {}
diff --git a/scene/2d/animated_sprite_2d.cpp b/scene/2d/animated_sprite_2d.cpp
index 7fe464d2f4..afa4633848 100644
--- a/scene/2d/animated_sprite_2d.cpp
+++ b/scene/2d/animated_sprite_2d.cpp
@@ -63,9 +63,13 @@ Rect2 AnimatedSprite2D::_edit_get_rect() const {
}
bool AnimatedSprite2D::_edit_use_rect() const {
- if (!frames.is_valid() || !frames->has_animation(animation) || frame < 0 || frame >= frames->get_frame_count(animation)) {
+ if (frames.is_null() || !frames->has_animation(animation)) {
return false;
}
+ if (frame < 0 || frame >= frames->get_frame_count(animation)) {
+ return false;
+ }
+
Ref<Texture2D> t;
if (animation) {
t = frames->get_frame(animation, frame);
@@ -79,7 +83,10 @@ Rect2 AnimatedSprite2D::get_anchorable_rect() const {
}
Rect2 AnimatedSprite2D::_get_rect() const {
- if (!frames.is_valid() || !frames->has_animation(animation) || frame < 0 || frame >= frames->get_frame_count(animation)) {
+ if (frames.is_null() || !frames->has_animation(animation)) {
+ return Rect2();
+ }
+ if (frame < 0 || frame >= frames->get_frame_count(animation)) {
return Rect2();
}
@@ -161,29 +168,22 @@ void AnimatedSprite2D::_validate_property(PropertyInfo &p_property) const {
void AnimatedSprite2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_INTERNAL_PROCESS: {
- if (frames.is_null()) {
+ if (frames.is_null() || !frames->has_animation(animation)) {
return;
}
- if (!frames->has_animation(animation)) {
- return;
- }
- if (frame < 0) {
- return;
+
+ double speed = frames->get_animation_speed(animation) * Math::abs(speed_scale);
+ if (speed == 0) {
+ return; // Do nothing.
}
+ int last_frame = frames->get_frame_count(animation) - 1;
double remaining = get_process_delta_time();
-
while (remaining) {
- double speed = frames->get_animation_speed(animation) * speed_scale;
- if (speed == 0) {
- return; // Do nothing.
- }
-
if (timeout <= 0) {
timeout = _get_frame_duration();
- int last_frame = frames->get_frame_count(animation) - 1;
- if (!backwards) {
+ if (!playing_backwards) {
// Forward.
if (frame >= last_frame) {
if (frames->get_animation_loop(animation)) {
@@ -229,13 +229,7 @@ void AnimatedSprite2D::_notification(int p_what) {
} break;
case NOTIFICATION_DRAW: {
- if (frames.is_null()) {
- return;
- }
- if (frame < 0) {
- return;
- }
- if (!frames->has_animation(animation)) {
+ if (frames.is_null() || !frames->has_animation(animation)) {
return;
}
@@ -327,9 +321,14 @@ int AnimatedSprite2D::get_frame() const {
}
void AnimatedSprite2D::set_speed_scale(double p_speed_scale) {
+ if (speed_scale == p_speed_scale) {
+ return;
+ }
+
double elapsed = _get_frame_duration() - timeout;
- speed_scale = MAX(p_speed_scale, 0.0f);
+ speed_scale = p_speed_scale;
+ playing_backwards = signbit(speed_scale) != backwards;
// We adapt the timeout so that the animation speed adapts as soon as the speed scale is changed.
_reset_timeout();
@@ -398,12 +397,13 @@ bool AnimatedSprite2D::is_playing() const {
return playing;
}
-void AnimatedSprite2D::play(const StringName &p_animation, const bool p_backwards) {
+void AnimatedSprite2D::play(const StringName &p_animation, bool p_backwards) {
backwards = p_backwards;
+ playing_backwards = signbit(speed_scale) != backwards;
if (p_animation) {
set_animation(p_animation);
- if (frames.is_valid() && backwards && get_frame() == 0) {
+ if (frames.is_valid() && playing_backwards && get_frame() == 0) {
set_frame(frames->get_frame_count(p_animation) - 1);
}
}
@@ -418,7 +418,7 @@ void AnimatedSprite2D::stop() {
double AnimatedSprite2D::_get_frame_duration() {
if (frames.is_valid() && frames->has_animation(animation)) {
- double speed = frames->get_animation_speed(animation) * speed_scale;
+ double speed = frames->get_animation_speed(animation) * Math::abs(speed_scale);
if (speed > 0) {
return 1.0 / speed;
}
diff --git a/scene/2d/animated_sprite_2d.h b/scene/2d/animated_sprite_2d.h
index 0a19e250d8..be1cc5353e 100644
--- a/scene/2d/animated_sprite_2d.h
+++ b/scene/2d/animated_sprite_2d.h
@@ -39,6 +39,7 @@ class AnimatedSprite2D : public Node2D {
Ref<SpriteFrames> frames;
bool playing = false;
+ bool playing_backwards = false;
bool backwards = false;
StringName animation = "default";
int frame = 0;
@@ -81,7 +82,7 @@ public:
void set_sprite_frames(const Ref<SpriteFrames> &p_frames);
Ref<SpriteFrames> get_sprite_frames() const;
- void play(const StringName &p_animation = StringName(), const bool p_backwards = false);
+ void play(const StringName &p_animation = StringName(), bool p_backwards = false);
void stop();
void set_playing(bool p_playing);
diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp
index b0bccc4571..555884f445 100644
--- a/scene/3d/lightmap_gi.cpp
+++ b/scene/3d/lightmap_gi.cpp
@@ -1418,7 +1418,8 @@ float LightmapGI::get_bias() const {
}
void LightmapGI::set_max_texture_size(int p_size) {
- ERR_FAIL_COND(p_size < 2048);
+ ERR_FAIL_COND_MSG(p_size < 2048, vformat("The LightmapGI maximum texture size supplied (%d) is too small. The minimum allowed value is 2048.", p_size));
+ ERR_FAIL_COND_MSG(p_size > 16384, vformat("The LightmapGI maximum texture size supplied (%d) is too large. The maximum allowed value is 16384.", p_size));
max_texture_size = p_size;
}
@@ -1506,7 +1507,7 @@ void LightmapGI::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_denoiser"), "set_use_denoiser", "is_using_denoiser");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0.00001,0.1,0.00001,or_greater"), "set_bias", "get_bias");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "max_texture_size"), "set_max_texture_size", "get_max_texture_size");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_texture_size", PROPERTY_HINT_RANGE, "2048,16384,1"), "set_max_texture_size", "get_max_texture_size");
ADD_GROUP("Environment", "environment_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "environment_mode", PROPERTY_HINT_ENUM, "Disabled,Scene,Custom Sky,Custom Color"), "set_environment_mode", "get_environment_mode");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment_custom_sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_environment_custom_sky", "get_environment_custom_sky");
diff --git a/scene/3d/lightmap_gi.h b/scene/3d/lightmap_gi.h
index 0062a4a093..1d282e92c8 100644
--- a/scene/3d/lightmap_gi.h
+++ b/scene/3d/lightmap_gi.h
@@ -142,16 +142,16 @@ public:
private:
BakeQuality bake_quality = BAKE_QUALITY_MEDIUM;
bool use_denoiser = true;
- int bounces = 1;
+ int bounces = 3;
float bias = 0.0005;
int max_texture_size = 16384;
bool interior = false;
- EnvironmentMode environment_mode = ENVIRONMENT_MODE_DISABLED;
+ EnvironmentMode environment_mode = ENVIRONMENT_MODE_SCENE;
Ref<Sky> environment_custom_sky;
- Color environment_custom_color = Color(0.2, 0.7, 1.0);
+ Color environment_custom_color = Color(1, 1, 1);
float environment_custom_energy = 1.0;
bool directional = false;
- GenerateProbes gen_probes = GENERATE_PROBES_DISABLED;
+ GenerateProbes gen_probes = GENERATE_PROBES_SUBDIV_8;
Ref<CameraAttributes> camera_attributes;
Ref<LightmapGIData> light_data;
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index 7a89bf81bb..380172f396 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -447,7 +447,7 @@ void Sprite3D::_draw() {
if (get_base() != get_mesh()) {
set_base(get_mesh());
}
- if (!texture.is_valid()) {
+ if (texture.is_null()) {
set_base(RID());
return;
}
@@ -807,15 +807,7 @@ void AnimatedSprite3D::_draw() {
set_base(get_mesh());
}
- if (frames.is_null()) {
- return;
- }
-
- if (frame < 0) {
- return;
- }
-
- if (!frames->has_animation(animation)) {
+ if (frames.is_null() || !frames->has_animation(animation)) {
return;
}
@@ -1050,29 +1042,22 @@ void AnimatedSprite3D::_validate_property(PropertyInfo &p_property) const {
void AnimatedSprite3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_INTERNAL_PROCESS: {
- if (frames.is_null()) {
- return;
- }
- if (!frames->has_animation(animation)) {
+ if (frames.is_null() || !frames->has_animation(animation)) {
return;
}
- if (frame < 0) {
- return;
+
+ double speed = frames->get_animation_speed(animation) * Math::abs(speed_scale);
+ if (speed == 0) {
+ return; // Do nothing.
}
+ int last_frame = frames->get_frame_count(animation) - 1;
double remaining = get_process_delta_time();
-
while (remaining) {
- double speed = frames->get_animation_speed(animation) * speed_scale;
- if (speed == 0) {
- return; // Do nothing.
- }
-
if (timeout <= 0) {
timeout = _get_frame_duration();
- int last_frame = frames->get_frame_count(animation) - 1;
- if (!backwards) {
+ if (!playing_backwards) {
// Forward.
if (frame >= last_frame) {
if (frames->get_animation_loop(animation)) {
@@ -1177,9 +1162,14 @@ int AnimatedSprite3D::get_frame() const {
}
void AnimatedSprite3D::set_speed_scale(double p_speed_scale) {
+ if (speed_scale == p_speed_scale) {
+ return;
+ }
+
double elapsed = _get_frame_duration() - timeout;
- speed_scale = MAX(p_speed_scale, 0.0f);
+ speed_scale = p_speed_scale;
+ playing_backwards = signbit(speed_scale) != backwards;
// We adapt the timeout so that the animation speed adapts as soon as the speed scale is changed.
_reset_timeout();
@@ -1191,7 +1181,10 @@ double AnimatedSprite3D::get_speed_scale() const {
}
Rect2 AnimatedSprite3D::get_item_rect() const {
- if (!frames.is_valid() || !frames->has_animation(animation) || frame < 0 || frame >= frames->get_frame_count(animation)) {
+ if (frames.is_null() || !frames->has_animation(animation)) {
+ return Rect2(0, 0, 1, 1);
+ }
+ if (frame < 0 || frame >= frames->get_frame_count(animation)) {
return Rect2(0, 0, 1, 1);
}
@@ -1236,12 +1229,13 @@ bool AnimatedSprite3D::is_playing() const {
return playing;
}
-void AnimatedSprite3D::play(const StringName &p_animation, const bool p_backwards) {
+void AnimatedSprite3D::play(const StringName &p_animation, bool p_backwards) {
backwards = p_backwards;
+ playing_backwards = signbit(speed_scale) != backwards;
if (p_animation) {
set_animation(p_animation);
- if (frames.is_valid() && backwards && get_frame() == 0) {
+ if (frames.is_valid() && playing_backwards && get_frame() == 0) {
set_frame(frames->get_frame_count(p_animation) - 1);
}
}
@@ -1256,7 +1250,7 @@ void AnimatedSprite3D::stop() {
double AnimatedSprite3D::_get_frame_duration() {
if (frames.is_valid() && frames->has_animation(animation)) {
- double speed = frames->get_animation_speed(animation) * speed_scale;
+ double speed = frames->get_animation_speed(animation) * Math::abs(speed_scale);
if (speed > 0) {
return 1.0 / speed;
}
diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h
index e6a546a76d..f6ad1bbdb8 100644
--- a/scene/3d/sprite_3d.h
+++ b/scene/3d/sprite_3d.h
@@ -209,6 +209,7 @@ class AnimatedSprite3D : public SpriteBase3D {
Ref<SpriteFrames> frames;
bool playing = false;
+ bool playing_backwards = false;
bool backwards = false;
StringName animation = "default";
int frame = 0;
@@ -237,7 +238,7 @@ public:
void set_sprite_frames(const Ref<SpriteFrames> &p_frames);
Ref<SpriteFrames> get_sprite_frames() const;
- void play(const StringName &p_animation = StringName(), const bool p_backwards = false);
+ void play(const StringName &p_animation = StringName(), bool p_backwards = false);
void stop();
void set_playing(bool p_playing);
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 72710cf802..ce9406883d 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -650,15 +650,14 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
double c = Math::ease(p_time / first_key_time, transition);
Variant first_value = a->track_get_key_value(i, first_key);
first_value = _post_process_key_value(a, i, first_value, nc->node);
- Variant interp_value;
- Variant::interpolate(pa->capture, first_value, c, interp_value);
+ Variant interp_value = Animation::interpolate_variant(pa->capture, first_value, c);
if (pa->accum_pass != accum_pass) {
ERR_CONTINUE(cache_update_prop_size >= NODE_CACHE_UPDATE_MAX);
cache_update_prop[cache_update_prop_size++] = pa;
pa->value_accum = interp_value;
pa->accum_pass = accum_pass;
} else {
- Variant::interpolate(pa->value_accum, interp_value, p_interp, pa->value_accum);
+ pa->value_accum = Animation::interpolate_variant(pa->value_accum, interp_value, p_interp);
}
continue; //handled
@@ -679,7 +678,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
pa->value_accum = value;
pa->accum_pass = accum_pass;
} else {
- Variant::interpolate(pa->value_accum, value, p_interp, pa->value_accum);
+ pa->value_accum = Animation::interpolate_variant(pa->value_accum, value, p_interp);
}
} else if (p_is_current && p_delta != 0) {
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index c1e674dad5..776706d7f3 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -1383,8 +1383,13 @@ void AnimationTree::_process_graph(double p_delta) {
}
t->value = Math::fposmod(rot_a + (rot_b - rot_init) * (float)blend, (float)Math_TAU);
} else {
- Variant::sub(value, t->init_value, value);
- Variant::blend(t->value, value, blend, t->value);
+ if (t->init_value.get_type() == Variant::BOOL) {
+ value = Animation::subtract_variant(value.operator real_t(), t->init_value.operator real_t());
+ t->value = Animation::blend_variant(t->value.operator real_t(), value.operator real_t(), blend);
+ } else {
+ value = Animation::subtract_variant(value, t->init_value);
+ t->value = Animation::blend_variant(t->value, value, blend);
+ }
}
} else {
if (blend < CMP_EPSILON) {
@@ -1703,7 +1708,11 @@ void AnimationTree::_process_graph(double p_delta) {
case Animation::TYPE_VALUE: {
TrackCacheValue *t = static_cast<TrackCacheValue *>(track);
- t->object->set_indexed(t->subpath, t->value);
+ if (t->init_value.get_type() == Variant::BOOL) {
+ t->object->set_indexed(t->subpath, t->value.operator real_t() >= 0.5);
+ } else {
+ t->object->set_indexed(t->subpath, t->value);
+ }
} break;
case Animation::TYPE_BEZIER: {
diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp
index 5b18d4e457..b02f1959b7 100644
--- a/scene/animation/tween.cpp
+++ b/scene/animation/tween.cpp
@@ -32,6 +32,7 @@
#include "scene/animation/easing_equations.h"
#include "scene/main/node.h"
+#include "scene/resources/animation.h"
Tween::interpolater Tween::interpolaters[Tween::TRANS_MAX][Tween::EASE_MAX] = {
{ &linear::in, &linear::in, &linear::in, &linear::in }, // Linear is the same for each easing.
@@ -314,6 +315,7 @@ bool Tween::step(float p_delta) {
running = false;
dead = true;
emit_signal(SNAME("finished"));
+ break;
} else {
emit_signal(SNAME("loop_finished"), loops_done);
current_step = 0;
@@ -375,264 +377,14 @@ Variant Tween::interpolate_variant(Variant p_initial_val, Variant p_delta_val, f
ERR_FAIL_INDEX_V(p_trans, TransitionType::TRANS_MAX, Variant());
ERR_FAIL_INDEX_V(p_ease, EaseType::EASE_MAX, Variant());
-// Helper macro to run equation on sub-elements of the value (e.g. x and y of Vector2).
-#define APPLY_EQUATION(element) \
- r.element = run_equation(p_trans, p_ease, p_time, i.element, d.element, p_duration);
-
- switch (p_initial_val.get_type()) {
- case Variant::BOOL: {
- return (run_equation(p_trans, p_ease, p_time, p_initial_val, p_delta_val, p_duration)) >= 0.5;
- }
-
- case Variant::INT: {
- return (int)run_equation(p_trans, p_ease, p_time, (int)p_initial_val, (int)p_delta_val, p_duration);
- }
-
- case Variant::FLOAT: {
- return run_equation(p_trans, p_ease, p_time, (real_t)p_initial_val, (real_t)p_delta_val, p_duration);
- }
-
- case Variant::VECTOR2: {
- Vector2 i = p_initial_val;
- Vector2 d = p_delta_val;
- Vector2 r;
-
- APPLY_EQUATION(x);
- APPLY_EQUATION(y);
- return r;
- }
-
- case Variant::VECTOR2I: {
- Vector2i i = p_initial_val;
- Vector2i d = p_delta_val;
- Vector2i r;
-
- APPLY_EQUATION(x);
- APPLY_EQUATION(y);
- return r;
- }
-
- case Variant::RECT2: {
- Rect2 i = p_initial_val;
- Rect2 d = p_delta_val;
- Rect2 r;
-
- APPLY_EQUATION(position.x);
- APPLY_EQUATION(position.y);
- APPLY_EQUATION(size.x);
- APPLY_EQUATION(size.y);
- return r;
- }
-
- case Variant::RECT2I: {
- Rect2i i = p_initial_val;
- Rect2i d = p_delta_val;
- Rect2i r;
-
- APPLY_EQUATION(position.x);
- APPLY_EQUATION(position.y);
- APPLY_EQUATION(size.x);
- APPLY_EQUATION(size.y);
- return r;
- }
-
- case Variant::VECTOR3: {
- Vector3 i = p_initial_val;
- Vector3 d = p_delta_val;
- Vector3 r;
-
- APPLY_EQUATION(x);
- APPLY_EQUATION(y);
- APPLY_EQUATION(z);
- return r;
- }
-
- case Variant::VECTOR3I: {
- Vector3i i = p_initial_val;
- Vector3i d = p_delta_val;
- Vector3i r;
-
- APPLY_EQUATION(x);
- APPLY_EQUATION(y);
- APPLY_EQUATION(z);
- return r;
- }
-
- case Variant::TRANSFORM2D: {
- Transform2D i = p_initial_val;
- Transform2D d = p_delta_val;
- Transform2D r;
-
- APPLY_EQUATION(columns[0][0]);
- APPLY_EQUATION(columns[0][1]);
- APPLY_EQUATION(columns[1][0]);
- APPLY_EQUATION(columns[1][1]);
- APPLY_EQUATION(columns[2][0]);
- APPLY_EQUATION(columns[2][1]);
- return r;
- }
- case Variant::VECTOR4: {
- Vector4 i = p_initial_val;
- Vector4 d = p_delta_val;
- Vector4 r;
-
- APPLY_EQUATION(x);
- APPLY_EQUATION(y);
- APPLY_EQUATION(z);
- APPLY_EQUATION(w);
- return r;
- }
-
- case Variant::QUATERNION: {
- Quaternion i = p_initial_val;
- Quaternion d = p_delta_val;
- Quaternion r = i * d;
- r = i.slerp(r, run_equation(p_trans, p_ease, p_time, 0.0, 1.0, p_duration));
- return r;
- }
-
- case Variant::AABB: {
- AABB i = p_initial_val;
- AABB d = p_delta_val;
- AABB r;
-
- APPLY_EQUATION(position.x);
- APPLY_EQUATION(position.y);
- APPLY_EQUATION(position.z);
- APPLY_EQUATION(size.x);
- APPLY_EQUATION(size.y);
- APPLY_EQUATION(size.z);
- return r;
- }
-
- case Variant::BASIS: {
- Basis i = p_initial_val;
- Basis d = p_delta_val;
- Basis r;
-
- APPLY_EQUATION(rows[0][0]);
- APPLY_EQUATION(rows[0][1]);
- APPLY_EQUATION(rows[0][2]);
- APPLY_EQUATION(rows[1][0]);
- APPLY_EQUATION(rows[1][1]);
- APPLY_EQUATION(rows[1][2]);
- APPLY_EQUATION(rows[2][0]);
- APPLY_EQUATION(rows[2][1]);
- APPLY_EQUATION(rows[2][2]);
- return r;
- }
-
- case Variant::TRANSFORM3D: {
- Transform3D i = p_initial_val;
- Transform3D d = p_delta_val;
- Transform3D r;
-
- APPLY_EQUATION(basis.rows[0][0]);
- APPLY_EQUATION(basis.rows[0][1]);
- APPLY_EQUATION(basis.rows[0][2]);
- APPLY_EQUATION(basis.rows[1][0]);
- APPLY_EQUATION(basis.rows[1][1]);
- APPLY_EQUATION(basis.rows[1][2]);
- APPLY_EQUATION(basis.rows[2][0]);
- APPLY_EQUATION(basis.rows[2][1]);
- APPLY_EQUATION(basis.rows[2][2]);
- APPLY_EQUATION(origin.x);
- APPLY_EQUATION(origin.y);
- APPLY_EQUATION(origin.z);
- return r;
- }
-
- case Variant::COLOR: {
- Color i = p_initial_val;
- Color d = p_delta_val;
- Color r;
-
- APPLY_EQUATION(r);
- APPLY_EQUATION(g);
- APPLY_EQUATION(b);
- APPLY_EQUATION(a);
- return r;
- }
-
- default: {
- return p_initial_val;
- }
- };
-#undef APPLY_EQUATION
-}
-
-Variant Tween::calculate_delta_value(Variant p_intial_val, Variant p_final_val) {
- ERR_FAIL_COND_V_MSG(p_intial_val.get_type() != p_final_val.get_type(), p_intial_val, "Type mismatch between initial and final value: " + Variant::get_type_name(p_intial_val.get_type()) + " and " + Variant::get_type_name(p_final_val.get_type()));
-
- switch (p_intial_val.get_type()) {
- case Variant::BOOL: {
- return (int)p_final_val - (int)p_intial_val;
- }
-
- case Variant::RECT2: {
- Rect2 i = p_intial_val;
- Rect2 f = p_final_val;
- return Rect2(f.position - i.position, f.size - i.size);
- }
-
- case Variant::RECT2I: {
- Rect2i i = p_intial_val;
- Rect2i f = p_final_val;
- return Rect2i(f.position - i.position, f.size - i.size);
- }
-
- case Variant::TRANSFORM2D: {
- Transform2D i = p_intial_val;
- Transform2D f = p_final_val;
- return Transform2D(f.columns[0][0] - i.columns[0][0],
- f.columns[0][1] - i.columns[0][1],
- f.columns[1][0] - i.columns[1][0],
- f.columns[1][1] - i.columns[1][1],
- f.columns[2][0] - i.columns[2][0],
- f.columns[2][1] - i.columns[2][1]);
- }
-
- case Variant::AABB: {
- AABB i = p_intial_val;
- AABB f = p_final_val;
- return AABB(f.position - i.position, f.size - i.size);
- }
-
- case Variant::BASIS: {
- Basis i = p_intial_val;
- Basis f = p_final_val;
- return Basis(f.rows[0][0] - i.rows[0][0],
- f.rows[0][1] - i.rows[0][1],
- f.rows[0][2] - i.rows[0][2],
- f.rows[1][0] - i.rows[1][0],
- f.rows[1][1] - i.rows[1][1],
- f.rows[1][2] - i.rows[1][2],
- f.rows[2][0] - i.rows[2][0],
- f.rows[2][1] - i.rows[2][1],
- f.rows[2][2] - i.rows[2][2]);
- }
-
- case Variant::TRANSFORM3D: {
- Transform3D i = p_intial_val;
- Transform3D f = p_final_val;
- return Transform3D(f.basis.rows[0][0] - i.basis.rows[0][0],
- f.basis.rows[0][1] - i.basis.rows[0][1],
- f.basis.rows[0][2] - i.basis.rows[0][2],
- f.basis.rows[1][0] - i.basis.rows[1][0],
- f.basis.rows[1][1] - i.basis.rows[1][1],
- f.basis.rows[1][2] - i.basis.rows[1][2],
- f.basis.rows[2][0] - i.basis.rows[2][0],
- f.basis.rows[2][1] - i.basis.rows[2][1],
- f.basis.rows[2][2] - i.basis.rows[2][2],
- f.origin.x - i.origin.x,
- f.origin.y - i.origin.y,
- f.origin.z - i.origin.z);
- }
+ // Special case for bool.
+ if (p_initial_val.get_type() == Variant::BOOL) {
+ return run_equation(p_trans, p_ease, p_time, p_initial_val, p_delta_val, p_duration) >= 0.5;
+ }
- default: {
- return Variant::evaluate(Variant::OP_SUBTRACT, p_final_val, p_intial_val);
- }
- };
+ Variant ret = Animation::add_variant(p_initial_val, p_delta_val);
+ ret = Animation::interpolate_variant(p_initial_val, ret, run_equation(p_trans, p_ease, p_time, 0.0, 1.0, p_duration));
+ return ret;
}
void Tween::_bind_methods() {
@@ -748,10 +500,10 @@ void PropertyTweener::start() {
}
if (relative) {
- final_val = Variant::evaluate(Variant::Operator::OP_ADD, initial_val, base_final_val);
+ final_val = Animation::add_variant(initial_val, base_final_val);
}
- delta_val = tween->calculate_delta_value(initial_val, final_val);
+ delta_val = Animation::subtract_variant(final_val, initial_val);
}
bool PropertyTweener::step(float &r_delta) {
@@ -973,7 +725,7 @@ void MethodTweener::_bind_methods() {
MethodTweener::MethodTweener(Callable p_callback, Variant p_from, Variant p_to, float p_duration) {
callback = p_callback;
initial_val = p_from;
- delta_val = tween->calculate_delta_value(p_from, p_to);
+ delta_val = Animation::subtract_variant(p_to, p_from);
final_val = p_to;
duration = p_duration;
}
diff --git a/scene/animation/tween.h b/scene/animation/tween.h
index b57ec2e5e7..da7a8b5d71 100644
--- a/scene/animation/tween.h
+++ b/scene/animation/tween.h
@@ -164,7 +164,6 @@ public:
static real_t run_equation(TransitionType p_trans_type, EaseType p_ease_type, real_t t, real_t b, real_t c, real_t d);
static Variant interpolate_variant(Variant p_initial_val, Variant p_delta_val, float p_time, float p_duration, Tween::TransitionType p_trans, Tween::EaseType p_ease);
- Variant calculate_delta_value(Variant p_intial_val, Variant p_final_val);
bool step(float p_delta);
bool can_process(bool p_tree_paused) const;
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 64a0402149..3a238e9edd 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -2188,6 +2188,30 @@ RichTextLabel::ItemFont *RichTextLabel::_find_font(Item *p_item) {
while (fontitem) {
if (fontitem->type == ITEM_FONT) {
ItemFont *fi = static_cast<ItemFont *>(fontitem);
+ switch (fi->def_font) {
+ case NORMAL_FONT: {
+ fi->font = theme_cache.normal_font;
+ fi->font_size = theme_cache.normal_font_size;
+ } break;
+ case BOLD_FONT: {
+ fi->font = theme_cache.bold_font;
+ fi->font_size = theme_cache.bold_font_size;
+ } break;
+ case ITALICS_FONT: {
+ fi->font = theme_cache.italics_font;
+ fi->font_size = theme_cache.italics_font_size;
+ } break;
+ case BOLD_ITALICS_FONT: {
+ fi->font = theme_cache.bold_italics_font;
+ fi->font_size = theme_cache.bold_italics_font_size;
+ } break;
+ case MONO_FONT: {
+ fi->font = theme_cache.mono_font;
+ fi->font_size = theme_cache.mono_font_size;
+ } break;
+ default: {
+ } break;
+ }
return fi;
}
@@ -3004,6 +3028,17 @@ void RichTextLabel::push_dropcap(const String &p_string, const Ref<Font> &p_font
_add_item(item, false);
}
+void RichTextLabel::_push_def_font(DefaultFont p_font) {
+ _stop_thread();
+ MutexLock data_lock(data_mutex);
+
+ ERR_FAIL_COND(current->type == ITEM_TABLE);
+ ItemFont *item = memnew(ItemFont);
+
+ item->def_font = p_font;
+ _add_item(item, true);
+}
+
void RichTextLabel::push_font(const Ref<Font> &p_font, int p_size) {
_stop_thread();
MutexLock data_lock(data_mutex);
@@ -3020,31 +3055,31 @@ void RichTextLabel::push_font(const Ref<Font> &p_font, int p_size) {
void RichTextLabel::push_normal() {
ERR_FAIL_COND(theme_cache.normal_font.is_null());
- push_font(theme_cache.normal_font, theme_cache.normal_font_size);
+ _push_def_font(NORMAL_FONT);
}
void RichTextLabel::push_bold() {
ERR_FAIL_COND(theme_cache.bold_font.is_null());
- push_font(theme_cache.bold_font, theme_cache.bold_font_size);
+ _push_def_font(BOLD_FONT);
}
void RichTextLabel::push_bold_italics() {
ERR_FAIL_COND(theme_cache.bold_italics_font.is_null());
- push_font(theme_cache.bold_italics_font, theme_cache.bold_italics_font_size);
+ _push_def_font(BOLD_ITALICS_FONT);
}
void RichTextLabel::push_italics() {
ERR_FAIL_COND(theme_cache.italics_font.is_null());
- push_font(theme_cache.italics_font, theme_cache.italics_font_size);
+ _push_def_font(ITALICS_FONT);
}
void RichTextLabel::push_mono() {
ERR_FAIL_COND(theme_cache.mono_font.is_null());
- push_font(theme_cache.mono_font, theme_cache.mono_font_size);
+ _push_def_font(MONO_FONT);
}
void RichTextLabel::push_font_size(int p_font_size) {
@@ -3635,9 +3670,9 @@ void RichTextLabel::append_text(const String &p_bbcode) {
//use bold font
in_bold = true;
if (in_italics) {
- push_font(theme_cache.bold_italics_font, theme_cache.bold_italics_font_size);
+ _push_def_font(BOLD_ITALICS_FONT);
} else {
- push_font(theme_cache.bold_font, theme_cache.bold_font_size);
+ _push_def_font(BOLD_FONT);
}
pos = brk_end + 1;
tag_stack.push_front(tag);
@@ -3645,15 +3680,15 @@ void RichTextLabel::append_text(const String &p_bbcode) {
//use italics font
in_italics = true;
if (in_bold) {
- push_font(theme_cache.bold_italics_font, theme_cache.bold_italics_font_size);
+ _push_def_font(BOLD_ITALICS_FONT);
} else {
- push_font(theme_cache.italics_font, theme_cache.italics_font_size);
+ _push_def_font(ITALICS_FONT);
}
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag == "code") {
//use monospace font
- push_font(theme_cache.mono_font, theme_cache.mono_font_size);
+ _push_def_font(MONO_FONT);
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag.begins_with("table=")) {
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 8bc28a9ecf..2a5ec4b5d5 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -82,6 +82,15 @@ public:
MENU_SELECT_ALL,
};
+ enum DefaultFont {
+ NORMAL_FONT,
+ BOLD_FONT,
+ ITALICS_FONT,
+ BOLD_ITALICS_FONT,
+ MONO_FONT,
+ CUSTOM_FONT,
+ };
+
protected:
virtual void _update_theme_item_cache() override;
void _notification(int p_what);
@@ -178,6 +187,7 @@ private:
};
struct ItemFont : public Item {
+ DefaultFont def_font = CUSTOM_FONT;
Ref<Font> font;
int font_size = 0;
ItemFont() { type = ITEM_FONT; }
@@ -560,6 +570,7 @@ public:
void add_newline();
bool remove_line(const int p_line);
void push_dropcap(const String &p_string, const Ref<Font> &p_font, int p_size, const Rect2 &p_dropcap_margins = Rect2(), const Color &p_color = Color(1, 1, 1), int p_ol_size = 0, const Color &p_ol_color = Color(0, 0, 0, 0));
+ void _push_def_font(DefaultFont p_font);
void push_font(const Ref<Font> &p_font, int p_size = 0);
void push_font_size(int p_font_size);
void push_outline_size(int p_font_size);
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 5295de5c09..879d494909 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -795,11 +795,20 @@ void Viewport::_set_size(const Size2i &p_size, const Size2i &p_size_2d_override,
stretch_transform = p_stretch_transform;
to_screen_rect = p_to_screen_rect;
- if (p_allocated) {
- RS::get_singleton()->viewport_set_size(viewport, size.width, size.height);
- } else {
- RS::get_singleton()->viewport_set_size(viewport, 0, 0);
- }
+#ifndef _3D_DISABLED
+ if (!use_xr) {
+#endif
+
+ if (p_allocated) {
+ RS::get_singleton()->viewport_set_size(viewport, size.width, size.height);
+ } else {
+ RS::get_singleton()->viewport_set_size(viewport, 0, 0);
+ }
+
+#ifndef _3D_DISABLED
+ } // if (!use_xr)
+#endif
+
_update_global_transform();
update_configuration_warnings();
@@ -813,6 +822,19 @@ void Viewport::_set_size(const Size2i &p_size, const Size2i &p_size_2d_override,
}
Size2i Viewport::_get_size() const {
+#ifndef _3D_DISABLED
+ if (use_xr) {
+ if (XRServer::get_singleton() != nullptr) {
+ Ref<XRInterface> xr_interface = XRServer::get_singleton()->get_primary_interface();
+ if (xr_interface.is_valid() && xr_interface->is_initialized()) {
+ Size2 xr_size = xr_interface->get_render_target_size();
+ return (Size2i)xr_size;
+ }
+ }
+ return Size2i();
+ }
+#endif // _3D_DISABLED
+
return size;
}
@@ -3612,9 +3634,20 @@ void Viewport::_propagate_exit_world_3d(Node *p_node) {
}
void Viewport::set_use_xr(bool p_use_xr) {
- use_xr = p_use_xr;
+ if (use_xr != p_use_xr) {
+ use_xr = p_use_xr;
- RS::get_singleton()->viewport_set_use_xr(viewport, use_xr);
+ RS::get_singleton()->viewport_set_use_xr(viewport, use_xr);
+
+ if (!use_xr) {
+ // Set viewport to previous size when exiting XR.
+ if (size_allocated) {
+ RS::get_singleton()->viewport_set_size(viewport, size.width, size.height);
+ } else {
+ RS::get_singleton()->viewport_set_size(viewport, 0, 0);
+ }
+ }
+ }
}
bool Viewport::is_using_xr() {
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index afea3ea56c..c7c474c70f 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -568,7 +568,7 @@ public:
bool is_input_disabled() const;
Vector2 get_mouse_position() const;
- virtual void warp_mouse(const Vector2 &p_position);
+ void warp_mouse(const Vector2 &p_position);
void set_physics_object_picking(bool p_enable);
bool get_physics_object_picking();
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index 04f56bb874..ebe9587b31 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -986,18 +986,6 @@ DisplayServer::WindowID Window::get_window_id() const {
return window_id;
}
-void Window::warp_mouse(const Vector2 &p_position) {
- Transform2D xform = get_screen_transform();
- Vector2 gpos = xform.xform(p_position);
-
- if (transient_parent && !transient_parent->is_embedding_subwindows()) {
- Transform2D window_trans = Transform2D().translated(get_position() + (transient_parent->get_visible_rect().size - transient_parent->get_real_size()));
- gpos = window_trans.xform(gpos);
- }
-
- Input::get_singleton()->warp_mouse(gpos);
-}
-
void Window::set_wrap_controls(bool p_enable) {
wrap_controls = p_enable;
if (wrap_controls) {
@@ -1153,7 +1141,7 @@ void Window::popup_centered_clamped(const Size2i &p_size, float p_fallback_ratio
Rect2 parent_rect;
if (is_embedded()) {
- parent_rect = get_parent_viewport()->get_visible_rect();
+ parent_rect = _get_embedder()->get_visible_rect();
} else {
DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id();
int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id);
@@ -1179,7 +1167,7 @@ void Window::popup_centered(const Size2i &p_minsize) {
Rect2 parent_rect;
if (is_embedded()) {
- parent_rect = get_parent_viewport()->get_visible_rect();
+ parent_rect = _get_embedder()->get_visible_rect();
} else {
DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id();
int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id);
@@ -1207,7 +1195,7 @@ void Window::popup_centered_ratio(float p_ratio) {
Rect2 parent_rect;
if (is_embedded()) {
- parent_rect = get_parent_viewport()->get_visible_rect();
+ parent_rect = _get_embedder()->get_visible_rect();
} else {
DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id();
int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id);
diff --git a/scene/main/window.h b/scene/main/window.h
index 8113117103..8c6ca65436 100644
--- a/scene/main/window.h
+++ b/scene/main/window.h
@@ -254,8 +254,6 @@ public:
void set_use_font_oversampling(bool p_oversampling);
bool is_using_font_oversampling() const;
- void warp_mouse(const Vector2 &p_position) override;
-
void set_wrap_controls(bool p_enable);
bool is_wrapping_controls() const;
void child_controls_changed();
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 9d5bc18c96..a52bfe97e7 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -2317,9 +2317,7 @@ Quaternion Animation::_interpolate(const Quaternion &p_a, const Quaternion &p_b,
}
Variant Animation::_interpolate(const Variant &p_a, const Variant &p_b, real_t p_c) const {
- Variant dst;
- Variant::interpolate(p_a, p_b, p_c, dst);
- return dst;
+ return interpolate_variant(p_a, p_b, p_c);
}
real_t Animation::_interpolate(const real_t &p_a, const real_t &p_b, real_t p_c) const {
@@ -5563,6 +5561,466 @@ bool Animation::_fetch_compressed_by_index(uint32_t p_compressed_track, int p_in
return false;
}
+// Helper math functions for Variant.
+Variant Animation::add_variant(const Variant &a, const Variant &b) {
+ if (a.get_type() != b.get_type()) {
+ return a;
+ }
+
+ switch (a.get_type()) {
+ case Variant::NIL: {
+ return Variant();
+ }
+ case Variant::BOOL: {
+ return (a.operator real_t()) + (b.operator real_t()); // It is cast for interpolation.
+ }
+ case Variant::RECT2: {
+ const Rect2 ra = a.operator Rect2();
+ const Rect2 rb = b.operator Rect2();
+ return Rect2(ra.position + rb.position, ra.size + rb.size);
+ }
+ case Variant::RECT2I: {
+ const Rect2i ra = a.operator Rect2i();
+ const Rect2i rb = b.operator Rect2i();
+ return Rect2i(ra.position + rb.position, ra.size + rb.size);
+ }
+ case Variant::PLANE: {
+ const Plane pa = a.operator Plane();
+ const Plane pb = b.operator Plane();
+ return Plane(pa.normal + pb.normal, pa.d + pb.d);
+ }
+ case Variant::AABB: {
+ const ::AABB aa = a.operator ::AABB();
+ const ::AABB ab = b.operator ::AABB();
+ return ::AABB(aa.position + ab.position, aa.size + ab.size);
+ }
+ case Variant::QUATERNION: {
+ return (a.operator Quaternion()) * (b.operator Quaternion());
+ }
+ case Variant::TRANSFORM2D: {
+ return (a.operator Transform2D()) * (b.operator Transform2D());
+ }
+ case Variant::TRANSFORM3D: {
+ return (a.operator Transform3D()) * (b.operator Transform3D());
+ }
+ default: {
+ return Variant::evaluate(Variant::OP_ADD, a, b);
+ }
+ }
+}
+
+Variant Animation::subtract_variant(const Variant &a, const Variant &b) {
+ if (a.get_type() != b.get_type()) {
+ return a;
+ }
+
+ switch (a.get_type()) {
+ case Variant::NIL: {
+ return Variant();
+ }
+ case Variant::BOOL: {
+ return (a.operator real_t()) - (b.operator real_t()); // It is cast for interpolation.
+ }
+ case Variant::RECT2: {
+ const Rect2 ra = a.operator Rect2();
+ const Rect2 rb = b.operator Rect2();
+ return Rect2(ra.position - rb.position, ra.size - rb.size);
+ }
+ case Variant::RECT2I: {
+ const Rect2i ra = a.operator Rect2i();
+ const Rect2i rb = b.operator Rect2i();
+ return Rect2i(ra.position - rb.position, ra.size - rb.size);
+ }
+ case Variant::PLANE: {
+ const Plane pa = a.operator Plane();
+ const Plane pb = b.operator Plane();
+ return Plane(pa.normal - pb.normal, pa.d - pb.d);
+ }
+ case Variant::AABB: {
+ const ::AABB aa = a.operator ::AABB();
+ const ::AABB ab = b.operator ::AABB();
+ return ::AABB(aa.position - ab.position, aa.size - ab.size);
+ }
+ case Variant::QUATERNION: {
+ return (b.operator Quaternion()).inverse() * (a.operator Quaternion());
+ }
+ case Variant::TRANSFORM2D: {
+ return (b.operator Transform2D()).inverse() * (a.operator Transform2D());
+ }
+ case Variant::TRANSFORM3D: {
+ return (b.operator Transform3D()).inverse() * (a.operator Transform3D());
+ }
+ default: {
+ return Variant::evaluate(Variant::OP_SUBTRACT, a, b);
+ }
+ }
+}
+
+Variant Animation::blend_variant(const Variant &a, const Variant &b, float c) {
+ if (a.get_type() != b.get_type()) {
+ if (a.is_num() && b.is_num()) {
+ real_t va = a;
+ real_t vb = b;
+ return va + vb * c;
+ }
+ return a;
+ }
+
+ switch (a.get_type()) {
+ case Variant::NIL: {
+ return Variant();
+ }
+ case Variant::INT: {
+ return int((a.operator int64_t()) + (b.operator int64_t()) * c + 0.5);
+ }
+ case Variant::FLOAT: {
+ return (a.operator double()) + (b.operator double()) * c;
+ }
+ case Variant::VECTOR2: {
+ return (a.operator Vector2()) + (b.operator Vector2()) * c;
+ }
+ case Variant::VECTOR2I: {
+ const Vector2i va = a.operator Vector2i();
+ const Vector2i vb = b.operator Vector2i();
+ return Vector2i(int32_t(va.x + vb.x * c + 0.5), int32_t(va.y + vb.y * c + 0.5));
+ }
+ case Variant::RECT2: {
+ const Rect2 ra = a.operator Rect2();
+ const Rect2 rb = b.operator Rect2();
+ return Rect2(ra.position + rb.position * c, ra.size + rb.size * c);
+ }
+ case Variant::RECT2I: {
+ const Rect2i ra = a.operator Rect2i();
+ const Rect2i rb = b.operator Rect2i();
+ return Rect2i(int32_t(ra.position.x + rb.position.x * c + 0.5), int32_t(ra.position.y + rb.position.y * c + 0.5), int32_t(ra.size.x + rb.size.x * c + 0.5), int32_t(ra.size.y + rb.size.y * c + 0.5));
+ }
+ case Variant::VECTOR3: {
+ return (a.operator Vector3()) + (b.operator Vector3()) * c;
+ }
+ case Variant::VECTOR3I: {
+ const Vector3i va = a.operator Vector3i();
+ const Vector3i vb = b.operator Vector3i();
+ return Vector3i(int32_t(va.x + vb.x * c + 0.5), int32_t(va.y + vb.y * c + 0.5), int32_t(va.z + vb.z * c + 0.5));
+ }
+ case Variant::VECTOR4: {
+ return (a.operator Vector4()) + (b.operator Vector4()) * c;
+ }
+ case Variant::VECTOR4I: {
+ const Vector4i va = a.operator Vector4i();
+ const Vector4i vb = b.operator Vector4i();
+ return Vector4i(int32_t(va.x + vb.x * c + 0.5), int32_t(va.y + vb.y * c + 0.5), int32_t(va.z + vb.z * c + 0.5), int32_t(va.w + vb.w * c + 0.5));
+ }
+ case Variant::PLANE: {
+ const Plane pa = a.operator Plane();
+ const Plane pb = b.operator Plane();
+ return Plane(pa.normal + pb.normal * c, pa.d + pb.d * c);
+ }
+ case Variant::COLOR: {
+ return (a.operator Color()) + (b.operator Color()) * c;
+ }
+ case Variant::AABB: {
+ const ::AABB aa = a.operator ::AABB();
+ const ::AABB ab = b.operator ::AABB();
+ return ::AABB(aa.position + ab.position * c, aa.size + ab.size * c);
+ }
+ case Variant::BASIS: {
+ return (a.operator Basis()) + (b.operator Basis()) * c;
+ }
+ case Variant::QUATERNION: {
+ return (a.operator Quaternion()) * Quaternion().slerp((b.operator Quaternion()), c);
+ }
+ case Variant::TRANSFORM2D: {
+ return (a.operator Transform2D()) * Transform2D().interpolate_with((b.operator Transform2D()), c);
+ }
+ case Variant::TRANSFORM3D: {
+ return (a.operator Transform3D()) * Transform3D().interpolate_with((b.operator Transform3D()), c);
+ }
+ default: {
+ return c < 0.5 ? a : b;
+ }
+ }
+}
+
+Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float c) {
+ if (a.get_type() != b.get_type()) {
+ if (a.is_num() && b.is_num()) {
+ real_t va = a;
+ real_t vb = b;
+ return va + (vb - va) * c;
+ }
+ return a;
+ }
+
+ switch (a.get_type()) {
+ case Variant::NIL: {
+ return Variant();
+ }
+ case Variant::INT: {
+ const int64_t va = a.operator int64_t();
+ return int(va + ((b.operator int64_t()) - va) * c);
+ }
+ case Variant::FLOAT: {
+ const real_t va = a.operator real_t();
+ return va + ((b.operator real_t()) - va) * c;
+ }
+ case Variant::VECTOR2: {
+ return (a.operator Vector2()).lerp(b.operator Vector2(), c);
+ }
+ case Variant::VECTOR2I: {
+ const Vector2i va = a.operator Vector2i();
+ const Vector2i vb = b.operator Vector2i();
+ return Vector2i(int32_t(va.x + (vb.x - va.x) * c), int32_t(va.y + (vb.y - va.y) * c));
+ }
+ case Variant::RECT2: {
+ const Rect2 ra = a.operator Rect2();
+ const Rect2 rb = b.operator Rect2();
+ return Rect2(ra.position.lerp(rb.position, c), ra.size.lerp(rb.size, c));
+ }
+ case Variant::RECT2I: {
+ const Rect2i ra = a.operator Rect2i();
+ const Rect2i rb = b.operator Rect2i();
+ return Rect2i(int32_t(ra.position.x + (rb.position.x - ra.position.x) * c), int32_t(ra.position.y + (rb.position.y - ra.position.y) * c), int32_t(ra.size.x + (rb.size.x - ra.size.x) * c), int32_t(ra.size.y + (rb.size.y - ra.size.y) * c));
+ }
+ case Variant::VECTOR3: {
+ return (a.operator Vector3()).lerp(b.operator Vector3(), c);
+ }
+ case Variant::VECTOR3I: {
+ const Vector3i va = a.operator Vector3i();
+ const Vector3i vb = b.operator Vector3i();
+ return Vector3i(int32_t(va.x + (vb.x - va.x) * c), int32_t(va.y + (vb.y - va.y) * c), int32_t(va.z + (vb.z - va.z) * c));
+ }
+ case Variant::VECTOR4: {
+ return (a.operator Vector4()).lerp(b.operator Vector4(), c);
+ }
+ case Variant::VECTOR4I: {
+ const Vector4i va = a.operator Vector4i();
+ const Vector4i vb = b.operator Vector4i();
+ return Vector4i(int32_t(va.x + (vb.x - va.x) * c), int32_t(va.y + (vb.y - va.y) * c), int32_t(va.z + (vb.z - va.z) * c), int32_t(va.w + (vb.w - va.w) * c));
+ }
+ 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);
+ }
+ case Variant::COLOR: {
+ return (a.operator Color()).lerp(b.operator Color(), c);
+ }
+ case Variant::AABB: {
+ const ::AABB aa = a.operator ::AABB();
+ const ::AABB ab = b.operator ::AABB();
+ return ::AABB(aa.position.lerp(ab.position, c), aa.size.lerp(ab.size, c));
+ }
+ case Variant::BASIS: {
+ return (a.operator Basis()).lerp(b.operator Basis(), c);
+ }
+ case Variant::QUATERNION: {
+ return (a.operator Quaternion()).slerp(b.operator Quaternion(), c);
+ }
+ case Variant::TRANSFORM2D: {
+ return (a.operator Transform2D()).interpolate_with(b.operator Transform2D(), c);
+ }
+ case Variant::TRANSFORM3D: {
+ return (a.operator Transform3D()).interpolate_with(b.operator Transform3D(), c);
+ }
+ case Variant::STRING: {
+ // This is pretty funny and bizarre, but artists like to use it for typewriter effects.
+ const String sa = a.operator String();
+ const String sb = b.operator String();
+ String dst;
+ int sa_len = sa.length();
+ int sb_len = sb.length();
+ int csize = sa_len + (sb_len - sa_len) * c;
+ if (csize == 0) {
+ return "";
+ }
+ dst.resize(csize + 1);
+ dst[csize] = 0;
+ int split = csize / 2;
+
+ for (int i = 0; i < csize; i++) {
+ char32_t chr = ' ';
+
+ if (i < split) {
+ if (i < sa.length()) {
+ chr = sa[i];
+ } else if (i < sb.length()) {
+ chr = sb[i];
+ }
+
+ } else {
+ if (i < sb.length()) {
+ chr = sb[i];
+ } else if (i < sa.length()) {
+ chr = sa[i];
+ }
+ }
+
+ dst[i] = chr;
+ }
+
+ return dst;
+ }
+ case Variant::PACKED_INT32_ARRAY: {
+ const Vector<int32_t> *arr_a = Object::cast_to<Vector<int32_t>>(a);
+ const Vector<int32_t> *arr_b = Object::cast_to<Vector<int32_t>>(b);
+ int32_t sz = arr_a->size();
+ if (sz == 0 || arr_b->size() != sz) {
+ return a;
+ } else {
+ Vector<int32_t> v;
+ v.resize(sz);
+ {
+ int32_t *vw = v.ptrw();
+ const int32_t *ar = arr_a->ptr();
+ const int32_t *br = arr_b->ptr();
+
+ Variant va;
+ for (int32_t i = 0; i < sz; i++) {
+ va = interpolate_variant(ar[i], br[i], c);
+ vw[i] = va;
+ }
+ }
+ return v;
+ }
+ }
+ case Variant::PACKED_INT64_ARRAY: {
+ const Vector<int64_t> *arr_a = Object::cast_to<Vector<int64_t>>(a);
+ const Vector<int64_t> *arr_b = Object::cast_to<Vector<int64_t>>(b);
+ int64_t sz = arr_a->size();
+ if (sz == 0 || arr_b->size() != sz) {
+ return a;
+ } else {
+ Vector<int64_t> v;
+ v.resize(sz);
+ {
+ int64_t *vw = v.ptrw();
+ const int64_t *ar = arr_a->ptr();
+ const int64_t *br = arr_b->ptr();
+
+ Variant va;
+ for (int64_t i = 0; i < sz; i++) {
+ va = interpolate_variant(ar[i], br[i], c);
+ vw[i] = va;
+ }
+ }
+ return v;
+ }
+ }
+ case Variant::PACKED_FLOAT32_ARRAY: {
+ const Vector<float> *arr_a = Object::cast_to<Vector<float>>(a);
+ const Vector<float> *arr_b = Object::cast_to<Vector<float>>(b);
+ int sz = arr_a->size();
+ if (sz == 0 || arr_b->size() != sz) {
+ return a;
+ } else {
+ Vector<float> v;
+ v.resize(sz);
+ {
+ float *vw = v.ptrw();
+ const float *ar = arr_a->ptr();
+ const float *br = arr_b->ptr();
+
+ Variant va;
+ for (int i = 0; i < sz; i++) {
+ va = interpolate_variant(ar[i], br[i], c);
+ vw[i] = va;
+ }
+ }
+ return v;
+ }
+ }
+ case Variant::PACKED_FLOAT64_ARRAY: {
+ const Vector<double> *arr_a = Object::cast_to<Vector<double>>(a);
+ const Vector<double> *arr_b = Object::cast_to<Vector<double>>(b);
+ int sz = arr_a->size();
+ if (sz == 0 || arr_b->size() != sz) {
+ return a;
+ } else {
+ Vector<double> v;
+ v.resize(sz);
+ {
+ double *vw = v.ptrw();
+ const double *ar = arr_a->ptr();
+ const double *br = arr_b->ptr();
+
+ Variant va;
+ for (int i = 0; i < sz; i++) {
+ va = interpolate_variant(ar[i], br[i], c);
+ vw[i] = va;
+ }
+ }
+ return v;
+ }
+ }
+ case Variant::PACKED_VECTOR2_ARRAY: {
+ const Vector<Vector2> *arr_a = Object::cast_to<Vector<Vector2>>(a);
+ const Vector<Vector2> *arr_b = Object::cast_to<Vector<Vector2>>(b);
+ int sz = arr_a->size();
+ if (sz == 0 || arr_b->size() != sz) {
+ return a;
+ } else {
+ Vector<Vector2> v;
+ v.resize(sz);
+ {
+ Vector2 *vw = v.ptrw();
+ const Vector2 *ar = arr_a->ptr();
+ const Vector2 *br = arr_b->ptr();
+
+ for (int i = 0; i < sz; i++) {
+ vw[i] = ar[i].lerp(br[i], c);
+ }
+ }
+ return v;
+ }
+ }
+ case Variant::PACKED_VECTOR3_ARRAY: {
+ const Vector<Vector3> *arr_a = Object::cast_to<Vector<Vector3>>(a);
+ const Vector<Vector3> *arr_b = Object::cast_to<Vector<Vector3>>(b);
+ int sz = arr_a->size();
+ if (sz == 0 || arr_b->size() != sz) {
+ return a;
+ } else {
+ Vector<Vector3> v;
+ v.resize(sz);
+ {
+ Vector3 *vw = v.ptrw();
+ const Vector3 *ar = arr_a->ptr();
+ const Vector3 *br = arr_b->ptr();
+
+ for (int i = 0; i < sz; i++) {
+ vw[i] = ar[i].lerp(br[i], c);
+ }
+ }
+ return v;
+ }
+ }
+ case Variant::PACKED_COLOR_ARRAY: {
+ const Vector<Color> *arr_a = Object::cast_to<Vector<Color>>(a);
+ const Vector<Color> *arr_b = Object::cast_to<Vector<Color>>(b);
+ int sz = arr_a->size();
+ if (sz == 0 || arr_b->size() != sz) {
+ return a;
+ } else {
+ Vector<Color> v;
+ v.resize(sz);
+ {
+ Color *vw = v.ptrw();
+ const Color *ar = arr_a->ptr();
+ const Color *br = arr_b->ptr();
+
+ for (int i = 0; i < sz; i++) {
+ vw[i] = ar[i].lerp(br[i], c);
+ }
+ }
+ return v;
+ }
+ }
+ default: {
+ return c < 0.5 ? a : b;
+ }
+ }
+}
+
Animation::Animation() {}
Animation::~Animation() {
diff --git a/scene/resources/animation.h b/scene/resources/animation.h
index 46a88df130..49c8fa4c22 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -496,6 +496,12 @@ public:
void optimize(real_t p_allowed_velocity_err = 0.01, real_t p_allowed_angular_err = 0.01, int p_precision = 3);
void compress(uint32_t p_page_size = 8192, uint32_t p_fps = 120, float p_split_tolerance = 4.0); // 4.0 seems to be the split tolerance sweet spot from many tests
+ // Helper math functions for Variant.
+ static Variant add_variant(const Variant &a, const Variant &b);
+ 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);
+
Animation();
~Animation();
};
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index e47bfef576..c1e30dd93c 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -257,23 +257,25 @@ void ShaderMaterial::_get_property_list(List<PropertyInfo> *p_list) const {
groups[last_group][last_subgroup].push_back(info);
}
- // Sort groups alphabetically.
- List<UniformProp> props;
+ List<String> group_names;
for (HashMap<String, HashMap<String, List<PropertyInfo>>>::Iterator group = groups.begin(); group; ++group) {
- for (HashMap<String, List<PropertyInfo>>::Iterator subgroup = group->value.begin(); subgroup; ++subgroup) {
- for (List<PropertyInfo>::Element *item = subgroup->value.front(); item; item = item->next()) {
- if (subgroup->key == "<None>") {
- props.push_back({ group->key, item->get() });
- } else {
- props.push_back({ group->key + "::" + subgroup->key, item->get() });
- }
- }
- }
+ group_names.push_back(group->key);
}
- props.sort_custom<UniformPropComparator>();
+ group_names.sort();
- for (List<UniformProp>::Element *E = props.front(); E; E = E->next()) {
- p_list->push_back(E->get().info);
+ for (const String &group_name : group_names) {
+ List<String> subgroup_names;
+ HashMap<String, List<PropertyInfo>> &subgroups = groups[group_name];
+ for (HashMap<String, List<PropertyInfo>>::Iterator subgroup = subgroups.begin(); subgroup; ++subgroup) {
+ subgroup_names.push_back(subgroup->key);
+ }
+ subgroup_names.sort();
+ for (const String &subgroup_name : subgroup_names) {
+ List<PropertyInfo> &prop_infos = subgroups[subgroup_name];
+ for (List<PropertyInfo>::Element *item = prop_infos.front(); item; item = item->next()) {
+ p_list->push_back(item->get());
+ }
+ }
}
}
}
diff --git a/scene/resources/material.h b/scene/resources/material.h
index 6c81293ee3..dd9589c577 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -84,17 +84,6 @@ class ShaderMaterial : public Material {
HashMap<StringName, Variant> param_cache;
- struct UniformProp {
- String str;
- PropertyInfo info;
- };
-
- struct UniformPropComparator {
- bool operator()(const UniformProp &p_a, const UniformProp &p_b) const {
- return p_a.str.naturalnocasecmp_to(p_b.str) < 0;
- }
- };
-
protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
diff --git a/scene/resources/skeleton_profile.cpp b/scene/resources/skeleton_profile.cpp
index 1367ea86dd..61a0350440 100644
--- a/scene/resources/skeleton_profile.cpp
+++ b/scene/resources/skeleton_profile.cpp
@@ -566,7 +566,7 @@ SkeletonProfileHumanoid::SkeletonProfileHumanoid() {
bones.write[14].bone_name = "LeftThumbMetacarpal";
bones.write[14].bone_parent = "LeftHand";
- bones.write[14].reference_pose = Transform3D(0, -0.577, 0.816, 0.707, 0.577, 0.408, -0.707, 0.577, 0.408, -0.025, 0, 0);
+ bones.write[14].reference_pose = Transform3D(0, -0.577, 0.816, 0, 0.816, 0.577, -1, 0, 0, -0.025, 0.025, 0);
bones.write[14].handle_offset = Vector2(0.4, 0.8);
bones.write[14].group = "LeftHand";
@@ -686,7 +686,7 @@ SkeletonProfileHumanoid::SkeletonProfileHumanoid() {
bones.write[33].bone_name = "RightThumbMetacarpal";
bones.write[33].bone_parent = "RightHand";
- bones.write[33].reference_pose = Transform3D(0, 0.577, -0.816, -0.707, 0.577, 0.408, 0.707, 0.577, 0.408, 0.025, 0, 0);
+ bones.write[33].reference_pose = Transform3D(0, 0.577, -0.816, 0, 0.816, 0.577, 1, 0, 0, 0.025, 0.025, 0);
bones.write[33].handle_offset = Vector2(0.6, 0.8);
bones.write[33].group = "RightHand";
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index aa9772a483..c5818d9290 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -189,7 +189,7 @@ void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item *
RenderingServerDefault::redraw_request();
}
- if (ci->commands != nullptr) {
+ if (ci->commands != nullptr || ci->copy_back_buffer) {
ci->final_transform = xform;
ci->final_modulate = modulate * ci->self_modulate;
ci->global_rect_cache = global_rect;
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index 935ea07f6b..2ad73960a0 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -477,7 +477,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
prev_material_uniform_set = material_uniform_set;
}
- if (surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH) {
+ if ((surf->owner->base_flags & (INSTANCE_DATA_FLAG_MULTIMESH | INSTANCE_DATA_FLAG_PARTICLES)) == INSTANCE_DATA_FLAG_MULTIMESH) {
mesh_storage->_multimesh_get_motion_vectors_offsets(surf->owner->data->base, push_constant.multimesh_motion_vectors_current_offset, push_constant.multimesh_motion_vectors_previous_offset);
}
@@ -984,8 +984,8 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
scene_state.used_depth_texture = true;
}
- if (p_color_pass_flags & COLOR_PASS_FLAG_MOTION_VECTORS && flags & INSTANCE_DATA_FLAG_MULTIMESH) {
- if (RendererRD::MeshStorage::get_singleton()->_multimesh_enable_motion_vectors(inst->data->base)) {
+ if (p_color_pass_flags & COLOR_PASS_FLAG_MOTION_VECTORS) {
+ if ((flags & (INSTANCE_DATA_FLAG_MULTIMESH | INSTANCE_DATA_FLAG_PARTICLES)) == INSTANCE_DATA_FLAG_MULTIMESH && RendererRD::MeshStorage::get_singleton()->_multimesh_enable_motion_vectors(inst->data->base)) {
inst->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(inst->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
}
}
@@ -2794,6 +2794,7 @@ void RenderForwardClustered::_geometry_instance_update(RenderGeometryInstance *p
ginstance->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
} else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) {
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_PARTICLES;
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index 605473ad0b..16f6da34f8 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -231,13 +231,14 @@ class RenderForwardClustered : public RendererSceneRenderRD {
};
enum {
- INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 5,
- INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 6,
- INSTANCE_DATA_FLAG_USE_SDFGI = 1 << 7,
- INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8,
- INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 9,
- INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 10,
- INSTANCE_DATA_FLAG_USE_VOXEL_GI = 1 << 11,
+ INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 4,
+ INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 5,
+ INSTANCE_DATA_FLAG_USE_SDFGI = 1 << 6,
+ INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 7,
+ INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 8,
+ INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 9,
+ INSTANCE_DATA_FLAG_USE_VOXEL_GI = 1 << 10,
+ INSTANCE_DATA_FLAG_PARTICLES = 1 << 11,
INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12,
INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13,
INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14,
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
index b2adebbf6a..04b2b3ce18 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -373,13 +373,14 @@ protected:
// check which ones of these apply, probably all except GI and SDFGI
enum {
- INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 5,
- INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 6,
- INSTANCE_DATA_FLAG_USE_SDFGI = 1 << 7,
- INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8,
- INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 9,
- INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 10,
- INSTANCE_DATA_FLAG_USE_VOXEL_GI = 1 << 11,
+ INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 4,
+ INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 5,
+ INSTANCE_DATA_FLAG_USE_SDFGI = 1 << 6,
+ INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 7,
+ INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 8,
+ INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 9,
+ INSTANCE_DATA_FLAG_USE_VOXEL_GI = 1 << 10,
+ INSTANCE_DATA_FLAG_PARTICLES = 1 << 11,
INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12,
INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13,
INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14,
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index ab3e3ebe51..0210151420 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -1362,9 +1362,12 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
default_repeat = p_default_repeat;
}
- //fill the list until rendering is possible.
- bool material_screen_texture_found = false;
Item *ci = p_item_list;
+
+ //fill the list until rendering is possible.
+ bool material_screen_texture_cached = false;
+ bool material_screen_texture_mipmaps_cached = false;
+
Rect2 back_buffer_rect;
bool backbuffer_copy = false;
bool backbuffer_gen_mipmaps = false;
@@ -1393,10 +1396,12 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
CanvasMaterialData *md = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::MaterialStorage::SHADER_TYPE_2D));
if (md && md->shader_data->valid) {
if (md->shader_data->uses_screen_texture && canvas_group_owner == nullptr) {
- if (!material_screen_texture_found) {
+ if (!material_screen_texture_cached) {
backbuffer_copy = true;
back_buffer_rect = Rect2();
backbuffer_gen_mipmaps = md->shader_data->uses_screen_texture_mipmaps;
+ } else if (!material_screen_texture_mipmaps_cached) {
+ backbuffer_gen_mipmaps = md->shader_data->uses_screen_texture_mipmaps;
}
}
@@ -1486,7 +1491,15 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
backbuffer_copy = false;
backbuffer_gen_mipmaps = false;
- material_screen_texture_found = true; //after a backbuffer copy, screen texture makes no further copies
+ material_screen_texture_cached = true; // After a backbuffer copy, screen texture makes no further copies.
+ material_screen_texture_mipmaps_cached = backbuffer_gen_mipmaps;
+ }
+
+ if (backbuffer_gen_mipmaps) {
+ texture_storage->render_target_gen_back_buffer_mipmaps(p_to_render_target, back_buffer_rect);
+
+ backbuffer_gen_mipmaps = false;
+ material_screen_texture_mipmaps_cached = true;
}
items[item_count++] = ci;
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index eacd9bbbc2..54d07dd3e1 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -179,7 +179,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
// to compensate for the loss of sharpness.
const float texture_mipmap_bias = log2f(MIN(scaling_3d_scale, 1.0)) + p_viewport->texture_mipmap_bias;
- p_viewport->render_buffers->configure(p_viewport->render_target, Size2i(render_width, render_height), Size2(width, height), p_viewport->fsr_sharpness, texture_mipmap_bias, p_viewport->msaa_3d, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->get_view_count());
+ p_viewport->render_buffers->configure(p_viewport->render_target, Size2i(render_width, render_height), Size2(width, height), p_viewport->fsr_sharpness, texture_mipmap_bias, p_viewport->msaa_3d, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->view_count);
}
}
}
@@ -616,14 +616,7 @@ void RendererViewport::draw_viewports() {
if (xr_interface.is_valid()) {
// Override our size, make sure it matches our required size and is created as a stereo target
Size2 xr_size = xr_interface->get_render_target_size();
-
- // Would have been nice if we could call viewport_set_size here,
- // but alas that takes our RID and we now have our pointer,
- // also we only check if view_count changes in render_target_set_size so we need to call that for this to reliably change
- vp->occlusion_buffer_dirty = vp->occlusion_buffer_dirty || (vp->size != xr_size);
- vp->size = xr_size;
- uint32_t view_count = xr_interface->get_view_count();
- RSG::texture_storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count);
+ _viewport_set_size(vp, xr_size.width, xr_size.height, xr_interface->get_view_count());
// Inform xr interface we're about to render its viewport, if this returns false we don't render
visible = xr_interface->pre_draw_viewport(vp->render_target);
@@ -686,12 +679,17 @@ void RendererViewport::draw_viewports() {
// commit our eyes
Vector<BlitToScreen> blits = xr_interface->post_draw_viewport(vp->render_target, vp->viewport_to_screen_rect);
if (vp->viewport_to_screen != DisplayServer::INVALID_WINDOW_ID && blits.size() > 0) {
- if (!blit_to_screen_list.has(vp->viewport_to_screen)) {
- blit_to_screen_list[vp->viewport_to_screen] = Vector<BlitToScreen>();
- }
+ if (OS::get_singleton()->get_current_rendering_driver_name() == "opengl3") {
+ RSG::rasterizer->blit_render_targets_to_screen(vp->viewport_to_screen, blits.ptr(), blits.size());
+ RSG::rasterizer->end_frame(true);
+ } else {
+ if (!blit_to_screen_list.has(vp->viewport_to_screen)) {
+ blit_to_screen_list[vp->viewport_to_screen] = Vector<BlitToScreen>();
+ }
- for (int b = 0; b < blits.size(); b++) {
- blit_to_screen_list[vp->viewport_to_screen].push_back(blits[b]);
+ for (int b = 0; b < blits.size(); b++) {
+ blit_to_screen_list[vp->viewport_to_screen].push_back(blits[b]);
+ }
}
}
} else {
@@ -777,7 +775,13 @@ void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) {
}
viewport->use_xr = p_use_xr;
- _configure_3d_render_buffers(viewport);
+
+ // Re-configure the 3D render buffers when disabling XR. They'll get
+ // re-configured when enabling XR in draw_viewports().
+ if (!p_use_xr) {
+ viewport->view_count = 1;
+ _configure_3d_render_buffers(viewport);
+ }
}
void RendererViewport::viewport_set_scaling_3d_mode(RID p_viewport, RS::ViewportScaling3DMode p_mode) {
@@ -823,34 +827,27 @@ void RendererViewport::viewport_set_scaling_3d_scale(RID p_viewport, float p_sca
_configure_3d_render_buffers(viewport);
}
-uint32_t RendererViewport::Viewport::get_view_count() {
- uint32_t view_count = 1;
-
- if (use_xr && XRServer::get_singleton() != nullptr) {
- Ref<XRInterface> xr_interface;
-
- xr_interface = XRServer::get_singleton()->get_primary_interface();
- if (xr_interface.is_valid()) {
- view_count = xr_interface->get_view_count();
- }
- }
-
- return view_count;
-}
-
void RendererViewport::viewport_set_size(RID p_viewport, int p_width, int p_height) {
ERR_FAIL_COND(p_width < 0 && p_height < 0);
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
+ ERR_FAIL_COND_MSG(viewport->use_xr, "Cannot set viewport size when using XR");
- viewport->size = Size2(p_width, p_height);
+ _viewport_set_size(viewport, p_width, p_height, 1);
+}
- uint32_t view_count = viewport->get_view_count();
- RSG::texture_storage->render_target_set_size(viewport->render_target, p_width, p_height, view_count);
- _configure_3d_render_buffers(viewport);
+void RendererViewport::_viewport_set_size(Viewport *p_viewport, int p_width, int p_height, uint32_t p_view_count) {
+ Size2i new_size(p_width, p_height);
+ if (p_viewport->size != new_size || p_viewport->view_count != p_view_count) {
+ p_viewport->size = new_size;
+ p_viewport->view_count = p_view_count;
- viewport->occlusion_buffer_dirty = true;
+ RSG::texture_storage->render_target_set_size(p_viewport->render_target, p_width, p_height, p_view_count);
+ _configure_3d_render_buffers(p_viewport);
+
+ p_viewport->occlusion_buffer_dirty = true;
+ }
}
void RendererViewport::viewport_set_active(RID p_viewport, bool p_active) {
@@ -890,7 +887,7 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
// If using OpenGL we can optimize this operation by rendering directly to system_fbo
// instead of rendering to fbo and copying to system_fbo after
if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
- RSG::texture_storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y, viewport->get_view_count());
+ RSG::texture_storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y, viewport->view_count);
RSG::texture_storage->render_target_set_position(viewport->render_target, p_rect.position.x, p_rect.position.y);
}
@@ -900,7 +897,7 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
// if render_direct_to_screen was used, reset size and position
if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
RSG::texture_storage->render_target_set_position(viewport->render_target, 0, 0);
- RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
+ RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->view_count);
}
viewport->viewport_to_screen_rect = Rect2();
@@ -919,7 +916,7 @@ void RendererViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool
// if disabled, reset render_target size and position
if (!p_enable) {
RSG::texture_storage->render_target_set_position(viewport->render_target, 0, 0);
- RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
+ RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->view_count);
}
RSG::texture_storage->render_target_set_direct_to_screen(viewport->render_target, p_enable);
@@ -927,7 +924,7 @@ void RendererViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool
// if attached to screen already, setup screen size and position, this needs to happen after setting flag to avoid an unnecessary buffer allocation
if (RSG::rasterizer->is_low_end() && viewport->viewport_to_screen_rect != Rect2() && p_enable) {
- RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y, viewport->get_view_count());
+ RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y, viewport->view_count);
RSG::texture_storage->render_target_set_position(viewport->render_target, viewport->viewport_to_screen_rect.position.x, viewport->viewport_to_screen_rect.position.y);
}
}
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index a123c70372..08ba6abc74 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -54,6 +54,7 @@ public:
Size2i internal_size;
Size2i size;
+ uint32_t view_count;
RID camera;
RID scenario;
@@ -150,6 +151,7 @@ public:
RendererScene::RenderInfo render_info;
Viewport() {
+ view_count = 1;
update_mode = RS::VIEWPORT_UPDATE_WHEN_VISIBLE;
clear_mode = RS::VIEWPORT_CLEAR_ALWAYS;
transparent_bg = false;
@@ -176,8 +178,6 @@ public:
time_gpu_begin = 0;
time_gpu_end = 0;
}
-
- uint32_t get_view_count();
};
HashMap<String, RID> timestamp_vp_map;
@@ -196,6 +196,7 @@ public:
private:
Vector<Viewport *> _sort_active_viewports();
+ void _viewport_set_size(Viewport *p_viewport, int p_width, int p_height, uint32_t p_view_count);
void _configure_3d_render_buffers(Viewport *p_viewport);
void _draw_3d(Viewport *p_viewport);
void _draw_viewport(Viewport *p_viewport);
diff --git a/thirdparty/README.md b/thirdparty/README.md
index df54f8cf36..2d0104ddea 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -276,7 +276,7 @@ Files extracted from upstream source:
## libpng
- Upstream: http://libpng.org/pub/png/libpng.html
-- Version: 1.6.37 (a40189cf881e9f0db80511c382292a5604c3c3d1, 2019)
+- Version: 1.6.38 (0a158f3506502dfa23edfc42790dfaed82efba17, 2022)
- License: libpng/zlib
Files extracted from upstream source:
diff --git a/thirdparty/libpng/LICENSE b/thirdparty/libpng/LICENSE
index e0c5b531cf..c8ad24eecf 100644
--- a/thirdparty/libpng/LICENSE
+++ b/thirdparty/libpng/LICENSE
@@ -4,8 +4,8 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
PNG Reference Library License version 2
---------------------------------------
- * Copyright (c) 1995-2019 The PNG Reference Library Authors.
- * Copyright (c) 2018-2019 Cosmin Truta.
+ * Copyright (c) 1995-2022 The PNG Reference Library Authors.
+ * Copyright (c) 2018-2022 Cosmin Truta.
* Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
* Copyright (c) 1996-1997 Andreas Dilger.
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
diff --git a/thirdparty/libpng/arm/arm_init.c b/thirdparty/libpng/arm/arm_init.c
index a34ecdbef7..ab22525b38 100644
--- a/thirdparty/libpng/arm/arm_init.c
+++ b/thirdparty/libpng/arm/arm_init.c
@@ -1,7 +1,7 @@
/* arm_init.c - NEON optimised filter functions
*
- * Copyright (c) 2018 Cosmin Truta
+ * Copyright (c) 2018-2022 Cosmin Truta
* Copyright (c) 2014,2016 Glenn Randers-Pehrson
* Written by Mans Rullgard, 2011.
*
@@ -10,9 +10,7 @@
* and license in png.h
*/
-/* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are
- * called.
- */
+/* This module requires POSIX 1003.1 functions. */
#define _POSIX_SOURCE 1
#include "../pngpriv.h"
@@ -33,21 +31,23 @@
* has partial support is contrib/arm-neon/linux.c - a generic Linux
* implementation which reads /proc/cpufino.
*/
+#include <signal.h> /* for sig_atomic_t */
+
#ifndef PNG_ARM_NEON_FILE
-# ifdef __linux__
-# define PNG_ARM_NEON_FILE "contrib/arm-neon/linux.c"
+# if defined(__aarch64__) || defined(_M_ARM64)
+ /* ARM Neon is expected to be unconditionally available on ARM64. */
+# error "PNG_ARM_NEON_CHECK_SUPPORTED must not be defined on this platform"
+# elif defined(__linux__)
+# define PNG_ARM_NEON_FILE "contrib/arm-neon/linux.c"
+# else
+# error "No support for run-time ARM Neon checking; use compile-time options"
# endif
#endif
-#ifdef PNG_ARM_NEON_FILE
-
-#include <signal.h> /* for sig_atomic_t */
static int png_have_neon(png_structp png_ptr);
-#include PNG_ARM_NEON_FILE
-
-#else /* PNG_ARM_NEON_FILE */
-# error "PNG_ARM_NEON_FILE undefined: no support for run-time ARM NEON checks"
-#endif /* PNG_ARM_NEON_FILE */
+#ifdef PNG_ARM_NEON_FILE
+# include PNG_ARM_NEON_FILE
+#endif
#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */
#ifndef PNG_ALIGNED_MEMORY_SUPPORTED
diff --git a/thirdparty/libpng/arm/filter_neon_intrinsics.c b/thirdparty/libpng/arm/filter_neon_intrinsics.c
index 553c0be21c..4466d48b20 100644
--- a/thirdparty/libpng/arm/filter_neon_intrinsics.c
+++ b/thirdparty/libpng/arm/filter_neon_intrinsics.c
@@ -18,7 +18,7 @@
/* This code requires -mfpu=neon on the command line: */
#if PNG_ARM_NEON_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */
-#if defined(_MSC_VER) && defined(_M_ARM64)
+#if defined(_MSC_VER) && !defined(__clang__) && defined(_M_ARM64)
# include <arm64_neon.h>
#else
# include <arm_neon.h>
diff --git a/thirdparty/libpng/arm/palette_neon_intrinsics.c b/thirdparty/libpng/arm/palette_neon_intrinsics.c
index b4d1fd2abf..92c7d6f9f6 100644
--- a/thirdparty/libpng/arm/palette_neon_intrinsics.c
+++ b/thirdparty/libpng/arm/palette_neon_intrinsics.c
@@ -14,7 +14,7 @@
#if PNG_ARM_NEON_IMPLEMENTATION == 1
-#if defined(_MSC_VER) && defined(_M_ARM64)
+#if defined(_MSC_VER) && !defined(__clang__) && defined(_M_ARM64)
# include <arm64_neon.h>
#else
# include <arm_neon.h>
@@ -30,8 +30,6 @@ png_riffle_palette_neon(png_structrp png_ptr)
int num_trans = png_ptr->num_trans;
int i;
- png_debug(1, "in png_riffle_palette_neon");
-
/* Initially black, opaque. */
uint8x16x4_t w = {{
vdupq_n_u8(0x00),
@@ -40,6 +38,8 @@ png_riffle_palette_neon(png_structrp png_ptr)
vdupq_n_u8(0xff),
}};
+ png_debug(1, "in png_riffle_palette_neon");
+
/* First, riffle the RGB colours into an RGBA8 palette.
* The alpha component is set to opaque for now.
*/
@@ -65,11 +65,12 @@ png_do_expand_palette_rgba8_neon(png_structrp png_ptr, png_row_infop row_info,
png_uint_32 row_width = row_info->width;
const png_uint_32 *riffled_palette =
(const png_uint_32 *)png_ptr->riffled_palette;
- const png_int_32 pixels_per_chunk = 4;
- int i;
+ const png_uint_32 pixels_per_chunk = 4;
+ png_uint_32 i;
png_debug(1, "in png_do_expand_palette_rgba8_neon");
+ PNG_UNUSED(row)
if (row_width < pixels_per_chunk)
return 0;
@@ -109,10 +110,11 @@ png_do_expand_palette_rgb8_neon(png_structrp png_ptr, png_row_infop row_info,
png_uint_32 row_width = row_info->width;
png_const_bytep palette = (png_const_bytep)png_ptr->palette;
const png_uint_32 pixels_per_chunk = 8;
- int i;
+ png_uint_32 i;
png_debug(1, "in png_do_expand_palette_rgb8_neon");
+ PNG_UNUSED(row)
if (row_width <= pixels_per_chunk)
return 0;
diff --git a/thirdparty/libpng/png.c b/thirdparty/libpng/png.c
index 757c755f97..fc09564262 100644
--- a/thirdparty/libpng/png.c
+++ b/thirdparty/libpng/png.c
@@ -1,7 +1,7 @@
/* png.c - location for general purpose libpng functions
*
- * Copyright (c) 2018-2019 Cosmin Truta
+ * Copyright (c) 2018-2022 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -14,7 +14,7 @@
#include "pngpriv.h"
/* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_37 Your_png_h_is_not_version_1_6_37;
+typedef png_libpng_version_1_6_38 Your_png_h_is_not_version_1_6_38;
#ifdef __GNUC__
/* The version tests may need to be added to, but the problem warning has
@@ -720,7 +720,7 @@ png_init_io(png_structrp png_ptr, png_FILE_p fp)
*
* Where UNSIGNED_MAX is the appropriate maximum unsigned value, so when the
* negative integral value is added the result will be an unsigned value
- * correspnding to the 2's complement representation.
+ * corresponding to the 2's complement representation.
*/
void PNGAPI
png_save_int_32(png_bytep buf, png_int_32 i)
@@ -815,8 +815,8 @@ png_get_copyright(png_const_structrp png_ptr)
return PNG_STRING_COPYRIGHT
#else
return PNG_STRING_NEWLINE \
- "libpng version 1.6.37" PNG_STRING_NEWLINE \
- "Copyright (c) 2018-2019 Cosmin Truta" PNG_STRING_NEWLINE \
+ "libpng version 1.6.38" PNG_STRING_NEWLINE \
+ "Copyright (c) 2018-2022 Cosmin Truta" PNG_STRING_NEWLINE \
"Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
PNG_STRING_NEWLINE \
"Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
@@ -1843,12 +1843,12 @@ png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace,
# ifdef PNG_WARNINGS_SUPPORTED
else
{
- char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114*/
+ char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114 */
pos = png_safecat(message, (sizeof message), pos,
png_format_number(number, number+(sizeof number),
PNG_NUMBER_FORMAT_x, value));
- pos = png_safecat(message, (sizeof message), pos, "h: "); /*+2 = 116*/
+ pos = png_safecat(message, (sizeof message), pos, "h: "); /* +2 = 116 */
}
# endif
/* The 'reason' is an arbitrary message, allow +79 maximum 195 */
diff --git a/thirdparty/libpng/png.h b/thirdparty/libpng/png.h
index b12174ba35..5fb494fb1a 100644
--- a/thirdparty/libpng/png.h
+++ b/thirdparty/libpng/png.h
@@ -1,9 +1,9 @@
/* png.h - header file for PNG reference library
*
- * libpng version 1.6.37 - April 14, 2019
+ * libpng version 1.6.38 - September 14, 2022
*
- * Copyright (c) 2018-2019 Cosmin Truta
+ * Copyright (c) 2018-2022 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -15,7 +15,7 @@
* libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
* libpng versions 0.97, January 1998, through 1.6.35, July 2018:
* Glenn Randers-Pehrson
- * libpng versions 1.6.36, December 2018, through 1.6.37, April 2019:
+ * libpng versions 1.6.36, December 2018, through 1.6.38, September 2022:
* Cosmin Truta
* See also "Contributing Authors", below.
*/
@@ -27,8 +27,8 @@
* PNG Reference Library License version 2
* ---------------------------------------
*
- * * Copyright (c) 1995-2019 The PNG Reference Library Authors.
- * * Copyright (c) 2018-2019 Cosmin Truta.
+ * * Copyright (c) 1995-2022 The PNG Reference Library Authors.
+ * * Copyright (c) 2018-2022 Cosmin Truta.
* * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
* * Copyright (c) 1996-1997 Andreas Dilger.
* * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -239,7 +239,7 @@
* ...
* 1.5.30 15 10530 15.so.15.30[.0]
* ...
- * 1.6.37 16 10637 16.so.16.37[.0]
+ * 1.6.38 16 10638 16.so.16.38[.0]
*
* Henceforth the source version will match the shared-library major and
* minor numbers; the shared-library major version number will be used for
@@ -278,8 +278,8 @@
*/
/* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.37"
-#define PNG_HEADER_VERSION_STRING " libpng version 1.6.37 - April 14, 2019\n"
+#define PNG_LIBPNG_VER_STRING "1.6.38"
+#define PNG_HEADER_VERSION_STRING " libpng version 1.6.38 - September 14, 2022\n"
#define PNG_LIBPNG_VER_SONUM 16
#define PNG_LIBPNG_VER_DLLNUM 16
@@ -287,7 +287,7 @@
/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
#define PNG_LIBPNG_VER_MAJOR 1
#define PNG_LIBPNG_VER_MINOR 6
-#define PNG_LIBPNG_VER_RELEASE 37
+#define PNG_LIBPNG_VER_RELEASE 38
/* This should be zero for a public release, or non-zero for a
* development version. [Deprecated]
@@ -318,7 +318,7 @@
* From version 1.0.1 it is:
* XXYYZZ, where XX=major, YY=minor, ZZ=release
*/
-#define PNG_LIBPNG_VER 10637 /* 1.6.37 */
+#define PNG_LIBPNG_VER 10638 /* 1.6.38 */
/* Library configuration: these options cannot be changed after
* the library has been built.
@@ -330,10 +330,6 @@
# include "pnglibconf.h"
#endif
-#define PNG_APNG_SUPPORTED
-#define PNG_READ_APNG_SUPPORTED
-#define PNG_WRITE_APNG_SUPPORTED
-
#ifndef PNG_VERSION_INFO_ONLY
/* Machine specific configuration. */
# include "pngconf.h"
@@ -429,21 +425,10 @@ extern "C" {
* See pngconf.h for base types that vary by machine/system
*/
-#ifdef PNG_APNG_SUPPORTED
-/* dispose_op flags from inside fcTL */
-#define PNG_DISPOSE_OP_NONE 0x00U
-#define PNG_DISPOSE_OP_BACKGROUND 0x01U
-#define PNG_DISPOSE_OP_PREVIOUS 0x02U
-
-/* blend_op flags from inside fcTL */
-#define PNG_BLEND_OP_SOURCE 0x00U
-#define PNG_BLEND_OP_OVER 0x01U
-#endif /* PNG_APNG_SUPPORTED */
-
/* This triggers a compiler error in png.c, if png.c and png.h
* do not agree upon the version number.
*/
-typedef char* png_libpng_version_1_6_37;
+typedef char* png_libpng_version_1_6_38;
/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info.
*
@@ -761,10 +746,6 @@ typedef png_unknown_chunk * * png_unknown_chunkpp;
#define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */
#define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */
#define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */
-#ifdef PNG_APNG_SUPPORTED
-#define PNG_INFO_acTL 0x20000U
-#define PNG_INFO_fcTL 0x40000U
-#endif
/* This is used for the transformation routines, as some of them
* change these values for the row. It also should enable using
@@ -802,10 +783,6 @@ typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32,
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop));
typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop));
-#ifdef PNG_APNG_SUPPORTED
-typedef PNG_CALLBACK(void, *png_progressive_frame_ptr, (png_structp,
- png_uint_32));
-#endif
/* The following callback receives png_uint_32 row_number, int pass for the
* png_bytep data of the row. When transforming an interlaced image the
@@ -1469,7 +1446,7 @@ PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action,
* mainly useful for testing, as the defaults should work with most users.
* Those users who are tight on memory or want faster performance at the
* expense of compression can modify them. See the compression library
- * header file (zlib.h) for an explination of the compression functions.
+ * header file (zlib.h) for an explanation of the compression functions.
*/
/* Set the filtering method(s) used by libpng. Currently, the only valid
@@ -1524,7 +1501,7 @@ PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed,
* 0 - 9, corresponding directly to the zlib compression levels 0 - 9
* (0 - no compression, 9 - "maximal" compression). Note that tests have
* shown that zlib compression levels 3-6 usually perform as well as level 9
- * for PNG images, and do considerably fewer caclulations. In the future,
+ * for PNG images, and do considerably fewer calculations. In the future,
* these values may not correspond directly to the zlib compression levels.
*/
#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
@@ -3249,74 +3226,6 @@ PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option,
/*******************************************************************************
* END OF HARDWARE AND SOFTWARE OPTIONS
******************************************************************************/
-#ifdef PNG_APNG_SUPPORTED
-PNG_EXPORT(250, png_uint_32, png_get_acTL, (png_structp png_ptr,
- png_infop info_ptr, png_uint_32 *num_frames, png_uint_32 *num_plays));
-
-PNG_EXPORT(251, png_uint_32, png_set_acTL, (png_structp png_ptr,
- png_infop info_ptr, png_uint_32 num_frames, png_uint_32 num_plays));
-
-PNG_EXPORT(252, png_uint_32, png_get_num_frames, (png_structp png_ptr,
- png_infop info_ptr));
-
-PNG_EXPORT(253, png_uint_32, png_get_num_plays, (png_structp png_ptr,
- png_infop info_ptr));
-
-PNG_EXPORT(254, png_uint_32, png_get_next_frame_fcTL,
- (png_structp png_ptr, png_infop info_ptr, png_uint_32 *width,
- png_uint_32 *height, png_uint_32 *x_offset, png_uint_32 *y_offset,
- png_uint_16 *delay_num, png_uint_16 *delay_den, png_byte *dispose_op,
- png_byte *blend_op));
-
-PNG_EXPORT(255, png_uint_32, png_set_next_frame_fcTL,
- (png_structp png_ptr, png_infop info_ptr, png_uint_32 width,
- png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset,
- png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
- png_byte blend_op));
-
-PNG_EXPORT(256, png_uint_32, png_get_next_frame_width,
- (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(257, png_uint_32, png_get_next_frame_height,
- (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(258, png_uint_32, png_get_next_frame_x_offset,
- (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(259, png_uint_32, png_get_next_frame_y_offset,
- (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(260, png_uint_16, png_get_next_frame_delay_num,
- (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(261, png_uint_16, png_get_next_frame_delay_den,
- (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(262, png_byte, png_get_next_frame_dispose_op,
- (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(263, png_byte, png_get_next_frame_blend_op,
- (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(264, png_byte, png_get_first_frame_is_hidden,
- (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(265, png_uint_32, png_set_first_frame_is_hidden,
- (png_structp png_ptr, png_infop info_ptr, png_byte is_hidden));
-
-#ifdef PNG_READ_APNG_SUPPORTED
-PNG_EXPORT(266, void, png_read_frame_head, (png_structp png_ptr,
- png_infop info_ptr));
-#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-PNG_EXPORT(267, void, png_set_progressive_frame_fn, (png_structp png_ptr,
- png_progressive_frame_ptr frame_info_fn,
- png_progressive_frame_ptr frame_end_fn));
-#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
-#endif /* PNG_READ_APNG_SUPPORTED */
-
-#ifdef PNG_WRITE_APNG_SUPPORTED
-PNG_EXPORT(268, void, png_write_frame_head, (png_structp png_ptr,
- png_infop info_ptr, png_bytepp row_pointers,
- png_uint_32 width, png_uint_32 height,
- png_uint_32 x_offset, png_uint_32 y_offset,
- png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
- png_byte blend_op));
-
-PNG_EXPORT(269, void, png_write_frame_tail, (png_structp png_ptr,
- png_infop info_ptr));
-#endif /* PNG_WRITE_APNG_SUPPORTED */
-#endif /* PNG_APNG_SUPPORTED */
/* Maintainer: Put new public prototypes here ^, in libpng.3, in project
* defs, and in scripts/symbols.def.
@@ -3326,11 +3235,7 @@ PNG_EXPORT(269, void, png_write_frame_tail, (png_structp png_ptr,
* one to use is one more than this.)
*/
#ifdef PNG_EXPORT_LAST_ORDINAL
-#ifdef PNG_APNG_SUPPORTED
- PNG_EXPORT_LAST_ORDINAL(269);
-#else
PNG_EXPORT_LAST_ORDINAL(249);
-#endif /* PNG_APNG_SUPPORTED */
#endif
#ifdef __cplusplus
diff --git a/thirdparty/libpng/pngconf.h b/thirdparty/libpng/pngconf.h
index 927a769dbe..89d28f83a0 100644
--- a/thirdparty/libpng/pngconf.h
+++ b/thirdparty/libpng/pngconf.h
@@ -1,9 +1,9 @@
/* pngconf.h - machine-configurable file for libpng
*
- * libpng version 1.6.37
+ * libpng version 1.6.38
*
- * Copyright (c) 2018-2019 Cosmin Truta
+ * Copyright (c) 2018-2022 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -180,8 +180,8 @@
* compiler-specific macros to the values required to change the calling
* conventions of the various functions.
*/
-#if defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\
- defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+#if defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || \
+ defined(__CYGWIN__)
/* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or
* MinGW on any architecture currently supported by Windows. Also includes
* Watcom builds but these need special treatment because they are not
diff --git a/thirdparty/libpng/pngget.c b/thirdparty/libpng/pngget.c
index 9ed101aedc..e44933c0d2 100644
--- a/thirdparty/libpng/pngget.c
+++ b/thirdparty/libpng/pngget.c
@@ -1151,7 +1151,7 @@ png_get_unknown_chunks(png_const_structrp png_ptr, png_inforp info_ptr,
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
png_byte PNGAPI
-png_get_rgb_to_gray_status (png_const_structrp png_ptr)
+png_get_rgb_to_gray_status(png_const_structrp png_ptr)
{
return (png_byte)(png_ptr ? png_ptr->rgb_to_gray_status : 0);
}
@@ -1192,27 +1192,27 @@ png_get_compression_buffer_size(png_const_structrp png_ptr)
/* These functions were added to libpng 1.2.6 and were enabled
* by default in libpng-1.4.0 */
png_uint_32 PNGAPI
-png_get_user_width_max (png_const_structrp png_ptr)
+png_get_user_width_max(png_const_structrp png_ptr)
{
return (png_ptr ? png_ptr->user_width_max : 0);
}
png_uint_32 PNGAPI
-png_get_user_height_max (png_const_structrp png_ptr)
+png_get_user_height_max(png_const_structrp png_ptr)
{
return (png_ptr ? png_ptr->user_height_max : 0);
}
/* This function was added to libpng 1.4.0 */
png_uint_32 PNGAPI
-png_get_chunk_cache_max (png_const_structrp png_ptr)
+png_get_chunk_cache_max(png_const_structrp png_ptr)
{
return (png_ptr ? png_ptr->user_chunk_cache_max : 0);
}
/* This function was added to libpng 1.4.1 */
png_alloc_size_t PNGAPI
-png_get_chunk_malloc_max (png_const_structrp png_ptr)
+png_get_chunk_malloc_max(png_const_structrp png_ptr)
{
return (png_ptr ? png_ptr->user_chunk_malloc_max : 0);
}
@@ -1221,13 +1221,13 @@ png_get_chunk_malloc_max (png_const_structrp png_ptr)
/* These functions were added to libpng 1.4.0 */
#ifdef PNG_IO_STATE_SUPPORTED
png_uint_32 PNGAPI
-png_get_io_state (png_const_structrp png_ptr)
+png_get_io_state(png_const_structrp png_ptr)
{
return png_ptr->io_state;
}
png_uint_32 PNGAPI
-png_get_io_chunk_type (png_const_structrp png_ptr)
+png_get_io_chunk_type(png_const_structrp png_ptr)
{
return png_ptr->chunk_name;
}
@@ -1246,166 +1246,4 @@ png_get_palette_max(png_const_structp png_ptr, png_const_infop info_ptr)
# endif
#endif
-#ifdef PNG_APNG_SUPPORTED
-png_uint_32 PNGAPI
-png_get_acTL(png_structp png_ptr, png_infop info_ptr,
- png_uint_32 *num_frames, png_uint_32 *num_plays)
-{
- png_debug1(1, "in %s retrieval function", "acTL");
-
- if (png_ptr != NULL && info_ptr != NULL &&
- (info_ptr->valid & PNG_INFO_acTL) &&
- num_frames != NULL && num_plays != NULL)
- {
- *num_frames = info_ptr->num_frames;
- *num_plays = info_ptr->num_plays;
- return (1);
- }
-
- return (0);
-}
-
-png_uint_32 PNGAPI
-png_get_num_frames(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_get_num_frames()");
-
- if (png_ptr != NULL && info_ptr != NULL)
- return (info_ptr->num_frames);
- return (0);
-}
-
-png_uint_32 PNGAPI
-png_get_num_plays(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_get_num_plays()");
-
- if (png_ptr != NULL && info_ptr != NULL)
- return (info_ptr->num_plays);
- return (0);
-}
-
-png_uint_32 PNGAPI
-png_get_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr,
- png_uint_32 *width, png_uint_32 *height,
- png_uint_32 *x_offset, png_uint_32 *y_offset,
- png_uint_16 *delay_num, png_uint_16 *delay_den,
- png_byte *dispose_op, png_byte *blend_op)
-{
- png_debug1(1, "in %s retrieval function", "fcTL");
-
- if (png_ptr != NULL && info_ptr != NULL &&
- (info_ptr->valid & PNG_INFO_fcTL) &&
- width != NULL && height != NULL &&
- x_offset != NULL && y_offset != NULL &&
- delay_num != NULL && delay_den != NULL &&
- dispose_op != NULL && blend_op != NULL)
- {
- *width = info_ptr->next_frame_width;
- *height = info_ptr->next_frame_height;
- *x_offset = info_ptr->next_frame_x_offset;
- *y_offset = info_ptr->next_frame_y_offset;
- *delay_num = info_ptr->next_frame_delay_num;
- *delay_den = info_ptr->next_frame_delay_den;
- *dispose_op = info_ptr->next_frame_dispose_op;
- *blend_op = info_ptr->next_frame_blend_op;
- return (1);
- }
-
- return (0);
-}
-
-png_uint_32 PNGAPI
-png_get_next_frame_width(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_get_next_frame_width()");
-
- if (png_ptr != NULL && info_ptr != NULL)
- return (info_ptr->next_frame_width);
- return (0);
-}
-
-png_uint_32 PNGAPI
-png_get_next_frame_height(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_get_next_frame_height()");
-
- if (png_ptr != NULL && info_ptr != NULL)
- return (info_ptr->next_frame_height);
- return (0);
-}
-
-png_uint_32 PNGAPI
-png_get_next_frame_x_offset(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_get_next_frame_x_offset()");
-
- if (png_ptr != NULL && info_ptr != NULL)
- return (info_ptr->next_frame_x_offset);
- return (0);
-}
-
-png_uint_32 PNGAPI
-png_get_next_frame_y_offset(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_get_next_frame_y_offset()");
-
- if (png_ptr != NULL && info_ptr != NULL)
- return (info_ptr->next_frame_y_offset);
- return (0);
-}
-
-png_uint_16 PNGAPI
-png_get_next_frame_delay_num(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_get_next_frame_delay_num()");
-
- if (png_ptr != NULL && info_ptr != NULL)
- return (info_ptr->next_frame_delay_num);
- return (0);
-}
-
-png_uint_16 PNGAPI
-png_get_next_frame_delay_den(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_get_next_frame_delay_den()");
-
- if (png_ptr != NULL && info_ptr != NULL)
- return (info_ptr->next_frame_delay_den);
- return (0);
-}
-
-png_byte PNGAPI
-png_get_next_frame_dispose_op(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_get_next_frame_dispose_op()");
-
- if (png_ptr != NULL && info_ptr != NULL)
- return (info_ptr->next_frame_dispose_op);
- return (0);
-}
-
-png_byte PNGAPI
-png_get_next_frame_blend_op(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_get_next_frame_blend_op()");
-
- if (png_ptr != NULL && info_ptr != NULL)
- return (info_ptr->next_frame_blend_op);
- return (0);
-}
-
-png_byte PNGAPI
-png_get_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_first_frame_is_hidden()");
-
- if (png_ptr != NULL)
- return (png_byte)(png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN);
-
- PNG_UNUSED(info_ptr)
-
- return 0;
-}
-#endif /* PNG_APNG_SUPPORTED */
#endif /* READ || WRITE */
diff --git a/thirdparty/libpng/pnginfo.h b/thirdparty/libpng/pnginfo.h
index ac7b269132..1f98dedc42 100644
--- a/thirdparty/libpng/pnginfo.h
+++ b/thirdparty/libpng/pnginfo.h
@@ -263,18 +263,5 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
png_bytepp row_pointers; /* the image bits */
#endif
-#ifdef PNG_APNG_SUPPORTED
- png_uint_32 num_frames; /* including default image */
- png_uint_32 num_plays;
- png_uint_32 next_frame_width;
- png_uint_32 next_frame_height;
- png_uint_32 next_frame_x_offset;
- png_uint_32 next_frame_y_offset;
- png_uint_16 next_frame_delay_num;
- png_uint_16 next_frame_delay_den;
- png_byte next_frame_dispose_op;
- png_byte next_frame_blend_op;
-#endif
-
};
#endif /* PNGINFO_H */
diff --git a/thirdparty/libpng/pnglibconf.h b/thirdparty/libpng/pnglibconf.h
index e1e27e957e..89d5b4c8ad 100644
--- a/thirdparty/libpng/pnglibconf.h
+++ b/thirdparty/libpng/pnglibconf.h
@@ -1,8 +1,8 @@
/* pnglibconf.h - library build configuration */
-/* libpng version 1.6.37 */
+/* libpng version 1.6.38 */
-/* Copyright (c) 2018-2019 Cosmin Truta */
+/* Copyright (c) 2018-2022 Cosmin Truta */
/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */
/* This code is released under the libpng license. */
diff --git a/thirdparty/libpng/pngpread.c b/thirdparty/libpng/pngpread.c
index 2eaeca08f7..e283627b77 100644
--- a/thirdparty/libpng/pngpread.c
+++ b/thirdparty/libpng/pngpread.c
@@ -195,106 +195,6 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
chunk_name = png_ptr->chunk_name;
-#ifdef PNG_READ_APNG_SUPPORTED
- if (png_ptr->num_frames_read > 0 &&
- png_ptr->num_frames_read < info_ptr->num_frames)
- {
- if (chunk_name == png_IDAT)
- {
- /* Discard trailing IDATs for the first frame */
- if (png_ptr->mode & PNG_HAVE_fcTL || png_ptr->num_frames_read > 1)
- png_error(png_ptr, "out of place IDAT");
-
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
- return;
- }
- else if (chunk_name == png_fdAT)
- {
- if (png_ptr->buffer_size < 4)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_ensure_sequence_number(png_ptr, 4);
-
- if (!(png_ptr->mode & PNG_HAVE_fcTL))
- {
- /* Discard trailing fdATs for frames other than the first */
- if (png_ptr->num_frames_read < 2)
- png_error(png_ptr, "out of place fdAT");
-
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
- return;
- }
-
- else
- {
- /* frame data follows */
- png_ptr->idat_size = png_ptr->push_length - 4;
- png_ptr->mode |= PNG_HAVE_IDAT;
- png_ptr->process_mode = PNG_READ_IDAT_MODE;
-
- return;
- }
- }
-
- else if (chunk_name == png_fcTL)
- {
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_read_reset(png_ptr);
- png_ptr->mode &= ~PNG_HAVE_fcTL;
-
- png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length);
-
- if (!(png_ptr->mode & PNG_HAVE_fcTL))
- png_error(png_ptr, "missing required fcTL chunk");
-
- png_read_reinit(png_ptr, info_ptr);
- png_progressive_read_reset(png_ptr);
-
- if (png_ptr->frame_info_fn != NULL)
- (*(png_ptr->frame_info_fn))(png_ptr, png_ptr->num_frames_read);
-
- png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
-
- return;
- }
-
- else
- {
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
- png_warning(png_ptr, "Skipped (ignored) a chunk "
- "between APNG chunks");
- png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
- return;
- }
-
- return;
- }
-#endif /* PNG_READ_APNG_SUPPORTED */
-
if (chunk_name == png_IDAT)
{
if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
@@ -361,9 +261,6 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
else if (chunk_name == png_IDAT)
{
-#ifdef PNG_READ_APNG_SUPPORTED
- png_have_info(png_ptr, info_ptr);
-#endif
png_ptr->idat_size = png_ptr->push_length;
png_ptr->process_mode = PNG_READ_IDAT_MODE;
png_push_have_info(png_ptr, info_ptr);
@@ -509,30 +406,6 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
-#ifdef PNG_READ_APNG_SUPPORTED
- else if (chunk_name == png_acTL)
- {
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_handle_acTL(png_ptr, info_ptr, png_ptr->push_length);
- }
-
- else if (chunk_name == png_fcTL)
- {
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length);
- }
-
-#endif /* PNG_READ_APNG_SUPPORTED */
else
{
@@ -666,11 +539,7 @@ png_push_read_IDAT(png_structrp png_ptr)
png_byte chunk_tag[4];
/* TODO: this code can be commoned up with the same code in push_read */
-#ifdef PNG_READ_APNG_SUPPORTED
- PNG_PUSH_SAVE_BUFFER_IF_LT(12)
-#else
PNG_PUSH_SAVE_BUFFER_IF_LT(8)
-#endif
png_push_fill_buffer(png_ptr, chunk_length, 4);
png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
png_reset_crc(png_ptr);
@@ -678,64 +547,17 @@ png_push_read_IDAT(png_structrp png_ptr)
png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
-#ifdef PNG_READ_APNG_SUPPORTED
- if (png_ptr->chunk_name != png_fdAT && png_ptr->num_frames_read > 0)
- {
- if (png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)
- {
- png_ptr->process_mode = PNG_READ_CHUNK_MODE;
- if (png_ptr->frame_end_fn != NULL)
- (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read);
- png_ptr->num_frames_read++;
- return;
- }
- else
- {
- if (png_ptr->chunk_name == png_IEND)
- png_error(png_ptr, "Not enough image data");
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
- png_warning(png_ptr, "Skipping (ignoring) a chunk between "
- "APNG chunks");
- png_crc_finish(png_ptr, png_ptr->push_length);
- png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
- return;
- }
- }
- else
-#endif
-#ifdef PNG_READ_APNG_SUPPORTED
- if (png_ptr->chunk_name != png_IDAT && png_ptr->num_frames_read == 0)
-#else
if (png_ptr->chunk_name != png_IDAT)
-#endif
{
png_ptr->process_mode = PNG_READ_CHUNK_MODE;
if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
png_error(png_ptr, "Not enough compressed data");
-#ifdef PNG_READ_APNG_SUPPORTED
- if (png_ptr->frame_end_fn != NULL)
- (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read);
- png_ptr->num_frames_read++;
-#endif
-
return;
}
png_ptr->idat_size = png_ptr->push_length;
-
-#ifdef PNG_READ_APNG_SUPPORTED
- if (png_ptr->num_frames_read > 0)
- {
- png_ensure_sequence_number(png_ptr, 4);
- png_ptr->idat_size -= 4;
- }
-#endif
}
if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0)
@@ -809,15 +631,6 @@ png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer,
if (!(buffer_length > 0) || buffer == NULL)
png_error(png_ptr, "No IDAT data (internal error)");
-#ifdef PNG_READ_APNG_SUPPORTED
- /* If the app is not APNG-aware, decode only the first frame */
- if (!(png_ptr->apng_flags & PNG_APNG_APP) && png_ptr->num_frames_read > 0)
- {
- png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
- return;
- }
-#endif
-
/* This routine must process all the data it has been given
* before returning, calling the row callback as required to
* handle the uncompressed results.
@@ -1272,18 +1085,6 @@ png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr,
png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
}
-#ifdef PNG_READ_APNG_SUPPORTED
-void PNGAPI
-png_set_progressive_frame_fn(png_structp png_ptr,
- png_progressive_frame_ptr frame_info_fn,
- png_progressive_frame_ptr frame_end_fn)
-{
- png_ptr->frame_info_fn = frame_info_fn;
- png_ptr->frame_end_fn = frame_end_fn;
- png_ptr->apng_flags |= PNG_APNG_APP;
-}
-#endif
-
png_voidp PNGAPI
png_get_progressive_ptr(png_const_structrp png_ptr)
{
diff --git a/thirdparty/libpng/pngpriv.h b/thirdparty/libpng/pngpriv.h
index 57e1bf989b..2e426cf47d 100644
--- a/thirdparty/libpng/pngpriv.h
+++ b/thirdparty/libpng/pngpriv.h
@@ -1,7 +1,7 @@
/* pngpriv.h - private declarations for use inside libpng
*
- * Copyright (c) 2018-2019 Cosmin Truta
+ * Copyright (c) 2018-2022 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -174,7 +174,7 @@
# else /* !defined __ARM_NEON__ */
/* The 'intrinsics' code simply won't compile without this -mfpu=neon:
*/
-# if !defined(__aarch64__)
+# if !defined(__aarch64__) && !defined(_M_ARM64)
/* The assembler code currently does not work on ARM64 */
# define PNG_ARM_NEON_IMPLEMENTATION 2
# endif /* __aarch64__ */
@@ -185,6 +185,8 @@
/* Use the intrinsics code by default. */
# define PNG_ARM_NEON_IMPLEMENTATION 1
# endif
+#else /* PNG_ARM_NEON_OPT == 0 */
+# define PNG_ARM_NEON_IMPLEMENTATION 0
#endif /* PNG_ARM_NEON_OPT > 0 */
#ifndef PNG_MIPS_MSA_OPT
@@ -263,11 +265,15 @@
# ifndef PNG_MIPS_MSA_IMPLEMENTATION
# define PNG_MIPS_MSA_IMPLEMENTATION 1
# endif
+#else
+# define PNG_MIPS_MSA_IMPLEMENTATION 0
#endif /* PNG_MIPS_MSA_OPT > 0 */
#if PNG_POWERPC_VSX_OPT > 0
# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_vsx
# define PNG_POWERPC_VSX_IMPLEMENTATION 1
+#else
+# define PNG_POWERPC_VSX_IMPLEMENTATION 0
#endif
@@ -492,16 +498,7 @@
static_cast<type>(static_cast<const void*>(value))
#else
# define png_voidcast(type, value) (value)
-# ifdef _WIN64
-# ifdef __GNUC__
- typedef unsigned long long png_ptruint;
-# else
- typedef unsigned __int64 png_ptruint;
-# endif
-# else
- typedef unsigned long png_ptruint;
-# endif
-# define png_constcast(type, value) ((type)(png_ptruint)(const void*)(value))
+# define png_constcast(type, value) ((type)(void*)(const void*)(value))
# define png_aligncast(type, value) ((void*)(value))
# define png_aligncastconst(type, value) ((const void*)(value))
#endif /* __cplusplus */
@@ -543,9 +540,8 @@
# include <alloc.h>
#endif
-#if defined(WIN32) || defined(_Windows) || defined(_WINDOWS) || \
- defined(_WIN32) || defined(__WIN32__)
-# include <windows.h> /* defines _WINDOWS_ macro */
+#if defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
+# include <windows.h>
#endif
#endif /* PNG_VERSION_INFO_ONLY */
@@ -554,24 +550,20 @@
* functions that are passed far data must be model-independent.
*/
-/* Memory model/platform independent fns */
+/* Platform-independent functions */
#ifndef PNG_ABORT
-# ifdef _WINDOWS_
-# define PNG_ABORT() ExitProcess(0)
-# else
-# define PNG_ABORT() abort()
-# endif
+# define PNG_ABORT() abort()
#endif
/* These macros may need to be architecture dependent. */
-#define PNG_ALIGN_NONE 0 /* do not use data alignment */
-#define PNG_ALIGN_ALWAYS 1 /* assume unaligned accesses are OK */
+#define PNG_ALIGN_NONE 0 /* do not use data alignment */
+#define PNG_ALIGN_ALWAYS 1 /* assume unaligned accesses are OK */
#ifdef offsetof
-# define PNG_ALIGN_OFFSET 2 /* use offsetof to determine alignment */
+# define PNG_ALIGN_OFFSET 2 /* use offsetof to determine alignment */
#else
# define PNG_ALIGN_OFFSET -1 /* prevent the use of this */
#endif
-#define PNG_ALIGN_SIZE 3 /* use sizeof to determine alignment */
+#define PNG_ALIGN_SIZE 3 /* use sizeof to determine alignment */
#ifndef PNG_ALIGN_TYPE
/* Default to using aligned access optimizations and requiring alignment to a
@@ -585,26 +577,25 @@
/* This is used because in some compiler implementations non-aligned
* structure members are supported, so the offsetof approach below fails.
* Set PNG_ALIGN_SIZE=0 for compiler combinations where unaligned access
- * is good for performance. Do not do this unless you have tested the result
- * and understand it.
+ * is good for performance. Do not do this unless you have tested the
+ * result and understand it.
*/
-# define png_alignof(type) (sizeof (type))
+# define png_alignof(type) (sizeof(type))
#else
# if PNG_ALIGN_TYPE == PNG_ALIGN_OFFSET
-# define png_alignof(type) offsetof(struct{char c; type t;}, t)
+# define png_alignof(type) offsetof(struct{char c; type t;}, t)
# else
-# if PNG_ALIGN_TYPE == PNG_ALIGN_ALWAYS
-# define png_alignof(type) (1)
-# endif
- /* Else leave png_alignof undefined to prevent use thereof */
+# if PNG_ALIGN_TYPE == PNG_ALIGN_ALWAYS
+# define png_alignof(type) 1
+# endif
+ /* Else leave png_alignof undefined to prevent use thereof */
# endif
#endif
-/* This implicitly assumes alignment is always to a power of 2. */
+/* This implicitly assumes alignment is always a multiple of 2. */
#ifdef png_alignof
-# define png_isaligned(ptr, type)\
- (((type)((const char*)ptr-(const char*)0) & \
- (type)(png_alignof(type)-1)) == 0)
+# define png_isaligned(ptr, type) \
+ (((type)(size_t)((const void*)(ptr)) & (type)(png_alignof(type)-1)) == 0)
#else
# define png_isaligned(ptr, type) 0
#endif
@@ -637,10 +628,6 @@
#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000U /* Have another chunk after IDAT */
/* 0x4000U (unused) */
#define PNG_IS_READ_STRUCT 0x8000U /* Else is a write struct */
-#ifdef PNG_APNG_SUPPORTED
-#define PNG_HAVE_acTL 0x10000U
-#define PNG_HAVE_fcTL 0x20000U
-#endif
/* Flags for the transformations the PNG library does on the image data */
#define PNG_BGR 0x0001U
@@ -877,16 +864,6 @@
#define png_tRNS PNG_U32(116, 82, 78, 83)
#define png_zTXt PNG_U32(122, 84, 88, 116)
-#ifdef PNG_APNG_SUPPORTED
-#define png_acTL PNG_U32( 97, 99, 84, 76)
-#define png_fcTL PNG_U32(102, 99, 84, 76)
-#define png_fdAT PNG_U32(102, 100, 65, 84)
-
-/* For png_struct.apng_flags: */
-#define PNG_FIRST_FRAME_HIDDEN 0x0001U
-#define PNG_APNG_APP 0x0002U
-#endif
-
/* The following will work on (signed char*) strings, whereas the get_uint_32
* macro will fail on top-bit-set values because of the sign extension.
*/
@@ -1658,47 +1635,6 @@ PNG_INTERNAL_FUNCTION(void,png_colorspace_sync,(png_const_structrp png_ptr,
*/
#endif
-#ifdef PNG_APNG_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_ensure_fcTL_is_valid,(png_structp png_ptr,
- png_uint_32 width, png_uint_32 height,
- png_uint_32 x_offset, png_uint_32 y_offset,
- png_uint_16 delay_num, png_uint_16 delay_den,
- png_byte dispose_op, png_byte blend_op), PNG_EMPTY);
-
-#ifdef PNG_READ_APNG_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_acTL,(png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_handle_fcTL,(png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_handle_fdAT,(png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_have_info,(png_structp png_ptr, png_infop info_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_ensure_sequence_number,(png_structp png_ptr,
- png_uint_32 length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_reset,(png_structp png_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_reinit,(png_structp png_ptr,
- png_infop info_ptr),PNG_EMPTY);
-#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_progressive_read_reset,(png_structp png_ptr),PNG_EMPTY);
-#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
-#endif /* PNG_READ_APNG_SUPPORTED */
-
-#ifdef PNG_WRITE_APNG_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_acTL,(png_structp png_ptr,
- png_uint_32 num_frames, png_uint_32 num_plays),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_write_fcTL,(png_structp png_ptr,
- png_uint_32 width, png_uint_32 height,
- png_uint_32 x_offset, png_uint_32 y_offset,
- png_uint_16 delay_num, png_uint_16 delay_den,
- png_byte dispose_op, png_byte blend_op),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_write_fdAT,(png_structp png_ptr,
- png_const_bytep data, png_size_t length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_write_reset,(png_structp png_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_write_reinit,(png_structp png_ptr,
- png_infop info_ptr, png_uint_32 width, png_uint_32 height),PNG_EMPTY);
-#endif /* PNG_WRITE_APNG_SUPPORTED */
-#endif /* PNG_APNG_SUPPORTED */
-
/* Added at libpng version 1.4.0 */
#ifdef PNG_COLORSPACE_SUPPORTED
/* These internal functions are for maintaining the colorspace structure within
diff --git a/thirdparty/libpng/pngread.c b/thirdparty/libpng/pngread.c
index fa44d5a8e4..5ab9224038 100644
--- a/thirdparty/libpng/pngread.c
+++ b/thirdparty/libpng/pngread.c
@@ -161,9 +161,6 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr)
else if (chunk_name == png_IDAT)
{
-#ifdef PNG_READ_APNG_SUPPORTED
- png_have_info(png_ptr, info_ptr);
-#endif
png_ptr->idat_size = length;
break;
}
@@ -258,17 +255,6 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr)
png_handle_iTXt(png_ptr, info_ptr, length);
#endif
-#ifdef PNG_READ_APNG_SUPPORTED
- else if (chunk_name == png_acTL)
- png_handle_acTL(png_ptr, info_ptr, length);
-
- else if (chunk_name == png_fcTL)
- png_handle_fcTL(png_ptr, info_ptr, length);
-
- else if (chunk_name == png_fdAT)
- png_handle_fdAT(png_ptr, info_ptr, length);
-#endif
-
else
png_handle_unknown(png_ptr, info_ptr, length,
PNG_HANDLE_CHUNK_AS_DEFAULT);
@@ -276,72 +262,6 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr)
}
#endif /* SEQUENTIAL_READ */
-#ifdef PNG_READ_APNG_SUPPORTED
-void PNGAPI
-png_read_frame_head(png_structp png_ptr, png_infop info_ptr)
-{
- png_byte have_chunk_after_DAT; /* after IDAT or after fdAT */
-
- png_debug(0, "Reading frame head");
-
- if (!(png_ptr->mode & PNG_HAVE_acTL))
- png_error(png_ptr, "attempt to png_read_frame_head() but "
- "no acTL present");
-
- /* do nothing for the main IDAT */
- if (png_ptr->num_frames_read == 0)
- return;
-
- png_read_reset(png_ptr);
- png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
- png_ptr->mode &= ~PNG_HAVE_fcTL;
-
- have_chunk_after_DAT = 0;
- for (;;)
- {
- png_uint_32 length = png_read_chunk_header(png_ptr);
-
- if (png_ptr->chunk_name == png_IDAT)
- {
- /* discard trailing IDATs for the first frame */
- if (have_chunk_after_DAT || png_ptr->num_frames_read > 1)
- png_error(png_ptr, "png_read_frame_head(): out of place IDAT");
- png_crc_finish(png_ptr, length);
- }
-
- else if (png_ptr->chunk_name == png_fcTL)
- {
- png_handle_fcTL(png_ptr, info_ptr, length);
- have_chunk_after_DAT = 1;
- }
-
- else if (png_ptr->chunk_name == png_fdAT)
- {
- png_ensure_sequence_number(png_ptr, length);
-
- /* discard trailing fdATs for frames other than the first */
- if (!have_chunk_after_DAT && png_ptr->num_frames_read > 1)
- png_crc_finish(png_ptr, length - 4);
- else if(png_ptr->mode & PNG_HAVE_fcTL)
- {
- png_ptr->idat_size = length - 4;
- png_ptr->mode |= PNG_HAVE_IDAT;
-
- break;
- }
- else
- png_error(png_ptr, "png_read_frame_head(): out of place fdAT");
- }
- else
- {
- png_warning(png_ptr, "Skipped (ignored) a chunk "
- "between APNG chunks");
- png_crc_finish(png_ptr, length);
- }
- }
-}
-#endif /* PNG_READ_APNG_SUPPORTED */
-
/* Optional call to update the users info_ptr structure */
void PNGAPI
png_read_update_info(png_structrp png_ptr, png_inforp info_ptr)
@@ -3532,7 +3452,6 @@ png_image_read_background(png_voidp argument)
for (pass = 0; pass < passes; ++pass)
{
- png_bytep row = png_voidcast(png_bytep, display->first_row);
unsigned int startx, stepx, stepy;
png_uint_32 y;
@@ -3637,8 +3556,6 @@ png_image_read_background(png_voidp argument)
inrow += 2; /* gray and alpha channel */
}
-
- row += display->row_bytes;
}
}
}
diff --git a/thirdparty/libpng/pngrtran.c b/thirdparty/libpng/pngrtran.c
index 9a8fad9f4a..238f5afe7e 100644
--- a/thirdparty/libpng/pngrtran.c
+++ b/thirdparty/libpng/pngrtran.c
@@ -21,7 +21,7 @@
#ifdef PNG_ARM_NEON_IMPLEMENTATION
# if PNG_ARM_NEON_IMPLEMENTATION == 1
# define PNG_ARM_NEON_INTRINSICS_AVAILABLE
-# if defined(_MSC_VER) && defined(_M_ARM64)
+# if defined(_MSC_VER) && !defined(__clang__) && defined(_M_ARM64)
# include <arm64_neon.h>
# else
# include <arm_neon.h>
diff --git a/thirdparty/libpng/pngrutil.c b/thirdparty/libpng/pngrutil.c
index ae66a48a83..ca060dd15f 100644
--- a/thirdparty/libpng/pngrutil.c
+++ b/thirdparty/libpng/pngrutil.c
@@ -1,7 +1,7 @@
/* pngrutil.c - utilities to read a PNG file
*
- * Copyright (c) 2018 Cosmin Truta
+ * Copyright (c) 2018-2022 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -302,7 +302,6 @@ png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn)
if (buffer != NULL && new_size > png_ptr->read_buffer_size)
{
png_ptr->read_buffer = NULL;
- png_ptr->read_buffer = NULL;
png_ptr->read_buffer_size = 0;
png_free(png_ptr, buffer);
buffer = NULL;
@@ -865,11 +864,6 @@ png_handle_IHDR(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
filter_type = buf[11];
interlace_type = buf[12];
-#ifdef PNG_READ_APNG_SUPPORTED
- png_ptr->first_frame_width = width;
- png_ptr->first_frame_height = height;
-#endif
-
/* Set internal variables */
png_ptr->width = width;
png_ptr->height = height;
@@ -2081,21 +2075,22 @@ png_handle_eXIf(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
png_byte buf[1];
png_crc_read(png_ptr, buf, 1);
info_ptr->eXIf_buf[i] = buf[0];
- if (i == 1 && buf[0] != 'M' && buf[0] != 'I'
- && info_ptr->eXIf_buf[0] != buf[0])
+ if (i == 1)
{
- png_crc_finish(png_ptr, length);
- png_chunk_benign_error(png_ptr, "incorrect byte-order specifier");
- png_free(png_ptr, info_ptr->eXIf_buf);
- info_ptr->eXIf_buf = NULL;
- return;
+ if ((buf[0] != 'M' && buf[0] != 'I') ||
+ (info_ptr->eXIf_buf[0] != buf[0]))
+ {
+ png_crc_finish(png_ptr, length - 2);
+ png_chunk_benign_error(png_ptr, "incorrect byte-order specifier");
+ png_free(png_ptr, info_ptr->eXIf_buf);
+ info_ptr->eXIf_buf = NULL;
+ return;
+ }
}
}
- if (png_crc_finish(png_ptr, 0) != 0)
- return;
-
- png_set_eXIf_1(png_ptr, info_ptr, length, info_ptr->eXIf_buf);
+ if (png_crc_finish(png_ptr, 0) == 0)
+ png_set_eXIf_1(png_ptr, info_ptr, length, info_ptr->eXIf_buf);
png_free(png_ptr, info_ptr->eXIf_buf);
info_ptr->eXIf_buf = NULL;
@@ -2131,8 +2126,9 @@ png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
num = length / 2 ;
- if (num != (unsigned int) png_ptr->num_palette ||
- num > (unsigned int) PNG_MAX_PALETTE_LENGTH)
+ if (length != num * 2 ||
+ num != (unsigned int)png_ptr->num_palette ||
+ num > (unsigned int)PNG_MAX_PALETTE_LENGTH)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "invalid");
@@ -2862,179 +2858,6 @@ png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
}
#endif
-#ifdef PNG_READ_APNG_SUPPORTED
-void /* PRIVATE */
-png_handle_acTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
-{
- png_byte data[8];
- png_uint_32 num_frames;
- png_uint_32 num_plays;
- png_uint_32 didSet;
-
- png_debug(1, "in png_handle_acTL");
-
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- {
- png_error(png_ptr, "Missing IHDR before acTL");
- }
- else if (png_ptr->mode & PNG_HAVE_IDAT)
- {
- png_warning(png_ptr, "Invalid acTL after IDAT skipped");
- png_crc_finish(png_ptr, length);
- return;
- }
- else if (png_ptr->mode & PNG_HAVE_acTL)
- {
- png_warning(png_ptr, "Duplicate acTL skipped");
- png_crc_finish(png_ptr, length);
- return;
- }
- else if (length != 8)
- {
- png_warning(png_ptr, "acTL with invalid length skipped");
- png_crc_finish(png_ptr, length);
- return;
- }
-
- png_crc_read(png_ptr, data, 8);
- png_crc_finish(png_ptr, 0);
-
- num_frames = png_get_uint_31(png_ptr, data);
- num_plays = png_get_uint_31(png_ptr, data + 4);
-
- /* the set function will do error checking on num_frames */
- didSet = png_set_acTL(png_ptr, info_ptr, num_frames, num_plays);
- if(didSet)
- png_ptr->mode |= PNG_HAVE_acTL;
-}
-
-void /* PRIVATE */
-png_handle_fcTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
-{
- png_byte data[22];
- png_uint_32 width;
- png_uint_32 height;
- png_uint_32 x_offset;
- png_uint_32 y_offset;
- png_uint_16 delay_num;
- png_uint_16 delay_den;
- png_byte dispose_op;
- png_byte blend_op;
-
- png_debug(1, "in png_handle_fcTL");
-
- png_ensure_sequence_number(png_ptr, length);
-
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- {
- png_error(png_ptr, "Missing IHDR before fcTL");
- }
- else if (png_ptr->mode & PNG_HAVE_IDAT)
- {
- /* for any frames other then the first this message may be misleading,
- * but correct. PNG_HAVE_IDAT is unset before the frame head is read
- * i can't think of a better message */
- png_warning(png_ptr, "Invalid fcTL after IDAT skipped");
- png_crc_finish(png_ptr, length-4);
- return;
- }
- else if (png_ptr->mode & PNG_HAVE_fcTL)
- {
- png_warning(png_ptr, "Duplicate fcTL within one frame skipped");
- png_crc_finish(png_ptr, length-4);
- return;
- }
- else if (length != 26)
- {
- png_warning(png_ptr, "fcTL with invalid length skipped");
- png_crc_finish(png_ptr, length-4);
- return;
- }
-
- png_crc_read(png_ptr, data, 22);
- png_crc_finish(png_ptr, 0);
-
- width = png_get_uint_31(png_ptr, data);
- height = png_get_uint_31(png_ptr, data + 4);
- x_offset = png_get_uint_31(png_ptr, data + 8);
- y_offset = png_get_uint_31(png_ptr, data + 12);
- delay_num = png_get_uint_16(data + 16);
- delay_den = png_get_uint_16(data + 18);
- dispose_op = data[20];
- blend_op = data[21];
-
- if (png_ptr->num_frames_read == 0 && (x_offset != 0 || y_offset != 0))
- {
- png_warning(png_ptr, "fcTL for the first frame must have zero offset");
- return;
- }
-
- if (info_ptr != NULL)
- {
- if (png_ptr->num_frames_read == 0 &&
- (width != info_ptr->width || height != info_ptr->height))
- {
- png_warning(png_ptr, "size in first frame's fcTL must match "
- "the size in IHDR");
- return;
- }
-
- /* The set function will do more error checking */
- png_set_next_frame_fcTL(png_ptr, info_ptr, width, height,
- x_offset, y_offset, delay_num, delay_den,
- dispose_op, blend_op);
-
- png_read_reinit(png_ptr, info_ptr);
-
- png_ptr->mode |= PNG_HAVE_fcTL;
- }
-}
-
-void /* PRIVATE */
-png_have_info(png_structp png_ptr, png_infop info_ptr)
-{
- if((info_ptr->valid & PNG_INFO_acTL) && !(info_ptr->valid & PNG_INFO_fcTL))
- {
- png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN;
- info_ptr->num_frames++;
- }
-}
-
-void /* PRIVATE */
-png_handle_fdAT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
-{
- png_ensure_sequence_number(png_ptr, length);
-
- /* This function is only called from png_read_end(), png_read_info(),
- * and png_push_read_chunk() which means that:
- * - the user doesn't want to read this frame
- * - or this is an out-of-place fdAT
- * in either case it is safe to ignore the chunk with a warning */
- png_warning(png_ptr, "ignoring fdAT chunk");
- png_crc_finish(png_ptr, length - 4);
- PNG_UNUSED(info_ptr)
-}
-
-void /* PRIVATE */
-png_ensure_sequence_number(png_structp png_ptr, png_uint_32 length)
-{
- png_byte data[4];
- png_uint_32 sequence_number;
-
- if (length < 4)
- png_error(png_ptr, "invalid fcTL or fdAT chunk found");
-
- png_crc_read(png_ptr, data, 4);
- sequence_number = png_get_uint_31(png_ptr, data);
-
- if (sequence_number != png_ptr->next_seq_num)
- png_error(png_ptr, "fcTL or fdAT chunk with out-of-order sequence "
- "number found");
-
- png_ptr->next_seq_num++;
-}
-#endif /* PNG_READ_APNG_SUPPORTED */
-
#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
/* Utility function for png_handle_unknown; set up png_ptr::unknown_chunk */
static int
@@ -4343,38 +4166,7 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output,
{
uInt avail_in;
png_bytep buffer;
-#ifdef PNG_READ_APNG_SUPPORTED
- png_uint_32 bytes_to_skip = 0;
-
- while (png_ptr->idat_size == 0 || bytes_to_skip != 0)
- {
- png_crc_finish(png_ptr, bytes_to_skip);
- bytes_to_skip = 0;
-
- png_ptr->idat_size = png_read_chunk_header(png_ptr);
- if (png_ptr->num_frames_read == 0)
- {
- if (png_ptr->chunk_name != png_IDAT)
- png_error(png_ptr, "Not enough image data");
- }
- else
- {
- if (png_ptr->chunk_name == png_IEND)
- png_error(png_ptr, "Not enough image data");
- if (png_ptr->chunk_name != png_fdAT)
- {
- png_warning(png_ptr, "Skipped (ignored) a chunk "
- "between APNG chunks");
- bytes_to_skip = png_ptr->idat_size;
- continue;
- }
-
- png_ensure_sequence_number(png_ptr, png_ptr->idat_size);
- png_ptr->idat_size -= 4;
- }
- }
-#else
while (png_ptr->idat_size == 0)
{
png_crc_finish(png_ptr, 0);
@@ -4386,7 +4178,7 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output,
if (png_ptr->chunk_name != png_IDAT)
png_error(png_ptr, "Not enough image data");
}
-#endif /* PNG_READ_APNG_SUPPORTED */
+
avail_in = png_ptr->IDAT_read_size;
if (avail_in > png_ptr->idat_size)
@@ -4449,9 +4241,6 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output,
png_ptr->mode |= PNG_AFTER_IDAT;
png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
-#ifdef PNG_READ_APNG_SUPPORTED
- png_ptr->num_frames_read++;
-#endif
if (png_ptr->zstream.avail_in > 0 || png_ptr->idat_size > 0)
png_chunk_benign_error(png_ptr, "Extra compressed data");
@@ -4833,14 +4622,13 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
*/
{
png_bytep temp = png_ptr->big_row_buf + 32;
- int extra = (int)((temp - (png_bytep)0) & 0x0f);
+ size_t extra = (size_t)temp & 0x0f;
png_ptr->row_buf = temp - extra - 1/*filter byte*/;
temp = png_ptr->big_prev_row + 32;
- extra = (int)((temp - (png_bytep)0) & 0x0f);
+ extra = (size_t)temp & 0x0f;
png_ptr->prev_row = temp - extra - 1/*filter byte*/;
}
-
#else
/* Use 31 bytes of padding before and 17 bytes after row_buf. */
png_ptr->row_buf = png_ptr->big_row_buf + 31;
@@ -4890,80 +4678,4 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
png_ptr->flags |= PNG_FLAG_ROW_INIT;
}
-
-#ifdef PNG_READ_APNG_SUPPORTED
-/* This function is to be called after the main IDAT set has been read and
- * before a new IDAT is read. It resets some parts of png_ptr
- * to make them usable by the read functions again */
-void /* PRIVATE */
-png_read_reset(png_structp png_ptr)
-{
- png_ptr->mode &= ~PNG_HAVE_IDAT;
- png_ptr->mode &= ~PNG_AFTER_IDAT;
- png_ptr->row_number = 0;
- png_ptr->pass = 0;
-}
-
-void /* PRIVATE */
-png_read_reinit(png_structp png_ptr, png_infop info_ptr)
-{
- png_ptr->width = info_ptr->next_frame_width;
- png_ptr->height = info_ptr->next_frame_height;
- png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width);
- png_ptr->info_rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,
- png_ptr->width);
- if (png_ptr->prev_row)
- memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
-}
-
-#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-/* same as png_read_reset() but for the progressive reader */
-void /* PRIVATE */
-png_progressive_read_reset(png_structp png_ptr)
-{
-#ifdef PNG_READ_INTERLACING_SUPPORTED
- /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
-
- /* Start of interlace block */
- const int png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
-
- /* Offset to next interlace block */
- const int png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
-
- /* Start of interlace block in the y direction */
- const int png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
-
- /* Offset to next interlace block in the y direction */
- const int png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
-
- if (png_ptr->interlaced)
- {
- if (!(png_ptr->transformations & PNG_INTERLACE))
- png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
- png_pass_ystart[0]) / png_pass_yinc[0];
- else
- png_ptr->num_rows = png_ptr->height;
-
- png_ptr->iwidth = (png_ptr->width +
- png_pass_inc[png_ptr->pass] - 1 -
- png_pass_start[png_ptr->pass]) /
- png_pass_inc[png_ptr->pass];
- }
- else
-#endif /* PNG_READ_INTERLACING_SUPPORTED */
- {
- png_ptr->num_rows = png_ptr->height;
- png_ptr->iwidth = png_ptr->width;
- }
- png_ptr->flags &= ~PNG_FLAG_ZSTREAM_ENDED;
- if (inflateReset(&(png_ptr->zstream)) != Z_OK)
- png_error(png_ptr, "inflateReset failed");
- png_ptr->zstream.avail_in = 0;
- png_ptr->zstream.next_in = 0;
- png_ptr->zstream.next_out = png_ptr->row_buf;
- png_ptr->zstream.avail_out = (uInt)PNG_ROWBYTES(png_ptr->pixel_depth,
- png_ptr->iwidth) + 1;
-}
-#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
-#endif /* PNG_READ_APNG_SUPPORTED */
#endif /* READ */
diff --git a/thirdparty/libpng/pngset.c b/thirdparty/libpng/pngset.c
index a281db58ae..8c372cf415 100644
--- a/thirdparty/libpng/pngset.c
+++ b/thirdparty/libpng/pngset.c
@@ -1,7 +1,7 @@
/* pngset.c - storage of image information into info struct
*
- * Copyright (c) 2018 Cosmin Truta
+ * Copyright (c) 2018-2022 Cosmin Truta
* Copyright (c) 1998-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -288,11 +288,6 @@ png_set_IHDR(png_const_structrp png_ptr, png_inforp info_ptr,
info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);
info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
-
-#ifdef PNG_APNG_SUPPORTED
- /* for non-animated png. this may be overwritten from an acTL chunk later */
- info_ptr->num_frames = 1;
-#endif
}
#ifdef PNG_oFFs_SUPPORTED
@@ -1024,6 +1019,9 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
info_ptr->trans_alpha = png_voidcast(png_bytep,
png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
memcpy(info_ptr->trans_alpha, trans_alpha, (size_t)num_trans);
+
+ info_ptr->valid |= PNG_INFO_tRNS;
+ info_ptr->free_me |= PNG_FREE_TRNS;
}
png_ptr->trans_alpha = info_ptr->trans_alpha;
}
@@ -1163,147 +1161,6 @@ png_set_sPLT(png_const_structrp png_ptr,
}
#endif /* sPLT */
-#ifdef PNG_APNG_SUPPORTED
-png_uint_32 PNGAPI
-png_set_acTL(png_structp png_ptr, png_infop info_ptr,
- png_uint_32 num_frames, png_uint_32 num_plays)
-{
- png_debug1(1, "in %s storage function", "acTL");
-
- if (png_ptr == NULL || info_ptr == NULL)
- {
- png_warning(png_ptr,
- "Call to png_set_acTL() with NULL png_ptr "
- "or info_ptr ignored");
- return (0);
- }
- if (num_frames == 0)
- {
- png_warning(png_ptr,
- "Ignoring attempt to set acTL with num_frames zero");
- return (0);
- }
- if (num_frames > PNG_UINT_31_MAX)
- {
- png_warning(png_ptr,
- "Ignoring attempt to set acTL with num_frames > 2^31-1");
- return (0);
- }
- if (num_plays > PNG_UINT_31_MAX)
- {
- png_warning(png_ptr,
- "Ignoring attempt to set acTL with num_plays "
- "> 2^31-1");
- return (0);
- }
-
- info_ptr->num_frames = num_frames;
- info_ptr->num_plays = num_plays;
-
- info_ptr->valid |= PNG_INFO_acTL;
-
- return (1);
-}
-
-/* delay_num and delay_den can hold any 16-bit values including zero */
-png_uint_32 PNGAPI
-png_set_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr,
- png_uint_32 width, png_uint_32 height,
- png_uint_32 x_offset, png_uint_32 y_offset,
- png_uint_16 delay_num, png_uint_16 delay_den,
- png_byte dispose_op, png_byte blend_op)
-{
- png_debug1(1, "in %s storage function", "fcTL");
-
- if (png_ptr == NULL || info_ptr == NULL)
- {
- png_warning(png_ptr,
- "Call to png_set_fcTL() with NULL png_ptr or info_ptr "
- "ignored");
- return (0);
- }
-
- png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset,
- delay_num, delay_den, dispose_op, blend_op);
-
- if (blend_op == PNG_BLEND_OP_OVER)
- {
- if (!(png_ptr->color_type & PNG_COLOR_MASK_ALPHA) &&
- !(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
- {
- png_warning(png_ptr, "PNG_BLEND_OP_OVER is meaningless "
- "and wasteful for opaque images, ignored");
- blend_op = PNG_BLEND_OP_SOURCE;
- }
- }
-
- info_ptr->next_frame_width = width;
- info_ptr->next_frame_height = height;
- info_ptr->next_frame_x_offset = x_offset;
- info_ptr->next_frame_y_offset = y_offset;
- info_ptr->next_frame_delay_num = delay_num;
- info_ptr->next_frame_delay_den = delay_den;
- info_ptr->next_frame_dispose_op = dispose_op;
- info_ptr->next_frame_blend_op = blend_op;
-
- info_ptr->valid |= PNG_INFO_fcTL;
-
- return (1);
-}
-
-void /* PRIVATE */
-png_ensure_fcTL_is_valid(png_structp png_ptr,
- png_uint_32 width, png_uint_32 height,
- png_uint_32 x_offset, png_uint_32 y_offset,
- png_uint_16 delay_num, png_uint_16 delay_den,
- png_byte dispose_op, png_byte blend_op)
-{
- if (width == 0 || width > PNG_UINT_31_MAX)
- png_error(png_ptr, "invalid width in fcTL (> 2^31-1)");
- if (height == 0 || height > PNG_UINT_31_MAX)
- png_error(png_ptr, "invalid height in fcTL (> 2^31-1)");
- if (x_offset > PNG_UINT_31_MAX)
- png_error(png_ptr, "invalid x_offset in fcTL (> 2^31-1)");
- if (y_offset > PNG_UINT_31_MAX)
- png_error(png_ptr, "invalid y_offset in fcTL (> 2^31-1)");
- if (width + x_offset > png_ptr->first_frame_width ||
- height + y_offset > png_ptr->first_frame_height)
- png_error(png_ptr, "dimensions of a frame are greater than"
- "the ones in IHDR");
-
- if (dispose_op != PNG_DISPOSE_OP_NONE &&
- dispose_op != PNG_DISPOSE_OP_BACKGROUND &&
- dispose_op != PNG_DISPOSE_OP_PREVIOUS)
- png_error(png_ptr, "invalid dispose_op in fcTL");
-
- if (blend_op != PNG_BLEND_OP_SOURCE &&
- blend_op != PNG_BLEND_OP_OVER)
- png_error(png_ptr, "invalid blend_op in fcTL");
-
- PNG_UNUSED(delay_num)
- PNG_UNUSED(delay_den)
-}
-
-png_uint_32 PNGAPI
-png_set_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr,
- png_byte is_hidden)
-{
- png_debug(1, "in png_first_frame_is_hidden()");
-
- if (png_ptr == NULL)
- return 0;
-
- if (is_hidden)
- png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN;
- else
- png_ptr->apng_flags &= ~PNG_FIRST_FRAME_HIDDEN;
-
- PNG_UNUSED(info_ptr)
-
- return 1;
-}
-#endif /* PNG_APNG_SUPPORTED */
-
#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
static png_byte
check_location(png_const_structrp png_ptr, int location)
@@ -1472,7 +1329,7 @@ png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr,
#ifdef PNG_MNG_FEATURES_SUPPORTED
png_uint_32 PNGAPI
-png_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features)
+png_permit_mng_features(png_structrp png_ptr, png_uint_32 mng_features)
{
png_debug(1, "in png_permit_mng_features");
@@ -1779,7 +1636,7 @@ png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask)
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
/* This function was added to libpng 1.2.6 */
void PNGAPI
-png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max,
+png_set_user_limits(png_structrp png_ptr, png_uint_32 user_width_max,
png_uint_32 user_height_max)
{
/* Images with dimensions larger than these limits will be
@@ -1795,7 +1652,7 @@ png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max,
/* This function was added to libpng 1.4.0 */
void PNGAPI
-png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
+png_set_chunk_cache_max(png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
{
if (png_ptr != NULL)
png_ptr->user_chunk_cache_max = user_chunk_cache_max;
@@ -1803,7 +1660,7 @@ png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
/* This function was added to libpng 1.4.1 */
void PNGAPI
-png_set_chunk_malloc_max (png_structrp png_ptr,
+png_set_chunk_malloc_max(png_structrp png_ptr,
png_alloc_size_t user_chunk_malloc_max)
{
if (png_ptr != NULL)
diff --git a/thirdparty/libpng/pngstruct.h b/thirdparty/libpng/pngstruct.h
index 2a2236f92e..e591d94d58 100644
--- a/thirdparty/libpng/pngstruct.h
+++ b/thirdparty/libpng/pngstruct.h
@@ -1,7 +1,7 @@
/* pngstruct.h - header file for PNG reference library
*
- * Copyright (c) 2018-2019 Cosmin Truta
+ * Copyright (c) 2018-2022 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -334,18 +334,8 @@ struct png_struct_def
size_t current_buffer_size; /* amount of data now in current_buffer */
int process_mode; /* what push library is currently doing */
int cur_palette; /* current push library palette index */
-
#endif /* PROGRESSIVE_READ */
-#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
-/* For the Borland special 64K segment handler */
- png_bytepp offset_table_ptr;
- png_bytep offset_table;
- png_uint_16 offset_table_number;
- png_uint_16 offset_table_count;
- png_uint_16 offset_table_count_free;
-#endif
-
#ifdef PNG_READ_QUANTIZE_SUPPORTED
png_bytep palette_lookup; /* lookup table for quantizing */
png_bytep quantize_index; /* index translation for palette files */
@@ -409,27 +399,6 @@ struct png_struct_def
png_byte filter_type;
#endif
-#ifdef PNG_APNG_SUPPORTED
- png_uint_32 apng_flags;
- png_uint_32 next_seq_num; /* next fcTL/fdAT chunk sequence number */
- png_uint_32 first_frame_width;
- png_uint_32 first_frame_height;
-
-#ifdef PNG_READ_APNG_SUPPORTED
- png_uint_32 num_frames_read; /* incremented after all image data of */
- /* a frame is read */
-#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
- png_progressive_frame_ptr frame_info_fn; /* frame info read callback */
- png_progressive_frame_ptr frame_end_fn; /* frame data read callback */
-#endif
-#endif
-
-#ifdef PNG_WRITE_APNG_SUPPORTED
- png_uint_32 num_frames_to_write;
- png_uint_32 num_frames_written;
-#endif
-#endif /* PNG_APNG_SUPPORTED */
-
/* New members added in libpng-1.2.0 */
/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */
diff --git a/thirdparty/libpng/pngwrite.c b/thirdparty/libpng/pngwrite.c
index 5e68032378..06c45d16ab 100644
--- a/thirdparty/libpng/pngwrite.c
+++ b/thirdparty/libpng/pngwrite.c
@@ -1,7 +1,7 @@
/* pngwrite.c - general routines to write a PNG file
*
- * Copyright (c) 2018-2019 Cosmin Truta
+ * Copyright (c) 2018-2022 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -128,10 +128,6 @@ png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr)
* the application continues writing the PNG. So check the 'invalid'
* flag here too.
*/
-#ifdef PNG_WRITE_APNG_SUPPORTED
- if (info_ptr->valid & PNG_INFO_acTL)
- png_write_acTL(png_ptr, info_ptr->num_frames, info_ptr->num_plays);
-#endif
#ifdef PNG_GAMMA_SUPPORTED
# ifdef PNG_WRITE_gAMA_SUPPORTED
if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
@@ -374,11 +370,6 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
png_benign_error(png_ptr, "Wrote palette index exceeding num_palette");
#endif
-#ifdef PNG_WRITE_APNG_SUPPORTED
- if (png_ptr->num_frames_written != png_ptr->num_frames_to_write)
- png_error(png_ptr, "Not enough frames written");
-#endif
-
/* See if user wants us to write information chunks */
if (info_ptr != NULL)
{
@@ -498,6 +489,16 @@ png_convert_from_time_t(png_timep ptime, time_t ttime)
png_debug(1, "in png_convert_from_time_t");
tbuf = gmtime(&ttime);
+ if (tbuf == NULL)
+ {
+ /* TODO: add a safe function which takes a png_ptr argument and raises
+ * a png_error if the ttime argument is invalid and the call to gmtime
+ * fails as a consequence.
+ */
+ memset(ptime, 0, sizeof(*ptime));
+ return;
+ }
+
png_convert_from_struct_tm(ptime, tbuf);
}
#endif
@@ -1470,43 +1471,6 @@ png_write_png(png_structrp png_ptr, png_inforp info_ptr,
}
#endif
-#ifdef PNG_WRITE_APNG_SUPPORTED
-void PNGAPI
-png_write_frame_head(png_structp png_ptr, png_infop info_ptr,
- png_bytepp row_pointers, png_uint_32 width, png_uint_32 height,
- png_uint_32 x_offset, png_uint_32 y_offset,
- png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
- png_byte blend_op)
-{
- png_debug(1, "in png_write_frame_head");
-
- /* there is a chance this has been set after png_write_info was called,
- * so it would be set but not written. is there a way to be sure? */
- if (!(info_ptr->valid & PNG_INFO_acTL))
- png_error(png_ptr, "png_write_frame_head(): acTL not set");
-
- png_write_reset(png_ptr);
-
- png_write_reinit(png_ptr, info_ptr, width, height);
-
- if ( !(png_ptr->num_frames_written == 0 &&
- (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) ) )
- png_write_fcTL(png_ptr, width, height, x_offset, y_offset,
- delay_num, delay_den, dispose_op, blend_op);
-
- PNG_UNUSED(row_pointers)
-}
-
-void PNGAPI
-png_write_frame_tail(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_write_frame_tail");
-
- png_ptr->num_frames_written++;
-
- PNG_UNUSED(info_ptr)
-}
-#endif /* PNG_WRITE_APNG_SUPPORTED */
#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
/* Initialize the write structure - general purpose utility. */
diff --git a/thirdparty/libpng/pngwutil.c b/thirdparty/libpng/pngwutil.c
index b4809cda6b..16345e4c0b 100644
--- a/thirdparty/libpng/pngwutil.c
+++ b/thirdparty/libpng/pngwutil.c
@@ -821,11 +821,6 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
/* Write the chunk */
png_write_complete_chunk(png_ptr, png_IHDR, buf, 13);
-#ifdef PNG_WRITE_APNG_SUPPORTED
- png_ptr->first_frame_width = width;
- png_ptr->first_frame_height = height;
-#endif
-
if ((png_ptr->do_filter) == PNG_NO_FILTERS)
{
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
@@ -1007,17 +1002,8 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
optimize_cmf(data, png_image_size(png_ptr));
#endif
- if (size > 0)
-#ifdef PNG_WRITE_APNG_SUPPORTED
- {
- if (png_ptr->num_frames_written == 0)
-#endif
- png_write_complete_chunk(png_ptr, png_IDAT, data, size);
-#ifdef PNG_WRITE_APNG_SUPPORTED
- else
- png_write_fdAT(png_ptr, data, size);
- }
-#endif /* PNG_WRITE_APNG_SUPPORTED */
+ if (size > 0)
+ png_write_complete_chunk(png_ptr, png_IDAT, data, size);
png_ptr->mode |= PNG_HAVE_IDAT;
png_ptr->zstream.next_out = data;
@@ -1064,17 +1050,7 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
#endif
if (size > 0)
-#ifdef PNG_WRITE_APNG_SUPPORTED
- {
- if (png_ptr->num_frames_written == 0)
-#endif
png_write_complete_chunk(png_ptr, png_IDAT, data, size);
-#ifdef PNG_WRITE_APNG_SUPPORTED
- else
- png_write_fdAT(png_ptr, data, size);
- }
-#endif /* PNG_WRITE_APNG_SUPPORTED */
-
png_ptr->zstream.avail_out = 0;
png_ptr->zstream.next_out = NULL;
png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT;
@@ -1909,82 +1885,6 @@ png_write_tIME(png_structrp png_ptr, png_const_timep mod_time)
}
#endif
-#ifdef PNG_WRITE_APNG_SUPPORTED
-void /* PRIVATE */
-png_write_acTL(png_structp png_ptr,
- png_uint_32 num_frames, png_uint_32 num_plays)
-{
- png_byte buf[8];
-
- png_debug(1, "in png_write_acTL");
-
- png_ptr->num_frames_to_write = num_frames;
-
- if (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN)
- num_frames--;
-
- png_save_uint_32(buf, num_frames);
- png_save_uint_32(buf + 4, num_plays);
-
- png_write_complete_chunk(png_ptr, png_acTL, buf, (png_size_t)8);
-}
-
-void /* PRIVATE */
-png_write_fcTL(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
- png_uint_32 x_offset, png_uint_32 y_offset,
- png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
- png_byte blend_op)
-{
- png_byte buf[26];
-
- png_debug(1, "in png_write_fcTL");
-
- if (png_ptr->num_frames_written == 0 && (x_offset != 0 || y_offset != 0))
- png_error(png_ptr, "x and/or y offset for the first frame aren't 0");
- if (png_ptr->num_frames_written == 0 &&
- (width != png_ptr->first_frame_width ||
- height != png_ptr->first_frame_height))
- png_error(png_ptr, "width and/or height in the first frame's fcTL "
- "don't match the ones in IHDR");
-
- /* more error checking */
- png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset,
- delay_num, delay_den, dispose_op, blend_op);
-
- png_save_uint_32(buf, png_ptr->next_seq_num);
- png_save_uint_32(buf + 4, width);
- png_save_uint_32(buf + 8, height);
- png_save_uint_32(buf + 12, x_offset);
- png_save_uint_32(buf + 16, y_offset);
- png_save_uint_16(buf + 20, delay_num);
- png_save_uint_16(buf + 22, delay_den);
- buf[24] = dispose_op;
- buf[25] = blend_op;
-
- png_write_complete_chunk(png_ptr, png_fcTL, buf, (png_size_t)26);
-
- png_ptr->next_seq_num++;
-}
-
-void /* PRIVATE */
-png_write_fdAT(png_structp png_ptr,
- png_const_bytep data, png_size_t length)
-{
- png_byte buf[4];
-
- png_write_chunk_header(png_ptr, png_fdAT, (png_uint_32)(4 + length));
-
- png_save_uint_32(buf, png_ptr->next_seq_num);
- png_write_chunk_data(png_ptr, buf, 4);
-
- png_write_chunk_data(png_ptr, data, length);
-
- png_write_chunk_end(png_ptr);
-
- png_ptr->next_seq_num++;
-}
-#endif /* PNG_WRITE_APNG_SUPPORTED */
-
/* Initializes the row writing capability of libpng */
void /* PRIVATE */
png_write_start_row(png_structrp png_ptr)
@@ -2878,39 +2778,4 @@ png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
}
#endif /* WRITE_FLUSH */
}
-
-#ifdef PNG_WRITE_APNG_SUPPORTED
-void /* PRIVATE */
-png_write_reset(png_structp png_ptr)
-{
- png_ptr->row_number = 0;
- png_ptr->pass = 0;
- png_ptr->mode &= ~PNG_HAVE_IDAT;
-}
-
-void /* PRIVATE */
-png_write_reinit(png_structp png_ptr, png_infop info_ptr,
- png_uint_32 width, png_uint_32 height)
-{
- if (png_ptr->num_frames_written == 0 &&
- (width != png_ptr->first_frame_width ||
- height != png_ptr->first_frame_height))
- png_error(png_ptr, "width and/or height in the first frame's fcTL "
- "don't match the ones in IHDR");
- if (width > png_ptr->first_frame_width ||
- height > png_ptr->first_frame_height)
- png_error(png_ptr, "width and/or height for a frame greater than"
- "the ones in IHDR");
-
- png_set_IHDR(png_ptr, info_ptr, width, height,
- info_ptr->bit_depth, info_ptr->color_type,
- info_ptr->interlace_type, info_ptr->compression_type,
- info_ptr->filter_type);
-
- png_ptr->width = width;
- png_ptr->height = height;
- png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
- png_ptr->usr_width = png_ptr->width;
-}
-#endif /* PNG_WRITE_APNG_SUPPORTED */
#endif /* WRITE */