添加各基本SDL类型
This commit is contained in:
parent
57b7a92d0b
commit
5f1c518576
476
LuaEngine.cpp
476
LuaEngine.cpp
|
@ -15,9 +15,7 @@ void check(lua_State* L, const vector<int>& typearr)
|
|||
{
|
||||
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);
|
||||
luaL_error(L, "Bad argument #%d. %s expected, got %s", i + 1, lua_typename(L, typearr[i]), lua_typename(L, lua_type(L, i + 1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,6 +46,7 @@ struct Window
|
|||
static int close(lua_State* L)
|
||||
{
|
||||
check(L, { LUA_TUSERDATA });
|
||||
cout << "In Window::close" << endl;
|
||||
Window* p = (Window*)lua_touserdata(L, 1);
|
||||
if (p->wnd)
|
||||
{
|
||||
|
@ -165,7 +164,7 @@ struct Window
|
|||
static int create(lua_State* L)
|
||||
{
|
||||
check(L, { LUA_TSTRING, LUA_TNUMBER, LUA_TNUMBER });
|
||||
cout << "In SDLWindow::Create" << endl;
|
||||
cout << "In Window::create" << endl;
|
||||
Window* p = (Window*) lua_newuserdata(L, sizeof(Window));
|
||||
// Data table (for storing lua values)
|
||||
lua_pushlightuserdata(L, p);
|
||||
|
@ -203,6 +202,161 @@ struct Window
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
struct Texture
|
||||
{
|
||||
SDL_Texture* text;
|
||||
int w;
|
||||
int h;
|
||||
|
||||
static int close(lua_State* L)
|
||||
{
|
||||
check(L, { LUA_TUSERDATA });
|
||||
cout << "In Texture::close" << endl;
|
||||
Texture* t = (Texture*)lua_touserdata(L, 1);
|
||||
if (t->text)
|
||||
{
|
||||
SDL_DestroyTexture(t->text);
|
||||
t->text = nullptr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void create(lua_State* L) // -2, +1
|
||||
{
|
||||
// 此函数由Renderer在C层直接调用. 调用前需要先放一个renderer userdata和lightuserdata在栈上, 值就是当前的SDL_Texture.
|
||||
// 调用后栈上会留下Texture的userdata.
|
||||
// 因此在Lua层没有直接创建Texture的方法.
|
||||
cout << "In Texture::create" << endl;
|
||||
Texture* p = (Texture*)lua_newuserdata(L, sizeof(Texture));
|
||||
// Metatable
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__texture_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, "texture"); lua_setfield(L, -2, "type");
|
||||
setfn(L, close, "close");
|
||||
|
||||
// Binding
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "__texture_mt");
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__texture_mt");
|
||||
}
|
||||
lua_setmetatable(L, -2);
|
||||
p->text = (SDL_Texture * )lua_touserdata(L, -2);
|
||||
SDL_QueryTexture(p->text, NULL, NULL, &p->w, &p->h);
|
||||
lua_pushvalue(L, -3);
|
||||
lua_setuservalue(L, -2); // 绑定这个Rendere userdata
|
||||
|
||||
// stack balance
|
||||
lua_remove(L, lua_gettop(L) - 1); // 删除lightuserdata
|
||||
lua_remove(L, lua_gettop(L) - 1); // 删除rendere userdata
|
||||
}
|
||||
};
|
||||
|
||||
int LuaRectPointToRect(lua_State* L, int index, SDL_Rect& rect)
|
||||
{
|
||||
if (lua_getfield(L, index, "type") != LUA_TSTRING)
|
||||
{
|
||||
lua_pop(L, 1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char* type = lua_tostring(L, -1);
|
||||
if (strcmp(type, "point") == 0)
|
||||
{
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, index, "x");
|
||||
rect.x = lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, index, "y");
|
||||
rect.y = lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (strcmp(type, "rect") == 0)
|
||||
{
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, index, "x");
|
||||
rect.x = lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, index, "y");
|
||||
rect.y = lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, index, "w");
|
||||
rect.w = lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, index, "h");
|
||||
rect.h = lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
struct Surface
|
||||
{
|
||||
SDL_Surface* surf;
|
||||
|
||||
static int close(lua_State* L)
|
||||
{
|
||||
check(L, { LUA_TUSERDATA });
|
||||
cout << "In Surface::close" << endl;
|
||||
Surface* p = (Surface*)lua_touserdata(L, 1);
|
||||
if (p->surf)
|
||||
{
|
||||
SDL_FreeSurface(p->surf);
|
||||
p->surf = nullptr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void create(lua_State* L) // -1, +1
|
||||
{
|
||||
cout << "In Surface::create" << endl;
|
||||
Surface* p = (Surface*)lua_newuserdata(L, sizeof(Surface));
|
||||
// Metatable
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__surface_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, "surface"); lua_setfield(L, -2, "type");
|
||||
setfn(L, close, "close");
|
||||
|
||||
// Binding
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "__surface_mt");
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__surface_mt");
|
||||
}
|
||||
lua_setmetatable(L, -2);
|
||||
p->surf = (SDL_Surface*)lua_touserdata(L, -2);
|
||||
|
||||
// stack balance
|
||||
lua_remove(L, lua_gettop(L) - 1); // 删除lightuserdata
|
||||
}
|
||||
};
|
||||
|
||||
struct Renderer
|
||||
{
|
||||
SDL_Renderer* rnd;
|
||||
|
@ -210,6 +364,7 @@ struct Renderer
|
|||
static int close(lua_State* L)
|
||||
{
|
||||
check(L, { LUA_TUSERDATA });
|
||||
cout << "In Renderer::close" << endl;
|
||||
Renderer* p = (Renderer*)lua_touserdata(L, 1);
|
||||
if (p->rnd)
|
||||
{
|
||||
|
@ -235,10 +390,50 @@ struct Renderer
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int loadTexture(lua_State* L)
|
||||
{
|
||||
check(L, { LUA_TUSERDATA, LUA_TSTRING });
|
||||
Renderer* p = (Renderer*)lua_touserdata(L, 1);
|
||||
const char* filepath = lua_tostring(L, 2);
|
||||
SDL_Texture* text = IMG_LoadTexture(p->rnd, filepath);
|
||||
lua_pushvalue(L, 1);
|
||||
lua_pushlightuserdata(L, text);
|
||||
Texture::create(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int copy(lua_State* L)
|
||||
{
|
||||
check(L, { LUA_TUSERDATA, LUA_TUSERDATA, LUA_TTABLE, LUA_TTABLE });
|
||||
Renderer* p = (Renderer*)lua_touserdata(L, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int copyTo(lua_State* L)
|
||||
{
|
||||
check(L, { LUA_TUSERDATA, LUA_TUSERDATA, LUA_TTABLE });
|
||||
Renderer* r = (Renderer*)lua_touserdata(L, 1);
|
||||
Texture* t = (Texture*)lua_touserdata(L, 2);
|
||||
SDL_Rect rect;
|
||||
int ret = LuaRectPointToRect(L, 3, rect);
|
||||
if (ret < 0)
|
||||
{
|
||||
luaL_error(L, "Bad argument #%d. Point or Rect expected, got %s", 3, lua_typename(L, lua_type(L, 3)));
|
||||
}
|
||||
if (ret == 1)
|
||||
{
|
||||
rect.w = t->w;
|
||||
rect.h = t->h;
|
||||
}
|
||||
SDL_RenderCopy(r->rnd, t->text, NULL, &rect);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int create(lua_State* L)
|
||||
{
|
||||
check(L, { LUA_TUSERDATA });
|
||||
cout << "In SDLWindow::Create" << endl;
|
||||
cout << "In Renderer::create" << endl;
|
||||
Renderer* p = (Renderer*)lua_newuserdata(L, sizeof(Renderer));
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__renderer_mt");
|
||||
if (lua_type(L, -1) == LUA_TNIL)
|
||||
|
@ -255,6 +450,9 @@ struct Renderer
|
|||
setfn(L, close, "close");
|
||||
setfn(L, update, "update");
|
||||
setfn(L, clear, "clear");
|
||||
setfn(L, loadTexture, "loadTexture");
|
||||
setfn(L, copy, "copy");
|
||||
setfn(L, copyTo, "copyTo");
|
||||
|
||||
// Set __index of metatable.
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
@ -263,25 +461,283 @@ struct Renderer
|
|||
lua_getfield(L, LUA_REGISTRYINDEX, "__renderer_mt");
|
||||
}
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
// 绑定当前Renderer的对象到自身, 防止SDL_Window被提前销毁.
|
||||
lua_pushvalue(L, 1);
|
||||
lua_setuservalue(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;
|
||||
}
|
||||
};
|
||||
|
||||
int LuaColorToColor(lua_State* L, int index, SDL_Color& c)
|
||||
{
|
||||
if (lua_getfield(L, index, "type") != LUA_TSTRING)
|
||||
{
|
||||
lua_pop(L, 1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char* type = lua_tostring(L, -1);
|
||||
if (strcmp(type, "color") == 0)
|
||||
{
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, index, "r");
|
||||
c.r = lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, index, "g");
|
||||
c.g = lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, index, "b");
|
||||
c.b = lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, index, "a");
|
||||
c.a = lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
struct Font
|
||||
{
|
||||
TTF_Font* font;
|
||||
|
||||
static int close(lua_State* L)
|
||||
{
|
||||
check(L, { LUA_TUSERDATA });
|
||||
cout << "In Font::close" << endl;
|
||||
Font* f = (Font*)lua_touserdata(L, 1);
|
||||
if (f->font)
|
||||
{
|
||||
TTF_CloseFont(f->font);
|
||||
f->font = nullptr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int renderText(lua_State* L)
|
||||
{
|
||||
Renderer* r = nullptr;
|
||||
Font* f = nullptr;
|
||||
const char* text = nullptr;
|
||||
SDL_Color c;
|
||||
if (lua_gettop(L) >= 4)
|
||||
{
|
||||
check(L, { LUA_TUSERDATA, LUA_TUSERDATA, LUA_TSTRING, LUA_TTABLE });
|
||||
f = (Font*)lua_touserdata(L, 1);
|
||||
r = (Renderer*)lua_touserdata(L, 2);
|
||||
text = lua_tostring(L, 3);
|
||||
if (LuaColorToColor(L, 4, c) < 0)
|
||||
{
|
||||
luaL_error(L, "Bad argument #%d. Color expected, got %s", 4, lua_typename(L, lua_type(L, 4)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
check(L, { LUA_TUSERDATA, LUA_TSTRING, LUA_TTABLE });
|
||||
f = (Font*)lua_touserdata(L, 1);
|
||||
text = lua_tostring(L, 3);
|
||||
if (LuaColorToColor(L, 4, c) < 0)
|
||||
{
|
||||
luaL_error(L, "Bad argument #%d. Color expected, got %s", 4, lua_typename(L, lua_type(L, 4)));
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Surface* surf = TTF_RenderText_Blended(f->font, text, c);
|
||||
|
||||
if (r)
|
||||
{
|
||||
SDL_Texture* text = SDL_CreateTextureFromSurface(r->rnd, surf);
|
||||
SDL_FreeSurface(surf);
|
||||
lua_pushvalue(L, 2);
|
||||
lua_pushlightuserdata(L, text);
|
||||
Texture::create(L);
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_pushlightuserdata(L, surf);
|
||||
Surface::create(L);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int create(lua_State* L)
|
||||
{
|
||||
check(L, { LUA_TSTRING, LUA_TNUMBER });
|
||||
cout << "In Font::create" << endl;
|
||||
Font* f = (Font*)lua_newuserdata(L, sizeof(Font));
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__font_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, "font"); lua_setfield(L, -2, "type");
|
||||
setfn(L, close, "close");
|
||||
setfn(L, renderText, "renderText");
|
||||
|
||||
// Set __index of metatable.
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "__font_mt");
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__font_mt");
|
||||
}
|
||||
lua_setmetatable(L, -2);
|
||||
const char* filename = lua_tostring(L, 1);
|
||||
int fontsz = lua_tointeger(L, 2);
|
||||
f->font = TTF_OpenFont(filename, fontsz);
|
||||
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
struct Music
|
||||
{
|
||||
Mix_Music* music;
|
||||
|
||||
static int close(lua_State* L)
|
||||
{
|
||||
check(L, { LUA_TUSERDATA });
|
||||
cout << "In Music::close" << endl;
|
||||
|
||||
Music* m = (Music*)lua_touserdata(L, 1);
|
||||
if (m->music)
|
||||
{
|
||||
Mix_FreeMusic(m->music);
|
||||
m->music = nullptr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int create(lua_State* L)
|
||||
{
|
||||
check(L, { LUA_TSTRING });
|
||||
cout << "In Music::create" << endl;
|
||||
|
||||
Music* m = (Music*)lua_newuserdata(L, sizeof(Music));
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__music_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, "music"); lua_setfield(L, -2, "type");
|
||||
setfn(L, close, "close");
|
||||
|
||||
// Set __index of metatable.
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "__music_mt");
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__music_mt");
|
||||
}
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
const char* filename = lua_tostring(L, 1);
|
||||
m->music = Mix_LoadMUS(filename);
|
||||
cout << "Load music error: " << SDL_GetError() << endl;
|
||||
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
struct MusicPlayer
|
||||
{
|
||||
static int close(lua_State* L)
|
||||
{
|
||||
check(L, { LUA_TUSERDATA });
|
||||
cout << "In MusicPlayer::close" << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int play(lua_State* L)
|
||||
{
|
||||
check(L, { LUA_TUSERDATA, LUA_TUSERDATA });
|
||||
MusicPlayer* p = (MusicPlayer*)lua_touserdata(L, 1);
|
||||
Music* m = (Music*)lua_touserdata(L, 2);
|
||||
cout << "Play music ret: " << Mix_PlayMusic(m->music, 1) << " " << SDL_GetError() << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int create(lua_State* L)
|
||||
{
|
||||
cout << "In MusicPlayer::create" << endl;
|
||||
|
||||
MusicPlayer* m = (MusicPlayer*)lua_newuserdata(L, sizeof(MusicPlayer));
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__musicplayer_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, "musicplayer"); lua_setfield(L, -2, "type");
|
||||
setfn(L, close, "close");
|
||||
setfn(L, play, "play");
|
||||
|
||||
// Set __index of metatable.
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "__musicplayer_mt");
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__musicplayer_mt");
|
||||
}
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
#define reg_in_lua(L, cfunc, name) lua_pushcfunction(L, cfunc); lua_setglobal(L, name)
|
||||
|
||||
void check_init(lua_State* L, const char* name, int ret, int expected = 0)
|
||||
{
|
||||
if (ret != expected)
|
||||
{
|
||||
luaL_error(L, "Failed to initialize %s. ret: %d. expected: %d. SDLError: %s", name, ret, expected, SDL_GetError());
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
int ret;
|
||||
ret = SDL_Init(SDL_INIT_EVERYTHING);
|
||||
check_init(L, "SDL", ret);
|
||||
ret = IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG);
|
||||
check_init(L, "IMG", ret, IMG_INIT_JPG | IMG_INIT_PNG);
|
||||
ret = TTF_Init();
|
||||
check_init(L, "TTF", ret);
|
||||
ret = Mix_Init(MIX_INIT_MP3 | MIX_INIT_MOD | MIX_INIT_OGG );
|
||||
check_init(L, "MIX", ret, MIX_INIT_MP3 | MIX_INIT_MOD | MIX_INIT_OGG);
|
||||
|
||||
ret = Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 512);
|
||||
check_init(L, "AUDIO", ret);
|
||||
Mix_AllocateChannels(16);
|
||||
|
||||
lua_newtable(L);
|
||||
reg_in_lua(L, Window::create, "Window");
|
||||
reg_in_lua(L, Renderer::create, "Renderer");
|
||||
reg_in_lua(L, Font::create, "Font");
|
||||
reg_in_lua(L, Music::create, "Music");
|
||||
reg_in_lua(L, MusicPlayer::create, "MusicPlayer");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user