diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/array.cpp | 43 | ||||
-rw-r--r-- | core/array.h | 2 | ||||
-rw-r--r-- | core/command_queue_mt.cpp | 24 | ||||
-rw-r--r-- | core/command_queue_mt.h | 1509 | ||||
-rw-r--r-- | core/io/logger.cpp | 5 | ||||
-rw-r--r-- | core/io/logger.h | 2 | ||||
-rw-r--r-- | core/io/marshalls.cpp | 20 | ||||
-rw-r--r-- | core/io/resource_format_binary.cpp | 6 | ||||
-rw-r--r-- | core/node_path.cpp | 76 | ||||
-rw-r--r-- | core/node_path.h | 13 | ||||
-rw-r--r-- | core/object.cpp | 123 | ||||
-rw-r--r-- | core/object.h | 5 | ||||
-rw-r--r-- | core/os/input_event.cpp | 98 | ||||
-rw-r--r-- | core/os/input_event.h | 40 | ||||
-rw-r--r-- | core/os/keyboard.cpp | 43 | ||||
-rw-r--r-- | core/os/keyboard.h | 1 | ||||
-rw-r--r-- | core/os/os.cpp | 17 | ||||
-rw-r--r-- | core/os/os.h | 7 | ||||
-rw-r--r-- | core/variant_call.cpp | 8 |
19 files changed, 749 insertions, 1293 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/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..aa51b00028 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -267,7 +267,6 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { Vector<StringName> names; Vector<StringName> subnames; - StringName property; bool absolute; int name_count = f->get_16(); @@ -279,9 +278,8 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { 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; @@ -1454,7 +1452,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 +1682,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/node_path.cpp b/core/node_path.cpp index 15f950f605..a01bb420a5 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,23 @@ 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::get_as_property_path() const { + + if (data->has_slashes || !data->path.size()) { + return NodePath(Vector<StringName>(), data->subpath, false); + } else { + ERR_FAIL_COND_V(data->path.size() != 1, NodePath()); + + Vector<StringName> new_path = data->subpath; + new_path.insert(0, data->path[0]); + return NodePath(Vector<StringName>(), new_path, false); + } } -NodePath::NodePath(const Vector<StringName> &p_path, bool p_absolute, const String &p_property) { +NodePath::NodePath(const Vector<StringName> &p_path, bool p_absolute) { data = NULL; @@ -264,14 +279,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 +294,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() { @@ -325,6 +340,7 @@ NodePath::NodePath(const String &p_path) { 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 +353,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 +373,7 @@ NodePath::NodePath(const String &p_path) { if (path[i] == '/') { last_is_slash = true; + has_slashes = true; } else { if (last_is_slash) @@ -369,13 +383,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/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/os.cpp b/core/os/os.cpp index 02f7d01cd3..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) { @@ -604,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 e48e5c6d70..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); @@ -114,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/variant_call.cpp b/core/variant_call.cpp index 9e6aaeb911..365ed07810 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -446,7 +446,7 @@ 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, is_empty); VCALL_LOCALMEM0R(Dictionary, size); @@ -483,6 +483,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); @@ -1590,7 +1592,7 @@ 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, BOOL, NodePath, is_empty, varray()); ADDFUNC0R(DICTIONARY, INT, Dictionary, size, varray()); @@ -1625,6 +1627,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()); |