summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/bind/core_bind.cpp7
-rw-r--r--core/bind/core_bind.h2
-rw-r--r--core/error_macros.h20
-rw-r--r--core/image.cpp4
-rw-r--r--core/image.h1
-rw-r--r--core/io/logger.h12
-rw-r--r--core/io/packet_peer.cpp2
-rw-r--r--core/io/resource_format_binary.cpp2
-rw-r--r--core/io/resource_importer.cpp57
-rw-r--r--core/io/resource_importer.h20
-rw-r--r--core/io/resource_loader.cpp27
-rw-r--r--core/io/resource_loader.h2
-rw-r--r--core/io/resource_saver.cpp2
-rw-r--r--core/math/basis.cpp10
-rw-r--r--core/math/geometry.cpp35
-rw-r--r--core/math/geometry.h2
-rw-r--r--core/math/quick_hull.cpp4
-rw-r--r--core/math/quick_hull.h2
-rw-r--r--core/math/random_pcg.cpp17
-rw-r--r--core/math/random_pcg.h21
-rw-r--r--core/object.cpp25
-rw-r--r--core/os/file_access.cpp17
-rw-r--r--core/os/file_access.h1
-rw-r--r--core/os/input.cpp1
-rw-r--r--core/os/input.h3
-rw-r--r--core/os/input_event.cpp43
-rw-r--r--core/os/input_event.h6
-rw-r--r--core/os/os.cpp11
-rw-r--r--core/os/os.h11
-rw-r--r--core/project_settings.cpp3
-rw-r--r--core/script_debugger_remote.cpp2
-rw-r--r--core/script_language.cpp30
-rw-r--r--core/script_language.h2
-rw-r--r--core/typedefs.h23
-rw-r--r--core/undo_redo.cpp11
-rw-r--r--core/undo_redo.h3
-rw-r--r--core/variant_op.cpp70
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: {