aboutsummaryrefslogtreecommitdiff
path: root/src/libjin-lua
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2018-12-20 18:34:50 +0800
committerchai <chaifix@163.com>2018-12-20 18:34:50 +0800
commitee8ef0433e36bf354a717bd4af679a0a5af2e6be (patch)
tree2fc748510200f8bc24928d1938300eecc0604deb /src/libjin-lua
parent7ae40127f15f8f2cb963a7efeb018f7887ebc1ea (diff)
*修改文件结构
Diffstat (limited to 'src/libjin-lua')
-rw-r--r--src/libjin-lua/common/je_lua.h83
-rw-r--r--src/libjin-lua/common/je_lua_callback.cpp43
-rw-r--r--src/libjin-lua/common/je_lua_callback.h66
-rw-r--r--src/libjin-lua/common/je_lua_common.h9
-rw-r--r--src/libjin-lua/common/je_lua_constant.h14
-rw-r--r--src/libjin-lua/common/je_lua_error.h30
-rw-r--r--src/libjin-lua/common/je_lua_function.cpp0
-rw-r--r--src/libjin-lua/common/je_lua_function.h6
-rw-r--r--src/libjin-lua/common/je_lua_object.cpp112
-rw-r--r--src/libjin-lua/common/je_lua_object.h69
-rw-r--r--src/libjin-lua/common/je_lua_port.h8
-rw-r--r--src/libjin-lua/common/je_lua_reference.cpp42
-rw-r--r--src/libjin-lua/common/je_lua_reference.h54
-rw-r--r--src/libjin-lua/common/je_lua_runtime.cpp215
-rw-r--r--src/libjin-lua/common/je_lua_shared.cpp11
-rw-r--r--src/libjin-lua/common/je_lua_shared.hpp84
-rw-r--r--src/libjin-lua/embed/embed.h47
-rw-r--r--src/libjin-lua/embed/scripts/ai.lua26
-rw-r--r--src/libjin-lua/embed/scripts/ai.lua.h26
-rw-r--r--src/libjin-lua/embed/scripts/boot.lua139
-rw-r--r--src/libjin-lua/embed/scripts/boot.lua.h139
-rw-r--r--src/libjin-lua/embed/scripts/graphics.lua139
-rw-r--r--src/libjin-lua/embed/scripts/graphics.lua.h139
-rw-r--r--src/libjin-lua/embed/scripts/keyboard.lua17
-rw-r--r--src/libjin-lua/embed/scripts/keyboard.lua.h17
-rw-r--r--src/libjin-lua/embed/scripts/mouse.lua16
-rw-r--r--src/libjin-lua/embed/scripts/mouse.lua.h16
-rw-r--r--src/libjin-lua/embed/scripts/net.lua7
-rw-r--r--src/libjin-lua/embed/scripts/net.lua.h7
-rw-r--r--src/libjin-lua/embed/scripts/path.lua16
-rw-r--r--src/libjin-lua/embed/scripts/path.lua.h16
-rw-r--r--src/libjin-lua/je_lua_jin.cpp101
-rw-r--r--src/libjin-lua/je_lua_jin.h36
-rw-r--r--src/libjin-lua/modules/ai/je_lua_ai.cpp13
-rw-r--r--src/libjin-lua/modules/ai/je_lua_ai.h17
-rw-r--r--src/libjin-lua/modules/ai/je_lua_behavior_tree.cpp11
-rw-r--r--src/libjin-lua/modules/ai/je_lua_behavior_tree.h14
-rw-r--r--src/libjin-lua/modules/ai/je_lua_state_machine.cpp25
-rw-r--r--src/libjin-lua/modules/ai/je_lua_state_machine.h14
-rw-r--r--src/libjin-lua/modules/audio/je_lua_audio.cpp132
-rw-r--r--src/libjin-lua/modules/audio/je_lua_audio.h16
-rw-r--r--src/libjin-lua/modules/audio/je_lua_source.cpp114
-rw-r--r--src/libjin-lua/modules/audio/je_lua_source.h16
-rw-r--r--src/libjin-lua/modules/bit/je_lua_bit.cpp86
-rw-r--r--src/libjin-lua/modules/bit/je_lua_bit.h14
-rw-r--r--src/libjin-lua/modules/core/je_lua_core.cpp46
-rw-r--r--src/libjin-lua/modules/core/je_lua_core.h14
-rw-r--r--src/libjin-lua/modules/event/je_lua_event.cpp130
-rw-r--r--src/libjin-lua/modules/event/je_lua_event.h14
-rw-r--r--src/libjin-lua/modules/filesystem/je_lua_filesystem.cpp140
-rw-r--r--src/libjin-lua/modules/filesystem/je_lua_filesystem.h14
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_animation.cpp122
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_animation.h24
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_animator.cpp163
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_animator.h23
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_bitmap.cpp110
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_bitmap.h16
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_canvas.cpp63
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_canvas.h16
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_graphics.cpp1048
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_graphics.h14
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_page.cpp66
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_page.h22
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_particle_system.cpp422
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_particle_system.h21
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_shader.cpp132
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_shader.h16
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_sprite.cpp66
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_sprite.h24
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_spritesheet.cpp118
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_spritesheet.h21
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_text.cpp31
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_text.h16
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_texture.cpp63
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_texture.h16
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_texture_font.cpp63
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_texture_font.h16
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_ttf.cpp63
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_ttf.h16
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_ttf_data.cpp49
-rw-r--r--src/libjin-lua/modules/graphics/je_lua_ttf_data.h21
-rw-r--r--src/libjin-lua/modules/je_lua_modules.h19
-rw-r--r--src/libjin-lua/modules/joypad/je_lua_joypad.cpp21
-rw-r--r--src/libjin-lua/modules/joypad/je_lua_joypad.h14
-rw-r--r--src/libjin-lua/modules/keyboard/je_lua_keyboard.cpp17
-rw-r--r--src/libjin-lua/modules/keyboard/je_lua_keyboard.h14
-rw-r--r--src/libjin-lua/modules/math/je_lua_math.cpp30
-rw-r--r--src/libjin-lua/modules/math/je_lua_math.h14
-rw-r--r--src/libjin-lua/modules/mouse/je_lua_mouse.cpp42
-rw-r--r--src/libjin-lua/modules/mouse/je_lua_mouse.h14
-rw-r--r--src/libjin-lua/modules/net/je_lua_buffer.cpp136
-rw-r--r--src/libjin-lua/modules/net/je_lua_buffer.h102
-rw-r--r--src/libjin-lua/modules/net/je_lua_net.cpp79
-rw-r--r--src/libjin-lua/modules/net/je_lua_net.h14
-rw-r--r--src/libjin-lua/modules/net/je_lua_socket.cpp123
-rw-r--r--src/libjin-lua/modules/net/je_lua_socket.h16
-rw-r--r--src/libjin-lua/modules/thread/je_lua_thread.cpp240
-rw-r--r--src/libjin-lua/modules/thread/je_lua_thread.h95
-rw-r--r--src/libjin-lua/modules/time/je_lua_time.cpp70
-rw-r--r--src/libjin-lua/modules/time/je_lua_time.h14
-rw-r--r--src/libjin-lua/modules/time/je_lua_timer.cpp132
-rw-r--r--src/libjin-lua/modules/time/je_lua_timer.h20
-rw-r--r--src/libjin-lua/resources/embed.py56
-rw-r--r--src/libjin-lua/resources/font.ttf.h369
104 files changed, 7092 insertions, 0 deletions
diff --git a/src/libjin-lua/common/je_lua.h b/src/libjin-lua/common/je_lua.h
new file mode 100644
index 0000000..74f9819
--- /dev/null
+++ b/src/libjin-lua/common/je_lua.h
@@ -0,0 +1,83 @@
+#ifndef __JE_LUA_H__
+#define __JE_LUA_H__
+
+#include <vector>
+
+#include "LuaJIT/lua.hpp"
+#include "luax/luax.h"
+
+#include "je_lua_shared.hpp"
+#include "je_lua_object.h"
+#include "je_lua_reference.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ // Extends luax.h library.
+
+ ///
+ ///
+ ///
+ LuaObject* luax_newinstance(lua_State* L, const char* type, Shared* shared);
+
+ ///
+ /// Copy instance to another lua state.
+ ///
+ LuaObject* luax_copyinstance(lua_State* to, LuaObject* src);
+
+ ///
+ ///
+ ///
+ LuaObject* luax_checkobject(lua_State* L, int idx, const char* type);
+
+ ///
+ /// Access lua object by object pointer.
+ ///
+ int luax_getobject(lua_State* L, LuaObject* obj);
+
+ ///
+ /// Get object's reference table.
+ ///
+ void luax_getreference(lua_State* L, LuaObject* obj);
+
+ ///
+ ///
+ ///
+ bool luax_addreference(lua_State* L, LuaObject* obj, LuaObject* dep);
+
+ ///
+ ///
+ ///
+ void luax_removereference(lua_State* L, LuaObject* obj);
+
+ ///
+ ///
+ ///
+ void luax_removereference(lua_State* L, LuaObject* obj, LuaObject* dep);
+
+ ///
+ ///
+ ///
+ void luax_removeobject(lua_State* L, LuaObject* obj);
+
+ ///
+ ///
+ ///
+ int luax_getobjectstable(lua_State* L);
+
+ ///
+ ///
+ ///
+ int luax_getmodulestable(lua_State* L);
+
+ ///
+ ///
+ ///
+ int luax_getreferencestable(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/common/je_lua_callback.cpp b/src/libjin-lua/common/je_lua_callback.cpp
new file mode 100644
index 0000000..392f919
--- /dev/null
+++ b/src/libjin-lua/common/je_lua_callback.cpp
@@ -0,0 +1,43 @@
+#include "je_lua_callback.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ LuaCallback::LuaCallback(lua_State* L)
+ : mLuaFunc(nullptr)
+ , mParams(0)
+ , mL(L)
+ {
+ }
+
+ LuaCallback::~LuaCallback()
+ {
+ delete mLuaFunc;
+ for (auto p : mParams)
+ delete p;
+ }
+
+ void LuaCallback::setFunc(int i)
+ {
+ if (mLuaFunc != nullptr)
+ delete mLuaFunc;
+ mLuaFunc = new LuaRef(mL, i);
+ }
+
+ void LuaCallback::pushParam(int i)
+ {
+ mParams.push_back(new LuaRef(mL, i));
+ }
+
+ void LuaCallback::call()
+ {
+ mLuaFunc->push();
+ for (auto p : mParams)
+ p->push();
+ luax_call(mL, mParams.size(), 0);
+ }
+
+ }
+} \ No newline at end of file
diff --git a/src/libjin-lua/common/je_lua_callback.h b/src/libjin-lua/common/je_lua_callback.h
new file mode 100644
index 0000000..0467e45
--- /dev/null
+++ b/src/libjin-lua/common/je_lua_callback.h
@@ -0,0 +1,66 @@
+#ifndef __JIN_COMMON_FUNCTION_H
+#define __JIN_COMMON_FUNCTION_H
+
+#include <vector>
+
+#include "libjin/jin.h"
+#include "je_lua_reference.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ ///
+ ///
+ ///
+ class LuaCallback
+ {
+ public:
+ ///
+ ///
+ ///
+ LuaCallback(lua_State* L);
+
+ ///
+ ///
+ ///
+ ~LuaCallback();
+
+ ///
+ ///
+ ///
+ void setFunc(int i);
+
+ ///
+ ///
+ ///
+ void pushParam(int i);
+
+ ///
+ ///
+ ///
+ void call();
+
+ private:
+ ///
+ ///
+ ///
+ LuaRef* mLuaFunc;
+
+ ///
+ ///
+ ///
+ std::vector<LuaRef*> mParams;
+
+ ///
+ ///
+ ///
+ lua_State* const mL;
+
+ };
+
+ } // namespace Lua
+} // namespace JinEngine
+
+#endif // __JIN_COMMON_REFERENCE_H \ No newline at end of file
diff --git a/src/libjin-lua/common/je_lua_common.h b/src/libjin-lua/common/je_lua_common.h
new file mode 100644
index 0000000..cdd4f36
--- /dev/null
+++ b/src/libjin-lua/common/je_lua_common.h
@@ -0,0 +1,9 @@
+#ifndef __JIN_M_TYPES_H
+#define __JIN_M_TYPES_H
+
+#include "je_lua.h"
+#include "je_lua_port.h"
+#include "je_lua_error.h"
+#include "je_lua_reference.h"
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/common/je_lua_constant.h b/src/libjin-lua/common/je_lua_constant.h
new file mode 100644
index 0000000..c173b88
--- /dev/null
+++ b/src/libjin-lua/common/je_lua_constant.h
@@ -0,0 +1,14 @@
+#ifndef __JE_LUA_CONSTANT_H__
+#define __JE_LUA_CONSTANT_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/common/je_lua_error.h b/src/libjin-lua/common/je_lua_error.h
new file mode 100644
index 0000000..bd5695d
--- /dev/null
+++ b/src/libjin-lua/common/je_lua_error.h
@@ -0,0 +1,30 @@
+#ifndef __JIN_ERROR_H
+#define __JIN_ERROR_H
+
+#include <string.h>
+
+#include "common/je_lua.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ static const int FORMAT_MSG_BUFFER_SIZE = 2048;
+
+ inline void error(lua_State* L, const char* fmt, ...)
+ {
+ char err[FORMAT_MSG_BUFFER_SIZE + 1] = { 0 };
+ va_list args;
+ va_start(args, fmt);
+ vsnprintf(err + strlen(err), FORMAT_MSG_BUFFER_SIZE, fmt, args);
+ va_end(args);
+ //luax_getglobal(L, "jin");
+ //luax_setfieldstring(L, "error", err);
+ luax_error(L, err);
+ }
+
+ } // namespace Lua
+} // namespace JinEngine
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/common/je_lua_function.cpp b/src/libjin-lua/common/je_lua_function.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/libjin-lua/common/je_lua_function.cpp
diff --git a/src/libjin-lua/common/je_lua_function.h b/src/libjin-lua/common/je_lua_function.h
new file mode 100644
index 0000000..49c1b31
--- /dev/null
+++ b/src/libjin-lua/common/je_lua_function.h
@@ -0,0 +1,6 @@
+#ifndef __JE_LUA_FUNCTION_H__
+#define __JE_LUA_FUNCTION_H__
+
+
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/common/je_lua_object.cpp b/src/libjin-lua/common/je_lua_object.cpp
new file mode 100644
index 0000000..c35356e
--- /dev/null
+++ b/src/libjin-lua/common/je_lua_object.cpp
@@ -0,0 +1,112 @@
+#include "je_lua_object.h"
+#include "je_lua.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ void LuaObject::bind(Shared* obj)
+ {
+ if (obj)
+ {
+ shared = obj;
+ shared->retain();
+ dependencies = new std::map<uint, LuaObject*>();
+ }
+ }
+
+ void LuaObject::release()
+ {
+ // Delete lua shared table reference and references.
+ if (dependencies)
+ {
+ clearDependencies();
+ delete dependencies;
+ dependencies = nullptr;
+ }
+ // Try delete engine side shared.
+ if (shared)
+ {
+ shared->release();
+ shared = nullptr;
+ }
+ }
+
+ const char* LuaObject::getObjectType()
+ {
+ return type;
+ }
+
+ Shared* LuaObject::getShared()
+ {
+ return shared;
+ }
+
+ void LuaObject::setDependency(uint key, LuaObject* dep)
+ {
+ removeDependency(key);
+ dependencies->insert(std::pair<uint, LuaObject*>(key, dep));
+ luax_addreference(state, this, dep);
+ }
+
+ void LuaObject::removeDependency(uint key)
+ {
+ if (!isDependOn(key))
+ return;
+ DepsMap::iterator it = dependencies->find(key);
+ LuaObject* dep = it->second;
+ luax_removereference(state, this, dep);
+ dependencies->erase(it);
+ }
+
+ void LuaObject::removeDependency(LuaObject* dependency)
+ {
+ for (DepsMap::iterator it = dependencies->begin(); it != dependencies->end();)
+ {
+ LuaObject* dep = it->second;
+ if (dep == dependency)
+ {
+ luax_removereference(state, this, dep);
+ dependencies->erase(it);
+ }
+ else
+ ++it;
+ }
+ }
+
+ bool LuaObject::isDependOn(uint key)
+ {
+ return dependencies->find(key) != dependencies->end();
+ }
+
+ bool LuaObject::isDependOn(LuaObject* shared)
+ {
+ for (std::pair<uint, LuaObject*> dep : (*dependencies))
+ {
+ if (dep.second == shared)
+ return true;
+ }
+ return false;
+ }
+
+ void LuaObject::clearDependencies()
+ {
+ luax_removereference(state, this);
+ dependencies->clear();
+ }
+
+ LuaObject* LuaObject::getDependency(uint key)
+ {
+ if (!isDependOn(key))
+ return nullptr;
+ return dependencies->find(key)->second;
+ }
+
+ int LuaObject::getDependenciesCount()
+ {
+ return dependencies->size();
+ }
+
+ }
+} \ No newline at end of file
diff --git a/src/libjin-lua/common/je_lua_object.h b/src/libjin-lua/common/je_lua_object.h
new file mode 100644
index 0000000..6e86508
--- /dev/null
+++ b/src/libjin-lua/common/je_lua_object.h
@@ -0,0 +1,69 @@
+#ifndef __JIN_COMMON_OBJECT_H__
+#define __JIN_COMMON_OBJECT_H__
+
+#include "libjin/jin.h"
+#include "je_lua_shared.hpp"
+
+struct lua_State;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ class LuaObject
+ {
+ public:
+ ///
+ /// Set lua_State and object it bind.
+ ///
+ void bind(Shared* obj);
+
+ void release();
+
+ const char* getObjectType();
+
+ Shared* getShared();
+
+ template<class T>
+ T* getObject()
+ {
+ return shared->getObject<T>();
+ }
+
+ void setDependency(uint key, LuaObject* dep);
+
+ void removeDependency(uint key);
+
+ void removeDependency(LuaObject* dep);
+
+ bool isDependOn(uint key);
+
+ bool isDependOn(LuaObject* shared);
+
+ void clearDependencies();
+
+ LuaObject* getDependency(uint key);
+
+ int getDependenciesCount();
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Lua state object.
+ //////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ using DepsMap = std::map<uint, LuaObject*>;
+
+ lua_State* state;
+
+ Shared* shared;
+
+ const char* type;
+
+ DepsMap* dependencies;
+
+ };
+
+ } // namespace Lua
+} // namespace JinEngine
+
+#endif // __JIN_COMMON_OBJECT_H__ \ No newline at end of file
diff --git a/src/libjin-lua/common/je_lua_port.h b/src/libjin-lua/common/je_lua_port.h
new file mode 100644
index 0000000..8e99ca4
--- /dev/null
+++ b/src/libjin-lua/common/je_lua_port.h
@@ -0,0 +1,8 @@
+#ifndef __JE_LUA_PORT_H
+#define __JE_LUA_PORT_H
+
+#define LUA_PORT extern
+#define LUA_IMPLEMENT static
+#define LUA_EXPORT
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/common/je_lua_reference.cpp b/src/libjin-lua/common/je_lua_reference.cpp
new file mode 100644
index 0000000..72c1c3e
--- /dev/null
+++ b/src/libjin-lua/common/je_lua_reference.cpp
@@ -0,0 +1,42 @@
+#include "common/je_lua.h"
+
+#include "je_lua_reference.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ LuaRef::LuaRef(lua_State* L, int i)
+ : mL(L)
+ {
+ // Get value.
+ luax_pushvalue(mL, i);
+ // Set reference.
+ luax_getreferencestable(L);
+ luax_pushvalue(mL, -2);
+ mIndex = luax_ref(mL, -2);
+ luax_pop(L, 3);
+ }
+
+ LuaRef::~LuaRef()
+ {
+ unref();
+ }
+
+ void LuaRef::unref()
+ {
+ luax_getreferencestable(mL);
+ luax_unref(mL, -1, mIndex);
+ luax_pop(mL, 1);
+ }
+
+ void LuaRef::push()
+ {
+ luax_getreferencestable(mL);
+ luax_rawgeti(mL, -1, mIndex);
+ luax_remove(mL, -2);
+ }
+
+ }
+} \ No newline at end of file
diff --git a/src/libjin-lua/common/je_lua_reference.h b/src/libjin-lua/common/je_lua_reference.h
new file mode 100644
index 0000000..1a62dba
--- /dev/null
+++ b/src/libjin-lua/common/je_lua_reference.h
@@ -0,0 +1,54 @@
+#ifndef __JIN_COMMON_REFERENCE_H
+#define __JIN_COMMON_REFERENCE_H
+
+#include "common/je_lua.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ ///
+ /// This class wraps the reference functionality built into Lua, which allows C++ code to refer to Lua
+ /// variables.
+ ///
+ class LuaRef
+ {
+ public:
+ ///
+ ///
+ ///
+ LuaRef(lua_State* L, int i);
+
+ ///
+ ///
+ ///
+ ~LuaRef();
+
+ ///
+ ///
+ ///
+ void unref();
+
+ ///
+ /// Push value onto the stack.
+ ///
+ void push();
+
+ private:
+ ///
+ ///
+ ///
+ lua_State* const mL;
+
+ ///
+ ///
+ ///
+ int mIndex;
+
+ };
+
+ } // namespace Lua
+} // namespace JinEngine
+
+#endif // __JIN_COMMON_REFERENCE_H \ No newline at end of file
diff --git a/src/libjin-lua/common/je_lua_runtime.cpp b/src/libjin-lua/common/je_lua_runtime.cpp
new file mode 100644
index 0000000..fb665f1
--- /dev/null
+++ b/src/libjin-lua/common/je_lua_runtime.cpp
@@ -0,0 +1,215 @@
+#include "libjin/jin.h"
+
+#include "je_lua.h"
+#include "je_lua_object.h"
+
+using namespace std;
+using namespace JinEngine::Math;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ static const char* Jin_Lua_Objects_Table = "Jin_Objects_Table";
+
+ static const char* Jin_Lua_Reference_Table = "Jin_Reference_Table";
+
+ static const char* Jin_Lua_Modules_Table = "Jin_Modules_Table";
+
+ using DepsMap = LuaObject::DepsMap;
+
+ LuaObject* luax_newinstance(lua_State* L, const char* type, Shared* shared)
+ {
+ LuaObject* obj = static_cast<LuaObject*>(luax_newinstance(L, type, sizeof(LuaObject)));
+ obj->state = L;
+ obj->type = type;
+ obj->bind(shared);
+ // Add to objects_table, objects_table[shared] = luaObj
+ luax_getobjectstable(L);
+ luax_pushlightuserdata(L, shared);
+ luax_pushvalue(L, -3);
+ luax_settable(L, -3);
+ luax_pop(L, 1); // Pop objects table.
+ return obj;
+ }
+
+ LuaObject* luax_checkobject(lua_State* L, int idx, const char* type)
+ {
+ return (LuaObject*)luax_checktype(L, idx, type);
+ }
+
+ LuaObject* luax_copyinstance(lua_State* to, LuaObject* src)
+ {
+ if (to == src->state)
+ return nullptr;
+ // Copy dependencies.
+ DepsMap& srcDeps = *src->dependencies;
+ for (DepsMap::iterator it = srcDeps.begin(); it != srcDeps.end(); ++it)
+ {
+ LuaObject* obj = it->second;
+ Shared* shr = obj->shared;
+ // Try get lua object.
+ luax_getobject(src->state, obj);
+ LuaObject* luaObj = (LuaObject*)luax_checktype(src->state, -1, obj->getObjectType());
+ luax_pop(src->state, 1); // Pop lua object.
+ luax_copyinstance(to, luaObj);
+ luax_pop(to, 1); // Pop reference object.
+ }
+ Shared* shr = src->getShared();
+ LuaObject* obj = luax_newinstance(to, src->getObjectType(), shr);
+ (*obj->dependencies) = (*src->dependencies);
+ // Add to objects_table.
+ luax_getobjectstable(to);
+ luax_pushlightuserdata(to, shr);
+ luax_pushvalue(to, -3);
+ luax_settable(to, -3);
+ luax_pop(to, 1); // Pop objects table.
+ // Set dependencies.
+ DepsMap& deps = *obj->dependencies;
+ DepsMap::iterator it = deps.begin();
+ for (; it != deps.end(); ++it)
+ {
+ LuaObject* dep = it->second;
+ luax_addreference(to, src, dep);
+ }
+ return obj;
+ }
+
+ int luax_getobject(lua_State* L, LuaObject* obj)
+ {
+ luax_getobjectstable(L);
+ luax_pushlightuserdata(L, obj->shared);
+ luax_gettable(L, -2);
+ luax_remove(L, -2); // Remove objects table on stack.
+ return 1;
+ }
+
+ void luax_removeobject(lua_State* L, LuaObject* obj)
+ {
+ luax_getobjectstable(L);
+ luax_pushlightuserdata(L, obj->shared);
+ luax_pushnil(L);
+ luax_settable(L, -3);
+ luax_pop(L, 1);
+ }
+
+ int luax_getobjectstable(lua_State* L)
+ {
+ luax_getfield(L, LUA_REGISTRYINDEX, Jin_Lua_Objects_Table);
+ // If no such table, add one.
+ if (luax_isnil(L, -1) || !luax_istable(L, -1))
+ {
+ luax_pop(L, 1);
+ luax_newtable(L);
+
+ // metatable
+ luax_newtable(L);
+ // weak table
+ luax_pushliteral(L, "v");
+ luax_setfield(L, -2, "__mode");
+ // setmetatable(newtable, metatable)
+ luax_setmetatable(L, -2);
+
+ luax_pushvalue(L, -1);
+ luax_setfield(L, LUA_REGISTRYINDEX, Jin_Lua_Objects_Table);
+ }
+ return 1;
+ }
+
+ int luax_getmodulestable(lua_State* L)
+ {
+ luax_getfield(L, LUA_REGISTRYINDEX, Jin_Lua_Modules_Table);
+ // If no such table, add one.
+ if (luax_isnil(L, -1) || !luax_istable(L, -1))
+ {
+ luax_pop(L, 1);
+ luax_newtable(L);
+
+ // metatable
+ luax_newtable(L);
+ // weak table
+ luax_pushliteral(L, "v");
+ luax_setfield(L, -2, "__mode");
+ // setmetatable(newtable, metatable)
+ luax_setmetatable(L, -2);
+
+ luax_pushvalue(L, -1);
+ luax_setfield(L, LUA_REGISTRYINDEX, Jin_Lua_Modules_Table);
+ }
+ return 1;
+ }
+
+ int luax_getreferencestable(lua_State* L)
+ {
+ luax_getfield(L, LUA_REGISTRYINDEX, Jin_Lua_Reference_Table);
+ // If no such table, add one.
+ if (luax_isnil(L, -1) || !luax_istable(L, -1))
+ {
+ luax_pop(L, 1);
+ luax_newtable(L);
+ luax_pushvalue(L, -1);
+ luax_setfield(L, LUA_REGISTRYINDEX, Jin_Lua_Reference_Table);
+ }
+ return 1;
+ }
+
+ void luax_getreference(lua_State* L, LuaObject* obj)
+ {
+ luax_getreferencestable(L);
+ luax_pushlightuserdata(L, obj->shared);
+ luax_gettable(L, -2);
+ luax_remove(L, -2);
+ }
+
+ bool luax_addreference(lua_State* L, LuaObject* obj, LuaObject* dep)
+ {
+ luax_getreference(L, obj);
+ // If no dependencies table, add one.
+ if (luax_isnil(L, -1))
+ {
+ luax_pop(L, 1);
+ luax_getreferencestable(L);
+ luax_newtable(L);
+ luax_pushlightuserdata(L, obj->shared);
+ luax_pushvalue(L, -2);
+ luax_settable(L, -4);
+ luax_remove(L, -2); // Remove references table.
+ }
+ luax_pushlightuserdata(L, dep->shared);
+ luax_getobject(L, dep);
+ if (luax_isnil(L, -1))
+ {
+ luax_pop(L, 3); // Pop nil, dep, reftbl.
+ return false;
+ }
+ luax_settable(L, -3);
+ luax_pop(L, 1);
+ return true;
+ }
+
+ void luax_removereference(lua_State* L, LuaObject* obj)
+ {
+ luax_getreferencestable(L);
+ luax_pushlightuserdata(L, obj->shared);
+ luax_pushnil(L);
+ luax_settable(L, -3);
+ luax_pop(L, 1);
+ }
+
+ void luax_removereference(lua_State* L, LuaObject* obj, LuaObject* dep)
+ {
+ luax_getreference(L, obj);
+ if (luax_isnil(L, -1))
+ {
+ luax_pop(L, 1);
+ return;
+ }
+ luax_pushlightuserdata(L, dep->shared);
+ luax_pushnil(L);
+ luax_settable(L, -3);
+ luax_pop(L, 1);
+ }
+
+ }
+} \ No newline at end of file
diff --git a/src/libjin-lua/common/je_lua_shared.cpp b/src/libjin-lua/common/je_lua_shared.cpp
new file mode 100644
index 0000000..fce6d81
--- /dev/null
+++ b/src/libjin-lua/common/je_lua_shared.cpp
@@ -0,0 +1,11 @@
+#include "je_lua.h"
+#include "je_lua_shared.hpp"
+#include "libjin/jin.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ }
+} \ No newline at end of file
diff --git a/src/libjin-lua/common/je_lua_shared.hpp b/src/libjin-lua/common/je_lua_shared.hpp
new file mode 100644
index 0000000..6a58ab3
--- /dev/null
+++ b/src/libjin-lua/common/je_lua_shared.hpp
@@ -0,0 +1,84 @@
+#ifndef __JE_LUA_SHARED_H__
+#define __JE_LUA_SHARED_H__
+
+#include <map>
+#include <vector>
+#include <functional>
+
+#include "libjin/jin.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ class LuaObject;
+
+ ///
+ /// Thread shared object wrapper.
+ ///
+ class Shared
+ {
+ public:
+ Shared(Object* obj)
+ : mCount(0)
+ , mObject(obj)
+ {
+ }
+
+ inline Object* operator->()
+ {
+ return static_cast<Object*>(mObject);
+ }
+
+ inline Object* getObject()
+ {
+ return static_cast<Object*>(mObject);
+ }
+
+ template<class T>
+ inline T* getObject()
+ {
+ return static_cast<T*>(mObject);
+ }
+
+ private:
+ friend class LuaObject;
+
+ // Disable copy.
+ Shared(const Shared& shared);
+
+ ///
+ /// Sharedֻڶ
+ ///
+ ~Shared()
+ {
+ delete mObject;
+ }
+
+ ///
+ /// ͬһ̵߳lua_StateУLuaObjectEngineObjectӦһһӦLuaObject(lua runtime)ü
+ /// ͻաEngine-sideüΪά̵ͬ߳lua_StateͬһEngineObjectÿLuaObjectһ
+ /// Sharedʱһüͬһ߳УһEngineObjectֻһLuaObject󶨣new
+ /// instanceУômCountͱEngineObjectĹ߳
+ ///
+ inline void Shared::retain()
+ {
+ ++mCount;
+ }
+
+ inline void Shared::release()
+ {
+ if (--mCount <= 0)
+ delete this;
+ }
+
+ Object* mObject;
+ int mCount;
+
+ };
+
+ } // namespace Lua
+} // namespace JinEngine
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/embed/embed.h b/src/libjin-lua/embed/embed.h
new file mode 100644
index 0000000..1928dd5
--- /dev/null
+++ b/src/libjin-lua/embed/embed.h
@@ -0,0 +1,47 @@
+#ifndef __JIN_LUA_EMBED_H
+#define __JIN_LUA_EMBED_H
+#include <cstring>
+
+namespace JinEngine
+{
+ namespace Embed
+ {
+
+ // Embed structure.
+ struct jin_Embed
+ {
+ const char* file, *source;
+ };
+
+ // Embed scripts.
+ #include "scripts/graphics.lua.h"
+ #include "scripts/keyboard.lua.h"
+ #include "scripts/mouse.lua.h"
+ #include "scripts/boot.lua.h"
+
+ // In order.
+ static const jin_Embed modules[] = {
+ { "graphics.lua", graphics_lua },
+ { "keyboard.lua", keyboard_lua },
+ { "mouse.lua", mouse_lua },
+ { 0, 0 }
+ };
+
+ static const jin_Embed bootscript = { "boot.lua", boot_lua };
+
+ static void run(lua_State* L)
+ {
+ for (int i = 0; modules[i].file; ++i)
+ {
+ const char* file = modules[i].file, *source = modules[i].source;
+ if (luax_loadbuffer(L, source, strlen(source), file) == 0)
+ luax_call(L, 0, 0);
+ }
+ if (luax_loadbuffer(L, bootscript.source, strlen(bootscript.source), bootscript.file) == 0)
+ luax_call(L, 0, 0);
+ }
+
+ } // namespace Embed
+} // namespace JinEngine
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/embed/scripts/ai.lua b/src/libjin-lua/embed/scripts/ai.lua
new file mode 100644
index 0000000..a69da84
--- /dev/null
+++ b/src/libjin-lua/embed/scripts/ai.lua
@@ -0,0 +1,26 @@
+/* graphics.lua */
+static const char* ai_lua = R"(
+jin.ai = jin.ai or {}
+
+local ja = jin.ai
+
+ja.StateMachineType = {
+ STEPWISE = 1,
+ ITERATIVE = 2,
+}
+
+
+
+)";
+
+
+//local sp = jin.graphics.newSprite()
+//local sm = jin.ai.newStateMachine(jin.StateMachineMode.STEPWISE, sp)
+//sm:addState("run")
+//sm:addEnterCallback("run", function(spr)
+// spr:setRun()
+//end)
+//
+//function jin.core.onUpdate(dt)
+// sm:update()
+//end
diff --git a/src/libjin-lua/embed/scripts/ai.lua.h b/src/libjin-lua/embed/scripts/ai.lua.h
new file mode 100644
index 0000000..a69da84
--- /dev/null
+++ b/src/libjin-lua/embed/scripts/ai.lua.h
@@ -0,0 +1,26 @@
+/* graphics.lua */
+static const char* ai_lua = R"(
+jin.ai = jin.ai or {}
+
+local ja = jin.ai
+
+ja.StateMachineType = {
+ STEPWISE = 1,
+ ITERATIVE = 2,
+}
+
+
+
+)";
+
+
+//local sp = jin.graphics.newSprite()
+//local sm = jin.ai.newStateMachine(jin.StateMachineMode.STEPWISE, sp)
+//sm:addState("run")
+//sm:addEnterCallback("run", function(spr)
+// spr:setRun()
+//end)
+//
+//function jin.core.onUpdate(dt)
+// sm:update()
+//end
diff --git a/src/libjin-lua/embed/scripts/boot.lua b/src/libjin-lua/embed/scripts/boot.lua
new file mode 100644
index 0000000..4b97b69
--- /dev/null
+++ b/src/libjin-lua/embed/scripts/boot.lua
@@ -0,0 +1,139 @@
+/* boot.lua */
+static const char* boot_lua = R"(
+local cwd = jin.args['cwd'] or '.'
+jin.filesystem.init()
+jin.filesystem.mount(cwd)
+
+-------------------------------------------------------------------------
+-- Config game
+-------------------------------------------------------------------------
+
+jin.config = {}
+if jin.filesystem.exist("config.lua") then
+ xpcall(function()jin.config = require "config" end, function()end)
+end
+jin.config.width = jin.config.width or 580
+jin.config.height = jin.config.height or 450
+jin.config.vsync = jin.config.vsync or true
+jin.config.title = jin.config.title or ("jin v" .. jin.version)
+jin.config.resizable = jin.config.resizable or false
+jin.config.fullscreen = jin.config.fullscreen or false
+jin.config.fps = jin.config.fps or 60
+jin.config.icon = jin.config.icon or ""
+
+-------------------------------------------------------------------------
+-- Default game loop
+-------------------------------------------------------------------------
+
+local function call(func, ...)
+ if func then
+ return func(...)
+ end
+end
+
+local step = jin.time.step
+jin.time.step = nil
+
+function jin.core.run()
+ jin.graphics.reset()
+ call(jin.core.onLoad)
+ local dt = 0
+ while jin.core.running() do
+ for _, e in pairs(jin.event.poll()) do
+ if e.type == "KeyDown" then
+ jin.keyboard.set(e.key, true)
+ elseif e.type == "KeyUp" then
+ jin.keyboard.set(e.key, false)
+ end
+ call(jin.core.onEvent, e)
+ end
+ step()
+ dt = jin.time.getDelta()
+ call(jin.core.onUpdate, dt)
+ jin.graphics.clear()
+ call(jin.core.onDraw)
+ jin.graphics.present()
+ jin.time.sleep(0.001)
+ end
+end
+
+-------------------------------------------------------------------------
+-- Boot game
+-------------------------------------------------------------------------
+
+-- Display error message.
+local function onError(msg)
+ jin.audio.destroy()
+ jin.graphics.showWindow()
+ local err = "Error:\n" .. msg .. "\n" .. debug.traceback()
+ jin.graphics.reset()
+ jin.graphics.setClearColor(100, 100, 100, 255)
+ jin.graphics.clear()
+ jin.graphics.print(err, 5, 5)
+ jin.graphics.present()
+ while jin.core.running() do
+ for _, e in pairs(jin.event.poll()) do
+ if e.type == "Quit" then
+ jin.core.stop()
+ end
+ end
+ jin.time.sleep(0.001)
+ end
+end
+
+-- No game screen.
+local function noGame()
+ jin.graphics.showWindow()
+ jin.graphics.reset()
+ jin.graphics.setClearColor(100, 100, 100, 255)
+ jin.graphics.clear()
+ jin.graphics.print("No Game", 5, 5)
+ jin.graphics.present()
+ while jin.core.running() do
+ for _, e in pairs(jin.event.poll()) do
+ if e.type == "Quit" then
+ jin.core.stop()
+ end
+ end
+ jin.time.sleep(0.001)
+ end
+end
+
+local function boot()
+ if jin.filesystem.exist("main.lua") then
+ call(function()
+ require"main"
+ jin.core.run()
+ end)
+ else
+ noGame()
+ end
+end
+
+-------------------------------------------------------------------------
+-- Initialize sub systems
+-------------------------------------------------------------------------
+
+jin.audio.init()
+jin.graphics.init(jin.config)
+
+-------------------------------------------------------------------------
+-- Boot game
+-------------------------------------------------------------------------
+
+xpcall(boot, onError)
+
+-------------------------------------------------------------------------
+-- Destroy sub-systems
+-------------------------------------------------------------------------
+
+jin.graphics.destroy()
+jin.audio.destroy()
+
+-------------------------------------------------------------------------
+-- Quit game
+-------------------------------------------------------------------------
+
+jin.core.quit()
+
+)"; \ No newline at end of file
diff --git a/src/libjin-lua/embed/scripts/boot.lua.h b/src/libjin-lua/embed/scripts/boot.lua.h
new file mode 100644
index 0000000..4b97b69
--- /dev/null
+++ b/src/libjin-lua/embed/scripts/boot.lua.h
@@ -0,0 +1,139 @@
+/* boot.lua */
+static const char* boot_lua = R"(
+local cwd = jin.args['cwd'] or '.'
+jin.filesystem.init()
+jin.filesystem.mount(cwd)
+
+-------------------------------------------------------------------------
+-- Config game
+-------------------------------------------------------------------------
+
+jin.config = {}
+if jin.filesystem.exist("config.lua") then
+ xpcall(function()jin.config = require "config" end, function()end)
+end
+jin.config.width = jin.config.width or 580
+jin.config.height = jin.config.height or 450
+jin.config.vsync = jin.config.vsync or true
+jin.config.title = jin.config.title or ("jin v" .. jin.version)
+jin.config.resizable = jin.config.resizable or false
+jin.config.fullscreen = jin.config.fullscreen or false
+jin.config.fps = jin.config.fps or 60
+jin.config.icon = jin.config.icon or ""
+
+-------------------------------------------------------------------------
+-- Default game loop
+-------------------------------------------------------------------------
+
+local function call(func, ...)
+ if func then
+ return func(...)
+ end
+end
+
+local step = jin.time.step
+jin.time.step = nil
+
+function jin.core.run()
+ jin.graphics.reset()
+ call(jin.core.onLoad)
+ local dt = 0
+ while jin.core.running() do
+ for _, e in pairs(jin.event.poll()) do
+ if e.type == "KeyDown" then
+ jin.keyboard.set(e.key, true)
+ elseif e.type == "KeyUp" then
+ jin.keyboard.set(e.key, false)
+ end
+ call(jin.core.onEvent, e)
+ end
+ step()
+ dt = jin.time.getDelta()
+ call(jin.core.onUpdate, dt)
+ jin.graphics.clear()
+ call(jin.core.onDraw)
+ jin.graphics.present()
+ jin.time.sleep(0.001)
+ end
+end
+
+-------------------------------------------------------------------------
+-- Boot game
+-------------------------------------------------------------------------
+
+-- Display error message.
+local function onError(msg)
+ jin.audio.destroy()
+ jin.graphics.showWindow()
+ local err = "Error:\n" .. msg .. "\n" .. debug.traceback()
+ jin.graphics.reset()
+ jin.graphics.setClearColor(100, 100, 100, 255)
+ jin.graphics.clear()
+ jin.graphics.print(err, 5, 5)
+ jin.graphics.present()
+ while jin.core.running() do
+ for _, e in pairs(jin.event.poll()) do
+ if e.type == "Quit" then
+ jin.core.stop()
+ end
+ end
+ jin.time.sleep(0.001)
+ end
+end
+
+-- No game screen.
+local function noGame()
+ jin.graphics.showWindow()
+ jin.graphics.reset()
+ jin.graphics.setClearColor(100, 100, 100, 255)
+ jin.graphics.clear()
+ jin.graphics.print("No Game", 5, 5)
+ jin.graphics.present()
+ while jin.core.running() do
+ for _, e in pairs(jin.event.poll()) do
+ if e.type == "Quit" then
+ jin.core.stop()
+ end
+ end
+ jin.time.sleep(0.001)
+ end
+end
+
+local function boot()
+ if jin.filesystem.exist("main.lua") then
+ call(function()
+ require"main"
+ jin.core.run()
+ end)
+ else
+ noGame()
+ end
+end
+
+-------------------------------------------------------------------------
+-- Initialize sub systems
+-------------------------------------------------------------------------
+
+jin.audio.init()
+jin.graphics.init(jin.config)
+
+-------------------------------------------------------------------------
+-- Boot game
+-------------------------------------------------------------------------
+
+xpcall(boot, onError)
+
+-------------------------------------------------------------------------
+-- Destroy sub-systems
+-------------------------------------------------------------------------
+
+jin.graphics.destroy()
+jin.audio.destroy()
+
+-------------------------------------------------------------------------
+-- Quit game
+-------------------------------------------------------------------------
+
+jin.core.quit()
+
+)"; \ No newline at end of file
diff --git a/src/libjin-lua/embed/scripts/graphics.lua b/src/libjin-lua/embed/scripts/graphics.lua
new file mode 100644
index 0000000..0a66127
--- /dev/null
+++ b/src/libjin-lua/embed/scripts/graphics.lua
@@ -0,0 +1,139 @@
+/* graphics.lua */
+static const char* graphics_lua = R"(
+jin.graphics = jin.graphics or {}
+
+local jg = jin.graphics
+
+jg.RenderMode = {
+ FILL = 1,
+ LINE = 2,
+}
+
+jg.SpriteOrigin = {
+ TOPLEFT = 0,
+ TOPCENTER = 1,
+ TOPRIGHT = 2,
+ MIDDLELEFT = 3,
+ MIDDLECENTER = 4,
+ MIDDLERIGHT = 5,
+ BOTTOMLEFT = 6,
+ BOTTOMCENTER = 7,
+ BOTTOMRIGHT = 8
+}
+
+jg.SpriteMode = {
+ SINGLE = 1,
+ RANDOM = 2,
+ ANIMATED = 3
+}
+
+-- built in shaders
+jg.Shaders = {
+ Font = nil,
+ Texture = nil,
+ Sprite = nil,
+ SpriteSheet = nil,
+ Default = nil
+}
+
+local function compileBuiltInShaders()
+ jg.Shaders.Font = jg.newShader([[
+ #VERTEX_SHADER
+ Vertex vert(Vertex v)
+ {
+ return v;
+ }
+ #END_VERTEX_SHADER
+ #FRAGMENT_SHADER
+ Color frag(Color col, Texture tex, Vertex v)
+ {
+ return Color(col.rgb, texel(tex, v.uv).a);
+ }
+ #END_FRAGMENT_SHADER
+ ]])
+ jg.Shaders.Texture = jg.newShader([[
+ #VERTEX_SHADER
+ Vertex vert(Vertex v)
+ {
+ return v;
+ }
+ #END_VERTEX_SHADER
+ #FRAGMENT_SHADER
+ Color frag(Color col, Texture tex, Vertex v)
+ {
+ return col * texel(tex, v.uv);
+ }
+ #END_FRAGMENT_SHADER
+ ]])
+ jg.Shaders.Sprite = jg.newShader([[
+ #VERTEX_SHADER
+ Vertex vert(Vertex v)
+ {
+ return v;
+ }
+ #END_VERTEX_SHADER
+ #FRAGMENT_SHADER
+ Color frag(Color col, Texture tex, Vertex v)
+ {
+ return col * texel(tex, v.uv);
+ }
+ #END_FRAGMENT_SHADER
+ ]])
+ jg.Shaders.SpriteSheet = jg.newShader([[
+ #VERTEX_SHADER
+ Vertex vert(Vertex v)
+ {
+ return v;
+ }
+ #END_VERTEX_SHADER
+ #FRAGMENT_SHADER
+ Color frag(Color col, Texture tex, Vertex v)
+ {
+ return col * texel(tex, v.uv);
+ }
+ #END_FRAGMENT_SHADER
+ ]])
+ jg.Shaders.Default = jg.newShader([[
+ #VERTEX_SHADER
+ Vertex vert(Vertex v)
+ {
+ return v;
+ }
+ #END_VERTEX_SHADER
+ #FRAGMENT_SHADER
+ Color frag(Color col, Texture tex, Vertex v)
+ {
+ return col * texel(tex, v.uv);
+ }
+ #END_FRAGMENT_SHADER
+ ]])
+end
+
+local _init = jg.init
+local initialized = false
+jg.init = function(setting)
+ if initialized then
+ return initialized
+ end
+ initialized = _init(setting)
+ if initialized then
+ compileBuiltInShaders()
+ jg.useShader(jg.Shaders.Default)
+ end
+ return initialized
+end
+
+jg.unuseShader = function()
+ jg.useShader(jg.Shaders.Default)
+end
+
+-- Reset all attributes to default value.
+jg.reset = function()
+ jg.setColor(255, 255, 255, 255)
+ jg.setClearColor(0, 0, 0, 255)
+ jg.clear()
+ jg.unsetFont()
+ jg.unuseShader()
+end
+
+)"; \ No newline at end of file
diff --git a/src/libjin-lua/embed/scripts/graphics.lua.h b/src/libjin-lua/embed/scripts/graphics.lua.h
new file mode 100644
index 0000000..0a66127
--- /dev/null
+++ b/src/libjin-lua/embed/scripts/graphics.lua.h
@@ -0,0 +1,139 @@
+/* graphics.lua */
+static const char* graphics_lua = R"(
+jin.graphics = jin.graphics or {}
+
+local jg = jin.graphics
+
+jg.RenderMode = {
+ FILL = 1,
+ LINE = 2,
+}
+
+jg.SpriteOrigin = {
+ TOPLEFT = 0,
+ TOPCENTER = 1,
+ TOPRIGHT = 2,
+ MIDDLELEFT = 3,
+ MIDDLECENTER = 4,
+ MIDDLERIGHT = 5,
+ BOTTOMLEFT = 6,
+ BOTTOMCENTER = 7,
+ BOTTOMRIGHT = 8
+}
+
+jg.SpriteMode = {
+ SINGLE = 1,
+ RANDOM = 2,
+ ANIMATED = 3
+}
+
+-- built in shaders
+jg.Shaders = {
+ Font = nil,
+ Texture = nil,
+ Sprite = nil,
+ SpriteSheet = nil,
+ Default = nil
+}
+
+local function compileBuiltInShaders()
+ jg.Shaders.Font = jg.newShader([[
+ #VERTEX_SHADER
+ Vertex vert(Vertex v)
+ {
+ return v;
+ }
+ #END_VERTEX_SHADER
+ #FRAGMENT_SHADER
+ Color frag(Color col, Texture tex, Vertex v)
+ {
+ return Color(col.rgb, texel(tex, v.uv).a);
+ }
+ #END_FRAGMENT_SHADER
+ ]])
+ jg.Shaders.Texture = jg.newShader([[
+ #VERTEX_SHADER
+ Vertex vert(Vertex v)
+ {
+ return v;
+ }
+ #END_VERTEX_SHADER
+ #FRAGMENT_SHADER
+ Color frag(Color col, Texture tex, Vertex v)
+ {
+ return col * texel(tex, v.uv);
+ }
+ #END_FRAGMENT_SHADER
+ ]])
+ jg.Shaders.Sprite = jg.newShader([[
+ #VERTEX_SHADER
+ Vertex vert(Vertex v)
+ {
+ return v;
+ }
+ #END_VERTEX_SHADER
+ #FRAGMENT_SHADER
+ Color frag(Color col, Texture tex, Vertex v)
+ {
+ return col * texel(tex, v.uv);
+ }
+ #END_FRAGMENT_SHADER
+ ]])
+ jg.Shaders.SpriteSheet = jg.newShader([[
+ #VERTEX_SHADER
+ Vertex vert(Vertex v)
+ {
+ return v;
+ }
+ #END_VERTEX_SHADER
+ #FRAGMENT_SHADER
+ Color frag(Color col, Texture tex, Vertex v)
+ {
+ return col * texel(tex, v.uv);
+ }
+ #END_FRAGMENT_SHADER
+ ]])
+ jg.Shaders.Default = jg.newShader([[
+ #VERTEX_SHADER
+ Vertex vert(Vertex v)
+ {
+ return v;
+ }
+ #END_VERTEX_SHADER
+ #FRAGMENT_SHADER
+ Color frag(Color col, Texture tex, Vertex v)
+ {
+ return col * texel(tex, v.uv);
+ }
+ #END_FRAGMENT_SHADER
+ ]])
+end
+
+local _init = jg.init
+local initialized = false
+jg.init = function(setting)
+ if initialized then
+ return initialized
+ end
+ initialized = _init(setting)
+ if initialized then
+ compileBuiltInShaders()
+ jg.useShader(jg.Shaders.Default)
+ end
+ return initialized
+end
+
+jg.unuseShader = function()
+ jg.useShader(jg.Shaders.Default)
+end
+
+-- Reset all attributes to default value.
+jg.reset = function()
+ jg.setColor(255, 255, 255, 255)
+ jg.setClearColor(0, 0, 0, 255)
+ jg.clear()
+ jg.unsetFont()
+ jg.unuseShader()
+end
+
+)"; \ No newline at end of file
diff --git a/src/libjin-lua/embed/scripts/keyboard.lua b/src/libjin-lua/embed/scripts/keyboard.lua
new file mode 100644
index 0000000..e989928
--- /dev/null
+++ b/src/libjin-lua/embed/scripts/keyboard.lua
@@ -0,0 +1,17 @@
+
+static const char* keyboard_lua = R"(
+jin.keyboard = jin.keyboard or {}
+
+local jk = jin.keyboard
+
+local keys = {}
+
+function jin.keyboard.isPressed(k)
+ return keys[k]
+end
+
+function jin.keyboard.set(k, status)
+ keys[k] = status
+end
+
+)";
diff --git a/src/libjin-lua/embed/scripts/keyboard.lua.h b/src/libjin-lua/embed/scripts/keyboard.lua.h
new file mode 100644
index 0000000..e989928
--- /dev/null
+++ b/src/libjin-lua/embed/scripts/keyboard.lua.h
@@ -0,0 +1,17 @@
+
+static const char* keyboard_lua = R"(
+jin.keyboard = jin.keyboard or {}
+
+local jk = jin.keyboard
+
+local keys = {}
+
+function jin.keyboard.isPressed(k)
+ return keys[k]
+end
+
+function jin.keyboard.set(k, status)
+ keys[k] = status
+end
+
+)";
diff --git a/src/libjin-lua/embed/scripts/mouse.lua b/src/libjin-lua/embed/scripts/mouse.lua
new file mode 100644
index 0000000..ca070a3
--- /dev/null
+++ b/src/libjin-lua/embed/scripts/mouse.lua
@@ -0,0 +1,16 @@
+static const char* mouse_lua = R"(
+jin.mouse = jin.mouse or {}
+
+local jm = jin.mouse
+
+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/libjin-lua/embed/scripts/mouse.lua.h b/src/libjin-lua/embed/scripts/mouse.lua.h
new file mode 100644
index 0000000..ca070a3
--- /dev/null
+++ b/src/libjin-lua/embed/scripts/mouse.lua.h
@@ -0,0 +1,16 @@
+static const char* mouse_lua = R"(
+jin.mouse = jin.mouse or {}
+
+local jm = jin.mouse
+
+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/libjin-lua/embed/scripts/net.lua b/src/libjin-lua/embed/scripts/net.lua
new file mode 100644
index 0000000..a986ce6
--- /dev/null
+++ b/src/libjin-lua/embed/scripts/net.lua
@@ -0,0 +1,7 @@
+/* net.lua */
+static const char* net_lua = R"(
+jin.net = jin.net or {}
+
+local jn = jin.net
+
+)"; \ No newline at end of file
diff --git a/src/libjin-lua/embed/scripts/net.lua.h b/src/libjin-lua/embed/scripts/net.lua.h
new file mode 100644
index 0000000..a986ce6
--- /dev/null
+++ b/src/libjin-lua/embed/scripts/net.lua.h
@@ -0,0 +1,7 @@
+/* net.lua */
+static const char* net_lua = R"(
+jin.net = jin.net or {}
+
+local jn = jin.net
+
+)"; \ No newline at end of file
diff --git a/src/libjin-lua/embed/scripts/path.lua b/src/libjin-lua/embed/scripts/path.lua
new file mode 100644
index 0000000..f7e1ec3
--- /dev/null
+++ b/src/libjin-lua/embed/scripts/path.lua
@@ -0,0 +1,16 @@
+/* path.lua */
+static const char* path_lua = R"(
+jin.path = jin.path or {}
+
+local jp = jin.path
+
+-- 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/libjin-lua/embed/scripts/path.lua.h b/src/libjin-lua/embed/scripts/path.lua.h
new file mode 100644
index 0000000..f7e1ec3
--- /dev/null
+++ b/src/libjin-lua/embed/scripts/path.lua.h
@@ -0,0 +1,16 @@
+/* path.lua */
+static const char* path_lua = R"(
+jin.path = jin.path or {}
+
+local jp = jin.path
+
+-- 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/libjin-lua/je_lua_jin.cpp b/src/libjin-lua/je_lua_jin.cpp
new file mode 100644
index 0000000..8d79415
--- /dev/null
+++ b/src/libjin-lua/je_lua_jin.cpp
@@ -0,0 +1,101 @@
+#include "common/je_lua.h"
+#include "common/je_lua_common.h"
+#include "modules/je_lua_modules.h"
+#include "embed/embed.h"
+#include "je_lua_jin.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ LUA_IMPLEMENT int l_getversion(lua_State* L)
+ {
+ luax_pushstring(L, VERSION);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_getAuthor(lua_State* L)
+ {
+ luax_pushstring(L, AUTHOR);
+ return 1;
+ }
+
+ LUA_IMPLEMENT 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;
+ }
+
+ LUA_IMPLEMENT int l_revision(lua_State* L)
+ {
+ luax_pushnumber(L, REVISION);
+ return 1;
+ }
+
+ // Register jin module, keep it on the top of stack.
+ LUA_EXPORT void open(lua_State* L)
+ {
+ luax_globaltable(L, MODULE_NAME);
+
+ const luax_Str s[] = {
+ { "version", VERSION },
+ { "author", AUTHOR },
+ { "codename", CODE_NAME },
+ { 0, 0 }
+ };
+ const luax_Num n[] = {
+ { "revision", REVISION },
+ { 0, 0 }
+ };
+ // Register values.
+ luax_setfieldstrings(L, s);
+ luax_setfieldnumbers(L, n);
+
+ luax_Reg modules[] = {
+ { "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 },
+ { "math", luaopen_math },
+ { "thread", luaopen_thread },
+ { "bit", luaopen_bit },
+ //{"ai", luaopen_ai },
+ { 0, 0 }
+ };
+
+ // Register sub modules.
+ for (int i = 0; modules[i].name; ++i)
+ {
+ modules[i].func(L);
+ luax_setfield(L, -2, modules[i].name);
+ }
+
+ // Pop jin table.
+ luax_pop(L, 1);
+ }
+
+ LUA_EXPORT void boot(lua_State* L, const char* cwd)
+ {
+ luax_getglobal(L, MODULE_NAME);
+ luax_newtable(L);
+ luax_setfieldstring(L, "cwd", cwd);
+ luax_setfield(L, -2, "args");
+ luax_clearstack(L);
+ Embed::run(L);
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/je_lua_jin.h b/src/libjin-lua/je_lua_jin.h
new file mode 100644
index 0000000..7b38ce7
--- /dev/null
+++ b/src/libjin-lua/je_lua_jin.h
@@ -0,0 +1,36 @@
+/**
+* Copyright (C) 2016~2018 chai
+*/
+
+#ifndef __JIN_M_JIN_H__
+#define __JIN_M_JIN_H__
+
+#include "common/je_lua.h"
+#include "common/je_lua_common.h"
+
+#define MODULE_NAME "jin"
+#define CODE_NAME "Side Part"
+#define VERSION "0.1.1"
+#define REVISION_S "101"
+#define REVISION 101
+#define AUTHOR "chai"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ ///
+ /// open jin module.
+ ///
+ LUA_EXPORT void open(lua_State* L);
+
+ ///
+ /// Boot jin.
+ ///
+ LUA_EXPORT void boot(lua_State* L, const char* cwd);
+
+ } // namespace JinEngine
+} // namespace Lua
+
+#endif // __JIN_M_JIN_H__ \ No newline at end of file
diff --git a/src/libjin-lua/modules/ai/je_lua_ai.cpp b/src/libjin-lua/modules/ai/je_lua_ai.cpp
new file mode 100644
index 0000000..4afd625
--- /dev/null
+++ b/src/libjin-lua/modules/ai/je_lua_ai.cpp
@@ -0,0 +1,13 @@
+#include "libjin/jin.h"
+
+using namespace JinEngine::AI;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+
+
+ }
+} \ No newline at end of file
diff --git a/src/libjin-lua/modules/ai/je_lua_ai.h b/src/libjin-lua/modules/ai/je_lua_ai.h
new file mode 100644
index 0000000..9e1a8ae
--- /dev/null
+++ b/src/libjin-lua/modules/ai/je_lua_ai.h
@@ -0,0 +1,17 @@
+#ifndef __JE_LUA_AI_H__
+#define __JE_LUA_AI_H__
+
+#include "je_lua_behavior_tree.h"
+#include "je_lua_state_machine.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ int luaopen_ai(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/ai/je_lua_behavior_tree.cpp b/src/libjin-lua/modules/ai/je_lua_behavior_tree.cpp
new file mode 100644
index 0000000..20e8e55
--- /dev/null
+++ b/src/libjin-lua/modules/ai/je_lua_behavior_tree.cpp
@@ -0,0 +1,11 @@
+#include "libjin/jin.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ const char* Jin_Lua_BehaviorTree = "Texture";
+
+ }
+} \ No newline at end of file
diff --git a/src/libjin-lua/modules/ai/je_lua_behavior_tree.h b/src/libjin-lua/modules/ai/je_lua_behavior_tree.h
new file mode 100644
index 0000000..083d12b
--- /dev/null
+++ b/src/libjin-lua/modules/ai/je_lua_behavior_tree.h
@@ -0,0 +1,14 @@
+#ifndef __JE_LUA_BEHAVIOR_TREE_H__
+#define __JE_LUA_BEHAVIOR_TREE_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ extern const char* Jin_Lua_BehaviorTree;
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/ai/je_lua_state_machine.cpp b/src/libjin-lua/modules/ai/je_lua_state_machine.cpp
new file mode 100644
index 0000000..06338b8
--- /dev/null
+++ b/src/libjin-lua/modules/ai/je_lua_state_machine.cpp
@@ -0,0 +1,25 @@
+#include "common/je_lua_common.h"
+#include "libjin/jin.h"
+
+using namespace JinEngine::AI;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ const char* Jin_Lua_StateMachine = "StateMachine";
+
+ LUA_IMPLEMENT int l_addEnterCallback(lua_State* L)
+ {
+ //StateMachine* sm;
+ //sm->addEnterListener("", [](void* p) -> void{
+
+ //
+ //});
+
+ return 0;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/src/libjin-lua/modules/ai/je_lua_state_machine.h b/src/libjin-lua/modules/ai/je_lua_state_machine.h
new file mode 100644
index 0000000..3c78f75
--- /dev/null
+++ b/src/libjin-lua/modules/ai/je_lua_state_machine.h
@@ -0,0 +1,14 @@
+#ifndef __JE_LUA_STATE_MACHINE_H__
+#define __JE_LUA_STATE_MACHINE_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ extern const char* Jin_Lua_StateMachine;
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/audio/je_lua_audio.cpp b/src/libjin-lua/modules/audio/je_lua_audio.cpp
new file mode 100644
index 0000000..f5ef31f
--- /dev/null
+++ b/src/libjin-lua/modules/audio/je_lua_audio.cpp
@@ -0,0 +1,132 @@
+#include "common/je_lua.h"
+#include "common/je_lua_common.h"
+#include "libjin/jin.h"
+#include "je_lua_source.h"
+
+using namespace JinEngine::Audio;
+using namespace JinEngine::Audio::SDL;
+using namespace JinEngine::Filesystem;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ typedef SDLAudio Audio;
+ typedef SDLSource Source;
+
+ struct
+ {
+ bool initialized = false;
+ } context;
+
+ LUA_IMPLEMENT int l_init(lua_State* L)
+ {
+ if (context.initialized)
+ {
+ // Already initialized.
+ luax_pushboolean(L, true);
+ return 1;
+ }
+ Audio::Setting setting;
+ setting.samplerate = 44100;
+ setting.samples = 44100;
+ Audio* audio = Audio::get();
+ context.initialized = audio->start(&setting);
+ if (!context.initialized)
+ {
+ luax_error(L, "could not init audio");
+ luax_pushboolean(L, false);
+ return 1;
+ }
+ luax_pushboolean(L, true);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_play(lua_State* L)
+ {
+ Audio::get()->play();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_stop(lua_State* L)
+ {
+ Audio::get()->stop();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_pause(lua_State* L)
+ {
+ Audio::get()->pause();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_resume(lua_State* L)
+ {
+ Audio::get()->resume();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setVolume(lua_State* L)
+ {
+ float volume = luax_checknumber(L, 1);
+ Audio::get()->setVolume(volume);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_newSource(lua_State* L)
+ {
+ AssetDatabase* fs = AssetDatabase::get();
+ const char* f = luax_checkstring(L, 1);
+ Buffer b;
+ try
+ {
+ if (!fs->exists(f))
+ throw Exception("No such source file %s.", f);
+ fs->read(f, b);
+ }
+ catch (Exception& e)
+ {
+ error(L, "Failed to read source file %s", f);
+ luax_pushnil(L);
+ return 1;
+ }
+ Source* src = new SDLSource((void*)&b, b.size());
+ if (src == nullptr)
+ {
+ error(L, "Failed to decode source file %s", f);
+ luax_pushnil(L);
+ return 1;
+ }
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_Source, new Shared(src));
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_destroy(lua_State* L)
+ {
+ Audio* audio = Audio::get();
+ audio->quit();
+ return 0;
+ }
+
+ LUA_EXPORT int luaopen_audio(lua_State* L)
+ {
+ luaopen_Source(L);
+
+ luaL_Reg methods[] = {
+ { "init", l_init },
+ { "play", l_play },
+ { "stop", l_stop },
+ { "pause", l_pause },
+ { "resume", l_resume },
+ { "setVolume", l_setVolume },
+ { "newSource", l_newSource },
+ { "destroy", l_destroy },
+ { 0, 0 }
+ };
+ luax_newlib(L, methods);
+ return 1;
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/audio/je_lua_audio.h b/src/libjin-lua/modules/audio/je_lua_audio.h
new file mode 100644
index 0000000..6b4669a
--- /dev/null
+++ b/src/libjin-lua/modules/audio/je_lua_audio.h
@@ -0,0 +1,16 @@
+#ifndef __JE_LUA_AUDIO_H__
+#define __JE_LUA_AUDIO_H__
+
+#include "je_lua_audio.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ int luaopen_audio(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/audio/je_lua_source.cpp b/src/libjin-lua/modules/audio/je_lua_source.cpp
new file mode 100644
index 0000000..8c9e247
--- /dev/null
+++ b/src/libjin-lua/modules/audio/je_lua_source.cpp
@@ -0,0 +1,114 @@
+#include "libjin/jin.h"
+#include "common/je_lua.h"
+#include "common/je_lua_common.h"
+
+using namespace JinEngine::Audio;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ const char* Jin_Lua_Source = "Source";
+
+ LUA_IMPLEMENT inline Source* checkSource(lua_State* L)
+ {
+ LuaObject* luaObj = luax_checkobject(L, 1, Jin_Lua_Source);
+ Source* source = luaObj->getObject<Source>();
+ return source;
+ }
+
+ LUA_IMPLEMENT int l_play(lua_State* L)
+ {
+ Source* source = checkSource(L);
+ source->play();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_stop(lua_State* L)
+ {
+ Source* source = checkSource(L);
+ source->stop();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_pause(lua_State* L)
+ {
+ Source* source = checkSource(L);
+ source->pause();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_rewind(lua_State* L)
+ {
+ Source* source = checkSource(L);
+ source->rewind();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_resume(lua_State* L)
+ {
+ Source* source = checkSource(L);
+ source->resume();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_isStop(lua_State* L)
+ {
+ Source* source = checkSource(L);
+ bool isStop = source->isStopped();
+ luax_pushboolean(L, isStop);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_isPaused(lua_State* L)
+ {
+ Source* source = checkSource(L);
+ bool isPaused = source->isPaused();
+ luax_pushboolean(L, isPaused);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_setVolume(lua_State* L)
+ {
+ Source* source = checkSource(L);
+ float volume = luax_checknumber(L, 2);
+ source->setVolume(volume);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setLoop(lua_State* L)
+ {
+ Source* source = checkSource(L);
+ bool loop = luax_checkbool(L, 2);
+ source->setLoop(loop);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_gc(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Source);
+ luaObj->release();
+ return 0;
+ }
+
+ LUA_EXPORT void luaopen_Source(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "__gc", l_gc },
+ { "play", l_play },
+ { "stop", l_stop },
+ { "pause", l_pause },
+ { "resume", l_resume },
+ { "rewind", l_rewind },
+ { "isStop", l_isStop },
+ { "isPaused", l_isPaused },
+ { "setVolume", l_setVolume },
+ { "setLoop", l_setLoop },
+ { 0, 0 }
+ };
+ luax_newtype(L, Jin_Lua_Source, methods);
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/audio/je_lua_source.h b/src/libjin-lua/modules/audio/je_lua_source.h
new file mode 100644
index 0000000..f7e6b48
--- /dev/null
+++ b/src/libjin-lua/modules/audio/je_lua_source.h
@@ -0,0 +1,16 @@
+#ifndef __JE_LUA_SOURCE_H__
+#define __JE_LUA_SOURCE_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ extern const char* Jin_Lua_Source;
+
+ void luaopen_Source(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/bit/je_lua_bit.cpp b/src/libjin-lua/modules/bit/je_lua_bit.cpp
new file mode 100644
index 0000000..9484743
--- /dev/null
+++ b/src/libjin-lua/modules/bit/je_lua_bit.cpp
@@ -0,0 +1,86 @@
+#include "common/je_lua_common.h"
+#include "common/je_lua.h"
+#include "libjin/jin.h"
+
+#include <cstdlib>
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ LUA_IMPLEMENT int l_and(lua_State* L)
+ {
+ int a = luax_checkinteger(L, 1);
+ int b = luax_checkinteger(L, 2);
+ luax_pushinteger(L, a & b);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_or(lua_State* L)
+ {
+ int a = luax_checkinteger(L, 1);
+ int b = luax_checkinteger(L, 2);
+ luax_pushinteger(L, a | b);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_xor(lua_State* L)
+ {
+ int a = luax_checkinteger(L, 1);
+ int b = luax_checkinteger(L, 2);
+ luax_pushinteger(L, a ^ b);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_not(lua_State* L)
+ {
+ int n = luax_checkinteger(L, 1);
+ luax_pushinteger(L, ~n);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_lshift(lua_State* L)
+ {
+ int a = luax_checkinteger(L, 1);
+ int b = luax_checkinteger(L, 2);
+ luax_pushinteger(L, a << b);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_rshift(lua_State* L)
+ {
+ int a = luax_checkinteger(L, 1);
+ int b = luax_checkinteger(L, 2);
+ luax_pushinteger(L, a >> b);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_include(lua_State* L)
+ {
+ int a = luax_checkinteger(L, 1);
+ int b = luax_checkinteger(L, 2);
+ luax_pushboolean(L, (a & b) == b);
+ return 1;
+ }
+
+ LUA_EXPORT int luaopen_bit(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "bAnd", l_and },
+ { "bOr" , l_or },
+ { "bXor", l_xor },
+ { "bNot", l_not },
+ { "bLs", l_lshift },
+ { "bRs", l_rshift },
+ { "bInc", l_include },
+ { 0, 0 }
+ };
+
+ luax_newlib(L, methods);
+
+ return 1;
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/bit/je_lua_bit.h b/src/libjin-lua/modules/bit/je_lua_bit.h
new file mode 100644
index 0000000..21cf064
--- /dev/null
+++ b/src/libjin-lua/modules/bit/je_lua_bit.h
@@ -0,0 +1,14 @@
+#ifndef __JE_LUA_BIT_H__
+#define __JE_LUA_BIT_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ int luaopen_bit(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/core/je_lua_core.cpp b/src/libjin-lua/modules/core/je_lua_core.cpp
new file mode 100644
index 0000000..956ffbe
--- /dev/null
+++ b/src/libjin-lua/modules/core/je_lua_core.cpp
@@ -0,0 +1,46 @@
+#include "common/je_lua_common.h"
+#include "common/je_lua.h"
+#include "libjin/jin.h"
+
+using namespace JinEngine::Game;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ LUA_IMPLEMENT int l_running(lua_State* L)
+ {
+ static Application* app = Application::get();
+ bool running = app->running();
+ luax_pushboolean(L, running);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_stop(lua_State* L)
+ {
+ Application::get()->stop();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_quit(lua_State* L)
+ {
+ Application::get()->quit();
+ return 0;
+ }
+
+ LUA_EXPORT int luaopen_core(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "running", l_running },
+ { "stop", l_stop },
+ { "quit", l_quit },
+ { 0, 0 }
+ };
+ luax_newlib(L, methods);
+
+ return 1;
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/core/je_lua_core.h b/src/libjin-lua/modules/core/je_lua_core.h
new file mode 100644
index 0000000..037ac4b
--- /dev/null
+++ b/src/libjin-lua/modules/core/je_lua_core.h
@@ -0,0 +1,14 @@
+#ifndef __JE_LUA_CORE_H__
+#define __JE_LUA_CORE_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ int luaopen_core(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/event/je_lua_event.cpp b/src/libjin-lua/modules/event/je_lua_event.cpp
new file mode 100644
index 0000000..8a550d6
--- /dev/null
+++ b/src/libjin-lua/modules/event/je_lua_event.cpp
@@ -0,0 +1,130 @@
+/**
+* Event module
+*/
+#include "common/je_lua_common.h"
+#include "common/je_lua.h"
+#include "libjin/jin.h"
+
+using namespace JinEngine;
+using namespace JinEngine::Input;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ /**
+ * Load event poll, return a iterator(a table).
+ */
+ LUA_IMPLEMENT int l_event_poll(lua_State *L)
+ {
+ /* table to store events */
+ luax_newtable(L);
+ static Event e;
+ int i = 1;
+ poll:
+ while (pollEvent(&e))
+ {
+ /**
+ * TODO: ڴСıʱҪtransform
+ *
+ */
+ luax_newtable(L);
+ switch (e.type)
+ {
+ case EventType::QUIT:
+ luax_setfieldstring(L, "type", "Quit");
+ break;
+
+ case EventType::KEY_DOWN:
+ case EventType::KEY_UP:
+ luax_setfieldstring(L, "type", e.type == EventType::KEY_DOWN ? "KeyDown" : "KeyUp");
+ luax_setfieldstring(L, "key", getKeyName(e.key.keysym.sym));
+ break;
+
+ case EventType::MOUSE_MOTION:
+ luax_setfieldstring(L, "type", "MouseMotion");
+ luax_setfieldnumber(L, "x", e.motion.x);
+ luax_setfieldnumber(L, "y", e.motion.y);
+ break;
+
+ case EventType::MOUSE_BUTTON_DOWN:
+ case EventType::MOUSE_BUTTON_UP:
+ luax_setfieldstring(L, "type", e.type == EventType::MOUSE_BUTTON_DOWN ? "MouseButtonDown" : "MouseButtonUp");
+ luax_setfieldstring(L, "button", getButtonName(e.button.button));
+ luax_setfieldnumber(L, "x", e.button.x);
+ luax_setfieldnumber(L, "y", e.button.y);
+ break;
+
+ case EventType::MOUSE_WHEEL:
+ luax_setfieldstring(L, "type", "Wheel");
+ if(e.wheel.x == -1)
+ luax_setfieldstring(L, "x", "Left");
+ else if(e.wheel.x == 1)
+ luax_setfieldstring(L, "x", "Right");
+ else
+ luax_setfieldstring(L, "x", "None");
+ if (e.wheel.y == -1)
+ luax_setfieldstring(L, "y", "Near");
+ else if (e.wheel.y == 1)
+ luax_setfieldstring(L, "y", "Far");
+ else
+ luax_setfieldstring(L, "y", "None");
+ break;
+
+ case EventType::JOYBUTTONDOWN:
+ case EventType::JOYBUTTONUP:
+ luax_setfieldstring(L, "type", e.type == EventType::JOYBUTTONDOWN ? "JoyButtonDown" : "JoyButtonUp");
+ luax_setfieldinteger(L, "which", e.jbutton.which);
+ luax_setfieldstring(L, "button", Input::getJoyButtonName(e.jbutton.button));
+ break;
+
+ case EventType::JOYAXISMOTION:
+ luax_setfieldstring(L, "type", "JoyAxisMotion");
+ luax_setfieldinteger(L, "which", e.jaxis.which);
+ luax_setfieldfstring(L, "axis", Input::getJoyAxisName(e.jaxis.axis));
+ break;
+
+ case EventType::JOYBALLMOTION:
+ case EventType::JOYHATMOTION:
+
+ case EventType::JOYDEVICEADDED:
+ case EventType::JOYDEVICEREMOVED:
+ luax_setfieldfstring(L, "type", e.type == EventType::JOYDEVICEADDED ? "JoyDeviceAdded" : "JoyDeviceRemoved");
+ luax_setfieldinteger(L, "which", e.jdevice.which);
+ break;
+
+ //https://stackoverflow.com/questions/50022316/what-is-sdl-joystick-and-what-is-sdl-gamecontroller-what-are-the-relationships
+ case EventType::CONTROLLERBUTTONDOWN:
+ case EventType::CONTROLLERBUTTONUP:
+
+
+ case EventType::CONTROLLERAXISMOTION:
+
+ default:
+ // Ignore oter events and pop up the event table.
+ luax_pop(L, 1);
+ goto poll;
+ break;
+ }
+ luax_rawseti(L, -2, i++);
+ }
+ return 1;
+ }
+
+ /**
+ * load event module
+ */
+ LUA_EXPORT int luaopen_event(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "poll", l_event_poll },
+ { 0, 0 }
+ };
+ luax_newlib(L, methods);
+
+ return 1;
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/event/je_lua_event.h b/src/libjin-lua/modules/event/je_lua_event.h
new file mode 100644
index 0000000..7a75459
--- /dev/null
+++ b/src/libjin-lua/modules/event/je_lua_event.h
@@ -0,0 +1,14 @@
+#ifndef __JE_LUA_EVENT_H__
+#define __JE_LUA_EVENT_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ int luaopen_event(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/filesystem/je_lua_filesystem.cpp b/src/libjin-lua/modules/filesystem/je_lua_filesystem.cpp
new file mode 100644
index 0000000..e73d1ad
--- /dev/null
+++ b/src/libjin-lua/modules/filesystem/je_lua_filesystem.cpp
@@ -0,0 +1,140 @@
+#include "common/je_lua_common.h"
+#include "common/je_lua.h"
+#include "libjin/jin.h"
+#include <string>
+
+using namespace JinEngine::Filesystem;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ LUA_IMPLEMENT struct
+ {
+ AssetDatabase* fs;
+ } context;
+
+ LUA_IMPLEMENT int l_init(lua_State* L)
+ {
+ context.fs = AssetDatabase::get();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_mount(lua_State* L)
+ {
+ const char* path = luax_checkstring(L, 1);
+ context.fs->mount(path);
+ return 0;
+ }
+
+ LUA_IMPLEMENT 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;
+ }
+
+ LUA_IMPLEMENT 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;
+ }
+
+ LUA_IMPLEMENT int l_isFile(lua_State* L)
+ {
+ const char* path = luax_checkstring(L, 1);
+ int r = context.fs->isFile(path);
+ luax_pushboolean(L, r);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int loadbuffer(lua_State* L)
+ {
+ const char* filename = lua_tostring(L, -1);
+ Buffer bf;
+ context.fs->read(filename, bf);
+ luax_loadbuffer(L, (const char*)&bf, bf.size(), filename);
+ return 1;
+ }
+
+ LUA_IMPLEMENT 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] = '/';
+ }
+ }
+
+ if (context.fs->exists(tmp.c_str()))
+ {
+ lua_pop(L, 1);
+ lua_pushstring(L, tmp.c_str());
+ return loadbuffer(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());
+ return loadbuffer(L);
+ }
+ }
+
+ lua_pushfstring(L, "\n\tno file \"%s\" in jin game directories.\n", (tmp + ".lua").c_str());
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_read(lua_State* L)
+ {
+ AssetDatabase* fs = context.fs;
+ const char* file = luax_checkstring(L, 1);
+ unsigned int len;
+ Buffer buffer;
+ fs->read(file, buffer);
+ luax_pushstring(L, (char*)&buffer);
+ luax_pushinteger(L, buffer.size());
+ return 2;
+ }
+
+ LUA_EXPORT int luaopen_filesystem(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "init", l_init },
+ { "mount", l_mount },
+ { "isDirectory", l_isDir },
+ { "isFile", l_isFile },
+ { "exist", l_exist },
+ { "read", l_read },
+ { 0, 0 }
+ };
+ luax_newlib(L, methods);
+ luax_registersearcher(L, loader, 1);
+ return 0;
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/filesystem/je_lua_filesystem.h b/src/libjin-lua/modules/filesystem/je_lua_filesystem.h
new file mode 100644
index 0000000..1e1ff23
--- /dev/null
+++ b/src/libjin-lua/modules/filesystem/je_lua_filesystem.h
@@ -0,0 +1,14 @@
+#ifndef __JE_LUA_FILESYSTEM_H__
+#define __JE_LUA_FILESYSTEM_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ int luaopen_filesystem(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_animation.cpp b/src/libjin-lua/modules/graphics/je_lua_animation.cpp
new file mode 100644
index 0000000..5cd3b1f
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_animation.cpp
@@ -0,0 +1,122 @@
+#include "libjin/jin.h"
+
+#include "common/je_lua_object.h"
+#include "common/je_lua_common.h"
+
+#include "je_lua_sprite.h"
+#include "je_lua_canvas.h"
+#include "je_lua_texture.h"
+#include "je_lua_shader.h"
+#include "je_lua_animation.h"
+
+using namespace JinEngine::Math;
+using namespace JinEngine::Graphics;
+using namespace JinEngine::Graphics::Shaders;
+using namespace JinEngine::Graphics::Animations;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+ const char* Jin_Lua_Animation = "Animation";
+
+ LUA_IMPLEMENT inline Animation* checkAnimation(lua_State* L)
+ {
+ LuaObject* luaObj = luax_checkobject(L, 1, Jin_Lua_Animation);
+ return luaObj->getObject<Animation>();
+ }
+
+ LUA_IMPLEMENT int l_gc(lua_State* L)
+ {
+ LuaObject* p = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Animation);
+ p->release();
+ return 0;
+ }
+
+ // addFrame(frame)
+ LUA_IMPLEMENT int l_addFrame(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Animation);
+ Animation* animation = luaObj->getObject<Animation>();
+ LuaObject* luaSprite = (LuaObject*)luax_checktype(L, 2, Jin_Lua_Sprite);
+ Sprite* sprite = luaSprite->getObject<Sprite>();
+ animation->addFrame(sprite);
+ int i = animation->getFrameCount() - 1;
+ luaObj->setDependency((int)AnimationDependency::DEP_SPRITES + i, luaSprite);
+ return 0;
+ }
+
+ // addFrames(frames table)
+ LUA_IMPLEMENT int l_addFrames(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Animation);
+ Animation* shrAnimation = luaObj->getObject<Animation>();
+ if (!luax_istable(L, 2))
+ {
+ luax_typerror(L, 2, "sprites table");
+ return 1;
+ }
+ int n = luax_tableidxlen(L, 2);
+ for (int i = 1; i <= n; ++i)
+ {
+ luax_rawgeti(L, 2, i);
+ LuaObject* luaSprite = (LuaObject*)luax_checktype(L, -1, Jin_Lua_Sprite);
+ Sprite* sprite = luaSprite->getObject<Sprite>();
+ shrAnimation->addFrame(sprite);
+ int index = shrAnimation->getFrameCount() - 1;
+ luaObj->setDependency((int)AnimationDependency::DEP_SPRITES + index, luaSprite);
+ }
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_isLoop(lua_State* L)
+ {
+ Animation* shrAnimation = checkAnimation(L);
+ bool loop = shrAnimation->isLoop();
+ luax_pushboolean(L, loop);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_getSpeed(lua_State* L)
+ {
+ Animation* shrAnimation = checkAnimation(L);
+ float speed = shrAnimation->getSpeed();
+ luax_pushnumber(L, speed);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_getFrame(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Animation);
+ Animation* shrAnimation = luaObj->getObject<Animation>();
+ int i = luax_checkinteger(L, 2);
+ LuaObject* frame = luaObj->getDependency((int)AnimationDependency::DEP_SPRITES + i);
+ luax_getobject(L, frame);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int getFrameCount(lua_State* L)
+ {
+ Animation* shrAnimation = checkAnimation(L);
+ int n = shrAnimation->getFrameCount();
+ luax_pushinteger(L, n);
+ return 1;
+ }
+
+ LUA_EXPORT void luaopen_Animation(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "__gc", l_gc },
+ { "addFrame", l_addFrame },
+ { "addFrames", l_addFrames },
+ { "isLoop", l_isLoop },
+ { "getSpeed", l_getSpeed },
+ { "getFrameCount", getFrameCount },
+ { "getFrame", l_getFrame },
+ { 0, 0 }
+ };
+ luax_newtype(L, Jin_Lua_Animation, methods);
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_animation.h b/src/libjin-lua/modules/graphics/je_lua_animation.h
new file mode 100644
index 0000000..1b32ec3
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_animation.h
@@ -0,0 +1,24 @@
+#ifndef __JE_LUA_ANIMATION_H__
+#define __JE_LUA_ANIMATION_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ extern const char* Jin_Lua_Animation;
+
+ ///
+ ///
+ ///
+ enum class AnimationDependency
+ {
+ DEP_SPRITES = 1 ///< Index from 1
+ };
+
+ void luaopen_Animation(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_animator.cpp b/src/libjin-lua/modules/graphics/je_lua_animator.cpp
new file mode 100644
index 0000000..94c61b5
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_animator.cpp
@@ -0,0 +1,163 @@
+#include "common/je_lua_object.h"
+#include "common/je_lua_common.h"
+#include "libjin/jin.h"
+
+#include "je_lua_sprite.h"
+#include "je_lua_canvas.h"
+#include "je_lua_texture.h"
+#include "je_lua_shader.h"
+#include "je_lua_animator.h"
+#include "je_lua_animation.h"
+
+using namespace JinEngine::Math;
+using namespace JinEngine::Graphics;
+using namespace JinEngine::Graphics::Shaders;
+using namespace JinEngine::Graphics::Animations;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+ const char* Jin_Lua_Animator = "Animator";
+
+ LUA_IMPLEMENT inline Animator* checkAnimator(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Animator);
+ return luaObj->getObject<Animator>();
+ }
+
+ LUA_IMPLEMENT int l_gc(lua_State* L)
+ {
+ LuaObject* obj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Animation);
+ obj->release();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_update(lua_State* L)
+ {
+ Animator* animator = checkAnimator(L);
+ float dt = luax_checknumber(L, 2);
+ animator->update(dt);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_play(lua_State* L)
+ {
+ Animator* animator = checkAnimator(L);
+ animator->play();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_pause(lua_State* L)
+ {
+ Animator* animator = checkAnimator(L);
+ animator->pause();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_resume(lua_State* L)
+ {
+ Animator* animator = checkAnimator(L);
+ animator->resume();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_rewind(lua_State* L)
+ {
+ Animator* animator = checkAnimator(L);
+ animator->rewind();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_render(lua_State* L)
+ {
+ Animator* animator = checkAnimator(L);
+ 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);
+ animator->render(x, y, sx, sy, r);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setAnimation(lua_State* L)
+ {
+ LuaObject* luaAnimator = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Animator);
+ Animator* animator = luaAnimator->getObject<Animator>();
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Animation);
+ luaAnimator->setDependency((int)AnimatorDependency::DEP_ANIMATION, luaObj);
+ animator->setAnimation(luaObj->getObject<Animation>());
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_forceToFrame(lua_State* L)
+ {
+ Animator* shrAnimator = checkAnimator(L);
+ int index = luax_checkinteger(L, 2);
+ shrAnimator->forceToFrame(index);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setSpeed(lua_State* L)
+ {
+ Animator* shrAnimator = checkAnimator(L);
+ float fps = luax_checknumber(L, 2);
+ shrAnimator->setSpeed(fps);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setDefaultSpeed(lua_State* L)
+ {
+ Animator* shrAnimator = checkAnimator(L);
+ shrAnimator->setDefaultSpeed();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setLoop(lua_State* L)
+ {
+ Animator* shrAnimator = checkAnimator(L);
+ bool loop = luax_checkbool(L, 2);
+ shrAnimator->setLoop(loop);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setDefaultLoop(lua_State* L)
+ {
+ Animator* shrAnimator = checkAnimator(L);
+ shrAnimator->setDefaultLoop();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_getSpeed(lua_State* L)
+ {
+ Animator* shrAnimator = checkAnimator(L);
+ float speed = shrAnimator->getSpeed();
+ luax_pushnumber(L, speed);
+ return 1;
+ }
+
+ LUA_EXPORT void luaopen_Animator(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "__gc", l_gc },
+ { "update", l_update },
+ { "play", l_play },
+ { "pause", l_pause },
+ { "resume", l_resume },
+ { "rewind", l_rewind },
+ { "render", l_render },
+ { "setAnimation", l_setAnimation },
+ { "forceToFrame", l_forceToFrame },
+ { "setSpeed", l_setSpeed },
+ { "setDefaultSpeed", l_setDefaultSpeed },
+ { "setLoop", l_setLoop },
+ { "setDefaultLoop", l_setDefaultLoop },
+ { "getSpeed", l_getSpeed },
+ { 0, 0 }
+ };
+ luax_newtype(L, Jin_Lua_Animator, methods);
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_animator.h b/src/libjin-lua/modules/graphics/je_lua_animator.h
new file mode 100644
index 0000000..0292a77
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_animator.h
@@ -0,0 +1,23 @@
+#ifndef __JE_LUA_ANIMATOR_H__
+#define __JE_LUA_ANIMATOR_H__
+
+#include "libjin/jin.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ extern const char* Jin_Lua_Animator;
+
+ enum class AnimatorDependency
+ {
+ DEP_ANIMATION = 1
+ };
+
+ void luaopen_Animator(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_bitmap.cpp b/src/libjin-lua/modules/graphics/je_lua_bitmap.cpp
new file mode 100644
index 0000000..553c786
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_bitmap.cpp
@@ -0,0 +1,110 @@
+#include "common/je_lua_common.h"
+#include "common/je_lua_object.h"
+
+#include "libjin/jin.h"
+#include "je_lua_bitmap.h"
+
+using namespace JinEngine::Graphics;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ const char* Jin_Lua_Bitmap = "Bitmap";
+
+ LUA_IMPLEMENT inline Bitmap* checkBitmap(lua_State* L)
+ {
+ LuaObject* luaObj = luax_checkobject(L, 1, Jin_Lua_Bitmap);
+ return luaObj->getObject<Bitmap>();
+ }
+
+ LUA_IMPLEMENT int l_gc(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Bitmap);
+ luaObj->release();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_getWidth(lua_State* L)
+ {
+ Bitmap* bitmap = checkBitmap(L);
+ int w = bitmap->getWidth();
+ luax_pushinteger(L, w);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_getHeight(lua_State* L)
+ {
+ Bitmap* bitmap = checkBitmap(L);
+ int h = bitmap->getHeight();
+ luax_pushinteger(L, h);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_getSize(lua_State* L)
+ {
+ Bitmap* bitmap = checkBitmap(L);
+ int w = bitmap->getWidth();
+ int h = bitmap->getHeight();
+ luax_pushinteger(L, w);
+ luax_pushinteger(L, h);
+ return 2;
+ }
+
+ LUA_IMPLEMENT int l_getPixel(lua_State* L)
+ {
+ Bitmap* bitmap = checkBitmap(L);
+ int x = luax_checkinteger(L, 2);
+ int y = luax_checkinteger(L, 3);
+ Color col = bitmap->getPixel(x, y);
+ luax_pushinteger(L, col.r);
+ luax_pushinteger(L, col.g);
+ luax_pushinteger(L, col.b);
+ luax_pushinteger(L, col.a);
+ return 4;
+ }
+
+ LUA_IMPLEMENT int l_setPixel(lua_State* L)
+ {
+ Bitmap* bitmap = checkBitmap(L);
+ int x = luax_checkinteger(L, 2);
+ int y = luax_checkinteger(L, 3);
+ if (!luax_istable(L, 4))
+ {
+ luax_typerror(L, 4, "table");
+ return 1;
+ }
+ unsigned int r = luax_rawgetnumber(L, 4, 1);
+ unsigned int g = luax_rawgetnumber(L, 4, 2);
+ unsigned int b = luax_rawgetnumber(L, 4, 3);
+ unsigned int a = luax_rawgetnumber(L, 4, 4);
+ bitmap->setPixel(Color(r, g, b, a), x, y);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_clone(lua_State* L)
+ {
+ Bitmap* bitmap = checkBitmap(L);
+ Bitmap* b = bitmap->clone();
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_Bitmap, new Shared(b));
+ return 1;
+ }
+
+ LUA_EXPORT void luaopen_Bitmap(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "__gc", l_gc },
+ { "getWidth", l_getWidth },
+ { "getHeight", l_getHeight },
+ { "getSize", l_getSize },
+ { "getPixel", l_getPixel },
+ { "setPixel", l_setPixel },
+ { "clone", l_clone },
+ { 0, 0 }
+ };
+ luax_newtype(L, Jin_Lua_Bitmap, methods);
+ }
+
+ } // namespace Graphics
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_bitmap.h b/src/libjin-lua/modules/graphics/je_lua_bitmap.h
new file mode 100644
index 0000000..b463d83
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_bitmap.h
@@ -0,0 +1,16 @@
+#ifndef __JE_LUA_BITMAP_H__
+#define __JE_LUA_BITMAP_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ extern const char* Jin_Lua_Bitmap;
+
+ void luaopen_Bitmap(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_canvas.cpp b/src/libjin-lua/modules/graphics/je_lua_canvas.cpp
new file mode 100644
index 0000000..97b3c96
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_canvas.cpp
@@ -0,0 +1,63 @@
+#include "common/je_lua_object.h"
+#include "common/je_lua_common.h"
+#include "libjin/jin.h"
+#include "je_lua_canvas.h"
+
+using namespace JinEngine::Graphics;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ const char* Jin_Lua_Canvas = "Canvas";
+
+ LUA_IMPLEMENT inline Canvas* checkCanvas(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Canvas);
+ return luaObj->getObject<Canvas>();
+ }
+
+ LUA_IMPLEMENT int l_getWidth(lua_State* L)
+ {
+ Canvas* canvas = checkCanvas(L);
+ luax_pushnumber(L, canvas->getWidth());
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_getHeight(lua_State* L)
+ {
+ Canvas* canvas = checkCanvas(L);
+ luax_pushnumber(L, canvas->getHeight());
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_getSize(lua_State* L)
+ {
+ Canvas* canvas = checkCanvas(L);
+ luax_pushnumber(L, canvas->getWidth());
+ luax_pushnumber(L, canvas->getHeight());
+ return 2;
+ }
+
+ LUA_IMPLEMENT int l_gc(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Canvas);
+ luaObj->release();
+ return 0;
+ }
+
+ LUA_EXPORT void luaopen_Canvas(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "__gc", l_gc },
+ { "getWidth", l_getWidth },
+ { "getHeight", l_getHeight },
+ { "getSize", l_getSize },
+ { 0, 0 }
+ };
+ luax_newtype(L, Jin_Lua_Canvas, methods);
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_canvas.h b/src/libjin-lua/modules/graphics/je_lua_canvas.h
new file mode 100644
index 0000000..d1fa885
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_canvas.h
@@ -0,0 +1,16 @@
+#ifndef __JE_LUA_CANVAS_H__
+#define __JE_LUA_CANVAS_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ extern const char* Jin_Lua_Canvas;
+
+ void luaopen_Canvas(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_graphics.cpp b/src/libjin-lua/modules/graphics/je_lua_graphics.cpp
new file mode 100644
index 0000000..fba77d7
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_graphics.cpp
@@ -0,0 +1,1048 @@
+#include <iostream>
+#include <fstream>
+
+#include "libjin/jin.h"
+#include "common/je_lua_object.h"
+#include "common/je_lua_common.h"
+
+#include "je_lua_canvas.h"
+#include "je_lua_sprite.h"
+#include "je_lua_spritesheet.h"
+#include "je_lua_bitmap.h"
+#include "je_lua_ttf.h"
+#include "je_lua_ttf_data.h"
+#include "je_lua_texture.h"
+#include "je_lua_shader.h"
+#include "je_lua_text.h"
+#include "je_lua_texture_font.h"
+#include "je_lua_page.h"
+#include "je_lua_sprite.h"
+#include "je_lua_animation.h"
+#include "je_lua_animator.h"
+#include "je_lua_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)
+ {
+ error(L, "Failed to read image %s", f);
+ luax_pushnil(L);
+ return 1;
+ }
+ bitmap = new Bitmap(&b, b.size());
+ if (bitmap == nullptr)
+ {
+ error(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;
+ }
+
+ LUA_IMPLEMENT int l_newShader(lua_State* L)
+ {
+ const char* program = luax_checkstring(L, 1);
+ Shader* jsl = new Shader(program);
+ if (jsl == nullptr)
+ {
+ error(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_newShaderf(lua_State* L)
+ {
+ const char* path = luax_checkstring(L, 1);
+ AssetDatabase* fs = AssetDatabase::get();
+ if (!fs->exists(path))
+ {
+ error(L, "No such shader file \"%s\"", path);
+ luax_pushnil(L);
+ return 1;
+ }
+ Buffer b;
+ fs->read(path, b);
+ Shader* jsl = new Shader((char*)&b);
+ if (jsl == nullptr)
+ {
+ error(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()->swapBuffers();
+ 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 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
+ {
+ 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");
+ }
+ }
+
+ /* 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_setBlend(lua_State* L)
+ {
+
+ return 0;
+ }
+
+ 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))
+ {
+ error(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;
+ }
+
+ /* 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_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);
+
+ luaL_Reg methods[] = {
+ /* 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 },
+ /* 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 },
+ /* 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
diff --git a/src/libjin-lua/modules/graphics/je_lua_graphics.h b/src/libjin-lua/modules/graphics/je_lua_graphics.h
new file mode 100644
index 0000000..02a2c63
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_graphics.h
@@ -0,0 +1,14 @@
+#ifndef __JE_LUA_GRAPHICS_H__
+#define __JE_LUA_GRAPHICS_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ int luaopen_graphics(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_page.cpp b/src/libjin-lua/modules/graphics/je_lua_page.cpp
new file mode 100644
index 0000000..5a312e2
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_page.cpp
@@ -0,0 +1,66 @@
+#include <iostream>
+
+#include "common/je_lua_object.h"
+#include "common/je_lua_common.h"
+#include "libjin/jin.h"
+
+using namespace JinEngine::Graphics;
+using namespace JinEngine::Graphics::Fonts;
+using namespace JinEngine::Graphics::Shaders;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ const char* Jin_Lua_Page = "Page";
+
+ Page* getPage(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Page);
+ return luaObj->getObject<Page>();
+ }
+
+ LUA_IMPLEMENT int l_gc(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Page);
+ luaObj->release();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_getSize(lua_State* L)
+ {
+ Page* page = getPage(L);
+ luax_pushinteger(L, page->size.w);
+ luax_pushinteger(L, page->size.h);
+ return 2;
+ }
+
+ LUA_IMPLEMENT int l_getWidth(lua_State* L)
+ {
+ Page* page = getPage(L);
+ luax_pushinteger(L, page->size.w);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_getHeight(lua_State* L)
+ {
+ Page* page = getPage(L);
+ luax_pushinteger(L, page->size.h);
+ return 1;
+ }
+
+ LUA_EXPORT void luaopen_Page(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "__gc", l_gc },
+ { "getSize", l_getSize },
+ { "getWidth", l_getWidth },
+ { "getHeight", l_getHeight },
+ { 0, 0 }
+ };
+ luax_newtype(L, Jin_Lua_Page, methods);
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_page.h b/src/libjin-lua/modules/graphics/je_lua_page.h
new file mode 100644
index 0000000..e4a21a3
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_page.h
@@ -0,0 +1,22 @@
+#ifndef __JE_LUA_PAGE_H__
+#define __JE_LUA_PAGE_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ enum class PageDependency
+ {
+ DEP_TTF = 1,
+ DEP_TEXTURE_FONT = 2,
+ };
+
+ extern const char* Jin_Lua_Page;
+
+ void luaopen_Page(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_particle_system.cpp b/src/libjin-lua/modules/graphics/je_lua_particle_system.cpp
new file mode 100644
index 0000000..0c42209
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_particle_system.cpp
@@ -0,0 +1,422 @@
+#include <vector>
+
+#include "common/je_lua_object.h"
+#include "common/je_lua_common.h"
+#include "libjin/jin.h"
+
+#include "je_lua_sprite.h"
+#include "je_lua_particle_system.h"
+
+using namespace std;
+using namespace JinEngine::Math;
+using namespace JinEngine::Graphics;
+using namespace JinEngine::Graphics::Particles;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ const char* Jin_Lua_ParticleSystem = "ParticleSystem";
+
+ LUA_IMPLEMENT inline ParticleSystem* checkPS(lua_State* L)
+ {
+ LuaObject* luaObj = luax_checkobject(L, 1, Jin_Lua_ParticleSystem);
+ return luaObj->getObject<ParticleSystem>();
+ }
+
+ LUA_IMPLEMENT int l_gc(lua_State* L)
+ {
+ LuaObject* luaObj = luax_checkobject(L, 1, Jin_Lua_ParticleSystem);
+ luaObj->release();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_update(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ float dt = luax_checknumber(L, 2);
+ ps->update(dt);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_render(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ ps->render();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setPosition(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ float x = luax_checknumber(L, 2);
+ float y = luax_checknumber(L, 3);
+ ps->setPosition(x, y);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setScale(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ float sx = luax_checknumber(L, 2);
+ float sy = luax_checknumber(L, 3);
+ //ps->setScale(sx, sy);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_pause(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ bool b = luax_checkbool(L, 2);
+ //ps->pause(b);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_clear(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ //ps->clear();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setEmitRate(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ if (luax_gettop(L) >= 3)
+ {
+ float floor = luax_checknumber(L, 2);
+ float ceil = luax_checknumber(L, 3);
+ ps->setEmitRate(floor, ceil);
+ }
+ else if (luax_gettop(L) >= 2)
+ {
+ float n = luax_checknumber(L, 2);
+ ps->setEmitRate(n);
+ }
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setEmitForce(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ if (luax_gettop(L) >= 3)
+ {
+ float floor = luax_checknumber(L, 2);
+ float ceil = luax_checknumber(L, 3);
+ ps->setEmitForce(floor, ceil);
+ }
+ else if (luax_gettop(L) >= 2)
+ {
+ float n = luax_checknumber(L, 2);
+ ps->setEmitForce(n);
+ }
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setEmitDirection(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ if (luax_gettop(L) >= 3)
+ {
+ float floor = luax_checknumber(L, 2);
+ float ceil = luax_checknumber(L, 3);
+ ps->setEmitDirection(floor, ceil);
+ }
+ else if (luax_gettop(L) >= 2)
+ {
+ float n = luax_checknumber(L, 2);
+ ps->setEmitDirection(n);
+ }
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setEmitPosition(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ if (luax_gettop(L) >= 3)
+ {
+ if (!luax_istable(L, 2))
+ {
+ luax_typerror(L, 2, "table");
+ return 1;
+ }
+ if (!luax_istable(L, 3))
+ {
+ luax_typerror(L, 3, "table");
+ return 1;
+ }
+ Vector2<float> floor, ceil;
+ floor.x = luax_rawgetnumber(L, 2, 1);
+ floor.y = luax_rawgetnumber(L, 2, 2);
+ ceil.x = luax_rawgetnumber(L, 3, 1);
+ ceil.y = luax_rawgetnumber(L, 3, 2);
+ ps->setEmitPosition(floor, ceil);
+ }
+ else if (luax_gettop(L) >= 2)
+ {
+ if (!luax_istable(L, 2))
+ {
+ luax_typerror(L, 2, "table");
+ return 1;
+ }
+ Vector2<float> pos;
+ pos.x = luax_rawgetnumber(L, 2, 1);
+ pos.y = luax_rawgetnumber(L, 2, 2);
+ ps->setEmitPosition(pos);
+ }
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setParticleLife(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ if (luax_gettop(L) >= 3)
+ {
+ float floor = luax_checknumber(L, 2);
+ float ceil = luax_checknumber(L, 3);
+ ps->setParticleLife(floor, ceil);
+ }
+ else if (luax_gettop(L) >= 2)
+ {
+ float n = luax_checknumber(L, 2);
+ ps->setParticleLife(n);
+ }
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setParticleLinearAccelaration(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ if (!luax_istable(L, 2))
+ {
+ luax_typerror(L, 2, "table");
+ return 1;
+ }
+ Vector2<float> ac;
+ ac.x = luax_rawgetnumber(L, 2, 1);
+ ac.y = luax_rawgetnumber(L, 2, 2);
+ ps->setParticleLinearAccelaration(ac);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setParticleRadialAccelaration(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ float ra = luax_checknumber(L, 2);
+ ps->setParticleRadialAccelaration(ra);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setParticleAngularSpeed(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ if (luax_gettop(L) >= 3)
+ {
+ float floor = luax_checknumber(L, 2);
+ float ceil = luax_checknumber(L, 3);
+ ps->setParticleAngularSpeed(floor, ceil);
+ }
+ else if (luax_gettop(L) >= 2)
+ {
+ float n = luax_checknumber(L, 2);
+ ps->setParticleAngularSpeed(n);
+ }
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setParticleSpritesMode(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ int n = luax_checkinteger(L, 2);
+ SpriteMode mode = static_cast<SpriteMode>(n);
+ ps->setParticleSpritesMode(mode);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_addParticleSprite(lua_State* L)
+ {
+ LuaObject* obj = luax_checkobject(L, 1, Jin_Lua_ParticleSystem);
+ ParticleSystem* ps = obj->getObject<ParticleSystem>();
+ LuaObject* objSpr = luax_checkobject(L, 2, Jin_Lua_Sprite);
+ Sprite* spr = objSpr->getObject<Sprite>();
+ ps->addParticleSprite(spr);
+ int depn = (*obj).getDependenciesCount();
+ (*obj).setDependency((int)ParticleSystemDependency::DEP_SPRITES + depn, objSpr);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_addParticleSprites(lua_State* L)
+ {
+ LuaObject* obj = luax_checkobject(L, 1, Jin_Lua_ParticleSystem);
+ ParticleSystem* ps = obj->getObject<ParticleSystem>();
+ if (!luax_istable(L, 2))
+ {
+ luax_typerror(L, 2, "sprites table");
+ return 1;
+ }
+ int n = luax_tableidxlen(L, 2);
+ int depn = (*obj).getDependenciesCount();
+ for (int i = 1; i <= n; ++i)
+ {
+ luax_rawgeti(L, 2, i);
+ LuaObject* objSpr = luax_checkobject(L, -1, Jin_Lua_Sprite);
+ luax_pop(L, 1);
+ Sprite* spr = objSpr->getObject<Sprite>();
+ ps->addParticleSprite(spr);
+ (*obj).setDependency((int)ParticleSystemDependency::DEP_SPRITES + depn + i - 1, objSpr);
+ }
+ return 0;
+ }
+
+ // From 0
+ LUA_IMPLEMENT int l_removeParticleSprite(lua_State* L)
+ {
+ LuaObject* obj = luax_checkobject(L, 1, Jin_Lua_ParticleSystem);
+ ParticleSystem* ps = obj->getObject<ParticleSystem>();
+ int n = luax_checkinteger(L, 2);
+ ps->removeParticleSprite(n);
+ (*obj).removeDependency((int)ParticleSystemDependency::DEP_SPRITES + n);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_enableParticleBlendAdditive(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ bool enable = luax_checkbool(L, 2);
+ ps->enableParticleBlendAdditive(enable);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setParticleScale(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ float scale = luax_checknumber(L, 2);
+ ps->setParticleScale(scale);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_addParticleScalePoint(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ float scale = luax_checknumber(L, 2);
+ float t = luax_checknumber(L, 3);
+ ps->addParticleScalePoint(scale, t);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_removeParticleScalePoint(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ int i = luax_checkinteger(L, 2);
+ ps->removeParticleScalePoint(i);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setParticleColor(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ if (!luax_istable(L, 2))
+ {
+ luax_typerror(L, 2, "color table");
+ return 1;
+ }
+ Color c;
+ c.r = luax_rawgetnumber(L, 2, 1);
+ c.g = luax_rawgetnumber(L, 2, 2);
+ c.b = luax_rawgetnumber(L, 2, 3);
+ c.a = luax_rawgetnumber(L, 2, 4);
+ ps->setParticleColor(c);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_addParticleColorPoint(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ if (!luax_istable(L, 2))
+ {
+ luax_typerror(L, 2, "color table");
+ return 1;
+ }
+ Color c;
+ c.r = luax_rawgetnumber(L, 2, 1);
+ c.g = luax_rawgetnumber(L, 2, 2);
+ c.b = luax_rawgetnumber(L, 2, 3);
+ c.a = luax_rawgetnumber(L, 2, 4);
+ float t = luax_checknumber(L, 3);
+ ps->addParticleColorPoint(c, t);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_removeParticleColorPoint(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ int i = luax_checkinteger(L, 2);
+ ps->removeParticleColorPoint(i);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_setParticleTransparency(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ float transparency = luax_checknumber(L, 2);
+ ps->setParticleTransparency(transparency);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_addParticleTransparencyPoint(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ float transparency = luax_checknumber(L, 2);
+ float t = luax_checknumber(L, 3);
+ ps->addParticleTransparencyPoint(transparency, t);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_removeParticleTransparencyPoint(lua_State* L)
+ {
+ ParticleSystem* ps = checkPS(L);
+ int i = luax_checkinteger(L, 2);
+ ps->removeParticleTransparencyPoint(i);
+ return 0;
+ }
+
+ LUA_EXPORT void luaopen_ParticleSystem(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "__gc", l_gc },
+ { "update", l_update },
+ { "render", l_render },
+ { "setPosition", l_setPosition },
+ { "setScale", l_setScale },
+ { "pause", l_pause },
+ { "clear", l_clear },
+ { "setEmitRate", l_setEmitRate },
+ { "setEmitForce", l_setEmitForce },
+ { "setEmitDirection", l_setEmitDirection },
+ { "setEmitPosition", l_setEmitPosition },
+ { "setParticleLife", l_setParticleLife },
+ { "setParticleLinearAccelaration", l_setParticleLinearAccelaration },
+ { "setParticleRadialAccelaration", l_setParticleRadialAccelaration },
+ { "setParticleAngularSpeed", l_setParticleAngularSpeed },
+ { "setParticleSpritesMode", l_setParticleSpritesMode },
+ { "addParticleSprite", l_addParticleSprite },
+ { "addParticleSprites", l_addParticleSprites },
+ { "removeParticleSprite", l_removeParticleSprite },
+ { "enableParticleBlendAdditive", l_enableParticleBlendAdditive },
+ { "setParticleScale", l_setParticleScale },
+ { "addParticleScalePoint", l_addParticleScalePoint },
+ { "removeParticleScalePoint", l_removeParticleScalePoint },
+ { "setParticleColor", l_setParticleColor },
+ { "addParticleColorPoint", l_addParticleColorPoint },
+ { "removeParticleColorPoint", l_removeParticleColorPoint },
+ { "setParticleTransparency", l_setParticleTransparency },
+ { "addParticleTransparencyPoint", l_addParticleTransparencyPoint },
+ { "removeParticleTransparencyPoint", l_removeParticleTransparencyPoint },
+ { 0, 0 }
+ };
+ luax_newtype(L, Jin_Lua_ParticleSystem, methods);
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_particle_system.h b/src/libjin-lua/modules/graphics/je_lua_particle_system.h
new file mode 100644
index 0000000..b75b569
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_particle_system.h
@@ -0,0 +1,21 @@
+#ifndef __JE_LUA_PARTICLESYSTEM_H__
+#define __JE_LUA_PARTICLESYSTEM_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ enum class ParticleSystemDependency
+ {
+ DEP_SPRITES = 1,
+ };
+
+ extern const char* Jin_Lua_ParticleSystem;
+
+ void luaopen_ParticleSystem(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_shader.cpp b/src/libjin-lua/modules/graphics/je_lua_shader.cpp
new file mode 100644
index 0000000..9505444
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_shader.cpp
@@ -0,0 +1,132 @@
+#include "common/je_lua_object.h"
+#include "common/je_lua_common.h"
+#include "libjin/jin.h"
+
+#include "je_lua_shader.h"
+#include "je_lua_canvas.h"
+#include "je_lua_texture.h"
+
+using namespace JinEngine::Graphics;
+using namespace JinEngine::Graphics::Shaders;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ const char* Jin_Lua_Shader = "Shader";
+
+ static inline Shader* checkShader(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Shader);
+ return luaObj->getObject<Shader>();
+ }
+
+ /**
+ * jsl:sendNumber("variable", 0.1)
+ */
+ LUA_IMPLEMENT int l_sendNumber(lua_State* L)
+ {
+ Shader* shader = checkShader(L);
+ const char* variable = luax_checkstring(L, 2);
+ float number = luax_checknumber(L, 3);
+ shader->sendFloat(variable, number);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_sendTexture(lua_State* L)
+ {
+ Shader* shader = checkShader(L);
+ const char* variable = luax_checkstring(L, 2);
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 3, Jin_Lua_Texture);
+ shader->sendTexture(variable, luaObj->getObject<Texture>());
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_sendCanvas(lua_State* L)
+ {
+ Shader* shader = checkShader(L);
+ const char* variable = luax_checkstring(L, 2);
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 3, Jin_Lua_Canvas);
+ shader->sendCanvas(variable, luaObj->getObject<Canvas>());
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_sendVec2(lua_State* L)
+ {
+ Shader* shader = checkShader(L);
+ const char* variable = luax_checkstring(L, 2);
+ if (!luax_istable(L, 3))
+ {
+ luax_typerror(L, 3, "table");
+ return 1;
+ }
+ float x = luax_rawgetnumber(L, 3, 1);
+ float y = luax_rawgetnumber(L, 3, 2);
+ shader->sendVec2(variable, x, y);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_sendVec3(lua_State* L)
+ {
+ Shader* shader = checkShader(L);
+ const char* variable = luax_checkstring(L, 2);
+ if (!luax_istable(L, 3))
+ {
+ luax_typerror(L, 3, "table");
+ return 1;
+ }
+ float x = luax_rawgetnumber(L, 3, 1);
+ float y = luax_rawgetnumber(L, 3, 2);
+ float z = luax_rawgetnumber(L, 3, 3);
+ shader->sendVec3(variable, x, y, z);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_sendVec4(lua_State* L)
+ {
+ Shader* shader = checkShader(L);
+ const char* variable = luax_checkstring(L, 2);
+ if (!luax_istable(L, 3))
+ {
+ luax_typerror(L, 3, "table");
+ return 1;
+ }
+ float x = luax_rawgetnumber(L, 3, 1);
+ float y = luax_rawgetnumber(L, 3, 2);
+ float z = luax_rawgetnumber(L, 3, 3);
+ float w = luax_rawgetnumber(L, 3, 4);
+ shader->sendVec4(variable, x, y, z, w);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_sendColor(lua_State* L)
+ {
+ return l_sendVec4(L);
+ }
+
+ LUA_IMPLEMENT int l_gc(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Shader);
+ luaObj->release();
+ return 0;
+ }
+
+ LUA_EXPORT void luaopen_Shader(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "__gc", l_gc },
+ { "sendNumber", l_sendNumber },
+ { "sendTexture", l_sendTexture },
+ { "sendCanvas", l_sendCanvas },
+ { "sendVec2", l_sendVec2 },
+ { "sendVec3", l_sendVec3 },
+ { "sendVec4", l_sendVec4 },
+ { "sendColor", l_sendColor },
+ { 0, 0 }
+ };
+ luax_newtype(L, Jin_Lua_Shader, methods);
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_shader.h b/src/libjin-lua/modules/graphics/je_lua_shader.h
new file mode 100644
index 0000000..5a84372
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_shader.h
@@ -0,0 +1,16 @@
+#ifndef __JE_LUA_SHDER_H__
+#define __JE_LUA_SHDER_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ extern const char* Jin_Lua_Shader;
+
+ void luaopen_Shader(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_sprite.cpp b/src/libjin-lua/modules/graphics/je_lua_sprite.cpp
new file mode 100644
index 0000000..f1bc6aa
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_sprite.cpp
@@ -0,0 +1,66 @@
+#include "common/je_lua_object.h"
+#include "common/je_lua_common.h"
+#include "libjin/jin.h"
+
+#include "je_lua_sprite.h"
+#include "je_lua_canvas.h"
+#include "je_lua_texture.h"
+#include "je_lua_shader.h"
+
+using namespace JinEngine::Math;
+using namespace JinEngine::Graphics;
+using namespace JinEngine::Graphics::Shaders;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+ const char* Jin_Lua_Sprite = "Sprite";
+
+ LUA_IMPLEMENT inline Sprite* checkSprite(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Sprite);
+ return luaObj->getObject<Sprite>();
+ }
+
+ LUA_IMPLEMENT int l_gc(lua_State* L)
+ {
+ LuaObject* p = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Sprite);
+ p->release();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_render(lua_State* L)
+ {
+ Sprite* sprite = checkSprite(L);
+ 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);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_getSize(lua_State* L)
+ {
+ Sprite* sprite = checkSprite(L);
+ Vector2<int> size = sprite->getSize();
+ luax_pushinteger(L, size.x);
+ luax_pushinteger(L, size.y);
+ return 1;
+ }
+
+ LUA_EXPORT void luaopen_Sprite(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "__gc", l_gc },
+ { "render", l_render },
+ { "getSize", l_getSize },
+ { 0, 0 }
+ };
+ luax_newtype(L, Jin_Lua_Sprite, methods);
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_sprite.h b/src/libjin-lua/modules/graphics/je_lua_sprite.h
new file mode 100644
index 0000000..02c44bf
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_sprite.h
@@ -0,0 +1,24 @@
+#ifndef __JE_LUA_SPRITE_H__
+#define __JE_LUA_SPRITE_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ // Sprite dependency slots.
+ enum class SpriteDependency
+ {
+ DEP_GRAPHIC = 1,
+ DEP_SHADER = 2,
+ DEP_SPRITESHEET = 3
+ };
+
+ extern const char* Jin_Lua_Sprite;
+
+ void luaopen_Sprite(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_spritesheet.cpp b/src/libjin-lua/modules/graphics/je_lua_spritesheet.cpp
new file mode 100644
index 0000000..a1a2c59
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_spritesheet.cpp
@@ -0,0 +1,118 @@
+#include <vector>
+
+#include "common/je_lua_object.h"
+#include "common/je_lua_common.h"
+#include "libjin/jin.h"
+#include "je_lua_sprite.h"
+#include "je_lua_spritesheet.h"
+
+using namespace std;
+using namespace JinEngine::Math;
+using namespace JinEngine::Graphics;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ const char* Jin_Lua_SpriteSheet = "SpriteSheet";
+
+ LUA_IMPLEMENT int l_gc(lua_State* L)
+ {
+ LuaObject* luaSSheet = (LuaObject*)luax_checktype(L, 1, Jin_Lua_SpriteSheet);
+ luaSSheet->release();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_newSprite(lua_State* L)
+ {
+ LuaObject* luaSSheet = (LuaObject*)luax_checktype(L, 1, Jin_Lua_SpriteSheet);
+ SpriteSheet* sheet = luaSSheet->getObject<SpriteSheet>();
+ 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);
+ Sprite* spr = nullptr;
+ if (luax_gettop(L) >= 4)
+ {
+ float ox = luax_checknumber(L, 3);
+ float oy = luax_checknumber(L, 4);
+ spr = sheet->createSprite(quad, ox, oy);
+ }
+ else if (luax_gettop(L) == 3)
+ {
+ int o = luax_checkinteger(L, 3);
+ Origin origin;
+ origin = static_cast<Origin>(o);
+ spr = sheet->createSprite(quad, origin);
+ }
+ Shared* shrSprite = new Shared(spr);
+ LuaObject* luaSprite = luax_newinstance(L, Jin_Lua_Sprite, shrSprite);
+ luaSprite->setDependency((int)SpriteDependency::DEP_SPRITESHEET, luaSSheet);
+ return 1;
+ }
+
+ // {} = newSprites
+ LUA_IMPLEMENT int l_newSprites(lua_State* L)
+ {
+ LuaObject* luaSS = (LuaObject*)luax_checktype(L, 1, Jin_Lua_SpriteSheet);
+ SpriteSheet* ss = luaSS->getObject<SpriteSheet>();
+ int count = luax_checkinteger(L, 2);
+ int r = luax_checkinteger(L, 3);
+ int c = luax_checkinteger(L, 4);
+ int w = luax_checkinteger(L, 5);
+ int h = luax_checkinteger(L, 6);
+ vector<Sprite*> sprs;
+ int argc = luax_gettop(L);
+ if (argc == 6)
+ {
+ sprs = ss->createSprites(count, r, c, w, h, Origin::TOPLEFT);
+ }
+ else if (argc >= 8)
+ {
+ int ox = luax_checkinteger(L, 7);
+ int oy = luax_checkinteger(L, 8);
+ int offx = luax_optinteger(L, 9, 0);
+ int offy = luax_optinteger(L, 10, 0);
+ sprs = ss->createSprites(count, r, c, w, h, ox, oy, offx, offy);
+ }
+ else if (argc >= 7)
+ {
+ int o = luax_checkinteger(L, 7);
+ Origin origin = static_cast<Origin>(o);
+ int offx = luax_optinteger(L, 8, 0);
+ int offy = luax_optinteger(L, 9, 0);
+ sprs = ss->createSprites(count, r, c, w, h, origin, offx, offy);
+ }
+ else
+ {
+ luax_error(L, "No matched override function.");
+ return 1;
+ }
+ luax_newtable(L);
+ LuaObject* graphic = luaSS->getDependency((int)SpriteSheetDependency::DEP_GRAPHIC);
+ for (int i = 0; i < sprs.size(); ++i)
+ {
+ Sprite* spr = sprs[i];
+ Shared* shrSpr = new Shared(spr);
+ LuaObject* luaSpr = (LuaObject*)luax_newinstance(L, Jin_Lua_Sprite, shrSpr);
+ luaSpr->setDependency((int)SpriteDependency::DEP_GRAPHIC, graphic);
+ luax_rawseti(L, -2, i + 1);
+ }
+ return 1;
+ }
+
+ LUA_EXPORT void luaopen_SpriteSheet(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "__gc", l_gc },
+ { "newSprite", l_newSprite },
+ { "newSprites", l_newSprites },
+ { 0, 0 }
+ };
+ luax_newtype(L, Jin_Lua_SpriteSheet, methods);
+ }
+
+ }
+} \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_spritesheet.h b/src/libjin-lua/modules/graphics/je_lua_spritesheet.h
new file mode 100644
index 0000000..bcae60b
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_spritesheet.h
@@ -0,0 +1,21 @@
+#ifndef __JE_LUA_SPRITE_SHEET_H__
+#define __JE_LUA_SPRITE_SHEET_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ enum class SpriteSheetDependency
+ {
+ DEP_GRAPHIC = 1
+ };
+
+ extern const char* Jin_Lua_SpriteSheet;
+
+ void luaopen_SpriteSheet(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_text.cpp b/src/libjin-lua/modules/graphics/je_lua_text.cpp
new file mode 100644
index 0000000..0afbceb
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_text.cpp
@@ -0,0 +1,31 @@
+#include "common/je_lua_object.h"
+#include "common/je_lua_common.h"
+#include "libjin/jin.h"
+
+using namespace JinEngine::Graphics;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ const char* Jin_Lua_Text = "Text";
+
+ LUA_IMPLEMENT int l_gc(lua_State* L)
+ {
+ LuaObject* p = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Text);
+ p->release();
+ return 0;
+ }
+
+ LUA_EXPORT void luaopen_Text(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "__gc", l_gc },
+ { 0, 0 }
+ };
+ luax_newtype(L, Jin_Lua_Text, methods);
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_text.h b/src/libjin-lua/modules/graphics/je_lua_text.h
new file mode 100644
index 0000000..dfcc9cc
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_text.h
@@ -0,0 +1,16 @@
+#ifndef __JE_LUA_TEXT_H__
+#define __JE_LUA_TEXT_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ extern const char* Jin_Lua_Text;
+
+ void luaopen_Text(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_texture.cpp b/src/libjin-lua/modules/graphics/je_lua_texture.cpp
new file mode 100644
index 0000000..b03b999
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_texture.cpp
@@ -0,0 +1,63 @@
+#include "common/je_lua_object.h"
+#include "common/je_lua_common.h"
+#include "libjin/jin.h"
+#include "je_lua_texture.h"
+
+using namespace JinEngine::Graphics;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ const char* Jin_Lua_Texture = "Texture";
+
+ LUA_IMPLEMENT inline Texture* checkTexture(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Texture);
+ return luaObj->getObject<Texture>();
+ }
+
+ LUA_IMPLEMENT int l_getWidth(lua_State* L)
+ {
+ Texture* shared = checkTexture(L);
+ luax_pushnumber(L, shared->getWidth());
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_getHeight(lua_State *L)
+ {
+ Texture* shared = checkTexture(L);
+ luax_pushnumber(L, shared->getHeight());
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_getSize(lua_State* L)
+ {
+ Texture* shared = checkTexture(L);
+ luax_pushnumber(L, shared->getWidth());
+ luax_pushnumber(L, shared->getHeight());
+ return 2;
+ }
+
+ LUA_IMPLEMENT int l_gc(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Texture);
+ luaObj->release();
+ return 0;
+ }
+
+ LUA_EXPORT void luaopen_Texture(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "__gc", l_gc },
+ { "getWidth", l_getWidth },
+ { "getHeight", l_getHeight },
+ { "getSize", l_getSize },
+ { 0, 0 }
+ };
+ luax_newtype(L, Jin_Lua_Texture, methods);
+ }
+
+ }// namespace Lua
+}// namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_texture.h b/src/libjin-lua/modules/graphics/je_lua_texture.h
new file mode 100644
index 0000000..c8bb71c
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_texture.h
@@ -0,0 +1,16 @@
+#ifndef __JE_LUA_TEXTURE_H__
+#define __JE_LUA_TEXTURE_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ extern const char* Jin_Lua_Texture;
+
+ void luaopen_Texture(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_texture_font.cpp b/src/libjin-lua/modules/graphics/je_lua_texture_font.cpp
new file mode 100644
index 0000000..6cbf7ca
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_texture_font.cpp
@@ -0,0 +1,63 @@
+#include "common/je_lua_object.h"
+#include "common/je_lua_common.h"
+#include "libjin/jin.h"
+
+#include "je_lua_page.h"
+#include "je_lua_text.h"
+
+using namespace JinEngine::Graphics;
+using namespace JinEngine::Graphics::Fonts;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ const char* Jin_Lua_TextureFont = "TextureFont";
+
+ LUA_IMPLEMENT int l_gc(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_TextureFont);
+ luaObj->release();
+ return 0;
+ }
+
+ /* typeset(Text | string, lineheight, spacing) */
+ LUA_IMPLEMENT int l_typeset(lua_State* L)
+ {
+ LuaObject* luaTexFont = (LuaObject*)luax_checktype(L, 1, Jin_Lua_TextureFont);
+ TextureFont* tf = luaTexFont->getObject<TextureFont>();
+ int lineheight = luax_checkinteger(L, 3);
+ int spacing = luax_optnumber(L, 4, 0);
+ Page* page = nullptr;
+ if (luax_isstring(L, 2))
+ {
+ unsigned length;
+ const char* str = luax_checklstring(L, 2, &length);
+ Text text(Encode::UTF8, str, length);
+ page = tf->typeset(text, lineheight, spacing);
+ }
+ else if (luax_istype(L, 2, Jin_Lua_Text))
+ {
+ LuaObject* p2 = (LuaObject*)luax_checktype(L, 2, Jin_Lua_Text);
+ Text* text = p2->getObject<Text>();
+ page = tf->typeset(*text, lineheight, spacing);
+ }
+ Shared* shrPage = new Shared(page);
+ LuaObject* luaPage = luax_newinstance(L, Jin_Lua_Page, shrPage);
+ luaPage->setDependency((int)PageDependency::DEP_TEXTURE_FONT, luaTexFont);
+ return 1;
+ }
+
+ LUA_EXPORT void luaopen_TextureFont(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "__gc", l_gc },
+ { "typeset", l_typeset },
+ { 0, 0 }
+ };
+ luax_newtype(L, Jin_Lua_TextureFont, methods);
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_texture_font.h b/src/libjin-lua/modules/graphics/je_lua_texture_font.h
new file mode 100644
index 0000000..d1fffe5
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_texture_font.h
@@ -0,0 +1,16 @@
+#ifndef __JE_LUA_TEXTURE_FONT_H__
+#define __JE_LUA_TEXTURE_FONT_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ extern const char* Jin_Lua_TextureFont;
+
+ void luaopen_TextureFont(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_ttf.cpp b/src/libjin-lua/modules/graphics/je_lua_ttf.cpp
new file mode 100644
index 0000000..ead46de
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_ttf.cpp
@@ -0,0 +1,63 @@
+#include "common/je_lua_object.h"
+#include "common/je_lua_common.h"
+#include "libjin/jin.h"
+
+#include "je_lua_page.h"
+#include "je_lua_text.h"
+
+using namespace JinEngine::Graphics;
+using namespace JinEngine::Graphics::Fonts;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ const char* Jin_Lua_TTF = "TTF";
+
+ LUA_IMPLEMENT int l_gc(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_TTF);
+ luaObj->release();
+ return 0;
+ }
+
+ /* typeset(Text | string, lineheight, spacing) */
+ LUA_IMPLEMENT int l_typeset(lua_State* L)
+ {
+ LuaObject* luaTTF = (LuaObject*)luax_checktype(L, 1, Jin_Lua_TTF);
+ TTF* ttf = luaTTF->getObject<TTF>();
+ int lineheight = luax_optnumber(L, 3, ttf->getFontSize());
+ int spacing = luax_optnumber(L, 4, 0);
+ Page* page = nullptr;
+ if (luax_isstring(L, 2))
+ {
+ unsigned length;
+ const char* str = luax_checklstring(L, 2, &length);
+ Text text(Encode::UTF8, str, length);
+ page = ttf->typeset(text, lineheight, spacing);
+ }
+ else if (luax_istype(L, 2, Jin_Lua_Text))
+ {
+ LuaObject* luaText = (LuaObject*)luax_checktype(L, 2, Jin_Lua_Text);
+ Text* text = luaText->getObject<Text>();
+ page = ttf->typeset(*text, lineheight, spacing);
+ }
+ Shared* refPage = new Shared(page);
+ LuaObject* luaPage = luax_newinstance(L, Jin_Lua_Page, refPage);
+ luaPage->setDependency((int)PageDependency::DEP_TTF, luaTTF);
+ return 1;
+ }
+
+ LUA_EXPORT void luaopen_TTF(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "__gc", l_gc },
+ { "typeset", l_typeset },
+ { 0, 0 }
+ };
+ luax_newtype(L, Jin_Lua_TTF, methods);
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_ttf.h b/src/libjin-lua/modules/graphics/je_lua_ttf.h
new file mode 100644
index 0000000..bfe503d
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_ttf.h
@@ -0,0 +1,16 @@
+#ifndef __JE_LUA_TTF_H__
+#define __JE_LUA_TTF_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ extern const char* Jin_Lua_TTF;
+
+ void luaopen_TTF(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_ttf_data.cpp b/src/libjin-lua/modules/graphics/je_lua_ttf_data.cpp
new file mode 100644
index 0000000..e251ac8
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_ttf_data.cpp
@@ -0,0 +1,49 @@
+#include "common/je_lua_object.h"
+#include "common/je_lua_common.h"
+#include "libjin/jin.h"
+
+#include "je_lua_ttf.h"
+#include "je_lua_ttf_data.h"
+
+using namespace JinEngine::Graphics;
+using namespace JinEngine::Graphics::Fonts;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ const char* Jin_Lua_TTFData = "TTFData";
+
+ LUA_IMPLEMENT int l_newTTF(lua_State* L)
+ {
+ LuaObject* luaTTFData = (LuaObject*)luax_checktype(L, 1, Jin_Lua_TTFData);
+ int fontsize = luax_checkinteger(L, 2);
+ TTFData* fontData = luaTTFData->getObject<TTFData>();
+ TTF* font = fontData->createTTF(fontsize);
+ Shared* shrTTF = new Shared(font);
+ LuaObject* luaTTF = luax_newinstance(L, Jin_Lua_TTF, shrTTF);
+ luaTTF->setDependency((int)TTFDependency::DEP_TTFDATA, luaTTFData);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_gc(lua_State* L)
+ {
+ LuaObject* p = (LuaObject*)luax_checktype(L, 1, Jin_Lua_TTFData);
+ p->release();
+ return 0;
+ }
+
+ LUA_EXPORT void luaopen_TTFData(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "__gc", l_gc },
+ { "newTTF", l_newTTF },
+ { 0, 0 }
+ };
+ luax_newtype(L, Jin_Lua_TTFData, methods);
+
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/graphics/je_lua_ttf_data.h b/src/libjin-lua/modules/graphics/je_lua_ttf_data.h
new file mode 100644
index 0000000..1fd832d
--- /dev/null
+++ b/src/libjin-lua/modules/graphics/je_lua_ttf_data.h
@@ -0,0 +1,21 @@
+#ifndef __JE_LUA_TTFDATA_H__
+#define __JE_LUA_TTFDATA_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ enum class TTFDependency
+ {
+ DEP_TTFDATA = 1,
+ };
+
+ extern const char* Jin_Lua_TTFData;
+
+ void luaopen_TTFData(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/je_lua_modules.h b/src/libjin-lua/modules/je_lua_modules.h
new file mode 100644
index 0000000..afe0a82
--- /dev/null
+++ b/src/libjin-lua/modules/je_lua_modules.h
@@ -0,0 +1,19 @@
+#ifndef __JE_LUA_MODULES_H__
+#define __JE_LUA_MODULES_H__
+
+#include "ai/je_lua_ai.h"
+#include "audio/je_lua_audio.h"
+#include "bit/je_lua_bit.h"
+#include "core/je_lua_core.h"
+#include "event/je_lua_event.h"
+#include "filesystem/je_lua_filesystem.h"
+#include "graphics/je_lua_graphics.h"
+#include "joypad/je_lua_joypad.h"
+#include "keyboard/je_lua_keyboard.h"
+#include "math/je_lua_math.h"
+#include "mouse/je_lua_mouse.h"
+#include "net/je_lua_net.h"
+#include "thread/je_lua_thread.h"
+#include "time/je_lua_time.h"
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/joypad/je_lua_joypad.cpp b/src/libjin-lua/modules/joypad/je_lua_joypad.cpp
new file mode 100644
index 0000000..a3623ae
--- /dev/null
+++ b/src/libjin-lua/modules/joypad/je_lua_joypad.cpp
@@ -0,0 +1,21 @@
+#include "common/je_lua_object.h"
+#include "common/je_lua_common.h"
+#include "libjin/jin.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ LUA_EXPORT int luaopen_joypad(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { 0, 0 }
+ };
+ luax_newlib(L, methods);
+
+ return 1;
+ }
+ /*SDL_JoystickGetButton*/
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/joypad/je_lua_joypad.h b/src/libjin-lua/modules/joypad/je_lua_joypad.h
new file mode 100644
index 0000000..ec0e20f
--- /dev/null
+++ b/src/libjin-lua/modules/joypad/je_lua_joypad.h
@@ -0,0 +1,14 @@
+#ifndef __JE_LUA_JOYPAD_H__
+#define __JE_LUA_JOYPAD_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ int luaopen_joypad(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/keyboard/je_lua_keyboard.cpp b/src/libjin-lua/modules/keyboard/je_lua_keyboard.cpp
new file mode 100644
index 0000000..93a62bd
--- /dev/null
+++ b/src/libjin-lua/modules/keyboard/je_lua_keyboard.cpp
@@ -0,0 +1,17 @@
+#include "common/je_lua_common.h"
+#include "common/je_lua_object.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+ //https://wiki.libsdl.org/SDL_Keycode
+
+ LUA_EXPORT int luaopen_keyboard(lua_State* L)
+ {
+ luax_newlib(L, 0);
+ return 1;
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/keyboard/je_lua_keyboard.h b/src/libjin-lua/modules/keyboard/je_lua_keyboard.h
new file mode 100644
index 0000000..bf00f83
--- /dev/null
+++ b/src/libjin-lua/modules/keyboard/je_lua_keyboard.h
@@ -0,0 +1,14 @@
+#ifndef __JE_LUA_KEYBOARD_H__
+#define __JE_LUA_KEYBOARD_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ int luaopen_keyboard(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/math/je_lua_math.cpp b/src/libjin-lua/modules/math/je_lua_math.cpp
new file mode 100644
index 0000000..5b320ff
--- /dev/null
+++ b/src/libjin-lua/modules/math/je_lua_math.cpp
@@ -0,0 +1,30 @@
+#include "common/je_lua_common.h"
+#include "common/je_lua_object.h"
+#include "libjin/jin.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ LUA_IMPLEMENT int l_mod(lua_State* L)
+ {
+ int n = luax_checkinteger(L, 1);
+ int m = luax_checkinteger(L, 2);
+ int mod = n % m;
+ luax_pushinteger(L, mod);
+ return 1;
+ }
+
+ LUA_EXPORT int luaopen_math(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "mod", l_mod },
+ { 0, 0 }
+ };
+ luax_newlib(L, methods);
+ return 1;
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/math/je_lua_math.h b/src/libjin-lua/modules/math/je_lua_math.h
new file mode 100644
index 0000000..2e7010c
--- /dev/null
+++ b/src/libjin-lua/modules/math/je_lua_math.h
@@ -0,0 +1,14 @@
+#ifndef __JE_LUA_MATH_H__
+#define __JE_LUA_MATH_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ int luaopen_math(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/mouse/je_lua_mouse.cpp b/src/libjin-lua/modules/mouse/je_lua_mouse.cpp
new file mode 100644
index 0000000..222f596
--- /dev/null
+++ b/src/libjin-lua/modules/mouse/je_lua_mouse.cpp
@@ -0,0 +1,42 @@
+#include "common/je_lua_common.h"
+#include "common/je_lua_object.h"
+#include "libjin/jin.h"
+
+using namespace JinEngine::Input;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ LUA_IMPLEMENT int l_pos(lua_State* L)
+ {
+ static Mouse* mouse = Mouse::get();
+ int x, y;
+ mouse->getState(&x, &y);
+ luax_pushnumber(L, x);
+ luax_pushnumber(L, y);
+ return 2;
+ }
+
+ LUA_IMPLEMENT int l_setVisible(lua_State* L)
+ {
+ bool visible = luax_checkbool(L, 1);
+ Mouse* mouse = Mouse::get();
+ mouse->setVisible(visible);
+ return 0;
+ }
+
+ LUA_EXPORT int luaopen_mouse(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "getPosition", l_pos },
+ { "setVisible", l_setVisible },
+ { 0, 0 }
+ };
+ luax_newlib(L, methods);
+ return 1;
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/mouse/je_lua_mouse.h b/src/libjin-lua/modules/mouse/je_lua_mouse.h
new file mode 100644
index 0000000..09738f5
--- /dev/null
+++ b/src/libjin-lua/modules/mouse/je_lua_mouse.h
@@ -0,0 +1,14 @@
+#ifndef __JE_LUA_MOUSE_H__
+#define __JE_LUA_MOUSE_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ int luaopen_mouse(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/net/je_lua_buffer.cpp b/src/libjin-lua/modules/net/je_lua_buffer.cpp
new file mode 100644
index 0000000..10e7143
--- /dev/null
+++ b/src/libjin-lua/modules/net/je_lua_buffer.cpp
@@ -0,0 +1,136 @@
+#include "common/je_lua_object.h"
+#include "common/je_lua_common.h"
+#include "libjin/jin.h"
+#include "je_lua_buffer.h"
+
+using namespace JinEngine::Lua::Net;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ const char* Jin_Lua_Buffer = "Buffer";
+
+ static inline Net::Buffer* checkNetBuffer(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Buffer);
+ return luaObj->getObject<Net::Buffer>();
+ }
+
+ // net.Buffer:append(value) -> value_length
+ LUA_IMPLEMENT int l_append(lua_State* L)
+ {
+ Buffer* buffer = checkNetBuffer(L);
+ const int vp = 2;
+ if (luax_isintegerstrict(L, vp))
+ {
+ int n = luax_checkinteger(L, vp);
+ int size = sizeof(n);
+ buffer->append(&n, size);
+ luax_pushinteger(L, size);
+ return 1;
+ }
+ else if (luax_isfloatstrict(L, vp))
+ {
+ float n = luax_checknumber(L, vp);
+ int size = sizeof(n);
+ buffer->append(&n, size);
+ luax_pushinteger(L, size);
+ return 1;
+ }
+ else if (luax_isbooleanstrict(L, vp))
+ {
+ bool n = luax_checkbool(L, vp);
+ int size = sizeof(n);
+ buffer->append(&n, size);
+ luax_pushinteger(L, size);
+ return 1;
+ }
+ else if (luax_isstringstrict(L, vp))
+ {
+ const char* str = luax_checkstring(L, vp);
+ int size = strlen(str) + 1;
+ buffer->append(str, size);
+ luax_pushinteger(L, size);
+ return 1;
+ }
+ else
+ {
+ luax_typerror(L, vp, "number, bool or string");
+ return 0;
+ }
+ }
+
+ // net.Buffer:grabString(offset) -> string, length
+ LUA_IMPLEMENT int l_grabString(lua_State* L)
+ {
+ Buffer* buffer = checkNetBuffer(L);
+ int offset = luax_checkinteger(L, 2);
+ unsigned int len;
+ char* data = buffer->grabString(&len, offset);
+ Array<char> str;
+ str.bind(data, len);
+ luax_pushstring(L, &str);
+ luax_pushinteger(L, str.count());
+ return 2;
+ }
+
+ // net.Buffer:grabInteger(offset) -> integer, length
+ LUA_IMPLEMENT int l_grabInteger(lua_State* L)
+ {
+ Buffer* buffer = checkNetBuffer(L);
+ int offset = luax_checkinteger(L, 2);
+ int len;
+ int integer = buffer->grabInteger(&len, offset);
+ luax_pushinteger(L, integer);
+ luax_pushinteger(L, len);
+ return 2;
+ }
+
+ LUA_IMPLEMENT int l_grabFloat(lua_State* L)
+ {
+ Buffer* buffer = checkNetBuffer(L);
+ int offset = luax_checkinteger(L, 2);
+ int len;
+ float floatv = buffer->grabFloat(&len, offset);
+ luax_pushnumber(L, floatv);
+ luax_pushinteger(L, len);
+ return 2;
+ }
+
+ LUA_IMPLEMENT int l_grabBoolean(lua_State* L)
+ {
+ Buffer* buffer = checkNetBuffer(L);
+ int offset = luax_checkinteger(L, 2);
+ int len;
+ bool boolean = buffer->grabBoolean(&len, offset);
+ luax_pushboolean(L, boolean);
+ luax_pushinteger(L, len);
+ return 2;
+ }
+
+ LUA_IMPLEMENT int l_gc(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Buffer);
+ luaObj->release();
+ return 0;
+ }
+
+ LUA_EXPORT void luaopen_Buffer(lua_State* L)
+ {
+ luaL_Reg netbuffer_function[] = {
+ { "__gc", l_gc },
+ { "append", l_append },
+ { "grabString", l_grabString },
+ { "grabInteger", l_grabInteger },
+ { "grabBoolean", l_grabBoolean },
+ { "grabFloat", l_grabFloat },
+ { 0, 0 }
+ };
+
+ luax_newtype(L, Jin_Lua_Buffer, netbuffer_function);
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/net/je_lua_buffer.h b/src/libjin-lua/modules/net/je_lua_buffer.h
new file mode 100644
index 0000000..974e23a
--- /dev/null
+++ b/src/libjin-lua/modules/net/je_lua_buffer.h
@@ -0,0 +1,102 @@
+#ifndef __JIN_LUA_NET_NETBUFFER_H
+#define __JIN_LUA_NET_NETBUFFER_H
+
+#include <cstring>
+#include <cstdlib>
+#include "common/je_lua_common.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ extern const char* Jin_Lua_Buffer;
+
+ void luaopen_Buffer(lua_State* L);
+
+ namespace Net
+ {
+
+ class Buffer : public Object
+ {
+ public:
+ Buffer(size_t s = 0)
+ : size(s)
+ {
+ buffer = new char[size];
+ memset(buffer, 0, size);
+ }
+
+ Buffer(const char* data, size_t s)
+ : size(s)
+ {
+ buffer = new char[size];
+ memcpy(buffer, data, size);
+ }
+
+ ~Buffer()
+ {
+ if (buffer != nullptr)
+ {
+ delete[] buffer;
+ buffer = nullptr;
+ size = 0;
+ }
+ }
+
+ void append(const void* data, size_t s)
+ {
+ if (data == nullptr)
+ return;
+ char* buf = buffer;
+ buffer = new char[size + s];
+ memcpy(buffer, buf, size);
+ memcpy(buffer + size, data, s);
+ delete[] buf;
+ size += s;
+ return;
+ }
+
+ /* grab and create a string */
+ char* grabString(unsigned int* length, int offset = 0)
+ {
+ int l = offset;
+ for (; l < size; ++l)
+ {
+ if (buffer[l] == 0)
+ break;
+ }
+ *length = l - offset + 1;
+ char* str = (char*)malloc(*length);
+ memcpy(str, buffer + offset, *length);
+ return str;
+ }
+
+ int grabInteger(int* length, int offset = 0)
+ {
+ *length = sizeof(int);
+ return *((int*)(buffer + offset));
+ }
+
+ float grabFloat(int* length, int offset = 0)
+ {
+ *length = sizeof(float);
+ return *((float*)(buffer + offset));
+ }
+
+ bool grabBoolean(int* length, int offset = 0)
+ {
+ *length = sizeof(bool);
+ return *((bool*)(buffer + offset));
+ }
+
+ char* buffer;
+ size_t size;
+
+ };
+
+ } // namespace Net
+ } // namespace Lua
+} // namespace JinEngine
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/net/je_lua_net.cpp b/src/libjin-lua/modules/net/je_lua_net.cpp
new file mode 100644
index 0000000..fad6fc5
--- /dev/null
+++ b/src/libjin-lua/modules/net/je_lua_net.cpp
@@ -0,0 +1,79 @@
+#include "common/je_lua_object.h"
+#include "libjin/jin.h"
+#include "common/je_lua_common.h"
+
+#include "je_lua_buffer.h"
+#include "je_lua_socket.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ using namespace JinEngine::Lua::Net;
+ using namespace JinEngine::Net;
+
+ LUA_IMPLEMENT int l_initNetwork(lua_State* L)
+ {
+ JinEngine::Net::NetManager::get()->start();
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_Socket(lua_State* L)
+ {
+ SocketInformation info = { 0 };
+ {
+ const char* socketType = luax_checkstring(L, 1);
+ if (strcmp(socketType, "TCP") == 0)
+ info.type = SocketType::TCP;
+ else if (strcmp(socketType, "UDP") == 0)
+ info.type = SocketType::UDP;
+ else
+ {
+ luax_error(L, "jin.net.Socket() first paramter wrong, must be TCP or UDP");
+ return 0;
+ }
+ // type, port
+ if (luax_gettop(L) == 2)
+ {
+ info.port = luax_checkinteger(L, 2);
+ }
+ // type, address, port
+ else if (luax_gettop(L) == 3)
+ {
+ if (luax_isstringstrict(L, 2))
+ info.address = tk_strtohl(luax_checkstring(L, 2));
+ else if (luax_isintegerstrict(L, 2))
+ info.address = luax_checkinteger(L, 2);
+ info.port = luax_checkinteger(L, 3);
+ }
+ }
+ Socket* socket = new Socket(info);
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_Socket, new Shared(socket));
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_Buffer(lua_State* L)
+ {
+ int size = luax_checkinteger(L, 1);
+ Net::Buffer* buffer = new Net::Buffer(size);
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_Buffer, new Shared(buffer));
+ return 1;
+ }
+
+ LUA_EXPORT int luaopen_net(lua_State* L)
+ {
+ luaopen_Socket(L);
+ luaopen_Buffer(L);
+ luaL_Reg methods[] = {
+ { "init", l_initNetwork },
+ { "newSocket", l_Socket },
+ { "newBuffer", l_Buffer },
+ { 0, 0 }
+ };
+ luax_newlib(L, methods);
+ return 1;
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/net/je_lua_net.h b/src/libjin-lua/modules/net/je_lua_net.h
new file mode 100644
index 0000000..1542791
--- /dev/null
+++ b/src/libjin-lua/modules/net/je_lua_net.h
@@ -0,0 +1,14 @@
+#ifndef __JE_LUA_NET_H__
+#define __JE_LUA_NET_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ int luaopen_net(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/net/je_lua_socket.cpp b/src/libjin-lua/modules/net/je_lua_socket.cpp
new file mode 100644
index 0000000..d6cfe91
--- /dev/null
+++ b/src/libjin-lua/modules/net/je_lua_socket.cpp
@@ -0,0 +1,123 @@
+#include "common/je_lua_object.h"
+#include "common/je_lua_common.h"
+#include "libjin/jin.h"
+#include "je_lua_buffer.h"
+
+using namespace JinEngine::Net;
+using namespace JinEngine::Lua::Net;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ const char* Jin_Lua_Socket = "Socket";
+
+ const int BUFFER_SIZE = 1024;
+
+ LUA_IMPLEMENT inline Socket* checkSocket(lua_State* L, int pos = 1)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, pos, Jin_Lua_Socket);
+ return luaObj->getObject<Socket>();
+ }
+
+ LUA_IMPLEMENT inline Buffer* checkNetBuffer(lua_State* L, int pos = 1)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, pos, Jin_Lua_Buffer);
+ return luaObj->getObject<Buffer>();
+ }
+
+ // return net.Socket
+ LUA_IMPLEMENT int l_accept(lua_State* L)
+ {
+ Socket* socket = checkSocket(L);
+ Socket* client = socket->accept();
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_Socket, new Shared(client));
+ return 1;
+ }
+
+ // return net.Buffer
+ LUA_IMPLEMENT int l_receive(lua_State* L)
+ {
+ Socket* socket = checkSocket(L);
+ char buffer[BUFFER_SIZE] = {0};
+ int size = socket->receive(buffer, BUFFER_SIZE);
+ Net::Buffer* netBuffer = new Net::Buffer(buffer, size);
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_Buffer, new Shared(netBuffer));
+ return 1;
+ }
+
+ // Socket:receiveFrom(address, port)
+ LUA_IMPLEMENT int l_receiveFrom(lua_State* L)
+ {
+ Socket* socket = checkSocket(L);
+ int address = luax_checkinteger(L, 2);
+ int port = luax_checkinteger(L, 3);
+ char buffer[BUFFER_SIZE];
+ int size = socket->receiveFrom(buffer, BUFFER_SIZE, address, port);
+ Net::Buffer* netBuffer = new Net::Buffer(buffer, size);
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_Buffer, new Shared(netBuffer));
+ return 1;
+ }
+
+ // Socket:send(net.Buffer) -> data_length
+ LUA_IMPLEMENT int l_send(lua_State* L)
+ {
+ Socket* socket = checkSocket(L);
+ Buffer* buffer = checkNetBuffer(L, 2);
+ int len = socket->send(buffer->buffer, buffer->size);
+ luax_pushinteger(L, len);
+ return 1;
+ }
+
+ // Socket:sendTo(address, port, net.Buffer)
+ LUA_IMPLEMENT int l_sendTo(lua_State* L)
+ {
+ Socket* socket = checkSocket(L);
+ int address = luax_checkinteger(L, 2);
+ int port = luax_checkinteger(L, 3);
+ Buffer* buffer = checkNetBuffer(L, 4);
+ socket->sendTo(buffer->buffer, buffer->size, address, port);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_close(lua_State* L)
+ {
+ Socket* socket = checkSocket(L);
+ socket->close();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_configBlocking(lua_State* L)
+ {
+ Socket* socket = checkSocket(L);
+ bool blocking = luax_checkbool(L, 2);
+ socket->configureBlocking(blocking);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_gc(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Socket);
+ luaObj->release();
+ return 0;
+ }
+
+ LUA_EXPORT void luaopen_Socket(lua_State* L)
+ {
+ luaL_Reg socket_function[] = {
+ { "__gc", l_gc },
+ { "accept", l_accept },
+ { "receive", l_receive },
+ { "receiveFrom", l_receiveFrom },
+ { "send", l_send },
+ { "sendTo", l_sendTo },
+ { "close", l_close },
+ { "configBlocking", l_configBlocking },
+ { 0, 0 }
+ };
+ luax_newtype(L, Jin_Lua_Socket, socket_function);
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/net/je_lua_socket.h b/src/libjin-lua/modules/net/je_lua_socket.h
new file mode 100644
index 0000000..b33fac6
--- /dev/null
+++ b/src/libjin-lua/modules/net/je_lua_socket.h
@@ -0,0 +1,16 @@
+#ifndef __JE_LUA_SOCKET_H__
+#define __JE_LUA_SOCKET_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ extern const char* Jin_Lua_Socket;
+
+ void luaopen_Socket(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/thread/je_lua_thread.cpp b/src/libjin-lua/modules/thread/je_lua_thread.cpp
new file mode 100644
index 0000000..2af3e53
--- /dev/null
+++ b/src/libjin-lua/modules/thread/je_lua_thread.cpp
@@ -0,0 +1,240 @@
+#include "common/je_lua_object.h"
+
+#include "libjin/jin.h"
+#include "libjin-lua/je_lua_jin.h"
+#include "common/je_lua_common.h"
+#include "je_lua_thread.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ const char* Jin_Lua_Thread = "Thread";
+
+ int luaopen_thread(lua_State* L);
+
+ static inline Thread* checkThread(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Thread);
+ return luaObj->getObject<Thread>();
+ }
+
+ LUA_IMPLEMENT int threadRunner(void* t)
+ {
+ Shared* shared = (Shared*)t;
+ Thread* thread = shared->getObject<Thread>();
+ lua_State* L = lua_open();
+ luax_openlibs(L);
+ open(L);
+ luax_getglobal(L, MODULE_NAME);
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_Thread, shared);
+ luax_setfield(L, -2, "_curThread");
+ luax_dostring(L, thread->code.c_str());
+ luax_close(L);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_thread_gc(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Thread);
+ luaObj->release();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_start(lua_State* L)
+ {
+ Thread* shared = checkThread(L);
+ bool result = shared->start(&shared);
+ luax_pushboolean(L, result);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_wait(lua_State* L)
+ {
+ Thread* shared = checkThread(L);
+ shared->wait();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_send(lua_State* L)
+ {
+ Thread* shared = checkThread(L);
+ int slot = luax_checkinteger(L, 2);
+ const int vp = 3;
+ if (luax_isnumberstrict(L, vp))
+ {
+ float real = luax_checknumber(L, vp);
+ shared->send(slot, real);
+ }
+ else if (luax_isbooleanstrict(L, vp))
+ {
+ bool bol = luax_checkbool(L, vp);
+ shared->send(slot, bol);
+ }
+ else if (luax_isstringstrict(L, vp))
+ {
+ const char* str = luax_checkstring(L, vp);
+ shared->send(slot, str);
+ }
+ else if (luax_isuserdata(L, vp))
+ {
+ LuaObject* luaObj = (LuaObject*)luax_touserdata(L, vp);
+ shared->send(slot, luaObj);
+ }/*
+ else if (luax_islightuserdata(L, vp))
+ {
+ void* p = luax_tolightuserdata(L, vp);
+ shared->send(slot, p);
+ }*/
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_receive(lua_State* L)
+ {
+ Thread* shared = checkThread(L);
+ int slot = luax_checkinteger(L, 2);
+ bool result = shared->receive(slot);
+ luax_pushboolean(L, result);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_fetch(lua_State* L)
+ {
+ Thread* shared = checkThread(L);
+ int slot = luax_checkinteger(L, 2);
+ Thread::Variant v = shared->fetch(slot);
+ switch (v.type)
+ {
+ case Thread::Variant::INTERGER:
+ luax_pushinteger(L, v.integer);
+ break;
+
+ case Thread::Variant::BOOLEAN:
+ luax_pushboolean(L, v.boolean);
+ break;
+
+ case Thread::Variant::CSTRING:
+ luax_pushstring(L, v.cstring);
+ break;
+
+ case Thread::Variant::REAL:
+ luax_pushnumber(L, v.real);
+ break;
+
+ case Thread::Variant::POINTER:
+ LuaObject* p = (LuaObject*)v.pointer;
+ // Create lua object from other lua_State.
+ LuaObject* luaObj = luax_copyinstance(L, p);
+ break;
+
+ }
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_demand(lua_State* L)
+ {
+ Thread* shared = checkThread(L);
+ int slot = luax_checkinteger(L, 2);
+ Thread::Variant v = shared->demand(slot);
+ switch (v.type)
+ {
+ case Thread::Variant::INTERGER:
+ luax_pushinteger(L, v.integer);
+ break;
+
+ case Thread::Variant::BOOLEAN:
+ luax_pushboolean(L, v.boolean);
+ break;
+
+ case Thread::Variant::CSTRING:
+ luax_pushstring(L, v.cstring);
+ break;
+
+ case Thread::Variant::REAL:
+ luax_pushnumber(L, v.real);
+ break;
+
+ case Thread::Variant::POINTER:
+ LuaObject* p = (LuaObject*)v.pointer;
+ // Create lua object from other lua_State.
+ LuaObject* luaObj = luax_copyinstance(L, p);
+ break;
+
+ }
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_remove(lua_State* L)
+ {
+ Thread* shared = checkThread(L);
+ int slot = luax_checkinteger(L, 2);
+ shared->remove(slot);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_getName(lua_State* L)
+ {
+ Thread* shared = checkThread(L);
+ const char* name = shared->getName();
+ luax_pushstring(L, name);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_isRunning(lua_State* L)
+ {
+ Thread* shared = checkThread(L);
+ bool running = shared->isRunning();
+ luax_pushboolean(L, running);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int luaopen_Thread(lua_State* L)
+ {
+ luaL_Reg thread_function[] = {
+ { "__gc", l_thread_gc },
+ { "start", l_start },
+ { "wait", l_wait },
+ { "send", l_send },
+ { "receive", l_receive },
+ { "fetch", l_fetch },
+ { "demand", l_demand },
+ { "remove", l_remove },
+ { "getName", l_getName },
+ { "isRunning", l_isRunning },
+ { 0, 0 }
+ };
+ luax_newtype(L, Jin_Lua_Thread, thread_function);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_newThread(lua_State* L)
+ {
+ const char* name = luax_checkstring(L, 1);
+ const char* code = luax_checkstring(L, 2);
+ Thread* thread = new Thread(name, code, threadRunner);
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_Thread, new Shared(thread));
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_getThread(lua_State* L)
+ {
+ luax_getglobal(L, MODULE_NAME);
+ luax_getfield(L, -1, "_curThread");
+ return 1;
+ }
+
+ LUA_EXPORT int luaopen_thread(lua_State* L)
+ {
+ luaopen_Thread(L);
+ luaL_Reg methods[] = {
+ { "newThread", l_newThread },
+ { "getThread", l_getThread },
+ { 0, 0 }
+ };
+ luax_newlib(L, methods);
+ return 1;
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/thread/je_lua_thread.h b/src/libjin-lua/modules/thread/je_lua_thread.h
new file mode 100644
index 0000000..acb4c49
--- /dev/null
+++ b/src/libjin-lua/modules/thread/je_lua_thread.h
@@ -0,0 +1,95 @@
+#include "libjin/jin.h"
+#include "common/je_lua_common.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ extern const char* Jin_Lua_Thread;
+
+ class Thread : public Object
+ {
+ public:
+ typedef JinEngine::Threads::Thread::Variant Variant;
+ typedef JinEngine::Threads::Thread::ThreadRunner ThreadRunner;
+
+ Thread(std::string _name, std::string _code, ThreadRunner runner)
+ : name(_name)
+ , code(_code)
+ {
+ thread = new JinEngine::Threads::Thread(_name, runner);
+ }
+
+ ~Thread()
+ {
+ delete thread;
+ }
+
+ bool start(void* p)
+ {
+ return thread->start(p);
+ }
+
+ void wait()
+ {
+ thread->wait();
+ }
+
+ void send(int slot, const Variant& value)
+ {
+ thread->send(slot, value);
+ }
+
+ bool receive(int slot)
+ {
+ return thread->receive(slot);
+ }
+
+ Variant fetch(int slot)
+ {
+ return thread->fetch(slot);
+ }
+
+ Variant demand(int slot)
+ {
+ return thread->demand(slot);
+ }
+
+ void remove(int slot)
+ {
+ thread->remove(slot);
+ }
+
+ const char* getName()
+ {
+ return name.c_str();
+ }
+
+ bool isRunning()
+ {
+ return thread->isRunning();
+ }
+
+ void lock()
+ {
+ thread->lock();
+ }
+
+ void unlock()
+ {
+ thread->unlock();
+ }
+
+ const std::string name;
+ const std::string code;
+
+ private:
+ JinEngine::Threads::Thread* thread;
+
+ };
+
+ int luaopen_thread(lua_State* L);
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/time/je_lua_time.cpp b/src/libjin-lua/modules/time/je_lua_time.cpp
new file mode 100644
index 0000000..cd49978
--- /dev/null
+++ b/src/libjin-lua/modules/time/je_lua_time.cpp
@@ -0,0 +1,70 @@
+#include "SDL2/SDL.h"
+#include "common/je_lua_common.h"
+#include "common/je_lua_object.h"
+#include "libjin/jin.h"
+
+#include "je_lua_timer.h"
+
+using namespace JinEngine::Time;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ static struct
+ {
+ float previous;
+ float current;
+ } context;
+
+ LUA_IMPLEMENT int l_sec(lua_State* L)
+ {
+ luax_pushnumber(L, getSecond());
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_sleep(lua_State* L)
+ {
+ double sec = luax_checknumber(L, 1);
+ sleep(sec * 1000.0f);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_newTimer(lua_State* L)
+ {
+ Shared* shrTimer = new Shared(new Timer());
+ luax_newinstance(L, Jin_Lua_Timer, shrTimer);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_getDelta(lua_State* L)
+ {
+ luax_pushnumber(L, context.current - context.previous);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_step(lua_State* L)
+ {
+ context.previous = context.current;
+ context.current = getSecond();
+ return 0;
+ }
+
+ LUA_EXPORT int luaopen_time(lua_State* L)
+ {
+ luaopen_Timer(L);
+ luaL_Reg methods[] = {
+ { "second", l_sec },
+ { "sleep", l_sleep },
+ { "newTimer", l_newTimer },
+ { "step", l_step },
+ { "getDelta", l_getDelta },
+ { 0, 0 },
+ };
+ luax_newlib(L, methods);
+ return 1;
+ }
+
+ } // namespace Lua
+} // namespace JinEngine \ No newline at end of file
diff --git a/src/libjin-lua/modules/time/je_lua_time.h b/src/libjin-lua/modules/time/je_lua_time.h
new file mode 100644
index 0000000..3c75221
--- /dev/null
+++ b/src/libjin-lua/modules/time/je_lua_time.h
@@ -0,0 +1,14 @@
+#ifndef __JE_LUA_TIME_H__
+#define __JE_LUA_TIME_H__
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ int luaopen_time(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/modules/time/je_lua_timer.cpp b/src/libjin-lua/modules/time/je_lua_timer.cpp
new file mode 100644
index 0000000..e30baab
--- /dev/null
+++ b/src/libjin-lua/modules/time/je_lua_timer.cpp
@@ -0,0 +1,132 @@
+#include "common/je_lua_callback.h"
+#include "common/je_lua_common.h"
+#include "je_lua_timer.h"
+
+using namespace JinEngine::Time;
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ const char* Jin_Lua_Timer = "Timer";
+
+ const char* Jin_Lua_Handler = "Handler";
+
+ static Timer::TimerCallback timerCallback = [](void* data)->void
+ {
+ LuaCallback* func = static_cast<LuaCallback*>(data);
+ func->call();
+ };
+
+ static Timer::FinishCallback finishCallback = [](void* data)->void
+ {
+ LuaCallback* func = static_cast<LuaCallback*>(data);
+ delete func;
+ };
+
+ LUA_IMPLEMENT inline Timer* checkTimer(lua_State* L)
+ {
+ LuaObject* luaObj = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Timer);
+ return luaObj->getObject<Timer>();
+ }
+
+ // timer:every(time, callback, parameter)
+ LUA_IMPLEMENT int l_every(lua_State* L)
+ {
+ int n = luax_gettop(L);
+ Timer* shared = checkTimer(L);
+ float s = luax_checknumber(L, 2);
+ LuaCallback* func = new LuaCallback(L);
+ func->setFunc(3);
+ for(int i = 4; i <= n; ++i)
+ func->pushParam(i);
+ Timer::Handler* handler = shared->every(s, timerCallback, func, finishCallback);
+ Shared* shrHandler = new Shared(handler);
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_Handler, shrHandler);
+ return 1;
+ }
+
+ // timer:after(time, callback, parameter)
+ LUA_IMPLEMENT int l_after(lua_State* L)
+ {
+ int n = luax_gettop(L);
+ Timer* shared = checkTimer(L);
+ float s = luax_checknumber(L, 2);
+ LuaCallback* func = new LuaCallback(L);
+ func->setFunc(3);
+ for (int i = 4; i <= n; ++i)
+ func->pushParam(i);
+ Timer::Handler* handler = shared->after(s, timerCallback, func, finishCallback);
+ Shared* shrHandler = new Shared(handler);
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_Handler, shrHandler);
+ return 1;
+ }
+
+ // timer:repeat(time, callback, parameter)
+ LUA_IMPLEMENT int l_repeat(lua_State* L)
+ {
+ int n = luax_gettop(L);
+ Timer* shared = checkTimer(L);
+ float s = luax_checknumber(L, 2);
+ int count = luax_checkinteger(L, 3);
+ LuaCallback* func = new LuaCallback(L);
+ func->setFunc(4);
+ for (int i = 5; i <= n; ++i)
+ func->pushParam(i);
+ Timer::Handler* handler = shared->repeat(s, count, timerCallback, func, finishCallback);
+ Shared* shrHandler = new Shared(handler);
+ LuaObject* luaObj = luax_newinstance(L, Jin_Lua_Handler, shrHandler);
+ return 1;
+ }
+
+ LUA_IMPLEMENT int l_update(lua_State* L)
+ {
+ Timer* shared = checkTimer(L);
+ float s = luax_checknumber(L, 2);
+ shared->update(s);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_cancel(lua_State* L)
+ {
+ LuaObject* p = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Timer);
+ Timer* timer = p->getObject<Timer>();
+ LuaObject* ph = (LuaObject*)luax_checktype(L, 2, Jin_Lua_Handler);
+ Timer::Handler* handler = ph->getObject<Timer::Handler>();
+ timer->cancel(handler);
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_cancelAll(lua_State* L)
+ {
+ LuaObject* p = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Timer);
+ Timer* timer = p->getObject<Timer>();
+ timer->cancelAll();
+ return 0;
+ }
+
+ LUA_IMPLEMENT int l_gc(lua_State* L)
+ {
+ LuaObject* p = (LuaObject*)luax_checktype(L, 1, Jin_Lua_Timer);
+ p->release();
+ return 0;
+ }
+
+ LUA_EXPORT void luaopen_Timer(lua_State* L)
+ {
+ luaL_Reg methods[] = {
+ { "__gc", l_gc },
+ { "every", l_every },
+ { "after", l_after },
+ { "duplicate", l_repeat },
+ { "update", l_update },
+ { "cancel", l_cancel },
+ { "cancelAll", l_cancelAll },
+ { 0, 0 }
+ };
+ luax_newtype(L, Jin_Lua_Timer, methods);
+ }
+
+ }
+} \ No newline at end of file
diff --git a/src/libjin-lua/modules/time/je_lua_timer.h b/src/libjin-lua/modules/time/je_lua_timer.h
new file mode 100644
index 0000000..35ec15d
--- /dev/null
+++ b/src/libjin-lua/modules/time/je_lua_timer.h
@@ -0,0 +1,20 @@
+#ifndef __JE_LUA_TIMER_H__
+#define __JE_LUA_TIMER_H__
+
+#include "libjin/jin.h"
+
+namespace JinEngine
+{
+ namespace Lua
+ {
+
+ extern const char* Jin_Lua_Timer;
+
+ extern const char* Jin_Lua_Handler;
+
+ void luaopen_Timer(lua_State* L);
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin-lua/resources/embed.py b/src/libjin-lua/resources/embed.py
new file mode 100644
index 0000000..7eb825d
--- /dev/null
+++ b/src/libjin-lua/resources/embed.py
@@ -0,0 +1,56 @@
+import os, sys, random, re
+
+def fmt(fmt, dic):
+ for k in dic:
+ fmt = fmt.replace("{%s}" % k, str(dic[k]))
+ return fmt
+
+
+def makeArray(data):
+ i = [0]
+ def fn(x):
+ x = str(ord(x)) + ","
+ if i[0] + len(x) > 78:
+ i[0] = len(x)
+ x = '\n' + x
+ else:
+ i[0] += len(x)
+ return x
+ return '{' + "".join(map(fn, data)).rstrip(",") + '}'
+
+
+def safename(filename):
+ return re.sub("[^a-z0-9]", "_", os.path.basename(filename).lower())
+
+
+def process(filenames):
+ if type(filenames) is str:
+ filenames = [filenames]
+
+ strings = []
+
+ for filename in filenames:
+ data = open(filename, "rb").read()
+ strings.append(
+ fmt("/* {filename} */\n" +\
+ "static const char {name}[] = \n{array};",
+ {
+ "filename" : os.path.basename(filename),
+ "name" : safename(filename),
+ "array" : makeArray(data),
+ }))
+
+ return "/* Automatically generated; do not edit */\n\n" +\
+ "\n\n".join(strings)
+
+
+def main():
+ if len(sys.argv) < 2:
+ print "usage: embed FILENAMES"
+ sys.exit(1)
+
+ print process(sys.argv[1:])
+
+
+if __name__ == "__main__":
+ main() \ No newline at end of file
diff --git a/src/libjin-lua/resources/font.ttf.h b/src/libjin-lua/resources/font.ttf.h
new file mode 100644
index 0000000..b220738
--- /dev/null
+++ b/src/libjin-lua/resources/font.ttf.h
@@ -0,0 +1,369 @@
+static const char
+default_font_bitmap[] =
+{ 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,3,154,0,0,0,14,8,6,0,0,0,78,
+234,99,67,0,0,0,4,103,65,77,65,0,0,177,143,11,252,97,5,0,0,0,9,112,72,89,115,
+0,0,14,189,0,0,14,189,1,71,251,144,173,0,0,0,24,116,69,88,116,83,111,102,116,
+119,97,114,101,0,112,97,105,110,116,46,110,101,116,32,52,46,49,46,49,99,42,
+156,75,0,0,29,72,73,68,65,84,120,94,237,93,61,200,181,73,82,29,4,67,83,13,69,
+16,76,76,6,4,17,131,5,215,81,16,49,80,55,88,21,113,13,12,92,208,100,50,5,13,
+84,12,6,68,5,153,104,52,48,144,85,80,16,35,17,99,127,34,19,77,196,68,35,5,81,
+76,68,228,218,167,78,215,173,83,63,125,239,115,191,239,27,118,132,173,203,121,
+223,167,171,78,87,87,87,87,247,243,60,247,157,111,247,189,219,123,183,27,240,
+94,17,215,79,54,23,229,60,226,65,174,240,174,112,32,202,123,196,125,198,121,
+102,119,81,222,43,220,173,186,235,118,51,201,196,159,100,226,89,107,208,95,
+145,171,253,148,247,105,113,183,106,20,229,157,184,143,108,144,43,125,31,245,
+135,188,202,219,205,167,242,46,253,190,43,142,139,115,175,250,188,194,133,188,
+194,133,92,225,43,231,42,111,171,142,162,220,183,229,159,244,46,207,236,42,87,
+184,87,56,147,104,191,171,125,63,205,62,87,121,85,94,233,115,133,119,213,223,
+85,30,68,185,175,242,183,234,37,249,52,198,121,215,62,159,241,212,254,136,231,
+242,105,242,30,113,175,112,32,159,53,222,219,232,171,205,229,100,127,85,239,
+242,204,14,185,106,175,156,103,253,32,39,142,235,171,237,164,119,81,251,137,
+227,242,166,220,173,74,114,213,190,155,73,62,75,182,147,120,159,79,163,223,21,
+142,202,171,124,151,123,191,123,239,130,170,201,173,64,213,228,86,160,106,78,
+122,197,172,37,246,149,58,216,83,179,201,169,126,76,76,229,24,110,183,79,22,
+62,66,75,197,152,153,187,45,33,198,120,192,217,90,250,207,188,49,62,72,226,
+125,225,126,133,248,32,159,168,125,119,105,178,108,53,46,200,181,121,222,110,
+255,181,240,37,209,249,213,151,22,254,117,225,3,177,65,62,88,128,30,246,237,
+117,244,251,115,11,136,33,235,87,235,138,88,175,11,253,140,149,121,47,229,105,
+155,154,24,51,115,183,37,139,177,50,47,113,67,211,109,46,102,61,216,139,109,
+236,15,49,214,235,188,173,61,75,225,191,149,223,55,229,220,91,2,211,103,238,
+237,246,75,169,21,192,190,42,218,147,95,67,229,159,252,46,92,142,3,186,170,
+189,192,123,41,78,160,248,76,253,31,197,208,109,185,85,237,101,156,132,39,92,
+139,137,159,35,7,112,73,250,234,27,152,252,75,123,236,147,91,29,53,62,32,183,
+136,87,107,107,193,236,213,255,48,255,59,148,27,247,136,140,26,135,218,20,53,
+23,143,114,247,36,111,46,119,221,3,223,137,119,130,246,47,113,37,212,113,196,
+214,198,121,7,62,19,248,201,26,109,85,63,142,174,33,170,191,139,235,107,19,93,
+146,56,192,80,143,165,69,116,94,110,57,234,124,78,57,172,188,139,243,184,204,
+91,45,155,47,63,207,245,30,231,180,30,117,14,157,51,251,124,162,119,49,235,3,
+59,196,24,131,253,174,169,49,241,185,235,43,246,219,117,101,30,46,171,21,125,
+53,191,53,167,222,191,142,85,252,54,59,177,71,203,2,189,112,12,219,52,74,226,
+214,90,24,106,32,181,52,174,26,51,63,108,85,191,143,250,229,49,179,237,234,
+120,181,95,129,203,106,101,102,245,121,66,237,23,243,251,112,193,158,249,167,
+220,217,152,170,81,84,159,207,248,14,237,87,109,142,170,201,173,64,213,228,86,
+160,106,110,183,111,177,171,170,87,204,90,98,95,169,3,155,60,196,180,161,31,
+139,185,114,12,159,229,23,205,159,177,159,241,34,247,155,171,45,246,221,165,
+137,177,132,103,248,218,139,102,19,99,190,57,119,91,178,24,43,243,18,55,52,
+221,230,98,86,183,127,238,126,69,160,157,53,187,87,22,99,189,206,219,218,179,
+20,254,91,249,125,83,206,110,161,222,254,123,1,135,233,182,218,199,91,16,212,
+230,127,218,85,200,135,233,6,17,92,191,242,47,117,92,58,159,99,86,225,129,14,
+212,53,154,249,31,38,14,121,117,108,204,79,247,34,196,175,42,247,163,195,188,
+48,54,30,72,222,95,208,252,161,127,250,226,106,243,99,63,103,155,95,157,206,1,
+248,199,56,177,30,28,99,154,67,59,51,150,190,230,204,215,110,138,29,240,156,
+78,121,116,27,207,155,0,124,230,135,51,7,127,250,28,84,56,159,190,239,32,149,
+251,201,147,218,66,60,42,81,51,125,254,115,45,192,170,177,240,97,164,214,249,
+84,179,53,86,151,92,3,186,190,75,35,57,63,213,11,252,198,60,2,157,207,249,215,
+53,1,15,177,219,120,27,189,198,184,14,145,131,224,241,12,112,13,185,83,76,104,
+67,255,190,240,188,78,170,48,30,237,29,62,92,56,143,90,23,188,103,59,183,251,
+113,244,90,155,253,113,125,125,158,16,206,1,227,8,207,22,106,201,214,68,94,10,
+207,192,177,84,62,105,227,162,205,43,157,115,206,31,208,125,185,228,53,225,60,
+52,223,92,203,90,167,157,199,28,246,121,112,190,252,60,215,71,190,167,243,66,
+247,207,180,102,179,207,39,122,23,179,62,176,67,140,81,236,210,3,107,80,247,
+82,63,203,168,75,231,42,100,217,194,55,235,19,107,246,81,203,41,251,157,206,
+246,223,95,248,237,133,94,3,196,30,45,11,244,194,49,108,211,40,137,203,90,192,
+216,136,247,131,86,43,81,163,61,110,214,16,99,133,70,227,96,14,188,198,242,
+122,135,158,245,169,57,138,241,16,79,206,3,99,224,158,131,70,199,203,113,250,
+62,166,127,234,125,238,209,7,96,236,24,7,18,115,9,125,31,11,96,222,242,89,85,
+115,151,91,191,178,128,88,128,143,77,87,125,198,28,128,186,231,99,46,224,57,
+43,248,25,85,147,91,129,170,225,207,111,92,248,229,133,239,218,237,137,247,
+151,11,223,211,244,138,89,75,236,43,117,108,11,4,49,109,232,199,98,174,28,131,
+111,186,210,197,152,153,187,45,33,198,120,192,217,90,250,207,188,49,62,72,226,
+177,96,176,128,216,228,239,215,98,217,93,154,24,75,120,134,171,243,196,198,
+202,7,144,90,171,13,242,252,112,35,239,107,47,154,75,66,211,109,46,102,117,59,
+15,69,228,150,7,105,205,255,208,31,98,172,215,121,91,123,150,194,127,43,191,
+111,194,185,95,177,150,255,109,97,190,153,0,165,54,247,111,220,88,234,75,20,
+196,15,239,122,160,163,102,235,141,55,223,196,8,240,168,235,123,164,243,251,
+58,66,248,64,161,218,238,11,63,99,172,176,160,239,233,165,235,206,181,156,6,
+255,211,124,209,196,111,222,196,235,77,174,172,139,197,196,207,196,129,15,247,
+233,192,88,56,19,105,83,11,16,99,199,141,159,128,79,196,152,99,7,24,11,248,
+118,70,110,128,15,63,167,151,120,157,175,207,191,157,245,75,220,143,174,173,
+243,169,211,27,52,251,212,90,64,27,252,92,95,225,91,227,192,3,97,125,33,240,
+171,88,63,180,123,125,37,187,173,13,45,167,122,137,184,66,235,115,171,47,128,
+136,177,114,49,71,136,174,19,199,210,47,86,113,77,174,230,4,215,31,213,47,96,
+151,192,23,114,194,57,106,60,202,197,220,163,23,16,188,94,179,234,211,121,189,
+46,200,131,160,62,251,62,9,30,230,232,115,14,127,125,61,48,30,230,9,206,113,
+92,89,39,32,114,250,188,110,137,90,127,232,199,24,53,223,189,94,122,14,225,23,
+254,107,253,161,174,144,63,219,243,11,81,55,207,121,185,22,8,214,38,63,207,
+245,145,187,233,188,248,173,5,175,21,204,183,214,249,236,243,137,222,197,172,
+15,236,16,99,20,251,110,33,46,158,149,97,135,64,143,249,68,125,113,143,32,95,
+128,105,205,143,250,230,186,114,223,244,218,69,206,249,172,153,245,200,29,244,
+120,33,233,118,162,107,168,109,22,11,234,32,137,27,53,130,223,24,55,175,11,
+107,207,99,203,95,90,212,92,104,125,51,7,168,83,214,182,214,52,251,69,206,213,
+39,199,139,188,107,77,178,95,248,212,241,34,78,214,31,181,62,55,232,201,156,
+239,1,140,255,124,141,62,181,159,239,193,95,92,0,239,203,11,185,126,48,22,175,
+48,62,98,198,188,208,143,241,105,78,0,230,12,245,81,239,145,0,250,98,207,230,
+154,202,156,64,213,228,86,160,106,248,243,23,22,254,105,1,107,78,139,114,128,
+219,237,91,23,254,167,233,21,252,249,195,11,63,176,175,129,111,179,223,187,
+165,142,119,121,14,155,57,174,2,117,33,1,223,116,89,219,185,177,48,129,186,24,
+19,199,253,87,109,110,5,180,197,226,141,205,175,133,13,196,85,70,141,11,184,
+58,79,244,205,253,213,218,125,235,166,124,204,155,95,52,193,139,214,25,83,156,
+106,119,212,113,129,220,10,84,159,64,110,5,42,119,94,235,121,252,26,171,114,
+38,63,58,86,212,0,31,90,106,13,92,205,195,21,222,137,163,120,151,126,95,229,
+196,149,223,92,112,40,70,237,241,227,92,72,173,205,104,43,143,92,236,141,124,
+240,59,114,12,16,63,200,43,151,123,172,239,211,196,31,207,43,242,16,131,237,
+17,23,99,117,206,181,56,129,105,108,90,56,150,114,129,115,142,252,42,106,81,
+237,244,143,113,48,30,56,241,176,88,247,78,89,23,139,137,159,137,19,223,162,
+135,21,253,176,254,172,1,237,7,196,156,113,163,245,151,3,88,240,27,250,233,69,
+115,62,31,117,46,213,18,243,117,13,174,79,47,99,60,251,50,16,15,124,247,191,
+60,245,62,136,131,121,87,110,228,34,215,67,241,39,235,30,126,208,230,231,206,
+91,146,236,210,239,84,47,145,159,208,134,143,199,92,95,15,64,115,207,181,152,
+31,242,152,47,2,215,253,203,183,92,139,208,224,55,218,245,75,32,157,31,16,57,
+239,53,91,235,35,124,42,143,113,2,115,14,28,93,195,177,117,206,64,248,115,204,
+188,184,66,92,168,7,206,191,242,0,218,117,189,78,123,20,62,88,39,39,222,106,
+73,14,145,119,250,238,241,97,60,173,211,57,63,186,6,68,196,161,60,31,151,159,
+231,122,141,77,245,64,206,49,199,87,141,219,115,237,156,245,171,165,98,214,7,
+118,136,49,138,125,183,230,58,155,242,130,156,151,60,155,31,245,77,14,242,59,
+125,153,2,159,176,61,122,209,252,120,172,169,208,228,186,225,71,121,125,242,
+34,137,251,187,246,19,243,225,23,134,104,171,157,115,65,126,250,158,165,45,98,
+209,53,170,253,248,169,253,80,155,185,142,105,139,252,62,178,233,120,172,19,
+228,16,177,96,92,180,99,124,175,185,90,71,252,235,34,124,58,31,188,199,235,
+203,126,190,135,188,79,175,81,228,138,156,73,78,245,230,103,175,207,5,2,29,
+226,241,92,199,253,56,122,59,190,123,225,79,154,246,118,251,247,133,31,219,
+173,64,110,65,240,243,31,23,190,207,90,183,219,55,47,156,120,93,175,184,221,
+126,221,126,82,126,117,1,218,255,88,248,38,231,168,3,75,52,196,180,161,135,
+224,167,38,242,244,159,53,129,227,15,51,46,125,19,70,33,161,232,93,242,67,14,
+57,88,136,42,167,23,77,141,111,90,220,234,171,126,67,140,159,234,3,133,201,13,
+162,60,114,235,60,49,143,252,159,6,144,247,86,255,233,236,2,198,161,239,204,
+155,95,52,195,47,14,49,23,223,32,46,211,183,111,62,46,250,249,154,244,28,146,
+139,159,154,39,198,55,215,67,245,201,135,153,185,30,174,174,53,198,198,218,
+192,23,98,140,27,25,253,104,108,249,63,99,234,99,228,155,160,174,11,53,113,
+160,101,30,242,201,252,100,94,196,219,125,97,108,206,63,218,117,124,248,85,14,
+230,146,215,161,143,237,60,29,27,253,225,71,133,126,157,19,89,65,28,238,15,
+126,128,167,47,52,11,209,79,121,228,66,15,187,105,84,150,166,250,213,241,201,
+161,101,246,95,248,134,186,239,200,67,158,56,23,71,223,159,41,206,132,217,103,
+31,155,224,88,170,1,52,103,217,230,87,81,35,106,167,127,140,131,189,131,117,
+139,24,249,81,110,90,23,203,223,153,3,63,186,134,0,114,4,61,127,107,63,32,207,
+57,234,131,62,161,175,15,173,144,20,15,4,215,11,62,175,105,28,234,67,115,202,
+233,157,231,130,235,13,196,54,157,111,181,22,98,30,249,124,192,156,114,190,
+129,146,79,25,51,214,111,224,45,73,118,233,119,154,155,231,7,118,215,146,219,
+191,112,137,92,82,131,177,240,144,130,47,4,160,135,221,215,61,159,207,124,48,
+2,208,23,118,128,126,250,190,119,30,124,250,154,79,220,184,162,61,206,49,126,
+194,202,56,181,6,35,79,202,139,94,39,187,193,18,187,100,107,34,135,181,14,98,
+222,64,228,175,159,11,248,233,185,195,95,48,200,171,254,200,213,115,22,188,
+211,127,133,129,57,195,238,50,249,211,22,250,244,26,5,248,133,41,108,92,7,214,
+200,244,165,92,173,251,168,7,229,173,94,150,63,126,158,235,153,59,174,161,234,
+129,200,113,228,87,237,186,62,89,143,53,70,46,199,216,92,208,22,91,179,67,140,
+33,118,97,51,103,61,79,94,215,81,95,88,67,157,195,210,54,223,88,63,247,89,215,
+146,253,251,125,196,245,142,186,182,132,95,69,92,212,118,46,215,120,146,41,
+191,220,67,30,179,218,57,23,214,17,52,58,86,228,130,107,174,115,101,191,168,
+85,237,71,91,212,92,239,135,152,224,243,241,139,166,218,34,127,24,211,37,206,
+26,198,63,125,121,20,115,139,107,230,33,88,211,249,135,56,240,252,10,46,251,
+87,78,212,60,184,120,54,69,174,192,103,76,181,6,52,95,234,55,98,194,53,57,209,
+199,175,190,115,225,143,22,254,97,225,199,239,90,199,237,246,249,133,63,182,
+43,125,225,236,188,31,89,248,235,221,250,243,133,95,179,235,206,227,85,213,43,
+110,183,255,93,248,246,221,250,67,40,150,252,222,194,189,159,58,176,141,4,49,
+109,232,33,152,180,47,72,20,142,114,200,67,146,248,226,65,13,126,247,195,131,
+122,240,98,145,251,98,68,95,106,48,46,218,211,203,135,23,142,107,184,96,202,
+225,225,12,95,44,222,249,80,198,166,70,145,64,131,54,231,162,60,114,235,60,
+209,158,30,6,222,230,69,51,226,233,155,230,209,139,166,111,10,104,144,95,136,
+231,6,246,105,61,60,183,62,127,111,79,15,132,156,107,104,48,6,184,211,3,167,
+250,132,38,230,148,121,17,23,53,62,143,105,173,49,54,199,115,109,216,16,139,
+142,151,15,133,168,1,230,190,175,87,216,168,129,31,248,171,55,75,93,39,104,
+162,95,112,208,151,7,51,53,254,114,236,53,143,121,100,191,140,15,122,228,9,
+253,250,65,123,101,236,124,51,11,190,250,137,195,209,199,195,117,172,101,223,
+143,240,3,155,74,255,102,148,92,230,108,181,170,24,59,115,211,154,25,135,150,
+62,175,224,171,156,246,40,230,164,194,121,101,206,61,206,13,228,194,101,170,
+189,58,182,202,244,226,16,185,207,54,191,58,205,209,235,14,130,152,204,98,185,
+233,249,75,245,112,129,131,188,184,207,24,159,186,105,191,235,250,128,143,124,
+67,135,62,208,231,216,217,39,197,3,193,245,6,235,77,53,64,94,11,248,230,94,
+121,192,83,65,123,129,115,155,31,50,84,124,156,156,43,244,163,13,194,122,129,
+165,60,88,200,120,154,191,236,11,40,246,22,167,114,1,254,196,248,158,239,56,
+67,234,156,120,86,232,90,226,26,136,117,225,248,60,67,242,126,246,43,175,179,
+123,141,237,143,183,32,248,9,95,152,7,190,248,160,191,206,245,43,112,185,118,
+97,81,30,228,94,31,27,145,39,229,69,175,147,157,200,45,204,133,249,171,103,24,
+207,60,95,95,8,99,236,103,157,231,5,246,184,174,107,64,174,182,48,246,244,28,
+128,117,209,231,5,248,237,231,81,244,138,117,167,54,251,139,251,132,202,244,2,
+133,113,234,184,211,121,201,218,172,227,156,244,26,159,234,1,222,123,60,103,
+211,151,62,97,203,122,196,136,156,100,159,244,23,168,107,181,90,85,140,33,246,
+125,21,53,212,215,59,246,140,235,226,254,136,156,205,251,131,231,5,108,227,
+151,6,67,44,119,189,139,89,179,93,231,172,123,121,154,123,159,188,72,226,62,
+203,99,212,20,230,203,168,220,150,159,21,242,92,153,131,200,145,246,163,205,
+207,142,124,134,113,60,244,195,252,166,191,90,198,122,105,93,211,230,53,4,59,
+160,53,142,56,78,127,76,65,125,65,208,23,95,200,145,27,210,215,145,115,128,
+111,140,193,113,42,39,114,139,249,0,24,11,190,17,231,244,242,138,49,157,23,
+235,75,29,243,200,49,63,150,62,63,177,240,7,11,152,195,207,47,208,226,246,224,
+249,213,119,44,252,197,194,223,46,124,49,113,128,219,237,207,22,126,118,183,
+190,119,1,255,116,234,235,6,30,175,170,94,209,53,95,127,191,222,26,117,176,
+203,115,60,88,240,211,147,237,114,122,9,65,18,85,11,93,125,80,7,199,19,122,26,
+51,113,54,232,95,53,0,23,171,202,87,18,39,10,134,55,202,94,136,240,129,133,
+118,77,108,16,229,1,125,158,232,135,254,245,5,234,77,95,52,17,35,253,193,210,
+11,245,217,95,52,189,112,99,14,181,157,251,85,30,112,202,117,229,249,166,159,
+234,161,114,49,14,184,117,222,175,172,117,205,125,228,128,254,177,17,121,19,
+135,86,15,176,168,1,196,53,253,123,183,176,81,51,207,45,14,101,143,153,49,233,
+129,72,14,226,4,224,15,28,63,220,230,60,48,62,159,67,28,158,186,254,225,215,
+199,230,181,142,29,87,17,63,218,234,135,135,163,143,229,117,31,237,236,15,2,
+155,174,167,251,126,248,210,80,101,217,171,223,216,59,155,143,223,73,255,128,
+111,208,53,14,158,230,136,168,60,137,179,128,235,89,181,211,216,4,199,82,13,
+160,57,203,54,191,138,122,83,123,228,214,255,58,21,243,224,71,185,105,93,44,
+127,143,57,0,214,24,191,57,79,178,112,61,237,225,58,103,240,209,255,167,22,
+160,207,177,179,79,138,7,130,235,5,159,215,52,14,244,42,167,7,123,246,95,45,
+23,92,111,112,62,125,95,107,45,120,252,200,73,206,85,60,80,57,15,210,94,92,
+101,76,204,145,235,135,182,250,2,138,93,250,49,30,229,2,252,169,107,21,185,
+175,181,203,179,2,28,220,43,208,39,94,76,124,45,9,206,91,247,126,204,19,113,
+248,189,198,114,154,120,64,92,121,62,200,3,248,97,43,124,98,60,207,53,231,172,
+60,32,199,10,68,158,148,23,189,78,118,130,63,145,3,172,235,125,236,54,151,136,
+209,193,88,31,215,75,212,108,61,19,23,108,130,75,182,102,142,51,251,3,230,125,
+16,241,197,186,163,205,79,240,104,143,26,230,184,220,211,202,99,141,248,186,
+65,144,119,230,94,121,203,187,205,161,142,115,210,51,174,201,143,142,201,249,
+214,53,224,125,167,159,197,39,125,172,171,75,61,59,44,70,21,232,238,246,200,
+233,57,38,142,129,124,235,186,249,85,216,168,13,11,231,10,159,239,246,69,51,
+175,153,74,187,39,109,55,163,20,238,214,82,208,22,27,36,214,212,216,246,185,
+247,221,87,136,43,159,175,204,65,156,51,218,143,54,228,141,231,153,246,227,56,
+220,43,208,232,186,123,45,232,62,112,13,159,127,48,22,98,113,173,215,63,190,8,
+163,207,83,125,17,190,166,184,135,193,23,230,14,31,152,127,126,222,200,123,18,
+118,60,151,229,26,100,95,125,55,82,249,112,168,55,214,140,142,73,11,243,203,
+107,230,52,250,252,134,253,196,76,194,83,246,11,228,214,247,47,252,243,194,
+223,36,45,112,187,253,144,180,128,31,92,248,134,164,1,252,170,234,21,179,150,
+216,87,234,96,151,224,88,132,88,20,46,56,129,235,233,97,161,22,192,204,37,135,
+133,233,232,7,76,231,184,127,213,0,62,70,214,102,127,44,250,88,88,45,122,160,
+251,136,13,162,60,160,207,19,253,152,159,204,123,147,23,77,108,24,124,187,16,
+55,146,94,168,255,95,95,52,35,190,204,123,101,173,107,238,35,7,60,132,0,140,
+131,141,159,215,36,106,128,49,244,26,8,27,53,243,220,178,159,120,224,214,26,
+206,245,134,23,6,196,12,191,244,135,111,171,234,131,11,251,128,131,181,159,95,
+52,121,96,250,216,63,186,0,255,87,254,90,9,123,112,152,43,216,38,201,121,3,24,
+23,198,100,76,4,215,77,121,128,235,179,150,232,251,60,246,142,242,60,246,154,
+163,194,31,207,43,242,238,49,184,24,235,192,1,140,195,107,142,237,45,199,52,
+54,45,167,60,68,206,178,205,175,188,62,106,174,163,238,162,30,48,198,233,33,
+233,190,46,22,83,159,103,93,59,204,47,254,105,64,232,166,61,92,215,199,99,115,
+244,135,127,207,95,214,2,24,11,115,153,206,84,159,111,104,235,92,129,178,102,
+2,207,211,179,127,163,233,241,247,124,114,111,41,198,245,147,117,199,124,96,7,
+143,89,23,222,146,154,119,7,227,81,13,16,87,158,191,200,99,205,5,99,117,255,
+200,27,184,190,70,232,227,253,153,83,141,45,206,38,174,5,57,184,110,15,104,
+167,185,154,190,251,12,63,155,3,73,60,160,175,53,174,161,203,251,32,122,197,
+216,217,78,228,185,152,118,28,183,175,239,236,151,190,38,121,180,102,192,201,
+31,230,231,245,7,196,254,86,30,227,11,155,91,234,60,180,46,136,217,95,220,7,
+28,136,175,159,55,203,251,195,124,149,154,88,130,241,120,223,81,61,192,62,94,
+123,221,231,106,189,52,150,235,29,213,190,90,85,140,225,118,246,207,251,80,
+237,0,237,200,159,174,155,50,34,223,253,188,224,30,59,196,101,218,65,239,98,
+214,108,215,57,71,92,104,247,49,32,136,107,146,122,255,218,35,82,208,22,155,
+190,192,177,238,212,30,117,68,187,62,107,196,190,239,235,77,91,228,94,251,113,
+188,216,247,58,55,206,63,246,146,62,3,104,237,81,227,128,47,72,95,39,66,91,62,
+79,248,192,125,16,58,248,133,62,239,221,88,11,240,225,155,115,85,14,231,18,
+253,131,75,70,141,133,54,32,114,195,107,156,59,240,209,247,51,127,242,223,101,
+222,110,255,178,240,69,211,185,61,243,240,18,249,87,11,127,183,240,147,166,
+155,121,29,85,115,210,43,102,45,177,175,212,193,46,193,161,8,153,0,36,15,45,
+252,134,76,15,37,72,210,253,70,179,0,46,219,153,135,196,66,239,197,130,223,95,
+46,28,244,141,135,109,254,70,123,122,0,196,162,177,96,169,65,223,28,31,139,30,
+62,120,208,106,209,3,140,93,125,192,39,199,87,94,112,163,144,56,30,251,102,
+222,219,252,167,179,145,187,30,235,87,243,69,19,122,142,77,204,107,12,80,175,
+92,246,157,95,30,174,174,53,227,82,109,216,248,191,8,198,22,126,51,23,110,143,
+26,160,190,199,129,60,32,102,196,3,13,126,67,30,61,16,224,75,1,206,177,223,
+132,60,175,224,120,92,224,162,221,255,242,194,3,203,231,135,177,89,83,122,8,
+231,67,31,232,28,206,179,238,137,124,163,138,248,25,123,0,113,114,111,170,54,
+230,226,243,240,254,211,26,121,30,213,55,248,104,215,154,143,121,134,118,158,
+215,137,95,57,228,97,254,54,190,139,177,50,103,138,19,64,123,154,87,26,219,
+124,210,194,177,148,11,104,206,84,143,120,121,197,126,189,14,61,183,24,15,26,
+228,28,251,161,127,115,222,215,165,231,163,115,220,159,206,27,215,211,153,62,
+173,143,247,71,238,166,125,239,118,204,207,181,158,235,94,247,128,204,215,197,
+88,157,55,173,153,231,139,186,249,198,174,124,196,7,31,245,91,118,140,175,188,
+113,253,44,54,182,224,7,118,240,122,188,177,159,53,127,49,182,114,23,196,47,
+226,0,135,60,232,170,239,126,14,212,249,97,76,220,235,122,108,145,47,95,159,
+200,95,169,197,211,92,77,159,125,250,186,120,205,6,30,239,97,31,123,252,171,
+208,190,138,177,179,157,224,220,181,214,136,121,92,229,49,111,125,255,105,43,
+226,171,60,128,118,229,77,127,33,173,185,241,245,205,243,65,63,114,225,103,
+206,51,160,253,169,153,107,42,206,25,224,156,103,231,205,249,234,113,178,174,
+223,27,243,145,199,236,123,241,60,214,60,135,197,82,65,91,108,205,14,49,134,
+219,153,83,204,3,115,231,90,169,29,208,156,135,158,190,216,66,108,124,110,212,
+184,233,155,168,243,241,254,252,52,189,139,89,179,221,56,251,42,213,194,254,
+40,175,79,94,164,112,183,150,130,182,216,124,46,177,143,212,206,53,155,235,39,
+242,203,243,71,251,209,134,216,121,134,246,126,145,215,171,54,214,30,247,45,
+53,128,199,6,161,190,174,71,156,151,17,171,142,161,215,206,4,152,15,244,1,112,
+205,177,149,195,252,96,158,176,193,23,94,94,225,111,206,181,230,132,126,33,
+168,125,252,209,2,191,33,249,62,25,189,129,207,45,252,233,194,244,151,74,252,
+5,243,239,23,126,122,33,44,202,1,114,43,80,53,39,189,98,214,18,251,74,29,88,
+82,32,166,13,61,4,9,118,193,98,176,224,148,67,30,18,237,255,22,13,130,135,141,
+92,96,0,11,201,19,12,129,191,188,192,228,232,184,224,96,236,233,1,16,63,49,
+182,11,11,73,57,44,134,40,166,90,136,44,16,47,86,72,124,227,175,60,114,225,
+159,27,146,192,92,250,28,222,254,127,12,200,231,159,231,252,213,125,209,172,
+121,226,141,168,174,49,185,240,137,255,209,36,23,230,168,230,254,181,181,174,
+185,15,95,61,182,124,40,178,6,148,147,15,140,30,199,92,235,249,208,98,141,163,
+205,79,229,32,94,206,187,246,233,53,168,92,143,179,254,47,168,249,149,239,31,
+252,206,55,116,198,131,49,84,56,102,230,240,198,190,52,182,239,105,1,16,71,
+206,13,107,196,247,181,203,233,165,1,63,235,90,204,103,65,204,67,37,214,183,
+62,168,156,248,202,33,15,62,48,15,155,27,100,233,171,47,191,2,79,133,53,173,
+92,128,99,223,215,210,124,210,194,177,148,11,156,247,155,215,24,199,57,159,69,
+92,91,194,231,93,207,130,105,93,242,63,27,208,56,168,153,252,35,7,87,95,52,1,
+240,79,121,194,207,41,46,142,87,215,148,125,238,241,184,24,171,243,240,179,
+214,22,36,246,97,207,231,189,22,4,104,115,94,174,233,251,31,210,30,204,45,54,
+182,48,30,242,138,185,246,120,251,121,227,50,189,84,169,95,239,195,248,160,
+171,190,163,229,117,161,107,249,184,191,174,93,244,193,92,144,195,84,3,167,
+185,154,190,251,156,164,215,8,127,42,31,57,159,234,194,175,98,236,108,39,122,
+126,33,156,187,242,184,190,58,46,57,165,94,108,114,75,182,198,115,121,250,255,
+209,212,26,135,239,62,15,142,235,249,133,204,103,33,235,37,237,55,139,131,159,
+234,79,235,244,116,182,214,61,56,239,63,198,198,231,162,172,7,127,90,63,247,
+219,207,11,248,102,108,156,67,31,11,243,194,88,245,76,68,12,240,153,245,171,
+183,10,218,98,107,118,136,49,220,30,47,38,172,49,235,97,31,111,65,48,31,196,
+171,243,164,47,182,34,102,205,49,245,232,247,209,84,187,214,159,159,166,119,
+49,107,182,27,103,95,69,92,212,54,238,118,51,74,225,110,45,5,109,177,121,77,
+97,189,123,13,211,22,177,232,62,168,253,212,111,244,227,189,71,115,71,91,212,
+221,35,155,142,199,61,226,121,87,65,12,170,207,247,73,214,37,124,198,121,77,
+248,62,154,247,16,99,209,51,163,127,145,68,223,35,158,228,26,130,223,106,13,
+232,26,84,27,241,249,166,185,221,126,71,90,129,170,201,173,64,213,156,244,138,
+89,75,236,43,117,96,73,129,152,54,244,16,109,17,211,161,203,34,232,168,155,
+112,90,152,234,239,180,120,211,184,185,21,208,86,245,87,99,82,27,17,69,89,45,
+167,121,214,216,208,206,58,191,154,125,191,234,23,173,170,143,214,25,147,63,
+181,59,42,15,200,173,64,205,39,224,7,76,214,94,171,7,191,57,84,237,20,171,95,
+77,54,29,171,142,83,231,55,199,49,229,33,183,66,171,150,108,155,80,243,48,197,
+15,204,115,192,1,133,67,21,135,43,71,118,203,201,143,206,163,112,92,238,186,
+58,231,43,177,57,114,43,227,234,156,23,44,30,126,66,59,241,107,172,128,240,92,
+86,43,241,76,119,111,21,60,241,9,164,254,143,248,213,86,252,188,146,147,167,
+190,128,43,156,9,181,31,80,250,166,57,3,83,159,220,234,224,39,107,165,229,178,
+90,15,121,5,56,103,240,176,192,7,6,181,200,28,204,111,88,114,252,177,183,50,
+202,250,52,31,142,26,239,201,31,80,215,124,225,232,23,168,190,91,239,39,208,
+254,101,77,19,202,122,158,98,50,253,27,250,148,171,12,245,231,26,109,85,63,
+142,174,33,42,255,133,245,133,36,14,48,172,89,105,17,252,132,230,226,184,19,
+207,226,120,83,127,167,53,169,254,120,47,233,255,76,193,251,215,60,158,244,64,
+141,173,198,196,135,124,220,219,243,75,237,217,167,229,192,197,172,15,236,16,
+99,184,93,159,181,150,166,217,201,137,151,168,208,147,27,44,188,144,228,191,
+126,123,204,64,157,167,247,231,167,233,93,204,154,237,198,105,26,106,155,101,
+187,25,165,112,183,150,130,182,216,124,46,243,11,53,95,214,49,127,190,172,235,
+92,227,165,137,47,154,186,126,236,55,191,104,114,188,200,187,230,149,253,194,
+167,142,87,235,235,132,90,71,87,251,213,117,140,126,220,35,19,103,181,30,137,
+177,149,31,62,49,127,253,34,200,5,99,229,126,209,59,163,106,114,43,80,53,185,
+21,168,154,147,94,49,107,137,125,165,14,118,90,122,98,182,58,73,229,108,108,
+107,22,232,133,51,242,140,241,132,3,49,86,230,205,196,37,133,183,181,20,180,
+197,6,193,226,114,129,9,20,121,255,207,106,136,237,37,11,244,194,49,222,254,
+176,29,7,83,63,180,136,237,41,139,177,10,207,62,188,74,250,43,98,189,46,244,
+51,86,230,29,7,48,102,225,46,185,191,104,170,24,51,115,183,133,178,181,243,
+139,166,112,67,211,109,46,102,61,216,139,109,236,15,49,214,235,188,173,61,75,
+225,95,243,203,131,61,190,73,189,247,180,207,117,63,7,142,75,225,94,245,105,
+216,166,81,140,157,249,219,50,139,177,159,240,141,145,57,151,120,91,61,74,229,
+110,108,107,23,216,132,151,248,248,45,186,187,222,197,172,15,236,42,198,124,
+194,53,198,19,206,36,214,43,247,123,218,23,118,225,26,182,233,40,214,227,66,
+31,99,93,225,37,198,66,125,200,88,173,147,24,243,9,175,112,142,206,42,15,173,
+147,24,51,115,207,228,37,198,206,252,109,185,38,214,251,66,223,194,123,37,166,
+173,237,82,120,71,98,229,161,165,98,214,108,55,108,115,147,101,171,252,109,
+201,98,44,225,109,117,147,202,3,182,41,137,177,50,111,91,178,24,235,179,192,
+243,255,212,239,176,111,76,123,77,127,183,185,160,45,54,8,31,216,245,165,131,
+152,249,91,239,98,86,181,199,51,85,64,231,225,207,90,219,54,250,208,23,158,
+208,27,23,178,53,206,209,87,150,205,56,199,109,218,65,239,98,214,108,111,28,
+23,232,133,99,216,166,81,10,119,107,41,104,139,77,103,213,255,8,194,53,195,
+220,79,95,106,195,14,201,127,253,14,61,191,252,211,117,137,241,176,54,244,237,
+26,198,128,62,124,30,215,241,214,213,21,41,125,222,170,95,106,81,211,56,143,
+196,216,133,159,90,39,104,191,106,115,84,77,110,5,170,38,183,2,85,115,210,43,
+102,45,177,175,212,193,78,75,79,204,86,39,169,156,141,109,205,2,189,112,70,
+158,49,158,112,32,198,202,188,153,184,164,240,182,150,130,182,216,32,248,137,
+162,119,97,241,247,3,17,216,94,178,64,47,28,227,237,15,219,60,244,32,220,144,
+135,195,182,138,177,10,207,62,188,74,250,43,98,189,46,244,51,86,230,29,7,48,
+102,225,46,249,218,139,230,3,41,252,107,126,227,240,126,116,243,52,93,149,43,
+28,151,194,189,234,211,176,77,163,24,59,243,183,101,22,99,63,225,27,35,115,46,
+241,182,122,148,202,221,216,214,46,176,9,47,241,241,91,116,119,189,139,89,31,
+216,85,140,249,132,107,140,39,156,73,172,87,238,247,180,47,236,194,53,108,211,
+81,172,199,133,62,198,186,192,171,98,189,114,191,109,233,98,204,39,188,194,57,
+58,171,60,180,78,98,204,204,125,56,55,99,103,254,182,92,19,235,125,161,111,
+225,189,18,211,214,118,41,188,35,177,242,208,82,49,107,182,27,182,185,201,178,
+85,254,182,100,49,150,240,182,186,73,229,1,219,148,196,88,153,183,45,89,140,
+245,89,224,241,203,203,247,110,95,88,80,253,238,111,218,107,250,187,205,5,109,
+177,189,241,88,46,102,85,123,126,102,115,137,127,198,224,227,45,184,172,86,
+245,113,229,69,147,200,207,108,155,113,142,219,180,131,222,197,172,217,222,56,
+46,208,11,199,176,77,163,20,238,214,82,208,22,155,217,83,75,231,41,57,52,104,
+95,172,163,218,30,245,203,107,158,109,87,199,91,87,87,164,244,121,167,253,140,
+241,132,163,98,236,23,248,46,214,203,251,104,111,69,213,228,86,160,106,114,43,
+80,53,39,189,98,214,18,246,243,118,251,63,227,27,138,9,123,111,123,255,0,0,0,
+0,73,69,78,68,174,66,96,130 };
+
+static const char*
+default_charset = R"( abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.!?;:-_/|\!'"+=*()[]{}&%$#@<>^`~)";
+
+#include "libjin/jin.h"
+
+static const JinEngine::Graphics::Color default_font_split(255, 0, 255, 255);