Riyyi
4 years ago
4 changed files with 201 additions and 175 deletions
@ -1,205 +1,78 @@ |
|||||||
extern "C" { |
#include "sol/unsafe_function_result.hpp" |
||||||
#include <lua/lua.h> |
|
||||||
#include <lua/lualib.h> |
|
||||||
#include <lua/lauxlib.h> |
|
||||||
} |
|
||||||
|
|
||||||
#include "inferno/assertions.h" |
#include "inferno/assertions.h" |
||||||
#include "inferno/file.h" |
#include "inferno/file.h" |
||||||
#include "inferno/scene/components.h" |
#include "inferno/scene/components.h" |
||||||
#include "inferno/scene/scene.h" |
#include "inferno/scene/scene.h" |
||||||
#include "inferno/script/lua.h" |
#include "inferno/script/lua.h" |
||||||
|
#include "inferno/script/registration.h" |
||||||
|
|
||||||
namespace Inferno { |
namespace Inferno { |
||||||
|
|
||||||
void Lua::initialize() |
void Lua::initialize() |
||||||
{ |
{ |
||||||
m_state = luaL_newstate(); |
// Type registration
|
||||||
|
// ---------------------------------
|
||||||
|
|
||||||
|
Registration::fill(m_state); |
||||||
|
|
||||||
// Add GetComponent()
|
// Load libraries
|
||||||
// ---------------------------------
|
// ---------------------------------
|
||||||
|
|
||||||
constexpr int32_t componentUpValueAmount = 1; |
m_state.open_libraries(sol::lib::base); |
||||||
lua_pushlightuserdata(m_state, this); |
|
||||||
lua_pushcclosure(m_state, Lua::getComponent, componentUpValueAmount); |
|
||||||
lua_setglobal(m_state, "GetComponent"); |
|
||||||
|
|
||||||
// Add Metatable
|
// Component get functions
|
||||||
// ---------------------------------
|
// ---------------------------------
|
||||||
|
|
||||||
luaL_newmetatable(m_state, "ComponentMetatable"); |
m_state.set_function("getTagComponent", [this]() -> TagComponent* { |
||||||
|
return &m_scene->getComponent<TagComponent>(m_entity); |
||||||
|
}); |
||||||
|
|
||||||
constexpr int32_t indexUpValueAmount = 1; |
m_state.set_function("getTransformComponent", [this]() -> TransformComponent* { |
||||||
lua_pushstring(m_state, "__index"); |
return &m_scene->getComponent<TransformComponent>(m_entity); |
||||||
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; |
// (*m_state).set_function("GetComponent", &Lua::getComponentSol);
|
||||||
lua_pushstring(m_state, "__newindex"); |
m_state.set_function("getCameraComponent", [this]() -> CameraComponent* { |
||||||
lua_pushlightuserdata(m_state, this); |
return &m_scene->getComponent<CameraComponent>(m_entity); |
||||||
lua_pushcclosure(m_state, Lua::componentNewIndex, newIndexUpValueAmount); |
}); |
||||||
lua_settable(m_state, -3); // Pops the string and table
|
|
||||||
|
|
||||||
// Load and Initialize Script
|
m_state.set_function("getSpriteComponent", [this]() -> SpriteComponent* { |
||||||
|
return &m_scene->getComponent<SpriteComponent>(m_entity); |
||||||
|
}); |
||||||
|
|
||||||
|
// Load and Initialize script
|
||||||
// ---------------------------------
|
// ---------------------------------
|
||||||
|
|
||||||
loadScript(); |
loadScript(); |
||||||
|
|
||||||
getFunction("LuaScript", "initialize"); |
callFunction("LuaScript", "initialize"); |
||||||
callFunction(); |
|
||||||
} |
} |
||||||
|
|
||||||
void Lua::destroy() |
void Lua::destroy() |
||||||
{ |
{ |
||||||
getFunction("LuaScript", "destroy"); |
callFunction("LuaScript", "destroy"); |
||||||
callFunction(); |
|
||||||
|
|
||||||
lua_close(m_state); |
|
||||||
m_state = nullptr; |
|
||||||
} |
} |
||||||
|
|
||||||
void Lua::update(float deltaTime) |
void Lua::update(float deltaTime) |
||||||
{ |
{ |
||||||
getFunction("LuaScript", "update"); |
m_state["LuaScript"]["transform"] = &m_scene->getComponent<TransformComponent>(m_entity); |
||||||
lua_pushnumber(m_state, deltaTime); // Push float argument
|
callFunction("LuaScript", "update", deltaTime); |
||||||
callFunction(1); |
|
||||||
} |
|
||||||
|
|
||||||
void Lua::valid(int32_t error) |
|
||||||
{ |
|
||||||
ASSERT(error == LUA_OK, "{}", lua_tostring(m_state, -1)); |
|
||||||
} |
} |
||||||
|
|
||||||
void Lua::loadScript() |
void Lua::loadScript() |
||||||
{ |
{ |
||||||
std::string script = File::read(m_path); |
std::string script = File::read(m_path); |
||||||
int32_t error = luaL_dostring(m_state, script.c_str()); |
auto result = m_state.script(script.c_str(), |
||||||
valid(error); |
[](lua_State*, sol::protected_function_result pfr) { return pfr; }); |
||||||
} |
ASSERT(result.valid(), "Lua script {}", ((sol::error)result).what()); |
||||||
|
|
||||||
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!
|
sol::table Lua::getTable(const char* name) |
||||||
{ |
{ |
||||||
ASSERT(lua_gettop(state) == 2, "Lua called with wrong amount of arguments"); |
sol::table table = m_state[name]; |
||||||
ASSERT(lua_isuserdata(state, -2)); // 1 // <component>.x
|
ASSERT(table.valid(), "Lua table does not exist"); |
||||||
ASSERT(lua_isstring(state, -1)); // 2 // component.<x>
|
return table; |
||||||
|
|
||||||
// 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; |
|
||||||
} |
} |
||||||
|
|
||||||
} |
} |
||||||
|
@ -0,0 +1,82 @@ |
|||||||
|
#include "glm/ext/vector_float2.hpp" // glm::vec2 |
||||||
|
#include "glm/ext/vector_float3.hpp" // glm::vec3 |
||||||
|
#include "glm/ext/vector_float4.hpp" // glm::vec4 |
||||||
|
|
||||||
|
#include "inferno/scene/components.h" |
||||||
|
#include "inferno/script/registration.h" |
||||||
|
|
||||||
|
namespace Inferno { |
||||||
|
|
||||||
|
void Registration::fill(sol::state_view &state) |
||||||
|
{ |
||||||
|
glm(state); |
||||||
|
component(state); |
||||||
|
} |
||||||
|
|
||||||
|
void Registration::glm(sol::state_view& state) |
||||||
|
{ |
||||||
|
auto vec2 = state.new_usertype<glm::vec2>( |
||||||
|
"vec2", |
||||||
|
sol::call_constructor, sol::constructors<glm::vec2(), glm::vec2(float), glm::vec2(float, float)>(), |
||||||
|
"x", &glm::vec2::x, "y", &glm::vec2::y, |
||||||
|
"r", &glm::vec2::r, "g", &glm::vec2::g, |
||||||
|
"s", &glm::vec2::s, "t", &glm::vec2::t, |
||||||
|
"__add", addition<glm::vec2, float>(), |
||||||
|
"__sub", subtraction<glm::vec2, float>(), |
||||||
|
"__mul", multiplication<glm::vec2, float>(), |
||||||
|
"__div", division<glm::vec2, float>() |
||||||
|
); |
||||||
|
|
||||||
|
auto vec3 = state.new_usertype<glm::vec3>( |
||||||
|
"vec3", |
||||||
|
sol::call_constructor, sol::constructors<glm::vec3(), glm::vec3(float), glm::vec3(float, float, float)>(), |
||||||
|
"x", &glm::vec3::x, "y", &glm::vec3::y, "z", &glm::vec3::z, |
||||||
|
"r", &glm::vec3::r, "g", &glm::vec3::g, "b", &glm::vec3::b, |
||||||
|
"s", &glm::vec3::s, "t", &glm::vec3::t, "p", &glm::vec3::p, |
||||||
|
"__add", addition<glm::vec3, float>(), |
||||||
|
"__sub", subtraction<glm::vec3, float>(), |
||||||
|
"__mul", multiplication<glm::vec3, float>(), |
||||||
|
"__div", division<glm::vec3, float>() |
||||||
|
// "__tostring", [](glm::vec3 self) { return self.x; } // Template!!! convert via logstream
|
||||||
|
); |
||||||
|
|
||||||
|
auto vec4 = state.new_usertype<glm::vec4>( |
||||||
|
"vec4", |
||||||
|
sol::call_constructor, sol::constructors<glm::vec4(), glm::vec4(float), glm::vec4(float, float, float, float)>(), |
||||||
|
"x", &glm::vec4::x, "y", &glm::vec4::y, "z", &glm::vec4::z, "w", &glm::vec4::w, |
||||||
|
"r", &glm::vec4::r, "g", &glm::vec4::g, "b", &glm::vec4::b, "a", &glm::vec4::a, |
||||||
|
"s", &glm::vec4::s, "t", &glm::vec4::t, "p", &glm::vec4::p, "q", &glm::vec4::q, |
||||||
|
"__add", addition<glm::vec4, float>(), |
||||||
|
"__sub", subtraction<glm::vec4, float>(), |
||||||
|
"__mul", multiplication<glm::vec4, float>(), |
||||||
|
"__div", division<glm::vec4, float>() |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
void Registration::component(sol::state_view& state) |
||||||
|
{ |
||||||
|
auto tagComponent = state.new_usertype<TagComponent>("TagComponent", sol::no_constructor); |
||||||
|
tagComponent["tag"] = &TagComponent::tag; |
||||||
|
|
||||||
|
auto transformComponent = state.new_usertype<TransformComponent>("TransformComponent", sol::no_constructor); |
||||||
|
transformComponent["translate"] = &TransformComponent::translate; |
||||||
|
transformComponent["rotate"] = &TransformComponent::rotate; |
||||||
|
transformComponent["scale"] = &TransformComponent::scale; |
||||||
|
transformComponent["transform"] = &TransformComponent::transform; |
||||||
|
|
||||||
|
auto cameraComponent = state.new_usertype<CameraComponent>("CameraComponent", sol::no_constructor); |
||||||
|
cameraComponent["type"] = &CameraComponent::type; |
||||||
|
cameraComponent["zoomLevel"] = &CameraComponent::zoomLevel; |
||||||
|
cameraComponent["rotateAxis"] = &CameraComponent::rotateAxis; |
||||||
|
cameraComponent["fov"] = &CameraComponent::fov; |
||||||
|
cameraComponent["pitch"] = &CameraComponent::pitch; |
||||||
|
cameraComponent["yaw"] = &CameraComponent::yaw; |
||||||
|
cameraComponent["up"] = &CameraComponent::up; |
||||||
|
cameraComponent["projection"] = &CameraComponent::projection; |
||||||
|
|
||||||
|
auto spriteComponent = state.new_usertype<SpriteComponent>("SpriteComponent", sol::no_constructor); |
||||||
|
spriteComponent["color"] = &SpriteComponent::color; |
||||||
|
spriteComponent["texture"] = &SpriteComponent::texture; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,60 @@ |
|||||||
|
#ifndef REGISTRATION_H |
||||||
|
#define REGISTRATION_H |
||||||
|
|
||||||
|
#include "sol/overload.hpp" // sol::overload |
||||||
|
#include "sol/state_view.hpp" // sol::state_view |
||||||
|
|
||||||
|
namespace Inferno { |
||||||
|
|
||||||
|
class Registration final { |
||||||
|
public: |
||||||
|
static void fill(sol::state_view& state); |
||||||
|
|
||||||
|
private: |
||||||
|
static void glm(sol::state_view& state); |
||||||
|
static void component(sol::state_view& state); |
||||||
|
|
||||||
|
template<typename T, typename V> |
||||||
|
static auto addition() |
||||||
|
{ |
||||||
|
return sol::overload( |
||||||
|
[](const T& lhs, const T& rhs) { return lhs + rhs; }, |
||||||
|
[](const T& lhs, const V& rhs) { return lhs + rhs; }, |
||||||
|
[](const V& lhs, const T& rhs) { return lhs + rhs; } |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
template<typename T, typename V> |
||||||
|
static auto subtraction() |
||||||
|
{ |
||||||
|
return sol::overload( |
||||||
|
[](const T& lhs, const T& rhs) { return lhs - rhs; }, |
||||||
|
[](const T& lhs, const V& rhs) { return lhs - rhs; }, |
||||||
|
[](const V& lhs, const T& rhs) { return lhs - rhs; } |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
template<typename T, typename V> |
||||||
|
static auto multiplication() |
||||||
|
{ |
||||||
|
return sol::overload( |
||||||
|
[](const T& lhs, const T& rhs) { return lhs * rhs; }, |
||||||
|
[](const T& lhs, const V& rhs) { return lhs * rhs; }, |
||||||
|
[](const V& lhs, const T& rhs) { return lhs * rhs; } |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
template<typename T, typename V> |
||||||
|
static auto division() |
||||||
|
{ |
||||||
|
return sol::overload( |
||||||
|
[](const T& lhs, const T& rhs) { return lhs / rhs; }, |
||||||
|
[](const T& lhs, const V& rhs) { return lhs / rhs; }, |
||||||
|
[](const V& lhs, const T& rhs) { return lhs / rhs; } |
||||||
|
); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
#endif // REGISTRATION_H
|
Loading…
Reference in new issue