feat: modules moved and engine moved to submodule

This commit is contained in:
Jan van der Weide 2025-04-12 18:40:44 +02:00
parent dfb5e645cd
commit c33d2130cc
5136 changed files with 225275 additions and 64485 deletions

View file

@ -42,6 +42,12 @@
#include <brotli/decode.h>
#endif
// Caches for zstd.
static BinaryMutex mutex;
static ZSTD_DCtx *current_zstd_d_ctx = nullptr;
static bool current_zstd_long_distance_matching;
static int current_zstd_window_log_size;
int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size, Mode p_mode) {
switch (p_mode) {
case MODE_BROTLI: {
@ -187,12 +193,22 @@ int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p
return total;
} break;
case MODE_ZSTD: {
ZSTD_DCtx *dctx = ZSTD_createDCtx();
if (zstd_long_distance_matching) {
ZSTD_DCtx_setParameter(dctx, ZSTD_d_windowLogMax, zstd_window_log_size);
MutexLock lock(mutex);
if (!current_zstd_d_ctx || current_zstd_long_distance_matching != zstd_long_distance_matching || current_zstd_window_log_size != zstd_window_log_size) {
if (current_zstd_d_ctx) {
ZSTD_freeDCtx(current_zstd_d_ctx);
}
current_zstd_d_ctx = ZSTD_createDCtx();
if (zstd_long_distance_matching) {
ZSTD_DCtx_setParameter(current_zstd_d_ctx, ZSTD_d_windowLogMax, zstd_window_log_size);
}
current_zstd_long_distance_matching = zstd_long_distance_matching;
current_zstd_window_log_size = zstd_window_log_size;
}
int ret = ZSTD_decompressDCtx(dctx, p_dst, p_dst_max_size, p_src, p_src_size);
ZSTD_freeDCtx(dctx);
int ret = ZSTD_decompressDCtx(current_zstd_d_ctx, p_dst, p_dst_max_size, p_src, p_src_size);
return ret;
} break;
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef COMPRESSION_H
#define COMPRESSION_H
#pragma once
#include "core/templates/vector.h"
#include "core/typedefs.h"
@ -56,5 +55,3 @@ public:
static int decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size, Mode p_mode = MODE_ZSTD);
static int decompress_dynamic(Vector<uint8_t> *p_dst_vect, int p_max_dst_size, const uint8_t *p_src, int p_src_size, Mode p_mode);
};
#endif // COMPRESSION_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef CONFIG_FILE_H
#define CONFIG_FILE_H
#pragma once
#include "core/io/file_access.h"
#include "core/object/ref_counted.h"
@ -78,5 +77,3 @@ public:
Error save_encrypted(const String &p_path, const Vector<uint8_t> &p_key);
Error save_encrypted_pass(const String &p_path, const String &p_pass);
};
#endif // CONFIG_FILE_H

View file

@ -146,7 +146,7 @@ Error DirAccess::make_dir_recursive(const String &p_dir) {
full_dir = p_dir;
}
full_dir = full_dir.replace("\\", "/");
full_dir = full_dir.replace_char('\\', '/');
String base;
@ -336,7 +336,7 @@ Ref<DirAccess> DirAccess::create_temp(const String &p_prefix, bool p_keep, Error
uint32_t suffix_i = 0;
String path;
while (true) {
String datetime = Time::get_singleton()->get_datetime_string_from_system().replace("-", "").replace("T", "").replace(":", "");
String datetime = Time::get_singleton()->get_datetime_string_from_system().remove_chars("-T:");
datetime += itos(Time::get_singleton()->get_ticks_usec());
String suffix = datetime + (suffix_i > 0 ? itos(suffix_i) : "");
path = (p_prefix.is_empty() ? "" : p_prefix + "-") + suffix;
@ -626,6 +626,10 @@ bool DirAccess::is_case_sensitive(const String &p_path) const {
return true;
}
bool DirAccess::is_equivalent(const String &p_path_a, const String &p_path_b) const {
return p_path_a == p_path_b;
}
void DirAccess::_bind_methods() {
ClassDB::bind_static_method("DirAccess", D_METHOD("open", "path"), &DirAccess::_open);
ClassDB::bind_static_method("DirAccess", D_METHOD("get_open_error"), &DirAccess::get_open_error);
@ -671,6 +675,7 @@ void DirAccess::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_include_hidden"), &DirAccess::get_include_hidden);
ClassDB::bind_method(D_METHOD("is_case_sensitive", "path"), &DirAccess::is_case_sensitive);
ClassDB::bind_method(D_METHOD("is_equivalent", "path_a", "path_b"), &DirAccess::is_equivalent);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "include_navigational"), "set_include_navigational", "get_include_navigational");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "include_hidden"), "set_include_hidden", "get_include_hidden");

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef DIR_ACCESS_H
#define DIR_ACCESS_H
#pragma once
#include "core/object/ref_counted.h"
#include "core/string/ustring.h"
@ -169,10 +168,9 @@ public:
virtual bool is_case_sensitive(const String &p_path) const;
virtual bool is_bundle(const String &p_file) const { return false; }
virtual bool is_equivalent(const String &p_path_a, const String &p_path_b) const;
public:
DirAccess() {}
virtual ~DirAccess();
};
#endif // DIR_ACCESS_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef DTLS_SERVER_H
#define DTLS_SERVER_H
#pragma once
#include "core/io/net_socket.h"
#include "core/io/packet_peer_dtls.h"
@ -53,5 +52,3 @@ public:
DTLSServer() {}
};
#endif // DTLS_SERVER_H

View file

@ -104,7 +104,7 @@ Ref<FileAccess> FileAccess::create_temp(int p_mode_flags, const String &p_prefix
uint32_t suffix_i = 0;
String path;
while (true) {
String datetime = Time::get_singleton()->get_datetime_string_from_system().replace("-", "").replace("T", "").replace(":", "");
String datetime = Time::get_singleton()->get_datetime_string_from_system().remove_chars("-T:");
datetime += itos(Time::get_singleton()->get_ticks_usec());
String suffix = datetime + (suffix_i > 0 ? itos(suffix_i) : "");
path = TEMP_DIR.path_join((p_prefix.is_empty() ? "" : p_prefix + "-") + suffix + (extension.is_empty() ? "" : "." + extension));
@ -259,7 +259,7 @@ FileAccess::AccessType FileAccess::get_access_type() const {
String FileAccess::fix_path(const String &p_path) const {
// Helper used by file accesses that use a single filesystem.
String r_path = p_path.replace("\\", "/");
String r_path = p_path.replace_char('\\', '/');
switch (_access_type) {
case ACCESS_RESOURCES: {
@ -313,9 +313,15 @@ uint16_t FileAccess::get_16() const {
uint16_t data = 0;
get_buffer(reinterpret_cast<uint8_t *>(&data), sizeof(uint16_t));
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
data = BSWAP16(data);
}
#else
if (big_endian) {
data = BSWAP16(data);
}
#endif
return data;
}
@ -324,9 +330,15 @@ uint32_t FileAccess::get_32() const {
uint32_t data = 0;
get_buffer(reinterpret_cast<uint8_t *>(&data), sizeof(uint32_t));
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
data = BSWAP32(data);
}
#else
if (big_endian) {
data = BSWAP32(data);
}
#endif
return data;
}
@ -335,9 +347,15 @@ uint64_t FileAccess::get_64() const {
uint64_t data = 0;
get_buffer(reinterpret_cast<uint8_t *>(&data), sizeof(uint64_t));
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
data = BSWAP64(data);
}
#else
if (big_endian) {
data = BSWAP64(data);
}
#endif
return data;
}
@ -429,7 +447,7 @@ class CharBuffer {
public:
_FORCE_INLINE_ CharBuffer() :
buffer(stack_buffer),
capacity(sizeof(stack_buffer) / sizeof(char)) {
capacity(std::size(stack_buffer)) {
}
_FORCE_INLINE_ void push_back(char c) {
@ -565,7 +583,7 @@ String FileAccess::get_as_utf8_string(bool p_skip_cr) const {
w[len] = 0;
String s;
s.parse_utf8((const char *)w, len, p_skip_cr);
s.append_utf8((const char *)w, len, p_skip_cr);
return s;
}
@ -574,25 +592,43 @@ bool FileAccess::store_8(uint8_t p_dest) {
}
bool FileAccess::store_16(uint16_t p_dest) {
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
p_dest = BSWAP16(p_dest);
}
#else
if (big_endian) {
p_dest = BSWAP16(p_dest);
}
#endif
return store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint16_t));
}
bool FileAccess::store_32(uint32_t p_dest) {
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
p_dest = BSWAP32(p_dest);
}
#else
if (big_endian) {
p_dest = BSWAP32(p_dest);
}
#endif
return store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint32_t));
}
bool FileAccess::store_64(uint64_t p_dest) {
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
p_dest = BSWAP64(p_dest);
}
#else
if (big_endian) {
p_dest = BSWAP64(p_dest);
}
#endif
return store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint64_t));
}
@ -629,8 +665,29 @@ uint64_t FileAccess::get_modified_time(const String &p_file) {
Ref<FileAccess> fa = create_for_path(p_file);
ERR_FAIL_COND_V_MSG(fa.is_null(), 0, vformat("Cannot create FileAccess for path '%s'.", p_file));
uint64_t mt = fa->_get_modified_time(p_file);
return mt;
return fa->_get_modified_time(p_file);
}
uint64_t FileAccess::get_access_time(const String &p_file) {
if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
return 0;
}
Ref<FileAccess> fa = create_for_path(p_file);
ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "Cannot create FileAccess for path '" + p_file + "'.");
return fa->_get_access_time(p_file);
}
int64_t FileAccess::get_size(const String &p_file) {
if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
return PackedData::get_singleton()->get_size(p_file);
}
Ref<FileAccess> fa = create_for_path(p_file);
ERR_FAIL_COND_V_MSG(fa.is_null(), -1, "Cannot create FileAccess for path '" + p_file + "'.");
return fa->_get_size(p_file);
}
BitField<FileAccess::UnixPermissionFlags> FileAccess::get_unix_permissions(const String &p_file) {
@ -723,9 +780,7 @@ String FileAccess::get_pascal_string() {
get_buffer((uint8_t *)cs.ptr(), sl);
cs[sl] = 0;
String ret;
ret.parse_utf8(cs.ptr(), sl);
return ret;
return String::utf8(cs.ptr(), sl);
}
bool FileAccess::store_line(const String &p_line) {
@ -817,7 +872,7 @@ String FileAccess::get_file_as_string(const String &p_path, Error *r_error) {
}
String ret;
ret.parse_utf8((const char *)array.ptr(), array.size());
ret.append_utf8((const char *)array.ptr(), array.size());
return ret;
}
@ -931,7 +986,7 @@ void FileAccess::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_float"), &FileAccess::get_float);
ClassDB::bind_method(D_METHOD("get_double"), &FileAccess::get_double);
ClassDB::bind_method(D_METHOD("get_real"), &FileAccess::get_real);
ClassDB::bind_method(D_METHOD("get_buffer", "length"), (Vector<uint8_t>(FileAccess::*)(int64_t) const) & FileAccess::get_buffer);
ClassDB::bind_method(D_METHOD("get_buffer", "length"), (Vector<uint8_t> (FileAccess::*)(int64_t) const) & FileAccess::get_buffer);
ClassDB::bind_method(D_METHOD("get_line"), &FileAccess::get_line);
ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &FileAccess::get_csv_line, DEFVAL(","));
ClassDB::bind_method(D_METHOD("get_as_text", "skip_cr"), &FileAccess::get_as_text, DEFVAL(false));
@ -950,7 +1005,7 @@ void FileAccess::_bind_methods() {
ClassDB::bind_method(D_METHOD("store_float", "value"), &FileAccess::store_float);
ClassDB::bind_method(D_METHOD("store_double", "value"), &FileAccess::store_double);
ClassDB::bind_method(D_METHOD("store_real", "value"), &FileAccess::store_real);
ClassDB::bind_method(D_METHOD("store_buffer", "buffer"), (bool(FileAccess::*)(const Vector<uint8_t> &)) & FileAccess::store_buffer);
ClassDB::bind_method(D_METHOD("store_buffer", "buffer"), (bool (FileAccess::*)(const Vector<uint8_t> &))&FileAccess::store_buffer);
ClassDB::bind_method(D_METHOD("store_line", "line"), &FileAccess::store_line);
ClassDB::bind_method(D_METHOD("store_csv_line", "values", "delim"), &FileAccess::store_csv_line, DEFVAL(","));
ClassDB::bind_method(D_METHOD("store_string", "string"), &FileAccess::store_string);
@ -963,6 +1018,8 @@ void FileAccess::_bind_methods() {
ClassDB::bind_static_method("FileAccess", D_METHOD("file_exists", "path"), &FileAccess::exists);
ClassDB::bind_static_method("FileAccess", D_METHOD("get_modified_time", "file"), &FileAccess::get_modified_time);
ClassDB::bind_static_method("FileAccess", D_METHOD("get_access_time", "file"), &FileAccess::get_access_time);
ClassDB::bind_static_method("FileAccess", D_METHOD("get_size", "file"), &FileAccess::get_size);
ClassDB::bind_static_method("FileAccess", D_METHOD("get_unix_permissions", "file"), &FileAccess::get_unix_permissions);
ClassDB::bind_static_method("FileAccess", D_METHOD("set_unix_permissions", "file", "permissions"), &FileAccess::set_unix_permissions);

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef FILE_ACCESS_H
#define FILE_ACCESS_H
#pragma once
#include "core/io/compression.h"
#include "core/math/math_defs.h"
@ -87,7 +86,11 @@ public:
typedef void (*FileCloseFailNotify)(const String &);
typedef Ref<FileAccess> (*CreateFunc)();
#ifdef BIG_ENDIAN_ENABLED
bool big_endian = true;
#else
bool big_endian = false;
#endif
bool real_is_double = false;
virtual BitField<UnixPermissionFlags> _get_unix_permissions(const String &p_file) = 0;
@ -105,6 +108,8 @@ protected:
virtual String fix_path(const String &p_path) const;
virtual Error open_internal(const String &p_path, int p_mode_flags) = 0; ///< open a file
virtual uint64_t _get_modified_time(const String &p_file) = 0;
virtual uint64_t _get_access_time(const String &p_file) = 0;
virtual int64_t _get_size(const String &p_file) = 0;
virtual void _set_access_type(AccessType p_access);
static FileCloseFailNotify close_fail_notify;
@ -239,6 +244,8 @@ public:
static CreateFunc get_create_func(AccessType p_access);
static bool exists(const String &p_name); ///< return true if a file exists
static uint64_t get_modified_time(const String &p_file);
static uint64_t get_access_time(const String &p_file);
static int64_t get_size(const String &p_file);
static BitField<FileAccess::UnixPermissionFlags> get_unix_permissions(const String &p_file);
static Error set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions);
@ -273,5 +280,3 @@ public:
VARIANT_ENUM_CAST(FileAccess::CompressionMode);
VARIANT_ENUM_CAST(FileAccess::ModeFlags);
VARIANT_BITFIELD_CAST(FileAccess::UnixPermissionFlags);
#endif // FILE_ACCESS_H

View file

@ -247,7 +247,11 @@ bool FileAccessCompressed::eof_reached() const {
}
uint64_t FileAccessCompressed::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
if (p_length == 0) {
return 0;
}
ERR_FAIL_NULL_V(p_dst, -1);
ERR_FAIL_COND_V_MSG(f.is_null(), -1, "File must be opened before use.");
ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode.");
@ -256,29 +260,38 @@ uint64_t FileAccessCompressed::get_buffer(uint8_t *p_dst, uint64_t p_length) con
return 0;
}
for (uint64_t i = 0; i < p_length; i++) {
p_dst[i] = read_ptr[read_pos];
read_pos++;
if (read_pos >= read_block_size) {
read_block++;
uint64_t dst_idx = 0;
while (true) {
// Copy over as much of our current block as possible.
const uint32_t copied_bytes_count = MIN(p_length - dst_idx, read_block_size - read_pos);
memcpy(p_dst + dst_idx, read_ptr + read_pos, copied_bytes_count);
dst_idx += copied_bytes_count;
read_pos += copied_bytes_count;
if (read_block < read_block_count) {
//read another block of compressed data
f->get_buffer(comp_buffer.ptrw(), read_blocks[read_block].csize);
int ret = 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(ret == -1, -1, "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;
if (i + 1 < p_length) {
read_eof = true;
}
return i + 1;
}
if (dst_idx == p_length) {
// We're done! We read back all that was requested.
return p_length;
}
// We're not done yet; try reading the next block.
read_block++;
if (read_block >= read_block_count) {
// We're done! We read back the whole file.
read_block--;
at_end = true;
if (dst_idx + 1 < p_length) {
read_eof = true;
}
return dst_idx;
}
// Read the next block of compressed data.
f->get_buffer(comp_buffer.ptrw(), read_blocks[read_block].csize);
int ret = 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(ret == -1, -1, "Compressed file is corrupt.");
read_block_size = read_block == read_block_count - 1 ? read_total % block_size : block_size;
read_pos = 0;
}
return p_length;
@ -332,6 +345,22 @@ uint64_t FileAccessCompressed::_get_modified_time(const String &p_file) {
}
}
uint64_t FileAccessCompressed::_get_access_time(const String &p_file) {
if (f.is_valid()) {
return f->get_access_time(p_file);
} else {
return 0;
}
}
int64_t FileAccessCompressed::_get_size(const String &p_file) {
if (f.is_valid()) {
return f->get_size(p_file);
} else {
return -1;
}
}
BitField<FileAccess::UnixPermissionFlags> FileAccessCompressed::_get_unix_permissions(const String &p_file) {
if (f.is_valid()) {
return f->_get_unix_permissions(p_file);

View file

@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef FILE_ACCESS_COMPRESSED_H
#define FILE_ACCESS_COMPRESSED_H
#pragma once
#include "core/io/compression.h"
#include "core/io/file_access.h"
class FileAccessCompressed : public FileAccess {
GDSOFTCLASS(FileAccessCompressed, FileAccess);
Compression::Mode cmode = Compression::MODE_ZSTD;
bool writing = false;
uint64_t write_pos = 0;
@ -94,6 +94,8 @@ public:
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file) override;
virtual uint64_t _get_access_time(const String &p_file) override;
virtual int64_t _get_size(const String &p_file) override;
virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override;
virtual Error _set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) override;
@ -107,5 +109,3 @@ public:
FileAccessCompressed() {}
virtual ~FileAccessCompressed();
};
#endif // FILE_ACCESS_COMPRESSED_H

View file

@ -30,9 +30,17 @@
#include "file_access_encrypted.h"
#include "core/crypto/crypto_core.h"
#include "core/variant/variant.h"
CryptoCore::RandomGenerator *FileAccessEncrypted::_fae_static_rng = nullptr;
void FileAccessEncrypted::deinitialize() {
if (_fae_static_rng) {
memdelete(_fae_static_rng);
_fae_static_rng = nullptr;
}
}
Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic, const Vector<uint8_t> &p_iv) {
ERR_FAIL_COND_V_MSG(file.is_valid(), ERR_ALREADY_IN_USE, vformat("Can't open file while another file from path '%s' is open.", file->get_path_absolute()));
ERR_FAIL_COND_V(p_key.size() != 32, ERR_INVALID_PARAMETER);
@ -48,9 +56,15 @@ Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<u
key = p_key;
if (p_iv.is_empty()) {
iv.resize(16);
CryptoCore::RandomGenerator rng;
ERR_FAIL_COND_V_MSG(rng.init(), FAILED, "Failed to initialize random number generator.");
Error err = rng.get_random_bytes(iv.ptrw(), 16);
if (unlikely(!_fae_static_rng)) {
_fae_static_rng = memnew(CryptoCore::RandomGenerator);
if (_fae_static_rng->init() != OK) {
memdelete(_fae_static_rng);
_fae_static_rng = nullptr;
ERR_FAIL_V_MSG(FAILED, "Failed to initialize random number generator.");
}
}
Error err = _fae_static_rng->get_random_bytes(iv.ptrw(), 16);
ERR_FAIL_COND_V(err != OK, err);
} else {
ERR_FAIL_COND_V(p_iv.size() != 16, ERR_INVALID_PARAMETER);
@ -265,7 +279,27 @@ bool FileAccessEncrypted::file_exists(const String &p_name) {
}
uint64_t FileAccessEncrypted::_get_modified_time(const String &p_file) {
return 0;
if (file.is_valid()) {
return file->get_modified_time(p_file);
} else {
return 0;
}
}
uint64_t FileAccessEncrypted::_get_access_time(const String &p_file) {
if (file.is_valid()) {
return file->get_access_time(p_file);
} else {
return 0;
}
}
int64_t FileAccessEncrypted::_get_size(const String &p_file) {
if (file.is_valid()) {
return file->get_size(p_file);
} else {
return -1;
}
}
BitField<FileAccess::UnixPermissionFlags> FileAccessEncrypted::_get_unix_permissions(const String &p_file) {

View file

@ -28,14 +28,16 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef FILE_ACCESS_ENCRYPTED_H
#define FILE_ACCESS_ENCRYPTED_H
#pragma once
#include "core/crypto/crypto_core.h"
#include "core/io/file_access.h"
#define ENCRYPTED_HEADER_MAGIC 0x43454447
class FileAccessEncrypted : public FileAccess {
GDSOFTCLASS(FileAccessEncrypted, FileAccess);
public:
enum Mode : int32_t {
MODE_READ,
@ -57,6 +59,8 @@ private:
void _close();
static CryptoCore::RandomGenerator *_fae_static_rng;
public:
Error open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic = true, const Vector<uint8_t> &p_iv = Vector<uint8_t>());
Error open_and_parse_password(Ref<FileAccess> p_base, const String &p_key, Mode p_mode);
@ -87,6 +91,8 @@ public:
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file) override;
virtual uint64_t _get_access_time(const String &p_file) override;
virtual int64_t _get_size(const String &p_file) override;
virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override;
virtual Error _set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) override;
@ -97,8 +103,8 @@ public:
virtual void close() override;
static void deinitialize();
FileAccessEncrypted() {}
~FileAccessEncrypted();
};
#endif // FILE_ACCESS_ENCRYPTED_H

View file

@ -28,12 +28,12 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef FILE_ACCESS_MEMORY_H
#define FILE_ACCESS_MEMORY_H
#pragma once
#include "core/io/file_access.h"
class FileAccessMemory : public FileAccess {
GDSOFTCLASS(FileAccessMemory, FileAccess);
uint8_t *data = nullptr;
uint64_t length = 0;
mutable uint64_t pos = 0;
@ -66,6 +66,9 @@ public:
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file) override { return 0; }
virtual uint64_t _get_access_time(const String &p_file) override { return 0; }
virtual int64_t _get_size(const String &p_file) override { return -1; }
virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override { return 0; }
virtual Error _set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) override { return FAILED; }
@ -78,5 +81,3 @@ public:
FileAccessMemory() {}
};
#endif // FILE_ACCESS_MEMORY_H

