aboutsummaryrefslogtreecommitdiff
path: root/src/lua
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2018-05-21 16:02:00 +0800
committerchai <chaifix@163.com>2018-05-21 16:02:00 +0800
commitfa234f9663b992cf50bcf865a1cde6845b42193c (patch)
tree34ecd41b60ef48c960a79a4077e5e0c8536102fd /src/lua
parent51ba9cb2a6b0b9395a2912eadeb954c95e4c1d3c (diff)
修改audio模块
Diffstat (limited to 'src/lua')
-rw-r--r--src/lua/audio/luaopen_Source.cpp26
-rw-r--r--src/lua/audio/luaopen_audio.cpp39
-rw-r--r--src/lua/core/luaopen_core.cpp43
-rw-r--r--src/lua/debug/luaopen_debug.cpp8
-rw-r--r--src/lua/embed/boot.lua132
-rw-r--r--src/lua/embed/boot.lua.h156
-rw-r--r--src/lua/embed/debug.lua128
-rw-r--r--src/lua/embed/debug.lua.h132
-rw-r--r--src/lua/embed/embed.h51
-rw-r--r--src/lua/embed/graphics.lua6
-rw-r--r--src/lua/embed/graphics.lua.h8
-rw-r--r--src/lua/embed/keyboard.lua16
-rw-r--r--src/lua/embed/keyboard.lua.h20
-rw-r--r--src/lua/embed/mouse.lua15
-rw-r--r--src/lua/embed/mouse.lua.h18
-rw-r--r--src/lua/embed/path.lua15
-rw-r--r--src/lua/embed/path.lua.h18
-rw-r--r--src/lua/event/luaopen_event.cpp124
-rw-r--r--src/lua/filesystem/luaopen_filesystem.cpp142
-rw-r--r--src/lua/graphics/luaopen_Canvas.cpp75
-rw-r--r--src/lua/graphics/luaopen_Font.cpp45
-rw-r--r--src/lua/graphics/luaopen_Image.cpp89
-rw-r--r--src/lua/graphics/luaopen_JSL.cpp146
-rw-r--r--src/lua/graphics/luaopen_graphics.cpp524
-rw-r--r--src/lua/joypad/joypad.h14
-rw-r--r--src/lua/joypad/luaopen_joypad.cpp21
-rw-r--r--src/lua/keyboard/luaopen_keyboard.cpp16
-rw-r--r--src/lua/luaopen_jin.cpp97
-rw-r--r--src/lua/luaopen_jin.h45
-rw-r--r--src/lua/luaopen_types.h24
-rw-r--r--src/lua/luax.h10
-rw-r--r--src/lua/mouse/luaopen_mouse.cpp27
-rw-r--r--src/lua/net/luaopen_net.cpp110
-rw-r--r--src/lua/thread/luaopen_Thread.cpp0
-rw-r--r--src/lua/time/luaopen_time.cpp34
35 files changed, 2374 insertions, 0 deletions
diff --git a/src/lua/audio/luaopen_Source.cpp b/src/lua/audio/luaopen_Source.cpp
new file mode 100644
index 0000000..8ecaf7e
--- /dev/null
+++ b/src/lua/audio/luaopen_Source.cpp
@@ -0,0 +1,26 @@
+#include "lua/luax.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ static int l_play(lua_State* L)
+ {
+
+ return 0;
+ }
+
+ static const luaL_Reg f[] = {
+ {"play", l_play},
+ {0, 0}
+ };
+
+ int luaopen_Source(lua_State* L)
+ {
+
+ return 1;
+ }
+
+}
+}
diff --git a/src/lua/audio/luaopen_audio.cpp b/src/lua/audio/luaopen_audio.cpp
new file mode 100644
index 0000000..992c3ec
--- /dev/null
+++ b/src/lua/audio/luaopen_audio.cpp
@@ -0,0 +1,39 @@
+#include <SDL2/SDL.h>
+
+#include "lua/luax.h"
+#include "libjin/jin.h"
+
+namespace jin
+{
+namespace lua
+{
+ static int l_init(lua_State* L)
+ {
+ if (SDL_Init(SDL_INIT_AUDIO) < 0)
+ {
+ luax_error(L, "could not init audio");
+ luax_pushboolean(L, false);
+ return 1;
+ }
+ }
+
+ static int l_newSound(lua_State* L)
+ {
+
+ return 0;
+ }
+
+ static const luaL_Reg f[] = {
+ {"init", l_init},
+ {"Sound", l_newSound},
+ {0, 0}
+ };
+
+ int luaopen_audio(lua_State* L)
+ {
+ luax_newlib(L, f);
+
+ return 1;
+ }
+}
+} \ No newline at end of file
diff --git a/src/lua/core/luaopen_core.cpp b/src/lua/core/luaopen_core.cpp
new file mode 100644
index 0000000..c8df1b6
--- /dev/null
+++ b/src/lua/core/luaopen_core.cpp
@@ -0,0 +1,43 @@
+#include "lua/luax.h"
+#include "libjin/jin.h"
+
+namespace jin
+{
+namespace lua
+{
+ using namespace jin::core;
+
+ static int l_running(lua_State* L)
+ {
+ bool running = Game::get()->running();
+ luax_pushboolean(L, running);
+ return 1;
+ }
+
+ static int l_quit(lua_State* L)
+ {
+ Game::get()->quit();
+ return 0;
+ }
+
+ static int l_exit(lua_State* L)
+ {
+ Game::get()->exit();
+ return 0;
+ }
+
+ static const luaL_Reg f[] = {
+ {"running", l_running},
+ {"quit", l_quit}, // for end game loop
+ {"exit", l_exit}, // for exit whole game
+ {0, 0}
+ };
+
+ int luaopen_core(lua_State* L)
+ {
+ luax_newlib(L, f);
+
+ return 1;
+ }
+}
+} \ No newline at end of file
diff --git a/src/lua/debug/luaopen_debug.cpp b/src/lua/debug/luaopen_debug.cpp
new file mode 100644
index 0000000..b33c058
--- /dev/null
+++ b/src/lua/debug/luaopen_debug.cpp
@@ -0,0 +1,8 @@
+namespace jin
+{
+namespace debug
+{
+
+
+}
+} \ No newline at end of file
diff --git a/src/lua/embed/boot.lua b/src/lua/embed/boot.lua
new file mode 100644
index 0000000..2f6fa93
--- /dev/null
+++ b/src/lua/embed/boot.lua
@@ -0,0 +1,132 @@
+--[[
+ program entry
+]]
+
+local function _onEvent(e)
+ -- update keyboard status
+ if e.type == "keydown" then
+ jin.keyboard.set(e.key, true)
+ elseif e.type == "keyup" then
+ jin.keyboard.set(e.key, false)
+ end
+
+ -- call user onEvent function
+ if jin.core.onEvent then
+ jin.core.onEvent(e)
+ end
+end
+
+-------------------------------------------------
+-- init file system
+-------------------------------------------------
+jin._argv[2] = jin._argv[2] or '.'
+jin.filesystem.init()
+jin.filesystem.mount(jin._argv[2])
+
+-- config
+local conf = {}
+if jin.filesystem.exist("config.lua") then
+ conf = require "config"
+end
+conf.width = conf.width or 600
+conf.height = conf.height or 500
+conf.fps = conf.fps or 60
+conf.title = conf.title or ("jin v" .. jin.version())
+
+-- init video subsystem
+jin.graphics.init(conf.width,conf.height,conf.title)
+
+-- open debug mode, must after jin.graphics.init
+if jin._argv[3] == '-d' then
+ jin.debug.init()
+end
+
+function jin.core.run()
+ local now = jin.time.second()
+ local last = now
+ local fsec = 1/conf.fps
+ -- for loading resources
+ if jin.core.load then
+ jin.core.load()
+ end
+ local dt = 0
+ while(jin.core.running()) do
+ -- frame controle
+ last = now
+ now = jin.time.second()
+ if (now - last) < fsec then
+ jin.time.sleep(fsec - now + last)
+ end
+
+ -- handle events
+ for _, e in pairs(jin.event.poll()) do
+ if _onEvent then
+ _onEvent(e)
+ end
+ end
+
+ -- update
+ dt = now - last
+ if dt < fsec then
+ dt = fsec
+ end
+ if jin.core.onUpdate then
+ jin.core.onUpdate(dt)
+ end
+
+ -- bind to default render buffer
+ jin.graphics.bind()
+ jin.graphics.clear()
+ jin.graphics.color()
+ jin.graphics.study()
+
+ -- custom drawing
+ if jin.core.onDraw then
+ jin.core.onDraw()
+ end
+
+ -- render debug window
+ if jin.debug.status() then
+ jin.debug.render()
+ end
+
+ -- swap window buffer
+ jin.graphics.present()
+
+ end
+end
+
+local function onError(msg)
+ local tab = ' '
+ print("Error:\n" .. msg)
+ function jin.core.onEvent(e)
+ if e.type == 'quit' then
+ jin.core.quit()
+ end
+ end
+ local ww, wh = jin.graphics.size()
+ function jin.core.onDraw()
+ jin.graphics.write("Error: ", 10, 10, 30, 3, 30)
+ jin.graphics.write(msg, 10, 50)
+ end
+end
+
+if jin.filesystem.exist("main.lua") then
+ -- require main game script
+ xpcall(function() require"main" end, onError)
+ jin.core.run()
+else
+ -- no game
+ function jin.core.onEvent(e)
+ if e.type == 'quit' then
+ jin.core.quit()
+ end
+ end
+ function jin.core.onDraw()
+ jin.graphics.clear(111, 134, 125, 255)
+ local ww, wh = jin.graphics.size()
+ local fw, fh = jin.graphics.box("no game", 20, 1, 20)
+ jin.graphics.write("no game", ww /2 - fw / 2, wh * 2/3, 16, 1, 18)
+ end
+ jin.core.run()
+end
diff --git a/src/lua/embed/boot.lua.h b/src/lua/embed/boot.lua.h
new file mode 100644
index 0000000..21c1899
--- /dev/null
+++ b/src/lua/embed/boot.lua.h
@@ -0,0 +1,156 @@
+/* boot.lua */
+static const char* boot_lua = R"(
+
+-- init filesystem
+jin._argv[2] = jin._argv[2] or '.'
+jin.filesystem.init()
+jin.filesystem.mount(jin._argv[2])
+
+-- config
+local conf = {}
+if jin.filesystem.exist("config.lua") then
+ conf = require "config"
+end
+conf.width = conf.width or 600
+conf.height = conf.height or 500
+conf.fps = conf.fps or 60
+conf.vsync = conf.vsync or false
+conf.title = conf.title or ("jin v" .. jin.version())
+
+-- initialize subsystems
+jin.graphics.init(conf)
+--jin.audio.init(conf)
+
+-- open debug mode, must after jin.graphics.init
+if jin._argv[3] == '-d' then
+ jin.debug.init()
+end
+
+function jin.core.run()
+ local load = jin.core.load
+ local running = jin.core.running
+ local second = jin.time.second
+ local sleep = jin.time.sleep
+ local poll = jin.event.poll
+ local unbind = jin.graphics.unbind
+ local clear = jin.graphics.clear
+ local color = jin.graphics.color
+ local study = jin.graphics.study
+ local onDraw = jin.core.onDraw
+ local onUpdate = jin.core.onUpdate
+ local onEvent = jin.core.onEvent
+ local present = jin.graphics.present
+ local setkey = jin.keyboard.set
+
+ local dstatus = jin.debug.status
+ local drender = jin.debug.render
+
+ local fps = conf.fps
+
+ local _onEvent = function (e)
+ if e.type == "keydown" then
+ setkey(e.key, true)
+ elseif e.type == "keyup" then
+ setkey(e.key, false)
+ end
+ if onEvent then
+ onEvent(e)
+ end
+ end
+
+ if load then
+ load()
+ end
+
+ local now = second()
+ local last = now
+ local fsec = 1/fps
+ local dt = 0
+
+ while(running()) do
+ -- frame controle
+ last = now
+ now = second()
+ dt = now - last
+ if dt < fsec then
+ sleep(fsec - dt)
+ dt = fsec
+ end
+
+ -- handle events
+ for _, e in pairs(poll()) do
+ if _onEvent then
+ _onEvent(e)
+ end
+ end
+
+ -- update
+ if onUpdate then
+ onUpdate(dt)
+ end
+
+ -- bind to default render buffer
+ unbind()
+ clear()
+ color()
+ study()
+
+ -- custom drawing
+ if onDraw then
+ onDraw()
+ end
+
+ -- render debug window
+ if dstatus() then
+ drender()
+ end
+
+ -- swap window buffer
+ present()
+ end
+end
+
+local function onError(msg)
+ local tab = ' '
+ print("Error:\n" .. msg)
+ function jin.core.onEvent(e)
+ if e.type == 'quit' then
+ jin.core.quit()
+ end
+ end
+ local ww, wh = jin.graphics.size()
+ function jin.core.onDraw()
+ jin.graphics.write("Error: ", 10, 10, 30, 3, 30)
+ jin.graphics.write(msg, 10, 50)
+ end
+end
+
+local function main()
+ if jin.filesystem.exist("main.lua") then
+ -- require main game script
+ xpcall(function() require"main" end, onError)
+ jin.core.run()
+ else
+ -- no game
+ function jin.core.onEvent(e)
+ if e.type == 'quit' then
+ jin.core.quit()
+ end
+ end
+ function jin.core.onDraw()
+ jin.graphics.clear(111, 134, 125, 255)
+ local ww, wh = jin.graphics.size()
+ local fw, fh = jin.graphics.box("no game", 20, 1, 20)
+ jin.graphics.write("no game", ww /2 - fw / 2, wh * 2/3, 16, 1, 18)
+ end
+ jin.core.run()
+ end
+ -- quit subsystems
+ jin.graphics.destroy()
+ -- exit whole game
+ jin.core.exit()
+end
+
+main()
+
+)";
diff --git a/src/lua/embed/debug.lua b/src/lua/embed/debug.lua
new file mode 100644
index 0000000..76f59ed
--- /dev/null
+++ b/src/lua/embed/debug.lua
@@ -0,0 +1,128 @@
+--[[
+ for debug purpose
+ +-------------------+
+ |debug msg old |
+ |... |
+ |... |
+ |... |
+ |debug msg new |
+ +-------------------+
+]]
+
+jin.debug = jin.debug or {}
+
+-- render panel
+local panel = nil
+
+local debug = false
+
+-- debug msg buffer
+local buffer = {}
+
+-- configure
+local bsize = 10
+local fsize = 15
+local lheight = 18
+local alpha = 220
+local margin = 10
+
+-- refresh buffer or not
+local refresh = true
+
+function jin.debug.init()
+ debug = true
+ panel = jin.graphics.Canvas(jin.graphics.size())
+end
+
+-- set buffer size
+function jin.debug.size(c)
+ bsize = c
+end
+
+function jin.debug.print(msg)
+ if not debug then return end
+
+ msg = tostring(msg)
+ local tp = type(msg)
+ if tp ~= "string" and tp ~= "number" then
+ msg = string.format("print failed, expect string or number but get a %s", tp)
+ end
+
+ -- remove the first one (old msg)
+ if #buffer >= bsize then
+ table.remove(buffer, 1)
+ end
+
+ buffer[#buffer + 1] = msg
+ refresh = true
+end
+
+-- clear debug buffer
+function jin.debug.clear()
+ buffer = {}
+end
+
+local function getStrHeight(str, lheight)
+ local h = lheight
+ if #str == 0 then
+ h = 0
+ end
+ for i = 1, #str do
+ local c = string.sub(str, i, i)
+ if c == '\n' then
+ h = h + lheight
+ end
+ end
+ return h
+end
+
+local function getBgQuad()
+ local width, height = 0, 0
+ for i = 1, #buffer do
+ local w, h = jin.graphics.box( buffer[i], fsize, 1, lheight)
+ height = height + h
+ if width < w then
+ width = w
+ end
+ end
+ return width, height
+end
+
+-- render to screen
+function jin.debug.render()
+ if not debug then return end
+
+ if refresh then
+
+ jin.graphics.bind(panel)
+
+ jin.graphics.clear(0, 0, 0, 0)
+
+ jin.graphics.study()
+
+ local ww, wh = jin.graphics.size()
+ local bgw, bgh = getBgQuad()
+ jin.graphics.color(0, 0, 0, alpha)
+ jin.graphics.rect("fill", 0, wh - bgh - margin, bgw + margin, bgh + margin)
+
+ jin.graphics.color()
+ local y = wh
+ for i = #buffer, 1, -1 do
+ local msg = buffer[i]
+ local h = getStrHeight(msg, lheight)
+ y = y - h
+ jin.graphics.write(msg, margin / 2, y - margin/ 2, fsize, 1, lheight)
+ end
+
+ jin.graphics.bind()
+
+ refresh = false
+ end
+
+ jin.graphics.color()
+ jin.graphics.draw(panel, 0, 0)
+end
+
+function jin.debug.status()
+ return debug
+end
diff --git a/src/lua/embed/debug.lua.h b/src/lua/embed/debug.lua.h
new file mode 100644
index 0000000..79c95ba
--- /dev/null
+++ b/src/lua/embed/debug.lua.h
@@ -0,0 +1,132 @@
+/* debug.lua */
+static const char* debug_lua = R"(
+--[[
+ for debug purpose
+ +-------------------+
+ |debug msg old |
+ |... |
+ |... |
+ |... |
+ |debug msg new |
+ +-------------------+
+]]
+
+jin.debug = jin.debug or {}
+
+-- render panel
+local panel = nil
+
+local debug = false
+
+-- debug msg buffer
+local buffer = {}
+
+-- configure
+local bsize = 10
+local fsize = 15
+local lheight = 18
+local alpha = 220
+local margin = 10
+
+-- refresh buffer or not
+local refresh = true
+
+function jin.debug.init()
+ debug = true
+ panel = jin.graphics.Canvas(jin.graphics.size())
+end
+
+-- set buffer size
+function jin.debug.size(c)
+ bsize = c
+end
+
+function jin.debug.print(msg)
+ if not debug then return end
+
+ msg = tostring(msg)
+ local tp = type(msg)
+ if tp ~= "string" and tp ~= "number" then
+ msg = string.format("print failed, expect string or number but get a %s", tp)
+ end
+
+ -- remove the first one (old msg)
+ if #buffer >= bsize then
+ table.remove(buffer, 1)
+ end
+
+ buffer[#buffer + 1] = msg
+ refresh = true
+end
+
+-- clear debug buffer
+function jin.debug.clear()
+ buffer = {}
+end
+
+local function getStrHeight(str, lheight)
+ local h = lheight
+ if #str == 0 then
+ h = 0
+ end
+ for i = 1, #str do
+ local c = string.sub(str, i, i)
+ if c == '\n' then
+ h = h + lheight
+ end
+ end
+ return h
+end
+
+local function getBgQuad()
+ local width, height = 0, 0
+ for i = 1, #buffer do
+ local w, h = jin.graphics.box( buffer[i], fsize, 1, lheight)
+ height = height + h
+ if width < w then
+ width = w
+ end
+ end
+ return width, height
+end
+
+-- render to screen
+function jin.debug.render()
+ if not debug then return end
+
+ if refresh then
+
+ jin.graphics.bind(panel)
+
+ jin.graphics.clear(0, 0, 0, 0)
+
+ jin.graphics.study()
+
+ local ww, wh = jin.graphics.size()
+ local bgw, bgh = getBgQuad()
+ jin.graphics.color(0, 0, 0, alpha)
+ jin.graphics.rect("fill", 0, wh - bgh - margin, bgw + margin, bgh + margin)
+
+ jin.graphics.color()
+ local y = wh
+ for i = #buffer, 1, -1 do
+ local msg = buffer[i]
+ local h = getStrHeight(msg, lheight)
+ y = y - h
+ jin.graphics.write(msg, margin / 2, y - margin/ 2, fsize, 1, lheight)
+ end
+
+ jin.graphics.bind()
+
+ refresh = false
+ end
+
+ jin.graphics.color()
+ jin.graphics.draw(panel, 0, 0)
+end
+
+function jin.debug.status()
+ return debug
+end
+
+)"; \ No newline at end of file
diff --git a/src/lua/embed/embed.h b/src/lua/embed/embed.h
new file mode 100644
index 0000000..2ef8b75
--- /dev/null
+++ b/src/lua/embed/embed.h
@@ -0,0 +1,51 @@
+#ifndef __JIN_LUA_EMBED_H
+#define __JIN_LUA_EMBED_H
+#include <cstring>
+
+namespace jin
+{
+namespace embed
+{
+
+ /**
+ * embed lua script to context.
+ */
+#define embed(L, script, name) \
+ if(luaL_loadbuffer(L, script, strlen(script), name) == 0)\
+ lua_call(L, 0, 0);
+
+ /**
+ * embed structure.
+ */
+ struct jin_Embed
+ {
+ const char* fname, *source;
+ };
+
+ static void boot(lua_State* L)
+ {
+ // embed scripts
+ #include "graphics.lua.h" // graphics
+ #include "keyboard.lua.h" // keyboard
+ #include "mouse.lua.h" // mouse
+ #include "debug.lua.h" // debug
+ #include "boot.lua.h" // boot
+
+ // embed scripts
+ const jin_Embed scripts[] = {
+ {"graphics.lua", graphics_lua},
+ {"keyboard.lua", keyboard_lua},
+ {"mouse.lua", mouse_lua},
+ {"debug.lua", debug_lua},
+ {"boot.lua", boot_lua},
+ {0, 0}
+ };
+
+ // load all emebd lua scripts
+ for (int i = 0; scripts[i].fname; ++i)
+ embed(L, scripts[i].source, scripts[i].fname);
+ }
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/lua/embed/graphics.lua b/src/lua/embed/graphics.lua
new file mode 100644
index 0000000..03a891d
--- /dev/null
+++ b/src/lua/embed/graphics.lua
@@ -0,0 +1,6 @@
+-----------------
+-- jin.graphics
+-----------------
+
+jin.graphics = jin.graphics or {}
+
diff --git a/src/lua/embed/graphics.lua.h b/src/lua/embed/graphics.lua.h
new file mode 100644
index 0000000..85cf979
--- /dev/null
+++ b/src/lua/embed/graphics.lua.h
@@ -0,0 +1,8 @@
+/* graphics.lua */
+static const char* graphics_lua = R"(
+-----------------
+-- jin.graphics
+-----------------
+
+jin.graphics = jin.graphics or {}
+)";
diff --git a/src/lua/embed/keyboard.lua b/src/lua/embed/keyboard.lua
new file mode 100644
index 0000000..08214f8
--- /dev/null
+++ b/src/lua/embed/keyboard.lua
@@ -0,0 +1,16 @@
+--[[
+ jin.keyboard extension
+]]
+
+jin.keyboard = jin.keyboard or {}
+
+local keys = {}
+
+function jin.keyboard.isDown(k)
+ return keys[k]
+end
+
+function jin.keyboard.set(k, status)
+ keys[k] = status
+end
+
diff --git a/src/lua/embed/keyboard.lua.h b/src/lua/embed/keyboard.lua.h
new file mode 100644
index 0000000..66e3c2a
--- /dev/null
+++ b/src/lua/embed/keyboard.lua.h
@@ -0,0 +1,20 @@
+
+static const char* keyboard_lua = R"(
+--[[
+ jin.keyboard extension
+]]
+
+jin.keyboard = jin.keyboard or {}
+
+local keys = {}
+
+function jin.keyboard.isDown(k)
+ return keys[k]
+end
+
+function jin.keyboard.set(k, status)
+ keys[k] = status
+end
+
+
+)";
diff --git a/src/lua/embed/mouse.lua b/src/lua/embed/mouse.lua
new file mode 100644
index 0000000..9dcd472
--- /dev/null
+++ b/src/lua/embed/mouse.lua
@@ -0,0 +1,15 @@
+--[[
+ jin.mouse extension
+]]
+
+jin.mouse = jin.mouse or {}
+
+local button = {}
+
+function jin.mouse.isDown(btn)
+ return button[btn]
+end
+
+function jin.mouse.set(btn, status)
+ button[btn] = status
+end
diff --git a/src/lua/embed/mouse.lua.h b/src/lua/embed/mouse.lua.h
new file mode 100644
index 0000000..f57d08c
--- /dev/null
+++ b/src/lua/embed/mouse.lua.h
@@ -0,0 +1,18 @@
+static const char* mouse_lua = R"(
+--[[
+ jin.mouse extension
+]]
+
+jin.mouse = jin.mouse or {}
+
+local button = {}
+
+function jin.mouse.isDown(btn)
+ return button[btn]
+end
+
+function jin.mouse.set(btn, status)
+ button[btn] = status
+end
+
+)"; \ No newline at end of file
diff --git a/src/lua/embed/path.lua b/src/lua/embed/path.lua
new file mode 100644
index 0000000..5b99dd2
--- /dev/null
+++ b/src/lua/embed/path.lua
@@ -0,0 +1,15 @@
+--[[
+ jin.path extension
+]]
+
+jin.path = jin.path or {}
+
+-- game root directory
+jin._root = nil
+
+-- return full path of a given path
+function jin.path.full(path)
+ local root = jin._dir .. '/' .. jin._argv[2]
+ return root .. '/' .. path
+end
+
diff --git a/src/lua/embed/path.lua.h b/src/lua/embed/path.lua.h
new file mode 100644
index 0000000..b398c99
--- /dev/null
+++ b/src/lua/embed/path.lua.h
@@ -0,0 +1,18 @@
+/* path.lua */
+static const char* path_lua = R"(
+--[[
+ jin.path extension
+]]
+
+jin.path = jin.path or {}
+
+-- game root directory
+jin._root = nil
+
+-- return full path of a given path
+function jin.path.full(path)
+ local root = jin._dir .. '/' .. jin._argv[2]
+ return root .. '/' .. path
+end
+
+)"; \ No newline at end of file
diff --git a/src/lua/event/luaopen_event.cpp b/src/lua/event/luaopen_event.cpp
new file mode 100644
index 0000000..8a84c97
--- /dev/null
+++ b/src/lua/event/luaopen_event.cpp
@@ -0,0 +1,124 @@
+/**
+* Event module
+*/
+#include <SDl2/SDL.h>
+
+#include "lua/luax.h"
+#include "libjin/jin.h"
+
+using namespace jin::input;
+
+namespace jin
+{
+namespace lua
+{
+
+ static inline const char* buttonstr(int id) {
+ switch (id) {
+ case 1: return "left";
+ case 2: return "middle";
+ case 3: return "right";
+ case 4: return "wheelup";
+ case 5: return "wheeldown";
+ default: return "?";
+ }
+ }
+
+ static inline const char* wheelstr(int dir)
+ {
+
+ }
+
+ /**
+ * Load event poll, return a iterator(a table).
+ */
+ static int l_event_poll(lua_State *L)
+ {
+ // table to store events
+ luax_newtable(L);
+ SDL_Event e;
+ int i = 1;
+ poll:
+ while (SDL_PollEvent(&e))
+ {
+ // each event is a table
+ luax_newtable(L);
+ switch (e.type)
+ {
+ case SDL_QUIT:
+ luax_setfield_string(L, "type", "quit");
+ break;
+
+ case SDL_KEYDOWN:
+ luax_setfield_string(L, "type", "keydown");
+ luax_setfield_string(L, "key", SDL_GetKeyName(e.key.keysym.sym));
+ break;
+
+ case SDL_KEYUP:
+ luax_setfield_string(L, "type", "keyup");
+ luax_setfield_string(L, "key", SDL_GetKeyName(e.key.keysym.sym));
+ break;
+
+ case SDL_MOUSEMOTION:
+ luax_setfield_string(L, "type", "mousemotion");
+ luax_setfield_number(L, "x", e.motion.x);
+ luax_setfield_number(L, "y", e.motion.y);
+ break;
+
+ case SDL_MOUSEBUTTONDOWN:
+ luax_setfield_string(L, "type", "mousebuttondown");
+ luax_setfield_string(L, "button", buttonstr(e.button.button));
+ luax_setfield_number(L, "x", e.button.x);
+ luax_setfield_number(L, "y", e.button.y);
+ break;
+
+ case SDL_MOUSEBUTTONUP:
+ luax_setfield_string(L, "type", "mousebuttonup");
+ luax_setfield_string(L, "button", buttonstr(e.button.button));
+ luax_setfield_number(L, "x", e.button.x);
+ luax_setfield_number(L, "y", e.button.y);
+ break;
+
+ case SDL_MOUSEWHEEL:
+ luax_setfield_string(L, "type", "wheel");
+ if(e.wheel.x == -1)
+ luax_setfield_string(L, "x", "left");
+ else if(e.wheel.x == 1)
+ luax_setfield_string(L, "x", "right");
+ else
+ luax_setfield_string(L, "x", "none");
+
+ if (e.wheel.y == -1)
+ luax_setfield_string(L, "y", "near");
+ else if (e.wheel.y == 1)
+ luax_setfield_string(L, "y", "far");
+ else
+ luax_setfield_string(L, "y", "none");
+ break;
+
+ default:
+ /* ignore other events */
+ luax_pop(L, 1); // pop table out
+ goto poll;
+ break;
+ }
+ luax_rawseti(L, -2, i++);
+ }
+ return 1;
+ }
+
+ static const luaL_Reg f[] = {
+ {"poll", l_event_poll},
+ {0 ,0 }
+ };
+
+ /**
+ * load event module
+ */
+ int luaopen_event(lua_State* L)
+ {
+ luax_newlib(L, f);
+ return 1;
+ }
+}
+} \ No newline at end of file
diff --git a/src/lua/filesystem/luaopen_filesystem.cpp b/src/lua/filesystem/luaopen_filesystem.cpp
new file mode 100644
index 0000000..db0216b
--- /dev/null
+++ b/src/lua/filesystem/luaopen_filesystem.cpp
@@ -0,0 +1,142 @@
+#include "lua/luax.h"
+#include "libjin/jin.h"
+#include <string>
+
+using namespace jin::fs;
+
+namespace jin
+{
+namespace lua
+{
+
+ static struct
+ {
+ Filesystem* fs;
+ } context;
+
+ static int l_init(lua_State* L)
+ {
+ context.fs = Filesystem::get();
+ return 0;
+ }
+
+ /**
+ * set current game root, like
+ * C:/jin/games/tank/
+ */
+ static int l_mount(lua_State* L)
+ {
+ const char* path = luax_checkstring(L, 1);
+ context.fs->mount(path);
+ return 0;
+ }
+
+ /**
+ *
+ */
+ static int l_isDir(lua_State *L)
+ {
+ const char* path = luax_checkstring(L, 1);
+ int r = context.fs->isDir(path);
+ luax_pushboolean(L, r);
+ return 1;
+ }
+
+ /**
+ *
+ */
+ static int l_exist(lua_State * L)
+ {
+ const char* path = luax_checkstring(L, 1);
+ int r = context.fs->exists(path);
+ luax_pushboolean(L, r);
+ return 1;
+ }
+
+ static int l_isdir(lua_State* L)
+ {
+ const char* path = luax_checkstring(L, 1);
+ int r = context.fs->isDir(path);
+ luax_pushboolean(L, r);
+ return 1;
+ }
+
+ // load but dont run it
+ static int loadf(lua_State* L)
+ {
+ const char* filename = lua_tostring(L, -1);
+ Buffer bf;
+ context.fs->read(filename, &bf);
+ luax_loadbuffer(L, (const char*)bf.data, bf.size, filename);
+ return 1;
+ }
+
+ static int loader(lua_State* L)
+ {
+ const char * filename = lua_tostring(L, -1);
+
+ std::string tmp(filename);
+ tmp += ".lua";
+
+ int size = tmp.size();
+
+ for (int i = 0; i<size - 4; ++i)
+ {
+ if (tmp[i] == '.')
+ {
+ tmp[i] = '/';
+ }
+ }
+
+ // Check whether file exists.
+ if (context.fs->exists(tmp.c_str()))
+ {
+ lua_pop(L, 1);
+ lua_pushstring(L, tmp.c_str());
+ // Ok, load it.
+ return loadf(L);
+ }
+
+ tmp = filename;
+ size = tmp.size();
+ for (int i = 0; i<size; ++i)
+ {
+ if (tmp[i] == '.')
+ {
+ tmp[i] = '/';
+ }
+ }
+
+ if (context.fs->isDir(tmp.c_str()))
+ {
+ tmp += "/init.lua";
+ if (context.fs->exists(tmp.c_str()))
+ {
+ lua_pop(L, 1);
+ lua_pushstring(L, tmp.c_str());
+ // Ok, load it.
+ return loadf(L);
+ }
+ }
+
+ lua_pushfstring(L, "\n\tno file \"%s\" in jin game directories.\n", (tmp + ".lua").c_str());
+ return 1;
+ }
+
+ static const luaL_Reg f[] = {
+ {"init", l_init},
+ {"mount", l_mount},
+ {"isdir", l_isDir},
+ {"exist", l_exist},
+ {0, 0}
+ };
+
+ int luaopen_filesystem(lua_State* L)
+ {
+ luax_newlib(L, f);
+ luax_register_searcher(L, loader, 1);
+ return 0;
+ }
+
+}
+} \ No newline at end of file
diff --git a/src/lua/graphics/luaopen_Canvas.cpp b/src/lua/graphics/luaopen_Canvas.cpp
new file mode 100644
index 0000000..5dede84
--- /dev/null
+++ b/src/lua/graphics/luaopen_Canvas.cpp
@@ -0,0 +1,75 @@
+#include "lua/luax.h"
+#include "lua/luaopen_types.h"
+#include "libjin/jin.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ using namespace jin::render;
+
+ static inline Canvas* checkCanvas(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, TYPE_CANVAS);
+ if (proxy != nullptr)
+ return (Canvas*)proxy->object;
+ return nullptr;
+ }
+
+ static int l_getWidth(lua_State* L)
+ {
+ Canvas* c = checkCanvas(L);
+ luax_pushnumber(L, c->getWidth());
+ return 1;
+ }
+
+ static int l_getHeight(lua_State* L)
+ {
+ Canvas* c = checkCanvas(L);
+ luax_pushnumber(L, c->getHeight());
+ return 1;
+ }
+
+ static int l_getSize(lua_State* L)
+ {
+ Canvas* c = checkCanvas(L);
+ luax_pushnumber(L, c->getWidth());
+ luax_pushnumber(L, c->getHeight());
+ return 2;
+ }
+
+ static int l_setAnchor(lua_State* L)
+ {
+ Canvas* c = checkCanvas(L);
+ int x = luax_checknumber(L, 1);
+ int y = luax_checknumber(L, 2);
+ c->setAnchor(x, y);
+ return 0;
+ }
+
+ static int l_gc(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, TYPE_CANVAS);
+ Canvas* canvas = (Canvas*)proxy->object;
+ delete canvas;
+ return 0;
+ }
+
+ static const luaL_Reg f[] = {
+ {"__gc", l_gc},
+ {"getWidth", l_getWidth},
+ {"getHeight", l_getHeight},
+ {"getSize", l_getSize},
+ {"setAnchor", l_setAnchor},
+ {0, 0 }
+ };
+
+ int luaopen_Canvas(lua_State* L)
+ {
+ luax_newtype(L, TYPE_CANVAS, f);
+ return 0;
+ }
+
+}// lua
+}// jin \ No newline at end of file
diff --git a/src/lua/graphics/luaopen_Font.cpp b/src/lua/graphics/luaopen_Font.cpp
new file mode 100644
index 0000000..387b220
--- /dev/null
+++ b/src/lua/graphics/luaopen_Font.cpp
@@ -0,0 +1,45 @@
+#include "lua/luax.h"
+#include "lua/luaopen_types.h"
+#include "libjin/jin.h"
+
+using namespace jin::render;
+
+namespace jin
+{
+namespace lua
+{
+
+ static int l_gc(lua_State* L)
+ {
+ return 0;
+ }
+
+ static int l_box(lua_State* L)
+ {
+ Font* font = (Font*)luax_checktype(L, 1, TYPE_FONT);
+ const char* text = luax_checkstring(L, 2);
+ int fheight = luax_checknumber(L, 3);
+ int spacing = luax_checknumber(L, 4);
+ int lheight = luax_checknumber(L, 5);
+ int w, h;
+ font->box(text, fheight, lheight, spacing, &w, &h);
+ luax_pushnumber(L, w);
+ luax_pushnumber(L, h);
+ return 2;
+ }
+
+ static const luaL_Reg f[] = {
+ {"__gc", l_gc},
+ {"box", l_box},
+ {0, 0}
+ };
+
+ int luaopen_Font(lua_State* L)
+ {
+ luax_newtype(L, TYPE_FONT, f);
+
+ return 0;
+ }
+
+}
+} \ No newline at end of file
diff --git a/src/lua/graphics/luaopen_Image.cpp b/src/lua/graphics/luaopen_Image.cpp
new file mode 100644
index 0000000..c5648a5
--- /dev/null
+++ b/src/lua/graphics/luaopen_Image.cpp
@@ -0,0 +1,89 @@
+#include "lua/luax.h"
+#include "libjin/jin.h"
+#include "lua/luaopen_types.h"
+
+using namespace jin::render;
+
+namespace jin
+{
+namespace lua
+{
+
+ static inline Image* checkImage(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, TYPE_IMAGE);
+ if (proxy != 0 && proxy != nullptr)
+ return (Image*)proxy->object;
+ return nullptr;
+ }
+
+ static int l_getWidth(lua_State* L)
+ {
+ Image* i = checkImage(L);
+ luax_pushnumber(L, i->getWidth());
+ return 1;
+ }
+
+ static int l_getHeight(lua_State *L)
+ {
+ Image* i = checkImage(L);
+ luax_pushnumber(L, i->getHeight());
+ return 1;
+ }
+
+ static int l_getPixel(lua_State* L)
+ {
+ Image* i = checkImage(L);
+ int x = luax_checknumber(L, 2);
+ int y = luax_checknumber(L, 3);
+ color c = i->getPixel(x, y);
+ luax_pushnumber(L, c.rgba.r);
+ luax_pushnumber(L, c.rgba.g);
+ luax_pushnumber(L, c.rgba.b);
+ luax_pushnumber(L, c.rgba.a);
+ return 4;
+ }
+
+ static int l_setAnchor(lua_State* L)
+ {
+ Image* i = checkImage(L);
+ int x = luax_checknumber(L, 2);
+ int y = luax_checknumber(L, 3);
+ i->setAnchor(x, y);
+ return 0;
+ }
+
+ static int l_getSize(lua_State* L)
+ {
+ Image* i = checkImage(L);
+ luax_pushnumber(L, i->getWidth());
+ luax_pushnumber(L, i->getHeight());
+ return 2;
+ }
+
+ static int l_gc(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, TYPE_IMAGE);
+ Image* img = (Image*)proxy->object;
+ delete img;
+ return 0;
+ }
+
+ static const luaL_Reg f[] = {
+ {"__gc", l_gc},
+ {"getWidth", l_getWidth},
+ {"getHeight", l_getHeight},
+ {"getSize", l_getSize},
+ {"getPixel", l_getPixel},
+ {"setAnchor", l_setAnchor},
+ {0, 0 }
+ };
+
+ int luaopen_Image(lua_State* L)
+ {
+ luax_newtype(L, TYPE_IMAGE, f);
+ return 0;
+ }
+
+}// graphics
+}// jin \ No newline at end of file
diff --git a/src/lua/graphics/luaopen_JSL.cpp b/src/lua/graphics/luaopen_JSL.cpp
new file mode 100644
index 0000000..93ca5d3
--- /dev/null
+++ b/src/lua/graphics/luaopen_JSL.cpp
@@ -0,0 +1,146 @@
+#include "lua/luax.h"
+#include "libjin/jin.h"
+#include "lua/luaopen_types.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ using namespace render;
+
+ static inline JSLProgram* checkJSLProgram(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, TYPE_JSL);
+ if(proxy != nullptr)
+ return (JSLProgram*)proxy->object;
+ return nullptr;
+ }
+
+ static enum VARIABLE_TYPE
+ {
+ INVALID = 0,
+
+ NUMBER,
+ IMAGE,
+ CANVAS,
+ VEC2,
+ VEC3,
+ VEC4,
+ COLOR,
+ };
+
+ static VARIABLE_TYPE strtotype(const char* str)
+ {
+ std::string s = std::string(str);
+ if (s == "number") return NUMBER;
+ else if (s == "Image") return IMAGE;
+ else if (s == "Canvas") return CANVAS;
+ else if (s == "vec2") return VEC2;
+ else if (s == "vec3") return VEC3;
+ else if (s == "vec4") return VEC4;
+ else if (s == "Color") return COLOR;
+ else return INVALID;
+ }
+
+ /**
+ * Use send function send variables to JSL program.
+ */
+ static int l_send(lua_State* L)
+ {
+ JSLProgram* jsl = checkJSLProgram(L);
+ // number Image Texel
+ const char* typestr = luax_checkstring(L, 2);
+ // variable name
+ const char* variable = luax_checkstring(L, 3);
+ if (typestr != nullptr)
+ {
+ int type = strtotype(typestr);
+ switch (type)
+ {
+ case NUMBER:
+ {
+ float number = luax_checknumber(L, 4);
+ jsl->sendFloat(variable, number);
+ break;
+ }
+ case IMAGE:
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 4, TYPE_IMAGE);
+ Image* img = (Image*)proxy->object;
+ jsl->sendImage(variable, img);
+ break;
+ }
+ case CANVAS:
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 4, TYPE_IMAGE);
+ Canvas* canvas = (Canvas*)proxy->object;
+ jsl->sendCanvas(variable, canvas);
+ break;
+ }
+ case VEC2:
+ {
+ float x = luax_checknumber(L, 4);
+ float y = luax_checknumber(L, 5);
+ jsl->sendVec2(variable, x, y);
+ break;
+ }
+ case VEC3:
+ {
+ float x = luax_checknumber(L, 4);
+ float y = luax_checknumber(L, 5);
+ float z = luax_checknumber(L, 6);
+ jsl->sendVec3(variable, x, y, z);
+ break;
+ }
+ case VEC4:
+ {
+ float x = luax_checknumber(L, 4);
+ float y = luax_checknumber(L, 5);
+ float z = luax_checknumber(L, 6);
+ float w = luax_checknumber(L, 7);
+ jsl->sendVec4(variable, x, y, z, w);
+ break;
+ }
+ case COLOR:
+ {
+ color col;
+ col.rgba.r = luax_checkinteger(L, 4);
+ col.rgba.g = luax_checkinteger(L, 5);
+ col.rgba.b = luax_checkinteger(L, 6);
+ col.rgba.a = luax_checkinteger(L, 7);
+ jsl->sendColor(variable, &col);
+ break;
+ }
+ default:
+ return 0;
+ }
+ }
+ return 1;
+ }
+
+ static int l_gc(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, TYPE_JSL);
+ JSLProgram* jsl = (JSLProgram*)proxy->object;
+ delete jsl;
+ return 0;
+ }
+
+ static const luaL_Reg f[] = {
+ {"__gc", l_gc },
+ {"send", l_send},
+ {0, 0}
+ };
+
+ /**
+ * JSL program
+ */
+ int luaopen_JSL(lua_State* L)
+ {
+ luax_newtype(L, TYPE_JSL, f);
+ return 0;
+ }
+
+}
+} \ No newline at end of file
diff --git a/src/lua/graphics/luaopen_graphics.cpp b/src/lua/graphics/luaopen_graphics.cpp
new file mode 100644
index 0000000..6fa5a4d
--- /dev/null
+++ b/src/lua/graphics/luaopen_graphics.cpp
@@ -0,0 +1,524 @@
+#include "libjin/jin.h"
+#include "lua/luax.h"
+#include "lua/luaopen_types.h"
+#include "lua/embed/graphics.lua.h"
+
+namespace jin
+{
+namespace lua
+{
+ using namespace render;
+ using namespace fs;
+
+ /**
+ * jin.graphics context, storge some module
+ * shared variables.
+ */
+ static struct
+ {
+ color curRenderColor;
+ Font* curFont = 0;
+ Font* defaultFont = 0;
+ } context;
+
+ /**
+ * Init video system.
+ * jin.graphics.init(width, height, title)
+ */
+ static int l_init(lua_State* L)
+ {
+ Window* wnd = Window::get();
+ WindowSetting setting;
+ setting.width = luax_getfield_integer(L, 1, "width");
+ setting.height = luax_getfield_integer(L, 1, "height");
+ setting.title = luax_getfield_string(L, 1, "title");
+ setting.vsync = luax_getfield_bool(L, 1, "vsync");
+ luax_pushboolean(L, wnd->init(&setting));
+ return 1;
+ }
+
+ static int l_destroy(lua_State* L)
+ {
+ Window* wnd = Window::get();
+ wnd->quit();
+ return 0;
+ }
+
+ /**
+ * Get windows size.
+ */
+ static int l_getSize(lua_State* L)
+ {
+ Window* wnd = Window::get();
+ luax_pushnumber(L, wnd->getW());
+ luax_pushnumber(L, wnd->getH());
+ return 2;
+ }
+
+ /**
+ * Create a image userdata and set metatable for it.
+ */
+ static int l_newImage(lua_State* L)
+ {
+ Filesystem* fs = Filesystem::get();
+ const char* f = luax_checkstring(L, 1);
+ if (!fs->exists(f))
+ {
+ printf("Error: no such image %s\n", f);
+ exit(1);
+ }
+ Buffer b;
+ fs->read(f, &b);
+
+ Proxy* proxy = (Proxy*)luax_newinstance(L, TYPE_IMAGE, sizeof(Proxy));
+ Image* img = new Image((const char*)b.data, b.size);
+ proxy->bind(img);
+ return 1;
+ }
+
+ /**
+ * Create a new JSL program.
+ * graphics.Shader(program)
+ */
+ static int l_newShader(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_newinstance(L, TYPE_JSL, sizeof(JSLProgram));
+ const char* program = luax_checkstring(L, 1);
+ JSLProgram* jsl = new JSLProgram(program);
+ proxy->bind(jsl);
+ return 1;
+ }
+
+ /**
+ * Create a new Canvas, don't use it in loop, very slow.
+ * jin.graphics.newCanvas(w, h)
+ */
+ static int l_newCanvas(lua_State* L)
+ {
+ int w = luax_checknumber(L, 1);
+ int h = luax_checknumber(L, 2);
+ Proxy* proxy = (Proxy*)luax_newinstance(L, TYPE_CANVAS, sizeof(Proxy));
+ Canvas* cvs = new Canvas(w, h);
+ proxy->bind(cvs);
+ return 1;
+ }
+
+ static int l_clear(lua_State* L)
+ {
+ if (luax_gettop(L) == 0)
+ {
+ glClearColor(0, 0, 0, 1);
+ }
+ else
+ {
+ int r = luax_checknumber(L, 1);
+ int g = luax_checknumber(L, 2);
+ int b = luax_checknumber(L, 3);
+ int a = luax_checknumber(L, 4);
+ glClearColor(r / 255.f, g / 255.f, b / 255.f, a / 255.f);
+ }
+ glClear(GL_COLOR_BUFFER_BIT);
+ return 0;
+ }
+
+ /**
+ * Swap render buffers, present current buffer to front.
+ */
+ static int l_present(lua_State* L)
+ {
+ Window::get()->swapBuffers();
+ return 0;
+ }
+
+ // jin.graphics.draw(x, y, scalex, scaley, r)
+ static int l_draw(lua_State* L)
+ {
+ int x = luax_optnumber(L, 2, 0);
+ int y = luax_optnumber(L, 3, 0);
+ float sx = luax_optnumber(L, 4, 1);
+ float sy = luax_optnumber(L, 5, 1);
+ float r = luax_optnumber(L, 6, 0);
+ if (luax_istype(L, 1, TYPE_IMAGE))
+ {
+ Proxy* proxy = (Proxy*)luax_toudata(L, 1);
+ Image* img = (Image*)proxy->object;
+ img->draw(x, y, sx, sy, r);
+ }
+ else if (luax_istype(L, 1, TYPE_CANVAS))
+ {
+ Proxy* proxy = (Proxy*)luax_toudata(L, 1);
+ Canvas* p = (Canvas*)proxy->object;
+ p->draw(x, y, sx, sy, r);
+ }
+ else
+ {
+ /* wrong type */
+ luax_typerror(L, 1, "image or canvas");
+ }
+ return 0;
+ }
+
+ static int l_setColor(lua_State* L)
+ {
+ // jin.graphics.color() to set back to default
+ // render color
+ if (luax_gettop(L) == 0)
+ {
+ glColor4f(1, 1, 1, 1);
+ return 0;
+ }
+
+ context.curRenderColor.rgba.r = luax_checknumber(L, 1);
+ context.curRenderColor.rgba.g = luax_checknumber(L, 2);
+ context.curRenderColor.rgba.b = luax_checknumber(L, 3);
+ context.curRenderColor.rgba.a = luax_checknumber(L, 4);
+
+ glColor4f(context.curRenderColor.rgba.r / 255.f,
+ context.curRenderColor.rgba.g / 255.f,
+ context.curRenderColor.rgba.b / 255.f,
+ context.curRenderColor.rgba.a / 255.f);
+ return 0;
+ }
+
+ static int l_getColor(lua_State * L)
+ {
+ luax_pushnumber(L, context.curRenderColor.rgba.r);
+ luax_pushnumber(L, context.curRenderColor.rgba.g);
+ luax_pushnumber(L, context.curRenderColor.rgba.b);
+ luax_pushnumber(L, context.curRenderColor.rgba.a);
+ return 4;
+ }
+
+ static int l_bindCanvas(lua_State* L)
+ {
+ if (luax_gettop(L) == 0)
+ {
+ // bind to default canvas
+ Canvas::unbind();
+ return 0;
+ }
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, TYPE_CANVAS);
+ Canvas* c = (Canvas*)proxy->object;
+ c->bind();
+ return 0;
+ }
+
+ static int l_unbindCanvas(lua_State* L)
+ {
+ Canvas::unbind();
+ return 0;
+ }
+
+ static int l_useShader(lua_State* L)
+ {
+ if (luax_gettop(L) == 0)
+ {
+ JSLProgram::unuse();
+ return 0;
+ }
+ if (luax_istype(L, 1, TYPE_JSL))
+ {
+ Proxy* proxy = (Proxy*)luax_toudata(L, 1);
+ JSLProgram* jsl = (JSLProgram*)proxy->object;
+ jsl->use();
+ }
+ else
+ {
+ luax_typerror(L, 1, "JSL shader");
+ }
+ return 0;
+ }
+
+ static int l_unuseShader(lua_State* L)
+ {
+ JSLProgram::unuse();
+ return 0;
+ }
+
+ static int l_setBlend(lua_State* L)
+ {
+
+ return 0;
+ }
+
+ static RENDER_MODE strtomode(const char* str)
+ {
+ std::string s = std::string(str);
+ if (s == "fill") return FILL;
+ else if (s == "line") return LINE;
+ else return NONE;
+ }
+
+ /**
+ * draw pixel to screen
+ * jin.graphics.pixel(x, y)
+ */
+ static int l_drawpoint(lua_State* L)
+ {
+ int x = luax_checknumber(L, 1);
+ int y = luax_checknumber(L, 2);
+ render::point(x, y);
+
+ return 0;
+ }
+
+ static int l_drawLine(lua_State* L)
+ {
+ int x1 = luax_checknumber(L, 1);
+ int y1 = luax_checknumber(L, 2);
+ int x2 = luax_checknumber(L, 3);
+ int y2 = luax_checknumber(L, 4);
+ render::line(x1, y1, x2, y2);
+
+ return 0;
+ }
+
+ static int l_drawRect(lua_State* L)
+ {
+ const char* modestr = luax_checkstring(L, 1);
+ RENDER_MODE mode = strtomode(modestr);
+ if (mode != NONE)
+ {
+ int x = luax_checknumber(L, 2);
+ int y = luax_checknumber(L, 3);
+ int w = luax_checknumber(L, 4);
+ int h = luax_checknumber(L, 5);
+ render::rect(mode, x, y, w, h);
+ }
+ else
+ {
+ luax_typerror(L, 1, "'fill' or 'line'");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ static int l_drawCircle(lua_State* L)
+ {
+ const char* modestr = luax_checkstring(L, 1);
+ RENDER_MODE mode = strtomode(modestr);
+ if (mode != NONE)
+ {
+ int x = luax_checknumber(L, 2);
+ int y = luax_checknumber(L, 3);
+ float r = luax_checknumber(L, 4);
+ render::circle(mode, x, y, r);
+ }
+ else
+ {
+ luax_typerror(L, 1, "'fill' or 'line'");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ static int l_drawTriangle(lua_State* L)
+ {
+ const char* modestr = luax_checkstring(L, 1);
+ RENDER_MODE mode = strtomode(modestr);
+ if (mode != NONE)
+ {
+ int x = luax_checknumber(L, 2);
+ int y = luax_checknumber(L, 3);
+
+ int x2 = luax_checknumber(L, 3);
+ int y2 = luax_checknumber(L, 4);
+
+ int x3 = luax_checknumber(L, 5);
+ int y3 = luax_checknumber(L, 6);
+
+ render::triangle(mode, x, y, x2, y2, x3, y3);
+ }
+ else
+ {
+ luax_typerror(L, 1, "'fill' or 'line'");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ /**
+ * draw polygon.
+ * jin.graphics.polygon(mode, n, {{}, {}, {}...})
+ */
+ static int l_drawPolygon(lua_State* L)
+ {
+ const char* modestr = luax_checkstring(L, 1);
+ int n = luax_checknumber(L, 2);
+ RENDER_MODE mode = strtomode(modestr);
+ if (mode != NONE)
+ {
+ if (!luax_istable(L, 3))
+ {
+ luax_typerror(L, 3, "table");
+ return 1;
+ }
+ int tn = luax_tableidxlen(L, 3);
+ if (tn != n * 2)
+ {
+ static char* emsg = \
+ "number of polygon vertices doesn't match " \
+ "provided n, expect %d numbers but get %d";
+ luax_error(L, emsg, n * 2, tn);
+ return 1;
+ }
+ float* p = new float[2 * n];
+ for (int i = 1; i <= 2 * n; ++i)
+ p[i - 1] = luax_rawgetnumber(L, 3, i);
+ render::polygon(mode, p, n);
+ delete[] p;
+ }
+ else
+ {
+ luax_typerror(L, 1, "'fill' or 'line'");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ static int l_newFont(lua_State* L)
+ {
+ Font* font = (Font*)luax_newinstance(L, TYPE_FONT, sizeof(Font));
+ const char* path = luax_checkstring(L, 1);
+ Filesystem* fs = Filesystem::get();
+ Buffer b = {};
+ if (!fs->exists(path))
+ {
+ printf("Error: no such font %s\n", path);
+ exit(1);
+ }
+ fs->read(path, &b);
+ font->loadb((const unsigned char*)b.data);
+
+ return 1;
+ }
+
+ /**
+ * study font, 0 args for study default font.
+ */
+ static int l_study(lua_State* L)
+ {
+ int n = luax_gettop(L);
+ if (n == 0)
+ {
+ if (context.defaultFont == 0)
+ {
+ #include "data/font.ttf.h"
+ // load default font
+ context.defaultFont = new Font();
+ context.defaultFont->loadb(font_ttf);
+ }
+ context.curFont = context.defaultFont;
+ return 0;
+ }
+ Font* font = (Font*)luax_checktype(L, 1, TYPE_FONT);
+ context.curFont = font;
+ return 0;
+ }
+
+ /**
+ * draw text with current font(after study). befor write, must
+ * study a font.
+ */
+ static int l_write(lua_State* L)
+ {
+ if (context.curFont == 0)
+ return 0;
+
+ const char* text = luax_checkstring(L, 1);
+ int x = luax_checknumber(L, 2);
+ int y = luax_checknumber(L, 3);
+
+ int fh = luax_optnumber(L, 4, 15);
+ int spacing = luax_optnumber(L, 5, 1);
+ int lh = luax_optnumber(L, 6, 18);
+
+ context.curFont->render(text, x, y, fh, spacing, lh);
+
+ return 0;
+ }
+
+ /**
+ * get text bound box
+ */
+ static int l_box(lua_State* L)
+ {
+ const char* text = luax_checkstring(L, 1);
+ int fontheight = luax_checknumber(L, 2);
+ int spacing = luax_checknumber(L, 3);
+ int lineheight = luax_checknumber(L, 4);
+ int w, h;
+ context.curFont->box(text, fontheight, spacing, lineheight, &w, &h);
+ luax_pushnumber(L, w);
+ luax_pushnumber(L, h);
+ return 2;
+ }
+
+ static const luaL_Reg f[] = {
+ {"init", l_init},
+ {"size", l_getSize},
+ {"Image", l_newImage},
+ {"Shader", l_newShader},
+ {"Canvas", l_newCanvas},
+ {"Font", l_newFont},
+ /**
+ * before using box and write
+ * must call study to set
+ * current font
+ */
+ {"box", l_box},
+ {"write", l_write},
+ {"clear", l_clear},
+ {"draw", l_draw},
+ {"color", l_setColor},
+ {"palette", l_getColor},
+ {"present", l_present},
+ //{"blend", l_setBlend},
+ // study font
+ {"study", l_study},
+ // bind canvas
+ {"bind", l_bindCanvas},
+ {"unbind", l_unbindCanvas},
+ // use shader
+ {"use", l_useShader},
+ {"unuse", l_unuseShader},
+ // draw shapes
+ {"point", l_drawpoint},
+ {"line", l_drawLine},
+ {"rect", l_drawRect},
+ {"circle", l_drawCircle},
+ {"triangle", l_drawTriangle},
+ {"polygon", l_drawPolygon},
+ //
+ {"destroy", l_destroy},
+ {0, 0}
+ };
+
+ extern int luaopen_Image(lua_State* L);
+
+ extern int luaopen_Font(lua_State* L);
+
+ extern int luaopen_Canvas(lua_State* L);
+
+ extern int luaopen_JSL(lua_State* L);
+
+ int luaopen_graphics(lua_State* L)
+ {
+ // register types
+ luaopen_Image(L);
+ luaopen_Canvas(L);
+ luaopen_Font(L);
+ luaopen_JSL(L);
+
+ // load whole lib
+ luax_newlib(L, f);
+
+ return 1;
+ }
+
+}// lua
+}// jin
diff --git a/src/lua/joypad/joypad.h b/src/lua/joypad/joypad.h
new file mode 100644
index 0000000..e8d309b
--- /dev/null
+++ b/src/lua/joypad/joypad.h
@@ -0,0 +1,14 @@
+#ifndef __JIN_JOYPAD_H
+#define __JIN_JOYPAD_H
+
+namespace jin
+{
+namespace input
+{
+
+
+
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/lua/joypad/luaopen_joypad.cpp b/src/lua/joypad/luaopen_joypad.cpp
new file mode 100644
index 0000000..6c98c3b
--- /dev/null
+++ b/src/lua/joypad/luaopen_joypad.cpp
@@ -0,0 +1,21 @@
+#include "libjin/jin.h"
+#include "lua/luax.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ static const luaL_Reg f[] = {
+ { 0, 0 }
+ };
+
+ int luaopen_joypad(lua_State* L)
+ {
+ luax_newlib(L, f);
+
+ return 1;
+ }
+
+}
+} \ No newline at end of file
diff --git a/src/lua/keyboard/luaopen_keyboard.cpp b/src/lua/keyboard/luaopen_keyboard.cpp
new file mode 100644
index 0000000..ea1386c
--- /dev/null
+++ b/src/lua/keyboard/luaopen_keyboard.cpp
@@ -0,0 +1,16 @@
+#include "lua/luax.h"
+#include "lua/embed/keyboard.lua.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ int luaopen_keyboard(lua_State* L)
+ {
+ luax_newlib(L, 0);
+ return 1;
+ }
+
+}
+} \ No newline at end of file
diff --git a/src/lua/luaopen_jin.cpp b/src/lua/luaopen_jin.cpp
new file mode 100644
index 0000000..93e0422
--- /dev/null
+++ b/src/lua/luaopen_jin.cpp
@@ -0,0 +1,97 @@
+#include "luaopen_jin.h"
+#include "lua/luax.h"
+
+// embed all lua scripts
+#include "embed/embed.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ extern int luaopen_core(lua_State* L);
+ extern int luaopen_graphics(lua_State* L);
+ extern int luaopen_audio(lua_State* L);
+ extern int luaopen_net(lua_State* L);
+ extern int luaopen_event(lua_State* L);
+ extern int luaopen_time(lua_State* L);
+ extern int luaopen_mouse(lua_State* L);
+ extern int luaopen_keyboard(lua_State* L);
+ extern int luaopen_filesystem(lua_State* L);
+ extern int luaopen_joypad(lua_State* L);
+
+ static int l_getversion(lua_State* L)
+ {
+ luax_pushstring(L, VERSION);
+ return 1;
+ }
+
+ static int l_getAuthor(lua_State* L)
+ {
+ luax_pushstring(L, AUTHOR);
+ return 1;
+ }
+
+ static int l_getOS(lua_State* L)
+ {
+ #ifdef _WIN32
+ luax_pushstring(L, "windows");
+ #elif defined __unix__
+ luax_pushstring(L, "unix");
+ #elif defined __APPLE__
+ luax_pushstring(L, "macos");
+ #endif
+ return 1;
+ }
+
+ static const luaL_Reg f[] = {
+ {"version", l_getversion},
+ {"author", l_getAuthor},
+ {"os", l_getOS},
+ {0, 0}
+ };
+
+ // submodules
+ static const luaL_Reg mods[] = {
+ {"core", luaopen_core},
+ {"event", luaopen_event},
+ {"graphics", luaopen_graphics},
+ {"time", luaopen_time},
+ {"mouse", luaopen_mouse},
+ {"keyboard", luaopen_keyboard},
+ {"filesystem", luaopen_filesystem},
+ {"net", luaopen_net},
+ {"audio", luaopen_audio},
+ {"joypad", luaopen_joypad},
+ {0, 0}
+ };
+
+ int luaopen_jin(lua_State* L)
+ {
+ // jin module is on top of the stack
+ luax_newlib(L, f);
+
+ // set to global field
+ luax_justglobal(L, -1, MODULE_NAME);
+
+ // register submodules
+ for (int i = 0; mods[i].name; ++i)
+ {
+ // open submodules
+ mods[i].func(L);
+ luax_setfield(L, -2, mods[i].name);
+ }
+
+ return 1;
+ }
+
+ /**
+ * boot jin
+ */
+ void boot(lua_State* L)
+ {
+ jin::embed::boot(L);
+ }
+
+}
+} \ No newline at end of file
diff --git a/src/lua/luaopen_jin.h b/src/lua/luaopen_jin.h
new file mode 100644
index 0000000..3d446a5
--- /dev/null
+++ b/src/lua/luaopen_jin.h
@@ -0,0 +1,45 @@
+/**
+* Copyright (C) 2016~2018 chai
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copyof
+* this software and associated documentation files (the "Software"), to deal in
+* the Software without restriction, including without limitation the rights to use,
+* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
+* Software, and to permit persons to whom the Software is furnished to do so,
+* subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all
+* copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef __JIN_M_JIN_H
+#define __JIN_M_JIN_H
+#include "lua/luax.h"
+
+#define MODULE_NAME "jin"
+#define VERSION "0.1.0"
+#define AUTHOR "chai"
+
+namespace jin
+{
+namespace lua
+{
+
+ /**
+ * open jin lib and boot
+ */
+ int luaopen_jin(lua_State* L);
+
+ void boot(lua_State* L);
+
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/lua/luaopen_types.h b/src/lua/luaopen_types.h
new file mode 100644
index 0000000..bb6f5b1
--- /dev/null
+++ b/src/lua/luaopen_types.h
@@ -0,0 +1,24 @@
+#ifndef __JIN_M_TYPES_H
+#define __JIN_M_TYPES_H
+
+// graphics module
+#define TYPE_IMAGE "Image"
+#define TYPE_JSL "Shader"
+#define TYPE_CANVAS "Canvas"
+#define TYPE_FONT "Font"
+
+// audio module
+#define TYPE_SOURCE "Source"
+
+class Proxy
+{
+public:
+ inline void bind(void* obj)
+ {
+ object = obj;
+ }
+
+ void* object;
+};
+
+#endif
diff --git a/src/lua/luax.h b/src/lua/luax.h
new file mode 100644
index 0000000..3b587d3
--- /dev/null
+++ b/src/lua/luax.h
@@ -0,0 +1,10 @@
+#ifndef __JIN_LUA_LUAX_H
+#define __JIN_LUA_LUAX_H
+
+#include "3rdparty/lua51/lua.h"
+#include "3rdparty/lua51/lauxlib.h"
+#include "3rdparty/lua51/lualib.h"
+
+#include "3rdparty/luax/luax.h"
+
+#endif \ No newline at end of file
diff --git a/src/lua/mouse/luaopen_mouse.cpp b/src/lua/mouse/luaopen_mouse.cpp
new file mode 100644
index 0000000..a013f3d
--- /dev/null
+++ b/src/lua/mouse/luaopen_mouse.cpp
@@ -0,0 +1,27 @@
+#include "lua/luax.h"
+#include "SDL2/SDL.h"
+namespace jin
+{
+namespace lua
+{
+ static int l_pos(lua_State* L)
+ {
+ int x, y;
+ SDL_GetMouseState(&x, &y);
+ luax_pushnumber(L, x);
+ luax_pushnumber(L, y);
+ return 2;
+ }
+
+ static const luaL_Reg f[] = {
+ {"position", l_pos},
+ {0, 0}
+ };
+
+ int luaopen_mouse(lua_State* L)
+ {
+ luax_newlib(L, f);
+ return 1;
+ }
+}
+} \ No newline at end of file
diff --git a/src/lua/net/luaopen_net.cpp b/src/lua/net/luaopen_net.cpp
new file mode 100644
index 0000000..821f273
--- /dev/null
+++ b/src/lua/net/luaopen_net.cpp
@@ -0,0 +1,110 @@
+/**
+* Notice: the net module is not finished yet.
+*/
+#include "lua/luax.h"
+#include "3rdparty/tekcos/tekcos.h"
+
+namespace jin
+{
+namespace lua
+{
+ struct
+ {
+ tk_TCPsocket* sk;
+ }context;
+
+ /**
+ * A table is needed. For example:
+ * local conf = {
+ * mode = "server",
+ * ip = "",
+ * port = 8000
+ * }
+ */
+ static int l_open(lua_State* L)
+ {
+ // init context.sk
+ context.sk = 0;
+ if (!luax_istable(L, 1))
+ {
+ luax_typerror(L, 1, "table is needed");
+ return 0;
+ }
+ luax_getfield(L, 1, "mode");
+ if (luax_isnil(L, -1))
+ {// no mode field
+ luax_error(L, "mode field is needed, but get nil");
+ return 0;
+ }
+ const char* mode = luax_checkstring(L, -1);
+ if (strcmp(mode, "server") == 0 || strcmp(mode, "client") == 0)
+ {
+
+ if (strcmp(mode, "server") == 0)
+ {// a server, ignore ip field
+
+ }
+ else
+ {
+
+ }
+ }
+ else
+ {
+ luax_error(L, "\"server\" or \"client\" is needed, but get %s", mode);
+ return 0;
+ }
+ return 1;
+ }
+
+ static int l_accept(lua_State* L)
+ {
+ return 1;
+ }
+
+ static int l_send(lua_State* L)
+ {
+ return 1;
+ }
+
+ static int l_recv(lua_State* L)
+ {
+ return 1;
+ }
+
+ static int l_close(lua_State* L)
+ {
+ return 1;
+ }
+
+ static int l_nonblocking(lua_State* L)
+ {
+ return 1;
+ }
+
+ // block mode by default
+ static int l_blocking(lua_State* L)
+ {
+ return 1;
+ }
+
+ static const luaL_Reg f[] = {
+ {"open", l_open},
+ {"accept", l_accept},
+ {"send", l_send},
+ {"recv", l_recv},
+ {"close", l_close},
+ {"blocking", l_blocking },
+ {"nonblocking", l_nonblocking},
+ {0, 0}
+ };
+
+ // only tcp
+ int luaopen_net(lua_State* L)
+ {
+ luax_newlib(L, f);
+
+ return 1;
+ }
+}
+} \ No newline at end of file
diff --git a/src/lua/thread/luaopen_Thread.cpp b/src/lua/thread/luaopen_Thread.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/lua/thread/luaopen_Thread.cpp
diff --git a/src/lua/time/luaopen_time.cpp b/src/lua/time/luaopen_time.cpp
new file mode 100644
index 0000000..f7310dc
--- /dev/null
+++ b/src/lua/time/luaopen_time.cpp
@@ -0,0 +1,34 @@
+#include "lua/luax.h"
+#include <SDL2/SDL.h>
+namespace jin
+{
+namespace lua
+{
+
+ static int l_sec(lua_State* L)
+ {
+ luax_pushnumber(L, SDL_GetTicks()/1000.f);
+ return 1;
+ }
+
+ static int l_sleep(lua_State* L)
+ {
+ double sec = luax_checknumber(L, 1);
+ SDL_Delay(sec * 1000);
+ return 0;
+ }
+
+ static const luaL_Reg f[] = {
+ {"second", l_sec},
+ {"sleep", l_sleep},
+ {0, 0},
+ };
+
+ int luaopen_time(lua_State* L)
+ {
+ luax_newlib(L, f);
+ return 1;
+ }
+
+}
+} \ No newline at end of file