From 681ebb06ea4a015da828a3c90d04d471c9147f45 Mon Sep 17 00:00:00 2001 From: Kevin Harrison Date: Mon, 14 Nov 2016 16:57:16 -0500 Subject: [PATCH] initial commit --- .gitmodules | 3 + CMakeLists.txt | 27 + LICENSE | 9 + README.md | 94 + cmake/FindLuaJIT.cmake | 63 + example/calculator.lua | 95 + example/main.lua | 53 + example/overview.lua | 106 + example/skin.lua | 62 + example/skin/button.png | Bin 0 -> 2428 bytes example/skin/button_active.png | Bin 0 -> 2368 bytes example/skin/button_hover.png | Bin 0 -> 2414 bytes example/skin/checkbox_false.png | Bin 0 -> 1198 bytes example/skin/checkbox_true.png | Bin 0 -> 2970 bytes example/skin/window.png | Bin 0 -> 2350 bytes example/skin/window_header.png | Bin 0 -> 1444 bytes example/style.lua | 69 + src/nuklear | 1 + src/nuklear_love.c | 3525 +++++++++++++++++++++++++++++++ 19 files changed, 4107 insertions(+) create mode 100644 .gitmodules create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 README.md create mode 100644 cmake/FindLuaJIT.cmake create mode 100644 example/calculator.lua create mode 100644 example/main.lua create mode 100644 example/overview.lua create mode 100644 example/skin.lua create mode 100644 example/skin/button.png create mode 100644 example/skin/button_active.png create mode 100644 example/skin/button_hover.png create mode 100644 example/skin/checkbox_false.png create mode 100644 example/skin/checkbox_true.png create mode 100644 example/skin/window.png create mode 100644 example/skin/window_header.png create mode 100644 example/style.lua create mode 160000 src/nuklear create mode 100644 src/nuklear_love.c diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..26ee9e0 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/nuklear"] + path = src/nuklear + url = https://github.com/vurtun/nuklear.git diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..d87381b --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,27 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT("love-nuklear" C) + +SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") +FIND_PACKAGE(LuaJIT REQUIRED) + +SET(LIB_NAME "nuklear") + +ADD_LIBRARY( + "${LIB_NAME}" + MODULE + src/nuklear/nuklear.h + src/nuklear_love.c +) + +TARGET_INCLUDE_DIRECTORIES( + "${LIB_NAME}" + PUBLIC + "${LUA_INCLUDE_DIR}" +) + +TARGET_LINK_LIBRARIES( + "${LIB_NAME}" + ${LUA_LIBRARIES} +) + +SET_TARGET_PROPERTIES("${LIB_NAME}" PROPERTIES PREFIX "") diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b257dc9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,9 @@ +The MIT License (MIT) + +Copyright (c) 2016 Kevin Harrison + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..8f055b6 --- /dev/null +++ b/README.md @@ -0,0 +1,94 @@ +# LÖVE-Nuklear + +[Nuklear](https://github.com/vurtun/nuklear) module for the [LÖVE](https://love2d.org/) game engine. + +Provides a lightweight immediate mode GUI for LÖVE games. + +## Example +```lua +-- Simple UI example. + +local nk = require 'nuklear' + +function love.load() + nk.init() +end + +local combo = {value = 1, items = {'A', 'B', 'C'}} + +function love.update(dt) + nk.frame_begin() + if nk.window_begin('Simple Example', 100, 100, 200, 160, + 'border', 'title', 'movable') then + nk.layout_row('dynamic', 30, 1) + nk.label('Hello, world!') + nk.layout_row('dynamic', 30, 2) + nk.label('Combo box:') + if nk.combobox(combo, combo.items) then + print('Combo!', combo.items[combo.value]) + end + nk.layout_row('dynamic', 30, 3) + nk.label('Buttons:') + if nk.button('Sample') then + print('Sample!') + end + if nk.button('Button') then + print('Button!') + end + end + nk.window_end() + nk.frame_end() +end + +function love.draw() + nk.draw() +end + +function love.keypressed(key, scancode, isrepeat) + nk.keypressed(key, scancode, isrepeat) +end + +function love.keyreleased(key, scancode) + nk.keyreleased(key, scancode) +end + +function love.mousepressed(x, y, button, istouch) + nk.mousepressed(x, y, button, istouch) +end + +function love.mousereleased(x, y, button, istouch) + nk.mousereleased(x, y, button, istouch) +end + +function love.mousemoved(x, y, dx, dy, istouch) + nk.mousemoved(x, y, dx, dy, istouch) +end + +function love.textinput(text) + nk.textinput(text) +end + +function love.wheelmoved(x, y) + nk.wheelmoved(x, y) +end +``` + +## Building + +Grab the code with: +```sh +$ git clone --recursive git@github.com:keharriso/love-nuklear.git +``` + +Compile with CMake (I recommend using the MinGW generator on Windows). You'll need to tell CMake where to find the LuaJIT headers and binaries. The end result is a native Lua module. + + + +## Documentation + +A complete description of all functions and style properties, alongside additional examples, is available at the [LÖVE-Nuklear wiki](https://github.com/keharriso/love-nuklear/wiki). + +## License + +Copyright (c) 2016 Kevin Harrison, released under the MIT License (see LICENSE for details). + diff --git a/cmake/FindLuaJIT.cmake b/cmake/FindLuaJIT.cmake new file mode 100644 index 0000000..e8384e2 --- /dev/null +++ b/cmake/FindLuaJIT.cmake @@ -0,0 +1,63 @@ +# Locate LuaJIT library +# This module defines +# LUAJIT_FOUND, if false, do not try to link to Lua +# LUA_LIBRARIES +# LUA_INCLUDE_DIR, where to find lua.h +# LUAJIT_VERSION_STRING, the version of Lua found (since CMake 2.8.8) + +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +find_path(LUA_INCLUDE_DIR luajit.h + HINTS + ENV LUA_DIR + PATH_SUFFIXES include/luajit-2.0 include + PATHS + ~/Library/Frameworks + /Library/Frameworks + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt +) + +find_library(LUA_LIBRARY + NAMES luajit-5.1 + HINTS + ENV LUA_DIR + PATH_SUFFIXES lib + PATHS + ~/Library/Frameworks + /Library/Frameworks + /sw + /opt/local + /opt/csw + /opt +) + +if(LUA_LIBRARY) + # include the math library for Unix + if(UNIX AND NOT APPLE AND NOT BEOS AND NOT HAIKU) + find_library(LUA_MATH_LIBRARY m) + set( LUA_LIBRARIES "${LUA_LIBRARY};${LUA_MATH_LIBRARY}" CACHE STRING "Lua Libraries") + # For Windows and Mac, don't need to explicitly include the math library + else() + set( LUA_LIBRARIES "${LUA_LIBRARY}" CACHE STRING "Lua Libraries") + endif() +endif() + +if(LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/luajit.h") + file(STRINGS "${LUA_INCLUDE_DIR}/luajit.h" luajit_version_str REGEX "^#define[ \t]+LUAJIT_VERSION[ \t]+\"LuaJIT .+\"") + + string(REGEX REPLACE "^#define[ \t]+LUAJIT_VERSION[ \t]+\"LuaJIT ([^\"]+)\".*" "\\1" LUAJIT_VERSION_STRING "${luajit_version_str}") + unset(luajit_version_str) +endif() + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set LUA_FOUND to TRUE if +# all listed variables are TRUE +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LuaJIT + REQUIRED_VARS LUA_LIBRARIES LUA_INCLUDE_DIR + VERSION_VAR LUAJIT_VERSION_STRING) + +mark_as_advanced(LUA_INCLUDE_DIR LUA_LIBRARIES LUA_LIBRARY LUA_MATH_LIBRARY) diff --git a/example/calculator.lua b/example/calculator.lua new file mode 100644 index 0000000..fa0bbb5 --- /dev/null +++ b/example/calculator.lua @@ -0,0 +1,95 @@ +-- Simple calculator example, adapted from the original nuklear demo. + +local nk = require 'nuklear' + +local ops = {'+', '-', '*', '/'} +local a, b, op = '0' + +local function clear() + a, b, op = '0' +end + +local function digit(d) + if op then + if b == nil or b == '0' then + b = d + else + b = b..d + end + else + if a == '0' then + a = d + else + a = a..d + end + end +end + +local function decimal() + if op then + b = b or '0' + b = b:find('.') and b or b..'.' + else + a = a:find('.') and a or a..'.' + end +end + +local function equals() + if not tonumber(b) then + return + end + if op == '+' then + a, b, op = tostring(tonumber(a) + tonumber(b)) + elseif op == '-' then + a, b, op = tostring(tonumber(a) - tonumber(b)) + elseif op == '*' then + a, b, op = tostring(tonumber(a) * tonumber(b)) + elseif op == '/' then + a, b, op = tostring(tonumber(a) / tonumber(b)) + end +end + +local function operator(o) + if op then + equals() + end + op = o +end + +local function display() + return b or a +end + +return function () + if nk.window_begin('Calculator', 50, 50, 180, 250, 'border', 'movable', 'title') then + nk.layout_row('dynamic', 35, 1) + nk.label(display(), 'right') + nk.layout_row('dynamic', 35, 4) + for i=1,16 do + if i >= 13 and i < 16 then + if i == 13 then + if nk.button('C') then + clear() + end + if nk.button('0') then + digit('0') + end + if nk.button('=') then + equals() + end + end + elseif i % 4 ~= 0 then + local d = tostring(math.floor(i / 4) * 3 + (i % 4)) + if nk.button(d) then + digit(d) + end + else + local o = ops[math.floor(i / 4)] + if nk.button(o) then + operator(o) + end + end + end + end + nk.window_end() +end diff --git a/example/main.lua b/example/main.lua new file mode 100644 index 0000000..0cf0042 --- /dev/null +++ b/example/main.lua @@ -0,0 +1,53 @@ +-- Several simple examples. + +local nk = require 'nuklear' + +local calculator = require 'calculator' +local overview = require 'overview' +local style = require 'style' +local skin = require 'skin' + +function love.load() + nk.init() +end + +function love.update(dt) + nk.frame_begin() + calculator() + style() + overview() + skin() + nk.frame_end() +end + +function love.draw() + nk.draw() +end + +function love.keypressed(key, scancode, isrepeat) + nk.keypressed(key, scancode, isrepeat) +end + +function love.keyreleased(key, scancode) + nk.keyreleased(key, scancode) +end + +function love.mousepressed(x, y, button, istouch) + nk.mousepressed(x, y, button, istouch) +end + +function love.mousereleased(x, y, button, istouch) + nk.mousereleased(x, y, button, istouch) +end + +function love.mousemoved(x, y, dx, dy, istouch) + nk.mousemoved(x, y, dx, dy, istouch) +end + +function love.textinput(text) + nk.textinput(text) +end + +function love.wheelmoved(x, y) + nk.wheelmoved(x, y) +end diff --git a/example/overview.lua b/example/overview.lua new file mode 100644 index 0000000..0819d0f --- /dev/null +++ b/example/overview.lua @@ -0,0 +1,106 @@ +-- An overview of most of the supported widgets. + +local nk = require 'nuklear' + +local checkA = {value = false} +local checkB = {value = true} +local radio = {value = 'A'} +local selectA = {value = false} +local selectB = {value = true} +local slider = {value = 0.2} +local progress = {value = 1} +local colorPicker = {value = '#ff0000'} +local property = {value = 6} +local edit = {value = 'Edit text'} +local comboA = {value = 1, items = {'A', 'B', 'C'}} + +return function () + if nk.window_begin('Overview', 100, 100, 600, 450, 'border', 'movable', 'title') then + nk.menubar_begin() + nk.layout_row('dynamic', 30, 1) + if nk.menu_begin('Menu', nil, 120, 90) then + nk.layout_row('dynamic', 40, 1) + nk.menu_item('Item A') + nk.menu_item('Item B') + nk.menu_item('Item C') + nk.menu_end() + end + nk.menubar_end() + nk.layout_row('dynamic', 400, 3) + nk.group_begin('Group 1', 'border') + nk.layout_row('dynamic', 30, 1) + nk.label('Left label') + nk.label('Centered label', 'centered') + nk.label('Right label', 'right') + nk.label('Colored label', 'left', '#ff0000') + if nk.tree_push('tab', 'Tree Tab') then + if nk.tree_push('node', 'Tree Node 1') then + nk.label('Label 1') + nk.tree_pop() + end + if nk.tree_push('node', 'Tree Node 2') then + nk.label('Label 2') + nk.tree_pop() + end + nk.tree_pop() + end + nk.spacing(1) + if nk.button('Button') then + print('button pressed!') + end + nk.spacing(1) + nk.checkbox('Checkbox A', checkA) + nk.checkbox('Checkbox B', checkB) + nk.group_end() + nk.group_begin('Group 2', 'border') + nk.layout_row('dynamic', 30, 1) + nk.label('Radio buttons:') + nk.layout_row('dynamic', 30, 3) + nk.radio('A', radio) + nk.radio('B', radio) + nk.radio('C', radio) + nk.layout_row('dynamic', 30, 1) + nk.selectable('Selectable A', selectA) + nk.selectable('Selectable B', selectB) + nk.layout_row('dynamic', 30, {.35, .65}) + nk.label('Slider:') + nk.slider(0, slider, 1, 0.05) + nk.label('Progress:') + nk.progress(progress, 10, true) + nk.layout_row('dynamic', 30, 2) + nk.spacing(2) + nk.label('Color picker:') + nk.button(nil, colorPicker.value) + nk.layout_row('dynamic', 90, 1) + nk.color_picker(colorPicker) + nk.group_end() + nk.group_begin('Group 3', 'border') + nk.layout_row('dynamic', 30, 1) + nk.property('Property', 0, property, 10, 0.25, 0.05) + nk.spacing(1) + nk.label('Edit:') + nk.layout_row('dynamic', 90, 1) + nk.edit('box', edit) + nk.layout_row('dynamic', 5, 1) + nk.spacing(1) + nk.layout_row('dynamic', 30, 1) + nk.label('Combobox:') + nk.combobox(comboA, comboA.items) + nk.layout_row('dynamic', 5, 1) + nk.spacing(1) + nk.layout_row('dynamic', 30, 1) + if nk.widget_is_hovered() then + nk.tooltip('Test tooltip') + end + local x, y, w, h = nk.widget_bounds() + if nk.contextual_begin(100, 100, x, y, w, h) then + nk.layout_row('dynamic', 30, 1) + nk.contextual_item('Item A') + nk.contextual_item('Item B') + nk.contextual_end() + end + nk.label('Contextual (Right click me)') + nk.group_end() + end + nk.window_end() +end diff --git a/example/skin.lua b/example/skin.lua new file mode 100644 index 0000000..3e046fc --- /dev/null +++ b/example/skin.lua @@ -0,0 +1,62 @@ +local nk = require 'nuklear' + +local window_header = love.graphics.newImage 'skin/window_header.png' +local checkbox_skin = love.graphics.newImage 'skin/checkbox_false.png' +local checkbox_check = love.graphics.newImage 'skin/checkbox_true.png' + +local style = { + ['text'] = { + ['color'] = '#000000' + }, + ['button'] = { + ['normal'] = love.graphics.newImage 'skin/button.png', + ['hover'] = love.graphics.newImage 'skin/button_hover.png', + ['active'] = love.graphics.newImage 'skin/button_active.png', + ['text background'] = '#00000000', + ['text normal'] = '#000000', + ['text hover'] = '#000000', + ['text active'] = '#ffffff' + }, + ['checkbox'] = { + ['normal'] = checkbox_skin, + ['hover'] = checkbox_skin, + ['active'] = checkbox_skin, + ['cursor normal'] = checkbox_check, + ['cursor hover'] = checkbox_check, + ['text normal'] = '#000000', + ['text hover'] = '#000000', + ['text active'] = '#000000', + ['text background'] = '#d3ceaa' + }, + ['window'] = { + ['header'] = { + ['normal'] = window_header, + ['hover'] = window_header, + ['active'] = window_header, + ['label normal'] = '#000000', + ['label hover'] = '#000000', + ['label active'] = '#000000', + ['label padding'] = {x = 10, y = 8} + }, + ['fixed background'] = love.graphics.newImage 'skin/window.png', + ['background'] = '#d3ceaa' + } +} + +local check = {value = false} + +return function () + nk.style_push(style) + if nk.window_begin('Skin Example', 200, 200, 350, 200, 'title', 'movable') then + nk.layout_space_begin('dynamic', 150, 3) + nk.layout_space_push(0.14, 0.15, 0.72, 0.3) + nk.label('Skin example! Styles can change skins, colors, padding, font, and more.', 'wrap') + nk.layout_space_push(0.2, 0.55, 0.2, 0.2) + nk.button('Button') + nk.layout_space_push(0.55, 0.55, 0.3, 0.2) + nk.checkbox('Checkbox', check) + nk.layout_space_end() + end + nk.window_end() + nk.style_pop() +end diff --git a/example/skin/button.png b/example/skin/button.png new file mode 100644 index 0000000000000000000000000000000000000000..0c4783dfb72eb4546b06d6160a6b9ff093478ffc GIT binary patch literal 2428 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 literal 0 HcmV?d00001 diff --git a/example/skin/checkbox_false.png b/example/skin/checkbox_false.png new file mode 100644 index 0000000000000000000000000000000000000000..df85f65883a5b93a54b2e2a251e9da1996a37962 GIT binary patch literal 1198 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 IY2kh8FKmrD4*&oF literal 0 HcmV?d00001 diff --git a/example/skin/window_header.png b/example/skin/window_header.png new file mode 100644 index 0000000000000000000000000000000000000000..cb39411954c04eb27c00a65588b85c7a3a3006ee GIT binary patch literal 1444 zcmV;V1zY-wP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00j(5L_t(|+U?y>Xp?6E$MN6W z+C!6SLb0WbosCXsb=6ijS8q#I3SE)pG@PBp31hH0hp{-egWI4P?BB5) zLm7x`*c|qv>GV*TGp((c9_(vt4U&{+hb8e%nyPD?Zk^u`Jka;elQ-pk;mgaDq_wn! zj4^&mfy`);)GPqNkfeyDe#^4##T>|5f>3)U9nK6Q4FL0-lJt?J$U@`2;Am&=s(U1b zi#;BX$7S2L1_lPWOaLAmfj~fhzh8d8|Do}=EUTyFzmPG;YmAAQ0+W-IrmwHh1cO22 z@pz0R27|$PY=_6=G2w97^!4?b2Z$SET1px0fH7vo`HG1|!i2+NE)s*mU_2z?i9}+) zcpoc8up`8p!C){JH^SktnVg&~7VhYhtZ5r#B*`l&Dk+%VABjZN)6=8dw{OpRPF0ml zJ6pDBd(&oZda7QVHa;o0yHe@&tkScyEP4U>Us+XNu2rkbH8Ydcwd-TL_UE{+T>V48 z{Cc_Qe2>SYXf&!&C{*~+mzHH6UU0M>!5&cNlOeWkD-;ST7K_c9zhnDm?cLL=eS4ng zDgt=y-MyRCZx^rV`yYPR^~B9NkB7ryMIsS-z1~L-xAjkg9goKq3*Vm>eXxd@YGkDn7EaUz0D!TkZQ2mm~SZ@xXNufIE+x38(GNwHW=)z#I`-LG1f6@8>=XM)`$>3vDM zaN&YFIyy8xJ)N7gal<;j)%}V#Y*@!t0DylWk+`Yj?|!VAnPhI?)~#E0{``5>)zxKp zB_(aMENkR}(ar?BMbc$S8XFr^dwaWvhllfmeX{qcT&_yaJ^(Dh#KbL~=>0rzt-GTt(&^Kub?)4`IWI!60buc5u1dZ4&TDeJ?>99Xjq1#qGtOzB zIXA3=V0$HvNb=aWt@Z2I=dELZ5;@KqHUKQKi-W)GMDG{5?fUw9jg5^tr{vz0EL_xXam4XLbL&ZXafLfM^2% yh&BL#XafMz1^^Ik007Yj0HO^5Ald+c#rq3?-tfqvWhig}0000 +#include + +#include +#include + +#define NK_IMPLEMENTATION +#define NK_INCLUDE_FIXED_TYPES +#define NK_INCLUDE_STANDARD_IO +#define NK_INCLUDE_STANDARD_VARARGS +#define NK_INCLUDE_DEFAULT_ALLOCATOR +#define NK_PRIVATE +#include "nuklear/nuklear.h" + +/* + * =============================================================== + * + * INTERNAL + * + * =============================================================== + */ + +#define NK_LOVE_MAX_POINTS 256 +#define NK_LOVE_EDIT_BUFFER_LEN (1024 * 1024) +#define NK_LOVE_COMBOBOX_MAX_ITEMS 1024 +#define NK_LOVE_MAX_FONTS 1024 +#define NK_LOVE_MAX_RATIOS 1024 + +static lua_State *L; +static struct nk_context context; +static struct nk_user_font *fonts; +static int font_count; +static char *edit_buffer; +static const char **combobox_items; +static struct nk_cursor cursors[NK_CURSOR_COUNT]; +static float *layout_ratios; +static int layout_ratio_count; + +static void nk_love_configureGraphics(int line_thickness, struct nk_color col) +{ + lua_getglobal(L, "love"); + lua_getfield(L, -1, "graphics"); + lua_remove(L, -2); + if (line_thickness >= 0) { + lua_getfield(L, -1, "setLineWidth"); + lua_pushnumber(L, line_thickness); + lua_call(L, 1, 0); + } + lua_getfield(L, -1, "setColor"); + lua_pushnumber(L, col.r); + lua_pushnumber(L, col.g); + lua_pushnumber(L, col.b); + lua_pushnumber(L, col.a); + lua_call(L, 4, 0); +} + +static void nk_love_scissor(int x, int y, int w, int h) +{ + lua_getglobal(L, "love"); + lua_getfield(L, -1, "graphics"); + lua_getfield(L, -1, "setScissor"); + lua_pushnumber(L, x); + lua_pushnumber(L, y); + lua_pushnumber(L, w); + lua_pushnumber(L, h); + lua_call(L, 4, 0); + lua_pop(L, 2); +} + +static void nk_love_draw_line(int x0, int y0, int x1, int y1, + int line_thickness, struct nk_color col) +{ + nk_love_configureGraphics(line_thickness, col); + lua_getfield(L, -1, "line"); + lua_pushnumber(L, x0); + lua_pushnumber(L, y0); + lua_pushnumber(L, x1); + lua_pushnumber(L, y1); + lua_call(L, 4, 0); + lua_pop(L, 1); +} + +static void nk_love_draw_rect(int x, int y, unsigned int w, + unsigned int h, unsigned int r, int line_thickness, + struct nk_color col) +{ + nk_love_configureGraphics(line_thickness, col); + lua_getfield(L, -1, "rectangle"); + if (line_thickness >= 0) { + lua_pushstring(L, "line"); + } else { + lua_pushstring(L, "fill"); + } + lua_pushnumber(L, x); + lua_pushnumber(L, y); + lua_pushnumber(L, w); + lua_pushnumber(L, h); + lua_pushnumber(L, r); + lua_pushnumber(L, r); + lua_call(L, 7, 0); + lua_pop(L, 1); +} + +static void nk_love_draw_triangle(int x0, int y0, int x1, int y1, + int x2, int y2, int line_thickness, struct nk_color col) +{ + nk_love_configureGraphics(line_thickness, col); + lua_getfield(L, -1, "polygon"); + if (line_thickness >= 0) { + lua_pushstring(L, "line"); + } else { + lua_pushstring(L, "fill"); + } + lua_pushnumber(L, x0); + lua_pushnumber(L, y0); + lua_pushnumber(L, x1); + lua_pushnumber(L, y1); + lua_pushnumber(L, x2); + lua_pushnumber(L, y2); + lua_call(L, 7, 0); + lua_pop(L, 1); +} + +static void nk_love_draw_polygon(const struct nk_vec2i *pnts, int count, + int line_thickness, struct nk_color col) +{ + nk_love_configureGraphics(line_thickness, col); + lua_getfield(L, -1, "polygon"); + if (line_thickness >= 0) { + lua_pushstring(L, "line"); + } else { + lua_pushstring(L, "fill"); + } + int i; + for (i = 0; (i < count) && (i < NK_LOVE_MAX_POINTS); ++i) { + lua_pushnumber(L, pnts[i].x); + lua_pushnumber(L, pnts[i].y); + } + lua_call(L, 1 + count * 2, 0); + lua_pop(L, 1); +} + +static void nk_love_draw_polyline(const struct nk_vec2i *pnts, + int count, int line_thickness, struct nk_color col) +{ + nk_love_configureGraphics(line_thickness, col); + lua_getfield(L, -1, "line"); + int i; + for (i = 0; (i < count) && (i < NK_LOVE_MAX_POINTS); ++i) { + lua_pushnumber(L, pnts[i].x); + lua_pushnumber(L, pnts[i].y); + } + lua_call(L, count * 2, 0); + lua_pop(L, 1); +} + +static void nk_love_draw_circle(int x, int y, unsigned int w, + unsigned int h, int line_thickness, struct nk_color col) +{ + nk_love_configureGraphics(line_thickness, col); + lua_getfield(L, -1, "ellipse"); + if (line_thickness >= 0) { + lua_pushstring(L, "line"); + } else { + lua_pushstring(L, "fill"); + } + lua_pushnumber(L, x + w / 2); + lua_pushnumber(L, y + h / 2); + lua_pushnumber(L, w / 2); + lua_pushnumber(L, h / 2); + lua_call(L, 5, 0); + lua_pop(L, 1); +} + +static void nk_love_draw_curve(struct nk_vec2i p1, struct nk_vec2i p2, + struct nk_vec2i p3, struct nk_vec2i p4, unsigned int num_segments, + int line_thickness, struct nk_color col) +{ + unsigned int i_step; + float t_step; + struct nk_vec2i last = p1; + + if (num_segments < 1) { + num_segments = 1; + } + t_step = 1.0f/(float)num_segments; + nk_love_configureGraphics(line_thickness, col); + lua_getfield(L, -1, "line"); + for (i_step = 1; i_step <= num_segments; ++i_step) { + float t = t_step * (float)i_step; + float u = 1.0f - t; + float w1 = u*u*u; + float w2 = 3*u*u*t; + float w3 = 3*u*t*t; + float w4 = t * t *t; + float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x; + float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y; + lua_pushnumber(L, x); + lua_pushnumber(L, y); + } + lua_call(L, (num_segments + 1) * 2, 0); + lua_pop(L, 1); +} + +static float nk_love_get_text_width(nk_handle handle, float height, + const char *text, int len) +{ + lua_getfield(L, LUA_REGISTRYINDEX, "nuklear"); + lua_getfield(L, -1, "font"); + lua_rawgeti(L, -1, handle.id); + lua_getfield(L, -1, "getWidth"); + lua_insert(L, -2); + lua_pushlstring(L, text, len); + lua_call(L, 2, 1); + float width = lua_tonumber(L, -1); + lua_pop(L, 3); + return width; +} + +static void nk_love_draw_text(int fontref, struct nk_color cbg, + struct nk_color cfg, int x, int y, unsigned int w, unsigned int h, + float height, int len, const char *text) +{ + lua_getglobal(L, "love"); + lua_getfield(L, -1, "graphics"); + + lua_getfield(L, -1, "setColor"); + lua_pushnumber(L, cbg.r); + lua_pushnumber(L, cbg.g); + lua_pushnumber(L, cbg.b); + lua_pushnumber(L, cbg.a); + lua_call(L, 4, 0); + + lua_getfield(L, -1, "rectangle"); + lua_pushstring(L, "fill"); + lua_pushnumber(L, x); + lua_pushnumber(L, y); + lua_pushnumber(L, w); + lua_pushnumber(L, h); + lua_call(L, 5, 0); + + lua_getfield(L, -1, "setColor"); + lua_pushnumber(L, cfg.r); + lua_pushnumber(L, cfg.g); + lua_pushnumber(L, cfg.b); + lua_pushnumber(L, cfg.a); + lua_call(L, 4, 0); + + lua_getfield(L, -1, "setFont"); + lua_getfield(L, LUA_REGISTRYINDEX, "nuklear"); + lua_getfield(L, -1, "font"); + lua_rawgeti(L, -1, fontref); + lua_replace(L, -3); + lua_pop(L, 1); + lua_call(L, 1, 0); + + lua_getfield(L, -1, "print"); + lua_pushlstring(L, text, len); + lua_pushnumber(L, x); + lua_pushnumber(L, y); + lua_call(L, 3, 0); + + lua_pop(L, 2); +} + +static void interpolate_color(struct nk_color c1, struct nk_color c2, + struct nk_color *result, float fraction) +{ + float r = c1.r + (c2.r - c1.r) * fraction; + float g = c1.g + (c2.g - c1.g) * fraction; + float b = c1.b + (c2.b - c1.b) * fraction; + float a = c1.a + (c2.a - c1.a) * fraction; + + result->r = (nk_byte)NK_CLAMP(0, r, 255); + result->g = (nk_byte)NK_CLAMP(0, g, 255); + result->b = (nk_byte)NK_CLAMP(0, b, 255); + result->a = (nk_byte)NK_CLAMP(0, a, 255); +} + +static void nk_love_draw_rect_multi_color(int x, int y, unsigned int w, + unsigned int h, struct nk_color left, struct nk_color top, + struct nk_color right, struct nk_color bottom) +{ + lua_getglobal(L, "love"); + lua_getfield(L, -1, "graphics"); + + lua_getfield(L, -1, "setPointSize"); + lua_pushnumber(L, 0); + lua_call(L, 1, 0); + + struct nk_color X1, X2, Y; + float fraction_x, fraction_y; + int i,j; + + lua_getfield(L, -1, "points"); + lua_createtable(L, w * h, 0); + + for (j = 0; j < h; j++) { + fraction_y = ((float)j) / h; + for (i = 0; i < w; i++) { + fraction_x = ((float)i) / w; + interpolate_color(left, top, &X1, fraction_x); + interpolate_color(right, bottom, &X2, fraction_x); + interpolate_color(X1, X2, &Y, fraction_y); + lua_createtable(L, 6, 0); + lua_pushnumber(L, x + i); + lua_rawseti(L, -2, 1); + lua_pushnumber(L, y + j); + lua_rawseti(L, -2, 2); + lua_pushnumber(L, Y.r); + lua_rawseti(L, -2, 3); + lua_pushnumber(L, Y.g); + lua_rawseti(L, -2, 4); + lua_pushnumber(L, Y.b); + lua_rawseti(L, -2, 5); + lua_pushnumber(L, Y.a); + lua_rawseti(L, -2, 6); + lua_rawseti(L, -2, i + j * w + 1); + } + } + + lua_call(L, 1, 0); + lua_pop(L, 2); +} + +static void nk_love_clear(struct nk_color col) +{ + lua_getglobal(L, "love"); + lua_getfield(L, -1, "graphics"); + lua_getfield(L, -1, "clear"); + lua_pushnumber(L, col.r); + lua_pushnumber(L, col.g); + lua_pushnumber(L, col.b); + lua_pushnumber(L, col.a); + lua_call(L, 4, 0); + lua_pop(L, 2); +} + +static void nk_love_blit() +{ + lua_getglobal(L, "love"); + lua_getfield(L, -1, "graphics"); + lua_getfield(L, -1, "present"); + lua_call(L, 0, 0); + lua_pop(L, 2); +} + +static void nk_love_draw_image(int x, int y, unsigned int w, unsigned int h, + struct nk_image image, struct nk_color color) +{ + nk_love_configureGraphics(-1, color); + lua_getfield(L, -1, "draw"); + lua_getfield(L, LUA_REGISTRYINDEX, "nuklear"); + lua_getfield(L, -1, "image"); + lua_rawgeti(L, -1, image.handle.id); + lua_getfield(L, -5, "newQuad"); + lua_pushnumber(L, image.region[0]); + lua_pushnumber(L, image.region[1]); + lua_pushnumber(L, image.region[2]); + lua_pushnumber(L, image.region[3]); + lua_pushnumber(L, image.w); + lua_pushnumber(L, image.h); + lua_call(L, 6, 1); + lua_replace(L, -3); + lua_replace(L, -3); + lua_pushnumber(L, x); + lua_pushnumber(L, y); + lua_pushnumber(L, 0); + lua_pushnumber(L, (double) w / image.region[2]); + lua_pushnumber(L, (double) h / image.region[3]); + lua_call(L, 7, 0); + lua_pop(L, 1); +} + +static void nk_love_draw_arc(int cx, int cy, unsigned int r, + int line_thickness, float a1, float a2, struct nk_color color) +{ + nk_love_configureGraphics(line_thickness, color); + lua_getfield(L, -1, "arc"); + if (line_thickness >= 0) { + lua_pushstring(L, "line"); + } else { + lua_pushstring(L, "fill"); + } + lua_pushnumber(L, cx); + lua_pushnumber(L, cy); + lua_pushnumber(L, r); + lua_pushnumber(L, a1); + lua_pushnumber(L, a2); + lua_call(L, 6, 0); + lua_pop(L, 1); +} + +static void nk_love_clipbard_paste(nk_handle usr, struct nk_text_edit *edit) +{ + (void)usr; + lua_getglobal(L, "love"); + lua_getfield(L, -1, "system"); + lua_getfield(L, -1, "getClipboardText"); + lua_call(L, 0, 1); + const char *text = lua_tostring(L, -1); + if (text) nk_textedit_paste(edit, text, nk_strlen(text)); + lua_pop(L, 3); +} + +static void nk_love_clipbard_copy(nk_handle usr, const char *text, int len) +{ + (void)usr; + char *str = 0; + if (!len) return; + str = (char*)malloc((size_t)len+1); + if (!str) return; + memcpy(str, text, (size_t)len); + str[len] = '\0'; + lua_getglobal(L, "love"); + lua_getfield(L, -1, "system"); + lua_getfield(L, -1, "setClipboardText"); + lua_pushstring(L, str); + free(str); + lua_call(L, 1, 0); + lua_pop(L, 2); +} + +static int nk_love_is_active(struct nk_context *ctx) +{ + struct nk_window *iter; + NK_ASSERT(ctx); + if (!ctx) return 0; + iter = ctx->begin; + while (iter) { + /* check if window is being hovered */ + if (iter->flags & NK_WINDOW_MINIMIZED) { + struct nk_rect header = iter->bounds; + header.h = ctx->style.font->height + 2 * ctx->style.window.header.padding.y; + if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) + return 1; + } else if (nk_input_is_mouse_hovering_rect(&ctx->input, iter->bounds)) { + return 1; + } + /* check if window popup is being hovered */ + if (iter->popup.active && iter->popup.win && nk_input_is_mouse_hovering_rect(&ctx->input, iter->popup.win->bounds)) + return 1; + if (iter->edit.active & NK_EDIT_ACTIVE) + return 1; + iter = iter->next; + } + return 0; +} + +static int nk_love_keyevent(const char *key, const char *scancode, + int isrepeat, int down) +{ + lua_getglobal(L, "love"); + lua_getfield(L, -1, "keyboard"); + lua_getfield(L, -1, "isScancodeDown"); + lua_pushstring(L, "lctrl"); + lua_call(L, 1, 1); + int lctrl = lua_toboolean(L, -1); + lua_pop(L, 3); + + if (!strcmp(key, "rshift") || !strcmp(key, "lshift")) + nk_input_key(&context, NK_KEY_SHIFT, down); + else if (!strcmp(key, "delete")) + nk_input_key(&context, NK_KEY_DEL, down); + else if (!strcmp(key, "return")) + nk_input_key(&context, NK_KEY_ENTER, down); + else if (!strcmp(key, "tab")) + nk_input_key(&context, NK_KEY_TAB, down); + else if (!strcmp(key, "backspace")) + nk_input_key(&context, NK_KEY_BACKSPACE, down); + else if (!strcmp(key, "home")) { + nk_input_key(&context, NK_KEY_TEXT_LINE_START, down); + } else if (!strcmp(key, "end")) { + nk_input_key(&context, NK_KEY_TEXT_LINE_END, down); + } else if (!strcmp(key, "pagedown")) { + nk_input_key(&context, NK_KEY_SCROLL_DOWN, down); + } else if (!strcmp(key, "pageup")) { + nk_input_key(&context, NK_KEY_SCROLL_UP, down); + } else if (!strcmp(key, "z")) + nk_input_key(&context, NK_KEY_TEXT_UNDO, down && lctrl); + else if (!strcmp(key, "r")) + nk_input_key(&context, NK_KEY_TEXT_REDO, down && lctrl); + else if (!strcmp(key, "c")) + nk_input_key(&context, NK_KEY_COPY, down && lctrl); + else if (!strcmp(key, "v")) + nk_input_key(&context, NK_KEY_PASTE, down && lctrl); + else if (!strcmp(key, "x")) + nk_input_key(&context, NK_KEY_CUT, down && lctrl); + else if (!strcmp(key, "b")) + nk_input_key(&context, NK_KEY_TEXT_LINE_START, down && lctrl); + else if (!strcmp(key, "e")) + nk_input_key(&context, NK_KEY_TEXT_LINE_END, down && lctrl); + else if (!strcmp(key, "left")) { + if (lctrl) + nk_input_key(&context, NK_KEY_TEXT_WORD_LEFT, down); + else + nk_input_key(&context, NK_KEY_LEFT, down); + } else if (!strcmp(key, "right")) { + if (lctrl) + nk_input_key(&context, NK_KEY_TEXT_WORD_RIGHT, down); + else + nk_input_key(&context, NK_KEY_RIGHT, down); + } else if (!strcmp(key, "up")) + nk_input_key(&context, NK_KEY_UP, down); + else if (!strcmp(key, "down")) + nk_input_key(&context, NK_KEY_DOWN, down); + else + return 0; + return nk_love_is_active(&context); +} + +static int nk_love_clickevent(int x, int y, int button, int istouch, int down) +{ + if (button == 1) + nk_input_button(&context, NK_BUTTON_LEFT, x, y, down); + else if (button == 3) + nk_input_button(&context, NK_BUTTON_MIDDLE, x, y, down); + else if (button == 2) + nk_input_button(&context, NK_BUTTON_RIGHT, x, y, down); + else + return 0; + return nk_window_is_any_hovered(&context); +} + +static int nk_love_mousemoved_event(int x, int y, int dx, int dy, int istouch) +{ + nk_input_motion(&context, x, y); + return nk_window_is_any_hovered(&context); +} + +static int nk_love_textinput_event(const char *text) +{ + nk_rune rune; + nk_utf_decode(text, &rune, strlen(text)); + nk_input_unicode(&context, rune); + return nk_love_is_active(&context); +} + +static int nk_love_wheelmoved_event(int x, int y) +{ + nk_input_scroll(&context,(float)y); + return nk_window_is_any_hovered(&context); +} + +/* + * =============================================================== + * + * WRAPPER + * + * =============================================================== + */ + +static void nk_love_error(const char *msg) +{ + lua_getglobal(L, "error"); + lua_pushstring(L, msg); + lua_call(L, 1, 0); +} + +static void nk_love_assert(int pass, const char *msg) +{ + if (!pass) { + nk_love_error(msg); + } +} + +static void nk_love_assert_type(int index, const char *type, const char *message) +{ + if (index < 0) { + index += lua_gettop(L) + 1; + } + nk_love_assert(lua_type(L, index) == LUA_TUSERDATA, message); + lua_getfield(L, index, "typeOf"); + nk_love_assert(lua_type(L, -1) == LUA_TFUNCTION, message); + lua_pushvalue(L, index); + lua_pushstring(L, type); + lua_call(L, 2, 1); + nk_love_assert(lua_type(L, -1) == LUA_TBOOLEAN, message); + int is_type = lua_toboolean(L, -1); + nk_love_assert(is_type, message); + lua_pop(L, 1); +} + +static void nk_love_assert_hex(char c, const char *message) +{ + nk_love_assert((c >= '0' && c <= '9') + || (c >= 'a' && c <= 'f') + || (c >= 'A' && c <= 'F'), message); +} + +static void nk_love_assert_color(int index, const char *message) +{ + nk_love_assert(lua_type(L, index) == LUA_TSTRING, message); + const char *color_string = lua_tostring(L, index); + size_t len = strlen(color_string); + if (len == 7 || len == 9) { + nk_love_assert(color_string[0] == '#', message); + int i; + for (i = 1; i < len; ++i) { + nk_love_assert_hex(color_string[i], message); + } + } else { + nk_love_error(message); + } +} + +static nk_flags nk_love_parse_window_flags(int flags_begin) { + int argc = lua_gettop(L); + nk_flags flags = NK_WINDOW_NO_SCROLLBAR; + int i; + for (i = flags_begin; i <= argc; ++i) { + nk_love_assert(lua_type(L, i) == LUA_TSTRING, "window flags must be strings"); + const char *flag = lua_tostring(L, i); + if (!strcmp(flag, "border")) + flags |= NK_WINDOW_BORDER; + else if (!strcmp(flag, "movable")) + flags |= NK_WINDOW_MOVABLE; + else if (!strcmp(flag, "scalable")) + flags |= NK_WINDOW_SCALABLE; + else if (!strcmp(flag, "closable")) + flags |= NK_WINDOW_CLOSABLE; + else if (!strcmp(flag, "minimizable")) + flags |= NK_WINDOW_MINIMIZABLE; + else if (!strcmp(flag, "scrollbar")) + flags &= ~NK_WINDOW_NO_SCROLLBAR; + else if (!strcmp(flag, "title")) + flags |= NK_WINDOW_TITLE; + else if (!strcmp(flag, "scroll auto hide")) + flags |= NK_WINDOW_SCROLL_AUTO_HIDE; + else if (!strcmp(flag, "background")) + flags |= NK_WINDOW_BACKGROUND; + else + nk_love_error("unrecognized window flag"); + + } + return flags; +} + +static void nk_love_tofont(struct nk_user_font *font) +{ + lua_getfield(L, LUA_REGISTRYINDEX, "nuklear"); + lua_getfield(L, -1, "font"); + lua_pushvalue(L, -3); + int ref = luaL_ref(L, -2); + lua_getfield(L, -3, "getHeight"); + lua_pushvalue(L, -4); + lua_call(L, 1, 1); + float height = lua_tonumber(L, -1); + font->userdata = nk_handle_id(ref); + font->height = height; + font->width = nk_love_get_text_width; + lua_pop(L, 4); +} + +static void nk_love_toimage(struct nk_image *image) +{ + lua_getfield(L, LUA_REGISTRYINDEX, "nuklear"); + lua_getfield(L, -1, "image"); + lua_pushvalue(L, -3); + int ref = luaL_ref(L, -2); + lua_getfield(L, -3, "getDimensions"); + lua_pushvalue(L, -4); + lua_call(L, 1, 2); + int width = lua_tointeger(L, -2); + int height = lua_tointeger(L, -1); + image->handle = nk_handle_id(ref); + image->w = width; + image->h = height; + image->region[0] = 0; + image->region[1] = 0; + image->region[2] = width; + image->region[3] = height; + lua_pop(L, 5); +} + +static int nk_love_parse_symbol(const char *s, enum nk_symbol_type *symbol) +{ + if (!strcmp(s, "none")) { + *symbol = NK_SYMBOL_NONE; + } else if (!strcmp(s, "x")) { + *symbol = NK_SYMBOL_X; + } else if (!strcmp(s, "underscore")) { + *symbol = NK_SYMBOL_UNDERSCORE; + } else if (!strcmp(s, "circle solid")) { + *symbol = NK_SYMBOL_CIRCLE_SOLID; + } else if (!strcmp(s, "circle outline")) { + *symbol = NK_SYMBOL_CIRCLE_OUTLINE; + } else if (!strcmp(s, "rect solid")) { + *symbol = NK_SYMBOL_RECT_SOLID; + } else if (!strcmp(s, "rect outline")) { + *symbol = NK_SYMBOL_RECT_OUTLINE; + } else if (!strcmp(s, "triangle up")) { + *symbol = NK_SYMBOL_TRIANGLE_UP; + } else if (!strcmp(s, "triangle down")) { + *symbol = NK_SYMBOL_TRIANGLE_DOWN; + } else if (!strcmp(s, "triangle left")) { + *symbol = NK_SYMBOL_TRIANGLE_LEFT; + } else if (!strcmp(s, "triangle right")) { + *symbol = NK_SYMBOL_TRIANGLE_RIGHT; + } else if (!strcmp(s, "plus")) { + *symbol = NK_SYMBOL_PLUS; + } else if (!strcmp(s, "minus")) { + *symbol = NK_SYMBOL_MINUS; + } else if (!strcmp(s, "max")) { + *symbol = NK_SYMBOL_MAX; + } else { + return 0; + } + return 1; +} + +static int nk_love_parse_align(const char *s, nk_flags *align) +{ + if (!strcmp(s, "left")) { + *align = NK_TEXT_LEFT; + } else if (!strcmp(s, "centered")) { + *align = NK_TEXT_CENTERED; + } else if (!strcmp(s, "right")) { + *align = NK_TEXT_RIGHT; + } else if (!strcmp(s, "top left")) { + *align = NK_TEXT_ALIGN_TOP | NK_TEXT_ALIGN_LEFT; + } else if (!strcmp(s, "top centered")) { + *align = NK_TEXT_ALIGN_TOP | NK_TEXT_ALIGN_CENTERED; + } else if (!strcmp(s, "top right")) { + *align = NK_TEXT_ALIGN_TOP | NK_TEXT_ALIGN_RIGHT; + } else if (!strcmp(s, "bottom left")) { + *align = NK_TEXT_ALIGN_BOTTOM | NK_TEXT_ALIGN_LEFT; + } else if (!strcmp(s, "bottom centered")) { + *align = NK_TEXT_ALIGN_BOTTOM | NK_TEXT_ALIGN_CENTERED; + } else if (!strcmp(s, "bottom right")) { + *align = NK_TEXT_ALIGN_BOTTOM | NK_TEXT_ALIGN_RIGHT; + } else { + return 0; + } + return 1; +} + +static int nk_love_parse_button(const char *s, enum nk_buttons *button) +{ + if (!strcmp(s, "left")) { + *button = NK_BUTTON_LEFT; + } else if (!strcmp(s, "right")) { + *button = NK_BUTTON_RIGHT; + } else if (!strcmp(s, "middle")) { + *button = NK_BUTTON_MIDDLE; + } else { + return 0; + } + return 1; +} + +static int nk_love_init(lua_State *luaState) +{ + L = luaState; + nk_love_assert(lua_gettop(L) == 0, "nk.init: wrong number of arguments"); + lua_newtable(L); + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, "nuklear"); + lua_newtable(L); + lua_setfield(L, -2, "font"); + lua_newtable(L); + lua_setfield(L, -2, "image"); + lua_newtable(L); + lua_setfield(L, -2, "stack"); + fonts = malloc(sizeof(struct nk_user_font) * NK_LOVE_MAX_FONTS); + nk_love_assert(fonts != NULL, "nk.init: out of memory"); + lua_getglobal(L, "love"); + nk_love_assert(lua_type(L, -1) == LUA_TTABLE, "nk.init: requires LOVE environment"); + lua_getfield(L, -1, "graphics"); + lua_getfield(L, -1, "getFont"); + lua_call(L, 0, 1); + nk_love_tofont(&fonts[0]); + nk_init_default(&context, &fonts[0]); + font_count = 1; + context.clip.copy = nk_love_clipbard_copy; + context.clip.paste = nk_love_clipbard_paste; + context.clip.userdata = nk_handle_ptr(0); + edit_buffer = malloc(NK_LOVE_EDIT_BUFFER_LEN); + nk_love_assert(edit_buffer != NULL, "nk.init: out of memory"); + combobox_items = malloc(sizeof(char*) * NK_LOVE_COMBOBOX_MAX_ITEMS); + nk_love_assert(combobox_items != NULL, "nk.init: out of memory"); + layout_ratios = malloc(sizeof(float) * NK_LOVE_MAX_RATIOS); + nk_love_assert(layout_ratios != NULL, "nk.init: out of memory"); + return 0; +} + +static int nk_love_shutdown(lua_State *luaState) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.shutdown: wrong number of arguments"); + nk_free(&context); + lua_pushnil(L); + lua_setfield(L, LUA_REGISTRYINDEX, "nuklear"); + L = NULL; + free(fonts); + fonts = NULL; + free(edit_buffer); + edit_buffer = NULL; + free(combobox_items); + combobox_items = NULL; + free(layout_ratios); + layout_ratios = NULL; + return 0; +} + +static int nk_love_keypressed(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 3, "nk.keypressed: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.keypressed: arg 1 should be a string"); + nk_love_assert(lua_type(L, 2) == LUA_TSTRING, "nk.keypressed: arg 2 should be a string"); + nk_love_assert(lua_type(L, 3) == LUA_TBOOLEAN, "nk.keypressed: arg 3 should be a boolean"); + const char *key = lua_tostring(L, 1); + const char *scancode = lua_tostring(L, 2); + int isrepeat = lua_toboolean(L, 3); + int consume = nk_love_keyevent(key, scancode, isrepeat, 1); + lua_pushboolean(L, consume); + return 1; +} + +static int nk_love_keyreleased(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 2, "nk.keyreleased: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.keyreleased: arg 1 should be a string"); + nk_love_assert(lua_type(L, 2) == LUA_TSTRING, "nk.keyreleased: arg 2 should be a string"); + const char *key = lua_tostring(L, 1); + const char *scancode = lua_tostring(L, 2); + int consume = nk_love_keyevent(key, scancode, 0, 0); + lua_pushboolean(L, consume); + return 1; +} + +static int nk_love_mousepressed(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 4, "nk.mousepressed: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TNUMBER, "nk.mousepressed: arg 1 should be a number"); + nk_love_assert(lua_type(L, 2) == LUA_TNUMBER, "nk.mousepressed: arg 2 should be a number"); + nk_love_assert(lua_type(L, 3) == LUA_TNUMBER, "nk.mousepressed: arg 3 should be a number"); + nk_love_assert(lua_type(L, 4) == LUA_TBOOLEAN, "nk.mousepressed: arg 4 should be a boolean"); + int x = lua_tointeger(L, 1); + int y = lua_tointeger(L, 2); + int button = lua_tointeger(L, 3); + int istouch = lua_toboolean(L, 4); + int consume = nk_love_clickevent(x, y, button, istouch, 1); + lua_pushboolean(L, consume); + return 1; +} + +static int nk_love_mousereleased(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 4, "nk.mousereleased: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TNUMBER, "nk.mousereleased: arg 1 should be a number"); + nk_love_assert(lua_type(L, 2) == LUA_TNUMBER, "nk.mousereleased: arg 2 should be a number"); + nk_love_assert(lua_type(L, 3) == LUA_TNUMBER, "nk.mousereleased: arg 3 should be a number"); + nk_love_assert(lua_type(L, 4) == LUA_TBOOLEAN, "nk.mousereleased: arg 4 should be a boolean"); + int x = lua_tointeger(L, 1); + int y = lua_tointeger(L, 2); + int button = lua_tointeger(L, 3); + int istouch = lua_toboolean(L, 4); + int consume = nk_love_clickevent(x, y, button, istouch, 0); + lua_pushboolean(L, consume); + return 1; +} + +static int nk_love_mousemoved(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 5, "nk.mousemoved: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TNUMBER, "nk.mousemoved: arg 1 should be a number"); + nk_love_assert(lua_type(L, 2) == LUA_TNUMBER, "nk.mousemoved: arg 2 should be a number"); + nk_love_assert(lua_type(L, 3) == LUA_TNUMBER, "nk.mousemoved: arg 3 should be a number"); + nk_love_assert(lua_type(L, 4) == LUA_TNUMBER, "nk.mousemoved: arg 4 should be a number"); + nk_love_assert(lua_type(L, 5) == LUA_TBOOLEAN, "nk.mousemoved: arg 5 should be a boolean"); + int x = lua_tointeger(L, 1); + int y = lua_tointeger(L, 2); + int dx = lua_tointeger(L, 3); + int dy = lua_tointeger(L, 4); + int istouch = lua_toboolean(L, 5); + int consume = nk_love_mousemoved_event(x, y, dx, dy, istouch); + lua_pushboolean(L, consume); + return 1; +} + +static int nk_love_textinput(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.textinput: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.textinput: arg 1 should be a string"); + const char *text = lua_tostring(L, 1); + int consume = nk_love_textinput_event(text); + lua_pushboolean(L, consume); + return 1; +} + +static int nk_love_wheelmoved(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 2, "nk.wheelmoved: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TNUMBER, "nk.wheelmoved: arg 1 should be a number"); + nk_love_assert(lua_type(L, 2) == LUA_TNUMBER, "nk.wheelmoved: arg 2 should be a number"); + int x = lua_tointeger(L, 1); + int y = lua_tointeger(L, 2); + int consume = nk_love_wheelmoved_event(x, y); + lua_pushboolean(L, consume); + return 1; +} + +static int nk_love_draw(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.draw: wrong number of arguments"); + + lua_getglobal(L, "love"); + lua_getfield(L, -1, "graphics"); + + lua_getfield(L, -1, "push"); + lua_pushstring(L, "all"); + lua_call(L, 1, 0); + + const struct nk_command *cmd; + nk_foreach(cmd, &context) + { + switch (cmd->type) { + case NK_COMMAND_NOP: break; + case NK_COMMAND_SCISSOR: { + const struct nk_command_scissor *s =(const struct nk_command_scissor*)cmd; + nk_love_scissor(s->x, s->y, s->w, s->h); + } break; + case NK_COMMAND_LINE: { + const struct nk_command_line *l = (const struct nk_command_line *)cmd; + nk_love_draw_line(l->begin.x, l->begin.y, l->end.x, + l->end.y, l->line_thickness, l->color); + } break; + case NK_COMMAND_RECT: { + const struct nk_command_rect *r = (const struct nk_command_rect *)cmd; + nk_love_draw_rect(r->x, r->y, r->w, r->h, + (unsigned int)r->rounding, r->line_thickness, r->color); + } break; + case NK_COMMAND_RECT_FILLED: { + const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled *)cmd; + nk_love_draw_rect(r->x, r->y, r->w, r->h, (unsigned int)r->rounding, -1, r->color); + } break; + case NK_COMMAND_CIRCLE: { + const struct nk_command_circle *c = (const struct nk_command_circle *)cmd; + nk_love_draw_circle(c->x, c->y, c->w, c->h, c->line_thickness, c->color); + } break; + case NK_COMMAND_CIRCLE_FILLED: { + const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd; + nk_love_draw_circle(c->x, c->y, c->w, c->h, -1, c->color); + } break; + case NK_COMMAND_TRIANGLE: { + const struct nk_command_triangle*t = (const struct nk_command_triangle*)cmd; + nk_love_draw_triangle(t->a.x, t->a.y, t->b.x, t->b.y, + t->c.x, t->c.y, t->line_thickness, t->color); + } break; + case NK_COMMAND_TRIANGLE_FILLED: { + const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled *)cmd; + nk_love_draw_triangle(t->a.x, t->a.y, t->b.x, t->b.y, t->c.x, t->c.y, -1, t->color); + } break; + case NK_COMMAND_POLYGON: { + const struct nk_command_polygon *p =(const struct nk_command_polygon*)cmd; + nk_love_draw_polygon(p->points, p->point_count, p->line_thickness, p->color); + } break; + case NK_COMMAND_POLYGON_FILLED: { + const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd; + nk_love_draw_polygon(p->points, p->point_count, -1, p->color); + } break; + case NK_COMMAND_POLYLINE: { + const struct nk_command_polyline *p = (const struct nk_command_polyline *)cmd; + nk_love_draw_polyline(p->points, p->point_count, p->line_thickness, p->color); + } break; + case NK_COMMAND_TEXT: { + const struct nk_command_text *t = (const struct nk_command_text*)cmd; + nk_love_draw_text(t->font->userdata.id, t->background, + t->foreground, t->x, t->y, t->w, t->h, + t->height, t->length, (const char*)t->string); + } break; + case NK_COMMAND_CURVE: { + const struct nk_command_curve *q = (const struct nk_command_curve *)cmd; + nk_love_draw_curve(q->begin, q->ctrl[0], q->ctrl[1], + q->end, 22, q->line_thickness, q->color); + } break; + case NK_COMMAND_RECT_MULTI_COLOR: { + const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color *)cmd; + nk_love_draw_rect_multi_color(r->x, r->y, r->w, r->h, r->left, r->top, r->right, r->bottom); + } break; + case NK_COMMAND_IMAGE: { + const struct nk_command_image *i = (const struct nk_command_image *)cmd; + nk_love_draw_image(i->x, i->y, i->w, i->h, i->img, i->col); + } break; + case NK_COMMAND_ARC: { + const struct nk_command_arc *a = (const struct nk_command_arc *)cmd; + nk_love_draw_arc(a->cx, a->cy, a->r, a->line_thickness, + a->a[0], a->a[1], a->color); + } break; + case NK_COMMAND_ARC_FILLED: { + const struct nk_command_arc_filled *a = (const struct nk_command_arc_filled *)cmd; + nk_love_draw_arc(a->cx, a->cy, a->r, -1, a->a[0], a->a[1], a->color); + } break; + default: break; + } + } + + lua_getfield(L, -1, "pop"); + lua_call(L, 0, 0); + lua_pop(L, 2); + nk_clear(&context); + return 0; +} + +static void nk_love_preserve(struct nk_style_item *item) +{ + if (item->type == NK_STYLE_ITEM_IMAGE) { + lua_rawgeti(L, -1, item->data.image.handle.id); + nk_love_toimage(&item->data.image); + } +} + +static void nk_love_preserve_all(void) +{ + nk_love_preserve(&context.style.button.normal); + nk_love_preserve(&context.style.button.hover); + nk_love_preserve(&context.style.button.active); + + nk_love_preserve(&context.style.contextual_button.normal); + nk_love_preserve(&context.style.contextual_button.hover); + nk_love_preserve(&context.style.contextual_button.active); + + nk_love_preserve(&context.style.menu_button.normal); + nk_love_preserve(&context.style.menu_button.hover); + nk_love_preserve(&context.style.menu_button.active); + + nk_love_preserve(&context.style.option.normal); + nk_love_preserve(&context.style.option.hover); + nk_love_preserve(&context.style.option.active); + nk_love_preserve(&context.style.option.cursor_normal); + nk_love_preserve(&context.style.option.cursor_hover); + + nk_love_preserve(&context.style.checkbox.normal); + nk_love_preserve(&context.style.checkbox.hover); + nk_love_preserve(&context.style.checkbox.active); + nk_love_preserve(&context.style.checkbox.cursor_normal); + nk_love_preserve(&context.style.checkbox.cursor_hover); + + nk_love_preserve(&context.style.selectable.normal); + nk_love_preserve(&context.style.selectable.hover); + nk_love_preserve(&context.style.selectable.pressed); + nk_love_preserve(&context.style.selectable.normal_active); + nk_love_preserve(&context.style.selectable.hover_active); + nk_love_preserve(&context.style.selectable.pressed_active); + + nk_love_preserve(&context.style.slider.normal); + nk_love_preserve(&context.style.slider.hover); + nk_love_preserve(&context.style.slider.active); + nk_love_preserve(&context.style.slider.cursor_normal); + nk_love_preserve(&context.style.slider.cursor_hover); + nk_love_preserve(&context.style.slider.cursor_active); + + nk_love_preserve(&context.style.progress.normal); + nk_love_preserve(&context.style.progress.hover); + nk_love_preserve(&context.style.progress.active); + nk_love_preserve(&context.style.progress.cursor_normal); + nk_love_preserve(&context.style.progress.cursor_hover); + nk_love_preserve(&context.style.progress.cursor_active); + + nk_love_preserve(&context.style.property.normal); + nk_love_preserve(&context.style.property.hover); + nk_love_preserve(&context.style.property.active); + nk_love_preserve(&context.style.property.edit.normal); + nk_love_preserve(&context.style.property.edit.hover); + nk_love_preserve(&context.style.property.edit.active); + nk_love_preserve(&context.style.property.inc_button.normal); + nk_love_preserve(&context.style.property.inc_button.hover); + nk_love_preserve(&context.style.property.inc_button.active); + nk_love_preserve(&context.style.property.dec_button.normal); + nk_love_preserve(&context.style.property.dec_button.hover); + nk_love_preserve(&context.style.property.dec_button.active); + + nk_love_preserve(&context.style.edit.normal); + nk_love_preserve(&context.style.edit.hover); + nk_love_preserve(&context.style.edit.active); + nk_love_preserve(&context.style.edit.scrollbar.normal); + nk_love_preserve(&context.style.edit.scrollbar.hover); + nk_love_preserve(&context.style.edit.scrollbar.active); + nk_love_preserve(&context.style.edit.scrollbar.cursor_normal); + nk_love_preserve(&context.style.edit.scrollbar.cursor_hover); + nk_love_preserve(&context.style.edit.scrollbar.cursor_active); + + nk_love_preserve(&context.style.chart.background); + + nk_love_preserve(&context.style.scrollh.normal); + nk_love_preserve(&context.style.scrollh.hover); + nk_love_preserve(&context.style.scrollh.active); + nk_love_preserve(&context.style.scrollh.cursor_normal); + nk_love_preserve(&context.style.scrollh.cursor_hover); + nk_love_preserve(&context.style.scrollh.cursor_active); + + nk_love_preserve(&context.style.scrollv.normal); + nk_love_preserve(&context.style.scrollv.hover); + nk_love_preserve(&context.style.scrollv.active); + nk_love_preserve(&context.style.scrollv.cursor_normal); + nk_love_preserve(&context.style.scrollv.cursor_hover); + nk_love_preserve(&context.style.scrollv.cursor_active); + + nk_love_preserve(&context.style.tab.background); + nk_love_preserve(&context.style.tab.tab_maximize_button.normal); + nk_love_preserve(&context.style.tab.tab_maximize_button.hover); + nk_love_preserve(&context.style.tab.tab_maximize_button.active); + nk_love_preserve(&context.style.tab.tab_minimize_button.normal); + nk_love_preserve(&context.style.tab.tab_minimize_button.hover); + nk_love_preserve(&context.style.tab.tab_minimize_button.active); + nk_love_preserve(&context.style.tab.node_maximize_button.normal); + nk_love_preserve(&context.style.tab.node_maximize_button.hover); + nk_love_preserve(&context.style.tab.node_maximize_button.active); + nk_love_preserve(&context.style.tab.node_minimize_button.normal); + nk_love_preserve(&context.style.tab.node_minimize_button.hover); + nk_love_preserve(&context.style.tab.node_minimize_button.active); + + nk_love_preserve(&context.style.combo.normal); + nk_love_preserve(&context.style.combo.hover); + nk_love_preserve(&context.style.combo.active); + nk_love_preserve(&context.style.combo.button.normal); + nk_love_preserve(&context.style.combo.button.hover); + nk_love_preserve(&context.style.combo.button.active); + + nk_love_preserve(&context.style.window.fixed_background); + nk_love_preserve(&context.style.window.scaler); + nk_love_preserve(&context.style.window.header.normal); + nk_love_preserve(&context.style.window.header.hover); + nk_love_preserve(&context.style.window.header.active); + nk_love_preserve(&context.style.window.header.close_button.normal); + nk_love_preserve(&context.style.window.header.close_button.hover); + nk_love_preserve(&context.style.window.header.close_button.active); + nk_love_preserve(&context.style.window.header.minimize_button.normal); + nk_love_preserve(&context.style.window.header.minimize_button.hover); + nk_love_preserve(&context.style.window.header.minimize_button.active); +} + +static int nk_love_frame_begin(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.frame_begin: wrong number of arguments"); + nk_input_end(&context); + lua_getglobal(L, "love"); + lua_getfield(L, -1, "timer"); + lua_getfield(L, -1, "getDelta"); + lua_call(L, 0, 1); + float dt = lua_tonumber(L, -1); + context.delta_time_seconds = dt; + lua_getfield(L, LUA_REGISTRYINDEX, "nuklear"); + lua_getfield(L, -1, "image"); + lua_newtable(L); + lua_setfield(L, -3, "image"); + nk_love_preserve_all(); + lua_pop(L, 1); + lua_getfield(L, -1, "font"); + lua_newtable(L); + lua_setfield(L, -3, "font"); + font_count = 0; + lua_rawgeti(L, -1, context.style.font->userdata.id); + nk_love_tofont(&fonts[font_count]); + context.style.font = &fonts[font_count++]; + int i; + for (i = 0; i < context.stacks.fonts.head; ++i) { + struct nk_config_stack_user_font_element *element = &context.stacks.fonts.elements[i]; + lua_rawgeti(L, -1, element->old_value->userdata.id); + nk_love_tofont(&fonts[font_count]); + context.stacks.fonts.elements[i].old_value = &fonts[font_count++]; + } + layout_ratio_count = 0; + return 0; +} + +static int nk_love_frame_end(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.frame_end: wrong number of arguments"); + nk_input_begin(&context); + return 0; +} + +static int nk_love_window_begin(lua_State *L) +{ + const char *name, *title; + int bounds_begin; + if (lua_type(L, 2) == LUA_TNUMBER) { + nk_love_assert(lua_gettop(L) >= 5, "nk.window_begin: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.window_begin: arg 1 should be a string"); + nk_love_assert(lua_type(L, 3) == LUA_TNUMBER, "nk.window_begin: arg 3 should be a number"); + nk_love_assert(lua_type(L, 4) == LUA_TNUMBER, "nk.window_begin: arg 4 should be a number"); + nk_love_assert(lua_type(L, 5) == LUA_TNUMBER, "nk.window_begin: arg 5 should be a number"); + name = title = lua_tostring(L, 1); + bounds_begin = 2; + } else { + nk_love_assert(lua_gettop(L) >= 6, "nk.window_begin: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.window_begin: arg 1 should be a string"); + nk_love_assert(lua_type(L, 2) == LUA_TSTRING, "nk.window_begin: arg 2 should be a string"); + nk_love_assert(lua_type(L, 3) == LUA_TNUMBER, "nk.window_begin: arg 3 should be a number"); + nk_love_assert(lua_type(L, 4) == LUA_TNUMBER, "nk.window_begin: arg 4 should be a number"); + nk_love_assert(lua_type(L, 5) == LUA_TNUMBER, "nk.window_begin: arg 5 should be a number"); + nk_love_assert(lua_type(L, 6) == LUA_TNUMBER, "nk.window_begin: arg 6 should be a number"); + name = lua_tostring(L, 1); + title = lua_tostring(L, 2); + bounds_begin = 3; + } + nk_flags flags = nk_love_parse_window_flags(bounds_begin + 4); + float x = lua_tonumber(L, bounds_begin); + float y = lua_tonumber(L, bounds_begin + 1); + float width = lua_tonumber(L, bounds_begin + 2); + float height = lua_tonumber(L, bounds_begin + 3); + int open = nk_begin_titled(&context, name, title, nk_rect(x, y, width, height), flags); + lua_pushboolean(L, open); + return 1; +} + +static int nk_love_window_end(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.window_end: wrong number of arguments"); + nk_end(&context); + return 0; +} + +static int nk_love_window_get_bounds(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.window_get_bounds: wrong number of arguments"); + struct nk_rect rect = nk_window_get_bounds(&context); + lua_pushnumber(L, rect.x); + lua_pushnumber(L, rect.y); + lua_pushnumber(L, rect.w); + lua_pushnumber(L, rect.h); + return 4; +} + +static int nk_love_window_get_position(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.window_get_position: wrong number of arguments"); + struct nk_vec2 pos = nk_window_get_position(&context); + lua_pushnumber(L, pos.x); + lua_pushnumber(L, pos.y); + return 2; +} + +static int nk_love_window_get_size(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.window_get_size: wrong number of arguments"); + struct nk_vec2 size = nk_window_get_size(&context); + lua_pushnumber(L, size.x); + lua_pushnumber(L, size.y); + return 2; +} + +static int nk_love_window_get_content_region(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.window_get_content_region: wrong number of arguments"); + struct nk_rect rect = nk_window_get_content_region(&context); + lua_pushnumber(L, rect.x); + lua_pushnumber(L, rect.y); + lua_pushnumber(L, rect.w); + lua_pushnumber(L, rect.h); + return 4; +} + +static int nk_love_window_has_focus(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.window_has_focus: wrong number of arguments"); + int has_focus = nk_window_has_focus(&context); + lua_pushboolean(L, has_focus); + return 1; +} + +static int nk_love_window_is_collapsed(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.window_is_collapsed: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.window_is_collapsed: arg 1 should be a string"); + const char *name = lua_tostring(L, 1); + int is_collapsed = nk_window_is_collapsed(&context, name); + lua_pushboolean(L, is_collapsed); + return 1; +} + +static int nk_love_window_is_hidden(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.window_is_hidden: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.window_is_hidden: arg 1 should be a string"); + const char *name = lua_tostring(L, 1); + int is_hidden = nk_window_is_hidden(&context, name); + lua_pushboolean(L, is_hidden); + return 1; +} + +static int nk_love_window_is_active(lua_State *L) { + nk_love_assert(lua_gettop(L) == 1, "nk.window_is_active: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.window_is_active: arg 1 should be a string"); + const char *name = lua_tostring(L, 1); + int is_active = nk_window_is_active(&context, name); + lua_pushboolean(L, is_active); + return 1; +} + +static int nk_love_window_is_hovered(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.window_is_hovered: wrong number of arguments"); + int is_hovered = nk_window_is_hovered(&context); + lua_pushboolean(L, is_hovered); + return 1; +} + +static int nk_love_window_is_any_hovered(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.window_is_any_hovered: wrong number of arguments"); + int is_any_hovered = nk_window_is_any_hovered(&context); + lua_pushboolean(L, is_any_hovered); + return 1; +} + +static int nk_love_item_is_any_active(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.item_is_any_active: wrong number of arguments"); + lua_pushboolean(L, nk_love_is_active(&context)); + return 1; +} + +static int nk_love_window_set_bounds(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 4, "nk.window_set_bounds: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TNUMBER, "nk.window_set_bounds: arg 1 should be a number"); + nk_love_assert(lua_type(L, 2) == LUA_TNUMBER, "nk.window_set_bounds: arg 2 should be a number"); + nk_love_assert(lua_type(L, 3) == LUA_TNUMBER, "nk.window_set_bounds: arg 3 should be a number"); + nk_love_assert(lua_type(L, 4) == LUA_TNUMBER, "nk.window_set_bounds: arg 4 should be a number"); + struct nk_rect bounds; + bounds.x = lua_tonumber(L, 1); + bounds.y = lua_tonumber(L, 2); + bounds.w = lua_tonumber(L, 3); + bounds.h = lua_tonumber(L, 4); + nk_window_set_bounds(&context, bounds); + return 0; +} + +static int nk_love_window_set_position(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 2, "nk.window_set_position: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TNUMBER, "nk.window_set_position: arg 1 should be a number"); + nk_love_assert(lua_type(L, 2) == LUA_TNUMBER, "nk.window_set_position: arg 2 should be a number"); + struct nk_vec2 pos; + pos.x = lua_tonumber(L, 1); + pos.y = lua_tonumber(L, 2); + nk_window_set_position(&context, pos); + return 0; +} + +static int nk_love_window_set_size(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 2, "nk.window_set_size: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TNUMBER, "nk.window_set_size: arg 1 should be a number"); + nk_love_assert(lua_type(L, 2) == LUA_TNUMBER, "nk.window_set_size: arg 2 should be a number"); + struct nk_vec2 size; + size.x = lua_tonumber(L, 1); + size.y = lua_tonumber(L, 2); + nk_window_set_size(&context, size); + return 0; +} + +static int nk_love_window_set_focus(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.window_set_focus: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.window_set_focus: arg 1 should be a string"); + const char *name = lua_tostring(L, 1); + nk_window_set_focus(&context, name); + return 0; +} + +static int nk_love_window_close(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.window_close: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.window_close: arg 1 should be a string"); + const char *name = lua_tostring(L, 1); + nk_window_close(&context, name); + return 0; +} + +static int nk_love_window_collapse(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.window_collapse: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.window_collapse: arg 1 should be a string"); + const char *name = lua_tostring(L, 1); + nk_window_collapse(&context, name, NK_MINIMIZED); + return 0; +} + +static int nk_love_window_expand(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.window_expand: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.window_expand: arg 1 should be a string"); + const char *name = lua_tostring(L, 1); + nk_window_collapse(&context, name, NK_MAXIMIZED); + return 0; +} + +static int nk_love_window_show(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.window_show: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.window_show: arg 1 should be a string"); + const char *name = lua_tostring(L, 1); + nk_window_show(&context, name, NK_SHOWN); + return 0; +} + +static int nk_love_window_hide(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.window_hide: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.window_hide: arg 1 should be a string"); + const char *name = lua_tostring(L, 1); + nk_window_show(&context, name, NK_HIDDEN); + return 0; +} + +static int nk_love_layout_row(lua_State *L) +{ + int argc = lua_gettop(L); + nk_love_assert(argc == 3 || argc == 4, "nk.layout_row: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.layout_row: arg 1 should be a string"); + nk_love_assert(lua_type(L, 2) == LUA_TNUMBER, "nk.layout_row: arg 2 should be a number"); + const char *type = lua_tostring(L, 1); + float height = lua_tonumber(L, 2); + enum nk_layout_format format; + int use_ratios = 0; + if (!strcmp(type, "dynamic")) { + nk_love_assert(argc == 3, "nk.layout_row: wrong number of arguments"); + if (lua_type(L, 3) == LUA_TNUMBER) { + int cols = lua_tointeger(L, 3); + nk_layout_row_dynamic(&context, height, cols); + } else { + nk_love_assert(lua_type(L, 3) == LUA_TTABLE, "nk.layout_row: arg 3 should be a number or table"); + format = NK_DYNAMIC; + use_ratios = 1; + } + } else if (!strcmp(type, "static")) { + if (argc == 4) { + nk_love_assert(lua_type(L, 3) == LUA_TNUMBER, "nk.layout_row: arg 3 should be a number"); + nk_love_assert(lua_type(L, 4) == LUA_TNUMBER, "nk.layout_row: arg 4 should be a number"); + int item_width = lua_tointeger(L, 3); + int cols = lua_tointeger(L, 4); + nk_layout_row_static(&context, height, item_width, cols); + } else { + nk_love_assert(lua_type(L, 3) == LUA_TTABLE, "nk.layout_row: arg 3 should be a number or table"); + format = NK_STATIC; + use_ratios = 1; + } + } else { + nk_love_error("nk.layout_row: arg 1 should be 'dynamic' or 'static'"); + } + if (use_ratios) { + int cols = lua_objlen(L, -1); + int i, j; + for (i = 1, j = layout_ratio_count; i <= cols && j < NK_LOVE_MAX_RATIOS; ++i, ++j) { + lua_rawgeti(L, -1, i); + layout_ratios[j] = lua_tonumber(L, -1); + lua_pop(L, 1); + } + nk_layout_row(&context, format, height, cols, layout_ratios + layout_ratio_count); + layout_ratio_count += cols; + } + return 0; +} + +static int nk_love_layout_row_begin(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 3, "nk.layout_row_begin: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.layout_row_begin: arg 1 should be a string"); + nk_love_assert(lua_type(L, 2) == LUA_TNUMBER, "nk.layout_row_begin: arg 2 should be a number"); + nk_love_assert(lua_type(L, 3) == LUA_TNUMBER, "nk.layout_row_begin: arg 3 should be a number"); + const char *type = lua_tostring(L, 1); + float height = lua_tonumber(L, 2); + int cols = lua_tointeger(L, 3); + enum nk_layout_format format; + if (!strcmp(type, "dynamic")) { + format = NK_DYNAMIC; + } else if (!strcmp(type, "static")) { + format = NK_STATIC; + } else { + nk_love_error("nk.layout_row_begin: arg 1 should be 'dynamic' or 'static'"); + } + nk_layout_row_begin(&context, format, height, cols); + return 0; +} + +static int nk_love_layout_row_push(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.layout_row_push: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TNUMBER, "nk.layout_row_push: arg 1 should be a number"); + float value = lua_tonumber(L, 1); + nk_layout_row_push(&context, value); + return 0; +} + +static int nk_love_layout_row_end(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.layout_row_end: wrong number of arguments"); + nk_layout_row_end(&context); + return 0; +} + +static int nk_love_layout_space_begin(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 3, "nk.layout_space_begin: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.layout_space_begin: arg 1 should be a string"); + nk_love_assert(lua_type(L, 2) == LUA_TNUMBER, "nk.layout_space_begin: arg 2 should be a number"); + nk_love_assert(lua_type(L, 3) == LUA_TNUMBER, "nk.layout_space_begin: arg 3 should be a number"); + const char *type = lua_tostring(L, 1); + float height = lua_tonumber(L, 2); + int widget_count = lua_tointeger(L, 3); + enum nk_layout_format format; + if (!strcmp(type, "dynamic")) { + format = NK_LAYOUT_DYNAMIC; + } else if (!strcmp(type, "static")) { + format = NK_LAYOUT_STATIC; + } else { + nk_love_error("nk.layout_space_begin: arg 1 should be 'dynamic' or 'static'"); + } + nk_layout_space_begin(&context, format, height, widget_count); + return 0; +} + +static int nk_love_layout_space_push(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 4, "nk.layout_space_push: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TNUMBER, "nk.layout_space_push: arg 1 should be a number"); + nk_love_assert(lua_type(L, 2) == LUA_TNUMBER, "nk.layout_space_push: arg 2 should be a number"); + nk_love_assert(lua_type(L, 3) == LUA_TNUMBER, "nk.layout_space_push: arg 3 should be a number"); + nk_love_assert(lua_type(L, 4) == LUA_TNUMBER, "nk.layout_space_push: arg 4 should be a number"); + float x = lua_tonumber(L, 1); + float y = lua_tonumber(L, 2); + float width = lua_tonumber(L, 3); + float height = lua_tonumber(L, 4); + nk_layout_space_push(&context, nk_rect(x, y, width, height)); + return 0; +} + +static int nk_love_layout_space_end(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.layout_space_end: wrong number of arguments"); + nk_layout_space_end(&context); + return 0; +} + +static int nk_love_layout_space_bounds(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.layout_space_bounds: wrong number of arguments"); + struct nk_rect bounds = nk_layout_space_bounds( &context); + lua_pushnumber(L, bounds.x); + lua_pushnumber(L, bounds.y); + lua_pushnumber(L, bounds.w); + lua_pushnumber(L, bounds.h); + return 4; +} + +static int nk_love_layout_space_to_screen(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 2, "nk.layout_space_to_screen: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TNUMBER, "nk.layout_space_to_screen: arg 1 should be a number"); + nk_love_assert(lua_type(L, 2) == LUA_TNUMBER, "nk.layout_space_to_screen: arg 2 should be a number"); + struct nk_vec2 local; + local.x = lua_tonumber(L, 1); + local.y = lua_tonumber(L, 2); + struct nk_vec2 screen = nk_layout_space_to_screen(&context, local); + lua_pushnumber(L, screen.x); + lua_pushnumber(L, screen.y); + return 2; +} + +static int nk_love_layout_space_to_local(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 2, "nk.layout_space_to_local: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TNUMBER, "nk.layout_space_to_local: arg 1 should be a number"); + nk_love_assert(lua_type(L, 2) == LUA_TNUMBER, "nk.layout_space_to_local: arg 2 should be a number"); + struct nk_vec2 screen; + screen.x = lua_tonumber(L, 1); + screen.y = lua_tonumber(L, 2); + struct nk_vec2 local = nk_layout_space_to_local(&context, screen); + lua_pushnumber(L, local.x); + lua_pushnumber(L, local.y); + return 2; +} + +static int nk_love_layout_space_rect_to_screen(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 4, "nk.layout_space_rect_to_screen: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TNUMBER, "nk.layout_space_rect_to_screen: arg 1 should be a number"); + nk_love_assert(lua_type(L, 2) == LUA_TNUMBER, "nk.layout_space_rect_to_screen: arg 2 should be a number"); + nk_love_assert(lua_type(L, 3) == LUA_TNUMBER, "nk.layout_space_rect_to_screen: arg 3 should be a number"); + nk_love_assert(lua_type(L, 4) == LUA_TNUMBER, "nk.layout_space_rect_to_screen: arg 4 should be a number"); + struct nk_rect local; + local.x = lua_tonumber(L, 1); + local.y = lua_tonumber(L, 2); + local.w = lua_tonumber(L, 3); + local.h = lua_tonumber(L, 4); + struct nk_rect screen = nk_layout_space_rect_to_screen(&context, local); + lua_pushnumber(L, screen.x); + lua_pushnumber(L, screen.y); + lua_pushnumber(L, screen.w); + lua_pushnumber(L, screen.h); + return 4; +} + +static int nk_love_layout_space_rect_to_local(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 4, "nk.layout_space_rect_to_local: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TNUMBER, "nk.layout_space_rect_to_local: arg 1 should be a number"); + nk_love_assert(lua_type(L, 2) == LUA_TNUMBER, "nk.layout_space_rect_to_local: arg 2 should be a number"); + nk_love_assert(lua_type(L, 3) == LUA_TNUMBER, "nk.layout_space_rect_to_local: arg 3 should be a number"); + nk_love_assert(lua_type(L, 4) == LUA_TNUMBER, "nk.layout_space_rect_to_local: arg 4 should be a number"); + struct nk_rect screen; + screen.x = lua_tonumber(L, 1); + screen.y = lua_tonumber(L, 2); + screen.w = lua_tonumber(L, 3); + screen.h = lua_tonumber(L, 4); + struct nk_rect local = nk_layout_space_rect_to_screen(&context, screen); + lua_pushnumber(L, local.x); + lua_pushnumber(L, local.y); + lua_pushnumber(L, local.w); + lua_pushnumber(L, local.h); + return 4; +} + +static int nk_love_layout_ratio_from_pixel(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.layout_ratio_from_pixel: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TNUMBER, "nk.layout_ratio_from_pixel: arg 1 should be a number"); + float pixel_width = lua_tonumber(L, 1); + float ratio = nk_layout_ratio_from_pixel(&context, pixel_width); + lua_pushnumber(L, ratio); + return 1; +} + +static int nk_love_group_begin(lua_State *L) +{ + nk_love_assert(lua_gettop(L) >= 1, "nk.group_begin: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.group_begin: arg 1 should be a string"); + const char *title = lua_tostring(L, 1); + nk_flags flags = nk_love_parse_window_flags(2); + int open = nk_group_begin(&context, title, flags); + lua_pushboolean(L, open); + return 1; +} + +static int nk_love_group_end(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.group_end: wrong number of arguments"); + nk_group_end(&context); + return 0; +} + +static int nk_love_tree_push(lua_State *L) +{ + int argc = lua_gettop(L); + nk_love_assert(argc >= 2 && argc <= 4, "nk.tree_push: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.tree_push: arg 1 should be a string"); + const char *type_string = lua_tostring(L, 1); + enum nk_tree_type type; + if (!strcmp(type_string, "node")) { + type = NK_TREE_NODE; + } else if (!strcmp(type_string, "tab")) { + type = NK_TREE_TAB; + } else { + nk_love_error("nk.tree_push: arg 1 should be 'node' or 'tab'"); + } + nk_love_assert(lua_type(L, 2) == LUA_TSTRING, "nk.tree_push: arg 2 should be a string"); + const char *title = lua_tostring(L, 2); + struct nk_image image; + int use_image = 0; + if (argc >= 3 && lua_type(L, 3) != LUA_TNIL) { + nk_love_assert_type(3, "Image", "nk.tree_push: arg 3 should be an image"); + lua_pushvalue(L, 3); + nk_love_toimage(&image); + use_image = 1; + } + const char *state_string = "collapsed"; + if (argc >= 4) { + nk_love_assert(lua_type(L, 4) == LUA_TSTRING, "nk.tree_push: arg 4 should be a string"); + state_string = lua_tostring(L, 4); + } + enum nk_collapse_states state; + if (!strcmp(state_string, "collapsed")) { + state = NK_MINIMIZED; + } else if (!strcmp(state_string, "expanded")) { + state = NK_MAXIMIZED; + } else { + nk_love_error("nk.tree_push: arg 4 should be 'collapsed' or 'expanded'"); + } + lua_Debug ar; + lua_getstack(L, 1, &ar); + lua_getinfo(L, "l", &ar); + int id = ar.currentline; + int open = 0; + if (use_image) { + open = nk_tree_image_push_hashed(&context, type, image, title, state, title, strlen(title), id); + } else { + open = nk_tree_push_hashed(&context, type, title, state, title, strlen(title), id); + } + lua_pushboolean(L, open); + return 1; +} + +static int nk_love_tree_pop(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.tree_pop: wrong number of arguments"); + nk_tree_pop(&context); + return 0; +} + +static void nk_love_color(int r, int g, int b, int a, char *color_string) +{ + r = NK_CLAMP(0, r, 255); + g = NK_CLAMP(0, g, 255); + b = NK_CLAMP(0, b, 255); + a = NK_CLAMP(0, a, 255); + const char *format_string; + if (a < 255) { + format_string = "#%02x%02x%02x%02x"; + } else { + format_string = "#%02x%02x%02x"; + } + sprintf(color_string, format_string, r, g, b, a); +} + +static int nk_love_color_rgba(lua_State *L) +{ + int argc = lua_gettop(L); + nk_love_assert(argc == 3 || argc == 4, "nk.color_rgba: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TNUMBER, "nk.color_rgba: arg 1 should be a number"); + nk_love_assert(lua_type(L, 2) == LUA_TNUMBER, "nk.color_rgba: arg 2 should be a number"); + nk_love_assert(lua_type(L, 3) == LUA_TNUMBER, "nk.color_rgba: arg 3 should be a number"); + + int r = lua_tointeger(L, 1); + int g = lua_tointeger(L, 2); + int b = lua_tointeger(L, 3); + int a = 255; + if (argc == 4) { + nk_love_assert(lua_type(L, 4) == LUA_TNUMBER, "nk.color_rgba: arg 4 should be a number"); + a = lua_tointeger(L, 4); + } + + char color_string[10]; + nk_love_color(r, g, b, a, color_string); + lua_pushstring(L, color_string); + return 1; +} + +static int nk_love_color_hsva(lua_State *L) +{ + int argc = lua_gettop(L); + nk_love_assert(argc == 3 || argc == 4, "nk.color_hsva: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TNUMBER, "nk.color_hsva: arg 1 should be a number"); + nk_love_assert(lua_type(L, 2) == LUA_TNUMBER, "nk.color_hsva: arg 2 should be a number"); + nk_love_assert(lua_type(L, 3) == LUA_TNUMBER, "nk.color_hsva: arg 3 should be a number"); + + int h = NK_CLAMP(0, lua_tointeger(L, 1), 255); + int s = NK_CLAMP(0, lua_tointeger(L, 2), 255); + int v = NK_CLAMP(0, lua_tointeger(L, 3), 255); + int a = 255; + if (argc == 4) { + nk_love_assert(lua_type(L, 4) == LUA_TNUMBER, "nk.color_hsva: arg 4 should be a number"); + a = NK_CLAMP(0, lua_tointeger(L, 4), 255); + } + + struct nk_color rgba = nk_hsva(h, s, v, a); + char color_string[10]; + nk_love_color(rgba.r, rgba.g, rgba.b, rgba.a, color_string); + lua_pushstring(L, color_string); + return 1; +} + +static struct nk_color nk_love_color_parse(const char *color_string) +{ + int r, g, b, a = 255; + sscanf(color_string, "#%02x%02x%02x", &r, &g, &b); + if (strlen(color_string) == 9) { + sscanf(color_string + 7, "%02x", &a); + } + struct nk_color color = {r, g, b, a}; + return color; +} + + +static int nk_love_color_parse_rgba(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.color_parse_rgba: wrong number of arguments"); + nk_love_assert_color(1, "nk.color_parse_rgba: arg 1 should be a color string"); + const char *color_string = lua_tostring(L, 1); + struct nk_color rgba = nk_love_color_parse(color_string); + lua_pushnumber(L, rgba.r); + lua_pushnumber(L, rgba.g); + lua_pushnumber(L, rgba.b); + lua_pushnumber(L, rgba.a); + return 4; +} + +static int nk_love_color_parse_hsva(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.color_parse_hsva: wrong number of arguments"); + nk_love_assert_color(1, "nk.color_parse_hsva: arg 1 should be a color string"); + const char *color_string = lua_tostring(L, 1); + struct nk_color rgba = nk_love_color_parse(color_string); + int h, s, v, a2; + nk_color_hsva_i(&h, &s, &v, &a2, rgba); + lua_pushnumber(L, h); + lua_pushnumber(L, s); + lua_pushnumber(L, v); + lua_pushnumber(L, a2); + return 4; +} + +static int nk_love_label(lua_State *L) +{ + int argc = lua_gettop(L); + nk_love_assert(argc >= 1 && argc <= 3, "nk.label: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING || lua_type(L, 1) == LUA_TNUMBER, "nk.label: arg 1 should be a string"); + const char *text = lua_tostring(L, 1); + const char *align_string = "left"; + const char *color_string = NULL; + if (argc >= 2) { + nk_love_assert(lua_type(L, 2) == LUA_TSTRING, "nk.label: arg 2 should be a string"); + align_string = lua_tostring(L, 2); + if (argc >= 3) { + nk_love_assert_color(3, "nk.label: arg 3 should be a color string"); + color_string = lua_tostring(L, 3); + } + } + nk_flags align; + int wrap = 0; + if (!strcmp(align_string, "wrap")) { + wrap = 1; + } else if (!nk_love_parse_align(align_string, &align)) { + nk_love_error("nk.label: arg 2 should be an alignment or 'wrap'"); + } + + struct nk_color color; + if (color_string != NULL) { + color = nk_love_color_parse(color_string); + if (wrap) { + nk_label_colored_wrap(&context, text, color); + } else { + nk_label_colored(&context, text, align, color); + } + } else { + if (wrap) { + nk_label_wrap(&context, text); + } else { + nk_label(&context, text, align); + } + } + return 0; +} + +static int nk_love_image(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.image: wrong number of arguments"); + nk_love_assert_type(1, "Image", "nk.image: arg 1 should be an image"); + struct nk_image image; + nk_love_toimage(&image); + nk_image(&context, image); + return 0; +} + +static int nk_love_button(lua_State *L) +{ + int argc = lua_gettop(L); + nk_love_assert(argc == 1 || argc == 2, "nk.button: wrong number of arguments"); + const char *title = NULL; + if (lua_type(L, 1) != LUA_TNIL) { + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.button: arg 1 should be a string"); + title = lua_tostring(L, 1); + } + int use_color = 0, use_image = 0; + struct nk_color color; + enum nk_symbol_type symbol = NK_SYMBOL_NONE; + struct nk_image image; + if (argc >= 2 && lua_type(L, 2) != LUA_TNIL) { + if (lua_type(L, 2) == LUA_TSTRING) { + const char *s = lua_tostring(L, 2); + if (!nk_love_parse_symbol(s, &symbol)) { + nk_love_assert_color(2, "nk.button: arg 2 should be a color string, symbol type, or image"); + color = nk_love_color_parse(s); + use_color = 1; + } + } else { + nk_love_assert_type(2, "Image", "nk.button: arg 2 should be a color string, symbol type, or image"); + lua_pushvalue(L, 2); + nk_love_toimage(&image); + use_image = 1; + } + } + nk_flags align = context.style.button.text_alignment; + int activated = 0; + if (title != NULL) { + if (use_color) { + nk_love_error("nk.button: color buttons can't have titles"); + } else if (symbol != NK_SYMBOL_NONE) { + activated = nk_button_symbol_label(&context, symbol, title, align); + } else if (use_image) { + activated = nk_button_image_label(&context, image, title, align); + } else { + activated = nk_button_label(&context, title); + } + } else { + if (use_color) { + activated = nk_button_color(&context, color); + } else if (symbol != NK_SYMBOL_NONE) { + activated = nk_button_symbol(&context, symbol); + } else if (use_image) { + activated = nk_button_image(&context, image); + } else { + nk_love_error("nk.button: must specify a title, color, symbol, and/or image"); + } + } + lua_pushboolean(L, activated); + return 1; +} + +static int nk_love_button_set_behavior(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.button_set_behavior: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.button_set_behavior: arg 1 should be 'default' or 'repeater'"); + const char *behavior_string = lua_tostring(L, 1); + enum nk_button_behavior behavior; + if (!strcmp(behavior_string, "default")) { + behavior = NK_BUTTON_DEFAULT; + } else if (!strcmp(behavior_string, "repeater")) { + behavior = NK_BUTTON_REPEATER; + } else { + nk_love_error("nk.button_set_behavior: arg 1 should be 'default' or 'repeater'"); + } + nk_button_set_behavior(&context, behavior); + return 0; +} + +static int nk_love_button_push_behavior(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.button_push_behavior: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.button_push_behavior: arg 1 should be 'default' or 'repeater'"); + const char *behavior_string = lua_tostring(L, 1); + enum nk_button_behavior behavior; + if (!strcmp(behavior_string, "default")) { + behavior = NK_BUTTON_DEFAULT; + } else if (!strcmp(behavior_string, "repeater")) { + behavior = NK_BUTTON_REPEATER; + } else { + nk_love_error("nk.button_push_behavior: arg 1 should be 'default' or 'repeater'"); + } + nk_button_push_behavior(&context, behavior); + return 0; +} + +static int nk_love_button_pop_behavior(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.button_pop_behavior: wrong number of arguments"); + nk_button_pop_behavior(&context); + return 0; +} + +static int nk_love_checkbox(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 2, "nk.checkbox: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.checkbox: arg 1 should be a string"); + const char *text = lua_tostring(L, 1); + if (lua_type(L, 2) == LUA_TBOOLEAN) { + int value = lua_toboolean(L, 2); + value = nk_check_label(&context, text, value); + lua_pushboolean(L, value); + } else if (lua_type(L, 2) == LUA_TTABLE) { + lua_getfield(L, 2, "value"); + int value = lua_toboolean(L, -1); + int changed = nk_checkbox_label(&context, text, &value); + if (changed) { + lua_pushboolean(L, value); + lua_setfield(L, 2, "value"); + } + lua_pushboolean(L, changed); + } else { + nk_love_error("nk.checkbox: arg 2 should be a boolean or table"); + } + return 1; +} + +static int nk_love_radio(lua_State *L) +{ + int argc = lua_gettop(L); + nk_love_assert(argc == 2 || argc == 3, "nk.radio: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.radio: arg 1 should be a string"); + const char *name = lua_tostring(L, 1); + const char *text; + if (argc == 3) { + nk_love_assert(lua_type(L, 2) == LUA_TSTRING, "nk.radio: arg 2 should be a string"); + text = lua_tostring(L, 2); + } else { + text = lua_tostring(L, 1); + } + if (lua_type(L, -1) == LUA_TSTRING) { + const char *value = lua_tostring(L, -1); + int active = !strcmp(value, name); + active = nk_option_label(&context, text, active); + if (active) { + lua_pushstring(L, name); + } else { + lua_pushstring(L, value); + } + } else if (lua_type(L, -1) == LUA_TTABLE) { + lua_getfield(L, -1, "value"); + const char *value = lua_tostring(L, -1); + int active = !strcmp(value, name); + int changed = nk_radio_label(&context, text, &active); + if (changed && active) { + lua_pushstring(L, name); + lua_setfield(L, -3, "value"); + } + lua_pushboolean(L, changed); + } else { + if (argc == 2) { + nk_love_error("nk.radio: arg 2 should be a boolean or table"); + } else { + nk_love_error("nk.radio: arg 3 should be a boolean or table"); + } + } + return 1; +} + +static int nk_love_selectable(lua_State *L) +{ + int argc = lua_gettop(L); + nk_love_assert(argc >= 2 && argc <= 4, "nk.selectable: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.selectable: arg 1 should be a string"); + const char *text = lua_tostring(L, 1); + struct nk_image image; + int use_image = 0; + if (argc >= 3 && lua_type(L, 2) != LUA_TNIL) { + nk_love_assert_type(2, "Image", "nk.selectable: arg 2 should be an image"); + lua_pushvalue(L, 2); + nk_love_toimage(&image); + use_image = 1; + } + nk_flags align = NK_TEXT_LEFT; + if (argc >= 4) { + nk_love_assert(lua_type(L, 3) == LUA_TSTRING, "nk.selectable: arg 3 should be a string"); + const char *align_text = lua_tostring(L, 3); + if (!nk_love_parse_align(align_text, &align)) { + nk_love_error("nk.selectable: arg 3 should be an alignment"); + } + } + if (lua_type(L, -1) == LUA_TBOOLEAN) { + int value = lua_toboolean(L, -1); + if (use_image) { + value = nk_select_image_label(&context, image, text, align, value); + } else { + value = nk_select_label(&context, text, align, value); + } + lua_pushboolean(L, value); + } else if (lua_type(L, -1) == LUA_TTABLE) { + lua_getfield(L, -1, "value"); + int value = lua_toboolean(L, -1); + int changed; + if (use_image) { + changed = nk_selectable_image_label(&context, image, text, align, &value); + } else { + changed = nk_selectable_label(&context, text, align, &value); + } + if (changed) { + lua_pushboolean(L, value); + lua_setfield(L, -3, "value"); + } + lua_pushboolean(L, changed); + } else { + if (argc == 2) { + nk_love_error("nk.selectable: arg 2 should be a boolean or table"); + } else if (argc == 3) { + nk_love_error("nk.selectable: arg 3 should be a boolean or table"); + } else { + nk_love_error("nk.selectable: arg 4 should be a boolean or table"); + } + } + return 1; +} + +static int nk_love_slider(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 4, "nk.slider: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TNUMBER, "nk.slider: arg 1 should be a number"); + nk_love_assert(lua_type(L, 3) == LUA_TNUMBER, "nk.slider: arg 3 should be a number"); + nk_love_assert(lua_type(L, 4) == LUA_TNUMBER, "nk.slider: arg 4 should be a number"); + float min = lua_tonumber(L, 1); + float max = lua_tonumber(L, 3); + float step = lua_tonumber(L, 4); + if (lua_type(L, 2) == LUA_TNUMBER) { + float value = lua_tonumber(L, 2); + value = nk_slide_float(&context, min, value, max, step); + lua_pushnumber(L, value); + } else if (lua_type(L, 2) == LUA_TTABLE) { + lua_getfield(L, 2, "value"); + float value = lua_tonumber(L, -1); + int changed = nk_slider_float(&context, min, &value, max, step); + if (changed) { + lua_pushnumber(L, value); + lua_setfield(L, 2, "value"); + } + lua_pushboolean(L, changed); + } else { + nk_love_error("nk.slider: arg 2 should be a number or table"); + } + return 1; +} + +static int nk_love_progress(lua_State *L) +{ + int argc = lua_gettop(L); + nk_love_assert(argc == 2 || argc == 3, "nk.progress: wrong number of arguments"); + nk_love_assert(lua_type(L, 2) == LUA_TNUMBER, "nk.progress: arg 2 should be a number"); + nk_size max = lua_tonumber(L, 2); + int modifiable = 0; + if (argc == 3) { + nk_love_assert(lua_type(L, 3) == LUA_TBOOLEAN || lua_type(L, 3) == LUA_TNIL, "nk.progress: arg 3 should be a boolean"); + modifiable = lua_toboolean(L, 3); + } + if (lua_type(L, 1) == LUA_TNUMBER) { + nk_size value = lua_tonumber(L, 1); + value = nk_prog(&context, value, max, modifiable); + lua_pushnumber(L, value); + } else if (lua_type(L, 1) == LUA_TTABLE) { + lua_getfield(L, 1, "value"); + nk_size value = lua_tonumber(L, -1); + int changed = nk_progress(&context, &value, max, modifiable); + if (changed) { + lua_pushnumber(L, value); + lua_setfield(L, 1, "value"); + } + lua_pushboolean(L, changed); + } else { + nk_love_error("nk.progress: arg 2 should be a number or table"); + } + return 1; +} + +static int nk_love_color_picker(lua_State *L) +{ + int argc = lua_gettop(L); + nk_love_assert(argc == 1 || argc == 2, "nk.color_picker: wrong number of arguments"); + const char *format_string = "RGB"; + if (argc == 2) { + nk_love_assert(lua_type(L, 2) == LUA_TSTRING, "nk.color_picker: arg 2 should be a string"); + format_string = lua_tostring(L, 2); + } + enum nk_color_format format; + if (!strcmp(format_string, "RGB")) { + format = NK_RGB; + } else if (!strcmp(format_string, "RGBA")) { + format = NK_RGBA; + } else { + nk_love_error("nk.color_picker: arg 2 should be 'RGB' or 'RGBA'"); + } + if (lua_type(L, 1) == LUA_TSTRING) { + nk_love_assert_color(1, "nk.color_picker: arg 1 should be a color string"); + const char *color_string = lua_tostring(L, 1); + struct nk_color color = nk_love_color_parse(color_string); + color = nk_color_picker(&context, color, format); + char new_color_string[10]; + nk_love_color(color.r, color.g, color.b, color.a, new_color_string); + lua_pushstring(L, new_color_string); + } else if (lua_type(L, 1) == LUA_TTABLE) { + lua_getfield(L, 1, "value"); + nk_love_assert_color(-1, "nk.color_picker: arg 1 should have a color string value"); + const char *color_string = lua_tostring(L, -1); + struct nk_color color = nk_love_color_parse(color_string); + int changed = nk_color_pick(&context, &color, format); + if (changed) { + char new_color_string[10]; + nk_love_color(color.r, color.g, color.b, color.a, new_color_string); + lua_pushstring(L, new_color_string); + lua_setfield(L, 1, "value"); + } + lua_pushboolean(L, changed); + } + return 1; +} + +static int nk_love_property(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 6, "nk.property: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.property: arg 1 should be a string"); + nk_love_assert(lua_type(L, 2) == LUA_TNUMBER, "nk.property: arg 2 should be a number"); + nk_love_assert(lua_type(L, 4) == LUA_TNUMBER, "nk.property: arg 4 should be a number"); + nk_love_assert(lua_type(L, 5) == LUA_TNUMBER, "nk.property: arg 5 should be a number"); + nk_love_assert(lua_type(L, 6) == LUA_TNUMBER, "nk.property: arg 6 should be a number"); + const char *name = lua_tostring(L, 1); + double min = lua_tonumber(L, 2); + double max = lua_tonumber(L, 4); + double step = lua_tonumber(L, 5); + float inc_per_pixel = lua_tonumber(L, 6); + if (lua_type(L, 3) == LUA_TNUMBER) { + double value = lua_tonumber(L, 3); + value = nk_propertyd(&context, name, min, value, max, step, inc_per_pixel); + lua_pushnumber(L, value); + } else if (lua_type(L, 3) == LUA_TTABLE) { + lua_getfield(L, 3, "value"); + nk_love_assert(lua_type(L, -1) == LUA_TNUMBER, "nk.property: arg 3 should have a number value"); + double value = lua_tonumber(L, -1); + double old = value; + nk_property_double(&context, name, min, &value, max, step, inc_per_pixel); + int changed = value != old; + if (changed) { + lua_pushnumber(L, value); + lua_setfield(L, 3, "value"); + } + lua_pushboolean(L, changed); + } else { + nk_love_error("nk.property: arg 3 should be a number or table"); + } + return 1; +} + +static int nk_love_edit(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 2, "nk.edit: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.edit: arg 1 should be a string"); + const char *type_string = lua_tostring(L, 1); + nk_flags flags; + if (!strcmp(type_string, "simple")) { + flags = NK_EDIT_SIMPLE; + } else if (!strcmp(type_string, "field")) { + flags = NK_EDIT_FIELD; + } else if (!strcmp(type_string, "box")) { + flags = NK_EDIT_BOX; + } else { + nk_love_error("nk.edit: arg 1 must be an editor type"); + } + nk_love_assert(lua_type(L, 2) == LUA_TTABLE, "nk.edit: arg 2 should be a table"); + lua_getfield(L, 2, "value"); + nk_love_assert(lua_type(L, -1) == LUA_TSTRING, "nk.edit: arg 2 should have a string value"); + const char *value = lua_tostring(L, -1); + size_t len = NK_CLAMP(0, strlen(value), NK_LOVE_EDIT_BUFFER_LEN - 1); + memcpy(edit_buffer, value, len); + edit_buffer[len] = '\0'; + nk_flags event = nk_edit_string_zero_terminated(&context, flags, edit_buffer, NK_LOVE_EDIT_BUFFER_LEN - 1, nk_filter_default); + lua_pushstring(L, edit_buffer); + lua_pushvalue(L, -1); + lua_setfield(L, 2, "value"); + int changed = !lua_equal(L, -1, -2); + if (event & NK_EDIT_COMMITED) { + lua_pushstring(L, "commited"); + } else if (event & NK_EDIT_ACTIVATED) { + lua_pushstring(L, "activated"); + } else if (event & NK_EDIT_DEACTIVATED) { + lua_pushstring(L, "deactivated"); + } else if (event & NK_EDIT_ACTIVE) { + lua_pushstring(L, "active"); + } else if (event & NK_EDIT_INACTIVE) { + lua_pushstring(L, "inactive"); + } else { + lua_pushnil(L); + } + lua_pushboolean(L, changed); + return 2; +} + +static int nk_love_popup_begin(lua_State *L) +{ + nk_love_assert(lua_gettop(L) >= 6, "nk.popup_begin: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.popup_begin: arg 1 should be a string"); + nk_love_assert(lua_type(L, 2) == LUA_TSTRING, "nk.popup_begin: arg 2 should be a string"); + nk_love_assert(lua_type(L, 3) == LUA_TNUMBER, "nk.popup_begin: arg 3 should be a number"); + nk_love_assert(lua_type(L, 4) == LUA_TNUMBER, "nk.popup_begin: arg 4 should be a number"); + nk_love_assert(lua_type(L, 5) == LUA_TNUMBER, "nk.popup_begin: arg 5 should be a number"); + nk_love_assert(lua_type(L, 6) == LUA_TNUMBER, "nk.popup_begin: arg 6 should be a number"); + const char *type_string = lua_tostring(L, 1); + enum nk_popup_type type; + if (!strcmp(type_string, "dynamic")) { + type = NK_POPUP_DYNAMIC; + } else if (!strcmp(type_string, "static")) { + type = NK_POPUP_STATIC; + } else { + nk_love_error("nk.popup_begin: arg 1 should be 'dynamic' or 'static'"); + } + const char *title = lua_tostring(L, 2); + struct nk_rect bounds; + bounds.x = lua_tonumber(L, 3); + bounds.y = lua_tonumber(L, 4); + bounds.w = lua_tonumber(L, 5); + bounds.h = lua_tonumber(L, 6); + nk_flags flags = nk_love_parse_window_flags(7); + int open = nk_popup_begin(&context, type, title, flags, bounds); + lua_pushboolean(L, open); + return 1; +} + +static int nk_love_popup_close(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.popup_close: wrong number of arguments"); + nk_popup_close(&context); + return 0; +} + +static int nk_love_popup_end(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.popup_end: wrong number of arguments"); + nk_popup_end(&context); + return 0; +} + +static int nk_love_combobox(lua_State *L) +{ + int argc = lua_gettop(L); + nk_love_assert(argc >= 2 && argc <= 5, "nk.combobox: wrong number of arguments"); + nk_love_assert(lua_type(L, 2) == LUA_TTABLE, "nk.combobox: arg 2 should be a table"); + int i; + for (i = 0; i < NK_LOVE_COMBOBOX_MAX_ITEMS && lua_checkstack(L, 4); ++i) { + lua_rawgeti(L, 2, i + 1); + if (lua_type(L, -1) == LUA_TSTRING) { + combobox_items[i] = lua_tostring(L, -1); + } else if (lua_type(L, -1) == LUA_TNIL) { + break; + } else { + nk_love_error("nk.combobox: items must be strings"); + } + } + struct nk_rect bounds = nk_widget_bounds(&context); + int item_height = bounds.h; + if (argc >= 3 && lua_type(L, 3) != LUA_TNIL) { + nk_love_assert(lua_type(L, 3) == LUA_TNUMBER, "nk.combobox: arg 3 should be a number"); + item_height = lua_tointeger(L, 3); + } + struct nk_vec2 size = nk_vec2(bounds.w, item_height * 8); + if (argc >= 4 && lua_type(L, 4) != LUA_TNIL) { + nk_love_assert(lua_type(L, 4) == LUA_TNUMBER, "nk.combobox: arg 4 should be a number"); + size.x = lua_tonumber(L, 4); + } + if (argc >= 5 && lua_type(L, 5) != LUA_TNIL) { + nk_love_assert(lua_type(L, 5) == LUA_TNUMBER, "nk.combobox: arg 5 should be a number"); + size.y = lua_tonumber(L, 5); + } + if (lua_type(L, 1) == LUA_TNUMBER) { + int value = lua_tointeger(L, 1) - 1; + value = nk_combo(&context, combobox_items, i, value, item_height, size); + lua_pushnumber(L, value + 1); + } else if (lua_type(L, 1) == LUA_TTABLE) { + lua_getfield(L, 1, "value"); + nk_love_assert(lua_type(L, -1) == LUA_TNUMBER, "nk.combobox: arg 1 should have a number value"); + int value = lua_tointeger(L, -1) - 1; + int old = value; + nk_combobox(&context, combobox_items, i, &value, item_height, size); + int changed = value != old; + if (changed) { + lua_pushnumber(L, value + 1); + lua_setfield(L, 1, "value"); + } + lua_pushboolean(L, changed); + } else { + nk_love_error("nk.combobox: arg 1 should be a number or table"); + } + return 1; +} + +static int nk_love_combobox_begin(lua_State *L) +{ + int argc = lua_gettop(L); + nk_love_assert(argc >= 1 && argc <= 4, "nk.combobox_begin: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING || lua_type(L, 1) == LUA_TNUMBER || lua_type(L, 1) == LUA_TNIL, "nk.combobox_begin: arg 1 should be a string"); + const char *text = lua_tostring(L, 1); + struct nk_color color; + int use_color = 0; + enum nk_symbol_type symbol = NK_SYMBOL_NONE; + struct nk_image image; + int use_image = 0; + if (argc >= 2 && lua_type(L, 2) != LUA_TNIL) { + if (lua_type(L, 2) == LUA_TSTRING) { + const char *s = lua_tostring(L, 2); + if (!nk_love_parse_symbol(s, &symbol)) { + nk_love_assert_color(2, "nk.combobox_begin: arg 1 should be a color string, symbol type, or image"); + color = nk_love_color_parse(s); + use_color = 1; + } + } else { + nk_love_assert_type(2, "Image", "nk.combobox_begin: arg 1 should be a color string, symbol type, or image"); + lua_pushvalue(L, 2); + nk_love_toimage(&image); + use_image = 1; + } + } + struct nk_rect bounds = nk_widget_bounds(&context); + struct nk_vec2 size = nk_vec2(bounds.w, bounds.h * 8); + if (argc >= 3 && lua_type(L, 3) != LUA_TNIL) { + nk_love_assert(lua_type(L, 3) == LUA_TNUMBER, "nk.combobox_begin: arg 3 should be a number"); + size.x = lua_tonumber(L, 3); + } + if (argc >= 4 && lua_type(L, 4) != LUA_TNIL) { + nk_love_assert(lua_type(L, 4) == LUA_TNUMBER, "nk.combobox_begin: arg 4 should be a number"); + size.y = lua_tonumber(L, 4); + } + int open = 0; + if (text != NULL) { + if (use_color) { + nk_love_error("nk.combobox_begin: color comboboxes can't have titles"); + } else if (symbol != NK_SYMBOL_NONE) { + open = nk_combo_begin_symbol_label(&context, text, symbol, size); + } else if (use_image) { + open = nk_combo_begin_image_label(&context, text, image, size); + } else { + open = nk_combo_begin_label(&context, text, size); + } + } else { + if (use_color) { + open = nk_combo_begin_color(&context, color, size); + } else if (symbol != NK_SYMBOL_NONE) { + open = nk_combo_begin_symbol(&context, symbol, size); + } else if (use_image) { + open = nk_combo_begin_image(&context, image, size); + } else { + nk_love_error("nk.combobox_begin: must specify color, symbol, image, and/or title"); + } + } + lua_pushboolean(L, open); + return 1; +} + +static int nk_love_combobox_item(lua_State *L) +{ + int argc = lua_gettop(L); + nk_love_assert(argc >= 1 && argc <= 3, "nk.combobox_item: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING || lua_type(L, 1) == LUA_TNUMBER, "nk.combobox_item: arg 1 should be a string"); + const char *text = lua_tostring(L, 1); + enum nk_symbol_type symbol = NK_SYMBOL_NONE; + struct nk_image image; + int use_image = 0; + if (argc >= 2 && lua_type(L, 2) != LUA_TNIL) { + if (lua_type(L, 2) == LUA_TSTRING) { + const char *s = lua_tostring(L, 2); + nk_love_assert(nk_love_parse_symbol(s, &symbol), "nk.combobox_item: arg 2 should be a symbol type or image"); + } else { + nk_love_assert_type(2, "Image", "nk.combobox_item: arg 1 should be a symbol type or image"); + lua_pushvalue(L, 2); + nk_love_toimage(&image); + use_image = 1; + } + } + nk_flags align = NK_TEXT_LEFT; + if (argc >= 3 && lua_type(L, 3) != LUA_TNIL) { + nk_love_assert(lua_type(L, 3) == LUA_TSTRING, "nk.combobox_item: arg 3 should be a string"); + const char *align_string = lua_tostring(L, 3); + if (!nk_love_parse_align(align_string, &align)) { + nk_love_error("nk.combobox_item: arg 3 should be an alignment"); + } + } + int activated = 0; + if (symbol != NK_SYMBOL_NONE) { + activated = nk_combo_item_symbol_label(&context, symbol, text, align); + } else if (use_image) { + activated = nk_combo_item_image_label(&context, image, text, align); + } else { + activated = nk_combo_item_label(&context, text, align); + } + lua_pushboolean(L, activated); + return 1; +} + +static int nk_love_combobox_close(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.combobox_close: wrong number of arguments"); + nk_combo_close(&context); + return 0; +} + +static int nk_love_combobox_end(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.combobox_end: wrong number of arguments"); + nk_combo_end(&context); + return 0; +} + +static int nk_love_contextual_begin(lua_State *L) +{ + nk_love_assert(lua_gettop(L) >= 6, "nk.contextual_begin: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TNUMBER, "nk.contextual_begin: arg 1 should be a number"); + nk_love_assert(lua_type(L, 2) == LUA_TNUMBER, "nk.contextual_begin: arg 2 should be a number"); + nk_love_assert(lua_type(L, 3) == LUA_TNUMBER, "nk.contextual_begin: arg 3 should be a number"); + nk_love_assert(lua_type(L, 4) == LUA_TNUMBER, "nk.contextual_begin: arg 4 should be a number"); + nk_love_assert(lua_type(L, 5) == LUA_TNUMBER, "nk.contextual_begin: arg 5 should be a number"); + nk_love_assert(lua_type(L, 6) == LUA_TNUMBER, "nk.contextual_begin: arg 6 should be a number"); + struct nk_vec2 size; + size.x = lua_tonumber(L, 1); + size.y = lua_tonumber(L, 2); + struct nk_rect trigger; + trigger.x = lua_tonumber(L, 3); + trigger.y = lua_tonumber(L, 4); + trigger.w = lua_tonumber(L, 5); + trigger.h = lua_tonumber(L, 6); + nk_flags flags = nk_love_parse_window_flags(7); + int open = nk_contextual_begin(&context, flags, size, trigger); + lua_pushboolean(L, open); + return 1; +} + +static int nk_love_contextual_item(lua_State *L) +{ + int argc = lua_gettop(L); + nk_love_assert(argc >= 1 && argc <= 3, "nk.contextual_item: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.contextual_item: arg 1 should be a string"); + const char *text = lua_tostring(L, 1); + enum nk_symbol_type symbol = NK_SYMBOL_NONE; + struct nk_image image; + int use_image = 0; + if (argc >= 2 && lua_type(L, 2) != LUA_TNIL) { + if (lua_type(L, 2) == LUA_TSTRING) { + const char *symbol_string = lua_tostring(L, 2); + if (!nk_love_parse_symbol(symbol_string, &symbol)) { + nk_love_error("nk.contextual_item: arg 1 should be a symbol type or image"); + } + } else { + nk_love_assert_type(2, "Image", "nk.contextual_item: arg 1 should be a symbol type or image"); + lua_pushvalue(L, 2); + nk_love_toimage(&image); + use_image = 1; + } + } + nk_flags align = NK_TEXT_LEFT; + if (argc >= 3 && lua_type(L, 3) != LUA_TNIL) { + nk_love_assert(lua_type(L, 3) == LUA_TSTRING, "nk.contextual_item: arg 3 should be a string"); + const char *align_string = lua_tostring(L, 3); + if (!nk_love_parse_align(align_string, &align)) { + nk_love_error("nk.contextual_item: arg 3 should be an alignment"); + } + } + int activated; + if (symbol != NK_SYMBOL_NONE) { + activated = nk_contextual_item_symbol_label(&context, symbol, text, align); + } else if (use_image) { + activated = nk_contextual_item_image_label(&context, image, text, align); + } else { + activated = nk_contextual_item_label(&context, text, align); + } + lua_pushboolean(L, activated); + return 1; +} + +static int nk_love_contextual_close(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.contextual_close: wrong number of arguments"); + nk_contextual_close(&context); + return 0; +} + +static int nk_love_contextual_end(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.contextual_end: wrong number of arguments"); + nk_contextual_end(&context); + return 0; +} + +static int nk_love_tooltip(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.tooltip: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.tooltip: arg 1 should be a string"); + const char *text = lua_tostring(L, 1); + nk_tooltip(&context, text); + return 0; +} + +static int nk_love_tooltip_begin(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.tooltip_begin: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TNUMBER, "nk.tooltip_begin: arg 1 should be a number"); + float width = lua_tonumber(L, 1); + int open = nk_tooltip_begin(&context, width); + lua_pushnumber(L, open); + return 1; +} + +static int nk_love_tooltip_end(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.tooltip_end: wrong number of arguments"); + nk_tooltip_end(&context); + return 0; +} + +static int nk_love_menubar_begin(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.menubar_begin: wrong number of arguments"); + nk_menubar_begin(&context); + return 0; +} + +static int nk_love_menubar_end(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.menubar_end: wrong number of arguments"); + nk_menubar_end(&context); + return 0; +} + +static int nk_love_menu_begin(lua_State *L) +{ + int argc = lua_gettop(L); + nk_love_assert(argc == 4 || argc == 5, "nk.menu_begin: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.menu_begin: arg 1 should be a string"); + const char *text = lua_tostring(L, 1); + enum nk_symbol_type symbol = NK_SYMBOL_NONE; + struct nk_image image; + int use_image = 0; + if (lua_type(L, 2) == LUA_TSTRING) { + const char *symbol_string = lua_tostring(L, 2); + if (!nk_love_parse_symbol(symbol_string, &symbol)) { + nk_love_error("nk.menu_begin: arg 2 should be a symbol type or image"); + } + } else if (lua_type(L, 2) != LUA_TNIL) { + nk_love_assert_type(2, "Image", "nk.menu_begin: arg 2 should be a symbol type or image"); + lua_pushvalue(L, 2); + nk_love_toimage(&image); + use_image = 1; + } + struct nk_vec2 size; + nk_love_assert(lua_type(L, 3) == LUA_TNUMBER, "nk.menu_begin: arg 3 should be a number"); + size.x = lua_tonumber(L, 3); + nk_love_assert(lua_type(L, 4) == LUA_TNUMBER, "nk.menu_begin: arg 4 should be a number"); + size.y = lua_tonumber(L, 4); + nk_flags align = NK_TEXT_LEFT; + if (argc == 5 && lua_type(L, 5) != LUA_TNIL) { + nk_love_assert(lua_type(L, 5) == LUA_TSTRING, "nk.menu_begin: arg 5 should be a string"); + const char *align_string = lua_tostring(L, 5); + if (!nk_love_parse_align(align_string, &align)) { + nk_love_error("nk.menu_begin: arg 5 should be an alignment"); + } + } + int open; + if (symbol != NK_SYMBOL_NONE) { + open = nk_menu_begin_symbol_label(&context, text, align, symbol, size); + } else if (use_image) { + open = nk_menu_begin_image_label(&context, text, align, image, size); + } else { + open = nk_menu_begin_label(&context, text, align, size); + } + lua_pushboolean(L, open); + return 1; +} + +static int nk_love_menu_item(lua_State *L) +{ + int argc = lua_gettop(L); + nk_love_assert(argc >= 1 && argc <= 3, "nk.menu_item: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.menu_item: arg 1 should be a string"); + const char *text = lua_tostring(L, 1); + enum nk_symbol_type symbol = NK_SYMBOL_NONE; + struct nk_image image; + int use_image = 0; + if (argc >= 2 && lua_type(L, 2) != LUA_TNIL) { + if (lua_type(L, 2) == LUA_TSTRING) { + const char *symbol_string = lua_tostring(L, 2); + if (!nk_love_parse_symbol(symbol_string, &symbol)) { + nk_love_error("nk.menu_item: arg 2 should be a symbol type or image"); + } + } else { + nk_love_assert_type(2, "Image", "nk.menu_item: arg 2 should be a symbol type or image"); + lua_pushvalue(L, 2); + nk_love_toimage(&image); + use_image = 1; + } + } + nk_flags align = NK_TEXT_LEFT; + if (argc >= 3 && lua_type(L, 3) != LUA_TNIL) { + nk_love_assert(lua_type(L, 3) == LUA_TSTRING, "nk.menu_item: arg 3 should be a string"); + const char *align_string = lua_tostring(L, 3); + if (!nk_love_parse_align(align_string, &align)) { + nk_love_error("nk.menu_item: arg 3 should be an alignment"); + } + } + int activated; + if (symbol != NK_SYMBOL_NONE) { + activated = nk_menu_item_symbol_label(&context, symbol, text, align); + } else if (use_image) { + activated = nk_menu_item_image_label(&context, image, text, align); + } else { + activated = nk_menu_item_label(&context, text, align); + } + lua_pushboolean(L, activated); + return 1; +} + +static int nk_love_menu_close(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.menu_close: wrong number of arguments"); + nk_menu_close(&context); + return 0; +} + +static int nk_love_menu_end(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.menu_end: wrong number of arguments"); + nk_menu_end(&context); + return 0; +} + +static int nk_love_style_default(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.style_default: wrong number of arguments"); + nk_style_default(&context); + return 0; +} + +#define NK_LOVE_LOAD_COLOR(type) \ + lua_getfield(L, -1, (type)); \ + nk_love_assert_color(-1, "nk.style_load_colors: table missing color value for '" type "'"); \ + colors[index++] = nk_love_color_parse(lua_tostring(L, -1)); \ + lua_pop(L, 1); + +static int nk_love_style_load_colors(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.style_load_colors: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TTABLE, "nk.style_load_colors: arg 1 should be a table"); + struct nk_color colors[NK_COLOR_COUNT]; + int index = 0; + NK_LOVE_LOAD_COLOR("text"); + NK_LOVE_LOAD_COLOR("window"); + NK_LOVE_LOAD_COLOR("header"); + NK_LOVE_LOAD_COLOR("border"); + NK_LOVE_LOAD_COLOR("button"); + NK_LOVE_LOAD_COLOR("button hover"); + NK_LOVE_LOAD_COLOR("button active"); + NK_LOVE_LOAD_COLOR("toggle"); + NK_LOVE_LOAD_COLOR("toggle hover"); + NK_LOVE_LOAD_COLOR("toggle cursor"); + NK_LOVE_LOAD_COLOR("select"); + NK_LOVE_LOAD_COLOR("select active"); + NK_LOVE_LOAD_COLOR("slider"); + NK_LOVE_LOAD_COLOR("slider cursor"); + NK_LOVE_LOAD_COLOR("slider cursor hover"); + NK_LOVE_LOAD_COLOR("slider cursor active"); + NK_LOVE_LOAD_COLOR("property"); + NK_LOVE_LOAD_COLOR("edit"); + NK_LOVE_LOAD_COLOR("edit cursor"); + NK_LOVE_LOAD_COLOR("combo"); + NK_LOVE_LOAD_COLOR("chart"); + NK_LOVE_LOAD_COLOR("chart color"); + NK_LOVE_LOAD_COLOR("chart color highlight"); + NK_LOVE_LOAD_COLOR("scrollbar"); + NK_LOVE_LOAD_COLOR("scrollbar cursor"); + NK_LOVE_LOAD_COLOR("scrollbar cursor hover"); + NK_LOVE_LOAD_COLOR("scrollbar cursor active"); + NK_LOVE_LOAD_COLOR("tab header"); + nk_style_from_table(&context, colors); + return 0; +} + +static int nk_love_style_set_font(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.style_set_font: wrong number of arguments"); + nk_love_assert_type(1, "Font", "nk.style_set_font: arg 1 should be a font"); + nk_love_tofont(&fonts[font_count]); + nk_style_set_font(&context, &fonts[font_count++]); + return 0; +} + +static int nk_love_style_push_color(struct nk_color *field) +{ + nk_love_assert_color(-1, "nk.style_push: color fields must be color strings"); + const char *color_string = lua_tostring(L, -1); + struct nk_color color = nk_love_color_parse(color_string); + int success = nk_style_push_color(&context, field, color); + if (success) { + lua_pushstring(L, "color"); + size_t stack_size = lua_objlen(L, 1); + lua_rawseti(L, 1, stack_size + 1); + } + return success; +} + +static int nk_love_style_push_vec2(struct nk_vec2 *field) +{ + nk_love_assert(lua_type(L, -1) == LUA_TTABLE, "nk.style_push: vec2 fields must have x and y components"); + lua_getfield(L, -1, "x"); + nk_love_assert(lua_type(L, -1) == LUA_TNUMBER, "nk.style_push: vec2 fields must have x and y components"); + lua_getfield(L, -2, "y"); + nk_love_assert(lua_type(L, -1) == LUA_TNUMBER, "nk.style_push: vec2 fields must have x and y components"); + struct nk_vec2 vec2; + vec2.x = lua_tonumber(L, -2); + vec2.y = lua_tonumber(L, -1); + lua_pop(L, 2); + int success = nk_style_push_vec2(&context, field, vec2); + if (success) { + lua_pushstring(L, "vec2"); + size_t stack_size = lua_objlen(L, 1); + lua_rawseti(L, 1, stack_size + 1); + } + return success; +} + +static int nk_love_style_push_item(struct nk_style_item *field) +{ + struct nk_style_item item; + if (lua_type(L, -1) == LUA_TSTRING) { + nk_love_assert_color(-1, "nk.style_push: item fields must be color strings or images"); + const char *color_string = lua_tostring(L, -1); + item.type = NK_STYLE_ITEM_COLOR; + item.data.color = nk_love_color_parse(color_string); + } else { + nk_love_assert_type(-1, "Image", "nk.style_push: item fields must be color strings or images"); + lua_pushvalue(L, -1); + item.type = NK_STYLE_ITEM_IMAGE; + nk_love_toimage(&item.data.image); + } + int success = nk_style_push_style_item(&context, field, item); + if (success) { + lua_pushstring(L, "item"); + size_t stack_size = lua_objlen(L, 1); + lua_rawseti(L, 1, stack_size + 1); + } + return success; +} + +static int nk_love_style_push_align(nk_flags *field) +{ + nk_love_assert(lua_type(L, -1) == LUA_TSTRING, "nk.style_push: alignment fields must be alignments"); + const char *align_string = lua_tostring(L, -1); + nk_flags align; + if (!nk_love_parse_align(align_string, &align)) { + nk_love_error("nk.style_push: alignment fields must be alignments"); + } + int success = nk_style_push_flags(&context, field, align); + if (success) { + lua_pushstring(L, "flags"); + size_t stack_size = lua_objlen(L, 1); + lua_rawseti(L, 1, stack_size + 1); + } + return success; +} + +static int nk_love_style_push_float(float *field) { + nk_love_assert(lua_type(L, -1) == LUA_TNUMBER, "nk.style_push: float fields must be numbers"); + float f = lua_tonumber(L, -1); + int success = nk_style_push_float(&context, field, f); + if (success) { + lua_pushstring(L, "float"); + size_t stack_size = lua_objlen(L, 1); + lua_rawseti(L, 1, stack_size + 1); + } + return success; +} + +static int nk_love_style_push_font(const struct nk_user_font **field) +{ + nk_love_assert_type(-1, "Font", "nk.style_push: font fields must be fonts"); + lua_pushvalue(L, -1); + nk_love_tofont(&fonts[font_count]); + int success = nk_style_push_font(&context, &fonts[font_count++]); + if (success) { + lua_pushstring(L, "font"); + size_t stack_size = lua_objlen(L, 1); + lua_rawseti(L, 1, stack_size + 1); + } + return success; +} + +#define NK_LOVE_STYLE_PUSH(name, type, field) \ + nk_love_assert(lua_type(L, -1) == LUA_TTABLE, "nk.style_push: " name " field must be a table"); \ + lua_getfield(L, -1, name); \ + if (lua_type(L, -1) != LUA_TNIL) \ + nk_love_style_push_##type(field); \ + lua_pop(L, 1); + +static void nk_love_style_push_text(struct nk_style_text *style) +{ + nk_love_assert(lua_type(L, -1) == LUA_TTABLE, "text style must be a table"); + NK_LOVE_STYLE_PUSH("color", color, &style->color); + NK_LOVE_STYLE_PUSH("padding", vec2, &style->padding); +} + +static void nk_love_style_push_button(struct nk_style_button *style) +{ + nk_love_assert(lua_type(L, -1) == LUA_TTABLE, "button style must be a table"); + NK_LOVE_STYLE_PUSH("normal", item, &style->normal); + NK_LOVE_STYLE_PUSH("hover", item, &style->hover); + NK_LOVE_STYLE_PUSH("active", item, &style->active); + NK_LOVE_STYLE_PUSH("border color", color, &style->border_color); + NK_LOVE_STYLE_PUSH("text background", color, &style->text_background); + NK_LOVE_STYLE_PUSH("text normal", color, &style->text_normal); + NK_LOVE_STYLE_PUSH("text hover", color, &style->text_hover); + NK_LOVE_STYLE_PUSH("text active", color, &style->text_active); + NK_LOVE_STYLE_PUSH("text alignment", align, &style->text_alignment); + NK_LOVE_STYLE_PUSH("border", float, &style->border); + NK_LOVE_STYLE_PUSH("rounding", float, &style->rounding); + NK_LOVE_STYLE_PUSH("padding", vec2, &style->padding); + NK_LOVE_STYLE_PUSH("image padding", vec2, &style->image_padding); + NK_LOVE_STYLE_PUSH("touch padding", vec2, &style->touch_padding); +} + +static void nk_love_style_push_scrollbar(struct nk_style_scrollbar *style) +{ + nk_love_assert(lua_type(L, -1) == LUA_TTABLE, "scrollbar style must be a table"); + NK_LOVE_STYLE_PUSH("normal", item, &style->normal); + NK_LOVE_STYLE_PUSH("hover", item, &style->hover); + NK_LOVE_STYLE_PUSH("active", item, &style->active); + NK_LOVE_STYLE_PUSH("border color", color, &style->border_color); + NK_LOVE_STYLE_PUSH("cursor normal", item, &style->cursor_normal); + NK_LOVE_STYLE_PUSH("cursor hover", item, &style->cursor_hover); + NK_LOVE_STYLE_PUSH("cursor active", item, &style->active); + NK_LOVE_STYLE_PUSH("cursor border color", color, &style->cursor_border_color); + NK_LOVE_STYLE_PUSH("border", float, &style->border); + NK_LOVE_STYLE_PUSH("rounding", float, &style->rounding); + NK_LOVE_STYLE_PUSH("border cursor", float, &style->border_cursor); + NK_LOVE_STYLE_PUSH("rounding cursor", float, &style->rounding_cursor); + NK_LOVE_STYLE_PUSH("padding", vec2, &style->padding); +} + +static void nk_love_style_push_edit(struct nk_style_edit *style) +{ + nk_love_assert(lua_type(L, -1) == LUA_TTABLE, "edit style must be a table"); + NK_LOVE_STYLE_PUSH("normal", item, &style->normal); + NK_LOVE_STYLE_PUSH("hover", item, &style->hover); + NK_LOVE_STYLE_PUSH("active", item, &style->active); + NK_LOVE_STYLE_PUSH("border color", color, &style->border_color); + NK_LOVE_STYLE_PUSH("scrollbar", scrollbar, &style->scrollbar); + NK_LOVE_STYLE_PUSH("cursor normal", color, &style->cursor_normal); + NK_LOVE_STYLE_PUSH("cursor hover", color, &style->cursor_hover); + NK_LOVE_STYLE_PUSH("cursor text normal", color, &style->cursor_text_normal); + NK_LOVE_STYLE_PUSH("cursor text hover", color, &style->cursor_text_hover); + NK_LOVE_STYLE_PUSH("text normal", color, &style->text_normal); + NK_LOVE_STYLE_PUSH("text hover", color, &style->text_hover); + NK_LOVE_STYLE_PUSH("text active", color, &style->text_active); + NK_LOVE_STYLE_PUSH("selected normal", color, &style->selected_normal); + NK_LOVE_STYLE_PUSH("selected hover", color, &style->selected_hover); + NK_LOVE_STYLE_PUSH("selected text normal", color, &style->text_normal); + NK_LOVE_STYLE_PUSH("selected text hover", color, &style->selected_text_hover); + NK_LOVE_STYLE_PUSH("border", float, &style->border); + NK_LOVE_STYLE_PUSH("rounding", float, &style->rounding); + NK_LOVE_STYLE_PUSH("cursor size", float, &style->cursor_size); + NK_LOVE_STYLE_PUSH("scrollbar size", vec2, &style->scrollbar_size); + NK_LOVE_STYLE_PUSH("padding", vec2, &style->padding); + NK_LOVE_STYLE_PUSH("row padding", float, &style->row_padding); +} + +static void nk_love_style_push_toggle(struct nk_style_toggle *style) +{ + nk_love_assert(lua_type(L, -1) == LUA_TTABLE, "toggle style must be a table"); + NK_LOVE_STYLE_PUSH("normal", item, &style->normal); + NK_LOVE_STYLE_PUSH("hover", item, &style->hover); + NK_LOVE_STYLE_PUSH("active", item, &style->active); + NK_LOVE_STYLE_PUSH("border color", color, &style->border_color); + NK_LOVE_STYLE_PUSH("cursor normal", item, &style->cursor_normal); + NK_LOVE_STYLE_PUSH("cursor hover", item, &style->cursor_hover); + NK_LOVE_STYLE_PUSH("text normal", color, &style->text_normal); + NK_LOVE_STYLE_PUSH("text hover", color, &style->text_hover); + NK_LOVE_STYLE_PUSH("text active", color, &style->text_active); + NK_LOVE_STYLE_PUSH("text background", color, &style->text_background); + NK_LOVE_STYLE_PUSH("text alignment", align, &style->text_alignment); + NK_LOVE_STYLE_PUSH("padding", vec2, &style->padding); + NK_LOVE_STYLE_PUSH("touch padding", vec2, &style->touch_padding); + NK_LOVE_STYLE_PUSH("spacing", float, &style->spacing); + NK_LOVE_STYLE_PUSH("border", float, &style->border); +} + +static void nk_love_style_push_selectable(struct nk_style_selectable *style) +{ + nk_love_assert(lua_type(L, -1) == LUA_TTABLE, "selectable style must be a table"); + NK_LOVE_STYLE_PUSH("normal", item, &style->normal); + NK_LOVE_STYLE_PUSH("hover", item, &style->hover); + NK_LOVE_STYLE_PUSH("pressed", item, &style->pressed); + NK_LOVE_STYLE_PUSH("normal active", item, &style->normal_active); + NK_LOVE_STYLE_PUSH("hover active", item, &style->hover_active); + NK_LOVE_STYLE_PUSH("pressed active", item, &style->pressed_active); + NK_LOVE_STYLE_PUSH("text normal", color, &style->text_normal); + NK_LOVE_STYLE_PUSH("text hover", color, &style->text_hover); + NK_LOVE_STYLE_PUSH("text pressed", color, &style->text_pressed); + NK_LOVE_STYLE_PUSH("text normal active", color, &style->text_normal_active); + NK_LOVE_STYLE_PUSH("text hover active", color, &style->text_hover_active); + NK_LOVE_STYLE_PUSH("text pressed active", color, &style->text_pressed_active); + NK_LOVE_STYLE_PUSH("text background", color, &style->text_background); + NK_LOVE_STYLE_PUSH("text alignment", align, &style->text_alignment); + NK_LOVE_STYLE_PUSH("rounding", float, &style->rounding); + NK_LOVE_STYLE_PUSH("padding", vec2, &style->padding); + NK_LOVE_STYLE_PUSH("touch padding", vec2, &style->touch_padding); + NK_LOVE_STYLE_PUSH("image padding", vec2, &style->image_padding); +} + +static void nk_love_style_push_slider(struct nk_style_slider *style) +{ + nk_love_assert(lua_type(L, -1) == LUA_TTABLE, "slider style must be a table"); + NK_LOVE_STYLE_PUSH("normal", item, &style->normal); + NK_LOVE_STYLE_PUSH("hover", item, &style->hover); + NK_LOVE_STYLE_PUSH("active", item, &style->active); + NK_LOVE_STYLE_PUSH("border color", color, &style->border_color); + NK_LOVE_STYLE_PUSH("bar normal", color, &style->bar_normal); + NK_LOVE_STYLE_PUSH("bar active", color, &style->bar_active); + NK_LOVE_STYLE_PUSH("bar filled", color, &style->bar_filled); + NK_LOVE_STYLE_PUSH("cursor normal", item, &style->cursor_normal); + NK_LOVE_STYLE_PUSH("cursor hover", item, &style->cursor_hover); + NK_LOVE_STYLE_PUSH("cursor active", item, &style->cursor_active); + NK_LOVE_STYLE_PUSH("border", float, &style->border); + NK_LOVE_STYLE_PUSH("rounding", float, &style->rounding); + NK_LOVE_STYLE_PUSH("bar height", float, &style->bar_height); + NK_LOVE_STYLE_PUSH("padding", vec2, &style->padding); + NK_LOVE_STYLE_PUSH("spacing", vec2, &style->spacing); + NK_LOVE_STYLE_PUSH("cursor size", vec2, &style->cursor_size); +} + +static void nk_love_style_push_progress(struct nk_style_progress *style) +{ + nk_love_assert(lua_type(L, -1) == LUA_TTABLE, "progress style must be a table"); + NK_LOVE_STYLE_PUSH("normal", item, &style->normal); + NK_LOVE_STYLE_PUSH("hover", item, &style->hover); + NK_LOVE_STYLE_PUSH("active", item, &style->active); + NK_LOVE_STYLE_PUSH("border color", color, &style->border_color); + NK_LOVE_STYLE_PUSH("cursor normal", item, &style->cursor_normal); + NK_LOVE_STYLE_PUSH("cursor hover", item, &style->cursor_hover); + NK_LOVE_STYLE_PUSH("cusor active", item, &style->cursor_active); + NK_LOVE_STYLE_PUSH("cursor border color", color, &style->cursor_border_color); + NK_LOVE_STYLE_PUSH("rounding", float, &style->rounding); + NK_LOVE_STYLE_PUSH("border", float, &style->border); + NK_LOVE_STYLE_PUSH("cursor border", float, &style->cursor_border); + NK_LOVE_STYLE_PUSH("cursor rounding", float, &style->cursor_rounding); + NK_LOVE_STYLE_PUSH("padding", vec2, &style->padding); +} + +static void nk_love_style_push_property(struct nk_style_property *style) +{ + nk_love_assert(lua_type(L, -1) == LUA_TTABLE, "property style must be a table"); + NK_LOVE_STYLE_PUSH("normal", item, &style->normal); + NK_LOVE_STYLE_PUSH("hover", item, &style->hover); + NK_LOVE_STYLE_PUSH("active", item, &style->active); + NK_LOVE_STYLE_PUSH("border color", color, &style->border_color); + NK_LOVE_STYLE_PUSH("label normal", color, &style->label_normal); + NK_LOVE_STYLE_PUSH("label hover", color, &style->label_hover); + NK_LOVE_STYLE_PUSH("label active", color, &style->label_active); + NK_LOVE_STYLE_PUSH("border", float, &style->border); + NK_LOVE_STYLE_PUSH("rounding", float, &style->rounding); + NK_LOVE_STYLE_PUSH("padding", vec2, &style->padding); + NK_LOVE_STYLE_PUSH("edit", edit, &style->edit); + NK_LOVE_STYLE_PUSH("inc button", button, &style->inc_button); + NK_LOVE_STYLE_PUSH("dec button", button, &style->dec_button); +} + +static void nk_love_style_push_chart(struct nk_style_chart *style) +{ + nk_love_assert(lua_type(L, -1) == LUA_TTABLE, "chart style must be a table"); + NK_LOVE_STYLE_PUSH("background", item, &style->background); + NK_LOVE_STYLE_PUSH("border color", color, &style->border_color); + NK_LOVE_STYLE_PUSH("selected color", color, &style->selected_color); + NK_LOVE_STYLE_PUSH("color", color, &style->color); + NK_LOVE_STYLE_PUSH("border", float, &style->border); + NK_LOVE_STYLE_PUSH("rounding", float, &style->rounding); + NK_LOVE_STYLE_PUSH("padding", vec2, &style->padding); +} + +static void nk_love_style_push_tab(struct nk_style_tab *style) +{ + nk_love_assert(lua_type(L, -1) == LUA_TTABLE, "tab style must be a table"); + NK_LOVE_STYLE_PUSH("background", item, &style->background); + NK_LOVE_STYLE_PUSH("border color", color, &style->border_color); + NK_LOVE_STYLE_PUSH("text", color, &style->text); + NK_LOVE_STYLE_PUSH("tab maximize button", button, &style->tab_maximize_button); + NK_LOVE_STYLE_PUSH("tab minimize button", button, &style->tab_minimize_button); + NK_LOVE_STYLE_PUSH("node maximize button", button, &style->node_maximize_button); + NK_LOVE_STYLE_PUSH("node minimize button", button, &style->node_minimize_button); + NK_LOVE_STYLE_PUSH("border", float, &style->border); + NK_LOVE_STYLE_PUSH("rounding", float, &style->rounding); + NK_LOVE_STYLE_PUSH("indent", float, &style->indent); + NK_LOVE_STYLE_PUSH("padding", vec2, &style->padding); + NK_LOVE_STYLE_PUSH("spacing", vec2, &style->spacing); +} + +static void nk_love_style_push_combo(struct nk_style_combo *style) +{ + nk_love_assert(lua_type(L, -1) == LUA_TTABLE, "combo style must be a table"); + NK_LOVE_STYLE_PUSH("normal", item, &style->normal); + NK_LOVE_STYLE_PUSH("hover", item, &style->hover); + NK_LOVE_STYLE_PUSH("active", item, &style->active); + NK_LOVE_STYLE_PUSH("border color", color, &style->border_color); + NK_LOVE_STYLE_PUSH("label normal", color, &style->label_normal); + NK_LOVE_STYLE_PUSH("label hover", color, &style->label_hover); + NK_LOVE_STYLE_PUSH("label active", color, &style->label_active); + NK_LOVE_STYLE_PUSH("symbol normal", color, &style->symbol_normal); + NK_LOVE_STYLE_PUSH("symbol hover", color, &style->symbol_hover); + NK_LOVE_STYLE_PUSH("symbol active", color, &style->symbol_active); + NK_LOVE_STYLE_PUSH("button", button, &style->button); + NK_LOVE_STYLE_PUSH("border", float, &style->border); + NK_LOVE_STYLE_PUSH("rounding", float, &style->rounding); + NK_LOVE_STYLE_PUSH("content padding", vec2, &style->content_padding); + NK_LOVE_STYLE_PUSH("button padding", vec2, &style->button_padding); + NK_LOVE_STYLE_PUSH("spacing", vec2, &style->spacing); +} + +static void nk_love_style_push_window_header(struct nk_style_window_header *style) +{ + nk_love_assert(lua_type(L, -1) == LUA_TTABLE, "window header style must be a table"); + NK_LOVE_STYLE_PUSH("normal", item, &style->normal); + NK_LOVE_STYLE_PUSH("hover", item, &style->hover); + NK_LOVE_STYLE_PUSH("active", item, &style->active); + NK_LOVE_STYLE_PUSH("close button", button, &style->close_button); + NK_LOVE_STYLE_PUSH("minimize button", button, &style->minimize_button); + NK_LOVE_STYLE_PUSH("label normal", color, &style->label_normal); + NK_LOVE_STYLE_PUSH("label hover", color, &style->label_hover); + NK_LOVE_STYLE_PUSH("label active", color, &style->label_active); + NK_LOVE_STYLE_PUSH("padding", vec2, &style->padding); + NK_LOVE_STYLE_PUSH("label padding", vec2, &style->label_padding); + NK_LOVE_STYLE_PUSH("spacing", vec2, &style->spacing); +} + +static void nk_love_style_push_window(struct nk_style_window *style) +{ + nk_love_assert(lua_type(L, -1) == LUA_TTABLE, "window style must be a table"); + NK_LOVE_STYLE_PUSH("header", window_header, &style->header); + NK_LOVE_STYLE_PUSH("fixed background", item, &style->fixed_background); + NK_LOVE_STYLE_PUSH("background", color, &style->background); + NK_LOVE_STYLE_PUSH("border color", color, &style->border_color); + NK_LOVE_STYLE_PUSH("popup border color", color, &style->popup_border_color); + NK_LOVE_STYLE_PUSH("combo border color", color, &style->combo_border_color); + NK_LOVE_STYLE_PUSH("contextual border color", color, &style->contextual_border_color); + NK_LOVE_STYLE_PUSH("menu border color", color, &style->menu_border_color); + NK_LOVE_STYLE_PUSH("group border color", color, &style->group_border_color); + NK_LOVE_STYLE_PUSH("tooltip border color", color, &style->tooltip_border_color); + NK_LOVE_STYLE_PUSH("scaler", item, &style->scaler); + NK_LOVE_STYLE_PUSH("border", float, &style->border); + NK_LOVE_STYLE_PUSH("combo border", float, &style->combo_border); + NK_LOVE_STYLE_PUSH("contextual border", float, &style->contextual_border); + NK_LOVE_STYLE_PUSH("menu border", float, &style->menu_border); + NK_LOVE_STYLE_PUSH("group border", float, &style->group_border); + NK_LOVE_STYLE_PUSH("tooltip border", float, &style->tooltip_border); + NK_LOVE_STYLE_PUSH("popup border", float, &style->popup_border); + NK_LOVE_STYLE_PUSH("rounding", float, &style->rounding); + NK_LOVE_STYLE_PUSH("spacing", vec2, &style->spacing); + NK_LOVE_STYLE_PUSH("scrollbar size", vec2, &style->scrollbar_size); + NK_LOVE_STYLE_PUSH("min size", vec2, &style->min_size); + NK_LOVE_STYLE_PUSH("padding", vec2, &style->padding); + NK_LOVE_STYLE_PUSH("group padding", vec2, &style->group_padding); + NK_LOVE_STYLE_PUSH("popup padding", vec2, &style->popup_padding); + NK_LOVE_STYLE_PUSH("combo padding", vec2, &style->combo_padding); + NK_LOVE_STYLE_PUSH("contextual padding", vec2, &style->contextual_padding); + NK_LOVE_STYLE_PUSH("menu padding", vec2, &style->menu_padding); + NK_LOVE_STYLE_PUSH("tooltip padding", vec2, &style->tooltip_padding); +} + +static int nk_love_style_push(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.style_push: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TTABLE, "nk.style_push: arg 1 should be a table"); + lua_newtable(L); + lua_insert(L, 1); + NK_LOVE_STYLE_PUSH("font", font, &context.style.font); + NK_LOVE_STYLE_PUSH("text", text, &context.style.text); + NK_LOVE_STYLE_PUSH("button", button, &context.style.button); + NK_LOVE_STYLE_PUSH("contextual button", button, &context.style.contextual_button); + NK_LOVE_STYLE_PUSH("menu button", button, &context.style.menu_button); + NK_LOVE_STYLE_PUSH("option", toggle, &context.style.option); + NK_LOVE_STYLE_PUSH("checkbox", toggle, &context.style.checkbox); + NK_LOVE_STYLE_PUSH("selectable", selectable, &context.style.selectable); + NK_LOVE_STYLE_PUSH("slider", slider, &context.style.slider); + NK_LOVE_STYLE_PUSH("progress", progress, &context.style.progress); + NK_LOVE_STYLE_PUSH("property", property, &context.style.property); + NK_LOVE_STYLE_PUSH("edit", edit, &context.style.edit); + NK_LOVE_STYLE_PUSH("chart", chart, &context.style.chart); + NK_LOVE_STYLE_PUSH("scrollh", scrollbar, &context.style.scrollh); + NK_LOVE_STYLE_PUSH("scrollv", scrollbar, &context.style.scrollv); + NK_LOVE_STYLE_PUSH("tab", tab, &context.style.tab); + NK_LOVE_STYLE_PUSH("combo", combo, &context.style.combo); + NK_LOVE_STYLE_PUSH("window", window, &context.style.window); + lua_pop(L, 1); + lua_getfield(L, LUA_REGISTRYINDEX, "nuklear"); + lua_getfield(L, -1, "stack"); + size_t stack_size = lua_objlen(L, -1); + lua_pushvalue(L, 1); + lua_rawseti(L, -2, stack_size + 1); + return 0; +} + +static int nk_love_style_pop(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.style_pop: wrong number of arguments"); + lua_getfield(L, LUA_REGISTRYINDEX, "nuklear"); + lua_getfield(L, -1, "stack"); + size_t stack_size = lua_objlen(L, -1); + lua_rawgeti(L, -1, stack_size); + lua_pushnil(L); + lua_rawseti(L, -3, stack_size); + stack_size = lua_objlen(L, -1); + size_t i; + for (i = stack_size; i > 0; --i) { + lua_rawgeti(L, -1, i); + const char *type = lua_tostring(L, -1); + if (!strcmp(type, "color")) { + nk_style_pop_color(&context); + } else if (!strcmp(type, "vec2")) { + nk_style_pop_vec2(&context); + } else if (!strcmp(type, "item")) { + nk_style_pop_style_item(&context); + } else if (!strcmp(type, "flags")) { + nk_style_pop_flags(&context); + } else if (!strcmp(type, "float")) { + nk_style_pop_float(&context); + } else if (!strcmp(type, "font")) { + nk_style_pop_font(&context); + } else { + nk_love_error("nk.pop: bad style item type"); + } + lua_pop(L, 1); + } + return 0; +} + +static int nk_love_widget_bounds(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.widget_bounds: wrong number of arguments"); + struct nk_rect bounds = nk_widget_bounds(&context); + lua_pushnumber(L, bounds.x); + lua_pushnumber(L, bounds.y); + lua_pushnumber(L, bounds.w); + lua_pushnumber(L, bounds.h); + return 4; +} + +static int nk_love_widget_position(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.widget_position: wrong number of arguments"); + struct nk_vec2 pos = nk_widget_position(&context); + lua_pushnumber(L, pos.x); + lua_pushnumber(L, pos.y); + return 2; +} + +static int nk_love_widget_size(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.widget_size: wrong number of arguments"); + struct nk_vec2 pos = nk_widget_size(&context); + lua_pushnumber(L, pos.x); + lua_pushnumber(L, pos.y); + return 2; +} + +static int nk_love_widget_width(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.widget_width: wrong number of arguments"); + float width = nk_widget_width(&context); + lua_pushnumber(L, width); + return 1; +} + +static int nk_love_widget_height(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.widget_height: wrong number of arguments"); + float height = nk_widget_height(&context); + lua_pushnumber(L, height); + return 1; +} + +static int nk_love_widget_is_hovered(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 0, "nk.widget_is_hovered: wrong number of arguments"); + int hovered = nk_widget_is_hovered(&context); + lua_pushboolean(L, hovered); + return 1; +} + +static int nk_love_widget_is_mouse_clicked(lua_State *L) +{ + int argc = lua_gettop(L); + nk_love_assert(argc == 0 || argc == 1, "nk.widget_is_mouse_clicked: wrong number of arguments"); + enum nk_buttons button = NK_BUTTON_LEFT; + if (argc == 1 && lua_type(L, 1) != LUA_TNIL) { + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.widget_is_mouse_clicked: arg 1 should be a string"); + const char *button_string = lua_tostring(L, 1); + if (!nk_love_parse_button(button_string, &button)) { + nk_love_error("nk.widget_is_mouse_clicked: arg 1 should be a button"); + } + } + int clicked = nk_widget_is_mouse_clicked(&context, button); + lua_pushboolean(L, clicked); + return 1; +} + +static int nk_love_widget_has_mouse_click(lua_State *L) +{ + int argc = lua_gettop(L); + nk_love_assert(argc >= 0 && argc <= 2, "nk.widget_has_mouse_click: wrong number of arguments"); + enum nk_buttons button = NK_BUTTON_LEFT; + if (argc >= 1 && lua_type(L, 1) != LUA_TNIL) { + nk_love_assert(lua_type(L, 1) == LUA_TSTRING, "nk.widget_has_mouse_click: arg 1 should be a string"); + const char *button_string = lua_tostring(L, 1); + if (!nk_love_parse_button(button_string, &button)) { + nk_love_error("nk.widget_has_mouse_click: arg 1 should be a button"); + } + } + int down = 1; + if (argc >= 2 && lua_type(L, 2) != LUA_TNIL) { + nk_love_assert(lua_type(L, 2) == LUA_TBOOLEAN, "nk.widget_has_mouse_click: arg 2 should be a boolean"); + down = lua_toboolean(L, 2); + } + int has_click = nk_widget_has_mouse_click_down(&context, button, down); + lua_pushboolean(L, has_click); + return 1; +} + +static int nk_love_spacing(lua_State *L) +{ + nk_love_assert(lua_gettop(L) == 1, "nk.spacing: wrong number of arguments"); + nk_love_assert(lua_type(L, 1) == LUA_TNUMBER, "nk.spacing: arg 1 should be a number"); + int cols = lua_tointeger(L, 1); + nk_spacing(&context, cols); + return 0; +} + +LUALIB_API int luaopen_nuklear(lua_State *L) +{ + lua_newtable(L); + + lua_pushcfunction(L, nk_love_init); + lua_setfield(L, -2, "init"); + lua_pushcfunction(L, nk_love_shutdown); + lua_setfield(L, -2, "shutdown"); + + lua_pushcfunction(L, nk_love_keypressed); + lua_setfield(L, -2, "keypressed"); + lua_pushcfunction(L, nk_love_keyreleased); + lua_setfield(L, -2, "keyreleased"); + lua_pushcfunction(L, nk_love_mousepressed); + lua_setfield(L, -2, "mousepressed"); + lua_pushcfunction(L, nk_love_mousereleased); + lua_setfield(L, -2, "mousereleased"); + lua_pushcfunction(L, nk_love_mousemoved); + lua_setfield(L, -2, "mousemoved"); + lua_pushcfunction(L, nk_love_textinput); + lua_setfield(L, -2, "textinput"); + lua_pushcfunction(L, nk_love_wheelmoved); + lua_setfield(L, -2, "wheelmoved"); + + lua_pushcfunction(L, nk_love_draw); + lua_setfield(L, -2, "draw"); + + lua_pushcfunction(L, nk_love_frame_begin); + lua_setfield(L, -2, "frame_begin"); + lua_pushcfunction(L, nk_love_frame_end); + lua_setfield(L, -2, "frame_end"); + + lua_pushcfunction(L, nk_love_window_begin); + lua_setfield(L, -2, "window_begin"); + lua_pushcfunction(L, nk_love_window_end); + lua_setfield(L, -2, "window_end"); + lua_pushcfunction(L, nk_love_window_get_bounds); + lua_setfield(L, -2, "window_get_bounds"); + lua_pushcfunction(L, nk_love_window_get_position); + lua_setfield(L, -2, "window_get_position"); + lua_pushcfunction(L, nk_love_window_get_size); + lua_setfield(L, -2, "window_get_size"); + lua_pushcfunction(L, nk_love_window_get_content_region); + lua_setfield(L, -2, "window_get_content_region"); + lua_pushcfunction(L, nk_love_window_has_focus); + lua_setfield(L, -2, "window_has_focus"); + lua_pushcfunction(L, nk_love_window_is_collapsed); + lua_setfield(L, -2, "window_is_collapsed"); + lua_pushcfunction(L, nk_love_window_is_hidden); + lua_setfield(L, -2, "window_is_hidden"); + lua_pushcfunction(L, nk_love_window_is_active); + lua_setfield(L, -2, "window_is_active"); + lua_pushcfunction(L, nk_love_window_is_hovered); + lua_setfield(L, -2, "window_is_hovered"); + lua_pushcfunction(L, nk_love_window_is_any_hovered); + lua_setfield(L, -2, "window_is_any_hovered"); + lua_pushcfunction(L, nk_love_item_is_any_active); + lua_setfield(L, -2, "item_is_any_active"); + lua_pushcfunction(L, nk_love_window_set_bounds); + lua_setfield(L, -2, "window_set_bounds"); + lua_pushcfunction(L, nk_love_window_set_position); + lua_setfield(L, -2, "window_set_position"); + lua_pushcfunction(L, nk_love_window_set_size); + lua_setfield(L, -2, "window_set_size"); + lua_pushcfunction(L, nk_love_window_set_focus); + lua_setfield(L, -2, "window_set_focus"); + lua_pushcfunction(L, nk_love_window_close); + lua_setfield(L, -2, "window_close"); + lua_pushcfunction(L, nk_love_window_collapse); + lua_setfield(L, -2, "window_collapse"); + lua_pushcfunction(L, nk_love_window_expand); + lua_setfield(L, -2, "window_expand"); + lua_pushcfunction(L, nk_love_window_show); + lua_setfield(L, -2, "window_show"); + lua_pushcfunction(L, nk_love_window_hide); + lua_setfield(L, -2, "window_hide"); + + lua_pushcfunction(L, nk_love_layout_row); + lua_setfield(L, -2, "layout_row"); + lua_pushcfunction(L, nk_love_layout_row_begin); + lua_setfield(L, -2, "layout_row_begin"); + lua_pushcfunction(L, nk_love_layout_row_push); + lua_setfield(L, -2, "layout_row_push"); + lua_pushcfunction(L, nk_love_layout_row_end); + lua_setfield(L, -2, "layout_row_end"); + lua_pushcfunction(L, nk_love_layout_space_begin); + lua_setfield(L, -2, "layout_space_begin"); + lua_pushcfunction(L, nk_love_layout_space_push); + lua_setfield(L, -2, "layout_space_push"); + lua_pushcfunction(L, nk_love_layout_space_end); + lua_setfield(L, -2, "layout_space_end"); + lua_pushcfunction(L, nk_love_layout_space_bounds); + lua_setfield(L, -2, "layout_space_bounds"); + lua_pushcfunction(L, nk_love_layout_space_to_screen); + lua_setfield(L, -2, "layout_space_to_screen"); + lua_pushcfunction(L, nk_love_layout_space_to_local); + lua_setfield(L, -2, "layout_space_to_local"); + lua_pushcfunction(L, nk_love_layout_space_rect_to_screen); + lua_setfield(L, -2, "layout_space_rect_to_screen"); + lua_pushcfunction(L, nk_love_layout_space_rect_to_local); + lua_setfield(L, -2, "layout_space_rect_to_local"); + lua_pushcfunction(L, nk_love_layout_ratio_from_pixel); + lua_setfield(L, -2, "layout_ratio_from_pixel"); + + lua_pushcfunction(L, nk_love_group_begin); + lua_setfield(L, -2, "group_begin"); + lua_pushcfunction(L, nk_love_group_end); + lua_setfield(L, -2, "group_end"); + + lua_pushcfunction(L, nk_love_tree_push); + lua_setfield(L, -2, "tree_push"); + lua_pushcfunction(L, nk_love_tree_pop); + lua_setfield(L, -2, "tree_pop"); + + lua_pushcfunction(L, nk_love_color_rgba); + lua_setfield(L, -2, "color_rgba"); + lua_pushcfunction(L, nk_love_color_hsva); + lua_setfield(L, -2, "color_hsva"); + lua_pushcfunction(L, nk_love_color_parse_rgba); + lua_setfield(L, -2, "color_parse_rgba"); + lua_pushcfunction(L, nk_love_color_parse_hsva); + lua_setfield(L, -2, "color_parse_hsva"); + + lua_pushcfunction(L, nk_love_label); + lua_setfield(L, -2, "label"); + lua_pushcfunction(L, nk_love_image); + lua_setfield(L, -2, "image"); + lua_pushcfunction(L, nk_love_button); + lua_setfield(L, -2, "button"); + lua_pushcfunction(L, nk_love_button_set_behavior); + lua_setfield(L, -2, "button_set_behavior"); + lua_pushcfunction(L, nk_love_button_push_behavior); + lua_setfield(L, -2, "button_push_behavior"); + lua_pushcfunction(L, nk_love_button_pop_behavior); + lua_setfield(L, -2, "button_pop_behavior"); + lua_pushcfunction(L, nk_love_checkbox); + lua_setfield(L, -2, "checkbox"); + lua_pushcfunction(L, nk_love_radio); + lua_setfield(L, -2, "radio"); + lua_pushcfunction(L, nk_love_selectable); + lua_setfield(L, -2, "selectable"); + lua_pushcfunction(L, nk_love_slider); + lua_setfield(L, -2, "slider"); + lua_pushcfunction(L, nk_love_progress); + lua_setfield(L, -2, "progress"); + lua_pushcfunction(L, nk_love_color_picker); + lua_setfield(L, -2, "color_picker"); + lua_pushcfunction(L, nk_love_property); + lua_setfield(L, -2, "property"); + lua_pushcfunction(L, nk_love_edit); + lua_setfield(L, -2, "edit"); + lua_pushcfunction(L, nk_love_popup_begin); + lua_setfield(L, -2, "popup_begin"); + lua_pushcfunction(L, nk_love_popup_close); + lua_setfield(L, -2, "popup_close"); + lua_pushcfunction(L, nk_love_popup_end); + lua_setfield(L, -2, "popup_end"); + lua_pushcfunction(L, nk_love_combobox); + lua_setfield(L, -2, "combobox"); + lua_pushcfunction(L, nk_love_combobox_begin); + lua_setfield(L, -2, "combobox_begin"); + lua_pushcfunction(L, nk_love_combobox_item); + lua_setfield(L, -2, "combobox_item"); + lua_pushcfunction(L, nk_love_combobox_close); + lua_setfield(L, -2, "combobox_close"); + lua_pushcfunction(L, nk_love_combobox_end); + lua_setfield(L, -2, "combobox_end"); + lua_pushcfunction(L, nk_love_contextual_begin); + lua_setfield(L, -2, "contextual_begin"); + lua_pushcfunction(L, nk_love_contextual_item); + lua_setfield(L, -2, "contextual_item"); + lua_pushcfunction(L, nk_love_contextual_close); + lua_setfield(L, -2, "contextual_close"); + lua_pushcfunction(L, nk_love_contextual_end); + lua_setfield(L, -2, "contextual_end"); + lua_pushcfunction(L, nk_love_tooltip); + lua_setfield(L, -2, "tooltip"); + lua_pushcfunction(L, nk_love_tooltip_begin); + lua_setfield(L, -2, "tooltip_begin"); + lua_pushcfunction(L, nk_love_tooltip_end); + lua_setfield(L, -2, "tooltip_end"); + lua_pushcfunction(L, nk_love_menubar_begin); + lua_setfield(L, -2, "menubar_begin"); + lua_pushcfunction(L, nk_love_menubar_end); + lua_setfield(L, -2, "menubar_end"); + lua_pushcfunction(L, nk_love_menu_begin); + lua_setfield(L, -2, "menu_begin"); + lua_pushcfunction(L, nk_love_menu_item); + lua_setfield(L, -2, "menu_item"); + lua_pushcfunction(L, nk_love_menu_close); + lua_setfield(L, -2, "menu_close"); + lua_pushcfunction(L, nk_love_menu_end); + lua_setfield(L, -2, "menu_end"); + + lua_pushcfunction(L, nk_love_style_default); + lua_setfield(L, -2, "style_default"); + lua_pushcfunction(L, nk_love_style_load_colors); + lua_setfield(L, -2, "style_load_colors"); + lua_pushcfunction(L, nk_love_style_set_font); + lua_setfield(L, -2, "style_set_font"); + lua_pushcfunction(L, nk_love_style_push); + lua_setfield(L, -2, "style_push"); + lua_pushcfunction(L, nk_love_style_pop); + lua_setfield(L, -2, "style_pop"); + + lua_pushcfunction(L, nk_love_widget_bounds); + lua_setfield(L, -2, "widget_bounds"); + lua_pushcfunction(L, nk_love_widget_position); + lua_setfield(L, -2, "widget_position"); + lua_pushcfunction(L, nk_love_widget_size); + lua_setfield(L, -2, "widget_size"); + lua_pushcfunction(L, nk_love_widget_width); + lua_setfield(L, -2, "widget_width"); + lua_pushcfunction(L, nk_love_widget_height); + lua_setfield(L, -2, "widget_height"); + lua_pushcfunction(L, nk_love_widget_is_hovered); + lua_setfield(L, -2, "widget_is_hovered"); + lua_pushcfunction(L, nk_love_widget_is_mouse_clicked); + lua_setfield(L, -2, "widget_is_mouse_clicked"); + lua_pushcfunction(L, nk_love_widget_has_mouse_click); + lua_setfield(L, -2, "widget_has_mouse_click"); + lua_pushcfunction(L, nk_love_spacing); + lua_setfield(L, -2, "spacing"); + + return 1; +}