summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/SCsub10
-rw-r--r--core/array.cpp14
-rw-r--r--core/array.h1
-rw-r--r--core/bind/core_bind.cpp34
-rw-r--r--core/bind/core_bind.h9
-rw-r--r--core/class_db.cpp23
-rw-r--r--core/color.cpp53
-rw-r--r--core/color.h1
-rw-r--r--core/command_queue_mt.cpp1
-rw-r--r--core/command_queue_mt.h6
-rw-r--r--core/compressed_translation.h2
-rw-r--r--core/error_macros.h2
-rw-r--r--core/global_constants.cpp2
-rw-r--r--core/input_map.cpp10
-rw-r--r--core/io/file_access_pack.cpp6
-rw-r--r--core/io/http_client.cpp2
-rw-r--r--core/io/ip_address.cpp2
-rw-r--r--core/io/marshalls.cpp2
-rw-r--r--core/make_binders.py10
-rw-r--r--core/map.h4
-rw-r--r--core/math/math_2d.cpp5
-rw-r--r--core/math/math_2d.h3
-rw-r--r--core/math/math_funcs.cpp15
-rw-r--r--core/math/math_funcs.h14
-rw-r--r--core/math/triangulate.cpp42
-rw-r--r--core/math/triangulate.h5
-rw-r--r--core/message_queue.cpp2
-rw-r--r--core/os/dir_access.cpp7
-rw-r--r--core/os/file_access.h3
-rw-r--r--core/os/input_event.cpp10
-rw-r--r--core/os/input_event.h2
-rw-r--r--core/os/os.cpp29
-rw-r--r--core/os/os.h18
-rw-r--r--core/os/thread_dummy.cpp8
-rw-r--r--core/os/thread_dummy.h17
-rw-r--r--core/pool_allocator.cpp4
-rw-r--r--core/project_settings.cpp103
-rw-r--r--core/project_settings.h3
-rw-r--r--core/reference.h5
-rw-r--r--core/script_debugger_remote.cpp4
-rw-r--r--core/script_language.h1
-rw-r--r--core/set.h4
-rw-r--r--core/string_buffer.h6
-rw-r--r--core/string_builder.h6
-rw-r--r--core/ustring.cpp30
-rw-r--r--core/ustring.h1
-rw-r--r--core/variant.cpp2
-rw-r--r--core/variant.h2
-rw-r--r--core/variant_call.cpp8
-rw-r--r--core/variant_op.cpp12
-rw-r--r--core/version.h29
51 files changed, 451 insertions, 143 deletions
diff --git a/core/SCsub b/core/SCsub
index 1545bc8aeb..383aaf0e12 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -18,9 +18,8 @@ gd_cpp = '#include "project_settings.h"\n'
gd_cpp += gd_inc
gd_cpp += "void ProjectSettings::register_global_defaults() {\n" + gd_call + "\n}\n"
-f = open("global_defaults.gen.cpp", "w")
-f.write(gd_cpp)
-f.close()
+with open("global_defaults.gen.cpp", "w") as f:
+ f.write(gd_cpp)
# Generate AES256 script encryption key
@@ -47,9 +46,8 @@ if ("SCRIPT_AES256_ENCRYPTION_KEY" in os.environ):
txt = "0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0"
print("Invalid AES256 encryption key, not 64 bits hex: " + e)
-f = open("script_encryption_key.gen.cpp", "w")
-f.write("#include \"project_settings.h\"\nuint8_t script_encryption_key[32]={" + txt + "};\n")
-f.close()
+with open("script_encryption_key.gen.cpp", "w") as f:
+ f.write("#include \"project_settings.h\"\nuint8_t script_encryption_key[32]={" + txt + "};\n")
# Add required thirdparty code. Header paths are hardcoded, we don't need to append
diff --git a/core/array.cpp b/core/array.cpp
index c53fea1f28..0ddac1662c 100644
--- a/core/array.cpp
+++ b/core/array.cpp
@@ -266,6 +266,20 @@ Array &Array::sort_custom(Object *p_obj, const StringName &p_function) {
return *this;
}
+void Array::shuffle() {
+
+ const int n = _p->array.size();
+ if (n < 2)
+ return;
+ Variant *data = _p->array.ptrw();
+ for (int i = n - 1; i >= 1; i--) {
+ const int j = Math::rand() % (i + 1);
+ const Variant tmp = data[j];
+ data[j] = data[i];
+ data[i] = tmp;
+ }
+}
+
template <typename Less>
_FORCE_INLINE_ int bisect(const Vector<Variant> &p_array, const Variant &p_value, bool p_before, const Less &p_less) {
diff --git a/core/array.h b/core/array.h
index 7c6fc59048..684a8e265d 100644
--- a/core/array.h
+++ b/core/array.h
@@ -71,6 +71,7 @@ public:
Array &sort();
Array &sort_custom(Object *p_obj, const StringName &p_function);
+ void shuffle();
int bsearch(const Variant &p_value, bool p_before = true);
int bsearch_custom(const Variant &p_value, Object *p_obj, const StringName &p_function, bool p_before = true);
Array &invert();
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index b57b24ee7d..20adf7ff02 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -205,6 +205,22 @@ String _OS::get_clipboard() const {
return OS::get_singleton()->get_clipboard();
}
+int _OS::get_video_driver_count() const {
+ return OS::get_singleton()->get_video_driver_count();
+}
+
+String _OS::get_video_driver_name(int p_driver) const {
+ return OS::get_singleton()->get_video_driver_name(p_driver);
+}
+
+int _OS::get_audio_driver_count() const {
+ return OS::get_singleton()->get_audio_driver_count();
+}
+
+String _OS::get_audio_driver_name(int p_driver) const {
+ return OS::get_singleton()->get_audio_driver_name(p_driver);
+}
+
void _OS::set_video_mode(const Size2 &p_size, bool p_fullscreen, bool p_resizeable, int p_screen) {
OS::VideoMode vm;
@@ -1015,6 +1031,11 @@ void _OS::_bind_methods() {
//ClassDB::bind_method(D_METHOD("is_video_mode_resizable","screen"),&_OS::is_video_mode_resizable,DEFVAL(0));
//ClassDB::bind_method(D_METHOD("get_fullscreen_mode_list","screen"),&_OS::get_fullscreen_mode_list,DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_video_driver_count"), &_OS::get_video_driver_count);
+ ClassDB::bind_method(D_METHOD("get_video_driver_name"), &_OS::get_video_driver_name);
+ ClassDB::bind_method(D_METHOD("get_audio_driver_count"), &_OS::get_audio_driver_count);
+ ClassDB::bind_method(D_METHOD("get_audio_driver_name"), &_OS::get_audio_driver_name);
+
ClassDB::bind_method(D_METHOD("get_screen_count"), &_OS::get_screen_count);
ClassDB::bind_method(D_METHOD("get_current_screen"), &_OS::get_current_screen);
ClassDB::bind_method(D_METHOD("set_current_screen", "screen"), &_OS::set_current_screen);
@@ -1514,6 +1535,17 @@ bool _File::is_open() const {
return f != NULL;
}
+String _File::get_path() const {
+
+ ERR_FAIL_COND_V(!f, "");
+ return f->get_path();
+}
+
+String _File::get_path_absolute() const {
+
+ ERR_FAIL_COND_V(!f, "");
+ return f->get_path_absolute();
+}
void _File::seek(int64_t p_position) {
@@ -1803,6 +1835,8 @@ void _File::_bind_methods() {
ClassDB::bind_method(D_METHOD("open", "path", "flags"), &_File::open);
ClassDB::bind_method(D_METHOD("close"), &_File::close);
+ ClassDB::bind_method(D_METHOD("get_path"), &_File::get_path);
+ ClassDB::bind_method(D_METHOD("get_path_absolute"), &_File::get_path_absolute);
ClassDB::bind_method(D_METHOD("is_open"), &_File::is_open);
ClassDB::bind_method(D_METHOD("seek", "position"), &_File::seek);
ClassDB::bind_method(D_METHOD("seek_end", "position"), &_File::seek_end, DEFVAL(0));
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 734b57937a..c40abd51f6 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -146,6 +146,12 @@ public:
bool is_video_mode_resizable(int p_screen = 0) const;
Array get_fullscreen_mode_list(int p_screen = 0) const;
+ virtual int get_video_driver_count() const;
+ virtual String get_video_driver_name(int p_driver) const;
+
+ virtual int get_audio_driver_count() const;
+ virtual String get_audio_driver_name(int p_driver) const;
+
virtual int get_screen_count() const;
virtual int get_current_screen() const;
virtual void set_current_screen(int p_screen);
@@ -409,6 +415,9 @@ public:
void close(); ///< close a file
bool is_open() const; ///< true when file is open
+ String get_path() const; /// returns the path for the current open file
+ String get_path_absolute() const; /// returns the absolute path for the current open file
+
void seek(int64_t p_position); ///< seek to a given position
void seek_end(int64_t p_position = 0); ///< seek from the end of file
int64_t get_position() const; ///< get position in the file
diff --git a/core/class_db.cpp b/core/class_db.cpp
index afcc8de0f2..291dc87e1c 100644
--- a/core/class_db.cpp
+++ b/core/class_db.cpp
@@ -33,18 +33,9 @@
#include "os/mutex.h"
#include "version.h"
-#ifdef NO_THREADS
-
-#define OBJTYPE_RLOCK
-#define OBJTYPE_WLOCK
-
-#else
-
#define OBJTYPE_RLOCK RWLockRead _rw_lockr_(lock);
#define OBJTYPE_WLOCK RWLockWrite _rw_lockw_(lock);
-#endif
-
#ifdef DEBUG_METHODS_ENABLED
MethodDefinition D_METHOD(const char *p_name) {
@@ -347,7 +338,7 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
OBJTYPE_RLOCK;
#ifdef DEBUG_METHODS_ENABLED
- uint64_t hash = hash_djb2_one_64(HashMapHasherDefault::hash(VERSION_FULL_NAME));
+ uint64_t hash = hash_djb2_one_64(HashMapHasherDefault::hash(VERSION_FULL_CONFIG));
List<StringName> names;
@@ -895,15 +886,9 @@ void ClassDB::add_property_group(StringName p_class, const String &p_name, const
void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index) {
-#ifndef NO_THREADS
lock->read_lock();
-#endif
-
ClassInfo *type = classes.getptr(p_class);
-
-#ifndef NO_THREADS
lock->read_unlock();
-#endif
ERR_FAIL_COND(!type);
@@ -1380,10 +1365,7 @@ RWLock *ClassDB::lock = NULL;
void ClassDB::init() {
-#ifndef NO_THREADS
-
lock = RWLock::create();
-#endif
}
void ClassDB::cleanup() {
@@ -1406,10 +1388,7 @@ void ClassDB::cleanup() {
resource_base_extensions.clear();
compat_classes.clear();
-#ifndef NO_THREADS
-
memdelete(lock);
-#endif
}
//
diff --git a/core/color.cpp b/core/color.cpp
index a0568d26ed..b2f5889166 100644
--- a/core/color.cpp
+++ b/core/color.cpp
@@ -400,6 +400,59 @@ String Color::to_html(bool p_alpha) const {
return txt;
}
+Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) {
+
+ p_h = Math::fmod(p_h * 360.0f, 360.0f);
+ if (p_h < 0.0)
+ p_h += 360.0f;
+
+ const float h_ = p_h / 60.0f;
+ const float c = p_v * p_s;
+ const float x = c * (1.0f - Math::abs(Math::fmod(h_, 2.0f) - 1.0f));
+ float r, g, b;
+
+ switch ((int)h_) {
+ case 0: {
+ r = c;
+ g = x;
+ b = 0;
+ } break;
+ case 1: {
+ r = x;
+ g = c;
+ b = 0;
+ } break;
+ case 2: {
+ r = 0;
+ g = c;
+ b = x;
+ } break;
+ case 3: {
+ r = 0;
+ g = x;
+ b = c;
+ } break;
+ case 4: {
+ r = x;
+ g = 0;
+ b = c;
+ } break;
+ case 5: {
+ r = c;
+ g = 0;
+ b = x;
+ } break;
+ default: {
+ r = 0;
+ g = 0;
+ b = 0;
+ } break;
+ }
+
+ const float m = p_v - c;
+ return Color(m + r, m + g, m + b, p_a);
+}
+
float Color::gray() const {
return (r + g + b) / 3.0;
diff --git a/core/color.h b/core/color.h
index 9af8fb0a78..a2015a34d6 100644
--- a/core/color.h
+++ b/core/color.h
@@ -190,6 +190,7 @@ struct Color {
static bool html_is_valid(const String &p_color);
static Color named(const String &p_name);
String to_html(bool p_alpha = true) const;
+ Color from_hsv(float p_h, float p_s, float p_v, float p_a);
_FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys
operator String() const;
diff --git a/core/command_queue_mt.cpp b/core/command_queue_mt.cpp
index 6bb3135757..a39c920dfa 100644
--- a/core/command_queue_mt.cpp
+++ b/core/command_queue_mt.cpp
@@ -105,6 +105,7 @@ CommandQueueMT::CommandQueueMT(bool p_sync) {
read_ptr = 0;
write_ptr = 0;
+ dealloc_ptr = 0;
mutex = Mutex::create();
for (int i = 0; i < SYNC_SEMAPHORES; i++) {
diff --git a/core/command_queue_mt.h b/core/command_queue_mt.h
index cecc9e405d..3942b961d3 100644
--- a/core/command_queue_mt.h
+++ b/core/command_queue_mt.h
@@ -55,7 +55,7 @@
#define _COMMA_11 ,
#define _COMMA_12 ,
-// 1-based comma separed list of ITEMs
+// 1-based comma separated list of ITEMs
#define COMMA_SEP_LIST(ITEM, LENGTH) _COMMA_SEP_LIST_##LENGTH(ITEM)
#define _COMMA_SEP_LIST_12(ITEM) \
_COMMA_SEP_LIST_11(ITEM) \
@@ -95,7 +95,7 @@
ITEM(1)
#define _COMMA_SEP_LIST_0(ITEM)
-// 1-based semicolon separed list of ITEMs
+// 1-based semicolon separated list of ITEMs
#define SEMIC_SEP_LIST(ITEM, LENGTH) _SEMIC_SEP_LIST_##LENGTH(ITEM)
#define _SEMIC_SEP_LIST_12(ITEM) \
_SEMIC_SEP_LIST_11(ITEM); \
@@ -135,7 +135,7 @@
ITEM(1)
#define _SEMIC_SEP_LIST_0(ITEM)
-// 1-based space separed list of ITEMs
+// 1-based space separated list of ITEMs
#define SPACE_SEP_LIST(ITEM, LENGTH) _SPACE_SEP_LIST_##LENGTH(ITEM)
#define _SPACE_SEP_LIST_12(ITEM) \
_SPACE_SEP_LIST_11(ITEM) \
diff --git a/core/compressed_translation.h b/core/compressed_translation.h
index 400fa4491b..ccc47d0bf6 100644
--- a/core/compressed_translation.h
+++ b/core/compressed_translation.h
@@ -38,7 +38,7 @@ class PHashTranslation : public Translation {
GDCLASS(PHashTranslation, Translation);
//this translation uses a sort of modified perfect hash algorithm
- //it requieres hashing strings twice and then does a binary search,
+ //it requires hashing strings twice and then does a binary search,
//so it's slower, but at the same time it has an extreemly high chance
//of catching untranslated strings
diff --git a/core/error_macros.h b/core/error_macros.h
index 1f9164a99b..b8d0c7e0c3 100644
--- a/core/error_macros.h
+++ b/core/error_macros.h
@@ -33,7 +33,7 @@
#include "typedefs.h"
/**
- * Error macros. Unlike exceptions and asserts, these macros try to mantain consistency and stability
+ * Error macros. Unlike exceptions and asserts, these macros try to maintain consistency and stability
* inside the code. It is recommended to always return processable data, so in case of an error, the
* engine can stay working well.
* In most cases, bugs and/or invalid data are not fatal and should never allow a perfectly running application
diff --git a/core/global_constants.cpp b/core/global_constants.cpp
index a24bf03c9a..04810afe73 100644
--- a/core/global_constants.cpp
+++ b/core/global_constants.cpp
@@ -580,7 +580,7 @@ void register_global_constants() {
BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_COLOR_ARRAY", Variant::POOL_COLOR_ARRAY);
BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_MAX", Variant::VARIANT_MAX);
- //comparation
+ //comparison
BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_EQUAL", Variant::OP_EQUAL);
BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_NOT_EQUAL", Variant::OP_NOT_EQUAL);
BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_LESS", Variant::OP_LESS);
diff --git a/core/input_map.cpp b/core/input_map.cpp
index a9ea1d9545..bd03d61196 100644
--- a/core/input_map.cpp
+++ b/core/input_map.cpp
@@ -282,6 +282,16 @@ void InputMap::load_default() {
key->set_scancode(KEY_PAGEDOWN);
action_add_event("ui_page_down", key);
+ add_action("ui_home");
+ key.instance();
+ key->set_scancode(KEY_HOME);
+ action_add_event("ui_home", key);
+
+ add_action("ui_end");
+ key.instance();
+ key->set_scancode(KEY_END);
+ action_add_event("ui_end", key);
+
//set("display/window/handheld/orientation", "landscape");
}
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index 1a16d0f61c..efb4c7a073 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -88,7 +88,11 @@ void PackedData::add_path(const String &pkg_path, const String &path, uint64_t o
}
}
}
- cd->files.insert(path.get_file());
+ String filename = path.get_file();
+ // Don't add as a file if the path points to a directoryy
+ if (!filename.empty()) {
+ cd->files.insert(filename);
+ }
}
}
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp
index a9eb9466b7..4d72f744e1 100644
--- a/core/io/http_client.cpp
+++ b/core/io/http_client.cpp
@@ -298,7 +298,7 @@ Error HTTPClient::poll() {
case StreamPeerTCP::STATUS_CONNECTED: {
if (ssl) {
Ref<StreamPeerSSL> ssl = StreamPeerSSL::create();
- Error err = ssl->connect_to_stream(tcp_connection, ssl_verify_host, ssl_verify_host ? conn_host : String());
+ Error err = ssl->connect_to_stream(tcp_connection, ssl_verify_host, conn_host);
if (err != OK) {
close();
status = STATUS_SSL_HANDSHAKE_ERROR;
diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp
index 7261363ad6..6d979d10eb 100644
--- a/core/io/ip_address.cpp
+++ b/core/io/ip_address.cpp
@@ -211,7 +211,7 @@ IP_Address::IP_Address(const String &p_string) {
clear();
if (p_string == "*") {
- // Wildcard (not a vaild IP)
+ // Wildcard (not a valid IP)
wildcard = true;
} else if (p_string.find(":") >= 0) {
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index 9e21287780..2ebe8d6df7 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -813,7 +813,7 @@ static void _encode_string(const String &p_string, uint8_t *&buf, int &r_len) {
while (r_len % 4) {
r_len++; //pad
if (buf) {
- buf++;
+ *(buf++) = 0;
}
}
}
diff --git a/core/make_binders.py b/core/make_binders.py
index 1e581f8ce3..6a7602cd5d 100644
--- a/core/make_binders.py
+++ b/core/make_binders.py
@@ -265,10 +265,8 @@ def run(target, source, env):
else:
text += t
- f = open(target[0].path, "w")
- f.write(text)
- f.close()
+ with open(target[0].path, "w") as f:
+ f.write(text)
- f = open(target[1].path, "w")
- f.write(text_ext)
- f.close()
+ with open(target[1].path, "w") as f:
+ f.write(text_ext)
diff --git a/core/map.h b/core/map.h
index 5ff269c26b..700d4b8693 100644
--- a/core/map.h
+++ b/core/map.h
@@ -197,7 +197,7 @@ private:
if (node->right != _data._nil) {
node = node->right;
- while (node->left != _data._nil) { /* returns the minium of the right subtree of node */
+ while (node->left != _data._nil) { /* returns the minimum of the right subtree of node */
node = node->left;
}
return node;
@@ -219,7 +219,7 @@ private:
if (node->left != _data._nil) {
node = node->left;
- while (node->right != _data._nil) { /* returns the minium of the left subtree of node */
+ while (node->right != _data._nil) { /* returns the minimum of the left subtree of node */
node = node->right;
}
return node;
diff --git a/core/math/math_2d.cpp b/core/math/math_2d.cpp
index d2e4101999..3767d298a1 100644
--- a/core/math/math_2d.cpp
+++ b/core/math/math_2d.cpp
@@ -98,11 +98,6 @@ real_t Vector2::cross(const Vector2 &p_other) const {
return x * p_other.y - y * p_other.x;
}
-Vector2 Vector2::cross(real_t p_other) const {
-
- return Vector2(p_other * y, -p_other * x);
-}
-
Vector2 Vector2::floor() const {
return Vector2(Math::floor(x), Math::floor(y));
diff --git a/core/math/math_2d.h b/core/math/math_2d.h
index 8928349a44..e7188da85b 100644
--- a/core/math/math_2d.h
+++ b/core/math/math_2d.h
@@ -104,7 +104,6 @@ struct Vector2 {
real_t dot(const Vector2 &p_other) const;
real_t cross(const Vector2 &p_other) const;
- Vector2 cross(real_t p_other) const;
Vector2 project(const Vector2 &p_vec) const;
Vector2 plane_project(real_t p_d, const Vector2 &p_vec) const;
@@ -304,7 +303,7 @@ struct Rect2 {
inline real_t distance_to(const Vector2 &p_point) const {
- real_t dist;
+ real_t dist = 0.0;
bool inside = true;
if (p_point.x < position.x) {
diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp
index f060a8e4ab..5c8512d8bd 100644
--- a/core/math/math_funcs.cpp
+++ b/core/math/math_funcs.cpp
@@ -177,18 +177,3 @@ float Math::random(float from, float to) {
float ret = (float)r / (float)RANDOM_MAX;
return (ret) * (to - from) + from;
}
-
-int Math::wrapi(int value, int min, int max) {
- --max;
- int rng = max - min + 1;
- value = ((value - min) % rng);
- if (value < 0)
- return max + 1 + value;
- else
- return min + value;
-}
-
-float Math::wrapf(float value, float min, float max) {
- float rng = max - min;
- return min + (value - min) - (rng * floor((value - min) / rng));
-}
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index e15abc6b50..26e87f009b 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -209,8 +209,18 @@ public:
static _ALWAYS_INLINE_ double round(double p_val) { return (p_val >= 0) ? Math::floor(p_val + 0.5) : -Math::floor(-p_val + 0.5); }
static _ALWAYS_INLINE_ float round(float p_val) { return (p_val >= 0) ? Math::floor(p_val + 0.5) : -Math::floor(-p_val + 0.5); }
- static int wrapi(int value, int min, int max);
- static float wrapf(float value, float min, float max);
+ static _ALWAYS_INLINE_ int wrapi(int value, int min, int max) {
+ int rng = max - min;
+ return min + ((((value - min) % rng) + rng) % rng);
+ }
+ static _ALWAYS_INLINE_ double wrapf(double value, double min, double max) {
+ double rng = max - min;
+ return min + (value - min) - (rng * Math::floor((value - min) / rng));
+ }
+ static _ALWAYS_INLINE_ float wrapf(float value, float min, float max) {
+ float rng = max - min;
+ return min + (value - min) - (rng * Math::floor((value - min) / rng));
+ }
// double only, as these functions are mainly used by the editor and not performance-critical,
static double ease(double p_x, double p_c);
diff --git a/core/math/triangulate.cpp b/core/math/triangulate.cpp
index 5bae74ac7e..563ba7268f 100644
--- a/core/math/triangulate.cpp
+++ b/core/math/triangulate.cpp
@@ -51,7 +51,8 @@ real_t Triangulate::get_area(const Vector<Vector2> &contour) {
bool Triangulate::is_inside_triangle(real_t Ax, real_t Ay,
real_t Bx, real_t By,
real_t Cx, real_t Cy,
- real_t Px, real_t Py)
+ real_t Px, real_t Py,
+ bool include_edges)
{
real_t ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
@@ -74,10 +75,14 @@ bool Triangulate::is_inside_triangle(real_t Ax, real_t Ay,
cCROSSap = cx * apy - cy * apx;
bCROSScp = bx * cpy - by * cpx;
- return ((aCROSSbp > 0.0) && (bCROSScp > 0.0) && (cCROSSap > 0.0));
+ if (include_edges) {
+ return ((aCROSSbp > 0.0) && (bCROSScp > 0.0) && (cCROSSap > 0.0));
+ } else {
+ return ((aCROSSbp >= 0.0) && (bCROSScp >= 0.0) && (cCROSSap >= 0.0));
+ }
};
-bool Triangulate::snip(const Vector<Vector2> &p_contour, int u, int v, int w, int n, const Vector<int> &V) {
+bool Triangulate::snip(const Vector<Vector2> &p_contour, int u, int v, int w, int n, const Vector<int> &V, bool relaxed) {
int p;
real_t Ax, Ay, Bx, By, Cx, Cy, Px, Py;
const Vector2 *contour = &p_contour[0];
@@ -91,13 +96,20 @@ bool Triangulate::snip(const Vector<Vector2> &p_contour, int u, int v, int w, in
Cx = contour[V[w]].x;
Cy = contour[V[w]].y;
- if (CMP_EPSILON > (((Bx - Ax) * (Cy - Ay)) - ((By - Ay) * (Cx - Ax)))) return false;
+ // It can happen that the triangulation ends up with three aligned vertices to deal with.
+ // In this scenario, making the check below strict may reject the possibility of
+ // forming a last triangle with these aligned vertices, preventing the triangulatiom
+ // from completing.
+ // To avoid that we allow zero-area triangles if all else failed.
+ float threshold = relaxed ? -CMP_EPSILON : CMP_EPSILON;
+
+ if (threshold > (((Bx - Ax) * (Cy - Ay)) - ((By - Ay) * (Cx - Ax)))) return false;
for (p = 0; p < n; p++) {
if ((p == u) || (p == v) || (p == w)) continue;
Px = contour[V[p]].x;
Py = contour[V[p]].y;
- if (is_inside_triangle(Ax, Ay, Bx, By, Cx, Cy, Px, Py)) return false;
+ if (is_inside_triangle(Ax, Ay, Bx, By, Cx, Cy, Px, Py, relaxed)) return false;
}
return true;
@@ -121,6 +133,8 @@ bool Triangulate::triangulate(const Vector<Vector2> &contour, Vector<int> &resul
for (int v = 0; v < n; v++)
V[v] = (n - 1) - v;
+ bool relaxed = false;
+
int nv = n;
/* remove nv-2 Vertices, creating 1 triangle every time */
@@ -129,8 +143,20 @@ bool Triangulate::triangulate(const Vector<Vector2> &contour, Vector<int> &resul
for (int v = nv - 1; nv > 2;) {
/* if we loop, it is probably a non-simple polygon */
if (0 >= (count--)) {
- //** Triangulate: ERROR - probable bad polygon!
- return false;
+ if (relaxed) {
+ //** Triangulate: ERROR - probable bad polygon!
+ return false;
+ } else {
+ // There may be aligned vertices that the strict
+ // checks prevent from triangulating. In this situation
+ // we are better off adding flat triangles than
+ // failing, so we relax the checks and try one last
+ // round.
+ // Only relaxing the constraints as a last resort avoids
+ // degenerate triangles when they aren't necessary.
+ count = 2 * nv;
+ relaxed = true;
+ }
}
/* three consecutive vertices in current polygon, <u,v,w> */
@@ -141,7 +167,7 @@ bool Triangulate::triangulate(const Vector<Vector2> &contour, Vector<int> &resul
int w = v + 1;
if (nv <= w) w = 0; /* next */
- if (snip(contour, u, v, w, nv, V)) {
+ if (snip(contour, u, v, w, nv, V, relaxed)) {
int a, b, c, s, t;
/* true names of the vertices */
diff --git a/core/math/triangulate.h b/core/math/triangulate.h
index e336dc5756..b1a583d0c5 100644
--- a/core/math/triangulate.h
+++ b/core/math/triangulate.h
@@ -51,10 +51,11 @@ public:
static bool is_inside_triangle(real_t Ax, real_t Ay,
real_t Bx, real_t By,
real_t Cx, real_t Cy,
- real_t Px, real_t Py);
+ real_t Px, real_t Py,
+ bool include_edges);
private:
- static bool snip(const Vector<Vector2> &p_contour, int u, int v, int w, int n, const Vector<int> &V);
+ static bool snip(const Vector<Vector2> &p_contour, int u, int v, int w, int n, const Vector<int> &V, bool relaxed);
};
#endif
diff --git a/core/message_queue.cpp b/core/message_queue.cpp
index 3ceafe1a30..25ee6eafae 100644
--- a/core/message_queue.cpp
+++ b/core/message_queue.cpp
@@ -278,7 +278,7 @@ void MessageQueue::flush() {
while (read_pos < buffer_end) {
- //lock on each interation, so a call can re-add itself to the message queue
+ //lock on each iteration, so a call can re-add itself to the message queue
Message *message = (Message *)&buffer[read_pos];
diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp
index 1941b82602..330a9153ef 100644
--- a/core/os/dir_access.cpp
+++ b/core/os/dir_access.cpp
@@ -301,8 +301,8 @@ Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) {
FileAccess *fsrc = FileAccess::open(p_from, FileAccess::READ, &err);
if (err) {
-
- ERR_FAIL_COND_V(err, err);
+ ERR_PRINTS("Failed to open " + p_from);
+ return err;
}
FileAccess *fdst = FileAccess::open(p_to, FileAccess::WRITE, &err);
@@ -310,7 +310,8 @@ Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) {
fsrc->close();
memdelete(fsrc);
- ERR_FAIL_COND_V(err, err);
+ ERR_PRINTS("Failed to open " + p_to);
+ return err;
}
fsrc->seek_end(0);
diff --git a/core/os/file_access.h b/core/os/file_access.h
index 5d10c1a9aa..c4635fdfbb 100644
--- a/core/os/file_access.h
+++ b/core/os/file_access.h
@@ -89,6 +89,9 @@ public:
virtual void close() = 0; ///< close a file
virtual bool is_open() const = 0; ///< true when file is open
+ virtual String get_path() const { return ""; } /// returns the path for the current open file
+ virtual String get_path_absolute() const { return ""; } /// returns the absolute path for the current open file
+
virtual void seek(size_t p_position) = 0; ///< seek to a given position
virtual void seek_end(int64_t p_position = 0) = 0; ///< seek from the end of file
virtual size_t get_position() const = 0; ///< get position in the file
diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp
index 12060f31df..b9607632f7 100644
--- a/core/os/input_event.cpp
+++ b/core/os/input_event.cpp
@@ -962,6 +962,11 @@ Ref<InputEvent> InputEventMagnifyGesture::xformed_by(const Transform2D &p_xform,
return ev;
}
+String InputEventMagnifyGesture::as_text() const {
+
+ return "InputEventMagnifyGesture : factor=" + rtos(get_factor()) + ", position=(" + String(get_position()) + ")";
+}
+
void InputEventMagnifyGesture::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_factor", "factor"), &InputEventMagnifyGesture::set_factor);
@@ -999,6 +1004,11 @@ Ref<InputEvent> InputEventPanGesture::xformed_by(const Transform2D &p_xform, con
return ev;
}
+String InputEventPanGesture::as_text() const {
+
+ return "InputEventPanGesture : delta=(" + String(get_delta()) + "), position=(" + String(get_position()) + ")";
+}
+
void InputEventPanGesture::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_delta", "delta"), &InputEventPanGesture::set_delta);
diff --git a/core/os/input_event.h b/core/os/input_event.h
index ad754d0d1f..0a33ab18a7 100644
--- a/core/os/input_event.h
+++ b/core/os/input_event.h
@@ -494,6 +494,7 @@ public:
real_t get_factor() const;
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const;
+ virtual String as_text() const;
InputEventMagnifyGesture();
};
@@ -511,6 +512,7 @@ public:
Vector2 get_delta() const;
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const;
+ virtual String as_text() const;
InputEventPanGesture();
};
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 422acf95dc..618a4bbac3 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -34,6 +34,7 @@
#include "input.h"
#include "os/file_access.h"
#include "project_settings.h"
+#include "servers/audio_server.h"
#include "version_generated.gen.h"
#include <stdarg.h>
@@ -627,6 +628,34 @@ void OS::center_window() {
set_window_position(Vector2(x, y));
}
+int OS::get_video_driver_count() const {
+
+ return 2;
+}
+
+const char *OS::get_video_driver_name(int p_driver) const {
+
+ switch (p_driver) {
+ case VIDEO_DRIVER_GLES2:
+ return "GLES2";
+ case VIDEO_DRIVER_GLES3:
+ default:
+ return "GLES3";
+ }
+}
+
+int OS::get_audio_driver_count() const {
+
+ return AudioDriverManager::get_driver_count();
+}
+
+const char *OS::get_audio_driver_name(int p_driver) const {
+
+ AudioDriver *driver = AudioDriverManager::get_driver(p_driver);
+ ERR_FAIL_COND_V(!driver, "");
+ return AudioDriverManager::get_driver(p_driver)->get_name();
+}
+
OS::OS() {
void *volatile stack_bottom;
diff --git a/core/os/os.h b/core/os/os.h
index 38e55fa3b7..5a2c998782 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -44,6 +44,12 @@
@author Juan Linietsky <reduzio@gmail.com>
*/
+enum VideoDriver {
+ VIDEO_DRIVER_GLES3,
+ VIDEO_DRIVER_GLES2,
+ VIDEO_DRIVER_MAX,
+};
+
class OS {
static OS *singleton;
@@ -115,12 +121,6 @@ protected:
RenderThreadMode _render_thread_mode;
// functions used by main to initialize/deintialize the OS
- virtual int get_video_driver_count() const = 0;
- virtual const char *get_video_driver_name(int p_driver) const = 0;
-
- virtual int get_audio_driver_count() const = 0;
- virtual const char *get_audio_driver_name(int p_driver) const = 0;
-
void add_logger(Logger *p_logger);
virtual void initialize_core() = 0;
@@ -175,6 +175,12 @@ public:
virtual VideoMode get_video_mode(int p_screen = 0) const = 0;
virtual void get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen = 0) const = 0;
+ virtual int get_video_driver_count() const;
+ virtual const char *get_video_driver_name(int p_driver) const;
+
+ virtual int get_audio_driver_count() const;
+ virtual const char *get_audio_driver_name(int p_driver) const;
+
virtual int get_screen_count() const { return 1; }
virtual int get_current_screen() const { return 0; }
virtual void set_current_screen(int p_screen) {}
diff --git a/core/os/thread_dummy.cpp b/core/os/thread_dummy.cpp
index fa0bb3dafd..b6371235c4 100644
--- a/core/os/thread_dummy.cpp
+++ b/core/os/thread_dummy.cpp
@@ -55,3 +55,11 @@ Semaphore *SemaphoreDummy::create() {
void SemaphoreDummy::make_default() {
Semaphore::create_func = &SemaphoreDummy::create;
};
+
+RWLock *RWLockDummy::create() {
+ return memnew(RWLockDummy);
+};
+
+void RWLockDummy::make_default() {
+ RWLock::create_func = &RWLockDummy::create;
+};
diff --git a/core/os/thread_dummy.h b/core/os/thread_dummy.h
index b67b52a726..74957b95fe 100644
--- a/core/os/thread_dummy.h
+++ b/core/os/thread_dummy.h
@@ -32,6 +32,7 @@
#define THREAD_DUMMY_H
#include "mutex.h"
+#include "rw_lock.h"
#include "semaphore.h"
#include "thread.h"
@@ -69,4 +70,20 @@ public:
static void make_default();
};
+class RWLockDummy : public RWLock {
+
+ static RWLock *create();
+
+public:
+ virtual void read_lock() {}
+ virtual void read_unlock() {}
+ virtual Error read_try_lock() { return OK; }
+
+ virtual void write_lock() {}
+ virtual void write_unlock() {}
+ virtual Error write_try_lock() { return OK; }
+
+ static void make_default();
+};
+
#endif
diff --git a/core/pool_allocator.cpp b/core/pool_allocator.cpp
index d81e1912bf..017586b92a 100644
--- a/core/pool_allocator.cpp
+++ b/core/pool_allocator.cpp
@@ -90,7 +90,7 @@ bool PoolAllocator::find_hole(EntryArrayPos *p_pos, int p_for_size) {
int hole_size = entry.pos - prev_entry_end_pos;
- /* detemine if what we want fits in that hole */
+ /* determine if what we want fits in that hole */
if (hole_size >= p_for_size) {
*p_pos = i;
return true;
@@ -100,7 +100,7 @@ bool PoolAllocator::find_hole(EntryArrayPos *p_pos, int p_for_size) {
prev_entry_end_pos = entry_end(entry);
}
- /* No holes between entrys, check at the end..*/
+ /* No holes between entries, check at the end..*/
if ((pool_size - prev_entry_end_pos) >= p_for_size) {
*p_pos = entry_count;
diff --git a/core/project_settings.cpp b/core/project_settings.cpp
index 0991c0df68..20d91e7940 100644
--- a/core/project_settings.cpp
+++ b/core/project_settings.cpp
@@ -268,12 +268,12 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bo
if (FileAccessNetworkClient::get_singleton()) {
- if (_load_settings("res://project.godot") == OK || _load_settings_binary("res://project.binary") == OK) {
-
- _load_settings("res://override.cfg");
+ Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
+ if (err == OK) {
+ // Optional, we don't mind if it fails
+ _load_settings_text("res://override.cfg");
}
-
- return OK;
+ return err;
}
String exec_path = OS::get_singleton()->get_executable_path();
@@ -285,12 +285,13 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bo
bool ok = _load_resource_pack(p_main_pack);
ERR_FAIL_COND_V(!ok, ERR_CANT_OPEN);
- if (_load_settings("res://project.godot") == OK || _load_settings_binary("res://project.binary") == OK) {
- //load override from location of the main pack
- _load_settings(p_main_pack.get_base_dir().plus_file("override.cfg"));
+ Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
+ if (err == OK) {
+ // Load override from location of the main pack
+ // Optional, we don't mind if it fails
+ _load_settings_text(p_main_pack.get_base_dir().plus_file("override.cfg"));
}
-
- return OK;
+ return err;
}
//Attempt with execname.pck
@@ -313,12 +314,13 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bo
// if we opened our package, try and load our project...
if (found) {
- if (_load_settings("res://project.godot") == OK || _load_settings_binary("res://project.binary") == OK) {
- // load override from location of executable
- _load_settings(exec_path.get_base_dir().plus_file("override.cfg"));
+ Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
+ if (err == OK) {
+ // Load override from location of executable
+ // Optional, we don't mind if it fails
+ _load_settings_text(exec_path.get_base_dir().plus_file("override.cfg"));
}
-
- return OK;
+ return err;
}
}
@@ -334,11 +336,13 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bo
// data.pck and data.zip are deprecated and no longer supported, apologies.
// make sure this is loaded from the resource path
- if (_load_settings("res://project.godot") == OK || _load_settings_binary("res://project.binary") == OK) {
- _load_settings("res://override.cfg");
+ Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
+ if (err == OK) {
+ // Optional, we don't mind if it fails
+ _load_settings_text("res://override.cfg");
}
- return OK;
+ return err;
}
//Nothing was found, try to find a project.godot somewhere!
@@ -350,20 +354,23 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bo
String candidate = d->get_current_dir();
String current_dir = d->get_current_dir();
+
bool found = false;
+ Error err;
while (true) {
- //try to load settings in ascending through dirs shape!
- if (_load_settings(current_dir + "/project.godot") == OK || _load_settings_binary(current_dir + "/project.binary") == OK) {
-
- _load_settings(current_dir + "/override.cfg");
+ err = _load_settings_text_or_binary(current_dir.plus_file("project.godot"), current_dir.plus_file("project.binary"));
+ if (err == OK) {
+ // Optional, we don't mind if it fails
+ _load_settings_text(current_dir.plus_file("override.cfg"));
candidate = current_dir;
found = true;
break;
}
if (p_upwards) {
+ // Try to load settings ascending through dirs shape!
d->change_dir("..");
if (d->get_current_dir() == current_dir)
break; //not doing anything useful
@@ -378,7 +385,7 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bo
memdelete(d);
if (!found)
- return ERR_FILE_NOT_FOUND;
+ return err;
if (resource_path.length() && resource_path[resource_path.length() - 1] == '/')
resource_path = resource_path.substr(0, resource_path.length() - 1); // chop end
@@ -440,13 +447,17 @@ Error ProjectSettings::_load_settings_binary(const String p_path) {
return OK;
}
-Error ProjectSettings::_load_settings(const String p_path) {
+
+Error ProjectSettings::_load_settings_text(const String p_path) {
Error err;
FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
- if (!f)
- return ERR_CANT_OPEN;
+ if (!f) {
+ // FIXME: Above 'err' error code is ERR_FILE_CANT_OPEN if the file is missing
+ // This needs to be streamlined if we want decent error reporting
+ return ERR_FILE_NOT_FOUND;
+ }
VariantParser::StreamFile stream;
stream.f = f;
@@ -471,7 +482,7 @@ Error ProjectSettings::_load_settings(const String p_path) {
memdelete(f);
return OK;
} else if (err != OK) {
- ERR_PRINTS("ProjectSettings::load - " + p_path + ":" + itos(lines) + " error: " + error_text);
+ ERR_PRINTS("Error parsing " + p_path + " at line " + itos(lines) + ": " + error_text + " File might be corrupted.");
memdelete(f);
return err;
}
@@ -497,6 +508,23 @@ Error ProjectSettings::_load_settings(const String p_path) {
return OK;
}
+Error ProjectSettings::_load_settings_text_or_binary(const String p_text_path, const String p_bin_path) {
+
+ // Attempt first to load the text-based project.godot file
+ Error err_text = _load_settings_text(p_text_path);
+ if (err_text == OK) {
+ return OK;
+ } else if (err_text != ERR_FILE_NOT_FOUND) {
+ // If the text-based file exists but can't be loaded, we want to know it
+ ERR_PRINTS("Couldn't load file '" + p_text_path + "', error code " + itos(err_text) + ".");
+ return err_text;
+ }
+
+ // Fallback to binary project.binary file if text-based was not found
+ Error err_bin = _load_settings_binary(p_bin_path);
+ return err_bin;
+}
+
int ProjectSettings::get_order(const String &p_name) const {
ERR_FAIL_COND_V(!props.has(p_name), -1);
@@ -525,7 +553,7 @@ void ProjectSettings::clear(const String &p_name) {
Error ProjectSettings::save() {
- return save_custom(get_resource_path() + "/project.godot");
+ return save_custom(get_resource_path().plus_file("project.godot"));
}
Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<String, List<String> > &props, const CustomMap &p_custom, const String &p_custom_features) {
@@ -664,7 +692,10 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const Map<Strin
String vstr;
VariantWriter::write_to_string(value, vstr);
- file->store_string(F->get() + "=" + vstr + "\n");
+ if (F->get().find(" ") != -1)
+ file->store_string(F->get().quote() + "=" + vstr + "\n");
+ else
+ file->store_string(F->get() + "=" + vstr + "\n");
}
}
@@ -999,6 +1030,20 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("input/ui_page_down", va);
input_presets.push_back("input/ui_page_down");
+ va = Array();
+ key.instance();
+ key->set_scancode(KEY_HOME);
+ va.push_back(key);
+ GLOBAL_DEF("input/ui_home", va);
+ input_presets.push_back("input/ui_home");
+
+ va = Array();
+ key.instance();
+ key->set_scancode(KEY_END);
+ va.push_back(key);
+ GLOBAL_DEF("input/ui_end", va);
+ input_presets.push_back("input/ui_end");
+
//GLOBAL_DEF("display/window/handheld/orientation", "landscape");
custom_prop_info["display/window/handheld/orientation"] = PropertyInfo(Variant::STRING, "display/window/handheld/orientation", PROPERTY_HINT_ENUM, "landscape,portrait,reverse_landscape,reverse_portrait,sensor_landscape,sensor_portrait,sensor");
diff --git a/core/project_settings.h b/core/project_settings.h
index eba53441cf..9b51bc3ac3 100644
--- a/core/project_settings.h
+++ b/core/project_settings.h
@@ -93,8 +93,9 @@ protected:
static ProjectSettings *singleton;
- Error _load_settings(const String p_path);
+ Error _load_settings_text(const String p_path);
Error _load_settings_binary(const String p_path);
+ Error _load_settings_text_or_binary(const String p_text_path, const String p_bin_path);
Error _save_settings_text(const String &p_file, const Map<String, List<String> > &props, const CustomMap &p_custom = CustomMap(), const String &p_custom_features = String());
Error _save_settings_binary(const String &p_file, const Map<String, List<String> > &props, const CustomMap &p_custom = CustomMap(), const String &p_custom_features = String());
diff --git a/core/reference.h b/core/reference.h
index a0bdb62258..0d6b1ced6e 100644
--- a/core/reference.h
+++ b/core/reference.h
@@ -63,7 +63,7 @@ public:
template <class T>
class Ref {
- T *reference = NULL;
+ T *reference;
void ref(const Ref &p_from) {
@@ -213,10 +213,9 @@ public:
Ref(T *p_reference) {
+ reference = NULL;
if (p_reference)
ref_pointer(p_reference);
- else
- reference = NULL;
}
Ref(const Variant &p_variant) {
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp
index 41071ace5d..632285f48d 100644
--- a/core/script_debugger_remote.cpp
+++ b/core/script_debugger_remote.cpp
@@ -1016,11 +1016,11 @@ void ScriptDebuggerRemote::add_profiling_frame_data(const StringName &p_name, co
}
void ScriptDebuggerRemote::profiling_start() {
- //ignores this, uses it via connnection
+ //ignores this, uses it via connection
}
void ScriptDebuggerRemote::profiling_end() {
- //ignores this, uses it via connnection
+ //ignores this, uses it via connection
}
void ScriptDebuggerRemote::profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) {
diff --git a/core/script_language.h b/core/script_language.h
index d1da0a3b72..6d32fc054c 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -203,6 +203,7 @@ public:
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 String validate_path(const String &p_path) const { return ""; }
virtual Script *create_script() const = 0;
virtual bool has_named_classes() const = 0;
virtual bool supports_builtin_mode() const = 0;
diff --git a/core/set.h b/core/set.h
index 4f17c953b1..d79dd81644 100644
--- a/core/set.h
+++ b/core/set.h
@@ -185,7 +185,7 @@ private:
if (node->right != _data._nil) {
node = node->right;
- while (node->left != _data._nil) { /* returns the minium of the right subtree of node */
+ while (node->left != _data._nil) { /* returns the minimum of the right subtree of node */
node = node->left;
}
return node;
@@ -207,7 +207,7 @@ private:
if (node->left != _data._nil) {
node = node->left;
- while (node->right != _data._nil) { /* returns the minium of the left subtree of node */
+ while (node->right != _data._nil) { /* returns the minimum of the left subtree of node */
node = node->right;
}
return node;
diff --git a/core/string_buffer.h b/core/string_buffer.h
index b148e45544..7e9b151bea 100644
--- a/core/string_buffer.h
+++ b/core/string_buffer.h
@@ -39,7 +39,7 @@ class StringBuffer {
CharType short_buffer[SHORT_BUFFER_SIZE];
String buffer;
- int string_length = 0;
+ int string_length;
_FORCE_INLINE_ CharType *current_buffer_ptr() {
return static_cast<Vector<CharType> &>(buffer).empty() ? short_buffer : buffer.ptrw();
@@ -79,6 +79,10 @@ public:
_FORCE_INLINE_ operator String() {
return as_string();
}
+
+ StringBuffer() {
+ string_length = 0;
+ }
};
template <int SHORT_BUFFER_SIZE>
diff --git a/core/string_builder.h b/core/string_builder.h
index 9e2599ac32..596b3bf730 100644
--- a/core/string_builder.h
+++ b/core/string_builder.h
@@ -37,7 +37,7 @@
class StringBuilder {
- uint32_t string_length = 0;
+ uint32_t string_length;
Vector<String> strings;
Vector<const char *> c_strings;
@@ -75,6 +75,10 @@ public:
_FORCE_INLINE_ operator String() const {
return as_string();
}
+
+ StringBuilder() {
+ string_length = 0;
+ }
};
#endif // STRING_BUILDER_H
diff --git a/core/ustring.cpp b/core/ustring.cpp
index d445e4ed47..a7a7810837 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -1135,6 +1135,36 @@ String String::num_int64(int64_t p_num, int base, bool capitalize_hex) {
return s;
}
+String String::num_uint64(uint64_t p_num, int base, bool capitalize_hex) {
+
+ uint64_t n = p_num;
+
+ int chars = 0;
+ do {
+ n /= base;
+ chars++;
+ } while (n);
+
+ String s;
+ s.resize(chars + 1);
+ CharType *c = s.ptrw();
+ c[chars] = 0;
+ n = p_num;
+ do {
+ int mod = ABS(n % base);
+ if (mod >= 10) {
+ char a = (capitalize_hex ? 'A' : 'a');
+ c[--chars] = a + (mod - 10);
+ } else {
+ c[--chars] = '0' + mod;
+ }
+
+ n /= base;
+ } while (n);
+
+ return s;
+}
+
String String::num_real(double p_num) {
String s;
diff --git a/core/ustring.h b/core/ustring.h
index 90496b71b6..bb676ce623 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -146,6 +146,7 @@ public:
static String num_scientific(double p_num);
static String num_real(double p_num);
static String num_int64(int64_t p_num, int base = 10, bool capitalize_hex = false);
+ static String num_uint64(uint64_t p_num, int base = 10, bool capitalize_hex = false);
static String chr(CharType p_char);
static String md5(const uint8_t *p_md5);
static String hex_encode_buffer(const uint8_t *p_buffer, int p_len);
diff --git a/core/variant.cpp b/core/variant.cpp
index 2e26169bfe..5d48c8785e 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -1607,6 +1607,8 @@ Variant::operator Vector3() const {
if (type == VECTOR3)
return *reinterpret_cast<const Vector3 *>(_data._mem);
+ else if (type == VECTOR2)
+ return Vector3(reinterpret_cast<const Vector2 *>(_data._mem)->x, reinterpret_cast<const Vector2 *>(_data._mem)->y, 0.0);
else
return Vector3();
}
diff --git a/core/variant.h b/core/variant.h
index 51ee8ea9d1..0a4afada5b 100644
--- a/core/variant.h
+++ b/core/variant.h
@@ -293,7 +293,7 @@ public:
// If this changes the table in variant_op must be updated
enum Operator {
- //comparation
+ //comparison
OP_EQUAL,
OP_NOT_EQUAL,
OP_LESS,
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 5607751a27..cda7dccf0c 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -347,7 +347,7 @@ struct _VariantCall {
VCALL_LOCALMEM1R(Vector2, bounce);
VCALL_LOCALMEM1R(Vector2, reflect);
VCALL_LOCALMEM0R(Vector2, angle);
- //VCALL_LOCALMEM1R(Vector2,cross);
+ VCALL_LOCALMEM1R(Vector2, cross);
VCALL_LOCALMEM0R(Vector2, abs);
VCALL_LOCALMEM1R(Vector2, clamped);
@@ -443,6 +443,7 @@ struct _VariantCall {
VCALL_LOCALMEM1R(Color, lightened);
VCALL_LOCALMEM1R(Color, darkened);
VCALL_LOCALMEM1R(Color, to_html);
+ VCALL_LOCALMEM4R(Color, from_hsv);
VCALL_LOCALMEM0R(RID, get_id);
@@ -490,6 +491,7 @@ struct _VariantCall {
VCALL_LOCALMEM1(Array, erase);
VCALL_LOCALMEM0(Array, sort);
VCALL_LOCALMEM2(Array, sort_custom);
+ VCALL_LOCALMEM0(Array, shuffle);
VCALL_LOCALMEM2R(Array, bsearch);
VCALL_LOCALMEM4R(Array, bsearch_custom);
VCALL_LOCALMEM0R(Array, duplicate);
@@ -1515,7 +1517,7 @@ void register_variant_methods() {
ADDFUNC1R(VECTOR2, VECTOR2, Vector2, slide, VECTOR2, "n", varray());
ADDFUNC1R(VECTOR2, VECTOR2, Vector2, bounce, VECTOR2, "n", varray());
ADDFUNC1R(VECTOR2, VECTOR2, Vector2, reflect, VECTOR2, "n", varray());
- //ADDFUNC1R(VECTOR2,REAL,Vector2,cross,VECTOR2,"with",varray());
+ ADDFUNC1R(VECTOR2, REAL, Vector2, cross, VECTOR2, "with", varray());
ADDFUNC0R(VECTOR2, VECTOR2, Vector2, abs, varray());
ADDFUNC1R(VECTOR2, VECTOR2, Vector2, clamped, REAL, "length", varray());
@@ -1589,6 +1591,7 @@ void register_variant_methods() {
ADDFUNC1R(COLOR, COLOR, Color, lightened, REAL, "amount", varray());
ADDFUNC1R(COLOR, COLOR, Color, darkened, REAL, "amount", varray());
ADDFUNC1R(COLOR, STRING, Color, to_html, BOOL, "with_alpha", varray(true));
+ ADDFUNC4R(COLOR, COLOR, Color, from_hsv, REAL, "h", REAL, "s", REAL, "v", REAL, "a", varray(1.0));
ADDFUNC0R(_RID, INT, RID, get_id, varray());
@@ -1634,6 +1637,7 @@ void register_variant_methods() {
ADDFUNC0RNC(ARRAY, NIL, Array, pop_front, varray());
ADDFUNC0NC(ARRAY, NIL, Array, sort, varray());
ADDFUNC2NC(ARRAY, NIL, Array, sort_custom, OBJECT, "obj", STRING, "func", varray());
+ ADDFUNC0NC(ARRAY, NIL, Array, shuffle, varray());
ADDFUNC2R(ARRAY, INT, Array, bsearch, NIL, "value", BOOL, "before", varray(true));
ADDFUNC4R(ARRAY, INT, Array, bsearch_custom, NIL, "value", OBJECT, "obj", STRING, "func", BOOL, "before", varray(true));
ADDFUNC0NC(ARRAY, NIL, Array, invert, varray());
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index e46fac77ee..842f5f0af6 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -147,7 +147,7 @@ Variant::operator bool() const {
return booleanize();
}
-// We consider all unitialized or empty types to be false based on the type's
+// We consider all uninitialized or empty types to be false based on the type's
// zeroiness.
bool Variant::booleanize() const {
return !is_zero();
@@ -177,7 +177,7 @@ bool Variant::booleanize() const {
CASE_TYPE(m_prefix, m_op_name, m_name) { \
if (p_b.type == INT) _RETURN(p_a._data.m_type m_op p_b._data._int); \
if (p_b.type == REAL) _RETURN(p_a._data.m_type m_op p_b._data._real); \
- if (p_b.type == NIL) _RETURN(!p_b.type m_op NIL); \
+ if (p_b.type == NIL) _RETURN(!(p_b.type m_op NIL)); \
\
_RETURN_FAIL \
};
@@ -252,7 +252,7 @@ bool Variant::booleanize() const {
CASE_TYPE(m_prefix, m_op_name, m_name) { \
if (p_b.type == STRING) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \
if (p_b.type == NODE_PATH) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \
- if (p_b.type == NIL) _RETURN(!p_b.type m_op NIL); \
+ if (p_b.type == NIL) _RETURN(!(p_b.type m_op NIL)); \
\
_RETURN_FAIL \
};
@@ -278,7 +278,7 @@ bool Variant::booleanize() const {
if (p_b.type == m_name) \
_RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \
if (p_b.type == NIL) \
- _RETURN(!p_b.type m_op NIL); \
+ _RETURN(!(p_b.type m_op NIL)); \
\
_RETURN_FAIL \
};
@@ -323,7 +323,7 @@ bool Variant::booleanize() const {
if (p_b.type == m_name) \
_RETURN(*p_a._data.m_sub m_op *p_b._data.m_sub); \
if (p_b.type == NIL) \
- _RETURN(!p_b.type m_op NIL); \
+ _RETURN(!(p_b.type m_op NIL)); \
\
_RETURN_FAIL \
}
@@ -1501,7 +1501,7 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool
v->set_hsv(v->get_h(), p_value._data._real, v->get_v());
valid = true;
} else if (p_index == CoreStringNames::singleton->v) {
- v->set_hsv(v->get_h(), v->get_v(), p_value._data._real);
+ v->set_hsv(v->get_h(), v->get_s(), p_value._data._real);
valid = true;
}
}
diff --git a/core/version.h b/core/version.h
index 7a55d69ad7..d39172865a 100644
--- a/core/version.h
+++ b/core/version.h
@@ -30,9 +30,32 @@
#include "version_generated.gen.h"
+// Godot versions are of the form <major>.<minor> for the initial release,
+// and then <major>.<minor>.<patch> for subsequent bugfix releases where <patch> != 0
+// That's arbitrary, but we find it pretty and it's the current policy.
+
+// Defines the main "branch" version. Patch versions in this branch should be
+// forward-compatible.
+// Example: "3.1"
+#define VERSION_BRANCH "" _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR)
#ifdef VERSION_PATCH
-#define VERSION_MKSTRING "" _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "." _MKSTR(VERSION_PATCH) "." VERSION_STATUS "." VERSION_BUILD VERSION_MODULE_CONFIG
+// Example: "3.1.4"
+#define VERSION_NUMBER "" VERSION_BRANCH "." _MKSTR(VERSION_PATCH)
#else
-#define VERSION_MKSTRING "" _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "." VERSION_STATUS "." VERSION_BUILD VERSION_MODULE_CONFIG
+// Example: "3.1"
+#define VERSION_NUMBER "" VERSION_BRANCH
#endif // VERSION_PATCH
-#define VERSION_FULL_NAME "" VERSION_NAME " v" VERSION_MKSTRING
+
+// Describes the full configuration of that Godot version, including the version number,
+// the status (beta, stable, etc.) and potential module-specific features (e.g. mono).
+// Example: "3.1.4.stable.mono"
+#define VERSION_FULL_CONFIG "" VERSION_NUMBER "." VERSION_STATUS VERSION_MODULE_CONFIG
+
+// Similar to VERSION_FULL_CONFIG, but also includes the (potentially custom) VERSION_BUILD
+// description (e.g. official, custom_build, etc.).
+// Example: "3.1.4.stable.mono.official"
+#define VERSION_FULL_BUILD "" VERSION_FULL_CONFIG "." VERSION_BUILD
+
+// Same as above, but prepended with Godot's name and a cosmetic "v" for "version".
+// Example: "Godot v3.1.4.stable.official.mono"
+#define VERSION_FULL_NAME "" VERSION_NAME " v" VERSION_FULL_BUILD