Browse Source

Add lua script class

master
Riyyi 3 years ago
parent
commit
8a740f55ba
  1. 32
      assets/lua/cameracontroller.lua
  2. 205
      inferno/src/inferno/script/lua.cpp
  3. 46
      inferno/src/inferno/script/lua.h

32
assets/lua/cameracontroller.lua

@ -0,0 +1,32 @@
LuaScript = {
camera = nil,
initialize = function(self)
--
end,
destroy = function(self)
--
end,
update = function(self, deltaTime)
self.camera = GetComponent("CameraComponent")
LuaScript:updateOrthographic(deltaTime)
LuaScript:updatePerspective(deltaTime)
local tmp = self.camera.fov
self.camera.fov = 30.0
--
end,
updateOrthographic = function(self, deltaTime)
--
end,
updatePerspective = function(self, deltaTime)
--
end,
}

205
inferno/src/inferno/script/lua.cpp

@ -0,0 +1,205 @@
extern "C" {
#include <lua/lua.h>
#include <lua/lualib.h>
#include <lua/lauxlib.h>
}
#include "inferno/assertions.h"
#include "inferno/file.h"
#include "inferno/scene/components.h"
#include "inferno/scene/scene.h"
#include "inferno/script/lua.h"
namespace Inferno {
void Lua::initialize()
{
m_state = luaL_newstate();
// Add GetComponent()
// ---------------------------------
constexpr int32_t componentUpValueAmount = 1;
lua_pushlightuserdata(m_state, this);
lua_pushcclosure(m_state, Lua::getComponent, componentUpValueAmount);
lua_setglobal(m_state, "GetComponent");
// Add Metatable
// ---------------------------------
luaL_newmetatable(m_state, "ComponentMetatable");
constexpr int32_t indexUpValueAmount = 1;
lua_pushstring(m_state, "__index");
lua_pushlightuserdata(m_state, this);
lua_pushcclosure(m_state, Lua::componentIndex, indexUpValueAmount);
lua_settable(m_state, -3); // Pops the string and table
constexpr int32_t newIndexUpValueAmount = 1;
lua_pushstring(m_state, "__newindex");
lua_pushlightuserdata(m_state, this);
lua_pushcclosure(m_state, Lua::componentNewIndex, newIndexUpValueAmount);
lua_settable(m_state, -3); // Pops the string and table
// Load and Initialize Script
// ---------------------------------
loadScript();
getFunction("LuaScript", "initialize");
callFunction();
}
void Lua::destroy()
{
getFunction("LuaScript", "destroy");
callFunction();
lua_close(m_state);
m_state = nullptr;
}
void Lua::update(float deltaTime)
{
getFunction("LuaScript", "update");
lua_pushnumber(m_state, deltaTime); // Push float argument
callFunction(1);
}
void Lua::valid(int32_t error)
{
ASSERT(error == LUA_OK, "{}", lua_tostring(m_state, -1));
}
void Lua::loadScript()
{
std::string script = File::read(m_path);
int32_t error = luaL_dostring(m_state, script.c_str());
valid(error);
}
void Lua::getFunction(const char* table, const char* function)
{
Lua::isTable(m_state, table); // Push table
int32_t tableIdx = lua_gettop(m_state); // Get table stack index
lua_pushstring(m_state, function); // Push string
lua_gettable(m_state, -2); // Pop string key, push value
lua_pushvalue(m_state, tableIdx); // Push table
}
void Lua::callFunction(int32_t parameters)
{
int32_t error = lua_pcall(m_state, parameters + 1, 0, 0); // Call function()
valid(error);
}
void Lua::isTable(lua_State* state, int32_t table)
{
ASSERT(lua_istable(state, table));
}
void Lua::isTable(lua_State* state, const char* table)
{
lua_getglobal(state, table); // Push table on the stack
Lua::isTable(state, -1);
}
int32_t Lua::getComponent(lua_State* state) // Local scope state, so stack begins at 1!
{
ASSERT(lua_gettop(state) == 1, "Lua called with wrong amount of arguments");
ASSERT(lua_islightuserdata(state, lua_upvalueindex(1)), "Lua did not receive required lightuserdata");
Lua* self = static_cast<Lua*>(lua_touserdata(state, lua_upvalueindex(1)));
// Verify parameter
std::string componentName = lua_tostring(state, -1);
ASSERT(lua_isstring(state, -1), "Lua did not receive correct parameter");
// Create userdata
/*void* pointer =*/ lua_newuserdatauv(state, sizeof(0), 2); // Push userdata
ASSERT(lua_isuserdata(state, -1), "Lua could not create userdata");
// Get component
void* component = nullptr;
if (componentName.compare("CameraComponent") == 0) {
component = static_cast<void*>(&self->m_scene->getComponent<CameraComponent>(self->m_entity));
}
// Add metatable to userdata
luaL_getmetatable(state, "ComponentMetatable"); // Push table
ASSERT(lua_istable(state, -1), "Lua could not find metatable");
lua_setmetatable(state, -2); // Pop table, set it as metatable onto userdata
// Add uservalues to userdata
lua_pushstring(state, componentName.c_str()); // Push string
lua_setiuservalue(state, -2, 1); // Pop value, set it as the n-th uservalue onto userdata
lua_pushlightuserdata(state, component); // Push pointer
lua_setiuservalue(state, -2, 2); // Pop value, set it as the n-th uservalue onto userdata
return 1; // Return amount of stack items pushed
}
int32_t Lua::componentIndex(lua_State* state) // Local scope state, so stack begins at 1!
{
ASSERT(lua_gettop(state) == 2, "Lua called with wrong amount of arguments");
ASSERT(lua_isuserdata(state, -2)); // 1 // <component>.x
ASSERT(lua_isstring(state, -1)); // 2 // component.<x>
// ASSERT(lua_islightuserdata(state, lua_upvalueindex(1)), "Lua did not receive required lightuserdata");
// Lua* self = static_cast<Lua*>(lua_touserdata(state, lua_upvalueindex(1)));
lua_getiuservalue(state, 1, 1); // Push the n-th uservalue from userdata
ASSERT(lua_isstring(state, -1), "Lua did not receive component type correctly");
std::string componentName = lua_tostring(state, -1);
if (componentName.compare("CameraComponent") == 0) {
lua_getiuservalue(state, 1, 2); // Push the n-th uservalue from userdata
ASSERT(lua_islightuserdata(state, -1), "Lua did not receive component pointer correctly");
CameraComponent* component = (CameraComponent*)lua_touserdata(state, -1);
std::string index = lua_tostring(state, 2);
if (index.compare("fov") == 0) {
lua_pushnumber(state, component->fov);
return 1;
}
else {
ASSERT_NOT_REACHED();
}
}
return 0;
}
int32_t Lua::componentNewIndex(lua_State* state) // Local scope state, so stack begins at 1!
{
ASSERT(lua_gettop(state) == 3, "Lua called with wrong amount of arguments");
ASSERT(lua_isuserdata(state, -3)); // 1 // <component>.x = thing
ASSERT(lua_isstring(state, -2)); // 2 // component.<x> = thing
// Value we want to set -1 // 3 // component.x = <thing>
lua_getiuservalue(state, 1, 1); // Push the n-th uservalue from userdata
ASSERT(lua_isstring(state, -1), "Lua did not receive component type correctly");
std::string componentName = lua_tostring(state, -1);
if (componentName.compare("CameraComponent") == 0) {
lua_getiuservalue(state, 1, 2); // Push the n-th uservalue from userdata
ASSERT(lua_islightuserdata(state, -1), "Lua did not receive component pointer correctly");
CameraComponent* component = (CameraComponent*)lua_touserdata(state, -1);
std::string index = lua_tostring(state, 2);
if (index.compare("fov") == 0) {
component->fov = lua_tonumber(state, 3);
}
else {
ASSERT_NOT_REACHED();
}
}
return 0;
}
}

46
inferno/src/inferno/script/lua.h

@ -0,0 +1,46 @@
#ifndef LUA_H
#define LUA_H
#include <cstdint> // int32_t, uint32_t
#include <string> // std::string
#include <lua/lua.h> // lua_State
namespace Inferno {
struct TransformComponent;
class Scene;
class Lua {
public:
void initialize();
void destroy();
void update(float deltaTime);
void valid(int32_t error);
void loadScript();
void getFunction(const char* table, const char* function);
void callFunction(int32_t parameters = 0);
private:
static void isTable(lua_State* state, int32_t table);
static void isTable(lua_State* state, const char* table);
static int32_t getComponent(lua_State* state);
static int32_t componentIndex(lua_State* state);
static int32_t componentNewIndex(lua_State* state);
std::string m_path = "";
lua_State* m_state = nullptr;
Scene* m_scene = nullptr;
uint32_t m_entity = 0;
TransformComponent* transform = nullptr;
friend class ScriptSystem;
};
}
#endif // LUA_H
Loading…
Cancel
Save