summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/SCsub4
-rw-r--r--core/array.cpp4
-rw-r--r--core/array.h2
-rw-r--r--core/dictionary.cpp4
-rw-r--r--core/dictionary.h2
-rw-r--r--core/error_macros.h6
-rw-r--r--core/image.cpp12
-rw-r--r--core/io/compression.cpp6
-rw-r--r--core/io/file_access_buffered_fa.h8
-rw-r--r--core/io/file_access_compressed.cpp13
-rw-r--r--core/io/file_access_compressed.h2
-rw-r--r--core/io/file_access_encrypted.cpp10
-rw-r--r--core/io/file_access_encrypted.h2
-rw-r--r--core/io/file_access_memory.h2
-rw-r--r--core/io/file_access_network.cpp10
-rw-r--r--core/io/file_access_network.h2
-rw-r--r--core/io/file_access_pack.h2
-rw-r--r--core/io/file_access_zip.h2
-rw-r--r--core/io/multiplayer_api.cpp13
-rw-r--r--core/io/resource_importer.cpp11
-rw-r--r--core/io/resource_importer.h5
-rw-r--r--core/io/resource_loader.cpp24
-rw-r--r--core/io/resource_loader.h2
-rw-r--r--core/list.h4
-rw-r--r--core/make_binders.py12
-rw-r--r--core/math/camera_matrix.cpp8
-rw-r--r--core/math/camera_matrix.h1
-rw-r--r--core/math/delaunay.h4
-rw-r--r--core/math/geometry.cpp2
-rw-r--r--core/math/geometry.h10
-rw-r--r--core/math/math_funcs.h19
-rw-r--r--core/math/plane.cpp4
-rw-r--r--core/math/plane.h4
-rw-r--r--core/math/transform_2d.cpp2
-rw-r--r--core/math/transform_2d.h2
-rw-r--r--core/math/vector2.h9
-rw-r--r--core/math/vector3.h23
-rw-r--r--core/method_bind.h6
-rw-r--r--core/object.cpp10
-rw-r--r--core/object.h2
-rw-r--r--core/ordered_hash_map.h4
-rw-r--r--core/os/dir_access.cpp2
-rw-r--r--core/os/file_access.cpp23
-rw-r--r--core/os/file_access.h7
-rw-r--r--core/os/os.h4
-rw-r--r--core/reference.h19
-rw-r--r--core/string_builder.h4
-rw-r--r--core/translation.cpp15
-rw-r--r--core/translation.h2
-rw-r--r--core/type_info.h122
-rw-r--r--core/ustring.cpp25
-rw-r--r--core/ustring.h5
-rw-r--r--core/variant.cpp27
-rw-r--r--core/variant.h1
-rw-r--r--core/variant_call.cpp15
-rw-r--r--core/variant_parser.cpp3
56 files changed, 450 insertions, 98 deletions
diff --git a/core/SCsub b/core/SCsub
index 00d0bcac24..d5be74a64f 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -129,10 +129,10 @@ if env['builtin_zstd']:
thirdparty_zstd_sources = [thirdparty_zstd_dir + file for file in thirdparty_zstd_sources]
env_thirdparty.Append(CPPPATH=[thirdparty_zstd_dir, thirdparty_zstd_dir + "common"])
- env_thirdparty.Append(CCFLAGS="-DZSTD_STATIC_LINKING_ONLY")
+ env_thirdparty.Append(CPPFLAGS="-DZSTD_STATIC_LINKING_ONLY")
env.Append(CPPPATH=thirdparty_zstd_dir)
# Also needed in main env includes will trigger warnings
- env.Append(CCFLAGS="-DZSTD_STATIC_LINKING_ONLY")
+ env.Append(CPPFLAGS="-DZSTD_STATIC_LINKING_ONLY")
env_thirdparty.add_source_files(env.core_sources, thirdparty_zstd_sources)
diff --git a/core/array.cpp b/core/array.cpp
index 649e610a69..65934d6ec9 100644
--- a/core/array.cpp
+++ b/core/array.cpp
@@ -401,6 +401,10 @@ Variant Array::max() const {
return maxval;
}
+const void *Array::id() const {
+ return _p->array.ptr();
+}
+
Array::Array(const Array &p_from) {
_p = NULL;
diff --git a/core/array.h b/core/array.h
index 6158db4065..d4e937a486 100644
--- a/core/array.h
+++ b/core/array.h
@@ -94,6 +94,8 @@ public:
Variant min() const;
Variant max() const;
+ const void *id() const;
+
Array(const Array &p_from);
Array();
~Array();
diff --git a/core/dictionary.cpp b/core/dictionary.cpp
index bea0997cc9..5e4dfb9a5a 100644
--- a/core/dictionary.cpp
+++ b/core/dictionary.cpp
@@ -270,6 +270,10 @@ void Dictionary::operator=(const Dictionary &p_dictionary) {
_ref(p_dictionary);
}
+const void *Dictionary::id() const {
+ return _p->variant_map.id();
+}
+
Dictionary::Dictionary(const Dictionary &p_from) {
_p = NULL;
_ref(p_from);
diff --git a/core/dictionary.h b/core/dictionary.h
index eab7354cef..b68d3f5737 100644
--- a/core/dictionary.h
+++ b/core/dictionary.h
@@ -82,6 +82,8 @@ public:
Dictionary duplicate(bool p_deep = false) const;
+ const void *id() const;
+
Dictionary(const Dictionary &p_from);
Dictionary();
~Dictionary();
diff --git a/core/error_macros.h b/core/error_macros.h
index ca5ccd24cf..78e29551d4 100644
--- a/core/error_macros.h
+++ b/core/error_macros.h
@@ -86,7 +86,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
#define _FNL __FILE__ ":"
-/** An index has failed if m_index<0 or m_index >=m_size, the function exists */
+/** An index has failed if m_index<0 or m_index >=m_size, the function exits */
extern bool _err_error_exists;
@@ -140,7 +140,7 @@ extern bool _err_error_exists;
_err_error_exists = false; \
} while (0); // (*)
-/** An index has failed if m_index<0 or m_index >=m_size, the function exists.
+/** An index has failed if m_index<0 or m_index >=m_size, the function exits.
* This function returns an error value, if returning Error, please select the most
* appropriate error condition from error_macros.h
*/
@@ -154,7 +154,7 @@ extern bool _err_error_exists;
_err_error_exists = false; \
} while (0); // (*)
-/** An index has failed if m_index >=m_size, the function exists.
+/** An index has failed if m_index >=m_size, the function exits.
* This function returns an error value, if returning Error, please select the most
* appropriate error condition from error_macros.h
*/
diff --git a/core/image.cpp b/core/image.cpp
index 90afd9f35a..99d5eab864 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -1876,7 +1876,7 @@ Image::Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const P
Rect2 Image::get_used_rect() const {
- if (format != FORMAT_LA8 && format != FORMAT_RGBA8)
+ if (format != FORMAT_LA8 && format != FORMAT_RGBA8 && format != FORMAT_RGBAF && format != FORMAT_RGBAH && format != FORMAT_RGBA4444 && format != FORMAT_RGBA5551)
return Rect2(Point2(), Size2(width, height));
int len = data.size();
@@ -1884,17 +1884,13 @@ Rect2 Image::get_used_rect() const {
if (len == 0)
return Rect2();
- //int data_size = len;
- PoolVector<uint8_t>::Read r = data.read();
- const unsigned char *rptr = r.ptr();
-
- int ps = format == FORMAT_LA8 ? 2 : 4;
+ const_cast<Image *>(this)->lock();
int minx = 0xFFFFFF, miny = 0xFFFFFFF;
int maxx = -1, maxy = -1;
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
- bool opaque = rptr[(j * width + i) * ps + (ps - 1)] > 2;
+ bool opaque = get_pixel(i, j).a > 0.99;
if (!opaque)
continue;
if (i > maxx)
@@ -1908,6 +1904,8 @@ Rect2 Image::get_used_rect() const {
}
}
+ const_cast<Image *>(this)->unlock();
+
if (maxx == -1)
return Rect2();
else
diff --git a/core/io/compression.cpp b/core/io/compression.cpp
index a113f3b61b..b51e50150e 100644
--- a/core/io/compression.cpp
+++ b/core/io/compression.cpp
@@ -175,7 +175,9 @@ int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p
} break;
case MODE_ZSTD: {
ZSTD_DCtx *dctx = ZSTD_createDCtx();
- if (zstd_long_distance_matching) ZSTD_DCtx_setMaxWindowSize(dctx, (size_t)1 << zstd_window_log_size);
+ if (zstd_long_distance_matching) {
+ ZSTD_DCtx_setParameter(dctx, ZSTD_d_windowLogMax, zstd_window_log_size);
+ }
int ret = ZSTD_decompressDCtx(dctx, p_dst, p_dst_max_size, p_src, p_src_size);
ZSTD_freeDCtx(dctx);
return ret;
@@ -189,4 +191,4 @@ int Compression::zlib_level = Z_DEFAULT_COMPRESSION;
int Compression::gzip_level = Z_DEFAULT_COMPRESSION;
int Compression::zstd_level = 3;
bool Compression::zstd_long_distance_matching = false;
-int Compression::zstd_window_log_size = 27;
+int Compression::zstd_window_log_size = 27; // ZSTD_WINDOWLOG_LIMIT_DEFAULT
diff --git a/core/io/file_access_buffered_fa.h b/core/io/file_access_buffered_fa.h
index be960fbc25..24b40cbce8 100644
--- a/core/io/file_access_buffered_fa.h
+++ b/core/io/file_access_buffered_fa.h
@@ -143,6 +143,14 @@ public:
return f._get_modified_time(p_file);
}
+ virtual uint32_t _get_unix_permissions(const String &p_file) {
+ return f._get_unix_permissions(p_file);
+ }
+
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+ return f._set_unix_permissions(p_file, p_permissions);
+ }
+
FileAccessBufferedFA(){
};
diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp
index b268d5c710..6c4310a572 100644
--- a/core/io/file_access_compressed.cpp
+++ b/core/io/file_access_compressed.cpp
@@ -373,6 +373,19 @@ uint64_t FileAccessCompressed::_get_modified_time(const String &p_file) {
return 0;
}
+uint32_t FileAccessCompressed::_get_unix_permissions(const String &p_file) {
+ if (f)
+ return f->_get_unix_permissions(p_file);
+ return 0;
+}
+
+Error FileAccessCompressed::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+ if (f) {
+ return f->_set_unix_permissions(p_file, p_permissions);
+ }
+ return FAILED;
+}
+
FileAccessCompressed::FileAccessCompressed() :
cmode(Compression::MODE_ZSTD),
writing(false),
diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h
index f408b1bc29..773fed6a3a 100644
--- a/core/io/file_access_compressed.h
+++ b/core/io/file_access_compressed.h
@@ -91,6 +91,8 @@ public:
virtual bool file_exists(const String &p_name); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file);
+ virtual uint32_t _get_unix_permissions(const String &p_file);
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
FileAccessCompressed();
virtual ~FileAccessCompressed();
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp
index 6ad68dd74d..3cf6908961 100644
--- a/core/io/file_access_encrypted.cpp
+++ b/core/io/file_access_encrypted.cpp
@@ -301,6 +301,16 @@ uint64_t FileAccessEncrypted::_get_modified_time(const String &p_file) {
return 0;
}
+uint32_t FileAccessEncrypted::_get_unix_permissions(const String &p_file) {
+
+ return 0;
+}
+
+Error FileAccessEncrypted::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+
+ return FAILED;
+}
+
FileAccessEncrypted::FileAccessEncrypted() {
file = NULL;
diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h
index e77d62a9f4..d779a150ac 100644
--- a/core/io/file_access_encrypted.h
+++ b/core/io/file_access_encrypted.h
@@ -79,6 +79,8 @@ public:
virtual bool file_exists(const String &p_name); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file);
+ virtual uint32_t _get_unix_permissions(const String &p_file);
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
FileAccessEncrypted();
~FileAccessEncrypted();
diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h
index 73952133c1..4db7811aaa 100644
--- a/core/io/file_access_memory.h
+++ b/core/io/file_access_memory.h
@@ -70,6 +70,8 @@ public:
virtual bool file_exists(const String &p_name); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
+ virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
FileAccessMemory();
};
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp
index 501a21a50d..722e62c54e 100644
--- a/core/io/file_access_network.cpp
+++ b/core/io/file_access_network.cpp
@@ -497,6 +497,16 @@ uint64_t FileAccessNetwork::_get_modified_time(const String &p_file) {
return exists_modtime;
}
+uint32_t FileAccessNetwork::_get_unix_permissions(const String &p_file) {
+ //could be implemented, not sure if worth it
+ return 0;
+}
+
+Error FileAccessNetwork::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+
+ return FAILED;
+}
+
void FileAccessNetwork::configure() {
GLOBAL_DEF("network/remote_fs/page_size", 65536);
diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h
index 5bbf7588c7..073b75a37b 100644
--- a/core/io/file_access_network.h
+++ b/core/io/file_access_network.h
@@ -159,6 +159,8 @@ public:
virtual bool file_exists(const String &p_path); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file);
+ virtual uint32_t _get_unix_permissions(const String &p_file);
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
static void configure();
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index a90672ce26..a21dd7d22d 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -142,6 +142,8 @@ class FileAccessPack : public FileAccess {
FileAccess *f;
virtual Error _open(const String &p_path, int p_mode_flags);
virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
+ virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
public:
virtual void close();
diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h
index fc8f85c07b..217176c0af 100644
--- a/core/io/file_access_zip.h
+++ b/core/io/file_access_zip.h
@@ -112,6 +112,8 @@ public:
virtual bool file_exists(const String &p_name); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file) { return 0; } // todo
+ virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file);
~FileAccessZip();
diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp
index 86382939f1..2e76ce68ed 100644
--- a/core/io/multiplayer_api.cpp
+++ b/core/io/multiplayer_api.cpp
@@ -659,8 +659,11 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const
}
if (call_local_native) {
+ int temp_id = rpc_sender_id;
+ rpc_sender_id = get_network_unique_id();
Variant::CallError ce;
p_node->call(p_method, p_arg, p_argcount, ce);
+ rpc_sender_id = temp_id;
if (ce.error != Variant::CallError::CALL_OK) {
String error = Variant::get_call_error_text(p_node, p_method, p_arg, p_argcount, ce);
error = "rpc() aborted in local call: - " + error;
@@ -670,9 +673,12 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const
}
if (call_local_script) {
+ int temp_id = rpc_sender_id;
+ rpc_sender_id = get_network_unique_id();
Variant::CallError ce;
ce.error = Variant::CallError::CALL_OK;
p_node->get_script_instance()->call(p_method, p_arg, p_argcount, ce);
+ rpc_sender_id = temp_id;
if (ce.error != Variant::CallError::CALL_OK) {
String error = Variant::get_call_error_text(p_node, p_method, p_arg, p_argcount, ce);
error = "rpc() aborted in script local call: - " + error;
@@ -708,7 +714,11 @@ void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const
if (set_local) {
bool valid;
+ int temp_id = rpc_sender_id;
+
+ rpc_sender_id = get_network_unique_id();
p_node->set(p_property, p_value, &valid);
+ rpc_sender_id = temp_id;
if (!valid) {
String error = "rset() aborted in local set, property not found: - " + String(p_property);
@@ -722,8 +732,11 @@ void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const
set_local = _should_call_local(rpc_mode, is_master, skip_rset);
if (set_local) {
+ int temp_id = rpc_sender_id;
+ rpc_sender_id = get_network_unique_id();
bool valid = p_node->get_script_instance()->set(p_property, p_value);
+ rpc_sender_id = temp_id;
if (!valid) {
String error = "rset() aborted in local script set, property not found: - " + String(p_property);
diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp
index b5fa412576..038a34ed51 100644
--- a/core/io/resource_importer.cpp
+++ b/core/io/resource_importer.cpp
@@ -94,6 +94,8 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
r_path_and_type.type = value;
} else if (assign == "importer") {
r_path_and_type.importer = value;
+ } else if (assign == "group_file") {
+ r_path_and_type.group_file = value;
} else if (assign == "metadata") {
r_path_and_type.metadata = value;
} else if (assign == "valid") {
@@ -294,6 +296,15 @@ void ResourceFormatImporter::get_internal_resource_path_list(const String &p_pat
memdelete(f);
}
+String ResourceFormatImporter::get_import_group_file(const String &p_path) const {
+
+ bool valid = true;
+ PathAndType pat;
+ _get_path_and_type(p_path, pat, &valid);
+ return valid?pat.group_file:String();
+
+}
+
bool ResourceFormatImporter::is_import_valid(const String &p_path) const {
bool valid = true;
diff --git a/core/io/resource_importer.h b/core/io/resource_importer.h
index 1c146c33d7..bdbdde6df6 100644
--- a/core/io/resource_importer.h
+++ b/core/io/resource_importer.h
@@ -43,6 +43,7 @@ class ResourceFormatImporter : public ResourceFormatLoader {
String path;
String type;
String importer;
+ String group_file;
Variant metadata;
};
@@ -69,6 +70,7 @@ public:
virtual bool is_import_valid(const String &p_path) const;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
virtual bool is_imported(const String &p_path) const { return recognize_path(p_path); }
+ virtual String get_import_group_file(const String &p_path) const;
virtual bool exists(const String &p_path) const;
virtual bool can_be_imported(const String &p_path) const;
@@ -120,8 +122,11 @@ public:
virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const = 0;
virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const = 0;
+ virtual String get_option_group_file() const { return String(); }
virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = NULL, Variant *r_metadata = NULL) = 0;
+
+ virtual Error import_group_file(const String& p_group_file,const Map<String,Map<StringName, Variant> >&p_source_file_options, const Map<String,String>& p_base_paths) { return ERR_UNAVAILABLE; }
virtual bool are_import_settings_valid(const String &p_path) const { return true; }
virtual String get_import_settings_string() const { return String(); }
};
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index e4b694b64f..56d3b8b133 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -608,6 +608,30 @@ int ResourceLoader::get_import_order(const String &p_path) {
return 0;
}
+String ResourceLoader::get_import_group_file(const String &p_path) {
+ String path = _path_remap(p_path);
+
+ String local_path;
+ if (path.is_rel_path())
+ local_path = "res://" + path;
+ else
+ local_path = ProjectSettings::get_singleton()->localize_path(path);
+
+ for (int i = 0; i < loader_count; i++) {
+
+ if (!loader[i]->recognize_path(local_path))
+ continue;
+ /*
+ if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint))
+ continue;
+ */
+
+ return loader[i]->get_import_group_file(p_path);
+ }
+
+ return String(); //not found
+}
+
bool ResourceLoader::is_import_valid(const String &p_path) {
String path = _path_remap(p_path);
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index ca7610a0d2..9e7020be7c 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -81,6 +81,7 @@ public:
virtual bool is_import_valid(const String &p_path) const { return true; }
virtual bool is_imported(const String &p_path) const { return false; }
virtual int get_import_order(const String &p_path) const { return 0; }
+ virtual String get_import_group_file(const String &p_path) const { return ""; } //no group
virtual ~ResourceFormatLoader() {}
};
@@ -155,6 +156,7 @@ public:
static void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
static Error rename_dependencies(const String &p_path, const Map<String, String> &p_map);
static bool is_import_valid(const String &p_path);
+ static String get_import_group_file(const String &p_path);
static bool is_imported(const String &p_path);
static int get_import_order(const String &p_path);
diff --git a/core/list.h b/core/list.h
index c26aad6463..c21c20ba34 100644
--- a/core/list.h
+++ b/core/list.h
@@ -691,6 +691,10 @@ public:
memdelete_arr(aux_buffer);
}
+ const void *id() const {
+ return (void *)_data;
+ }
+
/**
* copy constructor for the list
*/
diff --git a/core/make_binders.py b/core/make_binders.py
index 4c61b90d99..5c1c66cab6 100644
--- a/core/make_binders.py
+++ b/core/make_binders.py
@@ -9,6 +9,12 @@ public:
$ifret R$ $ifnoret void$ (T::*method)($arg, P@$) $ifconst const$;
#ifdef DEBUG_METHODS_ENABLED
virtual Variant::Type _gen_argument_type(int p_arg) const { return _get_argument_type(p_arg); }
+ virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const {
+ $ifret if (p_arg==-1) return GetTypeInfo<R>::METADATA;$
+ $arg if (p_arg==(@-1)) return GetTypeInfo<P@>::METADATA;
+ $
+ return GodotTypeInfo::METADATA_NONE;
+ }
Variant::Type _get_argument_type(int p_argument) const {
$ifret if (p_argument==-1) return (Variant::Type)GetTypeInfo<R>::VARIANT_TYPE;$
$arg if (p_argument==(@-1)) return (Variant::Type)GetTypeInfo<P@>::VARIANT_TYPE;
@@ -94,6 +100,12 @@ public:
#ifdef DEBUG_METHODS_ENABLED
virtual Variant::Type _gen_argument_type(int p_arg) const { return _get_argument_type(p_arg); }
+ virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const {
+ $ifret if (p_arg==-1) return GetTypeInfo<R>::METADATA;$
+ $arg if (p_arg==(@-1)) return GetTypeInfo<P@>::METADATA;
+ $
+ return GodotTypeInfo::METADATA_NONE;
+ }
Variant::Type _get_argument_type(int p_argument) const {
$ifret if (p_argument==-1) return (Variant::Type)GetTypeInfo<R>::VARIANT_TYPE;$
diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp
index caf08c7379..f615cc8c65 100644
--- a/core/math/camera_matrix.cpp
+++ b/core/math/camera_matrix.cpp
@@ -210,6 +210,14 @@ void CameraMatrix::set_frustum(real_t p_left, real_t p_right, real_t p_bottom, r
te[15] = 0;
}
+void CameraMatrix::set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov) {
+ if (!p_flip_fov) {
+ p_size *= p_aspect;
+ }
+
+ set_frustum(-p_size / 2 + p_offset.x, +p_size / 2 + p_offset.x, -p_size / p_aspect / 2 + p_offset.y, +p_size / p_aspect / 2 + p_offset.y, p_near, p_far);
+}
+
real_t CameraMatrix::get_z_far() const {
const real_t *matrix = (const real_t *)this->matrix;
diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h
index 015588a8cb..3bcf48f5da 100644
--- a/core/math/camera_matrix.h
+++ b/core/math/camera_matrix.h
@@ -61,6 +61,7 @@ struct CameraMatrix {
void set_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar);
void set_orthogonal(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov = false);
void set_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far);
+ void set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov = false);
static real_t get_fovy(real_t p_fovx, real_t p_aspect) {
diff --git a/core/math/delaunay.h b/core/math/delaunay.h
index bd0cf97937..ed52c506db 100644
--- a/core/math/delaunay.h
+++ b/core/math/delaunay.h
@@ -80,11 +80,11 @@ public:
}
static bool edge_compare(const Vector<Vector2> &p_vertices, const Edge &p_a, const Edge &p_b) {
- if (p_vertices[p_a.edge[0]].distance_to(p_vertices[p_b.edge[0]]) < CMP_EPSILON && p_vertices[p_a.edge[1]].distance_to(p_vertices[p_b.edge[1]]) < CMP_EPSILON) {
+ if (Math::is_zero_approx(p_vertices[p_a.edge[0]].distance_to(p_vertices[p_b.edge[0]])) && Math::is_zero_approx(p_vertices[p_a.edge[1]].distance_to(p_vertices[p_b.edge[1]]))) {
return true;
}
- if (p_vertices[p_a.edge[0]].distance_to(p_vertices[p_b.edge[1]]) < CMP_EPSILON && p_vertices[p_a.edge[1]].distance_to(p_vertices[p_b.edge[0]]) < CMP_EPSILON) {
+ if (Math::is_zero_approx(p_vertices[p_a.edge[0]].distance_to(p_vertices[p_b.edge[1]])) && Math::is_zero_approx(p_vertices[p_a.edge[1]].distance_to(p_vertices[p_b.edge[0]]))) {
return true;
}
diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp
index a84b5a16c7..0ab8707d3a 100644
--- a/core/math/geometry.cpp
+++ b/core/math/geometry.cpp
@@ -836,7 +836,7 @@ Geometry::MeshData Geometry::build_convex_mesh(const PoolVector<Plane> &p_planes
Vector3 rel = edge1_A - edge0_A;
real_t den = clip.normal.dot(rel);
- if (Math::abs(den) < CMP_EPSILON)
+ if (Math::is_zero_approx(den))
continue; // point too short
real_t dist = -(clip.normal.dot(edge0_A) - clip.d) / den;
diff --git a/core/math/geometry.h b/core/math/geometry.h
index 7347cb742a..f3a671aa9a 100644
--- a/core/math/geometry.h
+++ b/core/math/geometry.h
@@ -181,8 +181,8 @@ public:
}
}
// finally do the division to get sc and tc
- sc = (Math::abs(sN) < CMP_EPSILON ? 0.0 : sN / sD);
- tc = (Math::abs(tN) < CMP_EPSILON ? 0.0 : tN / tD);
+ sc = (Math::is_zero_approx(sN) ? 0.0 : sN / sD);
+ tc = (Math::is_zero_approx(tN) ? 0.0 : tN / tD);
// get the difference of the two closest points
Vector3 dP = w + (sc * u) - (tc * v); // = S1(sc) - S2(tc)
@@ -195,7 +195,7 @@ public:
Vector3 e2 = p_v2 - p_v0;
Vector3 h = p_dir.cross(e2);
real_t a = e1.dot(h);
- if (a > -CMP_EPSILON && a < CMP_EPSILON) // parallel test
+ if (Math::is_zero_approx(a)) // parallel test
return false;
real_t f = 1.0 / a;
@@ -233,7 +233,7 @@ public:
Vector3 e2 = p_v2 - p_v0;
Vector3 h = rel.cross(e2);
real_t a = e1.dot(h);
- if (a > -CMP_EPSILON && a < CMP_EPSILON) // parallel test
+ if (Math::is_zero_approx(a)) // parallel test
return false;
real_t f = 1.0 / a;
@@ -535,7 +535,7 @@ public:
// see http://paulbourke.net/geometry/pointlineplane/
const real_t denom = p_dir_b.y * p_dir_a.x - p_dir_b.x * p_dir_a.y;
- if (Math::abs(denom) < CMP_EPSILON) { // parallel?
+ if (Math::is_zero_approx(denom)) { // parallel?
return false;
}
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index 0d209402dd..a75f2fb4ab 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -272,13 +272,20 @@ public:
return diff < epsilon;
}
- static _ALWAYS_INLINE_ bool is_equal_approx(real_t a, real_t b, real_t epsilon = CMP_EPSILON) {
- // TODO: Comparing floats for approximate-equality is non-trivial.
- // Using epsilon should cover the typical cases in Godot (where a == b is used to compare two reals), such as matrix and vector comparison operators.
- // A proper implementation in terms of ULPs should eventually replace the contents of this function.
- // See https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ for details.
+ static _ALWAYS_INLINE_ bool is_equal_approx(real_t a, real_t b) {
+ real_t tolerance = CMP_EPSILON * abs(a);
+ if (tolerance < CMP_EPSILON) {
+ tolerance = CMP_EPSILON;
+ }
+ return abs(a - b) < tolerance;
+ }
+
+ static _ALWAYS_INLINE_ bool is_equal_approx(real_t a, real_t b, real_t tolerance) {
+ return abs(a - b) < tolerance;
+ }
- return abs(a - b) < epsilon;
+ static _ALWAYS_INLINE_ bool is_zero_approx(real_t s) {
+ return abs(s) < CMP_EPSILON;
}
static _ALWAYS_INLINE_ float absf(float g) {
diff --git a/core/math/plane.cpp b/core/math/plane.cpp
index cd3cbce300..b01853c4ac 100644
--- a/core/math/plane.cpp
+++ b/core/math/plane.cpp
@@ -110,7 +110,7 @@ bool Plane::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3
real_t den = normal.dot(segment);
//printf("den is %i\n",den);
- if (Math::abs(den) <= CMP_EPSILON) {
+ if (Math::is_zero_approx(den)) {
return false;
}
@@ -135,7 +135,7 @@ bool Plane::intersects_segment(const Vector3 &p_begin, const Vector3 &p_end, Vec
real_t den = normal.dot(segment);
//printf("den is %i\n",den);
- if (Math::abs(den) <= CMP_EPSILON) {
+ if (Math::is_zero_approx(den)) {
return false;
}
diff --git a/core/math/plane.h b/core/math/plane.h
index 1c6e4b816b..ec817edd2c 100644
--- a/core/math/plane.h
+++ b/core/math/plane.h
@@ -125,12 +125,12 @@ Plane::Plane(const Vector3 &p_point1, const Vector3 &p_point2, const Vector3 &p_
bool Plane::operator==(const Plane &p_plane) const {
- return normal == p_plane.normal && d == p_plane.d;
+ return normal == p_plane.normal && Math::is_equal_approx(d, p_plane.d);
}
bool Plane::operator!=(const Plane &p_plane) const {
- return normal != p_plane.normal || d != p_plane.d;
+ return normal != p_plane.normal || !Math::is_equal_approx(d, p_plane.d);
}
#endif // PLANE_H
diff --git a/core/math/transform_2d.cpp b/core/math/transform_2d.cpp
index 7d00158f3d..1d0387bd45 100644
--- a/core/math/transform_2d.cpp
+++ b/core/math/transform_2d.cpp
@@ -106,7 +106,7 @@ Size2 Transform2D::get_scale() const {
return Size2(elements[0].length(), det_sign * elements[1].length());
}
-void Transform2D::set_scale(Size2 &p_scale) {
+void Transform2D::set_scale(const Size2 &p_scale) {
elements[0].normalize();
elements[1].normalize();
elements[0] *= p_scale.x;
diff --git a/core/math/transform_2d.h b/core/math/transform_2d.h
index b9e7a36fb3..c44678674a 100644
--- a/core/math/transform_2d.h
+++ b/core/math/transform_2d.h
@@ -81,7 +81,7 @@ struct Transform2D {
real_t basis_determinant() const;
Size2 get_scale() const;
- void set_scale(Size2 &p_scale);
+ void set_scale(const Size2 &p_scale);
_FORCE_INLINE_ const Vector2 &get_origin() const { return elements[2]; }
_FORCE_INLINE_ void set_origin(const Vector2 &p_origin) { elements[2] = p_origin; }
diff --git a/core/math/vector2.h b/core/math/vector2.h
index ae2d1ec660..a0c6024c9f 100644
--- a/core/math/vector2.h
+++ b/core/math/vector2.h
@@ -99,14 +99,15 @@ struct Vector2 {
Vector2 operator/(const real_t &rvalue) const;
void operator/=(const real_t &rvalue);
+ void operator/=(const Vector2 &rvalue) { *this = *this / rvalue; }
Vector2 operator-() const;
bool operator==(const Vector2 &p_vec2) const;
bool operator!=(const Vector2 &p_vec2) const;
- bool operator<(const Vector2 &p_vec2) const { return (x == p_vec2.x) ? (y < p_vec2.y) : (x < p_vec2.x); }
- bool operator<=(const Vector2 &p_vec2) const { return (x == p_vec2.x) ? (y <= p_vec2.y) : (x <= p_vec2.x); }
+ bool operator<(const Vector2 &p_vec2) const { return (Math::is_equal_approx(x, p_vec2.x)) ? (y < p_vec2.y) : (x < p_vec2.x); }
+ bool operator<=(const Vector2 &p_vec2) const { return (Math::is_equal_approx(x, p_vec2.x)) ? (y <= p_vec2.y) : (x < p_vec2.x); }
real_t angle() const;
@@ -212,11 +213,11 @@ _FORCE_INLINE_ Vector2 Vector2::operator-() const {
_FORCE_INLINE_ bool Vector2::operator==(const Vector2 &p_vec2) const {
- return x == p_vec2.x && y == p_vec2.y;
+ return Math::is_equal_approx(x, p_vec2.x) && Math::is_equal_approx(y, p_vec2.y);
}
_FORCE_INLINE_ bool Vector2::operator!=(const Vector2 &p_vec2) const {
- return x != p_vec2.x || y != p_vec2.y;
+ return !Math::is_equal_approx(x, p_vec2.x) || !Math::is_equal_approx(y, p_vec2.y);
}
Vector2 Vector2::linear_interpolate(const Vector2 &p_b, real_t p_t) const {
diff --git a/core/math/vector3.h b/core/math/vector3.h
index e9074c5bd4..21fc09653f 100644
--- a/core/math/vector3.h
+++ b/core/math/vector3.h
@@ -341,17 +341,17 @@ Vector3 Vector3::operator-() const {
bool Vector3::operator==(const Vector3 &p_v) const {
- return (x == p_v.x && y == p_v.y && z == p_v.z);
+ return (Math::is_equal_approx(x, p_v.x) && Math::is_equal_approx(y, p_v.y) && Math::is_equal_approx(z, p_v.z));
}
bool Vector3::operator!=(const Vector3 &p_v) const {
- return (x != p_v.x || y != p_v.y || z != p_v.z);
+ return (!Math::is_equal_approx(x, p_v.x) || !Math::is_equal_approx(y, p_v.y) || !Math::is_equal_approx(z, p_v.z));
}
bool Vector3::operator<(const Vector3 &p_v) const {
- if (x == p_v.x) {
- if (y == p_v.y)
+ if (Math::is_equal_approx(x, p_v.x)) {
+ if (Math::is_equal_approx(y, p_v.y))
return z < p_v.z;
else
return y < p_v.y;
@@ -362,8 +362,8 @@ bool Vector3::operator<(const Vector3 &p_v) const {
bool Vector3::operator<=(const Vector3 &p_v) const {
- if (x == p_v.x) {
- if (y == p_v.y)
+ if (Math::is_equal_approx(x, p_v.x)) {
+ if (Math::is_equal_approx(y, p_v.y))
return z <= p_v.z;
else
return y < p_v.y;
@@ -402,13 +402,14 @@ real_t Vector3::length_squared() const {
void Vector3::normalize() {
- real_t l = length();
- if (l == 0) {
+ real_t lengthsq = length_squared();
+ if (lengthsq == 0) {
x = y = z = 0;
} else {
- x /= l;
- y /= l;
- z /= l;
+ real_t length = Math::sqrt(lengthsq);
+ x /= length;
+ y /= length;
+ z /= length;
}
}
diff --git a/core/method_bind.h b/core/method_bind.h
index 5ea8adb7e0..1b0c3b27c0 100644
--- a/core/method_bind.h
+++ b/core/method_bind.h
@@ -273,6 +273,8 @@ public:
void set_argument_names(const Vector<StringName> &p_names); //set by class, db, can't be inferred otherwise
Vector<StringName> get_argument_names() const;
+ virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const = 0;
+
#endif
void set_hint_flags(uint32_t p_hint) { hint_flags = p_hint; }
uint32_t get_hint_flags() const { return hint_flags | (is_const() ? METHOD_FLAG_CONST : 0) | (is_vararg() ? METHOD_FLAG_VARARG : 0); }
@@ -329,6 +331,10 @@ public:
return _gen_argument_type_info(p_arg).type;
}
+ virtual GodotTypeInfo::Metadata get_argument_meta(int) const {
+ return GodotTypeInfo::METADATA_NONE;
+ }
+
#else
virtual Variant::Type _gen_argument_type(int p_arg) const {
diff --git a/core/object.cpp b/core/object.cpp
index 03a11b8ca3..f860423a27 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -1059,6 +1059,10 @@ Variant Object::get_meta(const String &p_name) const {
return metadata[p_name];
}
+void Object::remove_meta(const String &p_name) {
+ metadata.erase(p_name);
+}
+
Array Object::_get_property_list_bind() const {
List<PropertyInfo> lpi;
@@ -1366,7 +1370,10 @@ Array Object::_get_incoming_connections() const {
void Object::get_signal_list(List<MethodInfo> *p_signals) const {
if (!script.is_null()) {
- Ref<Script>(script)->get_script_signal_list(p_signals);
+ Ref<Script> scr = script;
+ if (scr.is_valid()) {
+ scr->get_script_signal_list(p_signals);
+ }
}
ClassDB::get_signal_list(get_class_name(), p_signals);
@@ -1688,6 +1695,7 @@ void Object::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_script"), &Object::get_script);
ClassDB::bind_method(D_METHOD("set_meta", "name", "value"), &Object::set_meta);
+ ClassDB::bind_method(D_METHOD("remove_meta", "name"), &Object::remove_meta);
ClassDB::bind_method(D_METHOD("get_meta", "name"), &Object::get_meta);
ClassDB::bind_method(D_METHOD("has_meta", "name"), &Object::has_meta);
ClassDB::bind_method(D_METHOD("get_meta_list"), &Object::_get_meta_list_bind);
diff --git a/core/object.h b/core/object.h
index e8a6178052..94abaacdcc 100644
--- a/core/object.h
+++ b/core/object.h
@@ -88,6 +88,7 @@ enum PropertyHint {
PROPERTY_HINT_PROPERTY_OF_SCRIPT, ///< a property of a script & base
PROPERTY_HINT_OBJECT_TOO_BIG, ///< object is too big to send
PROPERTY_HINT_NODE_PATH_VALID_TYPES,
+ PROPERTY_HINT_SAVE_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,". This opens a save dialog
PROPERTY_HINT_MAX,
// When updating PropertyHint, also sync the hardcoded list in VisualScriptEditorVariableEdit
};
@@ -672,6 +673,7 @@ public:
bool has_meta(const String &p_name) const;
void set_meta(const String &p_name, const Variant &p_value);
+ void remove_meta(const String &p_name);
Variant get_meta(const String &p_name) const;
void get_meta_list(List<String> *p_list) const;
diff --git a/core/ordered_hash_map.h b/core/ordered_hash_map.h
index 09d43d6797..2c18de92be 100644
--- a/core/ordered_hash_map.h
+++ b/core/ordered_hash_map.h
@@ -274,6 +274,10 @@ public:
inline bool empty() const { return list.empty(); }
inline int size() const { return list.size(); }
+ const void *id() const {
+ return list.id();
+ }
+
void clear() {
map.clear();
list.clear();
diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp
index 2c1c655175..d81c30f33a 100644
--- a/core/os/dir_access.cpp
+++ b/core/os/dir_access.cpp
@@ -330,7 +330,7 @@ Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) {
if (err == OK && p_chmod_flags != -1) {
fdst->close();
- err = fdst->_chmod(p_to, p_chmod_flags);
+ err = FileAccess::set_unix_permissions(p_to, p_chmod_flags);
// If running on a platform with no chmod support (i.e., Windows), don't fail
if (err == ERR_UNAVAILABLE)
err = OK;
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
index 4be1364278..079f51bada 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -507,6 +507,29 @@ uint64_t FileAccess::get_modified_time(const String &p_file) {
return mt;
}
+uint32_t FileAccess::get_unix_permissions(const String &p_file) {
+
+ if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_file))
+ return 0;
+
+ FileAccess *fa = create_for_path(p_file);
+ ERR_FAIL_COND_V(!fa, 0);
+
+ uint32_t mt = fa->_get_unix_permissions(p_file);
+ memdelete(fa);
+ return mt;
+}
+
+Error FileAccess::set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+
+ FileAccess *fa = create_for_path(p_file);
+ ERR_FAIL_COND_V(!fa, ERR_CANT_CREATE);
+
+ Error err = fa->_set_unix_permissions(p_file, p_permissions);
+ memdelete(fa);
+ return err;
+}
+
void FileAccess::store_string(const String &p_string) {
if (p_string.length() == 0)
diff --git a/core/os/file_access.h b/core/os/file_access.h
index 9df2a5cade..4930eae35a 100644
--- a/core/os/file_access.h
+++ b/core/os/file_access.h
@@ -56,6 +56,9 @@ public:
bool endian_swap;
bool real_is_double;
+ virtual uint32_t _get_unix_permissions(const String &p_file) = 0;
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) = 0;
+
protected:
String fix_path(const String &p_path) const;
virtual Error _open(const String &p_path, int p_mode_flags) = 0; ///< open a file
@@ -148,14 +151,14 @@ public:
virtual Error reopen(const String &p_path, int p_mode_flags); ///< does not change the AccessType
- virtual Error _chmod(const String &p_path, int p_mod) { return ERR_UNAVAILABLE; }
-
static FileAccess *create(AccessType p_access); /// Create a file access (for the current platform) this is the only portable way of accessing files.
static FileAccess *create_for_path(const String &p_path);
static FileAccess *open(const String &p_path, int p_mode_flags, Error *r_error = NULL); /// Create a file access (for the current platform) this is the only portable way of accessing files.
static CreateFunc get_create_func(AccessType p_access);
static bool exists(const String &p_name); ///< return true if a file exists
static uint64_t get_modified_time(const String &p_file);
+ static uint32_t get_unix_permissions(const String &p_file);
+ static Error set_unix_permissions(const String &p_file, uint32_t p_permissions);
static void set_backup_save(bool p_enable) { backup_save = p_enable; };
static bool is_backup_save_enabled() { return backup_save; };
diff --git a/core/os/os.h b/core/os/os.h
index 12012fba80..4ae8a354e5 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -45,6 +45,8 @@
@author Juan Linietsky <reduzio@gmail.com>
*/
+class Mutex;
+
class OS {
static OS *singleton;
@@ -260,7 +262,7 @@ public:
virtual int get_low_processor_usage_mode_sleep_usec() const;
virtual String get_executable_path() const;
- virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false) = 0;
+ virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false, Mutex *p_pipe_mutex = NULL) = 0;
virtual Error kill(const ProcessID &p_pid) = 0;
virtual int get_process_id() const;
diff --git a/core/reference.h b/core/reference.h
index f3fcc922c7..8a19f846c7 100644
--- a/core/reference.h
+++ b/core/reference.h
@@ -197,6 +197,19 @@ public:
r.reference = NULL;
}
+ template <class T_Other>
+ void reference_ptr(T_Other *p_ptr) {
+ if (reference == p_ptr) {
+ return;
+ }
+ unref();
+
+ T *r = Object::cast_to<T>(p_ptr);
+ if (r) {
+ ref_pointer(r);
+ }
+ }
+
Ref(const Ref &p_from) {
reference = NULL;
@@ -362,7 +375,8 @@ struct PtrToArg<const RefPtr &> {
template <class T>
struct GetTypeInfo<Ref<T> > {
- enum { VARIANT_TYPE = Variant::OBJECT };
+ static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
+ static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
static inline PropertyInfo get_class_info() {
return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static());
@@ -371,7 +385,8 @@ struct GetTypeInfo<Ref<T> > {
template <class T>
struct GetTypeInfo<const Ref<T> &> {
- enum { VARIANT_TYPE = Variant::OBJECT };
+ static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
+ static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
static inline PropertyInfo get_class_info() {
return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static());
diff --git a/core/string_builder.h b/core/string_builder.h
index 40d70e8f45..0c4985d230 100644
--- a/core/string_builder.h
+++ b/core/string_builder.h
@@ -70,6 +70,10 @@ public:
return appended_strings.size();
}
+ _FORCE_INLINE_ uint32_t get_string_length() const {
+ return string_length;
+ }
+
String as_string() const;
_FORCE_INLINE_ operator String() const {
diff --git a/core/translation.cpp b/core/translation.cpp
index 6921f1d9f1..afbc639eaa 100644
--- a/core/translation.cpp
+++ b/core/translation.cpp
@@ -968,6 +968,19 @@ String TranslationServer::get_locale_name(const String &p_locale) const {
return locale_name_map[p_locale];
}
+Array TranslationServer::get_loaded_locales() const {
+ Array locales;
+ for (const Set<Ref<Translation> >::Element *E = translations.front(); E; E = E->next()) {
+
+ const Ref<Translation> &t = E->get();
+ String l = t->get_locale();
+
+ locales.push_back(l);
+ }
+
+ return locales;
+}
+
Vector<String> TranslationServer::get_all_locales() {
Vector<String> locales;
@@ -1168,6 +1181,8 @@ void TranslationServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("remove_translation", "translation"), &TranslationServer::remove_translation);
ClassDB::bind_method(D_METHOD("clear"), &TranslationServer::clear);
+
+ ClassDB::bind_method(D_METHOD("get_loaded_locales"), &TranslationServer::get_loaded_locales);
}
void TranslationServer::load_translations() {
diff --git a/core/translation.h b/core/translation.h
index b12bad0d72..d172b9ecf2 100644
--- a/core/translation.h
+++ b/core/translation.h
@@ -94,6 +94,8 @@ public:
String get_locale_name(const String &p_locale) const;
+ Array get_loaded_locales() const;
+
void add_translation(const Ref<Translation> &p_translation);
void remove_translation(const Ref<Translation> &p_translation);
diff --git a/core/type_info.h b/core/type_info.h
index c38688fea1..d85a63ee42 100644
--- a/core/type_info.h
+++ b/core/type_info.h
@@ -67,43 +67,80 @@ struct TypeInherits {
!TypesAreSame<B volatile const, void volatile const>::value;
};
+namespace GodotTypeInfo {
+enum Metadata {
+ METADATA_NONE,
+ METADATA_INT_IS_INT8,
+ METADATA_INT_IS_INT16,
+ METADATA_INT_IS_INT32,
+ METADATA_INT_IS_INT64,
+ METADATA_INT_IS_UINT8,
+ METADATA_INT_IS_UINT16,
+ METADATA_INT_IS_UINT32,
+ METADATA_INT_IS_UINT64,
+ METADATA_REAL_IS_FLOAT,
+ METADATA_REAL_IS_DOUBLE
+};
+}
+
template <class T, typename = void>
struct GetTypeInfo {
static const Variant::Type VARIANT_TYPE = Variant::NIL;
+ static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
static inline PropertyInfo get_class_info() {
ERR_PRINT("GetTypeInfo fallback. Bug!");
return PropertyInfo(); // Not "Nil", this is an error
}
};
-#define MAKE_TYPE_INFO(m_type, m_var_type) \
- template <> \
- struct GetTypeInfo<m_type> { \
- static const Variant::Type VARIANT_TYPE = m_var_type; \
- static inline PropertyInfo get_class_info() { \
- return PropertyInfo(VARIANT_TYPE, String()); \
- } \
- }; \
- template <> \
- struct GetTypeInfo<const m_type &> { \
- static const Variant::Type VARIANT_TYPE = m_var_type; \
- static inline PropertyInfo get_class_info() { \
- return PropertyInfo(VARIANT_TYPE, String()); \
- } \
+#define MAKE_TYPE_INFO(m_type, m_var_type) \
+ template <> \
+ struct GetTypeInfo<m_type> { \
+ static const Variant::Type VARIANT_TYPE = m_var_type; \
+ static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
+ static inline PropertyInfo get_class_info() { \
+ return PropertyInfo(VARIANT_TYPE, String()); \
+ } \
+ }; \
+ template <> \
+ struct GetTypeInfo<const m_type &> { \
+ static const Variant::Type VARIANT_TYPE = m_var_type; \
+ static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
+ static inline PropertyInfo get_class_info() { \
+ return PropertyInfo(VARIANT_TYPE, String()); \
+ } \
+ };
+
+#define MAKE_TYPE_INFO_WITH_META(m_type, m_var_type, m_metadata) \
+ template <> \
+ struct GetTypeInfo<m_type> { \
+ static const Variant::Type VARIANT_TYPE = m_var_type; \
+ static const GodotTypeInfo::Metadata METADATA = m_metadata; \
+ static inline PropertyInfo get_class_info() { \
+ return PropertyInfo(VARIANT_TYPE, String()); \
+ } \
+ }; \
+ template <> \
+ struct GetTypeInfo<const m_type &> { \
+ static const Variant::Type VARIANT_TYPE = m_var_type; \
+ static const GodotTypeInfo::Metadata METADATA = m_metadata; \
+ static inline PropertyInfo get_class_info() { \
+ return PropertyInfo(VARIANT_TYPE, String()); \
+ } \
};
MAKE_TYPE_INFO(bool, Variant::BOOL)
-MAKE_TYPE_INFO(uint8_t, Variant::INT)
-MAKE_TYPE_INFO(int8_t, Variant::INT)
-MAKE_TYPE_INFO(uint16_t, Variant::INT)
-MAKE_TYPE_INFO(int16_t, Variant::INT)
-MAKE_TYPE_INFO(uint32_t, Variant::INT)
-MAKE_TYPE_INFO(int32_t, Variant::INT)
-MAKE_TYPE_INFO(int64_t, Variant::INT)
-MAKE_TYPE_INFO(uint64_t, Variant::INT)
+MAKE_TYPE_INFO_WITH_META(uint8_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_UINT8)
+MAKE_TYPE_INFO_WITH_META(int8_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_INT8)
+MAKE_TYPE_INFO_WITH_META(uint16_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_UINT16)
+MAKE_TYPE_INFO_WITH_META(int16_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_INT16)
+MAKE_TYPE_INFO_WITH_META(uint32_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_UINT32)
+MAKE_TYPE_INFO_WITH_META(int32_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_INT32)
+MAKE_TYPE_INFO_WITH_META(uint64_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_UINT64)
+MAKE_TYPE_INFO_WITH_META(int64_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_INT64)
MAKE_TYPE_INFO(wchar_t, Variant::INT)
-MAKE_TYPE_INFO(float, Variant::REAL)
-MAKE_TYPE_INFO(double, Variant::REAL)
+MAKE_TYPE_INFO_WITH_META(float, Variant::REAL, GodotTypeInfo::METADATA_REAL_IS_FLOAT)
+MAKE_TYPE_INFO_WITH_META(double, Variant::REAL, GodotTypeInfo::METADATA_REAL_IS_DOUBLE)
MAKE_TYPE_INFO(String, Variant::STRING)
MAKE_TYPE_INFO(Vector2, Variant::VECTOR2)
@@ -138,6 +175,7 @@ MAKE_TYPE_INFO(BSP_Tree, Variant::DICTIONARY)
template <>
struct GetTypeInfo<RefPtr> {
static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
+ static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
static inline PropertyInfo get_class_info() {
return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, "Reference");
}
@@ -145,6 +183,7 @@ struct GetTypeInfo<RefPtr> {
template <>
struct GetTypeInfo<const RefPtr &> {
static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
+ static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
static inline PropertyInfo get_class_info() {
return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, "Reference");
}
@@ -154,6 +193,7 @@ struct GetTypeInfo<const RefPtr &> {
template <>
struct GetTypeInfo<Variant> {
static const Variant::Type VARIANT_TYPE = Variant::NIL;
+ static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
static inline PropertyInfo get_class_info() {
return PropertyInfo(Variant::NIL, String(), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
}
@@ -162,25 +202,28 @@ struct GetTypeInfo<Variant> {
template <>
struct GetTypeInfo<const Variant &> {
static const Variant::Type VARIANT_TYPE = Variant::NIL;
+ static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
static inline PropertyInfo get_class_info() {
return PropertyInfo(Variant::NIL, String(), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
}
};
-#define MAKE_TEMPLATE_TYPE_INFO(m_template, m_type, m_var_type) \
- template <> \
- struct GetTypeInfo<m_template<m_type> > { \
- static const Variant::Type VARIANT_TYPE = m_var_type; \
- static inline PropertyInfo get_class_info() { \
- return PropertyInfo(VARIANT_TYPE, String()); \
- } \
- }; \
- template <> \
- struct GetTypeInfo<const m_template<m_type> &> { \
- static const Variant::Type VARIANT_TYPE = m_var_type; \
- static inline PropertyInfo get_class_info() { \
- return PropertyInfo(VARIANT_TYPE, String()); \
- } \
+#define MAKE_TEMPLATE_TYPE_INFO(m_template, m_type, m_var_type) \
+ template <> \
+ struct GetTypeInfo<m_template<m_type> > { \
+ static const Variant::Type VARIANT_TYPE = m_var_type; \
+ static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
+ static inline PropertyInfo get_class_info() { \
+ return PropertyInfo(VARIANT_TYPE, String()); \
+ } \
+ }; \
+ template <> \
+ struct GetTypeInfo<const m_template<m_type> &> { \
+ static const Variant::Type VARIANT_TYPE = m_var_type; \
+ static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
+ static inline PropertyInfo get_class_info() { \
+ return PropertyInfo(VARIANT_TYPE, String()); \
+ } \
};
MAKE_TEMPLATE_TYPE_INFO(Vector, uint8_t, Variant::POOL_BYTE_ARRAY)
@@ -202,6 +245,7 @@ MAKE_TEMPLATE_TYPE_INFO(PoolVector, Face3, Variant::POOL_VECTOR3_ARRAY)
template <typename T>
struct GetTypeInfo<T *, typename EnableIf<TypeInherits<Object, T>::value>::type> {
static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
+ static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
static inline PropertyInfo get_class_info() {
return PropertyInfo(StringName(T::get_class_static()));
}
@@ -210,6 +254,7 @@ struct GetTypeInfo<T *, typename EnableIf<TypeInherits<Object, T>::value>::type>
template <typename T>
struct GetTypeInfo<const T *, typename EnableIf<TypeInherits<Object, T>::value>::type> {
static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
+ static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
static inline PropertyInfo get_class_info() {
return PropertyInfo(StringName(T::get_class_static()));
}
@@ -219,6 +264,7 @@ struct GetTypeInfo<const T *, typename EnableIf<TypeInherits<Object, T>::value>:
template <> \
struct GetTypeInfo<m_impl> { \
static const Variant::Type VARIANT_TYPE = Variant::INT; \
+ static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_ENUM, String(#m_enum).replace("::", ".")); \
} \
diff --git a/core/ustring.cpp b/core/ustring.cpp
index d60bd16921..78feddb229 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -123,6 +123,31 @@ const char *CharString::get_data() const {
return "";
}
+CharString &CharString::operator=(const char *p_cstr) {
+
+ copy_from(p_cstr);
+ return *this;
+}
+
+void CharString::copy_from(const char *p_cstr) {
+
+ if (!p_cstr) {
+ resize(0);
+ return;
+ }
+
+ size_t len = strlen(p_cstr);
+
+ if (len == 0) {
+ resize(0);
+ return;
+ }
+
+ resize(len + 1); // include terminating null char
+
+ strcpy(ptrw(), p_cstr);
+}
+
void String::copy_from(const char *p_cstr) {
if (!p_cstr) {
diff --git a/core/ustring.h b/core/ustring.h
index 85103057df..e2e62874d6 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -101,12 +101,17 @@ public:
_cowdata._ref(p_str._cowdata);
return *this;
}
+ _FORCE_INLINE_ CharString(const char *p_cstr) { copy_from(p_cstr); }
+ CharString &operator=(const char *p_cstr);
bool operator<(const CharString &p_right) const;
CharString &operator+=(char p_char);
int length() const { return size() ? size() - 1 : 0; }
const char *get_data() const;
operator const char *() const { return get_data(); };
+
+protected:
+ void copy_from(const char *p_cstr);
};
typedef wchar_t CharType;
diff --git a/core/variant.cpp b/core/variant.cpp
index 6c54faf233..1bc3cff505 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -1415,7 +1415,12 @@ struct _VariantStrPair {
};
Variant::operator String() const {
+ List<const void *> stack;
+ return stringify(stack);
+}
+
+String Variant::stringify(List<const void *> &stack) const {
switch (type) {
case NIL: return "Null";
@@ -1467,6 +1472,12 @@ Variant::operator String() const {
case DICTIONARY: {
const Dictionary &d = *reinterpret_cast<const Dictionary *>(_data._mem);
+ if (stack.find(d.id())) {
+ return "{...}";
+ }
+
+ stack.push_back(d.id());
+
//const String *K=NULL;
String str("{");
List<Variant> keys;
@@ -1477,8 +1488,9 @@ Variant::operator String() const {
for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
_VariantStrPair sp;
- sp.key = String(E->get());
- sp.value = d[E->get()];
+ sp.key = E->get().stringify(stack);
+ sp.value = d[E->get()].stringify(stack);
+
pairs.push_back(sp);
}
@@ -1561,12 +1573,19 @@ Variant::operator String() const {
case ARRAY: {
Array arr = operator Array();
+ if (stack.find(arr.id())) {
+ return "[...]";
+ }
+ stack.push_back(arr.id());
+
String str("[");
for (int i = 0; i < arr.size(); i++) {
if (i)
str += ", ";
- str += String(arr[i]);
- };
+
+ str += arr[i].stringify(stack);
+ }
+
str += "]";
return str;
diff --git a/core/variant.h b/core/variant.h
index 9215d15bf0..5151262f27 100644
--- a/core/variant.h
+++ b/core/variant.h
@@ -401,6 +401,7 @@ public:
bool hash_compare(const Variant &p_variant) const;
bool booleanize() const;
+ String stringify(List<const void *> &stack) const;
void static_assign(const Variant &p_variant);
static void get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_list);
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 143b07418e..f9f73b4e51 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -36,6 +36,7 @@
#include "core/object.h"
#include "core/os/os.h"
#include "core/script_language.h"
+#include "thirdparty/misc/sha256.h"
typedef void (*VariantFunc)(Variant &r_ret, Variant &p_self, const Variant **p_args);
typedef void (*VariantConstructFunc)(Variant &r_ret, const Variant **p_args);
@@ -587,6 +588,19 @@ struct _VariantCall {
r_ret = decompressed;
}
+ static void _call_PoolByteArray_sha256_string(Variant &r_ret, Variant &p_self, const Variant **p_args) {
+ PoolByteArray *ba = reinterpret_cast<PoolByteArray *>(p_self._data._mem);
+ PoolByteArray::Read r = ba->read();
+ String s;
+ unsigned char hash[32];
+ sha256_context sha256;
+ sha256_init(&sha256);
+ sha256_hash(&sha256, (unsigned char *)r.ptr(), ba->size());
+ sha256_done(&sha256, hash);
+ s = String::hex_encode_buffer(hash, 32);
+ r_ret = s;
+ }
+
VCALL_LOCALMEM0R(PoolByteArray, size);
VCALL_LOCALMEM2(PoolByteArray, set);
VCALL_LOCALMEM1R(PoolByteArray, get);
@@ -1733,6 +1747,7 @@ void register_variant_methods() {
ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_ascii, varray());
ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_utf8, varray());
+ ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, sha256_string, varray());
ADDFUNC1R(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, compress, INT, "compression_mode", varray(0));
ADDFUNC2R(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, decompress, INT, "buffer_size", INT, "compression_mode", varray(0));
diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp
index 6377197282..d7371b0434 100644
--- a/core/variant_parser.cpp
+++ b/core/variant_parser.cpp
@@ -1542,6 +1542,9 @@ Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r
} else if (c != '=') {
what += String::chr(c);
} else {
+ if (p_stream->is_utf8()) {
+ what.parse_utf8(what.ascii(true).get_data());
+ }
r_assign = what;
Token token;
get_token(p_stream, token, line, r_err_str);