summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/audio/audio.c51
-rw-r--r--src/audio/audio.h11
-rw-r--r--src/main.c23
-rw-r--r--src/modules.h25
-rw-r--r--src/nvg/CMakeLists.txt3
-rw-r--r--src/nvg/color.c117
-rw-r--r--src/nvg/composite.c35
-rw-r--r--src/nvg/context.c23
-rw-r--r--src/nvg/frame.c32
-rw-r--r--src/nvg/image.c39
-rw-r--r--src/nvg/nvg.h143
-rw-r--r--src/nvg/path.c117
-rw-r--r--src/nvg/render.c95
-rw-r--r--src/nvg/setup.c30
-rw-r--r--src/nvg/state.c29
-rw-r--r--src/nvg/transform.c86
-rw-r--r--src/util/util.c21
-rw-r--r--src/util/util.h17
-rw-r--r--src/vector/CMakeLists.txt3
-rw-r--r--src/vector/vector.c238
-rw-r--r--src/vector/vector.h6
21 files changed, 849 insertions, 295 deletions
diff --git a/src/audio/audio.c b/src/audio/audio.c
index 45d11c2..412a434 100644
--- a/src/audio/audio.c
+++ b/src/audio/audio.c
@@ -1,5 +1,5 @@
#include <lua.h>
-#include <honeysuckle.h>
+#include <lauxlib.h>
#define STB_VORBIS_HEADER_ONLY
#include <stb_vorbis.c>
@@ -11,64 +11,57 @@
/* stb_vorbis defines this for some reason? */
#undef L
+#include "util/util.h"
#include "audio.h"
-int audio_engine_init(lua_State *L);
-int audio_engine_uninit(lua_State *L);
-int audio_engine_play_sound(lua_State *L);
+const char *audio_engine_tname = "audio.Engine";
void setup_audio(lua_State *L, int honey_tbl)
{
- hs_create_table(L,
- hs_str_cfunc("engine_init", audio_engine_init),
- hs_str_cfunc("engine_uninit", audio_engine_uninit),
- hs_str_cfunc("engine_play_sound", audio_engine_play_sound),
+ luaL_newmetatable(L, audio_engine_tname); lua_pop(L, 1);
+
+ struct honey_tbl_t audio[] = {
+ #define X(name, func) H_FUNC(name, func),
+ AUDIO_FUNCTIONS
+ #undef X
/* ma_result values */
- hs_str_int("MA_SUCCESS", MA_SUCCESS),
- );
+ H_ENUM(MA_SUCCESS),
+
+ H_END,
+ };
+ create_table(L, audio);
lua_setfield(L, honey_tbl, "audio");
}
int audio_engine_init(lua_State *L)
{
- ma_engine *engine = malloc(sizeof(ma_engine));
- if (engine == NULL)
- hs_throw_error(L, "failed to allocate memory for engine");
-
+ ma_engine *engine = lua_newuserdata(L, sizeof(ma_engine));
ma_result result = ma_engine_init(NULL, engine);
if (result != MA_SUCCESS)
- hs_throw_error(L, "failed to initialize audio engine: %d", result);
-
- lua_pushlightuserdata(L, engine);
+ luaL_error(L, "failed to initialize audio engine: %d", result);
+
+ luaL_getmetatable(L, audio_engine_tname);
+ lua_setmetatable(L, -2);
return 1;
}
int audio_engine_uninit(lua_State *L)
{
- ma_engine *engine;
- void *engine_ptr;
- hs_parse_args(L, hs_light(engine_ptr));
- engine = engine_ptr;
-
+ ma_engine *engine = luaL_checkudata(L, 1, audio_engine_tname);
ma_engine_uninit(engine);
- free(engine);
return 0;
}
int audio_engine_play_sound(lua_State *L)
{
- ma_engine *engine;
- void *engine_ptr;
- char *filename;
- hs_parse_args(L, hs_light(engine_ptr), hs_str(filename));
- engine = engine_ptr;
-
+ ma_engine *engine = luaL_checkudata(L, 1, audio_engine_tname);
+ char *filename = luaL_checkstring(L, 2);
ma_engine_play_sound(engine, filename, NULL);
return 0;
}
diff --git a/src/audio/audio.h b/src/audio/audio.h
index 1aa7f43..319a86c 100644
--- a/src/audio/audio.h
+++ b/src/audio/audio.h
@@ -3,6 +3,15 @@
#include <lua.h>
-void setup_audio(lua_State *L, int honey_tbl);
+extern const char *audio_engine_tname;
+
+#define AUDIO_FUNCTIONS \
+ X("engine_init", audio_engine_init) \
+ X("engine_uninit", audio_engine_uninit) \
+ X("engine_play_sound", audio_engine_play_sound) \
+
+#define X(name, func) int func(lua_State *L);
+AUDIO_FUNCTIONS
+#undef X
#endif
diff --git a/src/main.c b/src/main.c
index a01dd49..cb11082 100644
--- a/src/main.c
+++ b/src/main.c
@@ -2,15 +2,9 @@
#include <lauxlib.h>
#include <lualib.h>
#include <honeysuckle.h>
-#include "audio/audio.h"
-#include "gl/gl.h"
-#include "glm/glm.h"
-#include "image/image.h"
-#include "import/import.h"
-#include "logging/logging.h"
-#include "ode/ode_bindings.h"
#include "options/options.h"
-#include "vector/vector.h"
+#include "modules.h"
+
void print_load_error(lua_State *L, const char *script_file, int error_type);
@@ -29,16 +23,9 @@ int main(int argc, char **argv)
/* load honey bindings */
lua_createtable(L, 0, 2);
int honey_index = lua_gettop(L);
- setup_audio(L, honey_index);
- setup_gl(L, honey_index);
- setup_glm(L, honey_index);
- setup_image(L, honey_index);
- // setup_import(L, honey_index);
- setup_logging(L, honey_index);
- setup_ode(L, honey_index);
- setup_util(L, honey_index);
- setup_window(L, honey_index);
- setup_nvg(L, honey_index);
+ #define X(module) setup_ ## module (L, honey_index);
+ HONEY_MODULES
+ #undef X
lua_setglobal(L, "honey");
/* load main script */
diff --git a/src/modules.h b/src/modules.h
new file mode 100644
index 0000000..bfe1de5
--- /dev/null
+++ b/src/modules.h
@@ -0,0 +1,25 @@
+#ifndef HONEY_COMMON_H
+#define HONEY_COMMON_H
+
+#include <lua.h>
+
+#define HONEY_MODULES \
+ X(audio) \
+ X(gl) \
+ X(glm) \
+ X(image) \
+ X(import) \
+ X(logging) \
+ X(ode) \
+ X(util) \
+ X(window) \
+ X(nvg) \
+
+
+#define X(module) \
+ void setup_ ## module (lua_State *L, int honey_index);
+HONEY_MODULES
+#undef X
+
+
+#endif
diff --git a/src/nvg/CMakeLists.txt b/src/nvg/CMakeLists.txt
new file mode 100644
index 0000000..8003158
--- /dev/null
+++ b/src/nvg/CMakeLists.txt
@@ -0,0 +1,3 @@
+project(honey_engine)
+
+target_sources(honey PUBLIC ${CMAKE_CURRENT_LIST_DIR}/nvg.c)
diff --git a/src/nvg/color.c b/src/nvg/color.c
new file mode 100644
index 0000000..05f3535
--- /dev/null
+++ b/src/nvg/color.c
@@ -0,0 +1,117 @@
+#include <lua.h>
+#include <lauxlib.h>
+#include <nanovg.h>
+#include "nvg.h"
+
+
+static NVGcolor * create_color(lua_State *L)
+{
+ NVGcolor *color = lua_newuserdata(L, sizeof(NVGcolor));
+ luaL_getmetatable(L, nvg_color_tname);
+ lua_setmetatable(L, -2);
+ return color;
+}
+
+
+int nvgRGB_bind(lua_State *L)
+{
+ unsigned char r, g, b;
+ r = luaL_checkinteger(L, 1);
+ g = luaL_checkinteger(L, 2);
+ b = luaL_checkinteger(L, 3);
+ NVGcolor *c = create_color(L);
+ *c = nvgRGB(r, g, b);
+ return 1;
+}
+
+
+int nvgRGBf_bind(lua_State *L)
+{
+ float r, g, b;
+ r = luaL_checknumber(L, 1);
+ g = luaL_checknumber(L, 2);
+ b = luaL_checknumber(L, 3);
+ NVGcolor *c = create_color(L);
+ *c = nvgRGBf(r, g, b);
+ return 1;
+}
+
+
+int nvgRGBA_bind(lua_State *L)
+{
+ unsigned char r, g, b, a;
+ r = luaL_checkinteger(L, 1);
+ g = luaL_checkinteger(L, 2);
+ b = luaL_checkinteger(L, 3);
+ a = luaL_checkinteger(L, 4);
+ NVGcolor *c = create_color(L);
+ *c = nvgRGBA(r, g, b, a);
+ return 1;
+}
+
+
+int nvgRGBAf_bind(lua_State *L)
+{
+ float r, g, b, a;
+ r = luaL_checknumber(L, 1);
+ g = luaL_checknumber(L, 2);
+ b = luaL_checknumber(L, 3);
+ a = luaL_checknumber(L, 4);
+ NVGcolor *c = create_color(L);
+ *c = nvgRGBAf(r, g, b, a);
+ return 1;
+}
+
+
+int nvgLerpRGBA_bind(lua_State *L)
+{
+ NVGcolor *c0 = luaL_checkudata(L, 1, nvg_color_tname);
+ NVGcolor *c1 = luaL_checkudata(L, 2, nvg_color_tname);
+ float u = luaL_checknumber(L, 3);
+ NVGcolor *result = create_color(L);
+ *result = nvgLerpRGBA(*c0, *c1, u);
+ return 1;
+}
+
+
+int nvgTransRGBA_bind(lua_State *L)
+{
+ NVGcolor *c0 = luaL_checkudata(L, 1, nvg_color_tname);
+ unsigned char a = luaL_checkinteger(L, 2);
+ NVGcolor *result = create_color(L);
+ *result = nvgTransRGBA(*c0, a);
+ return 1;
+}
+
+
+int nvgTransRGBAf_bind(lua_State *L)
+{
+ NVGcolor *c0 = luaL_checkudata(L, 1, nvg_color_tname);
+ float a = luaL_checknumber(L, 2);
+ NVGcolor *result = create_color(L);
+ *result = nvgTransRGBAf(*c0, a);
+ return 1;
+}
+
+
+int nvgHSL_bind(lua_State *L)
+{
+ float h = luaL_checknumber(L, 1);
+ float s = luaL_checknumber(L, 2);
+ float l = luaL_checknumber(L, 3);
+ NVGcolor *result = create_color(L);
+ *result = nvgHSL(h, s, l);
+ return 1;
+}
+
+
+int nvgHSLA_bind(lua_State *L)
+{
+ float h = luaL_checknumber(L, 1);
+ float s = luaL_checknumber(L, 2);
+ float l = luaL_checknumber(L, 3);
+ unsigned char a = luaL_checkinteger(L, 4);
+ NVGcolor *result = create_color(L);
+ *result = nvgHSLA(h, s, l, a);
+ return 1;
+}
diff --git a/src/nvg/composite.c b/src/nvg/composite.c
new file mode 100644
index 0000000..be5ff1f
--- /dev/null
+++ b/src/nvg/composite.c
@@ -0,0 +1,35 @@
+#include <lua.h>
+#include <lauxlib.h>
+#include <nanovg.h>
+#include "nvg.h"
+
+
+int nvgGlobalCompositeOperation_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ int op = luaL_checkinteger(L, 2);
+ nvgGlobalCompositeOperation(*ctx, op);
+ return 0;
+}
+
+
+int nvgGlobalCompositeBlendFunc_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ int sfactor = luaL_checkinteger(L, 2);
+ int dfactor = luaL_checkinteger(L, 3);
+ nvgGlobalCompositeBlendFunc(*ctx, sfactor, dfactor);
+ return 0;
+}
+
+
+int nvgGlobalCompositeBlendFuncSeparate_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ int src_rgb = luaL_checkinteger(L, 2);
+ int dst_rgb = luaL_checkinteger(L, 3);
+ int src_alpha = luaL_checkinteger(L, 4);
+ int dst_alpha = luaL_checkinteger(L, 5);
+ nvgGlobalCompositeBlendFuncSeparate(*ctx, src_rgb, dst_rgb, src_alpha, dst_alpha);
+ return 0;
+}
diff --git a/src/nvg/context.c b/src/nvg/context.c
new file mode 100644
index 0000000..48a7282
--- /dev/null
+++ b/src/nvg/context.c
@@ -0,0 +1,23 @@
+#include <lua.h>
+#include <lauxlib.h>
+#include <nanovg.h>
+#include <nanovg_gl.h>
+#include "nvg.h"
+
+
+int nvgCreateContext_bind(lua_State *L)
+{
+ struct NVGcontext **vg = lua_newuserdata(L, sizeof(struct NVGcontext *));
+ *vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
+ luaL_getmetatable(L, nvg_ctx_tname);
+ lua_setmetatable(L, -2);
+ return 1;
+}
+
+
+int nvgDeleteContext_bind(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
+ nvgDeleteGL3(*vg);
+ return 0;
+}
diff --git a/src/nvg/frame.c b/src/nvg/frame.c
new file mode 100644
index 0000000..0012431
--- /dev/null
+++ b/src/nvg/frame.c
@@ -0,0 +1,32 @@
+#include <lua.h>
+#include <lauxlib.h>
+#include <nanovg.h>
+#include "nvg.h"
+
+
+int nvgBeginFrame_bind(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
+ float width = luaL_checknumber(L, 2);
+ float height = luaL_checknumber(L, 3);
+ float pixelRatio = luaL_checknumber(L, 4);
+
+ nvgBeginFrame(*vg, width, height, pixelRatio);
+ return 0;
+}
+
+
+int nvgCancelFrame_bind(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
+ nvgCancelFrame(*vg);
+ return 0;
+}
+
+
+int nvgEndFrame_bind(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
+ nvgEndFrame(*vg);
+ return 0;
+}
diff --git a/src/nvg/image.c b/src/nvg/image.c
new file mode 100644
index 0000000..e7f39c2
--- /dev/null
+++ b/src/nvg/image.c
@@ -0,0 +1,39 @@
+#include <lua.h>
+#include <lauxlib.h>
+#include <nanovg.h>
+#include <nanovg_gl.h>
+#include "nvg.h"
+
+
+int CreateImage_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ const char *filename = luaL_checkstring(L, 2);
+ int flags = luaL_checkinteger(L, 3);
+ int *handle = lua_newuserdata(L, sizeof(int));
+ luaL_getmetatable(L, nvg_image_tname);
+ lua_setmetatable(L, -2);
+ *handle = nvgCreateImage(*ctx, filename, flags);
+ return 1;
+}
+
+
+int nvgImageSize_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ int *handle = luaL_checkudata(L, 2, nvg_image_tname);
+ int w, h;
+ nvgImageSize(*ctx, *handle, &w, &h);
+ lua_pushinteger(L, w);
+ lua_pushinteger(L, h);
+ return 2;
+}
+
+
+int nvgDeleteImage_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ int *handle = luaL_checkudata(L, 2, nvg_image_tname);
+ nvgDeleteImage(*ctx, *handle);
+ return 0;
+}
diff --git a/src/nvg/nvg.h b/src/nvg/nvg.h
new file mode 100644
index 0000000..33a2420
--- /dev/null
+++ b/src/nvg/nvg.h
@@ -0,0 +1,143 @@
+#ifndef HONEY_VECTOR_H
+#define HONEY_VECTOR_H
+
+#include <lua.h>
+
+
+extern const char *nvg_ctx_tname;
+extern const char *nvg_color_tname;
+extern const char *nvg_paint_tname;
+
+
+#define NVG_FUNCTIONS \
+ /* context */ \
+ X("CreateContext", nvgCreateContext_bind) \
+ X("DeleteContext", nvgDeleteContext_bind) \
+ \
+ /* frame control */ \
+ X("BeginFrame", nvgBeginFrame_bind) \
+ X("CancelFrame", nvgCancelFrame_bind) \
+ X("EndFrame", nvgEndFrame_bind) \
+ \
+ /* composite operation */ \
+ X("GlobalCompositeOperation", nvgGlobalCompositeOperation_bind) \
+ X("GlobalCompositeBlendFunc", nvgGlobalCompositeBlendFunc_bind) \
+ X("GlobalCompositeBlendFuncSeparate", nvgGlobalCompositeBlendFuncSeparate_bind) \
+ \
+ /* color utils */ \
+ X("RGB", nvgRGB_bind) \
+ X("RGBf", nvgRGBf_bind) \
+ X("RGBA", nvgRGBA_bind) \
+ X("RGBAf", nvgRGBAf_bind) \
+ X("LerpRGBA", nvgLerpRGBA_bind) \
+ X("TransRGBA", nvgTransRGBA_bind) \
+ X("TransRGBAf", nvgTransRGBAf_bind) \
+ X("HSL", nvgHSL_bind) \
+ X("HSLA", nvgHSLA_bind) \
+ \
+ /* state handling */ \
+ X("Save", nvgSave_bind) \
+ X("Restore", nvgRestore_bind) \
+ X("Reset", nvgReset_bind) \
+ \
+ /* render styles */ \
+ X("ShapeAntiAlias", nvgShapeAntiAlias_bind) \
+ X("StrokeColor", nvgStrokeColor_bind) \
+ X("StrokePaint", nvgStrokePaint_bind) \
+ X("FillColor", nvgFillColor_bind) \
+ X("FillPaint", nvgFillPaint_bind) \
+ X("MiterLimit", nvgMiterLimit_bind) \
+ X("StrokeWidth", nvgStrokeWidth_bind) \
+ X("LineCap", nvgLineCap_bind) \
+ X("LineJoin", nvgLineJoin_bind) \
+ X("GlobalAlpha", nvgGlobalAlpha_bind) \
+ \
+ /* transforms */ \
+ X("ResetTransform", nvgResetTransform_bind) \
+ X("Transform", nvgTransform_bind) \
+ X("Translate", nvgTranslate_bind) \
+ X("Rotate", nvgRotate_bind) \
+ X("SkewX", nvgSkewX_bind) \
+ X("SkewY", nvgSkewY_bind) \
+ X("Scale", nvgScale_bind) \
+ X("CurrentTransform", nvgCurrentTransform_bind) \
+ /* X("TransformIdentity", nvgTransformIdentity_bind) */ \
+ /* X("TransformTranslate", nvgTransformTranslate_bind) */ \
+ /* X("TransformScale", nvgTransformScale_bind) */ \
+ /* X("TransformRotate", nvgTransformRotate_bind) */ \
+ /* X("TransformSkewX", nvgTransformSkewX_bind) */ \
+ /* X("TransformSkewY", nvgTransformSkewY_bind) */ \
+ /* X("TransformMultiply", nvgTransformMultiply_bind) */ \
+ /* X("TransformPremultiply", nvgTransformPremultiply_bind) */ \
+ /* X("TransformInverse", nvgTransformInverse_bind) */ \
+ /* X("TransformPoint", nvgTransformPoint_bind) */ \
+ \
+ /* images */ \
+ X("CreateImage", nvgCreateImage_bind) \
+ /* X("CreateImageMem", nvgCreateImageMem_bind) */ \
+ /* X("CreateImageRGBA", nvgCreateImageRGBA_bind) */ \
+ /* X("UpdateImage", nvgUpdateImage_bind) */ \
+ X("ImageSize", nvgImageSize_bind) \
+ X("DeleteImage", nvgDeleteImage_bind) \
+ \
+ /* paints */ \
+ X("LinearGradient", nvgLinearGradient_bind) \
+ X("BoxGradient", nvgBoxGradient_bind) \
+ X("RadialGradient", nvgRadialGradient_bind) \
+ X("ImagePattern", nvgImagePattern_bind) \
+ \
+ /* scissoring */ \
+ X("Scissor", nvgScissor_bind) \
+ X("IntersectScissor", nvgIntersectScissor_bind) \
+ X("ResetScissor", nvgResetScissor_bind) \
+ \
+ /* paths */ \
+ X("BeginPath", nvgBeginPath_bind) \
+ X("MoveTo", nvgMoveTo_bind) \
+ X("LineTo", nvgLineTo_bind) \
+ X("BezierTo", nvgBezierTo_bind) \
+ X("QuadTo", nvgQuadTo_bind) \
+ X("ArcTo", nvgArcTo_bind) \
+ X("ClosePath", nvgClosePath_bind) \
+ X("PathWinding", nvgPathWinding_bind) \
+ X("Arc", nvgArc_bind) \
+ X("Rect", nvgRect_bind) \
+ X("RoundedRect", nvgRoundedRect_bind) \
+ X("RoundedRectVarying", nvgRoundedRectVarying_bind) \
+ X("Ellipse", nvgEllipse_bind) \
+ X("Circle", nvgCircle_bind) \
+ X("Fill", nvgFill_bind) \
+ X("Stroke", nvgStroke_bind) \
+ \
+ /* text */ \
+ X("CreateFont", nvgCreateFont_bind) \
+ X("CreateFontAtIndex", nvgCreateFontAtIndex_bind) \
+ X("CreateFontMem", nvgCreateFontMem_bind) \
+ X("CreateFontMemAtIndex", nvgCreateFontMemAtIndex_bind) \
+ X("FindFont", nvgFindFont_bind) \
+ X("AddFallbackFontId", nvgAddFallbackFontId_bind) \
+ X("AddFallbackFont", nvgAddFallbackFont_bind) \
+ X("ResetFallbackFontsId", nvgResetFallbackFontsId_bind) \
+ X("ResetFallbackFonts", nvgResetFallbackFonts_bind) \
+ X("FontSize", nvgFontSize_bind) \
+ X("FontBlur", nvgFontBlur_bind) \
+ X("TextLetterSpacing", nvgTextLetterSpacing_bind) \
+ X("TextLineHeight", nvgTextLineHeight_bind) \
+ X("TextAlign", nvgTextAlign_bind) \
+ X("FontFaceId", nvgFontFaceId_bind) \
+ X("FontFace", nvgFontFace_bind) \
+ X("Text", nvgText_bind) \
+ X("TextBox", nvgTextBox_bind) \
+ X("TextBounds", nvgTextBounds_bind) \
+ X("TextBoxBounds", nvgTextBoxBounds_bind) \
+ X("TextGlyphPositions", nvgTextGlyphPositions_bind) \
+ X("TextMetrics", nvgTextMetrics_bind) \
+ X("TextBreakLines", nvgTextBreakLines_bind) \
+
+
+/* function declarations */
+#define X(unused, name) int name(lua_State *L);
+NVG_FUNCTIONS
+#undef X
+
+#endif
diff --git a/src/nvg/path.c b/src/nvg/path.c
new file mode 100644
index 0000000..1e0f527
--- /dev/null
+++ b/src/nvg/path.c
@@ -0,0 +1,117 @@
+/* --===== paths =====-- */
+
+int nvg_begin_path(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ nvgBeginPath(*vg);
+ return 0;
+}
+
+
+int nvg_move_to(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ float x = luaL_checknumber(L, 2);
+ float y = luaL_checknumber(L, 3);
+ nvgMoveTo(*vg, x, y);
+ return 0;
+}
+
+
+int nvg_line_to(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ float x = luaL_checknumber(L, 2);
+ float y = luaL_checknumber(L, 3);
+ nvgLineTo(*vg, x, y);
+ return 0;
+}
+
+
+int nvg_bezier_to(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ float c1x = luaL_checknumber(L, 2);
+ float c1y = luaL_checknumber(L, 3);
+ float c2x = luaL_checknumber(L, 4);
+ float c2y = luaL_checknumber(L, 5);
+ float x = luaL_checknumber(L, 6);
+ float y = luaL_checknumber(L, 7);
+ nvgBezierTo(*vg, c1x, c1y, c2x, c2y, x, y);
+ return 0;
+}
+
+
+int nvg_quad_to(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ float cx = luaL_checknumber(L, 2);
+ float cy = luaL_checknumber(L, 3);
+ float x = luaL_checknumber(L, 4);
+ float y = luaL_checknumber(L, 5);
+ nvgQuadTo(*vg, cx, cy, x, y);
+ return 0;
+}
+
+
+int nvg_arc_to(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ float x1 = luaL_checknumber(L, 2);
+ float y1 = luaL_checknumber(L, 3);
+ float x2 = luaL_checknumber(L, 4);
+ float y2 = luaL_checknumber(L, 5);
+ float radius = luaL_checknumber(L, 6);
+ nvgArcTo(*vg, x1, y1, x2, y2, radius);
+ return 0;
+}
+
+
+int nvg_close_path(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ nvgClosePath(*vg);
+ return 0;
+}
+
+
+int nvg_path_winding(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ int dir = luaL_checkinteger(L, 2);
+ nvgPathWinding(*vg, dir);
+ return 0;
+}
+
+
+int nvg_arc(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ float cx = luaL_checknumber(L, 2);
+ float cy = luaL_checknumber(L, 3);
+ float r = luaL_checknumber(L, 4);
+ float a0 = luaL_checknumber(L, 5);
+ float a1 = luaL_checknumber(L, 6);
+ int dir = luaL_checkinteger(L, 7);
+ nvgArc(*vg, cx, cy, r, a0, a1, dir);
+ return 0;
+}
+
+/* ... */
+
+int nvg_fill(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ nvgFill(*vg);
+ return 0;
+}
+
+
+int nvg_stroke(lua_State *L)
+{
+ struct NVGcontext **vg = luaL_checkudata(L, 1, ctx_tname);
+ nvgStroke(*vg);
+ return 0;
+}
+
+
diff --git a/src/nvg/render.c b/src/nvg/render.c
new file mode 100644
index 0000000..f28da90
--- /dev/null
+++ b/src/nvg/render.c
@@ -0,0 +1,95 @@
+#include <lua.h>
+#include <lauxlib.h>
+#include <nanovg.h>
+#include <nanovg_gl.h>
+#include "nvg.h"
+
+
+int ShapeAntiAlias_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ int enabled = luaL_toboolean(L, 2);
+ nvgShapeAntiAlias(*ctx, enabled);
+ return 0;
+}
+
+
+int nvgStrokeColor_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ NVGcolor *color = luaL_checkudata(L, 2, nvg_color_tname);
+ nvgStrokeColor(*ctx, *color);
+ return 0;
+}
+
+
+int nvgStrokePaint_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ NVGpaint *paint = luaL_checkudata(L, 2, nvg_paint_tname);
+ nvgStrokePaint(*ctx, *paint);
+ return 0;
+}
+
+
+int nvgFillColor_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ NVGcolor *color = luaL_checkudata(L, 2, nvg_color_tname);
+ nvgFillColor(*ctx, *color);
+ return 0;
+}
+
+
+int nvgFillPaint_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ NVGpaint *paint = luaL_checkudata(L, 2, nvg_paint_tname);
+ nvgFillPaint(*ctx, *paint);
+ return 0;
+}
+
+
+int nvgMiterLimit_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ float limit = luaL_checknumber(L, 2);
+ nvgMiterLimit(*ctx, limit);
+ return 0;
+}
+
+
+int nvgStrokeWidth_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ float width = luaL_checknumber(L, 2);
+ nvgStrokeWidth(*ctx, width);
+ return 0;
+}
+
+
+int nvgLineCap_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ int cap = luaL_checkinteger(L, 2);
+ nvgLineCap(*ctx, cap);
+ return 0;
+}
+
+
+int nvgLineJoin_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ int join = luaL_checkinteger(L, 2);
+ nvgLineJoin(*ctx, join);
+ return 0;
+}
+
+
+int nvgGlobalAlpha_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ float alpha = luaL_checknumber(L, 2);
+ nvgGlobalAlpha(*ctx, alpha);
+ return 0;
+}
diff --git a/src/nvg/setup.c b/src/nvg/setup.c
new file mode 100644
index 0000000..16766c0
--- /dev/null
+++ b/src/nvg/setup.c
@@ -0,0 +1,30 @@
+#include <lua.h>
+#include <lauxlib.h>
+#include "gl/glad/glad.h"
+#include <GLFW/glfw3.h>
+#define NANOVG_GL3_IMPLEMENTATION
+#include <nanovg.h>
+#include <nanovg_gl.h>
+#include "util/util.h"
+#include "nvg.h"
+
+
+const char *nvg_ctx_tname = "nvg.Context";
+const char *nvg_color_tname = "nvg.Color";
+
+
+void setup_nvg(lua_State *L, int honey_tbl)
+{
+ luaL_newmetatable(L, nvg_ctx_tname); lua_pop(L, 1);
+ luaL_newmetatable(L, nvg_color_tname); lua_pop(L, 1);
+
+ struct honey_tbl_t nvg[] = {
+ #define X(name, func) H_FUNC(name, func),
+ NVG_FUNCTIONS
+ #undef X
+ H_END,
+ };
+ create_table(L, nvg);
+
+ lua_setfield(L, honey_tbl, "nvg");
+}
diff --git a/src/nvg/state.c b/src/nvg/state.c
new file mode 100644
index 0000000..e2ab73a
--- /dev/null
+++ b/src/nvg/state.c
@@ -0,0 +1,29 @@
+#include <lua.h>
+#include <lauxlib.h>
+#include <nanovg.h>
+#include <nanovg_gl.h>
+#include "nvg.h"
+
+
+int nvgSave_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ nvgSave(*ctx);
+ return 0;
+}
+
+
+int nvgRestore_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ nvgRestore(*ctx);
+ return 0;
+}
+
+
+int nvgReset_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudata(L, 1, nvg_ctx_tname);
+ nvgReset(*ctx);
+ return 0;
+}
diff --git a/src/nvg/transform.c b/src/nvg/transform.c
new file mode 100644
index 0000000..a4ab1eb
--- /dev/null
+++ b/src/nvg/transform.c
@@ -0,0 +1,86 @@
+#include <lua.h>
+#include <lauxlib.h>
+#include <nanovg.h>
+#include <nanovg_gl.h>
+#include "nvg.h"
+
+
+int nvgResetTransform_bind(lua_State *L)
+{
+ NVGcontext **ctx = lua_checkudata(L, 1, nvg_ctx_tname);
+ nvgResetTransform(*ctx);
+ return 0;
+}
+
+
+int nvgTransform_bind(lua_State *L)
+{
+ NVGcontext **ctx = lua_checkudata(L, 1, nvg_ctx_tname);
+ float a = luaL_checknumber(L, 2);
+ float b = luaL_checknumber(L, 3);
+ float c = luaL_checknumber(L, 4);
+ float d = luaL_checknumber(L, 5);
+ float e = luaL_checknumber(L, 6);
+ float f = luaL_checknumber(L, 7);
+ nvgTransform(ctx, a, b, c, d, e, f);
+ return 0;
+}
+
+
+int nvgTranslate_bind(lua_State *L)
+{
+ NVGcontext **ctx = lua_checkudata(L, 1, nvg_ctx_tname);
+ float x = luaL_checknumber(L, 2);
+ float y = luaL_checknumber(L, 3);
+ nvgTranslate(*ctx, x, y);
+ return 0;
+}
+
+
+int nvgRotate_bind(lua_State *L)
+{
+ NVGcontext **ctx = lua_checkudata(L, 1, nvg_ctx_tname);
+ float angle = luaL_checknumber(L, 2);
+ nvgRotate(*ctx, angle);
+ return 0;
+}
+
+
+int nvgSkewX_bind(lua_State *L)
+{
+ NVGcontext **ctx = lua_checkudata(L, 1, nvg_ctx_tname);
+ float angle = luaL_checknumber(L, 2);
+ nvgSkewX(*ctx, angle);
+ return 0;
+}
+
+
+int nvgSkewY_bind(lua_State *L)
+{
+ NVGcontext **ctx = lua_checkudata(L, 1, nvg_ctx_tname);
+ float angle = luaL_checknumber(L, 2);
+ nvgSkewY(*ctx, angle);
+ return 0;
+}
+
+
+int nvgScale_bind(lua_State *L)
+{
+ NVGcontext **ctx = lua_checkudata(L, 1, nvg_ctx_tname);
+ float x = luaL_checknumber(L, 2);
+ float y = luaL_checknumber(L, 3);
+ nvgScale(*ctx, x, y);
+ return 0;
+}
+
+
+int nvgCurrentTransform_bind(lua_State *L)
+{
+ NVGcontext **ctx = luaL_checkudate(L, 1, nvg_ctx_tname);
+ float xform[6];
+ nvgCurrentTransform(*ctx, xform);
+ for (int i=0; i<6; i++) {
+ lua_pushnumber(L, xform[i]);
+ }
+ return 6;
+}
diff --git a/src/util/util.c b/src/util/util.c
index 89e9d38..52e2a16 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -1,6 +1,27 @@
#include <lua.h>
#include <lauxlib.h>
#include <honeysuckle.h>
+#include "util.h"
+
+void create_table(lua_State *L, struct honey_tbl_t *tbl)
+{
+ lua_createtable(L, 0, 0);
+ int t = lua_gettop(L);
+
+ for (struct honey_tbl_t *pair = tbl; pair->key != NULL; pair += 1) {
+ if (pair->type == LUA_TNUMBER) {
+ lua_pushinteger(L, pair->value.integer);
+ lua_setfield(L, t, pair->key);
+ }
+ else if (pair->type == LUA_TFUNCTION) {
+ lua_pushcfunction(L, pair->value.function);
+ lua_setfield(L, t, pair->key);
+ }
+ else {
+ /* bad type, ignore */
+ }
+ }
+}
void append_table(lua_State *L, int tbl_a, int tbl_b)
{
diff --git a/src/util/util.h b/src/util/util.h
index 231bcc9..6092d11 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -3,7 +3,24 @@
#include <lua.h>
+
+struct honey_tbl_t {
+ const char *key;
+ int type;
+ union {
+ lua_Integer integer;
+ lua_CFunction function;
+ } value;
+};
+
+#define H_INT(k, v) { .key=k, .type=LUA_TNUMBER, .value.integer=v }
+#define H_ENUM(v) { .key=#v, .type=LUA_TNUMBER, .value.integer=v }
+#define H_FUNC(k, v) { .key=k, .type=LUA_TFUNCTION, .value.function=v }
+#define H_END { .key=NULL, .type=LUA_TNIL, .value.integer=0 }
+
+
void setup_util(lua_State *L, int honey_tbl);
+void create_table(lua_State *L, struct honey_tbl_t *tbl);
void append_table(lua_State *L, int tbl_a, int tbl_b);
#endif
diff --git a/src/vector/CMakeLists.txt b/src/vector/CMakeLists.txt
deleted file mode 100644
index d74b1af..0000000
--- a/src/vector/CMakeLists.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-project(honey_engine)
-
-target_sources(honey PUBLIC ${CMAKE_CURRENT_LIST_DIR}/vector.c)
diff --git a/src/vector/vector.c b/src/vector/vector.c
deleted file mode 100644
index 33f80e5..0000000
--- a/src/vector/vector.c
+++ /dev/null
@@ -1,238 +0,0 @@
-#include <lua.h>
-#include <honeysuckle.h>
-#include "gl/glad/glad.h"
-#include <GLFW/glfw3.h>
-#define NANOVG_GL3_IMPLEMENTATION
-#include <nanovg.h>
-#include <nanovg_gl.h>
-#include "vector.h"
-
-
-static const char *nvg_ctx_tname = "nvg.Context";
-
-
-/* --===== contexts =====-- */
-
-int nvg_context(lua_State *L)
-{
- struct NVGcontext **vg = lua_newuserdata(L, sizeof(struct NVGcontext *));
- *vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
- luaL_getmetatable(L, nvg_ctx_tname);
- lua_setmetatable(L, -2);
- return 1;
-}
-
-
-int nvg_delete(lua_State *L)
-{
- struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
- nvgDeleteGL3(*vg);
- return 0;
-}
-
-
-/* --===== frames =====-- */
-
-int nvg_begin_frame(lua_State *L)
-{
- struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
- float width = luaL_checknumber(L, 2);
- float height = luaL_checknumber(L, 3);
- float pixelRatio = luaL_checknumber(L, 4);
-
- nvgBeginFrame(*vg, width, height, pixelRatio);
- return 0;
-}
-
-
-int nvg_cancel_frame(lua_State *L)
-{
- struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
- nvgCancelFrame(*vg);
- return 0;
-}
-
-
-int nvg_end_frame(lua_State *L)
-{
- struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
- nvgEndFrame(*vg);
- return 0;
-}
-
-
-/* --===== paths =====-- */
-
-int nvg_begin_path(lua_State *L)
-{
- struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
- nvgBeginPath(*vg);
- return 0;
-}
-
-
-int nvg_move_to(lua_State *L)
-{
- struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
- float x = luaL_checknumber(L, 2);
- float y = luaL_checknumber(L, 3);
- nvgMoveTo(*vg, x, y);
- return 0;
-}
-
-
-int nvg_line_to(lua_State *L)
-{
- struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
- float x = luaL_checknumber(L, 2);
- float y = luaL_checknumber(L, 3);
- nvgLineTo(*vg, x, y);
- return 0;
-}
-
-
-int nvg_bezier_to(lua_State *L)
-{
- struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
- float c1x = luaL_checknumber(L, 2);
- float c1y = luaL_checknumber(L, 3);
- float c2x = luaL_checknumber(L, 4);
- float c2y = luaL_checknumber(L, 5);
- float x = luaL_checknumber(L, 6);
- float y = luaL_checknumber(L, 7);
- nvgBezierTo(*vg, c1x, c1y, c2x, c2y, x, y);
- return 0;
-}
-
-
-int nvg_quad_to(lua_State *L)
-{
- struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
- float cx = luaL_checknumber(L, 2);
- float cy = luaL_checknumber(L, 3);
- float x = luaL_checknumber(L, 4);
- float y = luaL_checknumber(L, 5);
- nvgQuadTo(*vg, cx, cy, x, y);
- return 0;
-}
-
-
-int nvg_arc_to(lua_State *L)
-{
- struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
- float x1 = luaL_checknumber(L, 2);
- float y1 = luaL_checknumber(L, 3);
- float x2 = luaL_checknumber(L, 4);
- float y2 = luaL_checknumber(L, 5);
- float radius = luaL_checknumber(L, 6);
- nvgArcTo(*vg, x1, y1, x2, y2, radius);
- return 0;
-}
-
-
-int nvg_close_path(lua_State *L)
-{
- struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
- nvgClosePath(*vg);
- return 0;
-}
-
-
-int nvg_path_winding(lua_State *L)
-{
- struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
- int dir = luaL_checkinteger(L, 2);
- nvgPathWinding(*vg, dir);
- return 0;
-}
-
-
-int nvg_arc(lua_State *L)
-{
- struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
- float cx = luaL_checknumber(L, 2);
- float cy = luaL_checknumber(L, 3);
- float r = luaL_checknumber(L, 4);
- float a0 = luaL_checknumber(L, 5);
- float a1 = luaL_checknumber(L, 6);
- int dir = luaL_checkinteger(L, 7);
- nvgArc(*vg, cx, cy, r, a0, a1, dir);
- return 0;
-}
-
-/* ... */
-
-int nvg_fill(lua_State *L)
-{
- struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
- nvgFill(*vg);
- return 0;
-}
-
-
-int nvg_stroke(lua_State *L)
-{
- struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
- nvgStroke(*vg);
- return 0;
-}
-
-
-/* --===== render styles =====-- */
-
-int nvg_stroke_color(lua_State *L)
-{
- struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
- NVGcolor color;
- color.r = luaL_checknumber(L, 2);
- color.g = luaL_checknumber(L, 3);
- color.b = luaL_checknumber(L, 4);
- color.a = luaL_checknumber(L, 5);
- nvgStrokeColor(*vg, color);
- return 0;
-}
-
-
-int nvg_stroke_width(lua_State *L)
-{
- struct NVGcontext **vg = luaL_checkudata(L, 1, nvg_ctx_tname);
- float size = luaL_checknumber(L, 2);
- nvgStrokeWidth(*vg, size);
- return 0;
-}
-
-
-/* --===== complete =====-- */
-
-void setup_nvg(lua_State *L, int honey_tbl)
-{
- luaL_newmetatable(L, nvg_ctx_tname);
- lua_pushcfunction(L, nvg_delete);
- lua_setfield(L, -2, "__gc");
- lua_pop(L, 1);
-
- hs_create_table(L,
- hs_str_cfunc("Context", nvg_context),
-
- hs_str_cfunc("BeginFrame", nvg_begin_frame),
- hs_str_cfunc("CancelFrame", nvg_cancel_frame),
- hs_str_cfunc("EndFrame", nvg_end_frame),
-
- hs_str_cfunc("BeginPath", nvg_begin_path),
- hs_str_cfunc("MoveTo", nvg_move_to),
- hs_str_cfunc("LineTo", nvg_line_to),
- hs_str_cfunc("BezierTo", nvg_bezier_to),
- hs_str_cfunc("QuadTo", nvg_quad_to),
- hs_str_cfunc("ArcTo", nvg_arc_to),
- hs_str_cfunc("ClosePath", nvg_close_path),
- hs_str_cfunc("PathWinding", nvg_path_winding),
- hs_str_cfunc("Arc", nvg_arc),
- hs_str_cfunc("Fill", nvg_fill),
- hs_str_cfunc("Stroke", nvg_stroke),
-
- hs_str_cfunc("StrokeColor", nvg_stroke_color),
- hs_str_cfunc("StrokeWidth", nvg_stroke_width),
- );
-
- lua_setfield(L, honey_tbl, "nvg");
-}
diff --git a/src/vector/vector.h b/src/vector/vector.h
deleted file mode 100644
index 1a08e8e..0000000
--- a/src/vector/vector.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef HONEY_VECTOR_H
-#define HONEY_VECTOR_H
-
-void setup_nvg(lua_State *L, int honey_tbl);
-
-#endif