diff --git a/assets/entities/cube.lua b/assets/entities/cube.lua index 86132f47..a116eb2e 100644 --- a/assets/entities/cube.lua +++ b/assets/entities/cube.lua @@ -1,21 +1,25 @@ -local Cube = {} +local Cube = setmetatable({}, { __index = Entity }) Cube.__index = Cube function Cube.new() - local self = setmetatable({}, Cube) - self.id = entityAdd() - local pos = entityPositionAdd(self.id) - pos.x = 0 - pos.y = 0 - pos.z = 0 - entityMeshAdd(self.id) - local mat = entityMaterialAdd(self.id) - mat.color = colorWhite() + 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:dispose() - entityRemove(self.id) +function Cube:update() + local speed = 3.0 + local dx = inputAxis(INPUT_ACTION_LEFT, INPUT_ACTION_RIGHT) + local dz = inputAxis(INPUT_ACTION_UP, INPUT_ACTION_DOWN) + self.position.x = self.position.x + dx * speed * TIME.delta + self.position.z = self.position.z + dz * speed * TIME.delta end return Cube diff --git a/assets/scenes/cube.lua b/assets/scenes/cube.lua index ef137caa..7b4850d8 100644 --- a/assets/scenes/cube.lua +++ b/assets/scenes/cube.lua @@ -1,26 +1,30 @@ local Cube = include('entities/cube.lua') +local SceneCube = {} +SceneCube.__index = SceneCube + local cam local cube -function Scene:init() - print("Scene init") - local camId = entityAdd() - local pos = entityPositionAdd(camId) - pos.x = 3 - pos.y = 3 - pos.z = 3 - pos:lookAt(0, 0, 0) - entityCameraAdd(camId) - cam = camId +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 Scene:update() +function SceneCube:update() + cube:update() end -function Scene:dispose() +function SceneCube:dispose() + cam:dispose() cube:dispose() - entityRemove(cam) end + +return SceneCube diff --git a/src/dusk/scene/scene.c b/src/dusk/scene/scene.c index 5e62fc04..43f0cdb2 100644 --- a/src/dusk/scene/scene.c +++ b/src/dusk/scene/scene.c @@ -21,19 +21,23 @@ scene_t SCENE; -// Rebuilds the Scene global to a clean table with only Scene.set bound. +// Releases the current scene class ref and rebuilds Scene.set global. static void sceneReset(void) { lua_State *L = SCRIPT_MANAGER.mainContext.luaState; + if(SCENE.scriptRef != LUA_NOREF) { + luaL_unref(L, LUA_REGISTRYINDEX, SCENE.scriptRef); + SCENE.scriptRef = LUA_NOREF; + } lua_newtable(L); lua_pushcfunction(L, sceneSetLua); lua_setfield(L, -2, "set"); lua_setglobal(L, "Scene"); } -// Calls Scene:method() if it exists. Returns an error if the call fails. +// Calls sceneClass:method() if it exists. Returns an error if the call fails. static errorret_t sceneCall(const char_t *method) { lua_State *L = SCRIPT_MANAGER.mainContext.luaState; - lua_getglobal(L, "Scene"); + lua_rawgeti(L, LUA_REGISTRYINDEX, SCENE.scriptRef); lua_getfield(L, -1, method); if(!lua_isfunction(L, -1)) { lua_pop(L, 2); @@ -45,12 +49,13 @@ static errorret_t sceneCall(const char_t *method) { lua_pop(L, 2); errorThrow("Scene:%s failed: %s", method, err); } - lua_pop(L, 1); // pop Scene + lua_pop(L, 1); // pop scene class errorOk(); } errorret_t sceneInit(void) { memoryZero(&SCENE, sizeof(scene_t)); + SCENE.scriptRef = LUA_NOREF; sceneReset(); errorOk(); } @@ -210,8 +215,13 @@ errorret_t sceneSetImmediate(const char_t *scene) { errorChain(scriptContextExecFile(&SCRIPT_MANAGER.mainContext, scene)); - // Discard any return values — we access Scene via the global. - lua_settop(L, stackBase); + 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); errorChain(sceneCall("init")); SCENE.scriptActive = true; diff --git a/src/dusk/scene/scene.h b/src/dusk/scene/scene.h index 62528e9d..9b79e5d6 100644 --- a/src/dusk/scene/scene.h +++ b/src/dusk/scene/scene.h @@ -14,6 +14,7 @@ typedef struct { bool_t scriptActive; + int scriptRef; char_t sceneCurrent[ASSET_FILE_PATH_MAX]; char_t sceneNext[ASSET_FILE_PATH_MAX]; } scene_t; diff --git a/src/dusk/script/module/entity/moduleentity.h b/src/dusk/script/module/entity/moduleentity.h index 51725449..c7ecde2e 100644 --- a/src/dusk/script/module/entity/moduleentity.h +++ b/src/dusk/script/module/entity/moduleentity.h @@ -239,6 +239,54 @@ static int _entityMaterialAdd(lua_State *L) { return 1; } +// ============================================================================ +// Component type Lua constants (auto-generated from componentlist.h) +// ============================================================================ + +#define X(enumName, type, field, init, dispose) \ + "COMPONENT_TYPE_" #enumName " = \"" #field "\"\n" +static const char_t *COMPONENT_TYPE_SCRIPT = +#include "entity/componentlist.h" +; +#undef X + +// ============================================================================ +// Entity base class Lua script +// ============================================================================ + +static const char_t *ENTITY_SCRIPT = + "Entity = {}\n" + "Entity.__index = Entity\n" + "\n" + "Entity.POSITION = COMPONENT_TYPE_POSITION\n" + "Entity.CAMERA = COMPONENT_TYPE_CAMERA\n" + "Entity.MESH = COMPONENT_TYPE_MESH\n" + "Entity.MATERIAL = COMPONENT_TYPE_MATERIAL\n" + "Entity.PHYSICS = COMPONENT_TYPE_PHYSICS\n" + "\n" + "local _addFns = {\n" + " [COMPONENT_TYPE_POSITION] = entityPositionAdd,\n" + " [COMPONENT_TYPE_CAMERA] = entityCameraAdd,\n" + " [COMPONENT_TYPE_MESH] = entityMeshAdd,\n" + " [COMPONENT_TYPE_MATERIAL] = entityMaterialAdd,\n" + "}\n" + "\n" + "function Entity.new()\n" + " return setmetatable({ id = entityAdd() }, Entity)\n" + "end\n" + "\n" + "function Entity:add(componentType)\n" + " local fn = _addFns[componentType]\n" + " if not fn then error('unknown component type: ' .. tostring(componentType)) end\n" + " self[componentType] = fn(self.id)\n" + " return self[componentType]\n" + "end\n" + "\n" + "function Entity:dispose()\n" + " entityRemove(self.id)\n" + "end\n" +; + // ============================================================================ // entityAdd / entityRemove // ============================================================================ @@ -288,4 +336,7 @@ static void moduleEntity(lua_State *L) { lua_register(L, "entityCameraAdd", _entityCameraAdd); lua_register(L, "entityMeshAdd", _entityMeshAdd); lua_register(L, "entityMaterialAdd", _entityMaterialAdd); + + luaL_dostring(L, COMPONENT_TYPE_SCRIPT); + luaL_dostring(L, ENTITY_SCRIPT); }