diff options
Diffstat (limited to 'core')
| -rw-r--r-- | core/color.h | 18 | ||||
| -rw-r--r-- | core/command_queue_mt.cpp | 24 | ||||
| -rw-r--r-- | core/command_queue_mt.h | 1509 | ||||
| -rw-r--r-- | core/io/marshalls.cpp | 20 | ||||
| -rw-r--r-- | core/io/resource_format_binary.cpp | 17 | ||||
| -rw-r--r-- | core/io/resource_format_binary.h | 1 | ||||
| -rw-r--r-- | core/list.h | 4 | ||||
| -rw-r--r-- | core/node_path.cpp | 81 | ||||
| -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 | 8 | ||||
| -rw-r--r-- | core/os/keyboard.cpp | 43 | ||||
| -rw-r--r-- | core/os/keyboard.h | 1 | ||||
| -rw-r--r-- | core/os/os.cpp | 13 | ||||
| -rw-r--r-- | core/os/os.h | 3 | ||||
| -rw-r--r-- | core/translation.cpp | 2 | ||||
| -rw-r--r-- | core/variant.cpp | 15 | ||||
| -rw-r--r-- | core/variant_call.cpp | 16 |
19 files changed, 621 insertions, 1295 deletions
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/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/list.h b/core/list.h index da201e9868..448be4a5ab 100644 --- a/core/list.h +++ b/core/list.h @@ -306,6 +306,8 @@ public: if (!p_element->next_ptr) { _data->last = n; + } else { + p_element->next_ptr->prev_ptr = n; } p_element->next_ptr = n; @@ -330,6 +332,8 @@ public: if (!p_element->prev_ptr) { _data->first = n; + } else { + p_element->prev_ptr->next_ptr = n; } p_element->prev_ptr = n; 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/input_event.cpp b/core/os/input_event.cpp index 103a8e82c2..3cdd9ae0e0 100644 --- a/core/os/input_event.cpp +++ b/core/os/input_event.cpp @@ -278,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; } 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 0e7e26df73..a39dfcc003 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -122,6 +122,16 @@ bool OS::is_in_low_processor_usage_mode() const { return low_processor_usage_mode; } +void OS::set_low_processor_usage_mode_sleep_usec(int p_usec) { + + low_processor_usage_mode_sleep_usec = p_usec; +} + +int OS::get_low_processor_usage_mode_sleep_usec() const { + + return low_processor_usage_mode_sleep_usec; +} + void OS::set_clipboard(const String &p_text) { _local_clipboard = p_text; @@ -554,7 +564,7 @@ bool OS::has_feature(const String &p_feature) { if (sizeof(void *) == 4 && p_feature == "32") { return true; } -#if defined(__x86_64) || defined(__x86_64__) +#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) if (p_feature == "x86_64") { return true; } @@ -599,6 +609,7 @@ OS::OS() { singleton = this; _keep_screen_on = true; // set default value to true, because this had been true before godot 2.0. low_processor_usage_mode = false; + low_processor_usage_mode_sleep_usec = 10000; _verbose_stdout = false; _no_window = false; _exit_code = 0; diff --git a/core/os/os.h b/core/os/os.h index fe4ffb2922..d7a1512e39 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -50,6 +50,7 @@ class OS { List<String> _cmdline; bool _keep_screen_on; bool low_processor_usage_mode; + int low_processor_usage_mode_sleep_usec; bool _verbose_stdout; String _local_clipboard; uint64_t _msec_splash; @@ -202,6 +203,8 @@ public: virtual bool is_keep_screen_on() const; virtual void set_low_processor_usage_mode(bool p_enabled); virtual bool is_in_low_processor_usage_mode() const; + virtual void set_low_processor_usage_mode_sleep_usec(int p_usec); + virtual int get_low_processor_usage_mode_sleep_usec() const; virtual String get_executable_path() const; virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false) = 0; 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/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 da6e602ccb..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); @@ -899,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; @@ -1583,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()); @@ -1592,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()); @@ -1799,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); |