summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/image.cpp144
-rw-r--r--core/image.h11
-rw-r--r--core/message_queue.cpp2
-rw-r--r--core/object.cpp6
-rw-r--r--core/os/os.cpp14
-rw-r--r--core/os/os.h10
-rw-r--r--core/project_settings.cpp12
-rw-r--r--core/project_settings.h11
-rw-r--r--core/register_core_types.cpp2
-rw-r--r--core/script_language.h2
-rw-r--r--core/ustring.cpp8
-rw-r--r--core/vector.h13
12 files changed, 189 insertions, 46 deletions
diff --git a/core/image.cpp b/core/image.cpp
index b0bed80a6f..19440d1718 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -33,6 +33,7 @@
#include "core/io/image_loader.h"
#include "core/os/copymem.h"
#include "hash_map.h"
+#include "math_funcs.h"
#include "print_string.h"
#include "thirdparty/misc/hq2x.h"
@@ -525,7 +526,7 @@ static double _bicubic_interp_kernel(double x) {
}
template <int CC>
-static void _scale_cubic(const uint8_t *p_src, uint8_t *p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
+static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
// get source image size
int width = p_src_width;
@@ -555,7 +556,7 @@ static void _scale_cubic(const uint8_t *p_src, uint8_t *p_dst, uint32_t p_src_wi
// initial pixel value
- uint8_t *dst = p_dst + (y * p_dst_width + x) * CC;
+ uint8_t *__restrict dst = p_dst + (y * p_dst_width + x) * CC;
double color[CC];
for (int i = 0; i < CC; i++) {
@@ -583,7 +584,7 @@ static void _scale_cubic(const uint8_t *p_src, uint8_t *p_dst, uint32_t p_src_wi
ox2 = xmax;
// get pixel of original image
- const uint8_t *p = p_src + (oy2 * p_src_width + ox2) * CC;
+ const uint8_t *__restrict p = p_src + (oy2 * p_src_width + ox2) * CC;
for (int i = 0; i < CC; i++) {
@@ -600,7 +601,7 @@ static void _scale_cubic(const uint8_t *p_src, uint8_t *p_dst, uint32_t p_src_wi
}
template <int CC>
-static void _scale_bilinear(const uint8_t *p_src, uint8_t *p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
+static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
enum {
FRAC_BITS = 8,
@@ -655,7 +656,7 @@ static void _scale_bilinear(const uint8_t *p_src, uint8_t *p_dst, uint32_t p_src
}
template <int CC>
-static void _scale_nearest(const uint8_t *p_src, uint8_t *p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
+static void _scale_nearest(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
for (uint32_t i = 0; i < p_dst_height; i++) {
@@ -676,6 +677,16 @@ static void _scale_nearest(const uint8_t *p_src, uint8_t *p_dst, uint32_t p_src_
}
}
+static void _overlay(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, float p_alpha, uint32_t p_width, uint32_t p_height, uint32_t p_pixel_size) {
+
+ uint16_t alpha = CLAMP((uint16_t)(p_alpha * 256.0f), 0, 256);
+
+ for (uint32_t i = 0; i < p_width * p_height * p_pixel_size; i++) {
+
+ p_dst[i] = (p_dst[i] * (256 - alpha) + p_src[i] * alpha) >> 8;
+ }
+}
+
void Image::resize_to_po2(bool p_square) {
if (!_can_modify(format)) {
@@ -707,6 +718,8 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
ERR_FAIL();
}
+ bool mipmap_aware = p_interpolation == INTERPOLATE_TRILINEAR /* || p_interpolation == INTERPOLATE_TRICUBIC */;
+
ERR_FAIL_COND(p_width <= 0);
ERR_FAIL_COND(p_height <= 0);
ERR_FAIL_COND(p_width > MAX_WIDTH);
@@ -717,6 +730,32 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
Image dst(p_width, p_height, 0, format);
+ // Setup mipmap-aware scaling
+ Image dst2;
+ int mip1;
+ int mip2;
+ float mip1_weight;
+ if (mipmap_aware) {
+ float avg_scale = ((float)p_width / width + (float)p_height / height) * 0.5f;
+ if (avg_scale >= 1.0f) {
+ mipmap_aware = false;
+ } else {
+ float level = Math::log(1.0f / avg_scale) / Math::log(2.0f);
+ mip1 = CLAMP((int)Math::floor(level), 0, get_mipmap_count());
+ mip2 = CLAMP((int)Math::ceil(level), 0, get_mipmap_count());
+ mip1_weight = 1.0f - (level - mip1);
+ }
+ }
+ bool interpolate_mipmaps = mipmap_aware && mip1 != mip2;
+ if (interpolate_mipmaps) {
+ dst2.create(p_width, p_height, 0, format);
+ }
+ bool had_mipmaps = mipmaps;
+ if (interpolate_mipmaps && !had_mipmaps) {
+ generate_mipmaps();
+ }
+ // --
+
PoolVector<uint8_t>::Read r = data.read();
const unsigned char *r_ptr = r.ptr();
@@ -734,13 +773,57 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
case 4: _scale_nearest<4>(r_ptr, w_ptr, width, height, p_width, p_height); break;
}
} break;
- case INTERPOLATE_BILINEAR: {
+ case INTERPOLATE_BILINEAR:
+ case INTERPOLATE_TRILINEAR: {
+
+ for (int i = 0; i < 2; ++i) {
+ int src_width;
+ int src_height;
+ const unsigned char *src_ptr;
+
+ if (!mipmap_aware) {
+ if (i == 0) {
+ // Standard behavior
+ src_width = width;
+ src_height = height;
+ src_ptr = r_ptr;
+ } else {
+ // No need for a second iteration
+ break;
+ }
+ } else {
+ if (i == 0) {
+ // Read from the first mipmap that will be interpolated
+ // (if both levels are the same, we will not interpolate, but at least we'll sample from the right level)
+ int offs;
+ _get_mipmap_offset_and_size(mip1, offs, src_width, src_height);
+ src_ptr = r_ptr + offs;
+ } else if (!interpolate_mipmaps) {
+ // No need generate a second image
+ break;
+ } else {
+ // Switch to read from the second mipmap that will be interpolated
+ int offs;
+ _get_mipmap_offset_and_size(mip2, offs, src_width, src_height);
+ src_ptr = r_ptr + offs;
+ // Switch to write to the second destination image
+ w = dst2.data.write();
+ w_ptr = w.ptr();
+ }
+ }
- switch (get_format_pixel_size(format)) {
- case 1: _scale_bilinear<1>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 2: _scale_bilinear<2>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 3: _scale_bilinear<3>(r_ptr, w_ptr, width, height, p_width, p_height); break;
- case 4: _scale_bilinear<4>(r_ptr, w_ptr, width, height, p_width, p_height); break;
+ switch (get_format_pixel_size(format)) {
+ case 1: _scale_bilinear<1>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
+ case 2: _scale_bilinear<2>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
+ case 3: _scale_bilinear<3>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
+ case 4: _scale_bilinear<4>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break;
+ }
+ }
+
+ if (interpolate_mipmaps) {
+ // Switch to read again from the first scaled mipmap to overlay it over the second
+ r = dst.data.read();
+ _overlay(r.ptr(), w.ptr(), mip1_weight, p_width, p_height, get_format_pixel_size(format));
}
} break;
@@ -759,7 +842,11 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
r = PoolVector<uint8_t>::Read();
w = PoolVector<uint8_t>::Write();
- if (mipmaps > 0)
+ if (interpolate_mipmaps) {
+ dst._copy_internals_from(dst2);
+ }
+
+ if (had_mipmaps)
dst.generate_mipmaps();
_copy_internals_from(dst);
@@ -1898,8 +1985,9 @@ void Image::fill(const Color &c) {
unlock();
}
-Ref<Image> (*Image::_png_mem_loader_func)(const uint8_t *, int) = NULL;
-Ref<Image> (*Image::_jpg_mem_loader_func)(const uint8_t *, int) = NULL;
+ImageMemLoadFunc Image::_png_mem_loader_func = NULL;
+ImageMemLoadFunc Image::_jpg_mem_loader_func = NULL;
+ImageMemLoadFunc Image::_webp_mem_loader_func = NULL;
void (*Image::_image_compress_bc_func)(Image *, Image::CompressSource) = NULL;
void (*Image::_image_compress_pvrtc2_func)(Image *) = NULL;
@@ -2357,6 +2445,7 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("load_png_from_buffer", "buffer"), &Image::load_png_from_buffer);
ClassDB::bind_method(D_METHOD("load_jpg_from_buffer", "buffer"), &Image::load_jpg_from_buffer);
+ ClassDB::bind_method(D_METHOD("load_webp_from_buffer", "buffer"), &Image::load_webp_from_buffer);
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "_set_data", "_get_data");
@@ -2402,6 +2491,7 @@ void Image::_bind_methods() {
BIND_ENUM_CONSTANT(INTERPOLATE_NEAREST);
BIND_ENUM_CONSTANT(INTERPOLATE_BILINEAR);
BIND_ENUM_CONSTANT(INTERPOLATE_CUBIC);
+ BIND_ENUM_CONSTANT(INTERPOLATE_TRILINEAR);
BIND_ENUM_CONSTANT(ALPHA_NONE);
BIND_ENUM_CONSTANT(ALPHA_BIT);
@@ -2649,32 +2739,26 @@ String Image::get_format_name(Format p_format) {
}
Error Image::load_png_from_buffer(const PoolVector<uint8_t> &p_array) {
-
- int buffer_size = p_array.size();
-
- ERR_FAIL_COND_V(buffer_size == 0, ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V(!_png_mem_loader_func, ERR_INVALID_PARAMETER);
-
- PoolVector<uint8_t>::Read r = p_array.read();
-
- Ref<Image> image = _png_mem_loader_func(r.ptr(), buffer_size);
- ERR_FAIL_COND_V(!image.is_valid(), ERR_PARSE_ERROR);
-
- copy_internals_from(image);
-
- return OK;
+ return _load_from_buffer(p_array, _png_mem_loader_func);
}
Error Image::load_jpg_from_buffer(const PoolVector<uint8_t> &p_array) {
+ return _load_from_buffer(p_array, _jpg_mem_loader_func);
+}
+
+Error Image::load_webp_from_buffer(const PoolVector<uint8_t> &p_array) {
+ return _load_from_buffer(p_array, _webp_mem_loader_func);
+}
+Error Image::_load_from_buffer(const PoolVector<uint8_t> &p_array, ImageMemLoadFunc p_loader) {
int buffer_size = p_array.size();
ERR_FAIL_COND_V(buffer_size == 0, ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V(!_jpg_mem_loader_func, ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(!p_loader, ERR_INVALID_PARAMETER);
PoolVector<uint8_t>::Read r = p_array.read();
- Ref<Image> image = _jpg_mem_loader_func(r.ptr(), buffer_size);
+ Ref<Image> image = p_loader(r.ptr(), buffer_size);
ERR_FAIL_COND_V(!image.is_valid(), ERR_PARSE_ERROR);
copy_internals_from(image);
diff --git a/core/image.h b/core/image.h
index 43516e2c0b..8c4854e053 100644
--- a/core/image.h
+++ b/core/image.h
@@ -47,6 +47,7 @@
class Image;
typedef Error (*SavePNGFunc)(const String &p_path, const Ref<Image> &p_img);
+typedef Ref<Image> (*ImageMemLoadFunc)(const uint8_t *p_png, int p_size);
class Image : public Resource {
GDCLASS(Image, Resource);
@@ -107,6 +108,8 @@ public:
INTERPOLATE_NEAREST,
INTERPOLATE_BILINEAR,
INTERPOLATE_CUBIC,
+ INTERPOLATE_TRILINEAR,
+ /* INTERPOLATE_TRICUBIC, */
/* INTERPOLATE GAUSS */
};
@@ -118,8 +121,9 @@ public:
//some functions provided by something else
- static Ref<Image> (*_png_mem_loader_func)(const uint8_t *p_png, int p_size);
- static Ref<Image> (*_jpg_mem_loader_func)(const uint8_t *p_png, int p_size);
+ static ImageMemLoadFunc _png_mem_loader_func;
+ static ImageMemLoadFunc _jpg_mem_loader_func;
+ static ImageMemLoadFunc _webp_mem_loader_func;
static void (*_image_compress_bc_func)(Image *, CompressSource p_source);
static void (*_image_compress_pvrtc2_func)(Image *);
@@ -175,6 +179,8 @@ private:
void _set_data(const Dictionary &p_data);
Dictionary _get_data() const;
+ Error _load_from_buffer(const PoolVector<uint8_t> &p_array, ImageMemLoadFunc p_loader);
+
public:
int get_width() const; ///< Get image width
int get_height() const; ///< Get image height
@@ -302,6 +308,7 @@ public:
Error load_png_from_buffer(const PoolVector<uint8_t> &p_array);
Error load_jpg_from_buffer(const PoolVector<uint8_t> &p_array);
+ Error load_webp_from_buffer(const PoolVector<uint8_t> &p_array);
Image(const uint8_t *p_mem_png_jpg, int p_len = -1);
Image(const char **p_xpm);
diff --git a/core/message_queue.cpp b/core/message_queue.cpp
index 25ee6eafae..3adaad868a 100644
--- a/core/message_queue.cpp
+++ b/core/message_queue.cpp
@@ -342,7 +342,7 @@ MessageQueue::MessageQueue() {
buffer_end = 0;
buffer_max_used = 0;
- buffer_size = GLOBAL_DEF("memory/limits/message_queue/max_size_kb", DEFAULT_QUEUE_SIZE_KB);
+ buffer_size = GLOBAL_DEF_RST("memory/limits/message_queue/max_size_kb", DEFAULT_QUEUE_SIZE_KB);
buffer_size *= 1024;
buffer = memnew_arr(uint8_t, buffer_size);
}
diff --git a/core/object.cpp b/core/object.cpp
index 1d2aeb7ba5..d86c60a3b8 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -601,8 +601,12 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
_get_property_listv(p_list, p_reversed);
- if (!is_class("Script")) // can still be set, but this is for userfriendlyness
+ if (!is_class("Script")) { // can still be set, but this is for userfriendlyness
+#ifdef TOOLS_ENABLED
+ p_list->push_back(PropertyInfo(Variant::NIL, "Script", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
+#endif
p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NONZERO));
+ }
#ifdef TOOLS_ENABLED
if (editor_section_folding.size()) {
p_list->push_back(PropertyInfo(Variant::ARRAY, CoreStringNames::get_singleton()->_sections_unfolded, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
diff --git a/core/os/os.cpp b/core/os/os.cpp
index d0a7bc6fbe..89866e4044 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -659,9 +659,23 @@ const char *OS::get_audio_driver_name(int p_driver) const {
return AudioDriverManager::get_driver(p_driver)->get_name();
}
+void OS::set_restart_on_exit(bool p_restart, const List<String> &p_restart_arguments) {
+ restart_on_exit = p_restart;
+ restart_commandline = p_restart_arguments;
+}
+
+bool OS::is_restart_on_exit_set() const {
+ return restart_on_exit;
+}
+
+List<String> OS::get_restart_on_exit_arguments() const {
+ return restart_commandline;
+}
+
OS::OS() {
void *volatile stack_bottom;
+ restart_on_exit = false;
last_error = NULL;
singleton = this;
_keep_screen_on = true; // set default value to true, because this had been true before godot 2.0.
diff --git a/core/os/os.h b/core/os/os.h
index adf01a90e7..4e0cb003fb 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -74,6 +74,9 @@ class OS {
CompositeLogger *_logger;
+ bool restart_on_exit;
+ List<String> restart_commandline;
+
protected:
void _set_logger(CompositeLogger *p_logger);
@@ -182,7 +185,7 @@ public:
virtual int get_video_driver_count() const;
virtual const char *get_video_driver_name(int p_driver) const;
-
+ virtual int get_current_video_driver() const = 0;
virtual int get_audio_driver_count() const;
virtual const char *get_audio_driver_name(int p_driver) const;
@@ -496,6 +499,11 @@ public:
bool is_layered_allowed() const { return _allow_layered; }
bool is_hidpi_allowed() const { return _allow_hidpi; }
+
+ void set_restart_on_exit(bool p_restart, const List<String> &p_restart_arguments);
+ bool is_restart_on_exit_set() const;
+ List<String> get_restart_on_exit_arguments() const;
+
OS();
virtual ~OS();
};
diff --git a/core/project_settings.cpp b/core/project_settings.cpp
index db1d0a604c..60e8933751 100644
--- a/core/project_settings.cpp
+++ b/core/project_settings.cpp
@@ -105,6 +105,11 @@ void ProjectSettings::set_initial_value(const String &p_name, const Variant &p_v
ERR_FAIL_COND(!props.has(p_name));
props[p_name].initial = p_value;
}
+void ProjectSettings::set_restart_if_changed(const String &p_name, bool p_restart) {
+
+ ERR_FAIL_COND(!props.has(p_name));
+ props[p_name].restart_if_changed = p_restart;
+}
String ProjectSettings::globalize_path(const String &p_path) const {
@@ -225,6 +230,9 @@ void ProjectSettings::_get_property_list(List<PropertyInfo> *p_list) const {
else
vc.flags = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE;
+ if (v->restart_if_changed) {
+ vc.flags |= PROPERTY_USAGE_RESTART_IF_CHANGED;
+ }
vclist.insert(vc);
}
@@ -817,7 +825,7 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust
return OK;
}
-Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default) {
+Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default, bool p_restart_if_changed) {
Variant ret;
if (!ProjectSettings::get_singleton()->has_setting(p_var)) {
@@ -827,6 +835,7 @@ Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default) {
ProjectSettings::get_singleton()->set_initial_value(p_var, p_default);
ProjectSettings::get_singleton()->set_builtin_order(p_var);
+ ProjectSettings::get_singleton()->set_restart_if_changed(p_var, p_restart_if_changed);
return ret;
}
@@ -1080,7 +1089,6 @@ ProjectSettings::ProjectSettings() {
custom_prop_info["rendering/threads/thread_model"] = PropertyInfo(Variant::INT, "rendering/threads/thread_model", PROPERTY_HINT_ENUM, "Single-Unsafe,Single-Safe,Multi-Threaded");
custom_prop_info["physics/2d/thread_model"] = PropertyInfo(Variant::INT, "physics/2d/thread_model", PROPERTY_HINT_ENUM, "Single-Unsafe,Single-Safe,Multi-Threaded");
custom_prop_info["rendering/quality/intended_usage/framebuffer_allocation"] = PropertyInfo(Variant::INT, "rendering/quality/intended_usage/framebuffer_allocation", PROPERTY_HINT_ENUM, "2D,2D Without Sampling,3D,3D Without Effects");
- GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_mode", 2);
GLOBAL_DEF("debug/settings/profiler/max_functions", 16384);
diff --git a/core/project_settings.h b/core/project_settings.h
index 045d942b31..75ebc5acc8 100644
--- a/core/project_settings.h
+++ b/core/project_settings.h
@@ -59,18 +59,21 @@ protected:
Variant initial;
bool hide_from_editor;
bool overridden;
+ bool restart_if_changed;
VariantContainer() :
order(0),
persist(false),
hide_from_editor(false),
- overridden(false) {
+ overridden(false),
+ restart_if_changed(false) {
}
VariantContainer(const Variant &p_variant, int p_order, bool p_persist = false) :
order(p_order),
persist(p_persist),
variant(p_variant),
hide_from_editor(false),
- overridden(false) {
+ overridden(false),
+ restart_if_changed(false) {
}
};
@@ -120,6 +123,7 @@ public:
String globalize_path(const String &p_path) const;
void set_initial_value(const String &p_name, const Variant &p_value);
+ void set_restart_if_changed(const String &p_name, bool p_restart);
bool property_can_revert(const String &p_name);
Variant property_get_revert(const String &p_name);
@@ -158,8 +162,9 @@ public:
};
//not a macro any longer
-Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default);
+Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default, bool p_restart_if_changed = false);
#define GLOBAL_DEF(m_var, m_value) _GLOBAL_DEF(m_var, m_value)
+#define GLOBAL_DEF_RST(m_var, m_value) _GLOBAL_DEF(m_var, m_value, true)
#define GLOBAL_GET(m_var) ProjectSettings::get_singleton()->get(m_var)
#endif
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 2a611ccf6a..9bcc2d4530 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -191,7 +191,7 @@ void register_core_types() {
void register_core_settings() {
//since in register core types, globals may not e present
- GLOBAL_DEF("network/limits/packet_peer_stream/max_buffer_po2", (16));
+ GLOBAL_DEF_RST("network/limits/packet_peer_stream/max_buffer_po2", (16));
}
void register_core_singletons() {
diff --git a/core/script_language.h b/core/script_language.h
index 2950b35109..4e81b9b626 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -213,7 +213,7 @@ public:
virtual Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const = 0;
virtual void make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script) {}
virtual bool is_using_templates() { return false; }
- virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL) const = 0;
+ virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL, Set<int> *r_safe_lines = NULL) const = 0;
virtual String validate_path(const String &p_path) const { return ""; }
virtual Script *create_script() const = 0;
virtual bool has_named_classes() const = 0;
diff --git a/core/ustring.cpp b/core/ustring.cpp
index bee5f5ffdb..bb08dd13c4 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -921,8 +921,8 @@ String String::to_upper() const {
for (int i = 0; i < upper.size(); i++) {
- const char s = upper[i];
- const char t = _find_upper(s);
+ const CharType s = upper[i];
+ const CharType t = _find_upper(s);
if (s != t) // avoid copy on write
upper[i] = t;
}
@@ -936,8 +936,8 @@ String String::to_lower() const {
for (int i = 0; i < lower.size(); i++) {
- const char s = lower[i];
- const char t = _find_lower(s);
+ const CharType s = lower[i];
+ const CharType t = _find_lower(s);
if (s != t) // avoid copy on write
lower[i] = t;
}
diff --git a/core/vector.h b/core/vector.h
index f586471e27..c026448ddd 100644
--- a/core/vector.h
+++ b/core/vector.h
@@ -152,6 +152,8 @@ public:
Error insert(int p_pos, const T &p_val);
+ void append_array(const Vector<T> &p_other);
+
template <class C>
void sort_custom() {
@@ -408,6 +410,17 @@ Error Vector<T>::insert(int p_pos, const T &p_val) {
}
template <class T>
+void Vector<T>::append_array(const Vector<T> &p_other) {
+ const int ds = p_other.size();
+ if (ds == 0)
+ return;
+ const int bs = size();
+ resize(bs + ds);
+ for (int i = 0; i < ds; ++i)
+ operator[](bs + i) = p_other[i];
+}
+
+template <class T>
Vector<T>::Vector(const Vector &p_from) {
_ptr = NULL;