summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/bind/core_bind.cpp26
-rw-r--r--core/bind/core_bind.h5
-rw-r--r--core/class_db.cpp39
-rw-r--r--core/class_db.h4
-rw-r--r--core/dictionary.cpp9
-rw-r--r--core/dictionary.h1
-rw-r--r--core/global_constants.cpp5
-rw-r--r--core/image.cpp21
-rw-r--r--core/image.h1
-rw-r--r--core/io/file_access_pack.cpp2
-rw-r--r--core/io/image_loader.cpp37
-rw-r--r--core/io/image_loader.h13
-rw-r--r--core/io/ip_address.cpp2
-rw-r--r--core/io/resource_format_binary.cpp7
-rw-r--r--core/io/resource_loader.h1
-rw-r--r--core/io/resource_saver.h2
-rw-r--r--core/math/geometry.h15
-rw-r--r--core/math/math_defs.h4
-rw-r--r--core/math/math_funcs.cpp25
-rw-r--r--core/math/math_funcs.h3
-rw-r--r--core/math/random_number_generator.cpp45
-rw-r--r--core/math/random_number_generator.h61
-rw-r--r--core/math/random_pcg.cpp55
-rw-r--r--core/math/random_pcg.h61
-rw-r--r--core/message_queue.cpp2
-rw-r--r--core/object.cpp55
-rw-r--r--core/object.h10
-rw-r--r--core/os/file_access.cpp28
-rw-r--r--core/os/file_access.h3
-rw-r--r--core/os/input.cpp2
-rw-r--r--core/os/input.h2
-rw-r--r--core/register_core_types.cpp2
-rw-r--r--core/resource.cpp4
-rw-r--r--core/ring_buffer.h6
-rw-r--r--core/script_debugger_remote.cpp2
-rw-r--r--core/script_language.cpp3
-rw-r--r--core/script_language.h1
-rw-r--r--core/undo_redo.cpp7
-rw-r--r--core/undo_redo.h2
-rw-r--r--core/ustring.cpp2
-rw-r--r--core/ustring.h2
-rw-r--r--core/variant.cpp12
-rw-r--r--core/variant_call.cpp4
-rw-r--r--core/variant_op.cpp4
-rw-r--r--core/vmap.h21
45 files changed, 506 insertions, 112 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index a3ff4bf13e..0032c43179 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -1020,6 +1020,11 @@ void _OS::center_window() {
OS::get_singleton()->center_window();
}
+void _OS::move_window_to_foreground() {
+
+ OS::get_singleton()->move_window_to_foreground();
+}
+
bool _OS::is_debug_build() const {
#ifdef DEBUG_ENABLED
@@ -1121,6 +1126,7 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("request_attention"), &_OS::request_attention);
ClassDB::bind_method(D_METHOD("get_real_window_size"), &_OS::get_real_window_size);
ClassDB::bind_method(D_METHOD("center_window"), &_OS::center_window);
+ ClassDB::bind_method(D_METHOD("move_window_to_foreground"), &_OS::move_window_to_foreground);
ClassDB::bind_method(D_METHOD("set_borderless_window", "borderless"), &_OS::set_borderless_window);
ClassDB::bind_method(D_METHOD("get_borderless_window"), &_OS::get_borderless_window);
@@ -1748,9 +1754,9 @@ String _File::get_line() const {
return f->get_line();
}
-Vector<String> _File::get_csv_line(String delim) const {
+Vector<String> _File::get_csv_line(const String &p_delim) const {
ERR_FAIL_COND_V(!f, Vector<String>());
- return f->get_csv_line(delim);
+ return f->get_csv_line(p_delim);
}
/**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
@@ -1847,6 +1853,11 @@ void _File::store_line(const String &p_string) {
f->store_line(p_string);
}
+void _File::store_csv_line(const Vector<String> &p_values, const String &p_delim) {
+ ERR_FAIL_COND(!f);
+ f->store_csv_line(p_values, p_delim);
+}
+
void _File::store_buffer(const PoolVector<uint8_t> &p_buffer) {
ERR_FAIL_COND(!f);
@@ -1930,6 +1941,7 @@ void _File::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_real"), &_File::get_real);
ClassDB::bind_method(D_METHOD("get_buffer", "len"), &_File::get_buffer);
ClassDB::bind_method(D_METHOD("get_line"), &_File::get_line);
+ ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &_File::get_csv_line, DEFVAL(","));
ClassDB::bind_method(D_METHOD("get_as_text"), &_File::get_as_text);
ClassDB::bind_method(D_METHOD("get_md5", "path"), &_File::get_md5);
ClassDB::bind_method(D_METHOD("get_sha256", "path"), &_File::get_sha256);
@@ -1937,7 +1949,6 @@ void _File::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_endian_swap", "enable"), &_File::set_endian_swap);
ClassDB::bind_method(D_METHOD("get_error"), &_File::get_error);
ClassDB::bind_method(D_METHOD("get_var"), &_File::get_var);
- ClassDB::bind_method(D_METHOD("get_csv_line", "delim"), &_File::get_csv_line, DEFVAL(","));
ClassDB::bind_method(D_METHOD("store_8", "value"), &_File::store_8);
ClassDB::bind_method(D_METHOD("store_16", "value"), &_File::store_16);
@@ -1948,6 +1959,7 @@ void _File::_bind_methods() {
ClassDB::bind_method(D_METHOD("store_real", "value"), &_File::store_real);
ClassDB::bind_method(D_METHOD("store_buffer", "buffer"), &_File::store_buffer);
ClassDB::bind_method(D_METHOD("store_line", "line"), &_File::store_line);
+ ClassDB::bind_method(D_METHOD("store_csv_line", "values", "delim"), &_File::store_csv_line, DEFVAL(","));
ClassDB::bind_method(D_METHOD("store_string", "string"), &_File::store_string);
ClassDB::bind_method(D_METHOD("store_var", "value"), &_File::store_var);
@@ -2860,10 +2872,10 @@ void JSONParseResult::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_error_line", "error_line"), &JSONParseResult::set_error_line);
ClassDB::bind_method(D_METHOD("set_result", "result"), &JSONParseResult::set_result);
- ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "error", PROPERTY_HINT_NONE, "Error", PROPERTY_USAGE_CLASS_IS_ENUM), "set_error", "get_error");
- ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "error_string"), "set_error_string", "get_error_string");
- ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "error_line"), "set_error_line", "get_error_line");
- ADD_PROPERTYNZ(PropertyInfo(Variant::NIL, "result", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "set_result", "get_result");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "error", PROPERTY_HINT_NONE, "Error", PROPERTY_USAGE_CLASS_IS_ENUM), "set_error", "get_error");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "error_string"), "set_error_string", "get_error_string");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "error_line"), "set_error_line", "get_error_line");
+ ADD_PROPERTY(PropertyInfo(Variant::NIL, "result", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "set_result", "get_result");
}
void JSONParseResult::set_error(Error p_error) {
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 79403879ac..720b14bf56 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -185,6 +185,7 @@ public:
virtual bool is_window_always_on_top() const;
virtual void request_attention();
virtual void center_window();
+ virtual void move_window_to_foreground();
virtual void set_borderless_window(bool p_borderless);
virtual bool get_borderless_window() const;
@@ -454,6 +455,7 @@ public:
PoolVector<uint8_t> get_buffer(int p_length) const; ///< get an array of bytes
String get_line() const;
+ Vector<String> get_csv_line(const String &p_delim = ",") const;
String get_as_text() const;
String get_md5(const String &p_path) const;
String get_sha256(const String &p_path) const;
@@ -479,12 +481,11 @@ public:
void store_string(const String &p_string);
void store_line(const String &p_string);
+ void store_csv_line(const Vector<String> &p_values, const String &p_delim = ",");
virtual void store_pascal_string(const String &p_string);
virtual String get_pascal_string();
- Vector<String> get_csv_line(String delim = ",") const;
-
void store_buffer(const PoolVector<uint8_t> &p_buffer); ///< store an array of bytes
void store_var(const Variant &p_var);
diff --git a/core/class_db.cpp b/core/class_db.cpp
index 71809d5454..052a4586fe 100644
--- a/core/class_db.cpp
+++ b/core/class_db.cpp
@@ -936,9 +936,8 @@ void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, cons
}
#ifdef DEBUG_METHODS_ENABLED
-
if (type->property_setget.has(p_pinfo.name)) {
- ERR_EXPLAIN("Object already has property: " + p_class);
+ ERR_EXPLAIN("Object " + p_class + " already has property: " + p_pinfo.name);
ERR_FAIL();
}
#endif
@@ -1367,6 +1366,41 @@ void ClassDB::get_extensions_for_type(const StringName &p_class, List<String> *p
}
}
+HashMap<StringName, HashMap<StringName, Variant> > ClassDB::default_values;
+
+Variant ClassDB::class_get_default_property_value(const StringName &p_class, const StringName &p_property) {
+
+ if (!default_values.has(p_class)) {
+
+ default_values[p_class] = HashMap<StringName, Variant>();
+
+ if (ClassDB::can_instance(p_class)) {
+
+ Object *c = ClassDB::instance(p_class);
+ List<PropertyInfo> plist;
+ c->get_property_list(&plist);
+ for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
+ if (E->get().usage & (PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR)) {
+
+ Variant v = c->get(E->get().name);
+ default_values[p_class][E->get().name] = v;
+ }
+ }
+ memdelete(c);
+ }
+ }
+
+ if (!default_values.has(p_class)) {
+ return Variant();
+ }
+
+ if (!default_values[p_class].has(p_property)) {
+ return Variant();
+ }
+
+ return default_values[p_class][p_property];
+}
+
RWLock *ClassDB::lock = NULL;
void ClassDB::init() {
@@ -1393,6 +1427,7 @@ void ClassDB::cleanup() {
classes.clear();
resource_base_extensions.clear();
compat_classes.clear();
+ default_values.clear();
memdelete(lock);
}
diff --git a/core/class_db.h b/core/class_db.h
index 11cc3033cf..75f9e8d6a7 100644
--- a/core/class_db.h
+++ b/core/class_db.h
@@ -161,6 +161,8 @@ public:
static void _add_class2(const StringName &p_class, const StringName &p_inherits);
+ static HashMap<StringName, HashMap<StringName, Variant> > default_values;
+
public:
// DO NOT USE THIS!!!!!! NEEDS TO BE PUBLIC BUT DO NOT USE NO MATTER WHAT!!!
template <class T>
@@ -352,6 +354,8 @@ public:
static void get_enum_list(const StringName &p_class, List<StringName> *p_enums, bool p_no_inheritance = false);
static void get_enum_constants(const StringName &p_class, const StringName &p_enum, List<StringName> *p_constants, bool p_no_inheritance = false);
+ static Variant class_get_default_property_value(const StringName &p_class, const StringName &p_property);
+
static StringName get_category(const StringName &p_node);
static void set_class_enabled(StringName p_class, bool p_enable);
diff --git a/core/dictionary.cpp b/core/dictionary.cpp
index ccbdff3816..6a3ab82879 100644
--- a/core/dictionary.cpp
+++ b/core/dictionary.cpp
@@ -112,6 +112,15 @@ Variant Dictionary::get_valid(const Variant &p_key) const {
return E.get();
}
+Variant Dictionary::get(const Variant &p_key, const Variant &p_default) const {
+ const Variant *result = getptr(p_key);
+ if (!result) {
+ return p_default;
+ }
+
+ return *result;
+}
+
int Dictionary::size() const {
return _p->variant_map.size();
diff --git a/core/dictionary.h b/core/dictionary.h
index d3b98c2f63..b77cc55254 100644
--- a/core/dictionary.h
+++ b/core/dictionary.h
@@ -58,6 +58,7 @@ public:
Variant *getptr(const Variant &p_key);
Variant get_valid(const Variant &p_key) const;
+ Variant get(const Variant &p_key, const Variant &p_default) const;
int size() const;
bool empty() const;
diff --git a/core/global_constants.cpp b/core/global_constants.cpp
index c70f960a66..7e9b8b393c 100644
--- a/core/global_constants.cpp
+++ b/core/global_constants.cpp
@@ -547,8 +547,9 @@ void register_global_constants() {
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_INTERNATIONALIZED);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_GROUP);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_CATEGORY);
- BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_STORE_IF_NONZERO);
- BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_STORE_IF_NONONE);
+ //deprecated, replaced by ClassDB function to check default value
+ //BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_STORE_IF_NONZERO);
+ //BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_STORE_IF_NONONE);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_NO_INSTANCE_STATE);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_RESTART_IF_CHANGED);
BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_SCRIPT_VARIABLE);
diff --git a/core/image.cpp b/core/image.cpp
index 172f5e517a..dca8aedb8f 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -1766,6 +1766,15 @@ int Image::get_image_required_mipmaps(int p_width, int p_height, Format p_format
return mm;
}
+int Image::get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap) {
+
+ if (p_mipmap <= 0) {
+ return 0;
+ }
+ int mm;
+ return _get_dst_image_size(p_width, p_height, p_format, mm, p_mipmap - 1);
+}
+
bool Image::is_compressed() const {
return format > FORMAT_RGBE9995;
}
@@ -1922,7 +1931,8 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po
if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0)
return;
- Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest, clipped_src_rect.size));
+ Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y));
+ Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size));
PoolVector<uint8_t>::Write wp = data.write();
uint8_t *dst_data_ptr = wp.ptr();
@@ -1976,7 +1986,8 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co
if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0)
return;
- Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest, clipped_src_rect.size));
+ Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y));
+ Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size));
PoolVector<uint8_t>::Write wp = data.write();
uint8_t *dst_data_ptr = wp.ptr();
@@ -2033,7 +2044,8 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P
if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0)
return;
- Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest, clipped_src_rect.size));
+ Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y));
+ Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size));
lock();
Ref<Image> img = p_src;
@@ -2087,7 +2099,8 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c
if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0)
return;
- Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest, clipped_src_rect.size));
+ Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y));
+ Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size));
lock();
Ref<Image> img = p_src;
diff --git a/core/image.h b/core/image.h
index 11f9380c3c..0770eb953e 100644
--- a/core/image.h
+++ b/core/image.h
@@ -286,6 +286,7 @@ public:
static int get_image_data_size(int p_width, int p_height, Format p_format, bool p_mipmaps = false);
static int get_image_required_mipmaps(int p_width, int p_height, Format p_format);
+ static int get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap);
enum CompressMode {
COMPRESS_S3TC,
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index 40f756ba9a..3823285792 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -455,7 +455,7 @@ String DirAccessPack::get_current_dir() {
while (pd->parent) {
pd = pd->parent;
- p = pd->name + "/" + p;
+ p = pd->name.plus_file(p);
}
return "res://" + p;
diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp
index 3ae9ff676c..e4fbb0247d 100644
--- a/core/io/image_loader.cpp
+++ b/core/io/image_loader.cpp
@@ -60,7 +60,7 @@ Error ImageLoader::load_image(String p_file, Ref<Image> p_image, FileAccess *p_c
String extension = p_file.get_extension();
- for (int i = 0; i < loader_count; i++) {
+ for (int i = 0; i < loader.size(); i++) {
if (!loader[i]->recognize(extension))
continue;
@@ -83,30 +83,45 @@ Error ImageLoader::load_image(String p_file, Ref<Image> p_image, FileAccess *p_c
void ImageLoader::get_recognized_extensions(List<String> *p_extensions) {
- for (int i = 0; i < loader_count; i++) {
+ for (int i = 0; i < loader.size(); i++) {
loader[i]->get_recognized_extensions(p_extensions);
}
}
-bool ImageLoader::recognize(const String &p_extension) {
+ImageFormatLoader *ImageLoader::recognize(const String &p_extension) {
- for (int i = 0; i < loader_count; i++) {
+ for (int i = 0; i < loader.size(); i++) {
if (loader[i]->recognize(p_extension))
- return true;
+ return loader[i];
}
- return false;
+ return NULL;
}
-ImageFormatLoader *ImageLoader::loader[MAX_LOADERS];
-int ImageLoader::loader_count = 0;
+Vector<ImageFormatLoader *> ImageLoader::loader;
void ImageLoader::add_image_format_loader(ImageFormatLoader *p_loader) {
- ERR_FAIL_COND(loader_count >= MAX_LOADERS);
- loader[loader_count++] = p_loader;
+ loader.push_back(p_loader);
+}
+
+void ImageLoader::remove_image_format_loader(ImageFormatLoader *p_loader) {
+
+ loader.erase(p_loader);
+}
+
+const Vector<ImageFormatLoader *> &ImageLoader::get_image_format_loaders() {
+
+ return loader;
+}
+
+void ImageLoader::cleanup() {
+
+ while (loader.size()) {
+ remove_image_format_loader(loader[0]);
+ }
}
/////////////////
@@ -137,7 +152,7 @@ RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_origin
int idx = -1;
- for (int i = 0; i < ImageLoader::loader_count; i++) {
+ for (int i = 0; i < ImageLoader::loader.size(); i++) {
if (ImageLoader::loader[i]->recognize(extension)) {
idx = i;
break;
diff --git a/core/io/image_loader.h b/core/io/image_loader.h
index 561f275e0c..7a58d46f93 100644
--- a/core/io/image_loader.h
+++ b/core/io/image_loader.h
@@ -70,20 +70,21 @@ public:
class ImageLoader {
- enum {
- MAX_LOADERS = 8
- };
+ static Vector<ImageFormatLoader *> loader;
friend class ResourceFormatLoaderImage;
- static ImageFormatLoader *loader[MAX_LOADERS];
- static int loader_count;
protected:
public:
static Error load_image(String p_file, Ref<Image> p_image, FileAccess *p_custom = NULL, bool p_force_linear = false, float p_scale = 1.0);
static void get_recognized_extensions(List<String> *p_extensions);
- static bool recognize(const String &p_extension);
+ static ImageFormatLoader *recognize(const String &p_extension);
static void add_image_format_loader(ImageFormatLoader *p_loader);
+ static void remove_image_format_loader(ImageFormatLoader *p_loader);
+
+ static const Vector<ImageFormatLoader *> &get_image_format_loaders();
+
+ static void cleanup();
};
class ResourceFormatLoaderImage : public ResourceFormatLoader {
diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp
index 6d979d10eb..194d1af6bf 100644
--- a/core/io/ip_address.cpp
+++ b/core/io/ip_address.cpp
@@ -184,7 +184,7 @@ bool IP_Address::is_ipv4() const {
}
const uint8_t *IP_Address::get_ipv4() const {
- ERR_FAIL_COND_V(!is_ipv4(), 0);
+ ERR_FAIL_COND_V(!is_ipv4(), &(field8[12])); // Not the correct IPv4 (it's an IPv6), but we don't want to return a null pointer risking an engine crash.
return &(field8[12]);
}
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index aa73d7bc5c..6f3a8c3d2e 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -1813,8 +1813,13 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
Property p;
p.name_idx = get_string_index(F->get().name);
p.value = E->get()->get(F->get().name);
- if (((F->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO) && p.value.is_zero()) || ((F->get().usage & PROPERTY_USAGE_STORE_IF_NONONE) && p.value.is_one()))
+
+ Variant default_value = ClassDB::class_get_default_property_value(E->get()->get_class(), F->get().name);
+
+ if (default_value.get_type() != Variant::NIL && bool(Variant::evaluate(Variant::OP_EQUAL, p.value, default_value))) {
continue;
+ }
+
p.pi = F->get();
rd.properties.push_back(p);
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index 7ade4a2dfc..a46a00203f 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -123,6 +123,7 @@ public:
static int get_import_order(const String &p_path);
static void set_timestamp_on_load(bool p_timestamp) { timestamp_on_load = p_timestamp; }
+ static bool get_timestamp_on_load() { return timestamp_on_load; }
static void notify_load_error(const String &p_err) {
if (err_notify) err_notify(err_notify_ud, p_err);
diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h
index 6134d9db57..cdd43292a2 100644
--- a/core/io/resource_saver.h
+++ b/core/io/resource_saver.h
@@ -76,6 +76,8 @@ public:
static void add_resource_format_saver(ResourceFormatSaver *p_format_saver, bool p_at_front = false);
static void set_timestamp_on_save(bool p_timestamp) { timestamp_on_save = p_timestamp; }
+ static bool get_timestamp_on_save() { return timestamp_on_save; }
+
static void set_save_callback(ResourceSavedCallback p_callback);
};
diff --git a/core/math/geometry.h b/core/math/geometry.h
index a813a90774..df63f0dabe 100644
--- a/core/math/geometry.h
+++ b/core/math/geometry.h
@@ -800,6 +800,21 @@ public:
return Vector<Vector<Vector2> >();
}
+ static bool is_polygon_clockwise(const Vector<Vector2> &p_polygon) {
+ int c = p_polygon.size();
+ if (c < 3)
+ return false;
+ const Vector2 *p = p_polygon.ptr();
+ real_t sum = 0;
+ for (int i = 0; i < c; i++) {
+ const Vector2 &v1 = p[i];
+ const Vector2 &v2 = p[(i + 1) % c];
+ sum += (v2.x - v1.x) * (v2.y + v1.y);
+ }
+
+ return sum > 0.0f;
+ }
+
static PoolVector<PoolVector<Face3> > separate_objects(PoolVector<Face3> p_array);
static PoolVector<Face3> wrap_geometry(PoolVector<Face3> p_array, real_t *p_error = NULL); ///< create a "wrap" that encloses the given geometry
diff --git a/core/math/math_defs.h b/core/math/math_defs.h
index a5feee6eb5..db9055cee2 100644
--- a/core/math/math_defs.h
+++ b/core/math/math_defs.h
@@ -93,9 +93,9 @@ enum Corner {
};
/**
- * The "Real" type is an abstract type used for real numbers, such as 1.5,
+ * The "Real" type is an abstract type used for real numbers, such as 1.5,
* in contrast to integer numbers. Precision can be controlled with the
- * presence or absence of the REAL_T_IS_DOUBLE define.
+ * presence or absence of the REAL_T_IS_DOUBLE define.
*/
#ifdef REAL_T_IS_DOUBLE
typedef double real_t;
diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp
index 0c06d2a2b5..06355d15ed 100644
--- a/core/math/math_funcs.cpp
+++ b/core/math/math_funcs.cpp
@@ -30,30 +30,27 @@
#include "math_funcs.h"
-#include "core/os/os.h"
-
-pcg32_random_t Math::default_pcg = { 12047754176567800795ULL, PCG_DEFAULT_INC_64 };
+RandomPCG Math::default_rand(RandomPCG::DEFAULT_SEED, RandomPCG::DEFAULT_INC);
#define PHI 0x9e3779b9
-// TODO: we should eventually expose pcg.inc too
uint32_t Math::rand_from_seed(uint64_t *seed) {
- pcg32_random_t pcg = { *seed, PCG_DEFAULT_INC_64 };
- uint32_t r = pcg32_random_r(&pcg);
- *seed = pcg.state;
+ RandomPCG rng = RandomPCG(*seed, RandomPCG::DEFAULT_INC);
+ uint32_t r = rng.rand();
+ *seed = rng.get_seed();
return r;
}
void Math::seed(uint64_t x) {
- default_pcg.state = x;
+ default_rand.seed(x);
}
void Math::randomize() {
- seed(OS::get_singleton()->get_ticks_usec() * default_pcg.state + PCG_DEFAULT_INC_64);
+ default_rand.randomize();
}
uint32_t Math::rand() {
- return pcg32_random_r(&default_pcg);
+ return default_rand.rand();
}
int Math::step_decimals(double p_step) {
@@ -169,13 +166,9 @@ uint32_t Math::larger_prime(uint32_t p_val) {
}
double Math::random(double from, double to) {
- unsigned int r = Math::rand();
- double ret = (double)r / (double)RANDOM_MAX;
- return (ret) * (to - from) + from;
+ return default_rand.random(from, to);
}
float Math::random(float from, float to) {
- unsigned int r = Math::rand();
- float ret = (float)r / (float)RANDOM_MAX;
- return (ret) * (to - from) + from;
+ return default_rand.random(from, to);
}
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index 65c318448c..f9d89d5d5a 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -32,6 +32,7 @@
#define MATH_FUNCS_H
#include "core/math/math_defs.h"
+#include "core/math/random_pcg.h"
#include "core/typedefs.h"
#include "thirdparty/misc/pcg.h"
@@ -41,7 +42,7 @@
class Math {
- static pcg32_random_t default_pcg;
+ static RandomPCG default_rand;
public:
Math() {} // useless to instance
diff --git a/core/math/random_number_generator.cpp b/core/math/random_number_generator.cpp
new file mode 100644
index 0000000000..e4ec0dac99
--- /dev/null
+++ b/core/math/random_number_generator.cpp
@@ -0,0 +1,45 @@
+/*************************************************************************/
+/* random_number_generator.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 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 "random_number_generator.h"
+
+RandomNumberGenerator::RandomNumberGenerator() :
+ randbase() {}
+
+void RandomNumberGenerator::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_seed", "seed"), &RandomNumberGenerator::set_seed);
+ ClassDB::bind_method(D_METHOD("get_seed"), &RandomNumberGenerator::get_seed);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "seed"), "set_seed", "get_seed");
+
+ ClassDB::bind_method(D_METHOD("randi"), &RandomNumberGenerator::randi);
+ ClassDB::bind_method(D_METHOD("randf"), &RandomNumberGenerator::randf);
+ ClassDB::bind_method(D_METHOD("rand_range", "from", "to"), &RandomNumberGenerator::rand_range);
+ ClassDB::bind_method(D_METHOD("randomize"), &RandomNumberGenerator::randomize);
+}
diff --git a/core/math/random_number_generator.h b/core/math/random_number_generator.h
new file mode 100644
index 0000000000..557863fdbd
--- /dev/null
+++ b/core/math/random_number_generator.h
@@ -0,0 +1,61 @@
+/*************************************************************************/
+/* random_number_generator.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 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 RANDOM_NUMBER_GENERATOR_H
+#define RANDOM_NUMBER_GENERATOR_H
+
+#include "core/math/random_pcg.h"
+#include "core/reference.h"
+
+class RandomNumberGenerator : public Reference {
+ GDCLASS(RandomNumberGenerator, Reference);
+
+ RandomPCG randbase;
+
+protected:
+ static void _bind_methods();
+
+public:
+ _FORCE_INLINE_ void set_seed(uint64_t seed) { randbase.seed(seed); }
+
+ _FORCE_INLINE_ uint64_t get_seed() { return randbase.get_seed(); }
+
+ _FORCE_INLINE_ void randomize() { return randbase.randomize(); }
+
+ _FORCE_INLINE_ uint32_t randi() { return randbase.rand(); }
+
+ _FORCE_INLINE_ real_t randf() { return randbase.randf(); }
+
+ _FORCE_INLINE_ real_t rand_range(real_t from, real_t to) { return randbase.random(from, to); }
+
+ RandomNumberGenerator();
+};
+
+#endif // RANDOM_NUMBER_GENERATOR_H
diff --git a/core/math/random_pcg.cpp b/core/math/random_pcg.cpp
new file mode 100644
index 0000000000..16899f79da
--- /dev/null
+++ b/core/math/random_pcg.cpp
@@ -0,0 +1,55 @@
+/*************************************************************************/
+/* random_pcg.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 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 "random_pcg.h"
+
+#include "core/os/os.h"
+
+RandomPCG::RandomPCG(uint64_t seed, uint64_t inc) :
+ pcg() {
+ pcg.state = seed;
+ pcg.inc = inc;
+}
+
+void RandomPCG::randomize() {
+ seed(OS::get_singleton()->get_ticks_usec() * pcg.state + PCG_DEFAULT_INC_64);
+}
+
+double RandomPCG::random(double from, double to) {
+ unsigned int r = rand();
+ double ret = (double)r / (double)RANDOM_MAX;
+ return (ret) * (to - from) + from;
+}
+
+float RandomPCG::random(float from, float to) {
+ unsigned int r = rand();
+ float ret = (float)r / (float)RANDOM_MAX;
+ return (ret) * (to - from) + from;
+}
diff --git a/core/math/random_pcg.h b/core/math/random_pcg.h
new file mode 100644
index 0000000000..4a43c36ede
--- /dev/null
+++ b/core/math/random_pcg.h
@@ -0,0 +1,61 @@
+/*************************************************************************/
+/* random_pcg.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 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 RANDOM_PCG_H
+#define RANDOM_PCG_H
+
+#include "core/math/math_defs.h"
+
+#include "thirdparty/misc/pcg.h"
+
+class RandomPCG {
+ pcg32_random_t pcg;
+
+public:
+ static const uint64_t DEFAULT_SEED = 12047754176567800795ULL;
+ static const uint64_t DEFAULT_INC = PCG_DEFAULT_INC_64;
+ static const uint64_t RANDOM_MAX = 4294967295;
+
+ RandomPCG(uint64_t seed = DEFAULT_SEED, uint64_t inc = PCG_DEFAULT_INC_64);
+
+ _FORCE_INLINE_ void seed(uint64_t seed) { pcg.state = seed; }
+ _FORCE_INLINE_ uint64_t get_seed() { return pcg.state; }
+
+ void randomize();
+ _FORCE_INLINE_ uint32_t rand() { return pcg32_random_r(&pcg); }
+ _FORCE_INLINE_ double randf() { return (double)rand() / (double)RANDOM_MAX; }
+ _FORCE_INLINE_ float randd() { return (float)rand() / (float)RANDOM_MAX; }
+
+ double random(double from, double to);
+ float random(float from, float to);
+ real_t random(int from, int to) { return (real_t)random((real_t)from, (real_t)to); }
+};
+
+#endif // RANDOM_PCG_H
diff --git a/core/message_queue.cpp b/core/message_queue.cpp
index abfc73407a..2952593798 100644
--- a/core/message_queue.cpp
+++ b/core/message_queue.cpp
@@ -209,9 +209,9 @@ void MessageQueue::statistics() {
} break;
}
+ } else {
//object was deleted
print_line("Object was deleted while awaiting a callback");
- } else {
null_count++;
}
diff --git a/core/object.cpp b/core/object.cpp
index 374e10726a..3a14c7c0b5 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -636,10 +636,11 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
#ifdef TOOLS_ENABLED
p_list->push_back(PropertyInfo(Variant::NIL, "Script", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
#endif
- p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NONZERO));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT));
+ }
+ if (!metadata.empty()) {
+ p_list->push_back(PropertyInfo(Variant::DICTIONARY, "__meta__", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
}
- if (!metadata.empty())
- p_list->push_back(PropertyInfo(Variant::DICTIONARY, "__meta__", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_STORE_IF_NONZERO));
if (script_instance && !p_reversed) {
p_list->push_back(PropertyInfo(Variant::NIL, "Script Variables", PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY));
script_instance->get_property_list(p_list);
@@ -1442,8 +1443,20 @@ Error Object::connect(const StringName &p_signal, Object *p_to_object, const Str
if (!s) {
bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal);
//check in script
- if (!signal_is_valid && !script.is_null() && Ref<Script>(script)->has_script_signal(p_signal))
- signal_is_valid = true;
+ if (!signal_is_valid && !script.is_null()) {
+
+ if (Ref<Script>(script)->has_script_signal(p_signal)) {
+ signal_is_valid = true;
+ }
+#ifdef TOOLS_ENABLED
+ else {
+ //allow connecting signals anyway if script is invalid, see issue #17070
+ if (!Ref<Script>(script)->is_valid()) {
+ signal_is_valid = true;
+ }
+ }
+#endif
+ }
if (!signal_is_valid) {
ERR_EXPLAIN("In Object of type '" + String(get_class()) + "': Attempt to connect nonexistent signal '" + p_signal + "' to method '" + p_to_object->get_class() + "." + p_to_method + "'");
@@ -1714,6 +1727,8 @@ void Object::_bind_methods() {
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_deferred", &Object::_call_deferred_bind, mi);
}
+ ClassDB::bind_method(D_METHOD("set_deferred", "property", "value"), &Object::set_deferred);
+
ClassDB::bind_method(D_METHOD("callv", "method", "arg_array"), &Object::callv);
ClassDB::bind_method(D_METHOD("has_method", "method"), &Object::has_method);
@@ -1770,6 +1785,10 @@ void Object::call_deferred(const StringName &p_method, VARIANT_ARG_DECLARE) {
MessageQueue::get_singleton()->push_call(this, p_method, VARIANT_ARG_PASS);
}
+void Object::set_deferred(const StringName &p_property, const Variant &p_value) {
+ MessageQueue::get_singleton()->push_set(this, p_property, p_value);
+}
+
void Object::set_block_signals(bool p_block) {
_block_signals = p_block;
@@ -1934,30 +1953,30 @@ Object::~Object() {
memdelete(script_instance);
script_instance = NULL;
- List<Connection> sconnections;
const StringName *S = NULL;
- while ((S = signal_map.next(S))) {
+ while ((S = signal_map.next(NULL))) {
Signal *s = &signal_map[*S];
- ERR_EXPLAIN("Attempt to delete an object in the middle of a signal emission from it");
- ERR_CONTINUE(s->lock > 0);
-
- for (int i = 0; i < s->slot_map.size(); i++) {
-
- sconnections.push_back(s->slot_map.getv(i).conn);
+ if (s->lock) {
+ ERR_EXPLAIN("Attempt to delete an object in the middle of a signal emission from it");
+ ERR_CONTINUE(s->lock > 0);
}
- }
- for (List<Connection>::Element *E = sconnections.front(); E; E = E->next()) {
+ //brute force disconnect for performance
+ int slot_count = s->slot_map.size();
+ const VMap<Signal::Target, Signal::Slot>::Pair *slot_list = s->slot_map.get_array();
- Connection &c = E->get();
- ERR_CONTINUE(c.source != this); //bug?
+ for (int i = 0; i < slot_count; i++) {
+
+ slot_list[i].value.conn.target->connections.erase(slot_list[i].value.cE);
+ }
- this->_disconnect(c.signal, c.target, c.method, true);
+ signal_map.erase(*S);
}
+ //signals from nodes that connect to this node
while (connections.size()) {
Connection c = connections.front()->get();
diff --git a/core/object.h b/core/object.h
index 0fee7c2157..88a98dacbe 100644
--- a/core/object.h
+++ b/core/object.h
@@ -103,8 +103,9 @@ enum PropertyUsageFlags {
PROPERTY_USAGE_INTERNATIONALIZED = 64, //hint for internationalized strings
PROPERTY_USAGE_GROUP = 128, //used for grouping props in the editor
PROPERTY_USAGE_CATEGORY = 256,
- PROPERTY_USAGE_STORE_IF_NONZERO = 512, //only store if nonzero
- PROPERTY_USAGE_STORE_IF_NONONE = 1024, //only store if false
+ //those below are deprecated thanks to ClassDB's now class value cache
+ //PROPERTY_USAGE_STORE_IF_NONZERO = 512, //only store if nonzero
+ //PROPERTY_USAGE_STORE_IF_NONONE = 1024, //only store if false
PROPERTY_USAGE_NO_INSTANCE_STATE = 2048,
PROPERTY_USAGE_RESTART_IF_CHANGED = 4096,
PROPERTY_USAGE_SCRIPT_VARIABLE = 8192,
@@ -126,10 +127,6 @@ enum PropertyUsageFlags {
#define ADD_SIGNAL(m_signal) ClassDB::add_signal(get_class_static(), m_signal)
#define ADD_PROPERTY(m_property, m_setter, m_getter) ClassDB::add_property(get_class_static(), m_property, _scs_create(m_setter), _scs_create(m_getter))
#define ADD_PROPERTYI(m_property, m_setter, m_getter, m_index) ClassDB::add_property(get_class_static(), m_property, _scs_create(m_setter), _scs_create(m_getter), m_index)
-#define ADD_PROPERTYNZ(m_property, m_setter, m_getter) ClassDB::add_property(get_class_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONZERO), _scs_create(m_setter), _scs_create(m_getter))
-#define ADD_PROPERTYINZ(m_property, m_setter, m_getter, m_index) ClassDB::add_property(get_class_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONZERO), _scs_create(m_setter), _scs_create(m_getter), m_index)
-#define ADD_PROPERTYNO(m_property, m_setter, m_getter) ClassDB::add_property(get_class_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONONE), _scs_create(m_setter), _scs_create(m_getter))
-#define ADD_PROPERTYINO(m_property, m_setter, m_getter, m_index) ClassDB::add_property(get_class_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONONE), _scs_create(m_setter), _scs_create(m_getter), m_index)
#define ADD_GROUP(m_name, m_prefix) ClassDB::add_property_group(get_class_static(), m_name, m_prefix)
struct PropertyInfo {
@@ -701,6 +698,7 @@ public:
bool is_connected(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method) const;
void call_deferred(const StringName &p_method, VARIANT_ARG_LIST);
+ void set_deferred(const StringName &p_property, const Variant &p_value);
void set_block_signals(bool p_block);
bool is_blocking_signals() const;
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
index e09e5e16ad..679b1c9054 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -346,9 +346,9 @@ String FileAccess::get_line() const {
return String::utf8(line.get_data());
}
-Vector<String> FileAccess::get_csv_line(String delim) const {
+Vector<String> FileAccess::get_csv_line(const String &p_delim) const {
- ERR_FAIL_COND_V(delim.length() != 1, Vector<String>());
+ ERR_FAIL_COND_V(p_delim.length() != 1, Vector<String>());
String l;
int qc = 0;
@@ -376,7 +376,7 @@ Vector<String> FileAccess::get_csv_line(String delim) const {
CharType c = l[i];
CharType s[2] = { 0, 0 };
- if (!in_quote && c == delim[0]) {
+ if (!in_quote && c == p_delim[0]) {
strings.push_back(current);
current = String();
} else if (c == '"') {
@@ -525,6 +525,28 @@ void FileAccess::store_line(const String &p_line) {
store_8('\n');
}
+void FileAccess::store_csv_line(const Vector<String> &p_values, const String &p_delim) {
+
+ ERR_FAIL_COND(p_delim.length() != 1);
+
+ String line = "";
+ int size = p_values.size();
+ for (int i = 0; i < size; ++i) {
+ String value = p_values[i];
+
+ if (value.find("\"") != -1 || value.find(p_delim) != -1 || value.find("\n") != -1) {
+ value = "\"" + value.replace("\"", "\"\"") + "\"";
+ }
+ if (i < size - 1) {
+ value += p_delim;
+ }
+
+ line += value;
+ }
+
+ store_line(line);
+}
+
void FileAccess::store_buffer(const uint8_t *p_src, int p_length) {
for (int i = 0; i < p_length; i++)
diff --git a/core/os/file_access.h b/core/os/file_access.h
index b7d93e9f5d..f1f3005dd9 100644
--- a/core/os/file_access.h
+++ b/core/os/file_access.h
@@ -112,7 +112,7 @@ public:
virtual int get_buffer(uint8_t *p_dst, int p_length) const; ///< get an array of bytes
virtual String get_line() const;
virtual String get_token() const;
- virtual Vector<String> get_csv_line(String delim = ",") const;
+ virtual Vector<String> get_csv_line(const String &p_delim = ",") const;
/**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac)
* It's not about the current CPU type but file formats.
@@ -136,6 +136,7 @@ public:
virtual void store_string(const String &p_string);
virtual void store_line(const String &p_line);
+ virtual void store_csv_line(const Vector<String> &p_values, const String &p_delim = ",");
virtual void store_pascal_string(const String &p_string);
virtual String get_pascal_string();
diff --git a/core/os/input.cpp b/core/os/input.cpp
index 4cd1f0b24a..3b895b16b4 100644
--- a/core/os/input.cpp
+++ b/core/os/input.cpp
@@ -86,7 +86,7 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_mouse_mode", "mode"), &Input::set_mouse_mode);
ClassDB::bind_method(D_METHOD("get_mouse_mode"), &Input::get_mouse_mode);
ClassDB::bind_method(D_METHOD("warp_mouse_position", "to"), &Input::warp_mouse_position);
- ClassDB::bind_method(D_METHOD("action_press", "action"), &Input::action_press);
+ ClassDB::bind_method(D_METHOD("action_press", "action", "strength"), &Input::action_press, DEFVAL(1.f));
ClassDB::bind_method(D_METHOD("action_release", "action"), &Input::action_release);
ClassDB::bind_method(D_METHOD("set_default_cursor_shape", "shape"), &Input::set_default_cursor_shape, DEFVAL(CURSOR_ARROW));
ClassDB::bind_method(D_METHOD("set_custom_mouse_cursor", "image", "shape", "hotspot"), &Input::set_custom_mouse_cursor, DEFVAL(CURSOR_ARROW), DEFVAL(Vector2()));
diff --git a/core/os/input.h b/core/os/input.h
index db523d6789..dc2c213db2 100644
--- a/core/os/input.h
+++ b/core/os/input.h
@@ -113,7 +113,7 @@ public:
virtual Vector3 get_magnetometer() const = 0;
virtual Vector3 get_gyroscope() const = 0;
- virtual void action_press(const StringName &p_action) = 0;
+ virtual void action_press(const StringName &p_action, float p_strength = 1.f) = 0;
virtual void action_release(const StringName &p_action) = 0;
void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const;
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 430004bb96..6b776cb0b1 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -55,6 +55,7 @@
#include "core/math/a_star.h"
#include "core/math/expression.h"
#include "core/math/geometry.h"
+#include "core/math/random_number_generator.h"
#include "core/math/triangle_mesh.h"
#include "core/os/input.h"
#include "core/os/main_loop.h"
@@ -180,6 +181,7 @@ void register_core_types() {
ClassDB::register_virtual_class<PackedDataContainerRef>();
ClassDB::register_class<AStar>();
ClassDB::register_class<EncodedObjectAsID>();
+ ClassDB::register_class<RandomNumberGenerator>();
ClassDB::register_class<JSONParseResult>();
diff --git a/core/resource.cpp b/core/resource.cpp
index 4dcd338e94..a76e16232e 100644
--- a/core/resource.cpp
+++ b/core/resource.cpp
@@ -379,9 +379,9 @@ void Resource::_bind_methods() {
ClassDB::bind_method(D_METHOD("duplicate", "subresources"), &Resource::duplicate, DEFVAL(false));
ADD_SIGNAL(MethodInfo("changed"));
ADD_GROUP("Resource", "resource_");
- ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "resource_local_to_scene"), "set_local_to_scene", "is_local_to_scene");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resource_local_to_scene"), "set_local_to_scene", "is_local_to_scene");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "resource_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_path", "get_path");
- ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "resource_name"), "set_name", "get_name");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "resource_name"), "set_name", "get_name");
BIND_VMETHOD(MethodInfo("_setup_local_to_scene"));
}
diff --git a/core/ring_buffer.h b/core/ring_buffer.h
index 2516880064..54486f8cad 100644
--- a/core/ring_buffer.h
+++ b/core/ring_buffer.h
@@ -135,6 +135,12 @@ public:
return p_n;
};
+ inline int decrease_write(int p_n) {
+ p_n = MIN(p_n, data_left());
+ inc(write_pos, size_mask + 1 - p_n);
+ return p_n;
+ }
+
Error write(const T &p_v) {
ERR_FAIL_COND_V(space_left() < 1, FAILED);
data.write[inc(write_pos, 1)] = p_v;
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp
index 621a94ab1a..a03ddd0983 100644
--- a/core/script_debugger_remote.cpp
+++ b/core/script_debugger_remote.cpp
@@ -108,7 +108,7 @@ void ScriptDebuggerRemote::_put_variable(const String &p_name, const Variant &p_
}
int len = 0;
- Error err = encode_variant(var, NULL, len);
+ Error err = encode_variant(var, NULL, len, true);
if (err != OK)
ERR_PRINT("Failed to encode variant");
diff --git a/core/script_language.cpp b/core/script_language.cpp
index 5b65da9ef1..496521486e 100644
--- a/core/script_language.cpp
+++ b/core/script_language.cpp
@@ -563,7 +563,8 @@ Variant PlaceHolderScriptInstance::property_get_fallback(const StringName &p_nam
PlaceHolderScriptInstance::PlaceHolderScriptInstance(ScriptLanguage *p_language, Ref<Script> p_script, Object *p_owner) :
owner(p_owner),
language(p_language),
- script(p_script) {
+ script(p_script),
+ build_failed(false) {
}
PlaceHolderScriptInstance::~PlaceHolderScriptInstance() {
diff --git a/core/script_language.h b/core/script_language.h
index bcd9c2c5ea..654d1d4265 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -128,6 +128,7 @@ public:
virtual MethodInfo get_method_info(const StringName &p_method) const = 0;
virtual bool is_tool() const = 0;
+ virtual bool is_valid() const = 0;
virtual ScriptLanguage *get_language() const = 0;
diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp
index 7d67076df5..3d41c374ea 100644
--- a/core/undo_redo.cpp
+++ b/core/undo_redo.cpp
@@ -325,7 +325,7 @@ bool UndoRedo::undo() {
return true;
}
-void UndoRedo::clear_history() {
+void UndoRedo::clear_history(bool p_increase_version) {
ERR_FAIL_COND(action_level > 0);
_discard_redo();
@@ -333,7 +333,8 @@ void UndoRedo::clear_history() {
while (actions.size())
_pop_history_tail();
- //version++;
+ if (p_increase_version)
+ version++;
}
String UndoRedo::get_current_action_name() const {
@@ -493,7 +494,7 @@ void UndoRedo::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_undo_property", "object", "property", "value"), &UndoRedo::add_undo_property);
ClassDB::bind_method(D_METHOD("add_do_reference", "object"), &UndoRedo::add_do_reference);
ClassDB::bind_method(D_METHOD("add_undo_reference", "object"), &UndoRedo::add_undo_reference);
- ClassDB::bind_method(D_METHOD("clear_history"), &UndoRedo::clear_history);
+ ClassDB::bind_method(D_METHOD("clear_history", "increase_version"), &UndoRedo::clear_history, DEFVAL(true));
ClassDB::bind_method(D_METHOD("get_current_action_name"), &UndoRedo::get_current_action_name);
ClassDB::bind_method(D_METHOD("get_version"), &UndoRedo::get_version);
ClassDB::bind_method(D_METHOD("redo"), &UndoRedo::redo);
diff --git a/core/undo_redo.h b/core/undo_redo.h
index 22dcd60472..f09fca9a78 100644
--- a/core/undo_redo.h
+++ b/core/undo_redo.h
@@ -112,7 +112,7 @@ public:
bool redo();
bool undo();
String get_current_action_name() const;
- void clear_history();
+ void clear_history(bool p_increase_version = true);
uint64_t get_version() const;
diff --git a/core/ustring.cpp b/core/ustring.cpp
index 2191bb5e23..3f017fa985 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -4035,7 +4035,7 @@ String String::sprintf(const Array &values, bool *error) const {
str = str.pad_decimals(min_decimals);
// Show sign
- if (show_sign && value >= 0) {
+ if (show_sign && str.left(1) != "-") {
str = str.insert(0, "+");
}
diff --git a/core/ustring.h b/core/ustring.h
index d2766ec7a3..8e4dbd8031 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -63,7 +63,7 @@ public:
CharString &operator+=(char p_char);
int length() const { return size() ? size() - 1 : 0; }
const char *get_data() const;
- operator const char *() { return get_data(); };
+ operator const char *() const { return get_data(); };
};
typedef wchar_t CharType;
diff --git a/core/variant.cpp b/core/variant.cpp
index edbe66ba31..eb9f34fee6 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -1662,7 +1662,17 @@ Variant::operator Transform() const {
return Transform(*_data._basis, Vector3());
else if (type == QUAT)
return Transform(Basis(*reinterpret_cast<const Quat *>(_data._mem)), Vector3());
- else
+ else if (type == TRANSFORM2D) {
+ const Transform2D &t = *_data._transform2d;
+ Transform m;
+ m.basis.elements[0][0] = t.elements[0][0];
+ m.basis.elements[1][0] = t.elements[0][1];
+ m.basis.elements[0][1] = t.elements[1][0];
+ m.basis.elements[1][1] = t.elements[1][1];
+ m.origin[0] = t.elements[2][0];
+ m.origin[1] = t.elements[2][1];
+ return m;
+ } else
return Transform();
}
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 8693a584f2..0c6e43fe36 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -155,9 +155,7 @@ struct _VariantCall {
funcdata.default_args = p_defaultarg;
funcdata._const = p_const;
funcdata.returns = p_has_return;
-#ifdef DEBUG_ENABLED
funcdata.return_type = p_return;
-#endif
if (p_argtype1.name) {
funcdata.arg_types.push_back(p_argtype1.type);
@@ -486,6 +484,7 @@ struct _VariantCall {
VCALL_LOCALMEM0R(Dictionary, keys);
VCALL_LOCALMEM0R(Dictionary, values);
VCALL_LOCALMEM1R(Dictionary, duplicate);
+ VCALL_LOCALMEM2R(Dictionary, get);
VCALL_LOCALMEM2(Array, set);
VCALL_LOCALMEM1R(Array, get);
@@ -1679,6 +1678,7 @@ void register_variant_methods() {
ADDFUNC0R(DICTIONARY, ARRAY, Dictionary, keys, varray());
ADDFUNC0R(DICTIONARY, ARRAY, Dictionary, values, varray());
ADDFUNC1R(DICTIONARY, DICTIONARY, Dictionary, duplicate, BOOL, "deep", varray(false));
+ ADDFUNC2R(DICTIONARY, NIL, Dictionary, get, NIL, "key", NIL, "default", varray(Variant()));
ADDFUNC0R(ARRAY, INT, Array, size, varray());
ADDFUNC0R(ARRAY, BOOL, Array, empty, varray());
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index d193858966..9f172f0d57 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -2149,7 +2149,7 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid)
int idx = p_index;
if (idx < 0)
idx += 4;
- if (idx >= 0 || idx < 4) {
+ if (idx >= 0 && idx < 4) {
Color *v = reinterpret_cast<Color *>(_data._mem);
(*v)[idx] = p_value;
valid = true;
@@ -2524,7 +2524,7 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const {
int idx = p_index;
if (idx < 0)
idx += 4;
- if (idx >= 0 || idx < 4) {
+ if (idx >= 0 && idx < 4) {
const Color *v = reinterpret_cast<const Color *>(_data._mem);
valid = true;
return (*v)[idx];
diff --git a/core/vmap.h b/core/vmap.h
index 9fc99e636d..5f6d8190c6 100644
--- a/core/vmap.h
+++ b/core/vmap.h
@@ -36,22 +36,23 @@
template <class T, class V>
class VMap {
-
- struct _Pair {
+public:
+ struct Pair {
T key;
V value;
- _FORCE_INLINE_ _Pair() {}
+ _FORCE_INLINE_ Pair() {}
- _FORCE_INLINE_ _Pair(const T &p_key, const V &p_value) {
+ _FORCE_INLINE_ Pair(const T &p_key, const V &p_value) {
key = p_key;
value = p_value;
}
};
- CowData<_Pair> _cowdata;
+private:
+ CowData<Pair> _cowdata;
_FORCE_INLINE_ int _find(const T &p_val, bool &r_exact) const {
@@ -61,7 +62,7 @@ class VMap {
int low = 0;
int high = _cowdata.size() - 1;
- const _Pair *a = _cowdata.ptr();
+ const Pair *a = _cowdata.ptr();
int middle = 0;
#if DEBUG_ENABLED
@@ -95,7 +96,7 @@ class VMap {
int low = 0;
int high = _cowdata.size() - 1;
int middle;
- const _Pair *a = _cowdata.ptr();
+ const Pair *a = _cowdata.ptr();
while (low <= high) {
middle = (low + high) / 2;
@@ -121,7 +122,7 @@ public:
_cowdata.get_m(pos).value = p_val;
return pos;
}
- _cowdata.insert(pos, _Pair(p_key, p_val));
+ _cowdata.insert(pos, Pair(p_key, p_val));
return pos;
}
@@ -152,12 +153,12 @@ public:
_FORCE_INLINE_ int size() const { return _cowdata.size(); }
_FORCE_INLINE_ bool empty() const { return _cowdata.empty(); }
- const _Pair *get_array() const {
+ const Pair *get_array() const {
return _cowdata.ptr();
}
- _Pair *get_array() {
+ Pair *get_array() {
return _cowdata.ptrw();
}