Initial Commit
This commit is contained in:
commit
57b7a92d0b
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
.vs/
|
||||
Debug/
|
||||
Release/
|
||||
|
||||
asserts/
|
||||
|
||||
*.sln
|
||||
*.vcxproj
|
||||
*.vcxproj.*
|
||||
|
||||
*.dll
|
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal 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
287
LuaEngine.cpp
Normal 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
5
LuaEngine.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
#include "LuaVM.h"
|
||||
#undef main
|
||||
|
||||
|
||||
int InitEngine(lua_State* L);
|
34
LuaVM.h
Normal file
34
LuaVM.h
Normal 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
15
LuaYard.cpp
Normal 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
1
SDL2
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit cc3d2307f4236a6411fcf78bd4fd7a0927db7014
|
20
code/game.lua
Normal file
20
code/game.lua
Normal 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
1
lua
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 04e7c8aa6d4c48f597885da8ecbde9908dbcdae5
|
Loading…
Reference in New Issue
Block a user