summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/io/file_access.cpp111
-rw-r--r--core/io/file_access.h8
-rw-r--r--core/io/file_access_compressed.cpp39
-rw-r--r--core/io/file_access_compressed.h3
-rw-r--r--core/io/file_access_encrypted.cpp42
-rw-r--r--core/io/file_access_encrypted.h2
-rw-r--r--core/io/file_access_memory.cpp18
-rw-r--r--core/io/file_access_memory.h3
-rw-r--r--core/io/file_access_pack.cpp15
-rw-r--r--core/io/file_access_pack.h4
-rw-r--r--core/io/file_access_zip.cpp8
-rw-r--r--core/io/file_access_zip.h3
-rw-r--r--doc/classes/AnimationMixer.xml14
-rw-r--r--doc/classes/EditorResourcePreviewGenerator.xml4
-rw-r--r--doc/classes/RenderingServer.xml8
-rw-r--r--drivers/gles3/storage/texture_storage.cpp22
-rw-r--r--drivers/unix/file_access_unix.cpp93
-rw-r--r--drivers/unix/file_access_unix.h8
-rw-r--r--drivers/unix/file_access_unix_pipe.cpp25
-rw-r--r--drivers/unix/file_access_unix_pipe.h2
-rw-r--r--drivers/vulkan/rendering_device_driver_vulkan.cpp11
-rw-r--r--drivers/windows/file_access_windows.cpp165
-rw-r--r--drivers/windows/file_access_windows.h8
-rw-r--r--drivers/windows/file_access_windows_pipe.cpp24
-rw-r--r--drivers/windows/file_access_windows_pipe.h2
-rw-r--r--editor/animation_track_editor.cpp4
-rw-r--r--editor/animation_track_editor.h1
-rw-r--r--editor/editor_resource_picker.cpp18
-rw-r--r--editor/editor_resource_picker.h2
-rw-r--r--editor/editor_resource_preview.cpp4
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp127
-rw-r--r--editor/plugins/animation_player_editor_plugin.h1
-rw-r--r--editor/plugins/gizmos/joint_3d_gizmo_plugin.cpp12
-rw-r--r--editor/plugins/gizmos/joint_3d_gizmo_plugin.h2
-rw-r--r--editor/plugins/node_3d_editor_gizmos.cpp2
-rw-r--r--editor/plugins/node_3d_editor_gizmos.h2
-rw-r--r--platform/android/file_access_android.cpp96
-rw-r--r--platform/android/file_access_android.h9
-rw-r--r--platform/android/file_access_filesystem_jandroid.cpp62
-rw-r--r--platform/android/file_access_filesystem_jandroid.h8
-rw-r--r--platform/windows/detect.py58
-rw-r--r--scene/animation/animation_mixer.cpp129
-rw-r--r--scene/animation/animation_mixer.h1
-rw-r--r--scene/animation/animation_tree.cpp7
-rw-r--r--scene/animation/animation_tree.h2
-rw-r--r--scene/resources/animation.h18
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp20
-rw-r--r--servers/rendering_server.cpp1
-rw-r--r--servers/rendering_server.h2
-rw-r--r--thirdparty/thorvg/inc/config.h2
-rw-r--r--thirdparty/thorvg/patches/pr2702-sw_engine-handle-small-cubics.patch96
-rw-r--r--thirdparty/thorvg/src/common/tvgMath.cpp8
-rw-r--r--thirdparty/thorvg/src/common/tvgMath.h1
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp6
-rw-r--r--thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h12
-rw-r--r--thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp19
-rw-r--r--thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp2
-rw-r--r--thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp5
-rw-r--r--thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.h2
-rw-r--r--thirdparty/thorvg/src/renderer/sw_engine/tvgSwStroke.cpp16
-rw-r--r--thirdparty/thorvg/src/renderer/tvgLoadModule.h3
-rw-r--r--thirdparty/thorvg/src/renderer/tvgPaint.cpp2
-rw-r--r--thirdparty/thorvg/src/renderer/tvgPicture.cpp2
-rw-r--r--thirdparty/thorvg/src/renderer/tvgRender.h2
-rw-r--r--thirdparty/thorvg/src/renderer/tvgScene.h2
-rw-r--r--thirdparty/thorvg/src/renderer/tvgShape.h3
-rw-r--r--thirdparty/thorvg/src/renderer/tvgText.h19
-rwxr-xr-xthirdparty/thorvg/update-thorvg.sh18
68 files changed, 599 insertions, 851 deletions
diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp
index c857d54925..d919243e6b 100644
--- a/core/io/file_access.cpp
+++ b/core/io/file_access.cpp
@@ -223,59 +223,44 @@ String FileAccess::fix_path(const String &p_path) const {
}
/* these are all implemented for ease of porting, then can later be optimized */
+uint8_t FileAccess::get_8() const {
+ uint8_t data = 0;
+ get_buffer(&data, sizeof(uint8_t));
-uint16_t FileAccess::get_16() const {
- uint16_t res;
- uint8_t a, b;
+ return data;
+}
- a = get_8();
- b = get_8();
+uint16_t FileAccess::get_16() const {
+ uint16_t data = 0;
+ get_buffer(reinterpret_cast<uint8_t *>(&data), sizeof(uint16_t));
if (big_endian) {
- SWAP(a, b);
+ data = BSWAP16(data);
}
- res = b;
- res <<= 8;
- res |= a;
-
- return res;
+ return data;
}
uint32_t FileAccess::get_32() const {
- uint32_t res;
- uint16_t a, b;
-
- a = get_16();
- b = get_16();
+ uint32_t data = 0;
+ get_buffer(reinterpret_cast<uint8_t *>(&data), sizeof(uint32_t));
if (big_endian) {
- SWAP(a, b);
+ data = BSWAP32(data);
}
- res = b;
- res <<= 16;
- res |= a;
-
- return res;
+ return data;
}
uint64_t FileAccess::get_64() const {
- uint64_t res;
- uint32_t a, b;
-
- a = get_32();
- b = get_32();
+ uint64_t data = 0;
+ get_buffer(reinterpret_cast<uint8_t *>(&data), sizeof(uint64_t));
if (big_endian) {
- SWAP(a, b);
+ data = BSWAP64(data);
}
- res = b;
- res <<= 32;
- res |= a;
-
- return res;
+ return data;
}
float FileAccess::get_float() const {
@@ -465,17 +450,6 @@ String FileAccess::get_as_text(bool p_skip_cr) const {
return text;
}
-uint64_t FileAccess::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
- ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
-
- uint64_t i = 0;
- for (i = 0; i < p_length && !eof_reached(); i++) {
- p_dst[i] = get_8();
- }
-
- return i;
-}
-
Vector<uint8_t> FileAccess::get_buffer(int64_t p_length) const {
Vector<uint8_t> data;
@@ -488,7 +462,7 @@ Vector<uint8_t> FileAccess::get_buffer(int64_t p_length) const {
ERR_FAIL_COND_V_MSG(err != OK, data, "Can't resize data to " + itos(p_length) + " elements.");
uint8_t *w = data.ptrw();
- int64_t len = get_buffer(&w[0], p_length);
+ int64_t len = get_buffer(w, p_length);
if (len < p_length) {
data.resize(len);
@@ -512,46 +486,32 @@ String FileAccess::get_as_utf8_string(bool p_skip_cr) const {
return s;
}
-void FileAccess::store_16(uint16_t p_dest) {
- uint8_t a, b;
-
- a = p_dest & 0xFF;
- b = p_dest >> 8;
+void FileAccess::store_8(uint8_t p_dest) {
+ store_buffer(&p_dest, sizeof(uint8_t));
+}
+void FileAccess::store_16(uint16_t p_dest) {
if (big_endian) {
- SWAP(a, b);
+ p_dest = BSWAP16(p_dest);
}
- store_8(a);
- store_8(b);
+ store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint16_t));
}
void FileAccess::store_32(uint32_t p_dest) {
- uint16_t a, b;
-
- a = p_dest & 0xFFFF;
- b = p_dest >> 16;
-
if (big_endian) {
- SWAP(a, b);
+ p_dest = BSWAP32(p_dest);
}
- store_16(a);
- store_16(b);
+ store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint32_t));
}
void FileAccess::store_64(uint64_t p_dest) {
- uint32_t a, b;
-
- a = p_dest & 0xFFFFFFFF;
- b = p_dest >> 32;
-
if (big_endian) {
- SWAP(a, b);
+ p_dest = BSWAP64(p_dest);
}
- store_32(a);
- store_32(b);
+ store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint64_t));
}
void FileAccess::store_real(real_t p_real) {
@@ -708,22 +668,11 @@ void FileAccess::store_csv_line(const Vector<String> &p_values, const String &p_
store_line(line);
}
-void FileAccess::store_buffer(const uint8_t *p_src, uint64_t p_length) {
- ERR_FAIL_COND(!p_src && p_length > 0);
- for (uint64_t i = 0; i < p_length; i++) {
- store_8(p_src[i]);
- }
-}
-
void FileAccess::store_buffer(const Vector<uint8_t> &p_buffer) {
uint64_t len = p_buffer.size();
- if (len == 0) {
- return;
- }
-
const uint8_t *r = p_buffer.ptr();
- store_buffer(&r[0], len);
+ store_buffer(r, len);
}
void FileAccess::store_var(const Variant &p_var, bool p_full_objects) {
diff --git a/core/io/file_access.h b/core/io/file_access.h
index 2ab84db4b6..2f4d1a8604 100644
--- a/core/io/file_access.h
+++ b/core/io/file_access.h
@@ -137,7 +137,7 @@ public:
virtual bool eof_reached() const = 0; ///< reading passed EOF
- virtual uint8_t get_8() const = 0; ///< get a byte
+ virtual uint8_t get_8() const; ///< get a byte
virtual uint16_t get_16() const; ///< get 16 bits uint
virtual uint32_t get_32() const; ///< get 32 bits uint
virtual uint64_t get_64() const; ///< get 64 bits uint
@@ -148,7 +148,7 @@ public:
Variant get_var(bool p_allow_objects = false) const;
- virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; ///< get an array of bytes
+ virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const = 0; ///< get an array of bytes, needs to be overwritten by children.
Vector<uint8_t> get_buffer(int64_t p_length) const;
virtual String get_line() const;
virtual String get_token() const;
@@ -168,7 +168,7 @@ public:
virtual Error resize(int64_t p_length) = 0;
virtual void flush() = 0;
- virtual void store_8(uint8_t p_dest) = 0; ///< store a byte
+ virtual void store_8(uint8_t p_dest); ///< store a byte
virtual void store_16(uint16_t p_dest); ///< store 16 bits uint
virtual void store_32(uint32_t p_dest); ///< store 32 bits uint
virtual void store_64(uint64_t p_dest); ///< store 64 bits uint
@@ -184,7 +184,7 @@ public:
virtual void store_pascal_string(const String &p_string);
virtual String get_pascal_string();
- virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes
+ virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) = 0; ///< store an array of bytes, needs to be overwritten by children.
void store_buffer(const Vector<uint8_t> &p_buffer);
void store_var(const Variant &p_var, bool p_full_objects = false);
diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp
index 0f00bd292c..3602baf8c5 100644
--- a/core/io/file_access_compressed.cpp
+++ b/core/io/file_access_compressed.cpp
@@ -260,38 +260,6 @@ bool FileAccessCompressed::eof_reached() const {
}
}
-uint8_t FileAccessCompressed::get_8() const {
- ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use.");
- ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode.");
-
- if (at_end) {
- read_eof = true;
- return 0;
- }
-
- uint8_t ret = read_ptr[read_pos];
-
- read_pos++;
- if (read_pos >= read_block_size) {
- read_block++;
-
- if (read_block < read_block_count) {
- //read another block of compressed data
- f->get_buffer(comp_buffer.ptrw(), read_blocks[read_block].csize);
- int total = Compression::decompress(buffer.ptrw(), read_blocks.size() == 1 ? read_total : block_size, comp_buffer.ptr(), read_blocks[read_block].csize, cmode);
- ERR_FAIL_COND_V_MSG(total == -1, 0, "Compressed file is corrupt.");
- read_block_size = read_block == read_block_count - 1 ? read_total % block_size : block_size;
- read_pos = 0;
-
- } else {
- read_block--;
- at_end = true;
- }
- }
-
- return ret;
-}
-
uint64_t FileAccessCompressed::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
ERR_FAIL_COND_V_MSG(f.is_null(), -1, "File must be opened before use.");
@@ -341,12 +309,13 @@ void FileAccessCompressed::flush() {
// compressed files keep data in memory till close()
}
-void FileAccessCompressed::store_8(uint8_t p_dest) {
+void FileAccessCompressed::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use.");
ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode.");
- WRITE_FIT(1);
- write_ptr[write_pos++] = p_dest;
+ WRITE_FIT(p_length);
+ memcpy(write_ptr + write_pos, p_src, p_length);
+ write_pos += p_length;
}
bool FileAccessCompressed::file_exists(const String &p_name) {
diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h
index f706c82f8e..ea9837dd03 100644
--- a/core/io/file_access_compressed.h
+++ b/core/io/file_access_compressed.h
@@ -83,14 +83,13 @@ public:
virtual bool eof_reached() const override; ///< reading passed EOF
- virtual uint8_t get_8() const override; ///< get a byte
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
virtual Error get_error() const override; ///< get last error
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
virtual void flush() override;
- virtual void store_8(uint8_t p_dest) override; ///< store a byte
+ virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp
index b689f5b628..605c5b2f6f 100644
--- a/core/io/file_access_encrypted.cpp
+++ b/core/io/file_access_encrypted.cpp
@@ -206,26 +206,13 @@ bool FileAccessEncrypted::eof_reached() const {
return eofed;
}
-uint8_t FileAccessEncrypted::get_8() const {
- ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode.");
- if (pos >= get_length()) {
- eofed = true;
- return 0;
- }
-
- uint8_t b = data[pos];
- pos++;
- return b;
-}
-
uint64_t FileAccessEncrypted::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode.");
uint64_t to_copy = MIN(p_length, get_length() - pos);
- for (uint64_t i = 0; i < to_copy; i++) {
- p_dst[i] = data[pos++];
- }
+ memcpy(p_dst, data.ptr() + pos, to_copy);
+ pos += to_copy;
if (to_copy < p_length) {
eofed = true;
@@ -242,17 +229,12 @@ void FileAccessEncrypted::store_buffer(const uint8_t *p_src, uint64_t p_length)
ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode.");
ERR_FAIL_COND(!p_src && p_length > 0);
- if (pos < get_length()) {
- for (uint64_t i = 0; i < p_length; i++) {
- store_8(p_src[i]);
- }
- } else if (pos == get_length()) {
+ if (pos + p_length >= get_length()) {
data.resize(pos + p_length);
- for (uint64_t i = 0; i < p_length; i++) {
- data.write[pos + i] = p_src[i];
- }
- pos += p_length;
}
+
+ memcpy(data.ptrw() + pos, p_src, p_length);
+ pos += p_length;
}
void FileAccessEncrypted::flush() {
@@ -261,18 +243,6 @@ void FileAccessEncrypted::flush() {
// encrypted files keep data in memory till close()
}
-void FileAccessEncrypted::store_8(uint8_t p_dest) {
- ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode.");
-
- if (pos < get_length()) {
- data.write[pos] = p_dest;
- pos++;
- } else if (pos == get_length()) {
- data.push_back(p_dest);
- pos++;
- }
-}
-
bool FileAccessEncrypted::file_exists(const String &p_name) {
Ref<FileAccess> fa = FileAccess::open(p_name, FileAccess::READ);
if (fa.is_null()) {
diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h
index 42afe49a5e..5f8c803d60 100644
--- a/core/io/file_access_encrypted.h
+++ b/core/io/file_access_encrypted.h
@@ -73,14 +73,12 @@ public:
virtual bool eof_reached() const override; ///< reading passed EOF
- virtual uint8_t get_8() const override; ///< get a byte
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
virtual Error get_error() const override; ///< get last error
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
virtual void flush() override;
- virtual void store_8(uint8_t p_dest) override; ///< store a byte
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp
index 9521a4f666..1541a5ed4a 100644
--- a/core/io/file_access_memory.cpp
+++ b/core/io/file_access_memory.cpp
@@ -122,16 +122,6 @@ bool FileAccessMemory::eof_reached() const {
return pos >= length;
}
-uint8_t FileAccessMemory::get_8() const {
- uint8_t ret = 0;
- if (pos < length) {
- ret = data[pos];
- }
- ++pos;
-
- return ret;
-}
-
uint64_t FileAccessMemory::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
ERR_FAIL_NULL_V(data, -1);
@@ -157,16 +147,12 @@ void FileAccessMemory::flush() {
ERR_FAIL_NULL(data);
}
-void FileAccessMemory::store_8(uint8_t p_byte) {
- ERR_FAIL_NULL(data);
- ERR_FAIL_COND(pos >= length);
- data[pos++] = p_byte;
-}
-
void FileAccessMemory::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND(!p_src && p_length > 0);
+
uint64_t left = length - pos;
uint64_t write = MIN(p_length, left);
+
if (write < p_length) {
WARN_PRINT("Writing less data than requested");
}
diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h
index e9fbc26d75..39e1528d97 100644
--- a/core/io/file_access_memory.h
+++ b/core/io/file_access_memory.h
@@ -55,15 +55,12 @@ public:
virtual bool eof_reached() const override; ///< reading passed EOF
- virtual uint8_t get_8() const override; ///< get a byte
-
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override; ///< get an array of bytes
virtual Error get_error() const override; ///< get last error
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
virtual void flush() override;
- virtual void store_8(uint8_t p_byte) override; ///< store a byte
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index 02bf0a6039..eec27ce0aa 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -313,17 +313,6 @@ bool FileAccessPack::eof_reached() const {
return eof;
}
-uint8_t FileAccessPack::get_8() const {
- ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use.");
- if (pos >= pf.size) {
- eof = true;
- return 0;
- }
-
- pos++;
- return f->get_8();
-}
-
uint64_t FileAccessPack::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V_MSG(f.is_null(), -1, "File must be opened before use.");
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
@@ -366,10 +355,6 @@ void FileAccessPack::flush() {
ERR_FAIL();
}
-void FileAccessPack::store_8(uint8_t p_dest) {
- ERR_FAIL();
-}
-
void FileAccessPack::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL();
}
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index 594ac8f089..595a36bca4 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -169,8 +169,6 @@ public:
virtual bool eof_reached() const override;
- virtual uint8_t get_8() const override;
-
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
virtual void set_big_endian(bool p_big_endian) override;
@@ -179,8 +177,6 @@ public:
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
virtual void flush() override;
- virtual void store_8(uint8_t p_dest) override;
-
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool file_exists(const String &p_name) override;
diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp
index c0d1afc8e1..b33b7b35c3 100644
--- a/core/io/file_access_zip.cpp
+++ b/core/io/file_access_zip.cpp
@@ -291,12 +291,6 @@ bool FileAccessZip::eof_reached() const {
return at_eof;
}
-uint8_t FileAccessZip::get_8() const {
- uint8_t ret = 0;
- get_buffer(&ret, 1);
- return ret;
-}
-
uint64_t FileAccessZip::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
ERR_FAIL_NULL_V(zfile, -1);
@@ -328,7 +322,7 @@ void FileAccessZip::flush() {
ERR_FAIL();
}
-void FileAccessZip::store_8(uint8_t p_dest) {
+void FileAccessZip::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL();
}
diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h
index 88b63e93e2..1e11e050df 100644
--- a/core/io/file_access_zip.h
+++ b/core/io/file_access_zip.h
@@ -95,14 +95,13 @@ public:
virtual bool eof_reached() const override; ///< reading passed EOF
- virtual uint8_t get_8() const override; ///< get a byte
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
virtual Error get_error() const override; ///< get last error
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
virtual void flush() override;
- virtual void store_8(uint8_t p_dest) override; ///< store a byte
+ virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
diff --git a/doc/classes/AnimationMixer.xml b/doc/classes/AnimationMixer.xml
index dc1bee4336..d762ffa5a6 100644
--- a/doc/classes/AnimationMixer.xml
+++ b/doc/classes/AnimationMixer.xml
@@ -376,7 +376,19 @@
</constant>
<constant name="ANIMATION_CALLBACK_MODE_DISCRETE_FORCE_CONTINUOUS" value="2" enum="AnimationCallbackModeDiscrete">
Always treat the [constant Animation.UPDATE_DISCRETE] track value as [constant Animation.UPDATE_CONTINUOUS] with [constant Animation.INTERPOLATION_NEAREST]. This is the default behavior for [AnimationTree].
- If a value track has non-numeric type key values, it is internally converted to use [constant ANIMATION_CALLBACK_MODE_DISCRETE_RECESSIVE] with [constant Animation.UPDATE_DISCRETE].
+ If a value track has un-interpolatable type key values, it is internally converted to use [constant ANIMATION_CALLBACK_MODE_DISCRETE_RECESSIVE] with [constant Animation.UPDATE_DISCRETE].
+ Un-interpolatable type list:
+ - [constant @GlobalScope.TYPE_NIL]
+ - [constant @GlobalScope.TYPE_NODE_PATH]
+ - [constant @GlobalScope.TYPE_RID]
+ - [constant @GlobalScope.TYPE_OBJECT]
+ - [constant @GlobalScope.TYPE_CALLABLE]
+ - [constant @GlobalScope.TYPE_SIGNAL]
+ - [constant @GlobalScope.TYPE_DICTIONARY]
+ - [constant @GlobalScope.TYPE_PACKED_BYTE_ARRAY]
+ [constant @GlobalScope.TYPE_BOOL] and [constant @GlobalScope.TYPE_INT] are treated as [constant @GlobalScope.TYPE_FLOAT] during blending and rounded when the result is retrieved.
+ It is same for arrays and vectors with them such as [constant @GlobalScope.TYPE_PACKED_INT32_ARRAY] or [constant @GlobalScope.TYPE_VECTOR2I], they are treated as [constant @GlobalScope.TYPE_PACKED_FLOAT32_ARRAY] or [constant @GlobalScope.TYPE_VECTOR2]. Also note that for arrays, the size is also interpolated.
+ [constant @GlobalScope.TYPE_STRING] and [constant @GlobalScope.TYPE_STRING_NAME] are interpolated between character codes and lengths, but note that there is a difference in algorithm between interpolation between keys and interpolation by blending.
</constant>
</constants>
</class>
diff --git a/doc/classes/EditorResourcePreviewGenerator.xml b/doc/classes/EditorResourcePreviewGenerator.xml
index fcfdbb5c44..9c9b6d11b2 100644
--- a/doc/classes/EditorResourcePreviewGenerator.xml
+++ b/doc/classes/EditorResourcePreviewGenerator.xml
@@ -23,7 +23,7 @@
<param index="2" name="metadata" type="Dictionary" />
<description>
Generate a preview from a given resource with the specified size. This must always be implemented.
- Returning an empty texture is an OK way to fail and let another generator take care.
+ Returning [code]null[/code] is an OK way to fail and let another generator take care.
Care must be taken because this function is always called from a thread (not the main thread).
[param metadata] dictionary can be modified to store file-specific metadata that can be used in [method EditorResourceTooltipPlugin._make_tooltip_for_path] (like image size, sample length etc.).
</description>
@@ -35,7 +35,7 @@
<param index="2" name="metadata" type="Dictionary" />
<description>
Generate a preview directly from a path with the specified size. Implementing this is optional, as default code will load and call [method _generate].
- Returning an empty texture is an OK way to fail and let another generator take care.
+ Returning [code]null[/code] is an OK way to fail and let another generator take care.
Care must be taken because this function is always called from a thread (not the main thread).
[param metadata] dictionary can be modified to store file-specific metadata that can be used in [method EditorResourceTooltipPlugin._make_tooltip_for_path] (like image size, sample length etc.).
</description>
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index c81d5d4fab..4cdfba17e9 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -412,6 +412,14 @@
[b]Note:[/b] [param count] is unused and can be left unspecified.
</description>
</method>
+ <method name="canvas_item_attach_skeleton">
+ <return type="void" />
+ <param index="0" name="item" type="RID" />
+ <param index="1" name="skeleton" type="RID" />
+ <description>
+ Attaches a skeleton to the [CanvasItem]. Removes the previous skeleton.
+ </description>
+ </method>
<method name="canvas_item_clear">
<return type="void" />
<param index="0" name="item" type="RID" />
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
index 57fe96fb6f..36393dde86 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -1389,8 +1389,22 @@ void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) {
tinfo.format = t->format;
tinfo.width = t->alloc_width;
tinfo.height = t->alloc_height;
- tinfo.depth = t->depth;
tinfo.bytes = t->total_data_size;
+
+ switch (t->type) {
+ case Texture::TYPE_3D:
+ tinfo.depth = t->depth;
+ break;
+
+ case Texture::TYPE_LAYERED:
+ tinfo.depth = t->layers;
+ break;
+
+ default:
+ tinfo.depth = 0;
+ break;
+ }
+
r_info->push_back(tinfo);
}
}
@@ -1521,7 +1535,11 @@ void TextureStorage::_texture_set_data(RID p_texture, const Ref<Image> &p_image,
h = MAX(1, h >> 1);
}
- texture->total_data_size = tsize;
+ if (texture->target == GL_TEXTURE_CUBE_MAP || texture->target == GL_TEXTURE_2D_ARRAY) {
+ texture->total_data_size = tsize * texture->layers;
+ } else {
+ texture->total_data_size = tsize;
+ }
texture->stored_cube_sides |= (1 << p_layer);
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index ea8b42b2e4..32f2d7dd79 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -218,67 +218,13 @@ bool FileAccessUnix::eof_reached() const {
return last_error == ERR_FILE_EOF;
}
-uint8_t FileAccessUnix::get_8() const {
- ERR_FAIL_NULL_V_MSG(f, 0, "File must be opened before use.");
- uint8_t b;
- if (fread(&b, 1, 1, f) == 0) {
- check_errors();
- b = '\0';
- }
- return b;
-}
-
-uint16_t FileAccessUnix::get_16() const {
- ERR_FAIL_NULL_V_MSG(f, 0, "File must be opened before use.");
-
- uint16_t b = 0;
- if (fread(&b, 1, 2, f) != 2) {
- check_errors();
- }
-
- if (big_endian) {
- b = BSWAP16(b);
- }
-
- return b;
-}
-
-uint32_t FileAccessUnix::get_32() const {
- ERR_FAIL_NULL_V_MSG(f, 0, "File must be opened before use.");
-
- uint32_t b = 0;
- if (fread(&b, 1, 4, f) != 4) {
- check_errors();
- }
-
- if (big_endian) {
- b = BSWAP32(b);
- }
-
- return b;
-}
-
-uint64_t FileAccessUnix::get_64() const {
- ERR_FAIL_NULL_V_MSG(f, 0, "File must be opened before use.");
-
- uint64_t b = 0;
- if (fread(&b, 1, 8, f) != 8) {
- check_errors();
- }
-
- if (big_endian) {
- b = BSWAP64(b);
- }
-
- return b;
-}
-
uint64_t FileAccessUnix::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
- ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
ERR_FAIL_NULL_V_MSG(f, -1, "File must be opened before use.");
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
uint64_t read = fread(p_dst, 1, p_length, f);
check_errors();
+
return read;
}
@@ -308,41 +254,6 @@ void FileAccessUnix::flush() {
fflush(f);
}
-void FileAccessUnix::store_8(uint8_t p_dest) {
- ERR_FAIL_NULL_MSG(f, "File must be opened before use.");
- ERR_FAIL_COND(fwrite(&p_dest, 1, 1, f) != 1);
-}
-
-void FileAccessUnix::store_16(uint16_t p_dest) {
- ERR_FAIL_NULL_MSG(f, "File must be opened before use.");
-
- if (big_endian) {
- p_dest = BSWAP16(p_dest);
- }
-
- ERR_FAIL_COND(fwrite(&p_dest, 1, 2, f) != 2);
-}
-
-void FileAccessUnix::store_32(uint32_t p_dest) {
- ERR_FAIL_NULL_MSG(f, "File must be opened before use.");
-
- if (big_endian) {
- p_dest = BSWAP32(p_dest);
- }
-
- ERR_FAIL_COND(fwrite(&p_dest, 1, 4, f) != 4);
-}
-
-void FileAccessUnix::store_64(uint64_t p_dest) {
- ERR_FAIL_NULL_MSG(f, "File must be opened before use.");
-
- if (big_endian) {
- p_dest = BSWAP64(p_dest);
- }
-
- ERR_FAIL_COND(fwrite(&p_dest, 1, 8, f) != 8);
-}
-
void FileAccessUnix::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_NULL_MSG(f, "File must be opened before use.");
ERR_FAIL_COND(!p_src && p_length > 0);
diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h
index c0286dbff3..76f629f7c2 100644
--- a/drivers/unix/file_access_unix.h
+++ b/drivers/unix/file_access_unix.h
@@ -67,20 +67,12 @@ public:
virtual bool eof_reached() const override; ///< reading passed EOF
- virtual uint8_t get_8() const override; ///< get a byte
- virtual uint16_t get_16() const override;
- virtual uint32_t get_32() const override;
- virtual uint64_t get_64() const override;
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
virtual Error get_error() const override; ///< get last error
virtual Error resize(int64_t p_length) override;
virtual void flush() override;
- virtual void store_8(uint8_t p_dest) override; ///< store a byte
- virtual void store_16(uint16_t p_dest) override;
- virtual void store_32(uint32_t p_dest) override;
- virtual void store_64(uint64_t p_dest) override;
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
virtual bool file_exists(const String &p_path) override; ///< return true if a file exists
diff --git a/drivers/unix/file_access_unix_pipe.cpp b/drivers/unix/file_access_unix_pipe.cpp
index 5d9a27ad05..34758e8c7d 100644
--- a/drivers/unix/file_access_unix_pipe.cpp
+++ b/drivers/unix/file_access_unix_pipe.cpp
@@ -125,22 +125,9 @@ String FileAccessUnixPipe::get_path_absolute() const {
return path_src;
}
-uint8_t FileAccessUnixPipe::get_8() const {
- ERR_FAIL_COND_V_MSG(fd[0] < 0, 0, "Pipe must be opened before use.");
-
- uint8_t b;
- if (::read(fd[0], &b, 1) == 0) {
- last_error = ERR_FILE_CANT_READ;
- b = '\0';
- } else {
- last_error = OK;
- }
- return b;
-}
-
uint64_t FileAccessUnixPipe::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
- ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
ERR_FAIL_COND_V_MSG(fd[0] < 0, -1, "Pipe must be opened before use.");
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
uint64_t read = ::read(fd[0], p_dst, p_length);
if (read == p_length) {
@@ -155,18 +142,10 @@ Error FileAccessUnixPipe::get_error() const {
return last_error;
}
-void FileAccessUnixPipe::store_8(uint8_t p_src) {
- ERR_FAIL_COND_MSG(fd[1] < 0, "Pipe must be opened before use.");
- if (::write(fd[1], &p_src, 1) != 1) {
- last_error = ERR_FILE_CANT_WRITE;
- } else {
- last_error = OK;
- }
-}
-
void FileAccessUnixPipe::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND_MSG(fd[1] < 0, "Pipe must be opened before use.");
ERR_FAIL_COND(!p_src && p_length > 0);
+
if (::write(fd[1], p_src, p_length) != (ssize_t)p_length) {
last_error = ERR_FILE_CANT_WRITE;
} else {
diff --git a/drivers/unix/file_access_unix_pipe.h b/drivers/unix/file_access_unix_pipe.h
index 8e7988791b..19acdb5a37 100644
--- a/drivers/unix/file_access_unix_pipe.h
+++ b/drivers/unix/file_access_unix_pipe.h
@@ -65,14 +65,12 @@ public:
virtual bool eof_reached() const override { return false; }
- virtual uint8_t get_8() const override; ///< get a byte
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
virtual Error get_error() const override; ///< get last error
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
virtual void flush() override {}
- virtual void store_8(uint8_t p_src) override; ///< store a byte
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
virtual bool file_exists(const String &p_path) override { return false; }
diff --git a/drivers/vulkan/rendering_device_driver_vulkan.cpp b/drivers/vulkan/rendering_device_driver_vulkan.cpp
index 2ba353868b..4ea46e8214 100644
--- a/drivers/vulkan/rendering_device_driver_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_driver_vulkan.cpp
@@ -497,6 +497,7 @@ Error RenderingDeviceDriverVulkan::_initialize_device_extensions() {
_register_requested_device_extension(VK_KHR_MAINTENANCE_2_EXTENSION_NAME, false);
_register_requested_device_extension(VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME, false);
_register_requested_device_extension(VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME, false);
+ _register_requested_device_extension(VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME, false);
if (Engine::get_singleton()->is_generate_spirv_debug_info_enabled()) {
_register_requested_device_extension(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME, true);
@@ -1705,6 +1706,16 @@ RDD::TextureID RenderingDeviceDriverVulkan::texture_create(const TextureFormat &
image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
}
+ VkImageViewASTCDecodeModeEXT decode_mode;
+ if (enabled_device_extension_names.has(VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME)) {
+ if (image_view_create_info.format >= VK_FORMAT_ASTC_4x4_UNORM_BLOCK && image_view_create_info.format <= VK_FORMAT_ASTC_12x12_SRGB_BLOCK) {
+ decode_mode.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT;
+ decode_mode.pNext = nullptr;
+ decode_mode.decodeMode = VK_FORMAT_R8G8B8A8_UNORM;
+ image_view_create_info.pNext = &decode_mode;
+ }
+ }
+
VkImageView vk_image_view = VK_NULL_HANDLE;
err = vkCreateImageView(vk_device, &image_view_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_IMAGE_VIEW), &vk_image_view);
if (err) {
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index f6f721639c..0243d863f8 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -323,93 +323,9 @@ bool FileAccessWindows::eof_reached() const {
return last_error == ERR_FILE_EOF;
}
-uint8_t FileAccessWindows::get_8() const {
- ERR_FAIL_NULL_V(f, 0);
-
- if (flags == READ_WRITE || flags == WRITE_READ) {
- if (prev_op == WRITE) {
- fflush(f);
- }
- prev_op = READ;
- }
- uint8_t b;
- if (fread(&b, 1, 1, f) == 0) {
- check_errors();
- b = '\0';
- }
-
- return b;
-}
-
-uint16_t FileAccessWindows::get_16() const {
- ERR_FAIL_NULL_V(f, 0);
-
- if (flags == READ_WRITE || flags == WRITE_READ) {
- if (prev_op == WRITE) {
- fflush(f);
- }
- prev_op = READ;
- }
-
- uint16_t b = 0;
- if (fread(&b, 1, 2, f) != 2) {
- check_errors();
- }
-
- if (big_endian) {
- b = BSWAP16(b);
- }
-
- return b;
-}
-
-uint32_t FileAccessWindows::get_32() const {
- ERR_FAIL_NULL_V(f, 0);
-
- if (flags == READ_WRITE || flags == WRITE_READ) {
- if (prev_op == WRITE) {
- fflush(f);
- }
- prev_op = READ;
- }
-
- uint32_t b = 0;
- if (fread(&b, 1, 4, f) != 4) {
- check_errors();
- }
-
- if (big_endian) {
- b = BSWAP32(b);
- }
-
- return b;
-}
-
-uint64_t FileAccessWindows::get_64() const {
- ERR_FAIL_NULL_V(f, 0);
-
- if (flags == READ_WRITE || flags == WRITE_READ) {
- if (prev_op == WRITE) {
- fflush(f);
- }
- prev_op = READ;
- }
-
- uint64_t b = 0;
- if (fread(&b, 1, 8, f) != 8) {
- check_errors();
- }
-
- if (big_endian) {
- b = BSWAP64(b);
- }
-
- return b;
-}
-
uint64_t FileAccessWindows::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
- ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
ERR_FAIL_NULL_V(f, -1);
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
if (flags == READ_WRITE || flags == WRITE_READ) {
if (prev_op == WRITE) {
@@ -417,8 +333,10 @@ uint64_t FileAccessWindows::get_buffer(uint8_t *p_dst, uint64_t p_length) const
}
prev_op = READ;
}
+
uint64_t read = fread(p_dst, 1, p_length, f);
check_errors();
+
return read;
}
@@ -453,77 +371,6 @@ void FileAccessWindows::flush() {
}
}
-void FileAccessWindows::store_8(uint8_t p_dest) {
- ERR_FAIL_NULL(f);
-
- if (flags == READ_WRITE || flags == WRITE_READ) {
- if (prev_op == READ) {
- if (last_error != ERR_FILE_EOF) {
- fseek(f, 0, SEEK_CUR);
- }
- }
- prev_op = WRITE;
- }
- fwrite(&p_dest, 1, 1, f);
-}
-
-void FileAccessWindows::store_16(uint16_t p_dest) {
- ERR_FAIL_NULL(f);
-
- if (flags == READ_WRITE || flags == WRITE_READ) {
- if (prev_op == READ) {
- if (last_error != ERR_FILE_EOF) {
- fseek(f, 0, SEEK_CUR);
- }
- }
- prev_op = WRITE;
- }
-
- if (big_endian) {
- p_dest = BSWAP16(p_dest);
- }
-
- fwrite(&p_dest, 1, 2, f);
-}
-
-void FileAccessWindows::store_32(uint32_t p_dest) {
- ERR_FAIL_NULL(f);
-
- if (flags == READ_WRITE || flags == WRITE_READ) {
- if (prev_op == READ) {
- if (last_error != ERR_FILE_EOF) {
- fseek(f, 0, SEEK_CUR);
- }
- }
- prev_op = WRITE;
- }
-
- if (big_endian) {
- p_dest = BSWAP32(p_dest);
- }
-
- fwrite(&p_dest, 1, 4, f);
-}
-
-void FileAccessWindows::store_64(uint64_t p_dest) {
- ERR_FAIL_NULL(f);
-
- if (flags == READ_WRITE || flags == WRITE_READ) {
- if (prev_op == READ) {
- if (last_error != ERR_FILE_EOF) {
- fseek(f, 0, SEEK_CUR);
- }
- }
- prev_op = WRITE;
- }
-
- if (big_endian) {
- p_dest = BSWAP64(p_dest);
- }
-
- fwrite(&p_dest, 1, 8, f);
-}
-
void FileAccessWindows::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_NULL(f);
ERR_FAIL_COND(!p_src && p_length > 0);
@@ -536,6 +383,7 @@ void FileAccessWindows::store_buffer(const uint8_t *p_src, uint64_t p_length) {
}
prev_op = WRITE;
}
+
ERR_FAIL_COND(fwrite(p_src, 1, p_length, f) != (size_t)p_length);
}
@@ -559,11 +407,10 @@ uint64_t FileAccessWindows::_get_modified_time(const String &p_file) {
return 0;
}
- String file = p_file;
- if (file.ends_with("/") && file != "/") {
+ String file = fix_path(p_file);
+ if (file.ends_with("\\") && file != "\\") {
file = file.substr(0, file.length() - 1);
}
- file = fix_path(file);
struct _stat st;
int rv = _wstat((LPCWSTR)(file.utf16().get_data()), &st);
diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h
index a25bbcfb3a..f458ff9c6c 100644
--- a/drivers/windows/file_access_windows.h
+++ b/drivers/windows/file_access_windows.h
@@ -69,20 +69,12 @@ public:
virtual bool eof_reached() const override; ///< reading passed EOF
- virtual uint8_t get_8() const override; ///< get a byte
- virtual uint16_t get_16() const override;
- virtual uint32_t get_32() const override;
- virtual uint64_t get_64() const override;
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
virtual Error get_error() const override; ///< get last error
virtual Error resize(int64_t p_length) override;
virtual void flush() override;
- virtual void store_8(uint8_t p_dest) override; ///< store a byte
- virtual void store_16(uint16_t p_dest) override;
- virtual void store_32(uint32_t p_dest) override;
- virtual void store_64(uint64_t p_dest) override;
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
diff --git a/drivers/windows/file_access_windows_pipe.cpp b/drivers/windows/file_access_windows_pipe.cpp
index 7902c8e1d8..0c953b14aa 100644
--- a/drivers/windows/file_access_windows_pipe.cpp
+++ b/drivers/windows/file_access_windows_pipe.cpp
@@ -96,22 +96,9 @@ String FileAccessWindowsPipe::get_path_absolute() const {
return path_src;
}
-uint8_t FileAccessWindowsPipe::get_8() const {
- ERR_FAIL_COND_V_MSG(fd[0] == 0, 0, "Pipe must be opened before use.");
-
- uint8_t b;
- if (!ReadFile(fd[0], &b, 1, nullptr, nullptr)) {
- last_error = ERR_FILE_CANT_READ;
- b = '\0';
- } else {
- last_error = OK;
- }
- return b;
-}
-
uint64_t FileAccessWindowsPipe::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
- ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
ERR_FAIL_COND_V_MSG(fd[0] == 0, -1, "Pipe must be opened before use.");
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
DWORD read = -1;
if (!ReadFile(fd[0], p_dst, p_length, &read, nullptr) || read != p_length) {
@@ -126,15 +113,6 @@ Error FileAccessWindowsPipe::get_error() const {
return last_error;
}
-void FileAccessWindowsPipe::store_8(uint8_t p_src) {
- ERR_FAIL_COND_MSG(fd[1] == 0, "Pipe must be opened before use.");
- if (!WriteFile(fd[1], &p_src, 1, nullptr, nullptr)) {
- last_error = ERR_FILE_CANT_WRITE;
- } else {
- last_error = OK;
- }
-}
-
void FileAccessWindowsPipe::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND_MSG(fd[1] == 0, "Pipe must be opened before use.");
ERR_FAIL_COND(!p_src && p_length > 0);
diff --git a/drivers/windows/file_access_windows_pipe.h b/drivers/windows/file_access_windows_pipe.h
index b885ef78e6..4e9bd036ae 100644
--- a/drivers/windows/file_access_windows_pipe.h
+++ b/drivers/windows/file_access_windows_pipe.h
@@ -64,14 +64,12 @@ public:
virtual bool eof_reached() const override { return false; }
- virtual uint8_t get_8() const override; ///< get a byte
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
virtual Error get_error() const override; ///< get last error
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
virtual void flush() override {}
- virtual void store_8(uint8_t p_src) override; ///< store a byte
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
virtual bool file_exists(const String &p_name) override { return false; }
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 8c07cefc19..80bf9f850e 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -4554,6 +4554,10 @@ bool AnimationTrackEditor::is_snap_enabled() const {
return snap->is_pressed() ^ Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL);
}
+bool AnimationTrackEditor::is_bezier_editor_active() const {
+ return bezier_edit->is_visible();
+}
+
bool AnimationTrackEditor::can_add_reset_key() const {
for (const KeyValue<SelectedKey, KeyInfo> &E : selection) {
const Animation::TrackType track_type = animation->track_get_type(E.key.track);
diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h
index a517ba8b43..516ddb0154 100644
--- a/editor/animation_track_editor.h
+++ b/editor/animation_track_editor.h
@@ -729,6 +729,7 @@ public:
bool is_key_clipboard_active() const;
bool is_moving_selection() const;
bool is_snap_enabled() const;
+ bool is_bezier_editor_active() const;
bool can_add_reset_key() const;
float get_moving_selection_offset() const;
float snap_time(float p_value, bool p_relative = false);
diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp
index 8935b9ad8a..f20dd992bb 100644
--- a/editor/editor_resource_picker.cpp
+++ b/editor/editor_resource_picker.cpp
@@ -175,6 +175,13 @@ void EditorResourcePicker::_file_quick_selected() {
_file_selected(quick_open->get_selected());
}
+void EditorResourcePicker::_resource_saved(Object *p_resource) {
+ if (edited_resource.is_valid() && p_resource == edited_resource.ptr()) {
+ emit_signal(SNAME("resource_changed"), edited_resource);
+ _update_resource();
+ }
+}
+
void EditorResourcePicker::_update_menu() {
_update_menu_items();
@@ -408,6 +415,10 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) {
if (edited_resource.is_null()) {
return;
}
+ Callable resource_saved = callable_mp(this, &EditorResourcePicker::_resource_saved);
+ if (!EditorNode::get_singleton()->is_connected("resource_saved", resource_saved)) {
+ EditorNode::get_singleton()->connect("resource_saved", resource_saved);
+ }
EditorNode::get_singleton()->save_resource_as(edited_resource);
} break;
@@ -833,6 +844,13 @@ void EditorResourcePicker::_notification(int p_what) {
assign_button->queue_redraw();
}
} break;
+
+ case NOTIFICATION_EXIT_TREE: {
+ Callable resource_saved = callable_mp(this, &EditorResourcePicker::_resource_saved);
+ if (EditorNode::get_singleton()->is_connected("resource_saved", resource_saved)) {
+ EditorNode::get_singleton()->disconnect("resource_saved", resource_saved);
+ }
+ } break;
}
}
diff --git a/editor/editor_resource_picker.h b/editor/editor_resource_picker.h
index 28229e6b37..05e392da2c 100644
--- a/editor/editor_resource_picker.h
+++ b/editor/editor_resource_picker.h
@@ -91,6 +91,8 @@ class EditorResourcePicker : public HBoxContainer {
void _file_quick_selected();
void _file_selected(const String &p_path);
+ void _resource_saved(Object *p_resource);
+
void _update_menu();
void _update_menu_items();
void _edit_menu_cbk(int p_which);
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index 71865f7e8c..956fdc5cfa 100644
--- a/editor/editor_resource_preview.cpp
+++ b/editor/editor_resource_preview.cpp
@@ -221,7 +221,9 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref<
r_small_texture->set_image(small_image);
}
- break;
+ if (generated.is_valid()) {
+ break;
+ }
}
if (!p_item.resource.is_valid()) {
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 1056c8abd0..73c17aa760 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -224,6 +224,69 @@ void AnimationPlayerEditor::_autoplay_pressed() {
}
}
+void AnimationPlayerEditor::_go_to_nearest_keyframe(bool p_backward) {
+ if (_get_current().is_empty()) {
+ return;
+ }
+
+ Ref<Animation> anim = player->get_animation(player->get_assigned_animation());
+
+ double current_time = player->get_current_animation_position();
+ // Offset the time to avoid finding the same keyframe with Animation::track_find_key().
+ double time_offset = MAX(CMP_EPSILON * 2, current_time * CMP_EPSILON * 2);
+ double current_time_offset = current_time + (p_backward ? -time_offset : time_offset);
+
+ float nearest_key_time = p_backward ? 0 : anim->get_length();
+ int track_count = anim->get_track_count();
+ bool bezier_active = track_editor->is_bezier_editor_active();
+
+ Node *root = get_tree()->get_edited_scene_root();
+ EditorSelection *selection = EditorNode::get_singleton()->get_editor_selection();
+
+ Vector<int> selected_tracks;
+ for (int i = 0; i < track_count; ++i) {
+ if (selection->is_selected(root->get_node_or_null(anim->track_get_path(i)))) {
+ selected_tracks.push_back(i);
+ }
+ }
+
+ // Find the nearest keyframe in selection if the scene has selected nodes
+ // or the nearest keyframe in the entire animation otherwise.
+ if (selected_tracks.size() > 0) {
+ for (int track : selected_tracks) {
+ if (bezier_active && anim->track_get_type(track) != Animation::TYPE_BEZIER) {
+ continue;
+ }
+ int key = anim->track_find_key(track, current_time_offset, Animation::FIND_MODE_NEAREST, false, !p_backward);
+ if (key == -1) {
+ continue;
+ }
+ double key_time = anim->track_get_key_time(track, key);
+ if ((p_backward && key_time > nearest_key_time) || (!p_backward && key_time < nearest_key_time)) {
+ nearest_key_time = key_time;
+ }
+ }
+ } else {
+ for (int track = 0; track < track_count; ++track) {
+ if (bezier_active && anim->track_get_type(track) != Animation::TYPE_BEZIER) {
+ continue;
+ }
+ int key = anim->track_find_key(track, current_time_offset, Animation::FIND_MODE_NEAREST, false, !p_backward);
+ if (key == -1) {
+ continue;
+ }
+ double key_time = anim->track_get_key_time(track, key);
+ if ((p_backward && key_time > nearest_key_time) || (!p_backward && key_time < nearest_key_time)) {
+ nearest_key_time = key_time;
+ }
+ }
+ }
+
+ player->seek_internal(nearest_key_time, true, true, true);
+ frame->set_value(nearest_key_time);
+ track_editor->set_anim_pos(nearest_key_time);
+}
+
void AnimationPlayerEditor::_play_pressed() {
String current = _get_current();
@@ -1511,30 +1574,28 @@ void AnimationPlayerEditor::shortcut_input(const Ref<InputEvent> &p_ev) {
ERR_FAIL_COND(p_ev.is_null());
Ref<InputEventKey> k = p_ev;
- if (is_visible_in_tree() && k.is_valid() && k->is_pressed() && !k->is_echo() && !k->is_alt_pressed() && !k->is_ctrl_pressed() && !k->is_meta_pressed()) {
- switch (k->get_keycode()) {
- case Key::A: {
- if (!k->is_shift_pressed()) {
- _play_bw_from_pressed();
- } else {
- _play_bw_pressed();
- }
- accept_event();
- } break;
- case Key::S: {
- _stop_pressed();
- accept_event();
- } break;
- case Key::D: {
- if (!k->is_shift_pressed()) {
- _play_from_pressed();
- } else {
- _play_pressed();
- }
- accept_event();
- } break;
- default:
- break;
+ if (is_visible_in_tree() && k.is_valid() && k->is_pressed() && !k->is_echo()) {
+ if (ED_IS_SHORTCUT("animation_editor/stop_animation", p_ev)) {
+ _stop_pressed();
+ accept_event();
+ } else if (ED_IS_SHORTCUT("animation_editor/play_animation", p_ev)) {
+ _play_from_pressed();
+ accept_event();
+ } else if (ED_IS_SHORTCUT("animation_editor/play_animation_backwards", p_ev)) {
+ _play_bw_from_pressed();
+ accept_event();
+ } else if (ED_IS_SHORTCUT("animation_editor/play_animation_from_start", p_ev)) {
+ _play_pressed();
+ accept_event();
+ } else if (ED_IS_SHORTCUT("animation_editor/play_animation_from_end", p_ev)) {
+ _play_bw_pressed();
+ accept_event();
+ } else if (ED_IS_SHORTCUT("animation_editor/go_to_next_keyframe", p_ev)) {
+ _go_to_nearest_keyframe(false);
+ accept_event();
+ } else if (ED_IS_SHORTCUT("animation_editor/go_to_previous_keyframe", p_ev)) {
+ _go_to_nearest_keyframe(true);
+ accept_event();
}
}
}
@@ -1909,27 +1970,27 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug
play_bw_from = memnew(Button);
play_bw_from->set_theme_type_variation("FlatButton");
- play_bw_from->set_tooltip_text(TTR("Play selected animation backwards from current pos. (A)"));
+ play_bw_from->set_tooltip_text(TTR("Play Animation Backwards"));
hb->add_child(play_bw_from);
play_bw = memnew(Button);
play_bw->set_theme_type_variation("FlatButton");
- play_bw->set_tooltip_text(TTR("Play selected animation backwards from end. (Shift+A)"));
+ play_bw->set_tooltip_text(TTR("Play Animation Backwards from End"));
hb->add_child(play_bw);
stop = memnew(Button);
stop->set_theme_type_variation("FlatButton");
+ stop->set_tooltip_text(TTR("Pause/Stop Animation"));
hb->add_child(stop);
- stop->set_tooltip_text(TTR("Pause/stop animation playback. (S)"));
play = memnew(Button);
play->set_theme_type_variation("FlatButton");
- play->set_tooltip_text(TTR("Play selected animation from start. (Shift+D)"));
+ play->set_tooltip_text(TTR("Play Animation from Start"));
hb->add_child(play);
play_from = memnew(Button);
play_from->set_theme_type_variation("FlatButton");
- play_from->set_tooltip_text(TTR("Play selected animation from current pos. (D)"));
+ play_from->set_tooltip_text(TTR("Play Animation"));
hb->add_child(play_from);
frame = memnew(SpinBox);
@@ -2145,6 +2206,14 @@ void fragment() {
}
)");
RS::get_singleton()->material_set_shader(onion.capture.material->get_rid(), onion.capture.shader->get_rid());
+
+ ED_SHORTCUT("animation_editor/stop_animation", TTR("Pause/Stop Animation"), Key::S);
+ ED_SHORTCUT("animation_editor/play_animation", TTR("Play Animation"), Key::D);
+ ED_SHORTCUT("animation_editor/play_animation_backwards", TTR("Play Animation Backwards"), Key::A);
+ ED_SHORTCUT("animation_editor/play_animation_from_start", TTR("Play Animation from Start"), KeyModifierMask::SHIFT + Key::D);
+ ED_SHORTCUT("animation_editor/play_animation_from_end", TTR("Play Animation Backwards from End"), KeyModifierMask::SHIFT + Key::A);
+ ED_SHORTCUT("animation_editor/go_to_next_keyframe", TTR("Go to Next Keyframe"), KeyModifierMask::SHIFT + KeyModifierMask::ALT + Key::D);
+ ED_SHORTCUT("animation_editor/go_to_previous_keyframe", TTR("Go to Previous Keyframe"), KeyModifierMask::SHIFT + KeyModifierMask::ALT + Key::A);
}
AnimationPlayerEditor::~AnimationPlayerEditor() {
diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h
index 8804e4e3b4..860d421b91 100644
--- a/editor/plugins/animation_player_editor_plugin.h
+++ b/editor/plugins/animation_player_editor_plugin.h
@@ -178,6 +178,7 @@ class AnimationPlayerEditor : public VBoxContainer {
void _select_anim_by_name(const String &p_anim);
float _get_editor_step() const;
+ void _go_to_nearest_keyframe(bool p_backward);
void _play_pressed();
void _play_from_pressed();
void _play_bw_pressed();
diff --git a/editor/plugins/gizmos/joint_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/joint_3d_gizmo_plugin.cpp
index ae24b4250e..c277ec8cd3 100644
--- a/editor/plugins/gizmos/joint_3d_gizmo_plugin.cpp
+++ b/editor/plugins/gizmos/joint_3d_gizmo_plugin.cpp
@@ -293,9 +293,15 @@ Joint3DGizmoPlugin::Joint3DGizmoPlugin() {
void Joint3DGizmoPlugin::incremental_update_gizmos() {
if (!current_gizmos.is_empty()) {
- update_idx++;
- update_idx = update_idx % current_gizmos.size();
- redraw(current_gizmos.get(update_idx));
+ HashSet<EditorNode3DGizmo *>::Iterator E = current_gizmos.find(last_drawn);
+ if (E) {
+ ++E;
+ }
+ if (!E) {
+ E = current_gizmos.begin();
+ }
+ redraw(*E);
+ last_drawn = *E;
}
}
diff --git a/editor/plugins/gizmos/joint_3d_gizmo_plugin.h b/editor/plugins/gizmos/joint_3d_gizmo_plugin.h
index 79fe40d1b2..25b08d71c6 100644
--- a/editor/plugins/gizmos/joint_3d_gizmo_plugin.h
+++ b/editor/plugins/gizmos/joint_3d_gizmo_plugin.h
@@ -37,7 +37,7 @@ class Joint3DGizmoPlugin : public EditorNode3DGizmoPlugin {
GDCLASS(Joint3DGizmoPlugin, EditorNode3DGizmoPlugin);
Timer *update_timer = nullptr;
- uint64_t update_idx = 0;
+ EditorNode3DGizmo *last_drawn = nullptr;
void incremental_update_gizmos();
diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp
index 67d5e44ce5..1b2cd441ad 100644
--- a/editor/plugins/node_3d_editor_gizmos.cpp
+++ b/editor/plugins/node_3d_editor_gizmos.cpp
@@ -1060,7 +1060,7 @@ Ref<EditorNode3DGizmo> EditorNode3DGizmoPlugin::get_gizmo(Node3D *p_spatial) {
ref->set_node_3d(p_spatial);
ref->set_hidden(current_state == HIDDEN);
- current_gizmos.push_back(ref.ptr());
+ current_gizmos.insert(ref.ptr());
return ref;
}
diff --git a/editor/plugins/node_3d_editor_gizmos.h b/editor/plugins/node_3d_editor_gizmos.h
index c4b275032a..1916bc2058 100644
--- a/editor/plugins/node_3d_editor_gizmos.h
+++ b/editor/plugins/node_3d_editor_gizmos.h
@@ -157,7 +157,7 @@ public:
protected:
int current_state;
- List<EditorNode3DGizmo *> current_gizmos;
+ HashSet<EditorNode3DGizmo *> current_gizmos;
HashMap<String, Vector<Ref<StandardMaterial3D>>> materials;
static void _bind_methods();
diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp
index ae336d6f9d..59b669eabb 100644
--- a/platform/android/file_access_android.cpp
+++ b/platform/android/file_access_android.cpp
@@ -113,87 +113,6 @@ bool FileAccessAndroid::eof_reached() const {
return eof;
}
-uint8_t FileAccessAndroid::get_8() const {
- if (pos >= len) {
- eof = true;
- return 0;
- }
-
- uint8_t byte;
- AAsset_read(asset, &byte, 1);
- pos++;
- return byte;
-}
-
-uint16_t FileAccessAndroid::get_16() const {
- if (pos >= len) {
- eof = true;
- return 0;
- }
-
- uint16_t bytes = 0;
- int r = AAsset_read(asset, &bytes, 2);
-
- if (r >= 0) {
- pos += r;
- if (pos >= len) {
- eof = true;
- }
- }
-
- if (big_endian) {
- bytes = BSWAP16(bytes);
- }
-
- return bytes;
-}
-
-uint32_t FileAccessAndroid::get_32() const {
- if (pos >= len) {
- eof = true;
- return 0;
- }
-
- uint32_t bytes = 0;
- int r = AAsset_read(asset, &bytes, 4);
-
- if (r >= 0) {
- pos += r;
- if (pos >= len) {
- eof = true;
- }
- }
-
- if (big_endian) {
- bytes = BSWAP32(bytes);
- }
-
- return bytes;
-}
-
-uint64_t FileAccessAndroid::get_64() const {
- if (pos >= len) {
- eof = true;
- return 0;
- }
-
- uint64_t bytes = 0;
- int r = AAsset_read(asset, &bytes, 8);
-
- if (r >= 0) {
- pos += r;
- if (pos >= len) {
- eof = true;
- }
- }
-
- if (big_endian) {
- bytes = BSWAP64(bytes);
- }
-
- return bytes;
-}
-
uint64_t FileAccessAndroid::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
@@ -209,6 +128,7 @@ uint64_t FileAccessAndroid::get_buffer(uint8_t *p_dst, uint64_t p_length) const
pos = len;
}
}
+
return r;
}
@@ -220,19 +140,7 @@ void FileAccessAndroid::flush() {
ERR_FAIL();
}
-void FileAccessAndroid::store_8(uint8_t p_dest) {
- ERR_FAIL();
-}
-
-void FileAccessAndroid::store_16(uint16_t p_dest) {
- ERR_FAIL();
-}
-
-void FileAccessAndroid::store_32(uint32_t p_dest) {
- ERR_FAIL();
-}
-
-void FileAccessAndroid::store_64(uint64_t p_dest) {
+void FileAccessAndroid::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL();
}
diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h
index b465a92c78..3224ab50b9 100644
--- a/platform/android/file_access_android.h
+++ b/platform/android/file_access_android.h
@@ -68,19 +68,12 @@ public:
virtual bool eof_reached() const override; // reading passed EOF
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
- virtual uint8_t get_8() const override; // get a byte
- virtual uint16_t get_16() const override;
- virtual uint32_t get_32() const override;
- virtual uint64_t get_64() const override;
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
virtual Error get_error() const override; // get last error
virtual void flush() override;
- virtual void store_8(uint8_t p_dest) override; // store a byte
- virtual void store_16(uint16_t p_dest) override;
- virtual void store_32(uint32_t p_dest) override;
- virtual void store_64(uint64_t p_dest) override;
+ virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool file_exists(const String &p_path) override; // return true if a file exists
diff --git a/platform/android/file_access_filesystem_jandroid.cpp b/platform/android/file_access_filesystem_jandroid.cpp
index 9ae48dfb10..8b52a00ed8 100644
--- a/platform/android/file_access_filesystem_jandroid.cpp
+++ b/platform/android/file_access_filesystem_jandroid.cpp
@@ -169,43 +169,6 @@ void FileAccessFilesystemJAndroid::_set_eof(bool eof) {
}
}
-uint8_t FileAccessFilesystemJAndroid::get_8() const {
- ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
- uint8_t byte;
- get_buffer(&byte, 1);
- return byte;
-}
-
-uint16_t FileAccessFilesystemJAndroid::get_16() const {
- ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
- uint16_t bytes = 0;
- get_buffer(reinterpret_cast<uint8_t *>(&bytes), 2);
- if (big_endian) {
- bytes = BSWAP16(bytes);
- }
- return bytes;
-}
-
-uint32_t FileAccessFilesystemJAndroid::get_32() const {
- ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
- uint32_t bytes = 0;
- get_buffer(reinterpret_cast<uint8_t *>(&bytes), 4);
- if (big_endian) {
- bytes = BSWAP32(bytes);
- }
- return bytes;
-}
-
-uint64_t FileAccessFilesystemJAndroid::get_64() const {
- ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
- uint64_t bytes = 0;
- get_buffer(reinterpret_cast<uint8_t *>(&bytes), 8);
- if (big_endian) {
- bytes = BSWAP64(bytes);
- }
- return bytes;
-}
-
String FileAccessFilesystemJAndroid::get_line() const {
ERR_FAIL_COND_V_MSG(!is_open(), String(), "File must be opened before use.");
@@ -271,31 +234,6 @@ uint64_t FileAccessFilesystemJAndroid::get_buffer(uint8_t *p_dst, uint64_t p_len
}
}
-void FileAccessFilesystemJAndroid::store_8(uint8_t p_dest) {
- store_buffer(&p_dest, 1);
-}
-
-void FileAccessFilesystemJAndroid::store_16(uint16_t p_dest) {
- if (big_endian) {
- p_dest = BSWAP16(p_dest);
- }
- store_buffer(reinterpret_cast<uint8_t *>(&p_dest), 2);
-}
-
-void FileAccessFilesystemJAndroid::store_32(uint32_t p_dest) {
- if (big_endian) {
- p_dest = BSWAP32(p_dest);
- }
- store_buffer(reinterpret_cast<uint8_t *>(&p_dest), 4);
-}
-
-void FileAccessFilesystemJAndroid::store_64(uint64_t p_dest) {
- if (big_endian) {
- p_dest = BSWAP64(p_dest);
- }
- store_buffer(reinterpret_cast<uint8_t *>(&p_dest), 8);
-}
-
void FileAccessFilesystemJAndroid::store_buffer(const uint8_t *p_src, uint64_t p_length) {
if (_file_write) {
ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use.");
diff --git a/platform/android/file_access_filesystem_jandroid.h b/platform/android/file_access_filesystem_jandroid.h
index 2795ac02ac..1345b72fa6 100644
--- a/platform/android/file_access_filesystem_jandroid.h
+++ b/platform/android/file_access_filesystem_jandroid.h
@@ -78,20 +78,12 @@ public:
virtual bool eof_reached() const override; ///< reading passed EOF
virtual Error resize(int64_t p_length) override;
- virtual uint8_t get_8() const override; ///< get a byte
- virtual uint16_t get_16() const override;
- virtual uint32_t get_32() const override;
- virtual uint64_t get_64() const override;
virtual String get_line() const override; ///< get a line
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
virtual Error get_error() const override; ///< get last error
virtual void flush() override;
- virtual void store_8(uint8_t p_dest) override; ///< store a byte
- virtual void store_16(uint16_t p_dest) override;
- virtual void store_32(uint32_t p_dest) override;
- virtual void store_64(uint64_t p_dest) override;
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool file_exists(const String &p_path) override; ///< return true if a file exists
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index d2a9c2315f..92ac921cee 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -649,6 +649,61 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
env.AppendUnique(LINKFLAGS=["/STACK:" + str(STACK_SIZE)])
+def get_ar_version(env):
+ ret = {
+ "major": -1,
+ "minor": -1,
+ "patch": -1,
+ "is_llvm": False,
+ }
+ try:
+ output = (
+ subprocess.check_output([env.subst(env["AR"]), "--version"], shell=(os.name == "nt"))
+ .strip()
+ .decode("utf-8")
+ )
+ except (subprocess.CalledProcessError, OSError):
+ print_warning("Couldn't check version of `ar`.")
+ return ret
+
+ match = re.search(r"GNU ar \(GNU Binutils\) (\d+)\.(\d+)(:?\.(\d+))?", output)
+ if match:
+ ret["major"] = int(match[1])
+ ret["minor"] = int(match[2])
+ if match[3]:
+ ret["patch"] = int(match[3])
+ else:
+ ret["patch"] = 0
+ return ret
+
+ match = re.search(r"LLVM version (\d+)\.(\d+)\.(\d+)", output)
+ if match:
+ ret["major"] = int(match[1])
+ ret["minor"] = int(match[2])
+ ret["patch"] = int(match[3])
+ ret["is_llvm"] = True
+ return ret
+
+ print_warning("Couldn't parse version of `ar`.")
+ return ret
+
+
+def get_is_ar_thin_supported(env):
+ """Check whether `ar --thin` is supported. It is only supported since Binutils 2.38 or LLVM 14."""
+ ar_version = get_ar_version(env)
+ if ar_version["major"] == -1:
+ return False
+
+ if ar_version["is_llvm"]:
+ return ar_version["major"] >= 14
+
+ if ar_version["major"] == 2:
+ return ar_version["minor"] >= 38
+
+ print_warning("Unknown Binutils `ar` version.")
+ return False
+
+
def configure_mingw(env: "SConsEnvironment"):
# Workaround for MinGW. See:
# https://www.scons.org/wiki/LongCmdLinesOnWin32
@@ -781,7 +836,8 @@ def configure_mingw(env: "SConsEnvironment"):
if env["use_llvm"] and os.name == "nt" and methods._colorize:
env.Append(CCFLAGS=["$(-fansi-escape-codes$)", "$(-fcolor-diagnostics$)"])
- env.Append(ARFLAGS=["--thin"])
+ if get_is_ar_thin_supported(env):
+ env.Append(ARFLAGS=["--thin"])
env.Append(CPPDEFINES=["WINDOWS_ENABLED", "WASAPI_ENABLED", "WINMIDI_ENABLED"])
env.Append(
diff --git a/scene/animation/animation_mixer.cpp b/scene/animation/animation_mixer.cpp
index 20dd12f8c3..0ab4dbe470 100644
--- a/scene/animation/animation_mixer.cpp
+++ b/scene/animation/animation_mixer.cpp
@@ -947,14 +947,6 @@ void AnimationMixer::_process_animation(double p_delta, bool p_update_only) {
clear_animation_instances();
}
-Variant AnimationMixer::post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, ObjectID p_object_id, int p_object_sub_idx) {
- Variant res;
- if (GDVIRTUAL_CALL(_post_process_key_value, p_anim, p_track, p_value, p_object_id, p_object_sub_idx, res)) {
- return res;
- }
- return _post_process_key_value(p_anim, p_track, p_value, p_object_id, p_object_sub_idx);
-}
-
Variant AnimationMixer::_post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, ObjectID p_object_id, int p_object_sub_idx) {
#ifndef _3D_DISABLED
switch (p_anim->track_get_type(p_track)) {
@@ -974,6 +966,17 @@ Variant AnimationMixer::_post_process_key_value(const Ref<Animation> &p_anim, in
return p_value;
}
+Variant AnimationMixer::post_process_key_value(const Ref<Animation> &p_anim, int p_track, Variant p_value, ObjectID p_object_id, int p_object_sub_idx) {
+ if (is_GDVIRTUAL_CALL_post_process_key_value) {
+ Variant res;
+ if (GDVIRTUAL_CALL(_post_process_key_value, p_anim, p_track, p_value, p_object_id, p_object_sub_idx, res)) {
+ return res;
+ }
+ is_GDVIRTUAL_CALL_post_process_key_value = false;
+ }
+ return _post_process_key_value(p_anim, p_track, p_value, p_object_id, p_object_sub_idx);
+}
+
void AnimationMixer::_blend_init() {
// Check all tracks, see if they need modification.
root_motion_position = Vector3(0, 0, 0);
@@ -1080,22 +1083,26 @@ void AnimationMixer::_blend_calc_total_weight() {
for (const AnimationInstance &ai : animation_instances) {
Ref<Animation> a = ai.animation_data.animation;
real_t weight = ai.playback_info.weight;
- Vector<real_t> track_weights = ai.playback_info.track_weights;
- Vector<Animation::TypeHash> processed_hashes;
- for (int i = 0; i < a->get_track_count(); i++) {
- if (!a->track_is_enabled(i)) {
+ const real_t *track_weights_ptr = ai.playback_info.track_weights.ptr();
+ int track_weights_count = ai.playback_info.track_weights.size();
+ static LocalVector<Animation::TypeHash> processed_hashes;
+ processed_hashes.clear();
+ const Vector<Animation::Track *> tracks = a->get_tracks();
+ for (const Animation::Track *animation_track : tracks) {
+ if (!animation_track->enabled) {
continue;
}
- Animation::TypeHash thash = a->track_get_type_hash(i);
- if (!track_cache.has(thash) || processed_hashes.has(thash)) {
+ Animation::TypeHash thash = animation_track->thash;
+ TrackCache **track_ptr = track_cache.getptr(thash);
+ if (track_ptr == nullptr || processed_hashes.has(thash)) {
// No path, but avoid error spamming.
// Or, there is the case different track type with same path; These can be distinguished by hash. So don't add the weight doubly.
continue;
}
- TrackCache *track = track_cache[thash];
+ TrackCache *track = *track_ptr;
int blend_idx = track_map[track->path];
ERR_CONTINUE(blend_idx < 0 || blend_idx >= track_count);
- real_t blend = blend_idx < track_weights.size() ? track_weights[blend_idx] * weight : weight;
+ real_t blend = blend_idx < track_weights_count ? track_weights_ptr[blend_idx] * weight : weight;
track->total_weight += blend;
processed_hashes.push_back(thash);
}
@@ -1115,26 +1122,33 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
Animation::LoopedFlag looped_flag = ai.playback_info.looped_flag;
bool is_external_seeking = ai.playback_info.is_external_seeking;
real_t weight = ai.playback_info.weight;
- Vector<real_t> track_weights = ai.playback_info.track_weights;
+ const real_t *track_weights_ptr = ai.playback_info.track_weights.ptr();
+ int track_weights_count = ai.playback_info.track_weights.size();
bool backward = signbit(delta); // This flag is used by the root motion calculates or detecting the end of audio stream.
bool seeked_backward = signbit(p_delta);
#ifndef _3D_DISABLED
bool calc_root = !seeked || is_external_seeking;
#endif // _3D_DISABLED
-
- for (int i = 0; i < a->get_track_count(); i++) {
- if (!a->track_is_enabled(i)) {
+ const Vector<Animation::Track *> tracks = a->get_tracks();
+ Animation::Track *const *tracks_ptr = tracks.ptr();
+ real_t a_length = a->get_length();
+ int count = tracks.size();
+ for (int i = 0; i < count; i++) {
+ const Animation::Track *animation_track = tracks_ptr[i];
+ if (!animation_track->enabled) {
continue;
}
- Animation::TypeHash thash = a->track_get_type_hash(i);
- if (!track_cache.has(thash)) {
+ Animation::TypeHash thash = animation_track->thash;
+ TrackCache **track_ptr = track_cache.getptr(thash);
+ if (track_ptr == nullptr) {
continue; // No path, but avoid error spamming.
}
- TrackCache *track = track_cache[thash];
- ERR_CONTINUE(!track_map.has(track->path));
- int blend_idx = track_map[track->path];
+ TrackCache *track = *track_ptr;
+ int *blend_idx_ptr = track_map.getptr(track->path);
+ ERR_CONTINUE(blend_idx_ptr == nullptr);
+ int blend_idx = *blend_idx_ptr;
ERR_CONTINUE(blend_idx < 0 || blend_idx >= track_count);
- real_t blend = blend_idx < track_weights.size() ? track_weights[blend_idx] * weight : weight;
+ real_t blend = blend_idx < track_weights_count ? track_weights_ptr[blend_idx] * weight : weight;
if (!deterministic) {
// If non-deterministic, do normalization.
// It would be better to make this if statement outside the for loop, but come here since too much code...
@@ -1143,8 +1157,8 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
}
blend = blend / track->total_weight;
}
- Animation::TrackType ttype = a->track_get_type(i);
- track->root_motion = root_motion_track == a->track_get_path(i);
+ Animation::TrackType ttype = animation_track->type;
+ track->root_motion = root_motion_track == animation_track->path;
switch (ttype) {
case Animation::TYPE_POSITION_3D: {
#ifndef _3D_DISABLED
@@ -1161,26 +1175,26 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
prev_time = 0;
} break;
case Animation::LOOP_LINEAR: {
- prev_time = Math::fposmod(prev_time, (double)a->get_length());
+ prev_time = Math::fposmod(prev_time, (double)a_length);
} break;
case Animation::LOOP_PINGPONG: {
- prev_time = Math::pingpong(prev_time, (double)a->get_length());
+ prev_time = Math::pingpong(prev_time, (double)a_length);
} break;
default:
break;
}
}
} else {
- if (Animation::is_greater_approx(prev_time, (double)a->get_length())) {
+ if (Animation::is_greater_approx(prev_time, (double)a_length)) {
switch (a->get_loop_mode()) {
case Animation::LOOP_NONE: {
- prev_time = (double)a->get_length();
+ prev_time = (double)a_length;
} break;
case Animation::LOOP_LINEAR: {
- prev_time = Math::fposmod(prev_time, (double)a->get_length());
+ prev_time = Math::fposmod(prev_time, (double)a_length);
} break;
case Animation::LOOP_PINGPONG: {
- prev_time = Math::pingpong(prev_time, (double)a->get_length());
+ prev_time = Math::pingpong(prev_time, (double)a_length);
} break;
default:
break;
@@ -1195,7 +1209,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
continue;
}
loc[0] = post_process_key_value(a, i, loc[0], t->object_id, t->bone_idx);
- a->try_position_track_interpolate(i, (double)a->get_length(), &loc[1]);
+ a->try_position_track_interpolate(i, (double)a_length, &loc[1]);
loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx);
root_motion_cache.loc += (loc[1] - loc[0]) * blend;
prev_time = 0;
@@ -1210,7 +1224,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
a->try_position_track_interpolate(i, 0, &loc[1]);
loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx);
root_motion_cache.loc += (loc[1] - loc[0]) * blend;
- prev_time = (double)a->get_length();
+ prev_time = (double)a_length;
}
}
Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]);
@@ -1221,7 +1235,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
a->try_position_track_interpolate(i, time, &loc[1]);
loc[1] = post_process_key_value(a, i, loc[1], t->object_id, t->bone_idx);
root_motion_cache.loc += (loc[1] - loc[0]) * blend;
- prev_time = !backward ? 0 : (double)a->get_length();
+ prev_time = !backward ? 0 : (double)a_length;
}
{
Vector3 loc;
@@ -1249,26 +1263,26 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
prev_time = 0;
} break;
case Animation::LOOP_LINEAR: {
- prev_time = Math::fposmod(prev_time, (double)a->get_length());
+ prev_time = Math::fposmod(prev_time, (double)a_length);
} break;
case Animation::LOOP_PINGPONG: {
- prev_time = Math::pingpong(prev_time, (double)a->get_length());
+ prev_time = Math::pingpong(prev_time, (double)a_length);
} break;
default:
break;
}
}
} else {
- if (Animation::is_greater_approx(prev_time, (double)a->get_length())) {
+ if (Animation::is_greater_approx(prev_time, (double)a_length)) {
switch (a->get_loop_mode()) {
case Animation::LOOP_NONE: {
- prev_time = (double)a->get_length();
+ prev_time = (double)a_length;
} break;
case Animation::LOOP_LINEAR: {
- prev_time = Math::fposmod(prev_time, (double)a->get_length());
+ prev_time = Math::fposmod(prev_time, (double)a_length);
} break;
case Animation::LOOP_PINGPONG: {
- prev_time = Math::pingpong(prev_time, (double)a->get_length());
+ prev_time = Math::pingpong(prev_time, (double)a_length);
} break;
default:
break;
@@ -1283,7 +1297,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
continue;
}
rot[0] = post_process_key_value(a, i, rot[0], t->object_id, t->bone_idx);
- a->try_rotation_track_interpolate(i, (double)a->get_length(), &rot[1]);
+ a->try_rotation_track_interpolate(i, (double)a_length, &rot[1]);
rot[1] = post_process_key_value(a, i, rot[1], t->object_id, t->bone_idx);
root_motion_cache.rot = (root_motion_cache.rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized();
prev_time = 0;
@@ -1297,7 +1311,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
rot[0] = post_process_key_value(a, i, rot[0], t->object_id, t->bone_idx);
a->try_rotation_track_interpolate(i, 0, &rot[1]);
root_motion_cache.rot = (root_motion_cache.rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized();
- prev_time = (double)a->get_length();
+ prev_time = (double)a_length;
}
}
Error err = a->try_rotation_track_interpolate(i, prev_time, &rot[0]);
@@ -1308,7 +1322,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
a->try_rotation_track_interpolate(i, time, &rot[1]);
rot[1] = post_process_key_value(a, i, rot[1], t->object_id, t->bone_idx);
root_motion_cache.rot = (root_motion_cache.rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized();
- prev_time = !backward ? 0 : (double)a->get_length();
+ prev_time = !backward ? 0 : (double)a_length;
}
{
Quaternion rot;
@@ -1336,26 +1350,26 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
prev_time = 0;
} break;
case Animation::LOOP_LINEAR: {
- prev_time = Math::fposmod(prev_time, (double)a->get_length());
+ prev_time = Math::fposmod(prev_time, (double)a_length);
} break;
case Animation::LOOP_PINGPONG: {
- prev_time = Math::pingpong(prev_time, (double)a->get_length());
+ prev_time = Math::pingpong(prev_time, (double)a_length);
} break;
default:
break;
}
}
} else {
- if (Animation::is_greater_approx(prev_time, (double)a->get_length())) {
+ if (Animation::is_greater_approx(prev_time, (double)a_length)) {
switch (a->get_loop_mode()) {
case Animation::LOOP_NONE: {
- prev_time = (double)a->get_length();
+ prev_time = (double)a_length;
} break;
case Animation::LOOP_LINEAR: {
- prev_time = Math::fposmod(prev_time, (double)a->get_length());
+ prev_time = Math::fposmod(prev_time, (double)a_length);
} break;
case Animation::LOOP_PINGPONG: {
- prev_time = Math::pingpong(prev_time, (double)a->get_length());
+ prev_time = Math::pingpong(prev_time, (double)a_length);
} break;
default:
break;
@@ -1370,7 +1384,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
continue;
}
scale[0] = post_process_key_value(a, i, scale[0], t->object_id, t->bone_idx);
- a->try_scale_track_interpolate(i, (double)a->get_length(), &scale[1]);
+ a->try_scale_track_interpolate(i, (double)a_length, &scale[1]);
root_motion_cache.scale += (scale[1] - scale[0]) * blend;
scale[1] = post_process_key_value(a, i, scale[1], t->object_id, t->bone_idx);
prev_time = 0;
@@ -1385,7 +1399,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
a->try_scale_track_interpolate(i, 0, &scale[1]);
scale[1] = post_process_key_value(a, i, scale[1], t->object_id, t->bone_idx);
root_motion_cache.scale += (scale[1] - scale[0]) * blend;
- prev_time = (double)a->get_length();
+ prev_time = (double)a_length;
}
}
Error err = a->try_scale_track_interpolate(i, prev_time, &scale[0]);
@@ -1396,7 +1410,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
a->try_scale_track_interpolate(i, time, &scale[1]);
scale[1] = post_process_key_value(a, i, scale[1], t->object_id, t->bone_idx);
root_motion_cache.scale += (scale[1] - scale[0]) * blend;
- prev_time = !backward ? 0 : (double)a->get_length();
+ prev_time = !backward ? 0 : (double)a_length;
}
{
Vector3 scale;
@@ -1560,7 +1574,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
}
PlayingAudioTrackInfo &track_info = t->playing_streams[oid];
- track_info.length = a->get_length();
+ track_info.length = a_length;
track_info.time = time;
track_info.volume += blend;
track_info.loop = a->get_loop_mode() != Animation::LOOP_NONE;
@@ -1679,7 +1693,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
at_anim_pos = Math::fposmod(time - pos, (double)anim->get_length()); // Seek to loop.
} break;
case Animation::LOOP_PINGPONG: {
- at_anim_pos = Math::pingpong(time - pos, (double)a->get_length());
+ at_anim_pos = Math::pingpong(time - pos, (double)a_length);
} break;
default:
break;
@@ -1717,6 +1731,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
}
}
}
+ is_GDVIRTUAL_CALL_post_process_key_value = true;
}
void AnimationMixer::_blend_apply() {
diff --git a/scene/animation/animation_mixer.h b/scene/animation/animation_mixer.h
index c029c68ae1..5482197fbd 100644
--- a/scene/animation/animation_mixer.h
+++ b/scene/animation/animation_mixer.h
@@ -48,6 +48,7 @@ class AnimationMixer : public Node {
#endif // TOOLS_ENABLED
bool reset_on_save = true;
+ bool is_GDVIRTUAL_CALL_post_process_key_value = true;
public:
enum AnimationCallbackModeProcess {
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index c5a6a99d07..867bbda4b3 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -203,10 +203,11 @@ AnimationNode::NodeTimeInfo AnimationNode::_blend_node(Ref<AnimationNode> p_node
}
for (const KeyValue<NodePath, bool> &E : filter) {
- if (!process_state->track_map.has(E.key)) {
+ const HashMap<NodePath, int> &map = *process_state->track_map;
+ if (!map.has(E.key)) {
continue;
}
- int idx = process_state->track_map[E.key];
+ int idx = map[E.key];
blendw[idx] = 1.0; // Filtered goes to one.
}
@@ -618,7 +619,7 @@ bool AnimationTree::_blend_pre_process(double p_delta, int p_track_count, const
process_state.valid = true;
process_state.invalid_reasons = "";
process_state.last_pass = process_pass;
- process_state.track_map = p_track_map;
+ process_state.track_map = &p_track_map;
// Init node state for root AnimationNode.
root_animation_node->node_state.track_weights.resize(p_track_count);
diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h
index aa497ff1d6..d4b7bf31c9 100644
--- a/scene/animation/animation_tree.h
+++ b/scene/animation/animation_tree.h
@@ -106,7 +106,7 @@ public:
// Temporary state for blending process which needs to be started in the AnimationTree, pass through the AnimationNodes, and then return to the AnimationTree.
struct ProcessState {
AnimationTree *tree = nullptr;
- HashMap<NodePath, int> track_map; // TODO: Is there a better way to manage filter/tracks?
+ const HashMap<NodePath, int> *track_map; // TODO: Is there a better way to manage filter/tracks?
bool is_testing = false;
bool valid = false;
String invalid_reasons;
diff --git a/scene/resources/animation.h b/scene/resources/animation.h
index 9e6d34959a..0c29790ea4 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -45,7 +45,7 @@ public:
static inline String PARAMETERS_BASE_PATH = "parameters/";
- enum TrackType {
+ enum TrackType : uint8_t {
TYPE_VALUE, // Set a value in a property, can be interpolated.
TYPE_POSITION_3D, // Position 3D track, can be compressed.
TYPE_ROTATION_3D, // Rotation 3D track, can be compressed.
@@ -57,7 +57,7 @@ public:
TYPE_ANIMATION,
};
- enum InterpolationType {
+ enum InterpolationType : uint8_t {
INTERPOLATION_NEAREST,
INTERPOLATION_LINEAR,
INTERPOLATION_CUBIC,
@@ -65,26 +65,26 @@ public:
INTERPOLATION_CUBIC_ANGLE,
};
- enum UpdateMode {
+ enum UpdateMode : uint8_t {
UPDATE_CONTINUOUS,
UPDATE_DISCRETE,
UPDATE_CAPTURE,
};
- enum LoopMode {
+ enum LoopMode : uint8_t {
LOOP_NONE,
LOOP_LINEAR,
LOOP_PINGPONG,
};
// LoopedFlag is used in Animataion to "process the keys at both ends correct".
- enum LoopedFlag {
+ enum LoopedFlag : uint8_t {
LOOPED_FLAG_NONE,
LOOPED_FLAG_END,
LOOPED_FLAG_START,
};
- enum FindMode {
+ enum FindMode : uint8_t {
FIND_MODE_NEAREST,
FIND_MODE_APPROX,
FIND_MODE_EXACT,
@@ -104,7 +104,6 @@ public:
};
#endif // TOOLS_ENABLED
-private:
struct Track {
TrackType type = TrackType::TYPE_ANIMATION;
InterpolationType interpolation = INTERPOLATION_LINEAR;
@@ -117,6 +116,7 @@ private:
virtual ~Track() {}
};
+private:
struct Key {
real_t transition = 1.0;
double time = 0.0; // Time in secs.
@@ -396,6 +396,10 @@ public:
int add_track(TrackType p_type, int p_at_pos = -1);
void remove_track(int p_track);
+ _FORCE_INLINE_ const Vector<Track *> get_tracks() {
+ return tracks;
+ }
+
bool is_capture_included() const;
int get_track_count() const;
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index 6e5e8f63e0..be29716f45 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -1470,8 +1470,24 @@ void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) {
tinfo.format = t->format;
tinfo.width = t->width;
tinfo.height = t->height;
- tinfo.depth = t->depth;
- tinfo.bytes = Image::get_image_data_size(t->width, t->height, t->format, t->mipmaps);
+ tinfo.bytes = Image::get_image_data_size(t->width, t->height, t->format, t->mipmaps > 1);
+
+ switch (t->type) {
+ case TextureType::TYPE_3D:
+ tinfo.depth = t->depth;
+ tinfo.bytes *= t->depth;
+ break;
+
+ case TextureType::TYPE_LAYERED:
+ tinfo.depth = t->layers;
+ tinfo.bytes *= t->layers;
+ break;
+
+ default:
+ tinfo.depth = 0;
+ break;
+ }
+
r_info->push_back(tinfo);
}
}
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 92f0f0dbc0..1848d5602e 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -3263,6 +3263,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_item_set_z_index", "item", "z_index"), &RenderingServer::canvas_item_set_z_index);
ClassDB::bind_method(D_METHOD("canvas_item_set_z_as_relative_to_parent", "item", "enabled"), &RenderingServer::canvas_item_set_z_as_relative_to_parent);
ClassDB::bind_method(D_METHOD("canvas_item_set_copy_to_backbuffer", "item", "enabled", "rect"), &RenderingServer::canvas_item_set_copy_to_backbuffer);
+ ClassDB::bind_method(D_METHOD("canvas_item_attach_skeleton", "item", "skeleton"), &RenderingServer::canvas_item_attach_skeleton);
ClassDB::bind_method(D_METHOD("canvas_item_clear", "item"), &RenderingServer::canvas_item_clear);
ClassDB::bind_method(D_METHOD("canvas_item_set_draw_index", "item", "index"), &RenderingServer::canvas_item_set_draw_index);
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index d8b6651833..62ca6b3b6d 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -176,7 +176,7 @@ public:
uint32_t height;
uint32_t depth;
Image::Format format;
- int bytes;
+ int64_t bytes;
String path;
};
diff --git a/thirdparty/thorvg/inc/config.h b/thirdparty/thorvg/inc/config.h
index 67ebc9381e..02fec07448 100644
--- a/thirdparty/thorvg/inc/config.h
+++ b/thirdparty/thorvg/inc/config.h
@@ -15,5 +15,5 @@
// For internal debugging:
//#define THORVG_LOG_ENABLED
-#define THORVG_VERSION_STRING "0.14.7"
+#define THORVG_VERSION_STRING "0.14.8"
#endif
diff --git a/thirdparty/thorvg/patches/pr2702-sw_engine-handle-small-cubics.patch b/thirdparty/thorvg/patches/pr2702-sw_engine-handle-small-cubics.patch
new file mode 100644
index 0000000000..69f4a5cf85
--- /dev/null
+++ b/thirdparty/thorvg/patches/pr2702-sw_engine-handle-small-cubics.patch
@@ -0,0 +1,96 @@
+From ac7d208ed8e4651c93ce1b2384070fccac9b6cb6 Mon Sep 17 00:00:00 2001
+From: Mira Grudzinska <mira@lottiefiles.com>
+Date: Sun, 1 Sep 2024 22:36:18 +0200
+Subject: [PATCH] sw_engine: handle small cubics
+
+During the stroke's outline calculation, the function
+handling small cubics set all angles to zero. Such cases
+should be ignored, as further processing caused errors -
+when the cubic was small but not zero, setting the angles
+to zero resulted in incorrect outlines.
+
+@Issue: https://github.com/godotengine/godot/issues/96262
+---
+ src/renderer/sw_engine/tvgSwCommon.h | 3 ++-
+ src/renderer/sw_engine/tvgSwMath.cpp | 19 ++++++++++++-------
+ src/renderer/sw_engine/tvgSwStroke.cpp | 16 +++++++++++-----
+ 3 files changed, 25 insertions(+), 13 deletions(-)
+
+diff --git a/src/renderer/sw_engine/tvgSwCommon.h b/src/renderer/sw_engine/tvgSwCommon.h
+index 893e9beca..158fe8ecd 100644
+--- a/src/renderer/sw_engine/tvgSwCommon.h
++++ b/src/renderer/sw_engine/tvgSwCommon.h
+@@ -491,7 +491,8 @@ SwFixed mathSin(SwFixed angle);
+ void mathSplitCubic(SwPoint* base);
+ SwFixed mathDiff(SwFixed angle1, SwFixed angle2);
+ SwFixed mathLength(const SwPoint& pt);
+-bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut);
++bool mathSmallCubic(const SwPoint* base);
++bool mathFlatCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut);
+ SwFixed mathMean(SwFixed angle1, SwFixed angle2);
+ SwPoint mathTransform(const Point* to, const Matrix& transform);
+ bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, SwBBox& renderRegion, bool fastTrack);
+diff --git a/src/renderer/sw_engine/tvgSwMath.cpp b/src/renderer/sw_engine/tvgSwMath.cpp
+index 1093edd62..b311be05f 100644
+--- a/src/renderer/sw_engine/tvgSwMath.cpp
++++ b/src/renderer/sw_engine/tvgSwMath.cpp
+@@ -44,7 +44,17 @@ SwFixed mathMean(SwFixed angle1, SwFixed angle2)
+ }
+
+
+-bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut)
++bool mathSmallCubic(const SwPoint* base)
++{
++ auto d1 = base[2] - base[3];
++ auto d2 = base[1] - base[2];
++ auto d3 = base[0] - base[1];
++
++ return d1.small() && d2.small() && d3.small();
++}
++
++
++bool mathFlatCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut)
+ {
+ auto d1 = base[2] - base[3];
+ auto d2 = base[1] - base[2];
+@@ -52,12 +62,7 @@ bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, Sw
+
+ if (d1.small()) {
+ if (d2.small()) {
+- if (d3.small()) {
+- angleIn = angleMid = angleOut = 0;
+- return true;
+- } else {
+- angleIn = angleMid = angleOut = mathAtan(d3);
+- }
++ angleIn = angleMid = angleOut = mathAtan(d3);
+ } else {
+ if (d3.small()) {
+ angleIn = angleMid = angleOut = mathAtan(d2);
+diff --git a/src/renderer/sw_engine/tvgSwStroke.cpp b/src/renderer/sw_engine/tvgSwStroke.cpp
+index 575d12951..4679b72cc 100644
+--- a/src/renderer/sw_engine/tvgSwStroke.cpp
++++ b/src/renderer/sw_engine/tvgSwStroke.cpp
+@@ -441,11 +441,17 @@ static void _cubicTo(SwStroke& stroke, const SwPoint& ctrl1, const SwPoint& ctrl
+ //initialize with current direction
+ angleIn = angleOut = angleMid = stroke.angleIn;
+
+- if (arc < limit && !mathSmallCubic(arc, angleIn, angleMid, angleOut)) {
+- if (stroke.firstPt) stroke.angleIn = angleIn;
+- mathSplitCubic(arc);
+- arc += 3;
+- continue;
++ if (arc < limit) {
++ if (mathSmallCubic(arc)) {
++ arc -= 3;
++ continue;
++ }
++ if (!mathFlatCubic(arc, angleIn, angleMid, angleOut)) {
++ if (stroke.firstPt) stroke.angleIn = angleIn;
++ mathSplitCubic(arc);
++ arc += 3;
++ continue;
++ }
+ }
+
+ if (firstArc) {
diff --git a/thirdparty/thorvg/src/common/tvgMath.cpp b/thirdparty/thorvg/src/common/tvgMath.cpp
index c56b32249f..0254cce9b8 100644
--- a/thirdparty/thorvg/src/common/tvgMath.cpp
+++ b/thirdparty/thorvg/src/common/tvgMath.cpp
@@ -133,3 +133,11 @@ Point operator*(const Point& pt, const Matrix& m)
auto ty = pt.x * m.e21 + pt.y * m.e22 + m.e23;
return {tx, ty};
}
+
+uint8_t mathLerp(const uint8_t &start, const uint8_t &end, float t)
+{
+ auto result = static_cast<int>(start + (end - start) * t);
+ if (result > 255) result = 255;
+ else if (result < 0) result = 0;
+ return static_cast<uint8_t>(result);
+}
diff --git a/thirdparty/thorvg/src/common/tvgMath.h b/thirdparty/thorvg/src/common/tvgMath.h
index 556ed410ff..df39e3b9af 100644
--- a/thirdparty/thorvg/src/common/tvgMath.h
+++ b/thirdparty/thorvg/src/common/tvgMath.h
@@ -259,5 +259,6 @@ static inline T mathLerp(const T &start, const T &end, float t)
return static_cast<T>(start + (end - start) * t);
}
+uint8_t mathLerp(const uint8_t &start, const uint8_t &end, float t);
#endif //_TVG_MATH_H_
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp
index 197d3cc13a..5aab4f1b0d 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp
@@ -588,6 +588,11 @@ static bool _hslToRgb(float hue, float saturation, float brightness, uint8_t* re
float _red = 0, _green = 0, _blue = 0;
uint32_t i = 0;
+ while (hue < 0) hue += 360.0f;
+ hue = fmod(hue, 360.0f);
+ saturation = saturation > 0 ? std::min(saturation, 1.0f) : 0.0f;
+ brightness = brightness > 0 ? std::min(brightness, 1.0f) : 0.0f;
+
if (mathZero(saturation)) _red = _green = _blue = brightness;
else {
if (mathEqual(hue, 360.0)) hue = 0.0f;
@@ -714,7 +719,6 @@ static bool _toColor(const char* str, uint8_t* r, uint8_t* g, uint8_t* b, char**
const char* hue = nullptr;
if (_parseNumber(&content, &hue, &th) && hue) {
const char* saturation = nullptr;
- th = float(uint32_t(th) % 360);
hue = _skipSpace(hue, nullptr);
hue = (char*)_skipComma(hue);
hue = _skipSpace(hue, nullptr);
diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h
index 3229eb39ba..09b75d370b 100644
--- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h
+++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h
@@ -367,7 +367,7 @@ static inline uint32_t opBlendSrcOver(uint32_t s, TVG_UNUSED uint32_t d, TVG_UNU
}
//TODO: BlendMethod could remove the alpha parameter.
-static inline uint32_t opBlendDifference(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
+static inline uint32_t opBlendDifference(uint32_t s, uint32_t d, uint8_t a)
{
//if (s > d) => s - d
//else => d - s
@@ -404,8 +404,7 @@ static inline uint32_t opBlendScreen(uint32_t s, uint32_t d, TVG_UNUSED uint8_t
return JOIN(255, c1, c2, c3);
}
-
-static inline uint32_t opBlendMultiply(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
+static inline uint32_t opBlendDirectMultiply(uint32_t s, uint32_t d, uint8_t a)
{
// s * d
auto c1 = MULTIPLY(C1(s), C1(d));
@@ -414,6 +413,10 @@ static inline uint32_t opBlendMultiply(uint32_t s, uint32_t d, TVG_UNUSED uint8_
return JOIN(255, c1, c2, c3);
}
+static inline uint32_t opBlendMultiply(uint32_t s, uint32_t d, uint8_t a)
+{
+ return opBlendDirectMultiply(s, d, a) + ALPHA_BLEND(d, IA(s));
+}
static inline uint32_t opBlendOverlay(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
{
@@ -492,7 +495,8 @@ SwFixed mathSin(SwFixed angle);
void mathSplitCubic(SwPoint* base);
SwFixed mathDiff(SwFixed angle1, SwFixed angle2);
SwFixed mathLength(const SwPoint& pt);
-bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut);
+bool mathSmallCubic(const SwPoint* base);
+bool mathFlatCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut);
SwFixed mathMean(SwFixed angle1, SwFixed angle2);
SwPoint mathTransform(const Point* to, const Matrix& transform);
bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, SwBBox& renderRegion, bool fastTrack);
diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp
index fb809c4f7e..60dbbc4fbc 100644
--- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp
+++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp
@@ -44,7 +44,17 @@ SwFixed mathMean(SwFixed angle1, SwFixed angle2)
}
-bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut)
+bool mathSmallCubic(const SwPoint* base)
+{
+ auto d1 = base[2] - base[3];
+ auto d2 = base[1] - base[2];
+ auto d3 = base[0] - base[1];
+
+ return d1.small() && d2.small() && d3.small();
+}
+
+
+bool mathFlatCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut)
{
auto d1 = base[2] - base[3];
auto d2 = base[1] - base[2];
@@ -52,12 +62,7 @@ bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, Sw
if (d1.small()) {
if (d2.small()) {
- if (d3.small()) {
- angleIn = angleMid = angleOut = 0;
- return true;
- } else {
- angleIn = angleMid = angleOut = mathAtan(d3);
- }
+ angleIn = angleMid = angleOut = mathAtan(d3);
} else {
if (d3.small()) {
angleIn = angleMid = angleOut = mathAtan(d2);
diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp
index a6f9d8745a..90d91e17e0 100644
--- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp
+++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp
@@ -1383,7 +1383,7 @@ static bool _rasterDirectBlendingImage(SwSurface* surface, const SwImage* image,
*dst = INTERPOLATE(tmp, *dst, A(*src));
}
} else {
- for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++src) {
+ for (auto x = region.min.x; x < region.max.x; x++, dst++, src++) {
auto tmp = ALPHA_BLEND(*src, opacity);
auto tmp2 = surface->blender(tmp, *dst, 255);
*dst = INTERPOLATE(tmp2, *dst, A(tmp));
diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp
index 47a7166115..6470089c7c 100644
--- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp
+++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp
@@ -100,7 +100,6 @@ struct SwShapeTask : SwTask
return (width * sqrt(transform.e11 * transform.e11 + transform.e12 * transform.e12));
}
-
bool clip(SwRleData* target) override
{
if (shape.fastTrack) rleClipRect(target, &bbox);
@@ -447,7 +446,7 @@ bool SwRenderer::renderShape(RenderData data)
}
-bool SwRenderer::blend(BlendMethod method)
+bool SwRenderer::blend(BlendMethod method, bool direct)
{
if (surface->blendMethod == method) return true;
surface->blendMethod = method;
@@ -460,7 +459,7 @@ bool SwRenderer::blend(BlendMethod method)
surface->blender = opBlendScreen;
break;
case BlendMethod::Multiply:
- surface->blender = opBlendMultiply;
+ surface->blender = direct ? opBlendDirectMultiply : opBlendMultiply;
break;
case BlendMethod::Overlay:
surface->blender = opBlendOverlay;
diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.h b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.h
index fcd8ad4620..7aa6d89aaa 100644
--- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.h
+++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.h
@@ -46,7 +46,7 @@ public:
RenderRegion region(RenderData data) override;
RenderRegion viewport() override;
bool viewport(const RenderRegion& vp) override;
- bool blend(BlendMethod method) override;
+ bool blend(BlendMethod method, bool direct) override;
ColorSpace colorSpace() override;
const Surface* mainSurface() override;
diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwStroke.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwStroke.cpp
index 75ac96be04..e0e74ce53c 100644
--- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwStroke.cpp
+++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwStroke.cpp
@@ -441,11 +441,17 @@ static void _cubicTo(SwStroke& stroke, const SwPoint& ctrl1, const SwPoint& ctrl
//initialize with current direction
angleIn = angleOut = angleMid = stroke.angleIn;
- if (arc < limit && !mathSmallCubic(arc, angleIn, angleMid, angleOut)) {
- if (stroke.firstPt) stroke.angleIn = angleIn;
- mathSplitCubic(arc);
- arc += 3;
- continue;
+ if (arc < limit) {
+ if (mathSmallCubic(arc)) {
+ arc -= 3;
+ continue;
+ }
+ if (!mathFlatCubic(arc, angleIn, angleMid, angleOut)) {
+ if (stroke.firstPt) stroke.angleIn = angleIn;
+ mathSplitCubic(arc);
+ arc += 3;
+ continue;
+ }
}
if (firstArc) {
diff --git a/thirdparty/thorvg/src/renderer/tvgLoadModule.h b/thirdparty/thorvg/src/renderer/tvgLoadModule.h
index c750683771..1b81d81a4f 100644
--- a/thirdparty/thorvg/src/renderer/tvgLoadModule.h
+++ b/thirdparty/thorvg/src/renderer/tvgLoadModule.h
@@ -101,7 +101,8 @@ struct FontLoader : LoadModule
FontLoader(FileType type) : LoadModule(type) {}
- virtual bool request(Shape* shape, char* text, bool italic = false) = 0;
+ virtual bool request(Shape* shape, char* text) = 0;
+ virtual bool transform(Paint* paint, float fontSize, bool italic) = 0;
};
#endif //_TVG_LOAD_MODULE_H_
diff --git a/thirdparty/thorvg/src/renderer/tvgPaint.cpp b/thirdparty/thorvg/src/renderer/tvgPaint.cpp
index 11cee0c54a..37813b19ef 100644
--- a/thirdparty/thorvg/src/renderer/tvgPaint.cpp
+++ b/thirdparty/thorvg/src/renderer/tvgPaint.cpp
@@ -225,8 +225,6 @@ bool Paint::Impl::render(RenderMethod* renderer)
if (cmp) renderer->beginComposite(cmp, compData->method, compData->target->pImpl->opacity);
- renderer->blend(blendMethod);
-
bool ret;
PAINT_METHOD(ret, render(renderer));
diff --git a/thirdparty/thorvg/src/renderer/tvgPicture.cpp b/thirdparty/thorvg/src/renderer/tvgPicture.cpp
index 68c7a41032..e6653b1c99 100644
--- a/thirdparty/thorvg/src/renderer/tvgPicture.cpp
+++ b/thirdparty/thorvg/src/renderer/tvgPicture.cpp
@@ -73,6 +73,8 @@ bool Picture::Impl::needComposition(uint8_t opacity)
bool Picture::Impl::render(RenderMethod* renderer)
{
bool ret = false;
+ renderer->blend(picture->blend(), true);
+
if (surface) return renderer->renderImage(rd);
else if (paint) {
Compositor* cmp = nullptr;
diff --git a/thirdparty/thorvg/src/renderer/tvgRender.h b/thirdparty/thorvg/src/renderer/tvgRender.h
index b0ee42db8d..f1042884ec 100644
--- a/thirdparty/thorvg/src/renderer/tvgRender.h
+++ b/thirdparty/thorvg/src/renderer/tvgRender.h
@@ -296,7 +296,7 @@ public:
virtual RenderRegion region(RenderData data) = 0;
virtual RenderRegion viewport() = 0;
virtual bool viewport(const RenderRegion& vp) = 0;
- virtual bool blend(BlendMethod method) = 0;
+ virtual bool blend(BlendMethod method, bool direct = false) = 0;
virtual ColorSpace colorSpace() = 0;
virtual const Surface* mainSurface() = 0;
diff --git a/thirdparty/thorvg/src/renderer/tvgScene.h b/thirdparty/thorvg/src/renderer/tvgScene.h
index cb6d179326..190ecd31b9 100644
--- a/thirdparty/thorvg/src/renderer/tvgScene.h
+++ b/thirdparty/thorvg/src/renderer/tvgScene.h
@@ -120,6 +120,8 @@ struct Scene::Impl
Compositor* cmp = nullptr;
auto ret = true;
+ renderer->blend(scene->blend());
+
if (needComp) {
cmp = renderer->target(bounds(renderer), renderer->colorSpace());
renderer->beginComposite(cmp, CompositeMethod::None, opacity);
diff --git a/thirdparty/thorvg/src/renderer/tvgShape.h b/thirdparty/thorvg/src/renderer/tvgShape.h
index b76fde7ced..94704aee67 100644
--- a/thirdparty/thorvg/src/renderer/tvgShape.h
+++ b/thirdparty/thorvg/src/renderer/tvgShape.h
@@ -54,10 +54,13 @@ struct Shape::Impl
Compositor* cmp = nullptr;
bool ret;
+ renderer->blend(shape->blend(), !needComp);
+
if (needComp) {
cmp = renderer->target(bounds(renderer), renderer->colorSpace());
renderer->beginComposite(cmp, CompositeMethod::None, opacity);
}
+
ret = renderer->renderShape(rd);
if (cmp) renderer->endComposite(cmp);
return ret;
diff --git a/thirdparty/thorvg/src/renderer/tvgText.h b/thirdparty/thorvg/src/renderer/tvgText.h
index f6faec2d53..746b85bea6 100644
--- a/thirdparty/thorvg/src/renderer/tvgText.h
+++ b/thirdparty/thorvg/src/renderer/tvgText.h
@@ -26,12 +26,7 @@
#include <cstring>
#include "tvgShape.h"
#include "tvgFill.h"
-
-#ifdef THORVG_TTF_LOADER_SUPPORT
- #include "tvgTtfLoader.h"
-#else
- #include "tvgLoader.h"
-#endif
+#include "tvgLoader.h"
struct Text::Impl
{
@@ -69,6 +64,11 @@ struct Text::Impl
auto loader = LoaderMgr::loader(name);
if (!loader) return Result::InsufficientCondition;
+ if (style && strstr(style, "italic")) italic = true;
+ else italic = false;
+
+ fontSize = size;
+
//Same resource has been loaded.
if (this->loader == loader) {
this->loader->sharing--; //make it sure the reference counting.
@@ -78,8 +78,6 @@ struct Text::Impl
}
this->loader = static_cast<FontLoader*>(loader);
- fontSize = size;
- if (style && strstr(style, "italic")) italic = true;
changed = true;
return Result::Success;
}
@@ -91,6 +89,7 @@ struct Text::Impl
bool render(RenderMethod* renderer)
{
+ renderer->blend(paint->blend(), true);
return PP(shape)->render(renderer);
}
@@ -98,13 +97,13 @@ struct Text::Impl
{
if (!loader) return false;
+ loader->request(shape, utf8);
//reload
if (changed) {
- loader->request(shape, utf8, italic);
loader->read();
changed = false;
}
- return loader->resize(shape, fontSize, fontSize);
+ return loader->transform(shape, fontSize, italic);
}
RenderData update(RenderMethod* renderer, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, TVG_UNUSED bool clipper)
diff --git a/thirdparty/thorvg/update-thorvg.sh b/thirdparty/thorvg/update-thorvg.sh
index 7ff07fe4c2..51dc156661 100755
--- a/thirdparty/thorvg/update-thorvg.sh
+++ b/thirdparty/thorvg/update-thorvg.sh
@@ -1,16 +1,22 @@
#!/bin/bash -e
-VERSION=0.14.7
+VERSION=0.14.8
+# Uncomment and set a git hash to use specific commit instead of tag.
+#GIT_COMMIT=
-cd thirdparty/thorvg/ || true
+pushd "$(dirname "$0")"
rm -rf AUTHORS LICENSE inc/ src/ *.zip *.tar.gz tmp/
mkdir tmp/ && pushd tmp/
# Release
-curl -L -O https://github.com/thorvg/thorvg/archive/v$VERSION.tar.gz
-# Current Github main branch tip
-#curl -L -O https://github.com/thorvg/thorvg/archive/refs/heads/main.tar.gz
+if [ ! -z "$GIT_COMMIT" ]; then
+ echo "Updating ThorVG to commit:" $GIT_COMMIT
+ curl -L -O https://github.com/thorvg/thorvg/archive/$GIT_COMMIT.tar.gz
+else
+ echo "Updating ThorVG to tagged release:" $VERSION
+ curl -L -O https://github.com/thorvg/thorvg/archive/v$VERSION.tar.gz
+fi
tar --strip-components=1 -xvf *.tar.gz
rm *.tar.gz
@@ -70,4 +76,4 @@ cp -rv src/loaders/jpg ../src/loaders/
popd
rm -rf tmp
-
+popd