View file

@ -264,7 +264,7 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
f->get_32(); // patch number, not used for validation.
ERR_FAIL_COND_V_MSG(version != PACK_FORMAT_VERSION, false, vformat("Pack version unsupported: %d.", version));
ERR_FAIL_COND_V_MSG(ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), false, vformat("Pack created with a newer version of the engine: %d.%d.", ver_major, ver_minor));
ERR_FAIL_COND_V_MSG(ver_major > GODOT_VERSION_MAJOR || (ver_major == GODOT_VERSION_MAJOR && ver_minor > GODOT_VERSION_MINOR), false, vformat("Pack created with a newer version of the engine: %d.%d.", ver_major, ver_minor));
uint32_t pack_flags = f->get_32();
uint64_t file_base = f->get_64();
@ -306,9 +306,7 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
f->get_buffer((uint8_t *)cs.ptr(), sl);
cs[sl] = 0;
String path;
path.parse_utf8(cs.ptr(), sl);
String path = String::utf8(cs.ptr(), sl);
uint64_t ofs = f->get_64();
uint64_t size = f->get_64();
uint8_t md5[16];
@ -550,7 +548,7 @@ String DirAccessPack::get_drive(int p_drive) {
}
PackedData::PackedDir *DirAccessPack::_find_dir(const String &p_dir) {
String nd = p_dir.replace("\\", "/");
String nd = p_dir.replace_char('\\', '/');
// Special handling since simplify_path() will forbid it
if (p_dir == "..") {

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef FILE_ACCESS_PACK_H
#define FILE_ACCESS_PACK_H
#pragma once
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
@ -127,6 +126,8 @@ public:
_FORCE_INLINE_ Ref<FileAccess> try_open_path(const String &p_path);
_FORCE_INLINE_ bool has_path(const String &p_path);
_FORCE_INLINE_ int64_t get_size(const String &p_path);
_FORCE_INLINE_ Ref<DirAccess> try_open_directory(const String &p_path);
_FORCE_INLINE_ bool has_directory(const String &p_path);
@ -156,6 +157,7 @@ public:
};
class FileAccessPack : public FileAccess {
GDSOFTCLASS(FileAccessPack, FileAccess);
PackedData::PackedFile pf;
mutable uint64_t pos;
@ -165,6 +167,8 @@ class FileAccessPack : public FileAccess {
Ref<FileAccess> f;
virtual Error open_internal(const String &p_path, int p_mode_flags) override;
virtual uint64_t _get_modified_time(const String &p_file) override { return 0; }
virtual uint64_t _get_access_time(const String &p_file) override { return 0; }
virtual int64_t _get_size(const String &p_file) override { return -1; }
virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override { return 0; }
virtual Error _set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) override { return FAILED; }
@ -200,6 +204,19 @@ public:
FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file);
};
int64_t PackedData::get_size(const String &p_path) {
String simplified_path = p_path.simplify_path();
PathMD5 pmd5(simplified_path.md5_buffer());
HashMap<PathMD5, PackedFile, PathMD5>::Iterator E = files.find(pmd5);
if (!E) {
return -1; // File not found.
}
if (E->value.offset == 0) {
return -1; // File was erased.
}
return E->value.size;
}
Ref<FileAccess> PackedData::try_open_path(const String &p_path) {
String simplified_path = p_path.simplify_path().trim_prefix("res://");
PathMD5 pmd5(simplified_path.md5_buffer());
@ -225,6 +242,7 @@ bool PackedData::has_directory(const String &p_path) {
}
class DirAccessPack : public DirAccess {
GDSOFTCLASS(DirAccessPack, DirAccess);
PackedData::PackedDir *current;
List<String> list_dirs;
@ -272,5 +290,3 @@ Ref<DirAccess> PackedData::try_open_directory(const String &p_path) {
}
return da;
}
#endif // FILE_ACCESS_PACK_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef FILE_ACCESS_ZIP_H
#define FILE_ACCESS_ZIP_H
#pragma once
#ifdef MINIZIP_ENABLED
@ -74,6 +73,7 @@ public:
};
class FileAccessZip : public FileAccess {
GDSOFTCLASS(FileAccessZip, FileAccess);
unzFile zfile = nullptr;
unz_file_info64 file_info;
@ -102,7 +102,9 @@ public:
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file) override { return 0; } // todo
virtual uint64_t _get_modified_time(const String &p_file) override { return 0; }
virtual uint64_t _get_access_time(const String &p_file) override { return 0; }
virtual int64_t _get_size(const String &p_file) override { return -1; }
virtual BitField<FileAccess::UnixPermissionFlags> _get_unix_permissions(const String &p_file) override { return 0; }
virtual Error _set_unix_permissions(const String &p_file, BitField<FileAccess::UnixPermissionFlags> p_permissions) override { return FAILED; }
@ -118,5 +120,3 @@ public:
};
#endif // MINIZIP_ENABLED
#endif // FILE_ACCESS_ZIP_H

View file

