summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/array.cpp43
-rw-r--r--core/array.h2
-rw-r--r--core/color.h18
-rw-r--r--core/command_queue_mt.cpp24
-rw-r--r--core/command_queue_mt.h1509
-rw-r--r--core/io/logger.cpp5
-rw-r--r--core/io/logger.h2
-rw-r--r--core/io/marshalls.cpp20
-rw-r--r--core/io/resource_format_binary.cpp17
-rw-r--r--core/io/resource_format_binary.h1
-rw-r--r--core/node_path.cpp81
-rw-r--r--core/node_path.h13
-rw-r--r--core/object.cpp123
-rw-r--r--core/object.h5
-rw-r--r--core/os/dir_access.cpp97
-rw-r--r--core/os/dir_access.h4
-rw-r--r--core/os/input_event.cpp98
-rw-r--r--core/os/input_event.h40
-rw-r--r--core/os/keyboard.cpp43
-rw-r--r--core/os/keyboard.h1
-rw-r--r--core/os/memory.cpp20
-rw-r--r--core/os/memory.h8
-rw-r--r--core/os/os.cpp44
-rw-r--r--core/os/os.h11
-rw-r--r--core/script_debugger_remote.cpp157
-rw-r--r--core/script_language.h7
-rw-r--r--core/translation.cpp2
-rw-r--r--core/ustring.cpp11
-rw-r--r--core/ustring.h2
-rw-r--r--core/variant.cpp15
-rw-r--r--core/variant_call.cpp20
-rw-r--r--core/variant_parser.cpp2
32 files changed, 1083 insertions, 1362 deletions
diff --git a/core/array.cpp b/core/array.cpp
index 171c11776c..b7d4ae413a 100644
--- a/core/array.cpp
+++ b/core/array.cpp
@@ -265,6 +265,49 @@ Array &Array::sort_custom(Object *p_obj, const StringName &p_function) {
return *this;
}
+template <typename Less>
+_FORCE_INLINE_ int bisect(const Vector<Variant> &p_array, const Variant &p_value, bool p_before, const Less &p_less) {
+
+ int lo = 0;
+ int hi = p_array.size();
+ if (p_before) {
+ while (lo < hi) {
+ const int mid = (lo + hi) / 2;
+ if (p_less(p_array.get(mid), p_value)) {
+ lo = mid + 1;
+ } else {
+ hi = mid;
+ }
+ }
+ } else {
+ while (lo < hi) {
+ const int mid = (lo + hi) / 2;
+ if (p_less(p_value, p_array.get(mid))) {
+ hi = mid;
+ } else {
+ lo = mid + 1;
+ }
+ }
+ }
+ return lo;
+}
+
+int Array::bsearch(const Variant &p_value, bool p_before) {
+
+ return bisect(_p->array, p_value, p_before, _ArrayVariantSort());
+}
+
+int Array::bsearch_custom(const Variant &p_value, Object *p_obj, const StringName &p_function, bool p_before) {
+
+ ERR_FAIL_NULL_V(p_obj, 0);
+
+ _ArrayVariantSortCustom less;
+ less.obj = p_obj;
+ less.func = p_function;
+
+ return bisect(_p->array, p_value, p_before, less);
+}
+
Array &Array::invert() {
_p->array.invert();
diff --git a/core/array.h b/core/array.h
index 2c29103108..3d70a31d2f 100644
--- a/core/array.h
+++ b/core/array.h
@@ -70,6 +70,8 @@ public:
Array &sort();
Array &sort_custom(Object *p_obj, const StringName &p_function);
+ 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();
int find(const Variant &p_value, int p_from = 0) const;
diff --git a/core/color.h b/core/color.h
index 972b6a1b33..da2bfdcd98 100644
--- a/core/color.h
+++ b/core/color.h
@@ -101,6 +101,24 @@ struct Color {
return res;
}
+ _FORCE_INLINE_ Color darkened(float p_amount) const {
+
+ Color res = *this;
+ res.r = CLAMP(res.r * (1.0f - p_amount), 0.0, 1.0);
+ res.g = CLAMP(res.g * (1.0f - p_amount), 0.0, 1.0);
+ res.b = CLAMP(res.b * (1.0f - p_amount), 0.0, 1.0);
+ return res;
+ }
+
+ _FORCE_INLINE_ Color lightened(float p_amount) const {
+
+ Color res = *this;
+ res.r = CLAMP(res.r + (1.0f - res.r) * p_amount, 0.0, 1.0);
+ res.g = CLAMP(res.g + (1.0f - res.g) * p_amount, 0.0, 1.0);
+ res.b = CLAMP(res.b + (1.0f - res.b) * p_amount, 0.0, 1.0);
+ return res;
+ }
+
_FORCE_INLINE_ uint32_t to_rgbe9995() const {
const float pow2to9 = 512.0f;
diff --git a/core/command_queue_mt.cpp b/core/command_queue_mt.cpp
index 8e2aa24c22..2028a18a06 100644
--- a/core/command_queue_mt.cpp
+++ b/core/command_queue_mt.cpp
@@ -76,6 +76,30 @@ CommandQueueMT::SyncSemaphore *CommandQueueMT::_alloc_sync_sem() {
return &sync_sems[idx];
}
+bool CommandQueueMT::dealloc_one() {
+tryagain:
+ if (dealloc_ptr == write_ptr) {
+ // The queue is empty
+ return false;
+ }
+
+ uint32_t size = *(uint32_t *)&command_mem[dealloc_ptr];
+
+ if (size == 0) {
+ // End of command buffer wrap down
+ dealloc_ptr = 0;
+ goto tryagain;
+ }
+
+ if (size & 1) {
+ // Still used, nothing can be deallocated
+ return false;
+ }
+
+ dealloc_ptr += (size >> 1) + sizeof(uint32_t);
+ return true;
+}
+
CommandQueueMT::CommandQueueMT(bool p_sync) {
read_ptr = 0;
diff --git a/core/command_queue_mt.h b/core/command_queue_mt.h
index e37d593f9f..697fec3fc4 100644
--- a/core/command_queue_mt.h
+++ b/core/command_queue_mt.h
@@ -39,6 +39,230 @@
@author Juan Linietsky <reduzio@gmail.com>
*/
+#define COMMA(N) _COMMA_##N
+#define _COMMA_0
+#define _COMMA_1 ,
+#define _COMMA_2 ,
+#define _COMMA_3 ,
+#define _COMMA_4 ,
+#define _COMMA_5 ,
+#define _COMMA_6 ,
+#define _COMMA_7 ,
+#define _COMMA_8 ,
+#define _COMMA_9 ,
+#define _COMMA_10 ,
+#define _COMMA_11 ,
+#define _COMMA_12 ,
+
+// 1-based comma separed 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) \
+ , ITEM(12)
+#define _COMMA_SEP_LIST_11(ITEM) \
+ _COMMA_SEP_LIST_10(ITEM) \
+ , ITEM(11)
+#define _COMMA_SEP_LIST_10(ITEM) \
+ _COMMA_SEP_LIST_9(ITEM) \
+ , ITEM(10)
+#define _COMMA_SEP_LIST_9(ITEM) \
+ _COMMA_SEP_LIST_8(ITEM) \
+ , ITEM(9)
+#define _COMMA_SEP_LIST_8(ITEM) \
+ _COMMA_SEP_LIST_7(ITEM) \
+ , ITEM(8)
+#define _COMMA_SEP_LIST_7(ITEM) \
+ _COMMA_SEP_LIST_6(ITEM) \
+ , ITEM(7)
+#define _COMMA_SEP_LIST_6(ITEM) \
+ _COMMA_SEP_LIST_5(ITEM) \
+ , ITEM(6)
+#define _COMMA_SEP_LIST_5(ITEM) \
+ _COMMA_SEP_LIST_4(ITEM) \
+ , ITEM(5)
+#define _COMMA_SEP_LIST_4(ITEM) \
+ _COMMA_SEP_LIST_3(ITEM) \
+ , ITEM(4)
+#define _COMMA_SEP_LIST_3(ITEM) \
+ _COMMA_SEP_LIST_2(ITEM) \
+ , ITEM(3)
+#define _COMMA_SEP_LIST_2(ITEM) \
+ _COMMA_SEP_LIST_1(ITEM) \
+ , ITEM(2)
+#define _COMMA_SEP_LIST_1(ITEM) \
+ _COMMA_SEP_LIST_0(ITEM) \
+ ITEM(1)
+#define _COMMA_SEP_LIST_0(ITEM)
+
+// 1-based semicolon separed 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); \
+ ITEM(12)
+#define _SEMIC_SEP_LIST_11(ITEM) \
+ _SEMIC_SEP_LIST_10(ITEM); \
+ ITEM(11)
+#define _SEMIC_SEP_LIST_10(ITEM) \
+ _SEMIC_SEP_LIST_9(ITEM); \
+ ITEM(10)
+#define _SEMIC_SEP_LIST_9(ITEM) \
+ _SEMIC_SEP_LIST_8(ITEM); \
+ ITEM(9)
+#define _SEMIC_SEP_LIST_8(ITEM) \
+ _SEMIC_SEP_LIST_7(ITEM); \
+ ITEM(8)
+#define _SEMIC_SEP_LIST_7(ITEM) \
+ _SEMIC_SEP_LIST_6(ITEM); \
+ ITEM(7)
+#define _SEMIC_SEP_LIST_6(ITEM) \
+ _SEMIC_SEP_LIST_5(ITEM); \
+ ITEM(6)
+#define _SEMIC_SEP_LIST_5(ITEM) \
+ _SEMIC_SEP_LIST_4(ITEM); \
+ ITEM(5)
+#define _SEMIC_SEP_LIST_4(ITEM) \
+ _SEMIC_SEP_LIST_3(ITEM); \
+ ITEM(4)
+#define _SEMIC_SEP_LIST_3(ITEM) \
+ _SEMIC_SEP_LIST_2(ITEM); \
+ ITEM(3)
+#define _SEMIC_SEP_LIST_2(ITEM) \
+ _SEMIC_SEP_LIST_1(ITEM); \
+ ITEM(2)
+#define _SEMIC_SEP_LIST_1(ITEM) \
+ _SEMIC_SEP_LIST_0(ITEM) \
+ ITEM(1)
+#define _SEMIC_SEP_LIST_0(ITEM)
+
+// 1-based space separed 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) \
+ ITEM(12)
+#define _SPACE_SEP_LIST_11(ITEM) \
+ _SPACE_SEP_LIST_10(ITEM) \
+ ITEM(11)
+#define _SPACE_SEP_LIST_10(ITEM) \
+ _SPACE_SEP_LIST_9(ITEM) \
+ ITEM(10)
+#define _SPACE_SEP_LIST_9(ITEM) \
+ _SPACE_SEP_LIST_8(ITEM) \
+ ITEM(9)
+#define _SPACE_SEP_LIST_8(ITEM) \
+ _SPACE_SEP_LIST_7(ITEM) \
+ ITEM(8)
+#define _SPACE_SEP_LIST_7(ITEM) \
+ _SPACE_SEP_LIST_6(ITEM) \
+ ITEM(7)
+#define _SPACE_SEP_LIST_6(ITEM) \
+ _SPACE_SEP_LIST_5(ITEM) \
+ ITEM(6)
+#define _SPACE_SEP_LIST_5(ITEM) \
+ _SPACE_SEP_LIST_4(ITEM) \
+ ITEM(5)
+#define _SPACE_SEP_LIST_4(ITEM) \
+ _SPACE_SEP_LIST_3(ITEM) \
+ ITEM(4)
+#define _SPACE_SEP_LIST_3(ITEM) \
+ _SPACE_SEP_LIST_2(ITEM) \
+ ITEM(3)
+#define _SPACE_SEP_LIST_2(ITEM) \
+ _SPACE_SEP_LIST_1(ITEM) \
+ ITEM(2)
+#define _SPACE_SEP_LIST_1(ITEM) \
+ _SPACE_SEP_LIST_0(ITEM) \
+ ITEM(1)
+#define _SPACE_SEP_LIST_0(ITEM)
+
+#define ARG(N) p##N
+#define PARAM(N) P##N p##N
+#define TYPE_PARAM(N) class P##N
+#define PARAM_DECL(N) typename GetSimpleTypeT<P##N>::type_t p##N
+
+#define DECL_CMD(N) \
+ template <class T, class M COMMA(N) COMMA_SEP_LIST(TYPE_PARAM, N)> \
+ struct Command##N : public CommandBase { \
+ T *instance; \
+ M method; \
+ SEMIC_SEP_LIST(PARAM_DECL, N); \
+ virtual void call() { \
+ (instance->*method)(COMMA_SEP_LIST(ARG, N)); \
+ } \
+ };
+
+#define DECL_CMD_RET(N) \
+ template <class T, class M, COMMA_SEP_LIST(TYPE_PARAM, N) COMMA(N) class R> \
+ struct CommandRet##N : public SyncCommand { \
+ R *ret; \
+ T *instance; \
+ M method; \
+ SEMIC_SEP_LIST(PARAM_DECL, N); \
+ virtual void call() { \
+ *ret = (instance->*method)(COMMA_SEP_LIST(ARG, N)); \
+ } \
+ };
+
+#define DECL_CMD_SYNC(N) \
+ template <class T, class M COMMA(N) COMMA_SEP_LIST(TYPE_PARAM, N)> \
+ struct CommandSync##N : public SyncCommand { \
+ T *instance; \
+ M method; \
+ SEMIC_SEP_LIST(PARAM_DECL, N); \
+ virtual void call() { \
+ (instance->*method)(COMMA_SEP_LIST(ARG, N)); \
+ } \
+ };
+
+#define TYPE_ARG(N) P##N
+#define CMD_TYPE(N) Command##N<T, M COMMA(N) COMMA_SEP_LIST(TYPE_ARG, N)>
+#define CMD_ASSIGN_PARAM(N) cmd->p##N = p##N
+
+#define DECL_PUSH(N) \
+ template <class T, class M COMMA(N) COMMA_SEP_LIST(TYPE_PARAM, N)> \
+ void push(T *p_instance, M p_method COMMA(N) COMMA_SEP_LIST(PARAM, N)) { \
+ CMD_TYPE(N) *cmd = allocate_and_lock<CMD_TYPE(N)>(); \
+ cmd->instance = p_instance; \
+ cmd->method = p_method; \
+ SEMIC_SEP_LIST(CMD_ASSIGN_PARAM, N); \
+ unlock(); \
+ if (sync) sync->post(); \
+ }
+
+#define CMD_RET_TYPE(N) CommandRet##N<T, M, COMMA_SEP_LIST(TYPE_ARG, N) COMMA(N) R>
+
+#define DECL_PUSH_AND_RET(N) \
+ template <class T, class M, COMMA_SEP_LIST(TYPE_PARAM, N) COMMA(N) class R> \
+ void push_and_ret(T *p_instance, M p_method, COMMA_SEP_LIST(PARAM, N) COMMA(N) R *r_ret) { \
+ SyncSemaphore *ss = _alloc_sync_sem(); \
+ CMD_RET_TYPE(N) *cmd = allocate_and_lock<CMD_RET_TYPE(N)>(); \
+ cmd->instance = p_instance; \
+ cmd->method = p_method; \
+ SEMIC_SEP_LIST(CMD_ASSIGN_PARAM, N); \
+ cmd->ret = r_ret; \
+ cmd->sync_sem = ss; \
+ unlock(); \
+ if (sync) sync->post(); \
+ ss->sem->wait(); \
+ }
+
+#define CMD_SYNC_TYPE(N) CommandSync##N<T, M COMMA(N) COMMA_SEP_LIST(TYPE_ARG, N)>
+
+#define DECL_PUSH_AND_SYNC(N) \
+ template <class T, class M COMMA(N) COMMA_SEP_LIST(TYPE_PARAM, N)> \
+ void push_and_sync(T *p_instance, M p_method COMMA(N) COMMA_SEP_LIST(PARAM, N)) { \
+ SyncSemaphore *ss = _alloc_sync_sem(); \
+ CMD_SYNC_TYPE(N) *cmd = allocate_and_lock<CMD_SYNC_TYPE(N)>(); \
+ cmd->instance = p_instance; \
+ cmd->method = p_method; \
+ SEMIC_SEP_LIST(CMD_ASSIGN_PARAM, N); \
+ cmd->sync_sem = ss; \
+ unlock(); \
+ if (sync) sync->post(); \
+ ss->sem->wait(); \
+ }
+
+#define MAX_CMD_PARAMS 12
+
class CommandQueueMT {
struct SyncSemaphore {
@@ -50,556 +274,35 @@ class CommandQueueMT {
struct CommandBase {
virtual void call() = 0;
+ virtual void post(){};
virtual ~CommandBase(){};
};
- template <class T, class M>
- struct Command0 : public CommandBase {
-
- T *instance;
- M method;
-
- virtual void call() { (instance->*method)(); }
- };
-
- template <class T, class M, class P1>
- struct Command1 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
-
- virtual void call() { (instance->*method)(p1); }
- };
-
- template <class T, class M, class P1, class P2>
- struct Command2 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
-
- virtual void call() { (instance->*method)(p1, p2); }
- };
-
- template <class T, class M, class P1, class P2, class P3>
- struct Command3 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
-
- virtual void call() { (instance->*method)(p1, p2, p3); }
- };
-
- template <class T, class M, class P1, class P2, class P3, class P4>
- struct Command4 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
- typename GetSimpleTypeT<P4>::type_t p4;
-
- virtual void call() { (instance->*method)(p1, p2, p3, p4); }
- };
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5>
- struct Command5 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
- typename GetSimpleTypeT<P4>::type_t p4;
- typename GetSimpleTypeT<P5>::type_t p5;
-
- virtual void call() { (instance->*method)(p1, p2, p3, p4, p5); }
- };
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6>
- struct Command6 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
- typename GetSimpleTypeT<P4>::type_t p4;
- typename GetSimpleTypeT<P5>::type_t p5;
- typename GetSimpleTypeT<P6>::type_t p6;
-
- virtual void call() { (instance->*method)(p1, p2, p3, p4, p5, p6); }
- };
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7>
- struct Command7 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
- typename GetSimpleTypeT<P4>::type_t p4;
- typename GetSimpleTypeT<P5>::type_t p5;
- typename GetSimpleTypeT<P6>::type_t p6;
- typename GetSimpleTypeT<P7>::type_t p7;
-
- virtual void call() { (instance->*method)(p1, p2, p3, p4, p5, p6, p7); }
- };
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
- struct Command8 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
- typename GetSimpleTypeT<P4>::type_t p4;
- typename GetSimpleTypeT<P5>::type_t p5;
- typename GetSimpleTypeT<P6>::type_t p6;
- typename GetSimpleTypeT<P7>::type_t p7;
- typename GetSimpleTypeT<P8>::type_t p8;
-
- virtual void call() { (instance->*method)(p1, p2, p3, p4, p5, p6, p7, p8); }
- };
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9>
- struct Command9 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
- typename GetSimpleTypeT<P4>::type_t p4;
- typename GetSimpleTypeT<P5>::type_t p5;
- typename GetSimpleTypeT<P6>::type_t p6;
- typename GetSimpleTypeT<P7>::type_t p7;
- typename GetSimpleTypeT<P8>::type_t p8;
- typename GetSimpleTypeT<P9>::type_t p9;
-
- virtual void call() { (instance->*method)(p1, p2, p3, p4, p5, p6, p7, p8, p9); }
- };
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10>
- struct Command10 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
- typename GetSimpleTypeT<P4>::type_t p4;
- typename GetSimpleTypeT<P5>::type_t p5;
- typename GetSimpleTypeT<P6>::type_t p6;
- typename GetSimpleTypeT<P7>::type_t p7;
- typename GetSimpleTypeT<P8>::type_t p8;
- typename GetSimpleTypeT<P9>::type_t p9;
- typename GetSimpleTypeT<P10>::type_t p10;
-
- virtual void call() { (instance->*method)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); }
- };
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11>
- struct Command11 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
- typename GetSimpleTypeT<P4>::type_t p4;
- typename GetSimpleTypeT<P5>::type_t p5;
- typename GetSimpleTypeT<P6>::type_t p6;
- typename GetSimpleTypeT<P7>::type_t p7;
- typename GetSimpleTypeT<P8>::type_t p8;
- typename GetSimpleTypeT<P9>::type_t p9;
- typename GetSimpleTypeT<P10>::type_t p10;
- typename GetSimpleTypeT<P11>::type_t p11;
-
- virtual void call() { (instance->*method)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); }
- };
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11, class P12>
- struct Command12 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
- typename GetSimpleTypeT<P4>::type_t p4;
- typename GetSimpleTypeT<P5>::type_t p5;
- typename GetSimpleTypeT<P6>::type_t p6;
- typename GetSimpleTypeT<P7>::type_t p7;
- typename GetSimpleTypeT<P8>::type_t p8;
- typename GetSimpleTypeT<P9>::type_t p9;
- typename GetSimpleTypeT<P10>::type_t p10;
- typename GetSimpleTypeT<P11>::type_t p11;
- typename GetSimpleTypeT<P12>::type_t p12;
-
- virtual void call() { (instance->*method)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); }
- };
-
- /* comands that return */
-
- template <class T, class M, class R>
- struct CommandRet0 : public CommandBase {
-
- T *instance;
- M method;
- R *ret;
- SyncSemaphore *sync;
-
- virtual void call() {
- *ret = (instance->*method)();
- sync->sem->post();
- sync->in_use = false;
- }
- };
-
- template <class T, class M, class P1, class R>
- struct CommandRet1 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- R *ret;
- SyncSemaphore *sync;
-
- virtual void call() {
- *ret = (instance->*method)(p1);
- sync->sem->post();
- sync->in_use = false;
- }
- };
-
- template <class T, class M, class P1, class P2, class R>
- struct CommandRet2 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- R *ret;
- SyncSemaphore *sync;
-
- virtual void call() {
- *ret = (instance->*method)(p1, p2);
- sync->sem->post();
- sync->in_use = false;
- }
- };
-
- template <class T, class M, class P1, class P2, class P3, class R>
- struct CommandRet3 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
- R *ret;
- SyncSemaphore *sync;
-
- virtual void call() {
- *ret = (instance->*method)(p1, p2, p3);
- sync->sem->post();
- sync->in_use = false;
- }
- };
-
- template <class T, class M, class P1, class P2, class P3, class P4, class R>
- struct CommandRet4 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
- typename GetSimpleTypeT<P4>::type_t p4;
- R *ret;
- SyncSemaphore *sync;
-
- virtual void call() {
- *ret = (instance->*method)(p1, p2, p3, p4);
- sync->sem->post();
- sync->in_use = false;
- }
- };
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class R>
- struct CommandRet5 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
- typename GetSimpleTypeT<P4>::type_t p4;
- typename GetSimpleTypeT<P5>::type_t p5;
- R *ret;
- SyncSemaphore *sync;
-
- virtual void call() {
- *ret = (instance->*method)(p1, p2, p3, p4, p5);
- sync->sem->post();
- sync->in_use = false;
- }
- };
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class R>
- struct CommandRet6 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
- typename GetSimpleTypeT<P4>::type_t p4;
- typename GetSimpleTypeT<P5>::type_t p5;
- typename GetSimpleTypeT<P6>::type_t p6;
- R *ret;
- SyncSemaphore *sync;
-
- virtual void call() {
- *ret = (instance->*method)(p1, p2, p3, p4, p5, p6);
- sync->sem->post();
- sync->in_use = false;
- }
- };
+ struct SyncCommand : public CommandBase {
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class R>
- struct CommandRet7 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
- typename GetSimpleTypeT<P4>::type_t p4;
- typename GetSimpleTypeT<P5>::type_t p5;
- typename GetSimpleTypeT<P6>::type_t p6;
- typename GetSimpleTypeT<P7>::type_t p7;
- R *ret;
- SyncSemaphore *sync;
-
- virtual void call() {
- *ret = (instance->*method)(p1, p2, p3, p4, p5, p6, p7);
- sync->sem->post();
- sync->in_use = false;
- }
- };
+ SyncSemaphore *sync_sem;
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class R>
- struct CommandRet8 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
- typename GetSimpleTypeT<P4>::type_t p4;
- typename GetSimpleTypeT<P5>::type_t p5;
- typename GetSimpleTypeT<P6>::type_t p6;
- typename GetSimpleTypeT<P7>::type_t p7;
- typename GetSimpleTypeT<P8>::type_t p8;
- R *ret;
- SyncSemaphore *sync;
-
- virtual void call() {
- *ret = (instance->*method)(p1, p2, p3, p4, p5, p6, p7, p8);
- sync->sem->post();
- sync->in_use = false;
+ virtual void post() {
+ sync_sem->sem->post();
+ sync_sem->in_use = false;
}
};
- /** commands that don't return but sync */
+ DECL_CMD(0)
+ SPACE_SEP_LIST(DECL_CMD, 12)
/* comands that return */
+ DECL_CMD_RET(0)
+ SPACE_SEP_LIST(DECL_CMD_RET, 12)
- template <class T, class M>
- struct CommandSync0 : public CommandBase {
-
- T *instance;
- M method;
-
- SyncSemaphore *sync;
-
- virtual void call() {
- (instance->*method)();
- sync->sem->post();
- sync->in_use = false;
- }
- };
-
- template <class T, class M, class P1>
- struct CommandSync1 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
-
- SyncSemaphore *sync;
-
- virtual void call() {
- (instance->*method)(p1);
- sync->sem->post();
- sync->in_use = false;
- }
- };
-
- template <class T, class M, class P1, class P2>
- struct CommandSync2 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
-
- SyncSemaphore *sync;
-
- virtual void call() {
- (instance->*method)(p1, p2);
- sync->sem->post();
- sync->in_use = false;
- }
- };
-
- template <class T, class M, class P1, class P2, class P3>
- struct CommandSync3 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
-
- SyncSemaphore *sync;
-
- virtual void call() {
- (instance->*method)(p1, p2, p3);
- sync->sem->post();
- sync->in_use = false;
- }
- };
-
- template <class T, class M, class P1, class P2, class P3, class P4>
- struct CommandSync4 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
- typename GetSimpleTypeT<P4>::type_t p4;
-
- SyncSemaphore *sync;
-
- virtual void call() {
- (instance->*method)(p1, p2, p3, p4);
- sync->sem->post();
- sync->in_use = false;
- }
- };
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5>
- struct CommandSync5 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
- typename GetSimpleTypeT<P4>::type_t p4;
- typename GetSimpleTypeT<P5>::type_t p5;
-
- SyncSemaphore *sync;
-
- virtual void call() {
- (instance->*method)(p1, p2, p3, p4, p5);
- sync->sem->post();
- sync->in_use = false;
- }
- };
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6>
- struct CommandSync6 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
- typename GetSimpleTypeT<P4>::type_t p4;
- typename GetSimpleTypeT<P5>::type_t p5;
- typename GetSimpleTypeT<P6>::type_t p6;
-
- SyncSemaphore *sync;
-
- virtual void call() {
- (instance->*method)(p1, p2, p3, p4, p5, p6);
- sync->sem->post();
- sync->in_use = false;
- }
- };
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7>
- struct CommandSync7 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
- typename GetSimpleTypeT<P4>::type_t p4;
- typename GetSimpleTypeT<P5>::type_t p5;
- typename GetSimpleTypeT<P6>::type_t p6;
- typename GetSimpleTypeT<P7>::type_t p7;
-
- SyncSemaphore *sync;
-
- virtual void call() {
- (instance->*method)(p1, p2, p3, p4, p5, p6, p7);
- sync->sem->post();
- sync->in_use = false;
- }
- };
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
- struct CommandSync8 : public CommandBase {
-
- T *instance;
- M method;
- typename GetSimpleTypeT<P1>::type_t p1;
- typename GetSimpleTypeT<P2>::type_t p2;
- typename GetSimpleTypeT<P3>::type_t p3;
- typename GetSimpleTypeT<P4>::type_t p4;
- typename GetSimpleTypeT<P5>::type_t p5;
- typename GetSimpleTypeT<P6>::type_t p6;
- typename GetSimpleTypeT<P7>::type_t p7;
- typename GetSimpleTypeT<P8>::type_t p8;
-
- SyncSemaphore *sync;
-
- virtual void call() {
- (instance->*method)(p1, p2, p3, p4, p5, p6, p7, p8);
- sync->sem->post();
- sync->in_use = false;
- }
- };
+ /* commands that don't return but sync */
+ DECL_CMD_SYNC(0)
+ SPACE_SEP_LIST(DECL_CMD_SYNC, 12)
/***** BASE *******/
enum {
- COMMAND_MEM_SIZE_KB = 256,
+ COMMAND_MEM_SIZE_KB = 256 * 1024,
COMMAND_MEM_SIZE = COMMAND_MEM_SIZE_KB * 1024,
SYNC_SEMAPHORES = 8
};
@@ -607,6 +310,7 @@ class CommandQueueMT {
uint8_t command_mem[COMMAND_MEM_SIZE];
uint32_t read_ptr;
uint32_t write_ptr;
+ uint32_t dealloc_ptr;
SyncSemaphore sync_sems[SYNC_SEMAPHORES];
Mutex *mutex;
Semaphore *sync;
@@ -619,18 +323,30 @@ class CommandQueueMT {
tryagain:
- if (write_ptr < read_ptr) {
- // behind read_ptr, check that there is room
- if ((read_ptr - write_ptr) <= alloc_size)
+ if (write_ptr < dealloc_ptr) {
+ // behind dealloc_ptr, check that there is room
+ if ((dealloc_ptr - write_ptr) <= alloc_size) {
+
+ // There is no more room, try to deallocate something
+ if (dealloc_one()) {
+ goto tryagain;
+ }
return NULL;
- } else if (write_ptr >= read_ptr) {
- // ahead of read_ptr, check that there is room
+ }
+ } else if (write_ptr >= dealloc_ptr) {
+ // ahead of dealloc_ptr, check that there is room
- if ((COMMAND_MEM_SIZE - write_ptr) < alloc_size + 4) {
+ if ((COMMAND_MEM_SIZE - write_ptr) < alloc_size + sizeof(uint32_t)) {
// no room at the end, wrap down;
- if (read_ptr == 0) // don't want write_ptr to become read_ptr
+ if (dealloc_ptr == 0) { // don't want write_ptr to become dealloc_ptr
+
+ // There is no more room, try to deallocate something
+ if (dealloc_one()) {
+ goto tryagain;
+ }
return NULL;
+ }
// if this happens, it's a bug
ERR_FAIL_COND_V((COMMAND_MEM_SIZE - write_ptr) < sizeof(uint32_t), NULL);
@@ -642,9 +358,11 @@ class CommandQueueMT {
goto tryagain;
}
}
- // allocate the size
+ // Allocate the size and the 'in use' bit.
+ // First bit used to mark if command is still in use (1)
+ // or if it has been destroyed and can be deallocated (0).
uint32_t *p = (uint32_t *)&command_mem[write_ptr];
- *p = sizeof(T);
+ *p = (sizeof(T) << 1) | 1;
write_ptr += sizeof(uint32_t);
// allocate the command
T *cmd = memnew_placement(&command_mem[write_ptr], T);
@@ -669,15 +387,16 @@ class CommandQueueMT {
return ret;
}
- bool flush_one() {
-
+ bool flush_one(bool p_lock = true) {
+ if (p_lock) lock();
tryagain:
// tried to read an empty queue
if (read_ptr == write_ptr)
return false;
- uint32_t size = *(uint32_t *)(&command_mem[read_ptr]);
+ uint32_t size_ptr = read_ptr;
+ uint32_t size = *(uint32_t *)&command_mem[read_ptr] >> 1;
if (size == 0) {
//end of ringbuffer, wrap
@@ -689,11 +408,17 @@ class CommandQueueMT {
CommandBase *cmd = reinterpret_cast<CommandBase *>(&command_mem[read_ptr]);
+ read_ptr += size;
+
+ if (p_lock) unlock();
cmd->call();
- cmd->~CommandBase();
+ if (p_lock) lock();
- read_ptr += size;
+ cmd->post();
+ cmd->~CommandBase();
+ *(uint32_t *)&command_mem[size_ptr] &= ~1;
+ if (p_lock) unlock();
return true;
}
@@ -701,681 +426,33 @@ class CommandQueueMT {
void unlock();
void wait_for_flush();
SyncSemaphore *_alloc_sync_sem();
+ bool dealloc_one();
public:
/* NORMAL PUSH COMMANDS */
+ DECL_PUSH(0)
+ SPACE_SEP_LIST(DECL_PUSH, 12)
- template <class T, class M>
- void push(T *p_instance, M p_method) {
-
- Command0<T, M> *cmd = allocate_and_lock<Command0<T, M> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
-
- unlock();
-
- if (sync) sync->post();
- }
-
- template <class T, class M, class P1>
- void push(T *p_instance, M p_method, P1 p1) {
-
- Command1<T, M, P1> *cmd = allocate_and_lock<Command1<T, M, P1> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
-
- unlock();
-
- if (sync) sync->post();
- }
-
- template <class T, class M, class P1, class P2>
- void push(T *p_instance, M p_method, P1 p1, P2 p2) {
-
- Command2<T, M, P1, P2> *cmd = allocate_and_lock<Command2<T, M, P1, P2> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
-
- unlock();
-
- if (sync) sync->post();
- }
-
- template <class T, class M, class P1, class P2, class P3>
- void push(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3) {
-
- Command3<T, M, P1, P2, P3> *cmd = allocate_and_lock<Command3<T, M, P1, P2, P3> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
-
- unlock();
-
- if (sync) sync->post();
- }
-
- template <class T, class M, class P1, class P2, class P3, class P4>
- void push(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4) {
-
- Command4<T, M, P1, P2, P3, P4> *cmd = allocate_and_lock<Command4<T, M, P1, P2, P3, P4> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
- cmd->p4 = p4;
-
- unlock();
-
- if (sync) sync->post();
- }
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5>
- void push(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
-
- Command5<T, M, P1, P2, P3, P4, P5> *cmd = allocate_and_lock<Command5<T, M, P1, P2, P3, P4, P5> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
- cmd->p4 = p4;
- cmd->p5 = p5;
-
- unlock();
-
- if (sync) sync->post();
- }
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6>
- void push(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
-
- Command6<T, M, P1, P2, P3, P4, P5, P6> *cmd = allocate_and_lock<Command6<T, M, P1, P2, P3, P4, P5, P6> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
- cmd->p4 = p4;
- cmd->p5 = p5;
- cmd->p6 = p6;
-
- unlock();
-
- if (sync) sync->post();
- }
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7>
- void push(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
-
- Command7<T, M, P1, P2, P3, P4, P5, P6, P7> *cmd = allocate_and_lock<Command7<T, M, P1, P2, P3, P4, P5, P6, P7> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
- cmd->p4 = p4;
- cmd->p5 = p5;
- cmd->p6 = p6;
- cmd->p7 = p7;
-
- unlock();
-
- if (sync) sync->post();
- }
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
- void push(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {
-
- Command8<T, M, P1, P2, P3, P4, P5, P6, P7, P8> *cmd = allocate_and_lock<Command8<T, M, P1, P2, P3, P4, P5, P6, P7, P8> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
- cmd->p4 = p4;
- cmd->p5 = p5;
- cmd->p6 = p6;
- cmd->p7 = p7;
- cmd->p8 = p8;
-
- unlock();
-
- if (sync) sync->post();
- }
+ /* PUSH AND RET COMMANDS */
+ DECL_PUSH_AND_RET(0)
+ SPACE_SEP_LIST(DECL_PUSH_AND_RET, 12)
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9>
- void push(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9) {
-
- Command9<T, M, P1, P2, P3, P4, P5, P6, P7, P8, P9> *cmd = allocate_and_lock<Command9<T, M, P1, P2, P3, P4, P5, P6, P7, P8, P9> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
- cmd->p4 = p4;
- cmd->p5 = p5;
- cmd->p6 = p6;
- cmd->p7 = p7;
- cmd->p8 = p8;
- cmd->p9 = p9;
-
- unlock();
-
- if (sync) sync->post();
- }
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10>
- void push(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10) {
-
- Command10<T, M, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10> *cmd = allocate_and_lock<Command10<T, M, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
- cmd->p4 = p4;
- cmd->p5 = p5;
- cmd->p6 = p6;
- cmd->p7 = p7;
- cmd->p8 = p8;
- cmd->p9 = p9;
- cmd->p10 = p10;
-
- unlock();
-
- if (sync) sync->post();
- }
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11>
- void push(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10, P11 p11) {
-
- Command11<T, M, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11> *cmd = allocate_and_lock<Command11<T, M, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
- cmd->p4 = p4;
- cmd->p5 = p5;
- cmd->p6 = p6;
- cmd->p7 = p7;
- cmd->p8 = p8;
- cmd->p9 = p9;
- cmd->p10 = p10;
- cmd->p11 = p11;
-
- unlock();
-
- if (sync) sync->post();
- }
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11, class P12>
- void push(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10, P11 p11, P12 p12) {
-
- Command12<T, M, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12> *cmd = allocate_and_lock<Command12<T, M, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
- cmd->p4 = p4;
- cmd->p5 = p5;
- cmd->p6 = p6;
- cmd->p7 = p7;
- cmd->p8 = p8;
- cmd->p9 = p9;
- cmd->p10 = p10;
- cmd->p11 = p11;
- cmd->p12 = p12;
-
- unlock();
-
- if (sync) sync->post();
- }
-
- /*** PUSH AND RET COMMANDS ***/
-
- template <class T, class M, class R>
- void push_and_ret(T *p_instance, M p_method, R *r_ret) {
-
- SyncSemaphore *ss = _alloc_sync_sem();
-
- CommandRet0<T, M, R> *cmd = allocate_and_lock<CommandRet0<T, M, R> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->ret = r_ret;
-
- cmd->sync = ss;
-
- unlock();
-
- if (sync) sync->post();
- ss->sem->wait();
- }
-
- template <class T, class M, class P1, class R>
- void push_and_ret(T *p_instance, M p_method, P1 p1, R *r_ret) {
-
- SyncSemaphore *ss = _alloc_sync_sem();
-
- CommandRet1<T, M, P1, R> *cmd = allocate_and_lock<CommandRet1<T, M, P1, R> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->ret = r_ret;
-
- cmd->sync = ss;
-
- unlock();
-
- if (sync) sync->post();
- ss->sem->wait();
- }
-
- template <class T, class M, class P1, class P2, class R>
- void push_and_ret(T *p_instance, M p_method, P1 p1, P2 p2, R *r_ret) {
-
- SyncSemaphore *ss = _alloc_sync_sem();
-
- CommandRet2<T, M, P1, P2, R> *cmd = allocate_and_lock<CommandRet2<T, M, P1, P2, R> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->ret = r_ret;
-
- cmd->sync = ss;
-
- unlock();
-
- if (sync) sync->post();
- ss->sem->wait();
- }
-
- template <class T, class M, class P1, class P2, class P3, class R>
- void push_and_ret(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, R *r_ret) {
-
- SyncSemaphore *ss = _alloc_sync_sem();
-
- CommandRet3<T, M, P1, P2, P3, R> *cmd = allocate_and_lock<CommandRet3<T, M, P1, P2, P3, R> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
- cmd->ret = r_ret;
-
- cmd->sync = ss;
-
- unlock();
-
- if (sync) sync->post();
- ss->sem->wait();
- }
-
- template <class T, class M, class P1, class P2, class P3, class P4, class R>
- void push_and_ret(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, R *r_ret) {
-
- SyncSemaphore *ss = _alloc_sync_sem();
-
- CommandRet4<T, M, P1, P2, P3, P4, R> *cmd = allocate_and_lock<CommandRet4<T, M, P1, P2, P3, P4, R> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
- cmd->p4 = p4;
- cmd->ret = r_ret;
-
- cmd->sync = ss;
-
- unlock();
-
- if (sync) sync->post();
- ss->sem->wait();
- }
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class R>
- void push_and_ret(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, R *r_ret) {
-
- SyncSemaphore *ss = _alloc_sync_sem();
-
- CommandRet5<T, M, P1, P2, P3, P4, P5, R> *cmd = allocate_and_lock<CommandRet5<T, M, P1, P2, P3, P4, P5, R> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
- cmd->p4 = p4;
- cmd->p5 = p5;
- cmd->ret = r_ret;
-
- cmd->sync = ss;
-
- unlock();
-
- if (sync) sync->post();
- ss->sem->wait();
- }
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class R>
- void push_and_ret(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, R *r_ret) {
-
- SyncSemaphore *ss = _alloc_sync_sem();
-
- CommandRet6<T, M, P1, P2, P3, P4, P5, P6, R> *cmd = allocate_and_lock<CommandRet6<T, M, P1, P2, P3, P4, P5, P6, R> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
- cmd->p4 = p4;
- cmd->p5 = p5;
- cmd->p6 = p6;
- cmd->ret = r_ret;
-
- cmd->sync = ss;
-
- unlock();
-
- if (sync) sync->post();
- ss->sem->wait();
- }
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class R>
- void push_and_ret(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, R *r_ret) {
-
- SyncSemaphore *ss = _alloc_sync_sem();
-
- CommandRet7<T, M, P1, P2, P3, P4, P5, P6, P7, R> *cmd = allocate_and_lock<CommandRet7<T, M, P1, P2, P3, P4, P5, P6, P7, R> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
- cmd->p4 = p4;
- cmd->p5 = p5;
- cmd->p6 = p6;
- cmd->p7 = p7;
- cmd->ret = r_ret;
-
- cmd->sync = ss;
-
- unlock();
-
- if (sync) sync->post();
- ss->sem->wait();
- }
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class R>
- void push_and_ret(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, R *r_ret) {
-
- SyncSemaphore *ss = _alloc_sync_sem();
-
- CommandRet8<T, M, P1, P2, P3, P4, P5, P6, P7, P8, R> *cmd = allocate_and_lock<CommandRet8<T, M, P1, P2, P3, P4, P5, P6, P7, P8, R> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
- cmd->p4 = p4;
- cmd->p5 = p5;
- cmd->p6 = p6;
- cmd->p7 = p7;
- cmd->p8 = p8;
- cmd->ret = r_ret;
-
- cmd->sync = ss;
-
- unlock();
-
- if (sync) sync->post();
- ss->sem->wait();
- }
-
- template <class T, class M>
- void push_and_sync(T *p_instance, M p_method) {
-
- SyncSemaphore *ss = _alloc_sync_sem();
-
- CommandSync0<T, M> *cmd = allocate_and_lock<CommandSync0<T, M> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
-
- cmd->sync = ss;
-
- unlock();
-
- if (sync) sync->post();
- ss->sem->wait();
- }
-
- template <class T, class M, class P1>
- void push_and_sync(T *p_instance, M p_method, P1 p1) {
-
- SyncSemaphore *ss = _alloc_sync_sem();
-
- CommandSync1<T, M, P1> *cmd = allocate_and_lock<CommandSync1<T, M, P1> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
-
- cmd->sync = ss;
-
- unlock();
-
- if (sync) sync->post();
- ss->sem->wait();
- }
-
- template <class T, class M, class P1, class P2>
- void push_and_sync(T *p_instance, M p_method, P1 p1, P2 p2) {
-
- SyncSemaphore *ss = _alloc_sync_sem();
-
- CommandSync2<T, M, P1, P2> *cmd = allocate_and_lock<CommandSync2<T, M, P1, P2> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
-
- cmd->sync = ss;
-
- unlock();
-
- if (sync) sync->post();
- ss->sem->wait();
- }
-
- template <class T, class M, class P1, class P2, class P3>
- void push_and_sync(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3) {
-
- SyncSemaphore *ss = _alloc_sync_sem();
-
- CommandSync3<T, M, P1, P2, P3> *cmd = allocate_and_lock<CommandSync3<T, M, P1, P2, P3> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
-
- cmd->sync = ss;
-
- unlock();
-
- if (sync) sync->post();
- ss->sem->wait();
- }
-
- template <class T, class M, class P1, class P2, class P3, class P4>
- void push_and_sync(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4) {
-
- SyncSemaphore *ss = _alloc_sync_sem();
-
- CommandSync4<T, M, P1, P2, P3, P4> *cmd = allocate_and_lock<CommandSync4<T, M, P1, P2, P3, P4> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
- cmd->p4 = p4;
-
- cmd->sync = ss;
-
- unlock();
-
- if (sync) sync->post();
- ss->sem->wait();
- }
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5>
- void push_and_sync(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
-
- SyncSemaphore *ss = _alloc_sync_sem();
-
- CommandSync5<T, M, P1, P2, P3, P4, P5> *cmd = allocate_and_lock<CommandSync5<T, M, P1, P2, P3, P4, P5> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
- cmd->p4 = p4;
- cmd->p5 = p5;
-
- cmd->sync = ss;
-
- unlock();
-
- if (sync) sync->post();
- ss->sem->wait();
- }
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6>
- void push_and_sync(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
-
- SyncSemaphore *ss = _alloc_sync_sem();
-
- CommandSync6<T, M, P1, P2, P3, P4, P5, P6> *cmd = allocate_and_lock<CommandSync6<T, M, P1, P2, P3, P4, P5, P6> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
- cmd->p4 = p4;
- cmd->p5 = p5;
- cmd->p6 = p6;
-
- cmd->sync = ss;
-
- unlock();
-
- if (sync) sync->post();
- ss->sem->wait();
- }
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7>
- void push_and_sync(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
-
- SyncSemaphore *ss = _alloc_sync_sem();
-
- CommandSync7<T, M, P1, P2, P3, P4, P5, P6, P7> *cmd = allocate_and_lock<CommandSync7<T, M, P1, P2, P3, P4, P5, P6, P7> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
- cmd->p4 = p4;
- cmd->p5 = p5;
- cmd->p6 = p6;
- cmd->p7 = p7;
-
- cmd->sync = ss;
-
- unlock();
-
- if (sync) sync->post();
- ss->sem->wait();
- }
-
- template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
- void push_and_sync(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {
-
- SyncSemaphore *ss = _alloc_sync_sem();
-
- CommandSync8<T, M, P1, P2, P3, P4, P5, P6, P7, P8> *cmd = allocate_and_lock<CommandSync8<T, M, P1, P2, P3, P4, P5, P6, P7, P8> >();
-
- cmd->instance = p_instance;
- cmd->method = p_method;
- cmd->p1 = p1;
- cmd->p2 = p2;
- cmd->p3 = p3;
- cmd->p4 = p4;
- cmd->p5 = p5;
- cmd->p6 = p6;
- cmd->p7 = p7;
- cmd->p8 = p8;
-
- cmd->sync = ss;
-
- unlock();
-
- if (sync) sync->post();
- ss->sem->wait();
- }
+ /* PUSH AND RET SYNC COMMANDS*/
+ DECL_PUSH_AND_SYNC(0)
+ SPACE_SEP_LIST(DECL_PUSH_AND_SYNC, 12)
void wait_and_flush_one() {
ERR_FAIL_COND(!sync);
sync->wait();
- lock();
flush_one();
- unlock();
}
void flush_all() {
//ERR_FAIL_COND(sync);
lock();
- while (true) {
- bool exit = !flush_one();
- if (exit)
- break;
- }
+ while (flush_one(false))
+ ;
unlock();
}
@@ -1383,4 +460,20 @@ public:
~CommandQueueMT();
};
+#undef ARG
+#undef PARAM
+#undef TYPE_PARAM
+#undef PARAM_DECL
+#undef DECL_CMD
+#undef DECL_CMD_RET
+#undef DECL_CMD_SYNC
+#undef TYPE_ARG
+#undef CMD_TYPE
+#undef CMD_ASSIGN_PARAM
+#undef DECL_PUSH
+#undef CMD_RET_TYPE
+#undef DECL_PUSH_AND_RET
+#undef CMD_SYNC_TYPE
+#undef DECL_CMD_SYNC
+
#endif
diff --git a/core/io/logger.cpp b/core/io/logger.cpp
index ce2ce44b1d..7177359c8a 100644
--- a/core/io/logger.cpp
+++ b/core/io/logger.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "logger.h"
+
#include "os/dir_access.h"
#include "os/os.h"
#include "print_string.h"
@@ -259,6 +260,10 @@ void CompositeLogger::log_error(const char *p_function, const char *p_file, int
}
}
+void CompositeLogger::add_logger(Logger *p_logger) {
+ loggers.push_back(p_logger);
+}
+
CompositeLogger::~CompositeLogger() {
for (int i = 0; i < loggers.size(); ++i) {
memdelete(loggers[i]);
diff --git a/core/io/logger.h b/core/io/logger.h
index cf0cc7699f..f8a394193f 100644
--- a/core/io/logger.h
+++ b/core/io/logger.h
@@ -101,6 +101,8 @@ public:
virtual void logv(const char *p_format, va_list p_list, bool p_err);
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
+ void add_logger(Logger *p_logger);
+
virtual ~CompositeLogger();
};
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index 1d9d2dd959..37320d7a77 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -324,7 +324,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
ERR_FAIL_COND_V(len < 12, ERR_INVALID_DATA);
Vector<StringName> names;
Vector<StringName> subnames;
- StringName prop;
uint32_t namecount = strlen &= 0x7FFFFFFF;
uint32_t subnamecount = decode_uint32(buf + 4);
@@ -333,9 +332,10 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
len -= 12;
buf += 12;
+ if (flags & 2) // Obsolete format with property seperate from subpath
+ subnamecount++;
+
uint32_t total = namecount + subnamecount;
- if (flags & 2)
- total++;
if (r_len)
(*r_len) += 12;
@@ -359,10 +359,8 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
if (i < namecount)
names.push_back(str);
- else if (i < namecount + subnamecount)
- subnames.push_back(str);
else
- prop = str;
+ subnames.push_back(str);
buf += strlen + pad;
len -= strlen + pad;
@@ -371,7 +369,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
(*r_len) += 4 + strlen + pad;
}
- r_variant = NodePath(names, subnames, flags & 1, prop);
+ r_variant = NodePath(names, subnames, flags & 1);
} else {
//old format, just a string
@@ -919,8 +917,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
uint32_t flags = 0;
if (np.is_absolute())
flags |= 1;
- if (np.get_property() != StringName())
- flags |= 2;
encode_uint32(flags, buf + 8);
@@ -930,8 +926,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
r_len += 12;
int total = np.get_name_count() + np.get_subname_count();
- if (np.get_property() != StringName())
- total++;
for (int i = 0; i < total; i++) {
@@ -939,10 +933,8 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
if (i < np.get_name_count())
str = np.get_name(i);
- else if (i < np.get_name_count() + np.get_subname_count())
- str = np.get_subname(i - np.get_subname_count());
else
- str = np.get_property();
+ str = np.get_subname(i - np.get_name_count());
CharString utf8 = str.utf8();
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 8dc396c362..df0d41ea9d 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -84,8 +84,10 @@ enum {
OBJECT_INTERNAL_RESOURCE = 2,
OBJECT_EXTERNAL_RESOURCE_INDEX = 3,
//version 2: added 64 bits support for float and int
- FORMAT_VERSION = 2,
- FORMAT_VERSION_CAN_RENAME_DEPS = 1
+ //version 3: changed nodepath encoding
+ FORMAT_VERSION = 3,
+ FORMAT_VERSION_CAN_RENAME_DEPS = 1,
+ FORMAT_VERSION_NO_NODEPATH_PROPERTY = 3,
};
@@ -267,21 +269,22 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) {
Vector<StringName> names;
Vector<StringName> subnames;
- StringName property;
bool absolute;
int name_count = f->get_16();
uint32_t subname_count = f->get_16();
absolute = subname_count & 0x8000;
subname_count &= 0x7FFF;
+ if (ver_format < FORMAT_VERSION_NO_NODEPATH_PROPERTY) {
+ subname_count += 1; // has a property field, so we should count it as well
+ }
for (int i = 0; i < name_count; i++)
names.push_back(_get_string());
for (uint32_t i = 0; i < subname_count; i++)
subnames.push_back(_get_string());
- property = _get_string();
- NodePath np = NodePath(names, subnames, absolute, property);
+ NodePath np = NodePath(names, subnames, absolute);
r_v = np;
@@ -856,7 +859,7 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) {
uint32_t ver_major = f->get_32();
uint32_t ver_minor = f->get_32();
- uint32_t ver_format = f->get_32();
+ ver_format = f->get_32();
print_bl("big endian: " + itos(big_endian));
#ifdef BIG_ENDIAN_ENABLED
@@ -1454,7 +1457,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property,
f->store_32(get_string_index(np.get_name(i)));
for (int i = 0; i < np.get_subname_count(); i++)
f->store_32(get_string_index(np.get_subname(i)));
- f->store_32(get_string_index(np.get_property()));
} break;
case Variant::_RID: {
@@ -1685,7 +1687,6 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant
get_string_index(np.get_name(i));
for (int i = 0; i < np.get_subname_count(); i++)
get_string_index(np.get_subname(i));
- get_string_index(np.get_property());
} break;
default: {}
diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h
index 2316f05b3c..687da0a9b4 100644
--- a/core/io/resource_format_binary.h
+++ b/core/io/resource_format_binary.h
@@ -41,6 +41,7 @@ class ResourceInteractiveLoaderBinary : public ResourceInteractiveLoader {
String res_path;
String type;
Ref<Resource> resource;
+ uint32_t ver_format;
FileAccess *f;
diff --git a/core/node_path.cpp b/core/node_path.cpp
index 15f950f605..a12152aca6 100644
--- a/core/node_path.cpp
+++ b/core/node_path.cpp
@@ -48,8 +48,6 @@ uint32_t NodePath::hash() const {
h = h ^ ssn[i].hash();
}
- h = h ^ data->property.hash();
-
return h;
}
@@ -81,13 +79,6 @@ StringName NodePath::get_name(int p_idx) const {
return data->path[p_idx];
}
-StringName NodePath::get_property() const {
-
- if (!data)
- return StringName();
- return data->property;
-}
-
int NodePath::get_subname_count() const {
if (!data)
@@ -128,9 +119,6 @@ bool NodePath::operator==(const NodePath &p_path) const {
if (data->subpath.size() != p_path.data->subpath.size())
return false;
- if (data->property != p_path.data->property)
- return false;
-
for (int i = 0; i < data->path.size(); i++) {
if (data->path[i] != p_path.data->path[i])
@@ -184,8 +172,6 @@ NodePath::operator String() const {
ret += ":" + data->subpath[i].operator String();
}
- if (data->property.operator String() != "")
- ret += ":" + String(data->property);
return ret;
}
@@ -205,6 +191,7 @@ Vector<StringName> NodePath::get_names() const {
return data->path;
return Vector<StringName>();
}
+
Vector<StringName> NodePath::get_subnames() const {
if (data)
@@ -212,6 +199,21 @@ Vector<StringName> NodePath::get_subnames() const {
return Vector<StringName>();
}
+StringName NodePath::get_concatenated_subnames() const {
+ ERR_FAIL_COND_V(!data, StringName());
+
+ if (!data->concatenated_subpath) {
+ int spc = data->subpath.size();
+ String concatenated;
+ const StringName *ssn = data->subpath.ptr();
+ for (int i = 0; i < spc; i++) {
+ concatenated += i == 0 ? ssn[i].operator String() : ":" + ssn[i];
+ }
+ data->concatenated_subpath = concatenated;
+ }
+ return data->concatenated_subpath;
+}
+
NodePath NodePath::rel_path_to(const NodePath &p_np) const {
ERR_FAIL_COND_V(!is_absolute(), NodePath());
@@ -250,10 +252,27 @@ NodePath NodePath::rel_path_to(const NodePath &p_np) const {
if (relpath.size() == 0)
relpath.push_back(".");
- return NodePath(relpath, p_np.get_subnames(), false, p_np.get_property());
+ return NodePath(relpath, p_np.get_subnames(), false);
}
-NodePath::NodePath(const Vector<StringName> &p_path, bool p_absolute, const String &p_property) {
+NodePath NodePath::get_as_property_path() const {
+
+ if (!data->path.size()) {
+ return *this;
+ } else {
+ Vector<StringName> new_path = data->subpath;
+
+ String initial_subname = data->path[0];
+ for (size_t i = 1; i < data->path.size(); i++) {
+ initial_subname += i == 0 ? data->path[i].operator String() : "/" + data->path[i];
+ }
+ new_path.insert(0, initial_subname);
+
+ return NodePath(Vector<StringName>(), new_path, false);
+ }
+}
+
+NodePath::NodePath(const Vector<StringName> &p_path, bool p_absolute) {
data = NULL;
@@ -264,14 +283,14 @@ NodePath::NodePath(const Vector<StringName> &p_path, bool p_absolute, const Stri
data->refcount.init();
data->absolute = p_absolute;
data->path = p_path;
- data->property = p_property;
+ data->has_slashes = true;
}
-NodePath::NodePath(const Vector<StringName> &p_path, const Vector<StringName> &p_subpath, bool p_absolute, const String &p_property) {
+NodePath::NodePath(const Vector<StringName> &p_path, const Vector<StringName> &p_subpath, bool p_absolute) {
data = NULL;
- if (p_path.size() == 0)
+ if (p_path.size() == 0 && p_subpath.size() == 0)
return;
data = memnew(Data);
@@ -279,7 +298,7 @@ NodePath::NodePath(const Vector<StringName> &p_path, const Vector<StringName> &p
data->absolute = p_absolute;
data->path = p_path;
data->subpath = p_subpath;
- data->property = p_property;
+ data->has_slashes = true;
}
void NodePath::simplify() {
@@ -320,11 +339,11 @@ NodePath::NodePath(const String &p_path) {
return;
String path = p_path;
- StringName property;
Vector<StringName> subpath;
int absolute = (path[0] == '/') ? 1 : 0;
bool last_is_slash = true;
+ bool has_slashes = false;
int slices = 0;
int subpath_pos = path.find(":");
@@ -337,16 +356,13 @@ NodePath::NodePath(const String &p_path) {
if (path[i] == ':' || path[i] == 0) {
String str = path.substr(from, i - from);
- if (path[i] == ':') {
- if (str == "") {
- ERR_EXPLAIN("Invalid NodePath: " + p_path);
- ERR_FAIL();
- }
- subpath.push_back(str);
- } else {
- //property can be empty
- property = str;
+ if (str == "") {
+ if (path[i] == 0) continue; // Allow end-of-path :
+
+ ERR_EXPLAIN("Invalid NodePath: " + p_path);
+ ERR_FAIL();
}
+ subpath.push_back(str);
from = i + 1;
}
@@ -360,6 +376,7 @@ NodePath::NodePath(const String &p_path) {
if (path[i] == '/') {
last_is_slash = true;
+ has_slashes = true;
} else {
if (last_is_slash)
@@ -369,13 +386,13 @@ NodePath::NodePath(const String &p_path) {
}
}
- if (slices == 0 && !absolute && !property)
+ if (slices == 0 && !absolute && !subpath.size())
return;
data = memnew(Data);
data->refcount.init();
data->absolute = absolute ? true : false;
- data->property = property;
+ data->has_slashes = has_slashes;
data->subpath = subpath;
if (slices == 0)
diff --git a/core/node_path.h b/core/node_path.h
index eb5b9eb6cf..063c4f62db 100644
--- a/core/node_path.h
+++ b/core/node_path.h
@@ -41,10 +41,11 @@ class NodePath {
struct Data {
SafeRefCount refcount;
- StringName property;
Vector<StringName> path;
Vector<StringName> subpath;
+ StringName concatenated_subpath;
bool absolute;
+ bool has_slashes;
};
Data *data;
@@ -53,7 +54,7 @@ class NodePath {
public:
_FORCE_INLINE_ StringName get_sname() const {
- if (data && data->path.size() == 1 && data->subpath.empty() && !data->property) {
+ if (data && data->path.size() == 1 && data->subpath.empty()) {
return data->path[0];
} else {
return operator String();
@@ -67,13 +68,13 @@ public:
StringName get_subname(int p_idx) const;
Vector<StringName> get_names() const;
Vector<StringName> get_subnames() const;
+ StringName get_concatenated_subnames() const;
NodePath rel_path_to(const NodePath &p_np) const;
+ NodePath get_as_property_path() const;
void prepend_period();
- StringName get_property() const;
-
NodePath get_parent() const;
uint32_t hash() const;
@@ -88,8 +89,8 @@ public:
void simplify();
NodePath simplified() const;
- NodePath(const Vector<StringName> &p_path, bool p_absolute, const String &p_property = "");
- NodePath(const Vector<StringName> &p_path, const Vector<StringName> &p_subpath, bool p_absolute, const String &p_property = "");
+ NodePath(const Vector<StringName> &p_path, bool p_absolute);
+ NodePath(const Vector<StringName> &p_path, const Vector<StringName> &p_subpath, bool p_absolute);
NodePath(const NodePath &p_path);
NodePath(const String &p_path);
NodePath();
diff --git a/core/object.cpp b/core/object.cpp
index 823cbe14d4..631676d827 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -517,6 +517,80 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const {
}
}
+void Object::set_indexed(const Vector<StringName> &p_names, const Variant &p_value, bool *r_valid) {
+ if (p_names.empty()) {
+ if (r_valid)
+ *r_valid = false;
+ return;
+ }
+ if (p_names.size() == 1) {
+ set(p_names[0], p_value, r_valid);
+ return;
+ }
+
+ bool valid = false;
+ if (!r_valid) r_valid = &valid;
+
+ List<Variant> value_stack;
+
+ value_stack.push_back(get(p_names[0], r_valid));
+
+ if (!*r_valid) {
+ value_stack.clear();
+ return;
+ }
+
+ for (int i = 1; i < p_names.size() - 1; i++) {
+ value_stack.push_back(value_stack.back()->get().get_named(p_names[i], r_valid));
+
+ if (!*r_valid) {
+ value_stack.clear();
+ return;
+ }
+ }
+
+ value_stack.push_back(p_value); // p_names[p_names.size() - 1]
+
+ for (int i = p_names.size() - 1; i > 0; i--) {
+
+ value_stack.back()->prev()->get().set_named(p_names[i], value_stack.back()->get(), r_valid);
+ value_stack.pop_back();
+
+ if (!*r_valid) {
+ value_stack.clear();
+ return;
+ }
+ }
+
+ set(p_names[0], value_stack.back()->get(), r_valid);
+ value_stack.pop_back();
+
+ ERR_FAIL_COND(!value_stack.empty());
+}
+
+Variant Object::get_indexed(const Vector<StringName> &p_names, bool *r_valid) const {
+ if (p_names.empty()) {
+ if (r_valid)
+ *r_valid = false;
+ return Variant();
+ }
+ bool valid = false;
+
+ Variant current_value = get(p_names[0]);
+ for (int i = 1; i < p_names.size(); i++) {
+ current_value = current_value.get_named(p_names[i], &valid);
+
+ if (!valid) {
+ if (r_valid)
+ *r_valid = false;
+ return Variant();
+ }
+ }
+ if (r_valid)
+ *r_valid = true;
+ return current_value;
+}
+
void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) const {
if (script_instance && p_reversed) {
@@ -1416,6 +1490,16 @@ Variant Object::_get_bind(const String &p_name) const {
return get(p_name);
}
+void Object::_set_indexed_bind(const NodePath &p_name, const Variant &p_value) {
+
+ set_indexed(p_name.get_as_property_path().get_subnames(), p_value);
+}
+
+Variant Object::_get_indexed_bind(const NodePath &p_name) const {
+
+ return get_indexed(p_name.get_as_property_path().get_subnames());
+}
+
void Object::initialize_class() {
static bool initialized = false;
@@ -1513,6 +1597,8 @@ void Object::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_class", "type"), &Object::is_class);
ClassDB::bind_method(D_METHOD("set", "property", "value"), &Object::_set_bind);
ClassDB::bind_method(D_METHOD("get", "property"), &Object::_get_bind);
+ ClassDB::bind_method(D_METHOD("set_indexed", "property", "value"), &Object::_set_indexed_bind);
+ ClassDB::bind_method(D_METHOD("get_indexed", "property"), &Object::_get_indexed_bind);
ClassDB::bind_method(D_METHOD("get_property_list"), &Object::_get_property_list_bind);
ClassDB::bind_method(D_METHOD("get_method_list"), &Object::_get_method_list_bind);
ClassDB::bind_method(D_METHOD("notification", "what", "reversed"), &Object::notification, DEFVAL(false));
@@ -1661,6 +1747,43 @@ Variant::Type Object::get_static_property_type(const StringName &p_property, boo
return Variant::NIL;
}
+Variant::Type Object::get_static_property_type_indexed(const Vector<StringName> &p_path, bool *r_valid) const {
+
+ bool valid = false;
+ Variant::Type t = get_static_property_type(p_path[0], &valid);
+ if (!valid) {
+ if (r_valid)
+ *r_valid = false;
+
+ return Variant::NIL;
+ }
+
+ Variant::CallError ce;
+ Variant check = Variant::construct(t, NULL, 0, ce);
+
+ for (int i = 1; i < p_path.size(); i++) {
+ if (check.get_type() == Variant::OBJECT || check.get_type() == Variant::DICTIONARY || check.get_type() == Variant::ARRAY) {
+ // We cannot be sure about the type of properties this types can have
+ if (r_valid)
+ *r_valid = false;
+ return Variant::NIL;
+ }
+
+ check = check.get_named(p_path[i], &valid);
+
+ if (!valid) {
+ if (r_valid)
+ *r_valid = false;
+ return Variant::NIL;
+ }
+ }
+
+ if (r_valid)
+ *r_valid = true;
+
+ return check.get_type();
+}
+
bool Object::is_queued_for_deletion() const {
return _is_queued_for_deletion;
}
diff --git a/core/object.h b/core/object.h
index 7af2c78fc3..3ac699f978 100644
--- a/core/object.h
+++ b/core/object.h
@@ -477,6 +477,8 @@ private:
Array _get_incoming_connections() const;
void _set_bind(const String &p_set, const Variant &p_value);
Variant _get_bind(const String &p_name) const;
+ void _set_indexed_bind(const NodePath &p_name, const Variant &p_value);
+ Variant _get_indexed_bind(const NodePath &p_name) const;
void *_script_instance_bindings[MAX_SCRIPT_INSTANCE_BINDINGS];
@@ -627,6 +629,8 @@ public:
void set(const StringName &p_name, const Variant &p_value, bool *r_valid = NULL);
Variant get(const StringName &p_name, bool *r_valid = NULL) const;
+ void set_indexed(const Vector<StringName> &p_names, const Variant &p_value, bool *r_valid = NULL);
+ Variant get_indexed(const Vector<StringName> &p_names, bool *r_valid = NULL) const;
void get_property_list(List<PropertyInfo> *p_list, bool p_reversed = false) const;
@@ -687,6 +691,7 @@ public:
bool is_blocking_signals() const;
Variant::Type get_static_property_type(const StringName &p_property, bool *r_valid = NULL) const;
+ Variant::Type get_static_property_type_indexed(const Vector<StringName> &p_path, bool *r_valid = NULL) const;
virtual void get_translatable_strings(List<String> *p_strings) const;
diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp
index 35e4443f2a..6d4b46f4da 100644
--- a/core/os/dir_access.cpp
+++ b/core/os/dir_access.cpp
@@ -98,6 +98,7 @@ static Error _erase_recursive(DirAccess *da) {
err = _erase_recursive(da);
if (err) {
print_line("err recurso " + E->get());
+ da->change_dir("..");
return err;
}
err = da->change_dir("..");
@@ -340,6 +341,102 @@ Error DirAccess::copy(String p_from, String p_to, int chmod_flags) {
return err;
}
+// Changes dir for the current scope, returning back to the original dir
+// when scope exits
+class DirChanger {
+ DirAccess *da;
+ String original_dir;
+
+public:
+ DirChanger(DirAccess *p_da, String p_dir) {
+ da = p_da;
+ original_dir = p_da->get_current_dir();
+ p_da->change_dir(p_dir);
+ }
+
+ ~DirChanger() {
+ da->change_dir(original_dir);
+ }
+};
+
+Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags) {
+ List<String> dirs;
+
+ String curdir = get_current_dir();
+ list_dir_begin();
+ String n = get_next();
+ while (n != String()) {
+
+ if (n != "." && n != "..") {
+
+ if (current_is_dir())
+ dirs.push_back(n);
+ else {
+ String rel_path = n;
+ if (!n.is_rel_path()) {
+ list_dir_end();
+ return ERR_BUG;
+ }
+ Error err = copy(get_current_dir() + "/" + n, p_to + rel_path, p_chmod_flags);
+ if (err) {
+ list_dir_end();
+ return err;
+ }
+ }
+ }
+
+ n = get_next();
+ }
+
+ list_dir_end();
+
+ for (List<String>::Element *E = dirs.front(); E; E = E->next()) {
+ String rel_path = E->get();
+ String target_dir = p_to + rel_path;
+ if (!p_target_da->dir_exists(target_dir)) {
+ Error err = p_target_da->make_dir(target_dir);
+ ERR_FAIL_COND_V(err, err);
+ }
+
+ Error err = change_dir(E->get());
+ ERR_FAIL_COND_V(err, err);
+ err = _copy_dir(p_target_da, p_to + rel_path + "/", p_chmod_flags);
+ if (err) {
+ change_dir("..");
+ ERR_PRINT("Failed to copy recursively");
+ return err;
+ }
+ err = change_dir("..");
+ if (err) {
+ ERR_PRINT("Failed to go back");
+ return err;
+ }
+ }
+
+ return OK;
+}
+
+Error DirAccess::copy_dir(String p_from, String p_to, int p_chmod_flags) {
+ ERR_FAIL_COND_V(!dir_exists(p_from), ERR_FILE_NOT_FOUND);
+
+ DirAccess *target_da = DirAccess::create_for_path(p_to);
+ ERR_FAIL_COND_V(!target_da, ERR_CANT_CREATE);
+
+ if (!target_da->dir_exists(p_to)) {
+ Error err = target_da->make_dir_recursive(p_to);
+ if (err) {
+ memdelete(target_da);
+ }
+ ERR_FAIL_COND_V(err, err);
+ }
+
+ DirChanger dir_changer(this, p_from);
+ Error err = _copy_dir(target_da, p_to + "/", p_chmod_flags);
+ memdelete(target_da);
+
+ return err;
+}
+
bool DirAccess::exists(String p_dir) {
DirAccess *da = DirAccess::create_for_path(p_dir);
diff --git a/core/os/dir_access.h b/core/os/dir_access.h
index 7fa3ce5cf1..f3d1320041 100644
--- a/core/os/dir_access.h
+++ b/core/os/dir_access.h
@@ -52,6 +52,9 @@ public:
private:
AccessType _access_type;
static CreateFunc create_func[ACCESS_MAX]; ///< set this to instance a filesystem object
+
+ Error _copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags);
+
protected:
String _get_root_path() const;
String _get_root_string() const;
@@ -89,6 +92,7 @@ public:
static bool exists(String p_dir);
virtual size_t get_space_left() = 0;
+ Error copy_dir(String p_from, String p_to, int chmod_flags = -1);
virtual Error copy(String p_from, String p_to, int chmod_flags = -1);
virtual Error rename(String p_from, String p_to) = 0;
virtual Error remove(String p_name) = 0;
diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp
index 6b43f2c63b..3cdd9ae0e0 100644
--- a/core/os/input_event.cpp
+++ b/core/os/input_event.cpp
@@ -177,6 +177,14 @@ bool InputEventWithModifiers::get_command() const {
return command;
}
+void InputEventWithModifiers::set_modifiers_from_event(const InputEventWithModifiers *event) {
+
+ set_alt(event->get_alt());
+ set_shift(event->get_shift());
+ set_control(event->get_control());
+ set_metakey(event->get_metakey());
+}
+
void InputEventWithModifiers::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_alt", "enable"), &InputEventWithModifiers::set_alt);
@@ -270,16 +278,16 @@ String InputEventKey::as_text() const {
return kc;
if (get_metakey()) {
- kc = "Meta+" + kc;
+ kc = find_keycode_name(KEY_META) + ("+" + kc);
}
if (get_alt()) {
- kc = "Alt+" + kc;
+ kc = find_keycode_name(KEY_ALT) + ("+" + kc);
}
if (get_shift()) {
- kc = "Shift+" + kc;
+ kc = find_keycode_name(KEY_SHIFT) + ("+" + kc);
}
if (get_control()) {
- kc = "Ctrl+" + kc;
+ kc = find_keycode_name(KEY_CONTROL) + ("+" + kc);
}
return kc;
}
@@ -436,10 +444,7 @@ Ref<InputEvent> InputEventMouseButton::xformed_by(const Transform2D &p_xform, co
mb->set_id(get_id());
mb->set_device(get_device());
- mb->set_alt(get_alt());
- mb->set_shift(get_shift());
- mb->set_control(get_control());
- mb->set_metakey(get_metakey());
+ mb->set_modifiers_from_event(this);
mb->set_position(l);
mb->set_global_position(g);
@@ -555,10 +560,7 @@ Ref<InputEvent> InputEventMouseMotion::xformed_by(const Transform2D &p_xform, co
mm->set_id(get_id());
mm->set_device(get_device());
- mm->set_alt(get_alt());
- mm->set_shift(get_shift());
- mm->set_control(get_control());
- mm->set_metakey(get_metakey());
+ mm->set_modifiers_from_event(this);
mm->set_position(l);
mm->set_global_position(g);
@@ -930,3 +932,75 @@ void InputEventAction::_bind_methods() {
InputEventAction::InputEventAction() {
pressed = false;
}
+/////////////////////////////
+
+void InputEventGesture::set_position(const Vector2 &p_pos) {
+
+ pos = p_pos;
+}
+
+Vector2 InputEventGesture::get_position() const {
+
+ return pos;
+}
+/////////////////////////////
+
+void InputEventMagnifyGesture::set_factor(real_t p_factor) {
+
+ factor = p_factor;
+}
+
+real_t InputEventMagnifyGesture::get_factor() const {
+
+ return factor;
+}
+
+Ref<InputEvent> InputEventMagnifyGesture::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
+
+ Ref<InputEventMagnifyGesture> ev;
+ ev.instance();
+
+ ev->set_id(get_id());
+ ev->set_device(get_device());
+ ev->set_modifiers_from_event(this);
+
+ ev->set_position(p_xform.xform(get_position() + p_local_ofs));
+ ev->set_factor(get_factor());
+
+ return ev;
+}
+
+InputEventMagnifyGesture::InputEventMagnifyGesture() {
+
+ factor = 1.0;
+}
+/////////////////////////////
+
+void InputEventPanGesture::set_delta(const Vector2 &p_delta) {
+
+ delta = p_delta;
+}
+
+Vector2 InputEventPanGesture::get_delta() const {
+ return delta;
+}
+
+Ref<InputEvent> InputEventPanGesture::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
+
+ Ref<InputEventPanGesture> ev;
+ ev.instance();
+
+ ev->set_id(get_id());
+ ev->set_device(get_device());
+ ev->set_modifiers_from_event(this);
+
+ ev->set_position(p_xform.xform(get_position() + p_local_ofs));
+ ev->set_delta(get_delta());
+
+ return ev;
+}
+
+InputEventPanGesture::InputEventPanGesture() {
+
+ delta = Vector2(0, 0);
+}
diff --git a/core/os/input_event.h b/core/os/input_event.h
index de3c0232ff..2cba60bede 100644
--- a/core/os/input_event.h
+++ b/core/os/input_event.h
@@ -213,6 +213,8 @@ public:
void set_command(bool p_enabled);
bool get_command() const;
+ void set_modifiers_from_event(const InputEventWithModifiers *event);
+
InputEventWithModifiers();
};
@@ -468,4 +470,42 @@ public:
InputEventAction();
};
+class InputEventGesture : public InputEventWithModifiers {
+
+ GDCLASS(InputEventGesture, InputEventWithModifiers)
+
+ Vector2 pos;
+
+public:
+ void set_position(const Vector2 &p_pos);
+ Vector2 get_position() const;
+};
+
+class InputEventMagnifyGesture : public InputEventGesture {
+
+ GDCLASS(InputEventMagnifyGesture, InputEventGesture)
+ real_t factor;
+
+public:
+ void set_factor(real_t p_factor);
+ real_t get_factor() const;
+
+ virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const;
+
+ InputEventMagnifyGesture();
+};
+
+class InputEventPanGesture : public InputEventGesture {
+
+ GDCLASS(InputEventPanGesture, InputEventGesture)
+ Vector2 delta;
+
+public:
+ void set_delta(const Vector2 &p_delta);
+ Vector2 get_delta() const;
+
+ virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const;
+
+ InputEventPanGesture();
+};
#endif
diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp
index edf4f3e2f9..dead3b6ac0 100644
--- a/core/os/keyboard.cpp
+++ b/core/os/keyboard.cpp
@@ -60,7 +60,11 @@ static const _KeyCodeText _keycodes[] = {
{KEY_PAGEDOWN ,"PageDown"},
{KEY_SHIFT ,"Shift"},
{KEY_CONTROL ,"Control"},
+#ifdef OSX_ENABLED
+ {KEY_META ,"Command"},
+#else
{KEY_META ,"Meta"},
+#endif
{KEY_ALT ,"Alt"},
{KEY_CAPSLOCK ,"CapsLock"},
{KEY_NUMLOCK ,"NumLock"},
@@ -390,14 +394,22 @@ bool keycode_has_unicode(uint32_t p_keycode) {
String keycode_get_string(uint32_t p_code) {
String codestr;
- if (p_code & KEY_MASK_SHIFT)
- codestr += "Shift+";
- if (p_code & KEY_MASK_ALT)
- codestr += "Alt+";
- if (p_code & KEY_MASK_CTRL)
- codestr += "Ctrl+";
- if (p_code & KEY_MASK_META)
- codestr += "Meta+";
+ if (p_code & KEY_MASK_SHIFT) {
+ codestr += find_keycode_name(KEY_SHIFT);
+ codestr += "+";
+ }
+ if (p_code & KEY_MASK_ALT) {
+ codestr += find_keycode_name(KEY_ALT);
+ codestr += "+";
+ }
+ if (p_code & KEY_MASK_CTRL) {
+ codestr += find_keycode_name(KEY_CONTROL);
+ codestr += "+";
+ }
+ if (p_code & KEY_MASK_META) {
+ codestr += find_keycode_name(KEY_META);
+ codestr += "+";
+ }
p_code &= KEY_CODE_MASK;
@@ -433,6 +445,21 @@ int find_keycode(const String &p_code) {
return 0;
}
+const char *find_keycode_name(int p_keycode) {
+
+ const _KeyCodeText *kct = &_keycodes[0];
+
+ while (kct->text) {
+
+ if (kct->code == p_keycode) {
+ return kct->text;
+ }
+ kct++;
+ }
+
+ return "";
+}
+
struct _KeyCodeReplace {
int from;
int to;
diff --git a/core/os/keyboard.h b/core/os/keyboard.h
index 509ff23a93..f49cbc6b18 100644
--- a/core/os/keyboard.h
+++ b/core/os/keyboard.h
@@ -326,6 +326,7 @@ enum KeyModifierMask {
String keycode_get_string(uint32_t p_code);
bool keycode_has_unicode(uint32_t p_keycode);
int find_keycode(const String &p_code);
+const char *find_keycode_name(int p_keycode);
int keycode_get_count();
int keycode_get_value_by_index(int p_index);
const char *keycode_get_name_by_index(int p_index);
diff --git a/core/os/memory.cpp b/core/os/memory.cpp
index 74d5cbbea1..439951f711 100644
--- a/core/os/memory.cpp
+++ b/core/os/memory.cpp
@@ -44,6 +44,26 @@ void *operator new(size_t p_size, void *(*p_allocfunc)(size_t p_size)) {
return p_allocfunc(p_size);
}
+#ifdef _MSC_VER
+void operator delete(void *p_mem, const char *p_description) {
+
+ ERR_EXPLAINC("Call to placement delete should not happen.");
+ CRASH_NOW();
+}
+
+void operator delete(void *p_mem, void *(*p_allocfunc)(size_t p_size)) {
+
+ ERR_EXPLAINC("Call to placement delete should not happen.");
+ CRASH_NOW();
+}
+
+void operator delete(void *p_mem, void *p_pointer, size_t check, const char *p_description) {
+
+ ERR_EXPLAINC("Call to placement delete should not happen.");
+ CRASH_NOW();
+}
+#endif
+
#ifdef DEBUG_ENABLED
uint64_t Memory::mem_usage = 0;
uint64_t Memory::max_usage = 0;
diff --git a/core/os/memory.h b/core/os/memory.h
index f8b3da579b..7801d56837 100644
--- a/core/os/memory.h
+++ b/core/os/memory.h
@@ -72,6 +72,14 @@ void *operator new(size_t p_size, void *(*p_allocfunc)(size_t p_size)); ///< ope
void *operator new(size_t p_size, void *p_pointer, size_t check, const char *p_description); ///< operator new that takes a description and uses a pointer to the preallocated memory
+#ifdef _MSC_VER
+// When compiling with VC++ 2017, the above declarations of placement new generate many irrelevant warnings (C4291).
+// The purpose of the following definitions is to muffle these warnings, not to provide a usable implementation of placement delete.
+void operator delete(void *p_mem, const char *p_description);
+void operator delete(void *p_mem, void *(*p_allocfunc)(size_t p_size));
+void operator delete(void *p_mem, void *p_pointer, size_t check, const char *p_description);
+#endif
+
#define memalloc(m_size) Memory::alloc_static(m_size)
#define memrealloc(m_mem, m_size) Memory::realloc_static(m_mem, m_size)
#define memfree(m_size) Memory::free_static(m_size)
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 65d0b2e05d..84937c0e59 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -63,15 +63,21 @@ void OS::debug_break(){
// something
};
-void OS::_set_logger(Logger *p_logger) {
+void OS::_set_logger(CompositeLogger *p_logger) {
if (_logger) {
memdelete(_logger);
}
_logger = p_logger;
}
-void OS::initialize_logger() {
- _set_logger(memnew(StdLogger));
+void OS::add_logger(Logger *p_logger) {
+ if (!_logger) {
+ Vector<Logger *> loggers;
+ loggers.push_back(p_logger);
+ _logger = memnew(CompositeLogger(loggers));
+ } else {
+ _logger->add_logger(p_logger);
+ }
}
void OS::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, Logger::ErrorType p_type) {
@@ -548,6 +554,33 @@ bool OS::has_feature(const String &p_feature) {
if (sizeof(void *) == 4 && p_feature == "32") {
return true;
}
+#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__)
+ if (p_feature == "x86_64") {
+ return true;
+ }
+#elif (defined(__i386) || defined(__i386__))
+ if (p_feature == "x86") {
+ return true;
+ }
+#elif defined(__aarch64__)
+ if (p_feature == "arm64") {
+ return true;
+ }
+#elif defined(__arm__)
+#if defined(__ARM_ARCH_7A__)
+ if (p_feature == "armv7a" || p_feature == "armv7") {
+ return true;
+ }
+#endif
+#if defined(__ARM_ARCH_7S__)
+ if (p_feature == "armv7s" || p_feature == "armv7") {
+ return true;
+ }
+#endif
+ if (p_feature == "arm") {
+ return true;
+ }
+#endif
if (_check_internal_feature_support(p_feature))
return true;
@@ -577,7 +610,10 @@ OS::OS() {
_stack_bottom = (void *)(&stack_bottom);
_logger = NULL;
- _set_logger(memnew(StdLogger));
+
+ Vector<Logger *> loggers;
+ loggers.push_back(memnew(StdLogger));
+ _set_logger(memnew(CompositeLogger(loggers)));
}
OS::~OS() {
diff --git a/core/os/os.h b/core/os/os.h
index 474cb60627..fe4ffb2922 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -62,10 +62,10 @@ class OS {
void *_stack_bottom;
- Logger *_logger;
+ CompositeLogger *_logger;
protected:
- void _set_logger(Logger *p_logger);
+ void _set_logger(CompositeLogger *p_logger);
public:
typedef void (*ImeCallback)(void *p_inp, String p_text, Point2 p_selection);
@@ -90,13 +90,15 @@ public:
bool fullscreen;
bool resizable;
bool borderless_window;
+ bool maximized;
float get_aspect() const { return (float)width / (float)height; }
- VideoMode(int p_width = 1024, int p_height = 600, bool p_fullscreen = false, bool p_resizable = true, bool p_borderless_window = false) {
+ VideoMode(int p_width = 1024, int p_height = 600, bool p_fullscreen = false, bool p_resizable = true, bool p_borderless_window = false, bool p_maximized = false) {
width = p_width;
height = p_height;
fullscreen = p_fullscreen;
resizable = p_resizable;
borderless_window = p_borderless_window;
+ maximized = p_maximized;
}
};
@@ -112,7 +114,8 @@ protected:
virtual int get_audio_driver_count() const = 0;
virtual const char *get_audio_driver_name(int p_driver) const = 0;
- virtual void initialize_logger();
+ void add_logger(Logger *p_logger);
+
virtual void initialize_core() = 0;
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) = 0;
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp
index 5655a4d5e4..5e06339b9e 100644
--- a/core/script_debugger_remote.cpp
+++ b/core/script_debugger_remote.cpp
@@ -35,6 +35,8 @@
#include "os/input.h"
#include "os/os.h"
#include "project_settings.h"
+#include "scene/main/node.h"
+
void ScriptDebuggerRemote::_send_video_memory() {
List<ResourceUsage> usage;
@@ -201,20 +203,39 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue)
List<String> members;
List<Variant> member_vals;
-
+ if (ScriptInstance *inst = p_script->debug_get_stack_level_instance(lv)) {
+ members.push_back("self");
+ member_vals.push_back(inst->get_owner());
+ }
p_script->debug_get_stack_level_members(lv, &members, &member_vals);
-
ERR_CONTINUE(members.size() != member_vals.size());
List<String> locals;
List<Variant> local_vals;
-
p_script->debug_get_stack_level_locals(lv, &locals, &local_vals);
-
ERR_CONTINUE(locals.size() != local_vals.size());
+ List<String> globals;
+ List<Variant> globals_vals;
+ p_script->debug_get_globals(&globals, &globals_vals);
+ ERR_CONTINUE(globals.size() != globals_vals.size());
+
packet_peer_stream->put_var("stack_frame_vars");
- packet_peer_stream->put_var(2 + locals.size() * 2 + members.size() * 2);
+ packet_peer_stream->put_var(3 + (locals.size() + members.size() + globals.size()) * 2);
+
+ { //locals
+ packet_peer_stream->put_var(locals.size());
+
+ List<String>::Element *E = locals.front();
+ List<Variant>::Element *F = local_vals.front();
+
+ while (E) {
+ _put_variable(E->get(), F->get());
+
+ E = E->next();
+ F = F->next();
+ }
+ }
{ //members
packet_peer_stream->put_var(members.size());
@@ -231,11 +252,11 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue)
}
}
- { //locals
- packet_peer_stream->put_var(locals.size());
+ { //globals
+ packet_peer_stream->put_var(globals.size());
- List<String>::Element *E = locals.front();
- List<Variant>::Element *F = local_vals.front();
+ List<String>::Element *E = globals.front();
+ List<Variant>::Element *F = globals_vals.front();
while (E) {
_put_variable(E->get(), F->get());
@@ -532,56 +553,88 @@ void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) {
if (!obj)
return;
- List<PropertyInfo> pinfo;
- obj->get_property_list(&pinfo, true);
+ typedef Pair<PropertyInfo, Variant> PropertyDesc;
+ List<PropertyDesc> properties;
- int props_to_send = 0;
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
+ if (ScriptInstance *si = obj->get_script_instance()) {
+ if (!si->get_script().is_null()) {
- if (E->get().usage & (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CATEGORY)) {
- props_to_send++;
- }
- }
+ Set<StringName> members;
+ si->get_script()->get_members(&members);
+ for (Set<StringName>::Element *E = members.front(); E; E = E->next()) {
- packet_peer_stream->put_var("message:inspect_object");
- packet_peer_stream->put_var(props_to_send * 5 + 4);
- packet_peer_stream->put_var(p_id);
- packet_peer_stream->put_var(obj->get_class());
- if (obj->is_class("Resource") || obj->is_class("Node"))
- packet_peer_stream->put_var(obj->call("get_path"));
- else
- packet_peer_stream->put_var("");
+ Variant m;
+ if (si->get(E->get(), m)) {
+ PropertyInfo pi(m.get_type(), String("Members/") + E->get());
+ properties.push_back(PropertyDesc(pi, m));
+ }
+ }
- packet_peer_stream->put_var(props_to_send);
+ Map<StringName, Variant> constants;
+ si->get_script()->get_constants(&constants);
+ for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) {
+ PropertyInfo pi(E->value().get_type(), (String("Constants/") + E->key()));
+ properties.push_back(PropertyDesc(pi, E->value()));
+ }
+ }
+ }
+ if (Node *node = Object::cast_to<Node>(obj)) {
+ PropertyInfo pi(Variant::NODE_PATH, String("Node/path"));
+ properties.push_front(PropertyDesc(pi, node->get_path()));
+ } else if (Resource *res = Object::cast_to<Resource>(obj)) {
+ if (Script *s = Object::cast_to<Script>(res)) {
+ Map<StringName, Variant> constants;
+ s->get_constants(&constants);
+ for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) {
+ PropertyInfo pi(E->value().get_type(), String("Constants/") + E->key());
+ properties.push_front(PropertyDesc(pi, E->value()));
+ }
+ }
+ }
+ List<PropertyInfo> pinfo;
+ obj->get_property_list(&pinfo, true);
for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
-
if (E->get().usage & (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CATEGORY)) {
+ properties.push_back(PropertyDesc(E->get(), obj->get(E->get().name)));
+ }
+ }
- if (E->get().usage & PROPERTY_USAGE_CATEGORY) {
- packet_peer_stream->put_var("*" + E->get().name);
- } else {
- packet_peer_stream->put_var(E->get().name);
- }
-
- Variant var = obj->get(E->get().name);
- packet_peer_stream->put_var(E->get().type);
- //only send information that can be sent..
-
- int len = 0; //test how big is this to encode
- encode_variant(var, NULL, len);
-
- if (len > packet_peer_stream->get_output_buffer_max_size()) { //limit to max size
- packet_peer_stream->put_var(PROPERTY_HINT_OBJECT_TOO_BIG);
- packet_peer_stream->put_var("");
- packet_peer_stream->put_var(Variant());
- } else {
- packet_peer_stream->put_var(E->get().hint);
- packet_peer_stream->put_var(E->get().hint_string);
- packet_peer_stream->put_var(var);
- }
+ Array send_props;
+ for (int i = 0; i < properties.size(); i++) {
+ const PropertyInfo &pi = properties[i].first;
+ const Variant &var = properties[i].second;
+ RES res = var;
+
+ Array prop;
+ prop.push_back(pi.name);
+ prop.push_back(pi.type);
+
+ //only send information that can be sent..
+ int len = 0; //test how big is this to encode
+ encode_variant(var, NULL, len);
+ if (len > packet_peer_stream->get_output_buffer_max_size()) { //limit to max size
+ prop.push_back(PROPERTY_HINT_OBJECT_TOO_BIG);
+ prop.push_back("");
+ prop.push_back(pi.usage);
+ prop.push_back(Variant());
+ } else {
+ prop.push_back(pi.hint);
+ if (res.is_null())
+ prop.push_back(pi.hint_string);
+ else
+ prop.push_back(String("RES:") + res->get_path());
+ prop.push_back(pi.usage);
+ prop.push_back(var);
}
+ send_props.push_back(prop);
}
+
+ packet_peer_stream->put_var("message:inspect_object");
+ packet_peer_stream->put_var(3);
+ packet_peer_stream->put_var(p_id);
+ packet_peer_stream->put_var(obj->get_class());
+ packet_peer_stream->put_var(send_props);
}
void ScriptDebuggerRemote::_set_object_property(ObjectID p_id, const String &p_property, const Variant &p_value) {
@@ -590,7 +643,11 @@ void ScriptDebuggerRemote::_set_object_property(ObjectID p_id, const String &p_p
if (!obj)
return;
- obj->set(p_property, p_value);
+ String prop_name = p_property;
+ if (p_property.begins_with("Members/"))
+ prop_name = p_property.substr(8, p_property.length());
+
+ obj->set(prop_name, p_value);
}
void ScriptDebuggerRemote::_poll_events() {
diff --git a/core/script_language.h b/core/script_language.h
index 5da72d0492..3d01381f3b 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -120,6 +120,9 @@ public:
virtual int get_member_line(const StringName &p_member) const { return -1; }
+ virtual void get_constants(Map<StringName, Variant> *p_constants) {}
+ virtual void get_members(Set<StringName> *p_constants) {}
+
Script() {}
};
@@ -130,6 +133,7 @@ public:
virtual void get_property_list(List<PropertyInfo> *p_properties) const = 0;
virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = NULL) const = 0;
+ virtual Object *get_owner() { return NULL; }
virtual void get_property_state(List<Pair<StringName, Variant> > &state);
virtual void get_method_list(List<MethodInfo> *p_list) const = 0;
@@ -244,7 +248,8 @@ public:
virtual String debug_get_stack_level_source(int p_level) const = 0;
virtual void debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) = 0;
virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) = 0;
- virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) = 0;
+ virtual ScriptInstance *debug_get_stack_level_instance(int p_level) { return NULL; }
+ virtual void debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) = 0;
virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems = -1, int p_max_depth = -1) = 0;
struct StackInfo {
diff --git a/core/translation.cpp b/core/translation.cpp
index 7e4d4feb89..dcca58692a 100644
--- a/core/translation.cpp
+++ b/core/translation.cpp
@@ -333,6 +333,7 @@ static const char *locale_list[] = {
"sq_KV", // Albanian (Kosovo)
"sq_MK", // Albanian (Macedonia)
"sr", // Serbian
+ "sr_Cyrl", // Serbian (Cyrillic)
"sr_ME", // Serbian (Montenegro)
"sr_RS", // Serbian (Serbia)
"ss_ZA", // Swati (South Africa)
@@ -693,6 +694,7 @@ static const char *locale_names[] = {
"Albanian (Kosovo)",
"Albanian (Macedonia)",
"Serbian",
+ "Serbian (Cyrillic)",
"Serbian (Montenegro)",
"Serbian (Serbia)",
"Swati (South Africa)",
diff --git a/core/ustring.cpp b/core/ustring.cpp
index 7c3a784c5b..8d40f56386 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -862,6 +862,17 @@ Vector<int> String::split_ints_mk(const Vector<String> &p_splitters, bool p_allo
return ret;
}
+String String::join(Vector<String> parts) {
+ String ret;
+ for (int i = 0; i < parts.size(); ++i) {
+ if (i > 0) {
+ ret += *this;
+ }
+ ret += parts[i];
+ }
+ return ret;
+}
+
CharType String::char_uppercase(CharType p_char) {
return _find_upper(p_char);
diff --git a/core/ustring.h b/core/ustring.h
index 353c8e6c1d..9c24133b55 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -169,6 +169,8 @@ public:
Vector<int> split_ints(const String &p_splitter, bool p_allow_empty = true) const;
Vector<int> split_ints_mk(const Vector<String> &p_splitters, bool p_allow_empty = true) const;
+ String join(Vector<String> parts);
+
static CharType char_uppercase(CharType p_char);
static CharType char_lowercase(CharType p_char);
String to_upper() const;
diff --git a/core/variant.cpp b/core/variant.cpp
index d4143b8d84..0f97b98a6f 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -66,7 +66,7 @@ String Variant::get_type_name(Variant::Type p_type) {
return "String";
} break;
- // math types
+ // math types
case VECTOR2: {
@@ -513,6 +513,7 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type
static const Type valid[] = {
QUAT,
+ VECTOR3,
NIL
};
@@ -723,7 +724,7 @@ bool Variant::is_zero() const {
} break;
- // math types
+ // math types
case VECTOR2: {
@@ -932,7 +933,7 @@ void Variant::reference(const Variant &p_variant) {
memnew_placement(_data._mem, String(*reinterpret_cast<const String *>(p_variant._data._mem)));
} break;
- // math types
+ // math types
case VECTOR2: {
@@ -1632,7 +1633,9 @@ Variant::operator Basis() const {
return *_data._basis;
else if (type == QUAT)
return *reinterpret_cast<const Quat *>(_data._mem);
- else if (type == TRANSFORM)
+ else if (type == VECTOR3) {
+ return Basis(*reinterpret_cast<const Vector3 *>(_data._mem));
+ } else if (type == TRANSFORM) // unexposed in Variant::can_convert?
return _data._transform->basis;
else
return Basis();
@@ -2502,7 +2505,7 @@ void Variant::operator=(const Variant &p_variant) {
*reinterpret_cast<String *>(_data._mem) = *reinterpret_cast<const String *>(p_variant._data._mem);
} break;
- // math types
+ // math types
case VECTOR2: {
@@ -2642,7 +2645,7 @@ uint32_t Variant::hash() const {
return reinterpret_cast<const String *>(_data._mem)->hash();
} break;
- // math types
+ // math types
case VECTOR2: {
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 9e6aaeb911..4a140bdb99 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -437,6 +437,8 @@ struct _VariantCall {
VCALL_LOCALMEM0R(Color, contrasted);
VCALL_LOCALMEM2R(Color, linear_interpolate);
VCALL_LOCALMEM1R(Color, blend);
+ VCALL_LOCALMEM1R(Color, lightened);
+ VCALL_LOCALMEM1R(Color, darkened);
VCALL_LOCALMEM1R(Color, to_html);
VCALL_LOCALMEM0R(RID, get_id);
@@ -446,7 +448,8 @@ struct _VariantCall {
VCALL_LOCALMEM1R(NodePath, get_name);
VCALL_LOCALMEM0R(NodePath, get_subname_count);
VCALL_LOCALMEM1R(NodePath, get_subname);
- VCALL_LOCALMEM0R(NodePath, get_property);
+ VCALL_LOCALMEM0R(NodePath, get_concatenated_subnames);
+ VCALL_LOCALMEM0R(NodePath, get_as_property_path);
VCALL_LOCALMEM0R(NodePath, is_empty);
VCALL_LOCALMEM0R(Dictionary, size);
@@ -483,6 +486,8 @@ struct _VariantCall {
VCALL_LOCALMEM1(Array, erase);
VCALL_LOCALMEM0(Array, sort);
VCALL_LOCALMEM2(Array, sort_custom);
+ VCALL_LOCALMEM2R(Array, bsearch);
+ VCALL_LOCALMEM4R(Array, bsearch_custom);
VCALL_LOCALMEM0R(Array, duplicate);
VCALL_LOCALMEM0(Array, invert);
@@ -897,11 +902,6 @@ struct _VariantCall {
r_ret = Basis(p_args[0]->operator Vector3(), p_args[1]->operator real_t());
}
- static void Basis_init3(Variant &r_ret, const Variant **p_args) {
-
- r_ret = Basis(p_args[0]->operator Vector3());
- }
-
static void Transform_init1(Variant &r_ret, const Variant **p_args) {
Transform t;
@@ -1581,6 +1581,8 @@ void register_variant_methods() {
ADDFUNC0R(COLOR, COLOR, Color, contrasted, varray());
ADDFUNC2R(COLOR, COLOR, Color, linear_interpolate, COLOR, "b", REAL, "t", varray());
ADDFUNC1R(COLOR, COLOR, Color, blend, COLOR, "over", varray());
+ 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));
ADDFUNC0R(_RID, INT, RID, get_id, varray());
@@ -1590,7 +1592,8 @@ void register_variant_methods() {
ADDFUNC1R(NODE_PATH, STRING, NodePath, get_name, INT, "idx", varray());
ADDFUNC0R(NODE_PATH, INT, NodePath, get_subname_count, varray());
ADDFUNC1R(NODE_PATH, STRING, NodePath, get_subname, INT, "idx", varray());
- ADDFUNC0R(NODE_PATH, STRING, NodePath, get_property, varray());
+ ADDFUNC0R(NODE_PATH, STRING, NodePath, get_concatenated_subnames, varray());
+ ADDFUNC0R(NODE_PATH, NODE_PATH, NodePath, get_as_property_path, varray());
ADDFUNC0R(NODE_PATH, BOOL, NodePath, is_empty, varray());
ADDFUNC0R(DICTIONARY, INT, Dictionary, size, varray());
@@ -1625,6 +1628,8 @@ 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());
+ 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());
ADDFUNC0RNC(ARRAY, ARRAY, Array, duplicate, varray());
@@ -1795,7 +1800,6 @@ void register_variant_methods() {
_VariantCall::add_constructor(_VariantCall::Basis_init1, Variant::BASIS, "x_axis", Variant::VECTOR3, "y_axis", Variant::VECTOR3, "z_axis", Variant::VECTOR3);
_VariantCall::add_constructor(_VariantCall::Basis_init2, Variant::BASIS, "axis", Variant::VECTOR3, "phi", Variant::REAL);
- _VariantCall::add_constructor(_VariantCall::Basis_init3, Variant::BASIS, "euler", Variant::VECTOR3);
_VariantCall::add_constructor(_VariantCall::Transform_init1, Variant::TRANSFORM, "x_axis", Variant::VECTOR3, "y_axis", Variant::VECTOR3, "z_axis", Variant::VECTOR3, "origin", Variant::VECTOR3);
_VariantCall::add_constructor(_VariantCall::Transform_init2, Variant::TRANSFORM, "basis", Variant::BASIS, "origin", Variant::VECTOR3);
diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp
index 1552b62c64..1c02c627b5 100644
--- a/core/variant_parser.cpp
+++ b/core/variant_parser.cpp
@@ -595,7 +595,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
value = Quat(args[0], args[1], args[2], args[3]);
return OK;
- } else if (id == "AABB") {
+ } else if (id == "AABB" || id == "Rect3") {
Vector<float> args;
Error err = _parse_construct<float>(p_stream, args, line, r_err_str);