summaryrefslogtreecommitdiff
path: root/core/io
diff options
context:
space:
mode:
Diffstat (limited to 'core/io')
-rw-r--r--core/io/config_file.cpp27
-rw-r--r--core/io/config_file.h4
-rw-r--r--core/io/file_access_network.h11
-rw-r--r--core/io/file_access_pack.cpp68
-rw-r--r--core/io/file_access_pack.h2
-rw-r--r--core/io/file_access_zip.h2
-rw-r--r--core/io/http_client_tcp.cpp3
-rw-r--r--core/io/image.cpp4
-rw-r--r--core/io/image_loader.cpp10
-rw-r--r--core/io/image_loader.h2
-rw-r--r--core/io/ip.cpp3
-rw-r--r--core/io/logger.h12
-rw-r--r--core/io/marshalls.cpp20
-rw-r--r--core/io/missing_resource.cpp90
-rw-r--r--core/io/missing_resource.h63
-rw-r--r--core/io/packet_peer_udp.cpp4
-rw-r--r--core/io/packet_peer_udp.h2
-rw-r--r--core/io/resource.cpp31
-rw-r--r--core/io/resource.h2
-rw-r--r--core/io/resource_format_binary.cpp219
-rw-r--r--core/io/resource_format_binary.h30
-rw-r--r--core/io/resource_importer.cpp6
-rw-r--r--core/io/resource_importer.h2
-rw-r--r--core/io/resource_loader.cpp43
-rw-r--r--core/io/resource_loader.h16
-rw-r--r--core/io/resource_saver.cpp12
-rw-r--r--core/io/resource_saver.h16
-rw-r--r--core/io/resource_uid.cpp22
-rw-r--r--core/io/resource_uid.h4
-rw-r--r--core/io/stream_peer_tcp.cpp87
-rw-r--r--core/io/stream_peer_tcp.h11
-rw-r--r--core/io/translation_loader_po.cpp36
-rw-r--r--core/io/translation_loader_po.h4
-rw-r--r--core/io/zip_io.cpp58
-rw-r--r--core/io/zip_io.h6
35 files changed, 585 insertions, 347 deletions
diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp
index bc24cac955..dd0191f43f 100644
--- a/core/io/config_file.cpp
+++ b/core/io/config_file.cpp
@@ -73,7 +73,7 @@ void ConfigFile::set_value(const String &p_section, const String &p_key, const V
} else {
if (!values.has(p_section)) {
- values[p_section] = OrderedHashMap<String, Variant>();
+ values[p_section] = HashMap<String, Variant>();
}
values[p_section][p_key] = p_value;
@@ -102,16 +102,16 @@ bool ConfigFile::has_section_key(const String &p_section, const String &p_key) c
}
void ConfigFile::get_sections(List<String> *r_sections) const {
- for (OrderedHashMap<String, OrderedHashMap<String, Variant>>::ConstElement E = values.front(); E; E = E.next()) {
- r_sections->push_back(E.key());
+ for (const KeyValue<String, HashMap<String, Variant>> &E : values) {
+ r_sections->push_back(E.key);
}
}
void ConfigFile::get_section_keys(const String &p_section, List<String> *r_keys) const {
ERR_FAIL_COND_MSG(!values.has(p_section), vformat("Cannot get keys from nonexistent section \"%s\".", p_section));
- for (OrderedHashMap<String, Variant>::ConstElement E = values[p_section].front(); E; E = E.next()) {
- r_keys->push_back(E.key());
+ for (const KeyValue<String, Variant> &E : values[p_section]) {
+ r_keys->push_back(E.key);
}
}
@@ -174,18 +174,21 @@ Error ConfigFile::save_encrypted_pass(const String &p_path, const String &p_pass
}
Error ConfigFile::_internal_save(Ref<FileAccess> file) {
- for (OrderedHashMap<String, OrderedHashMap<String, Variant>>::Element E = values.front(); E; E = E.next()) {
- if (E != values.front()) {
+ bool first = true;
+ for (const KeyValue<String, HashMap<String, Variant>> &E : values) {
+ if (first) {
+ first = false;
+ } else {
file->store_string("\n");
}
- if (!E.key().is_empty()) {
- file->store_string("[" + E.key() + "]\n\n");
+ if (!E.key.is_empty()) {
+ file->store_string("[" + E.key + "]\n\n");
}
- for (OrderedHashMap<String, Variant>::Element F = E.get().front(); F; F = F.next()) {
+ for (const KeyValue<String, Variant> &F : E.value) {
String vstr;
- VariantWriter::write_to_string(F.get(), vstr);
- file->store_string(F.key().property_name_encode() + "=" + vstr + "\n");
+ VariantWriter::write_to_string(F.value, vstr);
+ file->store_string(F.key.property_name_encode() + "=" + vstr + "\n");
}
}
diff --git a/core/io/config_file.h b/core/io/config_file.h
index 7a52b0e16a..3b07ec52f5 100644
--- a/core/io/config_file.h
+++ b/core/io/config_file.h
@@ -33,13 +33,13 @@
#include "core/io/file_access.h"
#include "core/object/ref_counted.h"
-#include "core/templates/ordered_hash_map.h"
+#include "core/templates/hash_map.h"
#include "core/variant/variant_parser.h"
class ConfigFile : public RefCounted {
GDCLASS(ConfigFile, RefCounted);
- OrderedHashMap<String, OrderedHashMap<String, Variant>> values;
+ HashMap<String, HashMap<String, Variant>> values;
PackedStringArray _get_sections() const;
PackedStringArray _get_section_keys(const String &p_section) const;
diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h
index 6afbf6adf5..214d391c95 100644
--- a/core/io/file_access_network.h
+++ b/core/io/file_access_network.h
@@ -86,15 +86,15 @@ class FileAccessNetwork : public FileAccess {
Semaphore page_sem;
Mutex buffer_mutex;
bool opened = false;
- uint64_t total_size;
+ uint64_t total_size = 0;
mutable uint64_t pos = 0;
- int32_t id;
+ int32_t id = -1;
mutable bool eof_flag = false;
mutable int32_t last_page = -1;
mutable uint8_t *last_page_buff = nullptr;
- int32_t page_size;
- int32_t read_ahead;
+ int32_t page_size = 0;
+ int32_t read_ahead = 0;
mutable int waiting_on_page = -1;
@@ -108,7 +108,8 @@ class FileAccessNetwork : public FileAccess {
mutable Error response;
- uint64_t exists_modtime;
+ uint64_t exists_modtime = 0;
+
friend class FileAccessNetworkClient;
void _queue_page(int32_t p_page) const;
void _respond(uint64_t p_len, Error p_status);
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index c6e14ffee7..ba120de68b 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -32,6 +32,7 @@
#include "core/io/file_access_encrypted.h"
#include "core/object/script_language.h"
+#include "core/os/os.h"
#include "core/version.h"
#include <stdio.h>
@@ -131,32 +132,69 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
return false;
}
- f->seek(p_offset);
+ bool pck_header_found = false;
+ // Search for the header at the start offset - standalone PCK file.
+ f->seek(p_offset);
uint32_t magic = f->get_32();
+ if (magic == PACK_HEADER_MAGIC) {
+ pck_header_found = true;
+ }
- if (magic != PACK_HEADER_MAGIC) {
- // loading with offset feature not supported for self contained exe files
- ERR_FAIL_COND_V_MSG(p_offset != 0, false, "Loading self-contained executable with offset not supported.");
+ // Search for the header in the executable "pck" section - self contained executable.
+ if (!pck_header_found) {
+ // Loading with offset feature not supported for self contained exe files.
+ if (p_offset != 0) {
+ ERR_FAIL_V_MSG(false, "Loading self-contained executable with offset not supported.");
+ }
- //maybe at the end.... self contained exe
- f->seek_end();
- f->seek(f->get_position() - 4);
- magic = f->get_32();
- if (magic != PACK_HEADER_MAGIC) {
- return false;
+ int64_t pck_off = OS::get_singleton()->get_embedded_pck_offset();
+ if (pck_off != 0) {
+ // Search for the header, in case PCK start and section have different alignment.
+ for (int i = 0; i < 8; i++) {
+ f->seek(pck_off);
+ magic = f->get_32();
+ if (magic == PACK_HEADER_MAGIC) {
+#ifdef DEBUG_ENABLED
+ print_verbose("PCK header found in executable pck section, loading from offset 0x" + String::num_int64(pck_off - 4, 16));
+#endif
+ pck_header_found = true;
+ break;
+ }
+ pck_off++;
+ }
}
- f->seek(f->get_position() - 12);
+ }
- uint64_t ds = f->get_64();
- f->seek(f->get_position() - ds - 8);
+ // Search for the header at the end of file - self contained executable.
+ if (!pck_header_found) {
+ // Loading with offset feature not supported for self contained exe files.
+ if (p_offset != 0) {
+ ERR_FAIL_V_MSG(false, "Loading self-contained executable with offset not supported.");
+ }
+ f->seek_end();
+ f->seek(f->get_position() - 4);
magic = f->get_32();
- if (magic != PACK_HEADER_MAGIC) {
- return false;
+
+ if (magic == PACK_HEADER_MAGIC) {
+ f->seek(f->get_position() - 12);
+ uint64_t ds = f->get_64();
+ f->seek(f->get_position() - ds - 8);
+ magic = f->get_32();
+ if (magic == PACK_HEADER_MAGIC) {
+#ifdef DEBUG_ENABLED
+ print_verbose("PCK header found at the end of executable, loading from offset 0x" + String::num_int64(f->get_position() - 4, 16));
+#endif
+ pck_header_found = true;
+ }
}
}
+ if (!pck_header_found) {
+ return false;
+ }
+
uint32_t version = f->get_32();
uint32_t ver_major = f->get_32();
uint32_t ver_minor = f->get_32();
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index 44df2029bd..17e87c835a 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -93,7 +93,7 @@ private:
PathMD5() {}
- PathMD5(const Vector<uint8_t> &p_buf) {
+ explicit PathMD5(const Vector<uint8_t> &p_buf) {
a = *((uint64_t *)&p_buf[0]);
b = *((uint64_t *)&p_buf[8]);
}
diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h
index 2504aeedc4..ae58d99a66 100644
--- a/core/io/file_access_zip.h
+++ b/core/io/file_access_zip.h
@@ -80,7 +80,7 @@ class FileAccessZip : public FileAccess {
unzFile zfile = nullptr;
unz_file_info64 file_info;
- mutable bool at_eof;
+ mutable bool at_eof = false;
void _close();
diff --git a/core/io/http_client_tcp.cpp b/core/io/http_client_tcp.cpp
index f920799677..d983d86b99 100644
--- a/core/io/http_client_tcp.cpp
+++ b/core/io/http_client_tcp.cpp
@@ -264,6 +264,9 @@ void HTTPClientTCP::close() {
}
Error HTTPClientTCP::poll() {
+ if (tcp_connection.is_valid()) {
+ tcp_connection->poll();
+ }
switch (status) {
case STATUS_RESOLVING: {
ERR_FAIL_COND_V(resolving == IP::RESOLVER_INVALID_ID, ERR_BUG);
diff --git a/core/io/image.cpp b/core/io/image.cpp
index 661a9f7177..671a000e2c 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -436,7 +436,7 @@ static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p
const uint8_t *rofs = &p_src[((y * p_width) + x) * (read_bytes + (read_alpha ? 1 : 0))];
uint8_t *wofs = &p_dst[((y * p_width) + x) * (write_bytes + (write_alpha ? 1 : 0))];
- uint8_t rgba[4];
+ uint8_t rgba[4] = { 0, 0, 0, 255 };
if (read_gray) {
rgba[0] = rofs[0];
@@ -454,7 +454,7 @@ static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p
if (write_gray) {
//TODO: not correct grayscale, should use fixed point version of actual weights
- wofs[0] = uint8_t((uint16_t(rofs[0]) + uint16_t(rofs[1]) + uint16_t(rofs[2])) / 3);
+ wofs[0] = uint8_t((uint16_t(rgba[0]) + uint16_t(rgba[1]) + uint16_t(rgba[2])) / 3);
} else {
for (uint32_t i = 0; i < write_bytes; i++) {
wofs[i] = rgba[i];
diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp
index 2ccc95f0de..9cf7c9caba 100644
--- a/core/io/image_loader.cpp
+++ b/core/io/image_loader.cpp
@@ -111,13 +111,13 @@ void ImageLoader::cleanup() {
/////////////////
-RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
+Ref<Resource> ResourceFormatLoaderImage::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
if (f.is_null()) {
if (r_error) {
*r_error = ERR_CANT_OPEN;
}
- return RES();
+ return Ref<Resource>();
}
uint8_t header[4] = { 0, 0, 0, 0 };
@@ -128,7 +128,7 @@ RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_origin
if (r_error) {
*r_error = ERR_FILE_UNRECOGNIZED;
}
- ERR_FAIL_V(RES());
+ ERR_FAIL_V(Ref<Resource>());
}
String extension = f->get_pascal_string();
@@ -146,7 +146,7 @@ RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_origin
if (r_error) {
*r_error = ERR_FILE_UNRECOGNIZED;
}
- ERR_FAIL_V(RES());
+ ERR_FAIL_V(Ref<Resource>());
}
Ref<Image> image;
@@ -158,7 +158,7 @@ RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_origin
if (r_error) {
*r_error = err;
}
- return RES();
+ return Ref<Resource>();
}
if (r_error) {
diff --git a/core/io/image_loader.h b/core/io/image_loader.h
index 9409617268..c91d382c25 100644
--- a/core/io/image_loader.h
+++ b/core/io/image_loader.h
@@ -72,7 +72,7 @@ public:
class ResourceFormatLoaderImage : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
+ virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/core/io/ip.cpp b/core/io/ip.cpp
index 52674150bb..5156a5cb99 100644
--- a/core/io/ip.cpp
+++ b/core/io/ip.cpp
@@ -74,8 +74,7 @@ struct _IP_ResolverPrivate {
Semaphore sem;
Thread thread;
- //Semaphore* semaphore;
- bool thread_abort;
+ bool thread_abort = false;
void resolve_queues() {
for (int i = 0; i < IP::RESOLVER_MAX_QUERIES; i++) {
diff --git a/core/io/logger.h b/core/io/logger.h
index e3ac00f11c..8ac086e376 100644
--- a/core/io/logger.h
+++ b/core/io/logger.h
@@ -67,7 +67,7 @@ public:
*/
class StdLogger : public Logger {
public:
- virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0;
+ virtual void logv(const char *p_format, va_list p_list, bool p_err) override _PRINTF_FORMAT_ATTRIBUTE_2_0;
virtual ~StdLogger() {}
};
@@ -87,19 +87,19 @@ class RotatedFileLogger : public Logger {
void rotate_file();
public:
- RotatedFileLogger(const String &p_base_path, int p_max_files = 10);
+ explicit RotatedFileLogger(const String &p_base_path, int p_max_files = 10);
- virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0;
+ virtual void logv(const char *p_format, va_list p_list, bool p_err) override _PRINTF_FORMAT_ATTRIBUTE_2_0;
};
class CompositeLogger : public Logger {
Vector<Logger *> loggers;
public:
- CompositeLogger(Vector<Logger *> p_loggers);
+ explicit CompositeLogger(Vector<Logger *> p_loggers);
- virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0;
- virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type = ERR_ERROR);
+ virtual void logv(const char *p_format, va_list p_list, bool p_err) override _PRINTF_FORMAT_ATTRIBUTE_2_0;
+ virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type = ERR_ERROR) override;
void add_logger(Logger *p_logger);
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index d0bc05566e..bb9606c94b 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -291,7 +291,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 6, ERR_INVALID_DATA);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
- val.elements[i][j] = decode_double(&buf[(i * 2 + j) * sizeof(double)]);
+ val.columns[i][j] = decode_double(&buf[(i * 2 + j) * sizeof(double)]);
}
}
@@ -302,7 +302,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
ERR_FAIL_COND_V((size_t)len < sizeof(float) * 6, ERR_INVALID_DATA);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
- val.elements[i][j] = decode_float(&buf[(i * 2 + j) * sizeof(float)]);
+ val.columns[i][j] = decode_float(&buf[(i * 2 + j) * sizeof(float)]);
}
}
@@ -401,7 +401,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 9, ERR_INVALID_DATA);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
- val.elements[i][j] = decode_double(&buf[(i * 3 + j) * sizeof(double)]);
+ val.rows[i][j] = decode_double(&buf[(i * 3 + j) * sizeof(double)]);
}
}
@@ -412,7 +412,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
ERR_FAIL_COND_V((size_t)len < sizeof(float) * 9, ERR_INVALID_DATA);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
- val.elements[i][j] = decode_float(&buf[(i * 3 + j) * sizeof(float)]);
+ val.rows[i][j] = decode_float(&buf[(i * 3 + j) * sizeof(float)]);
}
}
@@ -429,7 +429,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
ERR_FAIL_COND_V((size_t)len < sizeof(double) * 12, ERR_INVALID_DATA);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
- val.basis.elements[i][j] = decode_double(&buf[(i * 3 + j) * sizeof(double)]);
+ val.basis.rows[i][j] = decode_double(&buf[(i * 3 + j) * sizeof(double)]);
}
}
val.origin[0] = decode_double(&buf[sizeof(double) * 9]);
@@ -443,7 +443,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
ERR_FAIL_COND_V((size_t)len < sizeof(float) * 12, ERR_INVALID_DATA);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
- val.basis.elements[i][j] = decode_float(&buf[(i * 3 + j) * sizeof(float)]);
+ val.basis.rows[i][j] = decode_float(&buf[(i * 3 + j) * sizeof(float)]);
}
}
val.origin[0] = decode_float(&buf[sizeof(float) * 9]);
@@ -601,7 +601,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
}
if (Object::cast_to<RefCounted>(obj)) {
- REF ref = REF(Object::cast_to<RefCounted>(obj));
+ Ref<RefCounted> ref = Ref<RefCounted>(Object::cast_to<RefCounted>(obj));
r_variant = ref;
} else {
r_variant = obj;
@@ -1261,7 +1261,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
Transform2D val = p_variant;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
- memcpy(&buf[(i * 2 + j) * sizeof(real_t)], &val.elements[i][j], sizeof(real_t));
+ memcpy(&buf[(i * 2 + j) * sizeof(real_t)], &val.columns[i][j], sizeof(real_t));
}
}
}
@@ -1312,7 +1312,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
Basis val = p_variant;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
- memcpy(&buf[(i * 3 + j) * sizeof(real_t)], &val.elements[i][j], sizeof(real_t));
+ memcpy(&buf[(i * 3 + j) * sizeof(real_t)], &val.rows[i][j], sizeof(real_t));
}
}
}
@@ -1325,7 +1325,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
Transform3D val = p_variant;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
- memcpy(&buf[(i * 3 + j) * sizeof(real_t)], &val.basis.elements[i][j], sizeof(real_t));
+ memcpy(&buf[(i * 3 + j) * sizeof(real_t)], &val.basis.rows[i][j], sizeof(real_t));
}
}
diff --git a/core/io/missing_resource.cpp b/core/io/missing_resource.cpp
new file mode 100644
index 0000000000..29814cdeb3
--- /dev/null
+++ b/core/io/missing_resource.cpp
@@ -0,0 +1,90 @@
+/*************************************************************************/
+/* missing_resource.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "missing_resource.h"
+
+bool MissingResource::_set(const StringName &p_name, const Variant &p_value) {
+ if (is_recording_properties()) {
+ properties.insert(p_name, p_value);
+ return true; //always valid to set (add)
+ } else {
+ if (!properties.has(p_name)) {
+ return false;
+ }
+
+ properties[p_name] = p_value;
+ return true;
+ }
+}
+
+bool MissingResource::_get(const StringName &p_name, Variant &r_ret) const {
+ if (!properties.has(p_name)) {
+ return false;
+ }
+ r_ret = properties[p_name];
+ return true;
+}
+
+void MissingResource::_get_property_list(List<PropertyInfo> *p_list) const {
+ for (const KeyValue<StringName, Variant> &E : properties) {
+ p_list->push_back(PropertyInfo(E.value.get_type(), E.key));
+ }
+}
+
+void MissingResource::set_original_class(const String &p_class) {
+ original_class = p_class;
+}
+
+String MissingResource::get_original_class() const {
+ return original_class;
+}
+
+void MissingResource::set_recording_properties(bool p_enable) {
+ recording_properties = p_enable;
+}
+
+bool MissingResource::is_recording_properties() const {
+ return recording_properties;
+}
+
+void MissingResource::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_original_class", "name"), &MissingResource::set_original_class);
+ ClassDB::bind_method(D_METHOD("get_original_class"), &MissingResource::get_original_class);
+
+ ClassDB::bind_method(D_METHOD("set_recording_properties", "enable"), &MissingResource::set_recording_properties);
+ ClassDB::bind_method(D_METHOD("is_recording_properties"), &MissingResource::is_recording_properties);
+
+ // Expose, but not save.
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "original_class", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_original_class", "get_original_class");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "recording_properties", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_recording_properties", "is_recording_properties");
+}
+
+MissingResource::MissingResource() {
+}
diff --git a/core/io/missing_resource.h b/core/io/missing_resource.h
new file mode 100644
index 0000000000..6536a4119b
--- /dev/null
+++ b/core/io/missing_resource.h
@@ -0,0 +1,63 @@
+/*************************************************************************/
+/* missing_resource.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef MISSING_RESOURCE_H
+#define MISSING_RESOURCE_H
+
+#include "core/io/resource.h"
+
+#define META_PROPERTY_MISSING_RESOURCES "metadata/_missing_resources"
+#define META_MISSING_RESOURCES "_missing_resources"
+
+class MissingResource : public Resource {
+ GDCLASS(MissingResource, Resource)
+ HashMap<StringName, Variant> properties;
+
+ String original_class;
+ bool recording_properties = false;
+
+protected:
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+ void _get_property_list(List<PropertyInfo> *p_list) const;
+
+ static void _bind_methods();
+
+public:
+ void set_original_class(const String &p_class);
+ String get_original_class() const;
+
+ void set_recording_properties(bool p_enable);
+ bool is_recording_properties() const;
+
+ MissingResource();
+};
+
+#endif // MISSING_RESOURCE_H
diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp
index 503eb17cae..84d1f3ebd4 100644
--- a/core/io/packet_peer_udp.cpp
+++ b/core/io/packet_peer_udp.cpp
@@ -242,7 +242,7 @@ Error PacketPeerUDP::connect_to_host(const IPAddress &p_host, int p_port) {
return OK;
}
-bool PacketPeerUDP::is_connected_to_host() const {
+bool PacketPeerUDP::is_socket_connected() const {
return connected;
}
@@ -348,7 +348,7 @@ void PacketPeerUDP::_bind_methods() {
ClassDB::bind_method(D_METHOD("wait"), &PacketPeerUDP::wait);
ClassDB::bind_method(D_METHOD("is_bound"), &PacketPeerUDP::is_bound);
ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port"), &PacketPeerUDP::connect_to_host);
- ClassDB::bind_method(D_METHOD("is_connected_to_host"), &PacketPeerUDP::is_connected_to_host);
+ ClassDB::bind_method(D_METHOD("is_socket_connected"), &PacketPeerUDP::is_socket_connected);
ClassDB::bind_method(D_METHOD("get_packet_ip"), &PacketPeerUDP::_get_packet_ip);
ClassDB::bind_method(D_METHOD("get_packet_port"), &PacketPeerUDP::get_packet_port);
ClassDB::bind_method(D_METHOD("get_local_port"), &PacketPeerUDP::get_local_port);
diff --git a/core/io/packet_peer_udp.h b/core/io/packet_peer_udp.h
index 444a6dd5ba..a174cf5347 100644
--- a/core/io/packet_peer_udp.h
+++ b/core/io/packet_peer_udp.h
@@ -79,7 +79,7 @@ public:
void disconnect_shared_socket(); // Used by UDPServer
Error store_packet(IPAddress p_ip, uint32_t p_port, uint8_t *p_buf, int p_buf_size); // Used internally and by UDPServer
Error connect_to_host(const IPAddress &p_host, int p_port);
- bool is_connected_to_host() const;
+ bool is_socket_connected() const;
IPAddress get_packet_address() const;
int get_packet_port() const;
diff --git a/core/io/resource.cpp b/core/io/resource.cpp
index bf91438810..e81382b72e 100644
--- a/core/io/resource.cpp
+++ b/core/io/resource.cpp
@@ -208,13 +208,13 @@ Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, Map<Ref<Res
}
Variant p = get(E.name);
if (p.get_type() == Variant::OBJECT) {
- RES sr = p;
+ Ref<Resource> sr = p;
if (sr.is_valid()) {
if (sr->is_local_to_scene()) {
if (remap_cache.has(sr)) {
p = remap_cache[sr];
} else {
- RES dupe = sr->duplicate_for_local_scene(p_for_scene, remap_cache);
+ Ref<Resource> dupe = sr->duplicate_for_local_scene(p_for_scene, remap_cache);
p = dupe;
remap_cache[sr] = dupe;
}
@@ -240,7 +240,7 @@ void Resource::configure_for_local_scene(Node *p_for_scene, Map<Ref<Resource>, R
}
Variant p = get(E.name);
if (p.get_type() == Variant::OBJECT) {
- RES sr = p;
+ Ref<Resource> sr = p;
if (sr.is_valid()) {
if (sr->is_local_to_scene()) {
if (!remap_cache.has(sr)) {
@@ -257,7 +257,7 @@ Ref<Resource> Resource::duplicate(bool p_subresources) const {
List<PropertyInfo> plist;
get_property_list(&plist);
- Ref<Resource> r = (Resource *)ClassDB::instantiate(get_class());
+ Ref<Resource> r = static_cast<Resource *>(ClassDB::instantiate(get_class()));
ERR_FAIL_COND_V(r.is_null(), Ref<Resource>());
for (const PropertyInfo &E : plist) {
@@ -269,7 +269,7 @@ Ref<Resource> Resource::duplicate(bool p_subresources) const {
if ((p.get_type() == Variant::DICTIONARY || p.get_type() == Variant::ARRAY)) {
r->set(E.name, p.duplicate(p_subresources));
} else if (p.get_type() == Variant::OBJECT && (p_subresources || (E.usage & PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE))) {
- RES sr = p;
+ Ref<Resource> sr = p;
if (sr.is_valid()) {
r->set(E.name, sr->duplicate(p_subresources));
}
@@ -321,7 +321,7 @@ void Resource::notify_change_to_owners() {
Object *obj = ObjectDB::get_instance(E->get());
ERR_CONTINUE_MSG(!obj, "Object was deleted, while still owning a resource."); //wtf
//TODO store string
- obj->call("resource_changed", RES(this));
+ obj->call("resource_changed", Ref<Resource>(this));
}
}
@@ -335,7 +335,7 @@ uint32_t Resource::hash_edited_version() const {
for (const PropertyInfo &E : plist) {
if (E.usage & PROPERTY_USAGE_STORAGE && E.type == Variant::OBJECT && E.hint == PROPERTY_HINT_RESOURCE_TYPE) {
- RES res = get(E.name);
+ Ref<Resource> res = get(E.name);
if (res.is_valid()) {
hash = hash_djb2_one_32(res->hash_edited_version(), hash);
}
@@ -478,10 +478,8 @@ void ResourceCache::clear() {
if (resources.size()) {
ERR_PRINT("Resources still in use at exit (run with --verbose for details).");
if (OS::get_singleton()->is_stdout_verbose()) {
- const String *K = nullptr;
- while ((K = resources.next(K))) {
- Resource *r = resources[*K];
- print_line(vformat("Resource still in use: %s (%s)", *K, r->get_class()));
+ for (const KeyValue<String, Resource *> &E : resources) {
+ print_line(vformat("Resource still in use: %s (%s)", E.key, E.value->get_class()));
}
}
}
@@ -516,10 +514,8 @@ Resource *ResourceCache::get(const String &p_path) {
void ResourceCache::get_cached_resources(List<Ref<Resource>> *p_resources) {
lock.read_lock();
- const String *K = nullptr;
- while ((K = resources.next(K))) {
- Resource *r = resources[*K];
- p_resources->push_back(Ref<Resource>(r));
+ for (KeyValue<String, Resource *> &E : resources) {
+ p_resources->push_back(Ref<Resource>(E.value));
}
lock.read_unlock();
}
@@ -544,9 +540,8 @@ void ResourceCache::dump(const char *p_file, bool p_short) {
ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file at path '" + String::utf8(p_file) + "'.");
}
- const String *K = nullptr;
- while ((K = resources.next(K))) {
- Resource *r = resources[*K];
+ for (KeyValue<String, Resource *> &E : resources) {
+ Resource *r = E.value;
if (!type_count.has(r->get_class())) {
type_count[r->get_class()] = 0;
diff --git a/core/io/resource.h b/core/io/resource.h
index 8068000f32..43ae104da5 100644
--- a/core/io/resource.h
+++ b/core/io/resource.h
@@ -150,8 +150,6 @@ public:
~Resource();
};
-typedef Ref<Resource> RES;
-
class ResourceCache {
friend class Resource;
friend class ResourceLoader; //need the lock
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index b6988109c5..3c854bbbe5 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -35,6 +35,7 @@
#include "core/io/file_access_compressed.h"
#include "core/io/image.h"
#include "core/io/marshalls.h"
+#include "core/io/missing_resource.h"
#include "core/version.h"
//#define print_bl(m_what) print_line(m_what)
@@ -266,40 +267,40 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
} break;
case VARIANT_TRANSFORM2D: {
Transform2D v;
- v.elements[0].x = f->get_real();
- v.elements[0].y = f->get_real();
- v.elements[1].x = f->get_real();
- v.elements[1].y = f->get_real();
- v.elements[2].x = f->get_real();
- v.elements[2].y = f->get_real();
+ v.columns[0].x = f->get_real();
+ v.columns[0].y = f->get_real();
+ v.columns[1].x = f->get_real();
+ v.columns[1].y = f->get_real();
+ v.columns[2].x = f->get_real();
+ v.columns[2].y = f->get_real();
r_v = v;
} break;
case VARIANT_BASIS: {
Basis v;
- v.elements[0].x = f->get_real();
- v.elements[0].y = f->get_real();
- v.elements[0].z = f->get_real();
- v.elements[1].x = f->get_real();
- v.elements[1].y = f->get_real();
- v.elements[1].z = f->get_real();
- v.elements[2].x = f->get_real();
- v.elements[2].y = f->get_real();
- v.elements[2].z = f->get_real();
+ v.rows[0].x = f->get_real();
+ v.rows[0].y = f->get_real();
+ v.rows[0].z = f->get_real();
+ v.rows[1].x = f->get_real();
+ v.rows[1].y = f->get_real();
+ v.rows[1].z = f->get_real();
+ v.rows[2].x = f->get_real();
+ v.rows[2].y = f->get_real();
+ v.rows[2].z = f->get_real();
r_v = v;
} break;
case VARIANT_TRANSFORM3D: {
Transform3D v;
- v.basis.elements[0].x = f->get_real();
- v.basis.elements[0].y = f->get_real();
- v.basis.elements[0].z = f->get_real();
- v.basis.elements[1].x = f->get_real();
- v.basis.elements[1].y = f->get_real();
- v.basis.elements[1].z = f->get_real();
- v.basis.elements[2].x = f->get_real();
- v.basis.elements[2].y = f->get_real();
- v.basis.elements[2].z = f->get_real();
+ v.basis.rows[0].x = f->get_real();
+ v.basis.rows[0].y = f->get_real();
+ v.basis.rows[0].z = f->get_real();
+ v.basis.rows[1].x = f->get_real();
+ v.basis.rows[1].y = f->get_real();
+ v.basis.rows[1].z = f->get_real();
+ v.basis.rows[2].x = f->get_real();
+ v.basis.rows[2].y = f->get_real();
+ v.basis.rows[2].z = f->get_real();
v.origin.x = f->get_real();
v.origin.y = f->get_real();
v.origin.z = f->get_real();
@@ -388,7 +389,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
path = remaps[path];
}
- RES res = ResourceLoader::load(path, exttype);
+ Ref<Resource> res = ResourceLoader::load(path, exttype);
if (res.is_null()) {
WARN_PRINT(String("Couldn't load resource: " + path).utf8().get_data());
@@ -634,8 +635,6 @@ Error ResourceLoaderBinary::load() {
return error;
}
- int stage = 0;
-
for (int i = 0; i < external_resources.size(); i++) {
String path = external_resources[i].path;
@@ -673,8 +672,6 @@ Error ResourceLoaderBinary::load() {
}
}
}
-
- stage++;
}
for (int i = 0; i < internal_resources.size(); i++) {
@@ -696,10 +693,9 @@ Error ResourceLoaderBinary::load() {
}
if (cache_mode == ResourceFormatLoader::CACHE_MODE_REUSE && ResourceCache::has(path)) {
- RES cached = ResourceCache::get(path);
+ Ref<Resource> cached = ResourceCache::get(path);
if (cached.is_valid()) {
//already loaded, don't do anything
- stage++;
error = OK;
internal_index_cache[path] = cached;
continue;
@@ -717,7 +713,7 @@ Error ResourceLoaderBinary::load() {
String t = get_unicode_string();
- RES res;
+ Ref<Resource> res;
if (cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE && ResourceCache::has(path)) {
//use the existing one
@@ -728,13 +724,23 @@ Error ResourceLoaderBinary::load() {
}
}
+ MissingResource *missing_resource = nullptr;
+
if (res.is_null()) {
//did not replace
Object *obj = ClassDB::instantiate(t);
if (!obj) {
- error = ERR_FILE_CORRUPT;
- ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, local_path + ":Resource of unrecognized type in file: " + t + ".");
+ if (ResourceLoader::is_creating_missing_resources_if_class_unavailable_enabled()) {
+ //create a missing resource
+ missing_resource = memnew(MissingResource);
+ missing_resource->set_original_class(t);
+ missing_resource->set_recording_properties(true);
+ obj = missing_resource;
+ } else {
+ error = ERR_FILE_CORRUPT;
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, local_path + ":Resource of unrecognized type in file: " + t + ".");
+ }
}
Resource *r = Object::cast_to<Resource>(obj);
@@ -745,7 +751,7 @@ Error ResourceLoaderBinary::load() {
ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, local_path + ":Resource type in resource field not a resource, type is: " + obj_class + ".");
}
- res = RES(r);
+ res = Ref<Resource>(r);
if (!path.is_empty() && cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) {
r->set_path(path, cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE); //if got here because the resource with same path has different type, replace it
}
@@ -760,6 +766,8 @@ Error ResourceLoaderBinary::load() {
//set properties
+ Dictionary missing_resource_properties;
+
for (int j = 0; j < pc; j++) {
StringName name = _get_string();
@@ -775,12 +783,35 @@ Error ResourceLoaderBinary::load() {
return error;
}
- res->set(name, value);
+ bool set_valid = true;
+ if (value.get_type() == Variant::OBJECT && missing_resource != nullptr) {
+ // If the property being set is a missing resource (and the parent is not),
+ // then setting it will most likely not work.
+ // Instead, save it as metadata.
+
+ Ref<MissingResource> mr = value;
+ if (mr.is_valid()) {
+ missing_resource_properties[name] = mr;
+ set_valid = false;
+ }
+ }
+
+ if (set_valid) {
+ res->set(name, value);
+ }
+ }
+
+ if (missing_resource) {
+ missing_resource->set_recording_properties(false);
}
+
+ if (!missing_resource_properties.is_empty()) {
+ res->set_meta(META_MISSING_RESOURCES, missing_resource_properties);
+ }
+
#ifdef TOOLS_ENABLED
res->set_edited(false);
#endif
- stage++;
if (progress) {
*progress = (i + 1) / float(internal_resources.size());
@@ -1026,7 +1057,7 @@ String ResourceLoaderBinary::recognize(Ref<FileAccess> p_f) {
return type;
}
-RES ResourceFormatLoaderBinary::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
+Ref<Resource> ResourceFormatLoaderBinary::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
if (r_error) {
*r_error = ERR_FILE_CANT_OPEN;
}
@@ -1034,7 +1065,7 @@ RES ResourceFormatLoaderBinary::load(const String &p_path, const String &p_origi
Error err;
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
- ERR_FAIL_COND_V_MSG(err != OK, RES(), "Cannot open file '" + p_path + "'.");
+ ERR_FAIL_COND_V_MSG(err != OK, Ref<Resource>(), "Cannot open file '" + p_path + "'.");
ResourceLoaderBinary loader;
loader.cache_mode = p_cache_mode;
@@ -1052,7 +1083,7 @@ RES ResourceFormatLoaderBinary::load(const String &p_path, const String &p_origi
}
if (err) {
- return RES();
+ return Ref<Resource>();
}
return loader.resource;
}
@@ -1178,7 +1209,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
err = loader.load();
ERR_FAIL_COND_V(err != ERR_FILE_EOF, ERR_FILE_CORRUPT);
- RES res = loader.get_resource();
+ Ref<Resource> res = loader.get_resource();
ERR_FAIL_COND_V(!res.is_valid(), ERR_FILE_CORRUPT);
return ResourceFormatSaverBinary::singleton->save(p_path, res);
@@ -1287,6 +1318,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
fw->store_8(b);
b = f->get_8();
}
+ f.unref();
bool all_ok = fw->get_error() == OK;
@@ -1352,7 +1384,7 @@ void ResourceFormatSaverBinaryInstance::_pad_buffer(Ref<FileAccess> f, int p_byt
}
}
-void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const Variant &p_property, Map<RES, int> &resource_map, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint) {
+void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const Variant &p_property, Map<Ref<Resource>, int> &resource_map, Map<Ref<Resource>, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint) {
switch (p_property.get_type()) {
case Variant::NIL: {
f->store_32(VARIANT_NIL);
@@ -1473,40 +1505,40 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
case Variant::TRANSFORM2D: {
f->store_32(VARIANT_TRANSFORM2D);
Transform2D val = p_property;
- f->store_real(val.elements[0].x);
- f->store_real(val.elements[0].y);
- f->store_real(val.elements[1].x);
- f->store_real(val.elements[1].y);
- f->store_real(val.elements[2].x);
- f->store_real(val.elements[2].y);
+ f->store_real(val.columns[0].x);
+ f->store_real(val.columns[0].y);
+ f->store_real(val.columns[1].x);
+ f->store_real(val.columns[1].y);
+ f->store_real(val.columns[2].x);
+ f->store_real(val.columns[2].y);
} break;
case Variant::BASIS: {
f->store_32(VARIANT_BASIS);
Basis val = p_property;
- f->store_real(val.elements[0].x);
- f->store_real(val.elements[0].y);
- f->store_real(val.elements[0].z);
- f->store_real(val.elements[1].x);
- f->store_real(val.elements[1].y);
- f->store_real(val.elements[1].z);
- f->store_real(val.elements[2].x);
- f->store_real(val.elements[2].y);
- f->store_real(val.elements[2].z);
+ f->store_real(val.rows[0].x);
+ f->store_real(val.rows[0].y);
+ f->store_real(val.rows[0].z);
+ f->store_real(val.rows[1].x);
+ f->store_real(val.rows[1].y);
+ f->store_real(val.rows[1].z);
+ f->store_real(val.rows[2].x);
+ f->store_real(val.rows[2].y);
+ f->store_real(val.rows[2].z);
} break;
case Variant::TRANSFORM3D: {
f->store_32(VARIANT_TRANSFORM3D);
Transform3D val = p_property;
- f->store_real(val.basis.elements[0].x);
- f->store_real(val.basis.elements[0].y);
- f->store_real(val.basis.elements[0].z);
- f->store_real(val.basis.elements[1].x);
- f->store_real(val.basis.elements[1].y);
- f->store_real(val.basis.elements[1].z);
- f->store_real(val.basis.elements[2].x);
- f->store_real(val.basis.elements[2].y);
- f->store_real(val.basis.elements[2].z);
+ f->store_real(val.basis.rows[0].x);
+ f->store_real(val.basis.rows[0].y);
+ f->store_real(val.basis.rows[0].z);
+ f->store_real(val.basis.rows[1].x);
+ f->store_real(val.basis.rows[1].y);
+ f->store_real(val.basis.rows[1].z);
+ f->store_real(val.basis.rows[2].x);
+ f->store_real(val.basis.rows[2].y);
+ f->store_real(val.basis.rows[2].z);
f->store_real(val.origin.x);
f->store_real(val.origin.y);
f->store_real(val.origin.z);
@@ -1561,7 +1593,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
} break;
case Variant::OBJECT: {
f->store_32(VARIANT_OBJECT);
- RES res = p_property;
+ Ref<Resource> res = p_property;
if (res.is_null()) {
f->store_32(OBJECT_EMPTY);
return; // don't save it
@@ -1727,7 +1759,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const V
void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant, bool p_main) {
switch (p_variant.get_type()) {
case Variant::OBJECT: {
- RES res = p_variant;
+ Ref<Resource> res = p_variant;
if (res.is_null() || external_resources.has(res)) {
return;
@@ -1755,7 +1787,7 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant
if (E.usage & PROPERTY_USAGE_STORAGE) {
Variant value = res->get(E.name);
if (E.usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) {
- RES sres = value;
+ Ref<Resource> sres = value;
if (sres.is_valid()) {
NonPersistentKey npk;
npk.base = res;
@@ -1832,7 +1864,16 @@ int ResourceFormatSaverBinaryInstance::get_string_index(const String &p_string)
return strings.size() - 1;
}
-Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
+static String _resource_get_class(Ref<Resource> p_resource) {
+ Ref<MissingResource> missing_resource = p_resource;
+ if (missing_resource.is_valid()) {
+ return missing_resource->get_original_class();
+ } else {
+ return p_resource->get_class();
+ }
+}
+
+Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) {
Error err;
Ref<FileAccess> f;
if (p_flags & ResourceSaver::FLAG_COMPRESS) {
@@ -1884,7 +1925,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
return ERR_CANT_CREATE;
}
- save_unicode_string(f, p_resource->get_class());
+ save_unicode_string(f, _resource_get_class(p_resource));
f->store_64(0); //offset to import metadata
{
uint32_t format_flags = FORMAT_FLAG_NAMED_SCENE_IDS | FORMAT_FLAG_UIDS;
@@ -1901,10 +1942,12 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
List<ResourceData> resources;
+ Dictionary missing_resource_properties = p_resource->get_meta(META_MISSING_RESOURCES, Dictionary());
+
{
- for (const RES &E : saved_resources) {
+ for (const Ref<Resource> &E : saved_resources) {
ResourceData &rd = resources.push_back(ResourceData())->get();
- rd.type = E->get_class();
+ rd.type = _resource_get_class(E);
List<PropertyInfo> property_list;
E->get_property_list(&property_list);
@@ -1913,6 +1956,10 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
if (skip_editor && F.name.begins_with("__editor")) {
continue;
}
+ if (F.name == META_PROPERTY_MISSING_RESOURCES) {
+ continue;
+ }
+
if ((F.usage & PROPERTY_USAGE_STORAGE)) {
Property p;
p.name_idx = get_string_index(F.name);
@@ -1928,6 +1975,14 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
p.value = E->get(F.name);
}
+ if (p.pi.type == Variant::OBJECT && missing_resource_properties.has(F.name)) {
+ // Was this missing resource overriden? If so do not save the old value.
+ Ref<Resource> res = p.value;
+ if (res.is_null()) {
+ p.value = missing_resource_properties[F.name];
+ }
+ }
+
Variant default_value = ClassDB::class_get_default_property_value(E->get_class(), F.name);
if (default_value.get_type() != Variant::NIL && bool(Variant::evaluate(Variant::OP_EQUAL, p.value, default_value))) {
@@ -1949,10 +2004,10 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
// save external resource table
f->store_32(external_resources.size()); //amount of external resources
- Vector<RES> save_order;
+ Vector<Ref<Resource>> save_order;
save_order.resize(external_resources.size());
- for (const KeyValue<RES, int> &E : external_resources) {
+ for (const KeyValue<Ref<Resource>, int> &E : external_resources) {
save_order.write[E.value] = E.key;
}
@@ -1969,7 +2024,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
Vector<uint64_t> ofs_pos;
Set<String> used_unique_ids;
- for (RES &r : saved_resources) {
+ for (Ref<Resource> &r : saved_resources) {
if (r->is_built_in()) {
if (!r->get_scene_unique_id().is_empty()) {
if (used_unique_ids.has(r->get_scene_unique_id())) {
@@ -1981,15 +2036,15 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
}
}
- Map<RES, int> resource_map;
+ Map<Ref<Resource>, int> resource_map;
int res_index = 0;
- for (RES &r : saved_resources) {
+ for (Ref<Resource> &r : saved_resources) {
if (r->is_built_in()) {
if (r->get_scene_unique_id().is_empty()) {
String new_id;
while (true) {
- new_id = r->get_class() + "_" + Resource::generate_scene_unique_id();
+ new_id = _resource_get_class(r) + "_" + Resource::generate_scene_unique_id();
if (!used_unique_ids.has(new_id)) {
break;
}
@@ -2044,17 +2099,17 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
return OK;
}
-Error ResourceFormatSaverBinary::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
+Error ResourceFormatSaverBinary::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) {
String local_path = ProjectSettings::get_singleton()->localize_path(p_path);
ResourceFormatSaverBinaryInstance saver;
return saver.save(local_path, p_resource, p_flags);
}
-bool ResourceFormatSaverBinary::recognize(const RES &p_resource) const {
+bool ResourceFormatSaverBinary::recognize(const Ref<Resource> &p_resource) const {
return true; //all recognized
}
-void ResourceFormatSaverBinary::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const {
+void ResourceFormatSaverBinary::get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const {
String base = p_resource->get_base_extension().to_lower();
p_extensions->push_back(base);
if (base != "res") {
diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h
index 72a3c6751d..92d4e4eeaa 100644
--- a/core/io/resource_format_binary.h
+++ b/core/io/resource_format_binary.h
@@ -50,7 +50,7 @@ class ResourceLoaderBinary {
ResourceUID::ID uid = ResourceUID::INVALID_ID;
Vector<char> str_buf;
- List<RES> resource_cache;
+ List<Ref<Resource>> resource_cache;
Vector<StringName> string_map;
@@ -60,7 +60,7 @@ class ResourceLoaderBinary {
String path;
String type;
ResourceUID::ID uid = ResourceUID::INVALID_ID;
- RES cache;
+ Ref<Resource> cache;
};
bool using_named_scene_ids = false;
@@ -75,7 +75,7 @@ class ResourceLoaderBinary {
};
Vector<IntResource> internal_resources;
- Map<String, RES> internal_index_cache;
+ Map<String, Ref<Resource>> internal_index_cache;
String get_unicode_string();
void _advance_padding(uint32_t p_len);
@@ -89,7 +89,7 @@ class ResourceLoaderBinary {
Error parse_variant(Variant &r_v);
- Map<String, RES> dependency_cache;
+ Map<String, Ref<Resource>> dependency_cache;
public:
void set_local_path(const String &p_local_path);
@@ -107,7 +107,7 @@ public:
class ResourceFormatLoaderBinary : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
+ virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const;
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
@@ -127,20 +127,20 @@ class ResourceFormatSaverBinaryInstance {
bool big_endian;
bool takeover_paths;
String magic;
- Set<RES> resource_set;
+ Set<Ref<Resource>> resource_set;
struct NonPersistentKey { //for resource properties generated on the fly
- RES base;
+ Ref<Resource> base;
StringName property;
bool operator<(const NonPersistentKey &p_key) const { return base == p_key.base ? property < p_key.property : base < p_key.base; }
};
- Map<NonPersistentKey, RES> non_persistent_map;
+ Map<NonPersistentKey, Ref<Resource>> non_persistent_map;
Map<StringName, int> string_map;
Vector<StringName> strings;
- Map<RES, int> external_resources;
- List<RES> saved_resources;
+ Map<Ref<Resource>, int> external_resources;
+ List<Ref<Resource>> saved_resources;
struct Property {
int name_idx;
@@ -167,16 +167,16 @@ public:
// Amount of reserved 32-bit fields in resource header
RESERVED_FIELDS = 11
};
- Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
- static void write_variant(Ref<FileAccess> f, const Variant &p_property, Map<RES, int> &resource_map, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint = PropertyInfo());
+ Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0);
+ static void write_variant(Ref<FileAccess> f, const Variant &p_property, Map<Ref<Resource>, int> &resource_map, Map<Ref<Resource>, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint = PropertyInfo());
};
class ResourceFormatSaverBinary : public ResourceFormatSaver {
public:
static ResourceFormatSaverBinary *singleton;
- virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
- virtual bool recognize(const RES &p_resource) const;
- virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const;
+ virtual Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0);
+ virtual bool recognize(const Ref<Resource> &p_resource) const;
+ virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const;
ResourceFormatSaverBinary();
};
diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp
index b4f73b3b25..984cf06d2b 100644
--- a/core/io/resource_importer.cpp
+++ b/core/io/resource_importer.cpp
@@ -114,7 +114,7 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
return OK;
}
-RES ResourceFormatImporter::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
+Ref<Resource> ResourceFormatImporter::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
PathAndType pat;
Error err = _get_path_and_type(p_path, pat);
@@ -123,10 +123,10 @@ RES ResourceFormatImporter::load(const String &p_path, const String &p_original_
*r_error = err;
}
- return RES();
+ return Ref<Resource>();
}
- RES res = ResourceLoader::_load(pat.path, p_path, pat.type, p_cache_mode, r_error, p_use_sub_threads, r_progress);
+ Ref<Resource> res = ResourceLoader::_load(pat.path, p_path, pat.type, p_cache_mode, r_error, p_use_sub_threads, r_progress);
#ifdef TOOLS_ENABLED
if (res.is_valid()) {
diff --git a/core/io/resource_importer.h b/core/io/resource_importer.h
index 2fffc16ad8..b3d777847b 100644
--- a/core/io/resource_importer.h
+++ b/core/io/resource_importer.h
@@ -58,7 +58,7 @@ class ResourceFormatImporter : public ResourceFormatLoader {
public:
static ResourceFormatImporter *get_singleton() { return singleton; }
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
+ virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const;
virtual bool recognize_path(const String &p_path, const String &p_for_type = String()) const;
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index fe9693aa20..d125dd4e91 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -125,14 +125,14 @@ void ResourceFormatLoader::get_recognized_extensions(List<String> *p_extensions)
}
}
-RES ResourceFormatLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
+Ref<Resource> ResourceFormatLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
Variant res;
if (GDVIRTUAL_CALL(_load, p_path, p_original_path, p_use_sub_threads, p_cache_mode, res)) {
if (res.get_type() == Variant::INT) { // Error code, abort.
if (r_error) {
*r_error = (Error)res.operator int64_t();
}
- return RES();
+ return Ref<Resource>();
} else { // Success, pass on result.
if (r_error) {
*r_error = OK;
@@ -141,7 +141,7 @@ RES ResourceFormatLoader::load(const String &p_path, const String &p_original_pa
}
}
- ERR_FAIL_V_MSG(RES(), "Failed to load resource '" + p_path + "'. ResourceFormatLoader::load was not implemented for this resource type.");
+ ERR_FAIL_V_MSG(Ref<Resource>(), "Failed to load resource '" + p_path + "'. ResourceFormatLoader::load was not implemented for this resource type.");
}
void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
@@ -185,7 +185,7 @@ void ResourceFormatLoader::_bind_methods() {
///////////////////////////////////
-RES ResourceLoader::_load(const String &p_path, const String &p_original_path, const String &p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error *r_error, bool p_use_sub_threads, float *r_progress) {
+Ref<Resource> ResourceLoader::_load(const String &p_path, const String &p_original_path, const String &p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error *r_error, bool p_use_sub_threads, float *r_progress) {
bool found = false;
// Try all loaders and pick the first match for the type hint
@@ -194,7 +194,7 @@ RES ResourceLoader::_load(const String &p_path, const String &p_original_path, c
continue;
}
found = true;
- RES res = loader[i]->load(p_path, !p_original_path.is_empty() ? p_original_path : p_path, r_error, p_use_sub_threads, r_progress, p_cache_mode);
+ Ref<Resource> res = loader[i]->load(p_path, !p_original_path.is_empty() ? p_original_path : p_path, r_error, p_use_sub_threads, r_progress, p_cache_mode);
if (res.is_null()) {
continue;
}
@@ -202,15 +202,15 @@ RES ResourceLoader::_load(const String &p_path, const String &p_original_path, c
return res;
}
- ERR_FAIL_COND_V_MSG(found, RES(),
+ ERR_FAIL_COND_V_MSG(found, Ref<Resource>(),
vformat("Failed loading resource: %s. Make sure resources have been imported by opening the project in the editor at least once.", p_path));
#ifdef TOOLS_ENABLED
Ref<FileAccess> file_check = FileAccess::create(FileAccess::ACCESS_RESOURCES);
- ERR_FAIL_COND_V_MSG(!file_check->file_exists(p_path), RES(), "Resource file not found: " + p_path + ".");
+ ERR_FAIL_COND_V_MSG(!file_check->file_exists(p_path), Ref<Resource>(), "Resource file not found: " + p_path + ".");
#endif
- ERR_FAIL_V_MSG(RES(), "No loader found for resource: " + p_path + ".");
+ ERR_FAIL_V_MSG(Ref<Resource>(), "No loader found for resource: " + p_path + ".");
}
void ResourceLoader::_thread_load_function(void *p_userdata) {
@@ -342,7 +342,7 @@ Error ResourceLoader::load_threaded_request(const String &p_path, const String &
Resource **rptr = ResourceCache::resources.getptr(local_path);
if (rptr) {
- RES res(*rptr);
+ Ref<Resource> res(*rptr);
//it is possible this resource was just freed in a thread. If so, this referencing will not work and resource is considered not cached
if (res.is_valid()) {
//referencing is fine
@@ -427,7 +427,7 @@ ResourceLoader::ThreadLoadStatus ResourceLoader::load_threaded_get_status(const
return status;
}
-RES ResourceLoader::load_threaded_get(const String &p_path, Error *r_error) {
+Ref<Resource> ResourceLoader::load_threaded_get(const String &p_path, Error *r_error) {
String local_path = _validate_local_path(p_path);
thread_load_mutex->lock();
@@ -436,7 +436,7 @@ RES ResourceLoader::load_threaded_get(const String &p_path, Error *r_error) {
if (r_error) {
*r_error = ERR_INVALID_PARAMETER;
}
- return RES();
+ return Ref<Resource>();
}
ThreadLoadTask &load_task = thread_load_tasks[local_path];
@@ -480,11 +480,11 @@ RES ResourceLoader::load_threaded_get(const String &p_path, Error *r_error) {
if (r_error) {
*r_error = ERR_INVALID_PARAMETER;
}
- return RES();
+ return Ref<Resource>();
}
}
- RES resource = load_task.resource;
+ Ref<Resource> resource = load_task.resource;
if (r_error) {
*r_error = load_task.error;
}
@@ -504,7 +504,7 @@ RES ResourceLoader::load_threaded_get(const String &p_path, Error *r_error) {
return resource;
}
-RES ResourceLoader::load(const String &p_path, const String &p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error *r_error) {
+Ref<Resource> ResourceLoader::load(const String &p_path, const String &p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error *r_error) {
if (r_error) {
*r_error = ERR_CANT_OPEN;
}
@@ -522,7 +522,7 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, Resour
*r_error = err;
}
thread_load_mutex->unlock();
- return RES();
+ return Ref<Resource>();
}
thread_load_mutex->unlock();
@@ -535,7 +535,7 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, Resour
Resource **rptr = ResourceCache::resources.getptr(local_path);
if (rptr) {
- RES res(*rptr);
+ Ref<Resource> res(*rptr);
//it is possible this resource was just freed in a thread. If so, this referencing will not work and resource is considered not cached
if (res.is_valid()) {
@@ -575,16 +575,16 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, Resour
String path = _path_remap(local_path, &xl_remapped);
if (path.is_empty()) {
- ERR_FAIL_V_MSG(RES(), "Remapping '" + local_path + "' failed.");
+ ERR_FAIL_V_MSG(Ref<Resource>(), "Remapping '" + local_path + "' failed.");
}
print_verbose("Loading resource: " + path);
float p;
- RES res = _load(path, local_path, p_type_hint, p_cache_mode, r_error, false, &p);
+ Ref<Resource> res = _load(path, local_path, p_type_hint, p_cache_mode, r_error, false, &p);
if (res.is_null()) {
print_verbose("Failed loading resource: " + path);
- return RES();
+ return Ref<Resource>();
}
if (xl_remapped) {
@@ -979,6 +979,10 @@ void ResourceLoader::remove_custom_resource_format_loader(String script_path) {
}
}
+void ResourceLoader::set_create_missing_resources_if_class_unavailable(bool p_enable) {
+ create_missing_resources_if_class_unavailable = p_enable;
+}
+
void ResourceLoader::add_custom_loaders() {
// Custom loaders registration exploits global class names
@@ -1030,6 +1034,7 @@ void *ResourceLoader::err_notify_ud = nullptr;
DependencyErrorNotify ResourceLoader::dep_err_notify = nullptr;
void *ResourceLoader::dep_err_notify_ud = nullptr;
+bool ResourceLoader::create_missing_resources_if_class_unavailable = false;
bool ResourceLoader::abort_on_missing_resource = true;
bool ResourceLoader::timestamp_on_load = false;
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index a3fdefa0f1..ea18ac23fd 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -61,7 +61,7 @@ protected:
GDVIRTUAL4RC(Variant, _load, String, String, bool, int)
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
+ virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual bool exists(const String &p_path) const;
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const;
@@ -85,7 +85,7 @@ typedef void (*ResourceLoadErrorNotify)(void *p_ud, const String &p_text);
typedef void (*DependencyErrorNotify)(void *p_ud, const String &p_loading, const String &p_which, const String &p_type);
typedef Error (*ResourceLoaderImport)(const String &p_path);
-typedef void (*ResourceLoadedCallback)(RES p_resource, const String &p_path);
+typedef void (*ResourceLoadedCallback)(Ref<Resource> p_resource, const String &p_path);
class ResourceLoader {
enum {
@@ -110,6 +110,7 @@ private:
static void *dep_err_notify_ud;
static DependencyErrorNotify dep_err_notify;
static bool abort_on_missing_resource;
+ static bool create_missing_resources_if_class_unavailable;
static HashMap<String, Vector<String>> translation_remaps;
static HashMap<String, String> path_remaps;
@@ -121,7 +122,7 @@ private:
friend class ResourceFormatImporter;
friend class ResourceInteractiveLoader;
// Internal load function.
- static RES _load(const String &p_path, const String &p_original_path, const String &p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error *r_error, bool p_use_sub_threads, float *r_progress);
+ static Ref<Resource> _load(const String &p_path, const String &p_original_path, const String &p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error *r_error, bool p_use_sub_threads, float *r_progress);
static ResourceLoadedCallback _loaded_callback;
@@ -138,7 +139,7 @@ private:
ThreadLoadStatus status = THREAD_LOAD_IN_PROGRESS;
ResourceFormatLoader::CacheMode cache_mode = ResourceFormatLoader::CACHE_MODE_REUSE;
Error error = OK;
- RES resource;
+ Ref<Resource> resource;
bool xl_remapped = false;
bool use_sub_threads = false;
bool start_next = true;
@@ -161,9 +162,9 @@ private:
public:
static Error load_threaded_request(const String &p_path, const String &p_type_hint = "", bool p_use_sub_threads = false, ResourceFormatLoader::CacheMode p_cache_mode = ResourceFormatLoader::CACHE_MODE_REUSE, const String &p_source_resource = String());
static ThreadLoadStatus load_threaded_get_status(const String &p_path, float *r_progress = nullptr);
- static RES load_threaded_get(const String &p_path, Error *r_error = nullptr);
+ static Ref<Resource> load_threaded_get(const String &p_path, Error *r_error = nullptr);
- static RES load(const String &p_path, const String &p_type_hint = "", ResourceFormatLoader::CacheMode p_cache_mode = ResourceFormatLoader::CACHE_MODE_REUSE, Error *r_error = nullptr);
+ static Ref<Resource> load(const String &p_path, const String &p_type_hint = "", ResourceFormatLoader::CacheMode p_cache_mode = ResourceFormatLoader::CACHE_MODE_REUSE, Error *r_error = nullptr);
static bool exists(const String &p_path, const String &p_type_hint = "");
static void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions);
@@ -222,6 +223,9 @@ public:
static void add_custom_loaders();
static void remove_custom_loaders();
+ static void set_create_missing_resources_if_class_unavailable(bool p_enable);
+ _FORCE_INLINE_ static bool is_creating_missing_resources_if_class_unavailable_enabled() { return create_missing_resources_if_class_unavailable; }
+
static void initialize();
static void finalize();
};
diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp
index c883e8502f..2f5c5b54dd 100644
--- a/core/io/resource_saver.cpp
+++ b/core/io/resource_saver.cpp
@@ -41,7 +41,7 @@ bool ResourceSaver::timestamp_on_save = false;
ResourceSavedCallback ResourceSaver::save_callback = nullptr;
ResourceSaverGetResourceIDForPath ResourceSaver::save_get_id_for_path = nullptr;
-Error ResourceFormatSaver::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
+Error ResourceFormatSaver::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) {
int64_t res;
if (GDVIRTUAL_CALL(_save, p_path, p_resource, p_flags, res)) {
return (Error)res;
@@ -50,7 +50,7 @@ Error ResourceFormatSaver::save(const String &p_path, const RES &p_resource, uin
return ERR_METHOD_NOT_FOUND;
}
-bool ResourceFormatSaver::recognize(const RES &p_resource) const {
+bool ResourceFormatSaver::recognize(const Ref<Resource> &p_resource) const {
bool success;
if (GDVIRTUAL_CALL(_recognize, p_resource, success)) {
return success;
@@ -59,7 +59,7 @@ bool ResourceFormatSaver::recognize(const RES &p_resource) const {
return false;
}
-void ResourceFormatSaver::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const {
+void ResourceFormatSaver::get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const {
PackedStringArray exts;
if (GDVIRTUAL_CALL(_get_recognized_extensions, p_resource, exts)) {
const String *r = exts.ptr();
@@ -75,7 +75,7 @@ void ResourceFormatSaver::_bind_methods() {
GDVIRTUAL_BIND(_get_recognized_extensions, "resource");
}
-Error ResourceSaver::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
+Error ResourceSaver::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) {
String extension = p_path.get_extension();
Error err = ERR_FILE_UNRECOGNIZED;
@@ -102,7 +102,7 @@ Error ResourceSaver::save(const String &p_path, const RES &p_resource, uint32_t
String local_path = ProjectSettings::get_singleton()->localize_path(p_path);
- RES rwcopy = p_resource;
+ Ref<Resource> rwcopy = p_resource;
if (p_flags & FLAG_CHANGE_PATH) {
rwcopy->set_path(local_path);
}
@@ -139,7 +139,7 @@ void ResourceSaver::set_save_callback(ResourceSavedCallback p_callback) {
save_callback = p_callback;
}
-void ResourceSaver::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) {
+void ResourceSaver::get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) {
for (int i = 0; i < saver_count; i++) {
saver[i]->get_recognized_extensions(p_resource, p_extensions);
}
diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h
index ebc3be91a1..088317bfbe 100644
--- a/core/io/resource_saver.h
+++ b/core/io/resource_saver.h
@@ -41,14 +41,14 @@ class ResourceFormatSaver : public RefCounted {
protected:
static void _bind_methods();
- GDVIRTUAL3R(int64_t, _save, String, RES, uint32_t)
- GDVIRTUAL1RC(bool, _recognize, RES)
- GDVIRTUAL1RC(Vector<String>, _get_recognized_extensions, RES)
+ GDVIRTUAL3R(int64_t, _save, String, Ref<Resource>, uint32_t)
+ GDVIRTUAL1RC(bool, _recognize, Ref<Resource>)
+ GDVIRTUAL1RC(Vector<String>, _get_recognized_extensions, Ref<Resource>)
public:
- virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
- virtual bool recognize(const RES &p_resource) const;
- virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const;
+ virtual Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = 0);
+ virtual bool recognize(const Ref<Resource> &p_resource) const;
+ virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const;
virtual ~ResourceFormatSaver() {}
};
@@ -81,8 +81,8 @@ public:
FLAG_REPLACE_SUBRESOURCE_PATHS = 64,
};
- static Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = (uint32_t)FLAG_NONE);
- static void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions);
+ static Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags = (uint32_t)FLAG_NONE);
+ static void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions);
static void add_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver, bool p_at_front = false);
static void remove_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver);
diff --git a/core/io/resource_uid.cpp b/core/io/resource_uid.cpp
index 515b7c710e..fc324a26da 100644
--- a/core/io/resource_uid.cpp
+++ b/core/io/resource_uid.cpp
@@ -149,12 +149,12 @@ Error ResourceUID::save_to_cache() {
cache_entries = 0;
- for (OrderedHashMap<ID, Cache>::Element E = unique_ids.front(); E; E = E.next()) {
- f->store_64(E.key());
- uint32_t s = E.get().cs.length();
+ for (KeyValue<ID, Cache> &E : unique_ids) {
+ f->store_64(E.key);
+ uint32_t s = E.value.cs.length();
f->store_32(s);
- f->store_buffer((const uint8_t *)E.get().cs.ptr(), s);
- E.get().saved_to_cache = true;
+ f->store_buffer((const uint8_t *)E.value.cs.ptr(), s);
+ E.value.saved_to_cache = true;
cache_entries++;
}
@@ -202,8 +202,8 @@ Error ResourceUID::update_cache() {
MutexLock l(mutex);
Ref<FileAccess> f;
- for (OrderedHashMap<ID, Cache>::Element E = unique_ids.front(); E; E = E.next()) {
- if (!E.get().saved_to_cache) {
+ for (KeyValue<ID, Cache> &E : unique_ids) {
+ if (!E.value.saved_to_cache) {
if (f.is_null()) {
f = FileAccess::open(get_cache_file(), FileAccess::READ_WRITE); //append
if (f.is_null()) {
@@ -211,11 +211,11 @@ Error ResourceUID::update_cache() {
}
f->seek_end();
}
- f->store_64(E.key());
- uint32_t s = E.get().cs.length();
+ f->store_64(E.key);
+ uint32_t s = E.value.cs.length();
f->store_32(s);
- f->store_buffer((const uint8_t *)E.get().cs.ptr(), s);
- E.get().saved_to_cache = true;
+ f->store_buffer((const uint8_t *)E.value.cs.ptr(), s);
+ E.value.saved_to_cache = true;
cache_entries++;
}
}
diff --git a/core/io/resource_uid.h b/core/io/resource_uid.h
index 0b7ffdf6d0..da42553cf5 100644
--- a/core/io/resource_uid.h
+++ b/core/io/resource_uid.h
@@ -33,7 +33,7 @@
#include "core/object/ref_counted.h"
#include "core/string/string_name.h"
-#include "core/templates/ordered_hash_map.h"
+#include "core/templates/hash_map.h"
class ResourceUID : public Object {
GDCLASS(ResourceUID, Object)
@@ -53,7 +53,7 @@ private:
bool saved_to_cache = false;
};
- OrderedHashMap<ID, Cache> unique_ids; //unique IDs and utf8 paths (less memory used)
+ HashMap<ID, Cache> unique_ids; //unique IDs and utf8 paths (less memory used)
static ResourceUID *singleton;
uint32_t cache_entries = 0;
diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp
index 6d5784a8ab..ba79590c19 100644
--- a/core/io/stream_peer_tcp.cpp
+++ b/core/io/stream_peer_tcp.cpp
@@ -32,8 +32,28 @@
#include "core/config/project_settings.h"
-Error StreamPeerTCP::_poll_connection() {
- ERR_FAIL_COND_V(status != STATUS_CONNECTING || !_sock.is_valid() || !_sock->is_open(), FAILED);
+Error StreamPeerTCP::poll() {
+ if (status == STATUS_CONNECTED) {
+ Error err;
+ err = _sock->poll(NetSocket::POLL_TYPE_IN, 0);
+ if (err == OK) {
+ // FIN received
+ if (_sock->get_available_bytes() == 0) {
+ disconnect_from_host();
+ return OK;
+ }
+ }
+ // Also poll write
+ err = _sock->poll(NetSocket::POLL_TYPE_IN_OUT, 0);
+ if (err != OK && err != ERR_BUSY) {
+ // Got an error
+ disconnect_from_host();
+ status = STATUS_ERROR;
+ return err;
+ }
+ } else if (status != STATUS_CONNECTING) {
+ return OK;
+ }
Error err = _sock->connect_to_host(peer_host, peer_port);
@@ -61,7 +81,7 @@ void StreamPeerTCP::accept_socket(Ref<NetSocket> p_sock, IPAddress p_host, uint1
_sock->set_blocking_enabled(false);
timeout = OS::get_singleton()->get_ticks_msec() + (((uint64_t)GLOBAL_GET("network/limits/tcp/connect_timeout_seconds")) * 1000);
- status = STATUS_CONNECTING;
+ status = STATUS_CONNECTED;
peer_host = p_host;
peer_port = p_port;
@@ -121,22 +141,7 @@ Error StreamPeerTCP::connect_to_host(const IPAddress &p_host, int p_port) {
Error StreamPeerTCP::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block) {
ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE);
- if (status == STATUS_NONE || status == STATUS_ERROR) {
- return FAILED;
- }
-
if (status != STATUS_CONNECTED) {
- if (_poll_connection() != OK) {
- return FAILED;
- }
-
- if (status != STATUS_CONNECTED) {
- r_sent = 0;
- return OK;
- }
- }
-
- if (!_sock->is_open()) {
return FAILED;
}
@@ -179,21 +184,10 @@ Error StreamPeerTCP::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool
}
Error StreamPeerTCP::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block) {
- if (!is_connected_to_host()) {
+ if (status != STATUS_CONNECTED) {
return FAILED;
}
- if (status == STATUS_CONNECTING) {
- if (_poll_connection() != OK) {
- return FAILED;
- }
-
- if (status != STATUS_CONNECTED) {
- r_received = 0;
- return OK;
- }
- }
-
Error err;
int to_read = p_bytes;
int total_read = 0;
@@ -243,36 +237,11 @@ Error StreamPeerTCP::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool
}
void StreamPeerTCP::set_no_delay(bool p_enabled) {
- ERR_FAIL_COND(!is_connected_to_host());
+ ERR_FAIL_COND(!_sock.is_valid() || !_sock->is_open());
_sock->set_tcp_no_delay_enabled(p_enabled);
}
-bool StreamPeerTCP::is_connected_to_host() const {
- return _sock.is_valid() && _sock->is_open() && (status == STATUS_CONNECTED || status == STATUS_CONNECTING);
-}
-
-StreamPeerTCP::Status StreamPeerTCP::get_status() {
- if (status == STATUS_CONNECTING) {
- _poll_connection();
- } else if (status == STATUS_CONNECTED) {
- Error err;
- err = _sock->poll(NetSocket::POLL_TYPE_IN, 0);
- if (err == OK) {
- // FIN received
- if (_sock->get_available_bytes() == 0) {
- disconnect_from_host();
- return status;
- }
- }
- // Also poll write
- err = _sock->poll(NetSocket::POLL_TYPE_IN_OUT, 0);
- if (err != OK && err != ERR_BUSY) {
- // Got an error
- disconnect_from_host();
- status = STATUS_ERROR;
- }
- }
-
+StreamPeerTCP::Status StreamPeerTCP::get_status() const {
return status;
}
@@ -287,7 +256,7 @@ void StreamPeerTCP::disconnect_from_host() {
peer_port = 0;
}
-Error StreamPeerTCP::poll(NetSocket::PollType p_type, int timeout) {
+Error StreamPeerTCP::wait(NetSocket::PollType p_type, int timeout) {
ERR_FAIL_COND_V(_sock.is_null() || !_sock->is_open(), ERR_UNAVAILABLE);
return _sock->poll(p_type, timeout);
}
@@ -346,7 +315,7 @@ Error StreamPeerTCP::_connect(const String &p_address, int p_port) {
void StreamPeerTCP::_bind_methods() {
ClassDB::bind_method(D_METHOD("bind", "port", "host"), &StreamPeerTCP::bind, DEFVAL("*"));
ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port"), &StreamPeerTCP::_connect);
- ClassDB::bind_method(D_METHOD("is_connected_to_host"), &StreamPeerTCP::is_connected_to_host);
+ ClassDB::bind_method(D_METHOD("poll"), &StreamPeerTCP::poll);
ClassDB::bind_method(D_METHOD("get_status"), &StreamPeerTCP::get_status);
ClassDB::bind_method(D_METHOD("get_connected_host"), &StreamPeerTCP::get_connected_host);
ClassDB::bind_method(D_METHOD("get_connected_port"), &StreamPeerTCP::get_connected_port);
diff --git a/core/io/stream_peer_tcp.h b/core/io/stream_peer_tcp.h
index bf49cc8a5f..39c2e84346 100644
--- a/core/io/stream_peer_tcp.h
+++ b/core/io/stream_peer_tcp.h
@@ -55,7 +55,6 @@ protected:
uint16_t peer_port = 0;
Error _connect(const String &p_address, int p_port);
- Error _poll_connection();
Error write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block);
Error read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block);
@@ -66,19 +65,21 @@ public:
Error bind(int p_port, const IPAddress &p_host);
Error connect_to_host(const IPAddress &p_host, int p_port);
- bool is_connected_to_host() const;
IPAddress get_connected_host() const;
int get_connected_port() const;
int get_local_port() const;
void disconnect_from_host();
int get_available_bytes() const override;
- Status get_status();
+ Status get_status() const;
void set_no_delay(bool p_enabled);
- // Poll functions (wait or check for writable, readable)
- Error poll(NetSocket::PollType p_type, int timeout = 0);
+ // Poll socket updating its state.
+ Error poll();
+
+ // Wait or check for writable, readable.
+ Error wait(NetSocket::PollType p_type, int timeout = 0);
// Read/Write from StreamPeer
Error put_data(const uint8_t *p_data, int p_bytes) override;
diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp
index ae1ad304d7..f36eb7c763 100644
--- a/core/io/translation_loader_po.cpp
+++ b/core/io/translation_loader_po.cpp
@@ -34,7 +34,7 @@
#include "core/string/translation.h"
#include "core/string/translation_po.h"
-RES TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_error) {
+Ref<Resource> TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_error) {
if (r_error) {
*r_error = ERR_FILE_CORRUPT;
}
@@ -49,7 +49,7 @@ RES TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_error) {
uint16_t version_maj = f->get_16();
uint16_t version_min = f->get_16();
- ERR_FAIL_COND_V_MSG(version_maj > 1, RES(), vformat("Unsupported MO file %s, version %d.%d.", path, version_maj, version_min));
+ ERR_FAIL_COND_V_MSG(version_maj > 1, Ref<Resource>(), vformat("Unsupported MO file %s, version %d.%d.", path, version_maj, version_min));
uint32_t num_strings = f->get_32();
uint32_t id_table_offset = f->get_32();
@@ -170,14 +170,14 @@ RES TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_error) {
// If we reached last line and it's not a content line, break, otherwise let processing that last loop
if (is_eof && l.is_empty()) {
if (status == STATUS_READING_ID || status == STATUS_READING_CONTEXT || (status == STATUS_READING_PLURAL && plural_index != plural_forms - 1)) {
- ERR_FAIL_V_MSG(RES(), "Unexpected EOF while reading PO file at: " + path + ":" + itos(line));
+ ERR_FAIL_V_MSG(Ref<Resource>(), "Unexpected EOF while reading PO file at: " + path + ":" + itos(line));
} else {
break;
}
}
if (l.begins_with("msgctxt")) {
- ERR_FAIL_COND_V_MSG(status != STATUS_READING_STRING && status != STATUS_READING_PLURAL, RES(), "Unexpected 'msgctxt', was expecting 'msgid_plural' or 'msgstr' before 'msgctxt' while parsing: " + path + ":" + itos(line));
+ ERR_FAIL_COND_V_MSG(status != STATUS_READING_STRING && status != STATUS_READING_PLURAL, Ref<Resource>(), "Unexpected 'msgctxt', was expecting 'msgid_plural' or 'msgstr' before 'msgctxt' while parsing: " + path + ":" + itos(line));
// In PO file, "msgctxt" appears before "msgid". If we encounter a "msgctxt", we add what we have read
// and set "entered_context" to true to prevent adding twice.
@@ -185,7 +185,7 @@ RES TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_error) {
if (status == STATUS_READING_STRING) {
translation->add_message(msg_id, msg_str, msg_context);
} else if (status == STATUS_READING_PLURAL) {
- ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, RES(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
+ ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, Ref<Resource>(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
translation->add_plural_message(msg_id, msgs_plural, msg_context);
}
}
@@ -197,9 +197,9 @@ RES TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_error) {
if (l.begins_with("msgid_plural")) {
if (plural_forms == 0) {
- ERR_FAIL_V_MSG(RES(), "PO file uses 'msgid_plural' but 'Plural-Forms' is invalid or missing in header: " + path + ":" + itos(line));
+ ERR_FAIL_V_MSG(Ref<Resource>(), "PO file uses 'msgid_plural' but 'Plural-Forms' is invalid or missing in header: " + path + ":" + itos(line));
} else if (status != STATUS_READING_ID) {
- ERR_FAIL_V_MSG(RES(), "Unexpected 'msgid_plural', was expecting 'msgid' before 'msgid_plural' while parsing: " + path + ":" + itos(line));
+ ERR_FAIL_V_MSG(Ref<Resource>(), "Unexpected 'msgid_plural', was expecting 'msgid' before 'msgid_plural' while parsing: " + path + ":" + itos(line));
}
// 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.
@@ -209,14 +209,14 @@ RES TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_error) {
msgs_plural.resize(plural_forms);
status = STATUS_READING_PLURAL;
} else if (l.begins_with("msgid")) {
- ERR_FAIL_COND_V_MSG(status == STATUS_READING_ID, RES(), "Unexpected 'msgid', was expecting 'msgstr' while parsing: " + path + ":" + itos(line));
+ ERR_FAIL_COND_V_MSG(status == STATUS_READING_ID, Ref<Resource>(), "Unexpected 'msgid', was expecting 'msgstr' while parsing: " + path + ":" + itos(line));
if (!msg_id.is_empty()) {
if (!skip_this && !entered_context) {
if (status == STATUS_READING_STRING) {
translation->add_message(msg_id, msg_str, msg_context);
} else if (status == STATUS_READING_PLURAL) {
- ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, RES(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
+ ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, Ref<Resource>(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
translation->add_plural_message(msg_id, msgs_plural, msg_context);
}
}
@@ -245,11 +245,11 @@ RES TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_error) {
}
if (l.begins_with("msgstr[")) {
- ERR_FAIL_COND_V_MSG(status != STATUS_READING_PLURAL, RES(), "Unexpected 'msgstr[]', was expecting 'msgid_plural' before 'msgstr[]' while parsing: " + path + ":" + itos(line));
+ ERR_FAIL_COND_V_MSG(status != STATUS_READING_PLURAL, Ref<Resource>(), "Unexpected 'msgstr[]', was expecting 'msgid_plural' before 'msgstr[]' while parsing: " + path + ":" + itos(line));
plural_index++; // Increment to add to the next slot in vector msgs_plural.
l = l.substr(9, l.length()).strip_edges();
} else if (l.begins_with("msgstr")) {
- ERR_FAIL_COND_V_MSG(status != STATUS_READING_ID, RES(), "Unexpected 'msgstr', was expecting 'msgid' before 'msgstr' while parsing: " + path + ":" + itos(line));
+ ERR_FAIL_COND_V_MSG(status != STATUS_READING_ID, Ref<Resource>(), "Unexpected 'msgstr', was expecting 'msgid' before 'msgstr' while parsing: " + path + ":" + itos(line));
l = l.substr(6, l.length()).strip_edges();
status = STATUS_READING_STRING;
}
@@ -262,7 +262,7 @@ RES TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_error) {
continue; // Nothing to read or comment.
}
- ERR_FAIL_COND_V_MSG(!l.begins_with("\"") || status == STATUS_NONE, RES(), "Invalid line '" + l + "' while parsing: " + path + ":" + itos(line));
+ ERR_FAIL_COND_V_MSG(!l.begins_with("\"") || status == STATUS_NONE, Ref<Resource>(), "Invalid line '" + l + "' while parsing: " + path + ":" + itos(line));
l = l.substr(1, l.length());
// Find final quote, ignoring escaped ones (\").
@@ -284,7 +284,7 @@ RES TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_error) {
escape_next = false;
}
- ERR_FAIL_COND_V_MSG(end_pos == -1, RES(), "Expected '\"' at end of message while parsing: " + path + ":" + itos(line));
+ ERR_FAIL_COND_V_MSG(end_pos == -1, Ref<Resource>(), "Expected '\"' at end of message while parsing: " + path + ":" + itos(line));
l = l.substr(0, end_pos);
l = l.c_unescape();
@@ -296,7 +296,7 @@ RES TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_error) {
} else if (status == STATUS_READING_CONTEXT) {
msg_context += l;
} else if (status == STATUS_READING_PLURAL && plural_index >= 0) {
- ERR_FAIL_COND_V_MSG(plural_index >= plural_forms, RES(), "Unexpected plural form while parsing: " + path + ":" + itos(line));
+ ERR_FAIL_COND_V_MSG(plural_index >= plural_forms, Ref<Resource>(), "Unexpected plural form while parsing: " + path + ":" + itos(line));
msgs_plural.write[plural_index] = msgs_plural[plural_index] + l;
}
@@ -314,13 +314,13 @@ RES TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_error) {
}
} else if (status == STATUS_READING_PLURAL) {
if (!skip_this && !msg_id.is_empty()) {
- ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, RES(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
+ ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, Ref<Resource>(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
translation->add_plural_message(msg_id, msgs_plural, msg_context);
}
}
}
- ERR_FAIL_COND_V_MSG(config.is_empty(), RES(), "No config found in file: " + path + ".");
+ ERR_FAIL_COND_V_MSG(config.is_empty(), Ref<Resource>(), "No config found in file: " + path + ".");
Vector<String> configs = config.split("\n");
for (int i = 0; i < configs.size(); i++) {
@@ -344,13 +344,13 @@ RES TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_error) {
return translation;
}
-RES TranslationLoaderPO::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
+Ref<Resource> TranslationLoaderPO::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
if (r_error) {
*r_error = ERR_CANT_OPEN;
}
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_V_MSG(f.is_null(), RES(), "Cannot open file '" + p_path + "'.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), Ref<Resource>(), "Cannot open file '" + p_path + "'.");
return load_translation(f, r_error);
}
diff --git a/core/io/translation_loader_po.h b/core/io/translation_loader_po.h
index 7da361cf24..4477ad7714 100644
--- a/core/io/translation_loader_po.h
+++ b/core/io/translation_loader_po.h
@@ -37,8 +37,8 @@
class TranslationLoaderPO : public ResourceFormatLoader {
public:
- static RES load_translation(Ref<FileAccess> f, Error *r_error = nullptr);
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
+ static Ref<Resource> load_translation(Ref<FileAccess> f, Error *r_error = nullptr);
+ virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/core/io/zip_io.cpp b/core/io/zip_io.cpp
index 2cc844b628..e573e8de19 100644
--- a/core/io/zip_io.cpp
+++ b/core/io/zip_io.cpp
@@ -31,18 +31,19 @@
#include "zip_io.h"
void *zipio_open(voidpf opaque, const char *p_fname, int mode) {
- ZipIOData *zd = (ZipIOData *)opaque;
+ Ref<FileAccess> *fa = reinterpret_cast<Ref<FileAccess> *>(opaque);
+ ERR_FAIL_COND_V(fa == nullptr, nullptr);
String fname;
fname.parse_utf8(p_fname);
if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
- zd->f = FileAccess::open(fname, FileAccess::WRITE);
+ (*fa) = FileAccess::open(fname, FileAccess::WRITE);
} else {
- zd->f = FileAccess::open(fname, FileAccess::READ);
+ (*fa) = FileAccess::open(fname, FileAccess::READ);
}
- if (zd->f.is_null()) {
+ if (fa->is_null()) {
return nullptr;
}
@@ -50,49 +51,66 @@ void *zipio_open(voidpf opaque, const char *p_fname, int mode) {
}
uLong zipio_read(voidpf opaque, voidpf stream, void *buf, uLong size) {
- ZipIOData *zd = (ZipIOData *)opaque;
- return zd->f->get_buffer((uint8_t *)buf, size);
+ Ref<FileAccess> *fa = reinterpret_cast<Ref<FileAccess> *>(opaque);
+ ERR_FAIL_COND_V(fa == nullptr, 0);
+ ERR_FAIL_COND_V(fa->is_null(), 0);
+
+ return (*fa)->get_buffer((uint8_t *)buf, size);
}
uLong zipio_write(voidpf opaque, voidpf stream, const void *buf, uLong size) {
- ZipIOData *zd = (ZipIOData *)opaque;
- zd->f->store_buffer((uint8_t *)buf, size);
+ Ref<FileAccess> *fa = reinterpret_cast<Ref<FileAccess> *>(opaque);
+ ERR_FAIL_COND_V(fa == nullptr, 0);
+ ERR_FAIL_COND_V(fa->is_null(), 0);
+
+ (*fa)->store_buffer((uint8_t *)buf, size);
return size;
}
long zipio_tell(voidpf opaque, voidpf stream) {
- ZipIOData *zd = (ZipIOData *)opaque;
- return zd->f->get_position();
+ Ref<FileAccess> *fa = reinterpret_cast<Ref<FileAccess> *>(opaque);
+ ERR_FAIL_COND_V(fa == nullptr, 0);
+ ERR_FAIL_COND_V(fa->is_null(), 0);
+
+ return (*fa)->get_position();
}
long zipio_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
- ZipIOData *zd = (ZipIOData *)opaque;
+ Ref<FileAccess> *fa = reinterpret_cast<Ref<FileAccess> *>(opaque);
+ ERR_FAIL_COND_V(fa == nullptr, 0);
+ ERR_FAIL_COND_V(fa->is_null(), 0);
uint64_t pos = offset;
switch (origin) {
case ZLIB_FILEFUNC_SEEK_CUR:
- pos = zd->f->get_position() + offset;
+ pos = (*fa)->get_position() + offset;
break;
case ZLIB_FILEFUNC_SEEK_END:
- pos = zd->f->get_length() + offset;
+ pos = (*fa)->get_length() + offset;
break;
default:
break;
}
- zd->f->seek(pos);
+ (*fa)->seek(pos);
return 0;
}
int zipio_close(voidpf opaque, voidpf stream) {
- ZipIOData *zd = (ZipIOData *)opaque;
- memdelete(zd);
+ Ref<FileAccess> *fa = reinterpret_cast<Ref<FileAccess> *>(opaque);
+ ERR_FAIL_COND_V(fa == nullptr, 0);
+ ERR_FAIL_COND_V(fa->is_null(), 0);
+
+ fa->unref();
return 0;
}
int zipio_testerror(voidpf opaque, voidpf stream) {
- ZipIOData *zd = (ZipIOData *)opaque;
- return (zd->f.is_valid() && zd->f->get_error() != OK) ? 1 : 0;
+ Ref<FileAccess> *fa = reinterpret_cast<Ref<FileAccess> *>(opaque);
+ ERR_FAIL_COND_V(fa == nullptr, 1);
+ ERR_FAIL_COND_V(fa->is_null(), 0);
+
+ return (fa->is_valid() && (*fa)->get_error() != OK) ? 1 : 0;
}
voidpf zipio_alloc(voidpf opaque, uInt items, uInt size) {
@@ -105,9 +123,9 @@ void zipio_free(voidpf opaque, voidpf address) {
memfree(address);
}
-zlib_filefunc_def zipio_create_io() {
+zlib_filefunc_def zipio_create_io(Ref<FileAccess> *p_data) {
zlib_filefunc_def io;
- io.opaque = (void *)memnew(ZipIOData);
+ io.opaque = (void *)p_data;
io.zopen_file = zipio_open;
io.zread_file = zipio_read;
io.zwrite_file = zipio_write;
diff --git a/core/io/zip_io.h b/core/io/zip_io.h
index 3bcd1f830d..f137bd2bbf 100644
--- a/core/io/zip_io.h
+++ b/core/io/zip_io.h
@@ -39,10 +39,6 @@
#include "thirdparty/minizip/unzip.h"
#include "thirdparty/minizip/zip.h"
-struct ZipIOData {
- Ref<FileAccess> f;
-};
-
void *zipio_open(voidpf opaque, const char *p_fname, int mode);
uLong zipio_read(voidpf opaque, voidpf stream, void *buf, uLong size);
uLong zipio_write(voidpf opaque, voidpf stream, const void *buf, uLong size);
@@ -57,6 +53,6 @@ int zipio_testerror(voidpf opaque, voidpf stream);
voidpf zipio_alloc(voidpf opaque, uInt items, uInt size);
void zipio_free(voidpf opaque, voidpf address);
-zlib_filefunc_def zipio_create_io();
+zlib_filefunc_def zipio_create_io(Ref<FileAccess> *p_data);
#endif // ZIP_IO_H