Initial Commit

This commit is contained in:
Kirigaya Kazuto 2019-08-06 20:36:04 +08:00
commit 57b7a92d0b
10 changed files with 380 additions and 0 deletions

11
.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
.vs/
Debug/
Release/
asserts/
*.sln
*.vcxproj
*.vcxproj.*
*.dll

6
.gitmodules vendored Normal file
View File

@ -0,0 +1,6 @@
[submodule "SDL2"]
path = SDL2
url = http://kiritow.com:3000/ToolCenter/SDL2-dev-env
[submodule "lua"]
path = lua
url = http://kiritow.com:3000/ToolCenter/Lua-dev-env

287
LuaEngine.cpp Normal file
View File

@ -0,0 +1,287 @@
#include "LuaEngine.h"
#include <iostream>
#include <string>
#include <vector>
#include "SDL2/include/SDL.h"
#include "SDL2/include/SDL_mixer.h"
#include "SDL2/include/SDL_ttf.h"
#include "SDL2/include/SDL_image.h"
using namespace std;
void check(lua_State* L, const vector<int>& typearr)
{
int sz = typearr.size();
for (int i = 0; i < sz; i++)
{
if (lua_type(L, i + 1) != typearr[i])
{
char tmp[128] = { 0 };
sprintf(tmp, "Bad argument #%d. %s expected, got %s", i + 1, lua_typename(L, typearr[i]), lua_typename(L, lua_type(L, i + 1)));
luaL_error(L, tmp);
}
}
}
struct LuaTimerCallbackData
{
void* p;
int id;
int type; // 0=setTimeout, 1=setInterval
};
Uint32 LuaTimerCallbackGate(Uint32 interval, void* param)
{
SDL_Event e;
e.type = SDL_USEREVENT;
e.user.code = 1001;
e.user.data1 = param;
SDL_PushEvent(&e);
return ((LuaTimerCallbackData*)(param))->type ? interval : 0;
}
#define setfn(L, cfunc, name) lua_pushcfunction(L, cfunc); lua_setfield(L, -2, name)
struct Window
{
SDL_Window* wnd;
static int close(lua_State* L)
{
check(L, { LUA_TUSERDATA });
Window* p = (Window*)lua_touserdata(L, 1);
if (p->wnd)
{
// release data table
lua_pushlightuserdata(L, p);
lua_pushnil(L);
lua_settable(L, LUA_REGISTRYINDEX);
SDL_DestroyWindow(p->wnd);
p->wnd = nullptr;
}
return 0;
}
static int start(lua_State* L)
{
check(L, { LUA_TUSERDATA });
Window* p = (Window*)lua_touserdata(L, 1);
lua_settop(L, 1);
lua_pushlightuserdata(L, p);
lua_gettable(L, LUA_REGISTRYINDEX);
bool running = true;
SDL_Event e;
while (running && SDL_WaitEvent(&e))
{
switch (e.type)
{
case SDL_MOUSEBUTTONDOWN:
{
if (lua_getfield(L, -1, "onclick") != LUA_TNIL)
{
lua_pushnumber(L, e.button.x);
lua_pushnumber(L, e.button.y);
lua_call(L, 2, LUA_MULTRET);
}
else lua_pop(L, 1);
break;
}
case SDL_QUIT:
{
if (lua_getfield(L, -1, "onquit") != LUA_TNIL)
{
lua_call(L, 0, LUA_MULTRET);
}
else lua_pop(L, 1);
running = 0;
break;
}
case SDL_KEYDOWN:
{
if (lua_getfield(L, -1, "onkeydown") != LUA_TNIL)
{
lua_pushnumber(L, e.key.keysym.sym);
lua_call(L, 1, LUA_MULTRET);
}
else lua_pop(L, 1);
break;
}
case SDL_USEREVENT:
{
switch (e.user.code)
{
case 1001:
{
LuaTimerCallbackData* pd = (LuaTimerCallbackData* )e.user.data1;
lua_pushlightuserdata(L, pd->p);
lua_gettable(L, LUA_REGISTRYINDEX);
lua_pushfstring(L, "tmcb%d", pd->id);
lua_gettable(L, -2);
delete pd;
lua_call(L, 0, LUA_MULTRET);
lua_pop(L, 1);
break;
}
}
break;
}
}
}
return 0;
}
static int set_event_handler(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TSTRING, LUA_TFUNCTION });
Window* p = (Window*)lua_touserdata(L, 1);
lua_pushlightuserdata(L, p);
lua_gettable(L, LUA_REGISTRYINDEX);
lua_pushfstring(L, "on%s", lua_tostring(L, 2));
lua_pushvalue(L, 3);
lua_settable(L, -3);
return 0;
}
static int setTimeout(lua_State* L)
{
check(L, { LUA_TUSERDATA, LUA_TFUNCTION, LUA_TNUMBER }); // ms
Window* p = (Window*)lua_touserdata(L, 1);
LuaTimerCallbackData* pd = new LuaTimerCallbackData();
pd->p = p;
pd->type = 0;
pd->id = SDL_AddTimer(lua_tointeger(L, 3), LuaTimerCallbackGate, pd);
lua_pushlightuserdata(L, p);
lua_gettable(L, LUA_REGISTRYINDEX);
lua_pushfstring(L, "tmcb%d", pd->id);
lua_pushvalue(L, 2);
lua_settable(L, -3);
return 0;
}
static int create(lua_State* L)
{
check(L, { LUA_TSTRING, LUA_TNUMBER, LUA_TNUMBER });
cout << "In SDLWindow::Create" << endl;
Window* p = (Window*) lua_newuserdata(L, sizeof(Window));
// Data table (for storing lua values)
lua_pushlightuserdata(L, p);
lua_newtable(L);
lua_settable(L, LUA_REGISTRYINDEX);
// Metatable
lua_getfield(L, LUA_REGISTRYINDEX, "__window_mt");
if (lua_type(L, -1) == LUA_TNIL)
{
lua_pop(L, 1);
lua_newtable(L);
// GC
lua_pushcfunction(L, close);
lua_setfield(L, -2, "__gc");
// Fields
lua_newtable(L);
lua_pushstring(L, "window"); lua_setfield(L, -2, "type");
setfn(L, close, "close");
setfn(L, set_event_handler, "on");
setfn(L, start, "start");
setfn(L, setTimeout, "setTimeout");
// Binding
lua_setfield(L, -2, "__index");
lua_setfield(L, LUA_REGISTRYINDEX, "__window_mt");
lua_getfield(L, LUA_REGISTRYINDEX, "__window_mt");
}
lua_setmetatable(L, -2);
// Internal logic
p->wnd = SDL_CreateWindow(lua_tostring(L, 1), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, lua_tointeger(L, 2), lua_tointeger(L, 3), SDL_WINDOW_SHOWN);
return 1;
}
};
struct Renderer
{
SDL_Renderer* rnd;
static int close(lua_State* L)
{
check(L, { LUA_TUSERDATA });
Renderer* p = (Renderer*)lua_touserdata(L, 1);
if (p->rnd)
{
SDL_DestroyRenderer(p->rnd);
p->rnd = nullptr;
}
return 0;
}
static int update(lua_State* L)
{
check(L, { LUA_TUSERDATA });
Renderer* p = (Renderer*)lua_touserdata(L, 1);
SDL_RenderPresent(p->rnd);
return 0;
}
static int clear(lua_State* L)
{
check(L, { LUA_TUSERDATA });
Renderer* p = (Renderer*)lua_touserdata(L, 1);
SDL_RenderClear(p->rnd);
return 0;
}
static int create(lua_State* L)
{
check(L, { LUA_TUSERDATA });
cout << "In SDLWindow::Create" << endl;
Renderer* p = (Renderer*)lua_newuserdata(L, sizeof(Renderer));
lua_getfield(L, LUA_REGISTRYINDEX, "__renderer_mt");
if (lua_type(L, -1) == LUA_TNIL)
{
lua_pop(L, 1);
lua_newtable(L);
// GC
lua_pushcfunction(L, close);
lua_setfield(L, -2, "__gc");
// Fields
lua_newtable(L);
lua_pushstring(L, "renderer"); lua_setfield(L, -2, "type");
setfn(L, close, "close");
setfn(L, update, "update");
setfn(L, clear, "clear");
// Set __index of metatable.
lua_setfield(L, -2, "__index");
lua_setfield(L, LUA_REGISTRYINDEX, "__renderer_mt");
lua_getfield(L, LUA_REGISTRYINDEX, "__renderer_mt");
}
lua_setmetatable(L, -2);
// Internal logic
p->rnd = SDL_CreateRenderer(static_cast<Window*>(lua_touserdata(L, 1))->wnd, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE);
return 1;
}
};
#define reg_in_lua(L, cfunc, name) lua_pushcfunction(L, cfunc); lua_setglobal(L, name)
int InitEngine(lua_State* L)
{
SDL_Init(SDL_INIT_EVERYTHING);
IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG);
TTF_Init();
Mix_Init(MIX_INIT_MP3);
lua_newtable(L);
reg_in_lua(L, Window::create, "Window");
reg_in_lua(L, Renderer::create, "Renderer");
return 0;
}

