From 6f315d9d994d3c31d6a4fa413e76130c13b4f13b Mon Sep 17 00:00:00 2001 From: Li Jin Date: Sat, 30 Mar 2024 09:48:28 +0800 Subject: [PATCH] update WASM3, adding docs to Rust APIs. --- Assets/Script/Lib/Dora/en/App.d.tl | 3 + Assets/Script/Lib/Dora/en/Array.d.tl | 2 +- Assets/Script/Lib/Dora/en/Node.d.tl | 6 + Assets/Script/Lib/Dora/zh-Hans/App.d.tl | 3 + Assets/Script/Lib/Dora/zh-Hans/Node.d.tl | 6 + Source/3rdParty/wasm3/m3_env.c | 63 +- Source/3rdParty/wasm3/m3_env.h | 4 + Source/3rdParty/wasm3/m3_exec.h | 33 +- Source/3rdParty/wasm3/m3_exec_defs.h | 21 +- Source/3rdParty/wasm3/m3_info.c | 1 - Source/3rdParty/wasm3/m3_parse.c | 15 +- Source/3rdParty/wasm3/wasm3.h | 3 + Source/3rdParty/wasm3/wasm3_defs.h | 586 ++++----- Source/Common/Debug.cpp | 4 +- Source/Common/Utils.cpp | 15 + Source/Common/Utils.h | 1 + Source/Wasm/Dora/NodeWasm.hpp | 18 +- Source/Wasm/Dora/PathWasm.hpp | 4 + Source/Wasm/WasmRuntime.cpp | 4 - Tools/RustWasmGen/Dora.h | 1147 ++++++++++++++++- Tools/RustWasmGen/gen.yue | 88 +- Tools/dora-rust/dora-test/src/main.rs | 4 + Tools/dora-rust/dora/src/dora.rs | 183 ++- Tools/dora-rust/dora/src/dora/action.rs | 118 ++ Tools/dora-rust/dora/src/dora/app.rs | 57 + Tools/dora-rust/dora/src/dora/array.rs | 42 + Tools/dora-rust/dora/src/dora/camera.rs | 2 + Tools/dora-rust/dora/src/dora/camera_2d.rs | 16 + Tools/dora-rust/dora/src/dora/camera_otho.rs | 12 + Tools/dora-rust/dora/src/dora/content.rs | 177 +++ Tools/dora-rust/dora/src/dora/dictionary.rs | 5 + Tools/dora-rust/dora/src/dora/director.rs | 29 + Tools/dora-rust/dora/src/dora/effect.rs | 29 + Tools/dora-rust/dora/src/dora/entity.rs | 13 + Tools/dora-rust/dora/src/dora/grabber.rs | 52 + Tools/dora-rust/dora/src/dora/group.rs | 20 + Tools/dora-rust/dora/src/dora/node.rs | 358 ++++- Tools/dora-rust/dora/src/dora/observer.rs | 11 + Tools/dora-rust/dora/src/dora/pass.rs | 43 + Tools/dora-rust/dora/src/dora/path.rs | 112 ++ Tools/dora-rust/dora/src/dora/rect.rs | 75 ++ Tools/dora-rust/dora/src/dora/scheduler.rs | 17 + .../dora-rust/dora/src/dora/sprite_effect.rs | 13 + Tools/dora-rust/dora/src/dora/view.rs | 17 + 44 files changed, 3024 insertions(+), 408 deletions(-) diff --git a/Assets/Script/Lib/Dora/en/App.d.tl b/Assets/Script/Lib/Dora/en/App.d.tl index 581cbf3a5..90ded2f73 100644 --- a/Assets/Script/Lib/Dora/en/App.d.tl +++ b/Assets/Script/Lib/Dora/en/App.d.tl @@ -38,6 +38,9 @@ local record App -- Should be in format of "v0.0.0". const version: string + -- The dependencies of the game engine. + const deps: string + -- The time in seconds since the last frame update. const deltaTime: number diff --git a/Assets/Script/Lib/Dora/en/Array.d.tl b/Assets/Script/Lib/Dora/en/Array.d.tl index 176ba5304..592b39086 100644 --- a/Assets/Script/Lib/Dora/en/Array.d.tl +++ b/Assets/Script/Lib/Dora/en/Array.d.tl @@ -96,7 +96,7 @@ local record Array index: function(self: Array, item: Item): integer -- Removes and returns the last item in the array. - -- @return (Item) The last item in the array. + -- @return (Item) The last item removed from the array. removeLast: function(self: Array): Item -- Removes the first occurrence of a given item from the array without preserving order. diff --git a/Assets/Script/Lib/Dora/en/Node.d.tl b/Assets/Script/Lib/Dora/en/Node.d.tl index dd60368f3..15c3e93e3 100644 --- a/Assets/Script/Lib/Dora/en/Node.d.tl +++ b/Assets/Script/Lib/Dora/en/Node.d.tl @@ -426,6 +426,12 @@ local record Node -- @param y (integer) The y-index of the vertex in the grabber grid. -- @param color (Color) The new color of the vertex. setColor: function(self: Grabber, x: integer, y: integer, color: Color) + + -- Sets the UV coordinates of a vertex in the grabber grid. + -- @param x (integer) The x-index of the vertex in the grabber grid. + -- @param y (integer) The y-index of the vertex in the grabber grid. + -- @param offset (Vec2) The new UV coordinates of the vertex. + moveUV: function(self: Grabber, x: integer, y: integer, offset: Vec2) end -- Creates or removes a texture grabber for the specified node. diff --git a/Assets/Script/Lib/Dora/zh-Hans/App.d.tl b/Assets/Script/Lib/Dora/zh-Hans/App.d.tl index 08b8e73a6..5650c66fa 100644 --- a/Assets/Script/Lib/Dora/zh-Hans/App.d.tl +++ b/Assets/Script/Lib/Dora/zh-Hans/App.d.tl @@ -37,6 +37,9 @@ local record App -- 格式为“v0.0.0”。 const version: string + -- 游戏引擎的第三方依赖库的版本信息。 + const deps: string + -- 自从上一帧游戏更新以来间隔的时间(以秒为单位)。 const deltaTime: number diff --git a/Assets/Script/Lib/Dora/zh-Hans/Node.d.tl b/Assets/Script/Lib/Dora/zh-Hans/Node.d.tl index ef90458e2..50289401f 100644 --- a/Assets/Script/Lib/Dora/zh-Hans/Node.d.tl +++ b/Assets/Script/Lib/Dora/zh-Hans/Node.d.tl @@ -428,6 +428,12 @@ local record Node -- @param y (integer) 顶点在抓取器网格中的 y 索引。 -- @param color (Color) 顶点的新颜色。 setColor: function(self: Grabber, x: integer, y: integer, color: Color) + + -- 设置抓取器网格中一个顶点的纹理坐标。 + -- @param x (integer) 顶点在抓取器网格中的 x 索引。 + -- @param y (integer) 顶点在抓取器网格中的 y 索引。 + -- @param offset (Vec2) 顶点的新纹理坐标。 + moveUV: function(self: Grabber, x: integer, y: integer, offset: Vec2) end -- 创建或移除节点上的纹理抓取器。 diff --git a/Source/3rdParty/wasm3/m3_env.c b/Source/3rdParty/wasm3/m3_env.c index 1121ae24e..6e3a0696c 100644 --- a/Source/3rdParty/wasm3/m3_env.c +++ b/Source/3rdParty/wasm3/m3_env.c @@ -181,11 +181,12 @@ IM3Runtime m3_NewRuntime (IM3Environment i_environment, u32 i_stackSizeInBytes runtime->environment = i_environment; runtime->userdata = i_userdata; - runtime->stack = m3_Malloc ("Wasm Stack", i_stackSizeInBytes + 4*sizeof (m3slot_t)); // TODO: more precise stack checks + runtime->originStack = m3_Malloc ("Wasm Stack", i_stackSizeInBytes + 4*sizeof (m3slot_t)); // TODO: more precise stack checks - if (runtime->stack) + if (runtime->originStack) { - runtime->numStackSlots = i_stackSizeInBytes / sizeof (m3slot_t); m3log (runtime, "new stack: %p", runtime->stack); + runtime->stack = runtime->originStack; + runtime->numStackSlots = i_stackSizeInBytes / sizeof (m3slot_t); m3log (runtime, "new stack: %p", runtime->originStack); } else m3_Free (runtime); } @@ -233,7 +234,7 @@ void Runtime_Release (IM3Runtime i_runtime) Environment_ReleaseCodePages (i_runtime->environment, i_runtime->pagesOpen); Environment_ReleaseCodePages (i_runtime->environment, i_runtime->pagesFull); - m3_Free (i_runtime->stack); + m3_Free (i_runtime->originStack); m3_Free (i_runtime->memory.mallocated); } @@ -297,8 +298,12 @@ M3Result EvaluateExpression (IM3Module i_module, void * o_expressed, u8 i_type if (not result) { +# if (d_m3EnableOpProfiling || d_m3EnableOpTracing) + m3ret_t r = RunCode (m3code, stack, NULL, d_m3OpDefaultArgs, d_m3BaseCstr); +# else m3ret_t r = RunCode (m3code, stack, NULL, d_m3OpDefaultArgs); - +# endif + if (r == 0) { m3log (runtime, "expression result: %s", SPrintValue (stack, i_type)); if (SizeOfType (i_type) == sizeof (u32)) @@ -317,7 +322,7 @@ M3Result EvaluateExpression (IM3Module i_module, void * o_expressed, u8 i_type } else result = m3Err_mallocFailedCodePage; - runtime.stack = NULL; // prevent free(stack) in ReleaseRuntime + runtime.originStack = NULL; // prevent free(stack) in ReleaseRuntime Runtime_Release (& runtime); i_module->runtime = savedRuntime; @@ -568,7 +573,11 @@ _ (CompileFunction (function)); startFunctionTmp = io_module->startFunction; io_module->startFunction = -1; +# if (d_m3EnableOpProfiling || d_m3EnableOpTracing) + result = (M3Result) RunCode (function->compiled, (m3stack_t) runtime->stack, runtime->memory.mallocated, d_m3OpDefaultArgs, d_m3BaseCstr); +# else result = (M3Result) RunCode (function->compiled, (m3stack_t) runtime->stack, runtime->memory.mallocated, d_m3OpDefaultArgs); +# endif if (result) { @@ -666,8 +675,7 @@ M3Result m3_SetGlobal (IM3Global i_global, const IM3TaggedValue i_value) { if (not i_global) return m3Err_globalLookupFailed; - // TODO: if (not g->isMutable) return m3Err_globalNotMutable; - + if (not i_global->isMutable) return m3Err_globalNotMutable; if (i_global->type != i_value->type) return m3Err_globalTypeMismatch; switch (i_value->type) { @@ -751,6 +759,31 @@ _ (CompileFunction (function)) return result; } + +M3Result m3_GetTableFunction (IM3Function * o_function, IM3Module i_module, uint32_t i_index) +{ +_try { + if (i_index >= i_module->table0Size) + { + _throw ("function index out of range"); + } + + IM3Function function = i_module->table0[i_index]; + + if (function) + { + if (not function->compiled) + { +_ (CompileFunction (function)) + } + } + + * o_function = function; +} _catch: + return result; +} + + static M3Result checkStartFunction(IM3Module i_module) { @@ -875,7 +908,11 @@ _ (checkStartFunction(i_function->module)) } } +# if (d_m3EnableOpProfiling || d_m3EnableOpTracing) + result = (M3Result) RunCode (i_function->compiled, (m3stack_t)(runtime->stack), runtime->memory.mallocated, d_m3OpDefaultArgs, d_m3BaseCstr); +# else result = (M3Result) RunCode (i_function->compiled, (m3stack_t)(runtime->stack), runtime->memory.mallocated, d_m3OpDefaultArgs); +# endif ReportNativeStackUsage (); runtime->lastCalled = result ? NULL : i_function; @@ -920,7 +957,12 @@ _ (checkStartFunction(i_function->module)) } } +# if (d_m3EnableOpProfiling || d_m3EnableOpTracing) + result = (M3Result) RunCode (i_function->compiled, (m3stack_t)(runtime->stack), runtime->memory.mallocated, d_m3OpDefaultArgs, d_m3BaseCstr); +# else result = (M3Result) RunCode (i_function->compiled, (m3stack_t)(runtime->stack), runtime->memory.mallocated, d_m3OpDefaultArgs); +# endif + ReportNativeStackUsage (); runtime->lastCalled = result ? NULL : i_function; @@ -965,7 +1007,12 @@ _ (checkStartFunction(i_function->module)) } } +# if (d_m3EnableOpProfiling || d_m3EnableOpTracing) + result = (M3Result) RunCode (i_function->compiled, (m3stack_t)(runtime->stack), runtime->memory.mallocated, d_m3OpDefaultArgs, d_m3BaseCstr); +# else result = (M3Result) RunCode (i_function->compiled, (m3stack_t)(runtime->stack), runtime->memory.mallocated, d_m3OpDefaultArgs); +# endif + ReportNativeStackUsage (); runtime->lastCalled = result ? NULL : i_function; diff --git a/Source/3rdParty/wasm3/m3_env.h b/Source/3rdParty/wasm3/m3_env.h index 61839987f..e5c398a87 100644 --- a/Source/3rdParty/wasm3/m3_env.h +++ b/Source/3rdParty/wasm3/m3_env.h @@ -110,9 +110,12 @@ typedef struct M3Module IM3Function * table0; u32 table0Size; + const char* table0ExportName; M3MemoryInfo memoryInfo; + M3ImportInfo memoryImport; bool memoryImported; + const char* memoryExportName; //bool hasWasmCodeCopy; @@ -168,6 +171,7 @@ typedef struct M3Runtime IM3Module modules; // linked list of imported modules void * stack; + void * originStack; u32 stackSize; u32 numStackSlots; IM3Function lastCalled; // last function that successfully executed diff --git a/Source/3rdParty/wasm3/m3_exec.h b/Source/3rdParty/wasm3/m3_exec.h index 47258eb5e..0d5567631 100644 --- a/Source/3rdParty/wasm3/m3_exec.h +++ b/Source/3rdParty/wasm3/m3_exec.h @@ -108,8 +108,11 @@ d_m3BeginExternC #endif - +# if (d_m3EnableOpProfiling || d_m3EnableOpTracing) +d_m3RetSig Call (d_m3OpSig, cstr_t i_operationName) +# else d_m3RetSig Call (d_m3OpSig) +# endif { m3ret_t possible_trap = m3_Yield (); if (M3_UNLIKELY(possible_trap)) return possible_trap; @@ -149,8 +152,8 @@ d_m3CommutativeOpMacro(RES, REG, TYPE,NAME, OP, ##__VA_ARGS__) #define d_m3CommutativeOpMacro_f(TYPE, NAME, MACRO, ...) d_m3CommutativeOpMacro (_fp0, _fp0, TYPE, NAME, MACRO, ##__VA_ARGS__) #define d_m3OpMacro_f(TYPE, NAME, MACRO, ...) d_m3OpMacro (_fp0, _fp0, TYPE, NAME, MACRO, ##__VA_ARGS__) -#define M3_FUNC(RES, A, B, OP) (RES) = OP((A), (B)) // Accept functions: res = OP(a,b) -#define M3_OPER(RES, A, B, OP) (RES) = ((A) OP (B)) // Accept operators: res = a OP b +#define M3_FUNC(RES, A, B, OP) (RES) = OP((A), (B)) // Accept functions: res = OP(a,b) +#define M3_OPER(RES, A, B, OP) (RES) = ((A) OP (B)) // Accept operators: res = a OP b #define d_m3CommutativeOpFunc_i(TYPE, NAME, OP) d_m3CommutativeOpMacro_i (TYPE, NAME, M3_FUNC, OP) #define d_m3OpFunc_i(TYPE, NAME, OP) d_m3OpMacro_i (TYPE, NAME, M3_FUNC, OP) @@ -193,10 +196,17 @@ d_m3CompareOp_f (f32, LessThanOrEqual, <=) d_m3CompareOp_f (f64, LessTh d_m3CompareOp_f (f32, GreaterThanOrEqual, >=) d_m3CompareOp_f (f64, GreaterThanOrEqual, >=) #endif -d_m3CommutativeOp_i (i32, Add, +) d_m3CommutativeOp_i (i64, Add, +) -d_m3CommutativeOp_i (i32, Multiply, *) d_m3CommutativeOp_i (i64, Multiply, *) +#define OP_ADD_32(A,B) (i32)((u32)(A) + (u32)(B)) +#define OP_ADD_64(A,B) (i64)((u64)(A) + (u64)(B)) +#define OP_SUB_32(A,B) (i32)((u32)(A) - (u32)(B)) +#define OP_SUB_64(A,B) (i64)((u64)(A) - (u64)(B)) +#define OP_MUL_32(A,B) (i32)((u32)(A) * (u32)(B)) +#define OP_MUL_64(A,B) (i64)((u64)(A) * (u64)(B)) -d_m3Op_i (i32, Subtract, -) d_m3Op_i (i64, Subtract, -) +d_m3CommutativeOpFunc_i (i32, Add, OP_ADD_32) d_m3CommutativeOpFunc_i (i64, Add, OP_ADD_64) +d_m3CommutativeOpFunc_i (i32, Multiply, OP_MUL_32) d_m3CommutativeOpFunc_i (i64, Multiply, OP_MUL_64) + +d_m3OpFunc_i (i32, Subtract, OP_SUB_32) d_m3OpFunc_i (i64, Subtract, OP_SUB_64) #define OP_SHL_32(X,N) ((X) << ((u32)(N) % 32)) #define OP_SHL_64(X,N) ((X) << ((u64)(N) % 64)) @@ -537,7 +547,12 @@ d_m3Op (Call) m3stack_t sp = _sp + stackOffset; +# if (d_m3EnableOpProfiling || d_m3EnableOpTracing) + m3ret_t r = Call (callPC, sp, _mem, d_m3OpDefaultArgs, d_m3BaseCstr); +# else m3ret_t r = Call (callPC, sp, _mem, d_m3OpDefaultArgs); +# endif + _mem = memory->mallocated; if (M3_LIKELY(not r)) @@ -575,7 +590,13 @@ d_m3Op (CallIndirect) if (M3_LIKELY(not r)) { + +# if (d_m3EnableOpProfiling || d_m3EnableOpTracing) + r = Call (function->compiled, sp, _mem, d_m3OpDefaultArgs, d_m3BaseCstr); +# else r = Call (function->compiled, sp, _mem, d_m3OpDefaultArgs); +# endif + _mem = memory->mallocated; if (M3_LIKELY(not r)) diff --git a/Source/3rdParty/wasm3/m3_exec_defs.h b/Source/3rdParty/wasm3/m3_exec_defs.h index 7b6b10938..1c0dc722e 100644 --- a/Source/3rdParty/wasm3/m3_exec_defs.h +++ b/Source/3rdParty/wasm3/m3_exec_defs.h @@ -21,6 +21,7 @@ d_m3BeginExternC # define d_m3BaseOpAllArgs _pc, _sp, _mem, _r0 # define d_m3BaseOpDefaultArgs 0 # define d_m3BaseClearRegisters _r0 = 0; +# define d_m3BaseCstr "" # define d_m3ExpOpSig(...) d_m3BaseOpSig, __VA_ARGS__ # define d_m3ExpOpArgs(...) d_m3BaseOpArgs, __VA_ARGS__ @@ -42,18 +43,30 @@ d_m3BeginExternC # define d_m3ClearRegisters d_m3BaseClearRegisters # endif -typedef m3ret_t (vectorcall * IM3Operation) (d_m3OpSig); #define d_m3RetSig static inline m3ret_t vectorcall -#define d_m3Op(NAME) M3_NO_UBSAN d_m3RetSig op_##NAME (d_m3OpSig) +# if (d_m3EnableOpProfiling || d_m3EnableOpTracing) + typedef m3ret_t (vectorcall * IM3Operation) (d_m3OpSig, cstr_t i_operationName); +# define d_m3Op(NAME) M3_NO_UBSAN d_m3RetSig op_##NAME (d_m3OpSig, cstr_t i_operationName) -#define nextOpImpl() ((IM3Operation)(* _pc))(_pc + 1, d_m3OpArgs) -#define jumpOpImpl(PC) ((IM3Operation)(* PC))( PC + 1, d_m3OpArgs) +# define nextOpImpl() ((IM3Operation)(* _pc))(_pc + 1, d_m3OpArgs, __FUNCTION__) +# define jumpOpImpl(PC) ((IM3Operation)(* PC))( PC + 1, d_m3OpArgs, __FUNCTION__) +# else + typedef m3ret_t (vectorcall * IM3Operation) (d_m3OpSig); +# define d_m3Op(NAME) M3_NO_UBSAN d_m3RetSig op_##NAME (d_m3OpSig) + +# define nextOpImpl() ((IM3Operation)(* _pc))(_pc + 1, d_m3OpArgs) +# define jumpOpImpl(PC) ((IM3Operation)(* PC))( PC + 1, d_m3OpArgs) +# endif #define nextOpDirect() M3_MUSTTAIL return nextOpImpl() #define jumpOpDirect(PC) M3_MUSTTAIL return jumpOpImpl((pc_t)(PC)) +# if (d_m3EnableOpProfiling || d_m3EnableOpTracing) +d_m3RetSig RunCode (d_m3OpSig, cstr_t i_operationName) +# else d_m3RetSig RunCode (d_m3OpSig) +# endif { nextOpDirect(); } diff --git a/Source/3rdParty/wasm3/m3_info.c b/Source/3rdParty/wasm3/m3_info.c index 8c25dca5d..7497daeed 100644 --- a/Source/3rdParty/wasm3/m3_info.c +++ b/Source/3rdParty/wasm3/m3_info.c @@ -305,7 +305,6 @@ void dump_code_page (IM3CodePage i_codePage, pc_t i_startPC) while (pc < end) { - // pc_t operationPC = pc; IM3Operation op = (IM3Operation) (* pc++); OpInfo i = find_operation_info (op); diff --git a/Source/3rdParty/wasm3/m3_parse.c b/Source/3rdParty/wasm3/m3_parse.c index 4c653d302..17c5223e0 100644 --- a/Source/3rdParty/wasm3/m3_parse.c +++ b/Source/3rdParty/wasm3/m3_parse.c @@ -184,6 +184,8 @@ _ (Module_AddFunction (io_module, typeIndex, & import)) { _ (ParseType_Memory (& io_module->memoryInfo, & i_bytes, i_end)); io_module->memoryImported = true; + io_module->memoryImport = import; + import = clearImport; } break; @@ -256,6 +258,18 @@ _ (ReadLEB_u32 (& index, & i_bytes, i_end)); global->name = utf8; utf8 = NULL; // ownership transferred to M3Global } + else if (exportKind == d_externalKind_memory) + { + m3_Free (io_module->memoryExportName); + io_module->memoryExportName = utf8; + utf8 = NULL; // ownership transferred to M3Module + } + else if (exportKind == d_externalKind_table) + { + m3_Free (io_module->table0ExportName); + io_module->table0ExportName = utf8; + utf8 = NULL; // ownership transferred to M3Module + } m3_Free (utf8); } @@ -342,7 +356,6 @@ _ (ReadLEB_u32 (& size, & i_bytes, i_end)); if (size) { - // const u8 * ptr = i_bytes; i_bytes += size; if (i_bytes <= i_end) diff --git a/Source/3rdParty/wasm3/wasm3.h b/Source/3rdParty/wasm3/wasm3.h index 0d8554fee..c567b801b 100644 --- a/Source/3rdParty/wasm3/wasm3.h +++ b/Source/3rdParty/wasm3/wasm3.h @@ -291,6 +291,9 @@ d_m3ErrorConst (trapStackOverflow, "[trap] stack overflow") M3Result m3_FindFunction (IM3Function * o_function, IM3Runtime i_runtime, const char * const i_functionName); + M3Result m3_GetTableFunction (IM3Function * o_function, + IM3Module i_module, + uint32_t i_index); uint32_t m3_GetArgCount (IM3Function i_function); uint32_t m3_GetRetCount (IM3Function i_function); diff --git a/Source/3rdParty/wasm3/wasm3_defs.h b/Source/3rdParty/wasm3/wasm3_defs.h index 7e1352577..2a9870048 100644 --- a/Source/3rdParty/wasm3/wasm3_defs.h +++ b/Source/3rdParty/wasm3/wasm3_defs.h @@ -1,293 +1,293 @@ -// -// wasm3_defs.h -// -// Created by Volodymyr Shymanskyy on 11/20/19. -// Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. -// - -#ifndef wasm3_defs_h -#define wasm3_defs_h - -#define M3_STR__(x) #x -#define M3_STR(x) M3_STR__(x) - -#define M3_CONCAT__(a,b) a##b -#define M3_CONCAT(a,b) M3_CONCAT__(a,b) - -/* - * Detect compiler - */ - -# if defined(__clang__) -# define M3_COMPILER_CLANG 1 -# elif defined(__INTEL_COMPILER) -# define M3_COMPILER_ICC 1 -# elif defined(__GNUC__) || defined(__GNUG__) -# define M3_COMPILER_GCC 1 -# elif defined(_MSC_VER) -# define M3_COMPILER_MSVC 1 -# else -# warning "Compiler not detected" -# endif - -# if defined(M3_COMPILER_CLANG) -# if defined(WIN32) -# define M3_COMPILER_VER __VERSION__ " for Windows" -# else -# define M3_COMPILER_VER __VERSION__ -# endif -# elif defined(M3_COMPILER_GCC) -# define M3_COMPILER_VER "GCC " __VERSION__ -# elif defined(M3_COMPILER_ICC) -# define M3_COMPILER_VER __VERSION__ -# elif defined(M3_COMPILER_MSVC) -# define M3_COMPILER_VER "MSVC " M3_STR(_MSC_VER) -# else -# define M3_COMPILER_VER "unknown" -# endif - -# ifdef __has_feature -# define M3_COMPILER_HAS_FEATURE(x) __has_feature(x) -# else -# define M3_COMPILER_HAS_FEATURE(x) 0 -# endif - -# ifdef __has_builtin -# define M3_COMPILER_HAS_BUILTIN(x) __has_builtin(x) -# else -# define M3_COMPILER_HAS_BUILTIN(x) 0 -# endif - -# ifdef __has_attribute -# define M3_COMPILER_HAS_ATTRIBUTE(x) __has_attribute(x) -# else -# define M3_COMPILER_HAS_ATTRIBUTE(x) 0 -# endif - -/* - * Detect endianness - */ - -# if defined(M3_COMPILER_MSVC) -# define M3_LITTLE_ENDIAN -# elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -# define M3_LITTLE_ENDIAN -# elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -# define M3_BIG_ENDIAN -# else -# error "Byte order not detected" -# endif - -/* - * Detect platform - */ - -# if defined(M3_COMPILER_CLANG) || defined(M3_COMPILER_GCC) || defined(M3_COMPILER_ICC) -# if defined(__wasm__) -# define M3_ARCH "wasm" - -# elif defined(__x86_64__) -# define M3_ARCH "x86_64" - -# elif defined(__i386__) -# define M3_ARCH "i386" - -# elif defined(__aarch64__) -# define M3_ARCH "arm64-v8a" - -# elif defined(__arm__) -# if defined(__ARM_ARCH_7A__) -# if defined(__ARM_NEON__) -# if defined(__ARM_PCS_VFP) -# define M3_ARCH "arm-v7a/NEON hard-float" -# else -# define M3_ARCH "arm-v7a/NEON" -# endif -# else -# if defined(__ARM_PCS_VFP) -# define M3_ARCH "arm-v7a hard-float" -# else -# define M3_ARCH "arm-v7a" -# endif -# endif -# else -# define M3_ARCH "arm" -# endif - -# elif defined(__riscv) -# if defined(__riscv_32e) -# define _M3_ARCH_RV "rv32e" -# elif __riscv_xlen == 128 -# define _M3_ARCH_RV "rv128i" -# elif __riscv_xlen == 64 -# define _M3_ARCH_RV "rv64i" -# elif __riscv_xlen == 32 -# define _M3_ARCH_RV "rv32i" -# endif -# if defined(__riscv_muldiv) -# define _M3_ARCH_RV_M _M3_ARCH_RV "m" -# else -# define _M3_ARCH_RV_M _M3_ARCH_RV -# endif -# if defined(__riscv_atomic) -# define _M3_ARCH_RV_A _M3_ARCH_RV_M "a" -# else -# define _M3_ARCH_RV_A _M3_ARCH_RV_M -# endif -# if defined(__riscv_flen) -# define _M3_ARCH_RV_F _M3_ARCH_RV_A "f" -# else -# define _M3_ARCH_RV_F _M3_ARCH_RV_A -# endif -# if defined(__riscv_flen) && __riscv_flen >= 64 -# define _M3_ARCH_RV_D _M3_ARCH_RV_F "d" -# else -# define _M3_ARCH_RV_D _M3_ARCH_RV_F -# endif -# if defined(__riscv_compressed) -# define _M3_ARCH_RV_C _M3_ARCH_RV_D "c" -# else -# define _M3_ARCH_RV_C _M3_ARCH_RV_D -# endif -# define M3_ARCH _M3_ARCH_RV_C - -# elif defined(__mips__) -# if defined(__MIPSEB__) && defined(__mips64) -# define M3_ARCH "mips64 " _MIPS_ARCH -# elif defined(__MIPSEL__) && defined(__mips64) -# define M3_ARCH "mips64el " _MIPS_ARCH -# elif defined(__MIPSEB__) -# define M3_ARCH "mips " _MIPS_ARCH -# elif defined(__MIPSEL__) -# define M3_ARCH "mipsel " _MIPS_ARCH -# endif - -# elif defined(__PPC__) -# if defined(__PPC64__) && defined(__LITTLE_ENDIAN__) -# define M3_ARCH "ppc64le" -# elif defined(__PPC64__) -# define M3_ARCH "ppc64" -# else -# define M3_ARCH "ppc" -# endif - -# elif defined(__sparc__) -# if defined(__arch64__) -# define M3_ARCH "sparc64" -# else -# define M3_ARCH "sparc" -# endif - -# elif defined(__s390x__) -# define M3_ARCH "s390x" - -# elif defined(__alpha__) -# define M3_ARCH "alpha" - -# elif defined(__m68k__) -# define M3_ARCH "m68k" - -# elif defined(__xtensa__) -# define M3_ARCH "xtensa" - -# elif defined(__arc__) -# define M3_ARCH "arc32" - -# elif defined(__AVR__) -# define M3_ARCH "avr" -# endif -# endif - -# if defined(M3_COMPILER_MSVC) -# if defined(_M_X64) -# define M3_ARCH "x86_64" -# elif defined(_M_IX86) -# define M3_ARCH "i386" -# elif defined(_M_ARM64) -# define M3_ARCH "arm64" -# elif defined(_M_ARM) -# define M3_ARCH "arm" -# endif -# endif - -# if !defined(M3_ARCH) -# warning "Architecture not detected" -# define M3_ARCH "unknown" -# endif - -/* - * Byte swapping (for Big-Endian systems only) - */ - -# if defined(M3_COMPILER_MSVC) -# define m3_bswap16(x) _byteswap_ushort((x)) -# define m3_bswap32(x) _byteswap_ulong((x)) -# define m3_bswap64(x) _byteswap_uint64((x)) -# elif defined(M3_COMPILER_GCC) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) -// __builtin_bswap32/64 added in gcc 4.3, __builtin_bswap16 added in gcc 4.8 -# define m3_bswap16(x) __builtin_bswap16((x)) -# define m3_bswap32(x) __builtin_bswap32((x)) -# define m3_bswap64(x) __builtin_bswap64((x)) -# elif defined(M3_COMPILER_CLANG) && M3_COMPILER_HAS_BUILTIN(__builtin_bswap16) -# define m3_bswap16(x) __builtin_bswap16((x)) -# define m3_bswap32(x) __builtin_bswap32((x)) -# define m3_bswap64(x) __builtin_bswap64((x)) -# elif defined(M3_COMPILER_ICC) -# define m3_bswap16(x) __builtin_bswap16((x)) -# define m3_bswap32(x) __builtin_bswap32((x)) -# define m3_bswap64(x) __builtin_bswap64((x)) -# else -# ifdef __linux__ -# include -# else -# include -# endif -# if defined(__bswap_16) -# define m3_bswap16(x) __bswap_16((x)) -# define m3_bswap32(x) __bswap_32((x)) -# define m3_bswap64(x) __bswap_64((x)) -# else -# warning "Using naive (probably slow) bswap operations" - static inline - uint16_t m3_bswap16(uint16_t x) { - return ((( x >> 8 ) & 0xffu ) | (( x & 0xffu ) << 8 )); - } - static inline - uint32_t m3_bswap32(uint32_t x) { - return ((( x & 0xff000000u ) >> 24 ) | - (( x & 0x00ff0000u ) >> 8 ) | - (( x & 0x0000ff00u ) << 8 ) | - (( x & 0x000000ffu ) << 24 )); - } - static inline - uint64_t m3_bswap64(uint64_t x) { - return ((( x & 0xff00000000000000ull ) >> 56 ) | - (( x & 0x00ff000000000000ull ) >> 40 ) | - (( x & 0x0000ff0000000000ull ) >> 24 ) | - (( x & 0x000000ff00000000ull ) >> 8 ) | - (( x & 0x00000000ff000000ull ) << 8 ) | - (( x & 0x0000000000ff0000ull ) << 24 ) | - (( x & 0x000000000000ff00ull ) << 40 ) | - (( x & 0x00000000000000ffull ) << 56 )); - } -# endif -# endif - -/* - * Bit ops - */ -#define m3_isBitSet(val, pos) ((val & (1 << pos)) != 0) - -/* - * Other - */ - -# if defined(M3_COMPILER_GCC) || defined(M3_COMPILER_CLANG) || defined(M3_COMPILER_ICC) -# define M3_UNLIKELY(x) __builtin_expect(!!(x), 0) -# define M3_LIKELY(x) __builtin_expect(!!(x), 1) -# else -# define M3_UNLIKELY(x) (x) -# define M3_LIKELY(x) (x) -# endif - -#endif // wasm3_defs_h +// +// wasm3_defs.h +// +// Created by Volodymyr Shymanskyy on 11/20/19. +// Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. +// + +#ifndef wasm3_defs_h +#define wasm3_defs_h + +#define M3_STR__(x) #x +#define M3_STR(x) M3_STR__(x) + +#define M3_CONCAT__(a,b) a##b +#define M3_CONCAT(a,b) M3_CONCAT__(a,b) + +/* + * Detect compiler + */ + +# if defined(__clang__) +# define M3_COMPILER_CLANG 1 +# elif defined(__INTEL_COMPILER) +# define M3_COMPILER_ICC 1 +# elif defined(__GNUC__) || defined(__GNUG__) +# define M3_COMPILER_GCC 1 +# elif defined(_MSC_VER) +# define M3_COMPILER_MSVC 1 +# else +# warning "Compiler not detected" +# endif + +# if defined(M3_COMPILER_CLANG) +# if defined(WIN32) +# define M3_COMPILER_VER __VERSION__ " for Windows" +# else +# define M3_COMPILER_VER __VERSION__ +# endif +# elif defined(M3_COMPILER_GCC) +# define M3_COMPILER_VER "GCC " __VERSION__ +# elif defined(M3_COMPILER_ICC) +# define M3_COMPILER_VER __VERSION__ +# elif defined(M3_COMPILER_MSVC) +# define M3_COMPILER_VER "MSVC " M3_STR(_MSC_VER) +# else +# define M3_COMPILER_VER "unknown" +# endif + +# ifdef __has_feature +# define M3_COMPILER_HAS_FEATURE(x) __has_feature(x) +# else +# define M3_COMPILER_HAS_FEATURE(x) 0 +# endif + +# ifdef __has_builtin +# define M3_COMPILER_HAS_BUILTIN(x) __has_builtin(x) +# else +# define M3_COMPILER_HAS_BUILTIN(x) 0 +# endif + +# ifdef __has_attribute +# define M3_COMPILER_HAS_ATTRIBUTE(x) __has_attribute(x) +# else +# define M3_COMPILER_HAS_ATTRIBUTE(x) 0 +# endif + +/* + * Detect endianness + */ + +# if defined(M3_COMPILER_MSVC) +# define M3_LITTLE_ENDIAN +# elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define M3_LITTLE_ENDIAN +# elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define M3_BIG_ENDIAN +# else +# error "Byte order not detected" +# endif + +/* + * Detect platform + */ + +# if defined(M3_COMPILER_CLANG) || defined(M3_COMPILER_GCC) || defined(M3_COMPILER_ICC) +# if defined(__wasm__) +# define M3_ARCH "wasm" + +# elif defined(__x86_64__) +# define M3_ARCH "x86_64" + +# elif defined(__i386__) +# define M3_ARCH "i386" + +# elif defined(__aarch64__) +# define M3_ARCH "arm64-v8a" + +# elif defined(__arm__) +# if defined(__ARM_ARCH_7A__) +# if defined(__ARM_NEON__) +# if defined(__ARM_PCS_VFP) +# define M3_ARCH "arm-v7a/NEON hard-float" +# else +# define M3_ARCH "arm-v7a/NEON" +# endif +# else +# if defined(__ARM_PCS_VFP) +# define M3_ARCH "arm-v7a hard-float" +# else +# define M3_ARCH "arm-v7a" +# endif +# endif +# else +# define M3_ARCH "arm" +# endif + +# elif defined(__riscv) +# if defined(__riscv_32e) +# define _M3_ARCH_RV "rv32e" +# elif __riscv_xlen == 128 +# define _M3_ARCH_RV "rv128i" +# elif __riscv_xlen == 64 +# define _M3_ARCH_RV "rv64i" +# elif __riscv_xlen == 32 +# define _M3_ARCH_RV "rv32i" +# endif +# if defined(__riscv_muldiv) +# define _M3_ARCH_RV_M _M3_ARCH_RV "m" +# else +# define _M3_ARCH_RV_M _M3_ARCH_RV +# endif +# if defined(__riscv_atomic) +# define _M3_ARCH_RV_A _M3_ARCH_RV_M "a" +# else +# define _M3_ARCH_RV_A _M3_ARCH_RV_M +# endif +# if defined(__riscv_flen) +# define _M3_ARCH_RV_F _M3_ARCH_RV_A "f" +# else +# define _M3_ARCH_RV_F _M3_ARCH_RV_A +# endif +# if defined(__riscv_flen) && __riscv_flen >= 64 +# define _M3_ARCH_RV_D _M3_ARCH_RV_F "d" +# else +# define _M3_ARCH_RV_D _M3_ARCH_RV_F +# endif +# if defined(__riscv_compressed) +# define _M3_ARCH_RV_C _M3_ARCH_RV_D "c" +# else +# define _M3_ARCH_RV_C _M3_ARCH_RV_D +# endif +# define M3_ARCH _M3_ARCH_RV_C + +# elif defined(__mips__) +# if defined(__MIPSEB__) && defined(__mips64) +# define M3_ARCH "mips64 " _MIPS_ARCH +# elif defined(__MIPSEL__) && defined(__mips64) +# define M3_ARCH "mips64el " _MIPS_ARCH +# elif defined(__MIPSEB__) +# define M3_ARCH "mips " _MIPS_ARCH +# elif defined(__MIPSEL__) +# define M3_ARCH "mipsel " _MIPS_ARCH +# endif + +# elif defined(__PPC__) +# if defined(__PPC64__) && defined(__LITTLE_ENDIAN__) +# define M3_ARCH "ppc64le" +# elif defined(__PPC64__) +# define M3_ARCH "ppc64" +# else +# define M3_ARCH "ppc" +# endif + +# elif defined(__sparc__) +# if defined(__arch64__) +# define M3_ARCH "sparc64" +# else +# define M3_ARCH "sparc" +# endif + +# elif defined(__s390x__) +# define M3_ARCH "s390x" + +# elif defined(__alpha__) +# define M3_ARCH "alpha" + +# elif defined(__m68k__) +# define M3_ARCH "m68k" + +# elif defined(__xtensa__) +# define M3_ARCH "xtensa" + +# elif defined(__arc__) +# define M3_ARCH "arc32" + +# elif defined(__AVR__) +# define M3_ARCH "avr" +# endif +# endif + +# if defined(M3_COMPILER_MSVC) +# if defined(_M_X64) +# define M3_ARCH "x86_64" +# elif defined(_M_IX86) +# define M3_ARCH "i386" +# elif defined(_M_ARM64) +# define M3_ARCH "arm64" +# elif defined(_M_ARM) +# define M3_ARCH "arm" +# endif +# endif + +# if !defined(M3_ARCH) +# warning "Architecture not detected" +# define M3_ARCH "unknown" +# endif + +/* + * Byte swapping (for Big-Endian systems only) + */ + +# if defined(M3_COMPILER_MSVC) +# define m3_bswap16(x) _byteswap_ushort((x)) +# define m3_bswap32(x) _byteswap_ulong((x)) +# define m3_bswap64(x) _byteswap_uint64((x)) +# elif defined(M3_COMPILER_GCC) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) +// __builtin_bswap32/64 added in gcc 4.3, __builtin_bswap16 added in gcc 4.8 +# define m3_bswap16(x) __builtin_bswap16((x)) +# define m3_bswap32(x) __builtin_bswap32((x)) +# define m3_bswap64(x) __builtin_bswap64((x)) +# elif defined(M3_COMPILER_CLANG) && M3_COMPILER_HAS_BUILTIN(__builtin_bswap16) +# define m3_bswap16(x) __builtin_bswap16((x)) +# define m3_bswap32(x) __builtin_bswap32((x)) +# define m3_bswap64(x) __builtin_bswap64((x)) +# elif defined(M3_COMPILER_ICC) +# define m3_bswap16(x) __builtin_bswap16((x)) +# define m3_bswap32(x) __builtin_bswap32((x)) +# define m3_bswap64(x) __builtin_bswap64((x)) +# else +# ifdef __linux__ +# include +# else +# include +# endif +# if defined(__bswap_16) +# define m3_bswap16(x) __bswap_16((x)) +# define m3_bswap32(x) __bswap_32((x)) +# define m3_bswap64(x) __bswap_64((x)) +# else +# warning "Using naive (probably slow) bswap operations" + static inline + uint16_t m3_bswap16(uint16_t x) { + return ((( x >> 8 ) & 0xffu ) | (( x & 0xffu ) << 8 )); + } + static inline + uint32_t m3_bswap32(uint32_t x) { + return ((( x & 0xff000000u ) >> 24 ) | + (( x & 0x00ff0000u ) >> 8 ) | + (( x & 0x0000ff00u ) << 8 ) | + (( x & 0x000000ffu ) << 24 )); + } + static inline + uint64_t m3_bswap64(uint64_t x) { + return ((( x & 0xff00000000000000ull ) >> 56 ) | + (( x & 0x00ff000000000000ull ) >> 40 ) | + (( x & 0x0000ff0000000000ull ) >> 24 ) | + (( x & 0x000000ff00000000ull ) >> 8 ) | + (( x & 0x00000000ff000000ull ) << 8 ) | + (( x & 0x0000000000ff0000ull ) << 24 ) | + (( x & 0x000000000000ff00ull ) << 40 ) | + (( x & 0x00000000000000ffull ) << 56 )); + } +# endif +# endif + +/* + * Bit ops + */ +#define m3_isBitSet(val, pos) ((val & (1 << pos)) != 0) + +/* + * Other + */ + +# if defined(M3_COMPILER_GCC) || defined(M3_COMPILER_CLANG) || defined(M3_COMPILER_ICC) +# define M3_UNLIKELY(x) __builtin_expect(!!(x), 0) +# define M3_LIKELY(x) __builtin_expect(!!(x), 1) +# else +# define M3_UNLIKELY(x) (x) +# define M3_LIKELY(x) (x) +# endif + +#endif // wasm3_defs_h diff --git a/Source/Common/Debug.cpp b/Source/Common/Debug.cpp index 839f67da8..8aee5a9f5 100644 --- a/Source/Common/Debug.cpp +++ b/Source/Common/Debug.cpp @@ -35,7 +35,7 @@ void LogError(const std::string& str) { #else std::cerr << str; #endif // BX_PLATFORM_ANDROID - if (!Singleton::isDisposed() && SharedApplication.isLogicRunning()) { + if (Singleton::isInitialized() && SharedApplication.isLogicRunning()) { SharedApplication.invokeInLogic([str]() { LogHandler(str); }); @@ -68,7 +68,7 @@ void LogPrintInThread(const std::string& str) { } bool IsInLua() { - return !Dora::Singleton::isDisposed() && SharedLuaEngine.isInLua(); + return Dora::Singleton::isInitialized() && SharedLuaEngine.isInLua(); } NS_DORA_END diff --git a/Source/Common/Utils.cpp b/Source/Common/Utils.cpp index 98c9f2885..1f1a288b8 100644 --- a/Source/Common/Utils.cpp +++ b/Source/Common/Utils.cpp @@ -70,6 +70,21 @@ Profiler::~Profiler() { level--; } +std::string Path::concatVector(const std::vector& paths) { + if (paths.empty()) return Slice::Empty; + if (paths.size() == 1) return paths.front(); + fs::path path = paths.front(); + for (auto it = ++paths.begin(); it != paths.end(); ++it) { + if (it->empty()) continue; + if (path.empty()) { + path = *it; + } else { + path /= *it; + } + } + return path.string(); +} + std::string Path::concat(const std::list& paths) { if (paths.empty()) return Slice::Empty; if (paths.size() == 1) return paths.front().toString(); diff --git a/Source/Common/Utils.h b/Source/Common/Utils.h index 813287676..7ff44315a 100644 --- a/Source/Common/Utils.h +++ b/Source/Common/Utils.h @@ -372,6 +372,7 @@ class Profiler { class Path { public: + static std::string concatVector(const std::vector& paths); static std::string concat(const std::list& paths); static std::string getExt(String path); static std::string getPath(String path); diff --git a/Source/Wasm/Dora/NodeWasm.hpp b/Source/Wasm/Dora/NodeWasm.hpp index 95b391f7f..d106d427c 100644 --- a/Source/Wasm/Dora/NodeWasm.hpp +++ b/Source/Wasm/Dora/NodeWasm.hpp @@ -327,8 +327,8 @@ static int64_t node_run_action(int64_t self, int64_t def) { static void node_stop_all_actions(int64_t self) { r_cast(self)->stopAllActions(); } -static int64_t node_perform(int64_t self, int64_t def) { - return from_object(node_perform_def(r_cast(self), std::move(*r_cast(def)))); +static int64_t node_perform(int64_t self, int64_t action_def) { + return from_object(node_perform_def(r_cast(self), std::move(*r_cast(action_def)))); } static void node_stop_action(int64_t self, int64_t action) { r_cast(self)->stopAction(r_cast(action)); @@ -372,27 +372,27 @@ static void node_stop_grab(int64_t self) { static void node_set_transform_target_null(int64_t self) { node_set_transform_target_nullptr(r_cast(self)); } -static int32_t node_slot(int64_t self, int64_t name, int32_t func, int64_t stack) { +static void node_slot(int64_t self, int64_t event_name, int32_t func, int64_t stack) { std::shared_ptr deref(nullptr, [func](auto) { SharedWasmRuntime.deref(func); }); auto args = r_cast(stack); - return r_cast(self)->slot(*str_from(name), [func, args, deref](Event* e) { + r_cast(self)->slot(*str_from(event_name), [func, args, deref](Event* e) { args->clear(); e->pushArgsToWasm(args); SharedWasmRuntime.invoke(func); - }) ? 1 : 0; + }); } -static int32_t node_gslot(int64_t self, int64_t name, int32_t func, int64_t stack) { +static void node_gslot(int64_t self, int64_t event_name, int32_t func, int64_t stack) { std::shared_ptr deref(nullptr, [func](auto) { SharedWasmRuntime.deref(func); }); auto args = r_cast(stack); - return r_cast(self)->gslot(*str_from(name), [func, args, deref](Event* e) { + r_cast(self)->gslot(*str_from(event_name), [func, args, deref](Event* e) { args->clear(); e->pushArgsToWasm(args); SharedWasmRuntime.invoke(func); - }) ? 1 : 0; + }); } static int64_t node_new() { return from_object(Node::create()); @@ -511,4 +511,4 @@ static void linkNode(wasm3::module3& mod) { mod.link_optional("*", "node_slot", node_slot); mod.link_optional("*", "node_gslot", node_gslot); mod.link_optional("*", "node_new", node_new); -} \ No newline at end of file +} diff --git a/Source/Wasm/Dora/PathWasm.hpp b/Source/Wasm/Dora/PathWasm.hpp index e28212816..a2ff46856 100644 --- a/Source/Wasm/Dora/PathWasm.hpp +++ b/Source/Wasm/Dora/PathWasm.hpp @@ -19,6 +19,9 @@ static int64_t path_replace_ext(int64_t path, int64_t new_ext) { static int64_t path_replace_filename(int64_t path, int64_t new_file) { return str_retain(Path::replaceFilename(*str_from(path), *str_from(new_file))); } +static int64_t path_concat(int64_t paths) { + return str_retain(Path::concatVector(from_str_vec(paths))); +} static void linkPath(wasm3::module3& mod) { mod.link_optional("*", "path_get_ext", path_get_ext); mod.link_optional("*", "path_get_path", path_get_path); @@ -27,4 +30,5 @@ static void linkPath(wasm3::module3& mod) { mod.link_optional("*", "path_get_relative", path_get_relative); mod.link_optional("*", "path_replace_ext", path_replace_ext); mod.link_optional("*", "path_replace_filename", path_replace_filename); + mod.link_optional("*", "path_concat", path_concat); } \ No newline at end of file diff --git a/Source/Wasm/WasmRuntime.cpp b/Source/Wasm/WasmRuntime.cpp index 92379237c..f386f7f5f 100644 --- a/Source/Wasm/WasmRuntime.cpp +++ b/Source/Wasm/WasmRuntime.cpp @@ -170,10 +170,6 @@ static int64_t to_vec(const std::vector& vec) { return buf_retain(dora_vec_t(std::move(buf))); } -static int64_t to_vec(const std::vector& vec) { - return buf_retain(dora_vec_t(std::move(vec))); -} - static std::vector from_str_vec(int64_t var) { auto vec = std::unique_ptr(r_cast(var)); auto vecInt = std::get>(*vec); diff --git a/Tools/RustWasmGen/Dora.h b/Tools/RustWasmGen/Dora.h index 423093b99..e6d588f63 100644 --- a/Tools/RustWasmGen/Dora.h +++ b/Tools/RustWasmGen/Dora.h @@ -1,357 +1,1440 @@ +/// An array data structure that supports various operations. object class Array { + /// the number of items in the array. readonly common size_t count; + /// whether the array is empty or not. readonly boolean bool empty; + /// Adds all items from another array to the end of this array. + /// + /// # Arguments + /// + /// * `other` - Another array object. void addRange(Array* other); + /// Removes all items from this array that are also in another array. + /// + /// # Arguments + /// + /// * `other` - Another array object. void removeFrom(Array* other); + /// Removes all items from the array. void clear(); + /// Reverses the order of the items in the array. void reverse(); + /// Removes any empty slots from the end of the array. + /// This method is used to release the unused memory this array holds. void shrink(); + /// Swaps the items at two given indices. + /// + /// # Arguments + /// + /// * `index_a` - The first index. + /// * `index_b` - The second index. void swap(int indexA, int indexB); + /// Removes the item at the given index. + /// + /// # Arguments + /// + /// * `index` - The index to remove. + /// + /// # Returns + /// + /// * `bool` - `true` if an item was removed, `false` otherwise. bool removeAt(int index); + /// Removes the item at the given index without preserving the order of the array. + /// + /// # Arguments + /// + /// * `index` - The index to remove. + /// + /// # Returns + /// + /// * `bool` - `true` if an item was removed, `false` otherwise. bool fastRemoveAt(int index); + /// Creates a new array object static Array* create(); }; +/// A struct for storing pairs of string keys and various values. object class Dictionary { + /// the number of items in the dictionary. readonly common int count; + /// the keys of the items in the dictionary. readonly common VecStr keys; + /// Removes all the items from the dictionary. void clear(); + /// Creates instance of the "Dictionary". static Dictionary* create(); }; +/// A rectangle object with a left-bottom origin position and a size. value struct Rect { + /// the position of the origin of the rectangle. Vec2 origin; + /// the dimensions of the rectangle. Size size; + /// the x-coordinate of the origin of the rectangle. common float x; + /// the y-coordinate of the origin of the rectangle. common float y; + /// the width of the rectangle. common float width; + /// the height of the rectangle. common float height; + /// the left edge in x-axis of the rectangle. common float left; + /// the right edge in x-axis of the rectangle. common float right; + /// the x-coordinate of the center of the rectangle. common float centerX; + /// the y-coordinate of the center of the rectangle. common float centerY; + /// the bottom edge in y-axis of the rectangle. common float bottom; + /// the top edge in y-axis of the rectangle. common float top; + /// the lower bound (left-bottom) of the rectangle. common Vec2 lowerBound; + /// the upper bound (right-top) of the rectangle. common Vec2 upperBound; + /// Sets the properties of the rectangle. + /// + /// # Arguments + /// + /// * `x` - The x-coordinate of the origin of the rectangle. + /// * `y` - The y-coordinate of the origin of the rectangle. + /// * `width` - The width of the rectangle. + /// * `height` - The height of the rectangle. void set(float x, float y, float width, float height); + /// Checks if a point is inside the rectangle. + /// + /// # Arguments + /// + /// * `point` - The point to check, represented by a Vec2 object. + /// + /// # Returns + /// + /// * `bool` - Whether or not the point is inside the rectangle. bool containsPoint(Vec2 point) const; + /// Checks if the rectangle intersects with another rectangle. + /// + /// # Arguments + /// + /// * `rect` - The other rectangle to check for intersection with, represented by a Rect object. + /// + /// # Returns + /// + /// * `bool` - Whether or not the rectangles intersect. bool intersectsRect(Rect rect) const; + /// Checks if two rectangles are equal. + /// + /// # Arguments + /// + /// * `other` - The other rectangle to compare to, represented by a Rect object. + /// + /// # Returns + /// + /// * `bool` - Whether or not the two rectangles are equal. bool operator== @ equals(Rect other) const; + /// Creates a new rectangle object using a Vec2 object for the origin and a Size object for the size. + /// + /// # Arguments + /// + /// * `origin` - The origin of the rectangle, represented by a Vec2 object. + /// * `size` - The size of the rectangle, represented by a Size object. + /// + /// # Returns + /// + /// * `Rect` - A new rectangle object. static Rect create(Vec2 origin, Size size); + /// Gets a rectangle object with all properties set to 0. static outside Rect rect_get_zero @ zero(); }; +/// A struct representing an application. singleton class Application @ App { + /// the current passed frame number. readonly common uint32_t frame; + /// the size of the main frame buffer texture used for rendering. readonly common Size bufferSize; + /// the logic visual size of the screen. + /// The visual size only changes when application window size changes. + /// And it won't be affacted by the view buffer scaling factor. readonly common Size visualSize; + /// the ratio of the pixel density displayed by the device + /// Can be calculated as the size of the rendering buffer divided by the size of the application window. readonly common float devicePixelRatio; + /// the platform the game engine is running on. readonly common string platform; + /// the version string of the game engine. + /// Should be in format of "v0.0.0". readonly common string version; + /// the dependencies of the game engine. readonly common string deps; + /// the time in seconds since the last frame update. readonly common double deltaTime; + /// the elapsed time since current frame was started, in seconds. readonly common double elapsedTime; + /// the total time the game engine has been running until last frame ended, in seconds. + /// Should be a contant number when invoked in a same frame for multiple times. readonly common double totalTime; + /// the total time the game engine has been running until this field being accessed, in seconds. + /// Should be a increasing number when invoked in a same frame for multiple times. readonly common double runningTime; + /// a random number generated by a random number engine based on Mersenne Twister algorithm. + /// So that the random number generated by a same seed should be consistent on every platform. readonly common uint32_t rand; + /// the maximum valid frames per second the game engine is allowed to run at. + /// The max FPS is being inferred by the device screen max refresh rate. readonly common uint32_t maxFPS @ max_fps; + /// whether the game engine is running in debug mode. readonly boolean bool debugging; + /// the system locale string, in format like: `zh-Hans`, `en`. common string locale; + /// the theme color for Dora SSR. common Color themeColor; + /// the random number seed. common uint32_t seed; + /// the target frames per second the game engine is supposed to run at. + /// Only works when `fpsLimited` is set to true. common uint32_t targetFPS @ target_fps; + /// the application window size. + /// May differ from visual size due to the different DPIs of display devices. + /// Set `winSize` to `Size.zero` to toggle application window into full screen mode, + /// It is not available to set this property on platform Android and iOS. common Size winSize; + /// the application window position. + /// It is not available to set this property on platform Android and iOS. common Vec2 winPosition; + /// whether the game engine is limiting the frames per second. + /// Set `fpsLimited` to true, will make engine run in a busy loop to track the precise frame time to switch to the next frame. And this behavior can lead to 100% CPU usage. This is usually common practice on Windows PCs for better CPU usage occupation. But it also results in extra heat and power consumption. boolean bool fPSLimited @ fpsLimited; + /// whether the game engine is currently idled. + /// Set `idled` to true, will make game logic thread use a sleep time and going idled for next frame to come. Due to the imprecision in sleep time. This idled state may cause game engine over slept for a few frames to lost. + /// `idled` state can reduce some CPU usage. boolean bool idled; + /// Shuts down the game engine. + /// It is not working and acts as a dummy function for platform Android and iOS to follow the specification of how mobile platform applications should operate. void shutdown(); }; +/// A struct representing an entity for an ECS game system. object class Entity { + /// the number of all running entities. static readonly common uint32_t count; + /// the index of the entity. readonly common int index; + /// Clears all entities. static void clear(); + /// Removes a property of the entity. + /// + /// This function will trigger events for Observer objects. + /// + /// # Arguments + /// + /// * `key` - The name of the property to remove. void remove(string key); + /// Destroys the entity. void destroy(); + /// Creates a new entity. static Entity* create(); }; +/// A struct representing a group of entities in the ECS game systems. object class EntityGroup @ Group { + /// the number of entities in the group. readonly common int count; + /// Finds the first entity in the group that satisfies a predicate function. + /// + /// # Arguments + /// + /// * `func` - The predicate function to test each entity with. + /// + /// # Returns + /// + /// * `Option` - The first entity that satisfies the predicate, or None if no entity does. optional Entity* find(function func) const; + /// A method that creates a new group with the specified component names. + /// + /// # Arguments + /// + /// * `components` - A vector listing the names of the components to include in the group. + /// + /// # Returns + /// + /// * `Group` - The new group. static EntityGroup* create(VecStr components); }; +/// A struct representing an observer of entity changes in the game systems. object class EntityObserver @ Observer { + /// A method that creates a new observer with the specified component filter and action to watch for. + /// + /// # Arguments + /// + /// * `event` - The type of event to watch for. + /// * `components` - A vector listing the names of the components to filter entities by. + /// + /// # Returns + /// + /// * `Observer` - The new observer. static EntityObserver* create(EntityEvent event, VecStr components); }; +/// Helper struct for file path operations. struct Path { + /// Extracts the file extension from a given file path. + /// + /// # Example + /// + /// Input: "/a/b/c.TXT" Output: "txt" + /// + /// # Arguments + /// + /// * `path` - The input file path. + /// + /// # Returns + /// + /// * `String` - The extension of the input file. static string getExt(string path); + /// Extracts the parent path from a given file path. + /// + /// # Example + /// + /// Input: "/a/b/c.TXT" Output: "/a/b" + /// + /// # Arguments + /// + /// * `path` - The input file path. + /// + /// # Returns + /// + /// * `String` - The parent path of the input file. static string getPath(string path); + /// Extracts the file name without extension from a given file path. + /// + /// # Example + /// + /// Input: "/a/b/c.TXT" Output: "c" + /// + /// # Arguments + /// + /// * `path` - The input file path. + /// + /// # Returns + /// + /// * `String` - The name of the input file without extension. static string getName(string path); + /// Extracts the file name from a given file path. + /// + /// # Example + /// + /// Input: "/a/b/c.TXT" Output: "c.TXT" + /// + /// # Arguments + /// + /// * `path` - The input file path. + /// + /// # Returns + /// + /// * `String` - The name of the input file. static string getFilename(string path); + /// Computes the relative path from the target file to the input file. + /// + /// # Example + /// + /// Input: "/a/b/c.TXT", base: "/a" Output: "b/c.TXT" + /// + /// # Arguments + /// + /// * `path` - The input file path. + /// * `base` - The target file path. + /// + /// # Returns + /// + /// * `String` - The relative path from the input file to the target file. static string getRelative(string path, string target); + /// Changes the file extension in a given file path. + /// + /// # Example + /// + /// Input: "/a/b/c.TXT", "lua" Output: "/a/b/c.lua" + /// + /// # Arguments + /// + /// * `path` - The input file path. + /// * `new_ext` - The new file extension to replace the old one. + /// + /// # Returns + /// + /// * `String` - The new file path. static string replaceExt(string path, string newExt); + /// Changes the filename in a given file path. + /// + /// # Example + /// + /// Input: "/a/b/c.TXT", "d" Output: "/a/b/d.TXT" + /// + /// # Arguments + /// + /// * `path` - The input file path. + /// * `new_file` - The new filename to replace the old one. + /// + /// # Returns + /// + /// * `String` - The new file path. static string replaceFilename(string path, string newFile); -}; - + /// Joins the given segments into a new file path. + /// + /// # Example + /// + /// Input: "a", "b", "c.TXT" Output: "a/b/c.TXT" + /// + /// # Arguments + /// + /// * `segments` - The segments to be joined as a new file path. + /// + /// # Returns + /// + /// * `String` - The new file path. + static string concatVector @ concat(VecStr paths); +}; + +/// The `Content` is a static struct that manages file searching, +/// loading and other operations related to resources. singleton class Content { + /// an array of directories to search for resource files. common VecStr searchPaths; + /// the path to the directory containing read-only resources. readonly common string assetPath; + /// the path to the directory where files can be written. readonly common string writablePath; + /// Saves the specified content to a file with the specified filename. + /// + /// # Arguments + /// + /// * `filename` - The name of the file to save. + /// * `content` - The content to save to the file. + /// + /// # Returns + /// + /// * `bool` - `true` if the content saves to file successfully, `false` otherwise. bool save(string filename, string content); + /// Checks if a file with the specified filename exists. + /// + /// # Arguments + /// + /// * `filename` - The name of the file to check. + /// + /// # Returns + /// + /// * `bool` - `true` if the file exists, `false` otherwise. bool exist(string filename); + /// Creates a new directory with the specified path. + /// + /// # Arguments + /// + /// * `path` - The path of the directory to create. + /// + /// # Returns + /// + /// * `bool` - `true` if the directory was created, `false` otherwise. bool createFolder @ mkdir(string path); + /// Checks if the specified path is a directory. + /// + /// # Arguments + /// + /// * `path` - The path to check. + /// + /// # Returns + /// + /// * `bool` - `true` if the path is a directory, `false` otherwise. bool isFolder @ isdir(string path); + /// Copies the file or directory at the specified source path to the target path. + /// + /// # Arguments + /// + /// * `src_path` - The path of the file or directory to copy. + /// * `dst_path` - The path to copy the file or directory to. + /// + /// # Returns + /// + /// * `bool` - `true` if the file or directory was successfully copied to the target path, `false` otherwise. bool copy(string src, string dst); + /// Moves the file or directory at the specified source path to the target path. + /// + /// # Arguments + /// + /// * `src_path` - The path of the file or directory to move. + /// * `dst_path` - The path to move the file or directory to. + /// + /// # Returns + /// + /// * `bool` - `true` if the file or directory was successfully moved to the target path, `false` otherwise. bool move @ moveTo(string src, string dst); + /// Removes the file or directory at the specified path. + /// + /// # Arguments + /// + /// * `path` - The path of the file or directory to remove. + /// + /// # Returns + /// + /// * `bool` - `true` if the file or directory was successfully removed, `false` otherwise. bool remove(string path); + /// Gets the full path of a file with the specified filename. + /// + /// # Arguments + /// + /// * `filename` - The name of the file to get the full path of. + /// + /// # Returns + /// + /// * `String` - The full path of the file. string getFullPath(string filename); + /// Adds a new search path to the end of the list. + /// + /// # Arguments + /// + /// * `path` - The search path to add. void addSearchPath(string path); + /// Inserts a search path at the specified index. + /// + /// # Arguments + /// + /// * `index` - The index at which to insert the search path. + /// * `path` - The search path to insert. void insertSearchPath(int index, string path); + /// Removes the specified search path from the list. + /// + /// # Arguments + /// + /// * `path` - The search path to remove. void removeSearchPath(string path); + /// Clears the search path cache of the map of relative paths to full paths. void clearPathCache(); + /// Gets the names of all subdirectories in the specified directory. + /// + /// # Arguments + /// + /// * `path` - The path of the directory to search. + /// + /// # Returns + /// + /// * `Vec` - An array of the names of all subdirectories in the specified directory. VecStr getDirs(string path); + /// Gets the names of all files in the specified directory. + /// + /// # Arguments + /// + /// * `path` - The path of the directory to search. + /// + /// # Returns + /// + /// * `Vec` - An array of the names of all files in the specified directory. VecStr getFiles(string path); + /// Gets the names of all files in the specified directory and its subdirectories. + /// + /// # Arguments + /// + /// * `path` - The path of the directory to search. + /// + /// # Returns + /// + /// * `Vec` - An array of the names of all files in the specified directory and its subdirectories. VecStr getAllFiles(string path); + /// Asynchronously loads the content of the file with the specified filename. + /// + /// # Arguments + /// + /// * `filename` - The name of the file to load. + /// * `callback` - The function to call with the content of the file once it is loaded. + /// + /// # Returns + /// + /// * `String` - The content of the loaded file. void loadAsync(string filename, function callback); + /// Asynchronously copies a file or a folder from the source path to the destination path. + /// + /// # Arguments + /// + /// * `src` - The path of the file or folder to copy. + /// * `dst` - The destination path of the copied files. + /// + /// # Returns + /// + /// * `bool` - `true` if the file or folder was copied successfully, `false` otherwise. void copyAsync(string srcFile, string targetFile, function callback); + /// Asynchronously saves the specified content to a file with the specified filename. + /// + /// # Arguments + /// + /// * `filename` - The name of the file to save. + /// * `content` - The content to save to the file. + /// + /// # Returns + /// + /// * `bool` - `true` if the content was saved successfully, `false` otherwise. void saveAsync(string filename, string content, function callback); + /// Asynchronously compresses the specified folder to a ZIP archive with the specified filename. + /// + /// # Arguments + /// + /// * `folder_path` - The path of the folder to compress, should be under the asset writable path. + /// * `zip_file` - The name of the ZIP archive to create. + /// * `filter` - An optional function to filter the files to include in the archive. The function takes a filename as input and returns a boolean indicating whether to include the file. If not provided, all files will be included. + /// + /// # Returns + /// + /// * `bool` - `true` if the folder was compressed successfully, `false` otherwise. void zipAsync(string folderPath, string zipFile, function filter, function callback); + /// Asynchronously decompresses a ZIP archive to the specified folder. + /// + /// # Arguments + /// + /// * `zip_file` - The name of the ZIP archive to decompress, should be a file under the asset writable path. + /// * `folder_path` - The path of the folder to decompress to, should be under the asset writable path. + /// * `filter` - An optional function to filter the files to include in the archive. The function takes a filename as input and returns a boolean indicating whether to include the file. If not provided, all files will be included. + /// + /// # Returns + /// + /// * `bool` - `true` if the folder was decompressed successfully, `false` otherwise. void unzipAsync(string zipFile, string folderPath, function filter, function callback); }; +/// A scheduler that manages the execution of scheduled tasks. object class Scheduler { + /// the time scale factor for the scheduler. + /// This factor is applied to deltaTime that the scheduled functions will receive. common float timeScale; + /// the target frame rate (in frames per second) for a fixed update mode. + /// The fixed update will ensure a constant frame rate, and the operation handled in a fixed update can use a constant delta time value. + /// It is used for preventing weird behavior of a physics engine or synchronizing some states via network communications. common int fixedFPS @ fixed_fps; + /// Schedules a function to be called every frame. + /// + /// # Arguments + /// + /// * `handler` - The function to be called. It should take a single argument of type `f64`, which represents the delta time since the last frame. If the function returns `true`, it will not be called again. void schedule(function func); + /// Creates a new Scheduler object. static Scheduler* create(); }; +/// A struct for Camera object in the game engine. interface object class Camera { + /// the name of the Camera. readonly common string name; }; +/// A struct for 2D camera object in the game engine. object class Camera2D : public ICamera { + /// the rotation angle of the camera in degrees. common float rotation; + /// the factor by which to zoom the camera. If set to 1.0, the view is normal sized. If set to 2.0, items will appear double in size. common float zoom; + /// the position of the camera in the game world. common Vec2 position; + /// Creates a new Camera2D object with the given name. + /// + /// # Arguments + /// + /// * `name` - The name of the Camera2D object. + /// + /// # Returns + /// + /// * `Camera2D` - A new instance of the Camera2D object. static Camera2D* create(string name); }; +/// A struct for an orthographic camera object in the game engine. object class CameraOtho : public ICamera { + /// the position of the camera in the game world. common Vec2 position; + /// Creates a new CameraOtho object with the given name. + /// + /// # Arguments + /// + /// * `name` - The name of the CameraOtho object. + /// + /// # Returns + /// + /// * `CameraOtho` - A new instance of the CameraOtho object. static CameraOtho* create(string name); }; +/// A struct representing a shader pass. object class Pass { + /// whether this Pass should be a grab pass. + /// A grab pass will render a portion of game scene into a texture frame buffer. + /// Then use this texture frame buffer as an input for next render pass. boolean bool grabPass; + /// Sets the value of shader parameters. + /// + /// # Arguments + /// + /// * `name` - The name of the parameter to set. + /// * `var` - The numeric value to set. void set @ set(string name, float var); + /// Sets the values of shader parameters. + /// + /// # Arguments + /// + /// * `name` - The name of the parameter to set. + /// * `var1` - The first numeric value to set. + /// * `var2` - An optional second numeric value to set. + /// * `var3` - An optional third numeric value to set. + /// * `var4` - An optional fourth numeric value to set. void set @ setVec4(string name, float var1, float var2, float var3, float var4); + /// Another function that sets the values of shader parameters. + /// + /// Works the same as: + /// pass.set("varName", color.r / 255.0, color.g / 255.0, color.b / 255.0, color.opacity); + /// + /// # Arguments + /// + /// * `name` - The name of the parameter to set. + /// * `var` - The Color object to set. void set @ setColor(string name, Color var); + /// Creates a new Pass object. + /// + /// # Arguments + /// + /// * `vert_shader` - The vertex shader in binary form file string. + /// * `frag_shader` - The fragment shader file string. A shader file string must be one of the formats: + /// * "builtin:" + theBuiltinShaderName + /// * "Shader/compiled_shader_file.bin" + /// + /// # Returns + /// + /// * `Pass` - A new Pass object. static Pass* create(string vertShader, string fragShader); }; +/// A struct for managing multiple render pass objects. +/// Effect objects allow you to combine multiple passes to create more complex shader effects. interface object class Effect { + /// Adds a Pass object to this Effect. + /// + /// # Arguments + /// + /// * `pass` - The Pass object to add. void add(Pass* pass); + /// Retrieves a Pass object from this Effect by index. + /// + /// # Arguments + /// + /// * `index` - The index of the Pass object to retrieve. + /// + /// # Returns + /// + /// * `Pass` - The Pass object at the given index. outside optional Pass* effect_get_pass @ get(size_t index) const; + /// Removes all Pass objects from this Effect. void clear(); + /// A method that allows you to create a new Effect object. + /// + /// # Arguments + /// + /// * `vert_shader` - The vertex shader file string. + /// * `frag_shader` - The fragment shader file string. A shader file string must be one of the formats: + /// * "builtin:" + theBuiltinShaderName + /// * "Shader/compiled_shader_file.bin" + /// + /// # Returns + /// + /// * `Effect` - A new Effect object. static Effect* create(string vertShader, string fragShader); }; +/// A struct that is a specialization of Effect for rendering 2D sprites. object class SpriteEffect : public IEffect { + /// A method that allows you to create a new SpriteEffect object. + /// + /// # Arguments + /// + /// * `vert_shader` - The vertex shader file string. + /// * `frag_shader` - The fragment shader file string. A shader file string must be one of the formats: + /// * "builtin:" + theBuiltinShaderName + /// * "Shader/compiled_shader_file.bin" + /// + /// # Returns + /// + /// * `SpriteEffect` - A new SpriteEffect object. static SpriteEffect* create(string vertShader, string fragShader); }; +/// A struct manages the game scene trees and provides access to root scene nodes for different game uses. singleton class Director { + /// the background color for the game world. common Color clearColor; + /// the game scheduler which is used for scheduling tasks like animations and gameplay events. common Scheduler* scheduler; + /// the root node for 2D user interface elements like buttons and labels. readonly common Node* uI @ ui; + /// the root node for 3D user interface elements with 3D projection effect. readonly common Node* uI3D @ ui_3d; + /// the root node for the starting point of a game. readonly common Node* entry; + /// the root node for post-rendering scene tree. readonly common Node* postNode; + /// the system scheduler which is used for low-level system tasks, should not put any game logic in it. readonly common Scheduler* systemScheduler; + /// the scheduler used for processing post game logic. readonly common Scheduler* postScheduler; + /// the current active camera in Director's camera stack. readonly common Camera* currentCamera; + /// Adds a new camera to Director's camera stack and sets it to the current camera. + /// + /// # Arguments + /// + /// * `camera` - The camera to add. void pushCamera(Camera* camera); + /// Removes the current camera from Director's camera stack. void popCamera(); + /// Removes a specified camera from Director's camera stack. + /// + /// # Arguments + /// + /// * `camera` - The camera to remove. + /// + /// # Returns + /// + /// * `bool` - `true` if the camera was removed, `false` otherwise. bool removeCamera(Camera* camera); + /// Removes all cameras from Director's camera stack. void clearCamera(); + /// Cleans up all resources managed by the Director, including scene trees and cameras. void cleanup(); }; +/// A struct that provides access to the 3D graphic view. singleton class View { + /// the size of the view in pixels. readonly common Size size; + /// the standard distance of the view from the origin. readonly common float standardDistance; + /// the aspect ratio of the view. readonly common float aspectRatio; + /// the distance to the near clipping plane. common float nearPlaneDistance; + /// the distance to the far clipping plane. common float farPlaneDistance; + /// the field of view of the view in degrees. common float fieldOfView; + /// the scale factor of the view. common float scale; + /// the post effect applied to the view. optional common SpriteEffect* postEffect; + /// Removes the post effect applied to the view. outside void view_set_post_effect_nullptr @ set_post_effect_null(); + /// whether or not vertical sync is enabled. boolean bool vSync @ vsync; }; value class ActionDef { }; +/// Represents an action that can be run on a node. object class Action { + /// the duration of the action. readonly common float duration; + /// whether the action is currently running. readonly boolean bool running; + /// whether the action is currently paused. readonly boolean bool paused; + /// whether the action should be run in reverse. boolean bool reversed; + /// the speed at which the action should be run. + /// Set to 1.0 to get normal speed, Set to 2.0 to get two times faster. common float speed; + /// Pauses the action. void pause(); + /// Resumes the action. void resume(); + /// Updates the state of the Action. + /// + /// # Arguments + /// + /// * `elapsed` - The amount of time in seconds that has elapsed to update action to. + /// * `reversed` - Whether or not to update the Action in reverse. void updateTo(float elapsed, bool reversed); - static outside ActionDef action_def_prop @ prop(float duration, float start, float stop, - Property prop, EaseType easing); - static outside ActionDef action_def_tint @ tint(float duration, Color3 start, Color3 stop, - EaseType easing); - static outside ActionDef action_def_roll @ roll(float duration, float start, float stop, - EaseType easing); + /// Creates a new Action object to change a property of a node. + /// + /// # Arguments + /// + /// * `duration` - The duration of the action. + /// * `start` - The starting value of the property. + /// * `stop` - The ending value of the property. + /// * `prop` - The property to change. + /// * `easing` - The easing function to use. + /// + /// # Returns + /// + /// * `Action` - A new Action object. + static outside ActionDef action_def_prop @ prop(float duration, float start, float stop, Property prop, EaseType easing); + /// Creates a new Action object to change the color of a node. + /// + /// # Arguments + /// + /// * `duration` - The duration of the action. + /// * `start` - The starting color. + /// * `stop` - The ending color. + /// * `easing` - The easing function to use. + /// + /// # Returns + /// + /// * `Action` - A new Action object. + static outside ActionDef action_def_tint @ tint(float duration, Color3 start, Color3 stop, EaseType easing); + /// Creates a new Action object to rotate a node by smallest angle. + /// + /// # Arguments + /// + /// * `duration` - The duration of the action. + /// * `start` - The starting angle. + /// * `stop` - The ending angle. + /// * `easing` - The easing function to use. + /// + /// # Returns + /// + /// * `Action` - A new Action object. + static outside ActionDef action_def_roll @ roll(float duration, float start, float stop, EaseType easing); + /// Creates a new Action object to run a group of actions in parallel. + /// + /// # Arguments + /// + /// * `defs` - The actions to run in parallel. + /// + /// # Returns + /// + /// * `Action` - A new Action object. static outside ActionDef action_def_spawn @ spawn(VecActionDef defs); + /// Creates a new Action object to run a group of actions in sequence. + /// + /// # Arguments + /// + /// * `defs` - The actions to run in sequence. + /// + /// # Returns + /// + /// * `Action` - A new Action object. static outside ActionDef action_def_sequence @ sequence(VecActionDef defs); + /// Creates a new Action object to delay the execution of following action. + /// + /// # Arguments + /// + /// * `duration` - The duration of the delay. + /// + /// # Returns + /// + /// * `Action` - A new Action object. static outside ActionDef action_def_delay @ delay(float duration); + /// Creates a new Action object to show a node. static outside ActionDef action_def_show @ show(); + /// Creates a new Action object to hide a node. static outside ActionDef action_def_hide @ hide(); + /// Creates a new Action object to emit an event. + /// + /// # Arguments + /// + /// * `eventName` - The name of the event to emit. + /// * `msg` - The message to send with the event. + /// + /// # Returns + /// + /// * `Action` - A new Action object. static outside ActionDef action_def_emit @ event(string eventName, string msg); - static outside ActionDef action_def_move @ move_to(float duration, Vec2 start, Vec2 stop, - EaseType easing); - static outside ActionDef action_def_scale @ scale(float duration, float start, float stop, - EaseType easing); -}; - + /// Creates a new Action object to move a node. + /// + /// # Arguments + /// + /// * `duration` - The duration of the action. + /// * `start` - The starting position. + /// * `stop` - The ending position. + /// * `easing` - The easing function to use. + /// + /// # Returns + /// + /// * `Action` - A new Action object. + static outside ActionDef action_def_move @ move_to(float duration, Vec2 start, Vec2 stop, EaseType easing); + /// Creates a new Action object to scale a node. + /// + /// # Arguments + /// + /// * `duration` - The duration of the action. + /// * `start` - The starting scale. + /// * `stop` - The ending scale. + /// * `easing` - The easing function to use. + /// + /// # Returns + /// + /// * `Action` - A new Action object. + static outside ActionDef action_def_scale @ scale(float duration, float start, float stop, EaseType easing); +}; + +/// A grabber which is used to render a part of the scene to a texture +/// by a grid of vertices. object class Grabber { + /// the camera used to render the texture. optional common Camera* camera; + /// the sprite effect applied to the texture. optional common SpriteEffect* effect; + /// the blend function applied to the texture. common BlendFunc blendFunc; + /// the clear color used to clear the texture. common Color clearColor; + /// Sets the position of a vertex in the grabber grid. + /// + /// # Arguments + /// + /// * `x` - The x-index of the vertex in the grabber grid. + /// * `y` - The y-index of the vertex in the grabber grid. + /// * `pos` - The new position of the vertex, represented by a Vec2 object. + /// * `z` - An optional argument representing the new z-coordinate of the vertex. void setPos(int x, int y, Vec2 pos, float z); + /// Gets the position of a vertex in the grabber grid. + /// + /// # Arguments + /// + /// * `x` - The x-index of the vertex in the grabber grid. + /// * `y` - The y-index of the vertex in the grabber grid. + /// + /// # Returns + /// + /// * `Vec2` - The position of the vertex. Vec2 getPos(int x, int y) const; + /// Sets the color of a vertex in the grabber grid. + /// + /// # Arguments + /// + /// * `x` - The x-index of the vertex in the grabber grid. + /// * `y` - The y-index of the vertex in the grabber grid. + /// * `color` - The new color of the vertex, represented by a Color object. void setColor(int x, int y, Color color); + /// Gets the color of a vertex in the grabber grid. + /// + /// # Arguments + /// + /// * `x` - The x-index of the vertex in the grabber grid. + /// * `y` - The y-index of the vertex in the grabber grid. + /// + /// # Returns + /// + /// * `Color` - The color of the vertex. Color getColor(int x, int y) const; + /// Sets the UV coordinates of a vertex in the grabber grid. + /// + /// # Arguments + /// + /// * `x` - The x-index of the vertex in the grabber grid. + /// * `y` - The y-index of the vertex in the grabber grid. + /// * `offset` - The new UV coordinates of the vertex, represented by a Vec2 object. void moveUV @ move_uv(int x, int y, Vec2 offset); }; +/// Struct used for building a hierarchical tree structure of game objects. interface object class Node { + /// the order of the node in the parent's children array. common int order; + /// the rotation angle of the node in degrees. common float angle; + /// the X-axis rotation angle of the node in degrees. common float angleX; + /// the Y-axis rotation angle of the node in degrees. common float angleY; + /// the X-axis scale factor of the node. common float scaleX; + /// the Y-axis scale factor of the node. common float scaleY; + /// the X-axis position of the node. common float x; + /// the Y-axis position of the node. common float y; + /// the Z-axis position of the node. common float z; + /// the position of the node as a Vec2 object. common Vec2 position; + /// the X-axis skew angle of the node in degrees. common float skewX; + /// the Y-axis skew angle of the node in degrees. common float skewY; + /// whether the node is visible. boolean bool visible; + /// the anchor point of the node as a Vec2 object. common Vec2 anchor; + /// the width of the node. common float width; + /// the height of the node. common float height; + /// the size of the node as a Size object. common Size size; + /// the tag of the node as a string. common string tag; + /// the opacity of the node, should be 0 to 1.0. common float opacity; + /// the color of the node as a Color object. common Color color; + /// the color of the node as a Color3 object. common Color3 color3; + /// whether to pass the opacity value to child nodes. boolean bool passOpacity; + /// whether to pass the color value to child nodes. boolean bool passColor3; + /// the target node acts as a parent node for transforming this node. optional common Node* transformTarget; + /// the scheduler used for scheduling update and action callbacks. common Scheduler* scheduler; + /// the children of the node as an Array object, could be None. optional readonly common Array* children; + /// the parent of the node, could be None. optional readonly common Node* parent; + /// the bounding box of the node as a Rect object. readonly common Rect boundingBox; + /// whether the node is currently running in a scene tree. readonly boolean bool running; + /// whether the node is currently scheduling a function or a coroutine for updates. readonly boolean bool scheduled; + /// the number of actions currently running on the node. readonly common int actionCount; + /// additional data stored on the node as a Dictionary object. readonly common Dictionary* userData @ data; + /// whether touch events are enabled on the node. boolean bool touchEnabled; + /// whether the node should swallow touch events. boolean bool swallowTouches; + /// whether the node should swallow mouse wheel events. boolean bool swallowMouseWheel; + /// whether keyboard events are enabled on the node. boolean bool keyboardEnabled; + /// whether controller events are enabled on the node. boolean bool controllerEnabled; + /// whether to group the node's rendering with all its recursive children. boolean bool renderGroup; + /// the rendering order number for group rendering. Nodes with lower rendering orders are rendered earlier. common int renderOrder; - + /// Adds a child node to the current node. + /// + /// # Arguments + /// + /// * `child` - The child node to add. + /// * `order` - The drawing order of the child node. + /// * `tag` - The tag of the child node. void addChild @ addChildWithOrderTag(Node* child, int order, string tag); + /// Adds a child node to the current node. + /// + /// # Arguments + /// + /// * `child` - The child node to add. + /// * `order` - The drawing order of the child node. void addChild @ addChildWithOrder(Node* child, int order); + /// Adds a child node to the current node. + /// + /// # Arguments + /// + /// * `child` - The child node to add. void addChild(Node* child); - + /// Adds the current node to a parent node. + /// + /// # Arguments + /// + /// * `parent` - The parent node to add the current node to. + /// * `order` - The drawing order of the current node. + /// * `tag` - The tag of the current node. + /// + /// # Returns + /// + /// * `Node` - The current node. Node* addTo @ addToWithOrderTag(Node* parent, int order, string tag); + /// Adds the current node to a parent node. + /// + /// # Arguments + /// + /// * `parent` - The parent node to add the current node to. + /// * `order` - The drawing order of the current node. + /// + /// # Returns + /// + /// * `Node` - The current node. Node* addTo @ addToWithOrder(Node* parent, int order); + /// Adds the current node to a parent node. + /// + /// # Arguments + /// + /// * `parent` - The parent node to add the current node to. + /// + /// # Returns + /// + /// * `Node` - The current node. Node* addTo(Node* parent); - + /// Removes a child node from the current node. + /// + /// # Arguments + /// + /// * `child` - The child node to remove. + /// * `cleanup` - Whether to cleanup the child node. void removeChild(Node* child, bool cleanup); + /// Removes a child node from the current node by tag. + /// + /// # Arguments + /// + /// * `tag` - The tag of the child node to remove. + /// * `cleanup` - Whether to cleanup the child node. void removeChildByTag(string tag, bool cleanup); + /// Removes all child nodes from the current node. + /// + /// # Arguments + /// + /// * `cleanup` - Whether to cleanup the child nodes. void removeAllChildren(bool cleanup); + /// Removes the current node from its parent node. + /// + /// # Arguments + /// + /// * `cleanup` - Whether to cleanup the current node. void removeFromParent(bool cleanup); + /// Moves the current node to a new parent node without triggering node events. + /// + /// # Arguments + /// + /// * `parent` - The new parent node to move the current node to. void moveToParent(Node* parent); - + /// Cleans up the current node. void cleanup(); - + /// Gets a child node by tag. + /// + /// # Arguments + /// + /// * `tag` - The tag of the child node to get. + /// + /// # Returns + /// + /// * `Option` - The child node, or `None` if not found. optional Node* getChildByTag(string tag); - + /// Schedules a function to be called every frame. + /// + /// # Arguments + /// + /// * `func` - The function to be called. If the function returns `true`, it will not be called again. void schedule(function func); + /// Unschedules the current node's scheduled function. void unschedule(); - + /// Converts a point from world space to node space. + /// + /// # Arguments + /// + /// * `world_point` - The point in world space, represented by a Vec2 object. + /// + /// # Returns + /// + /// * `Vec2` - The converted point in world space. Vec2 convertToNodeSpace(Vec2 worldPoint); + /// Converts a point from node space to world space. + /// + /// # Arguments + /// + /// * `node_point` - The point in node space, represented by a Vec2 object. + /// + /// # Returns + /// + /// * `Vec2` - The converted point in world space. Vec2 convertToWorldSpace(Vec2 nodePoint); + /// Converts a point from node space to world space. + /// + /// # Arguments + /// + /// * `node_point` - The point in node space, represented by a Vec2 object. + /// + /// # Returns + /// + /// * `Vec2` - The converted point in world space. void convertToWindowSpace(Vec2 nodePoint, function callback); - + /// Calls the given function for each child node of this node. + /// + /// # Arguments + /// + /// * `func` - The function to call for each child node. The function should return a boolean value indicating whether to continue the iteration. Return true to stop iteration. + /// + /// # Returns + /// + /// * `bool` - `false` if all children have been visited, `true` if the iteration was interrupted by the function. bool eachChild(function func); + /// Traverses the node hierarchy starting from this node and calls the given function for each visited node. The nodes without `TraverseEnabled` flag are not visited. + /// + /// # Arguments + /// + /// * `func` - The function to call for each visited node. The function should return a boolean value indicating whether to continue the traversal. Return true to stop iteration. + /// + /// # Returns + /// + /// * `bool` - `false` if all nodes have been visited, `true` if the traversal was interrupted by the function. bool traverse(function func); + /// Traverses the entire node hierarchy starting from this node and calls the given function for each visited node. + /// + /// # Arguments + /// + /// * `func` - The function to call for each visited node. The function should return a boolean value indicating whether to continue the traversal. + /// + /// # Returns + /// + /// * `bool` - `false` if all nodes have been visited, `true` if the traversal was interrupted by the function. bool traverseAll(function func); - + /// Runs an action defined by the given action definition on this node. + /// + /// # Arguments + /// + /// * `action_def` - The action definition to run. + /// + /// # Returns + /// + /// * `f64` - The duration of the newly running action in seconds. outside optional Action* node_run_action_def @ run_action(ActionDef def); + /// Stops all actions running on this node. void stopAllActions(); - outside optional Action* node_perform_def @ perform(ActionDef def); + /// Runs an action defined by the given action definition right after clearing all the previous running actions. + /// + /// # Arguments + /// + /// * `action_def` - The action definition to run. + /// + /// # Returns + /// + /// * `f64` - The duration of the newly running action in seconds. + outside optional Action* node_perform_def @ perform(ActionDef actionDef); + /// Stops the given action running on this node. + /// + /// # Arguments + /// + /// * `action` - The action to stop. void stopAction(Action* action); - + /// Vertically aligns all child nodes within the node using the given size and padding. + /// + /// # Arguments + /// + /// * `padding` - The amount of padding to use between each child node. + /// + /// # Returns + /// + /// * `Size` - The size of the node after alignment. Size alignItemsVertically(float padding); + /// Vertically aligns all child nodes within the node using the given size and padding. + /// + /// # Arguments + /// + /// * `size` - The size to use for alignment. + /// * `padding` - The amount of padding to use between each child node. + /// + /// # Returns + /// + /// * `Size` - The size of the node after alignment. Size alignItemsVertically @ alignItemsVerticallyWithSize(Size size, float padding); + /// Horizontally aligns all child nodes within the node using the given size and padding. + /// + /// # Arguments + /// + /// * `padding` - The amount of padding to use between each child node. + /// + /// # Returns + /// + /// * `Size` - The size of the node after alignment. Size alignItemsHorizontally(float padding); + /// Horizontally aligns all child nodes within the node using the given size and padding. + /// + /// # Arguments + /// + /// * `size` - The size to hint for alignment. + /// * `padding` - The amount of padding to use between each child node. + /// + /// # Returns + /// + /// * `Size` - The size of the node after alignment. Size alignItemsHorizontally @ alignItemsHorizontallyWithSize(Size size, float padding); + /// Aligns all child nodes within the node using the given size and padding. + /// + /// # Arguments + /// + /// * `padding` - The amount of padding to use between each child node. + /// + /// # Returns + /// + /// * `Size` - The size of the node after alignment. Size alignItems(float padding); + /// Aligns all child nodes within the node using the given size and padding. + /// + /// # Arguments + /// + /// * `size` - The size to use for alignment. + /// * `padding` - The amount of padding to use between each child node. + /// + /// # Returns + /// + /// * `Size` - The size of the node after alignment. Size alignItems @ alignItemsWithSize(Size size, float padding); + /// Moves and changes child nodes' visibility based on their position in parent's area. + /// + /// # Arguments + /// + /// * `delta` - The distance to move its children, represented by a Vec2 object. void moveAndCullItems(Vec2 delta); - + /// Attaches the input method editor (IME) to the node. + /// Makes node recieving "AttachIME", "DetachIME", "TextInput", "TextEditing" events. void attachIME @ attach_ime(); + /// Detaches the input method editor (IME) from the node. void detachIME @ detach_ime(); - + /// Creates a texture grabber for the specified node. + /// + /// # Returns + /// + /// * `Grabber` - A Grabber object. outside Grabber* node_start_grabbing @ grab(); + /// Creates a texture grabber for the specified node with a specified grid size. + /// + /// # Arguments + /// + /// * `grid_x` - The number of horizontal grid cells to divide the grabber into. + /// * `grid_y` - The number of vertical grid cells to divide the grabber into. + /// + /// # Returns + /// + /// * `Grabber` - A Grabber object. Grabber* grab @ grabWithSize(uint32_t gridX, uint32_t gridY); + /// Removes the texture grabber for the specified node. outside void node_stop_grabbing @ stop_grab(); - + /// Removes the transform target for the specified node. outside void node_set_transform_target_nullptr @ set_transform_target_null(); - - bool slot(string name, function func); - bool gslot(string name, function func); - + /// Associates the given handler function with the node event. + /// + /// # Arguments + /// + /// * `event_name` - The name of the node event. + /// * `handler` - The handler function to associate with the node event. + void slot(string eventName, function func); + /// Associates the given handler function with a global event. + /// + /// # Arguments + /// + /// * `event_name` - The name of the global event. + /// * `handler` - The handler function to associate with the event. + void gslot(string eventName, function func); + /// Creates a new instance of the `Node` struct. static Node* create(); }; diff --git a/Tools/RustWasmGen/gen.yue b/Tools/RustWasmGen/gen.yue index 41b1ff39d..593abba60 100755 --- a/Tools/RustWasmGen/gen.yue +++ b/Tools/RustWasmGen/gen.yue @@ -493,7 +493,7 @@ basicTypes = lastPos = 1 -Newline = Cmt P"\n", (str, pos)-> +Newline = Cmt P"\r"^-1 * P"\n", (str, pos)-> lastPos = pos true @@ -515,6 +515,10 @@ MethodLabel = C(P"static")^-1 * White * C(P"outside")^-1 * White * C(P"optional" Type = C (Indent * White * P"::" * White)^0 * Indent * (White * P"*")^-1 +Doc = C P"///" * (-Newline * P(1))^0 + +Docs = White * Ct (Doc * White)^0 + mark = (name) -> (...) -> {name, ...} Param = P { @@ -523,11 +527,10 @@ Param = P { Func: Ct P"function<" * White * Type * White * Ct P"(" * White * (V"Param" * (White * P"," * White * V"Param")^0 * White)^-1 * P")" * White * P">" } -Method = Ct(White * MethodLabel) * White * Type * White * (C(P"operator==") + Name) * White * (P"@" * White * Name + Cc false) * White * Ct(P"(" * White * (Param * (White * P"," * White * Param)^0 * White)^-1 * P")") * White * C(P"const")^-1 * White * P";" / mark"method" - -Field = Ct(White * FieldLabel) * White * Type * White * Name * White * (P"@" * White * Name + Cc false) * White * P";" / mark"field" +Method = Docs * Ct(White * MethodLabel) * White * Type * White * (C(P"operator==") + Name) * White * (P"@" * White * Name + Cc false) * White * Ct(P"(" * White * (Param * (White * P"," * White * Param)^0 * White)^-1 * P")") * White * C(P"const")^-1 * White * P";" / mark"method" -Class = White * Ct Ct(White * ClassLabel) * White * (P"class" + P"struct") * White * Ct(Name * White * (P"@" * White * Name + Cc false) * White * (P":" * White * (P"public")^-1 * White * ClassName * White + Cc false)) * +Field = Docs * Ct(White * FieldLabel) * White * Type * White * Name * White * (P"@" * White * Name + Cc false) * White * P";" / mark"field" +Class = White * Ct Docs * Ct(White * ClassLabel) * White * (P"class" + P"struct") * White * Ct(Name * White * (P"@" * White * Name + Cc false) * White * (P":" * White * (P"public")^-1 * White * ClassName * White + Cc false)) * P"{" * Ct (White * (Method + Field))^0 * White * P"}" * White * P";" @@ -610,7 +613,7 @@ else elseif not cls table.remove moduleScopes, #moduleScopes continue - {_, clsNames} = cls + [_, _, clsNames] = cls {clsName, clsNewName} = clsNames clsNewName or= clsName if #moduleScopes > 0 @@ -638,8 +641,8 @@ else table.concat(moduleScopes, "::") .. "::" else "" - {clsLabels, clsNames, clsBody} = cls - {clsName, clsNewName, clsParent} = clsNames + [clsDocs, clsLabels, clsNames, clsBody] = cls + [clsName, clsNewName, clsParent] = clsNames if clsParent clsParent = nameMap[clsParent] or clsParent clsNewName or= clsName @@ -682,6 +685,8 @@ else rustBinding[] = "use crate::dora::#{inherit};" rustBinding[] = "impl #{inherit} for #{clsNewName} { }" cppLink[] = "static void link#{table.concat moduleScopes}#{cppModuleName}(wasm3::module3& mod) {" + if #clsDocs > 0 + rustBinding[] = table.concat clsDocs, '\n' rustBinding[] = if isTrait if isObject rustBinding[] = "pub struct #{clsNewName} { raw: i64 } @@ -733,10 +738,10 @@ impl I#{clsNewName} for #{clsNewName} { }" pub fn raw(&self) -> i64 { self.raw }" for clsItem in *clsBody pub = isTrait and "" or "pub " - {itemType} = clsItem + [itemType,] = clsItem switch itemType when "field" - {_, labels, dataType, name, newName} = clsItem + [_, docs, labels, dataType, name, newName] = clsItem funcName = name\sub(1, 1)\lower! .. name\sub 2 funcName = table.concat [sub\lower! for sub in funcName\gsub("%u", "_%1")\gmatch "[^_]*"], "_" funcNewName = newName or name @@ -773,9 +778,12 @@ impl I#{clsNewName} for #{clsNewName} { }" if not isReadonly and not interfaces[rustName] objectUsed = nil if rustType - {rt, cast, castFrom, rtTypeIn, rtTypeOut, rtCast, rtCastFrom} = rustType + [rt, cast, castFrom, rtTypeIn, rtTypeOut, rtCast, rtCastFrom] = rustType cppType = cppTypes[rt] if not isReadonly + if #docs > 0 + text = table.concat docs, '\n\t' + rustBinding[] = '\t' .. text\sub(1, 4) .. 'Sets' .. text\sub(4) setFunc = switch fieldType when "primitive" "#{name} = #{cast 'var'}" @@ -803,6 +811,9 @@ impl I#{clsNewName} for #{clsNewName} { }" slfDecl = isStatic and "" or "&mut self, " slf = isStatic and "" or "self.raw(), " "\t#{pub}fn #{rustSetterName}(#{slfDecl}var: #{rtTypeIn or rt}) {\n\t\tunsafe { #{cppSetterName}(#{slf}#{rtCast and rtCast('var') or 'var'}) };\n\t}" + if #docs > 0 + text = table.concat docs, '\n\t' + rustBinding[] = '\t' .. text\sub(1, 4) .. 'Gets' .. text\sub(4) getFunc, prefix = switch fieldType when "primitive" "#{name}", "get" @@ -840,7 +851,7 @@ impl I#{clsNewName} for #{clsNewName} { }" error "\"#{dataType}\" is not supported." when "method" funcCount += 1 - {_, labels, dataType, name, newName, args, constFlag} = clsItem + [_, docs, labels, dataType, name, newName, args, constFlag] = clsItem funcNewName = newName or name funcName = name\sub(1, 1)\lower! .. name\sub 2 funcName = table.concat [sub\lower! for sub in funcName\gsub("%u", "_%1")\gmatch "[^_]*"], "_" @@ -877,13 +888,13 @@ impl I#{clsNewName} for #{clsNewName} { }" rustName = nameMap[dataTypeName] or dataTypeName rustType = getObjectType dataTypeName, rustName, isCreate, isOptional if rustType - {rt, cast, castFrom, _, rtTypeOut, _, rtCastFrom} = rustType + [rt, cast, castFrom, _, rtTypeOut, _, rtCastFrom] = rustType if isOptional and not rtTypeOut\match "^Option<" rtTypeOut = "Option<#{rtTypeOut}>" cppType = cppTypes[rt] ?? "void" funcArgCount = -1 argItems = for arg in *args - {argKind, argType, argName} = arg + [argKind, argType, argName] = arg argName = toCamelCase argName switch argKind when "variable" @@ -894,25 +905,25 @@ impl I#{clsNewName} for #{clsNewName} { }" rustTypeA = getObjectType argTypeName, rustName objectUsed = nil unless interfaces[rustName] if rustTypeA - {rtA, castA, _, rtTypeInA, _, rtCastA} = rustTypeA + [rtA, castA, _, rtTypeInA, _, rtCastA] = rustTypeA cppTypeA = cppTypes[rtA] - { + [ "#{cppTypeA} #{argName}" (argType == cppTypeA and argName or castA argName) "#{argName}: #{rtA}" "#{argName}: #{rtTypeInA or rtA}" "#{rtCastA and rtCastA(argName) or argName}" - } + ] else error "\"#{argType}\" is not supported." when "callback" funcArgCount += 1 fnArgId = funcArgCount == 0 and '' or tostring funcArgCount - {_, func, fname} = arg + [_, func, fname] = arg fname = toCamelCase fname - {freturnType, fargs} = func + [freturnType, fargs] = func items = for farg in *fargs - {fargKind, fargType, fargName} = farg + [fargKind, fargType, fargName] = farg if fargKind ~= "variable" error "\"#{fargKind}\" is not supported in function argument." frustType = basicTypes[fargType] @@ -925,42 +936,42 @@ impl I#{clsNewName} for #{clsNewName} { }" fcppType = callbackDefs[fargType] or fargType switch fargType\match "[^ \t*]+" when "Event" - { + [ "Event* #{fargName}" "\t\t#{fargName}->pushArgsToWasm(args#{fnArgId});" "&mut crate::dora::CallStack" "&mut stack#{fnArgId}" - } + ] when "Platformer::Behavior::Blackboard", "Platformer::UnitAction" - { + [ "#{fcppType}* #{fargName}" "\t\targs#{fnArgId}->push(r_cast(#{fargName}));" frtTypeIn fpopArg fnArgId - } + ] when "DBRecord" - { + [ "#{fcppType}& #{fargName}" "\t\targs#{fnArgId}->push(r_cast(new DBRecord{std::move(#{fargName})}));" frtTypeIn fpopArg fnArgId - } + ] when "MLQState", "MLQAction" - { + [ "#{fcppType} #{fargName}" "\t\targs#{fnArgId}->push(s_cast(#{fargName}));" frtTypeIn fpopArg fnArgId - } + ] when nil error "\"#{fargType}\" is not supported." else - { + [ "#{fcppType} #{fargName}" "\t\targs#{fnArgId}->push(#{fargName});" frtTypeIn fpopArg fnArgId - } + ] argPassed = #items > 0 cppArgDef = table.concat [item[1] for item in *items], ", " cppArgPass = table.concat [item[2] for item in *items], "\n" @@ -1053,7 +1064,11 @@ impl I#{clsNewName} for #{clsNewName} { }" rustBinding[] = if isSingleton rtOut = rtTypeOut or rt item = "#{cppFuncName}(#{argRtPass})" - "\t#{pub}fn #{rustFuncName}(#{argRtInDefs})#{rtOut and ' -> ' .. rtOut or ''} {\n#{argRtPrepare}\t\tunsafe { #{prefix}#{rtCastFrom and rtCastFrom(item, isOptional) or item}; }\n\t}" + docText = if #docs > 0 + '\t' .. table.concat(docs, '\n\t') .. '\n' + else + '' + "#{docText}\t#{pub}fn #{rustFuncName}(#{argRtInDefs})#{rtOut and ' -> ' .. rtOut or ''} {\n#{argRtPrepare}\t\tunsafe { #{prefix}#{rtCastFrom and rtCastFrom(item, isOptional) or item}; }\n\t}" else rtOut = rtTypeOut or rt slfParam = isConst and "&self" or "&mut self" @@ -1063,12 +1078,21 @@ impl I#{clsNewName} for #{clsNewName} { }" if slf ~= "" then argRtPass = slf .. (argRtPass ~= "" and ", " or "") .. argRtPass item = "#{cppFuncName}(#{argRtPass})" if funcNewName == "equals" + docText = if #docs > 0 + '\t' .. table.concat docs, '\n\t' + else + '' table.insert rustBinding, objectUsed and objectUsed + 1 or 2, "impl PartialEq for Rect { +#{docText} fn eq(&self, other: &Self) -> bool {\n#{argRtPrepare}\t\tunsafe { #{prefix}#{rtCastFrom and rtCastFrom(item, isOptional) or item} }\n\t} }" nil else - "\t#{pub}fn #{rustFuncName}(#{argRtInDefs})#{rtOut and ' -> ' .. rtOut or ''} {\n#{argRtPrepare}\t\tunsafe { #{prefix}#{rtCastFrom and rtCastFrom(item, isOptional) or item}; }\n\t}" + docText = if #docs > 0 + '\t' .. table.concat(docs, '\n\t') .. '\n' + else + '' + "#{docText}\t#{pub}fn #{rustFuncName}(#{argRtInDefs})#{rtOut and ' -> ' .. rtOut or ''} {\n#{argRtPrepare}\t\tunsafe { #{prefix}#{rtCastFrom and rtCastFrom(item, isOptional) or item}; }\n\t}" else error "\"#{dataType}\" is not supported." if objectUsed diff --git a/Tools/dora-rust/dora-test/src/main.rs b/Tools/dora-rust/dora-test/src/main.rs index 008f99776..ee6d74e7a 100644 --- a/Tools/dora-rust/dora-test/src/main.rs +++ b/Tools/dora-rust/dora-test/src/main.rs @@ -91,4 +91,8 @@ fn main() { e.remove("d"); return false; })); + let mut n = Node::new(); + let nn = cast::(n.obj()).unwrap(); + n.add_child(&nn); + n.align_items(10.0); } diff --git a/Tools/dora-rust/dora/src/dora.rs b/Tools/dora-rust/dora/src/dora.rs index 0252cb54c..5491ec557 100644 --- a/Tools/dora-rust/dora/src/dora.rs +++ b/Tools/dora-rust/dora/src/dora.rs @@ -1,3 +1,11 @@ +/* Copyright (c) 2024 Li Jin, dragon-fly@qq.com + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + use std::{ffi::c_void, any::Any}; use once_cell::sync::Lazy; @@ -1037,38 +1045,99 @@ extern "C" { } impl Array { + /// Sets the item at the given index. + /// + /// # Arguments + /// + /// * `index` - The index to set, should be 0 based. + /// * `item` - The new item value. pub fn set<'a, T>(&mut self, index: i32, v: T) where T: IntoValue<'a> { if unsafe { array_set(self.raw(), index, v.val().raw()) == 0 } { panic!("Out of bounds, expecting [0, {}), got {}", self.get_count(), index); } } + /// Gets the item at the given index. + /// + /// # Arguments + /// + /// * `index` - The index to get, should be 0 based. + /// + /// # Returns + /// + /// * `Option` - The item value. pub fn get(&self, index: i32) -> Option { Value::from(unsafe { array_get(self.raw(), index) }) } + /// The first item in the array. pub fn first(&self) -> Option { Value::from(unsafe { array_first(self.raw()) }) } + /// The last item in the array. pub fn last(&self) -> Option { Value::from(unsafe { array_last(self.raw()) }) } + /// A random item from the array. pub fn random_object(&self) -> Option { Value::from(unsafe { array_random_object(self.raw()) }) } + /// Adds an item to the end of the array. + /// + /// # Arguments + /// + /// * `item` - The item to add. pub fn add<'a, T>(&mut self, v: T) where T: IntoValue<'a> { unsafe { array_add(self.raw(), v.val().raw()); } } + /// Inserts an item at the given index, shifting other items to the right. + /// + /// # Arguments + /// + /// * `index` - The index to insert at. + /// * `item` - The item to insert. pub fn insert<'a, T>(&mut self, index: i32, v: T) where T: IntoValue<'a> { unsafe { array_insert(self.raw(), index, v.val().raw()); } } + /// Checks whether the array contains a given item. + /// + /// # Arguments + /// + /// * `item` - The item to check. + /// + /// # Returns + /// + /// * `bool` - True if the item is found, false otherwise. pub fn contains<'a, T>(&self, v: T) -> bool where T: IntoValue<'a> { unsafe { array_contains(self.raw(), v.val().raw()) != 0 } } + /// Gets the index of a given item. + /// + /// # Arguments + /// + /// * `item` - The item to search for. + /// + /// # Returns + /// + /// * `i32` - The index of the item, or -1 if it is not found. pub fn index<'a, T>(&self, v: T) -> i32 where T: IntoValue<'a> { unsafe { array_index(self.raw(), v.val().raw()) } } + /// Removes and returns the last item in the array. + /// + /// # Returns + /// + /// * `Option` - The last item removed from the array. pub fn remove_last(&mut self) -> Option { Value::from(unsafe { array_remove_last(self.raw()) }) } + /// Removes the first occurrence of a given item from the array without preserving order. + /// + /// # Arguments + /// + /// * `item` - The item to remove. + /// + /// # Returns + /// + /// * `bool` - True if the item was found and removed, false otherwise. pub fn fast_remove<'a, T>(&mut self, v: T) -> bool where T: IntoValue<'a> { unsafe { array_fast_remove(self.raw(), v.val().raw()) != 0 } } @@ -1082,9 +1151,24 @@ extern "C" { } impl Dictionary { + /// A method for setting items in the dictionary. + /// + /// # Arguments + /// + /// * `key` - The key of the item to set. + /// * `item` - The Item to set for the given key, set to None to delete this key-value pair. pub fn set<'a, T>(&mut self, key: &str, v: T) where T: IntoValue<'a> { unsafe { dictionary_set(self.raw(), from_string(key), v.val().raw()); } } + /// A method for accessing items in the dictionary. + /// + /// # Arguments + /// + /// * `key` - The key of the item to retrieve. + /// + /// # Returns + /// + /// * `Option` - The Item with the given key, or None if it does not exist. pub fn get(&self, key: &str) -> Option { Value::from(unsafe { dictionary_get(self.raw(), from_string(key)) }) } @@ -1099,12 +1183,38 @@ extern "C" { } impl Entity { + /// Sets a property of the entity to a given value. + /// This function will trigger events for Observer objects. + /// + /// # Arguments + /// + /// * `key` - The name of the property to set. + /// * `item` - The value to set the property to. pub fn set<'a, T>(&mut self, key: &str, value: T) where T: IntoValue<'a> { unsafe { entity_set(self.raw(), from_string(key), value.val().raw()); } } + /// Retrieves the value of a property of the entity. + /// + /// # Arguments + /// + /// * `key` - The name of the property to retrieve the value of. + /// + /// # Returns + /// + /// * `Option` - The value of the specified property. pub fn get(&self, key: &str) -> Option { Value::from(unsafe { entity_get(self.raw(), from_string(key)) }) } + /// Retrieves the previous value of a property of the entity. + /// The old values are values before the last change of the component values of the Entity. + /// + /// # Arguments + /// + /// * `key` - The name of the property to retrieve the previous value of. + /// + /// # Returns + /// + /// * `Option` - The previous value of the specified property. pub fn get_old(&self, key: &str) -> Option { Value::from(unsafe { entity_get_old(self.raw(), from_string(key)) }) } @@ -1117,7 +1227,16 @@ extern "C" { } impl Group { - pub fn watch(&mut self, mut func: Box bool>) { + /// Watches the group for changes to its entities, calling a function whenever an entity is added or changed. + /// + /// # Arguments + /// + /// * `func` - The function to call when an entity is added or changed. Returns true to stop watching. + /// + /// # Returns + /// + /// * `Group` - The same group, for method chaining. + pub fn watch(&mut self, mut func: Box bool>) -> &mut Group { let mut stack = CallStack::new(); let stack_raw = stack.raw(); let func_id = push_function(Box::new(move || { @@ -1125,7 +1244,17 @@ impl Group { stack.push_bool(result); })); unsafe { group_watch(self.raw(), func_id, stack_raw); } - } + self + } + /// Calls a function for each entity in the group. + /// + /// # Arguments + /// + /// * `func` - The function to call for each entity. Returning true inside the function will stop iteration. + /// + /// # Returns + /// + /// * `bool` - Returns false if all entities were processed, true if the iteration was interrupted. pub fn each(&self, func: Box bool>) -> bool { match self.find(func) { Some(_) => true, @@ -1137,7 +1266,7 @@ impl Group { // Observer extern "C" { - fn observer_watch(observer: i64, func: i32, stack: i64); + fn observer_watch(observer: i64, func: i32, stack: i64) -> i64; } #[repr(i32)] @@ -1149,7 +1278,16 @@ pub enum EntityEvent { } impl Observer { - pub fn watch(&mut self, mut func: Box bool>) { + /// Watches the components changes to entities that match the observer's component filter. + /// + /// # Arguments + /// + /// * `func` - The function to call when a change occurs. Returns true to stop watching. + /// + /// # Returns + /// + /// * `Observer` - The same observer, for method chaining. + pub fn watch(&mut self, mut func: Box bool>) -> &mut Observer { let mut stack = CallStack::new(); let stack_raw = stack.raw(); let func_id = push_function(Box::new(move || { @@ -1157,6 +1295,7 @@ impl Observer { stack.push_bool(result); })); unsafe { observer_watch(self.raw(), func_id, stack_raw); } + self } } @@ -1167,6 +1306,12 @@ extern "C" { } impl Node { + /// Emits an event to a node, triggering the event handler associated with the event name. + /// + /// # Arguments + /// + /// * `name` - The name of the event. + /// * `stack` - The argument stack to be passed to the event handler. pub fn emit(&mut self, name: &str, stack: CallStack) { unsafe { node_emit(self.raw(), from_string(name), stack.raw()); } } @@ -1271,9 +1416,39 @@ extern "C" { } impl platformer::behavior::Blackboard { + /// Sets a value in the blackboard. + /// + /// # Arguments + /// * `key` - The key associated with the value. + /// * `value` - The value to be set. + /// + /// # Example + /// + /// ``` + /// blackboard.set("score", 100); + /// ``` pub fn set<'a, T>(&mut self, key: &str, value: T) where T: IntoValue<'a> { unsafe { blackboard_set(self.raw(), from_string(key), value.val().raw()); } } + /// Retrieves a value from the blackboard. + /// + /// # Arguments + /// + /// * `key` - The key associated with the value. + /// + /// # Returns + /// + /// An `Option` containing the value associated with the key, or `None` if the key does not exist. + /// + /// # Example + /// + /// ``` + /// if let Some(score) = blackboard.get("score") { + /// println!("Score: {}", score.into_i32().unwrap()); + /// } else { + /// println!("Score not found."); + /// } + /// ``` pub fn get(&self, key: &str) -> Option { Value::from(unsafe { blackboard_get(self.raw(), from_string(key)) }) } diff --git a/Tools/dora-rust/dora/src/dora/action.rs b/Tools/dora-rust/dora/src/dora/action.rs index 5b95c98c1..fb974ddfa 100644 --- a/Tools/dora-rust/dora/src/dora/action.rs +++ b/Tools/dora-rust/dora/src/dora/action.rs @@ -23,6 +23,7 @@ extern "C" { fn action_scale(duration: f32, start: f32, stop: f32, easing: i32) -> i64; } use crate::dora::IObject; +/// Represents an action that can be run on a node. pub struct Action { raw: i64 } crate::dora_object!(Action); impl Action { @@ -34,66 +35,183 @@ impl Action { } }) } + /// Gets the duration of the action. pub fn get_duration(&self) -> f32 { return unsafe { action_get_duration(self.raw()) }; } + /// Gets whether the action is currently running. pub fn is_running(&self) -> bool { return unsafe { action_is_running(self.raw()) != 0 }; } + /// Gets whether the action is currently paused. pub fn is_paused(&self) -> bool { return unsafe { action_is_paused(self.raw()) != 0 }; } + /// Sets whether the action should be run in reverse. pub fn set_reversed(&mut self, var: bool) { unsafe { action_set_reversed(self.raw(), if var { 1 } else { 0 }) }; } + /// Gets whether the action should be run in reverse. pub fn is_reversed(&self) -> bool { return unsafe { action_is_reversed(self.raw()) != 0 }; } + /// Sets the speed at which the action should be run. + /// Set to 1.0 to get normal speed, Set to 2.0 to get two times faster. pub fn set_speed(&mut self, var: f32) { unsafe { action_set_speed(self.raw(), var) }; } + /// Gets the speed at which the action should be run. + /// Set to 1.0 to get normal speed, Set to 2.0 to get two times faster. pub fn get_speed(&self) -> f32 { return unsafe { action_get_speed(self.raw()) }; } + /// Pauses the action. pub fn pause(&mut self) { unsafe { action_pause(self.raw()); } } + /// Resumes the action. pub fn resume(&mut self) { unsafe { action_resume(self.raw()); } } + /// Updates the state of the Action. + /// + /// # Arguments + /// + /// * `elapsed` - The amount of time in seconds that has elapsed to update action to. + /// * `reversed` - Whether or not to update the Action in reverse. pub fn update_to(&mut self, elapsed: f32, reversed: bool) { unsafe { action_update_to(self.raw(), elapsed, if reversed { 1 } else { 0 }); } } + /// Creates a new Action object to change a property of a node. + /// + /// # Arguments + /// + /// * `duration` - The duration of the action. + /// * `start` - The starting value of the property. + /// * `stop` - The ending value of the property. + /// * `prop` - The property to change. + /// * `easing` - The easing function to use. + /// + /// # Returns + /// + /// * `Action` - A new Action object. pub fn prop(duration: f32, start: f32, stop: f32, prop: crate::dora::Property, easing: crate::dora::EaseType) -> crate::dora::ActionDef { unsafe { return crate::dora::ActionDef::from(action_prop(duration, start, stop, prop as i32, easing as i32)); } } + /// Creates a new Action object to change the color of a node. + /// + /// # Arguments + /// + /// * `duration` - The duration of the action. + /// * `start` - The starting color. + /// * `stop` - The ending color. + /// * `easing` - The easing function to use. + /// + /// # Returns + /// + /// * `Action` - A new Action object. pub fn tint(duration: f32, start: &crate::dora::Color3, stop: &crate::dora::Color3, easing: crate::dora::EaseType) -> crate::dora::ActionDef { unsafe { return crate::dora::ActionDef::from(action_tint(duration, start.to_rgb() as i32, stop.to_rgb() as i32, easing as i32)); } } + /// Creates a new Action object to rotate a node by smallest angle. + /// + /// # Arguments + /// + /// * `duration` - The duration of the action. + /// * `start` - The starting angle. + /// * `stop` - The ending angle. + /// * `easing` - The easing function to use. + /// + /// # Returns + /// + /// * `Action` - A new Action object. pub fn roll(duration: f32, start: f32, stop: f32, easing: crate::dora::EaseType) -> crate::dora::ActionDef { unsafe { return crate::dora::ActionDef::from(action_roll(duration, start, stop, easing as i32)); } } + /// Creates a new Action object to run a group of actions in parallel. + /// + /// # Arguments + /// + /// * `defs` - The actions to run in parallel. + /// + /// # Returns + /// + /// * `Action` - A new Action object. pub fn spawn(defs: &Vec) -> crate::dora::ActionDef { unsafe { return crate::dora::ActionDef::from(action_spawn(crate::dora::Vector::from_action_def(defs))); } } + /// Creates a new Action object to run a group of actions in sequence. + /// + /// # Arguments + /// + /// * `defs` - The actions to run in sequence. + /// + /// # Returns + /// + /// * `Action` - A new Action object. pub fn sequence(defs: &Vec) -> crate::dora::ActionDef { unsafe { return crate::dora::ActionDef::from(action_sequence(crate::dora::Vector::from_action_def(defs))); } } + /// Creates a new Action object to delay the execution of following action. + /// + /// # Arguments + /// + /// * `duration` - The duration of the delay. + /// + /// # Returns + /// + /// * `Action` - A new Action object. pub fn delay(duration: f32) -> crate::dora::ActionDef { unsafe { return crate::dora::ActionDef::from(action_delay(duration)); } } + /// Creates a new Action object to show a node. pub fn show() -> crate::dora::ActionDef { unsafe { return crate::dora::ActionDef::from(action_show()); } } + /// Creates a new Action object to hide a node. pub fn hide() -> crate::dora::ActionDef { unsafe { return crate::dora::ActionDef::from(action_hide()); } } + /// Creates a new Action object to emit an event. + /// + /// # Arguments + /// + /// * `eventName` - The name of the event to emit. + /// * `msg` - The message to send with the event. + /// + /// # Returns + /// + /// * `Action` - A new Action object. pub fn event(event_name: &str, msg: &str) -> crate::dora::ActionDef { unsafe { return crate::dora::ActionDef::from(action_event(crate::dora::from_string(event_name), crate::dora::from_string(msg))); } } + /// Creates a new Action object to move a node. + /// + /// # Arguments + /// + /// * `duration` - The duration of the action. + /// * `start` - The starting position. + /// * `stop` - The ending position. + /// * `easing` - The easing function to use. + /// + /// # Returns + /// + /// * `Action` - A new Action object. pub fn move_to(duration: f32, start: &crate::dora::Vec2, stop: &crate::dora::Vec2, easing: crate::dora::EaseType) -> crate::dora::ActionDef { unsafe { return crate::dora::ActionDef::from(action_move_to(duration, start.into_i64(), stop.into_i64(), easing as i32)); } } + /// Creates a new Action object to scale a node. + /// + /// # Arguments + /// + /// * `duration` - The duration of the action. + /// * `start` - The starting scale. + /// * `stop` - The ending scale. + /// * `easing` - The easing function to use. + /// + /// # Returns + /// + /// * `Action` - A new Action object. pub fn scale(duration: f32, start: f32, stop: f32, easing: crate::dora::EaseType) -> crate::dora::ActionDef { unsafe { return crate::dora::ActionDef::from(action_scale(duration, start, stop, easing as i32)); } } diff --git a/Tools/dora-rust/dora/src/dora/app.rs b/Tools/dora-rust/dora/src/dora/app.rs index 8fa3d4ee3..2a1157d52 100644 --- a/Tools/dora-rust/dora/src/dora/app.rs +++ b/Tools/dora-rust/dora/src/dora/app.rs @@ -31,98 +31,155 @@ extern "C" { fn application_is_idled() -> i32; fn application_shutdown(); } +/// A struct representing an application. pub struct App { } impl App { + /// Gets the current passed frame number. pub fn get_frame() -> i32 { return unsafe { application_get_frame() }; } + /// Gets the size of the main frame buffer texture used for rendering. pub fn get_buffer_size() -> crate::dora::Size { return unsafe { crate::dora::Size::from(application_get_buffer_size()) }; } + /// Gets the logic visual size of the screen. + /// The visual size only changes when application window size changes. + /// And it won't be affacted by the view buffer scaling factor. pub fn get_visual_size() -> crate::dora::Size { return unsafe { crate::dora::Size::from(application_get_visual_size()) }; } + /// Gets the ratio of the pixel density displayed by the device + /// Can be calculated as the size of the rendering buffer divided by the size of the application window. pub fn get_device_pixel_ratio() -> f32 { return unsafe { application_get_device_pixel_ratio() }; } + /// Gets the platform the game engine is running on. pub fn get_platform() -> String { return unsafe { crate::dora::to_string(application_get_platform()) }; } + /// Gets the version string of the game engine. + /// Should be in format of "v0.0.0". pub fn get_version() -> String { return unsafe { crate::dora::to_string(application_get_version()) }; } + /// Gets the dependencies of the game engine. pub fn get_deps() -> String { return unsafe { crate::dora::to_string(application_get_deps()) }; } + /// Gets the time in seconds since the last frame update. pub fn get_delta_time() -> f64 { return unsafe { application_get_delta_time() }; } + /// Gets the elapsed time since current frame was started, in seconds. pub fn get_elapsed_time() -> f64 { return unsafe { application_get_elapsed_time() }; } + /// Gets the total time the game engine has been running until last frame ended, in seconds. + /// Should be a contant number when invoked in a same frame for multiple times. pub fn get_total_time() -> f64 { return unsafe { application_get_total_time() }; } + /// Gets the total time the game engine has been running until this field being accessed, in seconds. + /// Should be a increasing number when invoked in a same frame for multiple times. pub fn get_running_time() -> f64 { return unsafe { application_get_running_time() }; } + /// Gets a random number generated by a random number engine based on Mersenne Twister algorithm. + /// So that the random number generated by a same seed should be consistent on every platform. pub fn get_rand() -> i32 { return unsafe { application_get_rand() }; } + /// Gets the maximum valid frames per second the game engine is allowed to run at. + /// The max FPS is being inferred by the device screen max refresh rate. pub fn get_max_fps() -> i32 { return unsafe { application_get_max_fps() }; } + /// Gets whether the game engine is running in debug mode. pub fn is_debugging() -> bool { return unsafe { application_is_debugging() != 0 }; } + /// Sets the system locale string, in format like: `zh-Hans`, `en`. pub fn set_locale(var: &str) { unsafe { application_set_locale(crate::dora::from_string(var)) }; } + /// Gets the system locale string, in format like: `zh-Hans`, `en`. pub fn get_locale() -> String { return unsafe { crate::dora::to_string(application_get_locale()) }; } + /// Sets the theme color for Dora SSR. pub fn set_theme_color(var: &crate::dora::Color) { unsafe { application_set_theme_color(var.to_argb() as i32) }; } + /// Gets the theme color for Dora SSR. pub fn get_theme_color() -> crate::dora::Color { return unsafe { crate::dora::Color::from(application_get_theme_color()) }; } + /// Sets the random number seed. pub fn set_seed(var: i32) { unsafe { application_set_seed(var) }; } + /// Gets the random number seed. pub fn get_seed() -> i32 { return unsafe { application_get_seed() }; } + /// Sets the target frames per second the game engine is supposed to run at. + /// Only works when `fpsLimited` is set to true. pub fn set_target_fps(var: i32) { unsafe { application_set_target_fps(var) }; } + /// Gets the target frames per second the game engine is supposed to run at. + /// Only works when `fpsLimited` is set to true. pub fn get_target_fps() -> i32 { return unsafe { application_get_target_fps() }; } + /// Sets the application window size. + /// May differ from visual size due to the different DPIs of display devices. + /// Set `winSize` to `Size.zero` to toggle application window into full screen mode, + /// It is not available to set this property on platform Android and iOS. pub fn set_win_size(var: &crate::dora::Size) { unsafe { application_set_win_size(var.into_i64()) }; } + /// Gets the application window size. + /// May differ from visual size due to the different DPIs of display devices. + /// Set `winSize` to `Size.zero` to toggle application window into full screen mode, + /// It is not available to set this property on platform Android and iOS. pub fn get_win_size() -> crate::dora::Size { return unsafe { crate::dora::Size::from(application_get_win_size()) }; } + /// Sets the application window position. + /// It is not available to set this property on platform Android and iOS. pub fn set_win_position(var: &crate::dora::Vec2) { unsafe { application_set_win_position(var.into_i64()) }; } + /// Gets the application window position. + /// It is not available to set this property on platform Android and iOS. pub fn get_win_position() -> crate::dora::Vec2 { return unsafe { crate::dora::Vec2::from(application_get_win_position()) }; } + /// Sets whether the game engine is limiting the frames per second. + /// Set `fpsLimited` to true, will make engine run in a busy loop to track the precise frame time to switch to the next frame. And this behavior can lead to 100% CPU usage. This is usually common practice on Windows PCs for better CPU usage occupation. But it also results in extra heat and power consumption. pub fn set_fps_limited(var: bool) { unsafe { application_set_fps_limited(if var { 1 } else { 0 }) }; } + /// Gets whether the game engine is limiting the frames per second. + /// Set `fpsLimited` to true, will make engine run in a busy loop to track the precise frame time to switch to the next frame. And this behavior can lead to 100% CPU usage. This is usually common practice on Windows PCs for better CPU usage occupation. But it also results in extra heat and power consumption. pub fn is_fps_limited() -> bool { return unsafe { application_is_fps_limited() != 0 }; } + /// Sets whether the game engine is currently idled. + /// Set `idled` to true, will make game logic thread use a sleep time and going idled for next frame to come. Due to the imprecision in sleep time. This idled state may cause game engine over slept for a few frames to lost. + /// `idled` state can reduce some CPU usage. pub fn set_idled(var: bool) { unsafe { application_set_idled(if var { 1 } else { 0 }) }; } + /// Gets whether the game engine is currently idled. + /// Set `idled` to true, will make game logic thread use a sleep time and going idled for next frame to come. Due to the imprecision in sleep time. This idled state may cause game engine over slept for a few frames to lost. + /// `idled` state can reduce some CPU usage. pub fn is_idled() -> bool { return unsafe { application_is_idled() != 0 }; } + /// Shuts down the game engine. + /// It is not working and acts as a dummy function for platform Android and iOS to follow the specification of how mobile platform applications should operate. pub fn shutdown() { unsafe { application_shutdown(); } } diff --git a/Tools/dora-rust/dora/src/dora/array.rs b/Tools/dora-rust/dora/src/dora/array.rs index aeeecb088..a4a2738cd 100644 --- a/Tools/dora-rust/dora/src/dora/array.rs +++ b/Tools/dora-rust/dora/src/dora/array.rs @@ -13,6 +13,7 @@ extern "C" { fn array_new() -> i64; } use crate::dora::IObject; +/// An array data structure that supports various operations. pub struct Array { raw: i64 } crate::dora_object!(Array); impl Array { @@ -24,36 +25,77 @@ impl Array { } }) } + /// Gets the number of items in the array. pub fn get_count(&self) -> i64 { return unsafe { array_get_count(self.raw()) }; } + /// Gets whether the array is empty or not. pub fn is_empty(&self) -> bool { return unsafe { array_is_empty(self.raw()) != 0 }; } + /// Adds all items from another array to the end of this array. + /// + /// # Arguments + /// + /// * `other` - Another array object. pub fn add_range(&mut self, other: &crate::dora::Array) { unsafe { array_add_range(self.raw(), other.raw()); } } + /// Removes all items from this array that are also in another array. + /// + /// # Arguments + /// + /// * `other` - Another array object. pub fn remove_from(&mut self, other: &crate::dora::Array) { unsafe { array_remove_from(self.raw(), other.raw()); } } + /// Removes all items from the array. pub fn clear(&mut self) { unsafe { array_clear(self.raw()); } } + /// Reverses the order of the items in the array. pub fn reverse(&mut self) { unsafe { array_reverse(self.raw()); } } + /// Removes any empty slots from the end of the array. + /// This method is used to release the unused memory this array holds. pub fn shrink(&mut self) { unsafe { array_shrink(self.raw()); } } + /// Swaps the items at two given indices. + /// + /// # Arguments + /// + /// * `index_a` - The first index. + /// * `index_b` - The second index. pub fn swap(&mut self, index_a: i32, index_b: i32) { unsafe { array_swap(self.raw(), index_a, index_b); } } + /// Removes the item at the given index. + /// + /// # Arguments + /// + /// * `index` - The index to remove. + /// + /// # Returns + /// + /// * `bool` - `true` if an item was removed, `false` otherwise. pub fn remove_at(&mut self, index: i32) -> bool { unsafe { return array_remove_at(self.raw(), index) != 0; } } + /// Removes the item at the given index without preserving the order of the array. + /// + /// # Arguments + /// + /// * `index` - The index to remove. + /// + /// # Returns + /// + /// * `bool` - `true` if an item was removed, `false` otherwise. pub fn fast_remove_at(&mut self, index: i32) -> bool { unsafe { return array_fast_remove_at(self.raw(), index) != 0; } } + /// Creates a new array object pub fn new() -> Array { unsafe { return Array { raw: array_new() }; } } diff --git a/Tools/dora-rust/dora/src/dora/camera.rs b/Tools/dora-rust/dora/src/dora/camera.rs index 90cb688f9..3db701319 100644 --- a/Tools/dora-rust/dora/src/dora/camera.rs +++ b/Tools/dora-rust/dora/src/dora/camera.rs @@ -3,10 +3,12 @@ extern "C" { fn camera_get_name(slf: i64) -> i64; } use crate::dora::IObject; +/// A struct for Camera object in the game engine. pub struct Camera { raw: i64 } crate::dora_object!(Camera); impl ICamera for Camera { } pub trait ICamera: IObject { + /// Gets the name of the Camera. fn get_name(&self) -> String { return unsafe { crate::dora::to_string(camera_get_name(self.raw())) }; } diff --git a/Tools/dora-rust/dora/src/dora/camera_2d.rs b/Tools/dora-rust/dora/src/dora/camera_2d.rs index d1c562137..b93d7dab5 100644 --- a/Tools/dora-rust/dora/src/dora/camera_2d.rs +++ b/Tools/dora-rust/dora/src/dora/camera_2d.rs @@ -11,6 +11,7 @@ extern "C" { use crate::dora::IObject; use crate::dora::ICamera; impl ICamera for Camera2D { } +/// A struct for 2D camera object in the game engine. pub struct Camera2D { raw: i64 } crate::dora_object!(Camera2D); impl Camera2D { @@ -22,24 +23,39 @@ impl Camera2D { } }) } + /// Sets the rotation angle of the camera in degrees. pub fn set_rotation(&mut self, var: f32) { unsafe { camera2d_set_rotation(self.raw(), var) }; } + /// Gets the rotation angle of the camera in degrees. pub fn get_rotation(&self) -> f32 { return unsafe { camera2d_get_rotation(self.raw()) }; } + /// Sets the factor by which to zoom the camera. If set to 1.0, the view is normal sized. If set to 2.0, items will appear double in size. pub fn set_zoom(&mut self, var: f32) { unsafe { camera2d_set_zoom(self.raw(), var) }; } + /// Gets the factor by which to zoom the camera. If set to 1.0, the view is normal sized. If set to 2.0, items will appear double in size. pub fn get_zoom(&self) -> f32 { return unsafe { camera2d_get_zoom(self.raw()) }; } + /// Sets the position of the camera in the game world. pub fn set_position(&mut self, var: &crate::dora::Vec2) { unsafe { camera2d_set_position(self.raw(), var.into_i64()) }; } + /// Gets the position of the camera in the game world. pub fn get_position(&self) -> crate::dora::Vec2 { return unsafe { crate::dora::Vec2::from(camera2d_get_position(self.raw())) }; } + /// Creates a new Camera2D object with the given name. + /// + /// # Arguments + /// + /// * `name` - The name of the Camera2D object. + /// + /// # Returns + /// + /// * `Camera2D` - A new instance of the Camera2D object. pub fn new(name: &str) -> Camera2D { unsafe { return Camera2D { raw: camera2d_new(crate::dora::from_string(name)) }; } } diff --git a/Tools/dora-rust/dora/src/dora/camera_otho.rs b/Tools/dora-rust/dora/src/dora/camera_otho.rs index 0a7ec550e..b6f0d9d9a 100644 --- a/Tools/dora-rust/dora/src/dora/camera_otho.rs +++ b/Tools/dora-rust/dora/src/dora/camera_otho.rs @@ -7,6 +7,7 @@ extern "C" { use crate::dora::IObject; use crate::dora::ICamera; impl ICamera for CameraOtho { } +/// A struct for an orthographic camera object in the game engine. pub struct CameraOtho { raw: i64 } crate::dora_object!(CameraOtho); impl CameraOtho { @@ -18,12 +19,23 @@ impl CameraOtho { } }) } + /// Sets the position of the camera in the game world. pub fn set_position(&mut self, var: &crate::dora::Vec2) { unsafe { cameraotho_set_position(self.raw(), var.into_i64()) }; } + /// Gets the position of the camera in the game world. pub fn get_position(&self) -> crate::dora::Vec2 { return unsafe { crate::dora::Vec2::from(cameraotho_get_position(self.raw())) }; } + /// Creates a new CameraOtho object with the given name. + /// + /// # Arguments + /// + /// * `name` - The name of the CameraOtho object. + /// + /// # Returns + /// + /// * `CameraOtho` - A new instance of the CameraOtho object. pub fn new(name: &str) -> CameraOtho { unsafe { return CameraOtho { raw: cameraotho_new(crate::dora::from_string(name)) }; } } diff --git a/Tools/dora-rust/dora/src/dora/content.rs b/Tools/dora-rust/dora/src/dora/content.rs index dbcf1789b..8b0938888 100644 --- a/Tools/dora-rust/dora/src/dora/content.rs +++ b/Tools/dora-rust/dora/src/dora/content.rs @@ -24,65 +24,200 @@ extern "C" { fn content_zip_async(folder_path: i64, zip_file: i64, func: i32, stack: i64, func1: i32, stack1: i64); fn content_unzip_async(zip_file: i64, folder_path: i64, func: i32, stack: i64, func1: i32, stack1: i64); } +/// The `Content` is a static struct that manages file searching, +/// loading and other operations related to resources. pub struct Content { } impl Content { + /// Sets an array of directories to search for resource files. pub fn set_search_paths(var: &Vec<&str>) { unsafe { content_set_search_paths(crate::dora::Vector::from_str(var)) }; } + /// Gets an array of directories to search for resource files. pub fn get_search_paths() -> Vec { return unsafe { crate::dora::Vector::to_str(content_get_search_paths()) }; } + /// Gets the path to the directory containing read-only resources. pub fn get_asset_path() -> String { return unsafe { crate::dora::to_string(content_get_asset_path()) }; } + /// Gets the path to the directory where files can be written. pub fn get_writable_path() -> String { return unsafe { crate::dora::to_string(content_get_writable_path()) }; } + /// Saves the specified content to a file with the specified filename. + /// + /// # Arguments + /// + /// * `filename` - The name of the file to save. + /// * `content` - The content to save to the file. + /// + /// # Returns + /// + /// * `bool` - `true` if the content saves to file successfully, `false` otherwise. pub fn save(filename: &str, content: &str) -> bool { unsafe { return content_save(crate::dora::from_string(filename), crate::dora::from_string(content)) != 0; } } + /// Checks if a file with the specified filename exists. + /// + /// # Arguments + /// + /// * `filename` - The name of the file to check. + /// + /// # Returns + /// + /// * `bool` - `true` if the file exists, `false` otherwise. pub fn exist(filename: &str) -> bool { unsafe { return content_exist(crate::dora::from_string(filename)) != 0; } } + /// Creates a new directory with the specified path. + /// + /// # Arguments + /// + /// * `path` - The path of the directory to create. + /// + /// # Returns + /// + /// * `bool` - `true` if the directory was created, `false` otherwise. pub fn mkdir(path: &str) -> bool { unsafe { return content_mkdir(crate::dora::from_string(path)) != 0; } } + /// Checks if the specified path is a directory. + /// + /// # Arguments + /// + /// * `path` - The path to check. + /// + /// # Returns + /// + /// * `bool` - `true` if the path is a directory, `false` otherwise. pub fn isdir(path: &str) -> bool { unsafe { return content_isdir(crate::dora::from_string(path)) != 0; } } + /// Copies the file or directory at the specified source path to the target path. + /// + /// # Arguments + /// + /// * `src_path` - The path of the file or directory to copy. + /// * `dst_path` - The path to copy the file or directory to. + /// + /// # Returns + /// + /// * `bool` - `true` if the file or directory was successfully copied to the target path, `false` otherwise. pub fn copy(src: &str, dst: &str) -> bool { unsafe { return content_copy(crate::dora::from_string(src), crate::dora::from_string(dst)) != 0; } } + /// Moves the file or directory at the specified source path to the target path. + /// + /// # Arguments + /// + /// * `src_path` - The path of the file or directory to move. + /// * `dst_path` - The path to move the file or directory to. + /// + /// # Returns + /// + /// * `bool` - `true` if the file or directory was successfully moved to the target path, `false` otherwise. pub fn move_to(src: &str, dst: &str) -> bool { unsafe { return content_move_to(crate::dora::from_string(src), crate::dora::from_string(dst)) != 0; } } + /// Removes the file or directory at the specified path. + /// + /// # Arguments + /// + /// * `path` - The path of the file or directory to remove. + /// + /// # Returns + /// + /// * `bool` - `true` if the file or directory was successfully removed, `false` otherwise. pub fn remove(path: &str) -> bool { unsafe { return content_remove(crate::dora::from_string(path)) != 0; } } + /// Gets the full path of a file with the specified filename. + /// + /// # Arguments + /// + /// * `filename` - The name of the file to get the full path of. + /// + /// # Returns + /// + /// * `String` - The full path of the file. pub fn get_full_path(filename: &str) -> String { unsafe { return crate::dora::to_string(content_get_full_path(crate::dora::from_string(filename))); } } + /// Adds a new search path to the end of the list. + /// + /// # Arguments + /// + /// * `path` - The search path to add. pub fn add_search_path(path: &str) { unsafe { content_add_search_path(crate::dora::from_string(path)); } } + /// Inserts a search path at the specified index. + /// + /// # Arguments + /// + /// * `index` - The index at which to insert the search path. + /// * `path` - The search path to insert. pub fn insert_search_path(index: i32, path: &str) { unsafe { content_insert_search_path(index, crate::dora::from_string(path)); } } + /// Removes the specified search path from the list. + /// + /// # Arguments + /// + /// * `path` - The search path to remove. pub fn remove_search_path(path: &str) { unsafe { content_remove_search_path(crate::dora::from_string(path)); } } + /// Clears the search path cache of the map of relative paths to full paths. pub fn clear_path_cache() { unsafe { content_clear_path_cache(); } } + /// Gets the names of all subdirectories in the specified directory. + /// + /// # Arguments + /// + /// * `path` - The path of the directory to search. + /// + /// # Returns + /// + /// * `Vec` - An array of the names of all subdirectories in the specified directory. pub fn get_dirs(path: &str) -> Vec { unsafe { return crate::dora::Vector::to_str(content_get_dirs(crate::dora::from_string(path))); } } + /// Gets the names of all files in the specified directory. + /// + /// # Arguments + /// + /// * `path` - The path of the directory to search. + /// + /// # Returns + /// + /// * `Vec` - An array of the names of all files in the specified directory. pub fn get_files(path: &str) -> Vec { unsafe { return crate::dora::Vector::to_str(content_get_files(crate::dora::from_string(path))); } } + /// Gets the names of all files in the specified directory and its subdirectories. + /// + /// # Arguments + /// + /// * `path` - The path of the directory to search. + /// + /// # Returns + /// + /// * `Vec` - An array of the names of all files in the specified directory and its subdirectories. pub fn get_all_files(path: &str) -> Vec { unsafe { return crate::dora::Vector::to_str(content_get_all_files(crate::dora::from_string(path))); } } + /// Asynchronously loads the content of the file with the specified filename. + /// + /// # Arguments + /// + /// * `filename` - The name of the file to load. + /// * `callback` - The function to call with the content of the file once it is loaded. + /// + /// # Returns + /// + /// * `String` - The content of the loaded file. pub fn load_async(filename: &str, mut callback: Box) { let mut stack = crate::dora::CallStack::new(); let stack_raw = stack.raw(); @@ -91,6 +226,16 @@ impl Content { })); unsafe { content_load_async(crate::dora::from_string(filename), func_id, stack_raw); } } + /// Asynchronously copies a file or a folder from the source path to the destination path. + /// + /// # Arguments + /// + /// * `src` - The path of the file or folder to copy. + /// * `dst` - The destination path of the copied files. + /// + /// # Returns + /// + /// * `bool` - `true` if the file or folder was copied successfully, `false` otherwise. pub fn copy_async(src_file: &str, target_file: &str, mut callback: Box) { let mut stack = crate::dora::CallStack::new(); let stack_raw = stack.raw(); @@ -99,6 +244,16 @@ impl Content { })); unsafe { content_copy_async(crate::dora::from_string(src_file), crate::dora::from_string(target_file), func_id, stack_raw); } } + /// Asynchronously saves the specified content to a file with the specified filename. + /// + /// # Arguments + /// + /// * `filename` - The name of the file to save. + /// * `content` - The content to save to the file. + /// + /// # Returns + /// + /// * `bool` - `true` if the content was saved successfully, `false` otherwise. pub fn save_async(filename: &str, content: &str, mut callback: Box) { let mut stack = crate::dora::CallStack::new(); let stack_raw = stack.raw(); @@ -107,6 +262,17 @@ impl Content { })); unsafe { content_save_async(crate::dora::from_string(filename), crate::dora::from_string(content), func_id, stack_raw); } } + /// Asynchronously compresses the specified folder to a ZIP archive with the specified filename. + /// + /// # Arguments + /// + /// * `folder_path` - The path of the folder to compress, should be under the asset writable path. + /// * `zip_file` - The name of the ZIP archive to create. + /// * `filter` - An optional function to filter the files to include in the archive. The function takes a filename as input and returns a boolean indicating whether to include the file. If not provided, all files will be included. + /// + /// # Returns + /// + /// * `bool` - `true` if the folder was compressed successfully, `false` otherwise. pub fn zip_async(folder_path: &str, zip_file: &str, mut filter: Box bool>, mut callback: Box) { let mut stack = crate::dora::CallStack::new(); let stack_raw = stack.raw(); @@ -121,6 +287,17 @@ impl Content { })); unsafe { content_zip_async(crate::dora::from_string(folder_path), crate::dora::from_string(zip_file), func_id, stack_raw, func_id1, stack_raw1); } } + /// Asynchronously decompresses a ZIP archive to the specified folder. + /// + /// # Arguments + /// + /// * `zip_file` - The name of the ZIP archive to decompress, should be a file under the asset writable path. + /// * `folder_path` - The path of the folder to decompress to, should be under the asset writable path. + /// * `filter` - An optional function to filter the files to include in the archive. The function takes a filename as input and returns a boolean indicating whether to include the file. If not provided, all files will be included. + /// + /// # Returns + /// + /// * `bool` - `true` if the folder was decompressed successfully, `false` otherwise. pub fn unzip_async(zip_file: &str, folder_path: &str, mut filter: Box bool>, mut callback: Box) { let mut stack = crate::dora::CallStack::new(); let stack_raw = stack.raw(); diff --git a/Tools/dora-rust/dora/src/dora/dictionary.rs b/Tools/dora-rust/dora/src/dora/dictionary.rs index a9ca2e765..27339351b 100644 --- a/Tools/dora-rust/dora/src/dora/dictionary.rs +++ b/Tools/dora-rust/dora/src/dora/dictionary.rs @@ -6,6 +6,7 @@ extern "C" { fn dictionary_new() -> i64; } use crate::dora::IObject; +/// A struct for storing pairs of string keys and various values. pub struct Dictionary { raw: i64 } crate::dora_object!(Dictionary); impl Dictionary { @@ -17,15 +18,19 @@ impl Dictionary { } }) } + /// Gets the number of items in the dictionary. pub fn get_count(&self) -> i32 { return unsafe { dictionary_get_count(self.raw()) }; } + /// Gets the keys of the items in the dictionary. pub fn get_keys(&self) -> Vec { return unsafe { crate::dora::Vector::to_str(dictionary_get_keys(self.raw())) }; } + /// Removes all the items from the dictionary. pub fn clear(&mut self) { unsafe { dictionary_clear(self.raw()); } } + /// Creates instance of the "Dictionary". pub fn new() -> Dictionary { unsafe { return Dictionary { raw: dictionary_new() }; } } diff --git a/Tools/dora-rust/dora/src/dora/director.rs b/Tools/dora-rust/dora/src/dora/director.rs index 6e4c32598..c85b26a02 100644 --- a/Tools/dora-rust/dora/src/dora/director.rs +++ b/Tools/dora-rust/dora/src/dora/director.rs @@ -17,53 +17,82 @@ extern "C" { fn director_cleanup(); } use crate::dora::IObject; +/// A struct manages the game scene trees and provides access to root scene nodes for different game uses. pub struct Director { } impl Director { + /// Sets the background color for the game world. pub fn set_clear_color(var: &crate::dora::Color) { unsafe { director_set_clear_color(var.to_argb() as i32) }; } + /// Gets the background color for the game world. pub fn get_clear_color() -> crate::dora::Color { return unsafe { crate::dora::Color::from(director_get_clear_color()) }; } + /// Sets the game scheduler which is used for scheduling tasks like animations and gameplay events. pub fn set_scheduler(var: &crate::dora::Scheduler) { unsafe { director_set_scheduler(var.raw()) }; } + /// Gets the game scheduler which is used for scheduling tasks like animations and gameplay events. pub fn get_scheduler() -> crate::dora::Scheduler { return unsafe { crate::dora::Scheduler::from(director_get_scheduler()).unwrap() }; } + /// Gets the root node for 2D user interface elements like buttons and labels. pub fn get_ui() -> crate::dora::Node { return unsafe { crate::dora::Node::from(director_get_ui()).unwrap() }; } + /// Gets the root node for 3D user interface elements with 3D projection effect. pub fn get_ui_3d() -> crate::dora::Node { return unsafe { crate::dora::Node::from(director_get_ui_3d()).unwrap() }; } + /// Gets the root node for the starting point of a game. pub fn get_entry() -> crate::dora::Node { return unsafe { crate::dora::Node::from(director_get_entry()).unwrap() }; } + /// Gets the root node for post-rendering scene tree. pub fn get_post_node() -> crate::dora::Node { return unsafe { crate::dora::Node::from(director_get_post_node()).unwrap() }; } + /// Gets the system scheduler which is used for low-level system tasks, should not put any game logic in it. pub fn get_system_scheduler() -> crate::dora::Scheduler { return unsafe { crate::dora::Scheduler::from(director_get_system_scheduler()).unwrap() }; } + /// Gets the scheduler used for processing post game logic. pub fn get_post_scheduler() -> crate::dora::Scheduler { return unsafe { crate::dora::Scheduler::from(director_get_post_scheduler()).unwrap() }; } + /// Gets the current active camera in Director's camera stack. pub fn get_current_camera() -> crate::dora::Camera { return unsafe { crate::dora::Camera::from(director_get_current_camera()).unwrap() }; } + /// Adds a new camera to Director's camera stack and sets it to the current camera. + /// + /// # Arguments + /// + /// * `camera` - The camera to add. pub fn push_camera(camera: &dyn crate::dora::ICamera) { unsafe { director_push_camera(camera.raw()); } } + /// Removes the current camera from Director's camera stack. pub fn pop_camera() { unsafe { director_pop_camera(); } } + /// Removes a specified camera from Director's camera stack. + /// + /// # Arguments + /// + /// * `camera` - The camera to remove. + /// + /// # Returns + /// + /// * `bool` - `true` if the camera was removed, `false` otherwise. pub fn remove_camera(camera: &dyn crate::dora::ICamera) -> bool { unsafe { return director_remove_camera(camera.raw()) != 0; } } + /// Removes all cameras from Director's camera stack. pub fn clear_camera() { unsafe { director_clear_camera(); } } + /// Cleans up all resources managed by the Director, including scene trees and cameras. pub fn cleanup() { unsafe { director_cleanup(); } } diff --git a/Tools/dora-rust/dora/src/dora/effect.rs b/Tools/dora-rust/dora/src/dora/effect.rs index b03595fd8..f5a519b97 100644 --- a/Tools/dora-rust/dora/src/dora/effect.rs +++ b/Tools/dora-rust/dora/src/dora/effect.rs @@ -6,16 +6,33 @@ extern "C" { fn effect_new(vert_shader: i64, frag_shader: i64) -> i64; } use crate::dora::IObject; +/// A struct for managing multiple render pass objects. +/// Effect objects allow you to combine multiple passes to create more complex shader effects. pub struct Effect { raw: i64 } crate::dora_object!(Effect); impl IEffect for Effect { } pub trait IEffect: IObject { + /// Adds a Pass object to this Effect. + /// + /// # Arguments + /// + /// * `pass` - The Pass object to add. fn add(&mut self, pass: &crate::dora::Pass) { unsafe { effect_add(self.raw(), pass.raw()); } } + /// Retrieves a Pass object from this Effect by index. + /// + /// # Arguments + /// + /// * `index` - The index of the Pass object to retrieve. + /// + /// # Returns + /// + /// * `Pass` - The Pass object at the given index. fn get(&self, index: i64) -> Option { unsafe { return crate::dora::Pass::from(effect_get(self.raw(), index)); } } + /// Removes all Pass objects from this Effect. fn clear(&mut self) { unsafe { effect_clear(self.raw()); } } @@ -29,6 +46,18 @@ impl Effect { } }) } + /// A method that allows you to create a new Effect object. + /// + /// # Arguments + /// + /// * `vert_shader` - The vertex shader file string. + /// * `frag_shader` - The fragment shader file string. A shader file string must be one of the formats: + /// * "builtin:" + theBuiltinShaderName + /// * "Shader/compiled_shader_file.bin" + /// + /// # Returns + /// + /// * `Effect` - A new Effect object. pub fn new(vert_shader: &str, frag_shader: &str) -> Effect { unsafe { return Effect { raw: effect_new(crate::dora::from_string(vert_shader), crate::dora::from_string(frag_shader)) }; } } diff --git a/Tools/dora-rust/dora/src/dora/entity.rs b/Tools/dora-rust/dora/src/dora/entity.rs index 043ba8b27..650409cc2 100644 --- a/Tools/dora-rust/dora/src/dora/entity.rs +++ b/Tools/dora-rust/dora/src/dora/entity.rs @@ -8,6 +8,7 @@ extern "C" { fn entity_new() -> i64; } use crate::dora::IObject; +/// A struct representing an entity for an ECS game system. pub struct Entity { raw: i64 } crate::dora_object!(Entity); impl Entity { @@ -19,21 +20,33 @@ impl Entity { } }) } + /// Gets the number of all running entities. pub fn get_count() -> i32 { return unsafe { entity_get_count() }; } + /// Gets the index of the entity. pub fn get_index(&self) -> i32 { return unsafe { entity_get_index(self.raw()) }; } + /// Clears all entities. pub fn clear() { unsafe { entity_clear(); } } + /// Removes a property of the entity. + /// + /// This function will trigger events for Observer objects. + /// + /// # Arguments + /// + /// * `key` - The name of the property to remove. pub fn remove(&mut self, key: &str) { unsafe { entity_remove(self.raw(), crate::dora::from_string(key)); } } + /// Destroys the entity. pub fn destroy(&mut self) { unsafe { entity_destroy(self.raw()); } } + /// Creates a new entity. pub fn new() -> Entity { unsafe { return Entity { raw: entity_new() }; } } diff --git a/Tools/dora-rust/dora/src/dora/grabber.rs b/Tools/dora-rust/dora/src/dora/grabber.rs index 5bdc3da81..e045d05bf 100644 --- a/Tools/dora-rust/dora/src/dora/grabber.rs +++ b/Tools/dora-rust/dora/src/dora/grabber.rs @@ -15,6 +15,8 @@ extern "C" { fn grabber_move_uv(slf: i64, x: i32, y: i32, offset: i64); } use crate::dora::IObject; +/// A grabber which is used to render a part of the scene to a texture +/// by a grid of vertices. pub struct Grabber { raw: i64 } crate::dora_object!(Grabber); impl Grabber { @@ -26,42 +28,92 @@ impl Grabber { } }) } + /// Sets the camera used to render the texture. pub fn set_camera(&mut self, var: &dyn crate::dora::ICamera) { unsafe { grabber_set_camera(self.raw(), var.raw()) }; } + /// Gets the camera used to render the texture. pub fn get_camera(&self) -> Option { return unsafe { crate::dora::Camera::from(grabber_get_camera(self.raw())) }; } + /// Sets the sprite effect applied to the texture. pub fn set_effect(&mut self, var: &crate::dora::SpriteEffect) { unsafe { grabber_set_effect(self.raw(), var.raw()) }; } + /// Gets the sprite effect applied to the texture. pub fn get_effect(&self) -> Option { return unsafe { crate::dora::SpriteEffect::from(grabber_get_effect(self.raw())) }; } + /// Sets the blend function applied to the texture. pub fn set_blend_func(&mut self, var: u64) { unsafe { grabber_set_blend_func(self.raw(), var as i64) }; } + /// Gets the blend function applied to the texture. pub fn get_blend_func(&self) -> u64 { return unsafe { grabber_get_blend_func(self.raw()) as u64 }; } + /// Sets the clear color used to clear the texture. pub fn set_clear_color(&mut self, var: &crate::dora::Color) { unsafe { grabber_set_clear_color(self.raw(), var.to_argb() as i32) }; } + /// Gets the clear color used to clear the texture. pub fn get_clear_color(&self) -> crate::dora::Color { return unsafe { crate::dora::Color::from(grabber_get_clear_color(self.raw())) }; } + /// Sets the position of a vertex in the grabber grid. + /// + /// # Arguments + /// + /// * `x` - The x-index of the vertex in the grabber grid. + /// * `y` - The y-index of the vertex in the grabber grid. + /// * `pos` - The new position of the vertex, represented by a Vec2 object. + /// * `z` - An optional argument representing the new z-coordinate of the vertex. pub fn set_pos(&mut self, x: i32, y: i32, pos: &crate::dora::Vec2, z: f32) { unsafe { grabber_set_pos(self.raw(), x, y, pos.into_i64(), z); } } + /// Gets the position of a vertex in the grabber grid. + /// + /// # Arguments + /// + /// * `x` - The x-index of the vertex in the grabber grid. + /// * `y` - The y-index of the vertex in the grabber grid. + /// + /// # Returns + /// + /// * `Vec2` - The position of the vertex. pub fn get_pos(&self, x: i32, y: i32) -> crate::dora::Vec2 { unsafe { return crate::dora::Vec2::from(grabber_get_pos(self.raw(), x, y)); } } + /// Sets the color of a vertex in the grabber grid. + /// + /// # Arguments + /// + /// * `x` - The x-index of the vertex in the grabber grid. + /// * `y` - The y-index of the vertex in the grabber grid. + /// * `color` - The new color of the vertex, represented by a Color object. pub fn set_color(&mut self, x: i32, y: i32, color: &crate::dora::Color) { unsafe { grabber_set_color(self.raw(), x, y, color.to_argb() as i32); } } + /// Gets the color of a vertex in the grabber grid. + /// + /// # Arguments + /// + /// * `x` - The x-index of the vertex in the grabber grid. + /// * `y` - The y-index of the vertex in the grabber grid. + /// + /// # Returns + /// + /// * `Color` - The color of the vertex. pub fn get_color(&self, x: i32, y: i32) -> crate::dora::Color { unsafe { return crate::dora::Color::from(grabber_get_color(self.raw(), x, y)); } } + /// Sets the UV coordinates of a vertex in the grabber grid. + /// + /// # Arguments + /// + /// * `x` - The x-index of the vertex in the grabber grid. + /// * `y` - The y-index of the vertex in the grabber grid. + /// * `offset` - The new UV coordinates of the vertex, represented by a Vec2 object. pub fn move_uv(&mut self, x: i32, y: i32, offset: &crate::dora::Vec2) { unsafe { grabber_move_uv(self.raw(), x, y, offset.into_i64()); } } diff --git a/Tools/dora-rust/dora/src/dora/group.rs b/Tools/dora-rust/dora/src/dora/group.rs index c8d16ac09..6af892102 100644 --- a/Tools/dora-rust/dora/src/dora/group.rs +++ b/Tools/dora-rust/dora/src/dora/group.rs @@ -5,6 +5,7 @@ extern "C" { fn entitygroup_new(components: i64) -> i64; } use crate::dora::IObject; +/// A struct representing a group of entities in the ECS game systems. pub struct Group { raw: i64 } crate::dora_object!(Group); impl Group { @@ -16,9 +17,19 @@ impl Group { } }) } + /// Gets the number of entities in the group. pub fn get_count(&self) -> i32 { return unsafe { entitygroup_get_count(self.raw()) }; } + /// Finds the first entity in the group that satisfies a predicate function. + /// + /// # Arguments + /// + /// * `func` - The predicate function to test each entity with. + /// + /// # Returns + /// + /// * `Option` - The first entity that satisfies the predicate, or None if no entity does. pub fn find(&self, mut func: Box bool>) -> Option { let mut stack = crate::dora::CallStack::new(); let stack_raw = stack.raw(); @@ -28,6 +39,15 @@ impl Group { })); unsafe { return crate::dora::Entity::from(entitygroup_find(self.raw(), func_id, stack_raw)); } } + /// A method that creates a new group with the specified component names. + /// + /// # Arguments + /// + /// * `components` - A vector listing the names of the components to include in the group. + /// + /// # Returns + /// + /// * `Group` - The new group. pub fn new(components: &Vec<&str>) -> Group { unsafe { return Group { raw: entitygroup_new(crate::dora::Vector::from_str(components)) }; } } diff --git a/Tools/dora-rust/dora/src/dora/node.rs b/Tools/dora-rust/dora/src/dora/node.rs index 927fe9fc7..3080815e8 100644 --- a/Tools/dora-rust/dora/src/dora/node.rs +++ b/Tools/dora-rust/dora/src/dora/node.rs @@ -94,7 +94,7 @@ extern "C" { fn node_traverse_all(slf: i64, func: i32, stack: i64) -> i32; fn node_run_action(slf: i64, def: i64) -> i64; fn node_stop_all_actions(slf: i64); - fn node_perform(slf: i64, def: i64) -> i64; + fn node_perform(slf: i64, action_def: i64) -> i64; fn node_stop_action(slf: i64, action: i64); fn node_align_items_vertically(slf: i64, padding: f32) -> i64; fn node_align_items_vertically_with_size(slf: i64, size: i64, padding: f32) -> i64; @@ -109,267 +109,429 @@ extern "C" { fn node_grab_with_size(slf: i64, grid_x: i32, grid_y: i32) -> i64; fn node_stop_grab(slf: i64); fn node_set_transform_target_null(slf: i64); - fn node_slot(slf: i64, name: i64, func: i32, stack: i64) -> i32; - fn node_gslot(slf: i64, name: i64, func: i32, stack: i64) -> i32; + fn node_slot(slf: i64, event_name: i64, func: i32, stack: i64); + fn node_gslot(slf: i64, event_name: i64, func: i32, stack: i64); fn node_new() -> i64; } use crate::dora::IObject; +/// Struct used for building a hierarchical tree structure of game objects. pub struct Node { raw: i64 } crate::dora_object!(Node); impl INode for Node { } pub trait INode: IObject { + /// Sets the order of the node in the parent's children array. fn set_order(&mut self, var: i32) { unsafe { node_set_order(self.raw(), var) }; } + /// Gets the order of the node in the parent's children array. fn get_order(&self) -> i32 { return unsafe { node_get_order(self.raw()) }; } + /// Sets the rotation angle of the node in degrees. fn set_angle(&mut self, var: f32) { unsafe { node_set_angle(self.raw(), var) }; } + /// Gets the rotation angle of the node in degrees. fn get_angle(&self) -> f32 { return unsafe { node_get_angle(self.raw()) }; } + /// Sets the X-axis rotation angle of the node in degrees. fn set_angle_x(&mut self, var: f32) { unsafe { node_set_angle_x(self.raw(), var) }; } + /// Gets the X-axis rotation angle of the node in degrees. fn get_angle_x(&self) -> f32 { return unsafe { node_get_angle_x(self.raw()) }; } + /// Sets the Y-axis rotation angle of the node in degrees. fn set_angle_y(&mut self, var: f32) { unsafe { node_set_angle_y(self.raw(), var) }; } + /// Gets the Y-axis rotation angle of the node in degrees. fn get_angle_y(&self) -> f32 { return unsafe { node_get_angle_y(self.raw()) }; } + /// Sets the X-axis scale factor of the node. fn set_scale_x(&mut self, var: f32) { unsafe { node_set_scale_x(self.raw(), var) }; } + /// Gets the X-axis scale factor of the node. fn get_scale_x(&self) -> f32 { return unsafe { node_get_scale_x(self.raw()) }; } + /// Sets the Y-axis scale factor of the node. fn set_scale_y(&mut self, var: f32) { unsafe { node_set_scale_y(self.raw(), var) }; } + /// Gets the Y-axis scale factor of the node. fn get_scale_y(&self) -> f32 { return unsafe { node_get_scale_y(self.raw()) }; } + /// Sets the X-axis position of the node. fn set_x(&mut self, var: f32) { unsafe { node_set_x(self.raw(), var) }; } + /// Gets the X-axis position of the node. fn get_x(&self) -> f32 { return unsafe { node_get_x(self.raw()) }; } + /// Sets the Y-axis position of the node. fn set_y(&mut self, var: f32) { unsafe { node_set_y(self.raw(), var) }; } + /// Gets the Y-axis position of the node. fn get_y(&self) -> f32 { return unsafe { node_get_y(self.raw()) }; } + /// Sets the Z-axis position of the node. fn set_z(&mut self, var: f32) { unsafe { node_set_z(self.raw(), var) }; } + /// Gets the Z-axis position of the node. fn get_z(&self) -> f32 { return unsafe { node_get_z(self.raw()) }; } + /// Sets the position of the node as a Vec2 object. fn set_position(&mut self, var: &crate::dora::Vec2) { unsafe { node_set_position(self.raw(), var.into_i64()) }; } + /// Gets the position of the node as a Vec2 object. fn get_position(&self) -> crate::dora::Vec2 { return unsafe { crate::dora::Vec2::from(node_get_position(self.raw())) }; } + /// Sets the X-axis skew angle of the node in degrees. fn set_skew_x(&mut self, var: f32) { unsafe { node_set_skew_x(self.raw(), var) }; } + /// Gets the X-axis skew angle of the node in degrees. fn get_skew_x(&self) -> f32 { return unsafe { node_get_skew_x(self.raw()) }; } + /// Sets the Y-axis skew angle of the node in degrees. fn set_skew_y(&mut self, var: f32) { unsafe { node_set_skew_y(self.raw(), var) }; } + /// Gets the Y-axis skew angle of the node in degrees. fn get_skew_y(&self) -> f32 { return unsafe { node_get_skew_y(self.raw()) }; } + /// Sets whether the node is visible. fn set_visible(&mut self, var: bool) { unsafe { node_set_visible(self.raw(), if var { 1 } else { 0 }) }; } + /// Gets whether the node is visible. fn is_visible(&self) -> bool { return unsafe { node_is_visible(self.raw()) != 0 }; } + /// Sets the anchor point of the node as a Vec2 object. fn set_anchor(&mut self, var: &crate::dora::Vec2) { unsafe { node_set_anchor(self.raw(), var.into_i64()) }; } + /// Gets the anchor point of the node as a Vec2 object. fn get_anchor(&self) -> crate::dora::Vec2 { return unsafe { crate::dora::Vec2::from(node_get_anchor(self.raw())) }; } + /// Sets the width of the node. fn set_width(&mut self, var: f32) { unsafe { node_set_width(self.raw(), var) }; } + /// Gets the width of the node. fn get_width(&self) -> f32 { return unsafe { node_get_width(self.raw()) }; } + /// Sets the height of the node. fn set_height(&mut self, var: f32) { unsafe { node_set_height(self.raw(), var) }; } + /// Gets the height of the node. fn get_height(&self) -> f32 { return unsafe { node_get_height(self.raw()) }; } + /// Sets the size of the node as a Size object. fn set_size(&mut self, var: &crate::dora::Size) { unsafe { node_set_size(self.raw(), var.into_i64()) }; } + /// Gets the size of the node as a Size object. fn get_size(&self) -> crate::dora::Size { return unsafe { crate::dora::Size::from(node_get_size(self.raw())) }; } + /// Sets the tag of the node as a string. fn set_tag(&mut self, var: &str) { unsafe { node_set_tag(self.raw(), crate::dora::from_string(var)) }; } + /// Gets the tag of the node as a string. fn get_tag(&self) -> String { return unsafe { crate::dora::to_string(node_get_tag(self.raw())) }; } + /// Sets the opacity of the node, should be 0 to 1.0. fn set_opacity(&mut self, var: f32) { unsafe { node_set_opacity(self.raw(), var) }; } + /// Gets the opacity of the node, should be 0 to 1.0. fn get_opacity(&self) -> f32 { return unsafe { node_get_opacity(self.raw()) }; } + /// Sets the color of the node as a Color object. fn set_color(&mut self, var: &crate::dora::Color) { unsafe { node_set_color(self.raw(), var.to_argb() as i32) }; } + /// Gets the color of the node as a Color object. fn get_color(&self) -> crate::dora::Color { return unsafe { crate::dora::Color::from(node_get_color(self.raw())) }; } + /// Sets the color of the node as a Color3 object. fn set_color3(&mut self, var: &crate::dora::Color3) { unsafe { node_set_color3(self.raw(), var.to_rgb() as i32) }; } + /// Gets the color of the node as a Color3 object. fn get_color3(&self) -> crate::dora::Color3 { return unsafe { crate::dora::Color3::from(node_get_color3(self.raw())) }; } + /// Sets whether to pass the opacity value to child nodes. fn set_pass_opacity(&mut self, var: bool) { unsafe { node_set_pass_opacity(self.raw(), if var { 1 } else { 0 }) }; } + /// Gets whether to pass the opacity value to child nodes. fn is_pass_opacity(&self) -> bool { return unsafe { node_is_pass_opacity(self.raw()) != 0 }; } + /// Sets whether to pass the color value to child nodes. fn set_pass_color3(&mut self, var: bool) { unsafe { node_set_pass_color3(self.raw(), if var { 1 } else { 0 }) }; } + /// Gets whether to pass the color value to child nodes. fn is_pass_color3(&self) -> bool { return unsafe { node_is_pass_color3(self.raw()) != 0 }; } + /// Sets the target node acts as a parent node for transforming this node. fn set_transform_target(&mut self, var: &dyn crate::dora::INode) { unsafe { node_set_transform_target(self.raw(), var.raw()) }; } + /// Gets the target node acts as a parent node for transforming this node. fn get_transform_target(&self) -> Option { return unsafe { crate::dora::Node::from(node_get_transform_target(self.raw())) }; } + /// Sets the scheduler used for scheduling update and action callbacks. fn set_scheduler(&mut self, var: &crate::dora::Scheduler) { unsafe { node_set_scheduler(self.raw(), var.raw()) }; } + /// Gets the scheduler used for scheduling update and action callbacks. fn get_scheduler(&self) -> crate::dora::Scheduler { return unsafe { crate::dora::Scheduler::from(node_get_scheduler(self.raw())).unwrap() }; } + /// Gets the children of the node as an Array object, could be None. fn get_children(&self) -> Option { return unsafe { crate::dora::Array::from(node_get_children(self.raw())) }; } + /// Gets the parent of the node, could be None. fn get_parent(&self) -> Option { return unsafe { crate::dora::Node::from(node_get_parent(self.raw())) }; } + /// Gets the bounding box of the node as a Rect object. fn get_bounding_box(&self) -> crate::dora::Rect { return unsafe { crate::dora::Rect::from(node_get_bounding_box(self.raw())) }; } + /// Gets whether the node is currently running in a scene tree. fn is_running(&self) -> bool { return unsafe { node_is_running(self.raw()) != 0 }; } + /// Gets whether the node is currently scheduling a function or a coroutine for updates. fn is_scheduled(&self) -> bool { return unsafe { node_is_scheduled(self.raw()) != 0 }; } + /// Gets the number of actions currently running on the node. fn get_action_count(&self) -> i32 { return unsafe { node_get_action_count(self.raw()) }; } + /// Gets additional data stored on the node as a Dictionary object. fn get_data(&self) -> crate::dora::Dictionary { return unsafe { crate::dora::Dictionary::from(node_get_data(self.raw())).unwrap() }; } + /// Sets whether touch events are enabled on the node. fn set_touch_enabled(&mut self, var: bool) { unsafe { node_set_touch_enabled(self.raw(), if var { 1 } else { 0 }) }; } + /// Gets whether touch events are enabled on the node. fn is_touch_enabled(&self) -> bool { return unsafe { node_is_touch_enabled(self.raw()) != 0 }; } + /// Sets whether the node should swallow touch events. fn set_swallow_touches(&mut self, var: bool) { unsafe { node_set_swallow_touches(self.raw(), if var { 1 } else { 0 }) }; } + /// Gets whether the node should swallow touch events. fn is_swallow_touches(&self) -> bool { return unsafe { node_is_swallow_touches(self.raw()) != 0 }; } + /// Sets whether the node should swallow mouse wheel events. fn set_swallow_mouse_wheel(&mut self, var: bool) { unsafe { node_set_swallow_mouse_wheel(self.raw(), if var { 1 } else { 0 }) }; } + /// Gets whether the node should swallow mouse wheel events. fn is_swallow_mouse_wheel(&self) -> bool { return unsafe { node_is_swallow_mouse_wheel(self.raw()) != 0 }; } + /// Sets whether keyboard events are enabled on the node. fn set_keyboard_enabled(&mut self, var: bool) { unsafe { node_set_keyboard_enabled(self.raw(), if var { 1 } else { 0 }) }; } + /// Gets whether keyboard events are enabled on the node. fn is_keyboard_enabled(&self) -> bool { return unsafe { node_is_keyboard_enabled(self.raw()) != 0 }; } + /// Sets whether controller events are enabled on the node. fn set_controller_enabled(&mut self, var: bool) { unsafe { node_set_controller_enabled(self.raw(), if var { 1 } else { 0 }) }; } + /// Gets whether controller events are enabled on the node. fn is_controller_enabled(&self) -> bool { return unsafe { node_is_controller_enabled(self.raw()) != 0 }; } + /// Sets whether to group the node's rendering with all its recursive children. fn set_render_group(&mut self, var: bool) { unsafe { node_set_render_group(self.raw(), if var { 1 } else { 0 }) }; } + /// Gets whether to group the node's rendering with all its recursive children. fn is_render_group(&self) -> bool { return unsafe { node_is_render_group(self.raw()) != 0 }; } + /// Sets the rendering order number for group rendering. Nodes with lower rendering orders are rendered earlier. fn set_render_order(&mut self, var: i32) { unsafe { node_set_render_order(self.raw(), var) }; } + /// Gets the rendering order number for group rendering. Nodes with lower rendering orders are rendered earlier. fn get_render_order(&self) -> i32 { return unsafe { node_get_render_order(self.raw()) }; } + /// Adds a child node to the current node. + /// + /// # Arguments + /// + /// * `child` - The child node to add. + /// * `order` - The drawing order of the child node. + /// * `tag` - The tag of the child node. fn add_child_with_order_tag(&mut self, child: &dyn crate::dora::INode, order: i32, tag: &str) { unsafe { node_add_child_with_order_tag(self.raw(), child.raw(), order, crate::dora::from_string(tag)); } } + /// Adds a child node to the current node. + /// + /// # Arguments + /// + /// * `child` - The child node to add. + /// * `order` - The drawing order of the child node. fn add_child_with_order(&mut self, child: &dyn crate::dora::INode, order: i32) { unsafe { node_add_child_with_order(self.raw(), child.raw(), order); } } + /// Adds a child node to the current node. + /// + /// # Arguments + /// + /// * `child` - The child node to add. fn add_child(&mut self, child: &dyn crate::dora::INode) { unsafe { node_add_child(self.raw(), child.raw()); } } + /// Adds the current node to a parent node. + /// + /// # Arguments + /// + /// * `parent` - The parent node to add the current node to. + /// * `order` - The drawing order of the current node. + /// * `tag` - The tag of the current node. + /// + /// # Returns + /// + /// * `Node` - The current node. fn add_to_with_order_tag(&mut self, parent: &dyn crate::dora::INode, order: i32, tag: &str) -> crate::dora::Node { unsafe { return crate::dora::Node::from(node_add_to_with_order_tag(self.raw(), parent.raw(), order, crate::dora::from_string(tag))).unwrap(); } } + /// Adds the current node to a parent node. + /// + /// # Arguments + /// + /// * `parent` - The parent node to add the current node to. + /// * `order` - The drawing order of the current node. + /// + /// # Returns + /// + /// * `Node` - The current node. fn add_to_with_order(&mut self, parent: &dyn crate::dora::INode, order: i32) -> crate::dora::Node { unsafe { return crate::dora::Node::from(node_add_to_with_order(self.raw(), parent.raw(), order)).unwrap(); } } + /// Adds the current node to a parent node. + /// + /// # Arguments + /// + /// * `parent` - The parent node to add the current node to. + /// + /// # Returns + /// + /// * `Node` - The current node. fn add_to(&mut self, parent: &dyn crate::dora::INode) -> crate::dora::Node { unsafe { return crate::dora::Node::from(node_add_to(self.raw(), parent.raw())).unwrap(); } } + /// Removes a child node from the current node. + /// + /// # Arguments + /// + /// * `child` - The child node to remove. + /// * `cleanup` - Whether to cleanup the child node. fn remove_child(&mut self, child: &dyn crate::dora::INode, cleanup: bool) { unsafe { node_remove_child(self.raw(), child.raw(), if cleanup { 1 } else { 0 }); } } + /// Removes a child node from the current node by tag. + /// + /// # Arguments + /// + /// * `tag` - The tag of the child node to remove. + /// * `cleanup` - Whether to cleanup the child node. fn remove_child_by_tag(&mut self, tag: &str, cleanup: bool) { unsafe { node_remove_child_by_tag(self.raw(), crate::dora::from_string(tag), if cleanup { 1 } else { 0 }); } } + /// Removes all child nodes from the current node. + /// + /// # Arguments + /// + /// * `cleanup` - Whether to cleanup the child nodes. fn remove_all_children(&mut self, cleanup: bool) { unsafe { node_remove_all_children(self.raw(), if cleanup { 1 } else { 0 }); } } + /// Removes the current node from its parent node. + /// + /// # Arguments + /// + /// * `cleanup` - Whether to cleanup the current node. fn remove_from_parent(&mut self, cleanup: bool) { unsafe { node_remove_from_parent(self.raw(), if cleanup { 1 } else { 0 }); } } + /// Moves the current node to a new parent node without triggering node events. + /// + /// # Arguments + /// + /// * `parent` - The new parent node to move the current node to. fn move_to_parent(&mut self, parent: &dyn crate::dora::INode) { unsafe { node_move_to_parent(self.raw(), parent.raw()); } } + /// Cleans up the current node. fn cleanup(&mut self) { unsafe { node_cleanup(self.raw()); } } + /// Gets a child node by tag. + /// + /// # Arguments + /// + /// * `tag` - The tag of the child node to get. + /// + /// # Returns + /// + /// * `Option` - The child node, or `None` if not found. fn get_child_by_tag(&mut self, tag: &str) -> Option { unsafe { return crate::dora::Node::from(node_get_child_by_tag(self.raw(), crate::dora::from_string(tag))); } } + /// Schedules a function to be called every frame. + /// + /// # Arguments + /// + /// * `func` - The function to be called. If the function returns `true`, it will not be called again. fn schedule(&mut self, mut func: Box bool>) { let mut stack = crate::dora::CallStack::new(); let stack_raw = stack.raw(); @@ -379,15 +541,43 @@ pub trait INode: IObject { })); unsafe { node_schedule(self.raw(), func_id, stack_raw); } } + /// Unschedules the current node's scheduled function. fn unschedule(&mut self) { unsafe { node_unschedule(self.raw()); } } + /// Converts a point from world space to node space. + /// + /// # Arguments + /// + /// * `world_point` - The point in world space, represented by a Vec2 object. + /// + /// # Returns + /// + /// * `Vec2` - The converted point in world space. fn convert_to_node_space(&mut self, world_point: &crate::dora::Vec2) -> crate::dora::Vec2 { unsafe { return crate::dora::Vec2::from(node_convert_to_node_space(self.raw(), world_point.into_i64())); } } + /// Converts a point from node space to world space. + /// + /// # Arguments + /// + /// * `node_point` - The point in node space, represented by a Vec2 object. + /// + /// # Returns + /// + /// * `Vec2` - The converted point in world space. fn convert_to_world_space(&mut self, node_point: &crate::dora::Vec2) -> crate::dora::Vec2 { unsafe { return crate::dora::Vec2::from(node_convert_to_world_space(self.raw(), node_point.into_i64())); } } + /// Converts a point from node space to world space. + /// + /// # Arguments + /// + /// * `node_point` - The point in node space, represented by a Vec2 object. + /// + /// # Returns + /// + /// * `Vec2` - The converted point in world space. fn convert_to_window_space(&mut self, node_point: &crate::dora::Vec2, mut callback: Box) { let mut stack = crate::dora::CallStack::new(); let stack_raw = stack.raw(); @@ -396,6 +586,15 @@ pub trait INode: IObject { })); unsafe { node_convert_to_window_space(self.raw(), node_point.into_i64(), func_id, stack_raw); } } + /// Calls the given function for each child node of this node. + /// + /// # Arguments + /// + /// * `func` - The function to call for each child node. The function should return a boolean value indicating whether to continue the iteration. Return true to stop iteration. + /// + /// # Returns + /// + /// * `bool` - `false` if all children have been visited, `true` if the iteration was interrupted by the function. fn each_child(&mut self, mut func: Box bool>) -> bool { let mut stack = crate::dora::CallStack::new(); let stack_raw = stack.raw(); @@ -405,6 +604,15 @@ pub trait INode: IObject { })); unsafe { return node_each_child(self.raw(), func_id, stack_raw) != 0; } } + /// Traverses the node hierarchy starting from this node and calls the given function for each visited node. The nodes without `TraverseEnabled` flag are not visited. + /// + /// # Arguments + /// + /// * `func` - The function to call for each visited node. The function should return a boolean value indicating whether to continue the traversal. Return true to stop iteration. + /// + /// # Returns + /// + /// * `bool` - `false` if all nodes have been visited, `true` if the traversal was interrupted by the function. fn traverse(&mut self, mut func: Box bool>) -> bool { let mut stack = crate::dora::CallStack::new(); let stack_raw = stack.raw(); @@ -414,6 +622,15 @@ pub trait INode: IObject { })); unsafe { return node_traverse(self.raw(), func_id, stack_raw) != 0; } } + /// Traverses the entire node hierarchy starting from this node and calls the given function for each visited node. + /// + /// # Arguments + /// + /// * `func` - The function to call for each visited node. The function should return a boolean value indicating whether to continue the traversal. + /// + /// # Returns + /// + /// * `bool` - `false` if all nodes have been visited, `true` if the traversal was interrupted by the function. fn traverse_all(&mut self, mut func: Box bool>) -> bool { let mut stack = crate::dora::CallStack::new(); let stack_raw = stack.raw(); @@ -423,72 +640,190 @@ pub trait INode: IObject { })); unsafe { return node_traverse_all(self.raw(), func_id, stack_raw) != 0; } } + /// Runs an action defined by the given action definition on this node. + /// + /// # Arguments + /// + /// * `action_def` - The action definition to run. + /// + /// # Returns + /// + /// * `f64` - The duration of the newly running action in seconds. fn run_action(&mut self, def: &crate::dora::ActionDef) -> Option { unsafe { return crate::dora::Action::from(node_run_action(self.raw(), def.raw())); } } + /// Stops all actions running on this node. fn stop_all_actions(&mut self) { unsafe { node_stop_all_actions(self.raw()); } } - fn perform(&mut self, def: &crate::dora::ActionDef) -> Option { - unsafe { return crate::dora::Action::from(node_perform(self.raw(), def.raw())); } - } + /// Runs an action defined by the given action definition right after clearing all the previous running actions. + /// + /// # Arguments + /// + /// * `action_def` - The action definition to run. + /// + /// # Returns + /// + /// * `f64` - The duration of the newly running action in seconds. + fn perform(&mut self, action_def: &crate::dora::ActionDef) -> Option { + unsafe { return crate::dora::Action::from(node_perform(self.raw(), action_def.raw())); } + } + /// Stops the given action running on this node. + /// + /// # Arguments + /// + /// * `action` - The action to stop. fn stop_action(&mut self, action: &crate::dora::Action) { unsafe { node_stop_action(self.raw(), action.raw()); } } + /// Vertically aligns all child nodes within the node using the given size and padding. + /// + /// # Arguments + /// + /// * `padding` - The amount of padding to use between each child node. + /// + /// # Returns + /// + /// * `Size` - The size of the node after alignment. fn align_items_vertically(&mut self, padding: f32) -> crate::dora::Size { unsafe { return crate::dora::Size::from(node_align_items_vertically(self.raw(), padding)); } } + /// Vertically aligns all child nodes within the node using the given size and padding. + /// + /// # Arguments + /// + /// * `size` - The size to use for alignment. + /// * `padding` - The amount of padding to use between each child node. + /// + /// # Returns + /// + /// * `Size` - The size of the node after alignment. fn align_items_vertically_with_size(&mut self, size: &crate::dora::Size, padding: f32) -> crate::dora::Size { unsafe { return crate::dora::Size::from(node_align_items_vertically_with_size(self.raw(), size.into_i64(), padding)); } } + /// Horizontally aligns all child nodes within the node using the given size and padding. + /// + /// # Arguments + /// + /// * `padding` - The amount of padding to use between each child node. + /// + /// # Returns + /// + /// * `Size` - The size of the node after alignment. fn align_items_horizontally(&mut self, padding: f32) -> crate::dora::Size { unsafe { return crate::dora::Size::from(node_align_items_horizontally(self.raw(), padding)); } } + /// Horizontally aligns all child nodes within the node using the given size and padding. + /// + /// # Arguments + /// + /// * `size` - The size to hint for alignment. + /// * `padding` - The amount of padding to use between each child node. + /// + /// # Returns + /// + /// * `Size` - The size of the node after alignment. fn align_items_horizontally_with_size(&mut self, size: &crate::dora::Size, padding: f32) -> crate::dora::Size { unsafe { return crate::dora::Size::from(node_align_items_horizontally_with_size(self.raw(), size.into_i64(), padding)); } } + /// Aligns all child nodes within the node using the given size and padding. + /// + /// # Arguments + /// + /// * `padding` - The amount of padding to use between each child node. + /// + /// # Returns + /// + /// * `Size` - The size of the node after alignment. fn align_items(&mut self, padding: f32) -> crate::dora::Size { unsafe { return crate::dora::Size::from(node_align_items(self.raw(), padding)); } } + /// Aligns all child nodes within the node using the given size and padding. + /// + /// # Arguments + /// + /// * `size` - The size to use for alignment. + /// * `padding` - The amount of padding to use between each child node. + /// + /// # Returns + /// + /// * `Size` - The size of the node after alignment. fn align_items_with_size(&mut self, size: &crate::dora::Size, padding: f32) -> crate::dora::Size { unsafe { return crate::dora::Size::from(node_align_items_with_size(self.raw(), size.into_i64(), padding)); } } + /// Moves and changes child nodes' visibility based on their position in parent's area. + /// + /// # Arguments + /// + /// * `delta` - The distance to move its children, represented by a Vec2 object. fn move_and_cull_items(&mut self, delta: &crate::dora::Vec2) { unsafe { node_move_and_cull_items(self.raw(), delta.into_i64()); } } + /// Attaches the input method editor (IME) to the node. + /// Makes node recieving "AttachIME", "DetachIME", "TextInput", "TextEditing" events. fn attach_ime(&mut self) { unsafe { node_attach_ime(self.raw()); } } + /// Detaches the input method editor (IME) from the node. fn detach_ime(&mut self) { unsafe { node_detach_ime(self.raw()); } } + /// Creates a texture grabber for the specified node. + /// + /// # Returns + /// + /// * `Grabber` - A Grabber object. fn grab(&mut self) -> crate::dora::Grabber { unsafe { return crate::dora::Grabber::from(node_grab(self.raw())).unwrap(); } } + /// Creates a texture grabber for the specified node with a specified grid size. + /// + /// # Arguments + /// + /// * `grid_x` - The number of horizontal grid cells to divide the grabber into. + /// * `grid_y` - The number of vertical grid cells to divide the grabber into. + /// + /// # Returns + /// + /// * `Grabber` - A Grabber object. fn grab_with_size(&mut self, grid_x: i32, grid_y: i32) -> crate::dora::Grabber { unsafe { return crate::dora::Grabber::from(node_grab_with_size(self.raw(), grid_x, grid_y)).unwrap(); } } + /// Removes the texture grabber for the specified node. fn stop_grab(&mut self) { unsafe { node_stop_grab(self.raw()); } } + /// Removes the transform target for the specified node. fn set_transform_target_null(&mut self) { unsafe { node_set_transform_target_null(self.raw()); } } - fn slot(&mut self, name: &str, mut func: Box) -> bool { + /// Associates the given handler function with the node event. + /// + /// # Arguments + /// + /// * `event_name` - The name of the node event. + /// * `handler` - The handler function to associate with the node event. + fn slot(&mut self, event_name: &str, mut func: Box) { let mut stack = crate::dora::CallStack::new(); let stack_raw = stack.raw(); let func_id = crate::dora::push_function(Box::new(move || { func(&mut stack) })); - unsafe { return node_slot(self.raw(), crate::dora::from_string(name), func_id, stack_raw) != 0; } - } - fn gslot(&mut self, name: &str, mut func: Box) -> bool { + unsafe { node_slot(self.raw(), crate::dora::from_string(event_name), func_id, stack_raw); } + } + /// Associates the given handler function with a global event. + /// + /// # Arguments + /// + /// * `event_name` - The name of the global event. + /// * `handler` - The handler function to associate with the event. + fn gslot(&mut self, event_name: &str, mut func: Box) { let mut stack = crate::dora::CallStack::new(); let stack_raw = stack.raw(); let func_id = crate::dora::push_function(Box::new(move || { func(&mut stack) })); - unsafe { return node_gslot(self.raw(), crate::dora::from_string(name), func_id, stack_raw) != 0; } + unsafe { node_gslot(self.raw(), crate::dora::from_string(event_name), func_id, stack_raw); } } } impl Node { @@ -500,6 +835,7 @@ impl Node { } }) } + /// Creates a new instance of the `Node` struct. pub fn new() -> Node { unsafe { return Node { raw: node_new() }; } } diff --git a/Tools/dora-rust/dora/src/dora/observer.rs b/Tools/dora-rust/dora/src/dora/observer.rs index d39d39c77..06d12c1c9 100644 --- a/Tools/dora-rust/dora/src/dora/observer.rs +++ b/Tools/dora-rust/dora/src/dora/observer.rs @@ -3,6 +3,7 @@ extern "C" { fn entityobserver_new(event: i32, components: i64) -> i64; } use crate::dora::IObject; +/// A struct representing an observer of entity changes in the game systems. pub struct Observer { raw: i64 } crate::dora_object!(Observer); impl Observer { @@ -14,6 +15,16 @@ impl Observer { } }) } + /// A method that creates a new observer with the specified component filter and action to watch for. + /// + /// # Arguments + /// + /// * `event` - The type of event to watch for. + /// * `components` - A vector listing the names of the components to filter entities by. + /// + /// # Returns + /// + /// * `Observer` - The new observer. pub fn new(event: crate::dora::EntityEvent, components: &Vec<&str>) -> Observer { unsafe { return Observer { raw: entityobserver_new(event as i32, crate::dora::Vector::from_str(components)) }; } } diff --git a/Tools/dora-rust/dora/src/dora/pass.rs b/Tools/dora-rust/dora/src/dora/pass.rs index a749b1f1e..420a7570a 100644 --- a/Tools/dora-rust/dora/src/dora/pass.rs +++ b/Tools/dora-rust/dora/src/dora/pass.rs @@ -8,6 +8,7 @@ extern "C" { fn pass_new(vert_shader: i64, frag_shader: i64) -> i64; } use crate::dora::IObject; +/// A struct representing a shader pass. pub struct Pass { raw: i64 } crate::dora_object!(Pass); impl Pass { @@ -19,21 +20,63 @@ impl Pass { } }) } + /// Sets whether this Pass should be a grab pass. + /// A grab pass will render a portion of game scene into a texture frame buffer. + /// Then use this texture frame buffer as an input for next render pass. pub fn set_grab_pass(&mut self, var: bool) { unsafe { pass_set_grab_pass(self.raw(), if var { 1 } else { 0 }) }; } + /// Gets whether this Pass should be a grab pass. + /// A grab pass will render a portion of game scene into a texture frame buffer. + /// Then use this texture frame buffer as an input for next render pass. pub fn is_grab_pass(&self) -> bool { return unsafe { pass_is_grab_pass(self.raw()) != 0 }; } + /// Sets the value of shader parameters. + /// + /// # Arguments + /// + /// * `name` - The name of the parameter to set. + /// * `var` - The numeric value to set. pub fn set(&mut self, name: &str, var: f32) { unsafe { pass_set(self.raw(), crate::dora::from_string(name), var); } } + /// Sets the values of shader parameters. + /// + /// # Arguments + /// + /// * `name` - The name of the parameter to set. + /// * `var1` - The first numeric value to set. + /// * `var2` - An optional second numeric value to set. + /// * `var3` - An optional third numeric value to set. + /// * `var4` - An optional fourth numeric value to set. pub fn set_vec4(&mut self, name: &str, var_1: f32, var_2: f32, var_3: f32, var_4: f32) { unsafe { pass_set_vec4(self.raw(), crate::dora::from_string(name), var_1, var_2, var_3, var_4); } } + /// Another function that sets the values of shader parameters. + /// + /// Works the same as: + /// pass.set("varName", color.r / 255.0, color.g / 255.0, color.b / 255.0, color.opacity); + /// + /// # Arguments + /// + /// * `name` - The name of the parameter to set. + /// * `var` - The Color object to set. pub fn set_color(&mut self, name: &str, var: &crate::dora::Color) { unsafe { pass_set_color(self.raw(), crate::dora::from_string(name), var.to_argb() as i32); } } + /// Creates a new Pass object. + /// + /// # Arguments + /// + /// * `vert_shader` - The vertex shader in binary form file string. + /// * `frag_shader` - The fragment shader file string. A shader file string must be one of the formats: + /// * "builtin:" + theBuiltinShaderName + /// * "Shader/compiled_shader_file.bin" + /// + /// # Returns + /// + /// * `Pass` - A new Pass object. pub fn new(vert_shader: &str, frag_shader: &str) -> Pass { unsafe { return Pass { raw: pass_new(crate::dora::from_string(vert_shader), crate::dora::from_string(frag_shader)) }; } } diff --git a/Tools/dora-rust/dora/src/dora/path.rs b/Tools/dora-rust/dora/src/dora/path.rs index 30de088dc..8ca61f71e 100644 --- a/Tools/dora-rust/dora/src/dora/path.rs +++ b/Tools/dora-rust/dora/src/dora/path.rs @@ -6,7 +6,9 @@ extern "C" { fn path_get_relative(path: i64, target: i64) -> i64; fn path_replace_ext(path: i64, new_ext: i64) -> i64; fn path_replace_filename(path: i64, new_file: i64) -> i64; + fn path_concat(paths: i64) -> i64; } +/// Helper struct for file path operations. pub struct Path { raw: i64 } impl Path { pub fn from(raw: i64) -> Option { @@ -16,25 +18,135 @@ impl Path { } } pub fn raw(&self) -> i64 { self.raw } + /// Extracts the file extension from a given file path. + /// + /// # Example + /// + /// Input: "/a/b/c.TXT" Output: "txt" + /// + /// # Arguments + /// + /// * `path` - The input file path. + /// + /// # Returns + /// + /// * `String` - The extension of the input file. pub fn get_ext(path: &str) -> String { unsafe { return crate::dora::to_string(path_get_ext(crate::dora::from_string(path))); } } + /// Extracts the parent path from a given file path. + /// + /// # Example + /// + /// Input: "/a/b/c.TXT" Output: "/a/b" + /// + /// # Arguments + /// + /// * `path` - The input file path. + /// + /// # Returns + /// + /// * `String` - The parent path of the input file. pub fn get_path(path: &str) -> String { unsafe { return crate::dora::to_string(path_get_path(crate::dora::from_string(path))); } } + /// Extracts the file name without extension from a given file path. + /// + /// # Example + /// + /// Input: "/a/b/c.TXT" Output: "c" + /// + /// # Arguments + /// + /// * `path` - The input file path. + /// + /// # Returns + /// + /// * `String` - The name of the input file without extension. pub fn get_name(path: &str) -> String { unsafe { return crate::dora::to_string(path_get_name(crate::dora::from_string(path))); } } + /// Extracts the file name from a given file path. + /// + /// # Example + /// + /// Input: "/a/b/c.TXT" Output: "c.TXT" + /// + /// # Arguments + /// + /// * `path` - The input file path. + /// + /// # Returns + /// + /// * `String` - The name of the input file. pub fn get_filename(path: &str) -> String { unsafe { return crate::dora::to_string(path_get_filename(crate::dora::from_string(path))); } } + /// Computes the relative path from the target file to the input file. + /// + /// # Example + /// + /// Input: "/a/b/c.TXT", base: "/a" Output: "b/c.TXT" + /// + /// # Arguments + /// + /// * `path` - The input file path. + /// * `base` - The target file path. + /// + /// # Returns + /// + /// * `String` - The relative path from the input file to the target file. pub fn get_relative(path: &str, target: &str) -> String { unsafe { return crate::dora::to_string(path_get_relative(crate::dora::from_string(path), crate::dora::from_string(target))); } } + /// Changes the file extension in a given file path. + /// + /// # Example + /// + /// Input: "/a/b/c.TXT", "lua" Output: "/a/b/c.lua" + /// + /// # Arguments + /// + /// * `path` - The input file path. + /// * `new_ext` - The new file extension to replace the old one. + /// + /// # Returns + /// + /// * `String` - The new file path. pub fn replace_ext(path: &str, new_ext: &str) -> String { unsafe { return crate::dora::to_string(path_replace_ext(crate::dora::from_string(path), crate::dora::from_string(new_ext))); } } + /// Changes the filename in a given file path. + /// + /// # Example + /// + /// Input: "/a/b/c.TXT", "d" Output: "/a/b/d.TXT" + /// + /// # Arguments + /// + /// * `path` - The input file path. + /// * `new_file` - The new filename to replace the old one. + /// + /// # Returns + /// + /// * `String` - The new file path. pub fn replace_filename(path: &str, new_file: &str) -> String { unsafe { return crate::dora::to_string(path_replace_filename(crate::dora::from_string(path), crate::dora::from_string(new_file))); } } + /// Joins the given segments into a new file path. + /// + /// # Example + /// + /// Input: "a", "b", "c.TXT" Output: "a/b/c.TXT" + /// + /// # Arguments + /// + /// * `segments` - The segments to be joined as a new file path. + /// + /// # Returns + /// + /// * `String` - The new file path. + pub fn concat(paths: &Vec<&str>) -> String { + unsafe { return crate::dora::to_string(path_concat(crate::dora::Vector::from_str(paths))); } + } } \ No newline at end of file diff --git a/Tools/dora-rust/dora/src/dora/rect.rs b/Tools/dora-rust/dora/src/dora/rect.rs index c29208674..789d4309b 100644 --- a/Tools/dora-rust/dora/src/dora/rect.rs +++ b/Tools/dora-rust/dora/src/dora/rect.rs @@ -36,10 +36,20 @@ extern "C" { fn rect_zero() -> i64; } impl PartialEq for Rect { + /// Checks if two rectangles are equal. + /// + /// # Arguments + /// + /// * `other` - The other rectangle to compare to, represented by a Rect object. + /// + /// # Returns + /// + /// * `bool` - Whether or not the two rectangles are equal. fn eq(&self, other: &Self) -> bool { unsafe { return rect_equals(self.raw(), other.raw()) != 0 } } } +/// A rectangle object with a left-bottom origin position and a size. pub struct Rect { raw: i64 } impl Drop for Rect { fn drop(&mut self) { unsafe { rect_release(self.raw); } } @@ -51,102 +61,167 @@ impl Rect { pub fn from(raw: i64) -> Rect { Rect { raw: raw } } + /// Sets the position of the origin of the rectangle. pub fn set_origin(&mut self, var: &crate::dora::Vec2) { unsafe { rect_set_origin(self.raw(), var.into_i64()) }; } + /// Gets the position of the origin of the rectangle. pub fn get_origin(&self) -> crate::dora::Vec2 { return unsafe { crate::dora::Vec2::from(rect_get_origin(self.raw())) }; } + /// Sets the dimensions of the rectangle. pub fn set_size(&mut self, var: &crate::dora::Size) { unsafe { rect_set_size(self.raw(), var.into_i64()) }; } + /// Gets the dimensions of the rectangle. pub fn get_size(&self) -> crate::dora::Size { return unsafe { crate::dora::Size::from(rect_get_size(self.raw())) }; } + /// Sets the x-coordinate of the origin of the rectangle. pub fn set_x(&mut self, var: f32) { unsafe { rect_set_x(self.raw(), var) }; } + /// Gets the x-coordinate of the origin of the rectangle. pub fn get_x(&self) -> f32 { return unsafe { rect_get_x(self.raw()) }; } + /// Sets the y-coordinate of the origin of the rectangle. pub fn set_y(&mut self, var: f32) { unsafe { rect_set_y(self.raw(), var) }; } + /// Gets the y-coordinate of the origin of the rectangle. pub fn get_y(&self) -> f32 { return unsafe { rect_get_y(self.raw()) }; } + /// Sets the width of the rectangle. pub fn set_width(&mut self, var: f32) { unsafe { rect_set_width(self.raw(), var) }; } + /// Gets the width of the rectangle. pub fn get_width(&self) -> f32 { return unsafe { rect_get_width(self.raw()) }; } + /// Sets the height of the rectangle. pub fn set_height(&mut self, var: f32) { unsafe { rect_set_height(self.raw(), var) }; } + /// Gets the height of the rectangle. pub fn get_height(&self) -> f32 { return unsafe { rect_get_height(self.raw()) }; } + /// Sets the left edge in x-axis of the rectangle. pub fn set_left(&mut self, var: f32) { unsafe { rect_set_left(self.raw(), var) }; } + /// Gets the left edge in x-axis of the rectangle. pub fn get_left(&self) -> f32 { return unsafe { rect_get_left(self.raw()) }; } + /// Sets the right edge in x-axis of the rectangle. pub fn set_right(&mut self, var: f32) { unsafe { rect_set_right(self.raw(), var) }; } + /// Gets the right edge in x-axis of the rectangle. pub fn get_right(&self) -> f32 { return unsafe { rect_get_right(self.raw()) }; } + /// Sets the x-coordinate of the center of the rectangle. pub fn set_center_x(&mut self, var: f32) { unsafe { rect_set_center_x(self.raw(), var) }; } + /// Gets the x-coordinate of the center of the rectangle. pub fn get_center_x(&self) -> f32 { return unsafe { rect_get_center_x(self.raw()) }; } + /// Sets the y-coordinate of the center of the rectangle. pub fn set_center_y(&mut self, var: f32) { unsafe { rect_set_center_y(self.raw(), var) }; } + /// Gets the y-coordinate of the center of the rectangle. pub fn get_center_y(&self) -> f32 { return unsafe { rect_get_center_y(self.raw()) }; } + /// Sets the bottom edge in y-axis of the rectangle. pub fn set_bottom(&mut self, var: f32) { unsafe { rect_set_bottom(self.raw(), var) }; } + /// Gets the bottom edge in y-axis of the rectangle. pub fn get_bottom(&self) -> f32 { return unsafe { rect_get_bottom(self.raw()) }; } + /// Sets the top edge in y-axis of the rectangle. pub fn set_top(&mut self, var: f32) { unsafe { rect_set_top(self.raw(), var) }; } + /// Gets the top edge in y-axis of the rectangle. pub fn get_top(&self) -> f32 { return unsafe { rect_get_top(self.raw()) }; } + /// Sets the lower bound (left-bottom) of the rectangle. pub fn set_lower_bound(&mut self, var: &crate::dora::Vec2) { unsafe { rect_set_lower_bound(self.raw(), var.into_i64()) }; } + /// Gets the lower bound (left-bottom) of the rectangle. pub fn get_lower_bound(&self) -> crate::dora::Vec2 { return unsafe { crate::dora::Vec2::from(rect_get_lower_bound(self.raw())) }; } + /// Sets the upper bound (right-top) of the rectangle. pub fn set_upper_bound(&mut self, var: &crate::dora::Vec2) { unsafe { rect_set_upper_bound(self.raw(), var.into_i64()) }; } + /// Gets the upper bound (right-top) of the rectangle. pub fn get_upper_bound(&self) -> crate::dora::Vec2 { return unsafe { crate::dora::Vec2::from(rect_get_upper_bound(self.raw())) }; } + /// Sets the properties of the rectangle. + /// + /// # Arguments + /// + /// * `x` - The x-coordinate of the origin of the rectangle. + /// * `y` - The y-coordinate of the origin of the rectangle. + /// * `width` - The width of the rectangle. + /// * `height` - The height of the rectangle. pub fn set(&mut self, x: f32, y: f32, width: f32, height: f32) { unsafe { rect_set(self.raw(), x, y, width, height); } } + /// Checks if a point is inside the rectangle. + /// + /// # Arguments + /// + /// * `point` - The point to check, represented by a Vec2 object. + /// + /// # Returns + /// + /// * `bool` - Whether or not the point is inside the rectangle. pub fn contains_point(&self, point: &crate::dora::Vec2) -> bool { unsafe { return rect_contains_point(self.raw(), point.into_i64()) != 0; } } + /// Checks if the rectangle intersects with another rectangle. + /// + /// # Arguments + /// + /// * `rect` - The other rectangle to check for intersection with, represented by a Rect object. + /// + /// # Returns + /// + /// * `bool` - Whether or not the rectangles intersect. pub fn intersects_rect(&self, rect: &crate::dora::Rect) -> bool { unsafe { return rect_intersects_rect(self.raw(), rect.raw()) != 0; } } + /// Creates a new rectangle object using a Vec2 object for the origin and a Size object for the size. + /// + /// # Arguments + /// + /// * `origin` - The origin of the rectangle, represented by a Vec2 object. + /// * `size` - The size of the rectangle, represented by a Size object. + /// + /// # Returns + /// + /// * `Rect` - A new rectangle object. pub fn new(origin: &crate::dora::Vec2, size: &crate::dora::Size) -> crate::dora::Rect { unsafe { return crate::dora::Rect::from(rect_new(origin.into_i64(), size.into_i64())); } } + /// Gets a rectangle object with all properties set to 0. pub fn zero() -> crate::dora::Rect { unsafe { return crate::dora::Rect::from(rect_zero()); } } diff --git a/Tools/dora-rust/dora/src/dora/scheduler.rs b/Tools/dora-rust/dora/src/dora/scheduler.rs index e252fa9b9..cfda8f79e 100644 --- a/Tools/dora-rust/dora/src/dora/scheduler.rs +++ b/Tools/dora-rust/dora/src/dora/scheduler.rs @@ -8,6 +8,7 @@ extern "C" { fn scheduler_new() -> i64; } use crate::dora::IObject; +/// A scheduler that manages the execution of scheduled tasks. pub struct Scheduler { raw: i64 } crate::dora_object!(Scheduler); impl Scheduler { @@ -19,18 +20,33 @@ impl Scheduler { } }) } + /// Sets the time scale factor for the scheduler. + /// This factor is applied to deltaTime that the scheduled functions will receive. pub fn set_time_scale(&mut self, var: f32) { unsafe { scheduler_set_time_scale(self.raw(), var) }; } + /// Gets the time scale factor for the scheduler. + /// This factor is applied to deltaTime that the scheduled functions will receive. pub fn get_time_scale(&self) -> f32 { return unsafe { scheduler_get_time_scale(self.raw()) }; } + /// Sets the target frame rate (in frames per second) for a fixed update mode. + /// The fixed update will ensure a constant frame rate, and the operation handled in a fixed update can use a constant delta time value. + /// It is used for preventing weird behavior of a physics engine or synchronizing some states via network communications. pub fn set_fixed_fps(&mut self, var: i32) { unsafe { scheduler_set_fixed_fps(self.raw(), var) }; } + /// Gets the target frame rate (in frames per second) for a fixed update mode. + /// The fixed update will ensure a constant frame rate, and the operation handled in a fixed update can use a constant delta time value. + /// It is used for preventing weird behavior of a physics engine or synchronizing some states via network communications. pub fn get_fixed_fps(&self) -> i32 { return unsafe { scheduler_get_fixed_fps(self.raw()) }; } + /// Schedules a function to be called every frame. + /// + /// # Arguments + /// + /// * `handler` - The function to be called. It should take a single argument of type `f64`, which represents the delta time since the last frame. If the function returns `true`, it will not be called again. pub fn schedule(&mut self, mut func: Box bool>) { let mut stack = crate::dora::CallStack::new(); let stack_raw = stack.raw(); @@ -40,6 +56,7 @@ impl Scheduler { })); unsafe { scheduler_schedule(self.raw(), func_id, stack_raw); } } + /// Creates a new Scheduler object. pub fn new() -> Scheduler { unsafe { return Scheduler { raw: scheduler_new() }; } } diff --git a/Tools/dora-rust/dora/src/dora/sprite_effect.rs b/Tools/dora-rust/dora/src/dora/sprite_effect.rs index 30c1af5a3..0feda9d56 100644 --- a/Tools/dora-rust/dora/src/dora/sprite_effect.rs +++ b/Tools/dora-rust/dora/src/dora/sprite_effect.rs @@ -5,6 +5,7 @@ extern "C" { use crate::dora::IObject; use crate::dora::IEffect; impl IEffect for SpriteEffect { } +/// A struct that is a specialization of Effect for rendering 2D sprites. pub struct SpriteEffect { raw: i64 } crate::dora_object!(SpriteEffect); impl SpriteEffect { @@ -16,6 +17,18 @@ impl SpriteEffect { } }) } + /// A method that allows you to create a new SpriteEffect object. + /// + /// # Arguments + /// + /// * `vert_shader` - The vertex shader file string. + /// * `frag_shader` - The fragment shader file string. A shader file string must be one of the formats: + /// * "builtin:" + theBuiltinShaderName + /// * "Shader/compiled_shader_file.bin" + /// + /// # Returns + /// + /// * `SpriteEffect` - A new SpriteEffect object. pub fn new(vert_shader: &str, frag_shader: &str) -> SpriteEffect { unsafe { return SpriteEffect { raw: spriteeffect_new(crate::dora::from_string(vert_shader), crate::dora::from_string(frag_shader)) }; } } diff --git a/Tools/dora-rust/dora/src/dora/view.rs b/Tools/dora-rust/dora/src/dora/view.rs index e4036cee2..0b30a0376 100644 --- a/Tools/dora-rust/dora/src/dora/view.rs +++ b/Tools/dora-rust/dora/src/dora/view.rs @@ -17,53 +17,70 @@ extern "C" { fn view_is_vsync() -> i32; } use crate::dora::IObject; +/// A struct that provides access to the 3D graphic view. pub struct View { } impl View { + /// Gets the size of the view in pixels. pub fn get_size() -> crate::dora::Size { return unsafe { crate::dora::Size::from(view_get_size()) }; } + /// Gets the standard distance of the view from the origin. pub fn get_standard_distance() -> f32 { return unsafe { view_get_standard_distance() }; } + /// Gets the aspect ratio of the view. pub fn get_aspect_ratio() -> f32 { return unsafe { view_get_aspect_ratio() }; } + /// Sets the distance to the near clipping plane. pub fn set_near_plane_distance(var: f32) { unsafe { view_set_near_plane_distance(var) }; } + /// Gets the distance to the near clipping plane. pub fn get_near_plane_distance() -> f32 { return unsafe { view_get_near_plane_distance() }; } + /// Sets the distance to the far clipping plane. pub fn set_far_plane_distance(var: f32) { unsafe { view_set_far_plane_distance(var) }; } + /// Gets the distance to the far clipping plane. pub fn get_far_plane_distance() -> f32 { return unsafe { view_get_far_plane_distance() }; } + /// Sets the field of view of the view in degrees. pub fn set_field_of_view(var: f32) { unsafe { view_set_field_of_view(var) }; } + /// Gets the field of view of the view in degrees. pub fn get_field_of_view() -> f32 { return unsafe { view_get_field_of_view() }; } + /// Sets the scale factor of the view. pub fn set_scale(var: f32) { unsafe { view_set_scale(var) }; } + /// Gets the scale factor of the view. pub fn get_scale() -> f32 { return unsafe { view_get_scale() }; } + /// Sets the post effect applied to the view. pub fn set_post_effect(var: &crate::dora::SpriteEffect) { unsafe { view_set_post_effect(var.raw()) }; } + /// Gets the post effect applied to the view. pub fn get_post_effect() -> Option { return unsafe { crate::dora::SpriteEffect::from(view_get_post_effect()) }; } + /// Removes the post effect applied to the view. pub fn set_post_effect_null() { unsafe { view_set_post_effect_null(); } } + /// Sets whether or not vertical sync is enabled. pub fn set_vsync(var: bool) { unsafe { view_set_vsync(if var { 1 } else { 0 }) }; } + /// Gets whether or not vertical sync is enabled. pub fn is_vsync() -> bool { return unsafe { view_is_vsync() != 0 }; }