aboutsummaryrefslogtreecommitdiff
path: root/src/libjin-lua/modules/graphics/l_graphics.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libjin-lua/modules/graphics/l_graphics.cpp')
-rw-r--r--src/libjin-lua/modules/graphics/l_graphics.cpp1112
1 files changed, 1112 insertions, 0 deletions
diff --git a/src/libjin-lua/modules/graphics/l_graphics.cpp b/src/libjin-lua/modules/graphics/l_graphics.cpp
new file mode 100644
index 0000000..950554a
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/l_graphics.cpp
@@ -0,0 +1,1112 @@
+#include <iostream>
+#include <fstream>
+
+#include "libjin/jin.h"
+#include "common/l_object.h"
+#include "common/l_common.h"
+
+#include "l_canvas.h"
+#include "l_sprite.h"
+#include "l_spritesheet.h"
+#include "l_bitmap.h"
+#include "l_mesh.h"
+#include "l_ttf.h"
+#include "l_ttf_data.h"
+#include "l_texture.h"
+#include "l_shader.h"
+#include "l_text.h"
+#include "l_texture_font.h"
+#include "l_page.h"
+#include "l_sprite.h"
+#include "l_animation.h"
+#include "l_animator.h"
+#include "l_particle_system.h"
+
+using namespace std;
+using namespace JinEngine;
+using namespace JinEngine::Math;
+using namespace JinEngine::Graphics;
+using namespace JinEngine::Graphics::Fonts;
+using namespace JinEngine::Graphics::Shaders;
+using namespace JinEngine::Graphics::Animations;
+using namespace JinEngine::Graphics::Particles;
+using namespace JinEngine::Filesystem;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ #include "../../resources/font.ttf.h"
+
+ static struct
+ {
+ Color curRenderColor;
+ Color curClearColor;
+ Font* defaultFont = nullptr;
+ bool initialized = false;
+ } context;
+
+ LUA_IMPLEMENT int l_init(lua_State* L)
+ {
+ if (context.initialized)
+ {
+ luax_pushboolean(L, true);
+ return 1;
+ }
+
+ Window* wnd = Window::get();
+ Window::Setting setting;
+ setting.width = luax_getfieldinteger(L, 1, "width");
+ setting.height = luax_getfieldinteger(L, 1, "height");
+ setting.title = luax_getfieldstring(L, 1, "title");
+ setting.icon = luax_getfieldstring(L, 1, "icon");
+ setting.vsync = luax_getfieldbool(L, 1, "vsync");
+ setting.fullscreen = luax_getfieldbool(L, 1, "fullscreen");
+ setting.resizable = luax_getfieldbool(L, 1, "resizable");
+ context.initialized = wnd->start(&setting);
+ if (!context.initialized)
+ {
+ luax_pushboolean(L, context.initialized);
+ return 1;
+ }
+
+ /* load default font */
+ Bitmap* bitmap = new Bitmap(default_font_bitmap, sizeof(default_font_bitmap));
+ TextureFont* tf = new TextureFont(bitmap, Text(Encode::UTF8, default_charset), default_font_split, bitmap->getHeight());
+ delete bitmap;
+ context.defaultFont = tf;
+ gl.setFont(tf);
+
+ luax_pushboolean(L, context.initialized);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_setTitle(lua_State* L)
+ {
+ Window* wnd = Window::get();
+ const char* title = luax_checkstring(L, 1);
+ wnd->setTitle(title);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_destroy(lua_State* L)
+ {
+ Window* wnd = Window::get();
+ wnd->quit();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_showWindow(lua_State* L)
+ {
+ Window* wnd = Window::get();
+ wnd->show();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_hideWindow(lua_State* L)
+ {
+ Window* wnd = Window::get();
+ wnd->hide();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_getSize(lua_State* L)
+ {
+ Window* wnd = Window::get();
+ luax_pushnumber(L, wnd->getW());
+ luax_pushnumber(L, wnd->getH());
+ return 2;
+ }
+
+ LUA_IMPLEMENT int l_getWidth(lua_State* L)
+ {
+ Window* wnd = Window::get();
+ luax_pushnumber(L, wnd->getW());
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_getHeight(lua_State* L)
+ {
+ Window* wnd = Window::get();
+ luax_pushnumber(L, wnd->getH());
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_newBitmap(lua_State* L)
+ {
+ Bitmap* bitmap = nullptr;
+ if (luax_gettop(L) == 2)
+ {
+ int w = luax_checkinteger(L, 1);
+ int h = luax_checkinteger(L, 2);
+ bitmap = new Bitmap(w, h);
+ }
+ else if (luax_gettop(L) == 3)
+ {
+ int w = luax_checkinteger(L, 1);
+ int h = luax_checkinteger(L, 2);
+ if (luax_istable(L, 3))
+ {
+ unsigned int r = luax_rawgetnumber(L, 3, 1);
+ unsigned int g = luax_rawgetnumber(L, 3, 2);
+ unsigned int b = luax_rawgetnumber(L, 3, 3);
+ unsigned int a = luax_rawgetnumber(L, 3, 4);
+ bitmap = new Bitmap(w, h, Color(r, g, b, a));
+ }
+ else if (luax_isfunction(L, 3))
+ {
+ std::function<Color(int, int, int, int)> drawer = [=](int w, int h, int x, int y)->Color{
+ luax_pushvalue(L, 3);
+ luax_pushnumber(L, w);
+ luax_pushnumber(L, h);
+ luax_pushnumber(L, x);
+ luax_pushnumber(L, y);
+ // Call drawer function.
+ luax_call(L, 4, 1);
+ // Get result color.
+ if (!luax_istable(L, -1))
+ luax_error(L, "Return value of bitmap drawer is wrong, should be a color table.");
+ Color c;
+ c.r = luax_rawgetnumberthenpop(L, -1, 1);
+ c.g = luax_rawgetnumberthenpop(L, -1, 2);
+ c.b = luax_rawgetnumberthenpop(L, -1, 3);
+ c.a = luax_rawgetnumberthenpop(L, -1, 4);
+ // Pop return value.
+ luax_pop(L, 1);
+ return c;
+ };
+ bitmap = new Bitmap(w, h, drawer);
+ }
+ else
+ {
+ luax_typerror(L, 3, "color table or color setter");
+ return 1;
+ }
+ }
+ else
+ {
+ const char* f = luax_checkstring(L, 1);
+ AssetDatabase* fs = AssetDatabase::get();
+ Buffer b;
+ try
+ {
+ if (!fs->exists(f))
+ throw Exception("No such image file %s.", f);
+ fs->read(f, b);
+ }
+ catch (Exception& e)
+ {
+ luax_errorf(L, "Failed to read image %s", f);
+ luax_pushnil(L);
+ return 1;
+ }
+ bitmap = new Bitmap(&b, b.size());
+ if (bitmap == nullptr)
+ {
+ luax_errorf(L, "Failed to decode image file %s", f);
+ luax_pushnil(L);
+ return 1;
+ }
+ }
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_Bitmap, new Shared(bitmap));
+ return 1;
+ }
+
+ /* jin.graphics.newTexture(bitmap) */
+ LUA_IMPLEMENT int l_newTexture(lua_State* L)
+ {
+ Texture* texture = nullptr;
+ if (luax_istype(L, 1, Jin_Lua_Bitmap))
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Bitmap);
+ Bitmap* bitmap = luaObj->getObject<Bitmap>();
+ texture = new Texture(bitmap);
+ }
+ else if (luax_isstring(L, 1))
+ {
+ const char* path = luax_checkstring(L, 1);
+ texture = new Texture(path);
+ }
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_Texture, new Shared(texture));
+ return 1;
+ }
+
+ // See embed graphics.lua.
+ LUA_IMPLEMENT int l_newShader(lua_State* L)
+ {
+ const char* program = luax_checkstring(L, 1);
+ Shader* jsl = nullptr;
+ try
+ {
+ jsl = new Shader(program);
+ }
+ catch (JinEngine::Exception& e)
+ {
+ //luax_errorf(L, "Failed to compile shader");
+ luax_pushnil(L);
+ return 1;
+ }
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_Shader, new Shared(jsl));
+ return 1;
+ }
+
+ // See embed graphics.lua
+ LUA_IMPLEMENT int l_newShaderf(lua_State* L)
+ {
+ const char* path = luax_checkstring(L, 1);
+ AssetDatabase* fs = AssetDatabase::get();
+ if (!fs->exists(path))
+ {
+ //luax_errorf(L, "No such shader file \"%s\"", path);
+ luax_pushnil(L);
+ return 1;
+ }
+ Buffer b;
+ fs->read(path, b);
+ Shader* jsl = nullptr;
+ try
+ {
+ jsl = new Shader((char*)&b);
+ }
+ catch (JinEngine::Exception& e)
+ {
+ //luax_errorf(L, "Failed to compile shader");
+ luax_pushnil(L);
+ return 1;
+ }
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_Shader, new Shared(jsl));
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_newCanvas(lua_State* L)
+ {
+ int w = luax_checknumber(L, 1);
+ int h = luax_checknumber(L, 2);
+ Canvas* cvs = new Canvas(w, h);
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_Canvas, new Shared(cvs));
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_clear(lua_State* L)
+ {
+ glClear(GL_COLOR_BUFFER_BIT);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setClearColor(lua_State* L)
+ {
+ if (luax_gettop(L) == 0)
+ {
+ glClearColor(0, 0, 0, 1);
+ return 0;
+ }
+
+ context.curClearColor.r = luax_checknumber(L, 1);
+ context.curClearColor.g = luax_checknumber(L, 2);
+ context.curClearColor.b = luax_checknumber(L, 3);
+ context.curClearColor.a = luax_checknumber(L, 4);
+
+ gl.setClearColor(context.curClearColor.r,
+ context.curClearColor.g,
+ context.curClearColor.b,
+ context.curClearColor.a);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_present(lua_State* L)
+ {
+ Window::get()->present();
+ return 0;
+ }
+
+ LUA_IMPLEMENT void l_draw_texture(lua_State* L)
+ {
+ if (!luax_istype(L, 1, Jin_Lua_Texture))
+ return;
+ 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);
+ float ox = luax_optnumber(L, 7, 0);
+ float oy = luax_optnumber(L, 8, 0);
+ LuaObject* luaObj = (LuaObject*)luax_toudata(L, 1);
+ Texture* tex = luaObj->getObject<Texture>();
+ tex->render(x, y, sx, sy, r, ox, oy);
+ }
+
+ LUA_IMPLEMENT void l_draw_canvas(lua_State* L)
+ {
+ if (!luax_istype(L, 1, Jin_Lua_Canvas))
+ return;
+ 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);
+ float ox = luax_optnumber(L, 7, 0);
+ float oy = luax_optnumber(L, 8, 0);
+ LuaObject* luaObj = (LuaObject*)luax_toudata(L, 1);
+ Canvas* canvas = luaObj->getObject<Canvas>();
+ canvas->render(x, y, sx, sy, r, ox, oy);
+ }
+
+ /* jin.graphics.draw(text, font, x, y) */
+ LUA_IMPLEMENT void l_draw_text(lua_State* L)
+ {
+ if (!luax_istype(L, 1, Jin_Lua_Text))
+ return;
+ LuaObject* p = (LuaObject*)luax_toudata(L, 1);
+ Text* text = p->getObject<Text>();
+ int x = luax_optnumber(L, 3, 0);
+ int y = luax_optnumber(L, 4, 0);
+ int spacing = luax_optnumber(L, 6, 0);
+ Font* font = nullptr;
+ LuaObject* p2 = (LuaObject*)luax_toudata(L, 2);
+ if (luax_istype(L, 2, Jin_Lua_TextureFont))
+ {
+ TextureFont* tf = p2->getObject<TextureFont>();
+ font = tf;
+ }
+ else if (luax_istype(L, 2, Jin_Lua_TTF))
+ {
+ TTF* ttf = p2->getObject<TTF>();
+ font = ttf;
+ }
+ else
+ {
+ font = context.defaultFont;
+ }
+ int lineheight = luax_optnumber(L, 5, font->getFontSize());
+ font->render(*text, x, y, lineheight, spacing);
+ }
+
+ /* jin.graphics.draw(page, x, y) */
+ LUA_IMPLEMENT void l_draw_page(lua_State* L)
+ {
+ if (!luax_istype(L, 1, Jin_Lua_Page))
+ return;
+ int x = luax_optnumber(L, 2, 0);
+ int y = luax_optnumber(L, 3, 0);
+ LuaObject* p = (LuaObject*)luax_toudata(L, 1);
+ Page* page = p->getObject<Page>();
+ Font* font = page->font;
+ font->render(page, x, y);
+ }
+
+ LUA_IMPLEMENT void l_draw_sprite(lua_State* L)
+ {
+ if (!luax_istype(L, 1, Jin_Lua_Sprite))
+ return;
+ LuaObject* luaSprite = (LuaObject*)luax_toudata(L, 1);
+ Sprite* sprite = luaSprite->getObject<Sprite>();
+ float x = luax_checknumber(L, 2);
+ float y = luax_checknumber(L, 3);
+ float sx = luax_checknumber(L, 4);
+ float sy = luax_checknumber(L, 5);
+ float r = luax_checknumber(L, 6);
+ sprite->render(x, y, sx, sy, r);
+ }
+
+ LUA_IMPLEMENT void l_draw_mesh(lua_State* L)
+ {
+ if (!luax_istype(L, 1, Jin_Lua_Mesh))
+ return;
+ LuaObject* obj= (LuaObject*)luax_toudata(L, 1);
+ Mesh* mesh = obj->getObject<Mesh>();
+ 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);
+ float ox = luax_optnumber(L, 7, 0);
+ float oy = luax_optnumber(L, 8, 0);
+ mesh->render(x, y, sx, sy, r, ox, oy);
+ }
+
+ LUA_IMPLEMENT int l_draw(lua_State* L)
+ {
+ if (luax_istype(L, 1, Jin_Lua_Texture))
+ l_draw_texture(L);
+ else if (luax_istype(L, 1, Jin_Lua_Canvas))
+ l_draw_canvas(L);
+ else if (luax_istype(L, 1, Jin_Lua_Text))
+ l_draw_text(L);
+ else if (luax_istype(L, 1, Jin_Lua_Page))
+ l_draw_page(L);
+ else if (luax_istype(L, 1, Jin_Lua_Sprite))
+ l_draw_sprite(L);
+ else if (luax_istype(L, 1, Jin_Lua_Mesh))
+ l_draw_mesh(L);
+ else
+ {
+ luax_typerror(L, 1, "texture or canvas");
+ return 1;
+ }
+ return 0;
+ }
+
+ // draw(tex, quad, x, y, sx, sy, r, ax, ay)
+ LUA_IMPLEMENT int l_drawq(lua_State* L)
+ {
+ if (!luax_istable(L, 2))
+ {
+ luax_typerror(L, 2, "table");
+ return 1;
+ }
+ Math::Quad q;
+ q.x = luax_rawgetnumber(L, 2, 1);
+ q.y = luax_rawgetnumber(L, 2, 2);
+ q.w = luax_rawgetnumber(L, 2, 3);
+ q.h = luax_rawgetnumber(L, 2, 4);
+ luax_pop(L, 4);
+ int x = luax_optnumber(L, 3, 0);
+ int y = luax_optnumber(L, 4, 0);
+ float sx = luax_optnumber(L, 5, 1);
+ float sy = luax_optnumber(L, 6, 1);
+ float r = luax_optnumber(L, 7, 0);
+ float ox = luax_optnumber(L, 8, 0);
+ float oy = luax_optnumber(L, 9, 0);
+
+ if (luax_istype(L, 1, Jin_Lua_Texture))
+ {
+ LuaObject* luaObj = (LuaObject*)luax_toudata(L, 1);
+ Texture* tex = luaObj->getObject<Texture>();
+ tex->render(q, x, y, sx, sy, r, ox, oy);
+ }
+ else if (luax_istype(L, 1, Jin_Lua_Canvas))
+ {
+ LuaObject* luaObj = (LuaObject*)luax_toudata(L, 1);
+ Canvas* canvas = luaObj->getObject<Canvas>();
+ canvas->render(q, x, y, sx, sy, r, ox, oy);
+ }
+ else
+ {
+ luax_typerror(L, 1, "texture or canvas");
+ return 1;
+ }
+ return 0;
+ }
+
+ /* print(string, x, y, lineheight, spacing) */
+ /* need set font */
+ LUA_IMPLEMENT int l_print(lua_State* L)
+ {
+ Font* font = gl.getFont();
+ if (font == nullptr)
+ return 0;
+ unsigned length;
+ const char* str = luax_checklstring(L, 1, &length);
+ Text text(Encode::UTF8, str, length);
+ int x = luax_optnumber(L, 2, 0);
+ int y = luax_optnumber(L, 3, 0);
+ int lineheight = luax_optnumber(L, 4, font->getFontSize());
+ int spacing = luax_optnumber(L, 5, 0);
+ font->render(text, x, y, lineheight, spacing);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setColor(lua_State* L)
+ {
+ if (luax_gettop(L) == 0)
+ {
+ gl.setColor(Color(255, 255, 255, 255));
+ return 0;
+ }
+
+ context.curRenderColor.r = luax_checknumber(L, 1);
+ context.curRenderColor.g = luax_checknumber(L, 2);
+ context.curRenderColor.b = luax_checknumber(L, 3);
+ if (luax_gettop(L) == 4)
+ context.curRenderColor.a = luax_checknumber(L, 4);
+ else
+ context.curRenderColor.a = 255;
+ gl.setColor(context.curRenderColor);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_getColor(lua_State * L)
+ {
+ luax_pushnumber(L, context.curRenderColor.r);
+ luax_pushnumber(L, context.curRenderColor.g);
+ luax_pushnumber(L, context.curRenderColor.b);
+ luax_pushnumber(L, context.curRenderColor.a);
+ return 4;
+ }
+
+ LUA_IMPLEMENT int l_bindCanvas(lua_State* L)
+ {
+ if (luax_gettop(L) == 0)
+ {
+ // bind to default canvas
+ gl.unbindCanvas();
+ return 0;
+ }
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Canvas);
+ Canvas* canvas = luaObj->getObject<Canvas>();
+ gl.bindCanvas(canvas);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_unbindCanvas(lua_State* L)
+ {
+ gl.unbindCanvas();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_useShader(lua_State* L)
+ {
+ if (luax_gettop(L) == 0)
+ {
+ gl.unuseShader();
+ return 0;
+ }
+ if (luax_istype(L, 1, Jin_Lua_Shader))
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Shader);
+ Shader* shader = luaObj->getObject<Shader>();
+ gl.useShader(shader);
+ }
+ else
+ {
+ luax_typerror(L, 1, "JSL shader");
+ }
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setBlendMode(lua_State* L)
+ {
+ int mode = luax_checkinteger(L, 1);
+ gl.setBlendMode(static_cast<OpenGL::BlendMode>(mode));
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_getBlendMode(lua_State* L)
+ {
+ int mode = static_cast<int>(gl.getBlendMode());
+ luax_pushinteger(L, mode);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_point(lua_State* L)
+ {
+ int x = luax_checknumber(L, 1);
+ int y = luax_checknumber(L, 2);
+ JinEngine::Graphics::point(x, y);
+
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_line(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);
+ JinEngine::Graphics::line(x1, y1, x2, y2);
+
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_rect(lua_State* L)
+ {
+ RenderMode mode = static_cast<RenderMode>(luax_checkinteger(L, 1));
+ if (mode != RenderMode::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);
+ rect(mode, x, y, w, h);
+ }
+ else
+ {
+ luax_typerror(L, 1, "'fill' or 'line'");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_circle(lua_State* L)
+ {
+ RenderMode mode = static_cast<RenderMode>(luax_checkinteger(L, 1));
+ if (mode != RenderMode::NONE)
+ {
+ int x = luax_checknumber(L, 2);
+ int y = luax_checknumber(L, 3);
+ float r = luax_checknumber(L, 4);
+ circle(mode, x, y, r);
+ }
+ else
+ {
+ luax_typerror(L, 1, "'fill' or 'line'");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_triangle(lua_State* L)
+ {
+ RenderMode mode = static_cast<RenderMode>(luax_checkinteger(L, 1));
+ if (mode != RenderMode::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);
+
+ triangle(mode, x, y, x2, y2, x3, y3);
+ }
+ else
+ {
+ luax_typerror(L, 1, "'fill' or 'line'");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_polygon(lua_State* L)
+ {
+ RenderMode mode = static_cast<RenderMode>(luax_checkinteger(L, 1));
+ int n = luax_checknumber(L, 2);
+ if (mode != RenderMode::NONE)
+ {
+ if (!luax_istable(L, 3))
+ {
+ luax_typerror(L, 3, "table");
+ return 1;
+ }
+ int tn = luax_tableidxlen(L, 3);
+ if (tn != n * 2)
+ {
+ LUA_IMPLEMENT 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 = (float*)alloca(2 * n * sizeof(float));
+ for (int i = 1; i <= 2 * n; ++i)
+ p[i - 1] = luax_rawgetnumber(L, 3, i);
+ polygon(mode, p, n);
+ }
+ else
+ {
+ luax_typerror(L, 1, "'fill' or 'line'");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_newTTFData(lua_State* L)
+ {
+ TTFData* fd = nullptr;
+ {
+ const char* path = luax_checkstring(L, 1);
+ AssetDatabase* fs = AssetDatabase::get();
+ if (!fs->exists(path))
+ {
+ luax_errorf(L, "No such font \"%s\"", path);
+ luax_pushnil(L);
+ return 1;
+ }
+ Buffer b;
+ fs->read(path, b);
+ fd = new TTFData(&b, b.size());
+ }
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_TTFData, new Shared(fd));
+ return 1;
+ }
+
+ /* newText(str[, encode]) */
+ LUA_IMPLEMENT int l_newText(lua_State* L)
+ {
+ Encode encode = Encode::UTF8;
+ if (luax_gettop(L) == 2)
+ {
+ const char* e = luax_checkstring(L, 2);
+ if (strcmp(e, "UTF8") == 0) encode = Encode::UTF8;
+ //else if (strcmp(e, "UTF16") == 0) encode = Encode::UTF16;
+ else if (strcmp(e, "ASCII") == 0) encode = Encode::ASCII;
+ else
+ {
+ luax_error(L, "wrong text encode %s", e);
+ return 0;
+ }
+ }
+ unsigned length;
+ const char* data = luax_checklstring(L, 1, &length);
+ Text* text = new Text(encode, data, length);
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_Text, new Shared(text));
+ return 1;
+ }
+
+ // newSprite(Texture tex, Quad quad, Origin origin)
+ // newSprite(Texture tex, Quad quad, Number ox, Number oy)
+ // newSprite(Texture tex, Origin origin)
+ // newSprite(Texture tex, Number ox, Number oy)
+ LUA_IMPLEMENT int l_newSprite(lua_State* L)
+ {
+ int n = luax_gettop(L);
+ LuaObject* objGraphic = nullptr;
+ if (luax_istype(L, 1, Jin_Lua_Texture))
+ objGraphic = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Texture);
+ else if (luax_istype(L, 1, Jin_Lua_Canvas))
+ objGraphic = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Canvas);
+ Graphic* graphic = objGraphic->getObject<Graphic>();
+ if (objGraphic != nullptr)
+ {
+ if (n == 3 && luax_istable(L, 2))
+ {
+ Quad quad;
+ quad.x = luax_rawgetnumberthenpop(L, 2, 1);
+ quad.y = luax_rawgetnumberthenpop(L, 2, 2);
+ quad.w = luax_rawgetnumberthenpop(L, 2, 3);
+ quad.h = luax_rawgetnumberthenpop(L, 2, 4);
+ int o = luax_checkinteger(L, 3);
+ Origin origin = static_cast<Origin>(o);
+ LuaObject* p = luax_newinstance(L, Jin_Lua_Sprite, new Shared(new Sprite(graphic, quad, origin)));
+ p->setDependency((int)SpriteDependency::DEP_GRAPHIC, objGraphic);
+ }
+ else if (n == 4)
+ {
+ Quad quad;
+ quad.x = luax_rawgetnumberthenpop(L, 2, 1);
+ quad.y = luax_rawgetnumberthenpop(L, 2, 2);
+ quad.w = luax_rawgetnumberthenpop(L, 2, 3);
+ quad.h = luax_rawgetnumberthenpop(L, 2, 4);
+ int ox = luax_checkinteger(L, 3);
+ int oy = luax_checkinteger(L, 4);
+ LuaObject* p = luax_newinstance(L, Jin_Lua_Sprite, new Shared(new Sprite(graphic, quad, ox, oy)));
+ p->setDependency((int)SpriteDependency::DEP_GRAPHIC, objGraphic);
+ }
+ else if (n == 2)
+ {
+ int o = luax_checkinteger(L, 2);
+ Origin origin = static_cast<Origin>(o);
+ LuaObject* p = luax_newinstance(L, Jin_Lua_Sprite, new Shared(new Sprite(graphic, origin)));
+ p->setDependency((int)SpriteDependency::DEP_GRAPHIC, objGraphic);
+ }
+ else if (n == 3)
+ {
+ int ox = luax_checkinteger(L, 2);
+ int oy = luax_checkinteger(L, 3);
+ LuaObject* p = luax_newinstance(L, Jin_Lua_Sprite, new Shared(new Sprite(graphic, ox, oy)));
+ p->setDependency((int)SpriteDependency::DEP_GRAPHIC, objGraphic);
+ }
+ else
+ {
+ luax_error(L, "No matched overloaded functions.");
+ return 1;
+ }
+ }
+
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_newSpriteSheet(lua_State* L)
+ {
+ LuaObject* objGraphic = nullptr;
+ if (luax_istype(L, 1, Jin_Lua_Texture))
+ objGraphic = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Texture);
+ else if(luax_istype(L, 1, Jin_Lua_Canvas))
+ objGraphic = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Canvas);
+ if (objGraphic != nullptr)
+ {
+ Graphic* graphic = objGraphic->getObject<Graphic>();
+ Shared* shrSSheet = new Shared(new SpriteSheet(graphic));
+ LuaObject* luaSSheet = luax_newinstance(L, Jin_Lua_SpriteSheet, shrSSheet);
+ luaSSheet->setDependency((int)SpriteSheetDependency::DEP_GRAPHIC, objGraphic);
+ return 1;
+ }
+ else
+ return 0;
+ }
+
+ // newAnimation([frames table, loop, speed])
+ LUA_IMPLEMENT int l_newAnimation(lua_State* L)
+ {
+ int argc = luax_gettop(L);
+ Animation* animation = new Animation();
+ Shared* shrAnimation = new Shared(animation);
+ LuaObject* luaAnimation = luax_newinstance(L, Jin_Lua_Animation, shrAnimation);
+ if (argc >= 3)
+ {
+ if (!luax_istable(L, 1))
+ {
+ luax_typerror(L, 1, "frames table");
+ return 1;
+ }
+ bool loop = luax_checkbool(L, 2);
+ float speed = luax_checknumber(L, 3);
+ int n = luax_tableidxlen(L, 1);
+ for (int i = 1; i <= n; ++i)
+ {
+ luax_rawgeti(L, 1, i);
+ LuaObject* luaSprite = (LuaObject*)luax_checktype(L, -1, Jin_Lua_Sprite);
+ animation->addFrame(luaSprite->getObject<Sprite>());
+ int index = animation->getFrameCount() - 1;
+ luaAnimation->setDependency((int)AnimationDependency::DEP_SPRITES + index, luaSprite);
+ }
+ animation->setLoop(loop);
+ animation->setSpeed(speed);
+ }
+ luax_pushvalue(L, argc + 1);
+ return 1;
+ }
+
+ // newAnimator([animation])
+ LUA_IMPLEMENT int l_newAnimator(lua_State* L)
+ {
+ int argc = luax_gettop(L);
+ Animator* animator = new Animator();
+ Shared* shrAniamtor = new Shared(animator);
+ if (argc >= 1)
+ {
+ LuaObject* animation = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Animation);
+ animator->setAnimation(animation->getObject<Animation>());
+ LuaObject* luaAnimator = luax_newinstance(L, Jin_Lua_Animator, shrAniamtor);
+ luaAnimator->setDependency((int)AnimatorDependency::DEP_ANIMATION, animation);
+ return 1;
+ }
+ LuaObject* luaAnimator = luax_newinstance(L, Jin_Lua_Animator, shrAniamtor);
+ return 1;
+ }
+
+ /* newTextureFont(bitmap, text, color | cellw, cellh) */
+ LUA_IMPLEMENT int l_newTextureFont(lua_State* L)
+ {
+ LuaObject* p = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Bitmap);
+ Bitmap* bitmap = p->getObject<Bitmap>();
+ Text* text;
+ if (luax_istype(L, 2, Jin_Lua_Text))
+ {
+ LuaObject* pt = (LuaObject*)luax_checktype(L, 2, Jin_Lua_Text);
+ text = pt->getObject<Text>();
+ }
+ else if (luax_isstring(L, 2))
+ {
+ unsigned len;
+ const char* str = luax_checklstring(L, 2, &len);
+ text = new Text(Encode::UTF8, str, len);
+ }
+ else
+ {
+ luax_typerror(L, 2, "Text or string");
+ return 1;
+ }
+ float cellh = luax_checknumber(L, 4);
+ TextureFont* textureFont = nullptr;
+ if (luax_istable(L, 3))
+ {
+ unsigned int r = luax_rawgetnumber(L, 3, 1);
+ unsigned int g = luax_rawgetnumber(L, 3, 2);
+ unsigned int b = luax_rawgetnumber(L, 3, 3);
+ unsigned int a = luax_rawgetnumber(L, 3, 4);
+ textureFont = new TextureFont(bitmap, *text, Color(r, g, b, a), cellh);
+ }
+ else if (luax_isnumber(L, 3))
+ {
+ float cellw = luax_checknumber(L, 3);
+ textureFont = new TextureFont(bitmap, *text, cellw, cellh);
+ }
+ else
+ {
+ luax_error(L, "bad arguments #3 to 'newTextureFont', need to be table or number");
+ return 0;
+ }
+ if (luax_isstring(L, 2))
+ {
+ // Delete temporary text.
+ delete text;
+ }
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_TextureFont, new Shared(textureFont));
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_newParticleSystem(lua_State* L)
+ {
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_ParticleSystem, new Shared(new ParticleSystem()));
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_newMesh(lua_State* L)
+ {
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_Mesh, new Shared(new Mesh()));
+ return 1;
+ }
+
+ /* setFont(font) */
+ LUA_IMPLEMENT int l_setFont(lua_State* L)
+ {
+ if (luax_istype(L, 1, Jin_Lua_TTF))
+ {
+ LuaObject* p = (LuaObject*)luax_checktype(L, 1, Jin_Lua_TTF);
+ TTF* ttf = p->getObject<TTF>();
+ gl.setFont(ttf);
+ }
+ else if (luax_istype(L, 1, Jin_Lua_TextureFont))
+ {
+ LuaObject* p = (LuaObject*)luax_checktype(L, 1, Jin_Lua_TextureFont);
+ TextureFont* tf = p->getObject<TextureFont>();
+ gl.setFont(tf);
+ }
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_unsetFont(lua_State* L)
+ {
+ gl.setFont(context.defaultFont);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_clearMatrix(lua_State* L)
+ {
+ gl.clearMatrix();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_pushMatrix(lua_State* L)
+ {
+ gl.pushMatrix();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_popMatrix(lua_State* L)
+ {
+ gl.popMatrix();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_scale(lua_State* L)
+ {
+ float sx = luax_checknumber(L, 1);
+ float sy = luax_checknumber(L, 2);
+ gl.scale(sx, sy);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_translate(lua_State* L)
+ {
+ float x = luax_checknumber(L, 1);
+ float y = luax_checknumber(L, 2);
+ gl.translate(x, y);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_rotate(lua_State* L)
+ {
+ float r = luax_checknumber(L, 1);
+ gl.rotate(r);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_getStats(lua_State* L)
+ {
+ OpenGL::Stats stats = gl.getStats();
+ luax_newtable(L);
+ luax_setfieldinteger(L, "drawCalls", stats.drawCalls);
+ luax_setfieldinteger(L, "canvasSwitches", stats.canvasSwitches);
+ luax_setfieldinteger(L, "shaderSwitches", stats.shaderSwitches);
+ luax_setfieldinteger(L, "fontSwitches", stats.fontSwitches);
+ luax_setfieldinteger(L, "textures", stats.textures);
+ luax_setfieldinteger(L, "canvases", stats.canvases);
+ luax_setfieldinteger(L, "fonts", stats.fonts);
+ return 1;
+ }
+
+ LUA_EXPORT int luaopen_graphics(lua_State* L)
+ {
+ luaopen_Bitmap(L);
+ luaopen_Texture(L);
+ luaopen_Canvas(L);
+ luaopen_TTFData(L);
+ luaopen_TTF(L);
+ luaopen_Text(L);
+ luaopen_TextureFont(L);
+ luaopen_Page(L);
+ luaopen_Shader(L);
+ luaopen_Sprite(L);
+ luaopen_SpriteSheet(L);
+ luaopen_Animation(L);
+ luaopen_Animator(L);
+ luaopen_ParticleSystem(L);
+ luaopen_Mesh(L);
+
+ luaL_Reg methods[] = {
+ { "getStats", l_getStats },
+ /* window */
+ { "init", l_init },
+ { "setTitle", l_setTitle },
+ { "getSize", l_getSize },
+ { "getWidth", l_getWidth },
+ { "getHeight", l_getHeight },
+ { "destroy", l_destroy },
+ { "hideWindow", l_hideWindow },
+ { "showWindow", l_showWindow },
+ /* creators */
+ { "newBitmap", l_newBitmap },
+ { "newTexture", l_newTexture },
+ { "newShader", l_newShader },
+ { "newShaderf", l_newShaderf },
+ { "newCanvas", l_newCanvas },
+ { "newTTFData", l_newTTFData },
+ { "newText", l_newText },
+ { "newTextureFont", l_newTextureFont },
+ { "newSprite", l_newSprite },
+ { "newSpriteSheet", l_newSpriteSheet },
+ { "newAnimation", l_newAnimation },
+ { "newAnimator", l_newAnimator },
+ { "newParticleSystem", l_newParticleSystem },
+ { "newMesh", l_newMesh },
+ /* render */
+ { "setClearColor", l_setClearColor },
+ { "clear", l_clear },
+ { "draw", l_draw },
+ { "print", l_print },
+ { "drawq", l_drawq },
+ { "setColor", l_setColor },
+ { "getColor", l_getColor },
+ { "present", l_present },
+ { "setBlendMode", l_setBlendMode },
+ { "getBlendMode", l_getBlendMode },
+ /* canvas */
+ { "bindCanvas", l_bindCanvas },
+ { "unbindCanvas", l_unbindCanvas },
+ /* shader */
+ { "useShader", l_useShader },
+ /* shapes */
+ { "point", l_point },
+ { "line", l_line },
+ { "rect", l_rect },
+ { "circle", l_circle },
+ { "triangle", l_triangle },
+ { "polygon", l_polygon },
+ /* font */
+ { "setFont", l_setFont },
+ { "unsetFont", l_unsetFont },
+ /* transform */
+ { "pushMatrix", l_pushMatrix },
+ { "clearMatrix", l_clearMatrix },
+ { "popMatrix", l_popMatrix },
+ { "translate", l_translate },
+ { "rotate", l_rotate },
+ { "scale", l_scale },
+ { 0, 0 }
+ };
+ // Load whole lib.
+ luax_newlib(L, methods);
+ return 1;
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file