diff options
Diffstat (limited to 'core')
37 files changed, 450 insertions, 61 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index f6828ea76a..f5dbacd62d 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -1093,6 +1093,11 @@ void _OS::alert(const String &p_alert, const String &p_title) { OS::get_singleton()->alert(p_alert, p_title); } +bool _OS::request_permission(const String &p_name) { + + return OS::get_singleton()->request_permission(p_name); +} + _OS *_OS::singleton = NULL; void _OS::_bind_methods() { @@ -1265,6 +1270,8 @@ void _OS::_bind_methods() { ClassDB::bind_method(D_METHOD("get_power_seconds_left"), &_OS::get_power_seconds_left); ClassDB::bind_method(D_METHOD("get_power_percent_left"), &_OS::get_power_percent_left); + ClassDB::bind_method(D_METHOD("request_permission", "name"), &_OS::request_permission); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "clipboard"), "set_clipboard", "get_clipboard"); ADD_PROPERTY(PropertyInfo(Variant::INT, "current_screen"), "set_current_screen", "get_current_screen"); ADD_PROPERTY(PropertyInfo(Variant::INT, "exit_code"), "set_exit_code", "get_exit_code"); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index f3bc4644d8..803743bc93 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -356,6 +356,8 @@ public: bool has_feature(const String &p_feature) const; + bool request_permission(const String &p_name); + static _OS *get_singleton() { return singleton; } _OS(); diff --git a/core/error_macros.h b/core/error_macros.h index 3aa8ed4596..ca5ccd24cf 100644 --- a/core/error_macros.h +++ b/core/error_macros.h @@ -310,6 +310,16 @@ extern bool _err_error_exists; _err_error_exists = false; \ } +#define ERR_PRINT_ONCE(m_string) \ + { \ + static bool first_print = true; \ + if (first_print) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_string); \ + _err_error_exists = false; \ + first_print = false; \ + } \ + } + /** Print a warning string. */ @@ -325,6 +335,16 @@ extern bool _err_error_exists; _err_error_exists = false; \ } +#define WARN_PRINT_ONCE(m_string) \ + { \ + static bool first_print = true; \ + if (first_print) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_string, ERR_HANDLER_WARNING); \ + _err_error_exists = false; \ + first_print = false; \ + } \ + } + #define WARN_DEPRECATED \ { \ static volatile bool warning_shown = false; \ diff --git a/core/image.cpp b/core/image.cpp index 5a287ca50e..f547d7e973 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -735,6 +735,10 @@ static void _overlay(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, } } +bool Image::is_size_po2() const { + return uint32_t(width) == next_power_of_2(width) && uint32_t(height) == next_power_of_2(height); +} + void Image::resize_to_po2(bool p_square) { if (!_can_modify(format)) { diff --git a/core/image.h b/core/image.h index 872b84d565..69a42f169a 100644 --- a/core/image.h +++ b/core/image.h @@ -223,6 +223,7 @@ public: void resize(int p_width, int p_height, Interpolation p_interpolation = INTERPOLATE_BILINEAR); void shrink_x2(); void expand_x2_hq2x(); + bool is_size_po2() const; /** * Crop the image to a specific size, if larger, then the image is filled by black */ diff --git a/core/io/logger.h b/core/io/logger.h index 0b871a13de..ff5b8ce489 100644 --- a/core/io/logger.h +++ b/core/io/logger.h @@ -49,11 +49,11 @@ public: ERR_SHADER }; - virtual void logv(const char *p_format, va_list p_list, bool p_err) = 0; + virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0 = 0; virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR); - void logf(const char *p_format, ...); - void logf_error(const char *p_format, ...); + void logf(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3; + void logf_error(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3; virtual ~Logger(); }; @@ -64,7 +64,7 @@ public: class StdLogger : public Logger { public: - virtual void logv(const char *p_format, va_list p_list, bool p_err); + virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0; virtual ~StdLogger(); }; @@ -88,7 +88,7 @@ class RotatedFileLogger : public Logger { public: RotatedFileLogger(const String &p_base_path, int p_max_files = 10); - virtual void logv(const char *p_format, va_list p_list, bool p_err); + virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0; virtual ~RotatedFileLogger(); }; @@ -99,7 +99,7 @@ class CompositeLogger : public Logger { public: CompositeLogger(Vector<Logger *> p_loggers); - virtual void logv(const char *p_format, va_list p_list, bool p_err); + virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0; virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR); void add_logger(Logger *p_logger); diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp index 3aa1fcfd8f..d7bfdbbb37 100644 --- a/core/io/packet_peer.cpp +++ b/core/io/packet_peer.cpp @@ -224,7 +224,7 @@ Error PacketPeerStream::get_packet(const uint8_t **r_buffer, int &r_buffer_size) uint32_t len = decode_uint32(lbuf); ERR_FAIL_COND_V(remaining < (int)len, ERR_UNAVAILABLE); - ERR_FAIL_COND_V(input_buffer.size() < len, ERR_UNAVAILABLE); + ERR_FAIL_COND_V(input_buffer.size() < (int)len, ERR_UNAVAILABLE); ring_buffer.read(lbuf, 4); //get rid of first 4 bytes ring_buffer.read(input_buffer.ptrw(), len); // read packet diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index 6c48942d72..42070cd132 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -106,7 +106,7 @@ StringName ResourceInteractiveLoaderBinary::_get_string() { uint32_t id = f->get_32(); if (id & 0x80000000) { uint32_t len = id & 0x7FFFFFFF; - if (len > str_buf.size()) { + if ((int)len > str_buf.size()) { str_buf.resize(len); } if (len == 0) diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp index 9327e000f5..b5fa412576 100644 --- a/core/io/resource_importer.cpp +++ b/core/io/resource_importer.cpp @@ -33,6 +33,10 @@ #include "core/os/os.h" #include "core/variant_parser.h" +bool ResourceFormatImporter::SortImporterByName::operator()(const Ref<ResourceImporter> &p_a, const Ref<ResourceImporter> &p_b) const { + return p_a->get_importer_name() < p_b->get_importer_name(); +} + Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndType &r_path_and_type, bool *r_valid) const { Error err; @@ -90,6 +94,8 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy r_path_and_type.type = value; } else if (assign == "importer") { r_path_and_type.importer = value; + } else if (assign == "metadata") { + r_path_and_type.metadata = value; } else if (assign == "valid") { if (r_valid) { *r_valid = value; @@ -177,6 +183,11 @@ void ResourceFormatImporter::get_recognized_extensions_for_type(const String &p_ } } +bool ResourceFormatImporter::exists(const String &p_path) const { + + return FileAccess::exists(p_path + ".import"); +} + bool ResourceFormatImporter::recognize_path(const String &p_path, const String &p_for_type) const { return FileAccess::exists(p_path + ".import"); @@ -304,6 +315,18 @@ String ResourceFormatImporter::get_resource_type(const String &p_path) const { return pat.type; } +Variant ResourceFormatImporter::get_resource_metadata(const String &p_path) const { + PathAndType pat; + Error err = _get_path_and_type(p_path, pat); + + if (err != OK) { + + return Variant(); + } + + return pat.metadata; +} + void ResourceFormatImporter::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) { PathAndType pat; @@ -366,6 +389,40 @@ String ResourceFormatImporter::get_import_base_path(const String &p_for_file) co return "res://.import/" + p_for_file.get_file() + "-" + p_for_file.md5_text(); } +bool ResourceFormatImporter::are_import_settings_valid(const String &p_path) const { + + bool valid = true; + PathAndType pat; + _get_path_and_type(p_path, pat, &valid); + + if (!valid) { + return false; + } + + for (int i = 0; i < importers.size(); i++) { + if (importers[i]->get_importer_name() == pat.importer) { + if (!importers[i]->are_import_settings_valid(p_path)) { //importer thinks this is not valid + return false; + } + } + } + + return true; +} + +String ResourceFormatImporter::get_import_settings_hash() const { + + Vector<Ref<ResourceImporter> > sorted_importers = importers; + + sorted_importers.sort_custom<SortImporterByName>(); + + String hash; + for (int i = 0; i < sorted_importers.size(); i++) { + hash += ":" + sorted_importers[i]->get_importer_name() + ":" + sorted_importers[i]->get_import_settings_string(); + } + return hash.md5_text(); +} + ResourceFormatImporter *ResourceFormatImporter::singleton = NULL; ResourceFormatImporter::ResourceFormatImporter() { diff --git a/core/io/resource_importer.h b/core/io/resource_importer.h index 32c39a8085..1c146c33d7 100644 --- a/core/io/resource_importer.h +++ b/core/io/resource_importer.h @@ -43,12 +43,18 @@ class ResourceFormatImporter : public ResourceFormatLoader { String path; String type; String importer; + Variant metadata; }; Error _get_path_and_type(const String &p_path, PathAndType &r_path_and_type, bool *r_valid = NULL) const; static ResourceFormatImporter *singleton; + //need them to stay in order to compute the settings hash + struct SortImporterByName { + bool operator()(const Ref<ResourceImporter> &p_a, const Ref<ResourceImporter> &p_b) const; + }; + Vector<Ref<ResourceImporter> > importers; public: @@ -59,8 +65,11 @@ public: virtual bool recognize_path(const String &p_path, const String &p_for_type = String()) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; + virtual Variant get_resource_metadata(const String &p_path) const; virtual bool is_import_valid(const String &p_path) const; virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false); + virtual bool is_imported(const String &p_path) const { return recognize_path(p_path); } + virtual bool exists(const String &p_path) const; virtual bool can_be_imported(const String &p_path) const; virtual int get_import_order(const String &p_path) const; @@ -68,12 +77,17 @@ public: String get_internal_resource_path(const String &p_path) const; void get_internal_resource_path_list(const String &p_path, List<String> *r_paths); - void add_importer(const Ref<ResourceImporter> &p_importer) { importers.push_back(p_importer); } + void add_importer(const Ref<ResourceImporter> &p_importer) { + importers.push_back(p_importer); + } void remove_importer(const Ref<ResourceImporter> &p_importer) { importers.erase(p_importer); } Ref<ResourceImporter> get_importer_by_name(const String &p_name) const; Ref<ResourceImporter> get_importer_by_extension(const String &p_extension) const; void get_importers_for_extension(const String &p_extension, List<Ref<ResourceImporter> > *r_importers); + bool are_import_settings_valid(const String &p_path) const; + String get_import_settings_hash() const; + String get_import_base_path(const String &p_for_file) const; ResourceFormatImporter(); }; @@ -107,7 +121,9 @@ public: virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const = 0; virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const = 0; - virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = NULL) = 0; + virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = NULL, Variant *r_metadata = NULL) = 0; + virtual bool are_import_settings_valid(const String &p_path) const { return true; } + virtual String get_import_settings_string() const { return String(); } }; #endif // RESOURCE_IMPORTER_H diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 98309048bb..e4b694b64f 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -633,6 +633,31 @@ bool ResourceLoader::is_import_valid(const String &p_path) { return false; //not found } +bool ResourceLoader::is_imported(const String &p_path) { + + String path = _path_remap(p_path); + + String local_path; + if (path.is_rel_path()) + local_path = "res://" + path; + else + local_path = ProjectSettings::get_singleton()->localize_path(path); + + for (int i = 0; i < loader_count; i++) { + + if (!loader[i]->recognize_path(local_path)) + continue; + /* + if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint)) + continue; + */ + + return loader[i]->is_imported(p_path); + } + + return false; //not found +} + void ResourceLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) { String path = _path_remap(p_path); @@ -921,7 +946,7 @@ void ResourceLoader::add_custom_loaders() { for (List<StringName>::Element *E = global_classes.front(); E; E = E->next()) { StringName class_name = E->get(); - StringName base_class = ScriptServer::get_global_class_base(class_name); + StringName base_class = ScriptServer::get_global_class_native_base(class_name); if (base_class == custom_loader_base_class) { String path = ScriptServer::get_global_class_path(class_name); diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index 70eb1a3de0..ca7610a0d2 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -79,6 +79,7 @@ public: virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false); virtual Error rename_dependencies(const String &p_path, const Map<String, String> &p_map); virtual bool is_import_valid(const String &p_path) const { return true; } + virtual bool is_imported(const String &p_path) const { return false; } virtual int get_import_order(const String &p_path) const { return 0; } virtual ~ResourceFormatLoader() {} @@ -154,6 +155,7 @@ public: static void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false); static Error rename_dependencies(const String &p_path, const Map<String, String> &p_map); static bool is_import_valid(const String &p_path); + static bool is_imported(const String &p_path); static int get_import_order(const String &p_path); static void set_timestamp_on_load(bool p_timestamp) { timestamp_on_load = p_timestamp; } diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp index c992e2bf94..0cecca904d 100644 --- a/core/io/resource_saver.cpp +++ b/core/io/resource_saver.cpp @@ -249,7 +249,7 @@ void ResourceSaver::add_custom_savers() { for (List<StringName>::Element *E = global_classes.front(); E; E = E->next()) { StringName class_name = E->get(); - StringName base_class = ScriptServer::get_global_class_base(class_name); + StringName base_class = ScriptServer::get_global_class_native_base(class_name); if (base_class == custom_saver_base_class) { String path = ScriptServer::get_global_class_path(class_name); diff --git a/core/math/basis.cpp b/core/math/basis.cpp index c293e753a6..8816e3639a 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -76,23 +76,17 @@ void Basis::invert() { } void Basis::orthonormalize() { - /* this check is undesired, the matrix could be wrong but we still may want to generate a valid one - * for practical purposes + #ifdef MATH_CHECKS ERR_FAIL_COND(determinant() == 0); #endif -*/ + // Gram-Schmidt Process Vector3 x = get_axis(0); Vector3 y = get_axis(1); Vector3 z = get_axis(2); -#ifdef MATH_CHECKS - ERR_FAIL_COND(x.length_squared() == 0); - ERR_FAIL_COND(y.length_squared() == 0); - ERR_FAIL_COND(z.length_squared() == 0); -#endif x.normalize(); y = (y - x * (x.dot(y))); y.normalize(); diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp index 12c88f43b3..194a6f6352 100644 --- a/core/math/geometry.cpp +++ b/core/math/geometry.cpp @@ -31,6 +31,7 @@ #include "geometry.h" #include "core/print_string.h" +#include "thirdparty/misc/triangulator.h" /* this implementation is very inefficient, commenting unless bugs happen. See the other one. bool Geometry::is_point_in_polygon(const Vector2 &p_point, const Vector<Vector2> &p_polygon) { @@ -737,6 +738,40 @@ PoolVector<Face3> Geometry::wrap_geometry(PoolVector<Face3> p_array, real_t *p_e return wrapped_faces; } +Vector<Vector<Vector2> > Geometry::decompose_polygon_in_convex(Vector<Point2> polygon) { + Vector<Vector<Vector2> > decomp; + List<TriangulatorPoly> in_poly, out_poly; + + TriangulatorPoly inp; + inp.Init(polygon.size()); + for (int i = 0; i < polygon.size(); i++) { + inp.GetPoint(i) = polygon[i]; + } + inp.SetOrientation(TRIANGULATOR_CCW); + in_poly.push_back(inp); + TriangulatorPartition tpart; + if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) { //failed! + ERR_PRINT("Convex decomposing failed!"); + return decomp; + } + + decomp.resize(out_poly.size()); + int idx = 0; + for (List<TriangulatorPoly>::Element *I = out_poly.front(); I; I = I->next()) { + TriangulatorPoly &tp = I->get(); + + decomp.write[idx].resize(tp.GetNumPoints()); + + for (int i = 0; i < tp.GetNumPoints(); i++) { + decomp.write[idx].write[i] = tp.GetPoint(i); + } + + idx++; + } + + return decomp; +} + Geometry::MeshData Geometry::build_convex_mesh(const PoolVector<Plane> &p_planes) { MeshData mesh; diff --git a/core/math/geometry.h b/core/math/geometry.h index f927a63ed5..4b478b6b16 100644 --- a/core/math/geometry.h +++ b/core/math/geometry.h @@ -950,6 +950,8 @@ public: return H; } + static Vector<Vector<Vector2> > decompose_polygon_in_convex(Vector<Point2> polygon); + static MeshData build_convex_mesh(const PoolVector<Plane> &p_planes); static PoolVector<Plane> build_sphere_planes(real_t p_radius, int p_lats, int p_lons, Vector3::Axis p_axis = Vector3::AXIS_Z); static PoolVector<Plane> build_box_planes(const Vector3 &p_extents); diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp index bc2b4e6fe0..fc2eb1454d 100644 --- a/core/math/quick_hull.cpp +++ b/core/math/quick_hull.cpp @@ -36,8 +36,6 @@ uint32_t QuickHull::debug_stop_after = 0xFFFFFFFF; Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_mesh) { - static const real_t over_tolerance = 0.0001; - /* CREATE AABB VOLUME */ AABB aabb; @@ -180,6 +178,8 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me faces.push_back(f); } + real_t over_tolerance = 3 * UNIT_EPSILON * (aabb.size.x + aabb.size.y + aabb.size.z); + /* COMPUTE AVAILABLE VERTICES */ for (int i = 0; i < p_points.size(); i++) { diff --git a/core/math/quick_hull.h b/core/math/quick_hull.h index 2e659cab6e..a445a47cbe 100644 --- a/core/math/quick_hull.h +++ b/core/math/quick_hull.h @@ -64,7 +64,7 @@ public: struct Face { Plane plane; - int vertices[3]; + uint32_t vertices[3]; Vector<int> points_over; bool operator<(const Face &p_face) const { diff --git a/core/math/random_pcg.cpp b/core/math/random_pcg.cpp index 8bbcca88fe..45467b32b2 100644 --- a/core/math/random_pcg.cpp +++ b/core/math/random_pcg.cpp @@ -32,24 +32,25 @@ #include "core/os/os.h" -RandomPCG::RandomPCG(uint64_t seed, uint64_t inc) : - pcg() { - pcg.state = seed; - pcg.inc = inc; +RandomPCG::RandomPCG(uint64_t p_seed, uint64_t p_inc) : + pcg(), + current_seed(DEFAULT_SEED) { + pcg.inc = p_inc; + seed(p_seed); } void RandomPCG::randomize() { seed(OS::get_singleton()->get_ticks_usec() * pcg.state + PCG_DEFAULT_INC_64); } -double RandomPCG::random(double from, double to) { +double RandomPCG::random(double p_from, double p_to) { unsigned int r = rand(); double ret = (double)r / (double)RANDOM_MAX; - return (ret) * (to - from) + from; + return (ret) * (p_to - p_from) + p_from; } -float RandomPCG::random(float from, float to) { +float RandomPCG::random(float p_from, float p_to) { unsigned int r = rand(); float ret = (float)r / (float)RANDOM_MAX; - return (ret) * (to - from) + from; + return (ret) * (p_to - p_from) + p_from; } diff --git a/core/math/random_pcg.h b/core/math/random_pcg.h index 2a69d43904..230eb9a11b 100644 --- a/core/math/random_pcg.h +++ b/core/math/random_pcg.h @@ -37,28 +37,33 @@ class RandomPCG { pcg32_random_t pcg; + uint64_t current_seed; // seed with this to get the same state public: static const uint64_t DEFAULT_SEED = 12047754176567800795U; static const uint64_t DEFAULT_INC = PCG_DEFAULT_INC_64; static const uint64_t RANDOM_MAX = 0xFFFFFFFF; - RandomPCG(uint64_t seed = DEFAULT_SEED, uint64_t inc = PCG_DEFAULT_INC_64); + RandomPCG(uint64_t p_seed = DEFAULT_SEED, uint64_t p_inc = PCG_DEFAULT_INC_64); - _FORCE_INLINE_ void seed(uint64_t seed) { - pcg.state = seed; + _FORCE_INLINE_ void seed(uint64_t p_seed) { + current_seed = p_seed; + pcg.state = p_seed; pcg32_random_r(&pcg); // Force changing internal state to avoid initial 0 } - _FORCE_INLINE_ uint64_t get_seed() { return pcg.state; } + _FORCE_INLINE_ uint64_t get_seed() { return current_seed; } void randomize(); - _FORCE_INLINE_ uint32_t rand() { return pcg32_random_r(&pcg); } + _FORCE_INLINE_ uint32_t rand() { + current_seed = pcg.state; + return pcg32_random_r(&pcg); + } _FORCE_INLINE_ double randd() { return (double)rand() / (double)RANDOM_MAX; } _FORCE_INLINE_ float randf() { 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); } + double random(double p_from, double p_to); + float random(float p_from, float p_to); + real_t random(int p_from, int p_to) { return (real_t)random((real_t)p_from, (real_t)p_to); } }; #endif // RANDOM_PCG_H diff --git a/core/object.cpp b/core/object.cpp index c46ecc5193..8b693f039c 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -832,23 +832,22 @@ void Object::setvar(const Variant &p_key, const Variant &p_value, bool *r_valid) } Variant Object::callv(const StringName &p_method, const Array &p_args) { + const Variant **argptrs = NULL; - if (p_args.size() == 0) { - return call(p_method); - } - - Vector<Variant> args; - args.resize(p_args.size()); - Vector<const Variant *> argptrs; - argptrs.resize(p_args.size()); - - for (int i = 0; i < p_args.size(); i++) { - args.write[i] = p_args[i]; - argptrs.write[i] = &args[i]; + if (p_args.size() > 0) { + argptrs = (const Variant **)alloca(sizeof(Variant *) * p_args.size()); + for (int i = 0; i < p_args.size(); i++) { + argptrs[i] = &p_args[i]; + } } Variant::CallError ce; - return call(p_method, (const Variant **)argptrs.ptr(), p_args.size(), ce); + Variant ret = call(p_method, argptrs, p_args.size(), ce); + if (ce.error != Variant::CallError::CALL_OK) { + ERR_EXPLAIN("Error calling method from 'callv': " + Variant::get_call_error_text(this, p_method, argptrs, p_args.size(), ce)); + ERR_FAIL_V(Variant()); + } + return ret; } Variant Object::call(const StringName &p_name, VARIANT_ARG_DECLARE) { diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp index d1f8236898..39d9f45bd7 100644 --- a/core/os/file_access.cpp +++ b/core/os/file_access.cpp @@ -409,6 +409,23 @@ int FileAccess::get_buffer(uint8_t *p_dst, int p_length) const { return i; } +String FileAccess::get_as_utf8_string() const { + PoolVector<uint8_t> sourcef; + int len = get_len(); + sourcef.resize(len + 1); + + PoolVector<uint8_t>::Write w = sourcef.write(); + int r = get_buffer(w.ptr(), len); + ERR_FAIL_COND_V(r != len, String()); + w[len] = 0; + + String s; + if (s.parse_utf8((const char *)w.ptr())) { + return String(); + } + return s; +} + void FileAccess::store_16(uint16_t p_dest) { uint8_t a, b; diff --git a/core/os/file_access.h b/core/os/file_access.h index 7bfbf6e7f0..c65b75369c 100644 --- a/core/os/file_access.h +++ b/core/os/file_access.h @@ -113,6 +113,7 @@ public: virtual String get_line() const; virtual String get_token() const; virtual Vector<String> get_csv_line(const String &p_delim = ",") const; + virtual String get_as_utf8_string() const; /**< use this for files WRITTEN in _big_ endian machines (ie, amiga/mac) * It's not about the current CPU type but file formats. diff --git a/core/os/input.cpp b/core/os/input.cpp index cf11ba3c6d..caa9fb1493 100644 --- a/core/os/input.cpp +++ b/core/os/input.cpp @@ -91,6 +91,7 @@ void Input::_bind_methods() { 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())); ClassDB::bind_method(D_METHOD("parse_input_event", "event"), &Input::parse_input_event); + ClassDB::bind_method(D_METHOD("set_use_accumulated_input", "enable"), &Input::set_use_accumulated_input); BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE); BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN); diff --git a/core/os/input.h b/core/os/input.h index b354acd961..c8b80b28d0 100644 --- a/core/os/input.h +++ b/core/os/input.h @@ -132,6 +132,9 @@ public: virtual int get_joy_axis_index_from_string(String p_axis) = 0; virtual void parse_input_event(const Ref<InputEvent> &p_event) = 0; + virtual void accumulate_input_event(const Ref<InputEvent> &p_event) = 0; + virtual void flush_accumulated_events() = 0; + virtual void set_use_accumulated_input(bool p_enable) = 0; Input(); }; diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp index 24ec8a1963..25a5c2afeb 100644 --- a/core/os/input_event.cpp +++ b/core/os/input_event.cpp @@ -33,6 +33,9 @@ #include "core/input_map.h" #include "core/os/keyboard.h" +const int InputEvent::DEVICE_ID_TOUCH_MOUSE = -1; +const int InputEvent::DEVICE_ID_INTERNAL = -2; + void InputEvent::set_device(int p_device) { device = p_device; } @@ -122,6 +125,8 @@ void InputEvent::_bind_methods() { ClassDB::bind_method(D_METHOD("is_action_type"), &InputEvent::is_action_type); + ClassDB::bind_method(D_METHOD("accumulate", "with_event"), &InputEvent::accumulate); + ClassDB::bind_method(D_METHOD("xformed_by", "xform", "local_ofs"), &InputEvent::xformed_by, DEFVAL(Vector2())); ADD_PROPERTY(PropertyInfo(Variant::INT, "device"), "set_device", "get_device"); @@ -620,6 +625,44 @@ String InputEventMouseMotion::as_text() const { return "InputEventMouseMotion : button_mask=" + button_mask_string + ", position=(" + String(get_position()) + "), relative=(" + String(get_relative()) + "), speed=(" + String(get_speed()) + ")"; } +bool InputEventMouseMotion::accumulate(const Ref<InputEvent> &p_event) { + + Ref<InputEventMouseMotion> motion = p_event; + if (motion.is_null()) + return false; + + if (is_pressed() != motion->is_pressed()) { + return false; + } + + if (get_button_mask() != motion->get_button_mask()) { + return false; + } + + if (get_shift() != motion->get_shift()) { + return false; + } + + if (get_control() != motion->get_control()) { + return false; + } + + if (get_alt() != motion->get_alt()) { + return false; + } + + if (get_metakey() != motion->get_metakey()) { + return false; + } + + set_position(motion->get_position()); + set_global_position(motion->get_global_position()); + set_speed(motion->get_speed()); + relative += motion->get_relative(); + + return true; +} + void InputEventMouseMotion::_bind_methods() { ClassDB::bind_method(D_METHOD("set_relative", "relative"), &InputEventMouseMotion::set_relative); diff --git a/core/os/input_event.h b/core/os/input_event.h index a6a7012298..ba01516519 100644 --- a/core/os/input_event.h +++ b/core/os/input_event.h @@ -165,6 +165,9 @@ protected: static void _bind_methods(); public: + static const int DEVICE_ID_TOUCH_MOUSE; + static const int DEVICE_ID_INTERNAL; + void set_device(int p_device); int get_device() const; @@ -186,6 +189,7 @@ public: virtual bool shortcut_match(const Ref<InputEvent> &p_event) const; virtual bool is_action_type() const; + virtual bool accumulate(const Ref<InputEvent> &p_event) { return false; } InputEvent(); }; @@ -351,6 +355,8 @@ public: virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const; virtual String as_text() const; + virtual bool accumulate(const Ref<InputEvent> &p_event); + InputEventMouseMotion(); }; diff --git a/core/os/os.cpp b/core/os/os.cpp index d2d39d253a..03e63f636e 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -569,6 +569,11 @@ int OS::get_power_percent_left() { return -1; } +void OS::set_has_server_feature_callback(HasServerFeatureCallback p_callback) { + + has_server_feature_callback = p_callback; +} + bool OS::has_feature(const String &p_feature) { if (p_feature == get_name()) @@ -625,6 +630,10 @@ bool OS::has_feature(const String &p_feature) { if (_check_internal_feature_support(p_feature)) return true; + if (has_server_feature_callback && has_server_feature_callback(p_feature)) { + return true; + } + if (ProjectSettings::get_singleton()->has_custom_feature(p_feature)) return true; @@ -729,6 +738,8 @@ OS::OS() { _logger = NULL; + has_server_feature_callback = NULL; + Vector<Logger *> loggers; loggers.push_back(memnew(StdLogger)); _set_logger(memnew(CompositeLogger(loggers))); diff --git a/core/os/os.h b/core/os/os.h index 396555970a..d02d5a2c84 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -77,6 +77,7 @@ protected: public: typedef void (*ImeCallback)(void *p_inp, String p_text, Point2 p_selection); + typedef bool (*HasServerFeatureCallback)(const String &p_feature); enum PowerState { POWERSTATE_UNKNOWN, /**< cannot determine power status */ @@ -121,6 +122,7 @@ public: protected: friend class Main; + HasServerFeatureCallback has_server_feature_callback; RenderThreadMode _render_thread_mode; // functions used by main to initialize/deinitialize the OS @@ -146,8 +148,8 @@ public: static OS *get_singleton(); void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, Logger::ErrorType p_type = Logger::ERR_ERROR); - void print(const char *p_format, ...); - void printerr(const char *p_format, ...); + void print(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3; + void printerr(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3; virtual void alert(const String &p_alert, const String &p_title = "ALERT!") = 0; virtual String get_stdin_string(bool p_block = true) = 0; @@ -507,6 +509,8 @@ public: virtual void force_process_input(){}; bool has_feature(const String &p_feature); + void set_has_server_feature_callback(HasServerFeatureCallback p_callback); + bool is_layered_allowed() const { return _allow_layered; } bool is_hidpi_allowed() const { return _allow_hidpi; } @@ -514,6 +518,9 @@ public: bool is_restart_on_exit_set() const; List<String> get_restart_on_exit_arguments() const; + virtual bool request_permission(const String &p_name) { return true; } + + virtual void process_and_drop_events() {} OS(); virtual ~OS(); }; diff --git a/core/project_settings.cpp b/core/project_settings.cpp index 6b4895d688..02c7c9e029 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -1185,6 +1185,9 @@ ProjectSettings::ProjectSettings() { Compression::gzip_level = GLOBAL_DEF("compression/formats/gzip/compression_level", Z_DEFAULT_COMPRESSION); custom_prop_info["compression/formats/gzip/compression_level"] = PropertyInfo(Variant::INT, "compression/formats/gzip/compression_level", PROPERTY_HINT_RANGE, "-1,9,1"); + // Would ideally be defined in an Android-specific file, but then it doesn't appear in the docs + GLOBAL_DEF("android/modules", ""); + using_datapack = false; } diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp index 9780cc48ea..e7ff7a3aef 100644 --- a/core/script_debugger_remote.cpp +++ b/core/script_debugger_remote.cpp @@ -311,6 +311,7 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue) } else { OS::get_singleton()->delay_usec(10000); + OS::get_singleton()->process_and_drop_events(); } } @@ -1054,7 +1055,6 @@ void ScriptDebuggerRemote::profiling_set_frame_times(float p_frame_time, float p physics_frame_time = p_physics_frame_time; } - ScriptDebuggerRemote::ResourceUsageFunc ScriptDebuggerRemote::resource_usage_func = NULL; ScriptDebuggerRemote::ScriptDebuggerRemote() : diff --git a/core/script_language.cpp b/core/script_language.cpp index f0310ffc31..4a6f904f9d 100644 --- a/core/script_language.cpp +++ b/core/script_language.cpp @@ -190,6 +190,14 @@ StringName ScriptServer::get_global_class_base(const String &p_class) { ERR_FAIL_COND_V(!global_classes.has(p_class), String()); return global_classes[p_class].base; } +StringName ScriptServer::get_global_class_native_base(const String &p_class) { + ERR_FAIL_COND_V(!global_classes.has(p_class), String()); + String base = global_classes[p_class].base; + while (global_classes.has(base)) { + base = global_classes[base].base; + } + return base; +} void ScriptServer::get_global_class_list(List<StringName> *r_global_classes) { const StringName *K = NULL; List<StringName> classes; @@ -409,6 +417,11 @@ bool PlaceHolderScriptInstance::get(const StringName &p_name, Variant &r_ret) co return true; } + if (constants.has(p_name)) { + r_ret = constants[p_name]; + return true; + } + if (!script->is_placeholder_fallback_enabled()) { Variant defval; if (script->get_property_default_value(p_name, defval)) { @@ -444,6 +457,13 @@ Variant::Type PlaceHolderScriptInstance::get_property_type(const StringName &p_n *r_is_valid = true; return values[p_name].get_type(); } + + if (constants.has(p_name)) { + if (r_is_valid) + *r_is_valid = true; + return constants[p_name].get_type(); + } + if (r_is_valid) *r_is_valid = false; @@ -513,6 +533,9 @@ void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties, c owner->_change_notify(); } //change notify + + constants.clear(); + script->get_constants(&constants); } void PlaceHolderScriptInstance::property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid) { @@ -552,6 +575,13 @@ Variant PlaceHolderScriptInstance::property_get_fallback(const StringName &p_nam *r_valid = true; return E->value(); } + + E = constants.find(p_name); + if (E) { + if (r_valid) + *r_valid = true; + return E->value(); + } } if (r_valid) diff --git a/core/script_language.h b/core/script_language.h index 2d35097692..b6d7bea9c7 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -87,6 +87,7 @@ public: static StringName get_global_class_language(const StringName &p_class); static String get_global_class_path(const String &p_class); static StringName get_global_class_base(const String &p_class); + static StringName get_global_class_native_base(const String &p_class); static void get_global_class_list(List<StringName> *r_global_classes); static void save_global_classes(); @@ -336,6 +337,7 @@ class PlaceHolderScriptInstance : public ScriptInstance { Object *owner; List<PropertyInfo> properties; Map<StringName, Variant> values; + Map<StringName, Variant> constants; ScriptLanguage *language; Ref<Script> script; diff --git a/core/typedefs.h b/core/typedefs.h index e01e1c00b9..03514466c0 100644 --- a/core/typedefs.h +++ b/core/typedefs.h @@ -250,21 +250,34 @@ static inline int get_shift_from_power_of_2(unsigned int p_pixel) { } /** Swap 16 bits value for endianness */ +#if defined(__GNUC__) || _llvm_has_builtin(__builtin_bswap16) +#define BSWAP16(x) __builtin_bswap16(x) +#else static inline uint16_t BSWAP16(uint16_t x) { return (x >> 8) | (x << 8); } +#endif + /** Swap 32 bits value for endianness */ +#if defined(__GNUC__) || _llvm_has_builtin(__builtin_bswap32) +#define BSWAP32(x) __builtin_bswap32(x) +#else static inline uint32_t BSWAP32(uint32_t x) { return ((x << 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x >> 24)); } -/** Swap 64 bits value for endianness */ +#endif +/** Swap 64 bits value for endianness */ +#if defined(__GNUC__) || _llvm_has_builtin(__builtin_bswap64) +#define BSWAP64(x) __builtin_bswap64(x) +#else static inline uint64_t BSWAP64(uint64_t x) { x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32; x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16; x = (x & 0x00FF00FF00FF00FF) << 8 | (x & 0xFF00FF00FF00FF00) >> 8; return x; } +#endif /** When compiling with RTTI, we can add an "extra" * layer of safeness in many operations, so dynamic_cast @@ -307,4 +320,12 @@ struct _GlobalLock { #define unlikely(x) x #endif +#if defined(__GNUC__) +#define _PRINTF_FORMAT_ATTRIBUTE_2_0 __attribute__((format(printf, 2, 0))) +#define _PRINTF_FORMAT_ATTRIBUTE_2_3 __attribute__((format(printf, 2, 3))) +#else +#define _PRINTF_FORMAT_ATTRIBUTE_2_0 +#define _PRINTF_FORMAT_ATTRIBUTE_2_3 +#endif + #endif // TYPEDEFS_H diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp index 00894b41d8..e13164d50f 100644 --- a/core/undo_redo.cpp +++ b/core/undo_redo.cpp @@ -239,6 +239,10 @@ void UndoRedo::_pop_history_tail() { } } +bool UndoRedo::is_commiting_action() const { + return commiting > 0; +} + void UndoRedo::commit_action() { ERR_FAIL_COND(action_level <= 0); @@ -246,8 +250,9 @@ void UndoRedo::commit_action() { if (action_level > 0) return; //still nested + commiting++; redo(); // perform action - + commiting--; if (callback && actions.size() > 0) { callback(callback_ud, actions[actions.size() - 1].name); } @@ -321,6 +326,7 @@ bool UndoRedo::redo() { if ((current_action + 1) >= actions.size()) return false; //nothing to redo + current_action++; _process_operation_list(actions.write[current_action].do_ops.front()); @@ -337,7 +343,6 @@ bool UndoRedo::undo() { _process_operation_list(actions.write[current_action].undo_ops.front()); current_action--; version--; - return true; } @@ -386,6 +391,7 @@ void UndoRedo::set_property_notify_callback(PropertyNotifyCallback p_property_ca UndoRedo::UndoRedo() { + commiting = 0; version = 1; action_level = 0; current_action = -1; @@ -484,6 +490,7 @@ void UndoRedo::_bind_methods() { ClassDB::bind_method(D_METHOD("create_action", "name", "merge_mode"), &UndoRedo::create_action, DEFVAL(MERGE_DISABLE)); ClassDB::bind_method(D_METHOD("commit_action"), &UndoRedo::commit_action); + ClassDB::bind_method(D_METHOD("is_commiting_action"), &UndoRedo::is_commiting_action); //ClassDB::bind_method(D_METHOD("add_do_method","p_object", "p_method", "VARIANT_ARG_LIST"),&UndoRedo::add_do_method); //ClassDB::bind_method(D_METHOD("add_undo_method","p_object", "p_method", "VARIANT_ARG_LIST"),&UndoRedo::add_undo_method); diff --git a/core/undo_redo.h b/core/undo_redo.h index 4ee64dbfcf..b626149ce6 100644 --- a/core/undo_redo.h +++ b/core/undo_redo.h @@ -94,6 +94,8 @@ private: MethodNotifyCallback method_callback; PropertyNotifyCallback property_callback; + int commiting; + protected: static void _bind_methods(); @@ -107,6 +109,7 @@ public: void add_do_reference(Object *p_object); void add_undo_reference(Object *p_object); + bool is_commiting_action() const; void commit_action(); bool redo(); diff --git a/core/variant_op.cpp b/core/variant_op.cpp index 26851e4c23..b40b6ce4a6 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -3656,11 +3656,55 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & } return; case POOL_INT_ARRAY: { - r_dst = a; + const PoolVector<int> *arr_a = reinterpret_cast<const PoolVector<int> *>(a._data._mem); + const PoolVector<int> *arr_b = reinterpret_cast<const PoolVector<int> *>(b._data._mem); + int sz = arr_a->size(); + if (sz == 0 || arr_b->size() != sz) { + + r_dst = a; + } else { + + PoolVector<int> v; + v.resize(sz); + { + PoolVector<int>::Write vw = v.write(); + PoolVector<int>::Read ar = arr_a->read(); + PoolVector<int>::Read br = arr_b->read(); + + Variant va; + for (int i = 0; i < sz; i++) { + Variant::interpolate(ar[i], br[i], c, va); + vw[i] = va; + } + } + r_dst = v; + } } return; case POOL_REAL_ARRAY: { - r_dst = a; + const PoolVector<real_t> *arr_a = reinterpret_cast<const PoolVector<real_t> *>(a._data._mem); + const PoolVector<real_t> *arr_b = reinterpret_cast<const PoolVector<real_t> *>(b._data._mem); + int sz = arr_a->size(); + if (sz == 0 || arr_b->size() != sz) { + + r_dst = a; + } else { + + PoolVector<real_t> v; + v.resize(sz); + { + PoolVector<real_t>::Write vw = v.write(); + PoolVector<real_t>::Read ar = arr_a->read(); + PoolVector<real_t>::Read br = arr_b->read(); + + Variant va; + for (int i = 0; i < sz; i++) { + Variant::interpolate(ar[i], br[i], c, va); + vw[i] = va; + } + } + r_dst = v; + } } return; case POOL_STRING_ARRAY: { @@ -3717,7 +3761,27 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & } return; case POOL_COLOR_ARRAY: { - r_dst = a; + const PoolVector<Color> *arr_a = reinterpret_cast<const PoolVector<Color> *>(a._data._mem); + const PoolVector<Color> *arr_b = reinterpret_cast<const PoolVector<Color> *>(b._data._mem); + int sz = arr_a->size(); + if (sz == 0 || arr_b->size() != sz) { + + r_dst = a; + } else { + + PoolVector<Color> v; + v.resize(sz); + { + PoolVector<Color>::Write vw = v.write(); + PoolVector<Color>::Read ar = arr_a->read(); + PoolVector<Color>::Read br = arr_b->read(); + + for (int i = 0; i < sz; i++) { + vw[i] = ar[i].linear_interpolate(br[i], c); + } + } + r_dst = v; + } } return; default: { |