@ -70,10 +70,9 @@ Error HTTPClient::_request(Method p_method, const String &p_url, const Vector<St
String HTTPClient::query_string_from_dict(const Dictionary &p_dict) {
String query = "";
Array keys = p_dict.keys();
for (int i = 0; i < keys.size(); ++i) {
String encoded_key = String(keys[i]).uri_encode();
const Variant &value = p_dict[keys[i]];
for (const KeyValue<Variant, Variant> &kv : p_dict) {
String encoded_key = String(kv.key).uri_encode();
const Variant &value = kv.value;
switch (value.get_type()) {
case Variant::ARRAY: {
// Repeat the key with every values
@ -118,7 +117,7 @@ Dictionary HTTPClient::_get_response_headers_as_dictionary() {
continue;
}
String key = s.substr(0, sp).strip_edges();
String value = s.substr(sp + 1, s.length()).strip_edges();
String value = s.substr(sp + 1).strip_edges();
ret[key] = value;
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef HTTP_CLIENT_H
#define HTTP_CLIENT_H
#pragma once
#include "core/crypto/crypto.h"
#include "core/io/ip.h"
@ -205,5 +204,3 @@ public:
VARIANT_ENUM_CAST(HTTPClient::ResponseCode)
VARIANT_ENUM_CAST(HTTPClient::Method);
VARIANT_ENUM_CAST(HTTPClient::Status);
#endif // HTTP_CLIENT_H

View file

@ -50,13 +50,13 @@ Error HTTPClientTCP::connect_to_host(const String &p_host, int p_port, Ref<TLSOp
String host_lower = conn_host.to_lower();
if (host_lower.begins_with("http://")) {
conn_host = conn_host.substr(7, conn_host.length() - 7);
conn_host = conn_host.substr(7);
tls_options.unref();
} else if (host_lower.begins_with("https://")) {
if (tls_options.is_null()) {
tls_options = TLSOptions::client();
}
conn_host = conn_host.substr(8, conn_host.length() - 8);
conn_host = conn_host.substr(8);
}
ERR_FAIL_COND_V(tls_options.is_valid() && tls_options->is_server(), ERR_INVALID_PARAMETER);
@ -196,7 +196,7 @@ Error HTTPClientTCP::request(Method p_method, const String &p_url, const Vector<
// Should it add utf8 encoding?
}
if (add_uagent) {
request += "User-Agent: GodotEngine/" + String(VERSION_FULL_BUILD) + " (" + OS::get_singleton()->get_name() + ")\r\n";
request += "User-Agent: GodotEngine/" + String(GODOT_VERSION_FULL_BUILD) + " (" + OS::get_singleton()->get_name() + ")\r\n";
}
if (add_accept) {
request += "Accept: */*\r\n";
@ -483,8 +483,7 @@ Error HTTPClientTCP::poll() {
(rs >= 4 && response_str[rs - 4] == '\r' && response_str[rs - 3] == '\n' && response_str[rs - 2] == '\r' && response_str[rs - 1] == '\n')) {
// End of response, parse.
response_str.push_back(0);
String response;
response.parse_utf8((const char *)response_str.ptr(), response_str.size());
String response = String::utf8((const char *)response_str.ptr(), response_str.size());
Vector<String> responses = response.split("\n");
body_size = -1;
chunked = false;
@ -508,11 +507,11 @@ Error HTTPClientTCP::poll() {
continue;
}
if (s.begins_with("content-length:")) {
body_size = s.substr(s.find_char(':') + 1, s.length()).strip_edges().to_int();
body_size = s.substr(s.find_char(':') + 1).strip_edges().to_int();
body_left = body_size;
} else if (s.begins_with("transfer-encoding:")) {
String encoding = header.substr(header.find_char(':') + 1, header.length()).strip_edges();
String encoding = header.substr(header.find_char(':') + 1).strip_edges();
if (encoding == "chunked") {
chunked = true;
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef HTTP_CLIENT_TCP_H
#define HTTP_CLIENT_TCP_H
#pragma once
#include "http_client.h"
@ -100,5 +99,3 @@ public:
void set_https_proxy(const String &p_host, int p_port) override;
HTTPClientTCP();
};
#endif // HTTP_CLIENT_TCP_H

View file

@ -31,7 +31,6 @@
#include "image.h"
#include "core/config/project_settings.h"
#include "core/error/error_list.h"
#include "core/error/error_macros.h"
#include "core/io/image_loader.h"
#include "core/io/resource_loader.h"
@ -89,11 +88,13 @@ SavePNGFunc Image::save_png_func = nullptr;
SaveJPGFunc Image::save_jpg_func = nullptr;
SaveEXRFunc Image::save_exr_func = nullptr;
SaveWebPFunc Image::save_webp_func = nullptr;
SaveDDSFunc Image::save_dds_func = nullptr;
SavePNGBufferFunc Image::save_png_buffer_func = nullptr;
SaveJPGBufferFunc Image::save_jpg_buffer_func = nullptr;
SaveEXRBufferFunc Image::save_exr_buffer_func = nullptr;
SaveWebPBufferFunc Image::save_webp_buffer_func = nullptr;
SaveDDSBufferFunc Image::save_dds_buffer_func = nullptr;
// External loader function pointers.
@ -105,6 +106,7 @@ ImageMemLoadFunc Image::_tga_mem_loader_func = nullptr;
ImageMemLoadFunc Image::_bmp_mem_loader_func = nullptr;
ScalableImageMemLoadFunc Image::_svg_scalable_mem_loader_func = nullptr;
ImageMemLoadFunc Image::_ktx_mem_loader_func = nullptr;
ImageMemLoadFunc Image::_dds_mem_loader_func = nullptr;
// External VRAM compression function pointers.
@ -571,7 +573,7 @@ static bool _are_formats_compatible(Image::Format p_format0, Image::Format p_for
void Image::convert(Format p_new_format) {
ERR_FAIL_INDEX_MSG(p_new_format, FORMAT_MAX, vformat("The Image format specified (%d) is out of range. See Image's Format enum.", p_new_format));
if (data.size() == 0 || p_new_format == format) {
if (data.is_empty() || p_new_format == format) {
return;
}
@ -796,7 +798,7 @@ Image::Format Image::get_format() const {
}
static double _bicubic_interp_kernel(double x) {
x = ABS(x);
x = Math::abs(x);
double bc = 0;
@ -1139,7 +1141,7 @@ bool Image::is_size_po2() const {
}
void Image::resize_to_po2(bool p_square, Interpolation p_interpolation) {
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot resize in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot resize in compressed image formats.");
int w = next_power_of_2(width);
int h = next_power_of_2(height);
@ -1158,7 +1160,7 @@ void Image::resize_to_po2(bool p_square, Interpolation p_interpolation) {
void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
ERR_FAIL_COND_MSG(data.is_empty(), "Cannot resize image before creating it, use set_data() first.");
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot resize in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot resize in compressed image formats.");
bool mipmap_aware = p_interpolation == INTERPOLATE_TRILINEAR /* || p_interpolation == INTERPOLATE_TRICUBIC */;
@ -1461,8 +1463,7 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
}
void Image::crop_from_point(int p_x, int p_y, int p_width, int p_height) {
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot crop in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot crop in compressed image formats.");
ERR_FAIL_COND_MSG(p_x < 0, "Start x position cannot be smaller than 0.");
ERR_FAIL_COND_MSG(p_y < 0, "Start y position cannot be smaller than 0.");
ERR_FAIL_COND_MSG(p_width <= 0, "Width of image must be greater than 0.");
@ -1515,7 +1516,7 @@ void Image::crop(int p_width, int p_height) {
}
void Image::rotate_90(ClockDirection p_direction) {
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot rotate in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot rotate in compressed image formats.");
ERR_FAIL_COND_MSG(width <= 0, vformat("The Image width specified (%d pixels) must be greater than 0 pixels.", width));
ERR_FAIL_COND_MSG(height <= 0, vformat("The Image height specified (%d pixels) must be greater than 0 pixels.", height));
@ -1633,7 +1634,7 @@ void Image::rotate_90(ClockDirection p_direction) {
}
void Image::rotate_180() {
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot rotate in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot rotate in compressed image formats.");
ERR_FAIL_COND_MSG(width <= 0, vformat("The Image width specified (%d pixels) must be greater than 0 pixels.", width));
ERR_FAIL_COND_MSG(height <= 0, vformat("The Image height specified (%d pixels) must be greater than 0 pixels.", height));
@ -1667,7 +1668,7 @@ void Image::rotate_180() {
}
void Image::flip_y() {
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot flip_y in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot flip_y in compressed image formats.");
bool used_mipmaps = has_mipmaps();
if (used_mipmaps) {
@ -1697,7 +1698,7 @@ void Image::flip_y() {
}
void Image::flip_x() {
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot flip_x in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot flip_x in compressed image formats.");
bool used_mipmaps = has_mipmaps();
if (used_mipmaps) {
@ -1789,10 +1790,6 @@ int64_t Image::_get_dst_image_size(int p_width, int p_height, Format p_format, i
return size;
}
bool Image::_can_modify(Format p_format) const {
return !Image::is_format_compressed(p_format);
}
template <typename Component, int CC, bool renormalize,
void (*average_func)(Component &, const Component &, const Component &, const Component &, const Component &),
void (*renormalize_func)(Component *)>
@ -1926,7 +1923,7 @@ void Image::shrink_x2() {
memcpy(new_data.ptrw(), data.ptr() + ofs, new_size);
} else {
// Generate a mipmap and replace the original.
ERR_FAIL_COND(!_can_modify(format));
ERR_FAIL_COND(is_compressed());
new_data.resize((width / 2) * (height / 2) * get_format_pixel_size(format));
ERR_FAIL_COND(data.is_empty() || new_data.is_empty());
@ -1963,7 +1960,7 @@ void Image::normalize() {
}
Error Image::generate_mipmaps(bool p_renormalize) {
ERR_FAIL_COND_V_MSG(!_can_modify(format), ERR_UNAVAILABLE, "Cannot generate mipmaps in compressed or custom image formats.");
ERR_FAIL_COND_V_MSG(is_compressed(), ERR_UNAVAILABLE, "Cannot generate mipmaps from compressed image formats.");
ERR_FAIL_COND_V_MSG(format == FORMAT_RGBA4444, ERR_UNAVAILABLE, "Cannot generate mipmaps from RGBA4444 format.");
ERR_FAIL_COND_V_MSG(width == 0 || height == 0, ERR_UNCONFIGURED, "Cannot generate mipmaps with width or height equal to 0.");
@ -2180,7 +2177,7 @@ void Image::clear_mipmaps() {
}
bool Image::is_empty() const {
return (data.size() == 0);
return (data.is_empty());
}
Vector<uint8_t> Image::get_data() const {
@ -2297,7 +2294,7 @@ void Image::initialize_data(const char **p_xpm) {
switch (status) {
case READING_HEADER: {
String line_str = line_ptr;
line_str.replace("\t", " ");
line_str.replace_char('\t', ' ');
size_width = line_str.get_slicec(' ', 0).to_int();
size_height = line_str.get_slicec(' ', 1).to_int();
@ -2441,47 +2438,75 @@ void Image::initialize_data(const char **p_xpm) {
}
bool Image::is_invisible() const {
if (format == FORMAT_L8 || format == FORMAT_RGB8 || format == FORMAT_RG8) {
return false;
}
int64_t len = data.size();
int w, h;
int64_t len;
_get_mipmap_offset_and_size(1, len, w, h);
if (len == 0) {
return true;
}
int w, h;
_get_mipmap_offset_and_size(1, len, w, h);
const uint8_t *r = data.ptr();
const unsigned char *data_ptr = r;
bool detected = false;
switch (format) {
case FORMAT_LA8: {
for (int i = 0; i < (len >> 1); i++) {
DETECT_NON_ALPHA(data_ptr[(i << 1) + 1]);
}
const int pixel_count = len / 2;
const uint16_t *pixeldata = reinterpret_cast<const uint16_t *>(data.ptr());
for (int i = 0; i < pixel_count; i++) {
if ((pixeldata[i] & 0xFF00) != 0) {
return false;
}
}
} break;
case FORMAT_RGBA8: {
for (int i = 0; i < (len >> 2); i++) {
DETECT_NON_ALPHA(data_ptr[(i << 2) + 3])
const int pixel_count = len / 4;
const uint32_t *pixeldata = reinterpret_cast<const uint32_t *>(data.ptr());
for (int i = 0; i < pixel_count; i++) {
if ((pixeldata[i] & 0xFF000000) != 0) {
return false;
}
}
} break;
case FORMAT_RGBA4444: {
const int pixel_count = len / 2;
const uint16_t *pixeldata = reinterpret_cast<const uint16_t *>(data.ptr());
case FORMAT_DXT3:
case FORMAT_DXT5: {
detected = true;
for (int i = 0; i < pixel_count; i++) {
if ((pixeldata[i] & 0x000F) != 0) {
return false;
}
}
} break;
case FORMAT_RGBAH: {
// The alpha mask accounts for the sign bit.
const int pixel_count = len / 4;
const uint16_t *pixeldata = reinterpret_cast<const uint16_t *>(data.ptr());
for (int i = 0; i < pixel_count; i += 4) {
if ((pixeldata[i + 3] & 0x7FFF) != 0) {
return false;
}
}
} break;
case FORMAT_RGBAF: {
// The alpha mask accounts for the sign bit.
const int pixel_count = len / 4;
const uint32_t *pixeldata = reinterpret_cast<const uint32_t *>(data.ptr());
for (int i = 0; i < pixel_count; i += 4) {
if ((pixeldata[i + 3] & 0x7FFFFFFF) != 0) {
return false;
}
}
} break;
default: {
// Formats that are compressed or don't support alpha channels are presumed to be visible.
return false;
}
}
return !detected;
// Every pixel has been checked, the image is invisible.
return true;
}
Image::AlphaMode Image::detect_alpha() const {
@ -2603,6 +2628,21 @@ Vector<uint8_t> Image::save_exr_to_buffer(bool p_grayscale) const {
return save_exr_buffer_func(Ref<Image>((Image *)this), p_grayscale);
}
Error Image::save_dds(const String &p_path) const {
if (save_dds_func == nullptr) {
return ERR_UNAVAILABLE;
}
return save_dds_func(p_path, Ref<Image>((Image *)this));
}
Vector<uint8_t> Image::save_dds_to_buffer() const {
if (save_dds_buffer_func == nullptr) {
return Vector<uint8_t>();
}
return save_dds_buffer_func(Ref<Image>((Image *)this));
}
Error Image::save_webp(const String &p_path, const bool p_lossy, const float p_quality) const {
if (save_webp_func == nullptr) {
return ERR_UNAVAILABLE;
@ -2682,6 +2722,19 @@ Error Image::decompress() {
return OK;
}
bool Image::can_decompress(const String &p_format_tag) {
if (p_format_tag == "astc") {
return _image_decompress_astc != nullptr;
} else if (p_format_tag == "bptc") {
return _image_decompress_bptc != nullptr;
} else if (p_format_tag == "etc2") {
return _image_decompress_etc2 != nullptr;
} else if (p_format_tag == "s3tc") {
return _image_decompress_bc != nullptr;
}
return false;
}
Error Image::compress(CompressMode p_mode, CompressSource p_source, ASTCFormat p_astc_format) {
ERR_FAIL_INDEX_V_MSG(p_mode, COMPRESS_MAX, ERR_INVALID_PARAMETER, "Invalid compress mode.");
ERR_FAIL_INDEX_V_MSG(p_source, COMPRESS_SOURCE_MAX, ERR_INVALID_PARAMETER, "Invalid compress source.");
@ -2863,7 +2916,7 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const P
ERR_FAIL_COND(dsize == 0);
ERR_FAIL_COND(srcdsize == 0);
ERR_FAIL_COND(format != p_src->format);
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot blit_rect in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot blit_rect in compressed image formats.");
Rect2i src_rect;
Rect2i dest_rect;
@ -3043,10 +3096,10 @@ void Image::_repeat_pixel_over_subsequent_memory(uint8_t *p_pixel, int p_pixel_s
}
void Image::fill(const Color &p_color) {
if (data.size() == 0) {
if (data.is_empty()) {
return;
}
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot fill in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot fill in compressed image formats.");
uint8_t *dst_data_ptr = data.ptrw();
@ -3059,10 +3112,10 @@ void Image::fill(const Color &p_color) {
}
void Image::fill_rect(const Rect2i &p_rect, const Color &p_color) {
if (data.size() == 0) {
if (data.is_empty()) {
return;
}
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot fill rect in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot fill rect in compressed image formats.");
Rect2i r = Rect2i(0, 0, width, height).intersection(p_rect.abs());
if (!r.has_area()) {
@ -3278,7 +3331,7 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color)
uint16_t rgba = 0;
rgba = uint16_t(CLAMP(p_color.r * 31.0, 0, 31));
rgba |= uint16_t(CLAMP(p_color.g * 63.0, 0, 33)) << 5;
rgba |= uint16_t(CLAMP(p_color.g * 63.0, 0, 63)) << 5;
rgba |= uint16_t(CLAMP(p_color.b * 31.0, 0, 31)) << 11;
((uint16_t *)ptr)[ofs] = rgba;
@ -3366,7 +3419,7 @@ int64_t Image::get_data_size() const {
}
void Image::adjust_bcs(float p_brightness, float p_contrast, float p_saturation) {
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot adjust_bcs in compressed or custom image formats.");
ERR_FAIL_COND_MSG(is_compressed(), "Cannot adjust_bcs in compressed image formats.");
uint8_t *w = data.ptrw();
uint32_t pixel_size = get_format_pixel_size(format);
@ -3524,6 +3577,9 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("save_jpg_to_buffer", "quality"), &Image::save_jpg_to_buffer, DEFVAL(0.75));
ClassDB::bind_method(D_METHOD("save_exr", "path", "grayscale"), &Image::save_exr, DEFVAL(false));
ClassDB::bind_method(D_METHOD("save_exr_to_buffer", "grayscale"), &Image::save_exr_to_buffer, DEFVAL(false));
ClassDB::bind_method(D_METHOD("save_dds", "path"), &Image::save_dds);
ClassDB::bind_method(D_METHOD("save_dds_to_buffer"), &Image::save_dds_to_buffer);
ClassDB::bind_method(D_METHOD("save_webp", "path", "lossy", "quality"), &Image::save_webp, DEFVAL(false), DEFVAL(0.75f));
ClassDB::bind_method(D_METHOD("save_webp_to_buffer", "lossy", "quality"), &Image::save_webp_to_buffer, DEFVAL(false), DEFVAL(0.75f));
@ -3577,6 +3633,7 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("load_tga_from_buffer", "buffer"), &Image::load_tga_from_buffer);
ClassDB::bind_method(D_METHOD("load_bmp_from_buffer", "buffer"), &Image::load_bmp_from_buffer);
ClassDB::bind_method(D_METHOD("load_ktx_from_buffer", "buffer"), &Image::load_ktx_from_buffer);
ClassDB::bind_method(D_METHOD("load_dds_from_buffer", "buffer"), &Image::load_dds_from_buffer);
ClassDB::bind_method(D_METHOD("load_svg_from_buffer", "buffer", "scale"), &Image::load_svg_from_buffer, DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("load_svg_from_string", "svg_str", "scale"), &Image::load_svg_from_string, DEFVAL(1.0));
@ -3677,7 +3734,7 @@ void Image::normal_map_to_xy() {
}
Ref<Image> Image::rgbe_to_srgb() {
if (data.size() == 0) {
if (data.is_empty()) {
return Ref<Image>();
}
@ -3724,7 +3781,7 @@ Ref<Image> Image::get_image_from_mipmap(int p_mipmap) const {
}
void Image::bump_map_to_normal_map(float bump_scale) {
ERR_FAIL_COND(!_can_modify(format));
ERR_FAIL_COND(is_compressed());
clear_mipmaps();
convert(Image::FORMAT_RF);
@ -3799,7 +3856,7 @@ bool Image::detect_signed(bool p_include_mips) const {
}
void Image::srgb_to_linear() {
if (data.size() == 0) {
if (data.is_empty()) {
return;
}
@ -3830,7 +3887,7 @@ void Image::srgb_to_linear() {
}
void Image::linear_to_srgb() {
if (data.size() == 0) {
if (data.is_empty()) {
return;
}
@ -3861,7 +3918,7 @@ void Image::linear_to_srgb() {
}
void Image::premultiply_alpha() {
if (data.size() == 0) {
if (data.is_empty()) {
return;
}
@ -3883,7 +3940,7 @@ void Image::premultiply_alpha() {
}
void Image::fix_alpha_edges() {
if (data.size() == 0) {
if (data.is_empty()) {
return;
}
@ -4072,6 +4129,14 @@ Error Image::load_bmp_from_buffer(const Vector<uint8_t> &p_array) {
return _load_from_buffer(p_array, _bmp_mem_loader_func);
}
Error Image::load_dds_from_buffer(const Vector<uint8_t> &p_array) {
ERR_FAIL_NULL_V_MSG(
_dds_mem_loader_func,
ERR_UNAVAILABLE,
"The DDS module isn't enabled. Recompile the Godot editor or export template binary with the `module_dds_enabled=yes` SCons option.");
return _load_from_buffer(p_array, _dds_mem_loader_func);
}
Error Image::load_svg_from_buffer(const Vector<uint8_t> &p_array, float scale) {
ERR_FAIL_NULL_V_MSG(
_svg_scalable_mem_loader_func,
@ -4266,10 +4331,10 @@ Dictionary Image::compute_image_metrics(const Ref<Image> p_compared_image, bool
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Dictionary result;
result["max"] = INFINITY;
result["mean"] = INFINITY;
result["mean_squared"] = INFINITY;
result["root_mean_squared"] = INFINITY;
result["max"] = Math::INF;
result["mean"] = Math::INF;
result["mean_squared"] = Math::INF;
result["root_mean_squared"] = Math::INF;
result["peak_snr"] = 0.0f;
ERR_FAIL_COND_V(p_compared_image.is_null(), result);

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef IMAGE_H
#define IMAGE_H
#pragma once
#include "core/io/resource.h"
#include "core/math/color.h"
@ -59,6 +58,9 @@ typedef Vector<uint8_t> (*SaveWebPBufferFunc)(const Ref<Image> &p_img, const boo
typedef Error (*SaveEXRFunc)(const String &p_path, const Ref<Image> &p_img, bool p_grayscale);
typedef Vector<uint8_t> (*SaveEXRBufferFunc)(const Ref<Image> &p_img, bool p_grayscale);
typedef Error (*SaveDDSFunc)(const String &p_path, const Ref<Image> &p_img);
typedef Vector<uint8_t> (*SaveDDSBufferFunc)(const Ref<Image> &p_img);
class Image : public Resource {
GDCLASS(Image, Resource);
@ -186,10 +188,12 @@ public:
static SaveJPGFunc save_jpg_func;
static SaveEXRFunc save_exr_func;
static SaveWebPFunc save_webp_func;
static SaveDDSFunc save_dds_func;
static SavePNGBufferFunc save_png_buffer_func;
static SaveEXRBufferFunc save_exr_buffer_func;
static SaveJPGBufferFunc save_jpg_buffer_func;
static SaveWebPBufferFunc save_webp_buffer_func;
static SaveDDSBufferFunc save_dds_buffer_func;
// External loader function pointers.
@ -201,6 +205,7 @@ public:
static ImageMemLoadFunc _bmp_mem_loader_func;
static ScalableImageMemLoadFunc _svg_scalable_mem_loader_func;
static ImageMemLoadFunc _ktx_mem_loader_func;
static ImageMemLoadFunc _dds_mem_loader_func;
// External VRAM compression function pointers.
@ -251,7 +256,6 @@ private:
_FORCE_INLINE_ void _get_mipmap_offset_and_size(int p_mipmap, int64_t &r_offset, int &r_width, int &r_height) const; // Get where the mipmap begins in data.
static int64_t _get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps = -1, int *r_mm_width = nullptr, int *r_mm_height = nullptr);
bool _can_modify(Format p_format) const;
_FORCE_INLINE_ void _get_clipped_src_and_dest_rects(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest, Rect2i &r_clipped_src_rect, Rect2i &r_clipped_dest_rect) const;
@ -334,9 +338,11 @@ public:
static Ref<Image> load_from_file(const String &p_path);
Error save_png(const String &p_path) const;
Error save_jpg(const String &p_path, float p_quality = 0.75) const;
Error save_dds(const String &p_path) const;
Vector<uint8_t> save_png_to_buffer() const;
Vector<uint8_t> save_jpg_to_buffer(float p_quality = 0.75) const;
Vector<uint8_t> save_exr_to_buffer(bool p_grayscale = false) const;
Vector<uint8_t> save_dds_to_buffer() const;
Error save_exr(const String &p_path, bool p_grayscale = false) const;
Error save_webp(const String &p_path, const bool p_lossy = false, const float p_quality = 0.75f) const;
Vector<uint8_t> save_webp_to_buffer(const bool p_lossy = false, const float p_quality = 0.75f) const;
@ -373,6 +379,8 @@ public:
bool is_compressed() const;
static bool is_format_compressed(Format p_format);
static bool can_decompress(const String &p_format_tag);
void fix_alpha_edges();
void premultiply_alpha();
void srgb_to_linear();
@ -403,6 +411,7 @@ public:
Error load_tga_from_buffer(const Vector<uint8_t> &p_array);
Error load_bmp_from_buffer(const Vector<uint8_t> &p_array);
Error load_ktx_from_buffer(const Vector<uint8_t> &p_array);
Error load_dds_from_buffer(const Vector<uint8_t> &p_array);
Error load_svg_from_buffer(const Vector<uint8_t> &p_array, float scale = 1.0);
Error load_svg_from_string(const String &p_svg_str, float scale = 1.0);
@ -442,5 +451,3 @@ VARIANT_ENUM_CAST(Image::UsedChannels)
VARIANT_ENUM_CAST(Image::AlphaMode)
VARIANT_ENUM_CAST(Image::RoughnessChannel)
VARIANT_ENUM_CAST(Image::ASTCFormat)
#endif // IMAGE_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef IMAGE_LOADER_H
#define IMAGE_LOADER_H
#pragma once
#include "core/core_bind.h"
#include "core/io/file_access.h"
@ -108,5 +107,3 @@ public:
virtual bool handles_type(const String &p_type) const override;
virtual String get_resource_type(const String &p_path) const override;
};
#endif // IMAGE_LOADER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef IP_H
#define IP_H
#pragma once
#include "core/io/ip_address.h"
#include "core/os/os.h"
@ -110,5 +109,3 @@ public:
VARIANT_ENUM_CAST(IP::Type);
VARIANT_ENUM_CAST(IP::ResolverStatus);
#endif // IP_H

View file

@ -148,7 +148,7 @@ void IPAddress::_parse_ipv6(const String &p_string) {
void IPAddress::_parse_ipv4(const String &p_string, int p_start, uint8_t *p_ret) {
String ip;
if (p_start != 0) {
ip = p_string.substr(p_start, p_string.length() - p_start);
ip = p_string.substr(p_start);
} else {
ip = p_string;
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef IP_ADDRESS_H
#define IP_ADDRESS_H
#pragma once
#include "core/string/ustring.h"
@ -96,4 +95,6 @@ public:
IPAddress() { clear(); }
};
#endif // IP_ADDRESS_H
// Zero-constructing IPAddress initializes field, valid, and wildcard to 0 (and thus empty).
template <>
struct is_zero_constructible<IPAddress> : std::true_type {};

View file

@ -122,8 +122,7 @@ String JSON::_stringify(const Variant &p_var, const String &p_indent, int p_cur_
ERR_FAIL_COND_V_MSG(p_markers.has(d.id()), "\"{...}\"", "Converting circular structure to JSON.");
p_markers.insert(d.id());
List<Variant> keys;
d.get_key_list(&keys);
LocalVector<Variant> keys = d.get_key_list();
if (p_sort_keys) {
keys.sort_custom<StringLikeVariantOrder>();
@ -664,201 +663,96 @@ Variant JSON::_from_native(const Variant &p_variant, bool p_full_objects, int p_
case Variant::VECTOR2: {
const Vector2 v = p_variant;
Array args;
args.push_back(v.x);
args.push_back(v.y);
Array args = { v.x, v.y };
RETURN_ARGS;
} break;
case Variant::VECTOR2I: {
const Vector2i v = p_variant;
Array args;
args.push_back(v.x);
args.push_back(v.y);
Array args = { v.x, v.y };
RETURN_ARGS;
} break;
case Variant::RECT2: {
const Rect2 r = p_variant;
Array args;
args.push_back(r.position.x);
args.push_back(r.position.y);
args.push_back(r.size.width);
args.push_back(r.size.height);
Array args = { r.position.x, r.position.y, r.size.width, r.size.height };
RETURN_ARGS;
} break;
case Variant::RECT2I: {
const Rect2i r = p_variant;
Array args;
args.push_back(r.position.x);
args.push_back(r.position.y);
args.push_back(r.size.width);
args.push_back(r.size.height);
Array args = { r.position.x, r.position.y, r.size.width, r.size.height };
RETURN_ARGS;
} break;
case Variant::VECTOR3: {
const Vector3 v = p_variant;
Array args;
args.push_back(v.x);
args.push_back(v.y);
args.push_back(v.z);
Array args = { v.x, v.y, v.z };
RETURN_ARGS;
} break;
case Variant::VECTOR3I: {
const Vector3i v = p_variant;
Array args;
args.push_back(v.x);
args.push_back(v.y);
args.push_back(v.z);
Array args = { v.x, v.y, v.z };
RETURN_ARGS;
} break;
case Variant::TRANSFORM2D: {
const Transform2D t = p_variant;
Array args;
args.push_back(t[0].x);
args.push_back(t[0].y);
args.push_back(t[1].x);
args.push_back(t[1].y);
args.push_back(t[2].x);
args.push_back(t[2].y);
Array args = { t[0].x, t[0].y, t[1].x, t[1].y, t[2].x, t[2].y };
RETURN_ARGS;
} break;
case Variant::VECTOR4: {
const Vector4 v = p_variant;
Array args;
args.push_back(v.x);
args.push_back(v.y);
args.push_back(v.z);
args.push_back(v.w);
Array args = { v.x, v.y, v.z, v.w };
RETURN_ARGS;
} break;
case Variant::VECTOR4I: {
const Vector4i v = p_variant;
Array args;
args.push_back(v.x);
args.push_back(v.y);
args.push_back(v.z);
args.push_back(v.w);
Array args = { v.x, v.y, v.z, v.w };
RETURN_ARGS;
} break;
case Variant::PLANE: {
const Plane p = p_variant;
Array args;
args.push_back(p.normal.x);
args.push_back(p.normal.y);
args.push_back(p.normal.z);
args.push_back(p.d);
Array args = { p.normal.x, p.normal.y, p.normal.z, p.d };
RETURN_ARGS;
} break;
case Variant::QUATERNION: {
const Quaternion q = p_variant;
Array args;
args.push_back(q.x);
args.push_back(q.y);
args.push_back(q.z);
args.push_back(q.w);
Array args = { q.x, q.y, q.z, q.w };
RETURN_ARGS;
} break;
case Variant::AABB: {
const AABB aabb = p_variant;
Array args;
args.push_back(aabb.position.x);
args.push_back(aabb.position.y);
args.push_back(aabb.position.z);
args.push_back(aabb.size.x);
args.push_back(aabb.size.y);
args.push_back(aabb.size.z);
Array args = { aabb.position.x, aabb.position.y, aabb.position.z, aabb.size.x, aabb.size.y, aabb.size.z };
RETURN_ARGS;
} break;
case Variant::BASIS: {
const Basis b = p_variant;
Array args;
args.push_back(b.get_column(0).x);
args.push_back(b.get_column(0).y);
args.push_back(b.get_column(0).z);
args.push_back(b.get_column(1).x);
args.push_back(b.get_column(1).y);
args.push_back(b.get_column(1).z);
args.push_back(b.get_column(2).x);
args.push_back(b.get_column(2).y);
args.push_back(b.get_column(2).z);
Array args = { b.get_column(0).x, b.get_column(0).y, b.get_column(0).z,
b.get_column(1).x, b.get_column(1).y, b.get_column(1).z,
b.get_column(2).x, b.get_column(2).y, b.get_column(2).z };
RETURN_ARGS;
} break;
case Variant::TRANSFORM3D: {
const Transform3D t = p_variant;
Array args;
args.push_back(t.basis.get_column(0).x);
args.push_back(t.basis.get_column(0).y);
args.push_back(t.basis.get_column(0).z);
args.push_back(t.basis.get_column(1).x);
args.push_back(t.basis.get_column(1).y);
args.push_back(t.basis.get_column(1).z);
args.push_back(t.basis.get_column(2).x);
args.push_back(t.basis.get_column(2).y);
args.push_back(t.basis.get_column(2).z);
args.push_back(t.origin.x);
args.push_back(t.origin.y);
args.push_back(t.origin.z);
Array args = { t.basis.get_column(0).x, t.basis.get_column(0).y, t.basis.get_column(0).z,
t.basis.get_column(1).x, t.basis.get_column(1).y, t.basis.get_column(1).z,
t.basis.get_column(2).x, t.basis.get_column(2).y, t.basis.get_column(2).z,
t.origin.x, t.origin.y, t.origin.z };
RETURN_ARGS;
} break;
case Variant::PROJECTION: {
const Projection p = p_variant;
Array args;
args.push_back(p[0].x);
args.push_back(p[0].y);
args.push_back(p[0].z);
args.push_back(p[0].w);
args.push_back(p[1].x);
args.push_back(p[1].y);
args.push_back(p[1].z);
args.push_back(p[1].w);
args.push_back(p[2].x);
args.push_back(p[2].y);
args.push_back(p[2].z);
args.push_back(p[2].w);
args.push_back(p[3].x);
args.push_back(p[3].y);
args.push_back(p[3].z);
args.push_back(p[3].w);
Array args = { p[0].x, p[0].y, p[0].z, p[0].w,
p[1].x, p[1].y, p[1].z, p[1].w,
p[2].x, p[2].y, p[2].z, p[2].w,
p[3].x, p[3].y, p[3].z, p[3].w };
RETURN_ARGS;
} break;
case Variant::COLOR: {
const Color c = p_variant;
Array args;
args.push_back(c.r);
args.push_back(c.g);
args.push_back(c.b);
args.push_back(c.a);
Array args = { c.r, c.g, c.b, c.a };
RETURN_ARGS;
} break;
@ -922,12 +816,9 @@ Variant JSON::_from_native(const Variant &p_variant, bool p_full_objects, int p_
ERR_FAIL_COND_V_MSG(p_depth > Variant::MAX_RECURSION_DEPTH, ret, "Variant is too deep. Bailing.");
List<Variant> keys;
dict.get_key_list(&keys);
for (const Variant &key : keys) {
args.push_back(_from_native(key, p_full_objects, p_depth + 1));
args.push_back(_from_native(dict[key], p_full_objects, p_depth + 1));
for (const KeyValue<Variant, Variant> &kv : dict) {
args.push_back(_from_native(kv.key, p_full_objects, p_depth + 1));
args.push_back(_from_native(kv.value, p_full_objects, p_depth + 1));
}
return ret;

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef JSON_H
#define JSON_H
#pragma once
#include "core/io/resource.h"
#include "core/io/resource_loader.h"
@ -125,5 +124,3 @@ public:
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const override;
virtual bool recognize(const Ref<Resource> &p_resource) const override;
};
#endif // JSON_H

View file

@ -36,10 +36,9 @@
#include "core/templates/rb_set.h"
#include "modules/modules_enabled.gen.h" // For regex.
#ifdef MODULE_REGEX_ENABLED
#include "modules/regex/regex.h"
#else
class RegEx : public RefCounted {};
#endif // MODULE_REGEX_ENABLED
#if defined(MINGW_ENABLED) || defined(_MSC_VER)
@ -156,7 +155,7 @@ void RotatedFileLogger::rotate_file() {
if (FileAccess::exists(base_path)) {
if (max_files > 1) {
String timestamp = Time::get_singleton()->get_datetime_string_from_system().replace(":", ".");
String timestamp = Time::get_singleton()->get_datetime_string_from_system().replace_char(':', '.');
String backup_name = base_path.get_basename() + timestamp;
if (!base_path.get_extension().is_empty()) {
backup_name += "." + base_path.get_extension();

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef LOGGER_H
#define LOGGER_H
#pragma once
#include "core/io/file_access.h"
#include "core/string/ustring.h"
@ -109,5 +108,3 @@ public:
virtual ~CompositeLogger();
};
#endif // LOGGER_H

View file

@ -107,7 +107,7 @@ static Error _decode_string(const uint8_t *&buf, int &len, int *r_len, String &r
ERR_FAIL_COND_V(strlen < 0 || strlen + pad > len, ERR_FILE_EOF);
String str;
ERR_FAIL_COND_V(str.parse_utf8((const char *)buf, strlen) != OK, ERR_INVALID_DATA);
ERR_FAIL_COND_V(str.append_utf8((const char *)buf, strlen) != OK, ERR_INVALID_DATA);
r_string = str;
// Add padding.
@ -1345,7 +1345,7 @@ static Error _encode_container_type(const ContainerType &p_type, uint8_t *&buf,
_encode_string(EncodedObjectAsID::get_class_static(), buf, r_len);
}
} else if (p_type.class_name != StringName()) {
_encode_string(p_full_objects ? p_type.class_name.operator String() : EncodedObjectAsID::get_class_static(), buf, r_len);
_encode_string(p_full_objects ? p_type.class_name : EncodedObjectAsID::get_class_static(), buf, r_len);
} else {
// No need to check `p_full_objects` since `class_name` should be non-empty for `builtin_type == Variant::OBJECT`.
if (buf) {
@ -1849,19 +1849,16 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
}
r_len += 4;
List<Variant> keys;
dict.get_key_list(&keys);
for (const Variant &key : keys) {
for (const KeyValue<Variant, Variant> &kv : dict) {
int len;
Error err = encode_variant(key, buf, len, p_full_objects, p_depth + 1);
Error err = encode_variant(kv.key, buf, len, p_full_objects, p_depth + 1);
ERR_FAIL_COND_V(err, err);
ERR_FAIL_COND_V(len % 4, ERR_BUG);
r_len += len;
if (buf) {
buf += len;
}
const Variant *value = dict.getptr(key);
const Variant *value = dict.getptr(kv.key);
ERR_FAIL_NULL_V(value, ERR_BUG);
err = encode_variant(*value, buf, len, p_full_objects, p_depth + 1);
ERR_FAIL_COND_V(err, err);

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef MARSHALLS_H
#define MARSHALLS_H
#pragma once
#include "core/math/math_defs.h"
#include "core/object/ref_counted.h"
@ -226,5 +225,3 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_full_objects = false, int p_depth = 0);
Vector<float> vector3_to_float32_array(const Vector3 *vecs, size_t count);
#endif // MARSHALLS_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef MISSING_RESOURCE_H
#define MISSING_RESOURCE_H
#pragma once
#include "core/io/resource.h"
@ -61,5 +60,3 @@ public:
MissingResource();
};
#endif // MISSING_RESOURCE_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef NET_SOCKET_H
#define NET_SOCKET_H
#pragma once
#include "core/io/ip.h"
#include "core/object/ref_counted.h"
@ -79,5 +78,3 @@ public:
virtual ~NetSocket() {}
};
#endif // NET_SOCKET_H

View file

@ -268,14 +268,12 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd
encode_uint32(TYPE_DICT, &tmpdata.write[pos + 0]);
encode_uint32(len, &tmpdata.write[pos + 4]);
List<Variant> keys;
d.get_key_list(&keys);
List<DictKey> sortk;
for (const Variant &key : keys) {
for (const KeyValue<Variant, Variant> &kv : d) {
DictKey dk;
dk.hash = key.hash();
dk.key = key;
dk.hash = kv.key.hash();
dk.key = kv.key;
sortk.push_back(dk);
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef PACKED_DATA_CONTAINER_H
#define PACKED_DATA_CONTAINER_H
#pragma once
#include "core/io/resource.h"
@ -100,5 +99,3 @@ public:
PackedDataContainerRef() {}
};
#endif // PACKED_DATA_CONTAINER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef PACKET_PEER_H
#define PACKET_PEER_H
#pragma once
#include "core/io/stream_peer.h"
#include "core/object/class_db.h"
@ -124,5 +123,3 @@ public:
int get_output_buffer_max_size() const;
PacketPeerStream();
};
#endif // PACKET_PEER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef PACKET_PEER_DTLS_H
#define PACKET_PEER_DTLS_H
#pragma once
#include "core/crypto/crypto.h"
#include "core/io/packet_peer_udp.h"
@ -64,5 +63,3 @@ public:
};
VARIANT_ENUM_CAST(PacketPeerDTLS::Status);
#endif // PACKET_PEER_DTLS_H

View file

@ -105,18 +105,16 @@ Error PacketPeerUDP::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
return ERR_UNAVAILABLE;
}
/* Bogus GCC warning here:
* In member function 'int RingBuffer<T>::read(T*, int, bool) [with T = unsigned char]',
* inlined from 'virtual Error PacketPeerUDP::get_packet(const uint8_t**, int&)' at core/io/packet_peer_udp.cpp:112:9,
* inlined from 'virtual Error PacketPeerUDP::get_packet(const uint8_t**, int&)' at core/io/packet_peer_udp.cpp:99:7:
* Error: ./core/ring_buffer.h:68:46: error: writing 1 byte into a region of size 0 [-Werror=stringop-overflow=]
* 68 | p_buf[dst++] = read[pos + i];
* | ~~~~~~~~~~~~~^~~~~~~
*/
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic warning "-Wstringop-overflow=0"
#endif
/* Bogus GCC warning here:
* In member function 'int RingBuffer<T>::read(T*, int, bool) [with T = unsigned char]',
* inlined from 'virtual Error PacketPeerUDP::get_packet(const uint8_t**, int&)' at core/io/packet_peer_udp.cpp:112:9,
* inlined from 'virtual Error PacketPeerUDP::get_packet(const uint8_t**, int&)' at core/io/packet_peer_udp.cpp:99:7:
* Error: ./core/ring_buffer.h:68:46: error: writing 1 byte into a region of size 0 [-Werror=stringop-overflow=]
* 68 | p_buf[dst++] = read[pos + i];
* | ~~~~~~~~~~~~~^~~~~~~
*/
GODOT_GCC_WARNING_PUSH
GODOT_GCC_PRAGMA(GCC diagnostic warning "-Wstringop-overflow=0") // Can't "ignore" this for some reason.
uint32_t size = 0;
uint8_t ipv6[16] = {};
@ -129,9 +127,7 @@ Error PacketPeerUDP::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
*r_buffer = packet_buffer;
r_buffer_size = size;
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
GODOT_GCC_WARNING_POP
return OK;
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef PACKET_PEER_UDP_H
#define PACKET_PEER_UDP_H
#pragma once
#include "core/io/ip.h"
#include "core/io/net_socket.h"
@ -97,5 +96,3 @@ public:
PacketPeerUDP();
~PacketPeerUDP();
};
#endif // PACKET_PEER_UDP_H

View file

@ -91,9 +91,9 @@ Error PCKPacker::pck_start(const String &p_pck_path, int p_alignment, const Stri
file->store_32(PACK_HEADER_MAGIC);
file->store_32(PACK_FORMAT_VERSION);
file->store_32(VERSION_MAJOR);
file->store_32(VERSION_MINOR);
file->store_32(VERSION_PATCH);
file->store_32(GODOT_VERSION_MAJOR);
file->store_32(GODOT_VERSION_MINOR);
file->store_32(GODOT_VERSION_PATCH);
uint32_t pack_flags = 0;
if (enc_dir) {
@ -118,8 +118,7 @@ Error PCKPacker::add_file_removal(const String &p_target_path) {
pf.size = 0;
pf.removal = true;
pf.md5.resize(16);
pf.md5.fill(0);
pf.md5.resize_zeroed(16);
files.push_back(pf);

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef PCK_PACKER_H
#define PCK_PACKER_H
#pragma once
#include "core/object/ref_counted.h"
@ -66,5 +65,3 @@ public:
PCKPacker() {}
};
#endif // PCK_PACKER_H

View file

@ -383,14 +383,16 @@ void PListNode::store_text(String &p_stream, uint8_t p_indent) const {
p_stream += String("\t").repeat(p_indent);
p_stream += "<data>\n";
p_stream += String("\t").repeat(p_indent);
p_stream += data_string + "\n";
// Data should be Base64 (i.e. ASCII only).
p_stream += String::ascii(data_string) + "\n";
p_stream += String("\t").repeat(p_indent);
p_stream += "</data>\n";
} break;
case PList::PLNodeType::PL_NODE_TYPE_DATE: {
p_stream += String("\t").repeat(p_indent);
p_stream += "<date>";
p_stream += data_string;
// Data should be ISO 8601 (i.e. ASCII only).
p_stream += String::ascii(data_string);
p_stream += "</date>\n";
} break;
case PList::PLNodeType::PL_NODE_TYPE_STRING: {
@ -629,7 +631,7 @@ bool PList::load_file(const String &p_filename) {
unsigned char magic[8];
fb->get_buffer(magic, 8);
if (String((const char *)magic, 8) == "bplist00") {
if (String::ascii(Span((const char *)magic, 8)) == "bplist00") {
fb->seek_end(-26);
trailer.offset_size = fb->get_8();
trailer.ref_size = fb->get_8();
@ -645,10 +647,8 @@ bool PList::load_file(const String &p_filename) {
Vector<uint8_t> array = FileAccess::get_file_as_bytes(p_filename, &err);
ERR_FAIL_COND_V(err != OK, false);
String ret;
ret.parse_utf8((const char *)array.ptr(), array.size());
String err_str;
bool ok = load_string(ret, err_str);
bool ok = load_string(String::utf8((const char *)array.ptr(), array.size()), err_str);
ERR_FAIL_COND_V_MSG(!ok, false, "PList: " + err_str);
return true;

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef PLIST_H
#define PLIST_H
#pragma once
// Property list file format (application/x-plist) parser, property list ASN-1 serialization.
@ -84,6 +83,8 @@ public:
/*************************************************************************/
class PListNode : public RefCounted {
GDSOFTCLASS(PListNode, RefCounted);
static int _asn1_size_len(uint8_t p_len_octets);
public:
@ -122,5 +123,3 @@ public:
PListNode() {}
~PListNode() {}
};
#endif // PLIST_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef REMOTE_FILESYSTEM_CLIENT_H
#define REMOTE_FILESYSTEM_CLIENT_H
#pragma once
#include "core/string/ustring.h"
#include "core/templates/hash_set.h"
@ -60,5 +59,3 @@ public:
Error synchronize_with_server(const String &p_host, int p_port, const String &p_password, String &r_cache_path);
virtual ~RemoteFilesystemClient() {}
};
#endif // REMOTE_FILESYSTEM_CLIENT_H

View file

@ -32,10 +32,15 @@
#include "core/io/resource_loader.h"
#include "core/math/math_funcs.h"
#include "core/math/random_pcg.h"
#include "core/os/os.h"
#include "scene/main/node.h" //only so casting works
void Resource::emit_changed() {
if (emit_changed_state != EMIT_CHANGED_UNBLOCKED) {
emit_changed_state = EMIT_CHANGED_BLOCKED_PENDING_EMIT;
return;
}
if (ResourceLoader::is_within_load() && !Thread::is_main_thread()) {
ResourceLoader::resource_changed_emit(this);
return;
@ -44,6 +49,20 @@ void Resource::emit_changed() {
emit_signal(CoreStringName(changed));
}
void Resource::_block_emit_changed() {
if (emit_changed_state == EMIT_CHANGED_UNBLOCKED) {
emit_changed_state = EMIT_CHANGED_BLOCKED;
}
}
void Resource::_unblock_emit_changed() {
bool emit = (emit_changed_state == EMIT_CHANGED_BLOCKED_PENDING_EMIT);
emit_changed_state = EMIT_CHANGED_UNBLOCKED;
if (emit) {
emit_changed();
}
}
void Resource::_resource_path_changed() {
}
@ -95,7 +114,7 @@ void Resource::set_path_cache(const String &p_path) {
GDVIRTUAL_CALL(_set_path_cache, p_path);
}
static thread_local RandomPCG unique_id_gen(0, RandomPCG::DEFAULT_INC);
static thread_local RandomPCG unique_id_gen = RandomPCG(0);
void Resource::seed_scene_unique_id(uint32_t p_seed) {
unique_id_gen.seed(p_seed);
@ -205,6 +224,8 @@ Error Resource::copy_from(const Ref<Resource> &p_resource) {
return ERR_INVALID_PARAMETER;
}
_block_emit_changed();
reset_state(); // May want to reset state.
List<PropertyInfo> pi;
@ -220,6 +241,9 @@ Error Resource::copy_from(const Ref<Resource> &p_resource) {
set(E.name, p_resource->get(E.name));
}
_unblock_emit_changed();
return OK;
}
@ -248,9 +272,7 @@ void Resource::_dupe_sub_resources(Variant &r_variant, Node *p_for_scene, HashMa
} break;
case Variant::DICTIONARY: {
Dictionary d = r_variant;
List<Variant> keys;
d.get_key_list(&keys);
for (Variant &k : keys) {
for (Variant &k : d.get_key_list()) {
if (k.get_type() == Variant::OBJECT) {
// Replace in dictionary key.
Ref<Resource> sr = k;
@ -322,11 +344,9 @@ void Resource::_find_sub_resources(const Variant &p_variant, HashSet<Ref<Resourc
} break;
case Variant::DICTIONARY: {
Dictionary d = p_variant;
List<Variant> keys;
d.get_key_list(&keys);
for (const Variant &k : keys) {
_find_sub_resources(k, p_resources_found);
_find_sub_resources(d[k], p_resources_found);
for (const KeyValue<Variant, Variant> &kv : d) {
_find_sub_resources(kv.key, p_resources_found);
_find_sub_resources(kv.value, p_resources_found);
}
} break;
case Variant::OBJECT: {

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef RESOURCE_H
#define RESOURCE_H
#pragma once
#include "core/io/resource_uid.h"
#include "core/object/class_db.h"
@ -72,6 +71,12 @@ private:
String import_path;
#endif
enum EmitChangedState {
EMIT_CHANGED_UNBLOCKED,
EMIT_CHANGED_BLOCKED,
EMIT_CHANGED_BLOCKED_PENDING_EMIT,
};
EmitChangedState emit_changed_state = EMIT_CHANGED_UNBLOCKED;
bool local_to_scene = false;
friend class SceneState;
Node *local_scene = nullptr;
@ -85,6 +90,9 @@ protected:
virtual void _resource_path_changed();
static void _bind_methods();
void _block_emit_changed();
void _unblock_emit_changed();
void _set_path(const String &p_path);
void _take_over_path(const String &p_path);
@ -179,5 +187,3 @@ public:
static void get_cached_resources(List<Ref<Resource>> *p_resources);
static int get_cached_resource_count();
};
#endif // RESOURCE_H

View file

@ -162,9 +162,7 @@ StringName ResourceLoaderBinary::_get_string() {
return StringName();
}
f->get_buffer((uint8_t *)&str_buf[0], len);
String s;
s.parse_utf8(&str_buf[0], len);
return s;
return String::utf8(&str_buf[0], len);
}
return string_map[id];
@ -918,9 +916,7 @@ static String get_ustring(Ref<FileAccess> f) {
Vector<char> str_buf;
str_buf.resize(len);
f->get_buffer((uint8_t *)&str_buf[0], len);
String s;
s.parse_utf8(&str_buf[0], len);
return s;
return String::utf8(&str_buf[0], len);
}
String ResourceLoaderBinary::get_unicode_string() {
@ -932,9 +928,7 @@ String ResourceLoaderBinary::get_unicode_string() {
return String();
}
f->get_buffer((uint8_t *)&str_buf[0], len);
String s;
s.parse_utf8(&str_buf[0], len);
return s;
return String::utf8(&str_buf[0], len);
}
void ResourceLoaderBinary::get_classes_used(Ref<FileAccess> p_f, HashSet<StringName> *p_classes) {
@ -1028,10 +1022,10 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p
print_bl("minor: " + itos(ver_minor));
print_bl("format: " + itos(ver_format));
if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
if (ver_format > FORMAT_VERSION || ver_major > GODOT_VERSION_MAJOR) {
f.unref();
ERR_FAIL_MSG(vformat("File '%s' can't be loaded, as it uses a format version (%d) or engine version (%d.%d) which are not supported by your engine version (%s).",
local_path, ver_format, ver_major, ver_minor, VERSION_BRANCH));
local_path, ver_format, ver_major, ver_minor, GODOT_VERSION_BRANCH));
}
type = get_unicode_string();
@ -1155,7 +1149,7 @@ String ResourceLoaderBinary::recognize(Ref<FileAccess> p_f) {
f->get_32(); // ver_minor
uint32_t ver_fmt = f->get_32();
if (ver_fmt > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
if (ver_fmt > FORMAT_VERSION || ver_major > GODOT_VERSION_MAJOR) {
f.unref();
return "";
}
@ -1196,7 +1190,7 @@ String ResourceLoaderBinary::recognize_script_class(Ref<FileAccess> p_f) {
f->get_32(); // ver_minor
uint32_t ver_fmt = f->get_32();
if (ver_fmt > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
if (ver_fmt > FORMAT_VERSION || ver_major > GODOT_VERSION_MAJOR) {
f.unref();
return "";
}
@ -1348,13 +1342,10 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
bool use_real64 = f->get_32();
f->set_big_endian(big_endian != 0); //read big endian if saved as big endian
#ifdef BIG_ENDIAN_ENABLED
fw->store_32(!big_endian);
#else
fw->store_32(big_endian);
#endif
fw->set_big_endian(big_endian != 0);
fw->store_32(use_real64); //use real64
fw->set_big_endian(big_endian != 0);
uint32_t ver_major = f->get_32();
uint32_t ver_minor = f->get_32();
@ -1392,10 +1383,10 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
return ResourceFormatSaverBinary::singleton->save(res, p_path);
}
if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
if (ver_format > FORMAT_VERSION || ver_major > GODOT_VERSION_MAJOR) {
ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED,
vformat("File '%s' can't be loaded, as it uses a format version (%d) or engine version (%d.%d) which are not supported by your engine version (%s).",
local_path, ver_format, ver_major, ver_minor, VERSION_BRANCH));
local_path, ver_format, ver_major, ver_minor, GODOT_VERSION_BRANCH));
}
// Since we're not actually converting the file contents, leave the version
@ -1876,12 +1867,9 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
Dictionary d = p_property;
f->store_32(uint32_t(d.size()));
List<Variant> keys;
d.get_key_list(&keys);
for (const Variant &E : keys) {
write_variant(f, E, resource_map, external_resources, string_map);
write_variant(f, d[E], resource_map, external_resources, string_map);
for (const KeyValue<Variant, Variant> &kv : d) {
write_variant(f, kv.key, resource_map, external_resources, string_map);
write_variant(f, kv.value, resource_map, external_resources, string_map);
}
} break;
@ -2086,12 +2074,9 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant
Dictionary d = p_variant;
_find_resources(d.get_typed_key_script());
_find_resources(d.get_typed_value_script());
List<Variant> keys;
d.get_key_list(&keys);
for (const Variant &E : keys) {
_find_resources(E);
Variant v = d[E];
_find_resources(v);
for (const KeyValue<Variant, Variant> &kv : d) {
_find_resources(kv.key);
_find_resources(kv.value);
}
} break;
case Variant::NODE_PATH: {
@ -2180,14 +2165,14 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Re
if (big_endian) {
f->store_32(1);
f->set_big_endian(true);
} else {
f->store_32(0);
}
f->store_32(0); //64 bits file, false for now
f->store_32(VERSION_MAJOR);
f->store_32(VERSION_MINOR);
f->set_big_endian(big_endian);
f->store_32(GODOT_VERSION_MAJOR);
f->store_32(GODOT_VERSION_MINOR);
f->store_32(FORMAT_VERSION);
if (f->get_error() != OK && f->get_error() != ERR_FILE_EOF) {
@ -2424,13 +2409,10 @@ Error ResourceFormatSaverBinaryInstance::set_uid(const String &p_path, ResourceU
big_endian = f->get_32();
bool use_real64 = f->get_32();
f->set_big_endian(big_endian != 0); //read big endian if saved as big endian
#ifdef BIG_ENDIAN_ENABLED
fw->store_32(!big_endian);
#else
fw->store_32(big_endian);
#endif
fw->set_big_endian(big_endian != 0);
fw->store_32(use_real64); //use real64
fw->set_big_endian(big_endian != 0);
uint32_t ver_major = f->get_32();
uint32_t ver_minor = f->get_32();
@ -2450,10 +2432,10 @@ Error ResourceFormatSaverBinaryInstance::set_uid(const String &p_path, ResourceU
return ERR_UNAVAILABLE;
}
if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
if (ver_format > FORMAT_VERSION || ver_major > GODOT_VERSION_MAJOR) {
ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED,
vformat("File '%s' can't be loaded, as it uses a format version (%d) or engine version (%d.%d) which are not supported by your engine version (%s).",
local_path, ver_format, ver_major, ver_minor, VERSION_BRANCH));
local_path, ver_format, ver_major, ver_minor, GODOT_VERSION_BRANCH));
}
// Since we're not actually converting the file contents, leave the version

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef RESOURCE_FORMAT_BINARY_H
#define RESOURCE_FORMAT_BINARY_H
#pragma once
#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
@ -189,5 +188,3 @@ public:
ResourceFormatSaverBinary();
};
#endif // RESOURCE_FORMAT_BINARY_H

View file

@ -32,6 +32,7 @@
#include "core/config/project_settings.h"
#include "core/io/config_file.h"
#include "core/io/image.h"
#include "core/os/os.h"
#include "core/variant/variant_parser.h"
@ -41,7 +42,7 @@ bool ResourceFormatImporter::SortImporterByName::operator()(const Ref<ResourceIm
return p_a->get_importer_name() < p_b->get_importer_name();
}
Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndType &r_path_and_type, bool *r_valid) const {
Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndType &r_path_and_type, bool p_load, bool *r_valid) const {
Error err;
Ref<FileAccess> f = FileAccess::open(p_path + ".import", FileAccess::READ, &err);
@ -65,7 +66,10 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
int lines = 0;
String error_text;
bool path_found = false; //first match must have priority
bool path_found = false; // First match must have priority.
String decomp_path;
bool decomp_path_found = false;
while (true) {
assign = Variant();
next_tag.fields.clear();
@ -73,6 +77,11 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, nullptr, true);
if (err == ERR_FILE_EOF) {
if (p_load && !path_found && decomp_path_found) {
print_verbose(vformat("No natively supported texture format found for %s, using decompressable format %s.", p_path, decomp_path));
r_path_and_type.path = decomp_path;
}
return OK;
} else if (err != OK) {
ERR_PRINT(vformat("ResourceFormatImporter::load - %s.import:%d error: %s.", p_path, lines, error_text));
@ -84,12 +93,15 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
String feature = assign.get_slicec('.', 1);
if (OS::get_singleton()->has_feature(feature)) {
r_path_and_type.path = value;
path_found = true; //first match must have priority
path_found = true; // First match must have priority.
} else if (p_load && Image::can_decompress(feature) && !decomp_path_found) { // When loading, check for decompressable formats and use first one found if nothing else is supported.
decomp_path = value;
decomp_path_found = true; // First match must have priority.
}
} else if (!path_found && assign == "path") {
r_path_and_type.path = value;
path_found = true; //first match must have priority
path_found = true; // First match must have priority.
} else if (assign == "type") {
r_path_and_type.type = ClassDB::get_compatibility_remapped_class(value);
} else if (assign == "importer") {
@ -154,7 +166,7 @@ Ref<Resource> ResourceFormatImporter::load(const String &p_path, const String &p
Ref<Resource> ResourceFormatImporter::load_internal(const String &p_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode, bool p_silence_errors) {
PathAndType pat;
Error err = _get_path_and_type(p_path, pat);
Error err = _get_path_and_type(p_path, pat, true);
if (err != OK) {
if (r_error) {
@ -244,13 +256,13 @@ Error ResourceFormatImporter::get_import_order_threads_and_importer(const String
if (FileAccess::exists(p_path + ".import")) {
PathAndType pat;
Error err = _get_path_and_type(p_path, pat);
Error err = _get_path_and_type(p_path, pat, false);
if (err == OK) {
importer = get_importer_by_name(pat.importer);
}
} else {
importer = get_importer_by_extension(p_path.get_extension().to_lower());
importer = get_importer_by_file(p_path);
}
if (importer.is_valid()) {
@ -268,13 +280,13 @@ int ResourceFormatImporter::get_import_order(const String &p_path) const {
if (FileAccess::exists(p_path + ".import")) {
PathAndType pat;
Error err = _get_path_and_type(p_path, pat);
Error err = _get_path_and_type(p_path, pat, false);
if (err == OK) {
importer = get_importer_by_name(pat.importer);
}
} else {
importer = get_importer_by_extension(p_path.get_extension().to_lower());
importer = get_importer_by_file(p_path);
}
if (importer.is_valid()) {
@ -300,7 +312,7 @@ bool ResourceFormatImporter::handles_type(const String &p_type) const {
String ResourceFormatImporter::get_internal_resource_path(const String &p_path) const {
PathAndType pat;
Error err = _get_path_and_type(p_path, pat);
Error err = _get_path_and_type(p_path, pat, false);
if (err != OK) {
return String();
@ -354,20 +366,20 @@ void ResourceFormatImporter::get_internal_resource_path_list(const String &p_pat
String ResourceFormatImporter::get_import_group_file(const String &p_path) const {
bool valid = true;
PathAndType pat;
_get_path_and_type(p_path, pat, &valid);
_get_path_and_type(p_path, pat, false, &valid);
return valid ? pat.group_file : String();
}
bool ResourceFormatImporter::is_import_valid(const String &p_path) const {
bool valid = true;
PathAndType pat;
_get_path_and_type(p_path, pat, &valid);
_get_path_and_type(p_path, pat, false, &valid);
return valid;
}
String ResourceFormatImporter::get_resource_type(const String &p_path) const {
PathAndType pat;
Error err = _get_path_and_type(p_path, pat);
Error err = _get_path_and_type(p_path, pat, false);
if (err != OK) {
return "";
@ -378,7 +390,7 @@ String ResourceFormatImporter::get_resource_type(const String &p_path) const {
ResourceUID::ID ResourceFormatImporter::get_resource_uid(const String &p_path) const {
PathAndType pat;
Error err = _get_path_and_type(p_path, pat);
Error err = _get_path_and_type(p_path, pat, false);
if (err != OK) {
return ResourceUID::INVALID_ID;
@ -393,7 +405,7 @@ bool ResourceFormatImporter::has_custom_uid_support() const {
Error ResourceFormatImporter::get_resource_import_info(const String &p_path, StringName &r_type, ResourceUID::ID &r_uid, String &r_import_group_file) const {
PathAndType pat;
Error err = _get_path_and_type(p_path, pat);
Error err = _get_path_and_type(p_path, pat, false);
if (err == OK) {
r_type = pat.type;
@ -410,7 +422,7 @@ Error ResourceFormatImporter::get_resource_import_info(const String &p_path, Str
Variant ResourceFormatImporter::get_resource_metadata(const String &p_path) const {
PathAndType pat;
Error err = _get_path_and_type(p_path, pat);
Error err = _get_path_and_type(p_path, pat, false);
if (err != OK) {
return Variant();
@ -420,7 +432,7 @@ Variant ResourceFormatImporter::get_resource_metadata(const String &p_path) cons
}
void ResourceFormatImporter::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) {
PathAndType pat;
Error err = _get_path_and_type(p_path, pat);
Error err = _get_path_and_type(p_path, pat, false);
if (err != OK) {
return;
@ -431,7 +443,7 @@ void ResourceFormatImporter::get_classes_used(const String &p_path, HashSet<Stri
void ResourceFormatImporter::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
PathAndType pat;
Error err = _get_path_and_type(p_path, pat);
Error err = _get_path_and_type(p_path, pat, false);
if (err != OK) {
return;
@ -459,12 +471,12 @@ void ResourceFormatImporter::add_importer(const Ref<ResourceImporter> &p_importe
}
}
void ResourceFormatImporter::get_importers_for_extension(const String &p_extension, List<Ref<ResourceImporter>> *r_importers) {
void ResourceFormatImporter::get_importers_for_file(const String &p_file, List<Ref<ResourceImporter>> *r_importers) {
for (int i = 0; i < importers.size(); i++) {
List<String> local_exts;
importers[i]->get_recognized_extensions(&local_exts);
for (const String &F : local_exts) {
if (p_extension.to_lower() == F) {
if (p_file.right(F.length()).nocasecmp_to(F) == 0) {
r_importers->push_back(importers[i]);
break;
}
@ -478,7 +490,7 @@ void ResourceFormatImporter::get_importers(List<Ref<ResourceImporter>> *r_import
}
}
Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_extension(const String &p_extension) const {
Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_file(const String &p_file) const {
Ref<ResourceImporter> importer;
float priority = 0;
@ -486,9 +498,10 @@ Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_extension(const St
List<String> local_exts;
importers[i]->get_recognized_extensions(&local_exts);
for (const String &F : local_exts) {
if (p_extension.to_lower() == F && importers[i]->get_priority() > priority) {
if (p_file.right(F.length()).nocasecmp_to(F) == 0 && importers[i]->get_priority() > priority) {
importer = importers[i];
priority = importers[i]->get_priority();
break;
}
}
}
@ -503,7 +516,7 @@ String ResourceFormatImporter::get_import_base_path(const String &p_for_file) co
bool ResourceFormatImporter::are_import_settings_valid(const String &p_path) const {
bool valid = true;
PathAndType pat;
_get_path_and_type(p_path, pat, &valid);
_get_path_and_type(p_path, pat, false, &valid);
if (!valid) {
return false;

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef RESOURCE_IMPORTER_H
#define RESOURCE_IMPORTER_H
#pragma once
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
@ -49,7 +48,7 @@ class ResourceFormatImporter : public ResourceFormatLoader {
ResourceUID::ID uid = ResourceUID::INVALID_ID;
};
Error _get_path_and_type(const String &p_path, PathAndType &r_path_and_type, bool *r_valid = nullptr) const;
Error _get_path_and_type(const String &p_path, PathAndType &r_path_and_type, bool p_load, bool *r_valid = nullptr) const;
static ResourceFormatImporter *singleton;
@ -90,8 +89,8 @@ public:
void remove_importer(const Ref<ResourceImporter> &p_importer) { importers.erase(p_importer); }
Ref<ResourceImporter> get_importer_by_name(const String &p_name) const;
Ref<ResourceImporter> get_importer_by_extension(const String &p_extension) const;
void get_importers_for_extension(const String &p_extension, List<Ref<ResourceImporter>> *r_importers);
Ref<ResourceImporter> get_importer_by_file(const String &p_file) const;
void get_importers_for_file(const String &p_file, List<Ref<ResourceImporter>> *r_importers);
void get_importers(List<Ref<ResourceImporter>> *r_importers);
bool are_import_settings_valid(const String &p_path) const;
@ -166,5 +165,3 @@ class ResourceFormatImporterSaver : public ResourceFormatSaver {
public:
virtual Error set_uid(const String &p_path, ResourceUID::ID p_uid) override;
};
#endif // RESOURCE_IMPORTER_H

View file

@ -61,8 +61,6 @@ bool ResourceFormatLoader::recognize_path(const String &p_path, const String &p_
return ret;
}
String extension = p_path.get_extension();
List<String> extensions;
if (p_for_type.is_empty()) {
get_recognized_extensions(&extensions);
@ -71,7 +69,8 @@ bool ResourceFormatLoader::recognize_path(const String &p_path, const String &p_
}
for (const String &E : extensions) {
if (E.nocasecmp_to(extension) == 0) {
const String ext = !E.begins_with(".") ? "." + E : E;
if (p_path.right(ext.length()).nocasecmp_to(ext) == 0) {
return true;
}
}
@ -264,6 +263,14 @@ void ResourceLoader::LoadToken::clear() {
thread_load_tasks.erase(local_path);
}
local_path.clear(); // Mark as already cleared.
if (task_to_await) {
for (KeyValue<String, ResourceLoader::ThreadLoadTask> &E : thread_load_tasks) {
if (E.value.task_id == task_to_await) {
task_to_await = 0;
break; // Same task is reused by nested loads, do not wait for completion here.
}
}
}
}
}
@ -322,7 +329,7 @@ Ref<Resource> ResourceLoader::_load(const String &p_path, const String &p_origin
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
if (ResourceFormatImporter::get_singleton()->get_importer_by_extension(p_path.get_extension()).is_valid()) {
if (ResourceFormatImporter::get_singleton()->get_importer_by_file(p_path).is_valid()) {
// The format is known to the editor, but the file hasn't been imported
// (otherwise, ResourceFormatImporter would have been found as a suitable loader).
found = true;
@ -772,6 +779,10 @@ Ref<Resource> ResourceLoader::_load_complete(LoadToken &p_load_token, Error *r_e
return _load_complete_inner(p_load_token, r_error, thread_load_lock);
}
void ResourceLoader::set_is_import_thread(bool p_import_thread) {
import_thread = p_import_thread;
}
Ref<Resource> ResourceLoader::_load_complete_inner(LoadToken &p_load_token, Error *r_error, MutexLock<SafeBinaryMutex<BINARY_MUTEX_TAG>> &p_thread_load_lock) {
if (r_error) {
*r_error = OK;
@ -825,6 +836,12 @@ Ref<Resource> ResourceLoader::_load_complete_inner(LoadToken &p_load_token, Erro
p_thread_load_lock.temp_relock();
load_task.awaited = true;
// Mark nested loads with the same task id as awaited.
for (KeyValue<String, ResourceLoader::ThreadLoadTask> &E : thread_load_tasks) {
if (E.value.task_id == load_task.task_id) {
E.value.awaited = true;
}
}
DEV_ASSERT(load_task.status == THREAD_LOAD_FAILED || load_task.status == THREAD_LOAD_LOADED);
} else if (load_task.need_wait) {
@ -886,9 +903,11 @@ Ref<Resource> ResourceLoader::_load_complete_inner(LoadToken &p_load_token, Erro
MessageQueue::get_main_singleton()->push_callable(callable_mp(rcc.source, &Resource::connect_changed).bind(rcc.callable, rcc.flags));
}
}
core_bind::Semaphore done;
MessageQueue::get_main_singleton()->push_callable(callable_mp(&done, &core_bind::Semaphore::post).bind(1));
done.wait();
if (!import_thread) { // Main thread is blocked by initial resource reimport, do not wait.
CoreBind::Semaphore done;
MessageQueue::get_main_singleton()->push_callable(callable_mp(&done, &CoreBind::Semaphore::post).bind(1));
done.wait();
}
}
}
}
@ -1339,10 +1358,8 @@ void ResourceLoader::load_translation_remaps() {
}
Dictionary remaps = GLOBAL_GET("internationalization/locale/translation_remaps");
List<Variant> keys;
remaps.get_key_list(&keys);
for (const Variant &E : keys) {
Array langs = remaps[E];
for (const KeyValue<Variant, Variant> &kv : remaps) {
Array langs = kv.value;
Vector<String> lang_remaps;
lang_remaps.resize(langs.size());
String *lang_remaps_ptrw = lang_remaps.ptrw();
@ -1350,7 +1367,7 @@ void ResourceLoader::load_translation_remaps() {
*lang_remaps_ptrw++ = lang;
}
translation_remaps[String(E)] = lang_remaps;
translation_remaps[String(kv.key)] = lang_remaps;
}
}
@ -1565,6 +1582,7 @@ bool ResourceLoader::create_missing_resources_if_class_unavailable = false;
bool ResourceLoader::abort_on_missing_resource = true;
bool ResourceLoader::timestamp_on_load = false;
thread_local bool ResourceLoader::import_thread = false;
thread_local int ResourceLoader::load_nesting = 0;
thread_local Vector<String> ResourceLoader::load_paths_stack;
thread_local HashMap<int, HashMap<String, Ref<Resource>>> ResourceLoader::res_ref_overrides;

View file

@ -28,15 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef RESOURCE_LOADER_H
#define RESOURCE_LOADER_H
#pragma once
#include "core/io/resource.h"
#include "core/object/gdvirtual.gen.inc"
#include "core/object/worker_thread_pool.h"
#include "core/os/thread.h"
namespace core_bind {
namespace CoreBind {
class ResourceLoader;
}
@ -105,7 +104,7 @@ typedef void (*ResourceLoadedCallback)(Ref<Resource> p_resource, const String &p
class ResourceLoader {
friend class LoadToken;
friend class core_bind::ResourceLoader;
friend class CoreBind::ResourceLoader;
enum {
MAX_LOADERS = 64
@ -205,6 +204,7 @@ private:
static void _run_load_task(void *p_userdata);
static thread_local bool import_thread;
static thread_local int load_nesting;
static thread_local HashMap<int, HashMap<String, Ref<Resource>>> res_ref_overrides; // Outermost key is nesting level.
static thread_local Vector<String> load_paths_stack;
@ -254,6 +254,8 @@ public:
static bool is_imported(const String &p_path);
static int get_import_order(const String &p_path);
static void set_is_import_thread(bool p_import_thread);
static void set_timestamp_on_load(bool p_timestamp) { timestamp_on_load = p_timestamp; }
static bool get_timestamp_on_load() { return timestamp_on_load; }
@ -316,5 +318,3 @@ public:
static void initialize();
static void finalize();
};
#endif // RESOURCE_LOADER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef RESOURCE_SAVER_H
#define RESOURCE_SAVER_H
#pragma once
#include "core/io/resource.h"
#include "core/object/gdvirtual.gen.inc"
@ -103,5 +102,3 @@ public:
static void add_custom_savers();
static void remove_custom_savers();
};
#endif // RESOURCE_SAVER_H

View file

@ -35,6 +35,7 @@
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
#include "core/math/random_pcg.h"
// These constants are off by 1, causing the 'z' and '9' characters never to be used.
// This cannot be fixed without breaking compatibility; see GH-83843.
@ -46,7 +47,7 @@ String ResourceUID::get_cache_file() {
}
static constexpr uint8_t uuid_characters[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', '0', '1', '2', '3', '4', '5', '6', '7', '8' };
static constexpr uint32_t uuid_characters_element_count = (sizeof(uuid_characters) / sizeof(*uuid_characters));
static constexpr uint32_t uuid_characters_element_count = std::size(uuid_characters);
static constexpr uint8_t max_uuid_number_length = 13; // Max 0x7FFFFFFFFFFFFFFF (uid://d4n4ub6itg400) size is 13 characters.
String ResourceUID::id_to_text(ID p_id) const {
@ -121,10 +122,31 @@ ResourceUID::ID ResourceUID::create_id() {
}
}
ResourceUID::ID ResourceUID::create_id_for_path(const String &p_path) {
ID id = INVALID_ID;
RandomPCG rng;
const String project_name = GLOBAL_GET("application/config/name");
rng.seed(project_name.hash64() * p_path.hash64() * FileAccess::get_md5(p_path).hash64());
while (true) {
int64_t num1 = rng.rand();
int64_t num2 = ((int64_t)rng.rand()) << 32;
id = (num1 | num2) & 0x7FFFFFFFFFFFFFFF;
MutexLock lock(mutex);
if (!unique_ids.has(id)) {
break;
}
}
return id;
}
bool ResourceUID::has_id(ID p_id) const {
MutexLock l(mutex);
return unique_ids.has(p_id);
}
void ResourceUID::add_id(ID p_id, const String &p_path) {
MutexLock l(mutex);
ERR_FAIL_COND(unique_ids.has(p_id));
@ -311,7 +333,7 @@ String ResourceUID::get_path_from_cache(Ref<FileAccess> &p_cache_file, const Str
ERR_FAIL_COND_V(rl != len, String());
if (singleton->id_to_text(id) == p_uid_string) {
return String(cs);
return String::utf8(cs.get_data());
}
}
return String();
@ -327,6 +349,7 @@ void ResourceUID::_bind_methods() {
ClassDB::bind_method(D_METHOD("text_to_id", "text_id"), &ResourceUID::text_to_id);
ClassDB::bind_method(D_METHOD("create_id"), &ResourceUID::create_id);
ClassDB::bind_method(D_METHOD("create_id_for_path", "path"), &ResourceUID::create_id_for_path);
ClassDB::bind_method(D_METHOD("has_id", "id"), &ResourceUID::has_id);
ClassDB::bind_method(D_METHOD("add_id", "id", "path"), &ResourceUID::add_id);

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef RESOURCE_UID_H
#define RESOURCE_UID_H
#pragma once
#include "core/object/ref_counted.h"
#include "core/string/string_name.h"
@ -71,6 +70,7 @@ public:
ID text_to_id(const String &p_text) const;
ID create_id();
ID create_id_for_path(const String &p_path);
bool has_id(ID p_id) const;
void add_id(ID p_id, const String &p_path);
void set_id(ID p_id, const String &p_path);
@ -93,5 +93,3 @@ public:
ResourceUID();
~ResourceUID();
};
#endif // RESOURCE_UID_H

View file

@ -125,54 +125,90 @@ void StreamPeer::put_8(int8_t p_val) {
}
void StreamPeer::put_u16(uint16_t p_val) {
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
p_val = BSWAP16(p_val);
}
#else
if (big_endian) {
p_val = BSWAP16(p_val);
}
#endif
uint8_t buf[2];
encode_uint16(p_val, buf);
put_data(buf, 2);
}
void StreamPeer::put_16(int16_t p_val) {
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
p_val = BSWAP16(p_val);
}
#else
if (big_endian) {
p_val = BSWAP16(p_val);
}
#endif
uint8_t buf[2];
encode_uint16(p_val, buf);
put_data(buf, 2);
}
void StreamPeer::put_u32(uint32_t p_val) {
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
p_val = BSWAP32(p_val);
}
#else
if (big_endian) {
p_val = BSWAP32(p_val);
}
#endif
uint8_t buf[4];
encode_uint32(p_val, buf);
put_data(buf, 4);
}
void StreamPeer::put_32(int32_t p_val) {
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
p_val = BSWAP32(p_val);
}
#else
if (big_endian) {
p_val = BSWAP32(p_val);
}
#endif
uint8_t buf[4];
encode_uint32(p_val, buf);
put_data(buf, 4);
}
void StreamPeer::put_u64(uint64_t p_val) {
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
p_val = BSWAP64(p_val);
}
#else
if (big_endian) {
p_val = BSWAP64(p_val);
}
#endif
uint8_t buf[8];
encode_uint64(p_val, buf);
put_data(buf, 8);
}
void StreamPeer::put_64(int64_t p_val) {
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
p_val = BSWAP64(p_val);
}
#else
if (big_endian) {
p_val = BSWAP64(p_val);
}
#endif
uint8_t buf[8];
encode_uint64(p_val, buf);
put_data(buf, 8);
@ -183,9 +219,15 @@ void StreamPeer::put_half(float p_val) {
encode_half(p_val, buf);
uint16_t *p16 = (uint16_t *)buf;
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
*p16 = BSWAP16(*p16);
}
#else
if (big_endian) {
*p16 = BSWAP16(*p16);
}
#endif
put_data(buf, 2);
}
@ -194,10 +236,17 @@ void StreamPeer::put_float(float p_val) {
uint8_t buf[4];
encode_float(p_val, buf);
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
uint32_t *p32 = (uint32_t *)buf;
*p32 = BSWAP32(*p32);
}
#else
if (big_endian) {
uint32_t *p32 = (uint32_t *)buf;
*p32 = BSWAP32(*p32);
}
#endif
put_data(buf, 4);
}
@ -206,10 +255,17 @@ void StreamPeer::put_double(double p_val) {
uint8_t buf[8];
encode_double(p_val, buf);
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
uint64_t *p64 = (uint64_t *)buf;
*p64 = BSWAP64(*p64);
}
#else
if (big_endian) {
uint64_t *p64 = (uint64_t *)buf;
*p64 = BSWAP64(*p64);
}
#endif
put_data(buf, 8);
}
@ -253,9 +309,15 @@ uint16_t StreamPeer::get_u16() {
get_data(buf, 2);
uint16_t r = decode_uint16(buf);
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
r = BSWAP16(r);
}
#else
if (big_endian) {
r = BSWAP16(r);
}
#endif
return r;
}
@ -265,9 +327,15 @@ int16_t StreamPeer::get_16() {
get_data(buf, 2);
uint16_t r = decode_uint16(buf);
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
r = BSWAP16(r);
}
#else
if (big_endian) {
r = BSWAP16(r);
}
#endif
return int16_t(r);
}
@ -277,9 +345,15 @@ uint32_t StreamPeer::get_u32() {
get_data(buf, 4);
uint32_t r = decode_uint32(buf);
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
r = BSWAP32(r);
}
#else
if (big_endian) {
r = BSWAP32(r);
}
#endif
return r;
}
@ -289,9 +363,15 @@ int32_t StreamPeer::get_32() {
get_data(buf, 4);
uint32_t r = decode_uint32(buf);
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
r = BSWAP32(r);
}
#else
if (big_endian) {
r = BSWAP32(r);
}
#endif
return int32_t(r);
}
@ -301,9 +381,15 @@ uint64_t StreamPeer::get_u64() {
get_data(buf, 8);
uint64_t r = decode_uint64(buf);
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
r = BSWAP64(r);
}
#else
if (big_endian) {
r = BSWAP64(r);
}
#endif
return r;
}
@ -313,9 +399,15 @@ int64_t StreamPeer::get_64() {
get_data(buf, 8);
uint64_t r = decode_uint64(buf);
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
r = BSWAP64(r);
}
#else
if (big_endian) {
r = BSWAP64(r);
}
#endif
return int64_t(r);
}
@ -324,10 +416,17 @@ float StreamPeer::get_half() {
uint8_t buf[2];
get_data(buf, 2);
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
uint16_t *p16 = (uint16_t *)buf;
*p16 = BSWAP16(*p16);
}
#else
if (big_endian) {
uint16_t *p16 = (uint16_t *)buf;
*p16 = BSWAP16(*p16);
}
#endif
return decode_half(buf);
}
@ -336,10 +435,17 @@ float StreamPeer::get_float() {
uint8_t buf[4];
get_data(buf, 4);
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
uint32_t *p32 = (uint32_t *)buf;
*p32 = BSWAP32(*p32);
}
#else
if (big_endian) {
uint32_t *p32 = (uint32_t *)buf;
*p32 = BSWAP32(*p32);
}
#endif
return decode_float(buf);
}
@ -348,10 +454,17 @@ double StreamPeer::get_double() {
uint8_t buf[8];
get_data(buf, 8);
#ifdef BIG_ENDIAN_ENABLED
if (!big_endian) {
uint64_t *p64 = (uint64_t *)buf;
*p64 = BSWAP64(*p64);
}
#else
if (big_endian) {
uint64_t *p64 = (uint64_t *)buf;
*p64 = BSWAP64(*p64);
}
#endif
return decode_double(buf);
}
@ -383,9 +496,7 @@ String StreamPeer::get_utf8_string(int p_bytes) {
err = get_data(buf.ptrw(), p_bytes);
ERR_FAIL_COND_V(err != OK, String());
String ret;
ret.parse_utf8((const char *)buf.ptr(), buf.size());
return ret;
return String::utf8((const char *)buf.ptr(), buf.size());
}
Variant StreamPeer::get_var(bool p_allow_objects) {

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef STREAM_PEER_H
#define STREAM_PEER_H
#pragma once
#include "core/object/ref_counted.h"
@ -50,7 +49,11 @@ protected:
Array _get_data(int p_bytes);
Array _get_partial_data(int p_bytes);
#ifdef BIG_ENDIAN_ENABLED
bool big_endian = true;
#else
bool big_endian = false;
#endif
public:
virtual Error put_data(const uint8_t *p_data, int p_bytes) = 0; ///< put a whole chunk of data, blocking until it sent
@ -152,5 +155,3 @@ public:
StreamPeerBuffer() {}
};
#endif // STREAM_PEER_H

View file

@ -195,12 +195,12 @@ int StreamPeerGZIP::get_available_bytes() const {
Error StreamPeerGZIP::finish() {
ERR_FAIL_COND_V(!ctx || !compressing, ERR_UNAVAILABLE);
// Ensure we have enough space in temporary buffer.
if (buffer.size() < 1024) {
buffer.resize(1024); // 1024 should be more than enough.
if (buffer.size() < get_available_bytes()) {
buffer.resize(get_available_bytes()); // get_available_bytes() is what we can store in RingBuffer.
}
int consumed = 0;
int to_write = 0;
Error err = _process(buffer.ptrw(), 1024, nullptr, 0, consumed, to_write, true); // compress
Error err = _process(buffer.ptrw(), buffer.size(), nullptr, 0, consumed, to_write, true); // compress
if (err != OK) {
return err;
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef STREAM_PEER_GZIP_H
#define STREAM_PEER_GZIP_H
#pragma once
#include "core/io/stream_peer.h"
@ -72,5 +71,3 @@ public:
StreamPeerGZIP();
~StreamPeerGZIP();
};
#endif // STREAM_PEER_GZIP_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef STREAM_PEER_TCP_H
#define STREAM_PEER_TCP_H
#pragma once
#include "core/io/ip.h"
#include "core/io/ip_address.h"
@ -92,5 +91,3 @@ public:
};
VARIANT_ENUM_CAST(StreamPeerTCP::Status);
#endif // STREAM_PEER_TCP_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef STREAM_PEER_TLS_H
#define STREAM_PEER_TLS_H
#pragma once
#include "core/crypto/crypto.h"
#include "core/io/stream_peer.h"
@ -66,5 +65,3 @@ public:
};
VARIANT_ENUM_CAST(StreamPeerTLS::Status);
#endif // STREAM_PEER_TLS_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TCP_SERVER_H
#define TCP_SERVER_H
#pragma once
#include "core/io/ip.h"
#include "core/io/net_socket.h"
@ -59,5 +58,3 @@ public:
TCPServer();
~TCPServer();
};
#endif // TCP_SERVER_H

View file

@ -76,14 +76,17 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
bool is_plural = false;
for (uint32_t j = 0; j < str_len + 1; j++) {
if (data[j] == 0x04) {
msg_context.parse_utf8((const char *)data.ptr(), j);
msg_context.clear();
msg_context.append_utf8((const char *)data.ptr(), j);
str_start = j + 1;
}
if (data[j] == 0x00) {
if (is_plural) {
msg_id_plural.parse_utf8((const char *)(data.ptr() + str_start), j - str_start);
msg_id_plural.clear();
msg_id_plural.append_utf8((const char *)(data.ptr() + str_start), j - str_start);
} else {
msg_id.parse_utf8((const char *)(data.ptr() + str_start), j - str_start);
msg_id.clear();
msg_id.append_utf8((const char *)(data.ptr() + str_start), j - str_start);
is_plural = true;
}
str_start = j + 1;
@ -189,7 +192,7 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
}
}
msg_context = "";
l = l.substr(7, l.length()).strip_edges();
l = l.substr(7).strip_edges();
status = STATUS_READING_CONTEXT;
entered_context = true;
}
@ -202,7 +205,7 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
}
// We don't record the message in "msgid_plural" itself as tr_n(), TTRN(), RTRN() interfaces provide the plural string already.
// We just have to reset variables related to plurals for "msgstr[]" later on.
l = l.substr(12, l.length()).strip_edges();
l = l.substr(12).strip_edges();
plural_index = -1;
msgs_plural.clear();
msgs_plural.resize(plural_forms);
@ -230,7 +233,7 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
}
}
l = l.substr(5, l.length()).strip_edges();
l = l.substr(5).strip_edges();
status = STATUS_READING_ID;
// If we did not encounter msgctxt, we reset context to empty to reset it.
if (!entered_context) {
@ -246,10 +249,10 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
if (l.begins_with("msgstr[")) {
ERR_FAIL_COND_V_MSG(status != STATUS_READING_PLURAL, Ref<Resource>(), vformat("Unexpected 'msgstr[]', was expecting 'msgid_plural' before 'msgstr[]' while parsing: %s:%d.", path, line));
plural_index++; // Increment to add to the next slot in vector msgs_plural.
l = l.substr(9, l.length()).strip_edges();
l = l.substr(9).strip_edges();
} else if (l.begins_with("msgstr")) {
ERR_FAIL_COND_V_MSG(status != STATUS_READING_ID, Ref<Resource>(), vformat("Unexpected 'msgstr', was expecting 'msgid' before 'msgstr' while parsing: %s:%d.", path, line));
l = l.substr(6, l.length()).strip_edges();
l = l.substr(6).strip_edges();
status = STATUS_READING_STRING;
}
@ -263,7 +266,7 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
ERR_FAIL_COND_V_MSG(!l.begins_with("\"") || status == STATUS_NONE, Ref<Resource>(), vformat("Invalid line '%s' while parsing: %s:%d.", l, path, line));
l = l.substr(1, l.length());
l = l.substr(1);
// Find final quote, ignoring escaped ones (\").
// The escape_next logic is necessary to properly parse things like \\"
// where the backslash is the one being escaped, not the quote.
@ -329,7 +332,7 @@ Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_
continue;
}
String prop = c.substr(0, p).strip_edges();
String value = c.substr(p + 1, c.length()).strip_edges();
String value = c.substr(p + 1).strip_edges();
if (prop == "X-Language" || prop == "Language") {
translation->set_locale(value);

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TRANSLATION_LOADER_PO_H
#define TRANSLATION_LOADER_PO_H
#pragma once
#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
@ -49,5 +48,3 @@ public:
TranslationLoaderPO() {}
};
#endif // TRANSLATION_LOADER_PO_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef UDP_SERVER_H
#define UDP_SERVER_H
#pragma once
#include "core/io/net_socket.h"
#include "core/io/packet_peer_udp.h"
@ -76,5 +75,3 @@ public:
UDPServer();
~UDPServer();
};
#endif // UDP_SERVER_H

View file

@ -95,7 +95,8 @@ void XMLParser::_ignore_definition() {
while (*P && *P != '>') {
next_char();
}
node_name.parse_utf8(F, P - F);
node_name.clear();
node_name.append_utf8(F, P - F);
if (*P) {
next_char();

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef XML_PARSER_H
#define XML_PARSER_H
#pragma once
#include "core/object/ref_counted.h"
#include "core/string/ustring.h"
@ -126,5 +125,3 @@ public:
};
VARIANT_ENUM_CAST(XMLParser::NodeType);
#endif // XML_PARSER_H

View file

@ -76,8 +76,7 @@ void *zipio_open(voidpf opaque, const char *p_fname, int mode) {
Ref<FileAccess> *fa = reinterpret_cast<Ref<FileAccess> *>(opaque);
ERR_FAIL_NULL_V(fa, nullptr);
String fname;
fname.parse_utf8(p_fname);
String fname = String::utf8(p_fname);
int file_access_mode = 0;
if (mode & ZLIB_FILEFUNC_MODE_READ) {

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef ZIP_IO_H
#define ZIP_IO_H
#pragma once
#include "core/io/file_access.h"
@ -61,5 +60,3 @@ voidpf zipio_alloc(voidpf opaque, uInt items, uInt size);
void zipio_free(voidpf opaque, voidpf address);
zlib_filefunc_def zipio_create_io(Ref<FileAccess> *p_data);
#endif // ZIP_IO_H