diff options
Diffstat (limited to 'core')
32 files changed, 394 insertions, 81 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index cd28081f76..0032c43179 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -1754,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) @@ -1853,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); @@ -1936,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); @@ -1943,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); @@ -1954,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); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 437d7515c6..720b14bf56 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -455,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; @@ -480,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 6565d242a2..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 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/image.cpp b/core/image.cpp index 172f5e517a..698a0b0b98 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; } 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/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/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/object.cpp b/core/object.cpp index 6a6749f3b8..ea77090a45 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -1715,6 +1715,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); @@ -1771,6 +1773,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; @@ -1935,30 +1941,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 25d41140aa..88a98dacbe 100644 --- a/core/object.h +++ b/core/object.h @@ -698,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/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/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/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/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(); } |