diff --git a/-DCMAKE_TOOLCHAIN_FILE=/opt/pspdev/psp/share/pspdev.cmake b/-DCMAKE_TOOLCHAIN_FILE=/opt/pspdev/psp/share/pspdev.cmake new file mode 100644 index 00000000..140f70a5 --- /dev/null +++ b/-DCMAKE_TOOLCHAIN_FILE=/opt/pspdev/psp/share/pspdev.cmake @@ -0,0 +1,1703 @@ +Avoid ctest truncation of output: CTEST_FULL_OUTPUT +======================================================== +=== MAIN VARIABLES +======================================================== +CMAKE_STATIC_LIBRARY_PREFIX == "lib" +CMAKE_STATIC_LIBRARY_SUFFIX == ".a" +CMAKE_SHARED_LIBRARY_PREFIX == "lib" +CMAKE_SHARED_LIBRARY_SUFFIX == ".so" +CMAKE_SHARED_LIBRARY_ARCHIVE_SUFFIX == "" +CMAKE_SHARED_MODULE_PREFIX == "lib" +CMAKE_SHARED_MODULE_SUFFIX == ".so" + + +CMAKE_DL_LIBS == "dl" +CMAKE_LIBRARY_PATH_FLAG == "-L" +CMAKE_LINK_LIBRARY_FLAG == "-l" +CMAKE_SKIP_RPATH == "NO" +CMAKE_SYSTEM_INFO_FILE == "Platform/Linux" +CMAKE_SYSTEM_NAME == "Linux" +CMAKE_SYSTEM == "Linux-6.19.12-arch1-1" +CMAKE_C_COMPILER == "/usr/bin/cc" +CMAKE_C_COMPILER_ID == "GNU" +CMAKE_C_COMPILER_VERSION == "15.2.1" +CMAKE_C_COMPILER_ARCHITECTURE_ID == "x86_64" +CMAKE_CXX_COMPILER == "/usr/bin/c++" +CMAKE_CXX_COMPILER_ID == "GNU" +CMAKE_CXX_COMPILER_VERSION == "15.2.1" +CMAKE_CXX_COMPILER_ARCHITECTURE_ID == "x86_64" +CMAKE_COMPILER_IS_GNUCC == "1" +CMAKE_COMPILER_IS_GNUCXX == "1" + +// C shared library flag +CMAKE_SHARED_LIBRARY_C_FLAGS == "-fPIC" +CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS == "-shared" +CMAKE_SHARED_LIBRARY_LINK_FLAGS == "" +CMAKE_SHARED_LIBRARY_RUNTIME_FLAG == "" +CMAKE_SHARED_LIBRARY_RUNTIME_FLAG_SEP == "" +CMAKE_SHARED_LIBRARY_LINK_STATIC_C_FLAGS == "-Wl,-Bstatic" +CMAKE_SHARED_LIBRARY_LINK_DYNAMIC_C_FLAGS == "-Wl,-Bdynamic" + +// C shared module flags +CMAKE_SHARED_MODULE_C_FLAGS == "-fPIC" +CMAKE_SHARED_MODULE_CREATE_C_FLAGS == "-shared" +CMAKE_SHARED_MODULE_LINK_STATIC_C_FLAGS == "-Wl,-Bstatic" +CMAKE_SHARED_MODULE_LINK_DYNAMIC_C_FLAGS == "-Wl,-Bdynamic" + +// C exe flags +CMAKE_EXE_LINK_STATIC_C_FLAGS == "-Wl,-Bstatic" +CMAKE_EXE_LINK_DYNAMIC_C_FLAGS == "-Wl,-Bdynamic" + +// CXX shared library flags +CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS == "-shared" +CMAKE_SHARED_LIBRARY_CXX_FLAGS == "-fPIC" +CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS == "-rdynamic" +CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG == "-Wl,-rpath," +CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG_SEP == ":" +CMAKE_SHARED_LIBRARY_LINK_STATIC_CXX_FLAGS == "-Wl,-Bstatic" +CMAKE_SHARED_LIBRARY_LINK_DYNAMIC_CXX_FLAGS == "-Wl,-Bdynamic" + +// CXX shared module flags +CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS == "-shared" +CMAKE_SHARED_MODULE_CXX_FLAGS == "-fPIC" +CMAKE_SHARED_MODULE_LINK_STATIC_CXX_FLAGS == "-Wl,-Bstatic" +CMAKE_SHARED_MODULE_LINK_DYNAMIC_CXX_FLAGS == "-Wl,-Bdynamic" + +// CXX exe flags +CMAKE_EXE_LINK_STATIC_CXX_FLAGS == "-Wl,-Bstatic" +CMAKE_EXE_LINK_DYNAMIC_CXX_FLAGS == "-Wl,-Bdynamic" + +CMAKE_USER_MAKE_RULES_OVERRIDE == "" +CMAKE_VERBOSE_MAKEFILE == "FALSE" +CMAKE_BUILD_TYPE == "" +CMAKE_CXX_FLAGS == "" +CMAKE_CXX_FLAGS_DEBUG == "-g" +CMAKE_CXX_FLAGS_MINSIZEREL == "-Os -DNDEBUG" +CMAKE_CXX_FLAGS_RELEASE == "-O3 -DNDEBUG" +CMAKE_CXX_FLAGS_RELWITHDEBINFO == "-O2 -g -DNDEBUG" + +CMAKE_C_FLAGS == "" +CMAKE_C_FLAGS_DEBUG == "-g" +CMAKE_C_FLAGS_MINSIZEREL == "-Os -DNDEBUG" +CMAKE_C_FLAGS_RELEASE == "-O3 -DNDEBUG" +CMAKE_C_FLAGS_RELWITHDEBINFO == "-O2 -g -DNDEBUG" + +// build rules +CMAKE_CXX_CREATE_SHARED_LIBRARY == " -o " +CMAKE_CXX_CREATE_SHARED_MODULE == " -o " +CMAKE_C_CREATE_SHARED_LIBRARY == " -o " +CMAKE_C_CREATE_SHARED_MODULE == " -o " +CMAKE_CXX_CREATE_STATIC_LIBRARY == "" +CMAKE_C_CREATE_STATIC_LIBRARY == "" +CMAKE_CXX_COMPILE_OBJECT == " -o -c " +CMAKE_C_COMPILE_OBJECT == " -o -c " +CMAKE_C_LINK_EXECUTABLE == " -o " +CMAKE_CXX_LINK_EXECUTABLE == " -o " + +================================================================= +=== VARIABLES +================================================================= +CMAKE_ADDR2LINE "/usr/bin/addr2line" +CMAKE_AR "/usr/bin/ar" +CMAKE_AR "/usr/bin/ar" +CMAKE_AUTOGEN_ORIGIN_DEPENDS "ON" +CMAKE_AUTOMOC_COMPILER_PREDEFINES "ON" +CMAKE_AUTOMOC_MACRO_NAMES "Q_OBJECT;Q_GADGET;Q_NAMESPACE;Q_NAMESPACE_EXPORT" +CMAKE_AUTOMOC_PATH_PREFIX "OFF" +CMAKE_BASE_NAME "g++" +CMAKE_BINARY_DIR "/home/yourwishes/htdocs/dusk/__cmake_systeminformation" +CMAKE_BUILD_TOOL "/usr/bin/make" +CMAKE_BUILD_TYPE "" +CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert" +CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11" +CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c11" +CMAKE_C11_STANDARD__HAS_FULL_SUPPORT "ON" +CMAKE_C17_COMPILE_FEATURES "c_std_17" +CMAKE_C17_EXTENSION_COMPILE_OPTION "-std=gnu17" +CMAKE_C17_STANDARD_COMPILE_OPTION "-std=c17" +CMAKE_C23_COMPILE_FEATURES "c_std_23" +CMAKE_C23_EXTENSION_COMPILE_OPTION "-std=gnu2x" +CMAKE_C23_STANDARD_COMPILE_OPTION "-std=c2x" +CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes" +CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90" +CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90" +CMAKE_C90_STANDARD__HAS_FULL_SUPPORT "ON" +CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros" +CMAKE_C99_EXTENSION_COMPILE_OPTION "-std=gnu99" +CMAKE_C99_STANDARD_COMPILE_OPTION "-std=c99" +CMAKE_C99_STANDARD__HAS_FULL_SUPPORT "ON" +CMAKE_CFG_INTDIR "." +CMAKE_COLOR_MAKEFILE "ON" +CMAKE_COMMAND "/usr/bin/cmake" +CMAKE_COMPILER_IS_GNUCC "1" +CMAKE_COMPILER_IS_GNUCXX "1" +CMAKE_CPACK_COMMAND "/usr/bin/cpack" +CMAKE_CROSSCOMPILING "FALSE" +CMAKE_CTEST_COMMAND "/usr/bin/ctest" +CMAKE_CURRENT_BINARY_DIR "/home/yourwishes/htdocs/dusk/__cmake_systeminformation" +CMAKE_CURRENT_LIST_DIR "/home/yourwishes/htdocs/dusk/__cmake_systeminformation" +CMAKE_CURRENT_LIST_FILE "/home/yourwishes/htdocs/dusk/__cmake_systeminformation/CMakeLists.txt" +CMAKE_CURRENT_SOURCE_DIR "/home/yourwishes/htdocs/dusk/__cmake_systeminformation" +CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates" +CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=gnu++11" +CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++11" +CMAKE_CXX11_STANDARD__HAS_FULL_SUPPORT "ON" +CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates" +CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-std=gnu++14" +CMAKE_CXX14_STANDARD_COMPILE_OPTION "-std=c++14" +CMAKE_CXX14_STANDARD__HAS_FULL_SUPPORT "ON" +CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17" +CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++17" +CMAKE_CXX17_STANDARD_COMPILE_OPTION "-std=c++17" +CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20" +CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-std=gnu++20" +CMAKE_CXX20_STANDARD_COMPILE_OPTION "-std=c++20" +CMAKE_CXX23_COMPILE_FEATURES "cxx_std_23" +CMAKE_CXX23_EXTENSION_COMPILE_OPTION "-std=gnu++23" +CMAKE_CXX23_STANDARD_COMPILE_OPTION "-std=c++23" +CMAKE_CXX26_COMPILE_FEATURES "cxx_std_26" +CMAKE_CXX26_EXTENSION_COMPILE_OPTION "-std=gnu++26" +CMAKE_CXX26_STANDARD_COMPILE_OPTION "-std=c++26" +CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters" +CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98" +CMAKE_CXX98_STANDARD_COMPILE_OPTION "-std=c++98" +CMAKE_CXX98_STANDARD__HAS_FULL_SUPPORT "ON" +CMAKE_CXX_ABI_COMPILED "TRUE" +CMAKE_CXX_ARCHIVE_APPEND " q " +CMAKE_CXX_ARCHIVE_APPEND_IPO ""/usr/bin/gcc-ar" q " +CMAKE_CXX_ARCHIVE_CREATE " qc " +CMAKE_CXX_ARCHIVE_CREATE_IPO ""/usr/bin/gcc-ar" qc " +CMAKE_CXX_ARCHIVE_FINISH " " +CMAKE_CXX_ARCHIVE_FINISH_IPO ""/usr/bin/gcc-ranlib" " +CMAKE_CXX_BYTE_ORDER "LITTLE_ENDIAN" +CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "" +CMAKE_CXX_COMPILER "/usr/bin/c++" +CMAKE_CXX_COMPILER "/usr/bin/c++" +CMAKE_CXX_COMPILER_ABI "ELF" +CMAKE_CXX_COMPILER_APPLE_SYSROOT "" +CMAKE_CXX_COMPILER_AR "/usr/bin/gcc-ar" +CMAKE_CXX_COMPILER_AR "/usr/bin/gcc-ar" +CMAKE_CXX_COMPILER_ARCHITECTURE_ID "x86_64" +CMAKE_CXX_COMPILER_ARG1 "" +CMAKE_CXX_COMPILER_CLANG_RESOURCE_DIR "" +CMAKE_CXX_COMPILER_ENV_VAR "CXX" +CMAKE_CXX_COMPILER_FRONTEND_VARIANT "GNU" +CMAKE_CXX_COMPILER_ID "GNU" +CMAKE_CXX_COMPILER_ID_PLATFORM_CONTENT "#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +# elif defined(_ADI_COMPILER) +# define PLATFORM_ID "ADSP" + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__clang__) && defined(__ti__) +# if defined(__ARM_ARCH) +# define ARCHITECTURE_ID "ARM" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +# elif defined(__ADSPSHARC__) +# define ARCHITECTURE_ID "SHARC" + +# elif defined(__ADSPBLACKFIN__) +# define ARCHITECTURE_ID "Blackfin" + +#elif defined(__TASKING__) + +# if defined(__CTC__) || defined(__CPTC__) +# define ARCHITECTURE_ID "TriCore" + +# elif defined(__CMCS__) +# define ARCHITECTURE_ID "MCS" + +# elif defined(__CARM__) || defined(__CPARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__CARC__) +# define ARCHITECTURE_ID "ARC" + +# elif defined(__C51__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__CPCP__) +# define ARCHITECTURE_ID "PCP" + +# else +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__RENESAS__) +# if defined(__CCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__CCRL__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__CCRH__) +# define ARCHITECTURE_ID "RH850" + +# else +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; +" +CMAKE_CXX_COMPILER_ID_RUN "1" +CMAKE_CXX_COMPILER_ID_TEST_FLAGS "-c;--c++;--ec++;--target=arm-arm-none-eabi -mcpu=cortex-m3;-c -I__does_not_exist__" +CMAKE_CXX_COMPILER_ID_TOOL_MATCH_INDEX "2" +CMAKE_CXX_COMPILER_ID_TOOL_MATCH_REGEX " +Ld[^ +]*( +[ ]+[^ +]*)* +[ ]+([^ +]+)[^ +]*-o[^ +]*CompilerIdCXX/(\./)?(CompilerIdCXX.(framework|xctest|build/[^ +]+)/)?CompilerIdCXX[ +\"]" +CMAKE_CXX_COMPILER_ID_VENDORS "IAR" +CMAKE_CXX_COMPILER_ID_VENDOR_REGEX_IAR "IAR .+ Compiler" +CMAKE_CXX_COMPILER_IMPORT_STD "" +CMAKE_CXX_COMPILER_IMPORT_STD_ERROR_MESSAGE "Unsupported generator: Unix Makefiles" +CMAKE_CXX_COMPILER_INIT "NOTFOUND" +CMAKE_CXX_COMPILER_LINKER "/usr/bin/ld" +CMAKE_CXX_COMPILER_LINKER_FRONTEND_VARIANT "GNU" +CMAKE_CXX_COMPILER_LINKER_ID "GNU" +CMAKE_CXX_COMPILER_LINKER_VERSION "2.46" +CMAKE_CXX_COMPILER_LIST "c++;CC;g++;aCC;cl;bcc;xlC;icpx;icx;clang++" +CMAKE_CXX_COMPILER_LOADED "1" +CMAKE_CXX_COMPILER_NAMES "c++" +CMAKE_CXX_COMPILER_PREDEFINES_COMMAND "/usr/bin/c++;-w;-dM;-E;/usr/share/cmake/Modules/CMakeCXXCompilerABI.cpp" +CMAKE_CXX_COMPILER_PRODUCED_FILES "a.out" +CMAKE_CXX_COMPILER_PRODUCED_OUTPUT "" +CMAKE_CXX_COMPILER_RANLIB "/usr/bin/gcc-ranlib" +CMAKE_CXX_COMPILER_RANLIB "/usr/bin/gcc-ranlib" +CMAKE_CXX_COMPILER_SYSROOT "" +CMAKE_CXX_COMPILER_VERSION "15.2.1" +CMAKE_CXX_COMPILER_VERSION_INTERNAL "" +CMAKE_CXX_COMPILER_WORKS "TRUE" +CMAKE_CXX_COMPILER_WRAPPER "" +CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20;cxx_std_23;cxx_std_26" +CMAKE_CXX_COMPILE_OBJECT " -o -c " +CMAKE_CXX_COMPILE_OPTIONS_COLOR_DIAGNOSTICS "-fdiagnostics-color=always" +CMAKE_CXX_COMPILE_OPTIONS_COLOR_DIAGNOSTICS_OFF "-fno-diagnostics-color" +CMAKE_CXX_COMPILE_OPTIONS_CREATE_PCH "-x;c++-header;-include;" +CMAKE_CXX_COMPILE_OPTIONS_EXPLICIT_LANGUAGE "-x;c++" +CMAKE_CXX_COMPILE_OPTIONS_INVALID_PCH "-Winvalid-pch" +CMAKE_CXX_COMPILE_OPTIONS_IPO "-flto=auto;-fno-fat-lto-objects" +CMAKE_CXX_COMPILE_OPTIONS_PIC "-fPIC" +CMAKE_CXX_COMPILE_OPTIONS_PIE "-fPIE" +CMAKE_CXX_COMPILE_OPTIONS_SYSROOT "--sysroot=" +CMAKE_CXX_COMPILE_OPTIONS_USE_PCH "-include;" +CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY "-fvisibility=" +CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden" +CMAKE_CXX_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror" +CMAKE_CXX_CREATE_ASSEMBLY_SOURCE " -S -o " +CMAKE_CXX_CREATE_PREPROCESSED_SOURCE " -E > " +CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " +CMAKE_CXX_CREATE_SHARED_MODULE " -o " +CMAKE_CXX_DEPENDS_USE_COMPILER "TRUE" +CMAKE_CXX_DEPFILE_FORMAT "gcc" +CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "ON" +CMAKE_CXX_EXTENSIONS_DEFAULT "ON" +CMAKE_CXX_FLAGS "" +CMAKE_CXX_FLAGS_DEBUG "-g" +CMAKE_CXX_FLAGS_DEBUG_INIT " -g" +CMAKE_CXX_FLAGS_INIT " " +CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG" +CMAKE_CXX_FLAGS_MINSIZEREL_INIT " -Os -DNDEBUG" +CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG" +CMAKE_CXX_FLAGS_RELEASE_INIT " -O3 -DNDEBUG" +CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DNDEBUG" +CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG" +CMAKE_CXX_HOST_COMPILER_ID "" +CMAKE_CXX_HOST_COMPILER_VERSION "" +CMAKE_CXX_IGNORE_EXTENSIONS "inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC" +CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/usr/include/c++/15.2.1;/usr/include/c++/15.2.1/x86_64-pc-linux-gnu;/usr/include/c++/15.2.1/backward;/usr/lib/gcc/x86_64-pc-linux-gnu/15.2.1/include;/usr/local/include;/usr/lib/gcc/x86_64-pc-linux-gnu/15.2.1/include-fixed;/usr/include" +CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-pc-linux-gnu/15.2.1;/usr/lib;/lib" +CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "" +CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;gcc_s;gcc;c;gcc_s;gcc" +CMAKE_CXX_INFORMATION_LOADED "1" +CMAKE_CXX_LIBRARY_ARCHITECTURE "" +CMAKE_CXX_LINKER_DEPFILE_FLAGS "LINKER:--dependency-file=" +CMAKE_CXX_LINKER_DEPFILE_FORMAT "gcc" +CMAKE_CXX_LINKER_DEPFILE_SUPPORTED "TRUE" +CMAKE_CXX_LINKER_INFORMATION_LOADED "1" +CMAKE_CXX_LINKER_PREFERENCE "30" +CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES "1" +CMAKE_CXX_LINKER_PUSHPOP_STATE_SUPPORTED "TRUE" +CMAKE_CXX_LINKER_WRAPPER_FLAG "-Wl," +CMAKE_CXX_LINKER_WRAPPER_FLAG_SEP "," +CMAKE_CXX_LINK_DEPENDS_USE_LINKER "TRUE" +CMAKE_CXX_LINK_EXECUTABLE " -o " +CMAKE_CXX_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--push-state,--whole-archive;;LINKER:--pop-state" +CMAKE_CXX_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED "TRUE" +CMAKE_CXX_LINK_LIBRARY_WHOLE_ARCHIVE_ATTRIBUTES "LIBRARY_TYPE=STATIC;DEDUPLICATION=YES;OVERRIDE=DEFAULT" +CMAKE_CXX_LINK_MODE "DRIVER" +CMAKE_CXX_LINK_OPTIONS_NO_PIE "-no-pie" +CMAKE_CXX_LINK_OPTIONS_PIE "-fPIE;-pie" +CMAKE_CXX_LINK_OPTIONS_WARNING_AS_ERROR "LINKER:--fatal-warnings" +CMAKE_CXX_LINK_WHAT_YOU_USE_FLAG "LINKER:--no-as-needed" +CMAKE_CXX_MODULE_BMI_ONLY_FLAG "-fmodule-only" +CMAKE_CXX_MODULE_MAP_FLAG "-fmodules-ts -fmodule-mapper= -MD -fdeps-format=p1689r5 -x c++" +CMAKE_CXX_MODULE_MAP_FORMAT "gcc" +CMAKE_CXX_OUTPUT_EXTENSION ".o" +CMAKE_CXX_PLATFORM_ID "Linux" +CMAKE_CXX_PLATFORM_LINKER_ID "GNU" +CMAKE_CXX_SCANDEP_SOURCE " -E -x c++ -MT -MD -MF -fmodules-ts -fdeps-file= -fdeps-target= -fdeps-format=p1689r5 -o " +CMAKE_CXX_SIMULATE_ID "" +CMAKE_CXX_SIMULATE_VERSION "" +CMAKE_CXX_SIZEOF_DATA_PTR "8" +CMAKE_CXX_SOURCE_FILE_EXTENSIONS "C;M;c++;cc;cpp;cxx;mm;mpp;CPP;ixx;cppm;ccm;cxxm;c++m" +CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "17" +CMAKE_CXX_STANDARD_DEFAULT "17" +CMAKE_CXX_STANDARD_LATEST "26" +CMAKE_CXX_STANDARD_LIBRARY "libstdc++" +CMAKE_CXX_STDLIB_MODULES_JSON "" +CMAKE_CXX_USE_LINKER_INFORMATION "TRUE" +CMAKE_CXX_USING_LINKER_BFD "-fuse-ld=bfd" +CMAKE_CXX_USING_LINKER_GOLD "-fuse-ld=gold" +CMAKE_CXX_USING_LINKER_LLD "-fuse-ld=lld" +CMAKE_CXX_USING_LINKER_MOLD "-fuse-ld=mold" +CMAKE_CXX_USING_LINKER_SYSTEM "" +CMAKE_CXX_VERBOSE_FLAG "-v" +CMAKE_CXX_VERBOSE_LINK_FLAG "-Wl,-v" +CMAKE_CXX_XCODE_ARCHS "" +CMAKE_C_ABI_COMPILED "TRUE" +CMAKE_C_ARCHIVE_APPEND " q " +CMAKE_C_ARCHIVE_APPEND_IPO ""/usr/bin/gcc-ar" q " +CMAKE_C_ARCHIVE_CREATE " qc " +CMAKE_C_ARCHIVE_CREATE_IPO ""/usr/bin/gcc-ar" qc " +CMAKE_C_ARCHIVE_FINISH " " +CMAKE_C_ARCHIVE_FINISH_IPO ""/usr/bin/gcc-ranlib" " +CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN" +CMAKE_C_CL_SHOWINCLUDES_PREFIX "" +CMAKE_C_COMPILER "/usr/bin/cc" +CMAKE_C_COMPILER "/usr/bin/cc" +CMAKE_C_COMPILER_ABI "ELF" +CMAKE_C_COMPILER_APPLE_SYSROOT "" +CMAKE_C_COMPILER_AR "/usr/bin/gcc-ar" +CMAKE_C_COMPILER_AR "/usr/bin/gcc-ar" +CMAKE_C_COMPILER_ARCHITECTURE_ID "x86_64" +CMAKE_C_COMPILER_ARG1 "" +CMAKE_C_COMPILER_CLANG_RESOURCE_DIR "" +CMAKE_C_COMPILER_ENV_VAR "CC" +CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU" +CMAKE_C_COMPILER_ID "GNU" +CMAKE_C_COMPILER_ID_PLATFORM_CONTENT "#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +# elif defined(_ADI_COMPILER) +# define PLATFORM_ID "ADSP" + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__clang__) && defined(__ti__) +# if defined(__ARM_ARCH) +# define ARCHITECTURE_ID "ARM" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +# elif defined(__ADSPSHARC__) +# define ARCHITECTURE_ID "SHARC" + +# elif defined(__ADSPBLACKFIN__) +# define ARCHITECTURE_ID "Blackfin" + +#elif defined(__TASKING__) + +# if defined(__CTC__) || defined(__CPTC__) +# define ARCHITECTURE_ID "TriCore" + +# elif defined(__CMCS__) +# define ARCHITECTURE_ID "MCS" + +# elif defined(__CARM__) || defined(__CPARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__CARC__) +# define ARCHITECTURE_ID "ARC" + +# elif defined(__C51__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__CPCP__) +# define ARCHITECTURE_ID "PCP" + +# else +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__RENESAS__) +# if defined(__CCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__CCRL__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__CCRH__) +# define ARCHITECTURE_ID "RH850" + +# else +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; +" +CMAKE_C_COMPILER_ID_RUN "1" +CMAKE_C_COMPILER_ID_TEST_FLAGS "-c;-Aa;-D__CLASSIC_C__;--target=arm-arm-none-eabi -mcpu=cortex-m3;-c -I__does_not_exist__" +CMAKE_C_COMPILER_ID_TOOL_MATCH_INDEX "2" +CMAKE_C_COMPILER_ID_TOOL_MATCH_REGEX " +Ld[^ +]*( +[ ]+[^ +]*)* +[ ]+([^ +]+)[^ +]*-o[^ +]*CompilerIdC/(\./)?(CompilerIdC.(framework|xctest|build/[^ +]+)/)?CompilerIdC[ +\"]" +CMAKE_C_COMPILER_ID_VENDORS "IAR" +CMAKE_C_COMPILER_ID_VENDOR_REGEX_IAR "IAR .+ Compiler" +CMAKE_C_COMPILER_INIT "NOTFOUND" +CMAKE_C_COMPILER_LINKER "/usr/bin/ld" +CMAKE_C_COMPILER_LINKER_FRONTEND_VARIANT "GNU" +CMAKE_C_COMPILER_LINKER_ID "GNU" +CMAKE_C_COMPILER_LINKER_VERSION "2.46" +CMAKE_C_COMPILER_LIST "cc;gcc;cl;bcc;xlc;icx;clang" +CMAKE_C_COMPILER_LOADED "1" +CMAKE_C_COMPILER_NAMES "cc" +CMAKE_C_COMPILER_PRODUCED_FILES "a.out" +CMAKE_C_COMPILER_PRODUCED_OUTPUT "" +CMAKE_C_COMPILER_RANLIB "/usr/bin/gcc-ranlib" +CMAKE_C_COMPILER_RANLIB "/usr/bin/gcc-ranlib" +CMAKE_C_COMPILER_SYSROOT "" +CMAKE_C_COMPILER_VERSION "15.2.1" +CMAKE_C_COMPILER_VERSION_INTERNAL "" +CMAKE_C_COMPILER_WORKS "TRUE" +CMAKE_C_COMPILER_WRAPPER "" +CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23" +CMAKE_C_COMPILE_OBJECT " -o -c " +CMAKE_C_COMPILE_OPTIONS_COLOR_DIAGNOSTICS "-fdiagnostics-color=always" +CMAKE_C_COMPILE_OPTIONS_COLOR_DIAGNOSTICS_OFF "-fno-diagnostics-color" +CMAKE_C_COMPILE_OPTIONS_CREATE_PCH "-x;c-header;-include;" +CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE "-x;c" +CMAKE_C_COMPILE_OPTIONS_INVALID_PCH "-Winvalid-pch" +CMAKE_C_COMPILE_OPTIONS_IPO "-flto=auto;-fno-fat-lto-objects" +CMAKE_C_COMPILE_OPTIONS_PIC "-fPIC" +CMAKE_C_COMPILE_OPTIONS_PIE "-fPIE" +CMAKE_C_COMPILE_OPTIONS_SYSROOT "--sysroot=" +CMAKE_C_COMPILE_OPTIONS_USE_PCH "-include;" +CMAKE_C_COMPILE_OPTIONS_VISIBILITY "-fvisibility=" +CMAKE_C_COMPILE_OPTIONS_WARNING_AS_ERROR "-Werror" +CMAKE_C_CREATE_ASSEMBLY_SOURCE " -S -o " +CMAKE_C_CREATE_PREPROCESSED_SOURCE " -E > " +CMAKE_C_CREATE_SHARED_LIBRARY " -o " +CMAKE_C_CREATE_SHARED_MODULE " -o " +CMAKE_C_DEPENDS_USE_COMPILER "TRUE" +CMAKE_C_DEPFILE_FORMAT "gcc" +CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON" +CMAKE_C_EXTENSIONS_DEFAULT "ON" +CMAKE_C_FLAGS "" +CMAKE_C_FLAGS_DEBUG "-g" +CMAKE_C_FLAGS_DEBUG_INIT " -g" +CMAKE_C_FLAGS_INIT " " +CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG" +CMAKE_C_FLAGS_MINSIZEREL_INIT " -Os -DNDEBUG" +CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG" +CMAKE_C_FLAGS_RELEASE_INIT " -O3 -DNDEBUG" +CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g -DNDEBUG" +CMAKE_C_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG" +CMAKE_C_HOST_COMPILER_ID "" +CMAKE_C_HOST_COMPILER_VERSION "" +CMAKE_C_IGNORE_EXTENSIONS "h;H;o;O;obj;OBJ;def;DEF;rc;RC" +CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/usr/lib/gcc/x86_64-pc-linux-gnu/15.2.1/include;/usr/local/include;/usr/lib/gcc/x86_64-pc-linux-gnu/15.2.1/include-fixed;/usr/include" +CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-pc-linux-gnu/15.2.1;/usr/lib;/lib" +CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "" +CMAKE_C_IMPLICIT_LINK_LIBRARIES "gcc;gcc_s;c;gcc;gcc_s" +CMAKE_C_INFORMATION_LOADED "1" +CMAKE_C_LIBRARY_ARCHITECTURE "" +CMAKE_C_LINKER_DEPFILE_FLAGS "LINKER:--dependency-file=" +CMAKE_C_LINKER_DEPFILE_FORMAT "gcc" +CMAKE_C_LINKER_DEPFILE_SUPPORTED "TRUE" +CMAKE_C_LINKER_INFORMATION_LOADED "1" +CMAKE_C_LINKER_PREFERENCE "10" +CMAKE_C_LINKER_PUSHPOP_STATE_SUPPORTED "TRUE" +CMAKE_C_LINKER_WRAPPER_FLAG "-Wl," +CMAKE_C_LINKER_WRAPPER_FLAG_SEP "," +CMAKE_C_LINK_DEPENDS_USE_LINKER "TRUE" +CMAKE_C_LINK_EXECUTABLE " -o " +CMAKE_C_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--push-state,--whole-archive;;LINKER:--pop-state" +CMAKE_C_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED "TRUE" +CMAKE_C_LINK_LIBRARY_WHOLE_ARCHIVE_ATTRIBUTES "LIBRARY_TYPE=STATIC;DEDUPLICATION=YES;OVERRIDE=DEFAULT" +CMAKE_C_LINK_MODE "DRIVER" +CMAKE_C_LINK_OPTIONS_NO_PIE "-no-pie" +CMAKE_C_LINK_OPTIONS_PIE "-fPIE;-pie" +CMAKE_C_LINK_OPTIONS_WARNING_AS_ERROR "LINKER:--fatal-warnings" +CMAKE_C_LINK_WHAT_YOU_USE_FLAG "LINKER:--no-as-needed" +CMAKE_C_OUTPUT_EXTENSION ".o" +CMAKE_C_PLATFORM_ID "Linux" +CMAKE_C_PLATFORM_LINKER_ID "GNU" +CMAKE_C_SIMULATE_ID "" +CMAKE_C_SIMULATE_VERSION "" +CMAKE_C_SIZEOF_DATA_PTR "8" +CMAKE_C_SOURCE_FILE_EXTENSIONS "c;m" +CMAKE_C_STANDARD_COMPUTED_DEFAULT "23" +CMAKE_C_STANDARD_DEFAULT "23" +CMAKE_C_STANDARD_LATEST "23" +CMAKE_C_STANDARD_LIBRARY "" +CMAKE_C_USE_LINKER_INFORMATION "TRUE" +CMAKE_C_USING_LINKER_BFD "-fuse-ld=bfd" +CMAKE_C_USING_LINKER_GOLD "-fuse-ld=gold" +CMAKE_C_USING_LINKER_LLD "-fuse-ld=lld" +CMAKE_C_USING_LINKER_MOLD "-fuse-ld=mold" +CMAKE_C_USING_LINKER_SYSTEM "" +CMAKE_C_VERBOSE_FLAG "-v" +CMAKE_C_VERBOSE_LINK_FLAG "-Wl,-v" +CMAKE_C_XCODE_ARCHS "" +CMAKE_DEPFILE_FLAGS_C "-MD -MT -MF " +CMAKE_DEPFILE_FLAGS_CXX "-MD -MT -MF " +CMAKE_DLLTOOL "CMAKE_DLLTOOL-NOTFOUND" +CMAKE_DL_LIBS "dl" +CMAKE_EDIT_COMMAND "/usr/bin/ccmake" +CMAKE_EFFECTIVE_SYSTEM_NAME "Linux" +CMAKE_EXECUTABLE_FORMAT "ELF" +CMAKE_EXECUTABLE_RPATH_LINK_CXX_FLAG "-Wl,-rpath-link," +CMAKE_EXECUTABLE_RPATH_LINK_C_FLAG "-Wl,-rpath-link," +CMAKE_EXECUTABLE_RUNTIME_CXX_FLAG "-Wl,-rpath," +CMAKE_EXECUTABLE_RUNTIME_CXX_FLAG_SEP ":" +CMAKE_EXECUTABLE_RUNTIME_C_FLAG "-Wl,-rpath," +CMAKE_EXECUTABLE_RUNTIME_C_FLAG_SEP ":" +CMAKE_EXECUTABLE_SUFFIX "" +CMAKE_EXE_EXPORTS_CXX_FLAG "-Wl,--export-dynamic" +CMAKE_EXE_EXPORTS_C_FLAG "-Wl,--export-dynamic" +CMAKE_EXE_LINKER_FLAGS "" +CMAKE_EXE_LINKER_FLAGS_DEBUG "" +CMAKE_EXE_LINKER_FLAGS_INIT " " +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "" +CMAKE_EXE_LINKER_FLAGS_RELEASE "" +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "" +CMAKE_EXE_LINK_DYNAMIC_CXX_FLAGS "-Wl,-Bdynamic" +CMAKE_EXE_LINK_DYNAMIC_C_FLAGS "-Wl,-Bdynamic" +CMAKE_EXE_LINK_STATIC_CXX_FLAGS "-Wl,-Bstatic" +CMAKE_EXE_LINK_STATIC_C_FLAGS "-Wl,-Bstatic" +CMAKE_EXPORT_COMPILE_COMMANDS "" +CMAKE_EXTRA_GENERATOR "" +CMAKE_FILES_DIRECTORY "/CMakeFiles" +CMAKE_FIND_LIBRARY_PREFIXES "lib" +CMAKE_FIND_LIBRARY_SUFFIXES ".so;.a" +CMAKE_FIND_PACKAGE_REDIRECTS_DIR "/home/yourwishes/htdocs/dusk/__cmake_systeminformation/CMakeFiles/pkgRedirects" +CMAKE_GENERATOR "Unix Makefiles" +CMAKE_GENERATOR_INSTANCE "" +CMAKE_GENERATOR_PLATFORM "" +CMAKE_GENERATOR_TOOLSET "" +CMAKE_HOME_DIRECTORY "/home/yourwishes/htdocs/dusk/__cmake_systeminformation" +CMAKE_HOST_EXECUTABLE_SUFFIX "" +CMAKE_HOST_LINUX "1" +CMAKE_HOST_SYSTEM "Linux-6.19.12-arch1-1" +CMAKE_HOST_SYSTEM_NAME "Linux" +CMAKE_HOST_SYSTEM_PROCESSOR "x86_64" +CMAKE_HOST_SYSTEM_VERSION "6.19.12-arch1-1" +CMAKE_HOST_UNIX "1" +CMAKE_INCLUDE_FLAG_C "-I" +CMAKE_INCLUDE_FLAG_CXX "-I" +CMAKE_INCLUDE_SYSTEM_FLAG_C "-isystem " +CMAKE_INCLUDE_SYSTEM_FLAG_CXX "-isystem " +CMAKE_INSTALL_DEFAULT_COMPONENT_NAME "Unspecified" +CMAKE_INSTALL_PREFIX "/usr/local" +CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT "1" +CMAKE_INSTALL_SO_NO_EXE "0" +CMAKE_INTERNAL_PLATFORM_ABI "ELF" +CMAKE_LIBRARY_ARCHITECTURE_REGEX "[a-z0-9_]+(-[a-z0-9_]+)?-linux-[a-z0-9_]*" +CMAKE_LIBRARY_PATH_FLAG "-L" +CMAKE_LIBRARY_PATH_TERMINATOR "" +CMAKE_LINKER "/usr/bin/ld" +CMAKE_LINKER "/usr/bin/ld" +CMAKE_LINKER_LINK "" +CMAKE_LINKER_LLD "" +CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED "TRUE" +CMAKE_LINK_GROUP_USING_RESCAN "LINKER:--start-group;LINKER:--end-group" +CMAKE_LINK_GROUP_USING_RESCAN_SUPPORTED "TRUE" +CMAKE_LINK_LIBRARY_FLAG "-l" +CMAKE_LINK_LIBRARY_SUFFIX "" +CMAKE_LINK_LIBRARY_USING_DEFAULT_SUPPORTED "TRUE" +CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--push-state,--whole-archive;;LINKER:--pop-state" +CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED "TRUE" +CMAKE_LINK_LIBRARY_WHOLE_ARCHIVE_ATTRIBUTES "LIBRARY_TYPE=STATIC;DEDUPLICATION=YES;OVERRIDE=DEFAULT" +CMAKE_LINK_WHAT_YOU_USE_CHECK "ldd;-u;-r" +CMAKE_LIST_FILE_NAME "CMakeLists.txt" +CMAKE_MAJOR_VERSION "4" +CMAKE_MAKE_PROGRAM "/usr/bin/make" +CMAKE_MATCH_0 "11.1 17" +CMAKE_MATCH_1 "" +CMAKE_MATCH_2 "" +CMAKE_MATCH_COUNT "0" +CMAKE_MINIMUM_REQUIRED_VERSION "4.3.1" +CMAKE_MINOR_VERSION "3" +CMAKE_MODULE_LINKER_FLAGS "" +CMAKE_MODULE_LINKER_FLAGS_DEBUG "" +CMAKE_MODULE_LINKER_FLAGS_INIT " " +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL "" +CMAKE_MODULE_LINKER_FLAGS_RELEASE "" +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "" +CMAKE_MT "" +CMAKE_NM "/usr/bin/nm" +CMAKE_OBJCOPY "/usr/bin/objcopy" +CMAKE_OBJDUMP "/usr/bin/objdump" +CMAKE_PATCH_VERSION "1" +CMAKE_PCH_EXTENSION ".gch" +CMAKE_PCH_PROLOGUE "#pragma GCC system_header" +CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "/lib;/lib32;/lib64;/usr/lib;/usr/lib32;/usr/lib64" +CMAKE_PLATFORM_INFO_DIR "/home/yourwishes/htdocs/dusk/__cmake_systeminformation/CMakeFiles/4.3.1" +CMAKE_PLATFORM_INFO_INITIALIZED "1" +CMAKE_PLATFORM_USES_PATH_WHEN_NO_SONAME "1" +CMAKE_PROJECT_COMPAT_VERSION "" +CMAKE_PROJECT_DESCRIPTION "" +CMAKE_PROJECT_HOMEPAGE_URL "" +CMAKE_PROJECT_NAME "DumpInformation" +CMAKE_PROJECT_SPDX_LICENSE "" +CMAKE_RANLIB "/usr/bin/ranlib" +CMAKE_RANLIB "/usr/bin/ranlib" +CMAKE_READELF "/usr/bin/readelf" +CMAKE_ROOT "/usr/share/cmake" +CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "-shared" +CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-shared" +CMAKE_SHARED_LIBRARY_CXX_FLAGS "-fPIC" +CMAKE_SHARED_LIBRARY_C_FLAGS "-fPIC" +CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "-rdynamic" +CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-rdynamic" +CMAKE_SHARED_LIBRARY_LINK_DYNAMIC_CXX_FLAGS "-Wl,-Bdynamic" +CMAKE_SHARED_LIBRARY_LINK_DYNAMIC_C_FLAGS "-Wl,-Bdynamic" +CMAKE_SHARED_LIBRARY_LINK_STATIC_CXX_FLAGS "-Wl,-Bstatic" +CMAKE_SHARED_LIBRARY_LINK_STATIC_C_FLAGS "-Wl,-Bstatic" +CMAKE_SHARED_LIBRARY_PREFIX "lib" +CMAKE_SHARED_LIBRARY_RPATH_LINK_CXX_FLAG "-Wl,-rpath-link," +CMAKE_SHARED_LIBRARY_RPATH_LINK_C_FLAG "-Wl,-rpath-link," +CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN "$ORIGIN" +CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG "-Wl,-rpath," +CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG_SEP ":" +CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-Wl,-rpath," +CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP ":" +CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG "-Wl,-soname," +CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-Wl,-soname," +CMAKE_SHARED_LIBRARY_SUFFIX ".so" +CMAKE_SHARED_LINKER_FLAGS "" +CMAKE_SHARED_LINKER_FLAGS_DEBUG "" +CMAKE_SHARED_LINKER_FLAGS_INIT " " +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "" +CMAKE_SHARED_LINKER_FLAGS_RELEASE "" +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "" +CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS "-shared" +CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-shared" +CMAKE_SHARED_MODULE_CXX_FLAGS "-fPIC" +CMAKE_SHARED_MODULE_C_FLAGS "-fPIC" +CMAKE_SHARED_MODULE_LINK_DYNAMIC_CXX_FLAGS "-Wl,-Bdynamic" +CMAKE_SHARED_MODULE_LINK_DYNAMIC_C_FLAGS "-Wl,-Bdynamic" +CMAKE_SHARED_MODULE_LINK_STATIC_CXX_FLAGS "-Wl,-Bstatic" +CMAKE_SHARED_MODULE_LINK_STATIC_C_FLAGS "-Wl,-Bstatic" +CMAKE_SHARED_MODULE_PREFIX "lib" +CMAKE_SHARED_MODULE_SUFFIX ".so" +CMAKE_SIZEOF_VOID_P "8" +CMAKE_SKIP_INSTALL_RPATH "NO" +CMAKE_SKIP_RPATH "NO" +CMAKE_SOURCE_DIR "/home/yourwishes/htdocs/dusk/__cmake_systeminformation" +CMAKE_STATIC_LIBRARY_PREFIX "lib" +CMAKE_STATIC_LIBRARY_SUFFIX ".a" +CMAKE_STATIC_LINKER_FLAGS "" +CMAKE_STATIC_LINKER_FLAGS_DEBUG "" +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL "" +CMAKE_STATIC_LINKER_FLAGS_RELEASE "" +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO "" +CMAKE_STRIP "/usr/bin/strip" +CMAKE_SYSTEM "Linux-6.19.12-arch1-1" +CMAKE_SYSTEM_INCLUDE_PATH "/usr/include/X11" +CMAKE_SYSTEM_INFO_FILE "Platform/Linux" +CMAKE_SYSTEM_LIBRARY_PATH "/usr/lib/X11" +CMAKE_SYSTEM_LOADED "1" +CMAKE_SYSTEM_NAME "Linux" +CMAKE_SYSTEM_PREFIX_PATH "/usr/local;/usr;/;/usr;/usr/local;/usr/X11R6;/usr/pkg;/opt" +CMAKE_SYSTEM_PROCESSOR "x86_64" +CMAKE_SYSTEM_SPECIFIC_INFORMATION_LOADED "1" +CMAKE_SYSTEM_SPECIFIC_INITIALIZE_LOADED "1" +CMAKE_SYSTEM_VERSION "6.19.12-arch1-1" +CMAKE_TAPI "CMAKE_TAPI-NOTFOUND" +CMAKE_TAPI "CMAKE_TAPI-NOTFOUND" +CMAKE_TWEAK_VERSION "0" +CMAKE_UNAME "/usr/bin/uname" +CMAKE_VERBOSE_MAKEFILE "FALSE" +CMAKE_VERSION "4.3.1" +COMPILER_BASENAME "c++" +DumpInformation_BINARY_DIR "/home/yourwishes/htdocs/dusk/__cmake_systeminformation" +DumpInformation_BINARY_DIR "/home/yourwishes/htdocs/dusk/__cmake_systeminformation" +DumpInformation_COMPAT_VERSION "" +DumpInformation_DESCRIPTION "" +DumpInformation_HOMEPAGE_URL "" +DumpInformation_IS_TOP_LEVEL "ON" +DumpInformation_IS_TOP_LEVEL "ON" +DumpInformation_SOURCE_DIR "/home/yourwishes/htdocs/dusk/__cmake_systeminformation" +DumpInformation_SOURCE_DIR "/home/yourwishes/htdocs/dusk/__cmake_systeminformation" +DumpInformation_SPDX_LICENSE "" +LINUX "1" +MSVC_CXX_ARCHITECTURE_ID "" +MSVC_C_ARCHITECTURE_ID "" +PROJECT_BINARY_DIR "/home/yourwishes/htdocs/dusk/__cmake_systeminformation" +PROJECT_COMPAT_VERSION "" +PROJECT_DESCRIPTION "" +PROJECT_HOMEPAGE_URL "" +PROJECT_IS_TOP_LEVEL "ON" +PROJECT_NAME "DumpInformation" +PROJECT_SOURCE_DIR "/home/yourwishes/htdocs/dusk/__cmake_systeminformation" +PROJECT_SPDX_LICENSE "" +RESULT_FILE "/home/yourwishes/htdocs/dusk/-DCMAKE_TOOLCHAIN_FILE=/opt/pspdev/psp/share/pspdev.cmake" +RUN_CONFIGURE "ON" +UNIX "1" +_CMAKE_CUDA_IMPLICIT_INCLUDE_DIRECTORIES_INIT "/usr/include" +_CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES_INIT "/usr/include" +_CMAKE_CXX_IPO_MAY_BE_SUPPORTED_BY_COMPILER "YES" +_CMAKE_CXX_IPO_SUPPORTED_BY_CMAKE "YES" +_CMAKE_CXX_PIE_MAY_BE_SUPPORTED_BY_LINKER "YES" +_CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES_INIT "/usr/include" +_CMAKE_C_IPO_MAY_BE_SUPPORTED_BY_COMPILER "YES" +_CMAKE_C_IPO_SUPPORTED_BY_CMAKE "YES" +_CMAKE_C_PIE_MAY_BE_SUPPORTED_BY_LINKER "YES" +_CMAKE_INSTALL_DIR "/usr" +_CMAKE_SYSTEM_PREFIX_PATH_INSTALL_PREFIX_COUNT "2" +_CMAKE_SYSTEM_PREFIX_PATH_INSTALL_PREFIX_VALUE "/usr/local" +_CMAKE_SYSTEM_PREFIX_PATH_STAGING_PREFIX_COUNT "0" +_CMAKE_SYSTEM_PREFIX_PATH_STAGING_PREFIX_VALUE "" +_CMAKE_TOOLCHAIN_LOCATION "/usr/bin" +_INCLUDED_FILE "/usr/share/cmake/Modules/Platform/Linker/Linux-GNU-CXX.cmake" +_INCLUDED_SYSTEM_INFO_FILE "/usr/share/cmake/Modules/Platform/Linux.cmake" +_IN_TC "0" +_SET_CMAKE_CXX_COMPILER_SYSROOT "" +_SET_CMAKE_C_COMPILER_SYSROOT "" +__COMPILER_CMAKE_COMMON_COMPILER_MACROS "1" +__COMPILER_GNU "1" +__INCGUARD_36c7e3b854b481442cb2658e808f4e5b__ "ON" +__INCGUARD_935abdd415bf4b838e60be86f7511346__ "ON" +__INCGUARD_a947fb0660fa28aac2814acc178fcbff__ "ON" +__LINUX_COMPILER_GNU "1" +__UNIX_PATHS_INCLUDED "1" +__gcc_hints "/usr/bin" +__lto_flags "-flto=auto;-fno-fat-lto-objects" +__pch_header_C "c-header" +__pch_header_CXX "c++-header" +__pch_header_OBJC "objective-c-header" +__pch_header_OBJCXX "objective-c++-header" +__version_x "15" +__version_x_y "15.2" +incl "/home/yourwishes/htdocs/dusk/__cmake_systeminformation/This does not exist" +val "0" + +================================================================= +=== COMMANDS +================================================================= +___cmake_include_compiler_wrapper +___determine_compiler_id_test +___resolve_linker_path +___resolve_tool_path +___testcompiler_restoretrycompiletargettype +___testcompiler_settrycompiletargettype +__cmake_common_language_platform_flags +__cmake_common_linker_platform_flags +__cmake_find_compiler +__cmake_find_compiler_path +__cmake_find_compiler_sysroot +__cmake_include_compiler_wrapper +__cmake_set_whole_archive_feature +__compiler_check_default_language_standard +__compiler_gnu +__compiler_gnu_c_standards +__compiler_gnu_cxx_standards +__determine_compiler_id_test +__has_compiler_features +__has_compiler_features_c +__has_compiler_features_cuda +__has_compiler_features_cxx +__has_compiler_features_hip +__linker_gnu +__linux_compiler_gnu +__linux_linker_gnu +__readfile +__record_compiler_features +__record_compiler_features_c +__record_compiler_features_cuda +__record_compiler_features_cxx +__record_compiler_features_hip +__resolve_linker_path +__resolve_tool_path +__testcompiler_restoretrycompiletargettype +__testcompiler_settrycompiletargettype +_cmake_common_language_platform_flags +_cmake_common_linker_platform_flags +_cmake_determine_compiler_abi +_cmake_determine_compiler_id +_cmake_determine_compiler_id_build +_cmake_determine_compiler_id_check +_cmake_determine_compiler_id_match_vendor +_cmake_determine_compiler_id_vendor +_cmake_determine_compiler_id_write +_cmake_determine_compiler_support +_cmake_determine_linker_id +_cmake_determine_msvc_i18n_dir +_cmake_determine_msvc_showincludes_prefix +_cmake_find_compiler +_cmake_find_compiler_path +_cmake_find_compiler_sysroot +_cmake_parse_implicit_include_info +_cmake_parse_implicit_include_line +_cmake_parse_implicit_link_info +_cmake_parse_implicit_link_info2 +_cmake_parse_library_architecture +_cmake_record_install_prefix +_compiler_id_detection +_has_compiler_features +_has_compiler_features_c +_has_compiler_features_cuda +_has_compiler_features_cxx +_has_compiler_features_hip +_printtestcompilerresult +_printtestcompilerstatus +_readfile +_record_compiler_features +_record_compiler_features_c +_record_compiler_features_cuda +_record_compiler_features_cxx +_record_compiler_features_hip +add_compile_definitions +add_compile_options +add_custom_command +add_custom_target +add_definitions +add_dependencies +add_executable +add_library +add_link_options +add_subdirectory +add_test +aux_source_directory +block +break +build_command +build_name +cmake_cxx_find_modules_json +cmake_determine_compiler_abi +cmake_determine_compiler_id +cmake_determine_compiler_id_build +cmake_determine_compiler_id_check +cmake_determine_compiler_id_match_vendor +cmake_determine_compiler_id_vendor +cmake_determine_compiler_id_write +cmake_determine_compiler_support +cmake_determine_linker_id +cmake_determine_msvc_i18n_dir +cmake_determine_msvc_showincludes_prefix +cmake_file_api +cmake_host_system_information +cmake_initialize_per_config_variable +cmake_instrumentation +cmake_language +cmake_minimum_required +cmake_parse_arguments +cmake_parse_implicit_include_info +cmake_parse_implicit_include_line +cmake_parse_implicit_link_info +cmake_parse_implicit_link_info2 +cmake_parse_library_architecture +cmake_path +cmake_pkg_config +cmake_policy +cmake_record_c_compile_features +cmake_record_cuda_compile_features +cmake_record_cxx_compile_features +cmake_record_hip_compile_features +compiler_id_detection +configure_file +continue +create_test_sourcelist +define_property +else +elseif +enable_language +enable_testing +endblock +endforeach +endfunction +endif +endmacro +endwhile +exec_program +execute_process +export +export_library_dependencies +file +find_file +find_library +find_package +find_path +find_program +fltk_wrap_ui +foreach +function +get_cmake_property +get_directory_property +get_filename_component +get_property +get_source_file_property +get_target_property +get_test_property +getdefaultwindowsprefixbase +if +include +include_directories +include_external_msproject +include_guard +include_regular_expression +install +install_files +install_programs +install_targets +link_directories +link_libraries +list +load_cache +load_command +macro +make_directory +mark_as_advanced +math +message +option +output_required_files +printtestcompilerresult +printtestcompilerstatus +project +qt_wrap_cpp +qt_wrap_ui +remove +remove_definitions +return +separate_arguments +set +set_directory_properties +set_property +set_source_files_properties +set_target_properties +set_tests_properties +site_name +source_group +string +subdir_depends +subdirs +target_compile_definitions +target_compile_features +target_compile_options +target_include_directories +target_link_directories +target_link_libraries +target_link_options +target_precompile_headers +target_sources +try_compile +try_run +unset +use_mangled_mesa +utility_source +variable_requires +variable_watch +while +write_file + +================================================================= +=== MACROS +================================================================= +_cmake_find_compiler +_cmake_find_compiler_path +__determine_compiler_id_test +__resolve_linker_path +_cmake_find_compiler +_cmake_find_compiler_path +__determine_compiler_id_test +__resolve_linker_path +__cmake_include_compiler_wrapper +__compiler_check_default_language_standard +cmake_record_c_compile_features +cmake_record_cxx_compile_features +cmake_record_cuda_compile_features +cmake_record_hip_compile_features +__compiler_gnu +__compiler_gnu_c_standards +__compiler_gnu_cxx_standards +__linux_compiler_gnu +_cmake_common_language_platform_flags +__TestCompiler_setTryCompileTargetType +__TestCompiler_restoreTryCompileTargetType +__TestCompiler_setTryCompileTargetType +__TestCompiler_restoreTryCompileTargetType +_record_compiler_features +_record_compiler_features_c +_record_compiler_features_cxx +_record_compiler_features_cuda +_record_compiler_features_hip +_has_compiler_features +_has_compiler_features_c +_has_compiler_features_cxx +_has_compiler_features_cuda +_has_compiler_features_hip +_cmake_common_linker_platform_flags +__linux_linker_gnu +__cmake_include_compiler_wrapper +_cmake_common_language_platform_flags +__TestCompiler_setTryCompileTargetType +__TestCompiler_restoreTryCompileTargetType +__TestCompiler_setTryCompileTargetType +__TestCompiler_restoreTryCompileTargetType +_record_compiler_features +_record_compiler_features_c +_record_compiler_features_cxx +_record_compiler_features_cuda +_record_compiler_features_hip +_has_compiler_features +_has_compiler_features_c +_has_compiler_features_cxx +_has_compiler_features_cuda +_has_compiler_features_hip +_cmake_common_linker_platform_flags + +================================================================= +=== OTHER +================================================================= +INCLUDE_DIRECTORY: /home/yourwishes/htdocs/dusk/__cmake_systeminformation +INCLUDE_DIRECTORY: /home/yourwishes/htdocs/dusk/__cmake_systeminformation +INCLUDE_REGULAR_EXPRESSION: ^.*$ diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f57d80c..b300f792 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,11 +4,13 @@ # https://opensource.org/licenses/MIT # Setup -cmake_minimum_required(VERSION 3.18) +cmake_minimum_required(VERSION 4.0) set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) +# [cmake] This is allowed only when policy CMP0079 is set to NEW. +cmake_policy(SET CMP0079 NEW) option(DUSK_BUILD_TESTS "Enable tests" OFF) diff --git a/assets/entities/cube.js b/assets/entities/cube.js new file mode 100644 index 00000000..087fb83e --- /dev/null +++ b/assets/entities/cube.js @@ -0,0 +1,32 @@ +var Cube = { + create: function() { + var e = Entity.create(); + e.add(COMPONENT_TYPE_POSITION); + e.position.x = 0; + e.position.y = 0; + e.position.z = 0; + e.add(COMPONENT_TYPE_MESH); + e.add(COMPONENT_TYPE_MATERIAL); + e.material.setColor(colorRed()); + + return { + _e: e, + update: Cube.update, + dispose: Cube.dispose + }; + }, + + update: function() { + var speed = 3.0; + var dx = inputAxis(INPUT_ACTION_LEFT, INPUT_ACTION_RIGHT); + var dz = inputAxis(INPUT_ACTION_UP, INPUT_ACTION_DOWN); + this._e.position.x += dx * speed * TIME.delta; + this._e.position.z += dz * speed * TIME.delta; + }, + + dispose: function() { + this._e.dispose(); + } +}; + +Cube; diff --git a/assets/entities/cube.lua b/assets/entities/cube.lua deleted file mode 100644 index a116eb2e..00000000 --- a/assets/entities/cube.lua +++ /dev/null @@ -1,25 +0,0 @@ -local Cube = setmetatable({}, { __index = Entity }) -Cube.__index = Cube - -function Cube.new() - local self = Entity.new() - setmetatable(self, Cube) - self:add(Entity.POSITION) - self.position.x = 0 - self.position.y = 0 - self.position.z = 0 - self:add(Entity.MESH) - self:add(Entity.MATERIAL) - self.material.color = colorRed() - return self -end - -function Cube:update() - local speed = 3.0 - local dx = inputAxis(INPUT_ACTION_LEFT, INPUT_ACTION_RIGHT) - local dz = inputAxis(INPUT_ACTION_UP, INPUT_ACTION_DOWN) - self.position.x = self.position.x + dx * speed * TIME.delta - self.position.z = self.position.z + dz * speed * TIME.delta -end - -return Cube diff --git a/assets/init.js b/assets/init.js new file mode 100644 index 00000000..11e21716 --- /dev/null +++ b/assets/init.js @@ -0,0 +1,75 @@ +// Default input bindings. +if (typeof PSP !== 'undefined') { + inputBind("up", INPUT_ACTION_UP); + inputBind("down", INPUT_ACTION_DOWN); + inputBind("left", INPUT_ACTION_LEFT); + inputBind("right", INPUT_ACTION_RIGHT); + inputBind("accept", INPUT_ACTION_ACCEPT); + inputBind("cancel", INPUT_ACTION_CANCEL); + inputBind("select", INPUT_ACTION_RAGEQUIT); + inputBind("lstick_up", INPUT_ACTION_UP); + inputBind("lstick_down", INPUT_ACTION_DOWN); + inputBind("lstick_left", INPUT_ACTION_LEFT); + inputBind("lstick_right", INPUT_ACTION_RIGHT); + inputBind("triangle", INPUT_ACTION_CONSOLE); + +} else if (typeof DOLPHIN !== 'undefined') { + inputBind("up", INPUT_ACTION_UP); + inputBind("down", INPUT_ACTION_DOWN); + inputBind("left", INPUT_ACTION_LEFT); + inputBind("right", INPUT_ACTION_RIGHT); + inputBind("b", INPUT_ACTION_CANCEL); + inputBind("a", INPUT_ACTION_ACCEPT); + inputBind("z", INPUT_ACTION_CONSOLE); + inputBind("lstick_up", INPUT_ACTION_UP); + inputBind("lstick_down", INPUT_ACTION_DOWN); + inputBind("lstick_left", INPUT_ACTION_LEFT); + inputBind("lstick_right", INPUT_ACTION_RIGHT); + +} else if (typeof LINUX !== 'undefined') { + if (typeof INPUT_KEYBOARD !== 'undefined') { + inputBind("w", INPUT_ACTION_UP); + inputBind("s", INPUT_ACTION_DOWN); + inputBind("a", INPUT_ACTION_LEFT); + inputBind("d", INPUT_ACTION_RIGHT); + + inputBind("left", INPUT_ACTION_LEFT); + inputBind("right", INPUT_ACTION_RIGHT); + inputBind("up", INPUT_ACTION_UP); + inputBind("down", INPUT_ACTION_DOWN); + + inputBind("enter", INPUT_ACTION_ACCEPT); + inputBind("e", INPUT_ACTION_ACCEPT); + + inputBind("q", INPUT_ACTION_CANCEL); + + inputBind("escape", INPUT_ACTION_RAGEQUIT); + inputBind("`", INPUT_ACTION_CONSOLE); + } + + if (typeof INPUT_GAMEPAD !== 'undefined') { + inputBind("gamepad_up", INPUT_ACTION_UP); + inputBind("gamepad_down", INPUT_ACTION_DOWN); + inputBind("gamepad_left", INPUT_ACTION_LEFT); + inputBind("gamepad_right", INPUT_ACTION_RIGHT); + + inputBind("gamepad_a", INPUT_ACTION_ACCEPT); + inputBind("gamepad_b", INPUT_ACTION_CANCEL); + inputBind("gamepad_back", INPUT_ACTION_RAGEQUIT); + + inputBind("gamepad_lstick_up", INPUT_ACTION_UP); + inputBind("gamepad_lstick_down", INPUT_ACTION_DOWN); + inputBind("gamepad_lstick_left", INPUT_ACTION_LEFT); + inputBind("gamepad_lstick_right", INPUT_ACTION_RIGHT); + } + + if (typeof INPUT_POINTER !== 'undefined') { + inputBind("mouse_x", INPUT_ACTION_POINTERX); + inputBind("mouse_y", INPUT_ACTION_POINTERY); + } + +} else { + consolePrint("Unknown platform, no default input bindings set."); +} + +Scene.set('scenes/cube.js'); diff --git a/assets/init.lua b/assets/init.lua deleted file mode 100644 index 34303093..00000000 --- a/assets/init.lua +++ /dev/null @@ -1,75 +0,0 @@ --- Default Input bindings. -if PSP then - inputBind("up", INPUT_ACTION_UP) - inputBind("down", INPUT_ACTION_DOWN) - inputBind("left", INPUT_ACTION_LEFT) - inputBind("right", INPUT_ACTION_RIGHT) - inputBind("accept", INPUT_ACTION_ACCEPT) - inputBind("cancel", INPUT_ACTION_CANCEL) - inputBind("select", INPUT_ACTION_RAGEQUIT) - inputBind("lstick_up", INPUT_ACTION_UP) - inputBind("lstick_down", INPUT_ACTION_DOWN) - inputBind("lstick_left", INPUT_ACTION_LEFT) - inputBind("lstick_right", INPUT_ACTION_RIGHT) - inputBind("triangle", INPUT_ACTION_CONSOLE) - -elseif DOLPHIN then - inputBind("up", INPUT_ACTION_UP) - inputBind("down", INPUT_ACTION_DOWN) - inputBind("left", INPUT_ACTION_LEFT) - inputBind("right", INPUT_ACTION_RIGHT) - inputBind("b", INPUT_ACTION_CANCEL) - inputBind("a", INPUT_ACTION_ACCEPT) - inputBind("z", INPUT_ACTION_CONSOLE) - inputBind("lstick_up", INPUT_ACTION_UP) - inputBind("lstick_down", INPUT_ACTION_DOWN) - inputBind("lstick_left", INPUT_ACTION_LEFT) - inputBind("lstick_right", INPUT_ACTION_RIGHT) - -elseif LINUX then - if INPUT_KEYBOARD then - inputBind("w", INPUT_ACTION_UP) - inputBind("s", INPUT_ACTION_DOWN) - inputBind("a", INPUT_ACTION_LEFT) - inputBind("d", INPUT_ACTION_RIGHT) - - inputBind("left", INPUT_ACTION_LEFT) - inputBind("right", INPUT_ACTION_RIGHT) - inputBind("up", INPUT_ACTION_UP) - inputBind("down", INPUT_ACTION_DOWN) - - inputBind("enter", INPUT_ACTION_ACCEPT) - inputBind("e", INPUT_ACTION_ACCEPT) - - inputBind("q", INPUT_ACTION_CANCEL) - - inputBind("escape", INPUT_ACTION_RAGEQUIT) - inputBind("`", INPUT_ACTION_CONSOLE) - end - - if INPUT_GAMEPAD then - inputBind("gamepad_up", INPUT_ACTION_UP) - inputBind("gamepad_down", INPUT_ACTION_DOWN) - inputBind("gamepad_left", INPUT_ACTION_LEFT) - inputBind("gamepad_right", INPUT_ACTION_RIGHT) - - inputBind("gamepad_a", INPUT_ACTION_ACCEPT) - inputBind("gamepad_b", INPUT_ACTION_CANCEL) - inputBind("gamepad_back", INPUT_ACTION_RAGEQUIT) - - inputBind("gamepad_lstick_up", INPUT_ACTION_UP) - inputBind("gamepad_lstick_down", INPUT_ACTION_DOWN) - inputBind("gamepad_lstick_left", INPUT_ACTION_LEFT) - inputBind("gamepad_lstick_right", INPUT_ACTION_RIGHT) - end - - if INPUT_POINTER then - inputBind("mouse_x", INPUT_ACTION_POINTERX) - inputBind("mouse_y", INPUT_ACTION_POINTERY) - end - -else - print("Unknown platform, no default input bindings set.") -end - -Scene.set('scenes/cube.lua') \ No newline at end of file diff --git a/assets/scenes/cube.js b/assets/scenes/cube.js new file mode 100644 index 00000000..f5b016fd --- /dev/null +++ b/assets/scenes/cube.js @@ -0,0 +1,29 @@ +var Cube = include('entities/cube.js'); + +var cam; +var cube; + +var SceneCube = { + init: function() { + cam = Entity.create(); + cam.add(COMPONENT_TYPE_POSITION); + cam.position.x = 3; + cam.position.y = 3; + cam.position.z = 3; + cam.position.lookAt(0, 0, 0); + cam.add(COMPONENT_TYPE_CAMERA); + + cube = Cube.create(); + }, + + update: function() { + cube.update(); + }, + + dispose: function() { + cam.dispose(); + cube.dispose(); + } +}; + +SceneCube; diff --git a/assets/scenes/cube.lua b/assets/scenes/cube.lua deleted file mode 100644 index 7b4850d8..00000000 --- a/assets/scenes/cube.lua +++ /dev/null @@ -1,30 +0,0 @@ -local Cube = include('entities/cube.lua') - -local SceneCube = {} -SceneCube.__index = SceneCube - -local cam -local cube - -function SceneCube:init() - cam = Entity.new() - cam:add(Entity.POSITION) - cam.position.x = 3 - cam.position.y = 3 - cam.position.z = 3 - cam.position:lookAt(0, 0, 0) - cam:add(Entity.CAMERA) - - cube = Cube.new() -end - -function SceneCube:update() - cube:update() -end - -function SceneCube:dispose() - cam:dispose() - cube:dispose() -end - -return SceneCube diff --git a/cmake/modules/Findjerryscript.cmake b/cmake/modules/Findjerryscript.cmake new file mode 100644 index 00000000..fe3f4134 --- /dev/null +++ b/cmake/modules/Findjerryscript.cmake @@ -0,0 +1,14 @@ +# Copyright (c) 2026 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +include(FetchContent) +FetchContent_Declare( + jerryscript + GIT_REPOSITORY https://github.com/jerryscript-project/jerryscript + GIT_TAG v2.4.0 +) + +FetchContent_MakeAvailable(jerryscript) +set(jerryscript_FOUND ON) \ No newline at end of file diff --git a/cmake/targets/dolphin.cmake b/cmake/targets/dolphin.cmake index e4f8c58f..0d31dcee 100644 --- a/cmake/targets/dolphin.cmake +++ b/cmake/targets/dolphin.cmake @@ -22,31 +22,9 @@ set(CGLM_SHARED OFF CACHE BOOL "Build cglm shared" FORCE) set(CGLM_STATIC ON CACHE BOOL "Build cglm static" FORCE) find_package(cglm REQUIRED) -# Compile lua -include(FetchContent) -FetchContent_Declare( - liblua - URL https://www.lua.org/ftp/lua-5.5.0.tar.gz -) -FetchContent_MakeAvailable(liblua) -set(LUA_SRC_DIR "${liblua_SOURCE_DIR}/src") -set(LUA_C_FILES - lapi.c lauxlib.c lbaselib.c lcode.c lcorolib.c lctype.c ldblib.c ldebug.c - ldo.c ldump.c lfunc.c lgc.c linit.c liolib.c llex.c lmathlib.c lmem.c - loadlib.c lobject.c lopcodes.c loslib.c lparser.c lstate.c lstring.c - lstrlib.c ltable.c ltablib.c ltm.c lundump.c lutf8lib.c lvm.c lzio.c -) -list(TRANSFORM LUA_C_FILES PREPEND "${LUA_SRC_DIR}/") -add_library(liblua STATIC ${LUA_C_FILES}) -target_include_directories(liblua PUBLIC "${LUA_SRC_DIR}") -target_compile_definitions(liblua PUBLIC LUA_USE_C89) -add_library(lua::lua ALIAS liblua) -set(Lua_FOUND TRUE CACHE BOOL "Lua found" FORCE) - # Link libraries target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PRIVATE cglm - liblua m fat PkgConfig::zip diff --git a/cmake/targets/vita.cmake b/cmake/targets/vita.cmake index 53f1d017..eadf73e1 100644 --- a/cmake/targets/vita.cmake +++ b/cmake/targets/vita.cmake @@ -20,31 +20,9 @@ set(CGLM_SHARED OFF CACHE BOOL "Build cglm shared" FORCE) set(CGLM_STATIC ON CACHE BOOL "Build cglm static" FORCE) find_package(cglm REQUIRED) -# Compile lua -include(FetchContent) -FetchContent_Declare( - liblua - URL https://www.lua.org/ftp/lua-5.5.0.tar.gz -) -FetchContent_MakeAvailable(liblua) -set(LUA_SRC_DIR "${liblua_SOURCE_DIR}/src") -set(LUA_C_FILES - lapi.c lauxlib.c lbaselib.c lcode.c lcorolib.c lctype.c ldblib.c ldebug.c - ldo.c ldump.c lfunc.c lgc.c linit.c liolib.c llex.c lmathlib.c lmem.c - loadlib.c lobject.c lopcodes.c loslib.c lparser.c lstate.c lstring.c - lstrlib.c ltable.c ltablib.c ltm.c lundump.c lutf8lib.c lvm.c lzio.c -) -list(TRANSFORM LUA_C_FILES PREPEND "${LUA_SRC_DIR}/") -add_library(liblua STATIC ${LUA_C_FILES}) -target_include_directories(liblua PUBLIC "${LUA_SRC_DIR}") -target_compile_definitions(liblua PRIVATE LUA_USE_C89) -add_library(lua::lua ALIAS liblua) -set(Lua_FOUND TRUE CACHE BOOL "Lua found" FORCE) - # Link libraries target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC ${SDL2_LIBRARIES} - liblua cglm SDL2 SDL2main diff --git a/src/dusk/CMakeLists.txt b/src/dusk/CMakeLists.txt index 0b879e61..969a96d7 100644 --- a/src/dusk/CMakeLists.txt +++ b/src/dusk/CMakeLists.txt @@ -32,18 +32,9 @@ if(NOT yyjson_FOUND) endif() endif() -if(NOT Lua_FOUND) - find_package(Lua REQUIRED) - if(Lua_FOUND AND NOT TARGET Lua::Lua) - add_library(Lua::Lua INTERFACE IMPORTED) - set_target_properties( - Lua::Lua - PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${LUA_INCLUDE_DIR}" - INTERFACE_LINK_LIBRARIES "${LUA_LIBRARIES}" - ) - endif() - target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC Lua::Lua) +if(NOT jerryscript_FOUND) + find_package(jerryscript REQUIRED) + target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC jerryscript) endif() # Includes diff --git a/src/dusk/asset/loader/script/assetscriptloader.c b/src/dusk/asset/loader/script/assetscriptloader.c index 8ddee48c..6637e817 100644 --- a/src/dusk/asset/loader/script/assetscriptloader.c +++ b/src/dusk/asset/loader/script/assetscriptloader.c @@ -1,82 +1,95 @@ /** * Copyright (c) 2026 Dominic Masters - * + * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #include "assetscriptloader.h" #include "assert/assert.h" +#include +#include errorret_t assetScriptLoader(assetfile_t *file) { assertNotNull(file, "Asset file cannot be NULL"); - assertNull(file->zipFile, "Asset file zip handle must be NULL"); + assertNull(file->zipFile, "Asset file zip handle must be NULL before open"); assertNotNull(file->output, "Asset file output cannot be NULL"); assetscript_t *script = (assetscript_t *)file->output; - // Open the asset for buffering errorChain(assetFileOpen(file)); - // Request loading - if(lua_load( - script->ctx->luaState, - assetScriptReader, - file, - file->filename, - NULL - ) != LUA_OK) { - const char_t *strErr = lua_tostring(script->ctx->luaState, -1); - lua_pop(script->ctx->luaState, 1); - errorThrow("Failed to load Lua script: %s", strErr); + // Accumulate full source into a dynamically grown buffer. + size_t srcLen = 0; + size_t capacity = ASSET_SCRIPT_CHUNK_SIZE; + char_t *src = (char_t *)malloc(capacity + 1); + if(!src) { + assetFileClose(file); + errorThrow("Out of memory reading script: %s", file->filename); } - // Now loaded, exec - if(lua_pcall(script->ctx->luaState, 0, LUA_MULTRET, 0) != LUA_OK) { - const char_t *strErr = lua_tostring(script->ctx->luaState, -1); - lua_pop(script->ctx->luaState, 1); - errorThrow("Failed to execute Lua script: %s", strErr); + while(1) { + if(srcLen + ASSET_SCRIPT_CHUNK_SIZE > capacity) { + capacity = srcLen + ASSET_SCRIPT_CHUNK_SIZE; + char_t *tmp = (char_t *)realloc(src, capacity + 1); + if(!tmp) { + free(src); + assetFileClose(file); + errorThrow("Out of memory reading script: %s", file->filename); + } + src = tmp; + } + zip_int64_t n = zip_fread( + file->zipFile, src + srcLen, ASSET_SCRIPT_CHUNK_SIZE + ); + if(n <= 0) break; + srcLen += (size_t)n; + } + src[srcLen] = '\0'; + + errorret_t closeRet = assetFileClose(file); + + jerry_value_t result = jerry_eval( + (const jerry_char_t *)src, + srcLen, + JERRY_PARSE_NO_OPTS + ); + free(src); + + if(jerry_value_is_exception(result)) { + jerry_value_t errVal = jerry_exception_value(result, false); + jerry_value_t errStr = jerry_value_to_string(errVal); + char_t buf[256]; + jerry_size_t len = jerry_string_to_buffer( + errStr, JERRY_ENCODING_UTF8, (jerry_char_t *)buf, sizeof(buf) - 1 + ); + buf[len] = '\0'; + jerry_value_free(errStr); + jerry_value_free(errVal); + jerry_value_free(result); + errorThrow("Script error in '%s': %s", file->filename, buf); } - // Close the file - return assetFileClose(file); + if(script->resultOut != NULL) { + *(script->resultOut) = result; + } else { + jerry_value_free(result); + } + + return closeRet; } -errorret_t assetScriptLoad(const char_t *path, scriptcontext_t *ctx) { +errorret_t assetScriptLoad( + const char_t *path, + scriptcontext_t *ctx, + jerry_value_t *resultOut +) { assertNotNull(path, "Script path cannot be NULL"); assertNotNull(ctx, "Script context cannot be NULL"); - - assetscript_t script; - script.ctx = ctx; - return assetLoad( - path, - assetScriptLoader, - NULL, - &script - ); + assetscript_t scriptData; + scriptData.ctx = ctx; + scriptData.resultOut = resultOut; + + return assetLoad(path, assetScriptLoader, NULL, &scriptData); } - -const char_t * assetScriptReader(lua_State* L, void* data, size_t* size) { - assetfile_t *file = (assetfile_t*)data; - assertNotNull(file, "Script asset file cannot be NULL"); - assertNotNull(file->zipFile, "Script asset zip handle cannot be NULL"); - assertNotNull(file->output, "Script asset output cannot be NULL"); - - assetscript_t *script = (assetscript_t *)file->output; - assertNotNull(script, "Script asset output cannot be NULL"); - - zip_int64_t read = zip_fread( - file->zipFile, - script->buffer, - sizeof(script->buffer) - ); - - if(read < 0) { - *size = 0; - return NULL; - } - - *size = (size_t)read; - return script->buffer; -} \ No newline at end of file diff --git a/src/dusk/asset/loader/script/assetscriptloader.h b/src/dusk/asset/loader/script/assetscriptloader.h index 847f4f13..3abfe63b 100644 --- a/src/dusk/asset/loader/script/assetscriptloader.h +++ b/src/dusk/asset/loader/script/assetscriptloader.h @@ -1,6 +1,6 @@ /** * Copyright (c) 2026 Dominic Masters - * + * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ @@ -9,7 +9,7 @@ #include "asset/asset.h" #include "script/scriptcontext.h" -#define ASSET_SCRIPT_BUFFER_SIZE 1024 +#define ASSET_SCRIPT_CHUNK_SIZE 1024 typedef struct { void *nothing; @@ -17,12 +17,13 @@ typedef struct { typedef struct { scriptcontext_t *ctx; - char_t buffer[ASSET_SCRIPT_BUFFER_SIZE]; + jerry_value_t *resultOut; } assetscript_t; /** - * Handler for script assets. - * + * Handler for script assets. Reads the full source, evaluates it with + * JerryScript, and optionally stores the result. + * * @param file Asset file to load the script from. * @return Any error that occurs during loading. */ @@ -30,19 +31,16 @@ errorret_t assetScriptLoader(assetfile_t *file); /** * Loads a script from the specified path. - * - * @param path Path to the script asset. - * @param ctx Script context to load the script into. + * + * @param path Path to the script asset. + * @param ctx Script context to load the script into. + * @param resultOut Optional out-parameter for the script return value. + * Caller must call jerry_value_free() if non-NULL. + * Pass NULL to discard the return value. * @return Any error that occurs during loading. */ -errorret_t assetScriptLoad(const char_t *path, scriptcontext_t *ctx); - -/** - * Reader function for Lua to read script data from the asset. - * - * @param L Lua state. - * @param data Pointer to the scriptcontext_t structure. - * @param size Pointer to store the size of the read data. - * @return Pointer to the read data buffer. - */ -const char_t * assetScriptReader(lua_State* L, void* data, size_t* size); \ No newline at end of file +errorret_t assetScriptLoad( + const char_t *path, + scriptcontext_t *ctx, + jerry_value_t *resultOut +); diff --git a/src/dusk/engine/engine.c b/src/dusk/engine/engine.c index dc2b2613..34c876d4 100644 --- a/src/dusk/engine/engine.c +++ b/src/dusk/engine/engine.c @@ -50,7 +50,7 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) { /* Run the init script. */ consolePrint("Engine initialized"); - errorChain(scriptContextExecFile(&SCRIPT_MANAGER.mainContext, "init.lua")); + errorChain(scriptContextExecFile(&SCRIPT_MANAGER.mainContext, "init.js", NULL)); errorOk(); } diff --git a/src/dusk/event/event.c b/src/dusk/event/event.c index 0f6bf074..c289f8ba 100644 --- a/src/dusk/event/event.c +++ b/src/dusk/event/event.c @@ -1,6 +1,6 @@ /** * Copyright (c) 2026 Dominic Masters - * + * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ @@ -10,16 +10,6 @@ #include "util/memory.h" #include "console/console.h" -static int eventLuaTraceback(lua_State *L) { - const char *msg = lua_tostring(L, 1); - if(msg) { - luaL_traceback(L, L, msg, 1); - } else { - lua_pushliteral(L, "(no error message)"); - } - return 1; -} - void eventInit( event_t *event, eventlistener_t *array, @@ -57,19 +47,16 @@ eventsub_t eventSubscribeUser( "Script event listener context cannot be NULL" ); assertTrue( - user.script.luaFunctionRef != LUA_NOREF, + user.script.funcValue != 0, "Script event listener function reference is invalid" ); } else { assertUnreachable("Unknown event listener type"); } - - // Gen a new ID + eventsub_t id = event->nextId++; - // Did we wrap? assertTrue(event->nextId != 0, "Event subscription ID overflow"); - // Append listener eventlistener_t *listener = &event->listenerArray[event->listenerCount++]; memoryZero(listener, sizeof(eventlistener_t)); listener->user = user; @@ -94,49 +81,29 @@ eventsub_t eventSubscribe( eventsub_t eventSubscribeScriptContext( event_t *event, scriptcontext_t *context, - const int functionIndex + jerry_value_t funcValue ) { assertNotNull(context, "Script context cannot be NULL"); - assertTrue( - lua_isfunction(context->luaState, functionIndex), - "Expected function at given index" - ); + assertTrue(funcValue != 0, "Script function value is invalid"); - // Create a reference to the function - lua_pushvalue(context->luaState, functionIndex); - int funcRef = luaL_ref(context->luaState, LUA_REGISTRYINDEX); - - eventscript_t scriptUser = { - .context = context, - .luaFunctionRef = funcRef - }; - - // Note to the context that it is now a part of this event bool_t alreadySubbed = false; - uint8_t i; - i = 0; + uint8_t i = 0; do { - if(context->subscribedEvents[i] != event) { - i++; - continue; + if(context->subscribedEvents[i] == event) { + alreadySubbed = true; + break; } - - if(context->subscribedEvents[i] == NULL) break; - - alreadySubbed = true; - break; + i++; } while(i < SCRIPT_CONTEXT_MAX_EVENT_SUBSCRIPTIONS); if(!alreadySubbed) { i = 0; do { - if(context->subscribedEvents[i] != NULL) { - i++; - continue; + if(context->subscribedEvents[i] == NULL) { + context->subscribedEvents[i] = event; + break; } - - context->subscribedEvents[i] = event; - break; + i++; } while(i < SCRIPT_CONTEXT_MAX_EVENT_SUBSCRIPTIONS); assertTrue( @@ -148,7 +115,12 @@ eventsub_t eventSubscribeScriptContext( return eventSubscribeUser( event, EVENT_TYPE_SCRIPT, - (eventuserdata_t){ .script = scriptUser } + (eventuserdata_t){ + .script = { + .context = context, + .funcValue = funcValue + } + } ); } @@ -165,19 +137,13 @@ void eventUnsubscribe(event_t *event, const eventsub_t id) { continue; } - // Release Lua registry reference before the slot is overwritten if(event->listenerArray[index].type == EVENT_TYPE_SCRIPT) { - scriptcontext_t *ctx = event->listenerArray[index].user.script.context; - if(ctx != NULL && ctx->luaState != NULL) { - luaL_unref( - ctx->luaState, - LUA_REGISTRYINDEX, - event->listenerArray[index].user.script.luaFunctionRef - ); + jerry_value_t funcVal = event->listenerArray[index].user.script.funcValue; + if(funcVal != 0) { + jerry_value_free(funcVal); } } - // Swap with last and shrink event->listenerArray[index] = event->listenerArray[--event->listenerCount]; return; } while(index < event->listenerCount); @@ -188,7 +154,7 @@ void eventUnsubscribeScriptContext(event_t *event, const scriptcontext_t *ctx) { assertNotNull(ctx, "Script context cannot be NULL"); if(event->listenerCount == 0) return; - + uint16_t i = 0; do { eventlistener_t *listener = &event->listenerArray[i]; @@ -199,9 +165,6 @@ void eventUnsubscribeScriptContext(event_t *event, const scriptcontext_t *ctx) { i++; continue; } - - // This listener belongs to the context and will need to go away. This will - // in turn decrement the listener count so we don't increment i here. eventUnsubscribe(event, listener->id); } while(i < event->listenerCount); } @@ -214,43 +177,55 @@ void eventInvoke( assertNotNull(event, "Event cannot be NULL"); if(event->listenerCount == 0) return; - + event->isInvoking = true; - uint16_t i = 0; - eventdata_t data ={ + eventdata_t data = { .event = event, .eventParams = eventParams, }; + uint16_t i = 0; do { eventlistener_t *listener = &event->listenerArray[i]; if(listener->type == EVENT_TYPE_C) { listener->user.c.callback(&data, listener->user.c); } else if(listener->type == EVENT_TYPE_SCRIPT) { - lua_State *L = listener->user.script.context->luaState; - assertNotNull(L, "Lua state in event listener cannot be NULL"); + jerry_value_t funcVal = listener->user.script.funcValue; + assertNotNull((void *)(uintptr_t)funcVal, "Script function value is NULL"); - lua_pushcfunction(L, eventLuaTraceback); - int handlerIdx = lua_gettop(L); - lua_rawgeti(L, LUA_REGISTRYINDEX, listener->user.script.luaFunctionRef); + jerry_value_t callArgs[1]; + jerry_length_t argCount = 0; - int numArgs = 0; if(eventParams != NULL) { - lua_pushlightuserdata(L, (void *)eventParams); - numArgs = 1; + callArgs[0] = jerry_object(); + jerry_object_set_native_ptr( + callArgs[0], &JS_PTR_NATIVE_INFO, (void *)eventParams + ); + argCount = 1; } - printf("Invoking Lua event listener with %d argument(s)\n", numArgs); + jerry_value_t result = jerry_call( + funcVal, jerry_undefined(), callArgs, argCount + ); - if(lua_pcall(L, numArgs, 0, handlerIdx) != LUA_OK) { - const char_t *strErr = lua_tostring(L, -1); - consolePrint("Error invoking Lua event listener:\n%s\n", strErr); - lua_pop(L, 1); + if(argCount > 0) jerry_value_free(callArgs[0]); + + if(jerry_value_is_exception(result)) { + jerry_value_t errStr = jerry_value_to_string( + jerry_exception_value(result, false) + ); + char_t buf[256]; + jerry_size_t len = jerry_string_to_buffer( + errStr, JERRY_ENCODING_UTF8, (jerry_char_t *)buf, sizeof(buf) - 1 + ); + buf[len] = '\0'; + jerry_value_free(errStr); + consolePrint("Error invoking script event listener:\n%s\n", buf); } - lua_pop(L, 1); + jerry_value_free(result); } else { assertUnreachable("Unknown event listener type"); } @@ -258,4 +233,4 @@ void eventInvoke( } while(i < event->listenerCount); event->isInvoking = false; -} \ No newline at end of file +} diff --git a/src/dusk/event/event.h b/src/dusk/event/event.h index 13c952a2..56ab4d92 100644 --- a/src/dusk/event/event.h +++ b/src/dusk/event/event.h @@ -84,7 +84,7 @@ eventsub_t eventSubscribe( eventsub_t eventSubscribeScriptContext( event_t *event, scriptcontext_t *context, - const int functionIndex + jerry_value_t funcValue ); /** diff --git a/src/dusk/event/eventuser.h b/src/dusk/event/eventuser.h index 1e6f3c5c..f61cd970 100644 --- a/src/dusk/event/eventuser.h +++ b/src/dusk/event/eventuser.h @@ -1,6 +1,6 @@ /** * Copyright (c) 2026 Dominic Masters - * + * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ @@ -16,7 +16,7 @@ typedef enum { typedef struct { scriptcontext_t *context; - int luaFunctionRef; + jerry_value_t funcValue; } eventscript_t; typedef struct eventc_s { @@ -27,4 +27,4 @@ typedef struct eventc_s { typedef union eventuserdata_u { eventscript_t script; eventc_t c; -} eventuserdata_t; \ No newline at end of file +} eventuserdata_t; diff --git a/src/dusk/scene/scene.c b/src/dusk/scene/scene.c index 5b2c25ce..323f23db 100644 --- a/src/dusk/scene/scene.c +++ b/src/dusk/scene/scene.c @@ -24,7 +24,7 @@ scene_t SCENE; errorret_t sceneInit(void) { memoryZero(&SCENE, sizeof(scene_t)); - SCENE.scriptRef = LUA_NOREF; + SCENE.scriptRef = SCENE_SCRIPT_REF_NONE; errorOk(); } @@ -40,25 +40,22 @@ errorret_t sceneUpdate(void) { } if(SCENE.sceneActive) { - errorChain(moduleSceneCall(SCRIPT_MANAGER.mainContext.luaState, "update")); + errorChain(moduleSceneCall("update")); } errorOk(); } errorret_t sceneRender(void) { - // Get Cameras entityid_t camEnts[ENTITY_COUNT_MAX]; componentid_t camComps[ENTITY_COUNT_MAX]; entityid_t camCount = componentGetEntitiesWithComponent( COMPONENT_TYPE_CAMERA, camEnts, camComps ); - // Prep Matricies mat4 view, proj, model; if(camCount > 0) { - // Get meshes entityid_t meshEnts[ENTITY_COUNT_MAX]; componentid_t meshComps[ENTITY_COUNT_MAX]; entityid_t meshCount = componentGetEntitiesWithComponent( @@ -68,7 +65,6 @@ errorret_t sceneRender(void) { if(meshCount > 0) { errorChain(shaderBind(&SHADER_UNLIT)); - // For each camera. for(entityid_t camIndex = 0; camIndex < camCount; camIndex++) { entityid_t camEnt = camEnts[camIndex]; componentid_t camComp = camComps[camIndex]; @@ -81,15 +77,11 @@ errorret_t sceneRender(void) { entityCameraGetProjection(camEnt, camComp, proj); entityPositionGetTransform(camEnt, camPos, view); - // For each mesh. for(entityid_t meshIndex = 0; meshIndex < meshCount; meshIndex++) { entityid_t meshEnt = meshEnts[meshIndex]; - componentid_t meshComp = meshComps[meshIndex]; mesh_t *mesh = entityMeshGetMesh(meshEnt, meshComp); - if(mesh == NULL) { - continue; - } + if(mesh == NULL) continue; componentid_t meshPos = entityGetComponent( meshEnt, COMPONENT_TYPE_POSITION @@ -129,7 +121,6 @@ errorret_t sceneRender(void) { } } - // Here is where UI will go glm_ortho( 0.0f, SCREEN.width, SCREEN.height, 0.0f, @@ -163,15 +154,11 @@ errorret_t sceneSetImmediate(const char_t *scene) { } if(SCENE.sceneActive) { - errorChain(moduleSceneCall( - SCRIPT_MANAGER.mainContext.luaState, "dispose" - )); + errorChain(moduleSceneCall("dispose")); SCENE.sceneActive = false; } - // Wipe Scene back to a clean table before loading the next file so custom - // methods from the previous scene (e.g. Scene.doThing) cannot bleed through. - moduleSceneReset(SCRIPT_MANAGER.mainContext.luaState); + moduleSceneReset(); stringCopy( SCENE.sceneCurrent, @@ -180,22 +167,19 @@ errorret_t sceneSetImmediate(const char_t *scene) { ); if(scene != NULL) { - lua_State *L = SCRIPT_MANAGER.mainContext.luaState; + jerry_value_t sceneObj = SCENE_SCRIPT_REF_NONE; + errorChain(scriptContextExecFile( + &SCRIPT_MANAGER.mainContext, scene, &sceneObj + )); - int32_t stackBase = lua_gettop(L); - - errorChain(scriptContextExecFile(&SCRIPT_MANAGER.mainContext, scene)); - - int32_t nReturns = lua_gettop(L) - stackBase; - if(nReturns < 1 || !lua_istable(L, stackBase + 1)) { - lua_settop(L, stackBase); - errorThrow("Scene '%s' must return a table", scene); + if(!jerry_value_is_object(sceneObj)) { + if(sceneObj != SCENE_SCRIPT_REF_NONE) jerry_value_free(sceneObj); + errorThrow("Scene '%s' must return an object", scene); } - lua_settop(L, stackBase + 1); - SCENE.scriptRef = luaL_ref(L, LUA_REGISTRYINDEX); + SCENE.scriptRef = sceneObj; - errorChain(moduleSceneCall(SCRIPT_MANAGER.mainContext.luaState, "init")); + errorChain(moduleSceneCall("init")); SCENE.sceneActive = true; } @@ -211,6 +195,6 @@ void sceneSet(const char_t *scene) { } errorret_t sceneDispose(void) { - errorChain(moduleSceneCall(SCRIPT_MANAGER.mainContext.luaState, "dispose")); + errorChain(moduleSceneCall("dispose")); errorOk(); } diff --git a/src/dusk/scene/scene.h b/src/dusk/scene/scene.h index 3f4eb8fe..7c0a9233 100644 --- a/src/dusk/scene/scene.h +++ b/src/dusk/scene/scene.h @@ -14,63 +14,55 @@ typedef struct { bool_t sceneActive; - int scriptRef; + jerry_value_t scriptRef; char_t sceneCurrent[ASSET_FILE_PATH_MAX]; char_t sceneNext[ASSET_FILE_PATH_MAX]; } scene_t; extern scene_t SCENE; +/** Sentinel value meaning no scene script is loaded. */ +#define SCENE_SCRIPT_REF_NONE ((jerry_value_t)0) + /** - * Initializes the scene manager - * + * Initializes the scene manager. + * * @return Any error state that happened. */ errorret_t sceneInit(void); /** - * Ticks the scene manager, may or may not call the scene's update method - * depending on time state. - * + * Ticks the scene manager; may call the scene's update method. + * * @return Any error state that happened. */ errorret_t sceneUpdate(void); /** - * Renders the scene, happens regardless of time. - * + * Renders the scene. + * * @return Any error state that happened. */ errorret_t sceneRender(void); /** - * Internal method to immediately switch scenes, this will also delete some of - * the lua state, which can cause problems if called during a lua callback, so - * this is managed by the scene manager. - * + * Immediately switches scenes, disposing the current one first. + * * @param scene Scene to switch to (asset file path). * @return Any error state that happened. */ errorret_t sceneSetImmediate(const char_t *scene); /** - * Requests the scene manager to change scenes when it is next able to. This - * will not guarantee that the scene is valid or without errors. - * + * Requests a scene change on the next safe opportunity. + * * @param scene Which scene to set. */ void sceneSet(const char_t *scene); /** * Disposes of the current scene. + * * @return Any error state that happened. */ errorret_t sceneDispose(void); - -/** - * Lua callback when Scene.set is invoked. - * - * @param L Lua state, expects the first argument to be the scene name (string). - * @return 0, does not return any values to Lua. - */ -int sceneSetLua(lua_State *L); \ No newline at end of file diff --git a/src/dusk/script/module/display/modulecolor.h b/src/dusk/script/module/display/modulecolor.h index 0291dbec..09c8abc4 100644 --- a/src/dusk/script/module/display/modulecolor.h +++ b/src/dusk/script/module/display/modulecolor.h @@ -10,112 +10,170 @@ #include "display/color.h" #include "time/time.h" -static int moduleColorIndex(lua_State *L) { - const color_t *color = (const color_t *)luaL_checkudata(L, 1, "color_mt"); - assertNotNull(color, "Color struct cannot be NULL."); - const char_t *key = luaL_checkstring(L, 2); +// --------------------------------------------------------------------------- +// Native info / prototype +// --------------------------------------------------------------------------- - if(stringCompare(key, "r") == 0) { lua_pushnumber(L, color->r); return 1; } - if(stringCompare(key, "g") == 0) { lua_pushnumber(L, color->g); return 1; } - if(stringCompare(key, "b") == 0) { lua_pushnumber(L, color->b); return 1; } - if(stringCompare(key, "a") == 0) { lua_pushnumber(L, color->a); return 1; } - - lua_getmetatable(L, 1); - lua_getfield(L, -1, key); - return 1; +static void freeColorNative(void *ptr, jerry_object_native_info_t *info) { + (void)info; + free(ptr); } +static const jerry_object_native_info_t COLOR_NATIVE_INFO = { + .free_cb = freeColorNative, + .number_of_references = 0, + .offset_of_references = 0 +}; +static jerry_value_t s_colorProto = 0; -static int moduleColorNewIndex(lua_State *L) { - color_t *color = (color_t *)luaL_checkudata(L, 1, "color_mt"); - assertNotNull(color, "Color struct cannot be NULL."); - const char_t *key = luaL_checkstring(L, 2); +// --------------------------------------------------------------------------- +// Property getters / setters +// --------------------------------------------------------------------------- - if(stringCompare(key, "r") == 0) { - color->r = (colorchannel8_t)luaL_checknumber(L, 3); return 0; - } else if(stringCompare(key, "g") == 0) { - color->g = (colorchannel8_t)luaL_checknumber(L, 3); return 0; - } else if(stringCompare(key, "b") == 0) { - color->b = (colorchannel8_t)luaL_checknumber(L, 3); return 0; - } else if(stringCompare(key, "a") == 0) { - color->a = (colorchannel8_t)luaL_checknumber(L, 3); return 0; - } - - luaL_error(L, "color: unknown property '%s'", key); - return 0; -} - -static int moduleColorToString(lua_State *L) { - const color_t *color = (const color_t *)luaL_checkudata(L, 1, "color_mt"); - assertNotNull(color, "Color struct cannot be NULL."); - lua_pushfstring(L, "color(r=%d, g=%d, b=%d, a=%d)", - color->r, color->g, color->b, color->a +JS_FUNC(moduleColorGetR) { + color_t *color = (color_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &COLOR_NATIVE_INFO ); - return 1; + return color ? jerry_number(color->r) : jerry_undefined(); } - -static int moduleColorCreate(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL."); - - if( - !lua_isnumber(L, 1) || !lua_isnumber(L, 2) || - !lua_isnumber(L, 3) || !lua_isnumber(L, 4) - ) { - return luaL_error(L, "color(r, g, b, a) requires four number arguments."); +JS_FUNC(moduleColorSetR) { + color_t *color = (color_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &COLOR_NATIVE_INFO + ); + if(color && args_count > 0) { + color->r = (colorchannel8_t)jerry_value_as_number(args_p[0]); } - - color_t *color = (color_t *)lua_newuserdata(L, sizeof(color_t)); - luaL_getmetatable(L, "color_mt"); - lua_setmetatable(L, -2); - - color->r = (colorchannel8_t)lua_tonumber(L, 1); - color->g = (colorchannel8_t)lua_tonumber(L, 2); - color->b = (colorchannel8_t)lua_tonumber(L, 3); - color->a = (colorchannel8_t)lua_tonumber(L, 4); - return 1; + return jerry_undefined(); } -static int moduleColorRainbow(lua_State *L) { +JS_FUNC(moduleColorGetG) { + color_t *color = (color_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &COLOR_NATIVE_INFO + ); + return color ? jerry_number(color->g) : jerry_undefined(); +} +JS_FUNC(moduleColorSetG) { + color_t *color = (color_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &COLOR_NATIVE_INFO + ); + if(color && args_count > 0) { + color->g = (colorchannel8_t)jerry_value_as_number(args_p[0]); + } + return jerry_undefined(); +} + +JS_FUNC(moduleColorGetB) { + color_t *color = (color_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &COLOR_NATIVE_INFO + ); + return color ? jerry_number(color->b) : jerry_undefined(); +} +JS_FUNC(moduleColorSetB) { + color_t *color = (color_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &COLOR_NATIVE_INFO + ); + if(color && args_count > 0) { + color->b = (colorchannel8_t)jerry_value_as_number(args_p[0]); + } + return jerry_undefined(); +} + +JS_FUNC(moduleColorGetA) { + color_t *color = (color_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &COLOR_NATIVE_INFO + ); + return color ? jerry_number(color->a) : jerry_undefined(); +} +JS_FUNC(moduleColorSetA) { + color_t *color = (color_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &COLOR_NATIVE_INFO + ); + if(color && args_count > 0) { + color->a = (colorchannel8_t)jerry_value_as_number(args_p[0]); + } + return jerry_undefined(); +} + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +/** + * Creates a new JS color object wrapping a heap-allocated color_t. + * + * @param color Value to copy into the new object. + * @return Owned jerry_value_t with COLOR_NATIVE_INFO and prototype set. + */ +static inline jerry_value_t moduleColorMakeObject(color_t color) { + color_t *ptr = (color_t *)malloc(sizeof(color_t)); + *ptr = color; + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &COLOR_NATIVE_INFO, ptr); + if(s_colorProto != 0) jerry_object_set_proto(obj, s_colorProto); + return obj; +} + +/** + * Returns the native color_t pointer stored in a JS value, or NULL. + * + * @param val JS value to inspect. + * @return Pointer to the color_t, or NULL if not a color object. + */ +static inline color_t *moduleColorGetNative(jerry_value_t val) { + return (color_t *)jerry_object_get_native_ptr(val, &COLOR_NATIVE_INFO); +} + +// --------------------------------------------------------------------------- +// Constructors +// --------------------------------------------------------------------------- + +JS_FUNC(moduleColorCreate) { + JS_REQUIRE_ARGS(4); + JS_REQUIRE_NUMBER(0); + JS_REQUIRE_NUMBER(1); + JS_REQUIRE_NUMBER(2); + JS_REQUIRE_NUMBER(3); + + color_t c; + c.r = (colorchannel8_t)jerry_value_as_number(args_p[0]); + c.g = (colorchannel8_t)jerry_value_as_number(args_p[1]); + c.b = (colorchannel8_t)jerry_value_as_number(args_p[2]); + c.a = (colorchannel8_t)jerry_value_as_number(args_p[3]); + return moduleColorMakeObject(c); +} + +JS_FUNC(moduleColorRainbow) { float_t t = TIME.time * 4.0f; - if(lua_gettop(L) >= 1) { - if(!lua_isnumber(L, 1)) { - return luaL_error(L, "Rainbow time offset must be a number."); - } - t += (float_t)lua_tonumber(L, 1); + + if(args_count >= 1 && jerry_value_is_number(args_p[0])) { + t += (float_t)jerry_value_as_number(args_p[0]); } - if(lua_gettop(L) >= 2) { - if(!lua_isnumber(L, 2)) { - return luaL_error(L, "Rainbow speed multiplier must be a number."); - } - t *= (float_t)lua_tonumber(L, 2); + if(args_count >= 2 && jerry_value_is_number(args_p[1])) { + t *= (float_t)jerry_value_as_number(args_p[1]); } - color_t *color = (color_t *)lua_newuserdata(L, sizeof(color_t)); - color->r = (colorchannel8_t)((sinf(t) + 1.0f) * 0.5f * 255.0f); - color->g = (colorchannel8_t)((sinf(t + 2.0f) + 1.0f) * 0.5f * 255.0f); - color->b = (colorchannel8_t)((sinf(t + 4.0f) + 1.0f) * 0.5f * 255.0f); - color->a = 255; - - luaL_getmetatable(L, "color_mt"); - lua_setmetatable(L, -2); - return 1; + color_t c; + c.r = (colorchannel8_t)((sinf(t) + 1.0f) * 0.5f * 255.0f); + c.g = (colorchannel8_t)((sinf(t + 2.0f) + 1.0f) * 0.5f * 255.0f); + c.b = (colorchannel8_t)((sinf(t + 4.0f) + 1.0f) * 0.5f * 255.0f); + c.a = 255; + return moduleColorMakeObject(c); } -static void moduleColor(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL."); +// --------------------------------------------------------------------------- +// Module init +// --------------------------------------------------------------------------- - if(luaL_newmetatable(L, "color_mt")) { - lua_pushcfunction(L, moduleColorIndex); - lua_setfield(L, -2, "__index"); - lua_pushcfunction(L, moduleColorNewIndex); - lua_setfield(L, -2, "__newindex"); - lua_pushcfunction(L, moduleColorToString); - lua_setfield(L, -2, "__tostring"); - } - lua_pop(L, 1); +static void moduleColor(void) { + s_colorProto = jerry_object(); - lua_register(L, "color", moduleColorCreate); - lua_register(L, "colorRainbow", moduleColorRainbow); + jsDefineProperty(s_colorProto, "r", moduleColorGetR, moduleColorSetR); + jsDefineProperty(s_colorProto, "g", moduleColorGetG, moduleColorSetG); + jsDefineProperty(s_colorProto, "b", moduleColorGetB, moduleColorSetB); + jsDefineProperty(s_colorProto, "a", moduleColorGetA, moduleColorSetA); - luaL_dostring(L, COLOR_SCRIPT); + jsRegister("color", moduleColorCreate); + jsRegister("colorRainbow", moduleColorRainbow); + + jsEvalStr(COLOR_SCRIPT); } diff --git a/src/dusk/script/module/display/modulescreen.h b/src/dusk/script/module/display/modulescreen.h index 021f0f5f..e745ccd9 100644 --- a/src/dusk/script/module/display/modulescreen.h +++ b/src/dusk/script/module/display/modulescreen.h @@ -8,35 +8,51 @@ #pragma once #include "script/module/modulebase.h" #include "display/screen/screen.h" +#include "display/color.h" -static int moduleScreenGetWidth(lua_State *L) { - assertNotNull(L, "Lua state is null"); - lua_pushnumber(L, SCREEN.width); - return 1; +JS_FUNC(moduleScreenGetWidth) { + return jerry_number(SCREEN.width); } -static int moduleScreenGetHeight(lua_State *L) { - assertNotNull(L, "Lua state is null"); - lua_pushnumber(L, SCREEN.height); - return 1; +JS_FUNC(moduleScreenGetHeight) { + return jerry_number(SCREEN.height); } -static int moduleScreenSetBackground(lua_State *L) { - assertNotNull(L, "Lua state is null"); - - if(!lua_isuserdata(L, 1)) { - luaL_error(L, "Screen background color must be a color struct"); - return 0; +JS_FUNC(moduleScreenSetBackground) { + if(args_count < 1 || !jerry_value_is_object(args_p[0])) { + return JS_THROW("Screen background color must be a color object"); } - color_t *color = (color_t*)luaL_checkudata(L, 1, "color_mt"); - SCREEN.background = *color; - return 0; + jerry_value_t keyR = jerry_string_sz("r"); + jerry_value_t keyG = jerry_string_sz("g"); + jerry_value_t keyB = jerry_string_sz("b"); + jerry_value_t keyA = jerry_string_sz("a"); + + jerry_value_t valR = jerry_object_get(args_p[0], keyR); + jerry_value_t valG = jerry_object_get(args_p[0], keyG); + jerry_value_t valB = jerry_object_get(args_p[0], keyB); + jerry_value_t valA = jerry_object_get(args_p[0], keyA); + + jerry_value_free(keyR); + jerry_value_free(keyG); + jerry_value_free(keyB); + jerry_value_free(keyA); + + SCREEN.background.r = (colorchannel8_t)jerry_value_as_number(valR); + SCREEN.background.g = (colorchannel8_t)jerry_value_as_number(valG); + SCREEN.background.b = (colorchannel8_t)jerry_value_as_number(valB); + SCREEN.background.a = (colorchannel8_t)jerry_value_as_number(valA); + + jerry_value_free(valR); + jerry_value_free(valG); + jerry_value_free(valB); + jerry_value_free(valA); + + return jerry_undefined(); } -static void moduleScreen(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL."); - lua_register(L, "screenGetWidth", moduleScreenGetWidth); - lua_register(L, "screenGetHeight", moduleScreenGetHeight); - lua_register(L, "screenSetBackground", moduleScreenSetBackground); +static void moduleScreen(void) { + jsRegister("screenGetWidth", moduleScreenGetWidth); + jsRegister("screenGetHeight", moduleScreenGetHeight); + jsRegister("screenSetBackground", moduleScreenSetBackground); } diff --git a/src/dusk/script/module/display/moduleshader.h b/src/dusk/script/module/display/moduleshader.h index 7a19a8ba..2b4963ed 100644 --- a/src/dusk/script/module/display/moduleshader.h +++ b/src/dusk/script/module/display/moduleshader.h @@ -11,80 +11,87 @@ #include "display/shader/shaderunlit.h" #include "script/module/math/modulemat4.h" -static int moduleShaderBind(lua_State *l) { - assertNotNull(l, "Lua state cannot be NULL."); - shader_t *shader = (shader_t *)lua_touserdata(l, 1); - assertNotNull(shader, "Shader pointer cannot be NULL."); +// --------------------------------------------------------------------------- +// Functions +// --------------------------------------------------------------------------- + +JS_FUNC(moduleShaderBind) { + JS_REQUIRE_ARGS(1); + shader_t *shader = (shader_t *)jsUnwrapPointer(args_p[0]); + if(!shader) return JS_THROW("shaderBind: expected a shader object"); errorret_t ret = shaderBind(shader); if(ret.code != ERROR_OK) { - luaL_error(l, "Failed to bind shader: %s", ret.state->message); errorCatch(errorPrint(ret)); - return 0; + return JS_THROW("shaderBind: failed to bind shader"); } - return 0; + return jerry_undefined(); } -static int moduleShaderSetMatrix(lua_State *l) { - assertNotNull(l, "Lua state cannot be NULL."); - shader_t *shader = (shader_t *)lua_touserdata(l, 1); - assertNotNull(shader, "Shader pointer cannot be NULL."); - const char_t *uniformName = luaL_checkstring(l, 2); - mat4 *mat = (mat4 *)luaL_checkudata(l, 3, "mat4_mt"); - assertNotNull(mat, "Matrix pointer cannot be NULL."); +JS_FUNC(moduleShaderSetMatrix) { + JS_REQUIRE_ARGS(3); + shader_t *shader = (shader_t *)jsUnwrapPointer(args_p[0]); + if(!shader) return JS_THROW("shaderSetMatrix: expected a shader object"); - errorret_t ret = shaderSetMatrix(shader, uniformName, *mat); + JS_REQUIRE_STRING(1); + char_t uniformName[128]; + jsToString(args_p[1], uniformName, sizeof(uniformName)); + + mat4 mat; + if(!moduleMat4Check(args_p[2], mat)) { + return JS_THROW("shaderSetMatrix: third argument must be a mat4"); + } + + errorret_t ret = shaderSetMatrix(shader, uniformName, mat); if(ret.code != ERROR_OK) { - luaL_error(l, "Failed to set shader matrix: %s", ret.state->message); errorCatch(errorPrint(ret)); - return 0; + return JS_THROW("shaderSetMatrix: failed to set shader matrix"); } - return 0; + return jerry_undefined(); } -static int moduleShaderSetTexture(lua_State *l) { - assertNotNull(l, "Lua state cannot be NULL."); - shader_t *shader = (shader_t *)lua_touserdata(l, 1); - assertNotNull(shader, "Shader pointer cannot be NULL."); - const char_t *uniformName = luaL_checkstring(l, 2); - assertStrLenMin(uniformName, 1, "Uniform name cannot be empty."); +JS_FUNC(moduleShaderSetTexture) { + JS_REQUIRE_ARGS(2); + shader_t *shader = (shader_t *)jsUnwrapPointer(args_p[0]); + if(!shader) return JS_THROW("shaderSetTexture: expected a shader object"); - texture_t *texture; - if(lua_isnil(l, 3)) { - texture = NULL; - } else if(lua_isuserdata(l, 3)) { - texture = (texture_t *)lua_touserdata(l, 3); - assertNotNull(texture, "Texture pointer cannot be NULL."); - } else { - luaL_error(l, "Third argument must be a texture_mt userdata or nil."); - return 0; + JS_REQUIRE_STRING(1); + char_t uniformName[128]; + jsToString(args_p[1], uniformName, sizeof(uniformName)); + + texture_t *texture = NULL; + if( + args_count >= 3 && + !jerry_value_is_null(args_p[2]) && + !jerry_value_is_undefined(args_p[2]) + ) { + texture = (texture_t *)jsUnwrapPointer(args_p[2]); + if(!texture) return JS_THROW("shaderSetTexture: third argument must be a texture object or null"); } errorret_t ret = shaderSetTexture(shader, uniformName, texture); if(ret.code != ERROR_OK) { - luaL_error(l, "Failed to set shader texture: %s", ret.state->message); errorCatch(errorPrint(ret)); - return 0; + return JS_THROW("shaderSetTexture: failed to set shader texture"); } - return 0; + return jerry_undefined(); } -static void moduleShader(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL."); +// --------------------------------------------------------------------------- +// Module init +// --------------------------------------------------------------------------- - lua_pushlightuserdata(L, &SHADER_UNLIT); - lua_setglobal(L, "SHADER_UNLIT"); +static void moduleShader(void) { + jerry_value_t shaderUnlitVal = jsWrapPointer(&SHADER_UNLIT); + jsSetValue("SHADER_UNLIT", shaderUnlitVal); + jerry_value_free(shaderUnlitVal); - lua_pushstring(L, SHADER_UNLIT_PROJECTION); - lua_setglobal(L, "SHADER_UNLIT_PROJECTION"); - lua_pushstring(L, SHADER_UNLIT_VIEW); - lua_setglobal(L, "SHADER_UNLIT_VIEW"); - lua_pushstring(L, SHADER_UNLIT_MODEL); - lua_setglobal(L, "SHADER_UNLIT_MODEL"); - lua_pushstring(L, SHADER_UNLIT_TEXTURE); - lua_setglobal(L, "SHADER_UNLIT_TEXTURE"); + jsSetString("SHADER_UNLIT_PROJECTION", SHADER_UNLIT_PROJECTION); + jsSetString("SHADER_UNLIT_VIEW", SHADER_UNLIT_VIEW); + jsSetString("SHADER_UNLIT_MODEL", SHADER_UNLIT_MODEL); + jsSetString("SHADER_UNLIT_TEXTURE", SHADER_UNLIT_TEXTURE); - lua_register(L, "shaderBind", moduleShaderBind); - lua_register(L, "shaderSetMatrix", moduleShaderSetMatrix); - lua_register(L, "shaderSetTexture", moduleShaderSetTexture); + jsRegister("shaderBind", moduleShaderBind); + jsRegister("shaderSetMatrix", moduleShaderSetMatrix); + jsRegister("shaderSetTexture", moduleShaderSetTexture); } diff --git a/src/dusk/script/module/display/modulespritebatch.h b/src/dusk/script/module/display/modulespritebatch.h index 040cdfa1..5b5cc6e0 100644 --- a/src/dusk/script/module/display/modulespritebatch.h +++ b/src/dusk/script/module/display/modulespritebatch.h @@ -11,61 +11,98 @@ #include "script/module/math/modulevec2.h" #include "script/module/math/modulevec4.h" -static int moduleSpriteBatchFlush(lua_State *L) { - assertNotNull(L, "Lua state is null"); +// --------------------------------------------------------------------------- +// Functions +// --------------------------------------------------------------------------- + +JS_FUNC(moduleSpriteBatchFlush) { spriteBatchFlush(); - return 0; + return jerry_undefined(); } -static int moduleSpriteBatchClear(lua_State *L) { - assertNotNull(L, "Lua state is null"); +JS_FUNC(moduleSpriteBatchClear) { spriteBatchClear(); - return 0; + return jerry_undefined(); } -static int moduleSpriteBatchPush(lua_State *L) { - assertNotNull(L, "Lua state is null"); +JS_FUNC(moduleSpriteBatchPush) { + JS_REQUIRE_ARGS(2); - vec2 min, max; - moduleVec2Check(L, 1, min); - moduleVec2Check(L, 2, max); - - color_t *color = NULL; - if(lua_gettop(L) < 3 || lua_isnil(L, 3)) { - // allow NULL (white) - } else if(lua_isuserdata(L, 3)) { - color = (color_t *)luaL_checkudata(L, 3, "color_mt"); - } else { - return luaL_error(L, "Sprite color must be a color struct or nil"); + vec2 minPos, maxPos; + if(!moduleVec2Check(args_p[0], minPos)) { + return JS_THROW("spriteBatchPush: first argument must be a vec2"); + } + if(!moduleVec2Check(args_p[1], maxPos)) { + return JS_THROW("spriteBatchPush: second argument must be a vec2"); } +#if MESH_ENABLE_COLOR + color_t col = COLOR_WHITE; + if( + args_count >= 3 && + jerry_value_is_object(args_p[2]) && + !jerry_value_is_null(args_p[2]) && + !jerry_value_is_undefined(args_p[2]) + ) { + jerry_value_t kr = jerry_string_sz("r"); + jerry_value_t vr = jerry_object_get(args_p[2], kr); + col.r = (colorchannel8_t)jerry_value_as_number(vr); + jerry_value_free(vr); + jerry_value_free(kr); + + jerry_value_t kg = jerry_string_sz("g"); + jerry_value_t vg = jerry_object_get(args_p[2], kg); + col.g = (colorchannel8_t)jerry_value_as_number(vg); + jerry_value_free(vg); + jerry_value_free(kg); + + jerry_value_t kb = jerry_string_sz("b"); + jerry_value_t vb = jerry_object_get(args_p[2], kb); + col.b = (colorchannel8_t)jerry_value_as_number(vb); + jerry_value_free(vb); + jerry_value_free(kb); + + jerry_value_t ka = jerry_string_sz("a"); + jerry_value_t va = jerry_object_get(args_p[2], ka); + col.a = (colorchannel8_t)jerry_value_as_number(va); + jerry_value_free(va); + jerry_value_free(ka); + } +#endif + float_t u0 = 0.0f, v0 = 0.0f, u1 = 1.0f, v1 = 1.0f; - if(lua_gettop(L) >= 4 && !lua_isnil(L, 4)) { - vec4 uv; moduleVec4Check(L, 4, uv); + if( + args_count >= 4 && + !jerry_value_is_null(args_p[3]) && + !jerry_value_is_undefined(args_p[3]) + ) { + vec4 uv; + if(!moduleVec4Check(args_p[3], uv)) { + return JS_THROW("spriteBatchPush: fourth argument must be a vec4 or null"); + } u0 = uv[0]; v0 = uv[1]; u1 = uv[2]; v1 = uv[3]; } errorret_t ret = spriteBatchPush( - min[0], min[1], max[0], max[1], - #if MESH_ENABLE_COLOR - color == NULL ? COLOR_WHITE : *color, - #endif + minPos[0], minPos[1], maxPos[0], maxPos[1], +#if MESH_ENABLE_COLOR + col, +#endif u0, v0, u1, v1 ); if(ret.code != ERROR_OK) { - int err = luaL_error(L, - "Failed to push sprite to batch: %s", - ret.state->message - ); errorCatch(errorPrint(ret)); - return err; + return JS_THROW("spriteBatchPush: failed to push sprite to batch"); } - - return 0; + return jerry_undefined(); } -static void moduleSpriteBatch(lua_State *L) { - lua_register(L, "spriteBatchFlush", moduleSpriteBatchFlush); - lua_register(L, "spriteBatchClear", moduleSpriteBatchClear); - lua_register(L, "spriteBatchPush", moduleSpriteBatchPush); +// --------------------------------------------------------------------------- +// Module init +// --------------------------------------------------------------------------- + +static void moduleSpriteBatch(void) { + jsRegister("spriteBatchFlush", moduleSpriteBatchFlush); + jsRegister("spriteBatchClear", moduleSpriteBatchClear); + jsRegister("spriteBatchPush", moduleSpriteBatchPush); } diff --git a/src/dusk/script/module/display/moduletext.h b/src/dusk/script/module/display/moduletext.h index bbcb81cb..2fcca8b2 100644 --- a/src/dusk/script/module/display/moduletext.h +++ b/src/dusk/script/module/display/moduletext.h @@ -11,62 +11,92 @@ #include "display/spritebatch/spritebatch.h" #include "script/module/math/modulevec2.h" -static int moduleTextDraw(lua_State *L) { - assertNotNull(L, "Lua state is null"); +// --------------------------------------------------------------------------- +// Functions +// --------------------------------------------------------------------------- - vec2 pos; moduleVec2Check(L, 1, pos); +JS_FUNC(moduleTextDraw) { + JS_REQUIRE_ARGS(2); - if(!lua_isstring(L, 2)) { - return luaL_error(L, "Text to draw must be a string"); + vec2 pos; + if(!moduleVec2Check(args_p[0], pos)) { + return JS_THROW("textDraw: first argument must be a vec2 position"); } - const char_t *text = (const char_t *)lua_tostring(L, 2); - color_t *color = NULL; - if(lua_gettop(L) < 3 || lua_isnil(L, 3)) { - // allow NULL (white) - } else if(lua_isuserdata(L, 3)) { - color = (color_t *)luaL_checkudata(L, 3, "color_mt"); - } else { - return luaL_error(L, "Text color must be a color struct or nil"); + JS_REQUIRE_STRING(1); + char_t text[1024]; + jsToString(args_p[1], text, sizeof(text)); + + color_t color = COLOR_WHITE; + if( + args_count >= 3 && + jerry_value_is_object(args_p[2]) && + !jerry_value_is_null(args_p[2]) && + !jerry_value_is_undefined(args_p[2]) + ) { + jerry_value_t kr = jerry_string_sz("r"); + jerry_value_t vr = jerry_object_get(args_p[2], kr); + color.r = (colorchannel8_t)jerry_value_as_number(vr); + jerry_value_free(vr); + jerry_value_free(kr); + + jerry_value_t kg = jerry_string_sz("g"); + jerry_value_t vg = jerry_object_get(args_p[2], kg); + color.g = (colorchannel8_t)jerry_value_as_number(vg); + jerry_value_free(vg); + jerry_value_free(kg); + + jerry_value_t kb = jerry_string_sz("b"); + jerry_value_t vb = jerry_object_get(args_p[2], kb); + color.b = (colorchannel8_t)jerry_value_as_number(vb); + jerry_value_free(vb); + jerry_value_free(kb); + + jerry_value_t ka = jerry_string_sz("a"); + jerry_value_t va = jerry_object_get(args_p[2], ka); + color.a = (colorchannel8_t)jerry_value_as_number(va); + jerry_value_free(va); + jerry_value_free(ka); } errorret_t ret = textDraw( - pos[0], pos[1], text, - color == NULL ? COLOR_WHITE : *color, + pos[0], pos[1], text, color, &DEFAULT_FONT_TILESET, &DEFAULT_FONT_TEXTURE ); if(ret.code != ERROR_OK) { errorCatch(errorPrint(ret)); - luaL_error(L, "Failed to draw text"); + return JS_THROW("textDraw: failed to draw text"); } ret = spriteBatchFlush(); if(ret.code != ERROR_OK) { errorCatch(errorPrint(ret)); - luaL_error(L, "Failed to flush sprite batch after drawing text"); + return JS_THROW("textDraw: failed to flush sprite batch"); } - return 0; + + return jerry_undefined(); } -static int moduleTextMeasure(lua_State *L) { - assertNotNull(L, "Lua state is null"); +JS_FUNC(moduleTextMeasure) { + JS_REQUIRE_ARGS(1); + JS_REQUIRE_STRING(0); - if(!lua_isstring(L, 1)) { - return luaL_error(L, "Text to measure must be a string"); - } - const char_t *text = (const char_t *)lua_tostring(L, 1); + char_t text[1024]; + jsToString(args_p[0], text, sizeof(text)); int32_t w = 0, h = 0; textMeasure(text, &DEFAULT_FONT_TILESET, &w, &h); vec2 size = { (float_t)w, (float_t)h }; - moduleVec2Push(L, size); - return 1; + return moduleVec2Push(size); } -static void moduleText(lua_State *L) { - assertNotNull(L, "Lua state is null"); - lua_register(L, "textDraw", moduleTextDraw); - lua_register(L, "textMeasure", moduleTextMeasure); +// --------------------------------------------------------------------------- +// Module init +// --------------------------------------------------------------------------- + +static void moduleText(void) { + jsRegister("textDraw", moduleTextDraw); + jsRegister("textMeasure", moduleTextMeasure); } diff --git a/src/dusk/script/module/display/moduletexture.h b/src/dusk/script/module/display/moduletexture.h index 4764d644..3bac1e31 100644 --- a/src/dusk/script/module/display/moduletexture.h +++ b/src/dusk/script/module/display/moduletexture.h @@ -10,89 +10,95 @@ #include "display/texture/texture.h" #include "asset/loader/display/assettextureloader.h" -static int moduleTextureIndex(lua_State *l) { - assertNotNull(l, "Lua state cannot be NULL."); +// --------------------------------------------------------------------------- +// Native info / prototype +// --------------------------------------------------------------------------- - texture_t *tex = (texture_t *)luaL_checkudata(l, 1, "texture_mt"); - assertNotNull(tex, "Texture pointer cannot be NULL."); - const char *key = luaL_checkstring(l, 2); - assertNotNull(key, "Key cannot be NULL."); +static void freeTextureNative(void *ptr, jerry_object_native_info_t *info) { + (void)info; + textureDispose((texture_t *)ptr); + free(ptr); +} +static const jerry_object_native_info_t TEXTURE_NATIVE_INFO = { + .free_cb = freeTextureNative, + .number_of_references = 0, + .offset_of_references = 0 +}; +static jerry_value_t s_textureProto = 0; - if(stringCompare(key, "width") == 0) { - lua_pushnumber(l, tex->width); return 1; - } else if(stringCompare(key, "height") == 0) { - lua_pushnumber(l, tex->height); return 1; - } +// --------------------------------------------------------------------------- +// Helper +// --------------------------------------------------------------------------- - lua_pushnil(l); - return 1; +/** + * Returns the native texture_t pointer stored in a JS value, or NULL. + * + * @param val JS value to inspect. + * @return Pointer to the texture_t, or NULL if not a texture object. + */ +static inline texture_t *moduleTextureGetNative(jerry_value_t val) { + return (texture_t *)jerry_object_get_native_ptr(val, &TEXTURE_NATIVE_INFO); } -static int moduleTextureToString(lua_State *l) { - assertNotNull(l, "Lua state cannot be NULL."); - texture_t *tex = (texture_t *)luaL_checkudata(l, 1, "texture_mt"); - assertNotNull(tex, "Texture pointer cannot be NULL."); - char buffer[64]; - snprintf(buffer, sizeof(buffer), "Texture(%dx%d)", tex->width, tex->height); - lua_pushstring(l, buffer); - return 1; +// --------------------------------------------------------------------------- +// Property getters (read-only) +// --------------------------------------------------------------------------- + +JS_FUNC(moduleTextureGetWidth) { + texture_t *tex = (texture_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &TEXTURE_NATIVE_INFO + ); + return tex ? jerry_number(tex->width) : jerry_undefined(); } -static int moduleTextureGC(lua_State *l) { - assertNotNull(l, "Lua state cannot be NULL."); - texture_t *tex = (texture_t *)luaL_checkudata(l, 1, "texture_mt"); - assertNotNull(tex, "Texture pointer cannot be NULL."); - textureDispose(tex); - return 0; +JS_FUNC(moduleTextureGetHeight) { + texture_t *tex = (texture_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &TEXTURE_NATIVE_INFO + ); + return tex ? jerry_number(tex->height) : jerry_undefined(); } -static int moduleTextureLoad(lua_State *l) { - assertNotNull(l, "Lua state cannot be NULL."); +// --------------------------------------------------------------------------- +// Constructor +// --------------------------------------------------------------------------- - if(!lua_isstring(l, 1)) { - luaL_error(l, "First argument must be a string filename."); - return 0; - } - if(!lua_isnumber(l, 2)) { - luaL_error(l, "Second argument must be a number format."); - return 0; - } +JS_FUNC(moduleTextureLoad) { + JS_REQUIRE_ARGS(2); + JS_REQUIRE_STRING(0); + JS_REQUIRE_NUMBER(1); - const char_t *filename = lua_tostring(l, 1); - assertNotNull(filename, "Filename cannot be NULL."); - assertStrLenMin(filename, 1, "Filename cannot be empty."); + char_t filename[256]; + jsToString(args_p[0], filename, sizeof(filename)); - texture_t *tex = (texture_t *)lua_newuserdata(l, sizeof(texture_t)); + textureformat_t format = (textureformat_t)(int32_t)jerry_value_as_number(args_p[1]); + + texture_t *tex = (texture_t *)malloc(sizeof(texture_t)); memoryZero(tex, sizeof(texture_t)); - textureformat_t format = (textureformat_t)lua_tonumber(l, 2); errorret_t ret = assetTextureLoad(filename, tex, format); if(ret.code != ERROR_OK) { errorCatch(errorPrint(ret)); - luaL_error(l, "Failed to load texture asset: %s", filename); - return 0; + free(tex); + return JS_THROW("textureLoad: failed to load texture"); } - luaL_getmetatable(l, "texture_mt"); - lua_setmetatable(l, -2); - return 1; + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &TEXTURE_NATIVE_INFO, tex); + if(s_textureProto != 0) jerry_object_set_proto(obj, s_textureProto); + return obj; } -static void moduleTexture(lua_State *L) { - assertNotNull(L, "Lua state cannot be null"); +// --------------------------------------------------------------------------- +// Module init +// --------------------------------------------------------------------------- - if(luaL_newmetatable(L, "texture_mt")) { - lua_pushcfunction(L, moduleTextureIndex); - lua_setfield(L, -2, "__index"); - lua_pushcfunction(L, moduleTextureToString); - lua_setfield(L, -2, "__tostring"); - lua_pushcfunction(L, moduleTextureGC); - lua_setfield(L, -2, "__gc"); - } - lua_pop(L, 1); +static void moduleTexture(void) { + s_textureProto = jerry_object(); - lua_pushnumber(L, TEXTURE_FORMAT_RGBA); - lua_setglobal(L, "TEXTURE_FORMAT_RGBA"); + jsDefineProperty(s_textureProto, "width", moduleTextureGetWidth, NULL); + jsDefineProperty(s_textureProto, "height", moduleTextureGetHeight, NULL); - lua_register(L, "textureLoad", moduleTextureLoad); + jsSetInt("TEXTURE_FORMAT_RGBA", (int32_t)TEXTURE_FORMAT_RGBA); + + jsRegister("textureLoad", moduleTextureLoad); } diff --git a/src/dusk/script/module/display/moduletileset.h b/src/dusk/script/module/display/moduletileset.h index 577c62fc..34e11f79 100644 --- a/src/dusk/script/module/display/moduletileset.h +++ b/src/dusk/script/module/display/moduletileset.h @@ -11,98 +11,133 @@ #include "asset/loader/display/assettilesetloader.h" #include "script/module/math/modulevec4.h" -static int moduleTilesetIndex(lua_State *l) { - assertNotNull(l, "Lua state cannot be NULL."); - const char_t *key = luaL_checkstring(l, 2); - assertNotNull(key, "Key cannot be NULL."); - tileset_t *ts = (tileset_t *)luaL_checkudata(l, 1, "tileset_mt"); - assertNotNull(ts, "Tileset pointer cannot be NULL."); +// --------------------------------------------------------------------------- +// Native info / prototype +// --------------------------------------------------------------------------- - if(stringCompare(key, "tileWidth") == 0) { - lua_pushnumber(l, ts->tileWidth); return 1; - } else if(stringCompare(key, "tileHeight") == 0) { - lua_pushnumber(l, ts->tileHeight); return 1; - } else if(stringCompare(key, "tileCount") == 0) { - lua_pushnumber(l, ts->tileCount); return 1; - } else if(stringCompare(key, "columns") == 0) { - lua_pushnumber(l, ts->columns); return 1; - } else if(stringCompare(key, "rows") == 0) { - lua_pushnumber(l, ts->rows); return 1; - } - - lua_pushnil(l); - return 1; +static void freeTilesetNative(void *ptr, jerry_object_native_info_t *info) { + (void)info; + free(ptr); } +static const jerry_object_native_info_t TILESET_NATIVE_INFO = { + .free_cb = freeTilesetNative, + .number_of_references = 0, + .offset_of_references = 0 +}; +static jerry_value_t s_tilesetProto = 0; -static int moduleTilesetToString(lua_State *l) { - tileset_t *ts = (tileset_t *)luaL_checkudata(l, 1, "tileset_mt"); - assertNotNull(ts, "Tileset pointer cannot be NULL."); - lua_pushfstring(l, "Tileset: %dx%d tile, %d columns, %d rows", - ts->tileWidth, ts->tileHeight, ts->columns, ts->rows +// --------------------------------------------------------------------------- +// Property getters (read-only) +// --------------------------------------------------------------------------- + +JS_FUNC(moduleTilesetGetTileWidth) { + tileset_t *ts = (tileset_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &TILESET_NATIVE_INFO ); - return 1; + return ts ? jerry_number(ts->tileWidth) : jerry_undefined(); } -static int moduleTilesetTileGetUV(lua_State *l) { - assertNotNull(l, "Lua state cannot be NULL."); - tileset_t *ts = (tileset_t *)luaL_checkudata(l, 1, "tileset_mt"); - assertNotNull(ts, "Tileset pointer cannot be NULL."); - uint16_t tileIndex = (uint16_t)luaL_checknumber(l, 2); - vec4 uv; tilesetTileGetUV(ts, tileIndex, uv); - moduleVec4Push(l, uv); - return 1; +JS_FUNC(moduleTilesetGetTileHeight) { + tileset_t *ts = (tileset_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &TILESET_NATIVE_INFO + ); + return ts ? jerry_number(ts->tileHeight) : jerry_undefined(); } -static int moduleTilesetPositionGetUV(lua_State *l) { - assertNotNull(l, "Lua state cannot be NULL."); - tileset_t *ts = (tileset_t *)luaL_checkudata(l, 1, "tileset_mt"); - assertNotNull(ts, "Tileset pointer cannot be NULL."); - uint16_t column = (uint16_t)luaL_checknumber(l, 2); - uint16_t row = (uint16_t)luaL_checknumber(l, 3); - vec4 uv; tilesetPositionGetUV(ts, column, row, uv); - moduleVec4Push(l, uv); - return 1; +JS_FUNC(moduleTilesetGetTileCount) { + tileset_t *ts = (tileset_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &TILESET_NATIVE_INFO + ); + return ts ? jerry_number(ts->tileCount) : jerry_undefined(); } -static int moduleTilesetLoad(lua_State *l) { - assertNotNull(l, "Lua state cannot be NULL."); +JS_FUNC(moduleTilesetGetColumns) { + tileset_t *ts = (tileset_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &TILESET_NATIVE_INFO + ); + return ts ? jerry_number(ts->columns) : jerry_undefined(); +} - if(!lua_isstring(l, 1)) { - luaL_error(l, "First argument must be a string filename."); - return 0; - } +JS_FUNC(moduleTilesetGetRows) { + tileset_t *ts = (tileset_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &TILESET_NATIVE_INFO + ); + return ts ? jerry_number(ts->rows) : jerry_undefined(); +} - const char_t *filename = lua_tostring(l, 1); - assertNotNull(filename, "Filename cannot be NULL."); - assertStrLenMin(filename, 1, "Filename cannot be empty."); +// --------------------------------------------------------------------------- +// Functions +// --------------------------------------------------------------------------- - tileset_t *tileset = (tileset_t *)lua_newuserdata(l, sizeof(tileset_t)); - memoryZero(tileset, sizeof(tileset_t)); +JS_FUNC(modulesTilesetTileGetUV) { + JS_REQUIRE_ARGS(2); + tileset_t *ts = (tileset_t *)jerry_object_get_native_ptr( + args_p[0], &TILESET_NATIVE_INFO + ); + if(!ts) return JS_THROW("tilesetTileGetUV: expected a tileset object"); - errorret_t ret = assetTilesetLoad(filename, tileset); + JS_REQUIRE_NUMBER(1); + uint16_t tileIndex = (uint16_t)jerry_value_as_number(args_p[1]); + + vec4 uv; + tilesetTileGetUV(ts, tileIndex, uv); + return moduleVec4Push(uv); +} + +JS_FUNC(moduleTilesetPositionGetUV) { + JS_REQUIRE_ARGS(3); + tileset_t *ts = (tileset_t *)jerry_object_get_native_ptr( + args_p[0], &TILESET_NATIVE_INFO + ); + if(!ts) return JS_THROW("tilesetPositionGetUV: expected a tileset object"); + + JS_REQUIRE_NUMBER(1); + JS_REQUIRE_NUMBER(2); + uint16_t col = (uint16_t)jerry_value_as_number(args_p[1]); + uint16_t row = (uint16_t)jerry_value_as_number(args_p[2]); + + vec4 uv; + tilesetPositionGetUV(ts, col, row, uv); + return moduleVec4Push(uv); +} + +JS_FUNC(moduleTilesetLoad) { + JS_REQUIRE_ARGS(1); + JS_REQUIRE_STRING(0); + + char_t filename[256]; + jsToString(args_p[0], filename, sizeof(filename)); + + tileset_t *ts = (tileset_t *)malloc(sizeof(tileset_t)); + memoryZero(ts, sizeof(tileset_t)); + + errorret_t ret = assetTilesetLoad(filename, ts); if(ret.code != ERROR_OK) { errorCatch(errorPrint(ret)); - luaL_error(l, "Failed to load tileset asset: %s", filename); - return 0; + free(ts); + return JS_THROW("tilesetLoad: failed to load tileset"); } - luaL_getmetatable(l, "tileset_mt"); - lua_setmetatable(l, -2); - return 1; + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &TILESET_NATIVE_INFO, ts); + if(s_tilesetProto != 0) jerry_object_set_proto(obj, s_tilesetProto); + return obj; } -static void moduleTileset(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +// --------------------------------------------------------------------------- +// Module init +// --------------------------------------------------------------------------- - if(luaL_newmetatable(L, "tileset_mt")) { - lua_pushcfunction(L, moduleTilesetIndex); - lua_setfield(L, -2, "__index"); - lua_pushcfunction(L, moduleTilesetToString); - lua_setfield(L, -2, "__tostring"); - } - lua_pop(L, 1); +static void moduleTileset(void) { + s_tilesetProto = jerry_object(); - lua_register(L, "tilesetLoad", moduleTilesetLoad); - lua_register(L, "tilesetTileGetUV", moduleTilesetTileGetUV); - lua_register(L, "tilesetPositionGetUV", moduleTilesetPositionGetUV); + jsDefineProperty(s_tilesetProto, "tileWidth", moduleTilesetGetTileWidth, NULL); + jsDefineProperty(s_tilesetProto, "tileHeight", moduleTilesetGetTileHeight, NULL); + jsDefineProperty(s_tilesetProto, "tileCount", moduleTilesetGetTileCount, NULL); + jsDefineProperty(s_tilesetProto, "columns", moduleTilesetGetColumns, NULL); + jsDefineProperty(s_tilesetProto, "rows", moduleTilesetGetRows, NULL); + + jsRegister("tilesetLoad", moduleTilesetLoad); + jsRegister("tilesetTileGetUV", modulesTilesetTileGetUV); + jsRegister("tilesetPositionGetUV", moduleTilesetPositionGetUV); } diff --git a/src/dusk/script/module/entity/component/moduleentitycamera.h b/src/dusk/script/module/entity/component/moduleentitycamera.h index d975889f..8a85dc3d 100644 --- a/src/dusk/script/module/entity/component/moduleentitycamera.h +++ b/src/dusk/script/module/entity/component/moduleentitycamera.h @@ -9,102 +9,67 @@ #include "script/module/modulebase.h" #include "entity/entity.h" #include "entity/component/display/entitycamera.h" +#include "moduleentityposition.h" -typedef struct { - entityid_t entityId; - componentid_t compId; -} entitycam_handle_t; +// ---- camera prototype ---- -/** - * __index metamethod for camera component userdata. - * - * @param L Lua state. Arg 1: entitycam userdata. Arg 2: key string. - * @return 1. - */ -static int moduleEntityCameraIndex(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +static jerry_value_t s_camProto = 0; - entitycam_handle_t *h = luaL_checkudata(L, 1, "entitycam_mt"); - assertNotNull(h, "invalid entitycam userdata"); +// -- zNear getter/setter -- - const char *k = luaL_checkstring(L, 2); - assertStrLenMin(k, 1, "property key cannot be empty"); - - if(stringCompare(k, "zNear") == 0) { - lua_pushnumber(L, entityCameraGetZNear(h->entityId, h->compId)); return 1; - } else if(stringCompare(k, "zFar") == 0) { - lua_pushnumber(L, entityCameraGetZFar(h->entityId, h->compId)); return 1; - } - - lua_getmetatable(L, 1); - lua_getfield(L, -1, k); - return 1; +JS_FUNC(moduleEntityCameraGetZNear) { + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + return jerry_number((double)entityCameraGetZNear(eid, cid)); } -/** - * __newindex metamethod for camera component userdata. - * - * @param L Lua state. Arg 1: entitycam userdata. Arg 2: key string. Arg 3: number. - * @return 0. - */ -static int moduleEntityCameraNewIndex(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - entitycam_handle_t *h = luaL_checkudata(L, 1, "entitycam_mt"); - assertNotNull(h, "invalid entitycam userdata"); - - const char *k = luaL_checkstring(L, 2); - assertStrLenMin(k, 1, "property key cannot be empty"); - - if(stringCompare(k, "zNear") == 0) { - entityCameraSetZNear(h->entityId, h->compId, (float_t)luaL_checknumber(L, 3)); - return 0; - } else if(stringCompare(k, "zFar") == 0) { - entityCameraSetZFar(h->entityId, h->compId, (float_t)luaL_checknumber(L, 3)); - return 0; - } - - luaL_error(L, "entitycam: unknown property '%s'", k); - return 0; +JS_FUNC(moduleEntityCameraSetZNear) { + JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + entityCameraSetZNear(eid, cid, (float_t)jerry_value_as_number(args_p[0])); + return jerry_undefined(); } +// -- zFar getter/setter -- + +JS_FUNC(moduleEntityCameraGetZFar) { + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + return jerry_number((double)entityCameraGetZFar(eid, cid)); +} + +JS_FUNC(moduleEntityCameraSetZFar) { + JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + entityCameraSetZFar(eid, cid, (float_t)jerry_value_as_number(args_p[0])); + return jerry_undefined(); +} + +// -- add function -- + /** - * Adds a camera component to an entity and returns its userdata handle. - * - * @param L Lua state. Arg 1: entity id (number). - * @return 1 (entitycam userdata). + * Adds a camera component to an entity and returns a handle object. + * Arg 0: entity id (number). */ -static int moduleEntityCameraAdd(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - entityid_t id = (entityid_t)luaL_checknumber(L, 1); +JS_FUNC(moduleEntityCameraAdd) { + JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0); + entityid_t id = (entityid_t)jerry_value_as_number(args_p[0]); componentid_t comp = entityAddComponent(id, COMPONENT_TYPE_CAMERA); - - entitycam_handle_t *h = lua_newuserdata(L, sizeof(entitycam_handle_t)); - assertNotNull(h, "failed to allocate entitycam userdata"); - - h->entityId = id; - h->compId = comp; - - luaL_getmetatable(L, "entitycam_mt"); - lua_setmetatable(L, -2); - return 1; + jerry_value_t handle = makeEntityHandle(id, comp); + if(s_camProto != 0) jerry_object_set_proto(handle, s_camProto); + return handle; } /** - * Registers the camera component metatable and entityCameraAdd global. - * - * @param L Lua state. + * Registers the camera component prototype and entityCameraAdd global. */ -static void moduleEntityCamera(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +static void moduleEntityCamera(void) { + s_camProto = jerry_object(); - luaL_newmetatable(L, "entitycam_mt"); - lua_pushcfunction(L, moduleEntityCameraIndex); - lua_setfield(L, -2, "__index"); - lua_pushcfunction(L, moduleEntityCameraNewIndex); - lua_setfield(L, -2, "__newindex"); - lua_pop(L, 1); + jsDefineProperty(s_camProto, "zNear", moduleEntityCameraGetZNear, moduleEntityCameraSetZNear); + jsDefineProperty(s_camProto, "zFar", moduleEntityCameraGetZFar, moduleEntityCameraSetZFar); - lua_register(L, "entityCameraAdd", moduleEntityCameraAdd); + jsRegister("entityCameraAdd", moduleEntityCameraAdd); } diff --git a/src/dusk/script/module/entity/component/moduleentitymaterial.h b/src/dusk/script/module/entity/component/moduleentitymaterial.h index 0da40e16..8c60bee5 100644 --- a/src/dusk/script/module/entity/component/moduleentitymaterial.h +++ b/src/dusk/script/module/entity/component/moduleentitymaterial.h @@ -9,73 +9,82 @@ #include "script/module/modulebase.h" #include "entity/entity.h" #include "entity/component/display/entitymaterial.h" +#include "display/color.h" +#include "moduleentityposition.h" -typedef struct { - entityid_t entityId; - componentid_t compId; -} entitymat_handle_t; +// ---- material prototype ---- + +static jerry_value_t s_matProto = 0; + +// -- methods -- /** - * __index metamethod for material component userdata. - * Delegates all lookups to the metatable (methods only, no plain properties). - * - * @param L Lua state. Arg 1: entitymat userdata. Arg 2: key string. - * @return 1. + * Sets the material's unlit color from a color object with r, g, b, a + * properties (each a number 0-255). + * Args: colorObj (object). */ -static int moduleEntityMaterialIndex(lua_State *L) { - lua_getmetatable(L, 1); - lua_getfield(L, -1, luaL_checkstring(L, 2)); - return 1; -} - -/** - * __newindex metamethod for material component userdata. - * Writes color (expects a color_mt userdata). Errors on unknown keys. - * - * @param L Lua state. Arg 1: entitymat userdata. Arg 2: key string. Arg 3: value. - * @return 0. - */ -static int moduleEntityMaterialNewIndex(lua_State *L) { - entitymat_handle_t *h = luaL_checkudata(L, 1, "entitymat_mt"); - const char *k = luaL_checkstring(L, 2); - if(stringCompare(k, "color") == 0) { - const color_t *col = (const color_t *)luaL_checkudata(L, 3, "color_mt"); - entityMaterialSetColor(h->entityId, h->compId, *col); - return 0; +JS_FUNC(moduleEntityMaterialSetColor) { + JS_REQUIRE_ARGS(1); + if(!jerry_value_is_object(args_p[0])) { + return JS_THROW("expected color object"); } - luaL_error(L, "entitymat: unknown property '%s'", k); - return 0; + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + + jerry_value_t key; + jerry_value_t v; + color_t col; + + key = jerry_string_sz("r"); + v = jerry_object_get(args_p[0], key); + jerry_value_free(key); + col.r = (colorchannel8_t)jerry_value_as_number(v); + jerry_value_free(v); + + key = jerry_string_sz("g"); + v = jerry_object_get(args_p[0], key); + jerry_value_free(key); + col.g = (colorchannel8_t)jerry_value_as_number(v); + jerry_value_free(v); + + key = jerry_string_sz("b"); + v = jerry_object_get(args_p[0], key); + jerry_value_free(key); + col.b = (colorchannel8_t)jerry_value_as_number(v); + jerry_value_free(v); + + key = jerry_string_sz("a"); + v = jerry_object_get(args_p[0], key); + jerry_value_free(key); + col.a = (colorchannel8_t)jerry_value_as_number(v); + jerry_value_free(v); + + entityMaterialSetColor(eid, cid, col); + return jerry_undefined(); } +// -- add function -- + /** - * Adds a material component to an entity and returns its userdata handle. - * - * @param L Lua state. Arg 1: entity id (number). - * @return 1 (entitymat userdata). + * Adds a material component to an entity and returns a handle object. + * Arg 0: entity id (number). */ -static int moduleEntityMaterialAdd(lua_State *L) { - entityid_t id = (entityid_t)luaL_checknumber(L, 1); +JS_FUNC(moduleEntityMaterialAdd) { + JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0); + entityid_t id = (entityid_t)jerry_value_as_number(args_p[0]); componentid_t comp = entityAddComponent(id, COMPONENT_TYPE_MATERIAL); - entitymat_handle_t *h = lua_newuserdata(L, sizeof(entitymat_handle_t)); - h->entityId = id; - h->compId = comp; - luaL_getmetatable(L, "entitymat_mt"); - lua_setmetatable(L, -2); - return 1; + jerry_value_t handle = makeEntityHandle(id, comp); + if(s_matProto != 0) jerry_object_set_proto(handle, s_matProto); + return handle; } /** - * Registers the material component metatable and entityMaterialAdd global. - * - * @param L Lua state. + * Registers the material component prototype and entityMaterialAdd global. */ -static void moduleEntityMaterial(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +static void moduleEntityMaterial(void) { + s_matProto = jerry_object(); - luaL_newmetatable(L, "entitymat_mt"); - lua_pushcfunction(L, moduleEntityMaterialIndex); lua_setfield(L, -2, "__index"); - lua_pushcfunction(L, moduleEntityMaterialNewIndex); lua_setfield(L, -2, "__newindex"); - lua_pop(L, 1); + jsDefineMethod(s_matProto, "setColor", moduleEntityMaterialSetColor); - lua_register(L, "entityMaterialAdd", moduleEntityMaterialAdd); + jsRegister("entityMaterialAdd", moduleEntityMaterialAdd); } diff --git a/src/dusk/script/module/entity/component/moduleentitymesh.h b/src/dusk/script/module/entity/component/moduleentitymesh.h index 32174b85..0c91d756 100644 --- a/src/dusk/script/module/entity/component/moduleentitymesh.h +++ b/src/dusk/script/module/entity/component/moduleentitymesh.h @@ -9,85 +9,65 @@ #include "script/module/modulebase.h" #include "entity/entity.h" #include "entity/component/display/entitymesh.h" +#include "moduleentityposition.h" -typedef struct { - entityid_t entityId; - componentid_t compId; -} entitymesh_handle_t; +// ---- mesh prototype ---- -/** - * __index metamethod for mesh component userdata. - * Delegates all lookups to the metatable (methods only, no plain properties). - * - * @param L Lua state. Arg 1: entitymesh userdata. Arg 2: key string. - * @return 1. - */ -static int moduleEntityMeshIndex(lua_State *L) { - lua_getmetatable(L, 1); - lua_getfield(L, -1, luaL_checkstring(L, 2)); - return 1; -} +static jerry_value_t s_meshProto = 0; + +// -- methods -- /** * Generates an XZ-aligned plane mesh owned by this component. - * - * @param L Lua state. Arg 1: entitymesh userdata. Arg 2: width. Arg 3: depth. - * @return 0. + * Args: width (number), depth (number). */ -static int moduleEntityMeshGeneratePlane(lua_State *L) { - entitymesh_handle_t *h = luaL_checkudata(L, 1, "entitymesh_mt"); - float_t w = (float_t)luaL_checknumber(L, 2); - float_t d = (float_t)luaL_checknumber(L, 3); - errorret_t err = entityMeshGeneratePlane(h->entityId, h->compId, w, d); - if(err.code != ERROR_OK) luaL_error(L, "entityMesh: generatePlane failed"); - return 0; +JS_FUNC(moduleEntityMeshGeneratePlane) { + JS_REQUIRE_ARGS(2); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + float_t w = (float_t)jerry_value_as_number(args_p[0]); + float_t d = (float_t)jerry_value_as_number(args_p[1]); + entityMeshGeneratePlane(eid, cid, w, d); + return jerry_undefined(); } /** * Generates a Y-axis capsule mesh owned by this component. - * - * @param L Lua state. Arg 1: entitymesh userdata. Arg 2: radius. Arg 3: halfHeight. - * @return 0. + * Args: radius (number), halfHeight (number). */ -static int moduleEntityMeshGenerateCapsule(lua_State *L) { - entitymesh_handle_t *h = luaL_checkudata(L, 1, "entitymesh_mt"); - float_t r = (float_t)luaL_checknumber(L, 2); - float_t hh = (float_t)luaL_checknumber(L, 3); - errorret_t err = entityMeshGenerateCapsule(h->entityId, h->compId, r, hh); - if(err.code != ERROR_OK) luaL_error(L, "entityMesh: generateCapsule failed"); - return 0; +JS_FUNC(moduleEntityMeshGenerateCapsule) { + JS_REQUIRE_ARGS(2); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + float_t r = (float_t)jerry_value_as_number(args_p[0]); + float_t hh = (float_t)jerry_value_as_number(args_p[1]); + entityMeshGenerateCapsule(eid, cid, r, hh); + return jerry_undefined(); } +// -- add function -- + /** - * Adds a mesh component to an entity and returns its userdata handle. - * - * @param L Lua state. Arg 1: entity id (number). - * @return 1 (entitymesh userdata). + * Adds a mesh component to an entity and returns a handle object. + * Arg 0: entity id (number). */ -static int moduleEntityMeshAdd(lua_State *L) { - entityid_t id = (entityid_t)luaL_checknumber(L, 1); +JS_FUNC(moduleEntityMeshAdd) { + JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0); + entityid_t id = (entityid_t)jerry_value_as_number(args_p[0]); componentid_t comp = entityAddComponent(id, COMPONENT_TYPE_MESH); - entitymesh_handle_t *h = lua_newuserdata(L, sizeof(entitymesh_handle_t)); - h->entityId = id; - h->compId = comp; - luaL_getmetatable(L, "entitymesh_mt"); - lua_setmetatable(L, -2); - return 1; + jerry_value_t handle = makeEntityHandle(id, comp); + if(s_meshProto != 0) jerry_object_set_proto(handle, s_meshProto); + return handle; } /** - * Registers the mesh component metatable and entityMeshAdd global. - * - * @param L Lua state. + * Registers the mesh component prototype and entityMeshAdd global. */ -static void moduleEntityMesh(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +static void moduleEntityMesh(void) { + s_meshProto = jerry_object(); - luaL_newmetatable(L, "entitymesh_mt"); - lua_pushcfunction(L, moduleEntityMeshIndex); lua_setfield(L, -2, "__index"); - lua_pushcfunction(L, moduleEntityMeshGeneratePlane); lua_setfield(L, -2, "generatePlane"); - lua_pushcfunction(L, moduleEntityMeshGenerateCapsule); lua_setfield(L, -2, "generateCapsule"); - lua_pop(L, 1); + jsDefineMethod(s_meshProto, "generatePlane", moduleEntityMeshGeneratePlane); + jsDefineMethod(s_meshProto, "generateCapsule", moduleEntityMeshGenerateCapsule); - lua_register(L, "entityMeshAdd", moduleEntityMeshAdd); + jsRegister("entityMeshAdd", moduleEntityMeshAdd); } diff --git a/src/dusk/script/module/entity/component/moduleentityphysics.h b/src/dusk/script/module/entity/component/moduleentityphysics.h index 8b9fd522..c6719461 100644 --- a/src/dusk/script/module/entity/component/moduleentityphysics.h +++ b/src/dusk/script/module/entity/component/moduleentityphysics.h @@ -9,210 +9,225 @@ #include "script/module/modulebase.h" #include "entity/entity.h" #include "entity/component/physics/entityphysics.h" +#include "moduleentityposition.h" -typedef struct { - entityid_t entityId; - componentid_t compId; -} entityphysics_handle_t; +// ---- physics prototype ---- -/** - * __index metamethod for physics component userdata. - * Reads velX, velY, velZ, onGround (bool), bodyType; falls through to the - * metatable for method lookups. - * - * @param L Lua state. Arg 1: entityphysics userdata. Arg 2: key string. - * @return 1. - */ -static int moduleEntityPhysicsIndex(lua_State *L) { - entityphysics_handle_t *h = luaL_checkudata(L, 1, "entityphysics_mt"); - const char *k = luaL_checkstring(L, 2); +static jerry_value_t s_physProto = 0; + +// -- velocity getters/setters -- + +JS_FUNC(moduleEntityPhysicsGetVelX) { + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); vec3 v; - if(stringCompare(k, "velX") == 0) { - entityPhysicsGetVelocity(h->entityId, h->compId, v); - lua_pushnumber(L, v[0]); return 1; - } else if(stringCompare(k, "velY") == 0) { - entityPhysicsGetVelocity(h->entityId, h->compId, v); - lua_pushnumber(L, v[1]); return 1; - } else if(stringCompare(k, "velZ") == 0) { - entityPhysicsGetVelocity(h->entityId, h->compId, v); - lua_pushnumber(L, v[2]); return 1; - } else if(stringCompare(k, "onGround") == 0) { - lua_pushboolean(L, entityPhysicsIsOnGround(h->entityId, h->compId)); - return 1; - } else if(stringCompare(k, "bodyType") == 0) { - lua_pushinteger(L, (lua_Integer)entityPhysicsGetBodyType(h->entityId, h->compId)); - return 1; - } - lua_getmetatable(L, 1); - lua_getfield(L, -1, k); - return 1; + entityPhysicsGetVelocity(eid, cid, v); + return jerry_number(v[0]); } -/** - * __newindex metamethod for physics component userdata. - * Writes velX, velY, velZ, bodyType. onGround is read-only. Errors on unknown keys. - * - * @param L Lua state. Arg 1: entityphysics userdata. Arg 2: key string. Arg 3: value. - * @return 0. - */ -static int moduleEntityPhysicsNewIndex(lua_State *L) { - entityphysics_handle_t *h = luaL_checkudata(L, 1, "entityphysics_mt"); - const char *k = luaL_checkstring(L, 2); +JS_FUNC(moduleEntityPhysicsSetVelX) { + JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); vec3 v; - if(stringCompare(k, "velX") == 0) { - entityPhysicsGetVelocity(h->entityId, h->compId, v); - v[0] = (float_t)luaL_checknumber(L, 3); - entityPhysicsSetVelocity(h->entityId, h->compId, v); return 0; - } else if(stringCompare(k, "velY") == 0) { - entityPhysicsGetVelocity(h->entityId, h->compId, v); - v[1] = (float_t)luaL_checknumber(L, 3); - entityPhysicsSetVelocity(h->entityId, h->compId, v); return 0; - } else if(stringCompare(k, "velZ") == 0) { - entityPhysicsGetVelocity(h->entityId, h->compId, v); - v[2] = (float_t)luaL_checknumber(L, 3); - entityPhysicsSetVelocity(h->entityId, h->compId, v); return 0; - } else if(stringCompare(k, "bodyType") == 0) { - entityPhysicsSetBodyType( - h->entityId, h->compId, - (physicsbodytype_t)luaL_checkinteger(L, 3) - ); - return 0; - } else if(stringCompare(k, "onGround") == 0) { - luaL_error(L, "entityphysics: onGround is read-only"); - return 0; - } - luaL_error(L, "entityphysics: unknown property '%s'", k); - return 0; + entityPhysicsGetVelocity(eid, cid, v); + v[0] = (float_t)jerry_value_as_number(args_p[0]); + entityPhysicsSetVelocity(eid, cid, v); + return jerry_undefined(); } +JS_FUNC(moduleEntityPhysicsGetVelY) { + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPhysicsGetVelocity(eid, cid, v); + return jerry_number(v[1]); +} + +JS_FUNC(moduleEntityPhysicsSetVelY) { + JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPhysicsGetVelocity(eid, cid, v); + v[1] = (float_t)jerry_value_as_number(args_p[0]); + entityPhysicsSetVelocity(eid, cid, v); + return jerry_undefined(); +} + +JS_FUNC(moduleEntityPhysicsGetVelZ) { + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPhysicsGetVelocity(eid, cid, v); + return jerry_number(v[2]); +} + +JS_FUNC(moduleEntityPhysicsSetVelZ) { + JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPhysicsGetVelocity(eid, cid, v); + v[2] = (float_t)jerry_value_as_number(args_p[0]); + entityPhysicsSetVelocity(eid, cid, v); + return jerry_undefined(); +} + +// -- onGround getter (read-only) -- + +JS_FUNC(moduleEntityPhysicsGetOnGround) { + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + return jerry_boolean(entityPhysicsIsOnGround(eid, cid)); +} + +// -- bodyType getter/setter -- + +JS_FUNC(moduleEntityPhysicsGetBodyType) { + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + return jerry_number((double)entityPhysicsGetBodyType(eid, cid)); +} + +JS_FUNC(moduleEntityPhysicsSetBodyType) { + JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + entityPhysicsSetBodyType( + eid, cid, + (physicsbodytype_t)(int32_t)jerry_value_as_number(args_p[0]) + ); + return jerry_undefined(); +} + +// -- methods -- + /** * Applies an immediate velocity impulse to the physics body. - * - * @param L Lua state. Arg 1: entityphysics userdata. Args 2-4: impulse x, y, z. - * @return 0. + * Args: x, y, z (numbers). */ -static int moduleEntityPhysicsApplyImpulse(lua_State *L) { - entityphysics_handle_t *h = luaL_checkudata(L, 1, "entityphysics_mt"); +JS_FUNC(moduleEntityPhysicsApplyImpulse) { + JS_REQUIRE_ARGS(3); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); vec3 impulse = { - (float_t)luaL_checknumber(L, 2), - (float_t)luaL_checknumber(L, 3), - (float_t)luaL_checknumber(L, 4) + (float_t)jerry_value_as_number(args_p[0]), + (float_t)jerry_value_as_number(args_p[1]), + (float_t)jerry_value_as_number(args_p[2]) }; - entityPhysicsApplyImpulse(h->entityId, h->compId, impulse); - return 0; + entityPhysicsApplyImpulse(eid, cid, impulse); + return jerry_undefined(); } /** * Sets the physics shape to an axis-aligned box. - * - * @param L Lua state. Arg 1: entityphysics userdata. Args 2-4: half-extents x, y, z. - * @return 0. + * Args: halfX, halfY, halfZ (numbers). */ -static int moduleEntityPhysicsSetShapeCube(lua_State *L) { - entityphysics_handle_t *h = luaL_checkudata(L, 1, "entityphysics_mt"); +JS_FUNC(moduleEntityPhysicsSetShapeCube) { + JS_REQUIRE_ARGS(3); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); physicsshape_t shape; shape.type = PHYSICS_SHAPE_CUBE; - shape.data.cube.halfExtents[0] = (float_t)luaL_checknumber(L, 2); - shape.data.cube.halfExtents[1] = (float_t)luaL_checknumber(L, 3); - shape.data.cube.halfExtents[2] = (float_t)luaL_checknumber(L, 4); - entityPhysicsSetShape(h->entityId, h->compId, shape); - return 0; + shape.data.cube.halfExtents[0] = (float_t)jerry_value_as_number(args_p[0]); + shape.data.cube.halfExtents[1] = (float_t)jerry_value_as_number(args_p[1]); + shape.data.cube.halfExtents[2] = (float_t)jerry_value_as_number(args_p[2]); + entityPhysicsSetShape(eid, cid, shape); + return jerry_undefined(); } /** * Sets the physics shape to a sphere. - * - * @param L Lua state. Arg 1: entityphysics userdata. Arg 2: radius. - * @return 0. + * Args: radius (number). */ -static int moduleEntityPhysicsSetShapeSphere(lua_State *L) { - entityphysics_handle_t *h = luaL_checkudata(L, 1, "entityphysics_mt"); +JS_FUNC(moduleEntityPhysicsSetShapeSphere) { + JS_REQUIRE_ARGS(1); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); physicsshape_t shape; shape.type = PHYSICS_SHAPE_SPHERE; - shape.data.sphere.radius = (float_t)luaL_checknumber(L, 2); - entityPhysicsSetShape(h->entityId, h->compId, shape); - return 0; + shape.data.sphere.radius = (float_t)jerry_value_as_number(args_p[0]); + entityPhysicsSetShape(eid, cid, shape); + return jerry_undefined(); } /** * Sets the physics shape to a Y-axis capsule. - * - * @param L Lua state. Arg 1: entityphysics userdata. Arg 2: radius. Arg 3: halfHeight. - * @return 0. + * Args: radius (number), halfHeight (number). */ -static int moduleEntityPhysicsSetShapeCapsule(lua_State *L) { - entityphysics_handle_t *h = luaL_checkudata(L, 1, "entityphysics_mt"); +JS_FUNC(moduleEntityPhysicsSetShapeCapsule) { + JS_REQUIRE_ARGS(2); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); physicsshape_t shape; shape.type = PHYSICS_SHAPE_CAPSULE; - shape.data.capsule.radius = (float_t)luaL_checknumber(L, 2); - shape.data.capsule.halfHeight = (float_t)luaL_checknumber(L, 3); - entityPhysicsSetShape(h->entityId, h->compId, shape); - return 0; + shape.data.capsule.radius = (float_t)jerry_value_as_number(args_p[0]); + shape.data.capsule.halfHeight = (float_t)jerry_value_as_number(args_p[1]); + entityPhysicsSetShape(eid, cid, shape); + return jerry_undefined(); } /** * Sets the physics shape to an infinite plane. - * - * @param L Lua state. Arg 1: entityphysics userdata. Args 2-4: normal x, y, z. - * Arg 5: distance from origin. - * @return 0. + * Args: normalX, normalY, normalZ, distance (numbers). */ -static int moduleEntityPhysicsSetShapePlane(lua_State *L) { - entityphysics_handle_t *h = luaL_checkudata(L, 1, "entityphysics_mt"); +JS_FUNC(moduleEntityPhysicsSetShapePlane) { + JS_REQUIRE_ARGS(4); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); physicsshape_t shape; shape.type = PHYSICS_SHAPE_PLANE; - shape.data.plane.normal[0] = (float_t)luaL_checknumber(L, 2); - shape.data.plane.normal[1] = (float_t)luaL_checknumber(L, 3); - shape.data.plane.normal[2] = (float_t)luaL_checknumber(L, 4); - shape.data.plane.distance = (float_t)luaL_checknumber(L, 5); - entityPhysicsSetShape(h->entityId, h->compId, shape); - return 0; + shape.data.plane.normal[0] = (float_t)jerry_value_as_number(args_p[0]); + shape.data.plane.normal[1] = (float_t)jerry_value_as_number(args_p[1]); + shape.data.plane.normal[2] = (float_t)jerry_value_as_number(args_p[2]); + shape.data.plane.distance = (float_t)jerry_value_as_number(args_p[3]); + entityPhysicsSetShape(eid, cid, shape); + return jerry_undefined(); } +// -- add function -- + /** - * Adds a physics component to an entity and returns its userdata handle. - * - * @param L Lua state. Arg 1: entity id (number). - * @return 1 (entityphysics userdata). + * Adds a physics component to an entity and returns a handle object. + * Arg 0: entity id (number). */ -static int moduleEntityPhysicsAdd(lua_State *L) { - entityid_t id = (entityid_t)luaL_checknumber(L, 1); +JS_FUNC(moduleEntityPhysicsAdd) { + JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0); + entityid_t id = (entityid_t)jerry_value_as_number(args_p[0]); componentid_t comp = entityAddComponent(id, COMPONENT_TYPE_PHYSICS); - entityphysics_handle_t *h = lua_newuserdata(L, sizeof(entityphysics_handle_t)); - h->entityId = id; - h->compId = comp; - luaL_getmetatable(L, "entityphysics_mt"); - lua_setmetatable(L, -2); - return 1; + jerry_value_t handle = makeEntityHandle(id, comp); + if(s_physProto != 0) jerry_object_set_proto(handle, s_physProto); + return handle; } /** - * Registers the physics component metatable, entityPhysicsAdd global, and - * PHYSICS_BODY_* / PHYSICS_SHAPE_* integer constants. - * - * @param L Lua state. + * Registers the physics component prototype, entityPhysicsAdd global, + * and PHYSICS_BODY_* / PHYSICS_SHAPE_* integer constants. */ -static void moduleEntityPhysics(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +static void moduleEntityPhysics(void) { + s_physProto = jerry_object(); - luaL_newmetatable(L, "entityphysics_mt"); - lua_pushcfunction(L, moduleEntityPhysicsIndex); lua_setfield(L, -2, "__index"); - lua_pushcfunction(L, moduleEntityPhysicsNewIndex); lua_setfield(L, -2, "__newindex"); - lua_pushcfunction(L, moduleEntityPhysicsApplyImpulse); lua_setfield(L, -2, "applyImpulse"); - lua_pushcfunction(L, moduleEntityPhysicsSetShapeCube); lua_setfield(L, -2, "setShapeCube"); - lua_pushcfunction(L, moduleEntityPhysicsSetShapeSphere); lua_setfield(L, -2, "setShapeSphere"); - lua_pushcfunction(L, moduleEntityPhysicsSetShapeCapsule); lua_setfield(L, -2, "setShapeCapsule"); - lua_pushcfunction(L, moduleEntityPhysicsSetShapePlane); lua_setfield(L, -2, "setShapePlane"); - lua_pop(L, 1); + jsDefineProperty(s_physProto, "velX", moduleEntityPhysicsGetVelX, moduleEntityPhysicsSetVelX); + jsDefineProperty(s_physProto, "velY", moduleEntityPhysicsGetVelY, moduleEntityPhysicsSetVelY); + jsDefineProperty(s_physProto, "velZ", moduleEntityPhysicsGetVelZ, moduleEntityPhysicsSetVelZ); + jsDefineProperty(s_physProto, "onGround", moduleEntityPhysicsGetOnGround, NULL); + jsDefineProperty(s_physProto, "bodyType", moduleEntityPhysicsGetBodyType, moduleEntityPhysicsSetBodyType); - lua_register(L, "entityPhysicsAdd", moduleEntityPhysicsAdd); + jsDefineMethod(s_physProto, "applyImpulse", moduleEntityPhysicsApplyImpulse); + jsDefineMethod(s_physProto, "setShapeCube", moduleEntityPhysicsSetShapeCube); + jsDefineMethod(s_physProto, "setShapeSphere", moduleEntityPhysicsSetShapeSphere); + jsDefineMethod(s_physProto, "setShapeCapsule", moduleEntityPhysicsSetShapeCapsule); + jsDefineMethod(s_physProto, "setShapePlane", moduleEntityPhysicsSetShapePlane); - lua_pushinteger(L, PHYSICS_BODY_STATIC); lua_setglobal(L, "PHYSICS_BODY_STATIC"); - lua_pushinteger(L, PHYSICS_BODY_DYNAMIC); lua_setglobal(L, "PHYSICS_BODY_DYNAMIC"); - lua_pushinteger(L, PHYSICS_BODY_KINEMATIC); lua_setglobal(L, "PHYSICS_BODY_KINEMATIC"); + jsRegister("entityPhysicsAdd", moduleEntityPhysicsAdd); - lua_pushinteger(L, PHYSICS_SHAPE_CUBE); lua_setglobal(L, "PHYSICS_SHAPE_CUBE"); - lua_pushinteger(L, PHYSICS_SHAPE_SPHERE); lua_setglobal(L, "PHYSICS_SHAPE_SPHERE"); - lua_pushinteger(L, PHYSICS_SHAPE_CAPSULE); lua_setglobal(L, "PHYSICS_SHAPE_CAPSULE"); - lua_pushinteger(L, PHYSICS_SHAPE_PLANE); lua_setglobal(L, "PHYSICS_SHAPE_PLANE"); + jsSetInt("PHYSICS_BODY_STATIC", PHYSICS_BODY_STATIC); + jsSetInt("PHYSICS_BODY_DYNAMIC", PHYSICS_BODY_DYNAMIC); + jsSetInt("PHYSICS_BODY_KINEMATIC", PHYSICS_BODY_KINEMATIC); + + jsSetInt("PHYSICS_SHAPE_CUBE", PHYSICS_SHAPE_CUBE); + jsSetInt("PHYSICS_SHAPE_SPHERE", PHYSICS_SHAPE_SPHERE); + jsSetInt("PHYSICS_SHAPE_CAPSULE", PHYSICS_SHAPE_CAPSULE); + jsSetInt("PHYSICS_SHAPE_PLANE", PHYSICS_SHAPE_PLANE); } diff --git a/src/dusk/script/module/entity/component/moduleentityposition.h b/src/dusk/script/module/entity/component/moduleentityposition.h index 60e4ee37..7eabaa64 100644 --- a/src/dusk/script/module/entity/component/moduleentityposition.h +++ b/src/dusk/script/module/entity/component/moduleentityposition.h @@ -10,166 +10,304 @@ #include "entity/entity.h" #include "entity/component/display/entityposition.h" -typedef struct { - entityid_t entityId; - componentid_t compId; -} entitypos_handle_t; +// ---- shared entity handle helpers (included once via this file) ---- + +#ifndef ENTITY_HANDLE_HELPERS +#define ENTITY_HANDLE_HELPERS /** - * __index metamethod for position component userdata. - * Reads x, y, z, rotX, rotY, rotZ, scaleX, scaleY, scaleZ; falls through to - * the metatable for method lookups. - * - * @param L Lua state. Arg 1: entitypos userdata. Arg 2: key string. - * @return 1. + * Create a plain JS object carrying _eid and _cid number properties. + * The caller is responsible for freeing the returned value. */ -static int moduleEntityPositionIndex(lua_State *L) { - entitypos_handle_t *h = luaL_checkudata(L, 1, "entitypos_mt"); - const char *k = luaL_checkstring(L, 2); - vec3 v; - if(stringCompare(k, "x") == 0) { - entityPositionGetPosition(h->entityId, h->compId, v); - lua_pushnumber(L, v[0]); return 1; - } else if(stringCompare(k, "y") == 0) { - entityPositionGetPosition(h->entityId, h->compId, v); - lua_pushnumber(L, v[1]); return 1; - } else if(stringCompare(k, "z") == 0) { - entityPositionGetPosition(h->entityId, h->compId, v); - lua_pushnumber(L, v[2]); return 1; - } else if(stringCompare(k, "rotX") == 0) { - entityPositionGetRotation(h->entityId, h->compId, v); - lua_pushnumber(L, v[0]); return 1; - } else if(stringCompare(k, "rotY") == 0) { - entityPositionGetRotation(h->entityId, h->compId, v); - lua_pushnumber(L, v[1]); return 1; - } else if(stringCompare(k, "rotZ") == 0) { - entityPositionGetRotation(h->entityId, h->compId, v); - lua_pushnumber(L, v[2]); return 1; - } else if(stringCompare(k, "scaleX") == 0) { - entityPositionGetScale(h->entityId, h->compId, v); - lua_pushnumber(L, v[0]); return 1; - } else if(stringCompare(k, "scaleY") == 0) { - entityPositionGetScale(h->entityId, h->compId, v); - lua_pushnumber(L, v[1]); return 1; - } else if(stringCompare(k, "scaleZ") == 0) { - entityPositionGetScale(h->entityId, h->compId, v); - lua_pushnumber(L, v[2]); return 1; - } - lua_getmetatable(L, 1); - lua_getfield(L, -1, k); - return 1; +static inline jerry_value_t makeEntityHandle( + entityid_t eid, + componentid_t cid +) { + jerry_value_t obj = jerry_object(); + jerry_value_t key; + jerry_value_t val; + + key = jerry_string_sz("_eid"); + val = jerry_number((double)eid); + jerry_object_set(obj, key, val); + jerry_value_free(val); + jerry_value_free(key); + + key = jerry_string_sz("_cid"); + val = jerry_number((double)cid); + jerry_object_set(obj, key, val); + jerry_value_free(val); + jerry_value_free(key); + + return obj; } /** - * __newindex metamethod for position component userdata. - * Writes x, y, z, rotX, rotY, rotZ, scaleX, scaleY, scaleZ and rebuilds the - * transform. Errors on unknown keys. - * - * @param L Lua state. Arg 1: entitypos userdata. Arg 2: key string. Arg 3: number. - * @return 0. + * Extract the entity ID stored in a handle object's _eid property. */ -static int moduleEntityPositionNewIndex(lua_State *L) { - entitypos_handle_t *h = luaL_checkudata(L, 1, "entitypos_mt"); - const char *k = luaL_checkstring(L, 2); - vec3 v; - if(stringCompare(k, "x") == 0) { - entityPositionGetPosition(h->entityId, h->compId, v); - v[0] = (float_t)luaL_checknumber(L, 3); - entityPositionSetPosition(h->entityId, h->compId, v); return 0; - } else if(stringCompare(k, "y") == 0) { - entityPositionGetPosition(h->entityId, h->compId, v); - v[1] = (float_t)luaL_checknumber(L, 3); - entityPositionSetPosition(h->entityId, h->compId, v); return 0; - } else if(stringCompare(k, "z") == 0) { - entityPositionGetPosition(h->entityId, h->compId, v); - v[2] = (float_t)luaL_checknumber(L, 3); - entityPositionSetPosition(h->entityId, h->compId, v); return 0; - } else if(stringCompare(k, "rotX") == 0) { - entityPositionGetRotation(h->entityId, h->compId, v); - v[0] = (float_t)luaL_checknumber(L, 3); - entityPositionSetRotation(h->entityId, h->compId, v); return 0; - } else if(stringCompare(k, "rotY") == 0) { - entityPositionGetRotation(h->entityId, h->compId, v); - v[1] = (float_t)luaL_checknumber(L, 3); - entityPositionSetRotation(h->entityId, h->compId, v); return 0; - } else if(stringCompare(k, "rotZ") == 0) { - entityPositionGetRotation(h->entityId, h->compId, v); - v[2] = (float_t)luaL_checknumber(L, 3); - entityPositionSetRotation(h->entityId, h->compId, v); return 0; - } else if(stringCompare(k, "scaleX") == 0) { - entityPositionGetScale(h->entityId, h->compId, v); - v[0] = (float_t)luaL_checknumber(L, 3); - entityPositionSetScale(h->entityId, h->compId, v); return 0; - } else if(stringCompare(k, "scaleY") == 0) { - entityPositionGetScale(h->entityId, h->compId, v); - v[1] = (float_t)luaL_checknumber(L, 3); - entityPositionSetScale(h->entityId, h->compId, v); return 0; - } else if(stringCompare(k, "scaleZ") == 0) { - entityPositionGetScale(h->entityId, h->compId, v); - v[2] = (float_t)luaL_checknumber(L, 3); - entityPositionSetScale(h->entityId, h->compId, v); return 0; - } - luaL_error(L, "entitypos: unknown property '%s'", k); - return 0; +static inline entityid_t getEntityId(jerry_value_t handle) { + jerry_value_t key = jerry_string_sz("_eid"); + jerry_value_t val = jerry_object_get(handle, key); + jerry_value_free(key); + entityid_t id = (entityid_t)jerry_value_as_number(val); + jerry_value_free(val); + return id; } +/** + * Extract the component ID stored in a handle object's _cid property. + */ +static inline componentid_t getCompId(jerry_value_t handle) { + jerry_value_t key = jerry_string_sz("_cid"); + jerry_value_t val = jerry_object_get(handle, key); + jerry_value_free(key); + componentid_t id = (componentid_t)jerry_value_as_number(val); + jerry_value_free(val); + return id; +} + +#endif /* ENTITY_HANDLE_HELPERS */ + +// ---- position prototype ---- + +static jerry_value_t s_posProto = 0; + +// -- position getters/setters -- + +JS_FUNC(moduleEntityPositionGetX) { + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPositionGetPosition(eid, cid, v); + return jerry_number(v[0]); +} + +JS_FUNC(moduleEntityPositionSetX) { + JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPositionGetPosition(eid, cid, v); + v[0] = (float_t)jerry_value_as_number(args_p[0]); + entityPositionSetPosition(eid, cid, v); + return jerry_undefined(); +} + +JS_FUNC(moduleEntityPositionGetY) { + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPositionGetPosition(eid, cid, v); + return jerry_number(v[1]); +} + +JS_FUNC(moduleEntityPositionSetY) { + JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPositionGetPosition(eid, cid, v); + v[1] = (float_t)jerry_value_as_number(args_p[0]); + entityPositionSetPosition(eid, cid, v); + return jerry_undefined(); +} + +JS_FUNC(moduleEntityPositionGetZ) { + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPositionGetPosition(eid, cid, v); + return jerry_number(v[2]); +} + +JS_FUNC(moduleEntityPositionSetZ) { + JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPositionGetPosition(eid, cid, v); + v[2] = (float_t)jerry_value_as_number(args_p[0]); + entityPositionSetPosition(eid, cid, v); + return jerry_undefined(); +} + +// -- rotation getters/setters -- + +JS_FUNC(moduleEntityPositionGetRotX) { + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPositionGetRotation(eid, cid, v); + return jerry_number(v[0]); +} + +JS_FUNC(moduleEntityPositionSetRotX) { + JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPositionGetRotation(eid, cid, v); + v[0] = (float_t)jerry_value_as_number(args_p[0]); + entityPositionSetRotation(eid, cid, v); + return jerry_undefined(); +} + +JS_FUNC(moduleEntityPositionGetRotY) { + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPositionGetRotation(eid, cid, v); + return jerry_number(v[1]); +} + +JS_FUNC(moduleEntityPositionSetRotY) { + JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPositionGetRotation(eid, cid, v); + v[1] = (float_t)jerry_value_as_number(args_p[0]); + entityPositionSetRotation(eid, cid, v); + return jerry_undefined(); +} + +JS_FUNC(moduleEntityPositionGetRotZ) { + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPositionGetRotation(eid, cid, v); + return jerry_number(v[2]); +} + +JS_FUNC(moduleEntityPositionSetRotZ) { + JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPositionGetRotation(eid, cid, v); + v[2] = (float_t)jerry_value_as_number(args_p[0]); + entityPositionSetRotation(eid, cid, v); + return jerry_undefined(); +} + +// -- scale getters/setters -- + +JS_FUNC(moduleEntityPositionGetScaleX) { + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPositionGetScale(eid, cid, v); + return jerry_number(v[0]); +} + +JS_FUNC(moduleEntityPositionSetScaleX) { + JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPositionGetScale(eid, cid, v); + v[0] = (float_t)jerry_value_as_number(args_p[0]); + entityPositionSetScale(eid, cid, v); + return jerry_undefined(); +} + +JS_FUNC(moduleEntityPositionGetScaleY) { + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPositionGetScale(eid, cid, v); + return jerry_number(v[1]); +} + +JS_FUNC(moduleEntityPositionSetScaleY) { + JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPositionGetScale(eid, cid, v); + v[1] = (float_t)jerry_value_as_number(args_p[0]); + entityPositionSetScale(eid, cid, v); + return jerry_undefined(); +} + +JS_FUNC(moduleEntityPositionGetScaleZ) { + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPositionGetScale(eid, cid, v); + return jerry_number(v[2]); +} + +JS_FUNC(moduleEntityPositionSetScaleZ) { + JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); + vec3 v; + entityPositionGetScale(eid, cid, v); + v[2] = (float_t)jerry_value_as_number(args_p[0]); + entityPositionSetScale(eid, cid, v); + return jerry_undefined(); +} + +// -- lookAt method -- + /** * Rotates the entity to face a world-space target point. - * An optional up vector may be provided (args 5-7); defaults to (0,1,0). - * - * @param L Lua state. Arg 1: entitypos userdata. Args 2-4: target x, y, z. - * Args 5-7 (optional): up x, y, z. - * @return 0. + * Args: target x, y, z [, up x, y, z]. Up defaults to (0,1,0). */ -static int moduleEntityPositionLookAt(lua_State *L) { - entitypos_handle_t *h = luaL_checkudata(L, 1, "entitypos_mt"); +JS_FUNC(moduleEntityPositionLookAt) { + JS_REQUIRE_ARGS(3); + entityid_t eid = getEntityId(call_info_p->this_value); + componentid_t cid = getCompId(call_info_p->this_value); vec3 target = { - (float_t)luaL_checknumber(L, 2), - (float_t)luaL_checknumber(L, 3), - (float_t)luaL_checknumber(L, 4) + (float_t)jerry_value_as_number(args_p[0]), + (float_t)jerry_value_as_number(args_p[1]), + (float_t)jerry_value_as_number(args_p[2]) }; vec3 up = { 0.0f, 1.0f, 0.0f }; - if(lua_gettop(L) >= 7) { - up[0] = (float_t)luaL_checknumber(L, 5); - up[1] = (float_t)luaL_checknumber(L, 6); - up[2] = (float_t)luaL_checknumber(L, 7); + if(args_count >= 6) { + up[0] = (float_t)jerry_value_as_number(args_p[3]); + up[1] = (float_t)jerry_value_as_number(args_p[4]); + up[2] = (float_t)jerry_value_as_number(args_p[5]); } vec3 eye; - entityPositionGetPosition(h->entityId, h->compId, eye); - entityPositionLookAt(h->entityId, h->compId, target, up, eye); - return 0; + entityPositionGetPosition(eid, cid, eye); + entityPositionLookAt(eid, cid, target, up, eye); + return jerry_undefined(); } +// -- add function -- + /** - * Adds a position component to an entity and returns its userdata handle. - * - * @param L Lua state. Arg 1: entity id (number). - * @return 1 (entitypos userdata). + * Adds a position component to an entity and returns a handle object. + * Arg 0: entity id (number). */ -static int moduleEntityPositionAdd(lua_State *L) { - entityid_t id = (entityid_t)luaL_checknumber(L, 1); +JS_FUNC(moduleEntityPositionAdd) { + JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0); + entityid_t id = (entityid_t)jerry_value_as_number(args_p[0]); componentid_t comp = entityAddComponent(id, COMPONENT_TYPE_POSITION); - entitypos_handle_t *h = lua_newuserdata(L, sizeof(entitypos_handle_t)); - h->entityId = id; - h->compId = comp; - luaL_getmetatable(L, "entitypos_mt"); - lua_setmetatable(L, -2); - return 1; + jerry_value_t handle = makeEntityHandle(id, comp); + if(s_posProto != 0) jerry_object_set_proto(handle, s_posProto); + return handle; } /** - * Registers the position component metatable and entityPositionAdd global. - * - * @param L Lua state. + * Registers the position component prototype and entityPositionAdd global. */ -static void moduleEntityPosition(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +static void moduleEntityPosition(void) { + s_posProto = jerry_object(); - luaL_newmetatable(L, "entitypos_mt"); - lua_pushcfunction(L, moduleEntityPositionIndex); lua_setfield(L, -2, "__index"); - lua_pushcfunction(L, moduleEntityPositionNewIndex); lua_setfield(L, -2, "__newindex"); - lua_pushcfunction(L, moduleEntityPositionLookAt); lua_setfield(L, -2, "lookAt"); - lua_pop(L, 1); + jsDefineProperty(s_posProto, "x", moduleEntityPositionGetX, moduleEntityPositionSetX); + jsDefineProperty(s_posProto, "y", moduleEntityPositionGetY, moduleEntityPositionSetY); + jsDefineProperty(s_posProto, "z", moduleEntityPositionGetZ, moduleEntityPositionSetZ); + jsDefineProperty(s_posProto, "rotX", moduleEntityPositionGetRotX, moduleEntityPositionSetRotX); + jsDefineProperty(s_posProto, "rotY", moduleEntityPositionGetRotY, moduleEntityPositionSetRotY); + jsDefineProperty(s_posProto, "rotZ", moduleEntityPositionGetRotZ, moduleEntityPositionSetRotZ); + jsDefineProperty(s_posProto, "scaleX", moduleEntityPositionGetScaleX, moduleEntityPositionSetScaleX); + jsDefineProperty(s_posProto, "scaleY", moduleEntityPositionGetScaleY, moduleEntityPositionSetScaleY); + jsDefineProperty(s_posProto, "scaleZ", moduleEntityPositionGetScaleZ, moduleEntityPositionSetScaleZ); - lua_register(L, "entityPositionAdd", moduleEntityPositionAdd); + jsDefineMethod(s_posProto, "lookAt", moduleEntityPositionLookAt); + + jsRegister("entityPositionAdd", moduleEntityPositionAdd); } diff --git a/src/dusk/script/module/entity/moduleentity.h b/src/dusk/script/module/entity/moduleentity.h index d72bb528..53bb8fcd 100644 --- a/src/dusk/script/module/entity/moduleentity.h +++ b/src/dusk/script/module/entity/moduleentity.h @@ -15,87 +15,83 @@ #include "component/moduleentitymaterial.h" #include "component/moduleentityphysics.h" +// ---- component type constants script ---- + #define X(enumName, type, field, init, dispose) \ - "COMPONENT_TYPE_" #enumName " = \"" #field "\"\n" + "var COMPONENT_TYPE_" #enumName " = \"" #field "\";\n" static const char_t *COMPONENT_TYPE_SCRIPT = #include "entity/componentlist.h" ; #undef X +// ---- Entity base class script ---- + static const char_t *ENTITY_SCRIPT = - "Entity = {}\n" - "Entity.__index = Entity\n" + "var Entity = {};\n" + "Entity.POSITION = COMPONENT_TYPE_POSITION;\n" + "Entity.CAMERA = COMPONENT_TYPE_CAMERA;\n" + "Entity.MESH = COMPONENT_TYPE_MESH;\n" + "Entity.MATERIAL = COMPONENT_TYPE_MATERIAL;\n" + "Entity.PHYSICS = COMPONENT_TYPE_PHYSICS;\n" "\n" - "Entity.POSITION = COMPONENT_TYPE_POSITION\n" - "Entity.CAMERA = COMPONENT_TYPE_CAMERA\n" - "Entity.MESH = COMPONENT_TYPE_MESH\n" - "Entity.MATERIAL = COMPONENT_TYPE_MATERIAL\n" - "Entity.PHYSICS = COMPONENT_TYPE_PHYSICS\n" + "var _addFns = {};\n" + "_addFns[COMPONENT_TYPE_POSITION] = entityPositionAdd;\n" + "_addFns[COMPONENT_TYPE_CAMERA] = entityCameraAdd;\n" + "_addFns[COMPONENT_TYPE_MESH] = entityMeshAdd;\n" + "_addFns[COMPONENT_TYPE_MATERIAL] = entityMaterialAdd;\n" + "_addFns[COMPONENT_TYPE_PHYSICS] = entityPhysicsAdd;\n" "\n" - "local _addFns = {\n" - " [COMPONENT_TYPE_POSITION] = entityPositionAdd,\n" - " [COMPONENT_TYPE_CAMERA] = entityCameraAdd,\n" - " [COMPONENT_TYPE_MESH] = entityMeshAdd,\n" - " [COMPONENT_TYPE_MATERIAL] = entityMaterialAdd,\n" - " [COMPONENT_TYPE_PHYSICS] = entityPhysicsAdd,\n" - "}\n" + "Entity.create = function() {\n" + " var self = Object.create(Entity);\n" + " self.id = entityAdd();\n" + " return self;\n" + "};\n" "\n" - "function Entity.new()\n" - " return setmetatable({ id = entityAdd() }, Entity)\n" - "end\n" + "Entity.add = function(componentType) {\n" + " var fn = _addFns[componentType];\n" + " if(!fn) throw new Error('unknown component type: ' + String(componentType));\n" + " this[componentType] = fn(this.id);\n" + " return this[componentType];\n" + "};\n" "\n" - "function Entity:add(componentType)\n" - " local fn = _addFns[componentType]\n" - " if not fn then error('unknown component type: ' .. tostring(componentType)) end\n" - " self[componentType] = fn(self.id)\n" - " return self[componentType]\n" - "end\n" - "\n" - "function Entity:dispose()\n" - " entityRemove(self.id)\n" - "end\n" + "Entity.dispose = function() {\n" + " entityRemove(this.id);\n" + "};\n" ; +// ---- module functions ---- + /** - * Allocates a new entity and pushes its id onto the Lua stack. - * - * @param L Lua state. - * @return 1 (entity id number). + * Allocates a new entity and returns its id as a JS number. */ -static int moduleEntityAdd(lua_State *L) { - lua_pushnumber(L, (lua_Number)entityManagerAdd()); - return 1; +JS_FUNC(moduleEntityAdd) { + return jerry_number((double)entityManagerAdd()); } /** * Disposes the entity with the given id. - * - * @param L Lua state. Arg 1: entity id (number). - * @return 0. + * Arg 0: entity id (number). */ -static int moduleEntityRemove(lua_State *L) { - entityDispose((entityid_t)luaL_checknumber(L, 1)); - return 0; +JS_FUNC(moduleEntityRemove) { + JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0); + entityDispose((entityid_t)jerry_value_as_number(args_p[0])); + return jerry_undefined(); } /** * Registers all entity and component modules, component type constants, and - * the Entity base class into the Lua state. - * - * @param L Lua state. + * the Entity base object into the JS realm. */ -static void moduleEntity(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +static void moduleEntity(void) { + moduleEntityPosition(); + moduleEntityCamera(); + moduleEntityMesh(); + moduleEntityMaterial(); + moduleEntityPhysics(); - moduleEntityPosition(L); - moduleEntityCamera(L); - moduleEntityMesh(L); - moduleEntityMaterial(L); - moduleEntityPhysics(L); + jsRegister("entityAdd", moduleEntityAdd); + jsRegister("entityRemove", moduleEntityRemove); - lua_register(L, "entityAdd", moduleEntityAdd); - lua_register(L, "entityRemove", moduleEntityRemove); - - luaL_dostring(L, COMPONENT_TYPE_SCRIPT); - luaL_dostring(L, ENTITY_SCRIPT); + jsEvalStr(COMPONENT_TYPE_SCRIPT); + jsEvalStr(ENTITY_SCRIPT); } diff --git a/src/dusk/script/module/event/moduleevent.h b/src/dusk/script/module/event/moduleevent.h index e6bee709..b0f00d9c 100644 --- a/src/dusk/script/module/event/moduleevent.h +++ b/src/dusk/script/module/event/moduleevent.h @@ -9,50 +9,35 @@ #include "script/module/modulebase.h" #include "event/event.h" -static int moduleEventSubscribe(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +JS_FUNC(moduleEventSubscribe) { + JS_REQUIRE_ARGS(2); + JS_REQUIRE_OBJECT(0); + JS_REQUIRE_FUNCTION(1); - scriptcontext_t *context = *(scriptcontext_t **)lua_getextraspace(L); - assertNotNull(context, "Script context cannot be NULL"); + event_t *event = (event_t *)jsUnwrapPointer(args_p[0]); + if(event == NULL) return JS_THROW("eventSubscribe: Expected event object"); - if(!lua_islightuserdata(L, 1)) { - luaL_error(L, "eventSubscribe: Expected event pointer as first argument"); - return 0; - } + jerry_value_t funcCopy = jerry_value_copy(args_p[1]); + eventsub_t id = eventSubscribeScriptContext(event, scriptContextCurrent, funcCopy); - if(!lua_isfunction(L, 2)) { - luaL_error(L, "eventSubscribe: Expected function as second argument"); - return 0; - } - - event_t *event = (event_t *)lua_touserdata(L, 1); - assertNotNull(event, "Event cannot be NULL"); - - eventsub_t id = eventSubscribeScriptContext(event, context, 2); - lua_pushnumber(L, id); - return 1; + return jerry_number((double)id); } -static int moduleEventUnsubscribe(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +JS_FUNC(moduleEventUnsubscribe) { + JS_REQUIRE_ARGS(2); + JS_REQUIRE_OBJECT(0); + JS_REQUIRE_NUMBER(1); - if(!lua_islightuserdata(L, 1)) { - luaL_error(L, "eventUnsubscribe: Expected event pointer as first argument"); - return 0; - } - if(!lua_isnumber(L, 2)) { - luaL_error(L, "eventUnsubscribe: Expected subscription ID as second argument"); - return 0; - } + event_t *event = (event_t *)jsUnwrapPointer(args_p[0]); + if(event == NULL) return JS_THROW("eventUnsubscribe: Expected event object"); - event_t *event = (event_t *)lua_touserdata(L, 1); - assertNotNull(event, "Event cannot be NULL"); - eventsub_t id = (eventsub_t)lua_tonumber(L, 2); + eventsub_t id = (eventsub_t)jerry_value_as_number(args_p[1]); eventUnsubscribe(event, id); - return 0; + + return jerry_undefined(); } -static void moduleEvent(lua_State *L) { - lua_register(L, "eventSubscribe", moduleEventSubscribe); - lua_register(L, "eventUnsubscribe", moduleEventUnsubscribe); +static void moduleEvent(void) { + jsRegister("eventSubscribe", moduleEventSubscribe); + jsRegister("eventUnsubscribe", moduleEventUnsubscribe); } diff --git a/src/dusk/script/module/input/moduleinput.h b/src/dusk/script/module/input/moduleinput.h index a953cf55..3318af47 100644 --- a/src/dusk/script/module/input/moduleinput.h +++ b/src/dusk/script/module/input/moduleinput.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2025 Dominic Masters + * Copyright (c) 2026 Dominic Masters * * This software is released under the MIT License. * https://opensource.org/licenses/MIT @@ -9,198 +9,136 @@ #include "script/module/modulebase.h" #include "input/input.h" -static int moduleInputIndex(lua_State *l) { - assertNotNull(l, "Lua state cannot be NULL"); +JS_FUNC(moduleInputBind) { + JS_REQUIRE_ARGS(2); + JS_REQUIRE_STRING(0); + JS_REQUIRE_NUMBER(1); - const char_t *key = luaL_checkstring(l, 2); - assertStrLenMin(key, 1, "Key cannot be empty."); - - if(stringCompare(key, "action") == 0) { - const inputevent_t *event = (const inputevent_t*)lua_touserdata(l, 1); - if(event == NULL) { - luaL_error(l, "Expected input event as first argument"); - return 0; - } - lua_pushnumber(l, event->action); - return 1; - } - - lua_pushnil(l); - return 1; -} - -static int moduleInputBind(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(!lua_isstring(L, 1)) { - luaL_error(L, "inputBind: Expected button name as first argument"); - return 0; - } - - if(!lua_isnumber(L, 2)) { - luaL_error(L, "inputBind: Expected action ID as second argument"); - return 0; - } - - const char_t *strBtn = lua_tostring(L, 1); - const inputaction_t action = (inputaction_t)lua_tonumber(L, 2); - - if(strBtn == NULL || strlen(strBtn) == 0) { - luaL_error(L, "inputBind: Button name cannot be NULL or empty"); - return 0; - } + char_t strBtn[128]; + jsToString(args_p[0], strBtn, sizeof(strBtn)); + if(strBtn[0] == '\0') return JS_THROW("inputBind: Button name cannot be empty"); + const inputaction_t action = (inputaction_t)jerry_value_as_number(args_p[1]); if(action < INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) { - luaL_error(L, "inputBind: Invalid action ID %d with str %s", action, strBtn); - return 0; + return JS_THROW("inputBind: Invalid action ID"); } inputbutton_t btn = inputButtonGetByName(strBtn); if(btn.type == INPUT_BUTTON_TYPE_NONE) { - luaL_error(L, "inputBind: Invalid button name '%s'", strBtn); - return 0; + return JS_THROW("inputBind: Invalid button name"); } inputBind(btn, action); - return 0; + return jerry_undefined(); } -static int moduleInputIsDown(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(!lua_isnumber(L, 1)) { - luaL_error(L, "inputIsDown: Expected action ID as first argument"); - return 0; - } - - const inputaction_t action = (inputaction_t)lua_tonumber(L, 1); +JS_FUNC(moduleInputIsDown) { + JS_REQUIRE_ARGS(1); + JS_REQUIRE_NUMBER(0); + const inputaction_t action = (inputaction_t)jerry_value_as_number(args_p[0]); if(action < INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) { - luaL_error(L, "inputIsDown: Invalid action ID %d", action); - return 0; + return JS_THROW("inputIsDown: Invalid action ID"); } - lua_pushboolean(L, inputIsDown(action)); - return 1; + return jerry_boolean(inputIsDown(action)); } -static int moduleInputPressed(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(!lua_isnumber(L, 1)) { - luaL_error(L, "inputPressed: Expected action ID as first argument"); - return 0; - } - - const inputaction_t action = (inputaction_t)lua_tonumber(L, 1); +JS_FUNC(moduleInputPressed) { + JS_REQUIRE_ARGS(1); + JS_REQUIRE_NUMBER(0); + const inputaction_t action = (inputaction_t)jerry_value_as_number(args_p[0]); if(action < INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) { - luaL_error(L, "inputPressed: Invalid action ID %d", action); - return 0; + return JS_THROW("inputPressed: Invalid action ID"); } - lua_pushboolean(L, inputPressed(action)); - return 1; + return jerry_boolean(inputPressed(action)); } -static int moduleInputReleased(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(!lua_isnumber(L, 1)) { - luaL_error(L, "inputReleased: Expected action ID as first argument"); - return 0; - } - - const inputaction_t action = (inputaction_t)lua_tonumber(L, 1); +JS_FUNC(moduleInputReleased) { + JS_REQUIRE_ARGS(1); + JS_REQUIRE_NUMBER(0); + const inputaction_t action = (inputaction_t)jerry_value_as_number(args_p[0]); if(action < INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) { - luaL_error(L, "inputReleased: Invalid action ID %d", action); - return 0; + return JS_THROW("inputReleased: Invalid action ID"); } - lua_pushboolean(L, inputReleased(action)); - return 1; + return jerry_boolean(inputReleased(action)); } -static int moduleInputGetValue(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +JS_FUNC(moduleInputGetValue) { + JS_REQUIRE_ARGS(1); + JS_REQUIRE_NUMBER(0); - if(!lua_isnumber(L, 1)) { - luaL_error(L, "inputGetValue: Expected action ID as first argument"); - return 0; - } - - const inputaction_t action = (inputaction_t)lua_tonumber(L, 1); + const inputaction_t action = (inputaction_t)jerry_value_as_number(args_p[0]); if(action < INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) { - luaL_error(L, "inputGetValue: Invalid action ID %d", action); - return 0; + return JS_THROW("inputGetValue: Invalid action ID"); } - lua_pushnumber(L, inputGetCurrentValue(action)); - return 1; + return jerry_number(inputGetCurrentValue(action)); } -static int moduleInputAxis(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +JS_FUNC(moduleInputAxis) { + JS_REQUIRE_ARGS(2); + JS_REQUIRE_NUMBER(0); + JS_REQUIRE_NUMBER(1); - if(!lua_isnumber(L, 1) || !lua_isnumber(L, 2)) { - luaL_error(L, "inputAxis: Expected two action IDs as arguments (neg, pos)"); - return 0; - } - - const inputaction_t neg = (inputaction_t)lua_tonumber(L, 1); - const inputaction_t pos = (inputaction_t)lua_tonumber(L, 2); + const inputaction_t neg = (inputaction_t)jerry_value_as_number(args_p[0]); + const inputaction_t pos = (inputaction_t)jerry_value_as_number(args_p[1]); if(neg < INPUT_ACTION_NULL || neg >= INPUT_ACTION_COUNT) { - luaL_error(L, "inputAxis: Invalid negative action ID %d", neg); - return 0; + return JS_THROW("inputAxis: Invalid negative action ID"); } if(pos < INPUT_ACTION_NULL || pos >= INPUT_ACTION_COUNT) { - luaL_error(L, "inputAxis: Invalid positive action ID %d", pos); - return 0; + return JS_THROW("inputAxis: Invalid positive action ID"); } - lua_pushnumber(L, inputAxis(neg, pos)); - return 1; + return jerry_number(inputAxis(neg, pos)); } -static void moduleInput(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +JS_FUNC(moduleInputGetEventAction) { + JS_REQUIRE_ARGS(1); - luaL_dostring(L, INPUT_ACTION_SCRIPT); + const inputevent_t *event = (const inputevent_t *)jsUnwrapPointer(args_p[0]); + if(event == NULL) return JS_THROW("inputGetEventAction: Expected input event object"); - luaL_dostring(L, + return jerry_number(event->action); +} + +static void moduleInput(void) { + jsEvalStr(INPUT_ACTION_SCRIPT); + + jsEvalStr( "" #ifdef DUSK_INPUT_KEYBOARD - "INPUT_KEYBOARD = true\n" + "var INPUT_KEYBOARD = true;\n" #endif #ifdef DUSK_INPUT_GAMEPAD - "INPUT_GAMEPAD = true\n" + "var INPUT_GAMEPAD = true;\n" #endif #ifdef DUSK_INPUT_POINTER - "INPUT_POINTER = true\n" + "var INPUT_POINTER = true;\n" #endif #ifdef DUSK_INPUT_TOUCH - "INPUT_TOUCH = true\n" + "var INPUT_TOUCH = true;\n" #endif ); - if(luaL_newmetatable(L, "input_mt")) { - lua_pushcfunction(L, moduleInputIndex); - lua_setfield(L, -2, "__index"); - } - lua_pop(L, 1); + jerry_value_t evPressed = jsWrapPointer(&INPUT.eventPressed); + jsSetValue("INPUT_EVENT_PRESSED", evPressed); + jerry_value_free(evPressed); - lua_pushlightuserdata(L, &INPUT.eventPressed); - lua_setglobal(L, "INPUT_EVENT_PRESSED"); + jerry_value_t evReleased = jsWrapPointer(&INPUT.eventReleased); + jsSetValue("INPUT_EVENT_RELEASED", evReleased); + jerry_value_free(evReleased); - lua_pushlightuserdata(L, &INPUT.eventReleased); - lua_setglobal(L, "INPUT_EVENT_RELEASED"); - - lua_register(L, "inputBind", moduleInputBind); - lua_register(L, "inputIsDown", moduleInputIsDown); - lua_register(L, "inputPressed", moduleInputPressed); - lua_register(L, "inputReleased", moduleInputReleased); - lua_register(L, "inputGetValue", moduleInputGetValue); - lua_register(L, "inputAxis", moduleInputAxis); + jsRegister("inputBind", moduleInputBind); + jsRegister("inputIsDown", moduleInputIsDown); + jsRegister("inputPressed", moduleInputPressed); + jsRegister("inputReleased", moduleInputReleased); + jsRegister("inputGetValue", moduleInputGetValue); + jsRegister("inputAxis", moduleInputAxis); + jsRegister("inputGetEventAction", moduleInputGetEventAction); } diff --git a/src/dusk/script/module/locale/modulelocale.h b/src/dusk/script/module/locale/modulelocale.h index 8701b416..615b7ff8 100644 --- a/src/dusk/script/module/locale/modulelocale.h +++ b/src/dusk/script/module/locale/modulelocale.h @@ -9,61 +9,57 @@ #include "script/module/modulebase.h" #include "locale/localemanager.h" -static int moduleLocaleGetText(lua_State *L) { - if(!lua_isstring(L, 1)) { - luaL_error(L, "Expected message ID as first argument"); - return 0; - } +#define MODULE_LOCALE_MAX_ARGS 16 - const char_t *id = lua_tostring(L, 1); - if(id == NULL || strlen(id) == 0) { - luaL_error(L, "Message ID cannot be NULL or empty"); - return 0; - } +JS_FUNC(moduleLocaleGetText) { + JS_REQUIRE_ARGS(1); + JS_REQUIRE_STRING(0); + + char_t id[256]; + jsToString(args_p[0], id, sizeof(id)); + if(id[0] == '\0') return JS_THROW("localeGetText: Message ID cannot be empty"); int32_t plural = 0; - int top = lua_gettop(L); - int argStart = 2; + jerry_length_t argStart = 1; - if(top >= 2 && !lua_isnil(L, 2)) { - if(!lua_isnumber(L, 2)) { - luaL_error(L, "Expected plural as second argument"); - return 0; + if(args_count >= 2 && !jerry_value_is_undefined(args_p[1])) { + if(!jerry_value_is_number(args_p[1])) { + return JS_THROW("localeGetText: Expected plural as second argument"); } - plural = (int32_t)lua_tonumber(L, 2); - if(plural < 0) { - luaL_error(L, "Plural cannot be negative"); - return 0; - } - argStart = 3; + plural = (int32_t)jerry_value_as_number(args_p[1]); + if(plural < 0) return JS_THROW("localeGetText: Plural cannot be negative"); + argStart = 2; } - size_t argCount = (top >= argStart) ? (size_t)(top - argStart + 1) : 0; - #define MODULE_LOCALE_MAX_ARGS 16 - assetlocalearg_t argsStack[MODULE_LOCALE_MAX_ARGS]; + size_t argCount = (args_count > argStart) ? (size_t)(args_count - argStart) : 0; if(argCount > MODULE_LOCALE_MAX_ARGS) { - luaL_error(L, "Too many args (max %d)", MODULE_LOCALE_MAX_ARGS); - return 0; + return JS_THROW("localeGetText: Too many format arguments"); } + assetlocalearg_t argsStack[MODULE_LOCALE_MAX_ARGS]; + char_t strBufs[MODULE_LOCALE_MAX_ARGS][128]; + for(size_t i = 0; i < argCount; ++i) { - int luaIndex = argStart + (int)i; - if(lua_isinteger(L, luaIndex)) { - argsStack[i].type = ASSET_LOCALE_ARG_INT; - argsStack[i].intValue = (int32_t)lua_tonumber(L, luaIndex); - } else if(lua_isnumber(L, luaIndex)) { - argsStack[i].type = ASSET_LOCALE_ARG_FLOAT; - argsStack[i].floatValue = lua_tonumber(L, luaIndex); - } else if(lua_isstring(L, luaIndex)) { + jerry_value_t arg = args_p[argStart + i]; + + if(jerry_value_is_number(arg)) { + double num = jerry_value_as_number(arg); + if(num == (double)(int32_t)num) { + argsStack[i].type = ASSET_LOCALE_ARG_INT; + argsStack[i].intValue = (int32_t)num; + } else { + argsStack[i].type = ASSET_LOCALE_ARG_FLOAT; + argsStack[i].floatValue = (float_t)num; + } + } else if(jerry_value_is_string(arg)) { + jsToString(arg, strBufs[i], sizeof(strBufs[i])); argsStack[i].type = ASSET_LOCALE_ARG_STRING; - argsStack[i].stringValue = lua_tostring(L, luaIndex); + argsStack[i].stringValue = strBufs[i]; } else { - luaL_error(L, "Unsupported localization argument type"); - return 0; + return JS_THROW("localeGetText: Unsupported argument type"); } } - #undef MODULE_LOCALE_MAX_ARGS char_t buffer[1024]; errorret_t err = localeManagerGetTextArgs( @@ -71,15 +67,12 @@ static int moduleLocaleGetText(lua_State *L) { ); if(err.code != ERROR_OK) { errorCatch(errorPrint(err)); - luaL_error(L, "Failed to get localized text for ID '%s'", id); - return 0; + return JS_THROW("localeGetText: Failed to get localized text"); } - lua_pushstring(L, buffer); - return 1; + return jerry_string_sz(buffer); } -static void moduleLocale(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - lua_register(L, "localeGetText", moduleLocaleGetText); +static void moduleLocale(void) { + jsRegister("localeGetText", moduleLocaleGetText); } diff --git a/src/dusk/script/module/math/modulemat4.h b/src/dusk/script/module/math/modulemat4.h index b31276fa..c52c3b74 100644 --- a/src/dusk/script/module/math/modulemat4.h +++ b/src/dusk/script/module/math/modulemat4.h @@ -7,293 +7,282 @@ #pragma once #include "script/module/modulebase.h" +#include "assert/assert.h" +#include "cglm/cglm.h" #include "modulevec3.h" #include "modulevec4.h" -/** - * Pushes a new mat4 userdata onto the Lua stack with the mat4_mt metatable. - * - * @param L Lua state. - * @param m Source matrix to copy. - */ -static void moduleMat4Push(lua_State *L, mat4 m) { - assertNotNull(L, "Lua state cannot be NULL"); +// Native info for heap-allocated mat4 (float[4][4]) +static void freeMat4Native(void *ptr, jerry_object_native_info_t *info) { + (void)info; + free(ptr); +} +static const jerry_object_native_info_t MAT4_NATIVE_INFO = { + .free_cb = freeMat4Native, + .number_of_references = 0, + .offset_of_references = 0 +}; +static jerry_value_t s_mat4Proto = 0; - mat4 *u = (mat4 *)lua_newuserdata(L, sizeof(mat4)); - glm_mat4_copy(m, *u); - luaL_getmetatable(L, "mat4_mt"); - lua_setmetatable(L, -2); +// --------------------------------------------------------------------------- +// Methods +// --------------------------------------------------------------------------- + +JS_FUNC(moduleMatMul) { + JS_REQUIRE_ARGS(1); + float_t (*a)[4] = (float_t (*)[4])jerry_object_get_native_ptr( + call_info_p->this_value, &MAT4_NATIVE_INFO + ); + if(!a) return JS_THROW("mat4.mul: invalid this"); + float_t (*b)[4] = (float_t (*)[4])jerry_object_get_native_ptr( + args_p[0], &MAT4_NATIVE_INFO + ); + if(!b) return JS_THROW("mat4.mul: argument must be a mat4"); + float_t (*r)[4] = (float_t (*)[4])malloc(sizeof(mat4)); + glm_mat4_mul(a, b, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &MAT4_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_mat4Proto); + return obj; } -/** - * Reads a mat4 userdata from the given stack index into out. - * - * @param L Lua state. - * @param idx Stack index of the mat4 userdata. - * @param out Destination matrix. - */ -static void moduleMat4Check(lua_State *L, int idx, mat4 out) { - assertNotNull(L, "Lua state cannot be NULL"); - - mat4 *m = (mat4 *)luaL_checkudata(L, idx, "mat4_mt"); - glm_mat4_copy(*m, out); +JS_FUNC(moduleMatTranspose) { + float_t (*m)[4] = (float_t (*)[4])jerry_object_get_native_ptr( + call_info_p->this_value, &MAT4_NATIVE_INFO + ); + if(!m) return JS_THROW("mat4.transpose: invalid this"); + float_t (*r)[4] = (float_t (*)[4])malloc(sizeof(mat4)); + glm_mat4_transpose_to(m, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &MAT4_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_mat4Proto); + return obj; } -/** - * __index metamethod for mat4 userdata. - * Delegates all lookups to the metatable (methods only). - * - * @param L Lua state. Arg 1: mat4 userdata. Arg 2: key string. - * @return 1. - */ -static int moduleMat4Index(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - lua_getmetatable(L, 1); - lua_getfield(L, -1, luaL_checkstring(L, 2)); - lua_remove(L, -2); - return 1; +JS_FUNC(moduleMatInverse) { + float_t (*m)[4] = (float_t (*)[4])jerry_object_get_native_ptr( + call_info_p->this_value, &MAT4_NATIVE_INFO + ); + if(!m) return JS_THROW("mat4.inverse: invalid this"); + float_t (*r)[4] = (float_t (*)[4])malloc(sizeof(mat4)); + glm_mat4_inv(m, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &MAT4_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_mat4Proto); + return obj; } -/** - * __mul metamethod: returns a * b as a new mat4. - * - * @param L Lua state. Arg 1: mat4. Arg 2: mat4. - * @return 1 (new mat4). - */ -static int moduleMat4OpMul(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - mat4 *a = (mat4 *)luaL_checkudata(L, 1, "mat4_mt"); - assertNotNull(a, "invalid mat4 userdata"); - - mat4 *b = (mat4 *)luaL_checkudata(L, 2, "mat4_mt"); - assertNotNull(b, "invalid mat4 userdata"); - - mat4 r; - glm_mat4_mul(*a, *b, r); - moduleMat4Push(L, r); - return 1; +JS_FUNC(moduleMatDeterminant) { + float_t (*m)[4] = (float_t (*)[4])jerry_object_get_native_ptr( + call_info_p->this_value, &MAT4_NATIVE_INFO + ); + if(!m) return JS_THROW("mat4.determinant: invalid this"); + return jerry_number(glm_mat4_det(m)); } -/** - * __tostring metamethod: returns a placeholder string. - * - * @param L Lua state. Arg 1: mat4. - * @return 1 (string). - */ -static int moduleMat4OpToString(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - lua_pushstring(L, "mat4(...)"); - return 1; -} - -/** - * Returns the transpose of a mat4 as a new mat4. - * - * @param L Lua state. Arg 1: mat4. - * @return 1 (new mat4). - */ -static int moduleMat4Transpose(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - mat4 *m = (mat4 *)luaL_checkudata(L, 1, "mat4_mt"); - assertNotNull(m, "invalid mat4 userdata"); - - mat4 r; - glm_mat4_transpose_to(*m, r); - moduleMat4Push(L, r); - return 1; -} - -/** - * Returns the inverse of a mat4 as a new mat4. - * - * @param L Lua state. Arg 1: mat4. - * @return 1 (new mat4). - */ -static int moduleMat4Inverse(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - mat4 *m = (mat4 *)luaL_checkudata(L, 1, "mat4_mt"); - assertNotNull(m, "invalid mat4 userdata"); - - mat4 r; - glm_mat4_inv(*m, r); - moduleMat4Push(L, r); - return 1; -} - -/** - * Multiplies a mat4 by a vec3, with an optional w component (default 1.0). - * - * @param L Lua state. Arg 1: mat4. Arg 2: vec3. Arg 3 (optional): number w. - * @return 1 (new vec3). - */ -static int moduleMat4MulVec3(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - mat4 *m = (mat4 *)luaL_checkudata(L, 1, "mat4_mt"); - assertNotNull(m, "invalid mat4 userdata"); - - vec3 v; - moduleVec3Check(L, 2, v); - - float_t w = lua_gettop(L) >= 3 ? (float_t)luaL_checknumber(L, 3) : 1.0f; - vec3 r; - glm_mat4_mulv3(*m, v, w, r); - moduleVec3Push(L, r); - return 1; -} - -/** - * Multiplies a mat4 by a vec4. - * - * @param L Lua state. Arg 1: mat4. Arg 2: vec4. - * @return 1 (new vec4). - */ -static int moduleMat4MulVec4(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - mat4 *m = (mat4 *)luaL_checkudata(L, 1, "mat4_mt"); - assertNotNull(m, "invalid mat4 userdata"); - - vec4 v; - moduleVec4Check(L, 2, v); - - vec4 r; - glm_mat4_mulv(*m, v, r); - moduleVec4Push(L, r); - return 1; -} - -/** - * Returns a copy of a mat4 translated by a vec3. - * - * @param L Lua state. Arg 1: mat4. Arg 2: vec3. - * @return 1 (new mat4). - */ -static int moduleMat4Translate(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - mat4 *m = (mat4 *)luaL_checkudata(L, 1, "mat4_mt"); - assertNotNull(m, "invalid mat4 userdata"); - - vec3 v; - moduleVec3Check(L, 2, v); - - mat4 r; - glm_mat4_copy(*m, r); - glm_translate(r, v); - moduleMat4Push(L, r); - return 1; -} - -/** - * Returns a copy of a mat4 scaled by a vec3. - * - * @param L Lua state. Arg 1: mat4. Arg 2: vec3. - * @return 1 (new mat4). - */ -static int moduleMat4Scale(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - mat4 *m = (mat4 *)luaL_checkudata(L, 1, "mat4_mt"); - assertNotNull(m, "invalid mat4 userdata"); - - vec3 v; - moduleVec3Check(L, 2, v); - - mat4 r; - glm_mat4_copy(*m, r); - glm_scale(r, v); - moduleMat4Push(L, r); - return 1; -} - -/** - * Returns a new identity mat4. - * - * @param L Lua state. - * @return 1 (new mat4). - */ -static int moduleMat4Identity(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - mat4 r; - glm_mat4_identity(r); - moduleMat4Push(L, r); - return 1; -} - -/** - * Returns the determinant of a mat4. - * - * @param L Lua state. Arg 1: mat4. - * @return 1 (number). - */ -static int moduleMat4Determinant(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - mat4 *m = (mat4 *)luaL_checkudata(L, 1, "mat4_mt"); - assertNotNull(m, "invalid mat4 userdata"); - - lua_pushnumber(L, (lua_Number)glm_mat4_det(*m)); - return 1; -} - -/** - * Constructor: creates a new identity mat4. - * - * @param L Lua state. - * @return 1 (new mat4). - */ -static int moduleMat4Create(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - mat4 m; - glm_mat4_identity(m); - moduleMat4Push(L, m); - return 1; -} - -/** - * Registers the mat4 metatable and mat4 constructor global. - * - * @param L Lua state. - */ -static void moduleMat4(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(!luaL_newmetatable(L, "mat4_mt")) { - lua_pop(L, 1); - return; +JS_FUNC(moduleMatMulVec3) { + JS_REQUIRE_ARGS(1); + float_t (*m)[4] = (float_t (*)[4])jerry_object_get_native_ptr( + call_info_p->this_value, &MAT4_NATIVE_INFO + ); + if(!m) return JS_THROW("mat4.mulVec3: invalid this"); + vec3 vin; + if(!moduleVec3Check(args_p[0], vin)) { + return JS_THROW("mat4.mulVec3: first argument must be a vec3"); } - - lua_pushcfunction(L, moduleMat4Index); - lua_setfield(L, -2, "__index"); - lua_pushcfunction(L, moduleMat4OpMul); - lua_setfield(L, -2, "__mul"); - lua_pushcfunction(L, moduleMat4OpToString); - lua_setfield(L, -2, "__tostring"); - lua_pushcfunction(L, moduleMat4Transpose); - lua_setfield(L, -2, "transpose"); - lua_pushcfunction(L, moduleMat4Inverse); - lua_setfield(L, -2, "inverse"); - lua_pushcfunction(L, moduleMat4MulVec3); - lua_setfield(L, -2, "mulVec3"); - lua_pushcfunction(L, moduleMat4MulVec4); - lua_setfield(L, -2, "mulVec4"); - lua_pushcfunction(L, moduleMat4Translate); - lua_setfield(L, -2, "translate"); - lua_pushcfunction(L, moduleMat4Scale); - lua_setfield(L, -2, "scale"); - lua_pushcfunction(L, moduleMat4Identity); - lua_setfield(L, -2, "identity"); - lua_pushcfunction(L, moduleMat4Determinant); - lua_setfield(L, -2, "determinant"); - lua_pop(L, 1); - - lua_register(L, "mat4", moduleMat4Create); + float_t w = (args_count >= 2 && jerry_value_is_number(args_p[1])) + ? (float_t)jerry_value_as_number(args_p[1]) + : 1.0f; + vec3 vout; + glm_mat4_mulv3(m, vin, w, vout); + return moduleVec3Push(vout); +} + +JS_FUNC(moduleMatMulVec4) { + JS_REQUIRE_ARGS(1); + float_t (*m)[4] = (float_t (*)[4])jerry_object_get_native_ptr( + call_info_p->this_value, &MAT4_NATIVE_INFO + ); + if(!m) return JS_THROW("mat4.mulVec4: invalid this"); + vec4 vin; + if(!moduleVec4Check(args_p[0], vin)) { + return JS_THROW("mat4.mulVec4: first argument must be a vec4"); + } + vec4 vout; + glm_mat4_mulv(m, vin, vout); + return moduleVec4Push(vout); +} + +JS_FUNC(moduleMatTranslate) { + JS_REQUIRE_ARGS(1); + float_t (*m)[4] = (float_t (*)[4])jerry_object_get_native_ptr( + call_info_p->this_value, &MAT4_NATIVE_INFO + ); + if(!m) return JS_THROW("mat4.translate: invalid this"); + vec3 tv; + if(!moduleVec3Check(args_p[0], tv)) { + return JS_THROW("mat4.translate: argument must be a vec3"); + } + float_t (*r)[4] = (float_t (*)[4])malloc(sizeof(mat4)); + glm_mat4_copy(m, r); + glm_translate(r, tv); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &MAT4_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_mat4Proto); + return obj; +} + +JS_FUNC(moduleMatScale) { + JS_REQUIRE_ARGS(1); + float_t (*m)[4] = (float_t (*)[4])jerry_object_get_native_ptr( + call_info_p->this_value, &MAT4_NATIVE_INFO + ); + if(!m) return JS_THROW("mat4.scale: invalid this"); + vec3 sv; + if(!moduleVec3Check(args_p[0], sv)) { + return JS_THROW("mat4.scale: argument must be a vec3"); + } + float_t (*r)[4] = (float_t (*)[4])malloc(sizeof(mat4)); + glm_mat4_copy(m, r); + glm_scale(r, sv); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &MAT4_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_mat4Proto); + return obj; +} + +JS_FUNC(moduleMatIdentityMethod) { + float_t (*r)[4] = (float_t (*)[4])malloc(sizeof(mat4)); + glm_mat4_identity(r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &MAT4_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_mat4Proto); + return obj; +} + +// --------------------------------------------------------------------------- +// Global constructor / factory functions +// --------------------------------------------------------------------------- + +/** + * mat4Identity() - returns a new identity matrix. + */ +JS_FUNC(moduleMatIdentity) { + float_t (*r)[4] = (float_t (*)[4])malloc(sizeof(mat4)); + glm_mat4_identity(r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &MAT4_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_mat4Proto); + return obj; +} + +/** + * mat4Perspective(fov, aspect, near, far) - returns a perspective projection + * matrix. + */ +JS_FUNC(moduleMatPerspective) { + JS_REQUIRE_ARGS(4); + JS_REQUIRE_NUMBER(0); + JS_REQUIRE_NUMBER(1); + JS_REQUIRE_NUMBER(2); + JS_REQUIRE_NUMBER(3); + float_t fov = (float_t)jerry_value_as_number(args_p[0]); + float_t aspect = (float_t)jerry_value_as_number(args_p[1]); + float_t znear = (float_t)jerry_value_as_number(args_p[2]); + float_t zfar = (float_t)jerry_value_as_number(args_p[3]); + float_t (*r)[4] = (float_t (*)[4])malloc(sizeof(mat4)); + glm_perspective(fov, aspect, znear, zfar, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &MAT4_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_mat4Proto); + return obj; +} + +/** + * mat4LookAt(eye, center, up) - returns a view matrix. + * eye, center, up are vec3 objects. + */ +JS_FUNC(moduleMatLookAt) { + JS_REQUIRE_ARGS(3); + vec3 eye, center, up; + if(!moduleVec3Check(args_p[0], eye)) { + return JS_THROW("mat4LookAt: first argument (eye) must be a vec3"); + } + if(!moduleVec3Check(args_p[1], center)) { + return JS_THROW("mat4LookAt: second argument (center) must be a vec3"); + } + if(!moduleVec3Check(args_p[2], up)) { + return JS_THROW("mat4LookAt: third argument (up) must be a vec3"); + } + float_t (*r)[4] = (float_t (*)[4])malloc(sizeof(mat4)); + glm_lookat(eye, center, up, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &MAT4_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_mat4Proto); + return obj; +} + +// --------------------------------------------------------------------------- +// Helper: push a cglm mat4 as a new JS object +// --------------------------------------------------------------------------- + +/** + * Wraps a copy of a cglm mat4 as a new JerryScript object. + * + * @param m Source mat4 (float[4][4]) to copy. + * @return Owned jerry_value_t with native ptr set. + */ +static inline jerry_value_t moduleMat4Push(float (*m)[4]) { + float_t (*copy)[4] = (float_t (*)[4])malloc(sizeof(mat4)); + glm_mat4_copy(m, copy); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &MAT4_NATIVE_INFO, copy); + jerry_object_set_proto(obj, s_mat4Proto); + return obj; +} + +// --------------------------------------------------------------------------- +// Helper: extract mat4 from a JS object +// --------------------------------------------------------------------------- + +/** + * Reads a JerryScript mat4 object into an existing mat4 (float[4][4]). + * + * @param val JS value to read from. + * @param out Destination mat4. + * @return true if val carries a valid mat4 native ptr. + */ +static inline bool_t moduleMat4Check(jerry_value_t val, float (*out)[4]) { + float_t (*m)[4] = (float_t (*)[4])jerry_object_get_native_ptr( + val, &MAT4_NATIVE_INFO + ); + if(!m) return false; + glm_mat4_copy(m, out); + return true; +} + +// --------------------------------------------------------------------------- +// Module init +// --------------------------------------------------------------------------- + +/** + * Creates the mat4 prototype with all methods, then registers the global + * factory functions mat4Identity(), mat4Perspective(), and mat4LookAt(). + */ +static void moduleMat4(void) { + s_mat4Proto = jerry_object(); + + jsDefineMethod(s_mat4Proto, "mul", moduleMatMul); + jsDefineMethod(s_mat4Proto, "transpose", moduleMatTranspose); + jsDefineMethod(s_mat4Proto, "inverse", moduleMatInverse); + jsDefineMethod(s_mat4Proto, "determinant", moduleMatDeterminant); + jsDefineMethod(s_mat4Proto, "mulVec3", moduleMatMulVec3); + jsDefineMethod(s_mat4Proto, "mulVec4", moduleMatMulVec4); + jsDefineMethod(s_mat4Proto, "translate", moduleMatTranslate); + jsDefineMethod(s_mat4Proto, "scale", moduleMatScale); + jsDefineMethod(s_mat4Proto, "identity", moduleMatIdentityMethod); + + jsRegister("mat4Identity", moduleMatIdentity); + jsRegister("mat4Perspective", moduleMatPerspective); + jsRegister("mat4LookAt", moduleMatLookAt); } diff --git a/src/dusk/script/module/math/modulemath.h b/src/dusk/script/module/math/modulemath.h index b4828396..16dfa5a2 100644 --- a/src/dusk/script/module/math/modulemath.h +++ b/src/dusk/script/module/math/modulemath.h @@ -14,14 +14,10 @@ /** * Registers all math modules: vec2, vec3, vec4, mat4. - * - * @param L Lua state. */ -static void moduleMath(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - moduleVec2(L); - moduleVec3(L); - moduleVec4(L); - moduleMat4(L); +static void moduleMath(void) { + moduleVec2(); + moduleVec3(); + moduleVec4(); + moduleMat4(); } diff --git a/src/dusk/script/module/math/modulevec2.h b/src/dusk/script/module/math/modulevec2.h index 136076c8..088fa9cd 100644 --- a/src/dusk/script/module/math/modulevec2.h +++ b/src/dusk/script/module/math/modulevec2.h @@ -7,441 +7,267 @@ #pragma once #include "script/module/modulebase.h" +#include "assert/assert.h" +#include "cglm/cglm.h" -/** - * Pushes a new vec2 userdata onto the Lua stack with the vec2_mt metatable. - * - * @param L Lua state. - * @param v Source vector to copy. - */ -static void moduleVec2Push(lua_State *L, vec2 v) { - assertNotNull(L, "Lua state cannot be NULL"); +// Native info for heap-allocated vec2 (float[2]) +static void freeVec2Native(void *ptr, jerry_object_native_info_t *info) { + (void)info; + free(ptr); +} +static const jerry_object_native_info_t VEC2_NATIVE_INFO = { + .free_cb = freeVec2Native, + .number_of_references = 0, + .offset_of_references = 0 +}; +static jerry_value_t s_vec2Proto = 0; - vec2 *u = (vec2 *)lua_newuserdata(L, sizeof(vec2)); - glm_vec2_copy(v, *u); - luaL_getmetatable(L, "vec2_mt"); - lua_setmetatable(L, -2); +// --------------------------------------------------------------------------- +// Property getters / setters +// --------------------------------------------------------------------------- + +JS_FUNC(moduleVec2GetX) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC2_NATIVE_INFO + ); + return v ? jerry_number(v[0]) : jerry_undefined(); +} +JS_FUNC(moduleVec2SetX) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC2_NATIVE_INFO + ); + if(v && args_count > 0) v[0] = (float_t)jerry_value_as_number(args_p[0]); + return jerry_undefined(); } -/** - * Reads a vec2 userdata from the given stack index into out. - * - * @param L Lua state. - * @param idx Stack index of the vec2 userdata. - * @param out Destination vector. - */ -static void moduleVec2Check(lua_State *L, int idx, vec2 out) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec2 *v = (vec2 *)luaL_checkudata(L, idx, "vec2_mt"); - glm_vec2_copy(*v, out); +JS_FUNC(moduleVec2GetY) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC2_NATIVE_INFO + ); + return v ? jerry_number(v[1]) : jerry_undefined(); +} +JS_FUNC(moduleVec2SetY) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC2_NATIVE_INFO + ); + if(v && args_count > 0) v[1] = (float_t)jerry_value_as_number(args_p[0]); + return jerry_undefined(); } -/** - * __index metamethod for vec2 userdata. - * Supports integer indices 1-2 and string keys x, y; falls through to the - * metatable for method lookups. - * - * @param L Lua state. Arg 1: vec2 userdata. Arg 2: integer or string key. - * @return 1. - */ -static int moduleVec2Index(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +// --------------------------------------------------------------------------- +// Methods +// --------------------------------------------------------------------------- - vec2 *v = (vec2 *)luaL_checkudata(L, 1, "vec2_mt"); - assertNotNull(v, "invalid vec2 userdata"); - - const char *key = luaL_checkstring(L, 2); - assertStrLenMin(key, 1, "property key cannot be empty"); - - if(lua_isnumber(L, 2)) { - lua_Integer i = lua_tointeger(L, 2); - if(i >= 1 && i <= 2) { - lua_pushnumber(L, (lua_Number)(*v)[i - 1]); - return 1; - } - return 0; - } - - if(stringCompare(key, "x") == 0) { - lua_pushnumber(L, (lua_Number)(*v)[0]); - return 1; - } - - if(stringCompare(key, "y") == 0) { - lua_pushnumber(L, (lua_Number)(*v)[1]); - return 1; - } - - lua_getmetatable(L, 1); - lua_getfield(L, -1, key); - lua_remove(L, -2); - return 1; +JS_FUNC(moduleVec2Dot) { + JS_REQUIRE_ARGS(1); + float_t *a = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC2_NATIVE_INFO + ); + if(!a) return JS_THROW("vec2.dot: invalid this"); + float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC2_NATIVE_INFO); + if(!b) return JS_THROW("vec2.dot: argument must be a vec2"); + return jerry_number(glm_vec2_dot(a, b)); } -/** - * __newindex metamethod for vec2 userdata. - * Writes x, y. Errors on unknown keys. - * - * @param L Lua state. Arg 1: vec2 userdata. Arg 2: key string. Arg 3: number. - * @return 0. - */ -static int moduleVec2NewIndex(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec2 *v = (vec2 *)luaL_checkudata(L, 1, "vec2_mt"); - assertNotNull(v, "invalid vec2 userdata"); - - const char *key = luaL_checkstring(L, 2); - assertStrLenMin(key, 1, "property key cannot be empty"); - - if(stringCompare(key, "x") == 0) { - (*v)[0] = (float_t)luaL_checknumber(L, 3); - return 0; - } - - if(stringCompare(key, "y") == 0) { - (*v)[1] = (float_t)luaL_checknumber(L, 3); - return 0; - } - - luaL_error(L, "vec2: unknown property '%s'", key); - return 0; +JS_FUNC(moduleVec2Length) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC2_NATIVE_INFO + ); + if(!v) return JS_THROW("vec2.length: invalid this"); + return jerry_number(glm_vec2_norm(v)); } -/** - * __add metamethod: returns a + b as a new vec2. - * - * @param L Lua state. Arg 1: vec2. Arg 2: vec2. - * @return 1 (new vec2). - */ -static int moduleVec2OpAdd(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec2 *a = (vec2 *)luaL_checkudata(L, 1, "vec2_mt"); - assertNotNull(a, "invalid vec2 userdata"); - - vec2 *b = (vec2 *)luaL_checkudata(L, 2, "vec2_mt"); - assertNotNull(b, "invalid vec2 userdata"); - - vec2 r; - glm_vec2_add(*a, *b, r); - moduleVec2Push(L, r); - return 1; +JS_FUNC(moduleVec2LengthSq) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC2_NATIVE_INFO + ); + if(!v) return JS_THROW("vec2.lengthSq: invalid this"); + return jerry_number(glm_vec2_norm2(v)); } -/** - * __sub metamethod: returns a - b as a new vec2. - * - * @param L Lua state. Arg 1: vec2. Arg 2: vec2. - * @return 1 (new vec2). - */ -static int moduleVec2OpSub(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec2 *a = (vec2 *)luaL_checkudata(L, 1, "vec2_mt"); - assertNotNull(a, "invalid vec2 userdata"); - - vec2 *b = (vec2 *)luaL_checkudata(L, 2, "vec2_mt"); - assertNotNull(b, "invalid vec2 userdata"); - - vec2 r; - glm_vec2_sub(*a, *b, r); - moduleVec2Push(L, r); - return 1; +JS_FUNC(moduleVec2Normalize) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC2_NATIVE_INFO + ); + if(!v) return JS_THROW("vec2.normalize: invalid this"); + float_t *r = (float_t *)malloc(sizeof(vec2)); + glm_vec2_normalize_to(v, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC2_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_vec2Proto); + return obj; } -/** - * __mul metamethod: returns v * scalar or scalar * v as a new vec2. - * - * @param L Lua state. Arg 1: vec2 or number. Arg 2: number or vec2. - * @return 1 (new vec2). - */ -static int moduleVec2OpMul(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec2 r; - if(lua_isnumber(L, 1)) { - float_t s = (float_t)lua_tonumber(L, 1); - vec2 *v = (vec2 *)luaL_checkudata(L, 2, "vec2_mt"); - assertNotNull(v, "invalid vec2 userdata"); - glm_vec2_scale(*v, s, r); - } else { - vec2 *v = (vec2 *)luaL_checkudata(L, 1, "vec2_mt"); - assertNotNull(v, "invalid vec2 userdata"); - float_t s = (float_t)luaL_checknumber(L, 2); - glm_vec2_scale(*v, s, r); - } - - moduleVec2Push(L, r); - return 1; +JS_FUNC(moduleVec2Negate) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC2_NATIVE_INFO + ); + if(!v) return JS_THROW("vec2.negate: invalid this"); + float_t *r = (float_t *)malloc(sizeof(vec2)); + glm_vec2_negate_to(v, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC2_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_vec2Proto); + return obj; } -/** - * __div metamethod: returns v / scalar as a new vec2. - * - * @param L Lua state. Arg 1: vec2. Arg 2: number. - * @return 1 (new vec2). - */ -static int moduleVec2OpDiv(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec2 *v = (vec2 *)luaL_checkudata(L, 1, "vec2_mt"); - assertNotNull(v, "invalid vec2 userdata"); - - float_t s = (float_t)luaL_checknumber(L, 2); - vec2 r; - glm_vec2_divs(*v, s, r); - moduleVec2Push(L, r); - return 1; +JS_FUNC(moduleVec2Add) { + JS_REQUIRE_ARGS(1); + float_t *a = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC2_NATIVE_INFO + ); + if(!a) return JS_THROW("vec2.add: invalid this"); + float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC2_NATIVE_INFO); + if(!b) return JS_THROW("vec2.add: argument must be a vec2"); + float_t *r = (float_t *)malloc(sizeof(vec2)); + glm_vec2_add(a, b, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC2_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_vec2Proto); + return obj; } -/** - * __unm metamethod: returns -v as a new vec2. - * - * @param L Lua state. Arg 1: vec2. - * @return 1 (new vec2). - */ -static int moduleVec2OpUnm(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec2 *v = (vec2 *)luaL_checkudata(L, 1, "vec2_mt"); - assertNotNull(v, "invalid vec2 userdata"); - - vec2 r; - glm_vec2_negate_to(*v, r); - moduleVec2Push(L, r); - return 1; +JS_FUNC(moduleVec2Sub) { + JS_REQUIRE_ARGS(1); + float_t *a = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC2_NATIVE_INFO + ); + if(!a) return JS_THROW("vec2.sub: invalid this"); + float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC2_NATIVE_INFO); + if(!b) return JS_THROW("vec2.sub: argument must be a vec2"); + float_t *r = (float_t *)malloc(sizeof(vec2)); + glm_vec2_sub(a, b, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC2_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_vec2Proto); + return obj; } -/** - * __eq metamethod: component-wise equality test. - * - * @param L Lua state. Arg 1: vec2. Arg 2: vec2. - * @return 1 (boolean). - */ -static int moduleVec2OpEq(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec2 *a = (vec2 *)luaL_checkudata(L, 1, "vec2_mt"); - assertNotNull(a, "invalid vec2 userdata"); - - vec2 *b = (vec2 *)luaL_checkudata(L, 2, "vec2_mt"); - assertNotNull(b, "invalid vec2 userdata"); - - lua_pushboolean(L, (*a)[0] == (*b)[0] && (*a)[1] == (*b)[1]); - return 1; +JS_FUNC(moduleVec2Scale) { + JS_REQUIRE_ARGS(1); + JS_REQUIRE_NUMBER(0); + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC2_NATIVE_INFO + ); + if(!v) return JS_THROW("vec2.scale: invalid this"); + float_t s = (float_t)jerry_value_as_number(args_p[0]); + float_t *r = (float_t *)malloc(sizeof(vec2)); + glm_vec2_scale(v, s, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC2_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_vec2Proto); + return obj; } -/** - * __tostring metamethod: returns a human-readable representation. - * - * @param L Lua state. Arg 1: vec2. - * @return 1 (string). - */ -static int moduleVec2OpToString(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec2 *v = (vec2 *)luaL_checkudata(L, 1, "vec2_mt"); - assertNotNull(v, "invalid vec2 userdata"); - - char buf[64]; - snprintf(buf, sizeof(buf), "vec2(%.3f, %.3f)", (*v)[0], (*v)[1]); - lua_pushstring(L, buf); - return 1; +JS_FUNC(moduleVec2Lerp) { + JS_REQUIRE_ARGS(2); + JS_REQUIRE_NUMBER(1); + float_t *a = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC2_NATIVE_INFO + ); + if(!a) return JS_THROW("vec2.lerp: invalid this"); + float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC2_NATIVE_INFO); + if(!b) return JS_THROW("vec2.lerp: first argument must be a vec2"); + float_t t = (float_t)jerry_value_as_number(args_p[1]); + float_t *r = (float_t *)malloc(sizeof(vec2)); + glm_vec2_lerp(a, b, t, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC2_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_vec2Proto); + return obj; } -/** - * Returns the dot product of two vec2 values. - * - * @param L Lua state. Arg 1: vec2. Arg 2: vec2. - * @return 1 (number). - */ -static int moduleVec2Dot(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec2 *a = (vec2 *)luaL_checkudata(L, 1, "vec2_mt"); - assertNotNull(a, "invalid vec2 userdata"); - - vec2 *b = (vec2 *)luaL_checkudata(L, 2, "vec2_mt"); - assertNotNull(b, "invalid vec2 userdata"); - - lua_pushnumber(L, (lua_Number)glm_vec2_dot(*a, *b)); - return 1; +JS_FUNC(moduleVec2Distance) { + JS_REQUIRE_ARGS(1); + float_t *a = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC2_NATIVE_INFO + ); + if(!a) return JS_THROW("vec2.distance: invalid this"); + float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC2_NATIVE_INFO); + if(!b) return JS_THROW("vec2.distance: argument must be a vec2"); + return jerry_number(glm_vec2_distance(a, b)); } -/** - * Returns the length (magnitude) of a vec2. - * - * @param L Lua state. Arg 1: vec2. - * @return 1 (number). - */ -static int moduleVec2Length(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +// --------------------------------------------------------------------------- +// Constructor +// --------------------------------------------------------------------------- - vec2 *v = (vec2 *)luaL_checkudata(L, 1, "vec2_mt"); - assertNotNull(v, "invalid vec2 userdata"); - - lua_pushnumber(L, (lua_Number)glm_vec2_norm(*v)); - return 1; +JS_FUNC(moduleVec2Create) { + JS_REQUIRE_ARGS(2); + JS_REQUIRE_NUMBER(0); + JS_REQUIRE_NUMBER(1); + float_t *v = (float_t *)malloc(sizeof(vec2)); + v[0] = (float_t)jerry_value_as_number(args_p[0]); + v[1] = (float_t)jerry_value_as_number(args_p[1]); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC2_NATIVE_INFO, v); + jerry_object_set_proto(obj, s_vec2Proto); + return obj; } -/** - * Returns the squared length of a vec2. - * - * @param L Lua state. Arg 1: vec2. - * @return 1 (number). - */ -static int moduleVec2LengthSq(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec2 *v = (vec2 *)luaL_checkudata(L, 1, "vec2_mt"); - assertNotNull(v, "invalid vec2 userdata"); - - lua_pushnumber(L, (lua_Number)glm_vec2_norm2(*v)); - return 1; -} +// --------------------------------------------------------------------------- +// Helper: push a cglm vec2 as a new JS object +// --------------------------------------------------------------------------- /** - * Returns a normalized copy of a vec2. + * Wraps a copy of a cglm vec2 as a new JerryScript object. * - * @param L Lua state. Arg 1: vec2. - * @return 1 (new vec2). + * @param v Source float[2] to copy. + * @return Owned jerry_value_t with native ptr set. */ -static int moduleVec2Normalize(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec2 *v = (vec2 *)luaL_checkudata(L, 1, "vec2_mt"); - assertNotNull(v, "invalid vec2 userdata"); - - vec2 r; - glm_vec2_normalize_to(*v, r); - moduleVec2Push(L, r); - return 1; +static inline jerry_value_t moduleVec2Push(const float_t *v) { + float_t *copy = (float_t *)malloc(sizeof(vec2)); + copy[0] = v[0]; + copy[1] = v[1]; + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC2_NATIVE_INFO, copy); + jerry_object_set_proto(obj, s_vec2Proto); + return obj; } +// --------------------------------------------------------------------------- +// Helper: extract vec2 from a JS object +// --------------------------------------------------------------------------- + /** - * Linearly interpolates between two vec2 values. + * Reads a JerryScript vec2 object into an existing float[2]. * - * @param L Lua state. Arg 1: vec2 a. Arg 2: vec2 b. Arg 3: number t. - * @return 1 (new vec2). + * @param val JS value to read from. + * @param out Destination float[2]. + * @return true if val carries a valid vec2 native ptr. */ -static int moduleVec2Lerp(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec2 *a = (vec2 *)luaL_checkudata(L, 1, "vec2_mt"); - assertNotNull(a, "invalid vec2 userdata"); - - vec2 *b = (vec2 *)luaL_checkudata(L, 2, "vec2_mt"); - assertNotNull(b, "invalid vec2 userdata"); - - float_t t = (float_t)luaL_checknumber(L, 3); - vec2 r; - glm_vec2_lerp(*a, *b, t, r); - moduleVec2Push(L, r); - return 1; +static inline bool_t moduleVec2Check(jerry_value_t val, float_t *out) { + float_t *v = (float_t *)jerry_object_get_native_ptr(val, &VEC2_NATIVE_INFO); + if(!v) return false; + out[0] = v[0]; + out[1] = v[1]; + return true; } +// --------------------------------------------------------------------------- +// Module init +// --------------------------------------------------------------------------- + /** - * Returns the distance between two vec2 points. - * - * @param L Lua state. Arg 1: vec2 a. Arg 2: vec2 b. - * @return 1 (number). + * Creates the vec2 prototype with x/y getter-setter properties and all + * methods, then registers the global vec2() constructor. */ -static int moduleVec2Distance(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +static void moduleVec2(void) { + s_vec2Proto = jerry_object(); - vec2 *a = (vec2 *)luaL_checkudata(L, 1, "vec2_mt"); - assertNotNull(a, "invalid vec2 userdata"); + jsDefineProperty(s_vec2Proto, "x", moduleVec2GetX, moduleVec2SetX); + jsDefineProperty(s_vec2Proto, "y", moduleVec2GetY, moduleVec2SetY); - vec2 *b = (vec2 *)luaL_checkudata(L, 2, "vec2_mt"); - assertNotNull(b, "invalid vec2 userdata"); + jsDefineMethod(s_vec2Proto, "dot", moduleVec2Dot); + jsDefineMethod(s_vec2Proto, "length", moduleVec2Length); + jsDefineMethod(s_vec2Proto, "lengthSq", moduleVec2LengthSq); + jsDefineMethod(s_vec2Proto, "normalize", moduleVec2Normalize); + jsDefineMethod(s_vec2Proto, "negate", moduleVec2Negate); + jsDefineMethod(s_vec2Proto, "add", moduleVec2Add); + jsDefineMethod(s_vec2Proto, "sub", moduleVec2Sub); + jsDefineMethod(s_vec2Proto, "scale", moduleVec2Scale); + jsDefineMethod(s_vec2Proto, "lerp", moduleVec2Lerp); + jsDefineMethod(s_vec2Proto, "distance", moduleVec2Distance); - lua_pushnumber(L, (lua_Number)glm_vec2_distance(*a, *b)); - return 1; -} - -/** - * Returns a negated copy of a vec2. - * - * @param L Lua state. Arg 1: vec2. - * @return 1 (new vec2). - */ -static int moduleVec2Negate(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec2 *v = (vec2 *)luaL_checkudata(L, 1, "vec2_mt"); - assertNotNull(v, "invalid vec2 userdata"); - - vec2 r; - glm_vec2_negate_to(*v, r); - moduleVec2Push(L, r); - return 1; -} - -/** - * Constructor: creates a vec2 from two optional numbers (defaults to 0). - * - * @param L Lua state. Arg 1 (optional): x. Arg 2 (optional): y. - * @return 1 (new vec2). - */ -static int moduleVec2Create(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec2 v = {0, 0}; - int top = lua_gettop(L); - if(top >= 1) v[0] = (float_t)luaL_checknumber(L, 1); - if(top >= 2) v[1] = (float_t)luaL_checknumber(L, 2); - moduleVec2Push(L, v); - return 1; -} - -/** - * Registers the vec2 metatable and vec2 constructor global. - * - * @param L Lua state. - */ -static void moduleVec2(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(!luaL_newmetatable(L, "vec2_mt")) { - lua_pop(L, 1); - return; - } - - lua_pushcfunction(L, moduleVec2Index); - lua_setfield(L, -2, "__index"); - lua_pushcfunction(L, moduleVec2NewIndex); - lua_setfield(L, -2, "__newindex"); - lua_pushcfunction(L, moduleVec2OpAdd); - lua_setfield(L, -2, "__add"); - lua_pushcfunction(L, moduleVec2OpSub); - lua_setfield(L, -2, "__sub"); - lua_pushcfunction(L, moduleVec2OpMul); - lua_setfield(L, -2, "__mul"); - lua_pushcfunction(L, moduleVec2OpDiv); - lua_setfield(L, -2, "__div"); - lua_pushcfunction(L, moduleVec2OpUnm); - lua_setfield(L, -2, "__unm"); - lua_pushcfunction(L, moduleVec2OpEq); - lua_setfield(L, -2, "__eq"); - lua_pushcfunction(L, moduleVec2OpToString); - lua_setfield(L, -2, "__tostring"); - lua_pushcfunction(L, moduleVec2Dot); - lua_setfield(L, -2, "dot"); - lua_pushcfunction(L, moduleVec2Length); - lua_setfield(L, -2, "length"); - lua_pushcfunction(L, moduleVec2LengthSq); - lua_setfield(L, -2, "lengthSq"); - lua_pushcfunction(L, moduleVec2Normalize); - lua_setfield(L, -2, "normalize"); - lua_pushcfunction(L, moduleVec2Lerp); - lua_setfield(L, -2, "lerp"); - lua_pushcfunction(L, moduleVec2Distance); - lua_setfield(L, -2, "distance"); - lua_pushcfunction(L, moduleVec2Negate); - lua_setfield(L, -2, "negate"); - lua_pop(L, 1); - - lua_register(L, "vec2", moduleVec2Create); + jsRegister("vec2", moduleVec2Create); } diff --git a/src/dusk/script/module/math/modulevec3.h b/src/dusk/script/module/math/modulevec3.h index f1081ace..b3b55749 100644 --- a/src/dusk/script/module/math/modulevec3.h +++ b/src/dusk/script/module/math/modulevec3.h @@ -7,475 +7,303 @@ #pragma once #include "script/module/modulebase.h" +#include "assert/assert.h" +#include "cglm/cglm.h" -/** - * Pushes a new vec3 userdata onto the Lua stack with the vec3_mt metatable. - * - * @param L Lua state. - * @param v Source vector to copy. - */ -static void moduleVec3Push(lua_State *L, vec3 v) { - assertNotNull(L, "Lua state cannot be NULL"); +// Native info for heap-allocated vec3 (float[3]) +static void freeVec3Native(void *ptr, jerry_object_native_info_t *info) { + (void)info; + free(ptr); +} +static const jerry_object_native_info_t VEC3_NATIVE_INFO = { + .free_cb = freeVec3Native, + .number_of_references = 0, + .offset_of_references = 0 +}; +static jerry_value_t s_vec3Proto = 0; - vec3 *u = (vec3 *)lua_newuserdata(L, sizeof(vec3)); - glm_vec3_copy(v, *u); - luaL_getmetatable(L, "vec3_mt"); - lua_setmetatable(L, -2); +// --------------------------------------------------------------------------- +// Property getters / setters +// --------------------------------------------------------------------------- + +JS_FUNC(moduleVec3GetX) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC3_NATIVE_INFO + ); + return v ? jerry_number(v[0]) : jerry_undefined(); +} +JS_FUNC(moduleVec3SetX) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC3_NATIVE_INFO + ); + if(v && args_count > 0) v[0] = (float_t)jerry_value_as_number(args_p[0]); + return jerry_undefined(); } -/** - * Reads a vec3 userdata from the given stack index into out. - * - * @param L Lua state. - * @param idx Stack index of the vec3 userdata. - * @param out Destination vector. - */ -static void moduleVec3Check(lua_State *L, int idx, vec3 out) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec3 *v = (vec3 *)luaL_checkudata(L, idx, "vec3_mt"); - glm_vec3_copy(*v, out); +JS_FUNC(moduleVec3GetY) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC3_NATIVE_INFO + ); + return v ? jerry_number(v[1]) : jerry_undefined(); +} +JS_FUNC(moduleVec3SetY) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC3_NATIVE_INFO + ); + if(v && args_count > 0) v[1] = (float_t)jerry_value_as_number(args_p[0]); + return jerry_undefined(); } -/** - * __index metamethod for vec3 userdata. - * Supports integer indices 1-3 and string keys x, y, z; falls through to the - * metatable for method lookups. - * - * @param L Lua state. Arg 1: vec3 userdata. Arg 2: integer or string key. - * @return 1. - */ -static int moduleVec3Index(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec3 *v = (vec3 *)luaL_checkudata(L, 1, "vec3_mt"); - assertNotNull(v, "invalid vec3 userdata"); - - const char *key = luaL_checkstring(L, 2); - assertStrLenMin(key, 1, "property key cannot be empty"); - - if(lua_isnumber(L, 2)) { - lua_Integer i = lua_tointeger(L, 2); - if(i >= 1 && i <= 3) { - lua_pushnumber(L, (lua_Number)(*v)[i - 1]); - return 1; - } - return 0; - } - - if(stringCompare(key, "x") == 0) { - lua_pushnumber(L, (lua_Number)(*v)[0]); - return 1; - } - - if(stringCompare(key, "y") == 0) { - lua_pushnumber(L, (lua_Number)(*v)[1]); - return 1; - } - - if(stringCompare(key, "z") == 0) { - lua_pushnumber(L, (lua_Number)(*v)[2]); - return 1; - } - - lua_getmetatable(L, 1); - lua_getfield(L, -1, key); - lua_remove(L, -2); - return 1; +JS_FUNC(moduleVec3GetZ) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC3_NATIVE_INFO + ); + return v ? jerry_number(v[2]) : jerry_undefined(); +} +JS_FUNC(moduleVec3SetZ) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC3_NATIVE_INFO + ); + if(v && args_count > 0) v[2] = (float_t)jerry_value_as_number(args_p[0]); + return jerry_undefined(); } -/** - * __newindex metamethod for vec3 userdata. - * Writes x, y, z. Errors on unknown keys. - * - * @param L Lua state. Arg 1: vec3 userdata. Arg 2: key string. Arg 3: number. - * @return 0. - */ -static int moduleVec3NewIndex(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +// --------------------------------------------------------------------------- +// Methods +// --------------------------------------------------------------------------- - vec3 *v = (vec3 *)luaL_checkudata(L, 1, "vec3_mt"); - assertNotNull(v, "invalid vec3 userdata"); - - const char *key = luaL_checkstring(L, 2); - assertStrLenMin(key, 1, "property key cannot be empty"); - - if(stringCompare(key, "x") == 0) { - (*v)[0] = (float_t)luaL_checknumber(L, 3); - return 0; - } - - if(stringCompare(key, "y") == 0) { - (*v)[1] = (float_t)luaL_checknumber(L, 3); - return 0; - } - - if(stringCompare(key, "z") == 0) { - (*v)[2] = (float_t)luaL_checknumber(L, 3); - return 0; - } - - luaL_error(L, "vec3: unknown property '%s'", key); - return 0; +JS_FUNC(moduleVec3Dot) { + JS_REQUIRE_ARGS(1); + float_t *a = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC3_NATIVE_INFO + ); + if(!a) return JS_THROW("vec3.dot: invalid this"); + float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC3_NATIVE_INFO); + if(!b) return JS_THROW("vec3.dot: argument must be a vec3"); + return jerry_number(glm_vec3_dot(a, b)); } -/** - * __add metamethod: returns a + b as a new vec3. - * - * @param L Lua state. Arg 1: vec3. Arg 2: vec3. - * @return 1 (new vec3). - */ -static int moduleVec3OpAdd(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec3 *a = (vec3 *)luaL_checkudata(L, 1, "vec3_mt"); - assertNotNull(a, "invalid vec3 userdata"); - - vec3 *b = (vec3 *)luaL_checkudata(L, 2, "vec3_mt"); - assertNotNull(b, "invalid vec3 userdata"); - - vec3 r; - glm_vec3_add(*a, *b, r); - moduleVec3Push(L, r); - return 1; +JS_FUNC(moduleVec3Cross) { + JS_REQUIRE_ARGS(1); + float_t *a = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC3_NATIVE_INFO + ); + if(!a) return JS_THROW("vec3.cross: invalid this"); + float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC3_NATIVE_INFO); + if(!b) return JS_THROW("vec3.cross: argument must be a vec3"); + float_t *r = (float_t *)malloc(sizeof(vec3)); + glm_vec3_cross(a, b, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC3_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_vec3Proto); + return obj; } -/** - * __sub metamethod: returns a - b as a new vec3. - * - * @param L Lua state. Arg 1: vec3. Arg 2: vec3. - * @return 1 (new vec3). - */ -static int moduleVec3OpSub(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec3 *a = (vec3 *)luaL_checkudata(L, 1, "vec3_mt"); - assertNotNull(a, "invalid vec3 userdata"); - - vec3 *b = (vec3 *)luaL_checkudata(L, 2, "vec3_mt"); - assertNotNull(b, "invalid vec3 userdata"); - - vec3 r; - glm_vec3_sub(*a, *b, r); - moduleVec3Push(L, r); - return 1; +JS_FUNC(moduleVec3Length) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC3_NATIVE_INFO + ); + if(!v) return JS_THROW("vec3.length: invalid this"); + return jerry_number(glm_vec3_norm(v)); } -/** - * __mul metamethod: returns v * scalar or scalar * v as a new vec3. - * - * @param L Lua state. Arg 1: vec3 or number. Arg 2: number or vec3. - * @return 1 (new vec3). - */ -static int moduleVec3OpMul(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec3 r; - if(lua_isnumber(L, 1)) { - float_t s = (float_t)lua_tonumber(L, 1); - vec3 *v = (vec3 *)luaL_checkudata(L, 2, "vec3_mt"); - assertNotNull(v, "invalid vec3 userdata"); - glm_vec3_scale(*v, s, r); - } else { - vec3 *v = (vec3 *)luaL_checkudata(L, 1, "vec3_mt"); - assertNotNull(v, "invalid vec3 userdata"); - float_t s = (float_t)luaL_checknumber(L, 2); - glm_vec3_scale(*v, s, r); - } - - moduleVec3Push(L, r); - return 1; +JS_FUNC(moduleVec3LengthSq) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC3_NATIVE_INFO + ); + if(!v) return JS_THROW("vec3.lengthSq: invalid this"); + return jerry_number(glm_vec3_norm2(v)); } -/** - * __div metamethod: returns v / scalar as a new vec3. - * - * @param L Lua state. Arg 1: vec3. Arg 2: number. - * @return 1 (new vec3). - */ -static int moduleVec3OpDiv(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec3 *v = (vec3 *)luaL_checkudata(L, 1, "vec3_mt"); - assertNotNull(v, "invalid vec3 userdata"); - - float_t s = (float_t)luaL_checknumber(L, 2); - vec3 r; - glm_vec3_divs(*v, s, r); - moduleVec3Push(L, r); - return 1; +JS_FUNC(moduleVec3Normalize) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC3_NATIVE_INFO + ); + if(!v) return JS_THROW("vec3.normalize: invalid this"); + float_t *r = (float_t *)malloc(sizeof(vec3)); + glm_vec3_normalize_to(v, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC3_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_vec3Proto); + return obj; } -/** - * __unm metamethod: returns -v as a new vec3. - * - * @param L Lua state. Arg 1: vec3. - * @return 1 (new vec3). - */ -static int moduleVec3OpUnm(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec3 *v = (vec3 *)luaL_checkudata(L, 1, "vec3_mt"); - assertNotNull(v, "invalid vec3 userdata"); - - vec3 r; - glm_vec3_negate_to(*v, r); - moduleVec3Push(L, r); - return 1; +JS_FUNC(moduleVec3Negate) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC3_NATIVE_INFO + ); + if(!v) return JS_THROW("vec3.negate: invalid this"); + float_t *r = (float_t *)malloc(sizeof(vec3)); + glm_vec3_negate_to(v, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC3_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_vec3Proto); + return obj; } -/** - * __eq metamethod: component-wise equality test. - * - * @param L Lua state. Arg 1: vec3. Arg 2: vec3. - * @return 1 (boolean). - */ -static int moduleVec3OpEq(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec3 *a = (vec3 *)luaL_checkudata(L, 1, "vec3_mt"); - assertNotNull(a, "invalid vec3 userdata"); - - vec3 *b = (vec3 *)luaL_checkudata(L, 2, "vec3_mt"); - assertNotNull(b, "invalid vec3 userdata"); - - lua_pushboolean(L, (*a)[0] == (*b)[0] && (*a)[1] == (*b)[1] && (*a)[2] == (*b)[2]); - return 1; +JS_FUNC(moduleVec3Add) { + JS_REQUIRE_ARGS(1); + float_t *a = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC3_NATIVE_INFO + ); + if(!a) return JS_THROW("vec3.add: invalid this"); + float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC3_NATIVE_INFO); + if(!b) return JS_THROW("vec3.add: argument must be a vec3"); + float_t *r = (float_t *)malloc(sizeof(vec3)); + glm_vec3_add(a, b, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC3_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_vec3Proto); + return obj; } -/** - * __tostring metamethod: returns a human-readable representation. - * - * @param L Lua state. Arg 1: vec3. - * @return 1 (string). - */ -static int moduleVec3OpToString(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec3 *v = (vec3 *)luaL_checkudata(L, 1, "vec3_mt"); - assertNotNull(v, "invalid vec3 userdata"); - - char buf[80]; - snprintf(buf, sizeof(buf), "vec3(%.3f, %.3f, %.3f)", (*v)[0], (*v)[1], (*v)[2]); - lua_pushstring(L, buf); - return 1; +JS_FUNC(moduleVec3Sub) { + JS_REQUIRE_ARGS(1); + float_t *a = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC3_NATIVE_INFO + ); + if(!a) return JS_THROW("vec3.sub: invalid this"); + float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC3_NATIVE_INFO); + if(!b) return JS_THROW("vec3.sub: argument must be a vec3"); + float_t *r = (float_t *)malloc(sizeof(vec3)); + glm_vec3_sub(a, b, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC3_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_vec3Proto); + return obj; } -/** - * Returns the dot product of two vec3 values. - * - * @param L Lua state. Arg 1: vec3. Arg 2: vec3. - * @return 1 (number). - */ -static int moduleVec3Dot(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec3 *a = (vec3 *)luaL_checkudata(L, 1, "vec3_mt"); - assertNotNull(a, "invalid vec3 userdata"); - - vec3 *b = (vec3 *)luaL_checkudata(L, 2, "vec3_mt"); - assertNotNull(b, "invalid vec3 userdata"); - - lua_pushnumber(L, (lua_Number)glm_vec3_dot(*a, *b)); - return 1; +JS_FUNC(moduleVec3Scale) { + JS_REQUIRE_ARGS(1); + JS_REQUIRE_NUMBER(0); + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC3_NATIVE_INFO + ); + if(!v) return JS_THROW("vec3.scale: invalid this"); + float_t s = (float_t)jerry_value_as_number(args_p[0]); + float_t *r = (float_t *)malloc(sizeof(vec3)); + glm_vec3_scale(v, s, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC3_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_vec3Proto); + return obj; } -/** - * Returns the cross product of two vec3 values as a new vec3. - * - * @param L Lua state. Arg 1: vec3. Arg 2: vec3. - * @return 1 (new vec3). - */ -static int moduleVec3Cross(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec3 *a = (vec3 *)luaL_checkudata(L, 1, "vec3_mt"); - assertNotNull(a, "invalid vec3 userdata"); - - vec3 *b = (vec3 *)luaL_checkudata(L, 2, "vec3_mt"); - assertNotNull(b, "invalid vec3 userdata"); - - vec3 r; - glm_vec3_cross(*a, *b, r); - moduleVec3Push(L, r); - return 1; +JS_FUNC(moduleVec3Lerp) { + JS_REQUIRE_ARGS(2); + JS_REQUIRE_NUMBER(1); + float_t *a = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC3_NATIVE_INFO + ); + if(!a) return JS_THROW("vec3.lerp: invalid this"); + float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC3_NATIVE_INFO); + if(!b) return JS_THROW("vec3.lerp: first argument must be a vec3"); + float_t t = (float_t)jerry_value_as_number(args_p[1]); + float_t *r = (float_t *)malloc(sizeof(vec3)); + glm_vec3_lerp(a, b, t, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC3_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_vec3Proto); + return obj; } -/** - * Returns the length (magnitude) of a vec3. - * - * @param L Lua state. Arg 1: vec3. - * @return 1 (number). - */ -static int moduleVec3Length(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec3 *v = (vec3 *)luaL_checkudata(L, 1, "vec3_mt"); - assertNotNull(v, "invalid vec3 userdata"); - - lua_pushnumber(L, (lua_Number)glm_vec3_norm(*v)); - return 1; +JS_FUNC(moduleVec3Distance) { + JS_REQUIRE_ARGS(1); + float_t *a = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC3_NATIVE_INFO + ); + if(!a) return JS_THROW("vec3.distance: invalid this"); + float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC3_NATIVE_INFO); + if(!b) return JS_THROW("vec3.distance: argument must be a vec3"); + return jerry_number(glm_vec3_distance(a, b)); } -/** - * Returns the squared length of a vec3. - * - * @param L Lua state. Arg 1: vec3. - * @return 1 (number). - */ -static int moduleVec3LengthSq(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +// --------------------------------------------------------------------------- +// Constructor +// --------------------------------------------------------------------------- - vec3 *v = (vec3 *)luaL_checkudata(L, 1, "vec3_mt"); - assertNotNull(v, "invalid vec3 userdata"); - - lua_pushnumber(L, (lua_Number)glm_vec3_norm2(*v)); - return 1; +JS_FUNC(moduleVec3Create) { + JS_REQUIRE_ARGS(3); + JS_REQUIRE_NUMBER(0); + JS_REQUIRE_NUMBER(1); + JS_REQUIRE_NUMBER(2); + float_t *v = (float_t *)malloc(sizeof(vec3)); + v[0] = (float_t)jerry_value_as_number(args_p[0]); + v[1] = (float_t)jerry_value_as_number(args_p[1]); + v[2] = (float_t)jerry_value_as_number(args_p[2]); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC3_NATIVE_INFO, v); + jerry_object_set_proto(obj, s_vec3Proto); + return obj; } -/** - * Returns a normalized copy of a vec3. - * - * @param L Lua state. Arg 1: vec3. - * @return 1 (new vec3). - */ -static int moduleVec3Normalize(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec3 *v = (vec3 *)luaL_checkudata(L, 1, "vec3_mt"); - assertNotNull(v, "invalid vec3 userdata"); - - vec3 r; - glm_vec3_normalize_to(*v, r); - moduleVec3Push(L, r); - return 1; -} +// --------------------------------------------------------------------------- +// Helper: push a cglm vec3 as a new JS object +// --------------------------------------------------------------------------- /** - * Linearly interpolates between two vec3 values. + * Wraps a copy of a cglm vec3 as a new JerryScript object. * - * @param L Lua state. Arg 1: vec3 a. Arg 2: vec3 b. Arg 3: number t. - * @return 1 (new vec3). + * @param v Source float[3] to copy. + * @return Owned jerry_value_t with native ptr set. */ -static int moduleVec3Lerp(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec3 *a = (vec3 *)luaL_checkudata(L, 1, "vec3_mt"); - assertNotNull(a, "invalid vec3 userdata"); - - vec3 *b = (vec3 *)luaL_checkudata(L, 2, "vec3_mt"); - assertNotNull(b, "invalid vec3 userdata"); - - float_t t = (float_t)luaL_checknumber(L, 3); - vec3 r; - glm_vec3_lerp(*a, *b, t, r); - moduleVec3Push(L, r); - return 1; +static inline jerry_value_t moduleVec3Push(const float_t *v) { + float_t *copy = (float_t *)malloc(sizeof(vec3)); + copy[0] = v[0]; + copy[1] = v[1]; + copy[2] = v[2]; + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC3_NATIVE_INFO, copy); + jerry_object_set_proto(obj, s_vec3Proto); + return obj; } +// --------------------------------------------------------------------------- +// Helper: extract vec3 from a JS object +// --------------------------------------------------------------------------- + /** - * Returns the distance between two vec3 points. + * Reads a JerryScript vec3 object into an existing float[3]. * - * @param L Lua state. Arg 1: vec3 a. Arg 2: vec3 b. - * @return 1 (number). + * @param val JS value to read from. + * @param out Destination float[3]. + * @return true if val carries a valid vec3 native ptr. */ -static int moduleVec3Distance(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec3 *a = (vec3 *)luaL_checkudata(L, 1, "vec3_mt"); - assertNotNull(a, "invalid vec3 userdata"); - - vec3 *b = (vec3 *)luaL_checkudata(L, 2, "vec3_mt"); - assertNotNull(b, "invalid vec3 userdata"); - - lua_pushnumber(L, (lua_Number)glm_vec3_distance(*a, *b)); - return 1; +static inline bool_t moduleVec3Check(jerry_value_t val, float_t *out) { + float_t *v = (float_t *)jerry_object_get_native_ptr(val, &VEC3_NATIVE_INFO); + if(!v) return false; + out[0] = v[0]; + out[1] = v[1]; + out[2] = v[2]; + return true; } +// --------------------------------------------------------------------------- +// Module init +// --------------------------------------------------------------------------- + /** - * Returns a negated copy of a vec3. - * - * @param L Lua state. Arg 1: vec3. - * @return 1 (new vec3). + * Creates the vec3 prototype with x/y/z getter-setter properties and all + * methods, then registers the global vec3() constructor. */ -static int moduleVec3Negate(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +static void moduleVec3(void) { + s_vec3Proto = jerry_object(); - vec3 *v = (vec3 *)luaL_checkudata(L, 1, "vec3_mt"); - assertNotNull(v, "invalid vec3 userdata"); + jsDefineProperty(s_vec3Proto, "x", moduleVec3GetX, moduleVec3SetX); + jsDefineProperty(s_vec3Proto, "y", moduleVec3GetY, moduleVec3SetY); + jsDefineProperty(s_vec3Proto, "z", moduleVec3GetZ, moduleVec3SetZ); - vec3 r; - glm_vec3_negate_to(*v, r); - moduleVec3Push(L, r); - return 1; -} - -/** - * Constructor: creates a vec3 from three optional numbers (defaults to 0). - * - * @param L Lua state. Arg 1 (optional): x. Arg 2 (optional): y. Arg 3 (optional): z. - * @return 1 (new vec3). - */ -static int moduleVec3Create(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec3 v = {0, 0, 0}; - int top = lua_gettop(L); - if(top >= 1) v[0] = (float_t)luaL_checknumber(L, 1); - if(top >= 2) v[1] = (float_t)luaL_checknumber(L, 2); - if(top >= 3) v[2] = (float_t)luaL_checknumber(L, 3); - moduleVec3Push(L, v); - return 1; -} - -/** - * Registers the vec3 metatable and vec3 constructor global. - * - * @param L Lua state. - */ -static void moduleVec3(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(!luaL_newmetatable(L, "vec3_mt")) { - lua_pop(L, 1); - return; - } - - lua_pushcfunction(L, moduleVec3Index); - lua_setfield(L, -2, "__index"); - lua_pushcfunction(L, moduleVec3NewIndex); - lua_setfield(L, -2, "__newindex"); - lua_pushcfunction(L, moduleVec3OpAdd); - lua_setfield(L, -2, "__add"); - lua_pushcfunction(L, moduleVec3OpSub); - lua_setfield(L, -2, "__sub"); - lua_pushcfunction(L, moduleVec3OpMul); - lua_setfield(L, -2, "__mul"); - lua_pushcfunction(L, moduleVec3OpDiv); - lua_setfield(L, -2, "__div"); - lua_pushcfunction(L, moduleVec3OpUnm); - lua_setfield(L, -2, "__unm"); - lua_pushcfunction(L, moduleVec3OpEq); - lua_setfield(L, -2, "__eq"); - lua_pushcfunction(L, moduleVec3OpToString); - lua_setfield(L, -2, "__tostring"); - lua_pushcfunction(L, moduleVec3Dot); - lua_setfield(L, -2, "dot"); - lua_pushcfunction(L, moduleVec3Cross); - lua_setfield(L, -2, "cross"); - lua_pushcfunction(L, moduleVec3Length); - lua_setfield(L, -2, "length"); - lua_pushcfunction(L, moduleVec3LengthSq); - lua_setfield(L, -2, "lengthSq"); - lua_pushcfunction(L, moduleVec3Normalize); - lua_setfield(L, -2, "normalize"); - lua_pushcfunction(L, moduleVec3Lerp); - lua_setfield(L, -2, "lerp"); - lua_pushcfunction(L, moduleVec3Distance); - lua_setfield(L, -2, "distance"); - lua_pushcfunction(L, moduleVec3Negate); - lua_setfield(L, -2, "negate"); - lua_pop(L, 1); - - lua_register(L, "vec3", moduleVec3Create); + jsDefineMethod(s_vec3Proto, "dot", moduleVec3Dot); + jsDefineMethod(s_vec3Proto, "cross", moduleVec3Cross); + jsDefineMethod(s_vec3Proto, "length", moduleVec3Length); + jsDefineMethod(s_vec3Proto, "lengthSq", moduleVec3LengthSq); + jsDefineMethod(s_vec3Proto, "normalize", moduleVec3Normalize); + jsDefineMethod(s_vec3Proto, "negate", moduleVec3Negate); + jsDefineMethod(s_vec3Proto, "add", moduleVec3Add); + jsDefineMethod(s_vec3Proto, "sub", moduleVec3Sub); + jsDefineMethod(s_vec3Proto, "scale", moduleVec3Scale); + jsDefineMethod(s_vec3Proto, "lerp", moduleVec3Lerp); + jsDefineMethod(s_vec3Proto, "distance", moduleVec3Distance); + + jsRegister("vec3", moduleVec3Create); } diff --git a/src/dusk/script/module/math/modulevec4.h b/src/dusk/script/module/math/modulevec4.h index bb17af63..8e302727 100644 --- a/src/dusk/script/module/math/modulevec4.h +++ b/src/dusk/script/module/math/modulevec4.h @@ -7,445 +7,358 @@ #pragma once #include "script/module/modulebase.h" +#include "assert/assert.h" +#include "cglm/cglm.h" -/** - * Pushes a new vec4 userdata onto the Lua stack with the vec4_mt metatable. - * - * @param L Lua state. - * @param v Source vector to copy. - */ -static void moduleVec4Push(lua_State *L, vec4 v) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec4 *u = (vec4 *)lua_newuserdata(L, sizeof(vec4)); - glm_vec4_copy(v, *u); - luaL_getmetatable(L, "vec4_mt"); - lua_setmetatable(L, -2); +// Native info for heap-allocated vec4 (float[4]) +static void freeVec4Native(void *ptr, jerry_object_native_info_t *info) { + (void)info; + free(ptr); } +static const jerry_object_native_info_t VEC4_NATIVE_INFO = { + .free_cb = freeVec4Native, + .number_of_references = 0, + .offset_of_references = 0 +}; +static jerry_value_t s_vec4Proto = 0; -/** - * Reads a vec4 userdata from the given stack index into out. - * - * @param L Lua state. - * @param idx Stack index of the vec4 userdata. - * @param out Destination vector. - */ -static void moduleVec4Check(lua_State *L, int idx, vec4 out) { - assertNotNull(L, "Lua state cannot be NULL"); +// --------------------------------------------------------------------------- +// Property getters / setters (x/u0, y/v0, z/u1, w/v1) +// --------------------------------------------------------------------------- - vec4 *v = (vec4 *)luaL_checkudata(L, idx, "vec4_mt"); - glm_vec4_copy(*v, out); -} - -/** - * __index metamethod for vec4 userdata. - * Supports integer indices 1-4 and string keys x/u0, y/v0, z/u1, w/v1; - * falls through to the metatable for method lookups. - * - * @param L Lua state. Arg 1: vec4 userdata. Arg 2: integer or string key. - * @return 1. - */ -static int moduleVec4Index(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec4 *v = (vec4 *)luaL_checkudata(L, 1, "vec4_mt"); - assertNotNull(v, "invalid vec4 userdata"); - - const char *key = luaL_checkstring(L, 2); - assertStrLenMin(key, 1, "property key cannot be empty"); - - if(lua_isnumber(L, 2)) { - lua_Integer i = lua_tointeger(L, 2); - if(i >= 1 && i <= 4) { - lua_pushnumber(L, (lua_Number)(*v)[i - 1]); - return 1; - } - return 0; - } - - if(stringEquals(key, "x") || stringEquals(key, "u0")) { - lua_pushnumber(L, (lua_Number)(*v)[0]); - return 1; - } - - if(stringEquals(key, "y") || stringEquals(key, "v0")) { - lua_pushnumber(L, (lua_Number)(*v)[1]); - return 1; - } - - if(stringEquals(key, "z") || stringEquals(key, "u1")) { - lua_pushnumber(L, (lua_Number)(*v)[2]); - return 1; - } - - if(stringEquals(key, "w") || stringEquals(key, "v1")) { - lua_pushnumber(L, (lua_Number)(*v)[3]); - return 1; - } - - lua_getmetatable(L, 1); - lua_getfield(L, -1, key); - lua_remove(L, -2); - return 1; -} - -/** - * __newindex metamethod for vec4 userdata. - * Writes x/u0, y/v0, z/u1, w/v1. Errors on unknown keys. - * - * @param L Lua state. Arg 1: vec4 userdata. Arg 2: key string. Arg 3: number. - * @return 0. - */ -static int moduleVec4NewIndex(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec4 *v = (vec4 *)luaL_checkudata(L, 1, "vec4_mt"); - assertNotNull(v, "invalid vec4 userdata"); - - const char *key = luaL_checkstring(L, 2); - assertStrLenMin(key, 1, "property key cannot be empty"); - - if(stringEquals(key, "x") || stringEquals(key, "u0")) { - (*v)[0] = (float_t)luaL_checknumber(L, 3); - return 0; - } - - if(stringEquals(key, "y") || stringEquals(key, "v0")) { - (*v)[1] = (float_t)luaL_checknumber(L, 3); - return 0; - } - - if(stringEquals(key, "z") || stringEquals(key, "u1")) { - (*v)[2] = (float_t)luaL_checknumber(L, 3); - return 0; - } - - if(stringEquals(key, "w") || stringEquals(key, "v1")) { - (*v)[3] = (float_t)luaL_checknumber(L, 3); - return 0; - } - - luaL_error(L, "vec4: unknown property '%s'", key); - return 0; -} - -/** - * __add metamethod: returns a + b as a new vec4. - * - * @param L Lua state. Arg 1: vec4. Arg 2: vec4. - * @return 1 (new vec4). - */ -static int moduleVec4OpAdd(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec4 *a = (vec4 *)luaL_checkudata(L, 1, "vec4_mt"); - assertNotNull(a, "invalid vec4 userdata"); - - vec4 *b = (vec4 *)luaL_checkudata(L, 2, "vec4_mt"); - assertNotNull(b, "invalid vec4 userdata"); - - vec4 r; - glm_vec4_add(*a, *b, r); - moduleVec4Push(L, r); - return 1; -} - -/** - * __sub metamethod: returns a - b as a new vec4. - * - * @param L Lua state. Arg 1: vec4. Arg 2: vec4. - * @return 1 (new vec4). - */ -static int moduleVec4OpSub(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec4 *a = (vec4 *)luaL_checkudata(L, 1, "vec4_mt"); - assertNotNull(a, "invalid vec4 userdata"); - - vec4 *b = (vec4 *)luaL_checkudata(L, 2, "vec4_mt"); - assertNotNull(b, "invalid vec4 userdata"); - - vec4 r; - glm_vec4_sub(*a, *b, r); - moduleVec4Push(L, r); - return 1; -} - -/** - * __mul metamethod: returns v * scalar or scalar * v as a new vec4. - * - * @param L Lua state. Arg 1: vec4 or number. Arg 2: number or vec4. - * @return 1 (new vec4). - */ -static int moduleVec4OpMul(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec4 r; - if(lua_isnumber(L, 1)) { - float_t s = (float_t)lua_tonumber(L, 1); - vec4 *v = (vec4 *)luaL_checkudata(L, 2, "vec4_mt"); - assertNotNull(v, "invalid vec4 userdata"); - glm_vec4_scale(*v, s, r); - } else { - vec4 *v = (vec4 *)luaL_checkudata(L, 1, "vec4_mt"); - assertNotNull(v, "invalid vec4 userdata"); - float_t s = (float_t)luaL_checknumber(L, 2); - glm_vec4_scale(*v, s, r); - } - - moduleVec4Push(L, r); - return 1; -} - -/** - * __div metamethod: returns v / scalar as a new vec4. - * - * @param L Lua state. Arg 1: vec4. Arg 2: number. - * @return 1 (new vec4). - */ -static int moduleVec4OpDiv(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec4 *v = (vec4 *)luaL_checkudata(L, 1, "vec4_mt"); - assertNotNull(v, "invalid vec4 userdata"); - - float_t s = (float_t)luaL_checknumber(L, 2); - vec4 r; - glm_vec4_divs(*v, s, r); - moduleVec4Push(L, r); - return 1; -} - -/** - * __unm metamethod: returns -v as a new vec4. - * - * @param L Lua state. Arg 1: vec4. - * @return 1 (new vec4). - */ -static int moduleVec4OpUnm(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec4 *v = (vec4 *)luaL_checkudata(L, 1, "vec4_mt"); - assertNotNull(v, "invalid vec4 userdata"); - - vec4 r; - glm_vec4_negate_to(*v, r); - moduleVec4Push(L, r); - return 1; -} - -/** - * __eq metamethod: component-wise equality test. - * - * @param L Lua state. Arg 1: vec4. Arg 2: vec4. - * @return 1 (boolean). - */ -static int moduleVec4OpEq(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec4 *a = (vec4 *)luaL_checkudata(L, 1, "vec4_mt"); - assertNotNull(a, "invalid vec4 userdata"); - - vec4 *b = (vec4 *)luaL_checkudata(L, 2, "vec4_mt"); - assertNotNull(b, "invalid vec4 userdata"); - - lua_pushboolean(L, - (*a)[0] == (*b)[0] && (*a)[1] == (*b)[1] && - (*a)[2] == (*b)[2] && (*a)[3] == (*b)[3] +JS_FUNC(moduleVec4GetX) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO ); - return 1; + return v ? jerry_number(v[0]) : jerry_undefined(); } +JS_FUNC(moduleVec4SetX) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + if(v && args_count > 0) v[0] = (float_t)jerry_value_as_number(args_p[0]); + return jerry_undefined(); +} + +JS_FUNC(moduleVec4GetY) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + return v ? jerry_number(v[1]) : jerry_undefined(); +} +JS_FUNC(moduleVec4SetY) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + if(v && args_count > 0) v[1] = (float_t)jerry_value_as_number(args_p[0]); + return jerry_undefined(); +} + +JS_FUNC(moduleVec4GetZ) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + return v ? jerry_number(v[2]) : jerry_undefined(); +} +JS_FUNC(moduleVec4SetZ) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + if(v && args_count > 0) v[2] = (float_t)jerry_value_as_number(args_p[0]); + return jerry_undefined(); +} + +JS_FUNC(moduleVec4GetW) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + return v ? jerry_number(v[3]) : jerry_undefined(); +} +JS_FUNC(moduleVec4SetW) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + if(v && args_count > 0) v[3] = (float_t)jerry_value_as_number(args_p[0]); + return jerry_undefined(); +} + +// u0/v0/u1/v1 aliases share the same backing floats +JS_FUNC(moduleVec4GetU0) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + return v ? jerry_number(v[0]) : jerry_undefined(); +} +JS_FUNC(moduleVec4SetU0) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + if(v && args_count > 0) v[0] = (float_t)jerry_value_as_number(args_p[0]); + return jerry_undefined(); +} + +JS_FUNC(moduleVec4GetV0) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + return v ? jerry_number(v[1]) : jerry_undefined(); +} +JS_FUNC(moduleVec4SetV0) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + if(v && args_count > 0) v[1] = (float_t)jerry_value_as_number(args_p[0]); + return jerry_undefined(); +} + +JS_FUNC(moduleVec4GetU1) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + return v ? jerry_number(v[2]) : jerry_undefined(); +} +JS_FUNC(moduleVec4SetU1) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + if(v && args_count > 0) v[2] = (float_t)jerry_value_as_number(args_p[0]); + return jerry_undefined(); +} + +JS_FUNC(moduleVec4GetV1) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + return v ? jerry_number(v[3]) : jerry_undefined(); +} +JS_FUNC(moduleVec4SetV1) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + if(v && args_count > 0) v[3] = (float_t)jerry_value_as_number(args_p[0]); + return jerry_undefined(); +} + +// --------------------------------------------------------------------------- +// Methods +// --------------------------------------------------------------------------- + +JS_FUNC(moduleVec4Dot) { + JS_REQUIRE_ARGS(1); + float_t *a = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + if(!a) return JS_THROW("vec4.dot: invalid this"); + float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC4_NATIVE_INFO); + if(!b) return JS_THROW("vec4.dot: argument must be a vec4"); + return jerry_number(glm_vec4_dot(a, b)); +} + +JS_FUNC(moduleVec4Length) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + if(!v) return JS_THROW("vec4.length: invalid this"); + return jerry_number(glm_vec4_norm(v)); +} + +JS_FUNC(moduleVec4LengthSq) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + if(!v) return JS_THROW("vec4.lengthSq: invalid this"); + return jerry_number(glm_vec4_norm2(v)); +} + +JS_FUNC(moduleVec4Normalize) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + if(!v) return JS_THROW("vec4.normalize: invalid this"); + float_t *r = (float_t *)malloc(sizeof(vec4)); + glm_vec4_normalize_to(v, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC4_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_vec4Proto); + return obj; +} + +JS_FUNC(moduleVec4Negate) { + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + if(!v) return JS_THROW("vec4.negate: invalid this"); + float_t *r = (float_t *)malloc(sizeof(vec4)); + glm_vec4_negate_to(v, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC4_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_vec4Proto); + return obj; +} + +JS_FUNC(moduleVec4Add) { + JS_REQUIRE_ARGS(1); + float_t *a = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + if(!a) return JS_THROW("vec4.add: invalid this"); + float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC4_NATIVE_INFO); + if(!b) return JS_THROW("vec4.add: argument must be a vec4"); + float_t *r = (float_t *)malloc(sizeof(vec4)); + glm_vec4_add(a, b, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC4_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_vec4Proto); + return obj; +} + +JS_FUNC(moduleVec4Sub) { + JS_REQUIRE_ARGS(1); + float_t *a = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + if(!a) return JS_THROW("vec4.sub: invalid this"); + float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC4_NATIVE_INFO); + if(!b) return JS_THROW("vec4.sub: argument must be a vec4"); + float_t *r = (float_t *)malloc(sizeof(vec4)); + glm_vec4_sub(a, b, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC4_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_vec4Proto); + return obj; +} + +JS_FUNC(moduleVec4Scale) { + JS_REQUIRE_ARGS(1); + JS_REQUIRE_NUMBER(0); + float_t *v = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + if(!v) return JS_THROW("vec4.scale: invalid this"); + float_t s = (float_t)jerry_value_as_number(args_p[0]); + float_t *r = (float_t *)malloc(sizeof(vec4)); + glm_vec4_scale(v, s, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC4_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_vec4Proto); + return obj; +} + +JS_FUNC(moduleVec4Lerp) { + JS_REQUIRE_ARGS(2); + JS_REQUIRE_NUMBER(1); + float_t *a = (float_t *)jerry_object_get_native_ptr( + call_info_p->this_value, &VEC4_NATIVE_INFO + ); + if(!a) return JS_THROW("vec4.lerp: invalid this"); + float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC4_NATIVE_INFO); + if(!b) return JS_THROW("vec4.lerp: first argument must be a vec4"); + float_t t = (float_t)jerry_value_as_number(args_p[1]); + float_t *r = (float_t *)malloc(sizeof(vec4)); + glm_vec4_lerp(a, b, t, r); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC4_NATIVE_INFO, r); + jerry_object_set_proto(obj, s_vec4Proto); + return obj; +} + +// --------------------------------------------------------------------------- +// Constructor +// --------------------------------------------------------------------------- + +JS_FUNC(moduleVec4Create) { + JS_REQUIRE_ARGS(4); + JS_REQUIRE_NUMBER(0); + JS_REQUIRE_NUMBER(1); + JS_REQUIRE_NUMBER(2); + JS_REQUIRE_NUMBER(3); + float_t *v = (float_t *)malloc(sizeof(vec4)); + v[0] = (float_t)jerry_value_as_number(args_p[0]); + v[1] = (float_t)jerry_value_as_number(args_p[1]); + v[2] = (float_t)jerry_value_as_number(args_p[2]); + v[3] = (float_t)jerry_value_as_number(args_p[3]); + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC4_NATIVE_INFO, v); + jerry_object_set_proto(obj, s_vec4Proto); + return obj; +} + +// --------------------------------------------------------------------------- +// Helper: push a cglm vec4 as a new JS object +// --------------------------------------------------------------------------- /** - * __tostring metamethod: returns a human-readable representation. + * Wraps a copy of a cglm vec4 as a new JerryScript object. * - * @param L Lua state. Arg 1: vec4. - * @return 1 (string). + * @param v Source float[4] to copy. + * @return Owned jerry_value_t with native ptr set. */ -static int moduleVec4OpToString(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec4 *v = (vec4 *)luaL_checkudata(L, 1, "vec4_mt"); - assertNotNull(v, "invalid vec4 userdata"); - - char buf[96]; - snprintf(buf, sizeof(buf), "vec4(%.3f, %.3f, %.3f, %.3f)", (*v)[0], (*v)[1], (*v)[2], (*v)[3]); - lua_pushstring(L, buf); - return 1; +static inline jerry_value_t moduleVec4Push(const float_t *v) { + float_t *copy = (float_t *)malloc(sizeof(vec4)); + copy[0] = v[0]; + copy[1] = v[1]; + copy[2] = v[2]; + copy[3] = v[3]; + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &VEC4_NATIVE_INFO, copy); + jerry_object_set_proto(obj, s_vec4Proto); + return obj; } +// --------------------------------------------------------------------------- +// Helper: extract vec4 from a JS object +// --------------------------------------------------------------------------- + /** - * Returns the dot product of two vec4 values. + * Reads a JerryScript vec4 object into an existing float[4]. * - * @param L Lua state. Arg 1: vec4. Arg 2: vec4. - * @return 1 (number). + * @param val JS value to read from. + * @param out Destination float[4]. + * @return true if val carries a valid vec4 native ptr. */ -static int moduleVec4Dot(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec4 *a = (vec4 *)luaL_checkudata(L, 1, "vec4_mt"); - assertNotNull(a, "invalid vec4 userdata"); - - vec4 *b = (vec4 *)luaL_checkudata(L, 2, "vec4_mt"); - assertNotNull(b, "invalid vec4 userdata"); - - lua_pushnumber(L, (lua_Number)glm_vec4_dot(*a, *b)); - return 1; +static inline bool_t moduleVec4Check(jerry_value_t val, float_t *out) { + float_t *v = (float_t *)jerry_object_get_native_ptr(val, &VEC4_NATIVE_INFO); + if(!v) return false; + out[0] = v[0]; + out[1] = v[1]; + out[2] = v[2]; + out[3] = v[3]; + return true; } +// --------------------------------------------------------------------------- +// Module init +// --------------------------------------------------------------------------- + /** - * Returns the length (magnitude) of a vec4. - * - * @param L Lua state. Arg 1: vec4. - * @return 1 (number). + * Creates the vec4 prototype with x/y/z/w (and u0/v0/u1/v1 alias) + * getter-setter properties and all methods, then registers the global + * vec4() constructor. */ -static int moduleVec4Length(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +static void moduleVec4(void) { + s_vec4Proto = jerry_object(); - vec4 *v = (vec4 *)luaL_checkudata(L, 1, "vec4_mt"); - assertNotNull(v, "invalid vec4 userdata"); + // Primary component names + jsDefineProperty(s_vec4Proto, "x", moduleVec4GetX, moduleVec4SetX); + jsDefineProperty(s_vec4Proto, "y", moduleVec4GetY, moduleVec4SetY); + jsDefineProperty(s_vec4Proto, "z", moduleVec4GetZ, moduleVec4SetZ); + jsDefineProperty(s_vec4Proto, "w", moduleVec4GetW, moduleVec4SetW); - lua_pushnumber(L, (lua_Number)glm_vec4_norm(*v)); - return 1; -} - -/** - * Returns the squared length of a vec4. - * - * @param L Lua state. Arg 1: vec4. - * @return 1 (number). - */ -static int moduleVec4LengthSq(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec4 *v = (vec4 *)luaL_checkudata(L, 1, "vec4_mt"); - assertNotNull(v, "invalid vec4 userdata"); - - lua_pushnumber(L, (lua_Number)glm_vec4_norm2(*v)); - return 1; -} - -/** - * Returns a normalized copy of a vec4. - * - * @param L Lua state. Arg 1: vec4. - * @return 1 (new vec4). - */ -static int moduleVec4Normalize(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec4 *v = (vec4 *)luaL_checkudata(L, 1, "vec4_mt"); - assertNotNull(v, "invalid vec4 userdata"); - - vec4 r; - glm_vec4_normalize_to(*v, r); - moduleVec4Push(L, r); - return 1; -} - -/** - * Linearly interpolates between two vec4 values. - * - * @param L Lua state. Arg 1: vec4 a. Arg 2: vec4 b. Arg 3: number t. - * @return 1 (new vec4). - */ -static int moduleVec4Lerp(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec4 *a = (vec4 *)luaL_checkudata(L, 1, "vec4_mt"); - assertNotNull(a, "invalid vec4 userdata"); - - vec4 *b = (vec4 *)luaL_checkudata(L, 2, "vec4_mt"); - assertNotNull(b, "invalid vec4 userdata"); - - float_t t = (float_t)luaL_checknumber(L, 3); - vec4 r; - glm_vec4_lerp(*a, *b, t, r); - moduleVec4Push(L, r); - return 1; -} - -/** - * Returns a negated copy of a vec4. - * - * @param L Lua state. Arg 1: vec4. - * @return 1 (new vec4). - */ -static int moduleVec4Negate(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec4 *v = (vec4 *)luaL_checkudata(L, 1, "vec4_mt"); - assertNotNull(v, "invalid vec4 userdata"); - - vec4 r; - glm_vec4_negate_to(*v, r); - moduleVec4Push(L, r); - return 1; -} - -/** - * Constructor: creates a vec4 from four optional numbers (defaults to 0). - * - * @param L Lua state. Args 1-4 (optional): x, y, z, w. - * @return 1 (new vec4). - */ -static int moduleVec4Create(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - vec4 v = {0, 0, 0, 0}; - int top = lua_gettop(L); - if(top >= 1) v[0] = (float_t)luaL_checknumber(L, 1); - if(top >= 2) v[1] = (float_t)luaL_checknumber(L, 2); - if(top >= 3) v[2] = (float_t)luaL_checknumber(L, 3); - if(top >= 4) v[3] = (float_t)luaL_checknumber(L, 4); - moduleVec4Push(L, v); - return 1; -} - -/** - * Registers the vec4 metatable and vec4 constructor global. - * - * @param L Lua state. - */ -static void moduleVec4(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(!luaL_newmetatable(L, "vec4_mt")) { - lua_pop(L, 1); - return; - } - - lua_pushcfunction(L, moduleVec4Index); - lua_setfield(L, -2, "__index"); - lua_pushcfunction(L, moduleVec4NewIndex); - lua_setfield(L, -2, "__newindex"); - lua_pushcfunction(L, moduleVec4OpAdd); - lua_setfield(L, -2, "__add"); - lua_pushcfunction(L, moduleVec4OpSub); - lua_setfield(L, -2, "__sub"); - lua_pushcfunction(L, moduleVec4OpMul); - lua_setfield(L, -2, "__mul"); - lua_pushcfunction(L, moduleVec4OpDiv); - lua_setfield(L, -2, "__div"); - lua_pushcfunction(L, moduleVec4OpUnm); - lua_setfield(L, -2, "__unm"); - lua_pushcfunction(L, moduleVec4OpEq); - lua_setfield(L, -2, "__eq"); - lua_pushcfunction(L, moduleVec4OpToString); - lua_setfield(L, -2, "__tostring"); - lua_pushcfunction(L, moduleVec4Dot); - lua_setfield(L, -2, "dot"); - lua_pushcfunction(L, moduleVec4Length); - lua_setfield(L, -2, "length"); - lua_pushcfunction(L, moduleVec4LengthSq); - lua_setfield(L, -2, "lengthSq"); - lua_pushcfunction(L, moduleVec4Normalize); - lua_setfield(L, -2, "normalize"); - lua_pushcfunction(L, moduleVec4Lerp); - lua_setfield(L, -2, "lerp"); - lua_pushcfunction(L, moduleVec4Negate); - lua_setfield(L, -2, "negate"); - lua_pop(L, 1); - - lua_register(L, "vec4", moduleVec4Create); + // UV alias names (same backing components) + jsDefineProperty(s_vec4Proto, "u0", moduleVec4GetU0, moduleVec4SetU0); + jsDefineProperty(s_vec4Proto, "v0", moduleVec4GetV0, moduleVec4SetV0); + jsDefineProperty(s_vec4Proto, "u1", moduleVec4GetU1, moduleVec4SetU1); + jsDefineProperty(s_vec4Proto, "v1", moduleVec4GetV1, moduleVec4SetV1); + + jsDefineMethod(s_vec4Proto, "dot", moduleVec4Dot); + jsDefineMethod(s_vec4Proto, "length", moduleVec4Length); + jsDefineMethod(s_vec4Proto, "lengthSq", moduleVec4LengthSq); + jsDefineMethod(s_vec4Proto, "normalize", moduleVec4Normalize); + jsDefineMethod(s_vec4Proto, "negate", moduleVec4Negate); + jsDefineMethod(s_vec4Proto, "add", moduleVec4Add); + jsDefineMethod(s_vec4Proto, "sub", moduleVec4Sub); + jsDefineMethod(s_vec4Proto, "scale", moduleVec4Scale); + jsDefineMethod(s_vec4Proto, "lerp", moduleVec4Lerp); + + jsRegister("vec4", moduleVec4Create); } diff --git a/src/dusk/script/module/module.h b/src/dusk/script/module/module.h index e2e5ae99..e65e7ad8 100644 --- a/src/dusk/script/module/module.h +++ b/src/dusk/script/module/module.h @@ -1,6 +1,6 @@ /** * Copyright (c) 2026 Dominic Masters - * + * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ @@ -24,24 +24,22 @@ #include "script/module/display/moduletileset.h" #include "script/module/scene/modulescene.h" -void moduleRegister(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - moduleScript(L); - moduleEntity(L); - moduleInput(L); - modulePlatform(L); - moduleLocale(L); - moduleTime(L); - moduleEvent(L); - moduleColor(L); - moduleSpriteBatch(L); - moduleMath(L); - moduleShader(L); - moduleUi(L); - moduleText(L); - moduleScreen(L); - moduleTexture(L); - moduleTileset(L); - moduleScene(L); -} \ No newline at end of file +static void moduleRegister(void) { + moduleScript(); + moduleEntity(); + moduleInput(); + modulePlatform(); + moduleLocale(); + moduleTime(); + moduleEvent(); + moduleColor(); + moduleSpriteBatch(); + moduleMath(); + moduleShader(); + moduleUi(); + moduleText(); + moduleScreen(); + moduleTexture(); + moduleTileset(); + moduleScene(); +} diff --git a/src/dusk/script/module/modulebase.h b/src/dusk/script/module/modulebase.h index d7183a64..d4d98d7e 100644 --- a/src/dusk/script/module/modulebase.h +++ b/src/dusk/script/module/modulebase.h @@ -1,6 +1,6 @@ /** * Copyright (c) 2026 Dominic Masters - * + * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ @@ -9,4 +9,257 @@ #include "script/scriptcontext.h" #include "assert/assert.h" #include "util/string.h" -#include "util/memory.h" \ No newline at end of file +#include "util/memory.h" +#include + +/** + * Standard JerryScript external function signature. + * Usage: JS_FUNC(myFunction) { ... } + */ +#define JS_FUNC(name) \ + static jerry_value_t name( \ + const jerry_call_info_t *call_info_p, \ + const jerry_value_t args_p[], \ + const jerry_length_t args_count) + +/** + * Return a type-error exception from a module function. + * Usage: return JS_THROW("message"); + */ +#define JS_THROW(msg) jerry_throw_sz(JERRY_ERROR_TYPE, (msg)) + +/** + * Assert minimum argument count; return type error if not met. + */ +#define JS_REQUIRE_ARGS(n) do { \ + if((jerry_length_t)(args_count) < (jerry_length_t)(n)) { \ + return JS_THROW("Not enough arguments"); \ + } \ +} while(0) + +/** + * Assert an argument is a number; return type error if not. + */ +#define JS_REQUIRE_NUMBER(i) do { \ + if(!jerry_value_is_number(args_p[(i)])) { \ + return JS_THROW("Expected number argument"); \ + } \ +} while(0) + +/** + * Assert an argument is a string; return type error if not. + */ +#define JS_REQUIRE_STRING(i) do { \ + if(!jerry_value_is_string(args_p[(i)])) { \ + return JS_THROW("Expected string argument"); \ + } \ +} while(0) + +/** + * Assert an argument is a function; return type error if not. + */ +#define JS_REQUIRE_FUNCTION(i) do { \ + if(!jerry_value_is_function(args_p[(i)])) { \ + return JS_THROW("Expected function argument"); \ + } \ +} while(0) + +/** + * Assert an argument is an object; return type error if not. + */ +#define JS_REQUIRE_OBJECT(i) do { \ + if(!jerry_value_is_object(args_p[(i)])) { \ + return JS_THROW("Expected object argument"); \ + } \ +} while(0) + +/* JS_PTR_NATIVE_INFO is declared in scriptcontext.h and defined in + scriptcontext.c so all TUs share a single address for native-ptr lookups. */ + +/** + * Register a global JS function. + * + * @param name Function name as seen in scripts. + * @param fn C handler function. + */ +static inline void jsRegister( + const char_t *name, + jerry_external_handler_t fn +) { + jerry_value_t global = jerry_current_realm(); + jerry_value_t key = jerry_string_sz(name); + jerry_value_t func = jerry_function_external(fn); + jerry_object_set(global, key, func); + jerry_value_free(func); + jerry_value_free(key); + jerry_value_free(global); +} + +/** + * Set a global numeric constant. + */ +static inline void jsSetNumber(const char_t *name, double value) { + jerry_value_t global = jerry_current_realm(); + jerry_value_t key = jerry_string_sz(name); + jerry_value_t val = jerry_number(value); + jerry_object_set(global, key, val); + jerry_value_free(val); + jerry_value_free(key); + jerry_value_free(global); +} + +/** + * Set a global integer constant. + */ +static inline void jsSetInt(const char_t *name, int32_t value) { + jsSetNumber(name, (double)value); +} + +/** + * Set a global string constant. + */ +static inline void jsSetString(const char_t *name, const char_t *value) { + jerry_value_t global = jerry_current_realm(); + jerry_value_t key = jerry_string_sz(name); + jerry_value_t val = jerry_string_sz(value); + jerry_object_set(global, key, val); + jerry_value_free(val); + jerry_value_free(key); + jerry_value_free(global); +} + +/** + * Set a global JS value. Caller retains ownership of the value and must free + * it independently. + */ +static inline void jsSetValue(const char_t *name, jerry_value_t value) { + jerry_value_t global = jerry_current_realm(); + jerry_value_t key = jerry_string_sz(name); + jerry_object_set(global, key, value); + jerry_value_free(key); + jerry_value_free(global); +} + +/** + * Wrap an engine-owned C pointer as a JS object (no GC free callback). + * Used for global singletons like INPUT_EVENT_PRESSED, SHADER_UNLIT, etc. + */ +static inline jerry_value_t jsWrapPointer(void *ptr) { + jerry_value_t obj = jerry_object(); + jerry_object_set_native_ptr(obj, &JS_PTR_NATIVE_INFO, ptr); + return obj; +} + +/** + * Unwrap a C pointer from a JS object created by jsWrapPointer. + * Returns NULL if the object does not carry a matching native pointer. + */ +static inline void *jsUnwrapPointer(jerry_value_t val) { + if(!jerry_value_is_object(val)) return NULL; + return jerry_object_get_native_ptr(val, &JS_PTR_NATIVE_INFO); +} + +/** + * Evaluate a JS source string in the global scope. + * Errors are silently discarded; use scriptContextExec for error-propagating + * execution. + */ +static inline void jsEvalStr(const char_t *script) { + jerry_value_t result = jerry_eval( + (const jerry_char_t *)script, + strlen(script), + JERRY_PARSE_NO_OPTS + ); + jerry_value_free(result); +} + +/** + * Copy a JerryScript string value into a C buffer (null-terminated). + * + * @param val Jerry string value. + * @param buf Output buffer. + * @param buflen Buffer capacity including the null terminator. + */ +static inline void jsToString( + jerry_value_t val, + char_t *buf, + jerry_size_t buflen +) { + jerry_size_t len = jerry_string_to_buffer( + val, JERRY_ENCODING_UTF8, (jerry_char_t *)buf, buflen - 1 + ); + buf[len] = '\0'; +} + +/** + * Define a named property on a JS object with getter and optional setter. + * Both getter and setter are external C functions. + * + * @param obj Target object (e.g. a prototype). + * @param name Property name. + * @param getter C getter handler. + * @param setter C setter handler, or NULL for read-only property. + */ +static inline void jsDefineProperty( + jerry_value_t obj, + const char_t *name, + jerry_external_handler_t getter, + jerry_external_handler_t setter +) { + jerry_property_descriptor_t desc; + memset(&desc, 0, sizeof(desc)); + desc.flags = (uint16_t)( + JERRY_PROP_IS_GET_DEFINED | + JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_ENUMERABLE | + JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE + ); + desc.getter = jerry_function_external(getter); + if(setter != NULL) { + desc.flags |= JERRY_PROP_IS_SET_DEFINED; + desc.setter = jerry_function_external(setter); + } + jerry_value_t key = jerry_string_sz(name); + jerry_value_t result = jerry_object_define_own_prop(obj, key, &desc); + jerry_value_free(result); + jerry_value_free(key); + jerry_value_free(desc.getter); + if(setter != NULL) jerry_value_free(desc.setter); +} + +/** + * Set a named method (C function) on a JS object. + * + * @param obj Target object (e.g. a prototype). + * @param name Method name. + * @param fn C handler function. + */ +static inline void jsDefineMethod( + jerry_value_t obj, + const char_t *name, + jerry_external_handler_t fn +) { + jerry_value_t key = jerry_string_sz(name); + jerry_value_t func = jerry_function_external(fn); + jerry_object_set(obj, key, func); + jerry_value_free(func); + jerry_value_free(key); +} + +/** + * Format an error message from a JerryScript exception value. + * Caller must ensure buf is large enough. + */ +static inline void jsExceptionMessage( + jerry_value_t exception, + char_t *buf, + size_t buflen +) { + jerry_value_t errVal = jerry_exception_value(exception, false); + jerry_value_t errStr = jerry_value_to_string(errVal); + jerry_size_t len = jerry_string_to_buffer( + errStr, JERRY_ENCODING_UTF8, (jerry_char_t *)buf, (jerry_size_t)(buflen - 1) + ); + buf[len] = '\0'; + jerry_value_free(errStr); + jerry_value_free(errVal); +} diff --git a/src/dusk/script/module/moduleplatform.h b/src/dusk/script/module/moduleplatform.h index 2920c20c..7735b778 100644 --- a/src/dusk/script/module/moduleplatform.h +++ b/src/dusk/script/module/moduleplatform.h @@ -1,27 +1,24 @@ /** * Copyright (c) 2025 Dominic Masters - * + * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #pragma once -#include "script/scriptcontext.h" -#include "assert/assert.h" +#include "script/module/modulebase.h" #include "script/module/moduleplatformplatform.h" #ifndef DUSK_TARGET_SYSTEM #error "DUSK_TARGET_SYSTEM must be defined" #endif -#define MODULE_PLATFORM_VALUE "PLATFORM = '" DUSK_TARGET_SYSTEM "'\n" +#define MODULE_PLATFORM_VALUE "var PLATFORM = '" DUSK_TARGET_SYSTEM "';\n" -static void modulePlatform(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - luaL_dostring(L, MODULE_PLATFORM_VALUE); +static void modulePlatform(void) { + jsEvalStr(MODULE_PLATFORM_VALUE); #ifdef modulePlatformPlatform - modulePlatformPlatform(L); + modulePlatformPlatform(); #endif } \ No newline at end of file diff --git a/src/dusk/script/module/scene/modulescene.h b/src/dusk/script/module/scene/modulescene.h index 18cc233e..a8b5c8d3 100644 --- a/src/dusk/script/module/scene/modulescene.h +++ b/src/dusk/script/module/scene/modulescene.h @@ -1,6 +1,6 @@ /** * Copyright (c) 2026 Dominic Masters - * + * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ @@ -9,118 +9,68 @@ #include "script/module/modulebase.h" #include "scene/scene.h" -/** - * __index metamethod for the Scene table. Handles dynamic read-only properties. - * - * @param L Lua state. Arg 1: table, Arg 2: key. - * @return 1. - */ -static int moduleSceneIndex(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +JS_FUNC(moduleSceneSet) { + JS_REQUIRE_ARGS(1); + JS_REQUIRE_STRING(0); - const char_t *key = lua_tostring(L, 2); - assertNotNull(key, "Scene property key cannot be NULL"); + char_t name[ASSET_FILE_PATH_MAX]; + jsToString(args_p[0], name, sizeof(name)); + if(name[0] == '\0') return JS_THROW("Scene.set: Scene name cannot be empty"); - // if(stringEquals(key, "current")) { - // if(SCENE.sceneActive) { - // lua_pushstring(L, SCENE.sceneCurrent); - // } else { - // lua_pushnil(L); - // } - // return 1; - // } - - lua_pushnil(L); - return 1; + sceneSet(name); + return jerry_undefined(); } -/** - * Attached Scene.set method to invoke internal C method. - * - * @param L Lua state. - * @return Number of return values on the Lua stack. - */ -static int moduleSceneSet(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +JS_FUNC(moduleSceneGetCurrent) { + if(SCENE.sceneCurrent[0] == '\0') return jerry_undefined(); + return jerry_string_sz(SCENE.sceneCurrent); +} - if(!lua_isstring(L, 1)) { - luaL_error(L, "Scene.set requires a string argument"); - return 0; +static void moduleSceneReset(void) { + if(SCENE.scriptRef != SCENE_SCRIPT_REF_NONE) { + jerry_value_free(SCENE.scriptRef); + SCENE.scriptRef = SCENE_SCRIPT_REF_NONE; } - sceneSet(lua_tostring(L, 1)); - return 0; + jerry_value_t obj = jerry_object(); + + jsDefineMethod(obj, "set", moduleSceneSet); + jsDefineProperty(obj, "current", moduleSceneGetCurrent, NULL); + + jsSetValue("Scene", obj); + jerry_value_free(obj); } -/** - * Resets the scene back to a clean slate, this is called before loading a new - * scene to ensure that no old state bleeds through. - */ -static void moduleSceneReset(lua_State *L) { - if(SCENE.scriptRef != LUA_NOREF) { - luaL_unref(L, LUA_REGISTRYINDEX, SCENE.scriptRef); - SCENE.scriptRef = LUA_NOREF; - } - - lua_newtable(L); - - // Scene.set - lua_pushcfunction(L, moduleSceneSet); - lua_setfield(L, -2, "set"); - - // Metatable for dynamic read-only properties (e.g. Scene.current) - lua_newtable(L); - lua_pushcfunction(L, moduleSceneIndex); - lua_setfield(L, -2, "__index"); - lua_setmetatable(L, -2); - - lua_setglobal(L, "Scene"); -} - -/** - * Invokes a method on the current scene. - * - * @param method Which method to call. - * @return Any error state that happened. - */ -static errorret_t moduleSceneCall(lua_State *L, const char_t *method) { - assertNotNull(L, "Lua state cannot be NULL"); +static errorret_t moduleSceneCall(const char_t *method) { assertStrLenMin(method, 1, "Method name cannot be empty"); - assertTrue( - SCENE.scriptRef != LUA_NOREF && SCENE.scriptRef != LUA_REFNIL, - "No active scene script to call method on" - ); - // Get the scene table - lua_rawgeti(L, LUA_REGISTRYINDEX, SCENE.scriptRef); - if(!lua_istable(L, -1)) { - lua_pop(L, 1); - errorThrow("Scene script ref %d is not a table", SCENE.scriptRef); + if(SCENE.scriptRef == SCENE_SCRIPT_REF_NONE) { + errorThrow("No active scene script to call method on"); } - // Get the method from the scene table - lua_getfield(L, -1, method); - if(!lua_isfunction(L, -1)) { - lua_pop(L, 2); - errorThrow("Scene method '%s' not found", method);// TODO: Needed? + jerry_value_t key = jerry_string_sz(method); + jerry_value_t fn = jerry_object_get(SCENE.scriptRef, key); + jerry_value_free(key); + + if(!jerry_value_is_function(fn)) { + jerry_value_free(fn); + errorThrow("Scene method '%s' not found", method); } - // Push the scene table as the first argument (self) - lua_pushvalue(L, -2); + jerry_value_t result = jerry_call(fn, SCENE.scriptRef, NULL, 0); + jerry_value_free(fn); - // Call the method with 1 argument (the scene table) and 0 return values - if(lua_pcall(L, 1, 0, 0) != LUA_OK) { - const char_t *err = lua_tostring(L, -1); - lua_pop(L, 2);// Pops the error message and the scene table - errorThrow("Scene:%s failed: %s", method, err); + if(jerry_value_is_exception(result)) { + char_t errMsg[512]; + jsExceptionMessage(result, errMsg, sizeof(errMsg)); + jerry_value_free(result); + errorThrow("Scene:%s failed: %s", method, errMsg); } - lua_pop(L, 1);// Pops the scene table + jerry_value_free(result); errorOk(); } -static void moduleScene(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - moduleSceneReset(L); -} \ No newline at end of file +static void moduleScene(void) { + moduleSceneReset(); +} diff --git a/src/dusk/script/module/script/modulescript.h b/src/dusk/script/module/script/modulescript.h index 2207ae23..1c10df5f 100644 --- a/src/dusk/script/module/script/modulescript.h +++ b/src/dusk/script/module/script/modulescript.h @@ -9,74 +9,68 @@ #include "script/module/modulebase.h" #include "console/console.h" -static int moduleScriptPrint(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +JS_FUNC(moduleScriptPrint) { + char_t buf[512]; + char_t msg[4096]; + size_t msgLen = 0; - int n = lua_gettop(L); - luaL_Buffer b; - luaL_buffinit(L, &b); + for(jerry_length_t i = 0; i < args_count; ++i) { + jerry_value_t strVal = jerry_value_to_string(args_p[i]); + jsToString(strVal, buf, sizeof(buf)); + jerry_value_free(strVal); - for(int i = 1; i <= n; ++i) { - size_t len; - const char *s = luaL_tolstring(L, i, &len); - luaL_addlstring(&b, s, len); - lua_pop(L, 1); - if(i < n) luaL_addlstring(&b, "\t", 1); + size_t partLen = strlen(buf); + if(msgLen + partLen + 1 < sizeof(msg)) { + stringCopy(msg + msgLen, buf, sizeof(msg) - msgLen); + msgLen += partLen; + } + + if(i + 1 < args_count && msgLen + 1 < sizeof(msg)) { + msg[msgLen++] = '\t'; + msg[msgLen] = '\0'; + } } - luaL_pushresult(&b); - const char *msg = lua_tostring(L, -1); consolePrint("%s", msg); - return 0; + return jerry_undefined(); } -static int moduleScriptInclude(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(!lua_isstring(L, 1)) { - luaL_error(L, "Expected string filename"); - return 0; +JS_FUNC(moduleScriptInclude) { + if(args_count < 1 || !jerry_value_is_string(args_p[0])) { + return JS_THROW("Expected string filename"); } - scriptcontext_t* ctx = *(scriptcontext_t**)lua_getextraspace(L); - if(ctx == NULL) { - luaL_error(L, "Script context is NULL"); - return 0; - } + char_t filename[1024]; + jsToString(args_p[0], filename, sizeof(filename)); - const char_t *filename = luaL_checkstring(L, 1); - if(filename == NULL || filename[0] == '\0') { - luaL_error(L, "Filename cannot be NULL"); - return 0; + if(filename[0] == '\0') { + return JS_THROW("Filename cannot be empty"); } char_t buffer[1024]; - stringCopy(buffer, filename, 1024); + stringCopy(buffer, filename, sizeof(buffer)); size_t len = strlen(buffer); - if(len < 4 || stringCompare(&buffer[len - 4], ".lua") != 0) { - if(len + 4 >= 1024) { - luaL_error(L, "Filename too long to append .lua"); - return 0; + if(len < 3 || stringCompare(&buffer[len - 3], ".js") != 0) { + if(len + 3 >= sizeof(buffer)) { + return JS_THROW("Filename too long to append .js"); } - stringCopy(&buffer[len], ".lua", 5); + stringCopy(&buffer[len], ".js", 4); } - int32_t stackBase = lua_gettop(L); - - errorret_t err = scriptContextExecFile(ctx, buffer); + jerry_value_t result = 0; + errorret_t err = scriptContextExecFile(scriptContextCurrent, buffer, &result); if(err.code != ERROR_OK) { - luaL_error(L, "Failed to include script file: %s", buffer); + if(result != 0) jerry_value_free(result); errorCatch(errorPrint(err)); - return 0; + return JS_THROW("Failed to include script file"); } - return lua_gettop(L) - stackBase; + if(result == 0) return jerry_undefined(); + return result; } -static void moduleScript(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - lua_register(L, "print", moduleScriptPrint); - lua_register(L, "include", moduleScriptInclude); +static void moduleScript(void) { + jsRegister("print", moduleScriptPrint); + jsRegister("include", moduleScriptInclude); } diff --git a/src/dusk/script/module/time/moduletime.h b/src/dusk/script/module/time/moduletime.h index 69b07190..7d47c133 100644 --- a/src/dusk/script/module/time/moduletime.h +++ b/src/dusk/script/module/time/moduletime.h @@ -9,33 +9,18 @@ #include "script/module/modulebase.h" #include "time/time.h" -static int moduleTimeIndex(lua_State *L) { - const char_t *key = lua_tostring(L, 2); - assertStrLenMin(key, 1, "Key cannot be empty."); - - if(stringCompare(key, "delta") == 0) { - lua_pushnumber(L, TIME.delta); - return 1; - } else if(stringCompare(key, "time") == 0) { - lua_pushnumber(L, TIME.time); - return 1; - } - - lua_pushnil(L); - return 1; +JS_FUNC(moduleTimeGetDelta) { + return jerry_number(TIME.delta); } -static void moduleTime(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(luaL_newmetatable(L, "time_mt")) { - lua_pushcfunction(L, moduleTimeIndex); - lua_setfield(L, -2, "__index"); - } - lua_pop(L, 1); - - dusktime_t **ud = (dusktime_t**)lua_newuserdata(L, sizeof(dusktime_t*)); - *ud = &TIME; - luaL_setmetatable(L, "time_mt"); - lua_setglobal(L, "TIME"); +JS_FUNC(moduleTimeGetTime) { + return jerry_number(TIME.time); +} + +static void moduleTime(void) { + jerry_value_t obj = jerry_object(); + jsDefineProperty(obj, "delta", moduleTimeGetDelta, NULL); + jsDefineProperty(obj, "time", moduleTimeGetTime, NULL); + jsSetValue("TIME", obj); + jerry_value_free(obj); } diff --git a/src/dusk/script/module/ui/moduleui.h b/src/dusk/script/module/ui/moduleui.h index 78dc99e8..91595a73 100644 --- a/src/dusk/script/module/ui/moduleui.h +++ b/src/dusk/script/module/ui/moduleui.h @@ -8,6 +8,5 @@ #pragma once #include "script/module/modulebase.h" -static void moduleUi(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +static void moduleUi(void) { } diff --git a/src/dusk/script/scriptcontext.c b/src/dusk/script/scriptcontext.c index 8e971e40..1ac561e7 100644 --- a/src/dusk/script/scriptcontext.c +++ b/src/dusk/script/scriptcontext.c @@ -1,6 +1,6 @@ /** * Copyright (c) 2025 Dominic Masters - * + * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ @@ -17,27 +17,26 @@ #include "script/scriptgame.h" #endif +scriptcontext_t *scriptContextCurrent = NULL; + +const jerry_object_native_info_t JS_PTR_NATIVE_INFO = { + .free_cb = NULL, + .number_of_references = 0, + .offset_of_references = 0 +}; + errorret_t scriptContextInit(scriptcontext_t *context) { assertNotNull(context, "Script context cannot be NULL"); memoryZero(context, sizeof(scriptcontext_t)); - // Create a new Lua state for this context. - context->luaState = luaL_newstate(); - if(context->luaState == NULL) { - errorThrow("Failed to init Lua state"); - } - luaL_openlibs(context->luaState); + jerry_init(JERRY_INIT_EMPTY); + scriptContextCurrent = context; - // Store context in Lua extraspace - *(scriptcontext_t**)lua_getextraspace(context->luaState) = context; + moduleRegister(); - // Register built-in script modules. - moduleRegister(context->luaState); - - // Fire any game script init function if defined. #ifdef SCRIPT_GAME_INIT - SCRIPT_GAME_INIT(L); + SCRIPT_GAME_INIT(); #endif errorOk(); @@ -47,33 +46,49 @@ errorret_t scriptContextExec(scriptcontext_t *context, const char_t *script) { assertNotNull(context, "Script context cannot be NULL"); assertNotNull(script, "Script cannot be NULL"); - if(luaL_dostring(context->luaState, script) != LUA_OK) { - const char_t *strErr = lua_tostring(context->luaState, -1); - lua_pop(context->luaState, 1); - errorThrow("Failed to execute Lua: %s", strErr); + jerry_value_t result = jerry_eval( + (const jerry_char_t *)script, + strlen(script), + JERRY_PARSE_NO_OPTS + ); + + if(jerry_value_is_exception(result)) { + jerry_value_t errVal = jerry_exception_value(result, false); + jerry_value_t errStr = jerry_value_to_string(errVal); + char_t buf[256]; + jerry_size_t len = jerry_string_to_buffer( + errStr, JERRY_ENCODING_UTF8, (jerry_char_t *)buf, sizeof(buf) - 1 + ); + buf[len] = '\0'; + jerry_value_free(errStr); + jerry_value_free(errVal); + jerry_value_free(result); + errorThrow("Failed to execute script: %s", buf); } + jerry_value_free(result); errorOk(); } -errorret_t scriptContextExecFile(scriptcontext_t *ctx, const char_t *fname) { +errorret_t scriptContextExecFile( + scriptcontext_t *ctx, + const char_t *fname, + jerry_value_t *resultOut +) { assertNotNull(ctx, "Script context cannot be NULL"); assertNotNull(fname, "Filename cannot be NULL"); - return assetScriptLoad(fname, ctx); + return assetScriptLoad(fname, ctx, resultOut); } void scriptContextDispose(scriptcontext_t *context) { assertNotNull(context, "Script context cannot be NULL"); - assertNotNull(context->luaState, "Lua state is not initialized"); - + for(uint8_t i = 0; i < SCRIPT_CONTEXT_MAX_EVENT_SUBSCRIPTIONS; i++) { event_t *event = context->subscribedEvents[i]; if(event == NULL) continue; eventUnsubscribeScriptContext(event, context); } - if(context->luaState != NULL) { - lua_close(context->luaState); - context->luaState = NULL; - } -} \ No newline at end of file + jerry_cleanup(); + scriptContextCurrent = NULL; +} diff --git a/src/dusk/script/scriptcontext.h b/src/dusk/script/scriptcontext.h index 7469f2aa..a508782d 100644 --- a/src/dusk/script/scriptcontext.h +++ b/src/dusk/script/scriptcontext.h @@ -1,6 +1,6 @@ /** * Copyright (c) 2025 Dominic Masters - * + * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ @@ -8,48 +8,62 @@ #pragma once #include "error/error.h" #include "scriptvalue.h" -#include -#include -#include +#include typedef struct event_s event_t; #define SCRIPT_CONTEXT_MAX_EVENT_SUBSCRIPTIONS 64 typedef struct scriptcontext_s { - lua_State *luaState; event_t* subscribedEvents[SCRIPT_CONTEXT_MAX_EVENT_SUBSCRIPTIONS]; } scriptcontext_t; +/** Points to the currently active script context. Set by scriptContextInit. */ +extern scriptcontext_t *scriptContextCurrent; + +/** + * Singleton native-info tag for engine-owned C pointers wrapped in JS objects. + * A single global instance ensures jerry_object_get_native_ptr() matches across + * all compilation units (including event.c and module headers). + */ +extern const jerry_object_native_info_t JS_PTR_NATIVE_INFO; + /** * Initialize a script context. - * + * * @param context The script context to initialize. * @return The error return value. */ errorret_t scriptContextInit(scriptcontext_t *context); /** - * Execute a script within a script context. - * + * Execute a script string within a script context. + * * @param context The script context to use. - * @param script The script to execute. + * @param script The JS source to execute. * @return The error return value. */ errorret_t scriptContextExec(scriptcontext_t *context, const char_t *script); /** * Execute a script from a file within a script context. - * - * @param ctx The script context to use. - * @param fname The filename of the script to execute. + * + * @param ctx The script context to use. + * @param fname The filename of the script to execute. + * @param result Optional out-parameter for the script's return value. + * Caller must call jerry_value_free() on it when done. + * Pass NULL to discard the return value. * @return The error return value. */ -errorret_t scriptContextExecFile(scriptcontext_t *ctx, const char_t *fname); +errorret_t scriptContextExecFile( + scriptcontext_t *ctx, + const char_t *fname, + jerry_value_t *result +); /** * Dispose of a script context. - * + * * @param context The script context to dispose of. */ -void scriptContextDispose(scriptcontext_t *context); \ No newline at end of file +void scriptContextDispose(scriptcontext_t *context); diff --git a/src/duskdolphin/script/module/moduleplatformdolphin.h b/src/duskdolphin/script/module/moduleplatformdolphin.h index 2a18b7e9..a60c55c2 100644 --- a/src/duskdolphin/script/module/moduleplatformdolphin.h +++ b/src/duskdolphin/script/module/moduleplatformdolphin.h @@ -1,13 +1,13 @@ /** * Copyright (c) 2026 Dominic Masters - * + * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #pragma once -#include "script/scriptcontext.h" +#include "script/module/modulebase.h" -static void modulePlatformDolphin(lua_State *L) { - luaL_dostring(L, "DOLPHIN = true\n"); -} \ No newline at end of file +static void modulePlatformDolphin(void) { + jsEvalStr("var DOLPHIN = true;\n"); +} diff --git a/src/dusklinux/script/module/moduleplatformlinux.h b/src/dusklinux/script/module/moduleplatformlinux.h index eb476dac..7dea1770 100644 --- a/src/dusklinux/script/module/moduleplatformlinux.h +++ b/src/dusklinux/script/module/moduleplatformlinux.h @@ -1,13 +1,13 @@ /** * Copyright (c) 2026 Dominic Masters - * + * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #pragma once -#include "script/scriptcontext.h" +#include "script/module/modulebase.h" -static void modulePlatformLinux(lua_State *L) { - luaL_dostring(L, "LINUX = true\n"); -} \ No newline at end of file +static void modulePlatformLinux(void) { + jsEvalStr("var LINUX = true;\n"); +} diff --git a/src/duskpsp/script/module/moduleplatformpsp.h b/src/duskpsp/script/module/moduleplatformpsp.h index bd12bb56..5ff1ed1e 100644 --- a/src/duskpsp/script/module/moduleplatformpsp.h +++ b/src/duskpsp/script/module/moduleplatformpsp.h @@ -1,13 +1,13 @@ /** * Copyright (c) 2026 Dominic Masters - * + * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #pragma once -#include "script/scriptcontext.h" +#include "script/module/modulebase.h" -void modulePlatformPSP(lua_State *L) { - luaL_dostring(L, "PSP = true\n"); -} \ No newline at end of file +static void modulePlatformPSP(void) { + jsEvalStr("var PSP = true;\n"); +} diff --git a/src/duskrpg/script/module/item/moduleitem.h b/src/duskrpg/script/module/item/moduleitem.h index f7cf67db..69992ff0 100644 --- a/src/duskrpg/script/module/item/moduleitem.h +++ b/src/duskrpg/script/module/item/moduleitem.h @@ -6,236 +6,195 @@ */ #pragma once -#include "script/scriptcontext.h" +#include "script/module/modulebase.h" #include "item/inventory.h" #include "item/backpack.h" #include "assert/assert.h" -static int moduleInventoryItemExists(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(!lua_islightuserdata(L, 1)) { - luaL_error(L, "inventoryItemExists: Expected inventory pointer as first argument"); - return 0; +JS_FUNC(moduleInventoryItemExists) { + if(!jerry_value_is_object(args_p[0])) { + return JS_THROW("inventoryItemExists: Expected inventory pointer as first argument"); } - if(!lua_isnumber(L, 2)) { - luaL_error(L, "inventoryItemExists: Expected item ID as second argument"); - return 0; + if(!jerry_value_is_number(args_p[1])) { + return JS_THROW("inventoryItemExists: Expected item ID as second argument"); } - inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1); - itemid_t item = (itemid_t)lua_tonumber(L, 2); + inventory_t *inventory = (inventory_t *)jsUnwrapPointer(args_p[0]); + itemid_t item = (itemid_t)jerry_value_as_number(args_p[1]); assertNotNull(inventory, "Inventory pointer cannot be NULL."); if(item == ITEM_ID_NULL) { - luaL_error(L, "inventoryItemExists: Item ID cannot be ITEM_ID_NULL"); - return 0; + return JS_THROW("inventoryItemExists: Item ID cannot be ITEM_ID_NULL"); } bool_t hasItem = inventoryItemExists(inventory, item); - lua_pushboolean(L, hasItem); - return 1; + return jerry_boolean(hasItem); } -static int moduleInventorySet(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(!lua_islightuserdata(L, 1)) { - luaL_error(L, "inventorySet: Expected inventory pointer as first argument"); - return 0; +JS_FUNC(moduleInventorySet) { + if(!jerry_value_is_object(args_p[0])) { + return JS_THROW("inventorySet: Expected inventory pointer as first argument"); } - if(!lua_isnumber(L, 2)) { - luaL_error(L, "inventorySet: Expected item ID as second argument"); - return 0; + if(!jerry_value_is_number(args_p[1])) { + return JS_THROW("inventorySet: Expected item ID as second argument"); } - if(!lua_isnumber(L, 3)) { - luaL_error(L, "inventorySet: Expected quantity as third argument"); - return 0; + if(!jerry_value_is_number(args_p[2])) { + return JS_THROW("inventorySet: Expected quantity as third argument"); } - inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1); - itemid_t item = (itemid_t)lua_tonumber(L, 2); - uint8_t quantity = (uint8_t)lua_tonumber(L, 3); + inventory_t *inventory = (inventory_t *)jsUnwrapPointer(args_p[0]); + itemid_t item = (itemid_t)jerry_value_as_number(args_p[1]); + uint8_t quantity = (uint8_t)jerry_value_as_number(args_p[2]); assertNotNull(inventory, "Inventory pointer cannot be NULL."); inventorySet(inventory, item, quantity); - return 0; + return jerry_undefined(); } -static int moduleInventoryAdd(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(!lua_islightuserdata(L, 1)) { - luaL_error(L, "inventoryAdd: Expected inventory pointer as first argument"); - return 0; +JS_FUNC(moduleInventoryAdd) { + if(!jerry_value_is_object(args_p[0])) { + return JS_THROW("inventoryAdd: Expected inventory pointer as first argument"); } - if(!lua_isnumber(L, 2)) { - luaL_error(L, "inventoryAdd: Expected item ID as second argument"); - return 0; + if(!jerry_value_is_number(args_p[1])) { + return JS_THROW("inventoryAdd: Expected item ID as second argument"); } - if(!lua_isnumber(L, 3)) { - luaL_error(L, "inventoryAdd: Expected quantity as third argument"); - return 0; + if(!jerry_value_is_number(args_p[2])) { + return JS_THROW("inventoryAdd: Expected quantity as third argument"); } - inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1); - itemid_t item = (itemid_t)lua_tonumber(L, 2); - uint8_t quantity = (uint8_t)lua_tonumber(L, 3); + inventory_t *inventory = (inventory_t *)jsUnwrapPointer(args_p[0]); + itemid_t item = (itemid_t)jerry_value_as_number(args_p[1]); + uint8_t quantity = (uint8_t)jerry_value_as_number(args_p[2]); assertNotNull(inventory, "Inventory pointer cannot be NULL."); inventoryAdd(inventory, item, quantity); - return 0; + return jerry_undefined(); } -static int moduleInventoryRemove(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(!lua_islightuserdata(L, 1)) { - luaL_error(L, "inventoryRemove: Expected inventory pointer as first argument"); - return 0; +JS_FUNC(moduleInventoryRemove) { + if(!jerry_value_is_object(args_p[0])) { + return JS_THROW("inventoryRemove: Expected inventory pointer as first argument"); } - if(!lua_isnumber(L, 2)) { - luaL_error(L, "inventoryRemove: Expected item ID as second argument"); - return 0; + if(!jerry_value_is_number(args_p[1])) { + return JS_THROW("inventoryRemove: Expected item ID as second argument"); } - inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1); - itemid_t item = (itemid_t)lua_tonumber(L, 2); + inventory_t *inventory = (inventory_t *)jsUnwrapPointer(args_p[0]); + itemid_t item = (itemid_t)jerry_value_as_number(args_p[1]); assertNotNull(inventory, "Inventory pointer cannot be NULL."); - if(lua_gettop(L) >= 3) { - if(!lua_isnumber(L, 3)) { - luaL_error(L, "inventoryRemove: Expected quantity as third argument"); - return 0; + if(args_count >= 3) { + if(!jerry_value_is_number(args_p[2])) { + return JS_THROW("inventoryRemove: Expected quantity as third argument"); } - uint8_t amount = (uint8_t)lua_tonumber(L, 3); + uint8_t amount = (uint8_t)jerry_value_as_number(args_p[2]); uint8_t currentQuantity = inventoryGetCount(inventory, item); if(amount >= currentQuantity) { inventoryRemove(inventory, item); - return 0; + return jerry_undefined(); } inventorySet(inventory, item, currentQuantity - amount); - return 0; + return jerry_undefined(); } inventoryRemove(inventory, item); - return 0; + return jerry_undefined(); } -static int moduleInventoryGetCount(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(!lua_islightuserdata(L, 1)) { - luaL_error(L, "inventoryGetCount: Expected inventory pointer as first argument"); - return 0; +JS_FUNC(moduleInventoryGetCount) { + if(!jerry_value_is_object(args_p[0])) { + return JS_THROW("inventoryGetCount: Expected inventory pointer as first argument"); } - if(!lua_isnumber(L, 2)) { - luaL_error(L, "inventoryGetCount: Expected item ID as second argument"); - return 0; + if(!jerry_value_is_number(args_p[1])) { + return JS_THROW("inventoryGetCount: Expected item ID as second argument"); } - inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1); - itemid_t item = (itemid_t)lua_tonumber(L, 2); + inventory_t *inventory = (inventory_t *)jsUnwrapPointer(args_p[0]); + itemid_t item = (itemid_t)jerry_value_as_number(args_p[1]); assertNotNull(inventory, "Inventory pointer cannot be NULL."); uint8_t count = inventoryGetCount(inventory, item); - lua_pushnumber(L, count); - return 1; + return jerry_number(count); } -static int moduleInventoryIsFull(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(!lua_islightuserdata(L, 1)) { - luaL_error(L, "inventoryIsFull: Expected inventory pointer as first argument"); - return 0; +JS_FUNC(moduleInventoryIsFull) { + if(!jerry_value_is_object(args_p[0])) { + return JS_THROW("inventoryIsFull: Expected inventory pointer as first argument"); } - inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1); + inventory_t *inventory = (inventory_t *)jsUnwrapPointer(args_p[0]); assertNotNull(inventory, "Inventory pointer cannot be NULL."); bool_t isFull = inventoryIsFull(inventory); - lua_pushboolean(L, isFull); - return 1; + return jerry_boolean(isFull); } -static int moduleInventoryItemFull(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(!lua_islightuserdata(L, 1)) { - luaL_error(L, "inventoryItemFull: Expected inventory pointer as first argument"); - return 0; +JS_FUNC(moduleInventoryItemFull) { + if(!jerry_value_is_object(args_p[0])) { + return JS_THROW("inventoryItemFull: Expected inventory pointer as first argument"); } - if(!lua_isnumber(L, 2)) { - luaL_error(L, "inventoryItemFull: Expected item ID as second argument"); - return 0; + if(!jerry_value_is_number(args_p[1])) { + return JS_THROW("inventoryItemFull: Expected item ID as second argument"); } - inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1); - itemid_t item = (itemid_t)lua_tonumber(L, 2); + inventory_t *inventory = (inventory_t *)jsUnwrapPointer(args_p[0]); + itemid_t item = (itemid_t)jerry_value_as_number(args_p[1]); assertNotNull(inventory, "Inventory pointer cannot be NULL."); bool_t isFull = inventoryItemFull(inventory, item); - lua_pushboolean(L, isFull); - return 1; + return jerry_boolean(isFull); } -static int moduleInventorySort(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(!lua_islightuserdata(L, 1)) { - luaL_error(L, "inventorySort: Expected inventory pointer as first argument"); - return 0; +JS_FUNC(moduleInventorySort) { + if(!jerry_value_is_object(args_p[0])) { + return JS_THROW("inventorySort: Expected inventory pointer as first argument"); } - if(!lua_isnumber(L, 2)) { - luaL_error(L, "inventorySort: Expected sort type as second argument"); - return 0; + if(!jerry_value_is_number(args_p[1])) { + return JS_THROW("inventorySort: Expected sort type as second argument"); } bool_t reverse = false; - if(lua_gettop(L) >= 3) { - if(!lua_isboolean(L, 3)) { - luaL_error(L, "inventorySort: Expected reverse flag as third argument"); - return 0; + if(args_count >= 3) { + if(!jerry_value_is_boolean(args_p[2])) { + return JS_THROW("inventorySort: Expected reverse flag as third argument"); } - reverse = (bool_t)lua_toboolean(L, 3); + reverse = (bool_t)jerry_value_is_true(args_p[2]); } - inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1); - inventorysort_t sortBy = (inventorysort_t)lua_tonumber(L, 2); + inventory_t *inventory = (inventory_t *)jsUnwrapPointer(args_p[0]); + inventorysort_t sortBy = (inventorysort_t)jerry_value_as_number(args_p[1]); assertNotNull(inventory, "Inventory pointer cannot be NULL."); inventorySort(inventory, sortBy, reverse); - return 0; + return jerry_undefined(); } -static void moduleItem(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); +static void moduleItem(void) { + jsEvalStr(ITEM_SCRIPT); - luaL_dostring(L, ITEM_SCRIPT); + jerry_value_t backpack = jsWrapPointer(&BACKPACK); + jsSetValue("BACKPACK", backpack); + jerry_value_free(backpack); - lua_pushlightuserdata(L, &BACKPACK); - lua_setglobal(L, "BACKPACK"); - - lua_register(L, "inventoryItemExists", moduleInventoryItemExists); - lua_register(L, "inventoryAdd", moduleInventoryAdd); - lua_register(L, "inventorySet", moduleInventorySet); - lua_register(L, "inventoryRemove", moduleInventoryRemove); - lua_register(L, "inventoryGetCount", moduleInventoryGetCount); - lua_register(L, "inventoryIsFull", moduleInventoryIsFull); - lua_register(L, "inventoryItemFull", moduleInventoryItemFull); - lua_register(L, "inventorySort", moduleInventorySort); + jsRegister("inventoryItemExists", moduleInventoryItemExists); + jsRegister("inventoryAdd", moduleInventoryAdd); + jsRegister("inventorySet", moduleInventorySet); + jsRegister("inventoryRemove", moduleInventoryRemove); + jsRegister("inventoryGetCount", moduleInventoryGetCount); + jsRegister("inventoryIsFull", moduleInventoryIsFull); + jsRegister("inventoryItemFull", moduleInventoryItemFull); + jsRegister("inventorySort", moduleInventorySort); } diff --git a/src/duskrpg/script/module/story/modulestoryflag.h b/src/duskrpg/script/module/story/modulestoryflag.h index 9218a2b2..3dbefcac 100644 --- a/src/duskrpg/script/module/story/modulestoryflag.h +++ b/src/duskrpg/script/module/story/modulestoryflag.h @@ -6,96 +6,58 @@ */ #pragma once -#include "script/scriptcontext.h" +#include "script/module/modulebase.h" #include "assert/assert.h" #include "story/storyflag.h" -static int moduleStoryFlagGet(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(!lua_isnumber(L, 1)) { - luaL_error(L, "Expected flag ID."); - return 0; - } - - storyflag_t flag = (storyflag_t)lua_tonumber(L, 1); +JS_FUNC(moduleStoryFlagGet) { + JS_REQUIRE_ARGS(1); + JS_REQUIRE_NUMBER(0); + storyflag_t flag = (storyflag_t)jerry_value_as_number(args_p[0]); if(flag <= STORY_FLAG_NULL || flag >= STORY_FLAG_COUNT) { - luaL_error(L, "Invalid flag ID %d", flag); - return 0; + return JS_THROW("storyFlagGet: invalid flag ID"); } - - storyflagvalue_t value = storyFlagGet(flag); - lua_pushnumber(L, value); - return 1; + return jerry_number((double)storyFlagGet(flag)); } -static int moduleStoryFlagSet(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(!lua_isnumber(L, 1)) { - luaL_error(L, "Expected flag ID."); - return 0; - } - - if(!lua_isnumber(L, 2)) { - luaL_error(L, "Expected flag value."); - return 0; - } - - storyflag_t flag = (storyflag_t)lua_tonumber(L, 1); +JS_FUNC(moduleStoryFlagSet) { + JS_REQUIRE_ARGS(2); + JS_REQUIRE_NUMBER(0); + JS_REQUIRE_NUMBER(1); + storyflag_t flag = (storyflag_t)jerry_value_as_number(args_p[0]); if(flag <= STORY_FLAG_NULL || flag >= STORY_FLAG_COUNT) { - luaL_error(L, "Invalid flag ID %d", flag); - return 0; + return JS_THROW("storyFlagSet: invalid flag ID"); } - - storyflagvalue_t value = (storyflagvalue_t)lua_tonumber(L, 2); + storyflagvalue_t value = (storyflagvalue_t)jerry_value_as_number(args_p[1]); storyFlagSet(flag, value); - return 0; + return jerry_undefined(); } -static int moduleStoryFlagIncrement(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(!lua_isnumber(L, 1)) { - luaL_error(L, "Expected flag ID."); - return 0; - } - - storyflag_t flag = (storyflag_t)lua_tonumber(L, 1); +JS_FUNC(moduleStoryFlagIncrement) { + JS_REQUIRE_ARGS(1); + JS_REQUIRE_NUMBER(0); + storyflag_t flag = (storyflag_t)jerry_value_as_number(args_p[0]); if(flag <= STORY_FLAG_NULL || flag >= STORY_FLAG_COUNT) { - luaL_error(L, "Invalid flag ID %d", flag); - return 0; + return JS_THROW("storyFlagIncrement: invalid flag ID"); } - - storyflagvalue_t value = storyFlagGet(flag); - storyFlagSet(flag, value + 1); - return 0; + storyFlagSet(flag, storyFlagGet(flag) + 1); + return jerry_undefined(); } -static int moduleStoryFlagDecrement(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - if(!lua_isnumber(L, 1)) { - luaL_error(L, "Expected flag ID."); - return 0; - } - - storyflag_t flag = (storyflag_t)lua_tonumber(L, 1); +JS_FUNC(moduleStoryFlagDecrement) { + JS_REQUIRE_ARGS(1); + JS_REQUIRE_NUMBER(0); + storyflag_t flag = (storyflag_t)jerry_value_as_number(args_p[0]); if(flag <= STORY_FLAG_NULL || flag >= STORY_FLAG_COUNT) { - luaL_error(L, "Invalid flag ID %d", flag); - return 0; + return JS_THROW("storyFlagDecrement: invalid flag ID"); } - - storyflagvalue_t value = storyFlagGet(flag); - storyFlagSet(flag, value - 1); - return 0; + storyFlagSet(flag, storyFlagGet(flag) - 1); + return jerry_undefined(); } -static void moduleStoryFlag(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - lua_register(L, "storyFlagGet", moduleStoryFlagGet); - lua_register(L, "storyFlagSet", moduleStoryFlagSet); - lua_register(L, "storyFlagIncrement", moduleStoryFlagIncrement); - lua_register(L, "storyFlagDecrement", moduleStoryFlagDecrement); +static void moduleStoryFlag(void) { + jsRegister("storyFlagGet", moduleStoryFlagGet); + jsRegister("storyFlagSet", moduleStoryFlagSet); + jsRegister("storyFlagIncrement", moduleStoryFlagIncrement); + jsRegister("storyFlagDecrement", moduleStoryFlagDecrement); } diff --git a/tools/color/csv/__main__.py b/tools/color/csv/__main__.py index a86836db..45fc5cce 100644 --- a/tools/color/csv/__main__.py +++ b/tools/color/csv/__main__.py @@ -45,7 +45,7 @@ out = [ "", ] -lua = [] +js = [] for name, (r, g, b, a) in colors.items(): r8, g8, b8, a8 = (int(float(ch) * 255) for ch in (r, g, b, a)) macro = "COLOR_" + name.upper() @@ -60,16 +60,16 @@ for name, (r, g, b, a) in colors.items(): f"#define {macro} {macro}_4B", "", ] - lua += [ - f"function color{camel}()", - f" return color({r8}, {g8}, {b8}, {a8})", - "end", + js += [ + f"function color{camel}() {{", + f" return color({r8}, {g8}, {b8}, {a8});", + "}", "", ] -out.append("// Lua color functions") +out.append("// JS color functions") out.append("#define COLOR_SCRIPT \\") -for line in "\n".join(lua).rstrip().splitlines(): +for line in "\n".join(js).rstrip().splitlines(): out.append(f' "{line}\\n" \\') out[-1] = out[-1].rstrip(" \\") out.append("") diff --git a/tools/input/csv/__main__.py b/tools/input/csv/__main__.py index 6055de08..d7ad0786 100644 --- a/tools/input/csv/__main__.py +++ b/tools/input/csv/__main__.py @@ -50,7 +50,7 @@ out += [ "static const char_t *INPUT_ACTION_SCRIPT =", ] for input_id in input_ids: - out.append(f" \"{id_enum(input_id)} = {id_values[input_id]}\\n\"") + out.append(f" \"var {id_enum(input_id)} = {id_values[input_id]};\\n\"") out += [";", ""] os.makedirs(os.path.dirname(args.output), exist_ok=True)