Merge branch 'jerryscript' into playertest
This commit is contained in:
File diff suppressed because it is too large
Load Diff
+3
-1
@@ -4,11 +4,13 @@
|
|||||||
# https://opensource.org/licenses/MIT
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
# Setup
|
# Setup
|
||||||
cmake_minimum_required(VERSION 3.18)
|
cmake_minimum_required(VERSION 4.0)
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
|
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)
|
option(DUSK_BUILD_TESTS "Enable tests" OFF)
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -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
|
|
||||||
@@ -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');
|
||||||
@@ -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')
|
|
||||||
@@ -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;
|
||||||
@@ -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
|
|
||||||
@@ -22,31 +22,9 @@ set(CGLM_SHARED OFF CACHE BOOL "Build cglm shared" FORCE)
|
|||||||
set(CGLM_STATIC ON CACHE BOOL "Build cglm static" FORCE)
|
set(CGLM_STATIC ON CACHE BOOL "Build cglm static" FORCE)
|
||||||
find_package(cglm REQUIRED)
|
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
|
# Link libraries
|
||||||
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PRIVATE
|
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PRIVATE
|
||||||
cglm
|
cglm
|
||||||
liblua
|
|
||||||
m
|
m
|
||||||
fat
|
fat
|
||||||
PkgConfig::zip
|
PkgConfig::zip
|
||||||
|
|||||||
@@ -20,31 +20,9 @@ set(CGLM_SHARED OFF CACHE BOOL "Build cglm shared" FORCE)
|
|||||||
set(CGLM_STATIC ON CACHE BOOL "Build cglm static" FORCE)
|
set(CGLM_STATIC ON CACHE BOOL "Build cglm static" FORCE)
|
||||||
find_package(cglm REQUIRED)
|
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
|
# Link libraries
|
||||||
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC
|
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC
|
||||||
${SDL2_LIBRARIES}
|
${SDL2_LIBRARIES}
|
||||||
liblua
|
|
||||||
cglm
|
cglm
|
||||||
SDL2
|
SDL2
|
||||||
SDL2main
|
SDL2main
|
||||||
|
|||||||
+3
-12
@@ -32,18 +32,9 @@ if(NOT yyjson_FOUND)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT Lua_FOUND)
|
if(NOT jerryscript_FOUND)
|
||||||
find_package(Lua REQUIRED)
|
find_package(jerryscript REQUIRED)
|
||||||
if(Lua_FOUND AND NOT TARGET Lua::Lua)
|
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC jerryscript)
|
||||||
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)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT jerryscript_FOUND)
|
if(NOT jerryscript_FOUND)
|
||||||
|
|||||||
@@ -7,76 +7,89 @@
|
|||||||
|
|
||||||
#include "assetscriptloader.h"
|
#include "assetscriptloader.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <zip.h>
|
||||||
|
|
||||||
errorret_t assetScriptLoader(assetfile_t *file) {
|
errorret_t assetScriptLoader(assetfile_t *file) {
|
||||||
assertNotNull(file, "Asset file cannot be NULL");
|
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");
|
assertNotNull(file->output, "Asset file output cannot be NULL");
|
||||||
|
|
||||||
assetscript_t *script = (assetscript_t *)file->output;
|
assetscript_t *script = (assetscript_t *)file->output;
|
||||||
|
|
||||||
// Open the asset for buffering
|
|
||||||
errorChain(assetFileOpen(file));
|
errorChain(assetFileOpen(file));
|
||||||
|
|
||||||
// Request loading
|
// Accumulate full source into a dynamically grown buffer.
|
||||||
if(lua_load(
|
size_t srcLen = 0;
|
||||||
script->ctx->luaState,
|
size_t capacity = ASSET_SCRIPT_CHUNK_SIZE;
|
||||||
assetScriptReader,
|
char_t *src = (char_t *)malloc(capacity + 1);
|
||||||
file,
|
if(!src) {
|
||||||
file->filename,
|
assetFileClose(file);
|
||||||
NULL
|
errorThrow("Out of memory reading script: %s", file->filename);
|
||||||
) != 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now loaded, exec
|
while(1) {
|
||||||
if(lua_pcall(script->ctx->luaState, 0, LUA_MULTRET, 0) != LUA_OK) {
|
if(srcLen + ASSET_SCRIPT_CHUNK_SIZE > capacity) {
|
||||||
const char_t *strErr = lua_tostring(script->ctx->luaState, -1);
|
capacity = srcLen + ASSET_SCRIPT_CHUNK_SIZE;
|
||||||
lua_pop(script->ctx->luaState, 1);
|
char_t *tmp = (char_t *)realloc(src, capacity + 1);
|
||||||
errorThrow("Failed to execute Lua script: %s", strErr);
|
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
|
if(script->resultOut != NULL) {
|
||||||
return assetFileClose(file);
|
*(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(path, "Script path cannot be NULL");
|
||||||
assertNotNull(ctx, "Script context cannot be NULL");
|
assertNotNull(ctx, "Script context cannot be NULL");
|
||||||
|
|
||||||
assetscript_t script;
|
assetscript_t scriptData;
|
||||||
script.ctx = ctx;
|
scriptData.ctx = ctx;
|
||||||
|
scriptData.resultOut = resultOut;
|
||||||
|
|
||||||
return assetLoad(
|
return assetLoad(path, assetScriptLoader, NULL, &scriptData);
|
||||||
path,
|
|
||||||
assetScriptLoader,
|
|
||||||
NULL,
|
|
||||||
&script
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
#include "asset/asset.h"
|
#include "asset/asset.h"
|
||||||
#include "script/scriptcontext.h"
|
#include "script/scriptcontext.h"
|
||||||
|
|
||||||
#define ASSET_SCRIPT_BUFFER_SIZE 1024
|
#define ASSET_SCRIPT_CHUNK_SIZE 1024
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *nothing;
|
void *nothing;
|
||||||
@@ -17,11 +17,12 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
scriptcontext_t *ctx;
|
scriptcontext_t *ctx;
|
||||||
char_t buffer[ASSET_SCRIPT_BUFFER_SIZE];
|
jerry_value_t *resultOut;
|
||||||
} assetscript_t;
|
} 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.
|
* @param file Asset file to load the script from.
|
||||||
* @return Any error that occurs during loading.
|
* @return Any error that occurs during loading.
|
||||||
@@ -33,16 +34,13 @@ errorret_t assetScriptLoader(assetfile_t *file);
|
|||||||
*
|
*
|
||||||
* @param path Path to the script asset.
|
* @param path Path to the script asset.
|
||||||
* @param ctx Script context to load the script into.
|
* @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.
|
* @return Any error that occurs during loading.
|
||||||
*/
|
*/
|
||||||
errorret_t assetScriptLoad(const char_t *path, scriptcontext_t *ctx);
|
errorret_t assetScriptLoad(
|
||||||
|
const char_t *path,
|
||||||
/**
|
scriptcontext_t *ctx,
|
||||||
* Reader function for Lua to read script data from the asset.
|
jerry_value_t *resultOut
|
||||||
*
|
);
|
||||||
* @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);
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
|
|||||||
|
|
||||||
/* Run the init script. */
|
/* Run the init script. */
|
||||||
consolePrint("Engine initialized");
|
consolePrint("Engine initialized");
|
||||||
errorChain(scriptContextExecFile(&SCRIPT_MANAGER.mainContext, "init.lua"));
|
errorChain(scriptContextExecFile(&SCRIPT_MANAGER.mainContext, "init.js", NULL));
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|||||||
+47
-72
@@ -10,16 +10,6 @@
|
|||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "console/console.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(
|
void eventInit(
|
||||||
event_t *event,
|
event_t *event,
|
||||||
eventlistener_t *array,
|
eventlistener_t *array,
|
||||||
@@ -57,19 +47,16 @@ eventsub_t eventSubscribeUser(
|
|||||||
"Script event listener context cannot be NULL"
|
"Script event listener context cannot be NULL"
|
||||||
);
|
);
|
||||||
assertTrue(
|
assertTrue(
|
||||||
user.script.luaFunctionRef != LUA_NOREF,
|
user.script.funcValue != 0,
|
||||||
"Script event listener function reference is invalid"
|
"Script event listener function reference is invalid"
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
assertUnreachable("Unknown event listener type");
|
assertUnreachable("Unknown event listener type");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gen a new ID
|
|
||||||
eventsub_t id = event->nextId++;
|
eventsub_t id = event->nextId++;
|
||||||
// Did we wrap?
|
|
||||||
assertTrue(event->nextId != 0, "Event subscription ID overflow");
|
assertTrue(event->nextId != 0, "Event subscription ID overflow");
|
||||||
|
|
||||||
// Append listener
|
|
||||||
eventlistener_t *listener = &event->listenerArray[event->listenerCount++];
|
eventlistener_t *listener = &event->listenerArray[event->listenerCount++];
|
||||||
memoryZero(listener, sizeof(eventlistener_t));
|
memoryZero(listener, sizeof(eventlistener_t));
|
||||||
listener->user = user;
|
listener->user = user;
|
||||||
@@ -94,49 +81,29 @@ eventsub_t eventSubscribe(
|
|||||||
eventsub_t eventSubscribeScriptContext(
|
eventsub_t eventSubscribeScriptContext(
|
||||||
event_t *event,
|
event_t *event,
|
||||||
scriptcontext_t *context,
|
scriptcontext_t *context,
|
||||||
const int functionIndex
|
jerry_value_t funcValue
|
||||||
) {
|
) {
|
||||||
assertNotNull(context, "Script context cannot be NULL");
|
assertNotNull(context, "Script context cannot be NULL");
|
||||||
assertTrue(
|
assertTrue(funcValue != 0, "Script function value is invalid");
|
||||||
lua_isfunction(context->luaState, functionIndex),
|
|
||||||
"Expected function at given index"
|
|
||||||
);
|
|
||||||
|
|
||||||
// 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;
|
bool_t alreadySubbed = false;
|
||||||
uint8_t i;
|
uint8_t i = 0;
|
||||||
i = 0;
|
|
||||||
do {
|
do {
|
||||||
if(context->subscribedEvents[i] != event) {
|
if(context->subscribedEvents[i] == event) {
|
||||||
i++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(context->subscribedEvents[i] == NULL) break;
|
|
||||||
|
|
||||||
alreadySubbed = true;
|
alreadySubbed = true;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
} while(i < SCRIPT_CONTEXT_MAX_EVENT_SUBSCRIPTIONS);
|
} while(i < SCRIPT_CONTEXT_MAX_EVENT_SUBSCRIPTIONS);
|
||||||
|
|
||||||
if(!alreadySubbed) {
|
if(!alreadySubbed) {
|
||||||
i = 0;
|
i = 0;
|
||||||
do {
|
do {
|
||||||
if(context->subscribedEvents[i] != NULL) {
|
if(context->subscribedEvents[i] == NULL) {
|
||||||
i++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
context->subscribedEvents[i] = event;
|
context->subscribedEvents[i] = event;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
} while(i < SCRIPT_CONTEXT_MAX_EVENT_SUBSCRIPTIONS);
|
} while(i < SCRIPT_CONTEXT_MAX_EVENT_SUBSCRIPTIONS);
|
||||||
|
|
||||||
assertTrue(
|
assertTrue(
|
||||||
@@ -148,7 +115,12 @@ eventsub_t eventSubscribeScriptContext(
|
|||||||
return eventSubscribeUser(
|
return eventSubscribeUser(
|
||||||
event,
|
event,
|
||||||
EVENT_TYPE_SCRIPT,
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release Lua registry reference before the slot is overwritten
|
|
||||||
if(event->listenerArray[index].type == EVENT_TYPE_SCRIPT) {
|
if(event->listenerArray[index].type == EVENT_TYPE_SCRIPT) {
|
||||||
scriptcontext_t *ctx = event->listenerArray[index].user.script.context;
|
jerry_value_t funcVal = event->listenerArray[index].user.script.funcValue;
|
||||||
if(ctx != NULL && ctx->luaState != NULL) {
|
if(funcVal != 0) {
|
||||||
luaL_unref(
|
jerry_value_free(funcVal);
|
||||||
ctx->luaState,
|
|
||||||
LUA_REGISTRYINDEX,
|
|
||||||
event->listenerArray[index].user.script.luaFunctionRef
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swap with last and shrink
|
|
||||||
event->listenerArray[index] = event->listenerArray[--event->listenerCount];
|
event->listenerArray[index] = event->listenerArray[--event->listenerCount];
|
||||||
return;
|
return;
|
||||||
} while(index < event->listenerCount);
|
} while(index < event->listenerCount);
|
||||||
@@ -199,9 +165,6 @@ void eventUnsubscribeScriptContext(event_t *event, const scriptcontext_t *ctx) {
|
|||||||
i++;
|
i++;
|
||||||
continue;
|
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);
|
eventUnsubscribe(event, listener->id);
|
||||||
} while(i < event->listenerCount);
|
} while(i < event->listenerCount);
|
||||||
}
|
}
|
||||||
@@ -217,40 +180,52 @@ void eventInvoke(
|
|||||||
|
|
||||||
event->isInvoking = true;
|
event->isInvoking = true;
|
||||||
|
|
||||||
uint16_t i = 0;
|
eventdata_t data = {
|
||||||
eventdata_t data ={
|
|
||||||
.event = event,
|
.event = event,
|
||||||
.eventParams = eventParams,
|
.eventParams = eventParams,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint16_t i = 0;
|
||||||
do {
|
do {
|
||||||
eventlistener_t *listener = &event->listenerArray[i];
|
eventlistener_t *listener = &event->listenerArray[i];
|
||||||
|
|
||||||
if(listener->type == EVENT_TYPE_C) {
|
if(listener->type == EVENT_TYPE_C) {
|
||||||
listener->user.c.callback(&data, listener->user.c);
|
listener->user.c.callback(&data, listener->user.c);
|
||||||
} else if(listener->type == EVENT_TYPE_SCRIPT) {
|
} else if(listener->type == EVENT_TYPE_SCRIPT) {
|
||||||
lua_State *L = listener->user.script.context->luaState;
|
jerry_value_t funcVal = listener->user.script.funcValue;
|
||||||
assertNotNull(L, "Lua state in event listener cannot be NULL");
|
assertNotNull((void *)(uintptr_t)funcVal, "Script function value is NULL");
|
||||||
|
|
||||||
lua_pushcfunction(L, eventLuaTraceback);
|
jerry_value_t callArgs[1];
|
||||||
int handlerIdx = lua_gettop(L);
|
jerry_length_t argCount = 0;
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, listener->user.script.luaFunctionRef);
|
|
||||||
|
|
||||||
int numArgs = 0;
|
|
||||||
if(eventParams != NULL) {
|
if(eventParams != NULL) {
|
||||||
lua_pushlightuserdata(L, (void *)eventParams);
|
callArgs[0] = jerry_object();
|
||||||
numArgs = 1;
|
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) {
|
if(argCount > 0) jerry_value_free(callArgs[0]);
|
||||||
const char_t *strErr = lua_tostring(L, -1);
|
|
||||||
consolePrint("Error invoking Lua event listener:\n%s\n", strErr);
|
if(jerry_value_is_exception(result)) {
|
||||||
lua_pop(L, 1);
|
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 {
|
} else {
|
||||||
assertUnreachable("Unknown event listener type");
|
assertUnreachable("Unknown event listener type");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ eventsub_t eventSubscribe(
|
|||||||
eventsub_t eventSubscribeScriptContext(
|
eventsub_t eventSubscribeScriptContext(
|
||||||
event_t *event,
|
event_t *event,
|
||||||
scriptcontext_t *context,
|
scriptcontext_t *context,
|
||||||
const int functionIndex
|
jerry_value_t funcValue
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ typedef enum {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
scriptcontext_t *context;
|
scriptcontext_t *context;
|
||||||
int luaFunctionRef;
|
jerry_value_t funcValue;
|
||||||
} eventscript_t;
|
} eventscript_t;
|
||||||
|
|
||||||
typedef struct eventc_s {
|
typedef struct eventc_s {
|
||||||
|
|||||||
+15
-31
@@ -24,7 +24,7 @@ scene_t SCENE;
|
|||||||
|
|
||||||
errorret_t sceneInit(void) {
|
errorret_t sceneInit(void) {
|
||||||
memoryZero(&SCENE, sizeof(scene_t));
|
memoryZero(&SCENE, sizeof(scene_t));
|
||||||
SCENE.scriptRef = LUA_NOREF;
|
SCENE.scriptRef = SCENE_SCRIPT_REF_NONE;
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,25 +40,22 @@ errorret_t sceneUpdate(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(SCENE.sceneActive) {
|
if(SCENE.sceneActive) {
|
||||||
errorChain(moduleSceneCall(SCRIPT_MANAGER.mainContext.luaState, "update"));
|
errorChain(moduleSceneCall("update"));
|
||||||
}
|
}
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
errorret_t sceneRender(void) {
|
errorret_t sceneRender(void) {
|
||||||
// Get Cameras
|
|
||||||
entityid_t camEnts[ENTITY_COUNT_MAX];
|
entityid_t camEnts[ENTITY_COUNT_MAX];
|
||||||
componentid_t camComps[ENTITY_COUNT_MAX];
|
componentid_t camComps[ENTITY_COUNT_MAX];
|
||||||
entityid_t camCount = componentGetEntitiesWithComponent(
|
entityid_t camCount = componentGetEntitiesWithComponent(
|
||||||
COMPONENT_TYPE_CAMERA, camEnts, camComps
|
COMPONENT_TYPE_CAMERA, camEnts, camComps
|
||||||
);
|
);
|
||||||
|
|
||||||
// Prep Matricies
|
|
||||||
mat4 view, proj, model;
|
mat4 view, proj, model;
|
||||||
|
|
||||||
if(camCount > 0) {
|
if(camCount > 0) {
|
||||||
// Get meshes
|
|
||||||
entityid_t meshEnts[ENTITY_COUNT_MAX];
|
entityid_t meshEnts[ENTITY_COUNT_MAX];
|
||||||
componentid_t meshComps[ENTITY_COUNT_MAX];
|
componentid_t meshComps[ENTITY_COUNT_MAX];
|
||||||
entityid_t meshCount = componentGetEntitiesWithComponent(
|
entityid_t meshCount = componentGetEntitiesWithComponent(
|
||||||
@@ -68,7 +65,6 @@ errorret_t sceneRender(void) {
|
|||||||
if(meshCount > 0) {
|
if(meshCount > 0) {
|
||||||
errorChain(shaderBind(&SHADER_UNLIT));
|
errorChain(shaderBind(&SHADER_UNLIT));
|
||||||
|
|
||||||
// For each camera.
|
|
||||||
for(entityid_t camIndex = 0; camIndex < camCount; camIndex++) {
|
for(entityid_t camIndex = 0; camIndex < camCount; camIndex++) {
|
||||||
entityid_t camEnt = camEnts[camIndex];
|
entityid_t camEnt = camEnts[camIndex];
|
||||||
componentid_t camComp = camComps[camIndex];
|
componentid_t camComp = camComps[camIndex];
|
||||||
@@ -81,15 +77,11 @@ errorret_t sceneRender(void) {
|
|||||||
entityCameraGetProjection(camEnt, camComp, proj);
|
entityCameraGetProjection(camEnt, camComp, proj);
|
||||||
entityPositionGetTransform(camEnt, camPos, view);
|
entityPositionGetTransform(camEnt, camPos, view);
|
||||||
|
|
||||||
// For each mesh.
|
|
||||||
for(entityid_t meshIndex = 0; meshIndex < meshCount; meshIndex++) {
|
for(entityid_t meshIndex = 0; meshIndex < meshCount; meshIndex++) {
|
||||||
entityid_t meshEnt = meshEnts[meshIndex];
|
entityid_t meshEnt = meshEnts[meshIndex];
|
||||||
|
|
||||||
componentid_t meshComp = meshComps[meshIndex];
|
componentid_t meshComp = meshComps[meshIndex];
|
||||||
mesh_t *mesh = entityMeshGetMesh(meshEnt, meshComp);
|
mesh_t *mesh = entityMeshGetMesh(meshEnt, meshComp);
|
||||||
if(mesh == NULL) {
|
if(mesh == NULL) continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
componentid_t meshPos = entityGetComponent(
|
componentid_t meshPos = entityGetComponent(
|
||||||
meshEnt, COMPONENT_TYPE_POSITION
|
meshEnt, COMPONENT_TYPE_POSITION
|
||||||
@@ -129,7 +121,6 @@ errorret_t sceneRender(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here is where UI will go
|
|
||||||
glm_ortho(
|
glm_ortho(
|
||||||
0.0f, SCREEN.width,
|
0.0f, SCREEN.width,
|
||||||
SCREEN.height, 0.0f,
|
SCREEN.height, 0.0f,
|
||||||
@@ -163,15 +154,11 @@ errorret_t sceneSetImmediate(const char_t *scene) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(SCENE.sceneActive) {
|
if(SCENE.sceneActive) {
|
||||||
errorChain(moduleSceneCall(
|
errorChain(moduleSceneCall("dispose"));
|
||||||
SCRIPT_MANAGER.mainContext.luaState, "dispose"
|
|
||||||
));
|
|
||||||
SCENE.sceneActive = false;
|
SCENE.sceneActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wipe Scene back to a clean table before loading the next file so custom
|
moduleSceneReset();
|
||||||
// methods from the previous scene (e.g. Scene.doThing) cannot bleed through.
|
|
||||||
moduleSceneReset(SCRIPT_MANAGER.mainContext.luaState);
|
|
||||||
|
|
||||||
stringCopy(
|
stringCopy(
|
||||||
SCENE.sceneCurrent,
|
SCENE.sceneCurrent,
|
||||||
@@ -180,22 +167,19 @@ errorret_t sceneSetImmediate(const char_t *scene) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if(scene != NULL) {
|
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);
|
if(!jerry_value_is_object(sceneObj)) {
|
||||||
|
if(sceneObj != SCENE_SCRIPT_REF_NONE) jerry_value_free(sceneObj);
|
||||||
errorChain(scriptContextExecFile(&SCRIPT_MANAGER.mainContext, scene));
|
errorThrow("Scene '%s' must return an object", 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);
|
|
||||||
}
|
}
|
||||||
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;
|
SCENE.sceneActive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,6 +195,6 @@ void sceneSet(const char_t *scene) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
errorret_t sceneDispose(void) {
|
errorret_t sceneDispose(void) {
|
||||||
errorChain(moduleSceneCall(SCRIPT_MANAGER.mainContext.luaState, "dispose"));
|
errorChain(moduleSceneCall("dispose"));
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-18
@@ -14,39 +14,39 @@
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool_t sceneActive;
|
bool_t sceneActive;
|
||||||
int scriptRef;
|
jerry_value_t scriptRef;
|
||||||
char_t sceneCurrent[ASSET_FILE_PATH_MAX];
|
char_t sceneCurrent[ASSET_FILE_PATH_MAX];
|
||||||
char_t sceneNext[ASSET_FILE_PATH_MAX];
|
char_t sceneNext[ASSET_FILE_PATH_MAX];
|
||||||
} scene_t;
|
} scene_t;
|
||||||
|
|
||||||
extern scene_t SCENE;
|
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.
|
* @return Any error state that happened.
|
||||||
*/
|
*/
|
||||||
errorret_t sceneInit(void);
|
errorret_t sceneInit(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ticks the scene manager, may or may not call the scene's update method
|
* Ticks the scene manager; may call the scene's update method.
|
||||||
* depending on time state.
|
|
||||||
*
|
*
|
||||||
* @return Any error state that happened.
|
* @return Any error state that happened.
|
||||||
*/
|
*/
|
||||||
errorret_t sceneUpdate(void);
|
errorret_t sceneUpdate(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the scene, happens regardless of time.
|
* Renders the scene.
|
||||||
*
|
*
|
||||||
* @return Any error state that happened.
|
* @return Any error state that happened.
|
||||||
*/
|
*/
|
||||||
errorret_t sceneRender(void);
|
errorret_t sceneRender(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal method to immediately switch scenes, this will also delete some of
|
* Immediately switches scenes, disposing the current one first.
|
||||||
* the lua state, which can cause problems if called during a lua callback, so
|
|
||||||
* this is managed by the scene manager.
|
|
||||||
*
|
*
|
||||||
* @param scene Scene to switch to (asset file path).
|
* @param scene Scene to switch to (asset file path).
|
||||||
* @return Any error state that happened.
|
* @return Any error state that happened.
|
||||||
@@ -54,8 +54,7 @@ errorret_t sceneRender(void);
|
|||||||
errorret_t sceneSetImmediate(const char_t *scene);
|
errorret_t sceneSetImmediate(const char_t *scene);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests the scene manager to change scenes when it is next able to. This
|
* Requests a scene change on the next safe opportunity.
|
||||||
* will not guarantee that the scene is valid or without errors.
|
|
||||||
*
|
*
|
||||||
* @param scene Which scene to set.
|
* @param scene Which scene to set.
|
||||||
*/
|
*/
|
||||||
@@ -63,14 +62,7 @@ void sceneSet(const char_t *scene);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Disposes of the current scene.
|
* Disposes of the current scene.
|
||||||
|
*
|
||||||
* @return Any error state that happened.
|
* @return Any error state that happened.
|
||||||
*/
|
*/
|
||||||
errorret_t sceneDispose(void);
|
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);
|
|
||||||
@@ -10,112 +10,170 @@
|
|||||||
#include "display/color.h"
|
#include "display/color.h"
|
||||||
#include "time/time.h"
|
#include "time/time.h"
|
||||||
|
|
||||||
static int moduleColorIndex(lua_State *L) {
|
// ---------------------------------------------------------------------------
|
||||||
const color_t *color = (const color_t *)luaL_checkudata(L, 1, "color_mt");
|
// Native info / prototype
|
||||||
assertNotNull(color, "Color struct cannot be NULL.");
|
// ---------------------------------------------------------------------------
|
||||||
const char_t *key = luaL_checkstring(L, 2);
|
|
||||||
|
|
||||||
if(stringCompare(key, "r") == 0) { lua_pushnumber(L, color->r); return 1; }
|
static void freeColorNative(void *ptr, jerry_object_native_info_t *info) {
|
||||||
if(stringCompare(key, "g") == 0) { lua_pushnumber(L, color->g); return 1; }
|
(void)info;
|
||||||
if(stringCompare(key, "b") == 0) { lua_pushnumber(L, color->b); return 1; }
|
free(ptr);
|
||||||
if(stringCompare(key, "a") == 0) { lua_pushnumber(L, color->a); return 1; }
|
|
||||||
|
|
||||||
lua_getmetatable(L, 1);
|
|
||||||
lua_getfield(L, -1, key);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
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");
|
// Property getters / setters
|
||||||
assertNotNull(color, "Color struct cannot be NULL.");
|
// ---------------------------------------------------------------------------
|
||||||
const char_t *key = luaL_checkstring(L, 2);
|
|
||||||
|
|
||||||
if(stringCompare(key, "r") == 0) {
|
JS_FUNC(moduleColorGetR) {
|
||||||
color->r = (colorchannel8_t)luaL_checknumber(L, 3); return 0;
|
color_t *color = (color_t *)jerry_object_get_native_ptr(
|
||||||
} else if(stringCompare(key, "g") == 0) {
|
call_info_p->this_value, &COLOR_NATIVE_INFO
|
||||||
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
|
|
||||||
);
|
);
|
||||||
return 1;
|
return color ? jerry_number(color->r) : jerry_undefined();
|
||||||
}
|
}
|
||||||
|
JS_FUNC(moduleColorSetR) {
|
||||||
static int moduleColorCreate(lua_State *L) {
|
color_t *color = (color_t *)jerry_object_get_native_ptr(
|
||||||
assertNotNull(L, "Lua state cannot be NULL.");
|
call_info_p->this_value, &COLOR_NATIVE_INFO
|
||||||
|
);
|
||||||
if(
|
if(color && args_count > 0) {
|
||||||
!lua_isnumber(L, 1) || !lua_isnumber(L, 2) ||
|
color->r = (colorchannel8_t)jerry_value_as_number(args_p[0]);
|
||||||
!lua_isnumber(L, 3) || !lua_isnumber(L, 4)
|
|
||||||
) {
|
|
||||||
return luaL_error(L, "color(r, g, b, a) requires four number arguments.");
|
|
||||||
}
|
}
|
||||||
|
return jerry_undefined();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
float_t t = TIME.time * 4.0f;
|
||||||
if(lua_gettop(L) >= 1) {
|
|
||||||
if(!lua_isnumber(L, 1)) {
|
if(args_count >= 1 && jerry_value_is_number(args_p[0])) {
|
||||||
return luaL_error(L, "Rainbow time offset must be a number.");
|
t += (float_t)jerry_value_as_number(args_p[0]);
|
||||||
}
|
|
||||||
t += (float_t)lua_tonumber(L, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lua_gettop(L) >= 2) {
|
if(args_count >= 2 && jerry_value_is_number(args_p[1])) {
|
||||||
if(!lua_isnumber(L, 2)) {
|
t *= (float_t)jerry_value_as_number(args_p[1]);
|
||||||
return luaL_error(L, "Rainbow speed multiplier must be a number.");
|
|
||||||
}
|
|
||||||
t *= (float_t)lua_tonumber(L, 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
color_t *color = (color_t *)lua_newuserdata(L, sizeof(color_t));
|
color_t c;
|
||||||
color->r = (colorchannel8_t)((sinf(t) + 1.0f) * 0.5f * 255.0f);
|
c.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);
|
c.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);
|
c.b = (colorchannel8_t)((sinf(t + 4.0f) + 1.0f) * 0.5f * 255.0f);
|
||||||
color->a = 255;
|
c.a = 255;
|
||||||
|
return moduleColorMakeObject(c);
|
||||||
luaL_getmetatable(L, "color_mt");
|
|
||||||
lua_setmetatable(L, -2);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void moduleColor(lua_State *L) {
|
// ---------------------------------------------------------------------------
|
||||||
assertNotNull(L, "Lua state cannot be NULL.");
|
// Module init
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
if(luaL_newmetatable(L, "color_mt")) {
|
static void moduleColor(void) {
|
||||||
lua_pushcfunction(L, moduleColorIndex);
|
s_colorProto = jerry_object();
|
||||||
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);
|
|
||||||
|
|
||||||
lua_register(L, "color", moduleColorCreate);
|
jsDefineProperty(s_colorProto, "r", moduleColorGetR, moduleColorSetR);
|
||||||
lua_register(L, "colorRainbow", moduleColorRainbow);
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,35 +8,51 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "script/module/modulebase.h"
|
#include "script/module/modulebase.h"
|
||||||
#include "display/screen/screen.h"
|
#include "display/screen/screen.h"
|
||||||
|
#include "display/color.h"
|
||||||
|
|
||||||
static int moduleScreenGetWidth(lua_State *L) {
|
JS_FUNC(moduleScreenGetWidth) {
|
||||||
assertNotNull(L, "Lua state is null");
|
return jerry_number(SCREEN.width);
|
||||||
lua_pushnumber(L, SCREEN.width);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleScreenGetHeight(lua_State *L) {
|
JS_FUNC(moduleScreenGetHeight) {
|
||||||
assertNotNull(L, "Lua state is null");
|
return jerry_number(SCREEN.height);
|
||||||
lua_pushnumber(L, SCREEN.height);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleScreenSetBackground(lua_State *L) {
|
JS_FUNC(moduleScreenSetBackground) {
|
||||||
assertNotNull(L, "Lua state is null");
|
if(args_count < 1 || !jerry_value_is_object(args_p[0])) {
|
||||||
|
return JS_THROW("Screen background color must be a color object");
|
||||||
if(!lua_isuserdata(L, 1)) {
|
|
||||||
luaL_error(L, "Screen background color must be a color struct");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
color_t *color = (color_t*)luaL_checkudata(L, 1, "color_mt");
|
jerry_value_t keyR = jerry_string_sz("r");
|
||||||
SCREEN.background = *color;
|
jerry_value_t keyG = jerry_string_sz("g");
|
||||||
return 0;
|
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) {
|
static void moduleScreen(void) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL.");
|
jsRegister("screenGetWidth", moduleScreenGetWidth);
|
||||||
lua_register(L, "screenGetWidth", moduleScreenGetWidth);
|
jsRegister("screenGetHeight", moduleScreenGetHeight);
|
||||||
lua_register(L, "screenGetHeight", moduleScreenGetHeight);
|
jsRegister("screenSetBackground", moduleScreenSetBackground);
|
||||||
lua_register(L, "screenSetBackground", moduleScreenSetBackground);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,80 +11,87 @@
|
|||||||
#include "display/shader/shaderunlit.h"
|
#include "display/shader/shaderunlit.h"
|
||||||
#include "script/module/math/modulemat4.h"
|
#include "script/module/math/modulemat4.h"
|
||||||
|
|
||||||
static int moduleShaderBind(lua_State *l) {
|
// ---------------------------------------------------------------------------
|
||||||
assertNotNull(l, "Lua state cannot be NULL.");
|
// Functions
|
||||||
shader_t *shader = (shader_t *)lua_touserdata(l, 1);
|
// ---------------------------------------------------------------------------
|
||||||
assertNotNull(shader, "Shader pointer cannot be NULL.");
|
|
||||||
|
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);
|
errorret_t ret = shaderBind(shader);
|
||||||
if(ret.code != ERROR_OK) {
|
if(ret.code != ERROR_OK) {
|
||||||
luaL_error(l, "Failed to bind shader: %s", ret.state->message);
|
|
||||||
errorCatch(errorPrint(ret));
|
errorCatch(errorPrint(ret));
|
||||||
return 0;
|
return JS_THROW("shaderBind: failed to bind shader");
|
||||||
}
|
}
|
||||||
return 0;
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleShaderSetMatrix(lua_State *l) {
|
JS_FUNC(moduleShaderSetMatrix) {
|
||||||
assertNotNull(l, "Lua state cannot be NULL.");
|
JS_REQUIRE_ARGS(3);
|
||||||
shader_t *shader = (shader_t *)lua_touserdata(l, 1);
|
shader_t *shader = (shader_t *)jsUnwrapPointer(args_p[0]);
|
||||||
assertNotNull(shader, "Shader pointer cannot be NULL.");
|
if(!shader) return JS_THROW("shaderSetMatrix: expected a shader object");
|
||||||
const char_t *uniformName = luaL_checkstring(l, 2);
|
|
||||||
mat4 *mat = (mat4 *)luaL_checkudata(l, 3, "mat4_mt");
|
|
||||||
assertNotNull(mat, "Matrix pointer cannot be NULL.");
|
|
||||||
|
|
||||||
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) {
|
if(ret.code != ERROR_OK) {
|
||||||
luaL_error(l, "Failed to set shader matrix: %s", ret.state->message);
|
|
||||||
errorCatch(errorPrint(ret));
|
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) {
|
JS_FUNC(moduleShaderSetTexture) {
|
||||||
assertNotNull(l, "Lua state cannot be NULL.");
|
JS_REQUIRE_ARGS(2);
|
||||||
shader_t *shader = (shader_t *)lua_touserdata(l, 1);
|
shader_t *shader = (shader_t *)jsUnwrapPointer(args_p[0]);
|
||||||
assertNotNull(shader, "Shader pointer cannot be NULL.");
|
if(!shader) return JS_THROW("shaderSetTexture: expected a shader object");
|
||||||
const char_t *uniformName = luaL_checkstring(l, 2);
|
|
||||||
assertStrLenMin(uniformName, 1, "Uniform name cannot be empty.");
|
|
||||||
|
|
||||||
texture_t *texture;
|
JS_REQUIRE_STRING(1);
|
||||||
if(lua_isnil(l, 3)) {
|
char_t uniformName[128];
|
||||||
texture = NULL;
|
jsToString(args_p[1], uniformName, sizeof(uniformName));
|
||||||
} else if(lua_isuserdata(l, 3)) {
|
|
||||||
texture = (texture_t *)lua_touserdata(l, 3);
|
texture_t *texture = NULL;
|
||||||
assertNotNull(texture, "Texture pointer cannot be NULL.");
|
if(
|
||||||
} else {
|
args_count >= 3 &&
|
||||||
luaL_error(l, "Third argument must be a texture_mt userdata or nil.");
|
!jerry_value_is_null(args_p[2]) &&
|
||||||
return 0;
|
!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);
|
errorret_t ret = shaderSetTexture(shader, uniformName, texture);
|
||||||
if(ret.code != ERROR_OK) {
|
if(ret.code != ERROR_OK) {
|
||||||
luaL_error(l, "Failed to set shader texture: %s", ret.state->message);
|
|
||||||
errorCatch(errorPrint(ret));
|
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);
|
static void moduleShader(void) {
|
||||||
lua_setglobal(L, "SHADER_UNLIT");
|
jerry_value_t shaderUnlitVal = jsWrapPointer(&SHADER_UNLIT);
|
||||||
|
jsSetValue("SHADER_UNLIT", shaderUnlitVal);
|
||||||
|
jerry_value_free(shaderUnlitVal);
|
||||||
|
|
||||||
lua_pushstring(L, SHADER_UNLIT_PROJECTION);
|
jsSetString("SHADER_UNLIT_PROJECTION", SHADER_UNLIT_PROJECTION);
|
||||||
lua_setglobal(L, "SHADER_UNLIT_PROJECTION");
|
jsSetString("SHADER_UNLIT_VIEW", SHADER_UNLIT_VIEW);
|
||||||
lua_pushstring(L, SHADER_UNLIT_VIEW);
|
jsSetString("SHADER_UNLIT_MODEL", SHADER_UNLIT_MODEL);
|
||||||
lua_setglobal(L, "SHADER_UNLIT_VIEW");
|
jsSetString("SHADER_UNLIT_TEXTURE", SHADER_UNLIT_TEXTURE);
|
||||||
lua_pushstring(L, SHADER_UNLIT_MODEL);
|
|
||||||
lua_setglobal(L, "SHADER_UNLIT_MODEL");
|
|
||||||
lua_pushstring(L, SHADER_UNLIT_TEXTURE);
|
|
||||||
lua_setglobal(L, "SHADER_UNLIT_TEXTURE");
|
|
||||||
|
|
||||||
lua_register(L, "shaderBind", moduleShaderBind);
|
jsRegister("shaderBind", moduleShaderBind);
|
||||||
lua_register(L, "shaderSetMatrix", moduleShaderSetMatrix);
|
jsRegister("shaderSetMatrix", moduleShaderSetMatrix);
|
||||||
lua_register(L, "shaderSetTexture", moduleShaderSetTexture);
|
jsRegister("shaderSetTexture", moduleShaderSetTexture);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,61 +11,98 @@
|
|||||||
#include "script/module/math/modulevec2.h"
|
#include "script/module/math/modulevec2.h"
|
||||||
#include "script/module/math/modulevec4.h"
|
#include "script/module/math/modulevec4.h"
|
||||||
|
|
||||||
static int moduleSpriteBatchFlush(lua_State *L) {
|
// ---------------------------------------------------------------------------
|
||||||
assertNotNull(L, "Lua state is null");
|
// Functions
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
JS_FUNC(moduleSpriteBatchFlush) {
|
||||||
spriteBatchFlush();
|
spriteBatchFlush();
|
||||||
return 0;
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleSpriteBatchClear(lua_State *L) {
|
JS_FUNC(moduleSpriteBatchClear) {
|
||||||
assertNotNull(L, "Lua state is null");
|
|
||||||
spriteBatchClear();
|
spriteBatchClear();
|
||||||
return 0;
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleSpriteBatchPush(lua_State *L) {
|
JS_FUNC(moduleSpriteBatchPush) {
|
||||||
assertNotNull(L, "Lua state is null");
|
JS_REQUIRE_ARGS(2);
|
||||||
|
|
||||||
vec2 min, max;
|
vec2 minPos, maxPos;
|
||||||
moduleVec2Check(L, 1, min);
|
if(!moduleVec2Check(args_p[0], minPos)) {
|
||||||
moduleVec2Check(L, 2, max);
|
return JS_THROW("spriteBatchPush: first argument must be a vec2");
|
||||||
|
}
|
||||||
color_t *color = NULL;
|
if(!moduleVec2Check(args_p[1], maxPos)) {
|
||||||
if(lua_gettop(L) < 3 || lua_isnil(L, 3)) {
|
return JS_THROW("spriteBatchPush: second argument must be a vec2");
|
||||||
// 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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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;
|
float_t u0 = 0.0f, v0 = 0.0f, u1 = 1.0f, v1 = 1.0f;
|
||||||
if(lua_gettop(L) >= 4 && !lua_isnil(L, 4)) {
|
if(
|
||||||
vec4 uv; moduleVec4Check(L, 4, uv);
|
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];
|
u0 = uv[0]; v0 = uv[1]; u1 = uv[2]; v1 = uv[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
errorret_t ret = spriteBatchPush(
|
errorret_t ret = spriteBatchPush(
|
||||||
min[0], min[1], max[0], max[1],
|
minPos[0], minPos[1], maxPos[0], maxPos[1],
|
||||||
#if MESH_ENABLE_COLOR
|
#if MESH_ENABLE_COLOR
|
||||||
color == NULL ? COLOR_WHITE : *color,
|
col,
|
||||||
#endif
|
#endif
|
||||||
u0, v0, u1, v1
|
u0, v0, u1, v1
|
||||||
);
|
);
|
||||||
if(ret.code != ERROR_OK) {
|
if(ret.code != ERROR_OK) {
|
||||||
int err = luaL_error(L,
|
|
||||||
"Failed to push sprite to batch: %s",
|
|
||||||
ret.state->message
|
|
||||||
);
|
|
||||||
errorCatch(errorPrint(ret));
|
errorCatch(errorPrint(ret));
|
||||||
return err;
|
return JS_THROW("spriteBatchPush: failed to push sprite to batch");
|
||||||
}
|
}
|
||||||
|
return jerry_undefined();
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void moduleSpriteBatch(lua_State *L) {
|
// ---------------------------------------------------------------------------
|
||||||
lua_register(L, "spriteBatchFlush", moduleSpriteBatchFlush);
|
// Module init
|
||||||
lua_register(L, "spriteBatchClear", moduleSpriteBatchClear);
|
// ---------------------------------------------------------------------------
|
||||||
lua_register(L, "spriteBatchPush", moduleSpriteBatchPush);
|
|
||||||
|
static void moduleSpriteBatch(void) {
|
||||||
|
jsRegister("spriteBatchFlush", moduleSpriteBatchFlush);
|
||||||
|
jsRegister("spriteBatchClear", moduleSpriteBatchClear);
|
||||||
|
jsRegister("spriteBatchPush", moduleSpriteBatchPush);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,62 +11,92 @@
|
|||||||
#include "display/spritebatch/spritebatch.h"
|
#include "display/spritebatch/spritebatch.h"
|
||||||
#include "script/module/math/modulevec2.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)) {
|
vec2 pos;
|
||||||
return luaL_error(L, "Text to draw must be a string");
|
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;
|
JS_REQUIRE_STRING(1);
|
||||||
if(lua_gettop(L) < 3 || lua_isnil(L, 3)) {
|
char_t text[1024];
|
||||||
// allow NULL (white)
|
jsToString(args_p[1], text, sizeof(text));
|
||||||
} else if(lua_isuserdata(L, 3)) {
|
|
||||||
color = (color_t *)luaL_checkudata(L, 3, "color_mt");
|
color_t color = COLOR_WHITE;
|
||||||
} else {
|
if(
|
||||||
return luaL_error(L, "Text color must be a color struct or nil");
|
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(
|
errorret_t ret = textDraw(
|
||||||
pos[0], pos[1], text,
|
pos[0], pos[1], text, color,
|
||||||
color == NULL ? COLOR_WHITE : *color,
|
|
||||||
&DEFAULT_FONT_TILESET,
|
&DEFAULT_FONT_TILESET,
|
||||||
&DEFAULT_FONT_TEXTURE
|
&DEFAULT_FONT_TEXTURE
|
||||||
);
|
);
|
||||||
if(ret.code != ERROR_OK) {
|
if(ret.code != ERROR_OK) {
|
||||||
errorCatch(errorPrint(ret));
|
errorCatch(errorPrint(ret));
|
||||||
luaL_error(L, "Failed to draw text");
|
return JS_THROW("textDraw: failed to draw text");
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = spriteBatchFlush();
|
ret = spriteBatchFlush();
|
||||||
if(ret.code != ERROR_OK) {
|
if(ret.code != ERROR_OK) {
|
||||||
errorCatch(errorPrint(ret));
|
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) {
|
JS_FUNC(moduleTextMeasure) {
|
||||||
assertNotNull(L, "Lua state is null");
|
JS_REQUIRE_ARGS(1);
|
||||||
|
JS_REQUIRE_STRING(0);
|
||||||
|
|
||||||
if(!lua_isstring(L, 1)) {
|
char_t text[1024];
|
||||||
return luaL_error(L, "Text to measure must be a string");
|
jsToString(args_p[0], text, sizeof(text));
|
||||||
}
|
|
||||||
const char_t *text = (const char_t *)lua_tostring(L, 1);
|
|
||||||
|
|
||||||
int32_t w = 0, h = 0;
|
int32_t w = 0, h = 0;
|
||||||
textMeasure(text, &DEFAULT_FONT_TILESET, &w, &h);
|
textMeasure(text, &DEFAULT_FONT_TILESET, &w, &h);
|
||||||
|
|
||||||
vec2 size = { (float_t)w, (float_t)h };
|
vec2 size = { (float_t)w, (float_t)h };
|
||||||
moduleVec2Push(L, size);
|
return moduleVec2Push(size);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void moduleText(lua_State *L) {
|
// ---------------------------------------------------------------------------
|
||||||
assertNotNull(L, "Lua state is null");
|
// Module init
|
||||||
lua_register(L, "textDraw", moduleTextDraw);
|
// ---------------------------------------------------------------------------
|
||||||
lua_register(L, "textMeasure", moduleTextMeasure);
|
|
||||||
|
static void moduleText(void) {
|
||||||
|
jsRegister("textDraw", moduleTextDraw);
|
||||||
|
jsRegister("textMeasure", moduleTextMeasure);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,89 +10,95 @@
|
|||||||
#include "display/texture/texture.h"
|
#include "display/texture/texture.h"
|
||||||
#include "asset/loader/display/assettextureloader.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");
|
static void freeTextureNative(void *ptr, jerry_object_native_info_t *info) {
|
||||||
assertNotNull(tex, "Texture pointer cannot be NULL.");
|
(void)info;
|
||||||
const char *key = luaL_checkstring(l, 2);
|
textureDispose((texture_t *)ptr);
|
||||||
assertNotNull(key, "Key cannot be NULL.");
|
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;
|
// Helper
|
||||||
} else if(stringCompare(key, "height") == 0) {
|
// ---------------------------------------------------------------------------
|
||||||
lua_pushnumber(l, tex->height); return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
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.");
|
// Property getters (read-only)
|
||||||
texture_t *tex = (texture_t *)luaL_checkudata(l, 1, "texture_mt");
|
// ---------------------------------------------------------------------------
|
||||||
assertNotNull(tex, "Texture pointer cannot be NULL.");
|
|
||||||
char buffer[64];
|
JS_FUNC(moduleTextureGetWidth) {
|
||||||
snprintf(buffer, sizeof(buffer), "Texture(%dx%d)", tex->width, tex->height);
|
texture_t *tex = (texture_t *)jerry_object_get_native_ptr(
|
||||||
lua_pushstring(l, buffer);
|
call_info_p->this_value, &TEXTURE_NATIVE_INFO
|
||||||
return 1;
|
);
|
||||||
|
return tex ? jerry_number(tex->width) : jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleTextureGC(lua_State *l) {
|
JS_FUNC(moduleTextureGetHeight) {
|
||||||
assertNotNull(l, "Lua state cannot be NULL.");
|
texture_t *tex = (texture_t *)jerry_object_get_native_ptr(
|
||||||
texture_t *tex = (texture_t *)luaL_checkudata(l, 1, "texture_mt");
|
call_info_p->this_value, &TEXTURE_NATIVE_INFO
|
||||||
assertNotNull(tex, "Texture pointer cannot be NULL.");
|
);
|
||||||
textureDispose(tex);
|
return tex ? jerry_number(tex->height) : jerry_undefined();
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleTextureLoad(lua_State *l) {
|
// ---------------------------------------------------------------------------
|
||||||
assertNotNull(l, "Lua state cannot be NULL.");
|
// Constructor
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
if(!lua_isstring(l, 1)) {
|
JS_FUNC(moduleTextureLoad) {
|
||||||
luaL_error(l, "First argument must be a string filename.");
|
JS_REQUIRE_ARGS(2);
|
||||||
return 0;
|
JS_REQUIRE_STRING(0);
|
||||||
}
|
JS_REQUIRE_NUMBER(1);
|
||||||
if(!lua_isnumber(l, 2)) {
|
|
||||||
luaL_error(l, "Second argument must be a number format.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char_t *filename = lua_tostring(l, 1);
|
char_t filename[256];
|
||||||
assertNotNull(filename, "Filename cannot be NULL.");
|
jsToString(args_p[0], filename, sizeof(filename));
|
||||||
assertStrLenMin(filename, 1, "Filename cannot be empty.");
|
|
||||||
|
|
||||||
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));
|
memoryZero(tex, sizeof(texture_t));
|
||||||
|
|
||||||
textureformat_t format = (textureformat_t)lua_tonumber(l, 2);
|
|
||||||
errorret_t ret = assetTextureLoad(filename, tex, format);
|
errorret_t ret = assetTextureLoad(filename, tex, format);
|
||||||
if(ret.code != ERROR_OK) {
|
if(ret.code != ERROR_OK) {
|
||||||
errorCatch(errorPrint(ret));
|
errorCatch(errorPrint(ret));
|
||||||
luaL_error(l, "Failed to load texture asset: %s", filename);
|
free(tex);
|
||||||
return 0;
|
return JS_THROW("textureLoad: failed to load texture");
|
||||||
}
|
}
|
||||||
|
|
||||||
luaL_getmetatable(l, "texture_mt");
|
jerry_value_t obj = jerry_object();
|
||||||
lua_setmetatable(l, -2);
|
jerry_object_set_native_ptr(obj, &TEXTURE_NATIVE_INFO, tex);
|
||||||
return 1;
|
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")) {
|
static void moduleTexture(void) {
|
||||||
lua_pushcfunction(L, moduleTextureIndex);
|
s_textureProto = jerry_object();
|
||||||
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);
|
|
||||||
|
|
||||||
lua_pushnumber(L, TEXTURE_FORMAT_RGBA);
|
jsDefineProperty(s_textureProto, "width", moduleTextureGetWidth, NULL);
|
||||||
lua_setglobal(L, "TEXTURE_FORMAT_RGBA");
|
jsDefineProperty(s_textureProto, "height", moduleTextureGetHeight, NULL);
|
||||||
|
|
||||||
lua_register(L, "textureLoad", moduleTextureLoad);
|
jsSetInt("TEXTURE_FORMAT_RGBA", (int32_t)TEXTURE_FORMAT_RGBA);
|
||||||
|
|
||||||
|
jsRegister("textureLoad", moduleTextureLoad);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,98 +11,133 @@
|
|||||||
#include "asset/loader/display/assettilesetloader.h"
|
#include "asset/loader/display/assettilesetloader.h"
|
||||||
#include "script/module/math/modulevec4.h"
|
#include "script/module/math/modulevec4.h"
|
||||||
|
|
||||||
static int moduleTilesetIndex(lua_State *l) {
|
// ---------------------------------------------------------------------------
|
||||||
assertNotNull(l, "Lua state cannot be NULL.");
|
// Native info / prototype
|
||||||
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.");
|
|
||||||
|
|
||||||
if(stringCompare(key, "tileWidth") == 0) {
|
static void freeTilesetNative(void *ptr, jerry_object_native_info_t *info) {
|
||||||
lua_pushnumber(l, ts->tileWidth); return 1;
|
(void)info;
|
||||||
} else if(stringCompare(key, "tileHeight") == 0) {
|
free(ptr);
|
||||||
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 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");
|
// Property getters (read-only)
|
||||||
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
|
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) {
|
JS_FUNC(moduleTilesetGetTileHeight) {
|
||||||
assertNotNull(l, "Lua state cannot be NULL.");
|
tileset_t *ts = (tileset_t *)jerry_object_get_native_ptr(
|
||||||
tileset_t *ts = (tileset_t *)luaL_checkudata(l, 1, "tileset_mt");
|
call_info_p->this_value, &TILESET_NATIVE_INFO
|
||||||
assertNotNull(ts, "Tileset pointer cannot be NULL.");
|
);
|
||||||
uint16_t tileIndex = (uint16_t)luaL_checknumber(l, 2);
|
return ts ? jerry_number(ts->tileHeight) : jerry_undefined();
|
||||||
vec4 uv; tilesetTileGetUV(ts, tileIndex, uv);
|
|
||||||
moduleVec4Push(l, uv);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleTilesetPositionGetUV(lua_State *l) {
|
JS_FUNC(moduleTilesetGetTileCount) {
|
||||||
assertNotNull(l, "Lua state cannot be NULL.");
|
tileset_t *ts = (tileset_t *)jerry_object_get_native_ptr(
|
||||||
tileset_t *ts = (tileset_t *)luaL_checkudata(l, 1, "tileset_mt");
|
call_info_p->this_value, &TILESET_NATIVE_INFO
|
||||||
assertNotNull(ts, "Tileset pointer cannot be NULL.");
|
);
|
||||||
uint16_t column = (uint16_t)luaL_checknumber(l, 2);
|
return ts ? jerry_number(ts->tileCount) : jerry_undefined();
|
||||||
uint16_t row = (uint16_t)luaL_checknumber(l, 3);
|
|
||||||
vec4 uv; tilesetPositionGetUV(ts, column, row, uv);
|
|
||||||
moduleVec4Push(l, uv);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleTilesetLoad(lua_State *l) {
|
JS_FUNC(moduleTilesetGetColumns) {
|
||||||
assertNotNull(l, "Lua state cannot be NULL.");
|
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)) {
|
JS_FUNC(moduleTilesetGetRows) {
|
||||||
luaL_error(l, "First argument must be a string filename.");
|
tileset_t *ts = (tileset_t *)jerry_object_get_native_ptr(
|
||||||
return 0;
|
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.");
|
// Functions
|
||||||
assertStrLenMin(filename, 1, "Filename cannot be empty.");
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
tileset_t *tileset = (tileset_t *)lua_newuserdata(l, sizeof(tileset_t));
|
JS_FUNC(modulesTilesetTileGetUV) {
|
||||||
memoryZero(tileset, sizeof(tileset_t));
|
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) {
|
if(ret.code != ERROR_OK) {
|
||||||
errorCatch(errorPrint(ret));
|
errorCatch(errorPrint(ret));
|
||||||
luaL_error(l, "Failed to load tileset asset: %s", filename);
|
free(ts);
|
||||||
return 0;
|
return JS_THROW("tilesetLoad: failed to load tileset");
|
||||||
}
|
}
|
||||||
|
|
||||||
luaL_getmetatable(l, "tileset_mt");
|
jerry_value_t obj = jerry_object();
|
||||||
lua_setmetatable(l, -2);
|
jerry_object_set_native_ptr(obj, &TILESET_NATIVE_INFO, ts);
|
||||||
return 1;
|
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")) {
|
static void moduleTileset(void) {
|
||||||
lua_pushcfunction(L, moduleTilesetIndex);
|
s_tilesetProto = jerry_object();
|
||||||
lua_setfield(L, -2, "__index");
|
|
||||||
lua_pushcfunction(L, moduleTilesetToString);
|
|
||||||
lua_setfield(L, -2, "__tostring");
|
|
||||||
}
|
|
||||||
lua_pop(L, 1);
|
|
||||||
|
|
||||||
lua_register(L, "tilesetLoad", moduleTilesetLoad);
|
jsDefineProperty(s_tilesetProto, "tileWidth", moduleTilesetGetTileWidth, NULL);
|
||||||
lua_register(L, "tilesetTileGetUV", moduleTilesetTileGetUV);
|
jsDefineProperty(s_tilesetProto, "tileHeight", moduleTilesetGetTileHeight, NULL);
|
||||||
lua_register(L, "tilesetPositionGetUV", moduleTilesetPositionGetUV);
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,102 +9,67 @@
|
|||||||
#include "script/module/modulebase.h"
|
#include "script/module/modulebase.h"
|
||||||
#include "entity/entity.h"
|
#include "entity/entity.h"
|
||||||
#include "entity/component/display/entitycamera.h"
|
#include "entity/component/display/entitycamera.h"
|
||||||
|
#include "moduleentityposition.h"
|
||||||
|
|
||||||
typedef struct {
|
// ---- camera prototype ----
|
||||||
entityid_t entityId;
|
|
||||||
componentid_t compId;
|
|
||||||
} entitycam_handle_t;
|
|
||||||
|
|
||||||
/**
|
static jerry_value_t s_camProto = 0;
|
||||||
* __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");
|
|
||||||
|
|
||||||
entitycam_handle_t *h = luaL_checkudata(L, 1, "entitycam_mt");
|
// -- zNear getter/setter --
|
||||||
assertNotNull(h, "invalid entitycam userdata");
|
|
||||||
|
|
||||||
const char *k = luaL_checkstring(L, 2);
|
JS_FUNC(moduleEntityCameraGetZNear) {
|
||||||
assertStrLenMin(k, 1, "property key cannot be empty");
|
entityid_t eid = getEntityId(call_info_p->this_value);
|
||||||
|
componentid_t cid = getCompId(call_info_p->this_value);
|
||||||
if(stringCompare(k, "zNear") == 0) {
|
return jerry_number((double)entityCameraGetZNear(eid, cid));
|
||||||
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(moduleEntityCameraSetZNear) {
|
||||||
* __newindex metamethod for camera component userdata.
|
JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0);
|
||||||
*
|
entityid_t eid = getEntityId(call_info_p->this_value);
|
||||||
* @param L Lua state. Arg 1: entitycam userdata. Arg 2: key string. Arg 3: number.
|
componentid_t cid = getCompId(call_info_p->this_value);
|
||||||
* @return 0.
|
entityCameraSetZNear(eid, cid, (float_t)jerry_value_as_number(args_p[0]));
|
||||||
*/
|
return jerry_undefined();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// -- zFar getter/setter --
|
||||||
* 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).
|
|
||||||
*/
|
|
||||||
static int moduleEntityCameraAdd(lua_State *L) {
|
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
|
||||||
|
|
||||||
entityid_t id = (entityid_t)luaL_checknumber(L, 1);
|
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 a handle object.
|
||||||
|
* Arg 0: entity id (number).
|
||||||
|
*/
|
||||||
|
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);
|
componentid_t comp = entityAddComponent(id, COMPONENT_TYPE_CAMERA);
|
||||||
|
jerry_value_t handle = makeEntityHandle(id, comp);
|
||||||
entitycam_handle_t *h = lua_newuserdata(L, sizeof(entitycam_handle_t));
|
if(s_camProto != 0) jerry_object_set_proto(handle, s_camProto);
|
||||||
assertNotNull(h, "failed to allocate entitycam userdata");
|
return handle;
|
||||||
|
|
||||||
h->entityId = id;
|
|
||||||
h->compId = comp;
|
|
||||||
|
|
||||||
luaL_getmetatable(L, "entitycam_mt");
|
|
||||||
lua_setmetatable(L, -2);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the camera component metatable and entityCameraAdd global.
|
* Registers the camera component prototype and entityCameraAdd global.
|
||||||
*
|
|
||||||
* @param L Lua state.
|
|
||||||
*/
|
*/
|
||||||
static void moduleEntityCamera(lua_State *L) {
|
static void moduleEntityCamera(void) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
s_camProto = jerry_object();
|
||||||
|
|
||||||
luaL_newmetatable(L, "entitycam_mt");
|
jsDefineProperty(s_camProto, "zNear", moduleEntityCameraGetZNear, moduleEntityCameraSetZNear);
|
||||||
lua_pushcfunction(L, moduleEntityCameraIndex);
|
jsDefineProperty(s_camProto, "zFar", moduleEntityCameraGetZFar, moduleEntityCameraSetZFar);
|
||||||
lua_setfield(L, -2, "__index");
|
|
||||||
lua_pushcfunction(L, moduleEntityCameraNewIndex);
|
|
||||||
lua_setfield(L, -2, "__newindex");
|
|
||||||
lua_pop(L, 1);
|
|
||||||
|
|
||||||
lua_register(L, "entityCameraAdd", moduleEntityCameraAdd);
|
jsRegister("entityCameraAdd", moduleEntityCameraAdd);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,73 +9,82 @@
|
|||||||
#include "script/module/modulebase.h"
|
#include "script/module/modulebase.h"
|
||||||
#include "entity/entity.h"
|
#include "entity/entity.h"
|
||||||
#include "entity/component/display/entitymaterial.h"
|
#include "entity/component/display/entitymaterial.h"
|
||||||
|
#include "display/color.h"
|
||||||
|
#include "moduleentityposition.h"
|
||||||
|
|
||||||
typedef struct {
|
// ---- material prototype ----
|
||||||
entityid_t entityId;
|
|
||||||
componentid_t compId;
|
static jerry_value_t s_matProto = 0;
|
||||||
} entitymat_handle_t;
|
|
||||||
|
// -- methods --
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __index metamethod for material component userdata.
|
* Sets the material's unlit color from a color object with r, g, b, a
|
||||||
* Delegates all lookups to the metatable (methods only, no plain properties).
|
* properties (each a number 0-255).
|
||||||
*
|
* Args: colorObj (object).
|
||||||
* @param L Lua state. Arg 1: entitymat userdata. Arg 2: key string.
|
|
||||||
* @return 1.
|
|
||||||
*/
|
*/
|
||||||
static int moduleEntityMaterialIndex(lua_State *L) {
|
JS_FUNC(moduleEntityMaterialSetColor) {
|
||||||
lua_getmetatable(L, 1);
|
JS_REQUIRE_ARGS(1);
|
||||||
lua_getfield(L, -1, luaL_checkstring(L, 2));
|
if(!jerry_value_is_object(args_p[0])) {
|
||||||
return 1;
|
return JS_THROW("expected color object");
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* __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;
|
|
||||||
}
|
}
|
||||||
luaL_error(L, "entitymat: unknown property '%s'", k);
|
entityid_t eid = getEntityId(call_info_p->this_value);
|
||||||
return 0;
|
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.
|
* Adds a material component to an entity and returns a handle object.
|
||||||
*
|
* Arg 0: entity id (number).
|
||||||
* @param L Lua state. Arg 1: entity id (number).
|
|
||||||
* @return 1 (entitymat userdata).
|
|
||||||
*/
|
*/
|
||||||
static int moduleEntityMaterialAdd(lua_State *L) {
|
JS_FUNC(moduleEntityMaterialAdd) {
|
||||||
entityid_t id = (entityid_t)luaL_checknumber(L, 1);
|
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);
|
componentid_t comp = entityAddComponent(id, COMPONENT_TYPE_MATERIAL);
|
||||||
entitymat_handle_t *h = lua_newuserdata(L, sizeof(entitymat_handle_t));
|
jerry_value_t handle = makeEntityHandle(id, comp);
|
||||||
h->entityId = id;
|
if(s_matProto != 0) jerry_object_set_proto(handle, s_matProto);
|
||||||
h->compId = comp;
|
return handle;
|
||||||
luaL_getmetatable(L, "entitymat_mt");
|
|
||||||
lua_setmetatable(L, -2);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the material component metatable and entityMaterialAdd global.
|
* Registers the material component prototype and entityMaterialAdd global.
|
||||||
*
|
|
||||||
* @param L Lua state.
|
|
||||||
*/
|
*/
|
||||||
static void moduleEntityMaterial(lua_State *L) {
|
static void moduleEntityMaterial(void) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
s_matProto = jerry_object();
|
||||||
|
|
||||||
luaL_newmetatable(L, "entitymat_mt");
|
jsDefineMethod(s_matProto, "setColor", moduleEntityMaterialSetColor);
|
||||||
lua_pushcfunction(L, moduleEntityMaterialIndex); lua_setfield(L, -2, "__index");
|
|
||||||
lua_pushcfunction(L, moduleEntityMaterialNewIndex); lua_setfield(L, -2, "__newindex");
|
|
||||||
lua_pop(L, 1);
|
|
||||||
|
|
||||||
lua_register(L, "entityMaterialAdd", moduleEntityMaterialAdd);
|
jsRegister("entityMaterialAdd", moduleEntityMaterialAdd);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,85 +9,65 @@
|
|||||||
#include "script/module/modulebase.h"
|
#include "script/module/modulebase.h"
|
||||||
#include "entity/entity.h"
|
#include "entity/entity.h"
|
||||||
#include "entity/component/display/entitymesh.h"
|
#include "entity/component/display/entitymesh.h"
|
||||||
|
#include "moduleentityposition.h"
|
||||||
|
|
||||||
typedef struct {
|
// ---- mesh prototype ----
|
||||||
entityid_t entityId;
|
|
||||||
componentid_t compId;
|
|
||||||
} entitymesh_handle_t;
|
|
||||||
|
|
||||||
/**
|
static jerry_value_t s_meshProto = 0;
|
||||||
* __index metamethod for mesh component userdata.
|
|
||||||
* Delegates all lookups to the metatable (methods only, no plain properties).
|
// -- methods --
|
||||||
*
|
|
||||||
* @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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates an XZ-aligned plane mesh owned by this component.
|
* Generates an XZ-aligned plane mesh owned by this component.
|
||||||
*
|
* Args: width (number), depth (number).
|
||||||
* @param L Lua state. Arg 1: entitymesh userdata. Arg 2: width. Arg 3: depth.
|
|
||||||
* @return 0.
|
|
||||||
*/
|
*/
|
||||||
static int moduleEntityMeshGeneratePlane(lua_State *L) {
|
JS_FUNC(moduleEntityMeshGeneratePlane) {
|
||||||
entitymesh_handle_t *h = luaL_checkudata(L, 1, "entitymesh_mt");
|
JS_REQUIRE_ARGS(2);
|
||||||
float_t w = (float_t)luaL_checknumber(L, 2);
|
entityid_t eid = getEntityId(call_info_p->this_value);
|
||||||
float_t d = (float_t)luaL_checknumber(L, 3);
|
componentid_t cid = getCompId(call_info_p->this_value);
|
||||||
errorret_t err = entityMeshGeneratePlane(h->entityId, h->compId, w, d);
|
float_t w = (float_t)jerry_value_as_number(args_p[0]);
|
||||||
if(err.code != ERROR_OK) luaL_error(L, "entityMesh: generatePlane failed");
|
float_t d = (float_t)jerry_value_as_number(args_p[1]);
|
||||||
return 0;
|
entityMeshGeneratePlane(eid, cid, w, d);
|
||||||
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a Y-axis capsule mesh owned by this component.
|
* Generates a Y-axis capsule mesh owned by this component.
|
||||||
*
|
* Args: radius (number), halfHeight (number).
|
||||||
* @param L Lua state. Arg 1: entitymesh userdata. Arg 2: radius. Arg 3: halfHeight.
|
|
||||||
* @return 0.
|
|
||||||
*/
|
*/
|
||||||
static int moduleEntityMeshGenerateCapsule(lua_State *L) {
|
JS_FUNC(moduleEntityMeshGenerateCapsule) {
|
||||||
entitymesh_handle_t *h = luaL_checkudata(L, 1, "entitymesh_mt");
|
JS_REQUIRE_ARGS(2);
|
||||||
float_t r = (float_t)luaL_checknumber(L, 2);
|
entityid_t eid = getEntityId(call_info_p->this_value);
|
||||||
float_t hh = (float_t)luaL_checknumber(L, 3);
|
componentid_t cid = getCompId(call_info_p->this_value);
|
||||||
errorret_t err = entityMeshGenerateCapsule(h->entityId, h->compId, r, hh);
|
float_t r = (float_t)jerry_value_as_number(args_p[0]);
|
||||||
if(err.code != ERROR_OK) luaL_error(L, "entityMesh: generateCapsule failed");
|
float_t hh = (float_t)jerry_value_as_number(args_p[1]);
|
||||||
return 0;
|
entityMeshGenerateCapsule(eid, cid, r, hh);
|
||||||
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -- add function --
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a mesh component to an entity and returns its userdata handle.
|
* Adds a mesh component to an entity and returns a handle object.
|
||||||
*
|
* Arg 0: entity id (number).
|
||||||
* @param L Lua state. Arg 1: entity id (number).
|
|
||||||
* @return 1 (entitymesh userdata).
|
|
||||||
*/
|
*/
|
||||||
static int moduleEntityMeshAdd(lua_State *L) {
|
JS_FUNC(moduleEntityMeshAdd) {
|
||||||
entityid_t id = (entityid_t)luaL_checknumber(L, 1);
|
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);
|
componentid_t comp = entityAddComponent(id, COMPONENT_TYPE_MESH);
|
||||||
entitymesh_handle_t *h = lua_newuserdata(L, sizeof(entitymesh_handle_t));
|
jerry_value_t handle = makeEntityHandle(id, comp);
|
||||||
h->entityId = id;
|
if(s_meshProto != 0) jerry_object_set_proto(handle, s_meshProto);
|
||||||
h->compId = comp;
|
return handle;
|
||||||
luaL_getmetatable(L, "entitymesh_mt");
|
|
||||||
lua_setmetatable(L, -2);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the mesh component metatable and entityMeshAdd global.
|
* Registers the mesh component prototype and entityMeshAdd global.
|
||||||
*
|
|
||||||
* @param L Lua state.
|
|
||||||
*/
|
*/
|
||||||
static void moduleEntityMesh(lua_State *L) {
|
static void moduleEntityMesh(void) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
s_meshProto = jerry_object();
|
||||||
|
|
||||||
luaL_newmetatable(L, "entitymesh_mt");
|
jsDefineMethod(s_meshProto, "generatePlane", moduleEntityMeshGeneratePlane);
|
||||||
lua_pushcfunction(L, moduleEntityMeshIndex); lua_setfield(L, -2, "__index");
|
jsDefineMethod(s_meshProto, "generateCapsule", moduleEntityMeshGenerateCapsule);
|
||||||
lua_pushcfunction(L, moduleEntityMeshGeneratePlane); lua_setfield(L, -2, "generatePlane");
|
|
||||||
lua_pushcfunction(L, moduleEntityMeshGenerateCapsule); lua_setfield(L, -2, "generateCapsule");
|
|
||||||
lua_pop(L, 1);
|
|
||||||
|
|
||||||
lua_register(L, "entityMeshAdd", moduleEntityMeshAdd);
|
jsRegister("entityMeshAdd", moduleEntityMeshAdd);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,210 +9,225 @@
|
|||||||
#include "script/module/modulebase.h"
|
#include "script/module/modulebase.h"
|
||||||
#include "entity/entity.h"
|
#include "entity/entity.h"
|
||||||
#include "entity/component/physics/entityphysics.h"
|
#include "entity/component/physics/entityphysics.h"
|
||||||
|
#include "moduleentityposition.h"
|
||||||
|
|
||||||
typedef struct {
|
// ---- physics prototype ----
|
||||||
entityid_t entityId;
|
|
||||||
componentid_t compId;
|
|
||||||
} entityphysics_handle_t;
|
|
||||||
|
|
||||||
/**
|
static jerry_value_t s_physProto = 0;
|
||||||
* __index metamethod for physics component userdata.
|
|
||||||
* Reads velX, velY, velZ, onGround (bool), bodyType; falls through to the
|
// -- velocity getters/setters --
|
||||||
* metatable for method lookups.
|
|
||||||
*
|
JS_FUNC(moduleEntityPhysicsGetVelX) {
|
||||||
* @param L Lua state. Arg 1: entityphysics userdata. Arg 2: key string.
|
entityid_t eid = getEntityId(call_info_p->this_value);
|
||||||
* @return 1.
|
componentid_t cid = getCompId(call_info_p->this_value);
|
||||||
*/
|
|
||||||
static int moduleEntityPhysicsIndex(lua_State *L) {
|
|
||||||
entityphysics_handle_t *h = luaL_checkudata(L, 1, "entityphysics_mt");
|
|
||||||
const char *k = luaL_checkstring(L, 2);
|
|
||||||
vec3 v;
|
vec3 v;
|
||||||
if(stringCompare(k, "velX") == 0) {
|
entityPhysicsGetVelocity(eid, cid, v);
|
||||||
entityPhysicsGetVelocity(h->entityId, h->compId, v);
|
return jerry_number(v[0]);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
JS_FUNC(moduleEntityPhysicsSetVelX) {
|
||||||
* __newindex metamethod for physics component userdata.
|
JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0);
|
||||||
* Writes velX, velY, velZ, bodyType. onGround is read-only. Errors on unknown keys.
|
entityid_t eid = getEntityId(call_info_p->this_value);
|
||||||
*
|
componentid_t cid = getCompId(call_info_p->this_value);
|
||||||
* @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);
|
|
||||||
vec3 v;
|
vec3 v;
|
||||||
if(stringCompare(k, "velX") == 0) {
|
entityPhysicsGetVelocity(eid, cid, v);
|
||||||
entityPhysicsGetVelocity(h->entityId, h->compId, v);
|
v[0] = (float_t)jerry_value_as_number(args_p[0]);
|
||||||
v[0] = (float_t)luaL_checknumber(L, 3);
|
entityPhysicsSetVelocity(eid, cid, v);
|
||||||
entityPhysicsSetVelocity(h->entityId, h->compId, v); return 0;
|
return jerry_undefined();
|
||||||
} else if(stringCompare(k, "velY") == 0) {
|
}
|
||||||
entityPhysicsGetVelocity(h->entityId, h->compId, v);
|
|
||||||
v[1] = (float_t)luaL_checknumber(L, 3);
|
JS_FUNC(moduleEntityPhysicsGetVelY) {
|
||||||
entityPhysicsSetVelocity(h->entityId, h->compId, v); return 0;
|
entityid_t eid = getEntityId(call_info_p->this_value);
|
||||||
} else if(stringCompare(k, "velZ") == 0) {
|
componentid_t cid = getCompId(call_info_p->this_value);
|
||||||
entityPhysicsGetVelocity(h->entityId, h->compId, v);
|
vec3 v;
|
||||||
v[2] = (float_t)luaL_checknumber(L, 3);
|
entityPhysicsGetVelocity(eid, cid, v);
|
||||||
entityPhysicsSetVelocity(h->entityId, h->compId, v); return 0;
|
return jerry_number(v[1]);
|
||||||
} else if(stringCompare(k, "bodyType") == 0) {
|
}
|
||||||
|
|
||||||
|
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(
|
entityPhysicsSetBodyType(
|
||||||
h->entityId, h->compId,
|
eid, cid,
|
||||||
(physicsbodytype_t)luaL_checkinteger(L, 3)
|
(physicsbodytype_t)(int32_t)jerry_value_as_number(args_p[0])
|
||||||
);
|
);
|
||||||
return 0;
|
return jerry_undefined();
|
||||||
} 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -- methods --
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies an immediate velocity impulse to the physics body.
|
* Applies an immediate velocity impulse to the physics body.
|
||||||
*
|
* Args: x, y, z (numbers).
|
||||||
* @param L Lua state. Arg 1: entityphysics userdata. Args 2-4: impulse x, y, z.
|
|
||||||
* @return 0.
|
|
||||||
*/
|
*/
|
||||||
static int moduleEntityPhysicsApplyImpulse(lua_State *L) {
|
JS_FUNC(moduleEntityPhysicsApplyImpulse) {
|
||||||
entityphysics_handle_t *h = luaL_checkudata(L, 1, "entityphysics_mt");
|
JS_REQUIRE_ARGS(3);
|
||||||
|
entityid_t eid = getEntityId(call_info_p->this_value);
|
||||||
|
componentid_t cid = getCompId(call_info_p->this_value);
|
||||||
vec3 impulse = {
|
vec3 impulse = {
|
||||||
(float_t)luaL_checknumber(L, 2),
|
(float_t)jerry_value_as_number(args_p[0]),
|
||||||
(float_t)luaL_checknumber(L, 3),
|
(float_t)jerry_value_as_number(args_p[1]),
|
||||||
(float_t)luaL_checknumber(L, 4)
|
(float_t)jerry_value_as_number(args_p[2])
|
||||||
};
|
};
|
||||||
entityPhysicsApplyImpulse(h->entityId, h->compId, impulse);
|
entityPhysicsApplyImpulse(eid, cid, impulse);
|
||||||
return 0;
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the physics shape to an axis-aligned box.
|
* Sets the physics shape to an axis-aligned box.
|
||||||
*
|
* Args: halfX, halfY, halfZ (numbers).
|
||||||
* @param L Lua state. Arg 1: entityphysics userdata. Args 2-4: half-extents x, y, z.
|
|
||||||
* @return 0.
|
|
||||||
*/
|
*/
|
||||||
static int moduleEntityPhysicsSetShapeCube(lua_State *L) {
|
JS_FUNC(moduleEntityPhysicsSetShapeCube) {
|
||||||
entityphysics_handle_t *h = luaL_checkudata(L, 1, "entityphysics_mt");
|
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;
|
physicsshape_t shape;
|
||||||
shape.type = PHYSICS_SHAPE_CUBE;
|
shape.type = PHYSICS_SHAPE_CUBE;
|
||||||
shape.data.cube.halfExtents[0] = (float_t)luaL_checknumber(L, 2);
|
shape.data.cube.halfExtents[0] = (float_t)jerry_value_as_number(args_p[0]);
|
||||||
shape.data.cube.halfExtents[1] = (float_t)luaL_checknumber(L, 3);
|
shape.data.cube.halfExtents[1] = (float_t)jerry_value_as_number(args_p[1]);
|
||||||
shape.data.cube.halfExtents[2] = (float_t)luaL_checknumber(L, 4);
|
shape.data.cube.halfExtents[2] = (float_t)jerry_value_as_number(args_p[2]);
|
||||||
entityPhysicsSetShape(h->entityId, h->compId, shape);
|
entityPhysicsSetShape(eid, cid, shape);
|
||||||
return 0;
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the physics shape to a sphere.
|
* Sets the physics shape to a sphere.
|
||||||
*
|
* Args: radius (number).
|
||||||
* @param L Lua state. Arg 1: entityphysics userdata. Arg 2: radius.
|
|
||||||
* @return 0.
|
|
||||||
*/
|
*/
|
||||||
static int moduleEntityPhysicsSetShapeSphere(lua_State *L) {
|
JS_FUNC(moduleEntityPhysicsSetShapeSphere) {
|
||||||
entityphysics_handle_t *h = luaL_checkudata(L, 1, "entityphysics_mt");
|
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;
|
physicsshape_t shape;
|
||||||
shape.type = PHYSICS_SHAPE_SPHERE;
|
shape.type = PHYSICS_SHAPE_SPHERE;
|
||||||
shape.data.sphere.radius = (float_t)luaL_checknumber(L, 2);
|
shape.data.sphere.radius = (float_t)jerry_value_as_number(args_p[0]);
|
||||||
entityPhysicsSetShape(h->entityId, h->compId, shape);
|
entityPhysicsSetShape(eid, cid, shape);
|
||||||
return 0;
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the physics shape to a Y-axis capsule.
|
* Sets the physics shape to a Y-axis capsule.
|
||||||
*
|
* Args: radius (number), halfHeight (number).
|
||||||
* @param L Lua state. Arg 1: entityphysics userdata. Arg 2: radius. Arg 3: halfHeight.
|
|
||||||
* @return 0.
|
|
||||||
*/
|
*/
|
||||||
static int moduleEntityPhysicsSetShapeCapsule(lua_State *L) {
|
JS_FUNC(moduleEntityPhysicsSetShapeCapsule) {
|
||||||
entityphysics_handle_t *h = luaL_checkudata(L, 1, "entityphysics_mt");
|
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;
|
physicsshape_t shape;
|
||||||
shape.type = PHYSICS_SHAPE_CAPSULE;
|
shape.type = PHYSICS_SHAPE_CAPSULE;
|
||||||
shape.data.capsule.radius = (float_t)luaL_checknumber(L, 2);
|
shape.data.capsule.radius = (float_t)jerry_value_as_number(args_p[0]);
|
||||||
shape.data.capsule.halfHeight = (float_t)luaL_checknumber(L, 3);
|
shape.data.capsule.halfHeight = (float_t)jerry_value_as_number(args_p[1]);
|
||||||
entityPhysicsSetShape(h->entityId, h->compId, shape);
|
entityPhysicsSetShape(eid, cid, shape);
|
||||||
return 0;
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the physics shape to an infinite plane.
|
* Sets the physics shape to an infinite plane.
|
||||||
*
|
* Args: normalX, normalY, normalZ, distance (numbers).
|
||||||
* @param L Lua state. Arg 1: entityphysics userdata. Args 2-4: normal x, y, z.
|
|
||||||
* Arg 5: distance from origin.
|
|
||||||
* @return 0.
|
|
||||||
*/
|
*/
|
||||||
static int moduleEntityPhysicsSetShapePlane(lua_State *L) {
|
JS_FUNC(moduleEntityPhysicsSetShapePlane) {
|
||||||
entityphysics_handle_t *h = luaL_checkudata(L, 1, "entityphysics_mt");
|
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;
|
physicsshape_t shape;
|
||||||
shape.type = PHYSICS_SHAPE_PLANE;
|
shape.type = PHYSICS_SHAPE_PLANE;
|
||||||
shape.data.plane.normal[0] = (float_t)luaL_checknumber(L, 2);
|
shape.data.plane.normal[0] = (float_t)jerry_value_as_number(args_p[0]);
|
||||||
shape.data.plane.normal[1] = (float_t)luaL_checknumber(L, 3);
|
shape.data.plane.normal[1] = (float_t)jerry_value_as_number(args_p[1]);
|
||||||
shape.data.plane.normal[2] = (float_t)luaL_checknumber(L, 4);
|
shape.data.plane.normal[2] = (float_t)jerry_value_as_number(args_p[2]);
|
||||||
shape.data.plane.distance = (float_t)luaL_checknumber(L, 5);
|
shape.data.plane.distance = (float_t)jerry_value_as_number(args_p[3]);
|
||||||
entityPhysicsSetShape(h->entityId, h->compId, shape);
|
entityPhysicsSetShape(eid, cid, shape);
|
||||||
return 0;
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -- add function --
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a physics component to an entity and returns its userdata handle.
|
* Adds a physics component to an entity and returns a handle object.
|
||||||
*
|
* Arg 0: entity id (number).
|
||||||
* @param L Lua state. Arg 1: entity id (number).
|
|
||||||
* @return 1 (entityphysics userdata).
|
|
||||||
*/
|
*/
|
||||||
static int moduleEntityPhysicsAdd(lua_State *L) {
|
JS_FUNC(moduleEntityPhysicsAdd) {
|
||||||
entityid_t id = (entityid_t)luaL_checknumber(L, 1);
|
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);
|
componentid_t comp = entityAddComponent(id, COMPONENT_TYPE_PHYSICS);
|
||||||
entityphysics_handle_t *h = lua_newuserdata(L, sizeof(entityphysics_handle_t));
|
jerry_value_t handle = makeEntityHandle(id, comp);
|
||||||
h->entityId = id;
|
if(s_physProto != 0) jerry_object_set_proto(handle, s_physProto);
|
||||||
h->compId = comp;
|
return handle;
|
||||||
luaL_getmetatable(L, "entityphysics_mt");
|
|
||||||
lua_setmetatable(L, -2);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the physics component metatable, entityPhysicsAdd global, and
|
* Registers the physics component prototype, entityPhysicsAdd global,
|
||||||
* PHYSICS_BODY_* / PHYSICS_SHAPE_* integer constants.
|
* and PHYSICS_BODY_* / PHYSICS_SHAPE_* integer constants.
|
||||||
*
|
|
||||||
* @param L Lua state.
|
|
||||||
*/
|
*/
|
||||||
static void moduleEntityPhysics(lua_State *L) {
|
static void moduleEntityPhysics(void) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
s_physProto = jerry_object();
|
||||||
|
|
||||||
luaL_newmetatable(L, "entityphysics_mt");
|
jsDefineProperty(s_physProto, "velX", moduleEntityPhysicsGetVelX, moduleEntityPhysicsSetVelX);
|
||||||
lua_pushcfunction(L, moduleEntityPhysicsIndex); lua_setfield(L, -2, "__index");
|
jsDefineProperty(s_physProto, "velY", moduleEntityPhysicsGetVelY, moduleEntityPhysicsSetVelY);
|
||||||
lua_pushcfunction(L, moduleEntityPhysicsNewIndex); lua_setfield(L, -2, "__newindex");
|
jsDefineProperty(s_physProto, "velZ", moduleEntityPhysicsGetVelZ, moduleEntityPhysicsSetVelZ);
|
||||||
lua_pushcfunction(L, moduleEntityPhysicsApplyImpulse); lua_setfield(L, -2, "applyImpulse");
|
jsDefineProperty(s_physProto, "onGround", moduleEntityPhysicsGetOnGround, NULL);
|
||||||
lua_pushcfunction(L, moduleEntityPhysicsSetShapeCube); lua_setfield(L, -2, "setShapeCube");
|
jsDefineProperty(s_physProto, "bodyType", moduleEntityPhysicsGetBodyType, moduleEntityPhysicsSetBodyType);
|
||||||
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);
|
|
||||||
|
|
||||||
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");
|
jsRegister("entityPhysicsAdd", moduleEntityPhysicsAdd);
|
||||||
lua_pushinteger(L, PHYSICS_BODY_DYNAMIC); lua_setglobal(L, "PHYSICS_BODY_DYNAMIC");
|
|
||||||
lua_pushinteger(L, PHYSICS_BODY_KINEMATIC); lua_setglobal(L, "PHYSICS_BODY_KINEMATIC");
|
|
||||||
|
|
||||||
lua_pushinteger(L, PHYSICS_SHAPE_CUBE); lua_setglobal(L, "PHYSICS_SHAPE_CUBE");
|
jsSetInt("PHYSICS_BODY_STATIC", PHYSICS_BODY_STATIC);
|
||||||
lua_pushinteger(L, PHYSICS_SHAPE_SPHERE); lua_setglobal(L, "PHYSICS_SHAPE_SPHERE");
|
jsSetInt("PHYSICS_BODY_DYNAMIC", PHYSICS_BODY_DYNAMIC);
|
||||||
lua_pushinteger(L, PHYSICS_SHAPE_CAPSULE); lua_setglobal(L, "PHYSICS_SHAPE_CAPSULE");
|
jsSetInt("PHYSICS_BODY_KINEMATIC", PHYSICS_BODY_KINEMATIC);
|
||||||
lua_pushinteger(L, PHYSICS_SHAPE_PLANE); lua_setglobal(L, "PHYSICS_SHAPE_PLANE");
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,166 +10,304 @@
|
|||||||
#include "entity/entity.h"
|
#include "entity/entity.h"
|
||||||
#include "entity/component/display/entityposition.h"
|
#include "entity/component/display/entityposition.h"
|
||||||
|
|
||||||
typedef struct {
|
// ---- shared entity handle helpers (included once via this file) ----
|
||||||
entityid_t entityId;
|
|
||||||
componentid_t compId;
|
#ifndef ENTITY_HANDLE_HELPERS
|
||||||
} entitypos_handle_t;
|
#define ENTITY_HANDLE_HELPERS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __index metamethod for position component userdata.
|
* Create a plain JS object carrying _eid and _cid number properties.
|
||||||
* Reads x, y, z, rotX, rotY, rotZ, scaleX, scaleY, scaleZ; falls through to
|
* The caller is responsible for freeing the returned value.
|
||||||
* the metatable for method lookups.
|
|
||||||
*
|
|
||||||
* @param L Lua state. Arg 1: entitypos userdata. Arg 2: key string.
|
|
||||||
* @return 1.
|
|
||||||
*/
|
*/
|
||||||
static int moduleEntityPositionIndex(lua_State *L) {
|
static inline jerry_value_t makeEntityHandle(
|
||||||
entitypos_handle_t *h = luaL_checkudata(L, 1, "entitypos_mt");
|
entityid_t eid,
|
||||||
const char *k = luaL_checkstring(L, 2);
|
componentid_t cid
|
||||||
vec3 v;
|
) {
|
||||||
if(stringCompare(k, "x") == 0) {
|
jerry_value_t obj = jerry_object();
|
||||||
entityPositionGetPosition(h->entityId, h->compId, v);
|
jerry_value_t key;
|
||||||
lua_pushnumber(L, v[0]); return 1;
|
jerry_value_t val;
|
||||||
} else if(stringCompare(k, "y") == 0) {
|
|
||||||
entityPositionGetPosition(h->entityId, h->compId, v);
|
key = jerry_string_sz("_eid");
|
||||||
lua_pushnumber(L, v[1]); return 1;
|
val = jerry_number((double)eid);
|
||||||
} else if(stringCompare(k, "z") == 0) {
|
jerry_object_set(obj, key, val);
|
||||||
entityPositionGetPosition(h->entityId, h->compId, v);
|
jerry_value_free(val);
|
||||||
lua_pushnumber(L, v[2]); return 1;
|
jerry_value_free(key);
|
||||||
} else if(stringCompare(k, "rotX") == 0) {
|
|
||||||
entityPositionGetRotation(h->entityId, h->compId, v);
|
key = jerry_string_sz("_cid");
|
||||||
lua_pushnumber(L, v[0]); return 1;
|
val = jerry_number((double)cid);
|
||||||
} else if(stringCompare(k, "rotY") == 0) {
|
jerry_object_set(obj, key, val);
|
||||||
entityPositionGetRotation(h->entityId, h->compId, v);
|
jerry_value_free(val);
|
||||||
lua_pushnumber(L, v[1]); return 1;
|
jerry_value_free(key);
|
||||||
} else if(stringCompare(k, "rotZ") == 0) {
|
|
||||||
entityPositionGetRotation(h->entityId, h->compId, v);
|
return obj;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __newindex metamethod for position component userdata.
|
* Extract the entity ID stored in a handle object's _eid property.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
static int moduleEntityPositionNewIndex(lua_State *L) {
|
static inline entityid_t getEntityId(jerry_value_t handle) {
|
||||||
entitypos_handle_t *h = luaL_checkudata(L, 1, "entitypos_mt");
|
jerry_value_t key = jerry_string_sz("_eid");
|
||||||
const char *k = luaL_checkstring(L, 2);
|
jerry_value_t val = jerry_object_get(handle, key);
|
||||||
vec3 v;
|
jerry_value_free(key);
|
||||||
if(stringCompare(k, "x") == 0) {
|
entityid_t id = (entityid_t)jerry_value_as_number(val);
|
||||||
entityPositionGetPosition(h->entityId, h->compId, v);
|
jerry_value_free(val);
|
||||||
v[0] = (float_t)luaL_checknumber(L, 3);
|
return id;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
* 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).
|
* Args: target x, y, z [, up x, y, z]. Up 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.
|
|
||||||
*/
|
*/
|
||||||
static int moduleEntityPositionLookAt(lua_State *L) {
|
JS_FUNC(moduleEntityPositionLookAt) {
|
||||||
entitypos_handle_t *h = luaL_checkudata(L, 1, "entitypos_mt");
|
JS_REQUIRE_ARGS(3);
|
||||||
|
entityid_t eid = getEntityId(call_info_p->this_value);
|
||||||
|
componentid_t cid = getCompId(call_info_p->this_value);
|
||||||
vec3 target = {
|
vec3 target = {
|
||||||
(float_t)luaL_checknumber(L, 2),
|
(float_t)jerry_value_as_number(args_p[0]),
|
||||||
(float_t)luaL_checknumber(L, 3),
|
(float_t)jerry_value_as_number(args_p[1]),
|
||||||
(float_t)luaL_checknumber(L, 4)
|
(float_t)jerry_value_as_number(args_p[2])
|
||||||
};
|
};
|
||||||
vec3 up = { 0.0f, 1.0f, 0.0f };
|
vec3 up = { 0.0f, 1.0f, 0.0f };
|
||||||
if(lua_gettop(L) >= 7) {
|
if(args_count >= 6) {
|
||||||
up[0] = (float_t)luaL_checknumber(L, 5);
|
up[0] = (float_t)jerry_value_as_number(args_p[3]);
|
||||||
up[1] = (float_t)luaL_checknumber(L, 6);
|
up[1] = (float_t)jerry_value_as_number(args_p[4]);
|
||||||
up[2] = (float_t)luaL_checknumber(L, 7);
|
up[2] = (float_t)jerry_value_as_number(args_p[5]);
|
||||||
}
|
}
|
||||||
vec3 eye;
|
vec3 eye;
|
||||||
entityPositionGetPosition(h->entityId, h->compId, eye);
|
entityPositionGetPosition(eid, cid, eye);
|
||||||
entityPositionLookAt(h->entityId, h->compId, target, up, eye);
|
entityPositionLookAt(eid, cid, target, up, eye);
|
||||||
return 0;
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -- add function --
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a position component to an entity and returns its userdata handle.
|
* Adds a position component to an entity and returns a handle object.
|
||||||
*
|
* Arg 0: entity id (number).
|
||||||
* @param L Lua state. Arg 1: entity id (number).
|
|
||||||
* @return 1 (entitypos userdata).
|
|
||||||
*/
|
*/
|
||||||
static int moduleEntityPositionAdd(lua_State *L) {
|
JS_FUNC(moduleEntityPositionAdd) {
|
||||||
entityid_t id = (entityid_t)luaL_checknumber(L, 1);
|
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);
|
componentid_t comp = entityAddComponent(id, COMPONENT_TYPE_POSITION);
|
||||||
entitypos_handle_t *h = lua_newuserdata(L, sizeof(entitypos_handle_t));
|
jerry_value_t handle = makeEntityHandle(id, comp);
|
||||||
h->entityId = id;
|
if(s_posProto != 0) jerry_object_set_proto(handle, s_posProto);
|
||||||
h->compId = comp;
|
return handle;
|
||||||
luaL_getmetatable(L, "entitypos_mt");
|
|
||||||
lua_setmetatable(L, -2);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the position component metatable and entityPositionAdd global.
|
* Registers the position component prototype and entityPositionAdd global.
|
||||||
*
|
|
||||||
* @param L Lua state.
|
|
||||||
*/
|
*/
|
||||||
static void moduleEntityPosition(lua_State *L) {
|
static void moduleEntityPosition(void) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
s_posProto = jerry_object();
|
||||||
|
|
||||||
luaL_newmetatable(L, "entitypos_mt");
|
jsDefineProperty(s_posProto, "x", moduleEntityPositionGetX, moduleEntityPositionSetX);
|
||||||
lua_pushcfunction(L, moduleEntityPositionIndex); lua_setfield(L, -2, "__index");
|
jsDefineProperty(s_posProto, "y", moduleEntityPositionGetY, moduleEntityPositionSetY);
|
||||||
lua_pushcfunction(L, moduleEntityPositionNewIndex); lua_setfield(L, -2, "__newindex");
|
jsDefineProperty(s_posProto, "z", moduleEntityPositionGetZ, moduleEntityPositionSetZ);
|
||||||
lua_pushcfunction(L, moduleEntityPositionLookAt); lua_setfield(L, -2, "lookAt");
|
jsDefineProperty(s_posProto, "rotX", moduleEntityPositionGetRotX, moduleEntityPositionSetRotX);
|
||||||
lua_pop(L, 1);
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,87 +15,83 @@
|
|||||||
#include "component/moduleentitymaterial.h"
|
#include "component/moduleentitymaterial.h"
|
||||||
#include "component/moduleentityphysics.h"
|
#include "component/moduleentityphysics.h"
|
||||||
|
|
||||||
|
// ---- component type constants script ----
|
||||||
|
|
||||||
#define X(enumName, type, field, init, dispose) \
|
#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 =
|
static const char_t *COMPONENT_TYPE_SCRIPT =
|
||||||
#include "entity/componentlist.h"
|
#include "entity/componentlist.h"
|
||||||
;
|
;
|
||||||
#undef X
|
#undef X
|
||||||
|
|
||||||
|
// ---- Entity base class script ----
|
||||||
|
|
||||||
static const char_t *ENTITY_SCRIPT =
|
static const char_t *ENTITY_SCRIPT =
|
||||||
"Entity = {}\n"
|
"var Entity = {};\n"
|
||||||
"Entity.__index = 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"
|
"\n"
|
||||||
"Entity.POSITION = COMPONENT_TYPE_POSITION\n"
|
"var _addFns = {};\n"
|
||||||
"Entity.CAMERA = COMPONENT_TYPE_CAMERA\n"
|
"_addFns[COMPONENT_TYPE_POSITION] = entityPositionAdd;\n"
|
||||||
"Entity.MESH = COMPONENT_TYPE_MESH\n"
|
"_addFns[COMPONENT_TYPE_CAMERA] = entityCameraAdd;\n"
|
||||||
"Entity.MATERIAL = COMPONENT_TYPE_MATERIAL\n"
|
"_addFns[COMPONENT_TYPE_MESH] = entityMeshAdd;\n"
|
||||||
"Entity.PHYSICS = COMPONENT_TYPE_PHYSICS\n"
|
"_addFns[COMPONENT_TYPE_MATERIAL] = entityMaterialAdd;\n"
|
||||||
|
"_addFns[COMPONENT_TYPE_PHYSICS] = entityPhysicsAdd;\n"
|
||||||
"\n"
|
"\n"
|
||||||
"local _addFns = {\n"
|
"Entity.create = function() {\n"
|
||||||
" [COMPONENT_TYPE_POSITION] = entityPositionAdd,\n"
|
" var self = Object.create(Entity);\n"
|
||||||
" [COMPONENT_TYPE_CAMERA] = entityCameraAdd,\n"
|
" self.id = entityAdd();\n"
|
||||||
" [COMPONENT_TYPE_MESH] = entityMeshAdd,\n"
|
" return self;\n"
|
||||||
" [COMPONENT_TYPE_MATERIAL] = entityMaterialAdd,\n"
|
"};\n"
|
||||||
" [COMPONENT_TYPE_PHYSICS] = entityPhysicsAdd,\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
"function Entity.new()\n"
|
"Entity.add = function(componentType) {\n"
|
||||||
" return setmetatable({ id = entityAdd() }, Entity)\n"
|
" var fn = _addFns[componentType];\n"
|
||||||
"end\n"
|
" if(!fn) throw new Error('unknown component type: ' + String(componentType));\n"
|
||||||
|
" this[componentType] = fn(this.id);\n"
|
||||||
|
" return this[componentType];\n"
|
||||||
|
"};\n"
|
||||||
"\n"
|
"\n"
|
||||||
"function Entity:add(componentType)\n"
|
"Entity.dispose = function() {\n"
|
||||||
" local fn = _addFns[componentType]\n"
|
" entityRemove(this.id);\n"
|
||||||
" if not fn then error('unknown component type: ' .. tostring(componentType)) end\n"
|
"};\n"
|
||||||
" self[componentType] = fn(self.id)\n"
|
|
||||||
" return self[componentType]\n"
|
|
||||||
"end\n"
|
|
||||||
"\n"
|
|
||||||
"function Entity:dispose()\n"
|
|
||||||
" entityRemove(self.id)\n"
|
|
||||||
"end\n"
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
// ---- module functions ----
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocates a new entity and pushes its id onto the Lua stack.
|
* Allocates a new entity and returns its id as a JS number.
|
||||||
*
|
|
||||||
* @param L Lua state.
|
|
||||||
* @return 1 (entity id number).
|
|
||||||
*/
|
*/
|
||||||
static int moduleEntityAdd(lua_State *L) {
|
JS_FUNC(moduleEntityAdd) {
|
||||||
lua_pushnumber(L, (lua_Number)entityManagerAdd());
|
return jerry_number((double)entityManagerAdd());
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disposes the entity with the given id.
|
* Disposes the entity with the given id.
|
||||||
*
|
* Arg 0: entity id (number).
|
||||||
* @param L Lua state. Arg 1: entity id (number).
|
|
||||||
* @return 0.
|
|
||||||
*/
|
*/
|
||||||
static int moduleEntityRemove(lua_State *L) {
|
JS_FUNC(moduleEntityRemove) {
|
||||||
entityDispose((entityid_t)luaL_checknumber(L, 1));
|
JS_REQUIRE_ARGS(1); JS_REQUIRE_NUMBER(0);
|
||||||
return 0;
|
entityDispose((entityid_t)jerry_value_as_number(args_p[0]));
|
||||||
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers all entity and component modules, component type constants, and
|
* Registers all entity and component modules, component type constants, and
|
||||||
* the Entity base class into the Lua state.
|
* the Entity base object into the JS realm.
|
||||||
*
|
|
||||||
* @param L Lua state.
|
|
||||||
*/
|
*/
|
||||||
static void moduleEntity(lua_State *L) {
|
static void moduleEntity(void) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
moduleEntityPosition();
|
||||||
|
moduleEntityCamera();
|
||||||
|
moduleEntityMesh();
|
||||||
|
moduleEntityMaterial();
|
||||||
|
moduleEntityPhysics();
|
||||||
|
|
||||||
moduleEntityPosition(L);
|
jsRegister("entityAdd", moduleEntityAdd);
|
||||||
moduleEntityCamera(L);
|
jsRegister("entityRemove", moduleEntityRemove);
|
||||||
moduleEntityMesh(L);
|
|
||||||
moduleEntityMaterial(L);
|
|
||||||
moduleEntityPhysics(L);
|
|
||||||
|
|
||||||
lua_register(L, "entityAdd", moduleEntityAdd);
|
jsEvalStr(COMPONENT_TYPE_SCRIPT);
|
||||||
lua_register(L, "entityRemove", moduleEntityRemove);
|
jsEvalStr(ENTITY_SCRIPT);
|
||||||
|
|
||||||
luaL_dostring(L, COMPONENT_TYPE_SCRIPT);
|
|
||||||
luaL_dostring(L, ENTITY_SCRIPT);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,50 +9,35 @@
|
|||||||
#include "script/module/modulebase.h"
|
#include "script/module/modulebase.h"
|
||||||
#include "event/event.h"
|
#include "event/event.h"
|
||||||
|
|
||||||
static int moduleEventSubscribe(lua_State *L) {
|
JS_FUNC(moduleEventSubscribe) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
JS_REQUIRE_ARGS(2);
|
||||||
|
JS_REQUIRE_OBJECT(0);
|
||||||
|
JS_REQUIRE_FUNCTION(1);
|
||||||
|
|
||||||
scriptcontext_t *context = *(scriptcontext_t **)lua_getextraspace(L);
|
event_t *event = (event_t *)jsUnwrapPointer(args_p[0]);
|
||||||
assertNotNull(context, "Script context cannot be NULL");
|
if(event == NULL) return JS_THROW("eventSubscribe: Expected event object");
|
||||||
|
|
||||||
if(!lua_islightuserdata(L, 1)) {
|
jerry_value_t funcCopy = jerry_value_copy(args_p[1]);
|
||||||
luaL_error(L, "eventSubscribe: Expected event pointer as first argument");
|
eventsub_t id = eventSubscribeScriptContext(event, scriptContextCurrent, funcCopy);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!lua_isfunction(L, 2)) {
|
return jerry_number((double)id);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleEventUnsubscribe(lua_State *L) {
|
JS_FUNC(moduleEventUnsubscribe) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
JS_REQUIRE_ARGS(2);
|
||||||
|
JS_REQUIRE_OBJECT(0);
|
||||||
|
JS_REQUIRE_NUMBER(1);
|
||||||
|
|
||||||
if(!lua_islightuserdata(L, 1)) {
|
event_t *event = (event_t *)jsUnwrapPointer(args_p[0]);
|
||||||
luaL_error(L, "eventUnsubscribe: Expected event pointer as first argument");
|
if(event == NULL) return JS_THROW("eventUnsubscribe: Expected event object");
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(!lua_isnumber(L, 2)) {
|
|
||||||
luaL_error(L, "eventUnsubscribe: Expected subscription ID as second argument");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
event_t *event = (event_t *)lua_touserdata(L, 1);
|
eventsub_t id = (eventsub_t)jerry_value_as_number(args_p[1]);
|
||||||
assertNotNull(event, "Event cannot be NULL");
|
|
||||||
eventsub_t id = (eventsub_t)lua_tonumber(L, 2);
|
|
||||||
eventUnsubscribe(event, id);
|
eventUnsubscribe(event, id);
|
||||||
return 0;
|
|
||||||
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void moduleEvent(lua_State *L) {
|
static void moduleEvent(void) {
|
||||||
lua_register(L, "eventSubscribe", moduleEventSubscribe);
|
jsRegister("eventSubscribe", moduleEventSubscribe);
|
||||||
lua_register(L, "eventUnsubscribe", moduleEventUnsubscribe);
|
jsRegister("eventUnsubscribe", moduleEventUnsubscribe);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) 2025 Dominic Masters
|
* Copyright (c) 2026 Dominic Masters
|
||||||
*
|
*
|
||||||
* This software is released under the MIT License.
|
* This software is released under the MIT License.
|
||||||
* https://opensource.org/licenses/MIT
|
* https://opensource.org/licenses/MIT
|
||||||
@@ -9,198 +9,136 @@
|
|||||||
#include "script/module/modulebase.h"
|
#include "script/module/modulebase.h"
|
||||||
#include "input/input.h"
|
#include "input/input.h"
|
||||||
|
|
||||||
static int moduleInputIndex(lua_State *l) {
|
JS_FUNC(moduleInputBind) {
|
||||||
assertNotNull(l, "Lua state cannot be NULL");
|
JS_REQUIRE_ARGS(2);
|
||||||
|
JS_REQUIRE_STRING(0);
|
||||||
|
JS_REQUIRE_NUMBER(1);
|
||||||
|
|
||||||
const char_t *key = luaL_checkstring(l, 2);
|
char_t strBtn[128];
|
||||||
assertStrLenMin(key, 1, "Key cannot be empty.");
|
jsToString(args_p[0], strBtn, sizeof(strBtn));
|
||||||
|
if(strBtn[0] == '\0') return JS_THROW("inputBind: Button name 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const inputaction_t action = (inputaction_t)jerry_value_as_number(args_p[1]);
|
||||||
if(action < INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) {
|
if(action < INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) {
|
||||||
luaL_error(L, "inputBind: Invalid action ID %d with str %s", action, strBtn);
|
return JS_THROW("inputBind: Invalid action ID");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inputbutton_t btn = inputButtonGetByName(strBtn);
|
inputbutton_t btn = inputButtonGetByName(strBtn);
|
||||||
if(btn.type == INPUT_BUTTON_TYPE_NONE) {
|
if(btn.type == INPUT_BUTTON_TYPE_NONE) {
|
||||||
luaL_error(L, "inputBind: Invalid button name '%s'", strBtn);
|
return JS_THROW("inputBind: Invalid button name");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inputBind(btn, action);
|
inputBind(btn, action);
|
||||||
return 0;
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleInputIsDown(lua_State *L) {
|
JS_FUNC(moduleInputIsDown) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
JS_REQUIRE_ARGS(1);
|
||||||
|
JS_REQUIRE_NUMBER(0);
|
||||||
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);
|
|
||||||
|
|
||||||
|
const inputaction_t action = (inputaction_t)jerry_value_as_number(args_p[0]);
|
||||||
if(action < INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) {
|
if(action < INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) {
|
||||||
luaL_error(L, "inputIsDown: Invalid action ID %d", action);
|
return JS_THROW("inputIsDown: Invalid action ID");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_pushboolean(L, inputIsDown(action));
|
return jerry_boolean(inputIsDown(action));
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleInputPressed(lua_State *L) {
|
JS_FUNC(moduleInputPressed) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
JS_REQUIRE_ARGS(1);
|
||||||
|
JS_REQUIRE_NUMBER(0);
|
||||||
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);
|
|
||||||
|
|
||||||
|
const inputaction_t action = (inputaction_t)jerry_value_as_number(args_p[0]);
|
||||||
if(action < INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) {
|
if(action < INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) {
|
||||||
luaL_error(L, "inputPressed: Invalid action ID %d", action);
|
return JS_THROW("inputPressed: Invalid action ID");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_pushboolean(L, inputPressed(action));
|
return jerry_boolean(inputPressed(action));
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleInputReleased(lua_State *L) {
|
JS_FUNC(moduleInputReleased) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
JS_REQUIRE_ARGS(1);
|
||||||
|
JS_REQUIRE_NUMBER(0);
|
||||||
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);
|
|
||||||
|
|
||||||
|
const inputaction_t action = (inputaction_t)jerry_value_as_number(args_p[0]);
|
||||||
if(action < INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) {
|
if(action < INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) {
|
||||||
luaL_error(L, "inputReleased: Invalid action ID %d", action);
|
return JS_THROW("inputReleased: Invalid action ID");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_pushboolean(L, inputReleased(action));
|
return jerry_boolean(inputReleased(action));
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleInputGetValue(lua_State *L) {
|
JS_FUNC(moduleInputGetValue) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
JS_REQUIRE_ARGS(1);
|
||||||
|
JS_REQUIRE_NUMBER(0);
|
||||||
|
|
||||||
if(!lua_isnumber(L, 1)) {
|
const inputaction_t action = (inputaction_t)jerry_value_as_number(args_p[0]);
|
||||||
luaL_error(L, "inputGetValue: Expected action ID as first argument");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const inputaction_t action = (inputaction_t)lua_tonumber(L, 1);
|
|
||||||
if(action < INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) {
|
if(action < INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) {
|
||||||
luaL_error(L, "inputGetValue: Invalid action ID %d", action);
|
return JS_THROW("inputGetValue: Invalid action ID");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_pushnumber(L, inputGetCurrentValue(action));
|
return jerry_number(inputGetCurrentValue(action));
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleInputAxis(lua_State *L) {
|
JS_FUNC(moduleInputAxis) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
JS_REQUIRE_ARGS(2);
|
||||||
|
JS_REQUIRE_NUMBER(0);
|
||||||
|
JS_REQUIRE_NUMBER(1);
|
||||||
|
|
||||||
if(!lua_isnumber(L, 1) || !lua_isnumber(L, 2)) {
|
const inputaction_t neg = (inputaction_t)jerry_value_as_number(args_p[0]);
|
||||||
luaL_error(L, "inputAxis: Expected two action IDs as arguments (neg, pos)");
|
const inputaction_t pos = (inputaction_t)jerry_value_as_number(args_p[1]);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const inputaction_t neg = (inputaction_t)lua_tonumber(L, 1);
|
|
||||||
const inputaction_t pos = (inputaction_t)lua_tonumber(L, 2);
|
|
||||||
|
|
||||||
if(neg < INPUT_ACTION_NULL || neg >= INPUT_ACTION_COUNT) {
|
if(neg < INPUT_ACTION_NULL || neg >= INPUT_ACTION_COUNT) {
|
||||||
luaL_error(L, "inputAxis: Invalid negative action ID %d", neg);
|
return JS_THROW("inputAxis: Invalid negative action ID");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
if(pos < INPUT_ACTION_NULL || pos >= INPUT_ACTION_COUNT) {
|
if(pos < INPUT_ACTION_NULL || pos >= INPUT_ACTION_COUNT) {
|
||||||
luaL_error(L, "inputAxis: Invalid positive action ID %d", pos);
|
return JS_THROW("inputAxis: Invalid positive action ID");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_pushnumber(L, inputAxis(neg, pos));
|
return jerry_number(inputAxis(neg, pos));
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void moduleInput(lua_State *L) {
|
JS_FUNC(moduleInputGetEventAction) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
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
|
#ifdef DUSK_INPUT_KEYBOARD
|
||||||
"INPUT_KEYBOARD = true\n"
|
"var INPUT_KEYBOARD = true;\n"
|
||||||
#endif
|
#endif
|
||||||
#ifdef DUSK_INPUT_GAMEPAD
|
#ifdef DUSK_INPUT_GAMEPAD
|
||||||
"INPUT_GAMEPAD = true\n"
|
"var INPUT_GAMEPAD = true;\n"
|
||||||
#endif
|
#endif
|
||||||
#ifdef DUSK_INPUT_POINTER
|
#ifdef DUSK_INPUT_POINTER
|
||||||
"INPUT_POINTER = true\n"
|
"var INPUT_POINTER = true;\n"
|
||||||
#endif
|
#endif
|
||||||
#ifdef DUSK_INPUT_TOUCH
|
#ifdef DUSK_INPUT_TOUCH
|
||||||
"INPUT_TOUCH = true\n"
|
"var INPUT_TOUCH = true;\n"
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
|
|
||||||
if(luaL_newmetatable(L, "input_mt")) {
|
jerry_value_t evPressed = jsWrapPointer(&INPUT.eventPressed);
|
||||||
lua_pushcfunction(L, moduleInputIndex);
|
jsSetValue("INPUT_EVENT_PRESSED", evPressed);
|
||||||
lua_setfield(L, -2, "__index");
|
jerry_value_free(evPressed);
|
||||||
}
|
|
||||||
lua_pop(L, 1);
|
|
||||||
|
|
||||||
lua_pushlightuserdata(L, &INPUT.eventPressed);
|
jerry_value_t evReleased = jsWrapPointer(&INPUT.eventReleased);
|
||||||
lua_setglobal(L, "INPUT_EVENT_PRESSED");
|
jsSetValue("INPUT_EVENT_RELEASED", evReleased);
|
||||||
|
jerry_value_free(evReleased);
|
||||||
|
|
||||||
lua_pushlightuserdata(L, &INPUT.eventReleased);
|
jsRegister("inputBind", moduleInputBind);
|
||||||
lua_setglobal(L, "INPUT_EVENT_RELEASED");
|
jsRegister("inputIsDown", moduleInputIsDown);
|
||||||
|
jsRegister("inputPressed", moduleInputPressed);
|
||||||
lua_register(L, "inputBind", moduleInputBind);
|
jsRegister("inputReleased", moduleInputReleased);
|
||||||
lua_register(L, "inputIsDown", moduleInputIsDown);
|
jsRegister("inputGetValue", moduleInputGetValue);
|
||||||
lua_register(L, "inputPressed", moduleInputPressed);
|
jsRegister("inputAxis", moduleInputAxis);
|
||||||
lua_register(L, "inputReleased", moduleInputReleased);
|
jsRegister("inputGetEventAction", moduleInputGetEventAction);
|
||||||
lua_register(L, "inputGetValue", moduleInputGetValue);
|
|
||||||
lua_register(L, "inputAxis", moduleInputAxis);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,61 +9,57 @@
|
|||||||
#include "script/module/modulebase.h"
|
#include "script/module/modulebase.h"
|
||||||
#include "locale/localemanager.h"
|
#include "locale/localemanager.h"
|
||||||
|
|
||||||
static int moduleLocaleGetText(lua_State *L) {
|
#define MODULE_LOCALE_MAX_ARGS 16
|
||||||
if(!lua_isstring(L, 1)) {
|
|
||||||
luaL_error(L, "Expected message ID as first argument");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char_t *id = lua_tostring(L, 1);
|
JS_FUNC(moduleLocaleGetText) {
|
||||||
if(id == NULL || strlen(id) == 0) {
|
JS_REQUIRE_ARGS(1);
|
||||||
luaL_error(L, "Message ID cannot be NULL or empty");
|
JS_REQUIRE_STRING(0);
|
||||||
return 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;
|
int32_t plural = 0;
|
||||||
int top = lua_gettop(L);
|
jerry_length_t argStart = 1;
|
||||||
int argStart = 2;
|
|
||||||
|
|
||||||
if(top >= 2 && !lua_isnil(L, 2)) {
|
if(args_count >= 2 && !jerry_value_is_undefined(args_p[1])) {
|
||||||
if(!lua_isnumber(L, 2)) {
|
if(!jerry_value_is_number(args_p[1])) {
|
||||||
luaL_error(L, "Expected plural as second argument");
|
return JS_THROW("localeGetText: Expected plural as second argument");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
plural = (int32_t)lua_tonumber(L, 2);
|
plural = (int32_t)jerry_value_as_number(args_p[1]);
|
||||||
if(plural < 0) {
|
if(plural < 0) return JS_THROW("localeGetText: Plural cannot be negative");
|
||||||
luaL_error(L, "Plural cannot be negative");
|
argStart = 2;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
argStart = 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t argCount = (top >= argStart) ? (size_t)(top - argStart + 1) : 0;
|
size_t argCount = (args_count > argStart) ? (size_t)(args_count - argStart) : 0;
|
||||||
#define MODULE_LOCALE_MAX_ARGS 16
|
|
||||||
assetlocalearg_t argsStack[MODULE_LOCALE_MAX_ARGS];
|
|
||||||
|
|
||||||
if(argCount > MODULE_LOCALE_MAX_ARGS) {
|
if(argCount > MODULE_LOCALE_MAX_ARGS) {
|
||||||
luaL_error(L, "Too many args (max %d)", MODULE_LOCALE_MAX_ARGS);
|
return JS_THROW("localeGetText: Too many format arguments");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assetlocalearg_t argsStack[MODULE_LOCALE_MAX_ARGS];
|
||||||
|
char_t strBufs[MODULE_LOCALE_MAX_ARGS][128];
|
||||||
|
|
||||||
for(size_t i = 0; i < argCount; ++i) {
|
for(size_t i = 0; i < argCount; ++i) {
|
||||||
int luaIndex = argStart + (int)i;
|
jerry_value_t arg = args_p[argStart + i];
|
||||||
if(lua_isinteger(L, luaIndex)) {
|
|
||||||
|
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].type = ASSET_LOCALE_ARG_INT;
|
||||||
argsStack[i].intValue = (int32_t)lua_tonumber(L, luaIndex);
|
argsStack[i].intValue = (int32_t)num;
|
||||||
} 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)) {
|
|
||||||
argsStack[i].type = ASSET_LOCALE_ARG_STRING;
|
|
||||||
argsStack[i].stringValue = lua_tostring(L, luaIndex);
|
|
||||||
} else {
|
} else {
|
||||||
luaL_error(L, "Unsupported localization argument type");
|
argsStack[i].type = ASSET_LOCALE_ARG_FLOAT;
|
||||||
return 0;
|
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 = strBufs[i];
|
||||||
|
} else {
|
||||||
|
return JS_THROW("localeGetText: Unsupported argument type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#undef MODULE_LOCALE_MAX_ARGS
|
|
||||||
|
|
||||||
char_t buffer[1024];
|
char_t buffer[1024];
|
||||||
errorret_t err = localeManagerGetTextArgs(
|
errorret_t err = localeManagerGetTextArgs(
|
||||||
@@ -71,15 +67,12 @@ static int moduleLocaleGetText(lua_State *L) {
|
|||||||
);
|
);
|
||||||
if(err.code != ERROR_OK) {
|
if(err.code != ERROR_OK) {
|
||||||
errorCatch(errorPrint(err));
|
errorCatch(errorPrint(err));
|
||||||
luaL_error(L, "Failed to get localized text for ID '%s'", id);
|
return JS_THROW("localeGetText: Failed to get localized text");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_pushstring(L, buffer);
|
return jerry_string_sz(buffer);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void moduleLocale(lua_State *L) {
|
static void moduleLocale(void) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
jsRegister("localeGetText", moduleLocaleGetText);
|
||||||
lua_register(L, "localeGetText", moduleLocaleGetText);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,293 +7,282 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "script/module/modulebase.h"
|
#include "script/module/modulebase.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "cglm/cglm.h"
|
||||||
#include "modulevec3.h"
|
#include "modulevec3.h"
|
||||||
#include "modulevec4.h"
|
#include "modulevec4.h"
|
||||||
|
|
||||||
/**
|
// Native info for heap-allocated mat4 (float[4][4])
|
||||||
* Pushes a new mat4 userdata onto the Lua stack with the mat4_mt metatable.
|
static void freeMat4Native(void *ptr, jerry_object_native_info_t *info) {
|
||||||
*
|
(void)info;
|
||||||
* @param L Lua state.
|
free(ptr);
|
||||||
* @param m Source matrix to copy.
|
}
|
||||||
*/
|
static const jerry_object_native_info_t MAT4_NATIVE_INFO = {
|
||||||
static void moduleMat4Push(lua_State *L, mat4 m) {
|
.free_cb = freeMat4Native,
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
.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);
|
// Methods
|
||||||
luaL_getmetatable(L, "mat4_mt");
|
// ---------------------------------------------------------------------------
|
||||||
lua_setmetatable(L, -2);
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
JS_FUNC(moduleMatTranspose) {
|
||||||
* Reads a mat4 userdata from the given stack index into out.
|
float_t (*m)[4] = (float_t (*)[4])jerry_object_get_native_ptr(
|
||||||
*
|
call_info_p->this_value, &MAT4_NATIVE_INFO
|
||||||
* @param L Lua state.
|
);
|
||||||
* @param idx Stack index of the mat4 userdata.
|
if(!m) return JS_THROW("mat4.transpose: invalid this");
|
||||||
* @param out Destination matrix.
|
float_t (*r)[4] = (float_t (*)[4])malloc(sizeof(mat4));
|
||||||
*/
|
glm_mat4_transpose_to(m, r);
|
||||||
static void moduleMat4Check(lua_State *L, int idx, mat4 out) {
|
jerry_value_t obj = jerry_object();
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
jerry_object_set_native_ptr(obj, &MAT4_NATIVE_INFO, r);
|
||||||
|
jerry_object_set_proto(obj, s_mat4Proto);
|
||||||
mat4 *m = (mat4 *)luaL_checkudata(L, idx, "mat4_mt");
|
return obj;
|
||||||
glm_mat4_copy(*m, out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
JS_FUNC(moduleMatInverse) {
|
||||||
* __index metamethod for mat4 userdata.
|
float_t (*m)[4] = (float_t (*)[4])jerry_object_get_native_ptr(
|
||||||
* Delegates all lookups to the metatable (methods only).
|
call_info_p->this_value, &MAT4_NATIVE_INFO
|
||||||
*
|
);
|
||||||
* @param L Lua state. Arg 1: mat4 userdata. Arg 2: key string.
|
if(!m) return JS_THROW("mat4.inverse: invalid this");
|
||||||
* @return 1.
|
float_t (*r)[4] = (float_t (*)[4])malloc(sizeof(mat4));
|
||||||
*/
|
glm_mat4_inv(m, r);
|
||||||
static int moduleMat4Index(lua_State *L) {
|
jerry_value_t obj = jerry_object();
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
jerry_object_set_native_ptr(obj, &MAT4_NATIVE_INFO, r);
|
||||||
|
jerry_object_set_proto(obj, s_mat4Proto);
|
||||||
lua_getmetatable(L, 1);
|
return obj;
|
||||||
lua_getfield(L, -1, luaL_checkstring(L, 2));
|
|
||||||
lua_remove(L, -2);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
JS_FUNC(moduleMatDeterminant) {
|
||||||
* __mul metamethod: returns a * b as a new mat4.
|
float_t (*m)[4] = (float_t (*)[4])jerry_object_get_native_ptr(
|
||||||
*
|
call_info_p->this_value, &MAT4_NATIVE_INFO
|
||||||
* @param L Lua state. Arg 1: mat4. Arg 2: mat4.
|
);
|
||||||
* @return 1 (new mat4).
|
if(!m) return JS_THROW("mat4.determinant: invalid this");
|
||||||
*/
|
return jerry_number(glm_mat4_det(m));
|
||||||
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(moduleMatMulVec3) {
|
||||||
* __tostring metamethod: returns a placeholder string.
|
JS_REQUIRE_ARGS(1);
|
||||||
*
|
float_t (*m)[4] = (float_t (*)[4])jerry_object_get_native_ptr(
|
||||||
* @param L Lua state. Arg 1: mat4.
|
call_info_p->this_value, &MAT4_NATIVE_INFO
|
||||||
* @return 1 (string).
|
);
|
||||||
*/
|
if(!m) return JS_THROW("mat4.mulVec3: invalid this");
|
||||||
static int moduleMat4OpToString(lua_State *L) {
|
vec3 vin;
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
if(!moduleVec3Check(args_p[0], vin)) {
|
||||||
|
return JS_THROW("mat4.mulVec3: first argument must be a vec3");
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
float_t w = (args_count >= 2 && jerry_value_is_number(args_p[1]))
|
||||||
lua_pushcfunction(L, moduleMat4Index);
|
? (float_t)jerry_value_as_number(args_p[1])
|
||||||
lua_setfield(L, -2, "__index");
|
: 1.0f;
|
||||||
lua_pushcfunction(L, moduleMat4OpMul);
|
vec3 vout;
|
||||||
lua_setfield(L, -2, "__mul");
|
glm_mat4_mulv3(m, vin, w, vout);
|
||||||
lua_pushcfunction(L, moduleMat4OpToString);
|
return moduleVec3Push(vout);
|
||||||
lua_setfield(L, -2, "__tostring");
|
}
|
||||||
lua_pushcfunction(L, moduleMat4Transpose);
|
|
||||||
lua_setfield(L, -2, "transpose");
|
JS_FUNC(moduleMatMulVec4) {
|
||||||
lua_pushcfunction(L, moduleMat4Inverse);
|
JS_REQUIRE_ARGS(1);
|
||||||
lua_setfield(L, -2, "inverse");
|
float_t (*m)[4] = (float_t (*)[4])jerry_object_get_native_ptr(
|
||||||
lua_pushcfunction(L, moduleMat4MulVec3);
|
call_info_p->this_value, &MAT4_NATIVE_INFO
|
||||||
lua_setfield(L, -2, "mulVec3");
|
);
|
||||||
lua_pushcfunction(L, moduleMat4MulVec4);
|
if(!m) return JS_THROW("mat4.mulVec4: invalid this");
|
||||||
lua_setfield(L, -2, "mulVec4");
|
vec4 vin;
|
||||||
lua_pushcfunction(L, moduleMat4Translate);
|
if(!moduleVec4Check(args_p[0], vin)) {
|
||||||
lua_setfield(L, -2, "translate");
|
return JS_THROW("mat4.mulVec4: first argument must be a vec4");
|
||||||
lua_pushcfunction(L, moduleMat4Scale);
|
}
|
||||||
lua_setfield(L, -2, "scale");
|
vec4 vout;
|
||||||
lua_pushcfunction(L, moduleMat4Identity);
|
glm_mat4_mulv(m, vin, vout);
|
||||||
lua_setfield(L, -2, "identity");
|
return moduleVec4Push(vout);
|
||||||
lua_pushcfunction(L, moduleMat4Determinant);
|
}
|
||||||
lua_setfield(L, -2, "determinant");
|
|
||||||
lua_pop(L, 1);
|
JS_FUNC(moduleMatTranslate) {
|
||||||
|
JS_REQUIRE_ARGS(1);
|
||||||
lua_register(L, "mat4", moduleMat4Create);
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,14 +14,10 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers all math modules: vec2, vec3, vec4, mat4.
|
* Registers all math modules: vec2, vec3, vec4, mat4.
|
||||||
*
|
|
||||||
* @param L Lua state.
|
|
||||||
*/
|
*/
|
||||||
static void moduleMath(lua_State *L) {
|
static void moduleMath(void) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
moduleVec2();
|
||||||
|
moduleVec3();
|
||||||
moduleVec2(L);
|
moduleVec4();
|
||||||
moduleVec3(L);
|
moduleMat4();
|
||||||
moduleVec4(L);
|
|
||||||
moduleMat4(L);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,441 +7,267 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "script/module/modulebase.h"
|
#include "script/module/modulebase.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "cglm/cglm.h"
|
||||||
|
|
||||||
/**
|
// Native info for heap-allocated vec2 (float[2])
|
||||||
* Pushes a new vec2 userdata onto the Lua stack with the vec2_mt metatable.
|
static void freeVec2Native(void *ptr, jerry_object_native_info_t *info) {
|
||||||
*
|
(void)info;
|
||||||
* @param L Lua state.
|
free(ptr);
|
||||||
* @param v Source vector to copy.
|
}
|
||||||
*/
|
static const jerry_object_native_info_t VEC2_NATIVE_INFO = {
|
||||||
static void moduleVec2Push(lua_State *L, vec2 v) {
|
.free_cb = freeVec2Native,
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
.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);
|
// Property getters / setters
|
||||||
luaL_getmetatable(L, "vec2_mt");
|
// ---------------------------------------------------------------------------
|
||||||
lua_setmetatable(L, -2);
|
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
JS_FUNC(moduleVec2GetY) {
|
||||||
* Reads a vec2 userdata from the given stack index into out.
|
float_t *v = (float_t *)jerry_object_get_native_ptr(
|
||||||
*
|
call_info_p->this_value, &VEC2_NATIVE_INFO
|
||||||
* @param L Lua state.
|
);
|
||||||
* @param idx Stack index of the vec2 userdata.
|
return v ? jerry_number(v[1]) : jerry_undefined();
|
||||||
* @param out Destination vector.
|
}
|
||||||
*/
|
JS_FUNC(moduleVec2SetY) {
|
||||||
static void moduleVec2Check(lua_State *L, int idx, vec2 out) {
|
float_t *v = (float_t *)jerry_object_get_native_ptr(
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
call_info_p->this_value, &VEC2_NATIVE_INFO
|
||||||
|
);
|
||||||
vec2 *v = (vec2 *)luaL_checkudata(L, idx, "vec2_mt");
|
if(v && args_count > 0) v[1] = (float_t)jerry_value_as_number(args_p[0]);
|
||||||
glm_vec2_copy(*v, out);
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// ---------------------------------------------------------------------------
|
||||||
* __index metamethod for vec2 userdata.
|
// Methods
|
||||||
* 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");
|
|
||||||
|
|
||||||
vec2 *v = (vec2 *)luaL_checkudata(L, 1, "vec2_mt");
|
JS_FUNC(moduleVec2Dot) {
|
||||||
assertNotNull(v, "invalid vec2 userdata");
|
JS_REQUIRE_ARGS(1);
|
||||||
|
float_t *a = (float_t *)jerry_object_get_native_ptr(
|
||||||
const char *key = luaL_checkstring(L, 2);
|
call_info_p->this_value, &VEC2_NATIVE_INFO
|
||||||
assertStrLenMin(key, 1, "property key cannot be empty");
|
);
|
||||||
|
if(!a) return JS_THROW("vec2.dot: invalid this");
|
||||||
if(lua_isnumber(L, 2)) {
|
float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC2_NATIVE_INFO);
|
||||||
lua_Integer i = lua_tointeger(L, 2);
|
if(!b) return JS_THROW("vec2.dot: argument must be a vec2");
|
||||||
if(i >= 1 && i <= 2) {
|
return jerry_number(glm_vec2_dot(a, b));
|
||||||
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(moduleVec2Length) {
|
||||||
* __newindex metamethod for vec2 userdata.
|
float_t *v = (float_t *)jerry_object_get_native_ptr(
|
||||||
* Writes x, y. Errors on unknown keys.
|
call_info_p->this_value, &VEC2_NATIVE_INFO
|
||||||
*
|
);
|
||||||
* @param L Lua state. Arg 1: vec2 userdata. Arg 2: key string. Arg 3: number.
|
if(!v) return JS_THROW("vec2.length: invalid this");
|
||||||
* @return 0.
|
return jerry_number(glm_vec2_norm(v));
|
||||||
*/
|
|
||||||
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(moduleVec2LengthSq) {
|
||||||
* __add metamethod: returns a + b as a new vec2.
|
float_t *v = (float_t *)jerry_object_get_native_ptr(
|
||||||
*
|
call_info_p->this_value, &VEC2_NATIVE_INFO
|
||||||
* @param L Lua state. Arg 1: vec2. Arg 2: vec2.
|
);
|
||||||
* @return 1 (new vec2).
|
if(!v) return JS_THROW("vec2.lengthSq: invalid this");
|
||||||
*/
|
return jerry_number(glm_vec2_norm2(v));
|
||||||
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(moduleVec2Normalize) {
|
||||||
* __sub metamethod: returns a - b as a new vec2.
|
float_t *v = (float_t *)jerry_object_get_native_ptr(
|
||||||
*
|
call_info_p->this_value, &VEC2_NATIVE_INFO
|
||||||
* @param L Lua state. Arg 1: vec2. Arg 2: vec2.
|
);
|
||||||
* @return 1 (new vec2).
|
if(!v) return JS_THROW("vec2.normalize: invalid this");
|
||||||
*/
|
float_t *r = (float_t *)malloc(sizeof(vec2));
|
||||||
static int moduleVec2OpSub(lua_State *L) {
|
glm_vec2_normalize_to(v, r);
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
jerry_value_t obj = jerry_object();
|
||||||
|
jerry_object_set_native_ptr(obj, &VEC2_NATIVE_INFO, r);
|
||||||
vec2 *a = (vec2 *)luaL_checkudata(L, 1, "vec2_mt");
|
jerry_object_set_proto(obj, s_vec2Proto);
|
||||||
assertNotNull(a, "invalid vec2 userdata");
|
return obj;
|
||||||
|
|
||||||
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(moduleVec2Negate) {
|
||||||
* __mul metamethod: returns v * scalar or scalar * v as a new vec2.
|
float_t *v = (float_t *)jerry_object_get_native_ptr(
|
||||||
*
|
call_info_p->this_value, &VEC2_NATIVE_INFO
|
||||||
* @param L Lua state. Arg 1: vec2 or number. Arg 2: number or vec2.
|
);
|
||||||
* @return 1 (new vec2).
|
if(!v) return JS_THROW("vec2.negate: invalid this");
|
||||||
*/
|
float_t *r = (float_t *)malloc(sizeof(vec2));
|
||||||
static int moduleVec2OpMul(lua_State *L) {
|
glm_vec2_negate_to(v, r);
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
jerry_value_t obj = jerry_object();
|
||||||
|
jerry_object_set_native_ptr(obj, &VEC2_NATIVE_INFO, r);
|
||||||
vec2 r;
|
jerry_object_set_proto(obj, s_vec2Proto);
|
||||||
if(lua_isnumber(L, 1)) {
|
return obj;
|
||||||
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(moduleVec2Add) {
|
||||||
* __div metamethod: returns v / scalar as a new vec2.
|
JS_REQUIRE_ARGS(1);
|
||||||
*
|
float_t *a = (float_t *)jerry_object_get_native_ptr(
|
||||||
* @param L Lua state. Arg 1: vec2. Arg 2: number.
|
call_info_p->this_value, &VEC2_NATIVE_INFO
|
||||||
* @return 1 (new vec2).
|
);
|
||||||
*/
|
if(!a) return JS_THROW("vec2.add: invalid this");
|
||||||
static int moduleVec2OpDiv(lua_State *L) {
|
float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC2_NATIVE_INFO);
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
if(!b) return JS_THROW("vec2.add: argument must be a vec2");
|
||||||
|
float_t *r = (float_t *)malloc(sizeof(vec2));
|
||||||
vec2 *v = (vec2 *)luaL_checkudata(L, 1, "vec2_mt");
|
glm_vec2_add(a, b, r);
|
||||||
assertNotNull(v, "invalid vec2 userdata");
|
jerry_value_t obj = jerry_object();
|
||||||
|
jerry_object_set_native_ptr(obj, &VEC2_NATIVE_INFO, r);
|
||||||
float_t s = (float_t)luaL_checknumber(L, 2);
|
jerry_object_set_proto(obj, s_vec2Proto);
|
||||||
vec2 r;
|
return obj;
|
||||||
glm_vec2_divs(*v, s, r);
|
|
||||||
moduleVec2Push(L, r);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
JS_FUNC(moduleVec2Sub) {
|
||||||
* __unm metamethod: returns -v as a new vec2.
|
JS_REQUIRE_ARGS(1);
|
||||||
*
|
float_t *a = (float_t *)jerry_object_get_native_ptr(
|
||||||
* @param L Lua state. Arg 1: vec2.
|
call_info_p->this_value, &VEC2_NATIVE_INFO
|
||||||
* @return 1 (new vec2).
|
);
|
||||||
*/
|
if(!a) return JS_THROW("vec2.sub: invalid this");
|
||||||
static int moduleVec2OpUnm(lua_State *L) {
|
float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC2_NATIVE_INFO);
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
if(!b) return JS_THROW("vec2.sub: argument must be a vec2");
|
||||||
|
float_t *r = (float_t *)malloc(sizeof(vec2));
|
||||||
vec2 *v = (vec2 *)luaL_checkudata(L, 1, "vec2_mt");
|
glm_vec2_sub(a, b, r);
|
||||||
assertNotNull(v, "invalid vec2 userdata");
|
jerry_value_t obj = jerry_object();
|
||||||
|
jerry_object_set_native_ptr(obj, &VEC2_NATIVE_INFO, r);
|
||||||
vec2 r;
|
jerry_object_set_proto(obj, s_vec2Proto);
|
||||||
glm_vec2_negate_to(*v, r);
|
return obj;
|
||||||
moduleVec2Push(L, r);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
JS_FUNC(moduleVec2Scale) {
|
||||||
* __eq metamethod: component-wise equality test.
|
JS_REQUIRE_ARGS(1);
|
||||||
*
|
JS_REQUIRE_NUMBER(0);
|
||||||
* @param L Lua state. Arg 1: vec2. Arg 2: vec2.
|
float_t *v = (float_t *)jerry_object_get_native_ptr(
|
||||||
* @return 1 (boolean).
|
call_info_p->this_value, &VEC2_NATIVE_INFO
|
||||||
*/
|
);
|
||||||
static int moduleVec2OpEq(lua_State *L) {
|
if(!v) return JS_THROW("vec2.scale: invalid this");
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
float_t s = (float_t)jerry_value_as_number(args_p[0]);
|
||||||
|
float_t *r = (float_t *)malloc(sizeof(vec2));
|
||||||
vec2 *a = (vec2 *)luaL_checkudata(L, 1, "vec2_mt");
|
glm_vec2_scale(v, s, r);
|
||||||
assertNotNull(a, "invalid vec2 userdata");
|
jerry_value_t obj = jerry_object();
|
||||||
|
jerry_object_set_native_ptr(obj, &VEC2_NATIVE_INFO, r);
|
||||||
vec2 *b = (vec2 *)luaL_checkudata(L, 2, "vec2_mt");
|
jerry_object_set_proto(obj, s_vec2Proto);
|
||||||
assertNotNull(b, "invalid vec2 userdata");
|
return obj;
|
||||||
|
|
||||||
lua_pushboolean(L, (*a)[0] == (*b)[0] && (*a)[1] == (*b)[1]);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
JS_FUNC(moduleVec2Lerp) {
|
||||||
* __tostring metamethod: returns a human-readable representation.
|
JS_REQUIRE_ARGS(2);
|
||||||
*
|
JS_REQUIRE_NUMBER(1);
|
||||||
* @param L Lua state. Arg 1: vec2.
|
float_t *a = (float_t *)jerry_object_get_native_ptr(
|
||||||
* @return 1 (string).
|
call_info_p->this_value, &VEC2_NATIVE_INFO
|
||||||
*/
|
);
|
||||||
static int moduleVec2OpToString(lua_State *L) {
|
if(!a) return JS_THROW("vec2.lerp: invalid this");
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
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");
|
||||||
vec2 *v = (vec2 *)luaL_checkudata(L, 1, "vec2_mt");
|
float_t t = (float_t)jerry_value_as_number(args_p[1]);
|
||||||
assertNotNull(v, "invalid vec2 userdata");
|
float_t *r = (float_t *)malloc(sizeof(vec2));
|
||||||
|
glm_vec2_lerp(a, b, t, r);
|
||||||
char buf[64];
|
jerry_value_t obj = jerry_object();
|
||||||
snprintf(buf, sizeof(buf), "vec2(%.3f, %.3f)", (*v)[0], (*v)[1]);
|
jerry_object_set_native_ptr(obj, &VEC2_NATIVE_INFO, r);
|
||||||
lua_pushstring(L, buf);
|
jerry_object_set_proto(obj, s_vec2Proto);
|
||||||
return 1;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
JS_FUNC(moduleVec2Distance) {
|
||||||
* Returns the dot product of two vec2 values.
|
JS_REQUIRE_ARGS(1);
|
||||||
*
|
float_t *a = (float_t *)jerry_object_get_native_ptr(
|
||||||
* @param L Lua state. Arg 1: vec2. Arg 2: vec2.
|
call_info_p->this_value, &VEC2_NATIVE_INFO
|
||||||
* @return 1 (number).
|
);
|
||||||
*/
|
if(!a) return JS_THROW("vec2.distance: invalid this");
|
||||||
static int moduleVec2Dot(lua_State *L) {
|
float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC2_NATIVE_INFO);
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
if(!b) return JS_THROW("vec2.distance: argument must be a vec2");
|
||||||
|
return jerry_number(glm_vec2_distance(a, b));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// ---------------------------------------------------------------------------
|
||||||
* Returns the length (magnitude) of a vec2.
|
// Constructor
|
||||||
*
|
// ---------------------------------------------------------------------------
|
||||||
* @param L Lua state. Arg 1: vec2.
|
|
||||||
* @return 1 (number).
|
|
||||||
*/
|
|
||||||
static int moduleVec2Length(lua_State *L) {
|
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
|
||||||
|
|
||||||
vec2 *v = (vec2 *)luaL_checkudata(L, 1, "vec2_mt");
|
JS_FUNC(moduleVec2Create) {
|
||||||
assertNotNull(v, "invalid vec2 userdata");
|
JS_REQUIRE_ARGS(2);
|
||||||
|
JS_REQUIRE_NUMBER(0);
|
||||||
lua_pushnumber(L, (lua_Number)glm_vec2_norm(*v));
|
JS_REQUIRE_NUMBER(1);
|
||||||
return 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.
|
// Helper: push a cglm vec2 as a new JS object
|
||||||
*
|
// ---------------------------------------------------------------------------
|
||||||
* @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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
* @param v Source float[2] to copy.
|
||||||
* @return 1 (new vec2).
|
* @return Owned jerry_value_t with native ptr set.
|
||||||
*/
|
*/
|
||||||
static int moduleVec2Normalize(lua_State *L) {
|
static inline jerry_value_t moduleVec2Push(const float_t *v) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
float_t *copy = (float_t *)malloc(sizeof(vec2));
|
||||||
|
copy[0] = v[0];
|
||||||
vec2 *v = (vec2 *)luaL_checkudata(L, 1, "vec2_mt");
|
copy[1] = v[1];
|
||||||
assertNotNull(v, "invalid vec2 userdata");
|
jerry_value_t obj = jerry_object();
|
||||||
|
jerry_object_set_native_ptr(obj, &VEC2_NATIVE_INFO, copy);
|
||||||
vec2 r;
|
jerry_object_set_proto(obj, s_vec2Proto);
|
||||||
glm_vec2_normalize_to(*v, r);
|
return obj;
|
||||||
moduleVec2Push(L, r);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// 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.
|
* @param val JS value to read from.
|
||||||
* @return 1 (new vec2).
|
* @param out Destination float[2].
|
||||||
|
* @return true if val carries a valid vec2 native ptr.
|
||||||
*/
|
*/
|
||||||
static int moduleVec2Lerp(lua_State *L) {
|
static inline bool_t moduleVec2Check(jerry_value_t val, float_t *out) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
float_t *v = (float_t *)jerry_object_get_native_ptr(val, &VEC2_NATIVE_INFO);
|
||||||
|
if(!v) return false;
|
||||||
vec2 *a = (vec2 *)luaL_checkudata(L, 1, "vec2_mt");
|
out[0] = v[0];
|
||||||
assertNotNull(a, "invalid vec2 userdata");
|
out[1] = v[1];
|
||||||
|
return true;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Module init
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the distance between two vec2 points.
|
* Creates the vec2 prototype with x/y getter-setter properties and all
|
||||||
*
|
* methods, then registers the global vec2() constructor.
|
||||||
* @param L Lua state. Arg 1: vec2 a. Arg 2: vec2 b.
|
|
||||||
* @return 1 (number).
|
|
||||||
*/
|
*/
|
||||||
static int moduleVec2Distance(lua_State *L) {
|
static void moduleVec2(void) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
s_vec2Proto = jerry_object();
|
||||||
|
|
||||||
vec2 *a = (vec2 *)luaL_checkudata(L, 1, "vec2_mt");
|
jsDefineProperty(s_vec2Proto, "x", moduleVec2GetX, moduleVec2SetX);
|
||||||
assertNotNull(a, "invalid vec2 userdata");
|
jsDefineProperty(s_vec2Proto, "y", moduleVec2GetY, moduleVec2SetY);
|
||||||
|
|
||||||
vec2 *b = (vec2 *)luaL_checkudata(L, 2, "vec2_mt");
|
jsDefineMethod(s_vec2Proto, "dot", moduleVec2Dot);
|
||||||
assertNotNull(b, "invalid vec2 userdata");
|
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));
|
jsRegister("vec2", moduleVec2Create);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,475 +7,303 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "script/module/modulebase.h"
|
#include "script/module/modulebase.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "cglm/cglm.h"
|
||||||
|
|
||||||
/**
|
// Native info for heap-allocated vec3 (float[3])
|
||||||
* Pushes a new vec3 userdata onto the Lua stack with the vec3_mt metatable.
|
static void freeVec3Native(void *ptr, jerry_object_native_info_t *info) {
|
||||||
*
|
(void)info;
|
||||||
* @param L Lua state.
|
free(ptr);
|
||||||
* @param v Source vector to copy.
|
}
|
||||||
*/
|
static const jerry_object_native_info_t VEC3_NATIVE_INFO = {
|
||||||
static void moduleVec3Push(lua_State *L, vec3 v) {
|
.free_cb = freeVec3Native,
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
.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);
|
// Property getters / setters
|
||||||
luaL_getmetatable(L, "vec3_mt");
|
// ---------------------------------------------------------------------------
|
||||||
lua_setmetatable(L, -2);
|
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
JS_FUNC(moduleVec3GetY) {
|
||||||
* Reads a vec3 userdata from the given stack index into out.
|
float_t *v = (float_t *)jerry_object_get_native_ptr(
|
||||||
*
|
call_info_p->this_value, &VEC3_NATIVE_INFO
|
||||||
* @param L Lua state.
|
);
|
||||||
* @param idx Stack index of the vec3 userdata.
|
return v ? jerry_number(v[1]) : jerry_undefined();
|
||||||
* @param out Destination vector.
|
}
|
||||||
*/
|
JS_FUNC(moduleVec3SetY) {
|
||||||
static void moduleVec3Check(lua_State *L, int idx, vec3 out) {
|
float_t *v = (float_t *)jerry_object_get_native_ptr(
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
call_info_p->this_value, &VEC3_NATIVE_INFO
|
||||||
|
);
|
||||||
vec3 *v = (vec3 *)luaL_checkudata(L, idx, "vec3_mt");
|
if(v && args_count > 0) v[1] = (float_t)jerry_value_as_number(args_p[0]);
|
||||||
glm_vec3_copy(*v, out);
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
JS_FUNC(moduleVec3GetZ) {
|
||||||
* __index metamethod for vec3 userdata.
|
float_t *v = (float_t *)jerry_object_get_native_ptr(
|
||||||
* Supports integer indices 1-3 and string keys x, y, z; falls through to the
|
call_info_p->this_value, &VEC3_NATIVE_INFO
|
||||||
* metatable for method lookups.
|
);
|
||||||
*
|
return v ? jerry_number(v[2]) : jerry_undefined();
|
||||||
* @param L Lua state. Arg 1: vec3 userdata. Arg 2: integer or string key.
|
}
|
||||||
* @return 1.
|
JS_FUNC(moduleVec3SetZ) {
|
||||||
*/
|
float_t *v = (float_t *)jerry_object_get_native_ptr(
|
||||||
static int moduleVec3Index(lua_State *L) {
|
call_info_p->this_value, &VEC3_NATIVE_INFO
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
);
|
||||||
|
if(v && args_count > 0) v[2] = (float_t)jerry_value_as_number(args_p[0]);
|
||||||
vec3 *v = (vec3 *)luaL_checkudata(L, 1, "vec3_mt");
|
return jerry_undefined();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// ---------------------------------------------------------------------------
|
||||||
* __newindex metamethod for vec3 userdata.
|
// Methods
|
||||||
* 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");
|
|
||||||
|
|
||||||
vec3 *v = (vec3 *)luaL_checkudata(L, 1, "vec3_mt");
|
JS_FUNC(moduleVec3Dot) {
|
||||||
assertNotNull(v, "invalid vec3 userdata");
|
JS_REQUIRE_ARGS(1);
|
||||||
|
float_t *a = (float_t *)jerry_object_get_native_ptr(
|
||||||
const char *key = luaL_checkstring(L, 2);
|
call_info_p->this_value, &VEC3_NATIVE_INFO
|
||||||
assertStrLenMin(key, 1, "property key cannot be empty");
|
);
|
||||||
|
if(!a) return JS_THROW("vec3.dot: invalid this");
|
||||||
if(stringCompare(key, "x") == 0) {
|
float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC3_NATIVE_INFO);
|
||||||
(*v)[0] = (float_t)luaL_checknumber(L, 3);
|
if(!b) return JS_THROW("vec3.dot: argument must be a vec3");
|
||||||
return 0;
|
return jerry_number(glm_vec3_dot(a, b));
|
||||||
}
|
|
||||||
|
|
||||||
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(moduleVec3Cross) {
|
||||||
* __add metamethod: returns a + b as a new vec3.
|
JS_REQUIRE_ARGS(1);
|
||||||
*
|
float_t *a = (float_t *)jerry_object_get_native_ptr(
|
||||||
* @param L Lua state. Arg 1: vec3. Arg 2: vec3.
|
call_info_p->this_value, &VEC3_NATIVE_INFO
|
||||||
* @return 1 (new vec3).
|
);
|
||||||
*/
|
if(!a) return JS_THROW("vec3.cross: invalid this");
|
||||||
static int moduleVec3OpAdd(lua_State *L) {
|
float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC3_NATIVE_INFO);
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
if(!b) return JS_THROW("vec3.cross: argument must be a vec3");
|
||||||
|
float_t *r = (float_t *)malloc(sizeof(vec3));
|
||||||
vec3 *a = (vec3 *)luaL_checkudata(L, 1, "vec3_mt");
|
glm_vec3_cross(a, b, r);
|
||||||
assertNotNull(a, "invalid vec3 userdata");
|
jerry_value_t obj = jerry_object();
|
||||||
|
jerry_object_set_native_ptr(obj, &VEC3_NATIVE_INFO, r);
|
||||||
vec3 *b = (vec3 *)luaL_checkudata(L, 2, "vec3_mt");
|
jerry_object_set_proto(obj, s_vec3Proto);
|
||||||
assertNotNull(b, "invalid vec3 userdata");
|
return obj;
|
||||||
|
|
||||||
vec3 r;
|
|
||||||
glm_vec3_add(*a, *b, r);
|
|
||||||
moduleVec3Push(L, r);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
JS_FUNC(moduleVec3Length) {
|
||||||
* __sub metamethod: returns a - b as a new vec3.
|
float_t *v = (float_t *)jerry_object_get_native_ptr(
|
||||||
*
|
call_info_p->this_value, &VEC3_NATIVE_INFO
|
||||||
* @param L Lua state. Arg 1: vec3. Arg 2: vec3.
|
);
|
||||||
* @return 1 (new vec3).
|
if(!v) return JS_THROW("vec3.length: invalid this");
|
||||||
*/
|
return jerry_number(glm_vec3_norm(v));
|
||||||
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(moduleVec3LengthSq) {
|
||||||
* __mul metamethod: returns v * scalar or scalar * v as a new vec3.
|
float_t *v = (float_t *)jerry_object_get_native_ptr(
|
||||||
*
|
call_info_p->this_value, &VEC3_NATIVE_INFO
|
||||||
* @param L Lua state. Arg 1: vec3 or number. Arg 2: number or vec3.
|
);
|
||||||
* @return 1 (new vec3).
|
if(!v) return JS_THROW("vec3.lengthSq: invalid this");
|
||||||
*/
|
return jerry_number(glm_vec3_norm2(v));
|
||||||
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(moduleVec3Normalize) {
|
||||||
* __div metamethod: returns v / scalar as a new vec3.
|
float_t *v = (float_t *)jerry_object_get_native_ptr(
|
||||||
*
|
call_info_p->this_value, &VEC3_NATIVE_INFO
|
||||||
* @param L Lua state. Arg 1: vec3. Arg 2: number.
|
);
|
||||||
* @return 1 (new vec3).
|
if(!v) return JS_THROW("vec3.normalize: invalid this");
|
||||||
*/
|
float_t *r = (float_t *)malloc(sizeof(vec3));
|
||||||
static int moduleVec3OpDiv(lua_State *L) {
|
glm_vec3_normalize_to(v, r);
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
jerry_value_t obj = jerry_object();
|
||||||
|
jerry_object_set_native_ptr(obj, &VEC3_NATIVE_INFO, r);
|
||||||
vec3 *v = (vec3 *)luaL_checkudata(L, 1, "vec3_mt");
|
jerry_object_set_proto(obj, s_vec3Proto);
|
||||||
assertNotNull(v, "invalid vec3 userdata");
|
return obj;
|
||||||
|
|
||||||
float_t s = (float_t)luaL_checknumber(L, 2);
|
|
||||||
vec3 r;
|
|
||||||
glm_vec3_divs(*v, s, r);
|
|
||||||
moduleVec3Push(L, r);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
JS_FUNC(moduleVec3Negate) {
|
||||||
* __unm metamethod: returns -v as a new vec3.
|
float_t *v = (float_t *)jerry_object_get_native_ptr(
|
||||||
*
|
call_info_p->this_value, &VEC3_NATIVE_INFO
|
||||||
* @param L Lua state. Arg 1: vec3.
|
);
|
||||||
* @return 1 (new vec3).
|
if(!v) return JS_THROW("vec3.negate: invalid this");
|
||||||
*/
|
float_t *r = (float_t *)malloc(sizeof(vec3));
|
||||||
static int moduleVec3OpUnm(lua_State *L) {
|
glm_vec3_negate_to(v, r);
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
jerry_value_t obj = jerry_object();
|
||||||
|
jerry_object_set_native_ptr(obj, &VEC3_NATIVE_INFO, r);
|
||||||
vec3 *v = (vec3 *)luaL_checkudata(L, 1, "vec3_mt");
|
jerry_object_set_proto(obj, s_vec3Proto);
|
||||||
assertNotNull(v, "invalid vec3 userdata");
|
return obj;
|
||||||
|
|
||||||
vec3 r;
|
|
||||||
glm_vec3_negate_to(*v, r);
|
|
||||||
moduleVec3Push(L, r);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
JS_FUNC(moduleVec3Add) {
|
||||||
* __eq metamethod: component-wise equality test.
|
JS_REQUIRE_ARGS(1);
|
||||||
*
|
float_t *a = (float_t *)jerry_object_get_native_ptr(
|
||||||
* @param L Lua state. Arg 1: vec3. Arg 2: vec3.
|
call_info_p->this_value, &VEC3_NATIVE_INFO
|
||||||
* @return 1 (boolean).
|
);
|
||||||
*/
|
if(!a) return JS_THROW("vec3.add: invalid this");
|
||||||
static int moduleVec3OpEq(lua_State *L) {
|
float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC3_NATIVE_INFO);
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
if(!b) return JS_THROW("vec3.add: argument must be a vec3");
|
||||||
|
float_t *r = (float_t *)malloc(sizeof(vec3));
|
||||||
vec3 *a = (vec3 *)luaL_checkudata(L, 1, "vec3_mt");
|
glm_vec3_add(a, b, r);
|
||||||
assertNotNull(a, "invalid vec3 userdata");
|
jerry_value_t obj = jerry_object();
|
||||||
|
jerry_object_set_native_ptr(obj, &VEC3_NATIVE_INFO, r);
|
||||||
vec3 *b = (vec3 *)luaL_checkudata(L, 2, "vec3_mt");
|
jerry_object_set_proto(obj, s_vec3Proto);
|
||||||
assertNotNull(b, "invalid vec3 userdata");
|
return obj;
|
||||||
|
|
||||||
lua_pushboolean(L, (*a)[0] == (*b)[0] && (*a)[1] == (*b)[1] && (*a)[2] == (*b)[2]);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
JS_FUNC(moduleVec3Sub) {
|
||||||
* __tostring metamethod: returns a human-readable representation.
|
JS_REQUIRE_ARGS(1);
|
||||||
*
|
float_t *a = (float_t *)jerry_object_get_native_ptr(
|
||||||
* @param L Lua state. Arg 1: vec3.
|
call_info_p->this_value, &VEC3_NATIVE_INFO
|
||||||
* @return 1 (string).
|
);
|
||||||
*/
|
if(!a) return JS_THROW("vec3.sub: invalid this");
|
||||||
static int moduleVec3OpToString(lua_State *L) {
|
float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC3_NATIVE_INFO);
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
if(!b) return JS_THROW("vec3.sub: argument must be a vec3");
|
||||||
|
float_t *r = (float_t *)malloc(sizeof(vec3));
|
||||||
vec3 *v = (vec3 *)luaL_checkudata(L, 1, "vec3_mt");
|
glm_vec3_sub(a, b, r);
|
||||||
assertNotNull(v, "invalid vec3 userdata");
|
jerry_value_t obj = jerry_object();
|
||||||
|
jerry_object_set_native_ptr(obj, &VEC3_NATIVE_INFO, r);
|
||||||
char buf[80];
|
jerry_object_set_proto(obj, s_vec3Proto);
|
||||||
snprintf(buf, sizeof(buf), "vec3(%.3f, %.3f, %.3f)", (*v)[0], (*v)[1], (*v)[2]);
|
return obj;
|
||||||
lua_pushstring(L, buf);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
JS_FUNC(moduleVec3Scale) {
|
||||||
* Returns the dot product of two vec3 values.
|
JS_REQUIRE_ARGS(1);
|
||||||
*
|
JS_REQUIRE_NUMBER(0);
|
||||||
* @param L Lua state. Arg 1: vec3. Arg 2: vec3.
|
float_t *v = (float_t *)jerry_object_get_native_ptr(
|
||||||
* @return 1 (number).
|
call_info_p->this_value, &VEC3_NATIVE_INFO
|
||||||
*/
|
);
|
||||||
static int moduleVec3Dot(lua_State *L) {
|
if(!v) return JS_THROW("vec3.scale: invalid this");
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
float_t s = (float_t)jerry_value_as_number(args_p[0]);
|
||||||
|
float_t *r = (float_t *)malloc(sizeof(vec3));
|
||||||
vec3 *a = (vec3 *)luaL_checkudata(L, 1, "vec3_mt");
|
glm_vec3_scale(v, s, r);
|
||||||
assertNotNull(a, "invalid vec3 userdata");
|
jerry_value_t obj = jerry_object();
|
||||||
|
jerry_object_set_native_ptr(obj, &VEC3_NATIVE_INFO, r);
|
||||||
vec3 *b = (vec3 *)luaL_checkudata(L, 2, "vec3_mt");
|
jerry_object_set_proto(obj, s_vec3Proto);
|
||||||
assertNotNull(b, "invalid vec3 userdata");
|
return obj;
|
||||||
|
|
||||||
lua_pushnumber(L, (lua_Number)glm_vec3_dot(*a, *b));
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
JS_FUNC(moduleVec3Lerp) {
|
||||||
* Returns the cross product of two vec3 values as a new vec3.
|
JS_REQUIRE_ARGS(2);
|
||||||
*
|
JS_REQUIRE_NUMBER(1);
|
||||||
* @param L Lua state. Arg 1: vec3. Arg 2: vec3.
|
float_t *a = (float_t *)jerry_object_get_native_ptr(
|
||||||
* @return 1 (new vec3).
|
call_info_p->this_value, &VEC3_NATIVE_INFO
|
||||||
*/
|
);
|
||||||
static int moduleVec3Cross(lua_State *L) {
|
if(!a) return JS_THROW("vec3.lerp: invalid this");
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
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");
|
||||||
vec3 *a = (vec3 *)luaL_checkudata(L, 1, "vec3_mt");
|
float_t t = (float_t)jerry_value_as_number(args_p[1]);
|
||||||
assertNotNull(a, "invalid vec3 userdata");
|
float_t *r = (float_t *)malloc(sizeof(vec3));
|
||||||
|
glm_vec3_lerp(a, b, t, r);
|
||||||
vec3 *b = (vec3 *)luaL_checkudata(L, 2, "vec3_mt");
|
jerry_value_t obj = jerry_object();
|
||||||
assertNotNull(b, "invalid vec3 userdata");
|
jerry_object_set_native_ptr(obj, &VEC3_NATIVE_INFO, r);
|
||||||
|
jerry_object_set_proto(obj, s_vec3Proto);
|
||||||
vec3 r;
|
return obj;
|
||||||
glm_vec3_cross(*a, *b, r);
|
|
||||||
moduleVec3Push(L, r);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
JS_FUNC(moduleVec3Distance) {
|
||||||
* Returns the length (magnitude) of a vec3.
|
JS_REQUIRE_ARGS(1);
|
||||||
*
|
float_t *a = (float_t *)jerry_object_get_native_ptr(
|
||||||
* @param L Lua state. Arg 1: vec3.
|
call_info_p->this_value, &VEC3_NATIVE_INFO
|
||||||
* @return 1 (number).
|
);
|
||||||
*/
|
if(!a) return JS_THROW("vec3.distance: invalid this");
|
||||||
static int moduleVec3Length(lua_State *L) {
|
float_t *b = (float_t *)jerry_object_get_native_ptr(args_p[0], &VEC3_NATIVE_INFO);
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
if(!b) return JS_THROW("vec3.distance: argument must be a vec3");
|
||||||
|
return jerry_number(glm_vec3_distance(a, b));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// ---------------------------------------------------------------------------
|
||||||
* Returns the squared length of a vec3.
|
// Constructor
|
||||||
*
|
// ---------------------------------------------------------------------------
|
||||||
* @param L Lua state. Arg 1: vec3.
|
|
||||||
* @return 1 (number).
|
|
||||||
*/
|
|
||||||
static int moduleVec3LengthSq(lua_State *L) {
|
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
|
||||||
|
|
||||||
vec3 *v = (vec3 *)luaL_checkudata(L, 1, "vec3_mt");
|
JS_FUNC(moduleVec3Create) {
|
||||||
assertNotNull(v, "invalid vec3 userdata");
|
JS_REQUIRE_ARGS(3);
|
||||||
|
JS_REQUIRE_NUMBER(0);
|
||||||
lua_pushnumber(L, (lua_Number)glm_vec3_norm2(*v));
|
JS_REQUIRE_NUMBER(1);
|
||||||
return 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.
|
// Helper: push a cglm vec3 as a new JS object
|
||||||
*
|
// ---------------------------------------------------------------------------
|
||||||
* @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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
* @param v Source float[3] to copy.
|
||||||
* @return 1 (new vec3).
|
* @return Owned jerry_value_t with native ptr set.
|
||||||
*/
|
*/
|
||||||
static int moduleVec3Lerp(lua_State *L) {
|
static inline jerry_value_t moduleVec3Push(const float_t *v) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
float_t *copy = (float_t *)malloc(sizeof(vec3));
|
||||||
|
copy[0] = v[0];
|
||||||
vec3 *a = (vec3 *)luaL_checkudata(L, 1, "vec3_mt");
|
copy[1] = v[1];
|
||||||
assertNotNull(a, "invalid vec3 userdata");
|
copy[2] = v[2];
|
||||||
|
jerry_value_t obj = jerry_object();
|
||||||
vec3 *b = (vec3 *)luaL_checkudata(L, 2, "vec3_mt");
|
jerry_object_set_native_ptr(obj, &VEC3_NATIVE_INFO, copy);
|
||||||
assertNotNull(b, "invalid vec3 userdata");
|
jerry_object_set_proto(obj, s_vec3Proto);
|
||||||
|
return obj;
|
||||||
float_t t = (float_t)luaL_checknumber(L, 3);
|
|
||||||
vec3 r;
|
|
||||||
glm_vec3_lerp(*a, *b, t, r);
|
|
||||||
moduleVec3Push(L, r);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// 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.
|
* @param val JS value to read from.
|
||||||
* @return 1 (number).
|
* @param out Destination float[3].
|
||||||
|
* @return true if val carries a valid vec3 native ptr.
|
||||||
*/
|
*/
|
||||||
static int moduleVec3Distance(lua_State *L) {
|
static inline bool_t moduleVec3Check(jerry_value_t val, float_t *out) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
float_t *v = (float_t *)jerry_object_get_native_ptr(val, &VEC3_NATIVE_INFO);
|
||||||
|
if(!v) return false;
|
||||||
vec3 *a = (vec3 *)luaL_checkudata(L, 1, "vec3_mt");
|
out[0] = v[0];
|
||||||
assertNotNull(a, "invalid vec3 userdata");
|
out[1] = v[1];
|
||||||
|
out[2] = v[2];
|
||||||
vec3 *b = (vec3 *)luaL_checkudata(L, 2, "vec3_mt");
|
return true;
|
||||||
assertNotNull(b, "invalid vec3 userdata");
|
|
||||||
|
|
||||||
lua_pushnumber(L, (lua_Number)glm_vec3_distance(*a, *b));
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Module init
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a negated copy of a vec3.
|
* Creates the vec3 prototype with x/y/z getter-setter properties and all
|
||||||
*
|
* methods, then registers the global vec3() constructor.
|
||||||
* @param L Lua state. Arg 1: vec3.
|
|
||||||
* @return 1 (new vec3).
|
|
||||||
*/
|
*/
|
||||||
static int moduleVec3Negate(lua_State *L) {
|
static void moduleVec3(void) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
s_vec3Proto = jerry_object();
|
||||||
|
|
||||||
vec3 *v = (vec3 *)luaL_checkudata(L, 1, "vec3_mt");
|
jsDefineProperty(s_vec3Proto, "x", moduleVec3GetX, moduleVec3SetX);
|
||||||
assertNotNull(v, "invalid vec3 userdata");
|
jsDefineProperty(s_vec3Proto, "y", moduleVec3GetY, moduleVec3SetY);
|
||||||
|
jsDefineProperty(s_vec3Proto, "z", moduleVec3GetZ, moduleVec3SetZ);
|
||||||
|
|
||||||
vec3 r;
|
jsDefineMethod(s_vec3Proto, "dot", moduleVec3Dot);
|
||||||
glm_vec3_negate_to(*v, r);
|
jsDefineMethod(s_vec3Proto, "cross", moduleVec3Cross);
|
||||||
moduleVec3Push(L, r);
|
jsDefineMethod(s_vec3Proto, "length", moduleVec3Length);
|
||||||
return 1;
|
jsDefineMethod(s_vec3Proto, "lengthSq", moduleVec3LengthSq);
|
||||||
}
|
jsDefineMethod(s_vec3Proto, "normalize", moduleVec3Normalize);
|
||||||
|
jsDefineMethod(s_vec3Proto, "negate", moduleVec3Negate);
|
||||||
/**
|
jsDefineMethod(s_vec3Proto, "add", moduleVec3Add);
|
||||||
* Constructor: creates a vec3 from three optional numbers (defaults to 0).
|
jsDefineMethod(s_vec3Proto, "sub", moduleVec3Sub);
|
||||||
*
|
jsDefineMethod(s_vec3Proto, "scale", moduleVec3Scale);
|
||||||
* @param L Lua state. Arg 1 (optional): x. Arg 2 (optional): y. Arg 3 (optional): z.
|
jsDefineMethod(s_vec3Proto, "lerp", moduleVec3Lerp);
|
||||||
* @return 1 (new vec3).
|
jsDefineMethod(s_vec3Proto, "distance", moduleVec3Distance);
|
||||||
*/
|
|
||||||
static int moduleVec3Create(lua_State *L) {
|
jsRegister("vec3", moduleVec3Create);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,445 +7,358 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "script/module/modulebase.h"
|
#include "script/module/modulebase.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "cglm/cglm.h"
|
||||||
|
|
||||||
/**
|
// Native info for heap-allocated vec4 (float[4])
|
||||||
* Pushes a new vec4 userdata onto the Lua stack with the vec4_mt metatable.
|
static void freeVec4Native(void *ptr, jerry_object_native_info_t *info) {
|
||||||
*
|
(void)info;
|
||||||
* @param L Lua state.
|
free(ptr);
|
||||||
* @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);
|
|
||||||
}
|
}
|
||||||
|
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.
|
// Property getters / setters (x/u0, y/v0, z/u1, w/v1)
|
||||||
*
|
// ---------------------------------------------------------------------------
|
||||||
* @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");
|
|
||||||
|
|
||||||
vec4 *v = (vec4 *)luaL_checkudata(L, idx, "vec4_mt");
|
JS_FUNC(moduleVec4GetX) {
|
||||||
glm_vec4_copy(*v, out);
|
float_t *v = (float_t *)jerry_object_get_native_ptr(
|
||||||
}
|
call_info_p->this_value, &VEC4_NATIVE_INFO
|
||||||
|
|
||||||
/**
|
|
||||||
* __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]
|
|
||||||
);
|
);
|
||||||
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.
|
* @param v Source float[4] to copy.
|
||||||
* @return 1 (string).
|
* @return Owned jerry_value_t with native ptr set.
|
||||||
*/
|
*/
|
||||||
static int moduleVec4OpToString(lua_State *L) {
|
static inline jerry_value_t moduleVec4Push(const float_t *v) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
float_t *copy = (float_t *)malloc(sizeof(vec4));
|
||||||
|
copy[0] = v[0];
|
||||||
vec4 *v = (vec4 *)luaL_checkudata(L, 1, "vec4_mt");
|
copy[1] = v[1];
|
||||||
assertNotNull(v, "invalid vec4 userdata");
|
copy[2] = v[2];
|
||||||
|
copy[3] = v[3];
|
||||||
char buf[96];
|
jerry_value_t obj = jerry_object();
|
||||||
snprintf(buf, sizeof(buf), "vec4(%.3f, %.3f, %.3f, %.3f)", (*v)[0], (*v)[1], (*v)[2], (*v)[3]);
|
jerry_object_set_native_ptr(obj, &VEC4_NATIVE_INFO, copy);
|
||||||
lua_pushstring(L, buf);
|
jerry_object_set_proto(obj, s_vec4Proto);
|
||||||
return 1;
|
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.
|
* @param val JS value to read from.
|
||||||
* @return 1 (number).
|
* @param out Destination float[4].
|
||||||
|
* @return true if val carries a valid vec4 native ptr.
|
||||||
*/
|
*/
|
||||||
static int moduleVec4Dot(lua_State *L) {
|
static inline bool_t moduleVec4Check(jerry_value_t val, float_t *out) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
float_t *v = (float_t *)jerry_object_get_native_ptr(val, &VEC4_NATIVE_INFO);
|
||||||
|
if(!v) return false;
|
||||||
vec4 *a = (vec4 *)luaL_checkudata(L, 1, "vec4_mt");
|
out[0] = v[0];
|
||||||
assertNotNull(a, "invalid vec4 userdata");
|
out[1] = v[1];
|
||||||
|
out[2] = v[2];
|
||||||
vec4 *b = (vec4 *)luaL_checkudata(L, 2, "vec4_mt");
|
out[3] = v[3];
|
||||||
assertNotNull(b, "invalid vec4 userdata");
|
return true;
|
||||||
|
|
||||||
lua_pushnumber(L, (lua_Number)glm_vec4_dot(*a, *b));
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Module init
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the length (magnitude) of a vec4.
|
* 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
|
||||||
* @param L Lua state. Arg 1: vec4.
|
* vec4() constructor.
|
||||||
* @return 1 (number).
|
|
||||||
*/
|
*/
|
||||||
static int moduleVec4Length(lua_State *L) {
|
static void moduleVec4(void) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
s_vec4Proto = jerry_object();
|
||||||
|
|
||||||
vec4 *v = (vec4 *)luaL_checkudata(L, 1, "vec4_mt");
|
// Primary component names
|
||||||
assertNotNull(v, "invalid vec4 userdata");
|
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));
|
// UV alias names (same backing components)
|
||||||
return 1;
|
jsDefineProperty(s_vec4Proto, "u0", moduleVec4GetU0, moduleVec4SetU0);
|
||||||
}
|
jsDefineProperty(s_vec4Proto, "v0", moduleVec4GetV0, moduleVec4SetV0);
|
||||||
|
jsDefineProperty(s_vec4Proto, "u1", moduleVec4GetU1, moduleVec4SetU1);
|
||||||
/**
|
jsDefineProperty(s_vec4Proto, "v1", moduleVec4GetV1, moduleVec4SetV1);
|
||||||
* Returns the squared length of a vec4.
|
|
||||||
*
|
jsDefineMethod(s_vec4Proto, "dot", moduleVec4Dot);
|
||||||
* @param L Lua state. Arg 1: vec4.
|
jsDefineMethod(s_vec4Proto, "length", moduleVec4Length);
|
||||||
* @return 1 (number).
|
jsDefineMethod(s_vec4Proto, "lengthSq", moduleVec4LengthSq);
|
||||||
*/
|
jsDefineMethod(s_vec4Proto, "normalize", moduleVec4Normalize);
|
||||||
static int moduleVec4LengthSq(lua_State *L) {
|
jsDefineMethod(s_vec4Proto, "negate", moduleVec4Negate);
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
jsDefineMethod(s_vec4Proto, "add", moduleVec4Add);
|
||||||
|
jsDefineMethod(s_vec4Proto, "sub", moduleVec4Sub);
|
||||||
vec4 *v = (vec4 *)luaL_checkudata(L, 1, "vec4_mt");
|
jsDefineMethod(s_vec4Proto, "scale", moduleVec4Scale);
|
||||||
assertNotNull(v, "invalid vec4 userdata");
|
jsDefineMethod(s_vec4Proto, "lerp", moduleVec4Lerp);
|
||||||
|
|
||||||
lua_pushnumber(L, (lua_Number)glm_vec4_norm2(*v));
|
jsRegister("vec4", moduleVec4Create);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,24 +24,22 @@
|
|||||||
#include "script/module/display/moduletileset.h"
|
#include "script/module/display/moduletileset.h"
|
||||||
#include "script/module/scene/modulescene.h"
|
#include "script/module/scene/modulescene.h"
|
||||||
|
|
||||||
void moduleRegister(lua_State *L) {
|
static void moduleRegister(void) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
moduleScript();
|
||||||
|
moduleEntity();
|
||||||
moduleScript(L);
|
moduleInput();
|
||||||
moduleEntity(L);
|
modulePlatform();
|
||||||
moduleInput(L);
|
moduleLocale();
|
||||||
modulePlatform(L);
|
moduleTime();
|
||||||
moduleLocale(L);
|
moduleEvent();
|
||||||
moduleTime(L);
|
moduleColor();
|
||||||
moduleEvent(L);
|
moduleSpriteBatch();
|
||||||
moduleColor(L);
|
moduleMath();
|
||||||
moduleSpriteBatch(L);
|
moduleShader();
|
||||||
moduleMath(L);
|
moduleUi();
|
||||||
moduleShader(L);
|
moduleText();
|
||||||
moduleUi(L);
|
moduleScreen();
|
||||||
moduleText(L);
|
moduleTexture();
|
||||||
moduleScreen(L);
|
moduleTileset();
|
||||||
moduleTexture(L);
|
moduleScene();
|
||||||
moduleTileset(L);
|
|
||||||
moduleScene(L);
|
|
||||||
}
|
}
|
||||||
@@ -10,3 +10,256 @@
|
|||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,22 +6,19 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "script/scriptcontext.h"
|
#include "script/module/modulebase.h"
|
||||||
#include "assert/assert.h"
|
|
||||||
#include "script/module/moduleplatformplatform.h"
|
#include "script/module/moduleplatformplatform.h"
|
||||||
|
|
||||||
#ifndef DUSK_TARGET_SYSTEM
|
#ifndef DUSK_TARGET_SYSTEM
|
||||||
#error "DUSK_TARGET_SYSTEM must be defined"
|
#error "DUSK_TARGET_SYSTEM must be defined"
|
||||||
#endif
|
#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) {
|
static void modulePlatform(void) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
jsEvalStr(MODULE_PLATFORM_VALUE);
|
||||||
|
|
||||||
luaL_dostring(L, MODULE_PLATFORM_VALUE);
|
|
||||||
|
|
||||||
#ifdef modulePlatformPlatform
|
#ifdef modulePlatformPlatform
|
||||||
modulePlatformPlatform(L);
|
modulePlatformPlatform();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -9,118 +9,68 @@
|
|||||||
#include "script/module/modulebase.h"
|
#include "script/module/modulebase.h"
|
||||||
#include "scene/scene.h"
|
#include "scene/scene.h"
|
||||||
|
|
||||||
/**
|
JS_FUNC(moduleSceneSet) {
|
||||||
* __index metamethod for the Scene table. Handles dynamic read-only properties.
|
JS_REQUIRE_ARGS(1);
|
||||||
*
|
JS_REQUIRE_STRING(0);
|
||||||
* @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");
|
|
||||||
|
|
||||||
const char_t *key = lua_tostring(L, 2);
|
char_t name[ASSET_FILE_PATH_MAX];
|
||||||
assertNotNull(key, "Scene property key cannot be NULL");
|
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")) {
|
sceneSet(name);
|
||||||
// if(SCENE.sceneActive) {
|
return jerry_undefined();
|
||||||
// lua_pushstring(L, SCENE.sceneCurrent);
|
|
||||||
// } else {
|
|
||||||
// lua_pushnil(L);
|
|
||||||
// }
|
|
||||||
// return 1;
|
|
||||||
// }
|
|
||||||
|
|
||||||
lua_pushnil(L);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
JS_FUNC(moduleSceneGetCurrent) {
|
||||||
* Attached Scene.set method to invoke internal C method.
|
if(SCENE.sceneCurrent[0] == '\0') return jerry_undefined();
|
||||||
*
|
return jerry_string_sz(SCENE.sceneCurrent);
|
||||||
* @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");
|
|
||||||
|
|
||||||
if(!lua_isstring(L, 1)) {
|
static void moduleSceneReset(void) {
|
||||||
luaL_error(L, "Scene.set requires a string argument");
|
if(SCENE.scriptRef != SCENE_SCRIPT_REF_NONE) {
|
||||||
return 0;
|
jerry_value_free(SCENE.scriptRef);
|
||||||
|
SCENE.scriptRef = SCENE_SCRIPT_REF_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
sceneSet(lua_tostring(L, 1));
|
jerry_value_t obj = jerry_object();
|
||||||
return 0;
|
|
||||||
|
jsDefineMethod(obj, "set", moduleSceneSet);
|
||||||
|
jsDefineProperty(obj, "current", moduleSceneGetCurrent, NULL);
|
||||||
|
|
||||||
|
jsSetValue("Scene", obj);
|
||||||
|
jerry_value_free(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static errorret_t moduleSceneCall(const char_t *method) {
|
||||||
* 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");
|
|
||||||
assertStrLenMin(method, 1, "Method name cannot be empty");
|
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
|
if(SCENE.scriptRef == SCENE_SCRIPT_REF_NONE) {
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, SCENE.scriptRef);
|
errorThrow("No active scene script to call method on");
|
||||||
if(!lua_istable(L, -1)) {
|
|
||||||
lua_pop(L, 1);
|
|
||||||
errorThrow("Scene script ref %d is not a table", SCENE.scriptRef);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the method from the scene table
|
jerry_value_t key = jerry_string_sz(method);
|
||||||
lua_getfield(L, -1, method);
|
jerry_value_t fn = jerry_object_get(SCENE.scriptRef, key);
|
||||||
if(!lua_isfunction(L, -1)) {
|
jerry_value_free(key);
|
||||||
lua_pop(L, 2);
|
|
||||||
errorThrow("Scene method '%s' not found", method);// TODO: Needed?
|
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)
|
jerry_value_t result = jerry_call(fn, SCENE.scriptRef, NULL, 0);
|
||||||
lua_pushvalue(L, -2);
|
jerry_value_free(fn);
|
||||||
|
|
||||||
// Call the method with 1 argument (the scene table) and 0 return values
|
if(jerry_value_is_exception(result)) {
|
||||||
if(lua_pcall(L, 1, 0, 0) != LUA_OK) {
|
char_t errMsg[512];
|
||||||
const char_t *err = lua_tostring(L, -1);
|
jsExceptionMessage(result, errMsg, sizeof(errMsg));
|
||||||
lua_pop(L, 2);// Pops the error message and the scene table
|
jerry_value_free(result);
|
||||||
errorThrow("Scene:%s failed: %s", method, err);
|
errorThrow("Scene:%s failed: %s", method, errMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_pop(L, 1);// Pops the scene table
|
jerry_value_free(result);
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void moduleScene(lua_State *L) {
|
static void moduleScene(void) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
moduleSceneReset();
|
||||||
|
|
||||||
moduleSceneReset(L);
|
|
||||||
}
|
}
|
||||||
@@ -9,74 +9,68 @@
|
|||||||
#include "script/module/modulebase.h"
|
#include "script/module/modulebase.h"
|
||||||
#include "console/console.h"
|
#include "console/console.h"
|
||||||
|
|
||||||
static int moduleScriptPrint(lua_State *L) {
|
JS_FUNC(moduleScriptPrint) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
char_t buf[512];
|
||||||
|
char_t msg[4096];
|
||||||
|
size_t msgLen = 0;
|
||||||
|
|
||||||
int n = lua_gettop(L);
|
for(jerry_length_t i = 0; i < args_count; ++i) {
|
||||||
luaL_Buffer b;
|
jerry_value_t strVal = jerry_value_to_string(args_p[i]);
|
||||||
luaL_buffinit(L, &b);
|
jsToString(strVal, buf, sizeof(buf));
|
||||||
|
jerry_value_free(strVal);
|
||||||
|
|
||||||
for(int i = 1; i <= n; ++i) {
|
size_t partLen = strlen(buf);
|
||||||
size_t len;
|
if(msgLen + partLen + 1 < sizeof(msg)) {
|
||||||
const char *s = luaL_tolstring(L, i, &len);
|
stringCopy(msg + msgLen, buf, sizeof(msg) - msgLen);
|
||||||
luaL_addlstring(&b, s, len);
|
msgLen += partLen;
|
||||||
lua_pop(L, 1);
|
}
|
||||||
if(i < n) luaL_addlstring(&b, "\t", 1);
|
|
||||||
|
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);
|
consolePrint("%s", msg);
|
||||||
return 0;
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleScriptInclude(lua_State *L) {
|
JS_FUNC(moduleScriptInclude) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
if(args_count < 1 || !jerry_value_is_string(args_p[0])) {
|
||||||
|
return JS_THROW("Expected string filename");
|
||||||
if(!lua_isstring(L, 1)) {
|
|
||||||
luaL_error(L, "Expected string filename");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scriptcontext_t* ctx = *(scriptcontext_t**)lua_getextraspace(L);
|
char_t filename[1024];
|
||||||
if(ctx == NULL) {
|
jsToString(args_p[0], filename, sizeof(filename));
|
||||||
luaL_error(L, "Script context is NULL");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char_t *filename = luaL_checkstring(L, 1);
|
if(filename[0] == '\0') {
|
||||||
if(filename == NULL || filename[0] == '\0') {
|
return JS_THROW("Filename cannot be empty");
|
||||||
luaL_error(L, "Filename cannot be NULL");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char_t buffer[1024];
|
char_t buffer[1024];
|
||||||
stringCopy(buffer, filename, 1024);
|
stringCopy(buffer, filename, sizeof(buffer));
|
||||||
|
|
||||||
size_t len = strlen(buffer);
|
size_t len = strlen(buffer);
|
||||||
if(len < 4 || stringCompare(&buffer[len - 4], ".lua") != 0) {
|
if(len < 3 || stringCompare(&buffer[len - 3], ".js") != 0) {
|
||||||
if(len + 4 >= 1024) {
|
if(len + 3 >= sizeof(buffer)) {
|
||||||
luaL_error(L, "Filename too long to append .lua");
|
return JS_THROW("Filename too long to append .js");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
stringCopy(&buffer[len], ".lua", 5);
|
stringCopy(&buffer[len], ".js", 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t stackBase = lua_gettop(L);
|
jerry_value_t result = 0;
|
||||||
|
errorret_t err = scriptContextExecFile(scriptContextCurrent, buffer, &result);
|
||||||
errorret_t err = scriptContextExecFile(ctx, buffer);
|
|
||||||
if(err.code != ERROR_OK) {
|
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));
|
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) {
|
static void moduleScript(void) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
jsRegister("print", moduleScriptPrint);
|
||||||
|
jsRegister("include", moduleScriptInclude);
|
||||||
lua_register(L, "print", moduleScriptPrint);
|
|
||||||
lua_register(L, "include", moduleScriptInclude);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,33 +9,18 @@
|
|||||||
#include "script/module/modulebase.h"
|
#include "script/module/modulebase.h"
|
||||||
#include "time/time.h"
|
#include "time/time.h"
|
||||||
|
|
||||||
static int moduleTimeIndex(lua_State *L) {
|
JS_FUNC(moduleTimeGetDelta) {
|
||||||
const char_t *key = lua_tostring(L, 2);
|
return jerry_number(TIME.delta);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void moduleTime(lua_State *L) {
|
JS_FUNC(moduleTimeGetTime) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
return jerry_number(TIME.time);
|
||||||
|
}
|
||||||
if(luaL_newmetatable(L, "time_mt")) {
|
|
||||||
lua_pushcfunction(L, moduleTimeIndex);
|
static void moduleTime(void) {
|
||||||
lua_setfield(L, -2, "__index");
|
jerry_value_t obj = jerry_object();
|
||||||
}
|
jsDefineProperty(obj, "delta", moduleTimeGetDelta, NULL);
|
||||||
lua_pop(L, 1);
|
jsDefineProperty(obj, "time", moduleTimeGetTime, NULL);
|
||||||
|
jsSetValue("TIME", obj);
|
||||||
dusktime_t **ud = (dusktime_t**)lua_newuserdata(L, sizeof(dusktime_t*));
|
jerry_value_free(obj);
|
||||||
*ud = &TIME;
|
|
||||||
luaL_setmetatable(L, "time_mt");
|
|
||||||
lua_setglobal(L, "TIME");
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "script/module/modulebase.h"
|
#include "script/module/modulebase.h"
|
||||||
|
|
||||||
static void moduleUi(lua_State *L) {
|
static void moduleUi(void) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,27 +17,26 @@
|
|||||||
#include "script/scriptgame.h"
|
#include "script/scriptgame.h"
|
||||||
#endif
|
#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) {
|
errorret_t scriptContextInit(scriptcontext_t *context) {
|
||||||
assertNotNull(context, "Script context cannot be NULL");
|
assertNotNull(context, "Script context cannot be NULL");
|
||||||
|
|
||||||
memoryZero(context, sizeof(scriptcontext_t));
|
memoryZero(context, sizeof(scriptcontext_t));
|
||||||
|
|
||||||
// Create a new Lua state for this context.
|
jerry_init(JERRY_INIT_EMPTY);
|
||||||
context->luaState = luaL_newstate();
|
scriptContextCurrent = context;
|
||||||
if(context->luaState == NULL) {
|
|
||||||
errorThrow("Failed to init Lua state");
|
|
||||||
}
|
|
||||||
luaL_openlibs(context->luaState);
|
|
||||||
|
|
||||||
// Store context in Lua extraspace
|
moduleRegister();
|
||||||
*(scriptcontext_t**)lua_getextraspace(context->luaState) = context;
|
|
||||||
|
|
||||||
// Register built-in script modules.
|
|
||||||
moduleRegister(context->luaState);
|
|
||||||
|
|
||||||
// Fire any game script init function if defined.
|
|
||||||
#ifdef SCRIPT_GAME_INIT
|
#ifdef SCRIPT_GAME_INIT
|
||||||
SCRIPT_GAME_INIT(L);
|
SCRIPT_GAME_INIT();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
@@ -47,24 +46,42 @@ errorret_t scriptContextExec(scriptcontext_t *context, const char_t *script) {
|
|||||||
assertNotNull(context, "Script context cannot be NULL");
|
assertNotNull(context, "Script context cannot be NULL");
|
||||||
assertNotNull(script, "Script cannot be NULL");
|
assertNotNull(script, "Script cannot be NULL");
|
||||||
|
|
||||||
if(luaL_dostring(context->luaState, script) != LUA_OK) {
|
jerry_value_t result = jerry_eval(
|
||||||
const char_t *strErr = lua_tostring(context->luaState, -1);
|
(const jerry_char_t *)script,
|
||||||
lua_pop(context->luaState, 1);
|
strlen(script),
|
||||||
errorThrow("Failed to execute Lua: %s", strErr);
|
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();
|
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(ctx, "Script context cannot be NULL");
|
||||||
assertNotNull(fname, "Filename cannot be NULL");
|
assertNotNull(fname, "Filename cannot be NULL");
|
||||||
return assetScriptLoad(fname, ctx);
|
return assetScriptLoad(fname, ctx, resultOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scriptContextDispose(scriptcontext_t *context) {
|
void scriptContextDispose(scriptcontext_t *context) {
|
||||||
assertNotNull(context, "Script context cannot be NULL");
|
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++) {
|
for(uint8_t i = 0; i < SCRIPT_CONTEXT_MAX_EVENT_SUBSCRIPTIONS; i++) {
|
||||||
event_t *event = context->subscribedEvents[i];
|
event_t *event = context->subscribedEvents[i];
|
||||||
@@ -72,8 +89,6 @@ void scriptContextDispose(scriptcontext_t *context) {
|
|||||||
eventUnsubscribeScriptContext(event, context);
|
eventUnsubscribeScriptContext(event, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(context->luaState != NULL) {
|
jerry_cleanup();
|
||||||
lua_close(context->luaState);
|
scriptContextCurrent = NULL;
|
||||||
context->luaState = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -8,19 +8,26 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
#include "scriptvalue.h"
|
#include "scriptvalue.h"
|
||||||
#include <lua.h>
|
#include <jerryscript.h>
|
||||||
#include <lauxlib.h>
|
|
||||||
#include <lualib.h>
|
|
||||||
|
|
||||||
typedef struct event_s event_t;
|
typedef struct event_s event_t;
|
||||||
|
|
||||||
#define SCRIPT_CONTEXT_MAX_EVENT_SUBSCRIPTIONS 64
|
#define SCRIPT_CONTEXT_MAX_EVENT_SUBSCRIPTIONS 64
|
||||||
|
|
||||||
typedef struct scriptcontext_s {
|
typedef struct scriptcontext_s {
|
||||||
lua_State *luaState;
|
|
||||||
event_t* subscribedEvents[SCRIPT_CONTEXT_MAX_EVENT_SUBSCRIPTIONS];
|
event_t* subscribedEvents[SCRIPT_CONTEXT_MAX_EVENT_SUBSCRIPTIONS];
|
||||||
} scriptcontext_t;
|
} 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.
|
* Initialize a script context.
|
||||||
*
|
*
|
||||||
@@ -30,10 +37,10 @@ typedef struct scriptcontext_s {
|
|||||||
errorret_t scriptContextInit(scriptcontext_t *context);
|
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 context The script context to use.
|
||||||
* @param script The script to execute.
|
* @param script The JS source to execute.
|
||||||
* @return The error return value.
|
* @return The error return value.
|
||||||
*/
|
*/
|
||||||
errorret_t scriptContextExec(scriptcontext_t *context, const char_t *script);
|
errorret_t scriptContextExec(scriptcontext_t *context, const char_t *script);
|
||||||
@@ -43,9 +50,16 @@ errorret_t scriptContextExec(scriptcontext_t *context, const char_t *script);
|
|||||||
*
|
*
|
||||||
* @param ctx The script context to use.
|
* @param ctx The script context to use.
|
||||||
* @param fname The filename of the script to execute.
|
* @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.
|
* @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.
|
* Dispose of a script context.
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "script/scriptcontext.h"
|
#include "script/module/modulebase.h"
|
||||||
|
|
||||||
static void modulePlatformDolphin(lua_State *L) {
|
static void modulePlatformDolphin(void) {
|
||||||
luaL_dostring(L, "DOLPHIN = true\n");
|
jsEvalStr("var DOLPHIN = true;\n");
|
||||||
}
|
}
|
||||||
@@ -6,8 +6,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "script/scriptcontext.h"
|
#include "script/module/modulebase.h"
|
||||||
|
|
||||||
static void modulePlatformLinux(lua_State *L) {
|
static void modulePlatformLinux(void) {
|
||||||
luaL_dostring(L, "LINUX = true\n");
|
jsEvalStr("var LINUX = true;\n");
|
||||||
}
|
}
|
||||||
@@ -6,8 +6,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "script/scriptcontext.h"
|
#include "script/module/modulebase.h"
|
||||||
|
|
||||||
void modulePlatformPSP(lua_State *L) {
|
static void modulePlatformPSP(void) {
|
||||||
luaL_dostring(L, "PSP = true\n");
|
jsEvalStr("var PSP = true;\n");
|
||||||
}
|
}
|
||||||
@@ -6,236 +6,195 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "script/scriptcontext.h"
|
#include "script/module/modulebase.h"
|
||||||
#include "item/inventory.h"
|
#include "item/inventory.h"
|
||||||
#include "item/backpack.h"
|
#include "item/backpack.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
|
|
||||||
static int moduleInventoryItemExists(lua_State *L) {
|
JS_FUNC(moduleInventoryItemExists) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
if(!jerry_value_is_object(args_p[0])) {
|
||||||
|
return JS_THROW("inventoryItemExists: Expected inventory pointer as first argument");
|
||||||
if(!lua_islightuserdata(L, 1)) {
|
|
||||||
luaL_error(L, "inventoryItemExists: Expected inventory pointer as first argument");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!lua_isnumber(L, 2)) {
|
if(!jerry_value_is_number(args_p[1])) {
|
||||||
luaL_error(L, "inventoryItemExists: Expected item ID as second argument");
|
return JS_THROW("inventoryItemExists: Expected item ID as second argument");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1);
|
inventory_t *inventory = (inventory_t *)jsUnwrapPointer(args_p[0]);
|
||||||
itemid_t item = (itemid_t)lua_tonumber(L, 2);
|
itemid_t item = (itemid_t)jerry_value_as_number(args_p[1]);
|
||||||
|
|
||||||
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
||||||
|
|
||||||
if(item == ITEM_ID_NULL) {
|
if(item == ITEM_ID_NULL) {
|
||||||
luaL_error(L, "inventoryItemExists: Item ID cannot be ITEM_ID_NULL");
|
return JS_THROW("inventoryItemExists: Item ID cannot be ITEM_ID_NULL");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t hasItem = inventoryItemExists(inventory, item);
|
bool_t hasItem = inventoryItemExists(inventory, item);
|
||||||
lua_pushboolean(L, hasItem);
|
return jerry_boolean(hasItem);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleInventorySet(lua_State *L) {
|
JS_FUNC(moduleInventorySet) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
if(!jerry_value_is_object(args_p[0])) {
|
||||||
|
return JS_THROW("inventorySet: Expected inventory pointer as first argument");
|
||||||
if(!lua_islightuserdata(L, 1)) {
|
|
||||||
luaL_error(L, "inventorySet: Expected inventory pointer as first argument");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!lua_isnumber(L, 2)) {
|
if(!jerry_value_is_number(args_p[1])) {
|
||||||
luaL_error(L, "inventorySet: Expected item ID as second argument");
|
return JS_THROW("inventorySet: Expected item ID as second argument");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!lua_isnumber(L, 3)) {
|
if(!jerry_value_is_number(args_p[2])) {
|
||||||
luaL_error(L, "inventorySet: Expected quantity as third argument");
|
return JS_THROW("inventorySet: Expected quantity as third argument");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1);
|
inventory_t *inventory = (inventory_t *)jsUnwrapPointer(args_p[0]);
|
||||||
itemid_t item = (itemid_t)lua_tonumber(L, 2);
|
itemid_t item = (itemid_t)jerry_value_as_number(args_p[1]);
|
||||||
uint8_t quantity = (uint8_t)lua_tonumber(L, 3);
|
uint8_t quantity = (uint8_t)jerry_value_as_number(args_p[2]);
|
||||||
|
|
||||||
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
||||||
inventorySet(inventory, item, quantity);
|
inventorySet(inventory, item, quantity);
|
||||||
return 0;
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleInventoryAdd(lua_State *L) {
|
JS_FUNC(moduleInventoryAdd) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
if(!jerry_value_is_object(args_p[0])) {
|
||||||
|
return JS_THROW("inventoryAdd: Expected inventory pointer as first argument");
|
||||||
if(!lua_islightuserdata(L, 1)) {
|
|
||||||
luaL_error(L, "inventoryAdd: Expected inventory pointer as first argument");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!lua_isnumber(L, 2)) {
|
if(!jerry_value_is_number(args_p[1])) {
|
||||||
luaL_error(L, "inventoryAdd: Expected item ID as second argument");
|
return JS_THROW("inventoryAdd: Expected item ID as second argument");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!lua_isnumber(L, 3)) {
|
if(!jerry_value_is_number(args_p[2])) {
|
||||||
luaL_error(L, "inventoryAdd: Expected quantity as third argument");
|
return JS_THROW("inventoryAdd: Expected quantity as third argument");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1);
|
inventory_t *inventory = (inventory_t *)jsUnwrapPointer(args_p[0]);
|
||||||
itemid_t item = (itemid_t)lua_tonumber(L, 2);
|
itemid_t item = (itemid_t)jerry_value_as_number(args_p[1]);
|
||||||
uint8_t quantity = (uint8_t)lua_tonumber(L, 3);
|
uint8_t quantity = (uint8_t)jerry_value_as_number(args_p[2]);
|
||||||
|
|
||||||
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
||||||
inventoryAdd(inventory, item, quantity);
|
inventoryAdd(inventory, item, quantity);
|
||||||
return 0;
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleInventoryRemove(lua_State *L) {
|
JS_FUNC(moduleInventoryRemove) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
if(!jerry_value_is_object(args_p[0])) {
|
||||||
|
return JS_THROW("inventoryRemove: Expected inventory pointer as first argument");
|
||||||
if(!lua_islightuserdata(L, 1)) {
|
|
||||||
luaL_error(L, "inventoryRemove: Expected inventory pointer as first argument");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!lua_isnumber(L, 2)) {
|
if(!jerry_value_is_number(args_p[1])) {
|
||||||
luaL_error(L, "inventoryRemove: Expected item ID as second argument");
|
return JS_THROW("inventoryRemove: Expected item ID as second argument");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1);
|
inventory_t *inventory = (inventory_t *)jsUnwrapPointer(args_p[0]);
|
||||||
itemid_t item = (itemid_t)lua_tonumber(L, 2);
|
itemid_t item = (itemid_t)jerry_value_as_number(args_p[1]);
|
||||||
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
||||||
|
|
||||||
if(lua_gettop(L) >= 3) {
|
if(args_count >= 3) {
|
||||||
if(!lua_isnumber(L, 3)) {
|
if(!jerry_value_is_number(args_p[2])) {
|
||||||
luaL_error(L, "inventoryRemove: Expected quantity as third argument");
|
return JS_THROW("inventoryRemove: Expected quantity as third argument");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
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);
|
uint8_t currentQuantity = inventoryGetCount(inventory, item);
|
||||||
if(amount >= currentQuantity) {
|
if(amount >= currentQuantity) {
|
||||||
inventoryRemove(inventory, item);
|
inventoryRemove(inventory, item);
|
||||||
return 0;
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
inventorySet(inventory, item, currentQuantity - amount);
|
inventorySet(inventory, item, currentQuantity - amount);
|
||||||
return 0;
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
inventoryRemove(inventory, item);
|
inventoryRemove(inventory, item);
|
||||||
return 0;
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleInventoryGetCount(lua_State *L) {
|
JS_FUNC(moduleInventoryGetCount) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
if(!jerry_value_is_object(args_p[0])) {
|
||||||
|
return JS_THROW("inventoryGetCount: Expected inventory pointer as first argument");
|
||||||
if(!lua_islightuserdata(L, 1)) {
|
|
||||||
luaL_error(L, "inventoryGetCount: Expected inventory pointer as first argument");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!lua_isnumber(L, 2)) {
|
if(!jerry_value_is_number(args_p[1])) {
|
||||||
luaL_error(L, "inventoryGetCount: Expected item ID as second argument");
|
return JS_THROW("inventoryGetCount: Expected item ID as second argument");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1);
|
inventory_t *inventory = (inventory_t *)jsUnwrapPointer(args_p[0]);
|
||||||
itemid_t item = (itemid_t)lua_tonumber(L, 2);
|
itemid_t item = (itemid_t)jerry_value_as_number(args_p[1]);
|
||||||
|
|
||||||
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
||||||
|
|
||||||
uint8_t count = inventoryGetCount(inventory, item);
|
uint8_t count = inventoryGetCount(inventory, item);
|
||||||
lua_pushnumber(L, count);
|
return jerry_number(count);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleInventoryIsFull(lua_State *L) {
|
JS_FUNC(moduleInventoryIsFull) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
if(!jerry_value_is_object(args_p[0])) {
|
||||||
|
return JS_THROW("inventoryIsFull: Expected inventory pointer as first argument");
|
||||||
if(!lua_islightuserdata(L, 1)) {
|
|
||||||
luaL_error(L, "inventoryIsFull: Expected inventory pointer as first argument");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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.");
|
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
||||||
|
|
||||||
bool_t isFull = inventoryIsFull(inventory);
|
bool_t isFull = inventoryIsFull(inventory);
|
||||||
lua_pushboolean(L, isFull);
|
return jerry_boolean(isFull);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleInventoryItemFull(lua_State *L) {
|
JS_FUNC(moduleInventoryItemFull) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
if(!jerry_value_is_object(args_p[0])) {
|
||||||
|
return JS_THROW("inventoryItemFull: Expected inventory pointer as first argument");
|
||||||
if(!lua_islightuserdata(L, 1)) {
|
|
||||||
luaL_error(L, "inventoryItemFull: Expected inventory pointer as first argument");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!lua_isnumber(L, 2)) {
|
if(!jerry_value_is_number(args_p[1])) {
|
||||||
luaL_error(L, "inventoryItemFull: Expected item ID as second argument");
|
return JS_THROW("inventoryItemFull: Expected item ID as second argument");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inventory_t *inventory = (inventory_t *)lua_touserdata(L, 1);
|
inventory_t *inventory = (inventory_t *)jsUnwrapPointer(args_p[0]);
|
||||||
itemid_t item = (itemid_t)lua_tonumber(L, 2);
|
itemid_t item = (itemid_t)jerry_value_as_number(args_p[1]);
|
||||||
|
|
||||||
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
||||||
|
|
||||||
bool_t isFull = inventoryItemFull(inventory, item);
|
bool_t isFull = inventoryItemFull(inventory, item);
|
||||||
lua_pushboolean(L, isFull);
|
return jerry_boolean(isFull);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleInventorySort(lua_State *L) {
|
JS_FUNC(moduleInventorySort) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
if(!jerry_value_is_object(args_p[0])) {
|
||||||
|
return JS_THROW("inventorySort: Expected inventory pointer as first argument");
|
||||||
if(!lua_islightuserdata(L, 1)) {
|
|
||||||
luaL_error(L, "inventorySort: Expected inventory pointer as first argument");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!lua_isnumber(L, 2)) {
|
if(!jerry_value_is_number(args_p[1])) {
|
||||||
luaL_error(L, "inventorySort: Expected sort type as second argument");
|
return JS_THROW("inventorySort: Expected sort type as second argument");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t reverse = false;
|
bool_t reverse = false;
|
||||||
if(lua_gettop(L) >= 3) {
|
if(args_count >= 3) {
|
||||||
if(!lua_isboolean(L, 3)) {
|
if(!jerry_value_is_boolean(args_p[2])) {
|
||||||
luaL_error(L, "inventorySort: Expected reverse flag as third argument");
|
return JS_THROW("inventorySort: Expected reverse flag as third argument");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
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);
|
inventory_t *inventory = (inventory_t *)jsUnwrapPointer(args_p[0]);
|
||||||
inventorysort_t sortBy = (inventorysort_t)lua_tonumber(L, 2);
|
inventorysort_t sortBy = (inventorysort_t)jerry_value_as_number(args_p[1]);
|
||||||
|
|
||||||
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
assertNotNull(inventory, "Inventory pointer cannot be NULL.");
|
||||||
inventorySort(inventory, sortBy, reverse);
|
inventorySort(inventory, sortBy, reverse);
|
||||||
return 0;
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void moduleItem(lua_State *L) {
|
static void moduleItem(void) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
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);
|
jsRegister("inventoryItemExists", moduleInventoryItemExists);
|
||||||
lua_setglobal(L, "BACKPACK");
|
jsRegister("inventoryAdd", moduleInventoryAdd);
|
||||||
|
jsRegister("inventorySet", moduleInventorySet);
|
||||||
lua_register(L, "inventoryItemExists", moduleInventoryItemExists);
|
jsRegister("inventoryRemove", moduleInventoryRemove);
|
||||||
lua_register(L, "inventoryAdd", moduleInventoryAdd);
|
jsRegister("inventoryGetCount", moduleInventoryGetCount);
|
||||||
lua_register(L, "inventorySet", moduleInventorySet);
|
jsRegister("inventoryIsFull", moduleInventoryIsFull);
|
||||||
lua_register(L, "inventoryRemove", moduleInventoryRemove);
|
jsRegister("inventoryItemFull", moduleInventoryItemFull);
|
||||||
lua_register(L, "inventoryGetCount", moduleInventoryGetCount);
|
jsRegister("inventorySort", moduleInventorySort);
|
||||||
lua_register(L, "inventoryIsFull", moduleInventoryIsFull);
|
|
||||||
lua_register(L, "inventoryItemFull", moduleInventoryItemFull);
|
|
||||||
lua_register(L, "inventorySort", moduleInventorySort);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,96 +6,58 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "script/scriptcontext.h"
|
#include "script/module/modulebase.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#include "story/storyflag.h"
|
#include "story/storyflag.h"
|
||||||
|
|
||||||
static int moduleStoryFlagGet(lua_State *L) {
|
JS_FUNC(moduleStoryFlagGet) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
JS_REQUIRE_ARGS(1);
|
||||||
|
JS_REQUIRE_NUMBER(0);
|
||||||
if(!lua_isnumber(L, 1)) {
|
storyflag_t flag = (storyflag_t)jerry_value_as_number(args_p[0]);
|
||||||
luaL_error(L, "Expected flag ID.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
storyflag_t flag = (storyflag_t)lua_tonumber(L, 1);
|
|
||||||
if(flag <= STORY_FLAG_NULL || flag >= STORY_FLAG_COUNT) {
|
if(flag <= STORY_FLAG_NULL || flag >= STORY_FLAG_COUNT) {
|
||||||
luaL_error(L, "Invalid flag ID %d", flag);
|
return JS_THROW("storyFlagGet: invalid flag ID");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
return jerry_number((double)storyFlagGet(flag));
|
||||||
storyflagvalue_t value = storyFlagGet(flag);
|
|
||||||
lua_pushnumber(L, value);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleStoryFlagSet(lua_State *L) {
|
JS_FUNC(moduleStoryFlagSet) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
JS_REQUIRE_ARGS(2);
|
||||||
|
JS_REQUIRE_NUMBER(0);
|
||||||
if(!lua_isnumber(L, 1)) {
|
JS_REQUIRE_NUMBER(1);
|
||||||
luaL_error(L, "Expected flag ID.");
|
storyflag_t flag = (storyflag_t)jerry_value_as_number(args_p[0]);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!lua_isnumber(L, 2)) {
|
|
||||||
luaL_error(L, "Expected flag value.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
storyflag_t flag = (storyflag_t)lua_tonumber(L, 1);
|
|
||||||
if(flag <= STORY_FLAG_NULL || flag >= STORY_FLAG_COUNT) {
|
if(flag <= STORY_FLAG_NULL || flag >= STORY_FLAG_COUNT) {
|
||||||
luaL_error(L, "Invalid flag ID %d", flag);
|
return JS_THROW("storyFlagSet: invalid flag ID");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
storyflagvalue_t value = (storyflagvalue_t)jerry_value_as_number(args_p[1]);
|
||||||
storyflagvalue_t value = (storyflagvalue_t)lua_tonumber(L, 2);
|
|
||||||
storyFlagSet(flag, value);
|
storyFlagSet(flag, value);
|
||||||
return 0;
|
return jerry_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleStoryFlagIncrement(lua_State *L) {
|
JS_FUNC(moduleStoryFlagIncrement) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
JS_REQUIRE_ARGS(1);
|
||||||
|
JS_REQUIRE_NUMBER(0);
|
||||||
if(!lua_isnumber(L, 1)) {
|
storyflag_t flag = (storyflag_t)jerry_value_as_number(args_p[0]);
|
||||||
luaL_error(L, "Expected flag ID.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
storyflag_t flag = (storyflag_t)lua_tonumber(L, 1);
|
|
||||||
if(flag <= STORY_FLAG_NULL || flag >= STORY_FLAG_COUNT) {
|
if(flag <= STORY_FLAG_NULL || flag >= STORY_FLAG_COUNT) {
|
||||||
luaL_error(L, "Invalid flag ID %d", flag);
|
return JS_THROW("storyFlagIncrement: invalid flag ID");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
storyFlagSet(flag, storyFlagGet(flag) + 1);
|
||||||
storyflagvalue_t value = storyFlagGet(flag);
|
return jerry_undefined();
|
||||||
storyFlagSet(flag, value + 1);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int moduleStoryFlagDecrement(lua_State *L) {
|
JS_FUNC(moduleStoryFlagDecrement) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
JS_REQUIRE_ARGS(1);
|
||||||
|
JS_REQUIRE_NUMBER(0);
|
||||||
if(!lua_isnumber(L, 1)) {
|
storyflag_t flag = (storyflag_t)jerry_value_as_number(args_p[0]);
|
||||||
luaL_error(L, "Expected flag ID.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
storyflag_t flag = (storyflag_t)lua_tonumber(L, 1);
|
|
||||||
if(flag <= STORY_FLAG_NULL || flag >= STORY_FLAG_COUNT) {
|
if(flag <= STORY_FLAG_NULL || flag >= STORY_FLAG_COUNT) {
|
||||||
luaL_error(L, "Invalid flag ID %d", flag);
|
return JS_THROW("storyFlagDecrement: invalid flag ID");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
storyFlagSet(flag, storyFlagGet(flag) - 1);
|
||||||
storyflagvalue_t value = storyFlagGet(flag);
|
return jerry_undefined();
|
||||||
storyFlagSet(flag, value - 1);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void moduleStoryFlag(lua_State *L) {
|
static void moduleStoryFlag(void) {
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
jsRegister("storyFlagGet", moduleStoryFlagGet);
|
||||||
|
jsRegister("storyFlagSet", moduleStoryFlagSet);
|
||||||
lua_register(L, "storyFlagGet", moduleStoryFlagGet);
|
jsRegister("storyFlagIncrement", moduleStoryFlagIncrement);
|
||||||
lua_register(L, "storyFlagSet", moduleStoryFlagSet);
|
jsRegister("storyFlagDecrement", moduleStoryFlagDecrement);
|
||||||
lua_register(L, "storyFlagIncrement", moduleStoryFlagIncrement);
|
|
||||||
lua_register(L, "storyFlagDecrement", moduleStoryFlagDecrement);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ out = [
|
|||||||
"",
|
"",
|
||||||
]
|
]
|
||||||
|
|
||||||
lua = []
|
js = []
|
||||||
for name, (r, g, b, a) in colors.items():
|
for name, (r, g, b, a) in colors.items():
|
||||||
r8, g8, b8, a8 = (int(float(ch) * 255) for ch in (r, g, b, a))
|
r8, g8, b8, a8 = (int(float(ch) * 255) for ch in (r, g, b, a))
|
||||||
macro = "COLOR_" + name.upper()
|
macro = "COLOR_" + name.upper()
|
||||||
@@ -60,16 +60,16 @@ for name, (r, g, b, a) in colors.items():
|
|||||||
f"#define {macro} {macro}_4B",
|
f"#define {macro} {macro}_4B",
|
||||||
"",
|
"",
|
||||||
]
|
]
|
||||||
lua += [
|
js += [
|
||||||
f"function color{camel}()",
|
f"function color{camel}() {{",
|
||||||
f" return color({r8}, {g8}, {b8}, {a8})",
|
f" return color({r8}, {g8}, {b8}, {a8});",
|
||||||
"end",
|
"}",
|
||||||
"",
|
"",
|
||||||
]
|
]
|
||||||
|
|
||||||
out.append("// Lua color functions")
|
out.append("// JS color functions")
|
||||||
out.append("#define COLOR_SCRIPT \\")
|
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.append(f' "{line}\\n" \\')
|
||||||
out[-1] = out[-1].rstrip(" \\")
|
out[-1] = out[-1].rstrip(" \\")
|
||||||
out.append("")
|
out.append("")
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ out += [
|
|||||||
"static const char_t *INPUT_ACTION_SCRIPT =",
|
"static const char_t *INPUT_ACTION_SCRIPT =",
|
||||||
]
|
]
|
||||||
for input_id in input_ids:
|
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 += [";", ""]
|
out += [";", ""]
|
||||||
|
|
||||||
os.makedirs(os.path.dirname(args.output), exist_ok=True)
|
os.makedirs(os.path.dirname(args.output), exist_ok=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user