summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/dictionary.cpp5
-rw-r--r--core/dictionary.h1
-rw-r--r--core/image.cpp144
-rw-r--r--core/image.h11
-rw-r--r--core/math/aabb.cpp4
-rw-r--r--core/math/bsp_tree.cpp10
-rw-r--r--core/message_queue.cpp2
-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/safe_refcount.cpp48
-rw-r--r--core/safe_refcount.h50
-rw-r--r--core/script_language.h2
-rw-r--r--core/translation.cpp8
-rw-r--r--core/ustring.cpp8
-rw-r--r--core/vector.h13
18 files changed, 245 insertions, 110 deletions
diff --git a/core/dictionary.cpp b/core/dictionary.cpp
index d68411a572..42d9eab310 100644
--- a/core/dictionary.cpp
+++ b/core/dictionary.cpp
@@ -140,6 +140,11 @@ void Dictionary::erase(const Variant &p_key) {
_p->variant_map.erase(p_key);
}
+bool Dictionary::erase_checked(const Variant &p_key) {
+
+ return _p->variant_map.erase(p_key);
+}
+
bool Dictionary::operator==(const Dictionary &p_dictionary) const {
return _p == p_dictionary._p;
diff --git a/core/dictionary.h b/core/dictionary.h
index 84a5cafe1d..00ec67fb99 100644
--- a/core/dictionary.h
+++ b/core/dictionary.h
@@ -66,6 +66,7 @@ public:
bool has_all(const Array &p_keys) const;
void erase(const Variant &p_key);
+ bool erase_checked(const Variant &p_key);
bool operator==(const Dictionary &p_dictionary) const;
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/math/aabb.cpp b/core/math/aabb.cpp
index cff19f990c..e2e71dda92 100644
--- a/core/math/aabb.cpp
+++ b/core/math/aabb.cpp
@@ -245,7 +245,6 @@ Vector3 AABB::get_longest_axis() const {
if (size.z > max_size) {
axis = Vector3(0, 0, 1);
- max_size = size.z;
}
return axis;
@@ -262,7 +261,6 @@ int AABB::get_longest_axis_index() const {
if (size.z > max_size) {
axis = 2;
- max_size = size.z;
}
return axis;
@@ -280,7 +278,6 @@ Vector3 AABB::get_shortest_axis() const {
if (size.z < max_size) {
axis = Vector3(0, 0, 1);
- max_size = size.z;
}
return axis;
@@ -297,7 +294,6 @@ int AABB::get_shortest_axis_index() const {
if (size.z < max_size) {
axis = 2;
- max_size = size.z;
}
return axis;
diff --git a/core/math/bsp_tree.cpp b/core/math/bsp_tree.cpp
index b1424e1d78..2e184f7a88 100644
--- a/core/math/bsp_tree.cpp
+++ b/core/math/bsp_tree.cpp
@@ -244,10 +244,8 @@ bool BSP_Tree::point_is_inside(const Vector3 &p_point) const {
const Node *nodesptr = &nodes[0];
const Plane *planesptr = &planes[0];
- int plane_count = planes.size();
int idx = node_count - 1;
- int steps = 0;
while (true) {
@@ -259,21 +257,19 @@ bool BSP_Tree::point_is_inside(const Vector3 &p_point) const {
return true;
}
- uint16_t plane = nodesptr[idx].plane;
#ifdef DEBUG_ENABLED
-
+ int plane_count = planes.size();
+ uint16_t plane = nodesptr[idx].plane;
ERR_FAIL_INDEX_V(plane, plane_count, false);
#endif
+
bool over = planesptr[nodesptr[idx].plane].is_point_over(p_point);
idx = over ? nodes[idx].over : nodes[idx].under;
#ifdef DEBUG_ENABLED
-
ERR_FAIL_COND_V(idx < MAX_NODES && idx >= node_count, false);
#endif
-
- steps++;
}
return false;
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/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/safe_refcount.cpp b/core/safe_refcount.cpp
index 3b203f6977..692ff722f3 100644
--- a/core/safe_refcount.cpp
+++ b/core/safe_refcount.cpp
@@ -57,113 +57,113 @@
return m_val; \
}
-_ALWAYS_INLINE_ uint32_t _atomic_conditional_increment_impl(register uint32_t *pw){
+_ALWAYS_INLINE_ uint32_t _atomic_conditional_increment_impl(volatile uint32_t *pw){
ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONG, InterlockedCompareExchange, uint32_t)
}
-_ALWAYS_INLINE_ uint32_t _atomic_decrement_impl(register uint32_t *pw) {
+_ALWAYS_INLINE_ uint32_t _atomic_decrement_impl(volatile uint32_t *pw) {
return InterlockedDecrement((LONG volatile *)pw);
}
-_ALWAYS_INLINE_ uint32_t _atomic_increment_impl(register uint32_t *pw) {
+_ALWAYS_INLINE_ uint32_t _atomic_increment_impl(volatile uint32_t *pw) {
return InterlockedIncrement((LONG volatile *)pw);
}
-_ALWAYS_INLINE_ uint32_t _atomic_sub_impl(register uint32_t *pw, register uint32_t val) {
+_ALWAYS_INLINE_ uint32_t _atomic_sub_impl(volatile uint32_t *pw, volatile uint32_t val) {
return InterlockedExchangeAdd((LONG volatile *)pw, -(int32_t)val) - val;
}
-_ALWAYS_INLINE_ uint32_t _atomic_add_impl(register uint32_t *pw, register uint32_t val) {
+_ALWAYS_INLINE_ uint32_t _atomic_add_impl(volatile uint32_t *pw, volatile uint32_t val) {
return InterlockedAdd((LONG volatile *)pw, val);
}
-_ALWAYS_INLINE_ uint32_t _atomic_exchange_if_greater_impl(register uint32_t *pw, register uint32_t val){
+_ALWAYS_INLINE_ uint32_t _atomic_exchange_if_greater_impl(volatile uint32_t *pw, volatile uint32_t val){
ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONG, InterlockedCompareExchange, uint32_t)
}
-_ALWAYS_INLINE_ uint64_t _atomic_conditional_increment_impl(register uint64_t *pw){
+_ALWAYS_INLINE_ uint64_t _atomic_conditional_increment_impl(volatile uint64_t *pw){
ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONGLONG, InterlockedCompareExchange64, uint64_t)
}
-_ALWAYS_INLINE_ uint64_t _atomic_decrement_impl(register uint64_t *pw) {
+_ALWAYS_INLINE_ uint64_t _atomic_decrement_impl(volatile uint64_t *pw) {
return InterlockedDecrement64((LONGLONG volatile *)pw);
}
-_ALWAYS_INLINE_ uint64_t _atomic_increment_impl(register uint64_t *pw) {
+_ALWAYS_INLINE_ uint64_t _atomic_increment_impl(volatile uint64_t *pw) {
return InterlockedIncrement64((LONGLONG volatile *)pw);
}
-_ALWAYS_INLINE_ uint64_t _atomic_sub_impl(register uint64_t *pw, register uint64_t val) {
+_ALWAYS_INLINE_ uint64_t _atomic_sub_impl(volatile uint64_t *pw, volatile uint64_t val) {
return InterlockedExchangeAdd64((LONGLONG volatile *)pw, -(int64_t)val) - val;
}
-_ALWAYS_INLINE_ uint64_t _atomic_add_impl(register uint64_t *pw, register uint64_t val) {
+_ALWAYS_INLINE_ uint64_t _atomic_add_impl(volatile uint64_t *pw, volatile uint64_t val) {
return InterlockedAdd64((LONGLONG volatile *)pw, val);
}
-_ALWAYS_INLINE_ uint64_t _atomic_exchange_if_greater_impl(register uint64_t *pw, register uint64_t val){
+_ALWAYS_INLINE_ uint64_t _atomic_exchange_if_greater_impl(volatile uint64_t *pw, volatile uint64_t val){
ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONGLONG, InterlockedCompareExchange64, uint64_t)
}
// The actual advertised functions; they'll call the right implementation
-uint32_t atomic_conditional_increment(register uint32_t *pw) {
+uint32_t atomic_conditional_increment(volatile uint32_t *pw) {
return _atomic_conditional_increment_impl(pw);
}
-uint32_t atomic_decrement(register uint32_t *pw) {
+uint32_t atomic_decrement(volatile uint32_t *pw) {
return _atomic_decrement_impl(pw);
}
-uint32_t atomic_increment(register uint32_t *pw) {
+uint32_t atomic_increment(volatile uint32_t *pw) {
return _atomic_increment_impl(pw);
}
-uint32_t atomic_sub(register uint32_t *pw, register uint32_t val) {
+uint32_t atomic_sub(volatile uint32_t *pw, volatile uint32_t val) {
return _atomic_sub_impl(pw, val);
}
-uint32_t atomic_add(register uint32_t *pw, register uint32_t val) {
+uint32_t atomic_add(volatile uint32_t *pw, volatile uint32_t val) {
return _atomic_add_impl(pw, val);
}
-uint32_t atomic_exchange_if_greater(register uint32_t *pw, register uint32_t val) {
+uint32_t atomic_exchange_if_greater(volatile uint32_t *pw, volatile uint32_t val) {
return _atomic_exchange_if_greater_impl(pw, val);
}
-uint64_t atomic_conditional_increment(register uint64_t *pw) {
+uint64_t atomic_conditional_increment(volatile uint64_t *pw) {
return _atomic_conditional_increment_impl(pw);
}
-uint64_t atomic_decrement(register uint64_t *pw) {
+uint64_t atomic_decrement(volatile uint64_t *pw) {
return _atomic_decrement_impl(pw);
}
-uint64_t atomic_increment(register uint64_t *pw) {
+uint64_t atomic_increment(volatile uint64_t *pw) {
return _atomic_increment_impl(pw);
}
-uint64_t atomic_sub(register uint64_t *pw, register uint64_t val) {
+uint64_t atomic_sub(volatile uint64_t *pw, volatile uint64_t val) {
return _atomic_sub_impl(pw, val);
}
-uint64_t atomic_add(register uint64_t *pw, register uint64_t val) {
+uint64_t atomic_add(volatile uint64_t *pw, volatile uint64_t val) {
return _atomic_add_impl(pw, val);
}
-uint64_t atomic_exchange_if_greater(register uint64_t *pw, register uint64_t val) {
+uint64_t atomic_exchange_if_greater(volatile uint64_t *pw, volatile uint64_t val) {
return _atomic_exchange_if_greater_impl(pw, val);
}
#endif
diff --git a/core/safe_refcount.h b/core/safe_refcount.h
index eff209c2db..36bcf5e576 100644
--- a/core/safe_refcount.h
+++ b/core/safe_refcount.h
@@ -44,7 +44,7 @@
/* Bogus implementation unaware of multiprocessing */
template <class T>
-static _ALWAYS_INLINE_ T atomic_conditional_increment(register T *pw) {
+static _ALWAYS_INLINE_ T atomic_conditional_increment(volatile T *pw) {
if (*pw == 0)
return 0;
@@ -55,7 +55,7 @@ static _ALWAYS_INLINE_ T atomic_conditional_increment(register T *pw) {
}
template <class T>
-static _ALWAYS_INLINE_ T atomic_decrement(register T *pw) {
+static _ALWAYS_INLINE_ T atomic_decrement(volatile T *pw) {
(*pw)--;
@@ -63,7 +63,7 @@ static _ALWAYS_INLINE_ T atomic_decrement(register T *pw) {
}
template <class T>
-static _ALWAYS_INLINE_ T atomic_increment(register T *pw) {
+static _ALWAYS_INLINE_ T atomic_increment(volatile T *pw) {
(*pw)++;
@@ -71,7 +71,7 @@ static _ALWAYS_INLINE_ T atomic_increment(register T *pw) {
}
template <class T, class V>
-static _ALWAYS_INLINE_ T atomic_sub(register T *pw, register V val) {
+static _ALWAYS_INLINE_ T atomic_sub(volatile T *pw, volatile V val) {
(*pw) -= val;
@@ -79,7 +79,7 @@ static _ALWAYS_INLINE_ T atomic_sub(register T *pw, register V val) {
}
template <class T, class V>
-static _ALWAYS_INLINE_ T atomic_add(register T *pw, register V val) {
+static _ALWAYS_INLINE_ T atomic_add(volatile T *pw, volatile V val) {
(*pw) += val;
@@ -87,7 +87,7 @@ static _ALWAYS_INLINE_ T atomic_add(register T *pw, register V val) {
}
template <class T, class V>
-static _ALWAYS_INLINE_ T atomic_exchange_if_greater(register T *pw, register V val) {
+static _ALWAYS_INLINE_ T atomic_exchange_if_greater(volatile T *pw, volatile V val) {
if (val > *pw)
*pw = val;
@@ -103,7 +103,7 @@ static _ALWAYS_INLINE_ T atomic_exchange_if_greater(register T *pw, register V v
// Clang states it supports GCC atomic builtins.
template <class T>
-static _ALWAYS_INLINE_ T atomic_conditional_increment(register T *pw) {
+static _ALWAYS_INLINE_ T atomic_conditional_increment(volatile T *pw) {
while (true) {
T tmp = static_cast<T const volatile &>(*pw);
@@ -115,31 +115,31 @@ static _ALWAYS_INLINE_ T atomic_conditional_increment(register T *pw) {
}
template <class T>
-static _ALWAYS_INLINE_ T atomic_decrement(register T *pw) {
+static _ALWAYS_INLINE_ T atomic_decrement(volatile T *pw) {
return __sync_sub_and_fetch(pw, 1);
}
template <class T>
-static _ALWAYS_INLINE_ T atomic_increment(register T *pw) {
+static _ALWAYS_INLINE_ T atomic_increment(volatile T *pw) {
return __sync_add_and_fetch(pw, 1);
}
template <class T, class V>
-static _ALWAYS_INLINE_ T atomic_sub(register T *pw, register V val) {
+static _ALWAYS_INLINE_ T atomic_sub(volatile T *pw, volatile V val) {
return __sync_sub_and_fetch(pw, val);
}
template <class T, class V>
-static _ALWAYS_INLINE_ T atomic_add(register T *pw, register V val) {
+static _ALWAYS_INLINE_ T atomic_add(volatile T *pw, volatile V val) {
return __sync_add_and_fetch(pw, val);
}
template <class T, class V>
-static _ALWAYS_INLINE_ T atomic_exchange_if_greater(register T *pw, register V val) {
+static _ALWAYS_INLINE_ T atomic_exchange_if_greater(volatile T *pw, volatile V val) {
while (true) {
T tmp = static_cast<T const volatile &>(*pw);
@@ -153,19 +153,19 @@ static _ALWAYS_INLINE_ T atomic_exchange_if_greater(register T *pw, register V v
#elif defined(_MSC_VER)
// For MSVC use a separate compilation unit to prevent windows.h from polluting
// the global namespace.
-uint32_t atomic_conditional_increment(register uint32_t *pw);
-uint32_t atomic_decrement(register uint32_t *pw);
-uint32_t atomic_increment(register uint32_t *pw);
-uint32_t atomic_sub(register uint32_t *pw, register uint32_t val);
-uint32_t atomic_add(register uint32_t *pw, register uint32_t val);
-uint32_t atomic_exchange_if_greater(register uint32_t *pw, register uint32_t val);
-
-uint64_t atomic_conditional_increment(register uint64_t *pw);
-uint64_t atomic_decrement(register uint64_t *pw);
-uint64_t atomic_increment(register uint64_t *pw);
-uint64_t atomic_sub(register uint64_t *pw, register uint64_t val);
-uint64_t atomic_add(register uint64_t *pw, register uint64_t val);
-uint64_t atomic_exchange_if_greater(register uint64_t *pw, register uint64_t val);
+uint32_t atomic_conditional_increment(volatile uint32_t *pw);
+uint32_t atomic_decrement(volatile uint32_t *pw);
+uint32_t atomic_increment(volatile uint32_t *pw);
+uint32_t atomic_sub(volatile uint32_t *pw, volatile uint32_t val);
+uint32_t atomic_add(volatile uint32_t *pw, volatile uint32_t val);
+uint32_t atomic_exchange_if_greater(volatile uint32_t *pw, volatile uint32_t val);
+
+uint64_t atomic_conditional_increment(volatile uint64_t *pw);
+uint64_t atomic_decrement(volatile uint64_t *pw);
+uint64_t atomic_increment(volatile uint64_t *pw);
+uint64_t atomic_sub(volatile uint64_t *pw, volatile uint64_t val);
+uint64_t atomic_add(volatile uint64_t *pw, volatile uint64_t val);
+uint64_t atomic_exchange_if_greater(volatile uint64_t *pw, volatile uint64_t val);
#else
//no threads supported?
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/translation.cpp b/core/translation.cpp
index aaa4de5912..78115c3749 100644
--- a/core/translation.cpp
+++ b/core/translation.cpp
@@ -1171,13 +1171,11 @@ void TranslationServer::_bind_methods() {
void TranslationServer::load_translations() {
String locale = get_locale();
- bool found = _load_translations("locale/translations"); //all
+ _load_translations("locale/translations"); //all
+ _load_translations("locale/translations_" + locale.substr(0, 2));
- if (_load_translations("locale/translations_" + locale.substr(0, 2)))
- found = true;
if (locale.substr(0, 2) != locale) {
- if (_load_translations("locale/translations_" + locale))
- found = true;
+ _load_translations("locale/translations_" + locale);
}
}
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;