5
LuaEngine.h Normal file
View File

@ -0,0 +1,5 @@
#include "LuaVM.h"
#undef main
int InitEngine(lua_State* L);

0
LuaVM.cpp Normal file
View File

34
LuaVM.h Normal file
View File

@ -0,0 +1,34 @@
#pragma once
#include "lua/lua.hpp"
class LuaVM
{
public:
LuaVM() {
_L = luaL_newstate();
luaL_openlibs(_L);
_managed = true;
}
LuaVM(lua_State* L, bool managed=false) {
_L = L;
_managed = managed;
}
/// NonMoveable,NonCopyable
LuaVM(const LuaVM&) = delete;
LuaVM& operator = (const LuaVM&) = delete;
LuaVM(LuaVM&&) = delete;
LuaVM& operator = (LuaVM&&) = delete;
~LuaVM() {
if (_managed) {
lua_close(_L);
}
}
operator lua_State* () {
return _L;
}
private:
lua_State* _L;
bool _managed;
};

15
LuaYard.cpp Normal file
View File

@ -0,0 +1,15 @@
#include <iostream>
#include <string>
#include "LuaEngine.h"
using namespace std;
int main()
{
LuaVM L;
InitEngine(L);
if (luaL_dofile(L, "code/game.lua"))
{
cout << lua_tostring(L, -1) << endl;
}
cout << "<ENGINE> Stopped." << endl;
}

1
SDL2 Submodule

@ -0,0 +1 @@
Subproject commit cc3d2307f4236a6411fcf78bd4fd7a0927db7014

20
code/game.lua Normal file
View File

@ -0,0 +1,20 @@
wnd = Window("Hello", 1024, 768)
rnd = Renderer(wnd)
wnd:on('click', function(x, y)
print("Clicked", x, y)
end)
wnd:on('quit', function()
print("before quit")
end)
wnd:on('keydown', function(key)
print("Keydown", key)
wnd:setTimeout(function()
print("timer callback.")
end, 1000)
end)
xpcall(function()
wnd:start()
end, function()
print(debug.traceback())
end)

1
lua Submodule

@ -0,0 +1 @@
Subproject commit 04e7c8aa6d4c48f597885da8ecbde9908dbcdae5