diff --git a/bin/linux/libjpeg.so b/bin/linux/libjpeg.so
new file mode 100644
index 0000000..50b008a
Binary files /dev/null and b/bin/linux/libjpeg.so differ
diff --git a/bin/linux/libuv.so b/bin/linux/libuv.so
new file mode 100644
index 0000000..3097614
Binary files /dev/null and b/bin/linux/libuv.so differ
diff --git a/bin/linux/luajit b/bin/linux/luajit
new file mode 100644
index 0000000..00f1a4a
Binary files /dev/null and b/bin/linux/luajit differ
diff --git a/bin/macos/png.dylib b/bin/macos/png.dylib
new file mode 100644
index 0000000..4d38d0f
Binary files /dev/null and b/bin/macos/png.dylib differ
diff --git a/bin/win64/hmm_dll.dll b/bin/win64/hmm_dll.dll
index db5e27f..267e672 100644
Binary files a/bin/win64/hmm_dll.dll and b/bin/win64/hmm_dll.dll differ
diff --git a/bin/win64/libuv.dll b/bin/win64/libuv.dll
new file mode 100644
index 0000000..0ddf30a
Binary files /dev/null and b/bin/win64/libuv.dll differ
diff --git a/bin/win64/sokol_debug_dll.dll b/bin/win64/sokol_debug_dll.dll
index f175c10..0881566 100644
Binary files a/bin/win64/sokol_debug_dll.dll and b/bin/win64/sokol_debug_dll.dll differ
diff --git a/bin/win64/sokol_dll.dll b/bin/win64/sokol_dll.dll
index 86cb26c..7148970 100644
Binary files a/bin/win64/sokol_dll.dll and b/bin/win64/sokol_dll.dll differ
diff --git a/bin/win64/sokol_imgui_dll.dll b/bin/win64/sokol_imgui_dll.dll
index dcf86f4..4d261d4 100644
Binary files a/bin/win64/sokol_imgui_dll.dll and b/bin/win64/sokol_imgui_dll.dll differ
diff --git a/bin/win64/sokol_nuklear_dll.dll b/bin/win64/sokol_nuklear_dll.dll
new file mode 100644
index 0000000..eb541f0
Binary files /dev/null and b/bin/win64/sokol_nuklear_dll.dll differ
diff --git a/bin/win64/sokol_shape_dll.dll b/bin/win64/sokol_shape_dll.dll
index 8537015..9b1694b 100644
Binary files a/bin/win64/sokol_shape_dll.dll and b/bin/win64/sokol_shape_dll.dll differ
diff --git a/examples/libuv/test.lua b/examples/libuv/test.lua
new file mode 100644
index 0000000..fc81f63
--- /dev/null
+++ b/examples/libuv/test.lua
@@ -0,0 +1,86 @@
+
+package.path = package.path..";lua/?.lua;lua/?/init.lua"
+package.path = package.path..";ffi/?.lua;ffi/?/init.lua"
+package.path = package.path..";deps/?.lua;deps/?/init.lua"
+
+-----------------------------------------------------------------------------------------------
+local ffi = require 'ffi'
+local ffiext = require 'ffi-extensions'
+
+local p = require 'pretty-print-ffi'.prettyPrint
+local loop = require 'uv-ffi'
+
+local function makeHeader(datalen)
+
+ local dt = os.date("%a, %d %b %Y %X GMT")
+
+ local data = "HTTP/1.1 200 OK\r\n"..
+ "Date: "..dt.."\r\n"..
+ "Server: Apache/2.4.29 (Ubuntu)\r\n"..
+ "Cache-Control: max-age=604800\r\n"..
+ "Pragma: no-cache\r\n"..
+ "Content-Encoding: none\r\n"..
+ "Content-Length: "..datalen.."\r\n"..
+ "Connection: Close\r\n"..
+ "Content-Type: text/html;charset=UTF-8\r\n\r\n"
+ return data
+end
+
+-- require 'safe-coro'(function ()
+-- local timer = loop:newTimer()
+-- p("About to sleep", timer)
+-- timer:sleep(1000)
+-- p("Done sleeping!", timer)
+-- timer:close()
+-- end)
+
+local function alloc_buffer(handle, suggested_size)
+ return loop.uv.uv_buf_init( ffi.new("char[?]", suggested_size), suggested_size)
+end
+
+local function echo_write(req, status)
+ if status == -1 then
+ p("Write error!")
+ end
+ p("Request:", req)
+end
+
+local function echo_read(client, nread, buf)
+ if nread == -1 then
+ p("Read error!");
+ loop.uv.uv_close(ffi.cast("uv_handle_t*",client), nil)
+ return
+ end
+
+ local write_req = ffi.new("uv_write_t[1]")
+ local data = ffi.new ("uv_buf_t[1]")
+
+ local resp = "
HELLOOOOO
\r\n"
+ local hdr = makeHeader(#resp)
+ hdr = hdr..resp
+
+ data[0].base = ffi.cast("char *", hdr)
+ data[0].len = #hdr
+
+ loop.uv.uv_write(write_req, client, data, 1, echo_write)
+end
+
+function on_new_connect( server, status )
+
+ client = ffi.new("uv_tcp_t[1]")
+ loop.uv.uv_tcp_init(loop, client)
+ -- Start accepting the request
+ if loop.uv.uv_accept(server, ffi.cast("uv_stream_t*", client)) == 0 then
+ -- Valid accept then start reading stream
+ loop.uv.uv_read_start(ffi.cast("uv_stream_t*", client), alloc_buffer, echo_read)
+ else
+ -- Bad request or connection closed
+ loop.uv.uv_close(ffi.cast("uv_handle_t*",client), nil)
+ end
+end
+
+local server = loop:newTcp()
+local res = loop:bind(server, "0.0.0.0", 7000)
+runcb = server:listen( 128, on_new_connect )
+if runcb == nil then p("Couldnt create server."); return end
+loop:run('default')
diff --git a/examples/libuv/threads.lua b/examples/libuv/threads.lua
new file mode 100644
index 0000000..7a32f3d
--- /dev/null
+++ b/examples/libuv/threads.lua
@@ -0,0 +1,55 @@
+
+package.path = package.path..";lua/?.lua;lua/?/init.lua"
+package.path = package.path..";ffi/?.lua;ffi/?/init.lua"
+package.path = package.path..";deps/?.lua;deps/?/init.lua"
+
+-----------------------------------------------------------------------------------------------
+local ffi = require 'ffi'
+local ffiext = require 'ffi-extensions'
+local kern = ffiext.kern
+
+local p = require 'pretty-print-ffi'.prettyPrint
+local loop = require 'uv-ffi'
+
+-----------------------------------------------------------------------------------------------
+
+function hare(arg)
+ local tracklen = arg[0]
+ while (tracklen) do
+ tracklen = tracklen - 1
+ kern.Sleep(100)
+ p("Hare ran another step.")
+ end
+end
+
+-----------------------------------------------------------------------------------------------
+function tortoise(arg)
+ local tracklen = arg[0]
+ while (tracklen) do
+ tracklen = tracklen - 1
+ kern.Sleep(500)
+ p("Tortise ran another step.")
+ end
+end
+
+-----------------------------------------------------------------------------------------------
+
+local tracklen1 = ffi.new("int[1]", 10)
+local tracklen2 = ffi.new("int[1]", 10)
+
+local hare_id = ffi.new("uv_thread_t[1]")
+local tortoise_id = ffi.new("uv_thread_t[1]")
+
+local id1 = loop.uv.uv_thread_create(hare_id, hare, tracklen1)
+local id2 = loop.uv.uv_thread_create(tortoise_id, tortoise, tracklen2)
+p("Res:", id1)
+p("Res:", id2)
+
+while tracklen2[0] > 0 do
+ kern.Sleep(50)
+end
+
+loop.uv.uv_thread_join(hare_id)
+loop.uv.uv_thread_join(tortoise_id)
+
+-----------------------------------------------------------------------------------------------
diff --git a/examples/samples.zip b/examples/samples.zip
deleted file mode 100644
index 7a1e7b4..0000000
Binary files a/examples/samples.zip and /dev/null differ
diff --git a/examples/samples/cimgui_sapp.lua b/examples/samples/cimgui_sapp.lua
index 5239f8a..161ea6c 100644
--- a/examples/samples/cimgui_sapp.lua
+++ b/examples/samples/cimgui_sapp.lua
@@ -4,7 +4,7 @@ package.path = package.path..";../?.lua"
--_G.SOKOL_DLL = "sokol_debug_dll"
local sapp = require("sokol_app")
-local sg = require("sokol_imgui") -- Includes gfx!!
+sg = require("sokol_imgui") -- Includes gfx!!
local im = sg -- Will NOT be using imgui in applications. Sample only. Dont recommend.
local slib = require("sokol_libs") -- Warn - always after gfx!!
diff --git a/examples/samples/font/ProggyClean.ttf b/examples/samples/font/ProggyClean.ttf
new file mode 100644
index 0000000..0270cdf
Binary files /dev/null and b/examples/samples/font/ProggyClean.ttf differ
diff --git a/examples/samples/nuklear_sapp.lua b/examples/samples/nuklear_sapp.lua
new file mode 100644
index 0000000..c783b2b
--- /dev/null
+++ b/examples/samples/nuklear_sapp.lua
@@ -0,0 +1,1475 @@
+package.cpath = package.cpath..";../bin/win64/?.dll"
+package.path = package.path..";../ffi/sokol/?.lua"
+package.path = package.path..";../?.lua"
+
+--_G.SOKOL_DLL = "sokol_debug_dll"
+local sapp = require("sokol_app")
+sg = require("sokol_nuklear")
+local nk = sg
+local slib = require("sokol_libs") -- Warn - always after gfx!!
+
+local hmm = require("hmm")
+local hutils = require("hmm_utils")
+
+local ffi = require("ffi")
+
+-- --------------------------------------------------------------------------------------
+
+local function init(void)
+ -- // setup sokol-gfx, sokol-time and sokol-imgui
+ local sg_desc = ffi.new("sg_desc[1]")
+ sg_desc[0].environment = slib.sglue_environment()
+ sg_desc[0].logger.func = slib.slog_func
+ sg.sg_setup( sg_desc )
+
+ -- // use sokol-nuklear with all default-options (we're not doing
+ -- // multi-sampled rendering or using non-default pixel formats)
+ local snk = ffi.new("snk_desc_t[1]")
+ snk[0].dpi_scale = sapp.sapp_dpi_scale()
+ snk[0].logger.func = slib.slog_func
+ nk.snk_setup(snk)
+end
+
+-- --------------------------------------------------------------------------------------
+
+local function cleanup()
+
+ sg.sg_shutdown()
+end
+
+-- --------------------------------------------------------------------------------------
+
+local function input(event)
+ nk.snk_handle_event(event)
+end
+
+-- --------------------------------------------------------------------------------------
+
+local show_menu = ffi.new("int[1]", { nk.nk_true })
+local titlebar = ffi.new("int[1]", {nk.nk_true})
+local border = ffi.new("int[1]", {nk.nk_true})
+local resize = ffi.new("int[1]", {nk.nk_true})
+local movable = ffi.new("int[1]", {nk.nk_true})
+local no_scrollbar = ffi.new("int[1]", {nk.nk_false})
+local scale_left = ffi.new("int[1]", {nk.nk_false})
+
+local function draw_demo_ui(ctx)
+
+ -- /* window flags */
+
+ window_flags = 0
+ minimizable = nk.nk_true
+
+ -- /* popups */
+ header_align = nk.NK_HEADER_RIGHT
+ show_app_about = nk.nk_false
+
+ -- /* window flags */
+ window_flags = 0
+ ctx[0].style.window.header.align = header_align
+ if (border) then window_flags = bit.bor(window_flags, nk.NK_WINDOW_BORDER) end
+ if (resize) then window_flags = bit.bor(window_flags, nk.NK_WINDOW_SCALABLE) end
+ if (movable) then window_flags = bit.bor(window_flags, nk.NK_WINDOW_MOVABLE) end
+ if (no_scrollbar) then window_flags = bit.bor(window_flags, nk.NK_WINDOW_NO_SCROLLBAR) end
+ if (scale_left) then window_flags = bit.bor(window_flags, nk.NK_WINDOW_SCALE_LEFT) end
+ if (minimizable) then window_flags = bit.bor(window_flags, nk.NK_WINDOW_MINIMIZABLE) end
+
+ winrect = ffi.new("struct nk_rect[1]", {{10, 25, 400, 600}})
+ if (nk.nk_begin(ctx, "Overview", winrect[0], window_flags)) then
+
+ if (show_menu) then
+
+ -- /* menubar */
+ menu_states = { MENU_DEFAULT = 0, MENU_WINDOWS = 1}
+ mprog = ffi.new("size_t[1]", {60})
+ mslider = ffi.new("int[1]", { 10 })
+ mcheck = ffi.new("bool[1]", {nk.nk_true})
+ nk.nk_menubar_begin(ctx)
+
+ -- /* menu #1 */
+ nk.nk_layout_row_begin(ctx, nk.NK_STATIC, 25, 5)
+ nk.nk_layout_row_push(ctx, 45)
+ if (nk.nk_menu_begin_label(ctx, "MENU", nk.NK_TEXT_LEFT, nk.nk_vec2(120, 200))) then
+
+ prog = ffi.new("size_t[1]", { 40 } )
+ slider = ffi.new("int[1]", { 10 } )
+ check = ffi.new("bool[1]", {nk.nk_true})
+ nk.nk_layout_row_dynamic(ctx, 25, 1)
+ if (nk.nk_menu_item_label(ctx, "Hide", nk.NK_TEXT_LEFT)) then
+ show_menu = nk.nk_false
+ end
+ if (nk.nk_menu_item_label(ctx, "About", nk.NK_TEXT_LEFT)) then
+ show_app_about = nk.nk_true
+ end
+ nk.nk_progress(ctx, prog, 100, nk.NK_MODIFIABLE)
+ nk.nk_slider_int(ctx, 0, slider, 16, 1)
+ nk.nk_checkbox_label(ctx, "check", check)
+ nk.nk_menu_end(ctx)
+ end
+ -- /* menu #2 */
+ nk.nk_layout_row_push(ctx, 60)
+ if (nk.nk_menu_begin_label(ctx, "ADVANCED", nk.NK_TEXT_LEFT, nk.nk_vec2(200, 600))) then
+
+ menu_states = { MENU_NONE = 0,MENU_FILE = 1, MENU_EDIT = 2,MENU_VIEW = 3,MENU_CHART = 4}
+ menu_state = menu_states.MENU_NONE
+ state = ffi.new("nk_collapse_states[1]")
+
+ state[0] = nk.NK_MINIMIZED
+ if(menu_state == menu_states.MENU_FILE) then state[0] = nk.NK_MAXIMIZED end
+ if (nk_tree_state_push(ctx, nk.NK_TREE_TAB, "FILE", state)) then
+ menu_state = menu_states.MENU_FILE
+ nk.nk_menu_item_label(ctx, "New", nk.NK_TEXT_LEFT)
+ nk.nk_menu_item_label(ctx, "Open", nk.NK_TEXT_LEFT)
+ nk.nk_menu_item_label(ctx, "Save", nk.NK_TEXT_LEFT)
+ nk.nk_menu_item_label(ctx, "Close", nk.NK_TEXT_LEFT)
+ nk.nk_menu_item_label(ctx, "Exit", nk.NK_TEXT_LEFT)
+ nk.nk_tree_pop(ctx)
+ else
+ if(menu_state == menu_states.MENU_FILE) then
+ menu_state = menu_states.MENU_NONE
+ end
+ end
+
+ state[0] = nk.NK_MINIMIZED
+ if(menu_state == menu_states.MENU_EDIT) then state[0] = nk.NK_MAXIMIZED end
+
+ if (nk_tree_state_push(ctx, nk.NK_TREE_TAB, "EDIT", state)) then
+ menu_state = menu_states.MENU_EDIT
+ nk.nk_menu_item_label(ctx, "Copy", nk.NK_TEXT_LEFT)
+ nk.nk_menu_item_label(ctx, "Delete", nk.NK_TEXT_LEFT)
+ nk.nk_menu_item_label(ctx, "Cut", nk.NK_TEXT_LEFT)
+ nk.nk_menu_item_label(ctx, "Paste", nk.NK_TEXT_LEFT)
+ nk.nk_tree_pop(ctx)
+ else
+ if(menu_state == menu_states.MENU_EDIT) then
+ menu_state = menu_states.MENU_NONE
+ end
+ end
+
+ state[0] = nk.NK_MINIMIZED
+ if(menu_state == menu_states.MENU_VIEW) then state[0] = nk.NK_MAXIMIZED end
+ if (nk_tree_state_push(ctx, nk.NK_TREE_TAB, "VIEW", state)) then
+ menu_state = menu_states.MENU_VIEW
+ nk.nk_menu_item_label(ctx, "About", nk.NK_TEXT_LEFT)
+ nk.nk_menu_item_label(ctx, "Options", nk.NK_TEXT_LEFT)
+ nk.nk_menu_item_label(ctx, "Customize", nk.NK_TEXT_LEFT)
+ nk.nk_tree_pop(ctx)
+ else
+ if(menu_state == menu_states.MENU_VIEW) then
+ menu_state = menu_states.MENU_NONE
+ end
+ end
+
+ state[0] = nk.NK_MINIMIZED
+ if(menu_state == menu_states.MENU_CHART) then state[0] = nk.NK_MAXIMIZED end
+ if (nk_tree_state_push(ctx, nk.NK_TREE_TAB, "CHART", state)) then
+ local i = 0
+ local values= ffi.new("float[12]", {26.0,13.0,30.0,15.0,25.0,10.0,20.0,40.0,12.0,8.0,22.0,28.0} )
+ menu_state = menu_states.MENU_CHART
+ nk.nk_layout_row_dynamic(ctx, 150, 1)
+ nk.nk_chart_begin(ctx, nk.NK_CHART_COLUMN, nk.NK_LEN(values), 0, 50)
+ for i = 0, nk.NK_LEN(values)-1 do
+ nk.nk_chart_push(ctx, values[i])
+ end
+ nk.nk_chart_end(ctx)
+ nk.nk_tree_pop(ctx)
+ else
+ if(menu_state == menu_states.MENU_CHART) then
+ menu_state = menu_states.MENU_NONE
+ end
+ end
+ nk.nk_menu_end(ctx)
+ end
+ -- /* menu widgets */
+ nk.nk_layout_row_push(ctx, 70)
+ nk.nk_progress(ctx, mprog, 100, nk.NK_MODIFIABLE)
+ nk.nk_slider_int(ctx, 0, mslider, 16, 1)
+ nk.nk_checkbox_label(ctx, "check", mcheck)
+ nk.nk_menubar_end(ctx)
+ end
+
+ if (show_app_about == nk.nk_true) then
+
+ -- /* about popup */
+ local s = ffi.new("struct nk_rect[1]", { {20, 100, 300, 190} })
+ if (nk.nk_popup_begin(ctx, nk.NK_POPUP_STATIC, "About", nk.NK_WINDOW_CLOSABLE, s[0])) then
+
+ nk.nk_layout_row_dynamic(ctx, 20, 1)
+ nk.nk_label(ctx, "Nuklear", nk.NK_TEXT_LEFT)
+ nk.nk_label(ctx, "By Micha Mettke", nk.NK_TEXT_LEFT)
+ nk.nk_label(ctx, "nuklear is licensed under the public domain License.", nk.NK_TEXT_LEFT)
+ nk.nk_popup_end(ctx)
+ else
+ show_app_about = nk.nk_false
+ end
+ end
+
+ -- /* window flags */
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_TAB, "Window", nk.NK_MINIMIZED)) then
+ nk.nk_layout_row_dynamic(ctx, 30, 2)
+ nk.nk_checkbox_label(ctx, "Titlebar", titlebar)
+ nk.nk_checkbox_label(ctx, "Menu", show_menu)
+ nk.nk_checkbox_label(ctx, "Border", border)
+ nk.nk_checkbox_label(ctx, "Resizable", resize)
+ nk.nk_checkbox_label(ctx, "Movable", movable)
+ nk.nk_checkbox_label(ctx, "No Scrollbar", no_scrollbar)
+ nk.nk_checkbox_label(ctx, "Minimizable", minimizable)
+ nk.nk_checkbox_label(ctx, "Scale Left", scale_left)
+ nk.nk_tree_pop(ctx)
+ end
+
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_TAB, "Widgets", nk.NK_MINIMIZED)) then
+ options = {A=0,B=1,C=2}
+ checkbox = ffi.new("int[1]")
+ option = ffi.new("int[1]")
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_NODE, "Text", nk.NK_MINIMIZED)) then
+
+ -- /* Text Widgets */
+ nk.nk_layout_row_dynamic(ctx, 20, 1)
+ nk.nk_label(ctx, "Label aligned left", nk.NK_TEXT_LEFT)
+ nk.nk_label(ctx, "Label aligned centered", nk.NK_TEXT_CENTERED)
+ nk.nk_label(ctx, "Label aligned right", nk.NK_TEXT_RIGHT)
+ nk.nk_label_colored(ctx, "Blue text", nk.NK_TEXT_LEFT, nk.nk_rgb(0,0,255))
+ nk.nk_label_colored(ctx, "Yellow text", nk.NK_TEXT_LEFT, nk.nk_rgb(255,255,0))
+ nk.nk_text(ctx, "Text without /0", 15, nk.NK_TEXT_RIGHT)
+
+ nk.nk_layout_row_static(ctx, 100, 200, 1)
+ nk.nk_label_wrap(ctx, "This is a very long line to hopefully get this text to be wrapped into multiple lines to show line wrapping")
+ nk.nk_layout_row_dynamic(ctx, 100, 1)
+ nk.nk_label_wrap(ctx, "This is another long text to show dynamic window changes on multiline text")
+ nk.nk_tree_pop(ctx)
+ end
+
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_NODE, "Button", nk.NK_MINIMIZED)) then
+
+ -- /* Buttons Widgets */
+ nk.nk_layout_row_static(ctx, 30, 100, 3)
+ if (nk_button_label(ctx, "Button")) then
+ print(stdout, "Button pressed!\n")
+ end
+ nk.nk_button_set_behavior(ctx, nk.NK_BUTTON_REPEATER)
+ if (nk_button_label(ctx, "Repeater")) then
+ print(stdout, "Repeater is being pressed!\n")
+ end
+ nk.nk_button_set_behavior(ctx, nk.NK_BUTTON_DEFAULT)
+ nk.nk_button_color(ctx, nk.nk_rgb(0,0,255))
+
+ nk.nk_layout_row_static(ctx, 25, 25, 8)
+ nk.nk_button_symbol(ctx, nk.NK_SYMBOL_CIRCLE_SOLID)
+ nk.nk_button_symbol(ctx, nk.NK_SYMBOL_CIRCLE_OUTLINE)
+ nk.nk_button_symbol(ctx, nk.NK_SYMBOL_RECT_SOLID)
+ nk.nk_button_symbol(ctx, nk.NK_SYMBOL_RECT_OUTLINE)
+ nk.nk_button_symbol(ctx, nk.NK_SYMBOL_TRIANGLE_UP)
+ nk.nk_button_symbol(ctx, nk.NK_SYMBOL_TRIANGLE_DOWN)
+ nk.nk_button_symbol(ctx, nk.NK_SYMBOL_TRIANGLE_LEFT)
+ nk.nk_button_symbol(ctx, nk.NK_SYMBOL_TRIANGLE_RIGHT)
+
+ nk.nk_layout_row_static(ctx, 30, 100, 2)
+ nk.nk_button_symbol_label(ctx, nk.NK_SYMBOL_TRIANGLE_LEFT, "prev", nk.NK_TEXT_RIGHT)
+ nk.nk_button_symbol_label(ctx, nk.NK_SYMBOL_TRIANGLE_RIGHT, "next", nk.NK_TEXT_LEFT)
+ nk.nk_tree_pop(ctx)
+ end
+
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_NODE, "Basic", nk.NK_MINIMIZED)) then
+
+ -- /* Basic widgets */
+ int_slider = ffi.new("int[1]", {5})
+ float_slider = ffi.new("float[1]", {2.5})
+ prog_value = ffi.new("size_t[1]", {40})
+ property_float = ffi.new("float[1]", {2.0})
+ property_int = ffi.new("int[1]", {10})
+ property_neg = ffi.new("int[1]", {10})
+
+ range_float_min = ffi.new("float[1]", {0})
+ range_float_max = ffi.new("float[1]", {100})
+ range_float_value = ffi.new("float[1]",{50})
+ range_int_min = ffi.new("int[1]",{0})
+ range_int_value = ffi.new("int[1]",{2048})
+ range_int_max = ffi.new("int[1]",{4096})
+ ratio = ffi.new("float[2]", {120, 150})
+
+ nk.nk_layout_row_static(ctx, 30, 100, 1)
+ nk.nk_checkbox_label(ctx, "Checkbox", checkbox)
+
+ nk.nk_layout_row_static(ctx, 30, 80, 3)
+ if nk.nk_option_label(ctx, "optionA", option == A) then option = options.A end
+ if nk.nk_option_label(ctx, "optionB", option == B) then option = options.B end
+ if nk.nk_option_label(ctx, "optionC", option == C) then option = options.C end
+
+ nk.nk_layout_row(ctx, nk.NK_STATIC, 30, 2, ratio)
+ nk.nk_labelf(ctx, nk.NK_TEXT_LEFT, "Slider int")
+ nk.nk_slider_int(ctx, 0, int_slider, 10, 1)
+
+ nk.nk_label(ctx, "Slider float", nk.NK_TEXT_LEFT)
+ nk.nk_slider_float(ctx, 0, float_slider, 5.0, 0.5)
+ nk.nk_labelf(ctx, nk.NK_TEXT_LEFT, "Progressbar: %zu" , prog_value)
+ nk.nk_progress(ctx, prog_value, 100, nk.NK_MODIFIABLE)
+
+ nk.nk_layout_row(ctx, nk.NK_STATIC, 25, 2, ratio)
+ nk.nk_label(ctx, "Property float:", nk.NK_TEXT_LEFT)
+ nk.nk_property_float(ctx, "Float:", 0, property_float, 64.0, 0.1, 0.2)
+ nk.nk_label(ctx, "Property int:", nk.NK_TEXT_LEFT)
+ nk.nk_property_int(ctx, "Int:", 0, property_int, 100, 1, 1)
+ nk.nk_label(ctx, "Property neg:", nk.NK_TEXT_LEFT)
+ nk.nk_property_int(ctx, "Neg:", -10, property_neg, 10, 1, 1)
+
+ nk.nk_layout_row_dynamic(ctx, 25, 1)
+ nk.nk_label(ctx, "Range:", nk.NK_TEXT_LEFT)
+ nk.nk_layout_row_dynamic(ctx, 25, 3)
+ nk.nk_property_float(ctx, "#min:", 0, range_float_min, range_float_max, 1.0, 0.2)
+ nk.nk_property_float(ctx, "#float:", range_float_min, range_float_value, range_float_max, 1.0, 0.2)
+ nk.nk_property_float(ctx, "#max:", range_float_min, range_float_max, 100, 1.0, 0.2)
+
+ nk.nk_property_int(ctx, "#min:", INT_MIN, range_int_min, range_int_max, 1, 10)
+ nk.nk_property_int(ctx, "#neg:", range_int_min, range_int_value, range_int_max, 1, 10)
+ nk.nk_property_int(ctx, "#max:", range_int_min, range_int_max, INT_MAX, 1, 10)
+
+ nk.nk_tree_pop(ctx)
+ end
+
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_NODE, "Inactive", nk.NK_MINIMIZED)) then
+
+ inactive = 1
+ nk.nk_layout_row_dynamic(ctx, 30, 1)
+ nk.nk_checkbox_label(ctx, "Inactive", inactive)
+
+ nk.nk_layout_row_static(ctx, 30, 80, 1)
+ if (inactive) then
+ button = ffi.new("nk_style_button[1]")
+ button[0] = ctx[0].style.button
+ ctx[0].style.button.normal = nk.nk_style_item_color(nk_rgb(40,40,40))
+ ctx[0].style.button.hover = nk.nk_style_item_color(nk_rgb(40,40,40))
+ ctx[0].style.button.active = nk.nk_style_item_color(nk_rgb(40,40,40))
+ ctx[0].style.button.border_color = nk.nk_rgb(60,60,60)
+ ctx[0].style.button.text_background = nk.nk_rgb(60,60,60)
+ ctx[0].style.button.text_normal = nk.nk_rgb(60,60,60)
+ ctx[0].style.button.text_hover = nk.nk_rgb(60,60,60)
+ ctx[0].style.button.text_active = nk.nk_rgb(60,60,60)
+ nk.nk_button_label(ctx, "button")
+ ctx[0].style.button = button
+ else
+ if (nk.nk_button_label(ctx, "button")) then
+ print(stdout, "button pressed\n")
+ end
+ end
+ nk.nk_tree_pop(ctx)
+ end
+
+
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_NODE, "Selectable", nk.NK_MINIMIZED)) then
+
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_NODE, "List", nk.NK_MINIMIZED)) then
+
+ selected[4] = {nk_false, nk.nk_false, nk.nk_true, nk.nk_false}
+ nk.nk_layout_row_static(ctx, 18, 100, 1)
+ nk.nk_selectable_label(ctx, "Selectable", nk.NK_TEXT_LEFT, selected[0])
+ nk.nk_selectable_label(ctx, "Selectable", nk.NK_TEXT_LEFT, selected[1])
+ nk.nk_label(ctx, "Not Selectable", nk.NK_TEXT_LEFT)
+ nk.nk_selectable_label(ctx, "Selectable", nk.NK_TEXT_LEFT, selected[2])
+ nk.nk_selectable_label(ctx, "Selectable", nk.NK_TEXT_LEFT, selected[3])
+ nk.nk_tree_pop(ctx)
+ end
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_NODE, "Grid", nk.NK_MINIMIZED)) then
+
+ selected[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}
+ nk.nk_layout_row_static(ctx, 50, 50, 4)
+ for i = 0, 16-1 do
+ if (nk_selectable_label(ctx, "Z", nk.NK_TEXT_CENTERED, selected[i])) then
+ local x = (i % 4)
+ local y = i / 4
+ if (x > 0) then selected[i - 1] = bit.bxor(selected[i - 1], 1) end
+ if (x < 3) then selected[i + 1] = bit.bxor(selected[i + 1], 1) end
+ if (y > 0) then selected[i - 4] = bit.bxor(selected[i - 4], 1) end
+ if (y < 3) then selected[i + 4] = bit.bxor(selected[i + 4], 1) end
+ end
+ end
+ nk.nk_tree_pop(ctx)
+ end
+ nk.nk_tree_pop(ctx)
+ end
+
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_NODE, "Combo", nk.NK_MINIMIZED)) then
+
+ -- /* Combobox Widgets
+ -- * In this library comboboxes are not limited to being a popup
+ -- * list of selectable text. Instead it is a abstract concept of
+ -- * having something that is *selected* or displayed, a popup window
+ -- * which opens if something needs to be modified and the content
+ -- * of the popup which causes the *selected* or displayed value to
+ -- * change or if wanted close the combobox.
+ -- *
+ -- * While strange at first handling comboboxes in a abstract way
+ -- * solves the problem of overloaded window content. For example
+ -- * changing a color value requires 4 value modifier (slider, property,...)
+ -- * for RGBA then you need a label and ways to display the current color.
+ -- * If you want to go fancy you even add rgb and hsv ratio boxes.
+ -- * While fine for one color if you have a lot of them it because
+ -- * tedious to look at and quite wasteful in space. You could add
+ -- * a popup which modifies the color but this does not solve the
+ -- * fact that it still requires a lot of cluttered space to do.
+ -- *
+ -- * In these kind of instance abstract comboboxes are quite handy. All
+ -- * value modifiers are hidden inside the combobox popup and only
+ -- * the color is shown if not open. This combines the clarity of the
+ -- * popup with the ease of use of just using the space for modifiers.
+ -- *
+ -- * Other instances are for example time and especially date picker,
+ -- * which only show the currently activated time/data and hide the
+ -- * selection logic inside the combobox popup.
+ -- */
+ chart_selection = ffi.new("float[1]", {8.0})
+ current_weapon = ffi.new("int[1]", {0})
+ check_values = ffi.new("int[5]", {0})
+ position = ffi.new("float[3]", {0})
+ combo_color = ffi.new("struct nk_color[1]", {{130, 50, 50, 255}})
+ combo_color2 = ffi.new("struct nk_colorf[1]", {{0.509, 0.705, 0.2, 1.0}})
+ prog_a = ffi.new("size_t[1]",{20})
+ prog_b = ffi.new("size_t[1]",{40})
+ prog_c = ffi.new("size_t[1]",{10})
+ prog_d = ffi.new("size_t[1]",{90})
+ weapons = ffi.new("char *[5]", {"Fist","Pistol","Shotgun","Plasma","BFG"})
+
+ local buffer = ffi.new("char[64]")
+ local sum = 0
+
+ -- /* default combobox */
+ nk.nk_layout_row_static(ctx, 25, 200, 1)
+ current_weapon = nk.nk_combo(ctx, weapons, nk.NK_LEN(weapons), current_weapon, 25, nk.nk_vec2(200,200))
+
+ -- /* slider color combobox */
+ if (nk.nk_combo_begin_color(ctx, combo_color, nk.nk_vec2(200,200))) then
+ ratios = ffi.new("float[2]", {0.15, 0.85})
+ nk.nk_layout_row(ctx, nk.NK_DYNAMIC, 30, 2, ratios)
+ nk.nk_label(ctx, "R:", nk.NK_TEXT_LEFT)
+ combo_color.r = (nk_byte)nk_slide_int(ctx, 0, combo_color.r, 255, 5)
+ nk.nk_label(ctx, "G:", nk.NK_TEXT_LEFT)
+ combo_color.g = (nk_byte)nk_slide_int(ctx, 0, combo_color.g, 255, 5)
+ nk.nk_label(ctx, "B:", nk.NK_TEXT_LEFT)
+ combo_color.b = (nk_byte)nk_slide_int(ctx, 0, combo_color.b, 255, 5)
+ nk.nk_label(ctx, "A:", nk.NK_TEXT_LEFT)
+ combo_color.a = (nk_byte)nk_slide_int(ctx, 0, combo_color.a , 255, 5)
+ nk.nk_combo_end(ctx)
+ end
+ -- /* complex color combobox */
+ if (nk.nk_combo_begin_color(ctx, nk.nk_rgb_cf(combo_color2), nk.nk_vec2(200,400))) then
+ color_mode = {COL_RGB = 0, COL_HSV = 1}
+ col_mode = color_mode.COL_RGB
+
+ nk.nk_layout_row_dynamic(ctx, 120, 1)
+ combo_color2 = nk.nk_color_picker(ctx, combo_color2, nk.NK_RGBA)
+
+ nk.nk_layout_row_dynamic(ctx, 25, 2)
+ if(nk.nk_option_label(ctx, "RGB", col_mode == COL_RGB)) then col_mode = nk.COL_RGB end
+ if(nk.nk_option_label(ctx, "HSV", col_mode == COL_HSV)) then col_mode = nk.COL_HSV end
+
+ nk.nk_layout_row_dynamic(ctx, 25, 1)
+ if (col_mode == COL_RGB) then
+ combo_color2.r = nk.nk_propertyf(ctx, "#R:", 0, combo_color2.r, 1.0, 0.01,0.005)
+ combo_color2.g = nk.nk_propertyf(ctx, "#G:", 0, combo_color2.g, 1.0, 0.01,0.005)
+ combo_color2.b = nk.nk_propertyf(ctx, "#B:", 0, combo_color2.b, 1.0, 0.01,0.005)
+ combo_color2.a = nk.nk_propertyf(ctx, "#A:", 0, combo_color2.a, 1.0, 0.01,0.005)
+ else
+ local hsva = ffi.new("float[4]")
+ nk.nk_colorf_hsva_fv(hsva, combo_color2)
+ hsva[0] = nk.nk_propertyf(ctx, "#H:", 0, hsva[0], 1.0, 0.01,0.05)
+ hsva[1] = nk.nk_propertyf(ctx, "#S:", 0, hsva[1], 1.0, 0.01,0.05)
+ hsva[2] = nk.nk_propertyf(ctx, "#V:", 0, hsva[2], 1.0, 0.01,0.05)
+ hsva[3] = nk.nk_propertyf(ctx, "#A:", 0, hsva[3], 1.0, 0.01,0.05)
+ combo_color2 = nk.nk_hsva_colorfv(hsva)
+ end
+ nk.nk_combo_end(ctx)
+ end
+ -- /* progressbar combobox */
+ sum = prog_a[0] + prog_b[0] + prog_c[0] + prog_d[0]
+ local buffer = ffi.string(sum)
+ if (nk.nk_combo_begin_label(ctx, buffer, nk.nk_vec2(200,200))) then
+ nk.nk_layout_row_dynamic(ctx, 30, 1)
+ nk.nk_progress(ctx, prog_a, 100, nk.NK_MODIFIABLE)
+ nk.nk_progress(ctx, prog_b, 100, nk.NK_MODIFIABLE)
+ nk.nk_progress(ctx, prog_c, 100, nk.NK_MODIFIABLE)
+ nk.nk_progress(ctx, prog_d, 100, nk.NK_MODIFIABLE)
+ nk.nk_combo_end(ctx)
+ end
+
+ -- /* checkbox combobox */
+ local sum = (check_values[0] + check_values[1] + check_values[2] + check_values[3] + check_values[4])
+ buffer = ffi.string(sum)
+ if (nk.nk_combo_begin_label(ctx, buffer, nk.nk_vec2(200,200))) then
+ nk.nk_layout_row_dynamic(ctx, 30, 1)
+ nk.nk_checkbox_label(ctx, weapons[0], check_values[0])
+ nk.nk_checkbox_label(ctx, weapons[1], check_values[1])
+ nk.nk_checkbox_label(ctx, weapons[2], check_values[2])
+ nk.nk_checkbox_label(ctx, weapons[3], check_values[3])
+ nk.nk_combo_end(ctx)
+ end
+
+ -- /* complex text combobox */
+ buffer = ffi.string(position[0]..","..position[1]..","..position[2])
+ if (nk.nk_combo_begin_label(ctx, buffer, nk.nk_vec2(200,200))) then
+ nk.nk_layout_row_dynamic(ctx, 25, 1)
+ nk.nk_property_float(ctx, "#X:", -1024.0, position[0], 1024.0, 1,0.5)
+ nk.nk_property_float(ctx, "#Y:", -1024.0, position[1], 1024.0, 1,0.5)
+ nk.nk_property_float(ctx, "#Z:", -1024.0, position[2], 1024.0, 1,0.5)
+ nk.nk_combo_end(ctx)
+ end
+
+ -- /* chart combobox */
+ buffer = ffi.string(chart_selection)
+ if (nk.nk_combo_begin_label(ctx, buffer, nk.nk_vec2(200,250))) then
+ local values = ffi.new(" float[13]", {26.0,13.0,30.0,15.0,25.0,10.0,20.0,40.0, 12.0, 8.0, 22.0, 28.0, 5.0})
+ nk.nk_layout_row_dynamic(ctx, 150, 1)
+ nk.nk_chart_begin(ctx, nk.NK_CHART_COLUMN, nk.NK_LEN(values), 0, 50)
+ for i = 0, nk.NK_LEN(values)-1 do
+ local res = nk.nk_chart_push(ctx, values[i])
+ if bit.band(res, nk.NK_CHART_CLICKED) then
+ chart_selection = values[i]
+ nk.nk_combo_close(ctx)
+ end
+ end
+ nk.nk_chart_end(ctx)
+ nk.nk_combo_end(ctx)
+ end
+
+ do
+ time_selected = 0
+ date_selected = 0
+
+ sel_time = os.date ("*t")
+ if (not time_selected or not date_selected) then
+ -- /* keep time and date updated if nothing is selected */
+ local cur_time = os.time()
+ if (not time_selected) then
+ -- memcpy(&sel_time, n, sizeof(struct tm))
+ end
+ if (not date_selected) then
+ -- memcpy(&sel_date, n, sizeof(struct tm))
+ end
+ end
+
+ -- /* time combobox */
+ buffer = sel_time.hour..":"..sel_time.min..":"..sel_time.sec
+ if (nk.nk_combo_begin_label(ctx, buffer, nk.nk_vec2(200,250))) then
+ time_selected = 1
+ nk.nk_layout_row_dynamic(ctx, 25, 1)
+ sel_time.tm_sec = nk.nk_propertyi(ctx, "#S:", 0, sel_time.sec, 60, 1, 1)
+ sel_time.tm_min = nk.nk_propertyi(ctx, "#M:", 0, sel_time.min, 60, 1, 1)
+ sel_time.tm_hour = nk.nk_propertyi(ctx, "#H:", 0, sel_time.hour, 23, 1, 1)
+ nk.nk_combo_end(ctx)
+ end
+
+ -- /* date combobox */
+ buffer = ffi.string(sel_date.tm_mday.."%-"..(sel_date.tm_mon+1).."%-"..(sel_date.tm_year+1900))
+ if (nk_combo_begin_label(ctx, buffer, nk.nk_vec2(350,400))) then
+
+ local month = ffi.new("char *[12]", {"January", "February", "March",
+ "April", "May", "June", "July", "August", "September",
+ "October", "November", "December"})
+ local week_days = ffi.new("char *[7]", {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"})
+ local month_days = ffi.new("int[12]",{31,28,31,30,31,30,31,31,30,31,30,31})
+ local year = sel_date.tm_year+1900
+ local leap_year = (not(year % 4) and ((year % 100))) or not(year % 400)
+ local days = month_days[sel_date.mon]
+ if(sel_date.mon == 1) then days = month_days[sel_date.mon] + leap_year end
+
+
+ -- /* header with month and year */
+ date_selected = 1
+ nk.nk_layout_row_begin(ctx, nk.NK_DYNAMIC, 20, 3)
+ nk.nk_layout_row_push(ctx, 0.05)
+ if (nk.nk_button_symbol(ctx, nk.NK_SYMBOL_TRIANGLE_LEFT)) then
+ if (sel_date.tm_mon == 0) then
+ sel_date.tm_mon = 11
+ sel_date.tm_year = nk.NK_MAX(0, sel_date.tm_year-1)
+ else
+ sel_date.tm_mon = sel_date.tm_mon - 1
+ end
+ end
+ nk.nk_layout_row_push(ctx, 0.9)
+ buffer = ffi.string(month[sel_date.tm_mon].." "..year)
+ nk.nk_label(ctx, buffer, nk.NK_TEXT_CENTERED)
+ nk.nk_layout_row_push(ctx, 0.05)
+ if (nk.nk_button_symbol(ctx, nk.NK_SYMBOL_TRIANGLE_RIGHT)) then
+ if (sel_date.mon == 11) then
+ sel_date.mon = 0
+ sel_date.year = sel_date.year + 1
+ else
+ sel_date.mon = sel_date.mon + 1
+ end
+ end
+ nk.nk_layout_row_end(ctx)
+
+ -- /* good old week day formula (double because precision) */
+ do
+ local year_n = year
+ if(sel_date.mon < 2) then year_n = year-1 end
+ local y = year_n % 100
+ local c = year_n / 100
+ local y4 = (int)(y / 4)
+ local c4 = (int)(c / 4)
+ local m = (int)(2.6 * (double)(((sel_date.tm_mon + 10) % 12) + 1) - 0.2)
+ local week_day = (((1 + m + y + y4 + c4 - 2 * c) % 7) + 7) % 7
+
+ -- /* weekdays */
+ nk.nk_layout_row_dynamic(ctx, 35, 7)
+ for i = 0, nk.NK_LEN(week_days)-1 do
+ nk.nk_label(ctx, week_days[i], nk.NK_TEXT_CENTERED)
+ end
+
+ -- /* days */
+ if (week_day > 0) then
+ nk.nk_spacing(ctx, week_day)
+ end
+
+ for i = 1, days do
+ buffer = ffi.string(i)
+ if (nk_button_label(ctx, buffer)) then
+ sel_date.tm_mday = i
+ nk.nk_combo_close(ctx)
+ end
+ end
+ end
+ nk.nk_combo_end(ctx)
+ end
+ end
+
+ nk.nk_tree_pop(ctx)
+ end
+
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_NODE, "Input", nk.NK_MINIMIZED)) then
+
+ ratio = ffi.new("float[2]", {120, 150})
+ field_buffer = ffi.new("char[64]")
+ text = ffi.new("char[9][64]")
+ text_len = ffi.new("int[9]")
+ box_buffer = ffi.new("char[512]")
+ field_len = ffi.new("int[1]")
+ box_len = ffi.new("int[1]")
+ active = ffi.new("nk_flags[1]")
+
+ nk.nk_layout_row(ctx, nk.NK_STATIC, 25, 2, ratio)
+ nk.nk_label(ctx, "Default:", nk.NK_TEXT_LEFT)
+
+ nk.nk_edit_string(ctx, nk.NK_EDIT_SIMPLE, text[0], text_len[0], 64, nk.nk_filter_default)
+ nk.nk_label(ctx, "Int:", nk.NK_TEXT_LEFT)
+ nk.nk_edit_string(ctx, nk.NK_EDIT_SIMPLE, text[1], text_len[1], 64, nk.nk_filter_decimal)
+ nk.nk_label(ctx, "Float:", nk.NK_TEXT_LEFT)
+ nk.nk_edit_string(ctx, nk.NK_EDIT_SIMPLE, text[2], text_len[2], 64, nk.nk_filter_float)
+ nk.nk_label(ctx, "Hex:", nk.NK_TEXT_LEFT)
+ nk.nk_edit_string(ctx, nk.NK_EDIT_SIMPLE, text[4], text_len[4], 64, nk.nk_filter_hex)
+ nk.nk_label(ctx, "Octal:", nk.NK_TEXT_LEFT)
+ nk.nk_edit_string(ctx, nk.NK_EDIT_SIMPLE, text[5], text_len[5], 64, nk.nk_filter_oct)
+ nk.nk_label(ctx, "Binary:", nk.NK_TEXT_LEFT)
+ nk.nk_edit_string(ctx, nk.NK_EDIT_SIMPLE, text[6], text_len[6], 64, nk.nk_filter_binary)
+
+ nk.nk_label(ctx, "Password:", nk.NK_TEXT_LEFT)
+ do
+ local i = 0
+ old_len = text_len[8]
+ buffer = ffi.new("char[64]")
+ for i = 0, text_len[8]-1 do buffer[i] = '*' end
+ nk.nk_edit_string(ctx, nk.NK_EDIT_FIELD, buffer, text_len[8], 64, nk.nk_filter_default)
+ if (old_len < text_len[8]) then
+ -- memcpy(&text[8][old_len], &buffer[old_len], (nk_size)(text_len[8] - old_len))
+ end
+ end
+
+ nk.nk_label(ctx, "Field:", nk.NK_TEXT_LEFT)
+ nk.nk_edit_string(ctx, nk.NK_EDIT_FIELD, field_buffer, field_len, 64, nk.nk_filter_default)
+
+ nk.nk_label(ctx, "Box:", nk.NK_TEXT_LEFT)
+ nk.nk_layout_row_static(ctx, 180, 278, 1)
+ nk.nk_edit_string(ctx, nk.NK_EDIT_BOX, box_buffer, box_len, 512, nk.nk_filter_default)
+
+ nk.nk_layout_row(ctx, nk.NK_STATIC, 25, 2, ratio)
+ active = nk.nk_edit_string(ctx, bit.bor(nk.NK_EDIT_FIELD,nk.NK_EDIT_SIG_ENTER), text[7], text_len[7], 64, nk.nk_filter_ascii)
+ if (nk.nk_button_label(ctx, "Submit") or bit.band(active, nk.NK_EDIT_COMMITED)) then
+
+ text[7][text_len[7]] = '\n'
+ text_len[7] = text_len[7] + 1
+ -- // memcpy(box_buffer[box_len], text[7], text_len[7])
+ box_len = box_len + text_len[7]
+ text_len[7] = 0
+ end
+ nk.nk_tree_pop(ctx)
+ end
+ nk.nk_tree_pop(ctx)
+ end
+
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_TAB, "Chart", nk.NK_MINIMIZED)) then
+
+ -- /* Chart Widgets
+ -- * This library has two different rather simple charts. The line and the
+ -- * column chart. Both provide a simple way of visualizing values and
+ -- * have a retained mode and immediate mode API version. For the retain
+ -- * mode version `nk_plot` and `nk_plot_function` you either provide
+ -- * an array or a callback to call to handle drawing the graph.
+ -- * For the immediate mode version you start by calling `nk_chart_begin`
+ -- * and need to provide min and max values for scaling on the Y-axis.
+ -- * and then call `nk_chart_push` to push values into the chart.
+ -- * Finally `nk_chart_end` needs to be called to end the process. */
+ local id = 0
+ local col_index = -1
+ local line_index = -1
+ local step = (2*3.141592654) / 32
+
+ local index = -1
+
+ -- /* line chart */
+ local id = 0
+ index = -1
+ nk.nk_layout_row_dynamic(ctx, 100, 1)
+ if (nk.nk_chart_begin(ctx, nk.NK_CHART_LINES, 32, -1.0, 1.0)) then
+ for i = 0, 32 do
+ local res = nk.nk_chart_push(ctx, math.cos(id))
+ if bit.band(res, nk.NK_CHART_HOVERING) then
+ index = i
+ end
+ if bit.band(res, nk.NK_CHART_CLICKED) then
+ line_index = i
+ end
+ id = id + step
+ end
+ nk.nk_chart_end(ctx)
+ end
+
+ if (index ~= -1) then
+ nk.nk_tooltipf(ctx, "Value: %.2f", (math.cos(index*step)) )
+ end
+ if (line_index ~= -1) then
+ nk.nk_layout_row_dynamic(ctx, 20, 1)
+ nk.nk_labelf(ctx, nk.NK_TEXT_LEFT, "Selected value: %.2f", math.cos(index*step))
+ end
+
+ -- /* column chart */
+ nk.nk_layout_row_dynamic(ctx, 100, 1)
+ if (nk.nk_chart_begin(ctx, nk.NK_CHART_COLUMN, 32, 0.0, 1.0)) then
+ for i = 0,32-1 do
+ local res = nk.nk_chart_push(ctx, math.abs(math.sin(id)))
+ if bit.band(res, nk.NK_CHART_HOVERING) then
+ index = i
+ end
+ if bit.band(res, nk.NK_CHART_CLICKED) then
+ col_index = i
+ end
+ id = id + step
+ end
+ nk.nk_chart_end(ctx)
+ end
+ if (index ~= -1) then
+ nk.nk_tooltipf(ctx, "Value: %.2f", math.abs(math.sin(step * index)))
+ end
+ if (col_index ~= -1) then
+ nk.nk_layout_row_dynamic(ctx, 20, 1)
+ nk.nk_labelf(ctx, nk.NK_TEXT_LEFT, "Selected value: %.2f", math.abs(math.sin(step * col_index)))
+ end
+
+ -- /* mixed chart */
+ nk.nk_layout_row_dynamic(ctx, 100, 1)
+ if (nk.nk_chart_begin(ctx, nk.NK_CHART_COLUMN, 32, 0.0, 1.0)) then
+ nk.nk_chart_add_slot(ctx, nk.NK_CHART_LINES, 32, -1.0, 1.0)
+ nk.nk_chart_add_slot(ctx, nk.NK_CHART_LINES, 32, -1.0, 1.0)
+ local id = 0
+ for i = 0, 32 - 1 do
+ nk.nk_chart_push_slot(ctx, math.abs(math.sin(id)), 0)
+ nk.nk_chart_push_slot(ctx, math.cos(id), 1)
+ nk.nk_chart_push_slot(ctx, math.sin(id), 2)
+ id = id + step
+ end
+ end
+ nk.nk_chart_end(ctx)
+
+ -- /* mixed colored chart */
+ nk.nk_layout_row_dynamic(ctx, 100, 1)
+ if (nk.nk_chart_begin_colored(ctx, nk.NK_CHART_LINES, nk.nk_rgb(255,0,0), nk.nk_rgb(150,0,0), 32, 0.0, 1.0)) then
+ nk.nk_chart_add_slot_colored(ctx, nk.NK_CHART_LINES, nk.nk_rgb(0,0,255), nk.nk_rgb(0,0,150),32, -1.0, 1.0)
+ nk.nk_chart_add_slot_colored(ctx, nk.NK_CHART_LINES, nk.nk_rgb(0,255,0), nk.nk_rgb(0,150,0), 32, -1.0, 1.0)
+ local id = 0
+ for i = 0, 32-1 do
+ nk.nk_chart_push_slot(ctx, math.abs(math.sin(id)), 0)
+ nk.nk_chart_push_slot(ctx, math.cos(id), 1)
+ nk.nk_chart_push_slot(ctx, math.sin(id), 2)
+ id = id + step
+ end
+ end
+ nk.nk_chart_end(ctx)
+ nk.nk_tree_pop(ctx)
+ end
+
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_TAB, "Popup", nk.NK_MINIMIZED)) then
+
+ color = ffi.new("struct nk_color[1]", {{255,0,0, 255}})
+ select = ffi.new("int[4]")
+ popup_active = ffi.new("int[1]")
+ inp = ctx[0].input
+ bounds = ffi.new("struct nk_rect[1]")
+
+ -- /* menu contextual */
+ nk.nk_layout_row_static(ctx, 30, 160, 1)
+ bounds = nk.nk_widget_bounds(ctx)
+ nk.nk_label(ctx, "Right click me for menu", nk.NK_TEXT_LEFT)
+
+ if (nk.nk_contextual_begin(ctx, 0, nk.nk_vec2(100, 300), bounds)) then
+ local size_t prog = 40
+ local int slider = 10
+
+ nk.nk_layout_row_dynamic(ctx, 25, 1)
+ nk.nk_checkbox_label(ctx, "Menu", show_menu)
+ nk.nk_progress(ctx, prog, 100, nk.NK_MODIFIABLE)
+ nk.nk_slider_int(ctx, 0, slider, 16, 1)
+ if (nk_contextual_item_label(ctx, "About", nk.NK_TEXT_CENTERED)) then
+ show_app_about = nk.nk_true
+ end
+ local select0 = "Select"
+ if(select[0]) then select0 = "Unselect" end
+ nk.nk_selectable_label(ctx, select0, nk.NK_TEXT_LEFT, select[0])
+ local select1 = "Select"
+ if(select[1]) then select1 = "Unselect" end
+ nk.nk_selectable_label(ctx, select1, nk.NK_TEXT_LEFT, select[1])
+ local select2 = "Select"
+ if(select[2]) then select2 = "Unselect" end
+ nk.nk_selectable_label(ctx, select2, nk.NK_TEXT_LEFT, select[2])
+ local select3 = "Select"
+ if(select[3]) then select3 = "Unselect" end
+ nk.nk_selectable_label(ctx, select3, nk.NK_TEXT_LEFT, select[3])
+ nk.nk_contextual_end(ctx)
+ end
+
+ -- /* color contextual */
+ nk.nk_layout_row_begin(ctx, nk.NK_STATIC, 30, 2)
+ nk.nk_layout_row_push(ctx, 120)
+ nk.nk_label(ctx, "Right Click here:", nk.NK_TEXT_LEFT)
+ nk.nk_layout_row_push(ctx, 50)
+ bounds = nk.nk_widget_bounds(ctx)
+ nk.nk_button_color(ctx, color[0])
+ nk.nk_layout_row_end(ctx)
+
+ if (nk.nk_contextual_begin(ctx, 0, nk.nk_vec2(350, 60), bounds)) then
+ nk.nk_layout_row_dynamic(ctx, 30, 4)
+ color.r = nk.nk_propertyi(ctx, "#r", 0, color.r, 255, 1, 1)
+ color.g = nk.nk_propertyi(ctx, "#g", 0, color.g, 255, 1, 1)
+ color.b = nk.nk_propertyi(ctx, "#b", 0, color.b, 255, 1, 1)
+ color.a = nk.nk_propertyi(ctx, "#a", 0, color.a, 255, 1, 1)
+ nk.nk_contextual_end(ctx)
+ end
+
+ -- /* popup */
+ nk.nk_layout_row_begin(ctx, nk.NK_STATIC, 30, 2)
+ nk.nk_layout_row_push(ctx, 120)
+ nk.nk_label(ctx, "Popup:", nk.NK_TEXT_LEFT)
+ nk.nk_layout_row_push(ctx, 50)
+ if (nk.nk_button_label(ctx, "Popup")) then
+ popup_active = 1
+ end
+ nk.nk_layout_row_end(ctx)
+
+ if (popup_active == 1) then
+
+ local s = ffi.new("struct nk_rect[1]",{{20, 100, 220, 90}})
+ if (nk.nk_popup_begin(ctx, nk.NK_POPUP_STATIC, "Error", 0, s)) then
+
+ nk.nk_layout_row_dynamic(ctx, 25, 1)
+ nk.nk_label(ctx, "A terrible error as occured", nk.NK_TEXT_LEFT)
+ nk.nk_layout_row_dynamic(ctx, 25, 2)
+ if (nk.nk_button_label(ctx, "OK")) then
+ popup_active = 0
+ nk.nk_popup_close(ctx)
+ end
+ if (nk.nk_button_label(ctx, "Cancel")) then
+ popup_active = 0
+ nk.nk_popup_close(ctx)
+ end
+ nk.nk_popup_end(ctx)
+ else
+ popup_active = nk.nk_false
+ end
+ end
+
+ -- /* tooltip */
+ nk.nk_layout_row_static(ctx, 30, 150, 1)
+ bounds = nk.nk_widget_bounds(ctx)
+ nk.nk_label(ctx, "Hover me for tooltip", nk.NK_TEXT_LEFT)
+ if (nk.nk_input_is_mouse_hovering_rect(inp, bounds)) then
+ nk.nk_tooltip(ctx, "This is a tooltip")
+ end
+
+ nk.nk_tree_pop(ctx)
+ end
+
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_TAB, "Layout", nk.NK_MINIMIZED)) then
+
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_NODE, "Widget", nk.NK_MINIMIZED)) then
+
+ ratio_two = ffi.new("float[3]", {0.2, 0.6, 0.2})
+ width_two = ffi.new("float[3]", {100, 200, 50})
+
+ nk.nk_layout_row_dynamic(ctx, 30, 1)
+ nk.nk_label(ctx, "Dynamic fixed column layout with generated position and size:", nk.NK_TEXT_LEFT)
+ nk.nk_layout_row_dynamic(ctx, 30, 3)
+ nk.nk_button_label(ctx, "button")
+ nk.nk_button_label(ctx, "button")
+ nk.nk_button_label(ctx, "button")
+
+ nk.nk_layout_row_dynamic(ctx, 30, 1)
+ nk.nk_label(ctx, "static fixed column layout with generated position and size:", nk.NK_TEXT_LEFT)
+ nk.nk_layout_row_static(ctx, 30, 100, 3)
+ nk.nk_button_label(ctx, "button")
+ nk.nk_button_label(ctx, "button")
+ nk.nk_button_label(ctx, "button")
+
+ nk.nk_layout_row_dynamic(ctx, 30, 1)
+ nk.nk_label(ctx, "Dynamic array-based custom column layout with generated position and custom size:",nk.NK_TEXT_LEFT)
+ nk.nk_layout_row(ctx, nk.NK_DYNAMIC, 30, 3, ratio_two)
+ nk.nk_button_label(ctx, "button")
+ nk.nk_button_label(ctx, "button")
+ nk.nk_button_label(ctx, "button")
+
+ nk.nk_layout_row_dynamic(ctx, 30, 1)
+ nk.nk_label(ctx, "Static array-based custom column layout with generated position and custom size:",nk.NK_TEXT_LEFT )
+ nk.nk_layout_row(ctx, nk.NK_STATIC, 30, 3, width_two)
+ nk.nk_button_label(ctx, "button")
+ nk.nk_button_label(ctx, "button")
+ nk.nk_button_label(ctx, "button")
+
+ nk.nk_layout_row_dynamic(ctx, 30, 1)
+ nk.nk_label(ctx, "Dynamic immediate mode custom column layout with generated position and custom size:",nk.NK_TEXT_LEFT)
+ nk.nk_layout_row_begin(ctx, nk.NK_DYNAMIC, 30, 3)
+ nk.nk_layout_row_push(ctx, 0.2)
+ nk.nk_button_label(ctx, "button")
+ nk.nk_layout_row_push(ctx, 0.6)
+ nk.nk_button_label(ctx, "button")
+ nk.nk_layout_row_push(ctx, 0.2)
+ nk.nk_button_label(ctx, "button")
+ nk.nk_layout_row_end(ctx)
+
+ nk.nk_layout_row_dynamic(ctx, 30, 1)
+ nk.nk_label(ctx, "Static immediate mode custom column layout with generated position and custom size:", nk.NK_TEXT_LEFT)
+ nk.nk_layout_row_begin(ctx, nk.NK_STATIC, 30, 3)
+ nk.nk_layout_row_push(ctx, 100)
+ nk.nk_button_label(ctx, "button")
+ nk.nk_layout_row_push(ctx, 200)
+ nk.nk_button_label(ctx, "button")
+ nk.nk_layout_row_push(ctx, 50)
+ nk.nk_button_label(ctx, "button")
+ nk.nk_layout_row_end(ctx)
+
+ nk.nk_layout_row_dynamic(ctx, 30, 1)
+ nk.nk_label(ctx, "Static free space with custom position and custom size:", nk.NK_TEXT_LEFT)
+ nk.nk_layout_space_begin(ctx, nk.NK_STATIC, 60, 4)
+ nk.nk_layout_space_push(ctx, nk.nk_rect(100, 0, 100, 30))
+ nk.nk_button_label(ctx, "button")
+ nk.nk_layout_space_push(ctx, nk.nk_rect(0, 15, 100, 30))
+ nk.nk_button_label(ctx, "button")
+ nk.nk_layout_space_push(ctx, nk.nk_rect(200, 15, 100, 30))
+ nk.nk_button_label(ctx, "button")
+ nk.nk_layout_space_push(ctx, nk.nk_rect(100, 30, 100, 30))
+ nk.nk_button_label(ctx, "button")
+ nk.nk_layout_space_end(ctx)
+
+ nk.nk_layout_row_dynamic(ctx, 30, 1)
+ nk.nk_label(ctx, "Row template:", nk.NK_TEXT_LEFT)
+ nk.nk_layout_row_template_begin(ctx, 30)
+ nk.nk_layout_row_template_push_dynamic(ctx)
+ nk.nk_layout_row_template_push_variable(ctx, 80)
+ nk.nk_layout_row_template_push_static(ctx, 80)
+ nk.nk_layout_row_template_end(ctx)
+ nk.nk_button_label(ctx, "button")
+ nk.nk_button_label(ctx, "button")
+ nk.nk_button_label(ctx, "button")
+
+ nk.nk_tree_pop(ctx)
+ end
+
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_NODE, "Group", nk.NK_MINIMIZED)) then
+
+ local group_titlebar = ffi.new("bool[1]", {nk.nk_false})
+ local group_border = ffi.new("bool[1]", {nk.nk_true})
+ local group_no_scrollbar = ffi.new("bool[1]", {nk.nk_false})
+ local group_width = ffi.new("int[1]", {320})
+ local group_height = ffi.new("int[1]", {200})
+
+ group_flags = ffi.new("nk_flags[1]", {0})
+ if (group_border) then group_flags[0] = bit.bor(group_flags[0], nk.NK_WINDOW_BORDER) end
+ if (group_no_scrollbar) then group_flags[0] = bit.bor(group_flags[0], nk.NK_WINDOW_NO_SCROLLBAR) end
+ if (group_titlebar) then group_flags[0] = bit.bor(group_flags[0], nk.NK_WINDOW_TITLE) end
+
+ nk.nk_layout_row_dynamic(ctx, 30, 3)
+ nk.nk_checkbox_label(ctx, "Titlebar", group_titlebar)
+ nk.nk_checkbox_label(ctx, "Border", group_border)
+ nk.nk_checkbox_label(ctx, "No Scrollbar", group_no_scrollbar)
+
+ nk.nk_layout_row_begin(ctx, nk.NK_STATIC, 22, 3)
+ nk.nk_layout_row_push(ctx, 50)
+ nk.nk_label(ctx, "size:", nk.NK_TEXT_LEFT)
+ nk.nk_layout_row_push(ctx, 130)
+ nk.nk_property_int(ctx, "#Width:", 100, group_width, 500, 10, 1)
+ nk.nk_layout_row_push(ctx, 130)
+ nk.nk_property_int(ctx, "#Height:", 100, group_height, 500, 10, 1)
+ nk.nk_layout_row_end(ctx)
+
+ nk.nk_layout_row_static(ctx, group_height[0], group_width[0], 2)
+ if (nk.nk_group_begin(ctx, "Group", group_flags[0])) then
+ local i = 0
+ local selected = ffi.new("int[16]")
+ nk.nk_layout_row_static(ctx, 18, 100, 1)
+ for i = 0, 16-1 do
+ local selected1 = ffi.string("Unselected")
+ if(selected[i]) then selected1 = ffi.string("Selected") end
+ nk.nk_selectable_label(ctx, selected1, nk.NK_TEXT_CENTERED, selected[i])
+ end
+ nk.nk_group_end(ctx)
+ end
+ nk.nk_tree_pop(ctx)
+ end
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_NODE, "Tree", nk.NK_MINIMIZED)) then
+
+ local root_selected = 0
+ local sel = ffi.new("bool[1]", {root_selected})
+ if (nk.nk_tree_element_push(ctx, nk.NK_TREE_NODE, "Root", nk.NK_MINIMIZED, sel)) then
+ local selected = ffi.new("int[8]")
+ local i = 0
+ local node_select = selected[0]
+ if (sel ~= root_selected) then
+ root_selected = sel
+ for i = 0, 8-1 do
+ selected[i] = sel
+ end
+ end
+ if (nk.nk_tree_element_push(ctx, nk.NK_TREE_NODE, "Node", nk.NK_MINIMIZED, node_select)) then
+ local j = 0
+ local sel_nodes = ffi.new("int[4]")
+ if (node_select ~= selected[0]) then
+ selected[0] = node_select
+ for i = 0, 4-1 do
+ sel_nodes[i] = node_select
+ end
+ end
+ nk.nk_layout_row_static(ctx, 18, 100, 1)
+ for j = 0, 4-1 do
+ local selectedj = ffi.string("Unselected")
+ if(sel_nodes[j]) then selectedj = ffi.string("Selected") end
+ nk.nk_selectable_symbol_label(ctx, nk.NK_SYMBOL_CIRCLE_SOLID, selectedj, nk.NK_TEXT_RIGHT, sel_nodes[j])
+ end
+ nk.nk_tree_element_pop(ctx)
+ end
+ nk.nk_layout_row_static(ctx, 18, 100, 1)
+ for i = 1, 8-1 do
+ local selectedi = ffi.string("Unselected")
+ if(selected[i]) then selectedi = ffi.string("Selected") end
+ nk.nk_selectable_symbol_label(ctx, nk.NK_SYMBOL_CIRCLE_SOLID, selectedi, nk.NK_TEXT_RIGHT, selected[i])
+ end
+ nk.nk_tree_element_pop(ctx)
+ end
+ nk.nk_tree_pop(ctx)
+ end
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_NODE, "Notebook", nk.NK_MINIMIZED)) then
+
+ local current_tab = 0
+ local step = (2*3.141592654) / 32
+ local chart_type = {CHART_LINE=0, CHART_HISTO=1, CHART_MIXED=2}
+ local names = ffi.new("char [3][20]", {"Lines", "Columns", "Mixed"})
+ local id = 0
+
+ -- /* Header */
+ nk.nk_style_push_vec2(ctx, ctx[0].style.window.spacing, nk.nk_vec2(0,0))
+ local rnding = ffi.new("float[1]", {ctx[0].style.button.rounding})
+ nk.nk_style_push_float(ctx, rnding, 0)
+ nk.nk_layout_row_begin(ctx, nk.NK_STATIC, 20, 3)
+ for i = 0, 3-1 do
+ -- /* make sure button perfectly fits text */
+ local f = ctx[0].style.font
+ local text_width = f.width(f.userdata, f.height, names[i], nk.nk_strlen(names[i]))
+ local widget_width = text_width + 3 * ctx[0].style.button.padding.x
+ nk.nk_layout_row_push(ctx, widget_width)
+ if (current_tab == i) then
+ -- /* active tab gets highlighted */
+ local button_color = ctx[0].style.button.normal
+ ctx[0].style.button.normal = ctx[0].style.button.active
+ if (nk.nk_button_label(ctx, names[i]) ) then current_tab = i end
+ ctx[0].style.button.normal = button_color
+ else
+ if(nk.nk_button_label(ctx, names[i])) then current_tab = i end
+ end
+ end
+ nk.nk_style_pop_float(ctx)
+
+ -- /* Body */
+ nk.nk_layout_row_dynamic(ctx, 140, 1)
+ if (nk.nk_group_begin(ctx, "Notebook", nk.NK_WINDOW_BORDER)) then
+
+ nk.nk_style_pop_vec2(ctx)
+ if(current_tab == nk.CHART_LINE) then
+ nk.nk_layout_row_dynamic(ctx, 100, 1)
+ if (nk.nk_chart_begin_colored(ctx, nk.NK_CHART_LINES, nk.nk_rgb(255,0,0), nk.nk_rgb(150,0,0), 32, 0.0, 1.0)) then
+ nk.nk_chart_add_slot_colored(ctx, nk.NK_CHART_LINES, nk.nk_rgb(0,0,255), nk.nk_rgb(0,0,150),32, -1.0, 1.0)
+ local id = 0
+ for i = 0, 32 -1 do
+ nk.nk_chart_push_slot(ctx, math.abs(sin(id)), 0)
+ nk.nk_chart_push_slot(ctx, math.cos(id), 1)
+ id = id + step
+ end
+ end
+ nk.nk_chart_end(ctx)
+ elseif(current_tab == nk.CHART_HISTO) then
+
+ nk.nk_layout_row_dynamic(ctx, 100, 1)
+ if (nk.nk_chart_begin_colored(ctx, nk.NK_CHART_COLUMN, nk.nk_rgb(255,0,0), nk.nk_rgb(150,0,0), 32, 0.0, 1.0)) then
+ local id = 0
+ for i = 0, 32-1 do
+ nk.nk_chart_push_slot(ctx, math.abs(math.sin(id)), 0)
+ id = id + step
+ end
+ end
+ nk.nk_chart_end(ctx)
+ elseif(current_tab == nk.CHART_MIXED) then
+ nk.nk_layout_row_dynamic(ctx, 100, 1)
+ if (nk.nk_chart_begin_colored(ctx, nk.NK_CHART_LINES, nk.nk_rgb(255,0,0), nk.nk_rgb(150,0,0), 32, 0.0, 1.0)) then
+ nk.nk_chart_add_slot_colored(ctx, nk.NK_CHART_LINES, nk.nk_rgb(0,0,255), nk.nk_rgb(0,0,150),32, -1.0, 1.0)
+ nk.nk_chart_add_slot_colored(ctx, nk.NK_CHART_COLUMN, nk.nk_rgb(0,255,0), nk.nk_rgb(0,150,0), 32, 0.0, 1.0)
+ local id = 0
+ for i = 0, 32-1 do
+ nk.nk_chart_push_slot(ctx, math.abs(math.sin(id)), 0)
+ nk.nk_chart_push_slot(ctx, math.abs(math.cos(id)), 1)
+ nk.nk_chart_push_slot(ctx, math.abs(math.sin(id)), 2)
+ id = id + step
+ end
+ end
+ nk.nk_chart_end(ctx)
+ end
+ nk.nk_group_end(ctx)
+ else
+ nk.nk_style_pop_vec2(ctx)
+ end
+ nk.nk_tree_pop(ctx)
+ end
+
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_NODE, "Simple", nk.NK_MINIMIZED)) then
+
+ nk.nk_layout_row_dynamic(ctx, 300, 2)
+ if (nk.nk_group_begin(ctx, "Group_Without_Border", 0)) then
+ local i = 0
+ nk.nk_layout_row_static(ctx, 18, 150, 1)
+ for i = 0, 64-1 do
+ local buffer = ffi.string( "0x"..i )
+ nk.nk_labelf(ctx, nk.NK_TEXT_LEFT, "%s: scrollable region", buffer)
+ end
+ nk.nk_group_end(ctx)
+ end
+ if (nk.nk_group_begin(ctx, "Group_With_Border", nk.NK_WINDOW_BORDER)) then
+ local i = 0
+ nk.nk_layout_row_dynamic(ctx, 25, 2)
+ for i = 0, 64-1 do
+ local buffer = ffi.string(""..((((i%7)*10)^32))+(64+(i%2)*2))
+ nk.nk_button_label(ctx, buffer)
+ end
+ nk.nk_group_end(ctx)
+ end
+ nk.nk_tree_pop(ctx)
+ end
+
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_NODE, "Complex", nk.NK_MINIMIZED)) then
+
+ nk.nk_layout_space_begin(ctx, nk.NK_STATIC, 500, 64)
+ nk.nk_layout_space_push(ctx, nk.nk_rect(0,0,150,500))
+ if (nk.nk_group_begin(ctx, "Group_left", nk.NK_WINDOW_BORDER)) then
+ local selected = ffi.new("int[32]")
+ nk.nk_layout_row_static(ctx, 18, 100, 1)
+ for i = 0, 32-1 do
+ local selectedi = ffi.string("Unselected")
+ if(selected[i]) then selectedi = "Selected" end
+ nk.nk_selectable_label(ctx, selectedi, nk.NK_TEXT_CENTERED, selected[i])
+ end
+ nk.nk_group_end(ctx)
+ end
+
+ nk.nk_layout_space_push(ctx, nk.nk_rect(160,0,150,240))
+ if (nk.nk_group_begin(ctx, "Group_top", nk.NK_WINDOW_BORDER)) then
+ nk.nk_layout_row_dynamic(ctx, 25, 1)
+ nk.nk_button_label(ctx, "#FFAA")
+ nk.nk_button_label(ctx, "#FFBB")
+ nk.nk_button_label(ctx, "#FFCC")
+ nk.nk_button_label(ctx, "#FFDD")
+ nk.nk_button_label(ctx, "#FFEE")
+ nk.nk_button_label(ctx, "#FFFF")
+ nk.nk_group_end(ctx)
+ end
+
+ nk.nk_layout_space_push(ctx, nk.nk_rect(160,250,150,250))
+ if (nk.nk_group_begin(ctx, "Group_buttom", nk.NK_WINDOW_BORDER)) then
+ nk.nk_layout_row_dynamic(ctx, 25, 1)
+ nk.nk_button_label(ctx, "#FFAA")
+ nk.nk_button_label(ctx, "#FFBB")
+ nk.nk_button_label(ctx, "#FFCC")
+ nk.nk_button_label(ctx, "#FFDD")
+ nk.nk_button_label(ctx, "#FFEE")
+ nk.nk_button_label(ctx, "#FFFF")
+ nk.nk_group_end(ctx)
+ end
+
+ nk.nk_layout_space_push(ctx, nk.nk_rect(320,0,150,150))
+ if (nk.nk_group_begin(ctx, "Group_right_top", nk.NK_WINDOW_BORDER)) then
+ local selected = ffi.new("int[4]")
+ nk.nk_layout_row_static(ctx, 18, 100, 1)
+ for i = 0, 4-1 do
+ local selectedi = ffi.string("Unselected")
+ if(selected[i]) then selectedi = ffi.string("Selected") end
+ nk.nk_selectable_label(ctx, selectedi, nk.NK_TEXT_CENTERED, selected[i])
+ end
+ nk.nk_group_end(ctx)
+ end
+
+ nk.nk_layout_space_push(ctx, nk.nk_rect(320,160,150,150))
+ if (nk.nk_group_begin(ctx, "Group_right_center", nk.NK_WINDOW_BORDER)) then
+ local selected = ffi.new("int[4]")
+ nk.nk_layout_row_static(ctx, 18, 100, 1)
+ for i = 0, 4-1 do
+ local selectedi = ffi.string("Unselected")
+ if(selected[i]) then selectedi = ffi.string("Selected") end
+ nk.nk_selectable_label(ctx, selectedi, nk.NK_TEXT_CENTERED, selected[i])
+ end
+ nk.nk_group_end(ctx)
+ end
+
+ nk.nk_layout_space_push(ctx, nk.nk_rect(320,320,150,150))
+ if (nk.nk_group_begin(ctx, "Group_right_bottom", nk.NK_WINDOW_BORDER)) then
+ local selected = ffi.new("int[4]")
+ nk.nk_layout_row_static(ctx, 18, 100, 1)
+ for i = 0, 4-1 do
+ local selectedi = ffi.string("Unselected")
+ nk.nk_selectable_label(ctx, selectedi, nk.NK_TEXT_CENTERED, selected[i])
+ end
+ nk.nk_group_end(ctx)
+ end
+ nk.nk_layout_space_end(ctx)
+ nk.nk_tree_pop(ctx)
+ end
+
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_NODE, "Splitter", nk.NK_MINIMIZED)) then
+
+ inp = ctx[0].input
+ nk.nk_layout_row_static(ctx, 20, 320, 1)
+ nk.nk_label(ctx, "Use slider and spinner to change tile size", nk.NK_TEXT_LEFT)
+ nk.nk_label(ctx, "Drag the space between tiles to change tile ratio", nk.NK_TEXT_LEFT)
+
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_NODE, "Vertical", nk.NK_MINIMIZED)) then
+
+ local a = ffi.new("float[1]", {100})
+ local b = ffi.new("float[1]", {100})
+ local c = ffi.new("float[1]", {100})
+ bounds = ffi.new("struct nk_rect[1]")
+
+ row_layout = ffi.new("float[5]")
+ row_layout[0] = a[0]
+ row_layout[1] = 8
+ row_layout[2] = b[0]
+ row_layout[3] = 8
+ row_layout[4] = c[0]
+
+ -- /* header */
+ nk.nk_layout_row_static(ctx, 30, 100, 2)
+ nk.nk_label(ctx, "left:", nk.NK_TEXT_LEFT)
+ nk.nk_slider_float(ctx, 10.0, a, 200.0, 10.0)
+
+ nk.nk_label(ctx, "middle:", nk.NK_TEXT_LEFT)
+ nk.nk_slider_float(ctx, 10.0, b, 200.0, 10.0)
+
+ nk.nk_label(ctx, "right:", nk.NK_TEXT_LEFT)
+ nk.nk_slider_float(ctx, 10.0, c, 200.0, 10.0)
+
+ -- /* tiles */
+ nk.nk_layout_row(ctx, nk.NK_STATIC, 200, 5, row_layout)
+
+ -- /* left space */
+ local winbit = bit.band(nk.NK_WINDOW_NO_SCROLLBAR, nk.NK_WINDOW_BORDER)
+ winbit = bit.band(winbit, nk.NK_WINDOW_NO_SCROLLBAR)
+ if (nk.nk_group_begin(ctx, "left", winbit)) then
+ nk.nk_layout_row_dynamic(ctx, 25, 1)
+ nk.nk_button_label(ctx, "#FFAA")
+ nk.nk_button_label(ctx, "#FFBB")
+ nk.nk_button_label(ctx, "#FFCC")
+ nk.nk_button_label(ctx, "#FFDD")
+ nk.nk_button_label(ctx, "#FFEE")
+ nk.nk_button_label(ctx, "#FFFF")
+ nk.nk_group_end(ctx)
+ end
+
+ -- /* scaler */
+ bounds = nk.nk_widget_bounds(ctx)
+ nk.nk_spacing(ctx, 1)
+ if ((nk.nk_input_is_mouse_hovering_rect(inp, bounds) or
+ nk.nk_input_is_mouse_prev_hovering_rect(inp, bounds)) and
+ nk.nk_input_is_mouse_down(inp, nk.NK_BUTTON_LEFT)) then
+
+ a[0] = row_layout[0] + inp.mouse.delta.x
+ b[0] = row_layout[2] - inp.mouse.delta.x
+ end
+
+ -- /* middle space */
+ if (nk.nk_group_begin(ctx, "center", bit.bor(nk.NK_WINDOW_BORDER, nk.NK_WINDOW_NO_SCROLLBAR))) then
+ nk.nk_layout_row_dynamic(ctx, 25, 1)
+ nk.nk_button_label(ctx, "#FFAA")
+ nk.nk_button_label(ctx, "#FFBB")
+ nk.nk_button_label(ctx, "#FFCC")
+ nk.nk_button_label(ctx, "#FFDD")
+ nk.nk_button_label(ctx, "#FFEE")
+ nk.nk_button_label(ctx, "#FFFF")
+ nk.nk_group_end(ctx)
+ end
+
+ -- /* scaler */
+ bounds = nk.nk_widget_bounds(ctx)
+ nk.nk_spacing(ctx, 1)
+ if ((nk.nk_input_is_mouse_hovering_rect(inp, bounds) or
+ nk.nk_input_is_mouse_prev_hovering_rect(inp, bounds)) and
+ nk.nk_input_is_mouse_down(inp, nk.NK_BUTTON_LEFT)) then
+
+ b[0] = (row_layout[2] + inp.mouse.delta.x)
+ c[0] = (row_layout[4] - inp.mouse.delta.x)
+ end
+
+ -- /* right space */
+ if (nk.nk_group_begin(ctx, "right", bit.bor(nk.NK_WINDOW_BORDER,nk.NK_WINDOW_NO_SCROLLBAR))) then
+ nk.nk_layout_row_dynamic(ctx, 25, 1)
+ nk.nk_button_label(ctx, "#FFAA")
+ nk.nk_button_label(ctx, "#FFBB")
+ nk.nk_button_label(ctx, "#FFCC")
+ nk.nk_button_label(ctx, "#FFDD")
+ nk.nk_button_label(ctx, "#FFEE")
+ nk.nk_button_label(ctx, "#FFFF")
+ nk.nk_group_end(ctx)
+ end
+
+ nk.nk_tree_pop(ctx)
+ end
+
+ if (nk.nk_tree_push(ctx, nk.NK_TREE_NODE, "Horizontal", nk.NK_MINIMIZED)) then
+
+ local a = ffi.new("float[1]", {100})
+ local b = ffi.new("float[1]", {100})
+ local c = ffi.new("float[1]", {100})
+ bounds = ffi.new("struct nk_rect[1]")
+
+ -- /* header */
+ nk.nk_layout_row_static(ctx, 30, 100, 2)
+ nk.nk_label(ctx, "top:", nk.NK_TEXT_LEFT)
+ nk.nk_slider_float(ctx, 10.0, a, 200.0, 10.0)
+
+ nk.nk_label(ctx, "middle:", nk.NK_TEXT_LEFT)
+ nk.nk_slider_float(ctx, 10.0, b, 200.0, 10.0)
+
+ nk.nk_label(ctx, "bottom:", nk.NK_TEXT_LEFT)
+ nk.nk_slider_float(ctx, 10.0, c, 200.0, 10.0)
+
+ -- /* top space */
+ nk.nk_layout_row_dynamic(ctx, a[0], 1)
+ if (nk.nk_group_begin(ctx, "top", bit.bor(nk.NK_WINDOW_NO_SCROLLBAR,nk.NK_WINDOW_BORDER))) then
+ nk.nk_layout_row_dynamic(ctx, 25, 3)
+ nk.nk_button_label(ctx, "#FFAA")
+ nk.nk_button_label(ctx, "#FFBB")
+ nk.nk_button_label(ctx, "#FFCC")
+ nk.nk_button_label(ctx, "#FFDD")
+ nk.nk_button_label(ctx, "#FFEE")
+ nk.nk_button_label(ctx, "#FFFF")
+ nk.nk_group_end(ctx)
+ end
+
+ -- /* scaler */
+ nk.nk_layout_row_dynamic(ctx, 8, 1)
+ bounds = nk.nk_widget_bounds(ctx)
+ nk.nk_spacing(ctx, 1)
+ if ((nk.nk_input_is_mouse_hovering_rect(inp, bounds) or
+ nk.nk_input_is_mouse_prev_hovering_rect(inp, bounds)) and
+ nk.nk_input_is_mouse_down(inp, nk.NK_BUTTON_LEFT)) then
+
+ a = a + inp.mouse.delta.y
+ b = b - inp.mouse.delta.y
+ end
+
+ -- /* middle space */
+ nk.nk_layout_row_dynamic(ctx, b[0], 1)
+ if (nk.nk_group_begin(ctx, "middle", bit.bor(nk.NK_WINDOW_NO_SCROLLBAR,nk.NK_WINDOW_BORDER))) then
+ nk.nk_layout_row_dynamic(ctx, 25, 3)
+ nk.nk_button_label(ctx, "#FFAA")
+ nk.nk_button_label(ctx, "#FFBB")
+ nk.nk_button_label(ctx, "#FFCC")
+ nk.nk_button_label(ctx, "#FFDD")
+ nk.nk_button_label(ctx, "#FFEE")
+ nk.nk_button_label(ctx, "#FFFF")
+ nk.nk_group_end(ctx)
+ end
+
+ do
+ -- /* scaler */
+ nk.nk_layout_row_dynamic(ctx, 8, 1)
+ bounds = nk.nk_widget_bounds(ctx)
+ if ((nk.nk_input_is_mouse_hovering_rect(inp, bounds) or
+ nk.nk_input_is_mouse_prev_hovering_rect(inp, bounds)) and
+ nk.nk_input_is_mouse_down(inp, nk.NK_BUTTON_LEFT)) then
+
+ b = b + inp.mouse.delta.y
+ c = c - inp.mouse.delta.y
+ end
+ end
+
+ -- /* bottom space */
+ nk.nk_layout_row_dynamic(ctx, c[0], 1)
+ if (nk.nk_group_begin(ctx, "bottom", bit.bor(nk.NK_WINDOW_NO_SCROLLBAR,nk.NK_WINDOW_BORDER))) then
+ nk.nk_layout_row_dynamic(ctx, 25, 3)
+ nk.nk_button_label(ctx, "#FFAA")
+ nk.nk_button_label(ctx, "#FFBB")
+ nk.nk_button_label(ctx, "#FFCC")
+ nk.nk_button_label(ctx, "#FFDD")
+ nk.nk_button_label(ctx, "#FFEE")
+ nk.nk_button_label(ctx, "#FFFF")
+ nk.nk_group_end(ctx)
+ end
+ nk.nk_tree_pop(ctx)
+ end
+ nk.nk_tree_pop(ctx)
+ end
+ nk.nk_tree_pop(ctx)
+ end
+ end
+ nk.nk_end(ctx)
+ return not nk.nk_window_is_closed(ctx, "Overview")
+end
+
+-- --------------------------------------------------------------------------------------
+
+local function frame(void)
+
+ local ctx = nk.snk_new_frame()
+ -- // see big function at end of file
+ draw_demo_ui(ctx)
+
+ -- // the sokol_gfx draw pass
+ local pass = ffi.new("sg_pass[1]")
+ pass[0].action.colors[0].load_action = sg.SG_LOADACTION_CLEAR
+ pass[0].action.colors[0].clear_value = { 0.25, 0.5, 0.7, 1.0 }
+ pass[0].swapchain = slib.sglue_swapchain()
+ sg.sg_begin_pass(pass)
+
+ nk.snk_render(sapp.sapp_width(), sapp.sapp_height())
+ sg.sg_end_pass()
+ sg.sg_commit()
+
+ nk.nk_clear(ctx)
+end
+
+-- --------------------------------------------------------------------------------------
+
+local app_desc = ffi.new("sapp_desc[1]")
+app_desc[0].init_cb = init
+app_desc[0].frame_cb = frame
+app_desc[0].cleanup_cb = cleanup
+app_desc[0].event_cb = input
+app_desc[0].width = 1920
+app_desc[0].height = 1080
+app_desc[0].window_title = "nuklear (sokol-app)"
+app_desc[0].icon.sokol_default = true
+app_desc[0].logger.func = slib.slog_func
+app_desc[0].enable_clipboard = true
+app_desc[0].ios_keyboard_resizes_canvas = false
+
+sapp.sapp_run( app_desc )
+
+-- --------------------------------------------------------------------------------------
diff --git a/ffi/sokol/hmm_utils.lua b/ffi/sokol/hmm_utils.lua
index c185538..6ecf74b 100644
--- a/ffi/sokol/hmm_utils.lua
+++ b/ffi/sokol/hmm_utils.lua
@@ -1,4 +1,4 @@
-local sg = _G.sg
+local sg = _G.sg or require("sokol_gfx")
local hmm_utils = {}
diff --git a/ffi/sokol/sokol_nuklear.lua b/ffi/sokol/sokol_nuklear.lua
new file mode 100644
index 0000000..3d6c200
--- /dev/null
+++ b/ffi/sokol/sokol_nuklear.lua
@@ -0,0 +1,7694 @@
+local ffi = require( "ffi" )
+
+local sokol_filename = _G.SOKOL_DLL or "sokol_nuklear_dll"
+local libs = ffi_sokol_nuklear or {
+ OSX = { x64 = sokol_filename..".so" },
+ Windows = { x64 = sokol_filename..".dll" },
+ Linux = { x64 = sokol_filename..".so", arm = sokol_filename..".so" },
+ BSD = { x64 = sokol_filename..".so" },
+ POSIX = { x64 = sokol_filename..".so" },
+ Other = { x64 = sokol_filename..".so" },
+}
+
+local lib = ffi_sokol_nuklear or libs[ ffi.os ][ ffi.arch ]
+local sokol_nuklear = ffi.load( lib )
+
+ffi.cdef[[
+
+/*
+ Resource id typedefs:
+
+ sg_buffer: vertex- and index-buffers
+ sg_image: images used as textures and render targets
+ sg_sampler sampler object describing how a texture is sampled in a shader
+ sg_shader: vertex- and fragment-shaders and shader interface information
+ sg_pipeline: associated shader and vertex-layouts, and render states
+ sg_attachments: a baked collection of render pass attachment images
+
+ Instead of pointers, resource creation functions return a 32-bit
+ number which uniquely identifies the resource object.
+
+ The 32-bit resource id is split into a 16-bit pool index in the lower bits,
+ and a 16-bit 'generation counter' in the upper bits. The index allows fast
+ pool lookups, and combined with the generation-counter it allows to detect
+ 'dangling accesses' (trying to use an object which no longer exists, and
+ its pool slot has been reused for a new object)
+
+ The resource ids are wrapped into a strongly-typed struct so that
+ trying to pass an incompatible resource id is a compile error.
+*/
+typedef struct sg_buffer { uint32_t id; } sg_buffer;
+typedef struct sg_image { uint32_t id; } sg_image;
+typedef struct sg_sampler { uint32_t id; } sg_sampler;
+typedef struct sg_shader { uint32_t id; } sg_shader;
+typedef struct sg_pipeline { uint32_t id; } sg_pipeline;
+typedef struct sg_attachments { uint32_t id; } sg_attachments;
+
+/*
+ sg_range is a pointer-size-pair struct used to pass memory blobs into
+ sokol-gfx. When initialized from a value type (array or struct), you can
+ use the SG_RANGE() macro to build an sg_range struct. For functions which
+ take either a sg_range pointer, or a (C++) sg_range reference, use the
+ SG_RANGE_REF macro as a solution which compiles both in C and C++.
+*/
+typedef struct sg_range {
+ const void* ptr;
+ size_t size;
+} sg_range;
+
+// various compile-time constants
+enum {
+ SG_INVALID_ID = 0,
+ SG_NUM_SHADER_STAGES = 2,
+ SG_NUM_INFLIGHT_FRAMES = 2,
+ SG_MAX_COLOR_ATTACHMENTS = 4,
+ SG_MAX_VERTEX_BUFFERS = 8,
+ SG_MAX_SHADERSTAGE_IMAGES = 12,
+ SG_MAX_SHADERSTAGE_SAMPLERS = 8,
+ SG_MAX_SHADERSTAGE_IMAGESAMPLERPAIRS = 12,
+ SG_MAX_SHADERSTAGE_STORAGEBUFFERS = 8,
+ SG_MAX_SHADERSTAGE_UBS = 4,
+ SG_MAX_UB_MEMBERS = 16,
+ SG_MAX_VERTEX_ATTRIBUTES = 16,
+ SG_MAX_MIPMAPS = 16,
+ SG_MAX_TEXTUREARRAY_LAYERS = 128
+};
+
+/*
+ sg_color
+
+ An RGBA color value.
+*/
+typedef struct sg_color { float r, g, b, a; } sg_color;
+
+/*
+ sg_backend
+
+ The active 3D-API backend, use the function sg_query_backend()
+ to get the currently active backend.
+*/
+typedef enum sg_backend {
+ SG_BACKEND_GLCORE,
+ SG_BACKEND_GLES3,
+ SG_BACKEND_D3D11,
+ SG_BACKEND_METAL_IOS,
+ SG_BACKEND_METAL_MACOS,
+ SG_BACKEND_METAL_SIMULATOR,
+ SG_BACKEND_WGPU,
+ SG_BACKEND_DUMMY,
+} sg_backend;
+
+/*
+ sg_pixel_format
+
+ sokol_gfx.h basically uses the same pixel formats as WebGPU, since these
+ are supported on most newer GPUs.
+
+ A pixelformat name consist of three parts:
+
+ - components (R, RG, RGB or RGBA)
+ - bit width per component (8, 16 or 32)
+ - component data type:
+ - unsigned normalized (no postfix)
+ - signed normalized (SN postfix)
+ - unsigned integer (UI postfix)
+ - signed integer (SI postfix)
+ - float (F postfix)
+
+ Not all pixel formats can be used for everything, call sg_query_pixelformat()
+ to inspect the capabilities of a given pixelformat. The function returns
+ an sg_pixelformat_info struct with the following members:
+
+ - sample: the pixelformat can be sampled as texture at least with
+ nearest filtering
+ - filter: the pixelformat can be samples as texture with linear
+ filtering
+ - render: the pixelformat can be used for render targets
+ - blend: blending is supported when using the pixelformat for
+ render targets
+ - msaa: multisample-antialiasing is supported when using the
+ pixelformat for render targets
+ - depth: the pixelformat can be used for depth-stencil attachments
+ - compressed: this is a block-compressed format
+ - bytes_per_pixel: the numbers of bytes in a pixel (0 for compressed formats)
+
+ The default pixel format for texture images is SG_PIXELFORMAT_RGBA8.
+
+ The default pixel format for render target images is platform-dependent
+ and taken from the sg_environment struct passed into sg_setup(). Typically
+ the default formats are:
+
+ - for the Metal, D3D11 and WebGPU backends: SG_PIXELFORMAT_BGRA8
+ - for GL backends: SG_PIXELFORMAT_RGBA8
+*/
+typedef enum sg_pixel_format {
+ _SG_PIXELFORMAT_DEFAULT, // value 0 reserved for default-init
+ SG_PIXELFORMAT_NONE,
+
+ SG_PIXELFORMAT_R8,
+ SG_PIXELFORMAT_R8SN,
+ SG_PIXELFORMAT_R8UI,
+ SG_PIXELFORMAT_R8SI,
+
+ SG_PIXELFORMAT_R16,
+ SG_PIXELFORMAT_R16SN,
+ SG_PIXELFORMAT_R16UI,
+ SG_PIXELFORMAT_R16SI,
+ SG_PIXELFORMAT_R16F,
+ SG_PIXELFORMAT_RG8,
+ SG_PIXELFORMAT_RG8SN,
+ SG_PIXELFORMAT_RG8UI,
+ SG_PIXELFORMAT_RG8SI,
+
+ SG_PIXELFORMAT_R32UI,
+ SG_PIXELFORMAT_R32SI,
+ SG_PIXELFORMAT_R32F,
+ SG_PIXELFORMAT_RG16,
+ SG_PIXELFORMAT_RG16SN,
+ SG_PIXELFORMAT_RG16UI,
+ SG_PIXELFORMAT_RG16SI,
+ SG_PIXELFORMAT_RG16F,
+ SG_PIXELFORMAT_RGBA8,
+ SG_PIXELFORMAT_SRGB8A8,
+ SG_PIXELFORMAT_RGBA8SN,
+ SG_PIXELFORMAT_RGBA8UI,
+ SG_PIXELFORMAT_RGBA8SI,
+ SG_PIXELFORMAT_BGRA8,
+ SG_PIXELFORMAT_RGB10A2,
+ SG_PIXELFORMAT_RG11B10F,
+ SG_PIXELFORMAT_RGB9E5,
+
+ SG_PIXELFORMAT_RG32UI,
+ SG_PIXELFORMAT_RG32SI,
+ SG_PIXELFORMAT_RG32F,
+ SG_PIXELFORMAT_RGBA16,
+ SG_PIXELFORMAT_RGBA16SN,
+ SG_PIXELFORMAT_RGBA16UI,
+ SG_PIXELFORMAT_RGBA16SI,
+ SG_PIXELFORMAT_RGBA16F,
+
+ SG_PIXELFORMAT_RGBA32UI,
+ SG_PIXELFORMAT_RGBA32SI,
+ SG_PIXELFORMAT_RGBA32F,
+
+ // NOTE: when adding/removing pixel formats before DEPTH, also update sokol_app.h/_SAPP_PIXELFORMAT_*
+ SG_PIXELFORMAT_DEPTH,
+ SG_PIXELFORMAT_DEPTH_STENCIL,
+
+ // NOTE: don't put any new compressed format in front of here
+ SG_PIXELFORMAT_BC1_RGBA,
+ SG_PIXELFORMAT_BC2_RGBA,
+ SG_PIXELFORMAT_BC3_RGBA,
+ SG_PIXELFORMAT_BC3_SRGBA,
+ SG_PIXELFORMAT_BC4_R,
+ SG_PIXELFORMAT_BC4_RSN,
+ SG_PIXELFORMAT_BC5_RG,
+ SG_PIXELFORMAT_BC5_RGSN,
+ SG_PIXELFORMAT_BC6H_RGBF,
+ SG_PIXELFORMAT_BC6H_RGBUF,
+ SG_PIXELFORMAT_BC7_RGBA,
+ SG_PIXELFORMAT_BC7_SRGBA,
+ SG_PIXELFORMAT_PVRTC_RGB_2BPP, // FIXME: deprecated
+ SG_PIXELFORMAT_PVRTC_RGB_4BPP, // FIXME: deprecated
+ SG_PIXELFORMAT_PVRTC_RGBA_2BPP, // FIXME: deprecated
+ SG_PIXELFORMAT_PVRTC_RGBA_4BPP, // FIXME: deprecated
+ SG_PIXELFORMAT_ETC2_RGB8,
+ SG_PIXELFORMAT_ETC2_SRGB8,
+ SG_PIXELFORMAT_ETC2_RGB8A1,
+ SG_PIXELFORMAT_ETC2_RGBA8,
+ SG_PIXELFORMAT_ETC2_SRGB8A8,
+ SG_PIXELFORMAT_EAC_R11,
+ SG_PIXELFORMAT_EAC_R11SN,
+ SG_PIXELFORMAT_EAC_RG11,
+ SG_PIXELFORMAT_EAC_RG11SN,
+
+ SG_PIXELFORMAT_ASTC_4x4_RGBA,
+ SG_PIXELFORMAT_ASTC_4x4_SRGBA,
+
+ _SG_PIXELFORMAT_NUM,
+ _SG_PIXELFORMAT_FORCE_U32 = 0x7FFFFFFF
+} sg_pixel_format;
+
+/*
+ Runtime information about a pixel format, returned
+ by sg_query_pixelformat().
+*/
+typedef struct sg_pixelformat_info {
+ bool sample; // pixel format can be sampled in shaders at least with nearest filtering
+ bool filter; // pixel format can be sampled with linear filtering
+ bool render; // pixel format can be used as render target
+ bool blend; // alpha-blending is supported
+ bool msaa; // pixel format can be used as MSAA render target
+ bool depth; // pixel format is a depth format
+ bool compressed; // true if this is a hardware-compressed format
+ int bytes_per_pixel; // NOTE: this is 0 for compressed formats, use sg_query_row_pitch() / sg_query_surface_pitch() as alternative
+} sg_pixelformat_info;
+
+/*
+ Runtime information about available optional features,
+ returned by sg_query_features()
+*/
+typedef struct sg_features {
+ bool origin_top_left; // framebuffer and texture origin is in top left corner
+ bool image_clamp_to_border; // border color and clamp-to-border UV-wrap mode is supported
+ bool mrt_independent_blend_state; // multiple-render-target rendering can use per-render-target blend state
+ bool mrt_independent_write_mask; // multiple-render-target rendering can use per-render-target color write masks
+ bool storage_buffer; // storage buffers are supported
+} sg_features;
+
+/*
+ Runtime information about resource limits, returned by sg_query_limit()
+*/
+typedef struct sg_limits {
+ int max_image_size_2d; // max width/height of SG_IMAGETYPE_2D images
+ int max_image_size_cube; // max width/height of SG_IMAGETYPE_CUBE images
+ int max_image_size_3d; // max width/height/depth of SG_IMAGETYPE_3D images
+ int max_image_size_array; // max width/height of SG_IMAGETYPE_ARRAY images
+ int max_image_array_layers; // max number of layers in SG_IMAGETYPE_ARRAY images
+ int max_vertex_attrs; // max number of vertex attributes, clamped to SG_MAX_VERTEX_ATTRIBUTES
+ int gl_max_vertex_uniform_components; // <= GL_MAX_VERTEX_UNIFORM_COMPONENTS (only on GL backends)
+ int gl_max_combined_texture_image_units; // <= GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (only on GL backends)
+} sg_limits;
+
+/*
+ sg_resource_state
+
+ The current state of a resource in its resource pool.
+ Resources start in the INITIAL state, which means the
+ pool slot is unoccupied and can be allocated. When a resource is
+ created, first an id is allocated, and the resource pool slot
+ is set to state ALLOC. After allocation, the resource is
+ initialized, which may result in the VALID or FAILED state. The
+ reason why allocation and initialization are separate is because
+ some resource types (e.g. buffers and images) might be asynchronously
+ initialized by the user application. If a resource which is not
+ in the VALID state is attempted to be used for rendering, rendering
+ operations will silently be dropped.
+
+ The special INVALID state is returned in sg_query_xxx_state() if no
+ resource object exists for the provided resource id.
+*/
+typedef enum sg_resource_state {
+ SG_RESOURCESTATE_INITIAL,
+ SG_RESOURCESTATE_ALLOC,
+ SG_RESOURCESTATE_VALID,
+ SG_RESOURCESTATE_FAILED,
+ SG_RESOURCESTATE_INVALID,
+ _SG_RESOURCESTATE_FORCE_U32 = 0x7FFFFFFF
+} sg_resource_state;
+
+/*
+ sg_usage
+
+ A resource usage hint describing the update strategy of
+ buffers and images. This is used in the sg_buffer_desc.usage
+ and sg_image_desc.usage members when creating buffers
+ and images:
+
+ SG_USAGE_IMMUTABLE: the resource will never be updated with
+ new data, instead the content of the
+ resource must be provided on creation
+ SG_USAGE_DYNAMIC: the resource will be updated infrequently
+ with new data (this could range from "once
+ after creation", to "quite often but not
+ every frame")
+ SG_USAGE_STREAM: the resource will be updated each frame
+ with new content
+
+ The rendering backends use this hint to prevent that the
+ CPU needs to wait for the GPU when attempting to update
+ a resource that might be currently accessed by the GPU.
+
+ Resource content is updated with the functions sg_update_buffer() or
+ sg_append_buffer() for buffer objects, and sg_update_image() for image
+ objects. For the sg_update_*() functions, only one update is allowed per
+ frame and resource object, while sg_append_buffer() can be called
+ multiple times per frame on the same buffer. The application must update
+ all data required for rendering (this means that the update data can be
+ smaller than the resource size, if only a part of the overall resource
+ size is used for rendering, you only need to make sure that the data that
+ *is* used is valid).
+
+ The default usage is SG_USAGE_IMMUTABLE.
+*/
+typedef enum sg_usage {
+ _SG_USAGE_DEFAULT, // value 0 reserved for default-init
+ SG_USAGE_IMMUTABLE,
+ SG_USAGE_DYNAMIC,
+ SG_USAGE_STREAM,
+ _SG_USAGE_NUM,
+ _SG_USAGE_FORCE_U32 = 0x7FFFFFFF
+} sg_usage;
+
+/*
+ sg_buffer_type
+
+ Indicates whether a buffer will be bound as vertex-,
+ index- or storage-buffer.
+
+ Used in the sg_buffer_desc.type member when creating a buffer.
+
+ The default value is SG_BUFFERTYPE_VERTEXBUFFER.
+*/
+typedef enum sg_buffer_type {
+ _SG_BUFFERTYPE_DEFAULT, // value 0 reserved for default-init
+ SG_BUFFERTYPE_VERTEXBUFFER,
+ SG_BUFFERTYPE_INDEXBUFFER,
+ SG_BUFFERTYPE_STORAGEBUFFER,
+ _SG_BUFFERTYPE_NUM,
+ _SG_BUFFERTYPE_FORCE_U32 = 0x7FFFFFFF
+} sg_buffer_type;
+
+/*
+ sg_index_type
+
+ Indicates whether indexed rendering (fetching vertex-indices from an
+ index buffer) is used, and if yes, the index data type (16- or 32-bits).
+ This is used in the sg_pipeline_desc.index_type member when creating a
+ pipeline object.
+
+ The default index type is SG_INDEXTYPE_NONE.
+*/
+typedef enum sg_index_type {
+ _SG_INDEXTYPE_DEFAULT, // value 0 reserved for default-init
+ SG_INDEXTYPE_NONE,
+ SG_INDEXTYPE_UINT16,
+ SG_INDEXTYPE_UINT32,
+ _SG_INDEXTYPE_NUM,
+ _SG_INDEXTYPE_FORCE_U32 = 0x7FFFFFFF
+} sg_index_type;
+
+/*
+ sg_image_type
+
+ Indicates the basic type of an image object (2D-texture, cubemap,
+ 3D-texture or 2D-array-texture). Used in the sg_image_desc.type member when
+ creating an image, and in sg_shader_image_desc to describe a sampled texture
+ in the shader (both must match and will be checked in the validation layer
+ when calling sg_apply_bindings).
+
+ The default image type when creating an image is SG_IMAGETYPE_2D.
+*/
+typedef enum sg_image_type {
+ _SG_IMAGETYPE_DEFAULT, // value 0 reserved for default-init
+ SG_IMAGETYPE_2D,
+ SG_IMAGETYPE_CUBE,
+ SG_IMAGETYPE_3D,
+ SG_IMAGETYPE_ARRAY,
+ _SG_IMAGETYPE_NUM,
+ _SG_IMAGETYPE_FORCE_U32 = 0x7FFFFFFF
+} sg_image_type;
+
+/*
+ sg_image_sample_type
+
+ The basic data type of a texture sample as expected by a shader.
+ Must be provided in sg_shader_image_desc and used by the validation
+ layer in sg_apply_bindings() to check if the provided image object
+ is compatible with what the shader expects. Apart from the sokol-gfx
+ validation layer, WebGPU is the only backend API which actually requires
+ matching texture and sampler type to be provided upfront for validation
+ (other 3D APIs treat texture/sampler type mismatches as undefined behaviour).
+
+ NOTE that the following texture pixel formats require the use
+ of SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT, combined with a sampler
+ of type SG_SAMPLERTYPE_NONFILTERING:
+
+ - SG_PIXELFORMAT_R32F
+ - SG_PIXELFORMAT_RG32F
+ - SG_PIXELFORMAT_RGBA32F
+
+ (when using sokol-shdc, also check out the meta tags `@image_sample_type`
+ and `@sampler_type`)
+*/
+typedef enum sg_image_sample_type {
+ _SG_IMAGESAMPLETYPE_DEFAULT, // value 0 reserved for default-init
+ SG_IMAGESAMPLETYPE_FLOAT,
+ SG_IMAGESAMPLETYPE_DEPTH,
+ SG_IMAGESAMPLETYPE_SINT,
+ SG_IMAGESAMPLETYPE_UINT,
+ SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT,
+ _SG_IMAGESAMPLETYPE_NUM,
+ _SG_IMAGESAMPLETYPE_FORCE_U32 = 0x7FFFFFFF
+} sg_image_sample_type;
+
+/*
+ sg_sampler_type
+
+ The basic type of a texture sampler (sampling vs comparison) as
+ defined in a shader. Must be provided in sg_shader_sampler_desc.
+
+ sg_image_sample_type and sg_sampler_type for a texture/sampler
+ pair must be compatible with each other, specifically only
+ the following pairs are allowed:
+
+ - SG_IMAGESAMPLETYPE_FLOAT => (SG_SAMPLERTYPE_FILTERING or SG_SAMPLERTYPE_NONFILTERING)
+ - SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT => SG_SAMPLERTYPE_NONFILTERING
+ - SG_IMAGESAMPLETYPE_SINT => SG_SAMPLERTYPE_NONFILTERING
+ - SG_IMAGESAMPLETYPE_UINT => SG_SAMPLERTYPE_NONFILTERING
+ - SG_IMAGESAMPLETYPE_DEPTH => SG_SAMPLERTYPE_COMPARISON
+*/
+typedef enum sg_sampler_type {
+ _SG_SAMPLERTYPE_DEFAULT,
+ SG_SAMPLERTYPE_FILTERING,
+ SG_SAMPLERTYPE_NONFILTERING,
+ SG_SAMPLERTYPE_COMPARISON,
+ _SG_SAMPLERTYPE_NUM,
+ _SG_SAMPLERTYPE_FORCE_U32,
+} sg_sampler_type;
+
+/*
+ sg_cube_face
+
+ The cubemap faces. Use these as indices in the sg_image_desc.content
+ array.
+*/
+typedef enum sg_cube_face {
+ SG_CUBEFACE_POS_X,
+ SG_CUBEFACE_NEG_X,
+ SG_CUBEFACE_POS_Y,
+ SG_CUBEFACE_NEG_Y,
+ SG_CUBEFACE_POS_Z,
+ SG_CUBEFACE_NEG_Z,
+ SG_CUBEFACE_NUM,
+ _SG_CUBEFACE_FORCE_U32 = 0x7FFFFFFF
+} sg_cube_face;
+
+/*
+ sg_shader_stage
+
+ There are 2 shader stages: vertex- and fragment-shader-stage.
+ Each shader stage
+
+ - SG_MAX_SHADERSTAGE_UBS slots for applying uniform data
+ - SG_MAX_SHADERSTAGE_IMAGES slots for images used as textures
+ - SG_MAX_SHADERSTAGE_SAMPLERS slots for texture samplers
+ - SG_MAX_SHADERSTAGE_STORAGEBUFFERS slots for storage buffer bindings
+*/
+typedef enum sg_shader_stage {
+ SG_SHADERSTAGE_VS,
+ SG_SHADERSTAGE_FS,
+ _SG_SHADERSTAGE_FORCE_U32 = 0x7FFFFFFF
+} sg_shader_stage;
+
+/*
+ sg_primitive_type
+
+ This is the common subset of 3D primitive types supported across all 3D
+ APIs. This is used in the sg_pipeline_desc.primitive_type member when
+ creating a pipeline object.
+
+ The default primitive type is SG_PRIMITIVETYPE_TRIANGLES.
+*/
+typedef enum sg_primitive_type {
+ _SG_PRIMITIVETYPE_DEFAULT, // value 0 reserved for default-init
+ SG_PRIMITIVETYPE_POINTS,
+ SG_PRIMITIVETYPE_LINES,
+ SG_PRIMITIVETYPE_LINE_STRIP,
+ SG_PRIMITIVETYPE_TRIANGLES,
+ SG_PRIMITIVETYPE_TRIANGLE_STRIP,
+ _SG_PRIMITIVETYPE_NUM,
+ _SG_PRIMITIVETYPE_FORCE_U32 = 0x7FFFFFFF
+} sg_primitive_type;
+
+/*
+ sg_filter
+
+ The filtering mode when sampling a texture image. This is
+ used in the sg_sampler_desc.min_filter, sg_sampler_desc.mag_filter
+ and sg_sampler_desc.mipmap_filter members when creating a sampler object.
+
+ For the default is SG_FILTER_NEAREST.
+*/
+typedef enum sg_filter {
+ _SG_FILTER_DEFAULT, // value 0 reserved for default-init
+ SG_FILTER_NEAREST,
+ SG_FILTER_LINEAR,
+ _SG_FILTER_NUM,
+ _SG_FILTER_FORCE_U32 = 0x7FFFFFFF
+} sg_filter;
+
+/*
+ sg_wrap
+
+ The texture coordinates wrapping mode when sampling a texture
+ image. This is used in the sg_image_desc.wrap_u, .wrap_v
+ and .wrap_w members when creating an image.
+
+ The default wrap mode is SG_WRAP_REPEAT.
+
+ NOTE: SG_WRAP_CLAMP_TO_BORDER is not supported on all backends
+ and platforms. To check for support, call sg_query_features()
+ and check the "clamp_to_border" boolean in the returned
+ sg_features struct.
+
+ Platforms which don't support SG_WRAP_CLAMP_TO_BORDER will silently fall back
+ to SG_WRAP_CLAMP_TO_EDGE without a validation error.
+*/
+typedef enum sg_wrap {
+ _SG_WRAP_DEFAULT, // value 0 reserved for default-init
+ SG_WRAP_REPEAT,
+ SG_WRAP_CLAMP_TO_EDGE,
+ SG_WRAP_CLAMP_TO_BORDER,
+ SG_WRAP_MIRRORED_REPEAT,
+ _SG_WRAP_NUM,
+ _SG_WRAP_FORCE_U32 = 0x7FFFFFFF
+} sg_wrap;
+
+/*
+ sg_border_color
+
+ The border color to use when sampling a texture, and the UV wrap
+ mode is SG_WRAP_CLAMP_TO_BORDER.
+
+ The default border color is SG_BORDERCOLOR_OPAQUE_BLACK
+*/
+typedef enum sg_border_color {
+ _SG_BORDERCOLOR_DEFAULT, // value 0 reserved for default-init
+ SG_BORDERCOLOR_TRANSPARENT_BLACK,
+ SG_BORDERCOLOR_OPAQUE_BLACK,
+ SG_BORDERCOLOR_OPAQUE_WHITE,
+ _SG_BORDERCOLOR_NUM,
+ _SG_BORDERCOLOR_FORCE_U32 = 0x7FFFFFFF
+} sg_border_color;
+
+/*
+ sg_vertex_format
+
+ The data type of a vertex component. This is used to describe
+ the layout of vertex data when creating a pipeline object.
+*/
+typedef enum sg_vertex_format {
+ SG_VERTEXFORMAT_INVALID,
+ SG_VERTEXFORMAT_FLOAT,
+ SG_VERTEXFORMAT_FLOAT2,
+ SG_VERTEXFORMAT_FLOAT3,
+ SG_VERTEXFORMAT_FLOAT4,
+ SG_VERTEXFORMAT_BYTE4,
+ SG_VERTEXFORMAT_BYTE4N,
+ SG_VERTEXFORMAT_UBYTE4,
+ SG_VERTEXFORMAT_UBYTE4N,
+ SG_VERTEXFORMAT_SHORT2,
+ SG_VERTEXFORMAT_SHORT2N,
+ SG_VERTEXFORMAT_USHORT2N,
+ SG_VERTEXFORMAT_SHORT4,
+ SG_VERTEXFORMAT_SHORT4N,
+ SG_VERTEXFORMAT_USHORT4N,
+ SG_VERTEXFORMAT_UINT10_N2,
+ SG_VERTEXFORMAT_HALF2,
+ SG_VERTEXFORMAT_HALF4,
+ _SG_VERTEXFORMAT_NUM,
+ _SG_VERTEXFORMAT_FORCE_U32 = 0x7FFFFFFF
+} sg_vertex_format;
+
+/*
+ sg_vertex_step
+
+ Defines whether the input pointer of a vertex input stream is advanced
+ 'per vertex' or 'per instance'. The default step-func is
+ SG_VERTEXSTEP_PER_VERTEX. SG_VERTEXSTEP_PER_INSTANCE is used with
+ instanced-rendering.
+
+ The vertex-step is part of the vertex-layout definition
+ when creating pipeline objects.
+*/
+typedef enum sg_vertex_step {
+ _SG_VERTEXSTEP_DEFAULT, // value 0 reserved for default-init
+ SG_VERTEXSTEP_PER_VERTEX,
+ SG_VERTEXSTEP_PER_INSTANCE,
+ _SG_VERTEXSTEP_NUM,
+ _SG_VERTEXSTEP_FORCE_U32 = 0x7FFFFFFF
+} sg_vertex_step;
+
+/*
+ sg_uniform_type
+
+ The data type of a uniform block member. This is used to
+ describe the internal layout of uniform blocks when creating
+ a shader object.
+*/
+typedef enum sg_uniform_type {
+ SG_UNIFORMTYPE_INVALID,
+ SG_UNIFORMTYPE_FLOAT,
+ SG_UNIFORMTYPE_FLOAT2,
+ SG_UNIFORMTYPE_FLOAT3,
+ SG_UNIFORMTYPE_FLOAT4,
+ SG_UNIFORMTYPE_INT,
+ SG_UNIFORMTYPE_INT2,
+ SG_UNIFORMTYPE_INT3,
+ SG_UNIFORMTYPE_INT4,
+ SG_UNIFORMTYPE_MAT4,
+ _SG_UNIFORMTYPE_NUM,
+ _SG_UNIFORMTYPE_FORCE_U32 = 0x7FFFFFFF
+} sg_uniform_type;
+
+/*
+ sg_uniform_layout
+
+ A hint for the interior memory layout of uniform blocks. This is
+ only really relevant for the GL backend where the internal layout
+ of uniform blocks must be known to sokol-gfx. For all other backends the
+ internal memory layout of uniform blocks doesn't matter, sokol-gfx
+ will just pass uniform data as a single memory blob to the
+ 3D backend.
+
+ SG_UNIFORMLAYOUT_NATIVE (default)
+ Native layout means that a 'backend-native' memory layout
+ is used. For the GL backend this means that uniforms
+ are packed tightly in memory (e.g. there are no padding
+ bytes).
+
+ SG_UNIFORMLAYOUT_STD140
+ The memory layout is a subset of std140. Arrays are only
+ allowed for the FLOAT4, INT4 and MAT4. Alignment is as
+ is as follows:
+
+ FLOAT, INT: 4 byte alignment
+ FLOAT2, INT2: 8 byte alignment
+ FLOAT3, INT3: 16 byte alignment(!)
+ FLOAT4, INT4: 16 byte alignment
+ MAT4: 16 byte alignment
+ FLOAT4[], INT4[]: 16 byte alignment
+
+ The overall size of the uniform block must be a multiple
+ of 16.
+
+ For more information search for 'UNIFORM DATA LAYOUT' in the documentation block
+ at the start of the header.
+*/
+typedef enum sg_uniform_layout {
+ _SG_UNIFORMLAYOUT_DEFAULT, // value 0 reserved for default-init
+ SG_UNIFORMLAYOUT_NATIVE, // default: layout depends on currently active backend
+ SG_UNIFORMLAYOUT_STD140, // std140: memory layout according to std140
+ _SG_UNIFORMLAYOUT_NUM,
+ _SG_UNIFORMLAYOUT_FORCE_U32 = 0x7FFFFFFF
+} sg_uniform_layout;
+
+/*
+ sg_cull_mode
+
+ The face-culling mode, this is used in the
+ sg_pipeline_desc.cull_mode member when creating a
+ pipeline object.
+
+ The default cull mode is SG_CULLMODE_NONE
+*/
+typedef enum sg_cull_mode {
+ _SG_CULLMODE_DEFAULT, // value 0 reserved for default-init
+ SG_CULLMODE_NONE,
+ SG_CULLMODE_FRONT,
+ SG_CULLMODE_BACK,
+ _SG_CULLMODE_NUM,
+ _SG_CULLMODE_FORCE_U32 = 0x7FFFFFFF
+} sg_cull_mode;
+
+/*
+ sg_face_winding
+
+ The vertex-winding rule that determines a front-facing primitive. This
+ is used in the member sg_pipeline_desc.face_winding
+ when creating a pipeline object.
+
+ The default winding is SG_FACEWINDING_CW (clockwise)
+*/
+typedef enum sg_face_winding {
+ _SG_FACEWINDING_DEFAULT, // value 0 reserved for default-init
+ SG_FACEWINDING_CCW,
+ SG_FACEWINDING_CW,
+ _SG_FACEWINDING_NUM,
+ _SG_FACEWINDING_FORCE_U32 = 0x7FFFFFFF
+} sg_face_winding;
+
+/*
+ sg_compare_func
+
+ The compare-function for configuring depth- and stencil-ref tests
+ in pipeline objects, and for texture samplers which perform a comparison
+ instead of regular sampling operation.
+
+ sg_pipeline_desc
+ .depth
+ .compare
+ .stencil
+ .front.compare
+ .back.compar
+
+ sg_sampler_desc
+ .compare
+
+ The default compare func for depth- and stencil-tests is
+ SG_COMPAREFUNC_ALWAYS.
+
+ The default compare func for sampler is SG_COMPAREFUNC_NEVER.
+*/
+typedef enum sg_compare_func {
+ _SG_COMPAREFUNC_DEFAULT, // value 0 reserved for default-init
+ SG_COMPAREFUNC_NEVER,
+ SG_COMPAREFUNC_LESS,
+ SG_COMPAREFUNC_EQUAL,
+ SG_COMPAREFUNC_LESS_EQUAL,
+ SG_COMPAREFUNC_GREATER,
+ SG_COMPAREFUNC_NOT_EQUAL,
+ SG_COMPAREFUNC_GREATER_EQUAL,
+ SG_COMPAREFUNC_ALWAYS,
+ _SG_COMPAREFUNC_NUM,
+ _SG_COMPAREFUNC_FORCE_U32 = 0x7FFFFFFF
+} sg_compare_func;
+
+/*
+ sg_stencil_op
+
+ The operation performed on a currently stored stencil-value when a
+ comparison test passes or fails. This is used when creating a pipeline
+ object in the members:
+
+ sg_pipeline_desc
+ .stencil
+ .front
+ .fail_op
+ .depth_fail_op
+ .pass_op
+ .back
+ .fail_op
+ .depth_fail_op
+ .pass_op
+
+ The default value is SG_STENCILOP_KEEP.
+*/
+typedef enum sg_stencil_op {
+ _SG_STENCILOP_DEFAULT, // value 0 reserved for default-init
+ SG_STENCILOP_KEEP,
+ SG_STENCILOP_ZERO,
+ SG_STENCILOP_REPLACE,
+ SG_STENCILOP_INCR_CLAMP,
+ SG_STENCILOP_DECR_CLAMP,
+ SG_STENCILOP_INVERT,
+ SG_STENCILOP_INCR_WRAP,
+ SG_STENCILOP_DECR_WRAP,
+ _SG_STENCILOP_NUM,
+ _SG_STENCILOP_FORCE_U32 = 0x7FFFFFFF
+} sg_stencil_op;
+
+/*
+ sg_blend_factor
+
+ The source and destination factors in blending operations.
+ This is used in the following members when creating a pipeline object:
+
+ sg_pipeline_desc
+ .colors[i]
+ .blend
+ .src_factor_rgb
+ .dst_factor_rgb
+ .src_factor_alpha
+ .dst_factor_alpha
+
+ The default value is SG_BLENDFACTOR_ONE for source
+ factors, and SG_BLENDFACTOR_ZERO for destination factors.
+*/
+typedef enum sg_blend_factor {
+ _SG_BLENDFACTOR_DEFAULT, // value 0 reserved for default-init
+ SG_BLENDFACTOR_ZERO,
+ SG_BLENDFACTOR_ONE,
+ SG_BLENDFACTOR_SRC_COLOR,
+ SG_BLENDFACTOR_ONE_MINUS_SRC_COLOR,
+ SG_BLENDFACTOR_SRC_ALPHA,
+ SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
+ SG_BLENDFACTOR_DST_COLOR,
+ SG_BLENDFACTOR_ONE_MINUS_DST_COLOR,
+ SG_BLENDFACTOR_DST_ALPHA,
+ SG_BLENDFACTOR_ONE_MINUS_DST_ALPHA,
+ SG_BLENDFACTOR_SRC_ALPHA_SATURATED,
+ SG_BLENDFACTOR_BLEND_COLOR,
+ SG_BLENDFACTOR_ONE_MINUS_BLEND_COLOR,
+ SG_BLENDFACTOR_BLEND_ALPHA,
+ SG_BLENDFACTOR_ONE_MINUS_BLEND_ALPHA,
+ _SG_BLENDFACTOR_NUM,
+ _SG_BLENDFACTOR_FORCE_U32 = 0x7FFFFFFF
+} sg_blend_factor;
+
+/*
+ sg_blend_op
+
+ Describes how the source and destination values are combined in the
+ fragment blending operation. It is used in the following members when
+ creating a pipeline object:
+
+ sg_pipeline_desc
+ .colors[i]
+ .blend
+ .op_rgb
+ .op_alpha
+
+ The default value is SG_BLENDOP_ADD.
+*/
+typedef enum sg_blend_op {
+ _SG_BLENDOP_DEFAULT, // value 0 reserved for default-init
+ SG_BLENDOP_ADD,
+ SG_BLENDOP_SUBTRACT,
+ SG_BLENDOP_REVERSE_SUBTRACT,
+ _SG_BLENDOP_NUM,
+ _SG_BLENDOP_FORCE_U32 = 0x7FFFFFFF
+} sg_blend_op;
+
+/*
+ sg_color_mask
+
+ Selects the active color channels when writing a fragment color to the
+ framebuffer. This is used in the members
+ sg_pipeline_desc.colors[i].write_mask when creating a pipeline object.
+
+ The default colormask is SG_COLORMASK_RGBA (write all colors channels)
+
+ NOTE: since the color mask value 0 is reserved for the default value
+ (SG_COLORMASK_RGBA), use SG_COLORMASK_NONE if all color channels
+ should be disabled.
+*/
+typedef enum sg_color_mask {
+ _SG_COLORMASK_DEFAULT = 0, // value 0 reserved for default-init
+ SG_COLORMASK_NONE = 0x10, // special value for 'all channels disabled
+ SG_COLORMASK_R = 0x1,
+ SG_COLORMASK_G = 0x2,
+ SG_COLORMASK_RG = 0x3,
+ SG_COLORMASK_B = 0x4,
+ SG_COLORMASK_RB = 0x5,
+ SG_COLORMASK_GB = 0x6,
+ SG_COLORMASK_RGB = 0x7,
+ SG_COLORMASK_A = 0x8,
+ SG_COLORMASK_RA = 0x9,
+ SG_COLORMASK_GA = 0xA,
+ SG_COLORMASK_RGA = 0xB,
+ SG_COLORMASK_BA = 0xC,
+ SG_COLORMASK_RBA = 0xD,
+ SG_COLORMASK_GBA = 0xE,
+ SG_COLORMASK_RGBA = 0xF,
+ _SG_COLORMASK_FORCE_U32 = 0x7FFFFFFF
+} sg_color_mask;
+
+/*
+ sg_load_action
+
+ Defines the load action that should be performed at the start of a render pass:
+
+ SG_LOADACTION_CLEAR: clear the render target
+ SG_LOADACTION_LOAD: load the previous content of the render target
+ SG_LOADACTION_DONTCARE: leave the render target in an undefined state
+
+ This is used in the sg_pass_action structure.
+
+ The default load action for all pass attachments is SG_LOADACTION_CLEAR,
+ with the values rgba = { 0.5f, 0.5f, 0.5f, 1.0f }, depth=1.0f and stencil=0.
+
+ If you want to override the default behaviour, it is important to not
+ only set the clear color, but the 'action' field as well (as long as this
+ is _SG_LOADACTION_DEFAULT, the value fields will be ignored).
+*/
+typedef enum sg_load_action {
+ _SG_LOADACTION_DEFAULT,
+ SG_LOADACTION_CLEAR,
+ SG_LOADACTION_LOAD,
+ SG_LOADACTION_DONTCARE,
+ _SG_LOADACTION_FORCE_U32 = 0x7FFFFFFF
+} sg_load_action;
+
+/*
+ sg_store_action
+
+ Defines the store action that be performed at the end of a render pass:
+
+ SG_STOREACTION_STORE: store the rendered content to the color attachment image
+ SG_STOREACTION_DONTCARE: allows the GPU to discard the rendered content
+*/
+typedef enum sg_store_action {
+ _SG_STOREACTION_DEFAULT,
+ SG_STOREACTION_STORE,
+ SG_STOREACTION_DONTCARE,
+ _SG_STOREACTION_FORCE_U32 = 0x7FFFFFFF
+} sg_store_action;
+
+
+/*
+ sg_pass_action
+
+ The sg_pass_action struct defines the actions to be performed
+ at the start and end of a render pass.
+
+ - at the start of the pass: whether the render targets should be cleared,
+ loaded with their previous content, or start in an undefined state
+ - for clear operations: the clear value (color, depth, or stencil values)
+ - at the end of the pass: whether the rendering result should be
+ stored back into the render target or discarded
+*/
+typedef struct sg_color_attachment_action {
+ sg_load_action load_action; // default: SG_LOADACTION_CLEAR
+ sg_store_action store_action; // default: SG_STOREACTION_STORE
+ sg_color clear_value; // default: { 0.5f, 0.5f, 0.5f, 1.0f }
+} sg_color_attachment_action;
+
+typedef struct sg_depth_attachment_action {
+ sg_load_action load_action; // default: SG_LOADACTION_CLEAR
+ sg_store_action store_action; // default: SG_STOREACTION_DONTCARE
+ float clear_value; // default: 1.0
+} sg_depth_attachment_action;
+
+typedef struct sg_stencil_attachment_action {
+ sg_load_action load_action; // default: SG_LOADACTION_CLEAR
+ sg_store_action store_action; // default: SG_STOREACTION_DONTCARE
+ uint8_t clear_value; // default: 0
+} sg_stencil_attachment_action;
+
+typedef struct sg_pass_action {
+ sg_color_attachment_action colors[SG_MAX_COLOR_ATTACHMENTS];
+ sg_depth_attachment_action depth;
+ sg_stencil_attachment_action stencil;
+} sg_pass_action;
+
+/*
+ sg_swapchain
+
+ Used in sg_begin_pass() to provide details about an external swapchain
+ (pixel formats, sample count and backend-API specific render surface objects).
+
+ The following information must be provided:
+
+ - the width and height of the swapchain surfaces in number of pixels,
+ - the pixel format of the render- and optional msaa-resolve-surface
+ - the pixel format of the optional depth- or depth-stencil-surface
+ - the MSAA sample count for the render and depth-stencil surface
+
+ If the pixel formats and MSAA sample counts are left zero-initialized,
+ their defaults are taken from the sg_environment struct provided in the
+ sg_setup() call.
+
+ The width and height *must* be > 0.
+
+ Additionally the following backend API specific objects must be passed in
+ as 'type erased' void pointers:
+
+ GL: on all GL backends, a GL framebuffer object must be provided. This
+ can be zero for the default framebuffer.
+
+ D3D11:
+ - an ID3D11RenderTargetView for the rendering surface, without
+ MSAA rendering this surface will also be displayed
+ - an optional ID3D11DepthStencilView for the depth- or depth/stencil
+ buffer surface
+ - when MSAA rendering is used, another ID3D11RenderTargetView
+ which serves as MSAA resolve target and will be displayed
+
+ WebGPU (same as D3D11, except different types)
+ - a WGPUTextureView for the rendering surface, without
+ MSAA rendering this surface will also be displayed
+ - an optional WGPUTextureView for the depth- or depth/stencil
+ buffer surface
+ - when MSAA rendering is used, another WGPUTextureView
+ which serves as MSAA resolve target and will be displayed
+
+ Metal (NOTE that the rolves of provided surfaces is slightly different
+ than on D3D11 or WebGPU in case of MSAA vs non-MSAA rendering):
+
+ - A current CAMetalDrawable (NOT an MTLDrawable!) which will be presented.
+ This will either be rendered to directly (if no MSAA is used), or serve
+ as MSAA-resolve target.
+ - an optional MTLTexture for the depth- or depth-stencil buffer
+ - an optional multisampled MTLTexture which serves as intermediate
+ rendering surface which will then be resolved into the
+ CAMetalDrawable.
+
+ NOTE that for Metal you must use an ObjC __bridge cast to
+ properly tunnel the ObjC object handle through a C void*, e.g.:
+
+ swapchain.metal.current_drawable = (__bridge const void*) [mtkView currentDrawable];
+
+ On all other backends you shouldn't need to mess with the reference count.
+
+ It's a good practice to write a helper function which returns an initialized
+ sg_swapchain structs, which can then be plugged directly into
+ sg_pass.swapchain. Look at the function sglue_swapchain() in the sokol_glue.h
+ as an example.
+*/
+typedef struct sg_metal_swapchain {
+ const void* current_drawable; // CAMetalDrawable (NOT MTLDrawable!!!)
+ const void* depth_stencil_texture; // MTLTexture
+ const void* msaa_color_texture; // MTLTexture
+} sg_metal_swapchain;
+
+typedef struct sg_d3d11_swapchain {
+ const void* render_view; // ID3D11RenderTargetView
+ const void* resolve_view; // ID3D11RenderTargetView
+ const void* depth_stencil_view; // ID3D11DepthStencilView
+} sg_d3d11_swapchain;
+
+typedef struct sg_wgpu_swapchain {
+ const void* render_view; // WGPUTextureView
+ const void* resolve_view; // WGPUTextureView
+ const void* depth_stencil_view; // WGPUTextureView
+} sg_wgpu_swapchain;
+
+typedef struct sg_gl_swapchain {
+ uint32_t framebuffer; // GL framebuffer object
+} sg_gl_swapchain;
+
+typedef struct sg_swapchain {
+ int width;
+ int height;
+ int sample_count;
+ sg_pixel_format color_format;
+ sg_pixel_format depth_format;
+ sg_metal_swapchain metal;
+ sg_d3d11_swapchain d3d11;
+ sg_wgpu_swapchain wgpu;
+ sg_gl_swapchain gl;
+} sg_swapchain;
+
+/*
+ sg_pass
+
+ The sg_pass structure is passed as argument into the sg_begin_pass()
+ function.
+
+ For an offscreen rendering pass, an sg_pass_action struct and sg_attachments
+ object must be provided, and for swapchain passes, and sg_pass_action and
+ an sg_swapchain struct. It is an error to provide both an sg_attachments
+ handle and an initialized sg_swapchain struct in the same sg_begin_pass().
+
+ An sg_begin_pass() call for an offscreen pass would look like this (where
+ `attachments` is an sg_attachments handle):
+
+ sg_begin_pass(&(sg_pass){
+ .action = { ... },
+ .attachments = attachments,
+ });
+
+ ...and a swapchain render pass would look like this (using the sokol_glue.h
+ helper function sglue_swapchain() which gets the swapchain properties from
+ sokol_app.h):
+
+ sg_begin_pass(&(sg_pass){
+ .action = { ... },
+ .swapchain = sglue_swapchain(),
+ });
+
+ You can also omit the .action object to get default pass action behaviour
+ (clear to color=grey, depth=1 and stencil=0).
+*/
+typedef struct sg_pass {
+ uint32_t _start_canary;
+ sg_pass_action action;
+ sg_attachments attachments;
+ sg_swapchain swapchain;
+ const char* label;
+ uint32_t _end_canary;
+} sg_pass;
+
+/*
+ sg_bindings
+
+ The sg_bindings structure defines the resource binding slots
+ of the sokol_gfx render pipeline, used as argument to the
+ sg_apply_bindings() function.
+
+ A resource binding struct contains:
+
+ - 1..N vertex buffers
+ - 0..N vertex buffer offsets
+ - 0..1 index buffers
+ - 0..1 index buffer offsets
+ - 0..N vertex shader stage images
+ - 0..N vertex shader stage samplers
+ - 0..N vertex shader storage buffers
+ - 0..N fragment shader stage images
+ - 0..N fragment shader stage samplers
+ - 0..N fragment shader storage buffers
+
+ For the max number of bindings, see the constant definitions:
+
+ - SG_MAX_VERTEX_BUFFERS
+ - SG_MAX_SHADERSTAGE_IMAGES
+ - SG_MAX_SHADERSTAGE_SAMPLERS
+ - SG_MAX_SHADERSTAGE_STORAGEBUFFERS
+
+ The optional buffer offsets can be used to put different unrelated
+ chunks of vertex- and/or index-data into the same buffer objects.
+*/
+typedef struct sg_stage_bindings {
+ sg_image images[SG_MAX_SHADERSTAGE_IMAGES];
+ sg_sampler samplers[SG_MAX_SHADERSTAGE_SAMPLERS];
+ sg_buffer storage_buffers[SG_MAX_SHADERSTAGE_STORAGEBUFFERS];
+} sg_stage_bindings;
+
+typedef struct sg_bindings {
+ uint32_t _start_canary;
+ sg_buffer vertex_buffers[SG_MAX_VERTEX_BUFFERS];
+ int vertex_buffer_offsets[SG_MAX_VERTEX_BUFFERS];
+ sg_buffer index_buffer;
+ int index_buffer_offset;
+ sg_stage_bindings vs;
+ sg_stage_bindings fs;
+ uint32_t _end_canary;
+} sg_bindings;
+
+/*
+ sg_buffer_desc
+
+ Creation parameters for sg_buffer objects, used in the
+ sg_make_buffer() call.
+
+ The default configuration is:
+
+ .size: 0 (*must* be >0 for buffers without data)
+ .type: SG_BUFFERTYPE_VERTEXBUFFER
+ .usage: SG_USAGE_IMMUTABLE
+ .data.ptr 0 (*must* be valid for immutable buffers)
+ .data.size 0 (*must* be > 0 for immutable buffers)
+ .label 0 (optional string label)
+
+ For immutable buffers which are initialized with initial data,
+ keep the .size item zero-initialized, and set the size together with the
+ pointer to the initial data in the .data item.
+
+ For mutable buffers without initial data, keep the .data item
+ zero-initialized, and set the buffer size in the .size item instead.
+
+ You can also set both size values, but currently both size values must
+ be identical (this may change in the future when the dynamic resource
+ management may become more flexible).
+
+ ADVANCED TOPIC: Injecting native 3D-API buffers:
+
+ The following struct members allow to inject your own GL, Metal
+ or D3D11 buffers into sokol_gfx:
+
+ .gl_buffers[SG_NUM_INFLIGHT_FRAMES]
+ .mtl_buffers[SG_NUM_INFLIGHT_FRAMES]
+ .d3d11_buffer
+
+ You must still provide all other struct items except the .data item, and
+ these must match the creation parameters of the native buffers you
+ provide. For SG_USAGE_IMMUTABLE, only provide a single native 3D-API
+ buffer, otherwise you need to provide SG_NUM_INFLIGHT_FRAMES buffers
+ (only for GL and Metal, not D3D11). Providing multiple buffers for GL and
+ Metal is necessary because sokol_gfx will rotate through them when
+ calling sg_update_buffer() to prevent lock-stalls.
+
+ Note that it is expected that immutable injected buffer have already been
+ initialized with content, and the .content member must be 0!
+
+ Also you need to call sg_reset_state_cache() after calling native 3D-API
+ functions, and before calling any sokol_gfx function.
+*/
+typedef struct sg_buffer_desc {
+ uint32_t _start_canary;
+ size_t size;
+ sg_buffer_type type;
+ sg_usage usage;
+ sg_range data;
+ const char* label;
+ // optionally inject backend-specific resources
+ uint32_t gl_buffers[SG_NUM_INFLIGHT_FRAMES];
+ const void* mtl_buffers[SG_NUM_INFLIGHT_FRAMES];
+ const void* d3d11_buffer;
+ const void* wgpu_buffer;
+ uint32_t _end_canary;
+} sg_buffer_desc;
+
+/*
+ sg_image_data
+
+ Defines the content of an image through a 2D array of sg_range structs.
+ The first array dimension is the cubemap face, and the second array
+ dimension the mipmap level.
+*/
+typedef struct sg_image_data {
+ sg_range subimage[SG_CUBEFACE_NUM][SG_MAX_MIPMAPS];
+} sg_image_data;
+
+/*
+ sg_image_desc
+
+ Creation parameters for sg_image objects, used in the sg_make_image() call.
+
+ The default configuration is:
+
+ .type: SG_IMAGETYPE_2D
+ .render_target: false
+ .width 0 (must be set to >0)
+ .height 0 (must be set to >0)
+ .num_slices 1 (3D textures: depth; array textures: number of layers)
+ .num_mipmaps: 1
+ .usage: SG_USAGE_IMMUTABLE
+ .pixel_format: SG_PIXELFORMAT_RGBA8 for textures, or sg_desc.environment.defaults.color_format for render targets
+ .sample_count: 1 for textures, or sg_desc.environment.defaults.sample_count for render targets
+ .data an sg_image_data struct to define the initial content
+ .label 0 (optional string label for trace hooks)
+
+ Q: Why is the default sample_count for render targets identical with the
+ "default sample count" from sg_desc.environment.defaults.sample_count?
+
+ A: So that it matches the default sample count in pipeline objects. Even
+ though it is a bit strange/confusing that offscreen render targets by default
+ get the same sample count as 'default swapchains', but it's better that
+ an offscreen render target created with default parameters matches
+ a pipeline object created with default parameters.
+
+ NOTE:
+
+ Images with usage SG_USAGE_IMMUTABLE must be fully initialized by
+ providing a valid .data member which points to initialization data.
+
+ ADVANCED TOPIC: Injecting native 3D-API textures:
+
+ The following struct members allow to inject your own GL, Metal or D3D11
+ textures into sokol_gfx:
+
+ .gl_textures[SG_NUM_INFLIGHT_FRAMES]
+ .mtl_textures[SG_NUM_INFLIGHT_FRAMES]
+ .d3d11_texture
+ .d3d11_shader_resource_view
+ .wgpu_texture
+ .wgpu_texture_view
+
+ For GL, you can also specify the texture target or leave it empty to use
+ the default texture target for the image type (GL_TEXTURE_2D for
+ SG_IMAGETYPE_2D etc)
+
+ For D3D11 and WebGPU, either only provide a texture, or both a texture and
+ shader-resource-view / texture-view object. If you want to use access the
+ injected texture in a shader you *must* provide a shader-resource-view.
+
+ The same rules apply as for injecting native buffers (see sg_buffer_desc
+ documentation for more details).
+*/
+typedef struct sg_image_desc {
+ uint32_t _start_canary;
+ sg_image_type type;
+ bool render_target;
+ int width;
+ int height;
+ int num_slices;
+ int num_mipmaps;
+ sg_usage usage;
+ sg_pixel_format pixel_format;
+ int sample_count;
+ sg_image_data data;
+ const char* label;
+ // optionally inject backend-specific resources
+ uint32_t gl_textures[SG_NUM_INFLIGHT_FRAMES];
+ uint32_t gl_texture_target;
+ const void* mtl_textures[SG_NUM_INFLIGHT_FRAMES];
+ const void* d3d11_texture;
+ const void* d3d11_shader_resource_view;
+ const void* wgpu_texture;
+ const void* wgpu_texture_view;
+ uint32_t _end_canary;
+} sg_image_desc;
+
+/*
+ sg_sampler_desc
+
+ Creation parameters for sg_sampler objects, used in the sg_make_sampler() call
+
+ .min_filter: SG_FILTER_NEAREST
+ .mag_filter: SG_FILTER_NEAREST
+ .mipmap_filter SG_FILTER_NEAREST
+ .wrap_u: SG_WRAP_REPEAT
+ .wrap_v: SG_WRAP_REPEAT
+ .wrap_w: SG_WRAP_REPEAT (only SG_IMAGETYPE_3D)
+ .min_lod 0.0f
+ .max_lod FLT_MAX
+ .border_color SG_BORDERCOLOR_OPAQUE_BLACK
+ .compare SG_COMPAREFUNC_NEVER
+ .max_anisotropy 1 (must be 1..16)
+
+*/
+typedef struct sg_sampler_desc {
+ uint32_t _start_canary;
+ sg_filter min_filter;
+ sg_filter mag_filter;
+ sg_filter mipmap_filter;
+ sg_wrap wrap_u;
+ sg_wrap wrap_v;
+ sg_wrap wrap_w;
+ float min_lod;
+ float max_lod;
+ sg_border_color border_color;
+ sg_compare_func compare;
+ uint32_t max_anisotropy;
+ const char* label;
+ // optionally inject backend-specific resources
+ uint32_t gl_sampler;
+ const void* mtl_sampler;
+ const void* d3d11_sampler;
+ const void* wgpu_sampler;
+ uint32_t _end_canary;
+} sg_sampler_desc;
+
+/*
+ sg_shader_desc
+
+ The structure sg_shader_desc defines all creation parameters for shader
+ programs, used as input to the sg_make_shader() function:
+
+ - reflection information for vertex attributes (vertex shader inputs):
+ - vertex attribute name (only optionally used by GLES3 and GL)
+ - a semantic name and index (required for D3D11)
+ - for each shader-stage (vertex and fragment):
+ - the shader source or bytecode
+ - an optional entry function name
+ - an optional compile target (only for D3D11 when source is provided,
+ defaults are "vs_4_0" and "ps_4_0")
+ - reflection info for each uniform block used by the shader stage:
+ - the size of the uniform block in bytes
+ - a memory layout hint (native vs std140, only required for GL backends)
+ - reflection info for each uniform block member (only required for GL backends):
+ - member name
+ - member type (SG_UNIFORMTYPE_xxx)
+ - if the member is an array, the number of array items
+ - reflection info for textures used in the shader stage:
+ - the image type (SG_IMAGETYPE_xxx)
+ - the image-sample type (SG_IMAGESAMPLETYPE_xxx, default is SG_IMAGESAMPLETYPE_FLOAT)
+ - whether the shader expects a multisampled texture
+ - reflection info for samplers used in the shader stage:
+ - the sampler type (SG_SAMPLERTYPE_xxx)
+ - reflection info for each image-sampler-pair used by the shader:
+ - the texture slot of the involved texture
+ - the sampler slot of the involved sampler
+ - for GLSL only: the name of the combined image-sampler object
+ - reflection info for each storage-buffer used by the shader:
+ - whether the storage buffer is readonly (currently this
+ must be true)
+
+ For all GL backends, shader source-code must be provided. For D3D11 and Metal,
+ either shader source-code or byte-code can be provided.
+
+ For D3D11, if source code is provided, the d3dcompiler_47.dll will be loaded
+ on demand. If this fails, shader creation will fail. When compiling HLSL
+ source code, you can provide an optional target string via
+ sg_shader_stage_desc.d3d11_target, the default target is "vs_4_0" for the
+ vertex shader stage and "ps_4_0" for the pixel shader stage.
+*/
+typedef struct sg_shader_attr_desc {
+ const char* name; // GLSL vertex attribute name (optional)
+ const char* sem_name; // HLSL semantic name
+ int sem_index; // HLSL semantic index
+} sg_shader_attr_desc;
+
+typedef struct sg_shader_uniform_desc {
+ const char* name;
+ sg_uniform_type type;
+ int array_count;
+} sg_shader_uniform_desc;
+
+typedef struct sg_shader_uniform_block_desc {
+ size_t size;
+ sg_uniform_layout layout;
+ sg_shader_uniform_desc uniforms[SG_MAX_UB_MEMBERS];
+} sg_shader_uniform_block_desc;
+
+typedef struct sg_shader_storage_buffer_desc {
+ bool used;
+ bool readonly;
+} sg_shader_storage_buffer_desc;
+
+typedef struct sg_shader_image_desc {
+ bool used;
+ bool multisampled;
+ sg_image_type image_type;
+ sg_image_sample_type sample_type;
+} sg_shader_image_desc;
+
+typedef struct sg_shader_sampler_desc {
+ bool used;
+ sg_sampler_type sampler_type;
+} sg_shader_sampler_desc;
+
+typedef struct sg_shader_image_sampler_pair_desc {
+ bool used;
+ int image_slot;
+ int sampler_slot;
+ const char* glsl_name;
+} sg_shader_image_sampler_pair_desc;
+
+typedef struct sg_shader_stage_desc {
+ const char* source;
+ sg_range bytecode;
+ const char* entry;
+ const char* d3d11_target;
+ sg_shader_uniform_block_desc uniform_blocks[SG_MAX_SHADERSTAGE_UBS];
+ sg_shader_storage_buffer_desc storage_buffers[SG_MAX_SHADERSTAGE_STORAGEBUFFERS];
+ sg_shader_image_desc images[SG_MAX_SHADERSTAGE_IMAGES];
+ sg_shader_sampler_desc samplers[SG_MAX_SHADERSTAGE_SAMPLERS];
+ sg_shader_image_sampler_pair_desc image_sampler_pairs[SG_MAX_SHADERSTAGE_IMAGESAMPLERPAIRS];
+} sg_shader_stage_desc;
+
+typedef struct sg_shader_desc {
+ uint32_t _start_canary;
+ sg_shader_attr_desc attrs[SG_MAX_VERTEX_ATTRIBUTES];
+ sg_shader_stage_desc vs;
+ sg_shader_stage_desc fs;
+ const char* label;
+ uint32_t _end_canary;
+} sg_shader_desc;
+
+/*
+ sg_pipeline_desc
+
+ The sg_pipeline_desc struct defines all creation parameters for an
+ sg_pipeline object, used as argument to the sg_make_pipeline() function:
+
+ - the vertex layout for all input vertex buffers
+ - a shader object
+ - the 3D primitive type (points, lines, triangles, ...)
+ - the index type (none, 16- or 32-bit)
+ - all the fixed-function-pipeline state (depth-, stencil-, blend-state, etc...)
+
+ If the vertex data has no gaps between vertex components, you can omit
+ the .layout.buffers[].stride and layout.attrs[].offset items (leave them
+ default-initialized to 0), sokol-gfx will then compute the offsets and
+ strides from the vertex component formats (.layout.attrs[].format).
+ Please note that ALL vertex attribute offsets must be 0 in order for the
+ automatic offset computation to kick in.
+
+ The default configuration is as follows:
+
+ .shader: 0 (must be initialized with a valid sg_shader id!)
+ .layout:
+ .buffers[]: vertex buffer layouts
+ .stride: 0 (if no stride is given it will be computed)
+ .step_func SG_VERTEXSTEP_PER_VERTEX
+ .step_rate 1
+ .attrs[]: vertex attribute declarations
+ .buffer_index 0 the vertex buffer bind slot
+ .offset 0 (offsets can be omitted if the vertex layout has no gaps)
+ .format SG_VERTEXFORMAT_INVALID (must be initialized!)
+ .depth:
+ .pixel_format: sg_desc.context.depth_format
+ .compare: SG_COMPAREFUNC_ALWAYS
+ .write_enabled: false
+ .bias: 0.0f
+ .bias_slope_scale: 0.0f
+ .bias_clamp: 0.0f
+ .stencil:
+ .enabled: false
+ .front/back:
+ .compare: SG_COMPAREFUNC_ALWAYS
+ .fail_op: SG_STENCILOP_KEEP
+ .depth_fail_op: SG_STENCILOP_KEEP
+ .pass_op: SG_STENCILOP_KEEP
+ .read_mask: 0
+ .write_mask: 0
+ .ref: 0
+ .color_count 1
+ .colors[0..color_count]
+ .pixel_format sg_desc.context.color_format
+ .write_mask: SG_COLORMASK_RGBA
+ .blend:
+ .enabled: false
+ .src_factor_rgb: SG_BLENDFACTOR_ONE
+ .dst_factor_rgb: SG_BLENDFACTOR_ZERO
+ .op_rgb: SG_BLENDOP_ADD
+ .src_factor_alpha: SG_BLENDFACTOR_ONE
+ .dst_factor_alpha: SG_BLENDFACTOR_ZERO
+ .op_alpha: SG_BLENDOP_ADD
+ .primitive_type: SG_PRIMITIVETYPE_TRIANGLES
+ .index_type: SG_INDEXTYPE_NONE
+ .cull_mode: SG_CULLMODE_NONE
+ .face_winding: SG_FACEWINDING_CW
+ .sample_count: sg_desc.context.sample_count
+ .blend_color: (sg_color) { 0.0f, 0.0f, 0.0f, 0.0f }
+ .alpha_to_coverage_enabled: false
+ .label 0 (optional string label for trace hooks)
+*/
+typedef struct sg_vertex_buffer_layout_state {
+ int stride;
+ sg_vertex_step step_func;
+ int step_rate;
+} sg_vertex_buffer_layout_state;
+
+typedef struct sg_vertex_attr_state {
+ int buffer_index;
+ int offset;
+ sg_vertex_format format;
+} sg_vertex_attr_state;
+
+typedef struct sg_vertex_layout_state {
+ sg_vertex_buffer_layout_state buffers[SG_MAX_VERTEX_BUFFERS];
+ sg_vertex_attr_state attrs[SG_MAX_VERTEX_ATTRIBUTES];
+} sg_vertex_layout_state;
+
+typedef struct sg_stencil_face_state {
+ sg_compare_func compare;
+ sg_stencil_op fail_op;
+ sg_stencil_op depth_fail_op;
+ sg_stencil_op pass_op;
+} sg_stencil_face_state;
+
+typedef struct sg_stencil_state {
+ bool enabled;
+ sg_stencil_face_state front;
+ sg_stencil_face_state back;
+ uint8_t read_mask;
+ uint8_t write_mask;
+ uint8_t ref;
+} sg_stencil_state;
+
+typedef struct sg_depth_state {
+ sg_pixel_format pixel_format;
+ sg_compare_func compare;
+ bool write_enabled;
+ float bias;
+ float bias_slope_scale;
+ float bias_clamp;
+} sg_depth_state;
+
+typedef struct sg_blend_state {
+ bool enabled;
+ sg_blend_factor src_factor_rgb;
+ sg_blend_factor dst_factor_rgb;
+ sg_blend_op op_rgb;
+ sg_blend_factor src_factor_alpha;
+ sg_blend_factor dst_factor_alpha;
+ sg_blend_op op_alpha;
+} sg_blend_state;
+
+typedef struct sg_color_target_state {
+ sg_pixel_format pixel_format;
+ sg_color_mask write_mask;
+ sg_blend_state blend;
+} sg_color_target_state;
+
+typedef struct sg_pipeline_desc {
+ uint32_t _start_canary;
+ sg_shader shader;
+ sg_vertex_layout_state layout;
+ sg_depth_state depth;
+ sg_stencil_state stencil;
+ int color_count;
+ sg_color_target_state colors[SG_MAX_COLOR_ATTACHMENTS];
+ sg_primitive_type primitive_type;
+ sg_index_type index_type;
+ sg_cull_mode cull_mode;
+ sg_face_winding face_winding;
+ int sample_count;
+ sg_color blend_color;
+ bool alpha_to_coverage_enabled;
+ const char* label;
+ uint32_t _end_canary;
+} sg_pipeline_desc;
+
+/*
+ sg_attachments_desc
+
+ Creation parameters for an sg_attachments object, used as argument to the
+ sg_make_attachments() function.
+
+ An attachments object bundles 0..4 color attachments, 0..4 msaa-resolve
+ attachments, and none or one depth-stencil attachmente for use
+ in a render pass. At least one color attachment or one depth-stencil
+ attachment must be provided (no color attachment and a depth-stencil
+ attachment is useful for a depth-only render pass).
+
+ Each attachment definition consists of an image object, and two additional indices
+ describing which subimage the pass will render into: one mipmap index, and if the image
+ is a cubemap, array-texture or 3D-texture, the face-index, array-layer or
+ depth-slice.
+
+ All attachments must have the same width and height.
+
+ All color attachments and the depth-stencil attachment must have the
+ same sample count.
+
+ If a resolve attachment is set, an MSAA-resolve operation from the
+ associated color attachment image into the resolve attachment image will take
+ place in the sg_end_pass() function. In this case, the color attachment
+ must have a (sample_count>1), and the resolve attachment a
+ (sample_count==1). The resolve attachment also must have the same pixel
+ format as the color attachment.
+
+ NOTE that MSAA depth-stencil attachments cannot be msaa-resolved!
+*/
+typedef struct sg_attachment_desc {
+ sg_image image;
+ int mip_level;
+ int slice; // cube texture: face; array texture: layer; 3D texture: slice
+} sg_attachment_desc;
+
+typedef struct sg_attachments_desc {
+ uint32_t _start_canary;
+ sg_attachment_desc colors[SG_MAX_COLOR_ATTACHMENTS];
+ sg_attachment_desc resolves[SG_MAX_COLOR_ATTACHMENTS];
+ sg_attachment_desc depth_stencil;
+ const char* label;
+ uint32_t _end_canary;
+} sg_attachments_desc;
+
+/*
+ sg_trace_hooks
+
+ Installable callback functions to keep track of the sokol-gfx calls,
+ this is useful for debugging, or keeping track of resource creation
+ and destruction.
+
+ Trace hooks are installed with sg_install_trace_hooks(), this returns
+ another sg_trace_hooks struct with the previous set of
+ trace hook function pointers. These should be invoked by the
+ new trace hooks to form a proper call chain.
+*/
+typedef struct sg_trace_hooks {
+ void* user_data;
+ void (*reset_state_cache)(void* user_data);
+ void (*make_buffer)(const sg_buffer_desc* desc, sg_buffer result, void* user_data);
+ void (*make_image)(const sg_image_desc* desc, sg_image result, void* user_data);
+ void (*make_sampler)(const sg_sampler_desc* desc, sg_sampler result, void* user_data);
+ void (*make_shader)(const sg_shader_desc* desc, sg_shader result, void* user_data);
+ void (*make_pipeline)(const sg_pipeline_desc* desc, sg_pipeline result, void* user_data);
+ void (*make_attachments)(const sg_attachments_desc* desc, sg_attachments result, void* user_data);
+ void (*destroy_buffer)(sg_buffer buf, void* user_data);
+ void (*destroy_image)(sg_image img, void* user_data);
+ void (*destroy_sampler)(sg_sampler smp, void* user_data);
+ void (*destroy_shader)(sg_shader shd, void* user_data);
+ void (*destroy_pipeline)(sg_pipeline pip, void* user_data);
+ void (*destroy_attachments)(sg_attachments atts, void* user_data);
+ void (*update_buffer)(sg_buffer buf, const sg_range* data, void* user_data);
+ void (*update_image)(sg_image img, const sg_image_data* data, void* user_data);
+ void (*append_buffer)(sg_buffer buf, const sg_range* data, int result, void* user_data);
+ void (*begin_pass)(const sg_pass* pass, void* user_data);
+ void (*apply_viewport)(int x, int y, int width, int height, bool origin_top_left, void* user_data);
+ void (*apply_scissor_rect)(int x, int y, int width, int height, bool origin_top_left, void* user_data);
+ void (*apply_pipeline)(sg_pipeline pip, void* user_data);
+ void (*apply_bindings)(const sg_bindings* bindings, void* user_data);
+ void (*apply_uniforms)(sg_shader_stage stage, int ub_index, const sg_range* data, void* user_data);
+ void (*draw)(int base_element, int num_elements, int num_instances, void* user_data);
+ void (*end_pass)(void* user_data);
+ void (*commit)(void* user_data);
+ void (*alloc_buffer)(sg_buffer result, void* user_data);
+ void (*alloc_image)(sg_image result, void* user_data);
+ void (*alloc_sampler)(sg_sampler result, void* user_data);
+ void (*alloc_shader)(sg_shader result, void* user_data);
+ void (*alloc_pipeline)(sg_pipeline result, void* user_data);
+ void (*alloc_attachments)(sg_attachments result, void* user_data);
+ void (*dealloc_buffer)(sg_buffer buf_id, void* user_data);
+ void (*dealloc_image)(sg_image img_id, void* user_data);
+ void (*dealloc_sampler)(sg_sampler smp_id, void* user_data);
+ void (*dealloc_shader)(sg_shader shd_id, void* user_data);
+ void (*dealloc_pipeline)(sg_pipeline pip_id, void* user_data);
+ void (*dealloc_attachments)(sg_attachments atts_id, void* user_data);
+ void (*init_buffer)(sg_buffer buf_id, const sg_buffer_desc* desc, void* user_data);
+ void (*init_image)(sg_image img_id, const sg_image_desc* desc, void* user_data);
+ void (*init_sampler)(sg_sampler smp_id, const sg_sampler_desc* desc, void* user_data);
+ void (*init_shader)(sg_shader shd_id, const sg_shader_desc* desc, void* user_data);
+ void (*init_pipeline)(sg_pipeline pip_id, const sg_pipeline_desc* desc, void* user_data);
+ void (*init_attachments)(sg_attachments atts_id, const sg_attachments_desc* desc, void* user_data);
+ void (*uninit_buffer)(sg_buffer buf_id, void* user_data);
+ void (*uninit_image)(sg_image img_id, void* user_data);
+ void (*uninit_sampler)(sg_sampler smp_id, void* user_data);
+ void (*uninit_shader)(sg_shader shd_id, void* user_data);
+ void (*uninit_pipeline)(sg_pipeline pip_id, void* user_data);
+ void (*uninit_attachments)(sg_attachments atts_id, void* user_data);
+ void (*fail_buffer)(sg_buffer buf_id, void* user_data);
+ void (*fail_image)(sg_image img_id, void* user_data);
+ void (*fail_sampler)(sg_sampler smp_id, void* user_data);
+ void (*fail_shader)(sg_shader shd_id, void* user_data);
+ void (*fail_pipeline)(sg_pipeline pip_id, void* user_data);
+ void (*fail_attachments)(sg_attachments atts_id, void* user_data);
+ void (*push_debug_group)(const char* name, void* user_data);
+ void (*pop_debug_group)(void* user_data);
+} sg_trace_hooks;
+
+/*
+ sg_buffer_info
+ sg_image_info
+ sg_sampler_info
+ sg_shader_info
+ sg_pipeline_info
+ sg_attachments_info
+
+ These structs contain various internal resource attributes which
+ might be useful for debug-inspection. Please don't rely on the
+ actual content of those structs too much, as they are quite closely
+ tied to sokol_gfx.h internals and may change more frequently than
+ the other public API elements.
+
+ The *_info structs are used as the return values of the following functions:
+
+ sg_query_buffer_info()
+ sg_query_image_info()
+ sg_query_sampler_info()
+ sg_query_shader_info()
+ sg_query_pipeline_info()
+ sg_query_pass_info()
+*/
+typedef struct sg_slot_info {
+ sg_resource_state state; // the current state of this resource slot
+ uint32_t res_id; // type-neutral resource if (e.g. sg_buffer.id)
+} sg_slot_info;
+
+typedef struct sg_buffer_info {
+ sg_slot_info slot; // resource pool slot info
+ uint32_t update_frame_index; // frame index of last sg_update_buffer()
+ uint32_t append_frame_index; // frame index of last sg_append_buffer()
+ int append_pos; // current position in buffer for sg_append_buffer()
+ bool append_overflow; // is buffer in overflow state (due to sg_append_buffer)
+ int num_slots; // number of renaming-slots for dynamically updated buffers
+ int active_slot; // currently active write-slot for dynamically updated buffers
+} sg_buffer_info;
+
+typedef struct sg_image_info {
+ sg_slot_info slot; // resource pool slot info
+ uint32_t upd_frame_index; // frame index of last sg_update_image()
+ int num_slots; // number of renaming-slots for dynamically updated images
+ int active_slot; // currently active write-slot for dynamically updated images
+} sg_image_info;
+
+typedef struct sg_sampler_info {
+ sg_slot_info slot; // resource pool slot info
+} sg_sampler_info;
+
+typedef struct sg_shader_info {
+ sg_slot_info slot; // resource pool slot info
+} sg_shader_info;
+
+typedef struct sg_pipeline_info {
+ sg_slot_info slot; // resource pool slot info
+} sg_pipeline_info;
+
+typedef struct sg_attachments_info {
+ sg_slot_info slot; // resource pool slot info
+} sg_attachments_info;
+
+/*
+ sg_frame_stats
+
+ Allows to track generic and backend-specific stats about a
+ render frame. Obtained by calling sg_query_frame_stats(). The returned
+ struct contains information about the *previous* frame.
+*/
+typedef struct sg_frame_stats_gl {
+ uint32_t num_bind_buffer;
+ uint32_t num_active_texture;
+ uint32_t num_bind_texture;
+ uint32_t num_bind_sampler;
+ uint32_t num_use_program;
+ uint32_t num_render_state;
+ uint32_t num_vertex_attrib_pointer;
+ uint32_t num_vertex_attrib_divisor;
+ uint32_t num_enable_vertex_attrib_array;
+ uint32_t num_disable_vertex_attrib_array;
+ uint32_t num_uniform;
+} sg_frame_stats_gl;
+
+typedef struct sg_frame_stats_d3d11_pass {
+ uint32_t num_om_set_render_targets;
+ uint32_t num_clear_render_target_view;
+ uint32_t num_clear_depth_stencil_view;
+ uint32_t num_resolve_subresource;
+} sg_frame_stats_d3d11_pass;
+
+typedef struct sg_frame_stats_d3d11_pipeline {
+ uint32_t num_rs_set_state;
+ uint32_t num_om_set_depth_stencil_state;
+ uint32_t num_om_set_blend_state;
+ uint32_t num_ia_set_primitive_topology;
+ uint32_t num_ia_set_input_layout;
+ uint32_t num_vs_set_shader;
+ uint32_t num_vs_set_constant_buffers;
+ uint32_t num_ps_set_shader;
+ uint32_t num_ps_set_constant_buffers;
+} sg_frame_stats_d3d11_pipeline;
+
+typedef struct sg_frame_stats_d3d11_bindings {
+ uint32_t num_ia_set_vertex_buffers;
+ uint32_t num_ia_set_index_buffer;
+ uint32_t num_vs_set_shader_resources;
+ uint32_t num_ps_set_shader_resources;
+ uint32_t num_vs_set_samplers;
+ uint32_t num_ps_set_samplers;
+} sg_frame_stats_d3d11_bindings;
+
+typedef struct sg_frame_stats_d3d11_uniforms {
+ uint32_t num_update_subresource;
+} sg_frame_stats_d3d11_uniforms;
+
+typedef struct sg_frame_stats_d3d11_draw {
+ uint32_t num_draw_indexed_instanced;
+ uint32_t num_draw_indexed;
+ uint32_t num_draw_instanced;
+ uint32_t num_draw;
+} sg_frame_stats_d3d11_draw;
+
+typedef struct sg_frame_stats_d3d11 {
+ sg_frame_stats_d3d11_pass pass;
+ sg_frame_stats_d3d11_pipeline pipeline;
+ sg_frame_stats_d3d11_bindings bindings;
+ sg_frame_stats_d3d11_uniforms uniforms;
+ sg_frame_stats_d3d11_draw draw;
+ uint32_t num_map;
+ uint32_t num_unmap;
+} sg_frame_stats_d3d11;
+
+typedef struct sg_frame_stats_metal_idpool {
+ uint32_t num_added;
+ uint32_t num_released;
+ uint32_t num_garbage_collected;
+} sg_frame_stats_metal_idpool;
+
+typedef struct sg_frame_stats_metal_pipeline {
+ uint32_t num_set_blend_color;
+ uint32_t num_set_cull_mode;
+ uint32_t num_set_front_facing_winding;
+ uint32_t num_set_stencil_reference_value;
+ uint32_t num_set_depth_bias;
+ uint32_t num_set_render_pipeline_state;
+ uint32_t num_set_depth_stencil_state;
+} sg_frame_stats_metal_pipeline;
+
+typedef struct sg_frame_stats_metal_bindings {
+ uint32_t num_set_vertex_buffer;
+ uint32_t num_set_vertex_texture;
+ uint32_t num_set_vertex_sampler_state;
+ uint32_t num_set_fragment_buffer;
+ uint32_t num_set_fragment_texture;
+ uint32_t num_set_fragment_sampler_state;
+} sg_frame_stats_metal_bindings;
+
+typedef struct sg_frame_stats_metal_uniforms {
+ uint32_t num_set_vertex_buffer_offset;
+ uint32_t num_set_fragment_buffer_offset;
+} sg_frame_stats_metal_uniforms;
+
+typedef struct sg_frame_stats_metal {
+ sg_frame_stats_metal_idpool idpool;
+ sg_frame_stats_metal_pipeline pipeline;
+ sg_frame_stats_metal_bindings bindings;
+ sg_frame_stats_metal_uniforms uniforms;
+} sg_frame_stats_metal;
+
+typedef struct sg_frame_stats_wgpu_uniforms {
+ uint32_t num_set_bindgroup;
+ uint32_t size_write_buffer;
+} sg_frame_stats_wgpu_uniforms;
+
+typedef struct sg_frame_stats_wgpu_bindings {
+ uint32_t num_set_vertex_buffer;
+ uint32_t num_skip_redundant_vertex_buffer;
+ uint32_t num_set_index_buffer;
+ uint32_t num_skip_redundant_index_buffer;
+ uint32_t num_create_bindgroup;
+ uint32_t num_discard_bindgroup;
+ uint32_t num_set_bindgroup;
+ uint32_t num_skip_redundant_bindgroup;
+ uint32_t num_bindgroup_cache_hits;
+ uint32_t num_bindgroup_cache_misses;
+ uint32_t num_bindgroup_cache_collisions;
+ uint32_t num_bindgroup_cache_invalidates;
+ uint32_t num_bindgroup_cache_hash_vs_key_mismatch;
+} sg_frame_stats_wgpu_bindings;
+
+typedef struct sg_frame_stats_wgpu {
+ sg_frame_stats_wgpu_uniforms uniforms;
+ sg_frame_stats_wgpu_bindings bindings;
+} sg_frame_stats_wgpu;
+
+typedef struct sg_frame_stats {
+ uint32_t frame_index; // current frame counter, starts at 0
+
+ uint32_t num_passes;
+ uint32_t num_apply_viewport;
+ uint32_t num_apply_scissor_rect;
+ uint32_t num_apply_pipeline;
+ uint32_t num_apply_bindings;
+ uint32_t num_apply_uniforms;
+ uint32_t num_draw;
+ uint32_t num_update_buffer;
+ uint32_t num_append_buffer;
+ uint32_t num_update_image;
+
+ uint32_t size_apply_uniforms;
+ uint32_t size_update_buffer;
+ uint32_t size_append_buffer;
+ uint32_t size_update_image;
+
+ sg_frame_stats_gl gl;
+ sg_frame_stats_d3d11 d3d11;
+ sg_frame_stats_metal metal;
+ sg_frame_stats_wgpu wgpu;
+} sg_frame_stats;
+
+/*
+ sg_desc
+
+ The sg_desc struct contains configuration values for sokol_gfx,
+ it is used as parameter to the sg_setup() call.
+
+ The default configuration is:
+
+ .buffer_pool_size 128
+ .image_pool_size 128
+ .sampler_pool_size 64
+ .shader_pool_size 32
+ .pipeline_pool_size 64
+ .pass_pool_size 16
+ .uniform_buffer_size 4 MB (4*1024*1024)
+ .max_commit_listeners 1024
+ .disable_validation false
+ .mtl_force_managed_storage_mode false
+ .wgpu_disable_bindgroups_cache false
+ .wgpu_bindgroups_cache_size 1024
+
+ .allocator.alloc_fn 0 (in this case, malloc() will be called)
+ .allocator.free_fn 0 (in this case, free() will be called)
+ .allocator.user_data 0
+
+ .environment.defaults.color_format: default value depends on selected backend:
+ all GL backends: SG_PIXELFORMAT_RGBA8
+ Metal and D3D11: SG_PIXELFORMAT_BGRA8
+ WebGPU: *no default* (must be queried from WebGPU swapchain object)
+ .environment.defaults.depth_format: SG_PIXELFORMAT_DEPTH_STENCIL
+ .environment.defaults.sample_count: 1
+
+ Metal specific:
+ (NOTE: All Objective-C object references are transferred through
+ a bridged (const void*) to sokol_gfx, which will use a unretained
+ bridged cast (__bridged id) to retrieve the Objective-C
+ references back. Since the bridge cast is unretained, the caller
+ must hold a strong reference to the Objective-C object for the
+ duration of the sokol_gfx call!
+
+ .mtl_force_managed_storage_mode
+ when enabled, Metal buffers and texture resources are created in managed storage
+ mode, otherwise sokol-gfx will decide whether to create buffers and
+ textures in managed or shared storage mode (this is mainly a debugging option)
+ .mtl_use_command_buffer_with_retained_references
+ when true, the sokol-gfx Metal backend will use Metal command buffers which
+ bump the reference count of resource objects as long as they are inflight,
+ this is slower than the default command-buffer-with-unretained-references
+ method, this may be a workaround when confronted with lifetime validation
+ errors from the Metal validation layer until a proper fix has been implemented
+ .environment.metal.device
+ a pointer to the MTLDevice object
+
+ D3D11 specific:
+ .environment.d3d11.device
+ a pointer to the ID3D11Device object, this must have been created
+ before sg_setup() is called
+ .environment.d3d11.device_context
+ a pointer to the ID3D11DeviceContext object
+ .d3d11_shader_debugging
+ set this to true to compile shaders which are provided as HLSL source
+ code with debug information and without optimization, this allows
+ shader debugging in tools like RenderDoc, to output source code
+ instead of byte code from sokol-shdc, omit the `--binary` cmdline
+ option
+
+ WebGPU specific:
+ .wgpu_disable_bindgroups_cache
+ When this is true, the WebGPU backend will create and immediately
+ release a BindGroup object in the sg_apply_bindings() call, only
+ use this for debugging purposes.
+ .wgpu_bindgroups_cache_size
+ The size of the bindgroups cache for re-using BindGroup objects
+ between sg_apply_bindings() calls. The smaller the cache size,
+ the more likely are cache slot collisions which will cause
+ a BindGroups object to be destroyed and a new one created.
+ Use the information returned by sg_query_stats() to check
+ if this is a frequent occurrence, and increase the cache size as
+ needed (the default is 1024).
+ NOTE: wgpu_bindgroups_cache_size must be a power-of-2 number!
+ .environment.wgpu.device
+ a WGPUDevice handle
+
+ When using sokol_gfx.h and sokol_app.h together, consider using the
+ helper function sglue_environment() in the sokol_glue.h header to
+ initialize the sg_desc.environment nested struct. sglue_environment() returns
+ a completely initialized sg_environment struct with information
+ provided by sokol_app.h.
+*/
+typedef struct sg_environment_defaults {
+ sg_pixel_format color_format;
+ sg_pixel_format depth_format;
+ int sample_count;
+} sg_environment_defaults;
+
+typedef struct sg_metal_environment {
+ const void* device;
+} sg_metal_environment;
+
+typedef struct sg_d3d11_environment {
+ const void* device;
+ const void* device_context;
+} sg_d3d11_environment;
+
+typedef struct sg_wgpu_environment {
+ const void* device;
+} sg_wgpu_environment;
+
+typedef struct sg_environment {
+ sg_environment_defaults defaults;
+ sg_metal_environment metal;
+ sg_d3d11_environment d3d11;
+ sg_wgpu_environment wgpu;
+} sg_environment;
+
+/*
+ sg_commit_listener
+
+ Used with function sg_add_commit_listener() to add a callback
+ which will be called in sg_commit(). This is useful for libraries
+ building on top of sokol-gfx to be notified about when a frame
+ ends (instead of having to guess, or add a manual 'new-frame'
+ function.
+*/
+typedef struct sg_commit_listener {
+ void (*func)(void* user_data);
+ void* user_data;
+} sg_commit_listener;
+
+/*
+ sg_allocator
+
+ Used in sg_desc to provide custom memory-alloc and -free functions
+ to sokol_gfx.h. If memory management should be overridden, both the
+ alloc_fn and free_fn function must be provided (e.g. it's not valid to
+ override one function but not the other).
+*/
+typedef struct sg_allocator {
+ void* (*alloc_fn)(size_t size, void* user_data);
+ void (*free_fn)(void* ptr, void* user_data);
+ void* user_data;
+} sg_allocator;
+
+/*
+ sg_logger
+
+ Used in sg_desc to provide a logging function. Please be aware
+ that without logging function, sokol-gfx will be completely
+ silent, e.g. it will not report errors, warnings and
+ validation layer messages. For maximum error verbosity,
+ compile in debug mode (e.g. NDEBUG *not* defined) and provide a
+ compatible logger function in the sg_setup() call
+ (for instance the standard logging function from sokol_log.h).
+*/
+typedef struct sg_logger {
+ void (*func)(
+ const char* tag, // always "sg"
+ uint32_t log_level, // 0=panic, 1=error, 2=warning, 3=info
+ uint32_t log_item_id, // SG_LOGITEM_*
+ const char* message_or_null, // a message string, may be nullptr in release mode
+ uint32_t line_nr, // line number in sokol_gfx.h
+ const char* filename_or_null, // source filename, may be nullptr in release mode
+ void* user_data);
+ void* user_data;
+} sg_logger;
+
+typedef struct sg_desc {
+ uint32_t _start_canary;
+ int buffer_pool_size;
+ int image_pool_size;
+ int sampler_pool_size;
+ int shader_pool_size;
+ int pipeline_pool_size;
+ int attachments_pool_size;
+ int uniform_buffer_size;
+ int max_commit_listeners;
+ bool disable_validation; // disable validation layer even in debug mode, useful for tests
+ bool d3d11_shader_debugging; // if true, HLSL shaders are compiled with D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION
+ bool mtl_force_managed_storage_mode; // for debugging: use Metal managed storage mode for resources even with UMA
+ bool mtl_use_command_buffer_with_retained_references; // Metal: use a managed MTLCommandBuffer which ref-counts used resources
+ bool wgpu_disable_bindgroups_cache; // set to true to disable the WebGPU backend BindGroup cache
+ int wgpu_bindgroups_cache_size; // number of slots in the WebGPU bindgroup cache (must be 2^N)
+ sg_allocator allocator;
+ sg_logger logger; // optional log function override
+ sg_environment environment;
+ uint32_t _end_canary;
+} sg_desc;
+
+// setup and misc functions
+void sg_setup(const sg_desc* desc);
+void sg_shutdown(void);
+bool sg_isvalid(void);
+void sg_reset_state_cache(void);
+sg_trace_hooks sg_install_trace_hooks(const sg_trace_hooks* trace_hooks);
+void sg_push_debug_group(const char* name);
+void sg_pop_debug_group(void);
+bool sg_add_commit_listener(sg_commit_listener listener);
+bool sg_remove_commit_listener(sg_commit_listener listener);
+
+// resource creation, destruction and updating
+sg_buffer sg_make_buffer(const sg_buffer_desc* desc);
+sg_image sg_make_image(const sg_image_desc* desc);
+sg_sampler sg_make_sampler(const sg_sampler_desc* desc);
+sg_shader sg_make_shader(const sg_shader_desc* desc);
+sg_pipeline sg_make_pipeline(const sg_pipeline_desc* desc);
+sg_attachments sg_make_attachments(const sg_attachments_desc* desc);
+void sg_destroy_buffer(sg_buffer buf);
+void sg_destroy_image(sg_image img);
+void sg_destroy_sampler(sg_sampler smp);
+void sg_destroy_shader(sg_shader shd);
+void sg_destroy_pipeline(sg_pipeline pip);
+void sg_destroy_attachments(sg_attachments atts);
+void sg_update_buffer(sg_buffer buf, const sg_range* data);
+void sg_update_image(sg_image img, const sg_image_data* data);
+int sg_append_buffer(sg_buffer buf, const sg_range* data);
+bool sg_query_buffer_overflow(sg_buffer buf);
+bool sg_query_buffer_will_overflow(sg_buffer buf, size_t size);
+
+// rendering functions
+void sg_begin_pass(const sg_pass* pass);
+void sg_apply_viewport(int x, int y, int width, int height, bool origin_top_left);
+void sg_apply_viewportf(float x, float y, float width, float height, bool origin_top_left);
+void sg_apply_scissor_rect(int x, int y, int width, int height, bool origin_top_left);
+void sg_apply_scissor_rectf(float x, float y, float width, float height, bool origin_top_left);
+void sg_apply_pipeline(sg_pipeline pip);
+void sg_apply_bindings(const sg_bindings* bindings);
+void sg_apply_uniforms(sg_shader_stage stage, int ub_index, const sg_range* data);
+void sg_draw(int base_element, int num_elements, int num_instances);
+void sg_end_pass(void);
+void sg_commit(void);
+
+// getting information
+sg_desc sg_query_desc(void);
+sg_backend sg_query_backend(void);
+sg_features sg_query_features(void);
+sg_limits sg_query_limits(void);
+sg_pixelformat_info sg_query_pixelformat(sg_pixel_format fmt);
+int sg_query_row_pitch(sg_pixel_format fmt, int width, int row_align_bytes);
+int sg_query_surface_pitch(sg_pixel_format fmt, int width, int height, int row_align_bytes);
+// get current state of a resource (INITIAL, ALLOC, VALID, FAILED, INVALID)
+sg_resource_state sg_query_buffer_state(sg_buffer buf);
+sg_resource_state sg_query_image_state(sg_image img);
+sg_resource_state sg_query_sampler_state(sg_sampler smp);
+sg_resource_state sg_query_shader_state(sg_shader shd);
+sg_resource_state sg_query_pipeline_state(sg_pipeline pip);
+sg_resource_state sg_query_attachments_state(sg_attachments atts);
+// get runtime information about a resource
+sg_buffer_info sg_query_buffer_info(sg_buffer buf);
+sg_image_info sg_query_image_info(sg_image img);
+sg_sampler_info sg_query_sampler_info(sg_sampler smp);
+sg_shader_info sg_query_shader_info(sg_shader shd);
+sg_pipeline_info sg_query_pipeline_info(sg_pipeline pip);
+sg_attachments_info sg_query_attachments_info(sg_attachments atts);
+// get desc structs matching a specific resource (NOTE that not all creation attributes may be provided)
+sg_buffer_desc sg_query_buffer_desc(sg_buffer buf);
+sg_image_desc sg_query_image_desc(sg_image img);
+sg_sampler_desc sg_query_sampler_desc(sg_sampler smp);
+sg_shader_desc sg_query_shader_desc(sg_shader shd);
+sg_pipeline_desc sg_query_pipeline_desc(sg_pipeline pip);
+sg_attachments_desc sg_query_attachments_desc(sg_attachments atts);
+// get resource creation desc struct with their default values replaced
+sg_buffer_desc sg_query_buffer_defaults(const sg_buffer_desc* desc);
+sg_image_desc sg_query_image_defaults(const sg_image_desc* desc);
+sg_sampler_desc sg_query_sampler_defaults(const sg_sampler_desc* desc);
+sg_shader_desc sg_query_shader_defaults(const sg_shader_desc* desc);
+sg_pipeline_desc sg_query_pipeline_defaults(const sg_pipeline_desc* desc);
+sg_attachments_desc sg_query_attachments_defaults(const sg_attachments_desc* desc);
+
+// separate resource allocation and initialization (for async setup)
+sg_buffer sg_alloc_buffer(void);
+sg_image sg_alloc_image(void);
+sg_sampler sg_alloc_sampler(void);
+sg_shader sg_alloc_shader(void);
+sg_pipeline sg_alloc_pipeline(void);
+sg_attachments sg_alloc_attachments(void);
+void sg_dealloc_buffer(sg_buffer buf);
+void sg_dealloc_image(sg_image img);
+void sg_dealloc_sampler(sg_sampler smp);
+void sg_dealloc_shader(sg_shader shd);
+void sg_dealloc_pipeline(sg_pipeline pip);
+void sg_dealloc_attachments(sg_attachments attachments);
+void sg_init_buffer(sg_buffer buf, const sg_buffer_desc* desc);
+void sg_init_image(sg_image img, const sg_image_desc* desc);
+void sg_init_sampler(sg_sampler smg, const sg_sampler_desc* desc);
+void sg_init_shader(sg_shader shd, const sg_shader_desc* desc);
+void sg_init_pipeline(sg_pipeline pip, const sg_pipeline_desc* desc);
+void sg_init_attachments(sg_attachments attachments, const sg_attachments_desc* desc);
+void sg_uninit_buffer(sg_buffer buf);
+void sg_uninit_image(sg_image img);
+void sg_uninit_sampler(sg_sampler smp);
+void sg_uninit_shader(sg_shader shd);
+void sg_uninit_pipeline(sg_pipeline pip);
+void sg_uninit_attachments(sg_attachments atts);
+void sg_fail_buffer(sg_buffer buf);
+void sg_fail_image(sg_image img);
+void sg_fail_sampler(sg_sampler smp);
+void sg_fail_shader(sg_shader shd);
+void sg_fail_pipeline(sg_pipeline pip);
+void sg_fail_attachments(sg_attachments atts);
+
+// frame stats
+void sg_enable_frame_stats(void);
+void sg_disable_frame_stats(void);
+bool sg_frame_stats_enabled(void);
+sg_frame_stats sg_query_frame_stats(void);
+
+]]
+
+ffi.cdef[[
+
+/********** nuklear ****************************************************************/
+
+enum {
+ NK_UTF_SIZE = 4,
+ NK_INPUT_MAX = 16,
+ NK_MAX_NUMBER_BUFFER = 64,
+ NK_SCROLLBAR_HIDING_TIMEOUT = 4
+};
+
+typedef int8_t NK_INT8;
+typedef uint8_t NK_UINT8;
+typedef int16_t NK_INT16;
+typedef uint16_t NK_UINT16;
+typedef int32_t NK_INT32;
+typedef uint32_t NK_UINT32;
+typedef uintptr_t NK_SIZE_TYPE;
+typedef uintptr_t NK_POINTER_TYPE;
+typedef bool NK_BOOL;
+
+typedef NK_INT8 nk_char;
+typedef NK_UINT8 nk_uchar;
+typedef NK_UINT8 nk_byte;
+typedef NK_INT16 nk_short;
+typedef NK_UINT16 nk_ushort;
+typedef NK_INT32 nk_int;
+typedef NK_UINT32 nk_uint;
+typedef NK_SIZE_TYPE nk_size;
+typedef NK_POINTER_TYPE nk_ptr;
+typedef NK_BOOL nk_bool;
+
+typedef nk_uint nk_hash;
+typedef nk_uint nk_flags;
+typedef nk_uint nk_rune;
+
+/* ============================================================================
+ *
+ * API
+ *
+ * =========================================================================== */
+ struct nk_buffer;
+ struct nk_allocator;
+ struct nk_command_buffer;
+ struct nk_draw_command;
+ struct nk_convert_config;
+ struct nk_style_item;
+ struct nk_text_edit;
+ struct nk_draw_list;
+ struct nk_user_font;
+ struct nk_panel;
+ struct nk_context;
+ struct nk_draw_vertex_layout_element;
+ struct nk_style_button;
+ struct nk_style_toggle;
+ struct nk_style_selectable;
+ struct nk_style_slide;
+ struct nk_style_progress;
+ struct nk_style_scrollbar;
+ struct nk_style_edit;
+ struct nk_style_property;
+ struct nk_style_chart;
+ struct nk_style_combo;
+ struct nk_style_tab;
+ struct nk_style_window_header;
+ struct nk_style_window;
+
+ enum {nk_false, nk_true};
+ struct nk_color {nk_byte r,g,b,a;};
+ struct nk_colorf {float r,g,b,a;};
+ struct nk_vec2 {float x,y;};
+ struct nk_vec2i {short x, y;};
+ struct nk_rect {float x,y,w,h;};
+ struct nk_recti {short x,y,w,h;};
+ typedef char nk_glyph[NK_UTF_SIZE];
+ typedef union {void *ptr; int id;} nk_handle;
+ struct nk_image {nk_handle handle;unsigned short w,h;unsigned short region[4];};
+ struct nk_cursor {struct nk_image img; struct nk_vec2 size, offset;};
+ struct nk_scroll {nk_uint x, y;};
+
+ enum nk_heading {NK_UP, NK_RIGHT, NK_DOWN, NK_LEFT};
+ enum nk_button_behavior {NK_BUTTON_DEFAULT, NK_BUTTON_REPEATER};
+ enum nk_modify {NK_FIXED = nk_false, NK_MODIFIABLE = nk_true};
+ enum nk_orientation {NK_VERTICAL, NK_HORIZONTAL};
+ enum nk_collapse_states {NK_MINIMIZED = nk_false, NK_MAXIMIZED = nk_true};
+ enum nk_show_states {NK_HIDDEN = nk_false, NK_SHOWN = nk_true};
+ enum nk_chart_type {NK_CHART_LINES, NK_CHART_COLUMN, NK_CHART_MAX};
+ enum nk_chart_event {NK_CHART_HOVERING = 0x01, NK_CHART_CLICKED = 0x02};
+ enum nk_color_format {NK_RGB, NK_RGBA};
+ enum nk_popup_type {NK_POPUP_STATIC, NK_POPUP_DYNAMIC};
+ enum nk_layout_format {NK_DYNAMIC, NK_STATIC};
+ enum nk_tree_type {NK_TREE_NODE, NK_TREE_TAB};
+
+ typedef void*(*nk_plugin_alloc)(nk_handle, void *old, nk_size);
+ typedef void (*nk_plugin_free)(nk_handle, void *old);
+ typedef nk_bool(*nk_plugin_filter)(const struct nk_text_edit*, nk_rune unicode);
+ typedef void(*nk_plugin_paste)(nk_handle, struct nk_text_edit*);
+ typedef void(*nk_plugin_copy)(nk_handle, const char*, int len);
+
+ struct nk_allocator {
+ nk_handle userdata;
+ nk_plugin_alloc alloc;
+ nk_plugin_free free;
+ };
+ enum nk_symbol_type {
+ NK_SYMBOL_NONE,
+ NK_SYMBOL_X,
+ NK_SYMBOL_UNDERSCORE,
+ NK_SYMBOL_CIRCLE_SOLID,
+ NK_SYMBOL_CIRCLE_OUTLINE,
+ NK_SYMBOL_RECT_SOLID,
+ NK_SYMBOL_RECT_OUTLINE,
+ NK_SYMBOL_TRIANGLE_UP,
+ NK_SYMBOL_TRIANGLE_DOWN,
+ NK_SYMBOL_TRIANGLE_LEFT,
+ NK_SYMBOL_TRIANGLE_RIGHT,
+ NK_SYMBOL_PLUS,
+ NK_SYMBOL_MINUS,
+ NK_SYMBOL_MAX
+ };
+
+]]
+
+ffi.cdef[[
+
+/* =============================================================================
+ *
+ * CONTEXT
+ *
+ * =============================================================================*/
+/*/// ### Context
+/// Contexts are the main entry point and the majestro of nuklear and contain all required state.
+/// They are used for window, memory, input, style, stack, commands and time management and need
+/// to be passed into all nuklear GUI specific functions.
+///
+/// #### Usage
+/// To use a context it first has to be initialized which can be achieved by calling
+/// one of either `nk_init_default`, `nk_init_fixed`, `nk_init`, `nk_init_custom`.
+/// Each takes in a font handle and a specific way of handling memory. Memory control
+/// hereby ranges from standard library to just specifying a fixed sized block of memory
+/// which nuklear has to manage itself from.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_context ctx;
+/// nk_init_xxx(&ctx, ...);
+/// while (1) {
+/// // [...]
+/// nk_clear(&ctx);
+/// }
+/// nk_free(&ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// #### Reference
+/// Function | Description
+/// --------------------|-------------------------------------------------------
+/// __nk_init_default__ | Initializes context with standard library memory allocation (malloc,free)
+/// __nk_init_fixed__ | Initializes context from single fixed size memory block
+/// __nk_init__ | Initializes context with memory allocator callbacks for alloc and free
+/// __nk_init_custom__ | Initializes context from two buffers. One for draw commands the other for window/panel/table allocations
+/// __nk_clear__ | Called at the end of the frame to reset and prepare the context for the next frame
+/// __nk_free__ | Shutdown and free all memory allocated inside the context
+/// __nk_set_user_data__| Utility function to pass user data to draw command
+ */
+
+/*/// #### nk_init_default
+/// Initializes a `nk_context` struct with a default standard library allocator.
+/// Should be used if you don't want to be bothered with memory management in nuklear.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_init_default(struct nk_context *ctx, const struct nk_user_font *font);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|---------------------------------------------------------------
+/// __ctx__ | Must point to an either stack or heap allocated `nk_context` struct
+/// __font__ | Must point to a previously initialized font handle for more info look at font documentation
+///
+/// Returns either `false(0)` on failure or `true(1)` on success.
+///
+*/
+nk_bool nk_init_default(struct nk_context*, const struct nk_user_font*);
+
+/*/// #### nk_init_fixed
+/// Initializes a `nk_context` struct from single fixed size memory block
+/// Should be used if you want complete control over nuklear's memory management.
+/// Especially recommended for system with little memory or systems with virtual memory.
+/// For the later case you can just allocate for example 16MB of virtual memory
+/// and only the required amount of memory will actually be committed.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size, const struct nk_user_font *font);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// !!! Warning
+/// make sure the passed memory block is aligned correctly for `nk_draw_commands`.
+///
+/// Parameter | Description
+/// ------------|--------------------------------------------------------------
+/// __ctx__ | Must point to an either stack or heap allocated `nk_context` struct
+/// __memory__ | Must point to a previously allocated memory block
+/// __size__ | Must contain the total size of __memory__
+/// __font__ | Must point to a previously initialized font handle for more info look at font documentation
+///
+/// Returns either `false(0)` on failure or `true(1)` on success.
+*/
+nk_bool nk_init_fixed(struct nk_context*, void *memory, nk_size size, const struct nk_user_font*);
+/*/// #### nk_init
+/// Initializes a `nk_context` struct with memory allocation callbacks for nuklear to allocate
+/// memory from. Used internally for `nk_init_default` and provides a kitchen sink allocation
+/// interface to nuklear. Can be useful for cases like monitoring memory consumption.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_init(struct nk_context *ctx, struct nk_allocator *alloc, const struct nk_user_font *font);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|---------------------------------------------------------------
+/// __ctx__ | Must point to an either stack or heap allocated `nk_context` struct
+/// __alloc__ | Must point to a previously allocated memory allocator
+/// __font__ | Must point to a previously initialized font handle for more info look at font documentation
+///
+/// Returns either `false(0)` on failure or `true(1)` on success.
+*/
+nk_bool nk_init(struct nk_context*, struct nk_allocator*, const struct nk_user_font*);
+/*/// #### nk_init_custom
+/// Initializes a `nk_context` struct from two different either fixed or growing
+/// buffers. The first buffer is for allocating draw commands while the second buffer is
+/// used for allocating windows, panels and state tables.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font *font);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|---------------------------------------------------------------
+/// __ctx__ | Must point to an either stack or heap allocated `nk_context` struct
+/// __cmds__ | Must point to a previously initialized memory buffer either fixed or dynamic to store draw commands into
+/// __pool__ | Must point to a previously initialized memory buffer either fixed or dynamic to store windows, panels and tables
+/// __font__ | Must point to a previously initialized font handle for more info look at font documentation
+///
+/// Returns either `false(0)` on failure or `true(1)` on success.
+*/
+nk_bool nk_init_custom(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font*);
+/*/// #### nk_clear
+/// Resets the context state at the end of the frame. This includes mostly
+/// garbage collector tasks like removing windows or table not called and therefore
+/// used anymore.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_clear(struct nk_context *ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to a previously initialized `nk_context` struct
+*/
+void nk_clear(struct nk_context*);
+/*/// #### nk_free
+/// Frees all memory allocated by nuklear. Not needed if context was
+/// initialized with `nk_init_fixed`.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_free(struct nk_context *ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to a previously initialized `nk_context` struct
+*/
+void nk_free(struct nk_context*);
+/* =============================================================================
+ *
+ * INPUT
+ *
+ * =============================================================================*/
+/*/// ### Input
+/// The input API is responsible for holding the current input state composed of
+/// mouse, key and text input states.
+/// It is worth noting that no direct OS or window handling is done in nuklear.
+/// Instead all input state has to be provided by platform specific code. This on one hand
+/// expects more work from the user and complicates usage but on the other hand
+/// provides simple abstraction over a big number of platforms, libraries and other
+/// already provided functionality.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// nk_input_begin(&ctx);
+/// while (GetEvent(&evt)) {
+/// if (evt.type == MOUSE_MOVE)
+/// nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
+/// else if (evt.type == [...]) {
+/// // [...]
+/// }
+/// } nk_input_end(&ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// #### Usage
+/// Input state needs to be provided to nuklear by first calling `nk_input_begin`
+/// which resets internal state like delta mouse position and button transistions.
+/// After `nk_input_begin` all current input state needs to be provided. This includes
+/// mouse motion, button and key pressed and released, text input and scrolling.
+/// Both event- or state-based input handling are supported by this API
+/// and should work without problems. Finally after all input state has been
+/// mirrored `nk_input_end` needs to be called to finish input process.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_context ctx;
+/// nk_init_xxx(&ctx, ...);
+/// while (1) {
+/// Event evt;
+/// nk_input_begin(&ctx);
+/// while (GetEvent(&evt)) {
+/// if (evt.type == MOUSE_MOVE)
+/// nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
+/// else if (evt.type == [...]) {
+/// // [...]
+/// }
+/// }
+/// nk_input_end(&ctx);
+/// // [...]
+/// nk_clear(&ctx);
+/// } nk_free(&ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// #### Reference
+/// Function | Description
+/// --------------------|-------------------------------------------------------
+/// __nk_input_begin__ | Begins the input mirroring process. Needs to be called before all other `nk_input_xxx` calls
+/// __nk_input_motion__ | Mirrors mouse cursor position
+/// __nk_input_key__ | Mirrors key state with either pressed or released
+/// __nk_input_button__ | Mirrors mouse button state with either pressed or released
+/// __nk_input_scroll__ | Mirrors mouse scroll values
+/// __nk_input_char__ | Adds a single ASCII text character into an internal text buffer
+/// __nk_input_glyph__ | Adds a single multi-byte UTF-8 character into an internal text buffer
+/// __nk_input_unicode__| Adds a single unicode rune into an internal text buffer
+/// __nk_input_end__ | Ends the input mirroring process by calculating state changes. Don't call any `nk_input_xxx` function referenced above after this call
+*/
+enum nk_keys {
+ NK_KEY_NONE,
+ NK_KEY_SHIFT,
+ NK_KEY_CTRL,
+ NK_KEY_DEL,
+ NK_KEY_ENTER,
+ NK_KEY_TAB,
+ NK_KEY_BACKSPACE,
+ NK_KEY_COPY,
+ NK_KEY_CUT,
+ NK_KEY_PASTE,
+ NK_KEY_UP,
+ NK_KEY_DOWN,
+ NK_KEY_LEFT,
+ NK_KEY_RIGHT,
+ /* Shortcuts: text field */
+ NK_KEY_TEXT_INSERT_MODE,
+ NK_KEY_TEXT_REPLACE_MODE,
+ NK_KEY_TEXT_RESET_MODE,
+ NK_KEY_TEXT_LINE_START,
+ NK_KEY_TEXT_LINE_END,
+ NK_KEY_TEXT_START,
+ NK_KEY_TEXT_END,
+ NK_KEY_TEXT_UNDO,
+ NK_KEY_TEXT_REDO,
+ NK_KEY_TEXT_SELECT_ALL,
+ NK_KEY_TEXT_WORD_LEFT,
+ NK_KEY_TEXT_WORD_RIGHT,
+ /* Shortcuts: scrollbar */
+ NK_KEY_SCROLL_START,
+ NK_KEY_SCROLL_END,
+ NK_KEY_SCROLL_DOWN,
+ NK_KEY_SCROLL_UP,
+ NK_KEY_MAX
+};
+enum nk_buttons {
+ NK_BUTTON_LEFT,
+ NK_BUTTON_MIDDLE,
+ NK_BUTTON_RIGHT,
+ NK_BUTTON_DOUBLE,
+ NK_BUTTON_MAX
+};
+/*/// #### nk_input_begin
+/// Begins the input mirroring process by resetting text, scroll
+/// mouse, previous mouse position and movement as well as key state transitions,
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_input_begin(struct nk_context*);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to a previously initialized `nk_context` struct
+*/
+void nk_input_begin(struct nk_context*);
+/*/// #### nk_input_motion
+/// Mirrors current mouse position to nuklear
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_input_motion(struct nk_context *ctx, int x, int y);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to a previously initialized `nk_context` struct
+/// __x__ | Must hold an integer describing the current mouse cursor x-position
+/// __y__ | Must hold an integer describing the current mouse cursor y-position
+*/
+void nk_input_motion(struct nk_context*, int x, int y);
+/*/// #### nk_input_key
+/// Mirrors the state of a specific key to nuklear
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_input_key(struct nk_context*, enum nk_keys key, nk_bool down);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to a previously initialized `nk_context` struct
+/// __key__ | Must be any value specified in enum `nk_keys` that needs to be mirrored
+/// __down__ | Must be 0 for key is up and 1 for key is down
+*/
+void nk_input_key(struct nk_context*, enum nk_keys, nk_bool down);
+/*/// #### nk_input_button
+/// Mirrors the state of a specific mouse button to nuklear
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_input_button(struct nk_context *ctx, enum nk_buttons btn, int x, int y, nk_bool down);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to a previously initialized `nk_context` struct
+/// __btn__ | Must be any value specified in enum `nk_buttons` that needs to be mirrored
+/// __x__ | Must contain an integer describing mouse cursor x-position on click up/down
+/// __y__ | Must contain an integer describing mouse cursor y-position on click up/down
+/// __down__ | Must be 0 for key is up and 1 for key is down
+*/
+void nk_input_button(struct nk_context*, enum nk_buttons, int x, int y, nk_bool down);
+/*/// #### nk_input_scroll
+/// Copies the last mouse scroll value to nuklear. Is generally
+/// a scroll value. So does not have to come from mouse and could also originate
+/// TODO finish this sentence
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to a previously initialized `nk_context` struct
+/// __val__ | vector with both X- as well as Y-scroll value
+*/
+void nk_input_scroll(struct nk_context*, struct nk_vec2 val);
+/*/// #### nk_input_char
+/// Copies a single ASCII character into an internal text buffer
+/// This is basically a helper function to quickly push ASCII characters into
+/// nuklear.
+///
+/// !!! Note
+/// Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_input_char(struct nk_context *ctx, char c);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to a previously initialized `nk_context` struct
+/// __c__ | Must be a single ASCII character preferable one that can be printed
+*/
+void nk_input_char(struct nk_context*, char);
+/*/// #### nk_input_glyph
+/// Converts an encoded unicode rune into UTF-8 and copies the result into an
+/// internal text buffer.
+///
+/// !!! Note
+/// Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_input_glyph(struct nk_context *ctx, const nk_glyph g);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to a previously initialized `nk_context` struct
+/// __g__ | UTF-32 unicode codepoint
+*/
+void nk_input_glyph(struct nk_context*, const nk_glyph);
+/*/// #### nk_input_unicode
+/// Converts a unicode rune into UTF-8 and copies the result
+/// into an internal text buffer.
+/// !!! Note
+/// Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_input_unicode(struct nk_context*, nk_rune rune);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to a previously initialized `nk_context` struct
+/// __rune__ | UTF-32 unicode codepoint
+*/
+void nk_input_unicode(struct nk_context*, nk_rune);
+/*/// #### nk_input_end
+/// End the input mirroring process by resetting mouse grabbing
+/// state to ensure the mouse cursor is not grabbed indefinitely.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_input_end(struct nk_context *ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to a previously initialized `nk_context` struct
+*/
+void nk_input_end(struct nk_context*);
+/* =============================================================================
+ *
+ * DRAWING
+ *
+ * =============================================================================*/
+/*/// ### Drawing
+/// This library was designed to be render backend agnostic so it does
+/// not draw anything to screen directly. Instead all drawn shapes, widgets
+/// are made of, are buffered into memory and make up a command queue.
+/// Each frame therefore fills the command buffer with draw commands
+/// that then need to be executed by the user and his own render backend.
+/// After that the command buffer needs to be cleared and a new frame can be
+/// started. It is probably important to note that the command buffer is the main
+/// drawing API and the optional vertex buffer API only takes this format and
+/// converts it into a hardware accessible format.
+///
+/// #### Usage
+/// To draw all draw commands accumulated over a frame you need your own render
+/// backend able to draw a number of 2D primitives. This includes at least
+/// filled and stroked rectangles, circles, text, lines, triangles and scissors.
+/// As soon as this criterion is met you can iterate over each draw command
+/// and execute each draw command in a interpreter like fashion:
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// const struct nk_command *cmd = 0;
+/// nk_foreach(cmd, &ctx) {
+/// switch (cmd->type) {
+/// case NK_COMMAND_LINE:
+/// your_draw_line_function(...)
+/// break;
+/// case NK_COMMAND_RECT
+/// your_draw_rect_function(...)
+/// break;
+/// case //...:
+/// //[...]
+/// }
+/// }
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// In program flow context draw commands need to be executed after input has been
+/// gathered and the complete UI with windows and their contained widgets have
+/// been executed and before calling `nk_clear` which frees all previously
+/// allocated draw commands.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_context ctx;
+/// nk_init_xxx(&ctx, ...);
+/// while (1) {
+/// Event evt;
+/// nk_input_begin(&ctx);
+/// while (GetEvent(&evt)) {
+/// if (evt.type == MOUSE_MOVE)
+/// nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
+/// else if (evt.type == [...]) {
+/// [...]
+/// }
+/// }
+/// nk_input_end(&ctx);
+/// //
+/// // [...]
+/// //
+/// const struct nk_command *cmd = 0;
+/// nk_foreach(cmd, &ctx) {
+/// switch (cmd->type) {
+/// case NK_COMMAND_LINE:
+/// your_draw_line_function(...)
+/// break;
+/// case NK_COMMAND_RECT
+/// your_draw_rect_function(...)
+/// break;
+/// case ...:
+/// // [...]
+/// }
+/// nk_clear(&ctx);
+/// }
+/// nk_free(&ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// You probably noticed that you have to draw all of the UI each frame which is
+/// quite wasteful. While the actual UI updating loop is quite fast rendering
+/// without actually needing it is not. So there are multiple things you could do.
+///
+/// First is only update on input. This of course is only an option if your
+/// application only depends on the UI and does not require any outside calculations.
+/// If you actually only update on input make sure to update the UI two times each
+/// frame and call `nk_clear` directly after the first pass and only draw in
+/// the second pass. In addition it is recommended to also add additional timers
+/// to make sure the UI is not drawn more than a fixed number of frames per second.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_context ctx;
+/// nk_init_xxx(&ctx, ...);
+/// while (1) {
+/// // [...wait for input ]
+/// // [...do two UI passes ...]
+/// do_ui(...)
+/// nk_clear(&ctx);
+/// do_ui(...)
+/// //
+/// // draw
+/// const struct nk_command *cmd = 0;
+/// nk_foreach(cmd, &ctx) {
+/// switch (cmd->type) {
+/// case NK_COMMAND_LINE:
+/// your_draw_line_function(...)
+/// break;
+/// case NK_COMMAND_RECT
+/// your_draw_rect_function(...)
+/// break;
+/// case ...:
+/// //[...]
+/// }
+/// nk_clear(&ctx);
+/// }
+/// nk_free(&ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// The second probably more applicable trick is to only draw if anything changed.
+/// It is not really useful for applications with continuous draw loop but
+/// quite useful for desktop applications. To actually get nuklear to only
+/// draw on changes you first have to define `NK_ZERO_COMMAND_MEMORY` and
+/// allocate a memory buffer that will store each unique drawing output.
+/// After each frame you compare the draw command memory inside the library
+/// with your allocated buffer by memcmp. If memcmp detects differences
+/// you have to copy the command buffer into the allocated buffer
+/// and then draw like usual (this example uses fixed memory but you could
+/// use dynamically allocated memory).
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// //[... other defines ...]
+/// #define NK_ZERO_COMMAND_MEMORY
+/// #include "nuklear.h"
+/// //
+/// // setup context
+/// struct nk_context ctx;
+/// void *last = calloc(1,64*1024);
+/// void *buf = calloc(1,64*1024);
+/// nk_init_fixed(&ctx, buf, 64*1024);
+/// //
+/// // loop
+/// while (1) {
+/// // [...input...]
+/// // [...ui...]
+/// void *cmds = nk_buffer_memory(&ctx.memory);
+/// if (memcmp(cmds, last, ctx.memory.allocated)) {
+/// memcpy(last,cmds,ctx.memory.allocated);
+/// const struct nk_command *cmd = 0;
+/// nk_foreach(cmd, &ctx) {
+/// switch (cmd->type) {
+/// case NK_COMMAND_LINE:
+/// your_draw_line_function(...)
+/// break;
+/// case NK_COMMAND_RECT
+/// your_draw_rect_function(...)
+/// break;
+/// case ...:
+/// // [...]
+/// }
+/// }
+/// }
+/// nk_clear(&ctx);
+/// }
+/// nk_free(&ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Finally while using draw commands makes sense for higher abstracted platforms like
+/// X11 and Win32 or drawing libraries it is often desirable to use graphics
+/// hardware directly. Therefore it is possible to just define
+/// `NK_INCLUDE_VERTEX_BUFFER_OUTPUT` which includes optional vertex output.
+/// To access the vertex output you first have to convert all draw commands into
+/// vertexes by calling `nk_convert` which takes in your preferred vertex format.
+/// After successfully converting all draw commands just iterate over and execute all
+/// vertex draw commands:
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// // fill configuration
+/// struct your_vertex
+/// {
+/// float pos[2]; // important to keep it to 2 floats
+/// float uv[2];
+/// unsigned char col[4];
+/// };
+/// struct nk_convert_config cfg = {};
+/// static const struct nk_draw_vertex_layout_element vertex_layout[] = {
+/// {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, pos)},
+/// {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, uv)},
+/// {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct your_vertex, col)},
+/// {NK_VERTEX_LAYOUT_END}
+/// };
+/// cfg.shape_AA = NK_ANTI_ALIASING_ON;
+/// cfg.line_AA = NK_ANTI_ALIASING_ON;
+/// cfg.vertex_layout = vertex_layout;
+/// cfg.vertex_size = sizeof(struct your_vertex);
+/// cfg.vertex_alignment = NK_ALIGNOF(struct your_vertex);
+/// cfg.circle_segment_count = 22;
+/// cfg.curve_segment_count = 22;
+/// cfg.arc_segment_count = 22;
+/// cfg.global_alpha = 1.0f;
+/// cfg.null = dev->null;
+/// //
+/// // setup buffers and convert
+/// struct nk_buffer cmds, verts, idx;
+/// nk_buffer_init_default(&cmds);
+/// nk_buffer_init_default(&verts);
+/// nk_buffer_init_default(&idx);
+/// nk_convert(&ctx, &cmds, &verts, &idx, &cfg);
+/// //
+/// // draw
+/// nk_draw_foreach(cmd, &ctx, &cmds) {
+/// if (!cmd->elem_count) continue;
+/// //[...]
+/// }
+/// nk_buffer_free(&cms);
+/// nk_buffer_free(&verts);
+/// nk_buffer_free(&idx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// #### Reference
+/// Function | Description
+/// --------------------|-------------------------------------------------------
+/// __nk__begin__ | Returns the first draw command in the context draw command list to be drawn
+/// __nk__next__ | Increments the draw command iterator to the next command inside the context draw command list
+/// __nk_foreach__ | Iterates over each draw command inside the context draw command list
+/// __nk_convert__ | Converts from the abstract draw commands list into a hardware accessible vertex format
+/// __nk_draw_begin__ | Returns the first vertex command in the context vertex draw list to be executed
+/// __nk__draw_next__ | Increments the vertex command iterator to the next command inside the context vertex command list
+/// __nk__draw_end__ | Returns the end of the vertex draw list
+/// __nk_draw_foreach__ | Iterates over each vertex draw command inside the vertex draw list
+*/
+enum nk_anti_aliasing {NK_ANTI_ALIASING_OFF, NK_ANTI_ALIASING_ON};
+enum nk_convert_result {
+ NK_CONVERT_SUCCESS = 0,
+ NK_CONVERT_INVALID_PARAM = 1,
+ NK_CONVERT_COMMAND_BUFFER_FULL = 2,
+ NK_CONVERT_VERTEX_BUFFER_FULL = 4,
+ NK_CONVERT_ELEMENT_BUFFER_FULL = 8
+};
+struct nk_draw_null_texture {
+ nk_handle texture; /* texture handle to a texture with a white pixel */
+ struct nk_vec2 uv; /* coordinates to a white pixel in the texture */
+};
+struct nk_convert_config {
+ float global_alpha; /* global alpha value */
+ enum nk_anti_aliasing line_AA; /* line anti-aliasing flag can be turned off if you are tight on memory */
+ enum nk_anti_aliasing shape_AA; /* shape anti-aliasing flag can be turned off if you are tight on memory */
+ unsigned circle_segment_count; /* number of segments used for circles: default to 22 */
+ unsigned arc_segment_count; /* number of segments used for arcs: default to 22 */
+ unsigned curve_segment_count; /* number of segments used for curves: default to 22 */
+ struct nk_draw_null_texture null; /* handle to texture with a white pixel for shape drawing */
+ const struct nk_draw_vertex_layout_element *vertex_layout; /* describes the vertex output format and packing */
+ nk_size vertex_size; /* sizeof one vertex for vertex packing */
+ nk_size vertex_alignment; /* vertex alignment: Can be obtained by NK_ALIGNOF */
+};
+/*/// #### nk__begin
+/// Returns a draw command list iterator to iterate all draw
+/// commands accumulated over one frame.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// const struct nk_command* nk__begin(struct nk_context*);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | must point to an previously initialized `nk_context` struct at the end of a frame
+///
+/// Returns draw command pointer pointing to the first command inside the draw command list
+*/
+const struct nk_command* nk__begin(struct nk_context*);
+/*/// #### nk__next
+/// Returns draw command pointer pointing to the next command inside the draw command list
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// const struct nk_command* nk__next(struct nk_context*, const struct nk_command*);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame
+/// __cmd__ | Must point to an previously a draw command either returned by `nk__begin` or `nk__next`
+///
+/// Returns draw command pointer pointing to the next command inside the draw command list
+*/
+const struct nk_command* nk__next(struct nk_context*, const struct nk_command*);
+/*/// #### nk_foreach
+/// Iterates over each draw command inside the context draw command list
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// #define nk_foreach(c, ctx)
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame
+/// __cmd__ | Command pointer initialized to NULL
+///
+/// Iterates over each draw command inside the context draw command list
+*/
+/*/// #### nk_convert
+/// Converts all internal draw commands into vertex draw commands and fills
+/// three buffers with vertexes, vertex draw commands and vertex indices. The vertex format
+/// as well as some other configuration values have to be configured by filling out a
+/// `nk_convert_config` struct.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// nk_flags nk_convert(struct nk_context *ctx, struct nk_buffer *cmds,
+/// struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame
+/// __cmds__ | Must point to a previously initialized buffer to hold converted vertex draw commands
+/// __vertices__| Must point to a previously initialized buffer to hold all produced vertices
+/// __elements__| Must point to a previously initialized buffer to hold all produced vertex indices
+/// __config__ | Must point to a filled out `nk_config` struct to configure the conversion process
+///
+/// Returns one of enum nk_convert_result error codes
+///
+/// Parameter | Description
+/// --------------------------------|-----------------------------------------------------------
+/// NK_CONVERT_SUCCESS | Signals a successful draw command to vertex buffer conversion
+/// NK_CONVERT_INVALID_PARAM | An invalid argument was passed in the function call
+/// NK_CONVERT_COMMAND_BUFFER_FULL | The provided buffer for storing draw commands is full or failed to allocate more memory
+/// NK_CONVERT_VERTEX_BUFFER_FULL | The provided buffer for storing vertices is full or failed to allocate more memory
+/// NK_CONVERT_ELEMENT_BUFFER_FULL | The provided buffer for storing indicies is full or failed to allocate more memory
+*/
+nk_flags nk_convert(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*);
+/*/// #### nk__draw_begin
+/// Returns a draw vertex command buffer iterator to iterate over the vertex draw command buffer
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame
+/// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer
+///
+/// Returns vertex draw command pointer pointing to the first command inside the vertex draw command buffer
+*/
+const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*);
+/*/// #### nk__draw_end
+/// Returns the vertex draw command at the end of the vertex draw command buffer
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// const struct nk_draw_command* nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buf);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame
+/// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer
+///
+/// Returns vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer
+*/
+const struct nk_draw_command* nk__draw_end(const struct nk_context*, const struct nk_buffer*);
+/*/// #### nk__draw_next
+/// Increments the vertex draw command buffer iterator
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __cmd__ | Must point to an previously either by `nk__draw_begin` or `nk__draw_next` returned vertex draw command
+/// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer
+/// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame
+///
+/// Returns vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer
+*/
+const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*);
+/*/// #### nk_draw_foreach
+/// Iterates over each vertex draw command inside a vertex draw command buffer
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// #define nk_draw_foreach(cmd,ctx, b)
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __cmd__ | `nk_draw_command`iterator set to NULL
+/// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer
+/// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame
+*/
+/* =============================================================================
+ *
+ * WINDOW
+ *
+ * =============================================================================
+/// ### Window
+/// Windows are the main persistent state used inside nuklear and are life time
+/// controlled by simply "retouching" (i.e. calling) each window each frame.
+/// All widgets inside nuklear can only be added inside the function pair `nk_begin_xxx`
+/// and `nk_end`. Calling any widgets outside these two functions will result in an
+/// assert in debug or no state change in release mode.
+///
+/// Each window holds frame persistent state like position, size, flags, state tables,
+/// and some garbage collected internal persistent widget state. Each window
+/// is linked into a window stack list which determines the drawing and overlapping
+/// order. The topmost window thereby is the currently active window.
+///
+/// To change window position inside the stack occurs either automatically by
+/// user input by being clicked on or programmatically by calling `nk_window_focus`.
+/// Windows by default are visible unless explicitly being defined with flag
+/// `NK_WINDOW_HIDDEN`, the user clicked the close button on windows with flag
+/// `NK_WINDOW_CLOSABLE` or if a window was explicitly hidden by calling
+/// `nk_window_show`. To explicitly close and destroy a window call `nk_window_close`.
+///
+/// #### Usage
+/// To create and keep a window you have to call one of the two `nk_begin_xxx`
+/// functions to start window declarations and `nk_end` at the end. Furthermore it
+/// is recommended to check the return value of `nk_begin_xxx` and only process
+/// widgets inside the window if the value is not 0. Either way you have to call
+/// `nk_end` at the end of window declarations. Furthermore, do not attempt to
+/// nest `nk_begin_xxx` calls which will hopefully result in an assert or if not
+/// in a segmentation fault.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// if (nk_begin_xxx(...) {
+/// // [... widgets ...]
+/// }
+/// nk_end(ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// In the grand concept window and widget declarations need to occur after input
+/// handling and before drawing to screen. Not doing so can result in higher
+/// latency or at worst invalid behavior. Furthermore make sure that `nk_clear`
+/// is called at the end of the frame. While nuklear's default platform backends
+/// already call `nk_clear` for you if you write your own backend not calling
+/// `nk_clear` can cause asserts or even worse undefined behavior.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_context ctx;
+/// nk_init_xxx(&ctx, ...);
+/// while (1) {
+/// Event evt;
+/// nk_input_begin(&ctx);
+/// while (GetEvent(&evt)) {
+/// if (evt.type == MOUSE_MOVE)
+/// nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
+/// else if (evt.type == [...]) {
+/// nk_input_xxx(...);
+/// }
+/// }
+/// nk_input_end(&ctx);
+///
+/// if (nk_begin_xxx(...) {
+/// //[...]
+/// }
+/// nk_end(ctx);
+///
+/// const struct nk_command *cmd = 0;
+/// nk_foreach(cmd, &ctx) {
+/// case NK_COMMAND_LINE:
+/// your_draw_line_function(...)
+/// break;
+/// case NK_COMMAND_RECT
+/// your_draw_rect_function(...)
+/// break;
+/// case //...:
+/// //[...]
+/// }
+/// nk_clear(&ctx);
+/// }
+/// nk_free(&ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// #### Reference
+/// Function | Description
+/// ------------------------------------|----------------------------------------
+/// nk_begin | Starts a new window; needs to be called every frame for every window (unless hidden) or otherwise the window gets removed
+/// nk_begin_titled | Extended window start with separated title and identifier to allow multiple windows with same name but not title
+/// nk_end | Needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup
+//
+/// nk_window_find | Finds and returns the window with give name
+/// nk_window_get_bounds | Returns a rectangle with screen position and size of the currently processed window.
+/// nk_window_get_position | Returns the position of the currently processed window
+/// nk_window_get_size | Returns the size with width and height of the currently processed window
+/// nk_window_get_width | Returns the width of the currently processed window
+/// nk_window_get_height | Returns the height of the currently processed window
+/// nk_window_get_panel | Returns the underlying panel which contains all processing state of the current window
+/// nk_window_get_content_region | Returns the position and size of the currently visible and non-clipped space inside the currently processed window
+/// nk_window_get_content_region_min | Returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window
+/// nk_window_get_content_region_max | Returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window
+/// nk_window_get_content_region_size | Returns the size of the currently visible and non-clipped space inside the currently processed window
+/// nk_window_get_canvas | Returns the draw command buffer. Can be used to draw custom widgets
+/// nk_window_get_scroll | Gets the scroll offset of the current window
+/// nk_window_has_focus | Returns if the currently processed window is currently active
+/// nk_window_is_collapsed | Returns if the window with given name is currently minimized/collapsed
+/// nk_window_is_closed | Returns if the currently processed window was closed
+/// nk_window_is_hidden | Returns if the currently processed window was hidden
+/// nk_window_is_active | Same as nk_window_has_focus for some reason
+/// nk_window_is_hovered | Returns if the currently processed window is currently being hovered by mouse
+/// nk_window_is_any_hovered | Return if any window currently hovered
+/// nk_item_is_any_active | Returns if any window or widgets is currently hovered or active
+//
+/// nk_window_set_bounds | Updates position and size of the currently processed window
+/// nk_window_set_position | Updates position of the currently process window
+/// nk_window_set_size | Updates the size of the currently processed window
+/// nk_window_set_focus | Set the currently processed window as active window
+/// nk_window_set_scroll | Sets the scroll offset of the current window
+//
+/// nk_window_close | Closes the window with given window name which deletes the window at the end of the frame
+/// nk_window_collapse | Collapses the window with given window name
+/// nk_window_collapse_if | Collapses the window with given window name if the given condition was met
+/// nk_window_show | Hides a visible or reshows a hidden window
+/// nk_window_show_if | Hides/shows a window depending on condition
+*/
+/*
+/// #### nk_panel_flags
+/// Flag | Description
+/// ----------------------------|----------------------------------------
+/// NK_WINDOW_BORDER | Draws a border around the window to visually separate window from the background
+/// NK_WINDOW_MOVABLE | The movable flag indicates that a window can be moved by user input or by dragging the window header
+/// NK_WINDOW_SCALABLE | The scalable flag indicates that a window can be scaled by user input by dragging a scaler icon at the button of the window
+/// NK_WINDOW_CLOSABLE | Adds a closable icon into the header
+/// NK_WINDOW_MINIMIZABLE | Adds a minimize icon into the header
+/// NK_WINDOW_NO_SCROLLBAR | Removes the scrollbar from the window
+/// NK_WINDOW_TITLE | Forces a header at the top at the window showing the title
+/// NK_WINDOW_SCROLL_AUTO_HIDE | Automatically hides the window scrollbar if no user interaction: also requires delta time in `nk_context` to be set each frame
+/// NK_WINDOW_BACKGROUND | Always keep window in the background
+/// NK_WINDOW_SCALE_LEFT | Puts window scaler in the left-bottom corner instead right-bottom
+/// NK_WINDOW_NO_INPUT | Prevents window of scaling, moving or getting focus
+///
+/// #### nk_collapse_states
+/// State | Description
+/// ----------------|-----------------------------------------------------------
+/// __NK_MINIMIZED__| UI section is collased and not visibile until maximized
+/// __NK_MAXIMIZED__| UI section is extended and visibile until minimized
+///
+*/
+enum nk_panel_flags {
+ NK_WINDOW_BORDER = 1,
+ NK_WINDOW_MOVABLE = 2,
+ NK_WINDOW_SCALABLE = 4,
+ NK_WINDOW_CLOSABLE = 8,
+ NK_WINDOW_MINIMIZABLE = 16,
+ NK_WINDOW_NO_SCROLLBAR = 32,
+ NK_WINDOW_TITLE = 64,
+ NK_WINDOW_SCROLL_AUTO_HIDE = 128,
+ NK_WINDOW_BACKGROUND = 256,
+ NK_WINDOW_SCALE_LEFT = 512,
+ NK_WINDOW_NO_INPUT = 1024
+};
+/*/// #### nk_begin
+/// Starts a new window; needs to be called every frame for every
+/// window (unless hidden) or otherwise the window gets removed
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __title__ | Window title and identifier. Needs to be persistent over frames to identify the window
+/// __bounds__ | Initial position and window size. However if you do not define `NK_WINDOW_SCALABLE` or `NK_WINDOW_MOVABLE` you can set window position and size every frame
+/// __flags__ | Window flags defined in the nk_panel_flags section with a number of different window behaviors
+///
+/// Returns `true(1)` if the window can be filled up with widgets from this point
+/// until `nk_end` or `false(0)` otherwise for example if minimized
+*/
+nk_bool nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags);
+/*/// #### nk_begin_titled
+/// Extended window start with separated title and identifier to allow multiple
+/// windows with same title but not name
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __name__ | Window identifier. Needs to be persistent over frames to identify the window
+/// __title__ | Window title displayed inside header if flag `NK_WINDOW_TITLE` or either `NK_WINDOW_CLOSABLE` or `NK_WINDOW_MINIMIZED` was set
+/// __bounds__ | Initial position and window size. However if you do not define `NK_WINDOW_SCALABLE` or `NK_WINDOW_MOVABLE` you can set window position and size every frame
+/// __flags__ | Window flags defined in the nk_panel_flags section with a number of different window behaviors
+///
+/// Returns `true(1)` if the window can be filled up with widgets from this point
+/// until `nk_end` or `false(0)` otherwise for example if minimized
+*/
+nk_bool nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags);
+/*/// #### nk_end
+/// Needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup.
+/// All widget calls after this functions will result in asserts or no state changes
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_end(struct nk_context *ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+*/
+void nk_end(struct nk_context *ctx);
+/*/// #### nk_window_find
+/// Finds and returns a window from passed name
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_window *nk_window_find(struct nk_context *ctx, const char *name);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __name__ | Window identifier
+///
+/// Returns a `nk_window` struct pointing to the identified window or NULL if
+/// no window with the given name was found
+*/
+struct nk_window *nk_window_find(struct nk_context *ctx, const char *name);
+/*/// #### nk_window_get_bounds
+/// Returns a rectangle with screen position and size of the currently processed window
+///
+/// !!! WARNING
+/// Only call this function between calls `nk_begin_xxx` and `nk_end`
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_rect nk_window_get_bounds(const struct nk_context *ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+///
+/// Returns a `nk_rect` struct with window upper left window position and size
+*/
+struct nk_rect nk_window_get_bounds(const struct nk_context *ctx);
+/*/// #### nk_window_get_position
+/// Returns the position of the currently processed window.
+///
+/// !!! WARNING
+/// Only call this function between calls `nk_begin_xxx` and `nk_end`
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_vec2 nk_window_get_position(const struct nk_context *ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+///
+/// Returns a `nk_vec2` struct with window upper left position
+*/
+struct nk_vec2 nk_window_get_position(const struct nk_context *ctx);
+/*/// #### nk_window_get_size
+/// Returns the size with width and height of the currently processed window.
+///
+/// !!! WARNING
+/// Only call this function between calls `nk_begin_xxx` and `nk_end`
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_vec2 nk_window_get_size(const struct nk_context *ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+///
+/// Returns a `nk_vec2` struct with window width and height
+*/
+struct nk_vec2 nk_window_get_size(const struct nk_context*);
+/*/// #### nk_window_get_width
+/// Returns the width of the currently processed window.
+///
+/// !!! WARNING
+/// Only call this function between calls `nk_begin_xxx` and `nk_end`
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// float nk_window_get_width(const struct nk_context *ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+///
+/// Returns the current window width
+*/
+float nk_window_get_width(const struct nk_context*);
+/*/// #### nk_window_get_height
+/// Returns the height of the currently processed window.
+///
+/// !!! WARNING
+/// Only call this function between calls `nk_begin_xxx` and `nk_end`
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// float nk_window_get_height(const struct nk_context *ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+///
+/// Returns the current window height
+*/
+float nk_window_get_height(const struct nk_context*);
+/*/// #### nk_window_get_panel
+/// Returns the underlying panel which contains all processing state of the current window.
+///
+/// !!! WARNING
+/// Only call this function between calls `nk_begin_xxx` and `nk_end`
+/// !!! WARNING
+/// Do not keep the returned panel pointer around, it is only valid until `nk_end`
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_panel* nk_window_get_panel(struct nk_context *ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+///
+/// Returns a pointer to window internal `nk_panel` state.
+*/
+struct nk_panel* nk_window_get_panel(struct nk_context*);
+/*/// #### nk_window_get_content_region
+/// Returns the position and size of the currently visible and non-clipped space
+/// inside the currently processed window.
+///
+/// !!! WARNING
+/// Only call this function between calls `nk_begin_xxx` and `nk_end`
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_rect nk_window_get_content_region(struct nk_context *ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+///
+/// Returns `nk_rect` struct with screen position and size (no scrollbar offset)
+/// of the visible space inside the current window
+*/
+struct nk_rect nk_window_get_content_region(struct nk_context*);
+/*/// #### nk_window_get_content_region_min
+/// Returns the upper left position of the currently visible and non-clipped
+/// space inside the currently processed window.
+///
+/// !!! WARNING
+/// Only call this function between calls `nk_begin_xxx` and `nk_end`
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_vec2 nk_window_get_content_region_min(struct nk_context *ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+///
+/// returns `nk_vec2` struct with upper left screen position (no scrollbar offset)
+/// of the visible space inside the current window
+*/
+struct nk_vec2 nk_window_get_content_region_min(struct nk_context*);
+/*/// #### nk_window_get_content_region_max
+/// Returns the lower right screen position of the currently visible and
+/// non-clipped space inside the currently processed window.
+///
+/// !!! WARNING
+/// Only call this function between calls `nk_begin_xxx` and `nk_end`
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_vec2 nk_window_get_content_region_max(struct nk_context *ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+///
+/// Returns `nk_vec2` struct with lower right screen position (no scrollbar offset)
+/// of the visible space inside the current window
+*/
+struct nk_vec2 nk_window_get_content_region_max(struct nk_context*);
+/*/// #### nk_window_get_content_region_size
+/// Returns the size of the currently visible and non-clipped space inside the
+/// currently processed window
+///
+/// !!! WARNING
+/// Only call this function between calls `nk_begin_xxx` and `nk_end`
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_vec2 nk_window_get_content_region_size(struct nk_context *ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+///
+/// Returns `nk_vec2` struct with size the visible space inside the current window
+*/
+struct nk_vec2 nk_window_get_content_region_size(struct nk_context*);
+/*/// #### nk_window_get_canvas
+/// Returns the draw command buffer. Can be used to draw custom widgets
+/// !!! WARNING
+/// Only call this function between calls `nk_begin_xxx` and `nk_end`
+/// !!! WARNING
+/// Do not keep the returned command buffer pointer around it is only valid until `nk_end`
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_command_buffer* nk_window_get_canvas(struct nk_context *ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+///
+/// Returns a pointer to window internal `nk_command_buffer` struct used as
+/// drawing canvas. Can be used to do custom drawing.
+*/
+struct nk_command_buffer* nk_window_get_canvas(struct nk_context*);
+/*/// #### nk_window_get_scroll
+/// Gets the scroll offset for the current window
+/// !!! WARNING
+/// Only call this function between calls `nk_begin_xxx` and `nk_end`
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_window_get_scroll(struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// -------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __offset_x__ | A pointer to the x offset output (or NULL to ignore)
+/// __offset_y__ | A pointer to the y offset output (or NULL to ignore)
+*/
+void nk_window_get_scroll(struct nk_context*, nk_uint *offset_x, nk_uint *offset_y);
+/*/// #### nk_window_has_focus
+/// Returns if the currently processed window is currently active
+/// !!! WARNING
+/// Only call this function between calls `nk_begin_xxx` and `nk_end`
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_window_has_focus(const struct nk_context *ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+///
+/// Returns `false(0)` if current window is not active or `true(1)` if it is
+*/
+nk_bool nk_window_has_focus(const struct nk_context*);
+/*/// #### nk_window_is_hovered
+/// Return if the current window is being hovered
+/// !!! WARNING
+/// Only call this function between calls `nk_begin_xxx` and `nk_end`
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_window_is_hovered(struct nk_context *ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+///
+/// Returns `true(1)` if current window is hovered or `false(0)` otherwise
+*/
+nk_bool nk_window_is_hovered(struct nk_context*);
+/*/// #### nk_window_is_collapsed
+/// Returns if the window with given name is currently minimized/collapsed
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_window_is_collapsed(struct nk_context *ctx, const char *name);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __name__ | Identifier of window you want to check if it is collapsed
+///
+/// Returns `true(1)` if current window is minimized and `false(0)` if window not
+/// found or is not minimized
+*/
+nk_bool nk_window_is_collapsed(struct nk_context *ctx, const char *name);
+/*/// #### nk_window_is_closed
+/// Returns if the window with given name was closed by calling `nk_close`
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_window_is_closed(struct nk_context *ctx, const char *name);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __name__ | Identifier of window you want to check if it is closed
+///
+/// Returns `true(1)` if current window was closed or `false(0)` window not found or not closed
+*/
+nk_bool nk_window_is_closed(struct nk_context*, const char*);
+/*/// #### nk_window_is_hidden
+/// Returns if the window with given name is hidden
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_window_is_hidden(struct nk_context *ctx, const char *name);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __name__ | Identifier of window you want to check if it is hidden
+///
+/// Returns `true(1)` if current window is hidden or `false(0)` window not found or visible
+*/
+nk_bool nk_window_is_hidden(struct nk_context*, const char*);
+/*/// #### nk_window_is_active
+/// Same as nk_window_has_focus for some reason
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_window_is_active(struct nk_context *ctx, const char *name);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __name__ | Identifier of window you want to check if it is active
+///
+/// Returns `true(1)` if current window is active or `false(0)` window not found or not active
+*/
+nk_bool nk_window_is_active(struct nk_context*, const char*);
+/*/// #### nk_window_is_any_hovered
+/// Returns if the any window is being hovered
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_window_is_any_hovered(struct nk_context*);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+///
+/// Returns `true(1)` if any window is hovered or `false(0)` otherwise
+*/
+nk_bool nk_window_is_any_hovered(struct nk_context*);
+/*/// #### nk_item_is_any_active
+/// Returns if the any window is being hovered or any widget is currently active.
+/// Can be used to decide if input should be processed by UI or your specific input handling.
+/// Example could be UI and 3D camera to move inside a 3D space.
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_item_is_any_active(struct nk_context*);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+///
+/// Returns `true(1)` if any window is hovered or any item is active or `false(0)` otherwise
+*/
+nk_bool nk_item_is_any_active(struct nk_context*);
+/*/// #### nk_window_set_bounds
+/// Updates position and size of window with passed in name
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __name__ | Identifier of the window to modify both position and size
+/// __bounds__ | Must point to a `nk_rect` struct with the new position and size
+*/
+void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds);
+/*/// #### nk_window_set_position
+/// Updates position of window with passed name
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __name__ | Identifier of the window to modify both position
+/// __pos__ | Must point to a `nk_vec2` struct with the new position
+*/
+void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos);
+/*/// #### nk_window_set_size
+/// Updates size of window with passed in name
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __name__ | Identifier of the window to modify both window size
+/// __size__ | Must point to a `nk_vec2` struct with new window size
+*/
+void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2);
+/*/// #### nk_window_set_focus
+/// Sets the window with given name as active
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_window_set_focus(struct nk_context*, const char *name);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __name__ | Identifier of the window to set focus on
+*/
+void nk_window_set_focus(struct nk_context*, const char *name);
+/*/// #### nk_window_set_scroll
+/// Sets the scroll offset for the current window
+/// !!! WARNING
+/// Only call this function between calls `nk_begin_xxx` and `nk_end`
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_window_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// -------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __offset_x__ | The x offset to scroll to
+/// __offset_y__ | The y offset to scroll to
+*/
+void nk_window_set_scroll(struct nk_context*, nk_uint offset_x, nk_uint offset_y);
+/*/// #### nk_window_close
+/// Closes a window and marks it for being freed at the end of the frame
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_window_close(struct nk_context *ctx, const char *name);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __name__ | Identifier of the window to close
+*/
+void nk_window_close(struct nk_context *ctx, const char *name);
+/*/// #### nk_window_collapse
+/// Updates collapse state of a window with given name
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __name__ | Identifier of the window to close
+/// __state__ | value out of nk_collapse_states section
+*/
+void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state);
+/*/// #### nk_window_collapse_if
+/// Updates collapse state of a window with given name if given condition is met
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __name__ | Identifier of the window to either collapse or maximize
+/// __state__ | value out of nk_collapse_states section the window should be put into
+/// __cond__ | condition that has to be met to actually commit the collapse state change
+*/
+void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond);
+/*/// #### nk_window_show
+/// updates visibility state of a window with given name
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_window_show(struct nk_context*, const char *name, enum nk_show_states);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __name__ | Identifier of the window to either collapse or maximize
+/// __state__ | state with either visible or hidden to modify the window with
+*/
+void nk_window_show(struct nk_context*, const char *name, enum nk_show_states);
+/*/// #### nk_window_show_if
+/// Updates visibility state of a window with given name if a given condition is met
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __name__ | Identifier of the window to either hide or show
+/// __state__ | state with either visible or hidden to modify the window with
+/// __cond__ | condition that has to be met to actually commit the visbility state change
+*/
+void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond);
+/* =============================================================================
+ *
+ * LAYOUT
+ *
+ * =============================================================================
+/// ### Layouting
+/// Layouting in general describes placing widget inside a window with position and size.
+/// While in this particular implementation there are five different APIs for layouting
+/// each with different trade offs between control and ease of use.
+///
+/// All layouting methods in this library are based around the concept of a row.
+/// A row has a height the window content grows by and a number of columns and each
+/// layouting method specifies how each widget is placed inside the row.
+/// After a row has been allocated by calling a layouting functions and then
+/// filled with widgets will advance an internal pointer over the allocated row.
+///
+/// To actually define a layout you just call the appropriate layouting function
+/// and each subsequent widget call will place the widget as specified. Important
+/// here is that if you define more widgets then columns defined inside the layout
+/// functions it will allocate the next row without you having to make another layouting
+/// call.
+///
+/// Biggest limitation with using all these APIs outside the `nk_layout_space_xxx` API
+/// is that you have to define the row height for each. However the row height
+/// often depends on the height of the font.
+///
+/// To fix that internally nuklear uses a minimum row height that is set to the
+/// height plus padding of currently active font and overwrites the row height
+/// value if zero.
+///
+/// If you manually want to change the minimum row height then
+/// use nk_layout_set_min_row_height, and use nk_layout_reset_min_row_height to
+/// reset it back to be derived from font height.
+///
+/// Also if you change the font in nuklear it will automatically change the minimum
+/// row height for you and. This means if you change the font but still want
+/// a minimum row height smaller than the font you have to repush your value.
+///
+/// For actually more advanced UI I would even recommend using the `nk_layout_space_xxx`
+/// layouting method in combination with a cassowary constraint solver (there are
+/// some versions on github with permissive license model) to take over all control over widget
+/// layouting yourself. However for quick and dirty layouting using all the other layouting
+/// functions should be fine.
+///
+/// #### Usage
+/// 1. __nk_layout_row_dynamic__
+/// The easiest layouting function is `nk_layout_row_dynamic`. It provides each
+/// widgets with same horizontal space inside the row and dynamically grows
+/// if the owning window grows in width. So the number of columns dictates
+/// the size of each widget dynamically by formula:
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// widget_width = (window_width - padding - spacing) * (1/colum_count)
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Just like all other layouting APIs if you define more widget than columns this
+/// library will allocate a new row and keep all layouting parameters previously
+/// defined.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// if (nk_begin_xxx(...) {
+/// // first row with height: 30 composed of two widgets
+/// nk_layout_row_dynamic(&ctx, 30, 2);
+/// nk_widget(...);
+/// nk_widget(...);
+/// //
+/// // second row with same parameter as defined above
+/// nk_widget(...);
+/// nk_widget(...);
+/// //
+/// // third row uses 0 for height which will use auto layouting
+/// nk_layout_row_dynamic(&ctx, 0, 2);
+/// nk_widget(...);
+/// nk_widget(...);
+/// }
+/// nk_end(...);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// 2. __nk_layout_row_static__
+/// Another easy layouting function is `nk_layout_row_static`. It provides each
+/// widget with same horizontal pixel width inside the row and does not grow
+/// if the owning window scales smaller or bigger.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// if (nk_begin_xxx(...) {
+/// // first row with height: 30 composed of two widgets with width: 80
+/// nk_layout_row_static(&ctx, 30, 80, 2);
+/// nk_widget(...);
+/// nk_widget(...);
+/// //
+/// // second row with same parameter as defined above
+/// nk_widget(...);
+/// nk_widget(...);
+/// //
+/// // third row uses 0 for height which will use auto layouting
+/// nk_layout_row_static(&ctx, 0, 80, 2);
+/// nk_widget(...);
+/// nk_widget(...);
+/// }
+/// nk_end(...);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// 3. __nk_layout_row_xxx__
+/// A little bit more advanced layouting API are functions `nk_layout_row_begin`,
+/// `nk_layout_row_push` and `nk_layout_row_end`. They allow to directly
+/// specify each column pixel or window ratio in a row. It supports either
+/// directly setting per column pixel width or widget window ratio but not
+/// both. Furthermore it is a immediate mode API so each value is directly
+/// pushed before calling a widget. Therefore the layout is not automatically
+/// repeating like the last two layouting functions.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// if (nk_begin_xxx(...) {
+/// // first row with height: 25 composed of two widgets with width 60 and 40
+/// nk_layout_row_begin(ctx, NK_STATIC, 25, 2);
+/// nk_layout_row_push(ctx, 60);
+/// nk_widget(...);
+/// nk_layout_row_push(ctx, 40);
+/// nk_widget(...);
+/// nk_layout_row_end(ctx);
+/// //
+/// // second row with height: 25 composed of two widgets with window ratio 0.25 and 0.75
+/// nk_layout_row_begin(ctx, NK_DYNAMIC, 25, 2);
+/// nk_layout_row_push(ctx, 0.25f);
+/// nk_widget(...);
+/// nk_layout_row_push(ctx, 0.75f);
+/// nk_widget(...);
+/// nk_layout_row_end(ctx);
+/// //
+/// // third row with auto generated height: composed of two widgets with window ratio 0.25 and 0.75
+/// nk_layout_row_begin(ctx, NK_DYNAMIC, 0, 2);
+/// nk_layout_row_push(ctx, 0.25f);
+/// nk_widget(...);
+/// nk_layout_row_push(ctx, 0.75f);
+/// nk_widget(...);
+/// nk_layout_row_end(ctx);
+/// }
+/// nk_end(...);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// 4. __nk_layout_row__
+/// The array counterpart to API nk_layout_row_xxx is the single nk_layout_row
+/// functions. Instead of pushing either pixel or window ratio for every widget
+/// it allows to define it by array. The trade of for less control is that
+/// `nk_layout_row` is automatically repeating. Otherwise the behavior is the
+/// same.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// if (nk_begin_xxx(...) {
+/// // two rows with height: 30 composed of two widgets with width 60 and 40
+/// const float size[] = {60,40};
+/// nk_layout_row(ctx, NK_STATIC, 30, 2, ratio);
+/// nk_widget(...);
+/// nk_widget(...);
+/// nk_widget(...);
+/// nk_widget(...);
+/// //
+/// // two rows with height: 30 composed of two widgets with window ratio 0.25 and 0.75
+/// const float ratio[] = {0.25, 0.75};
+/// nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio);
+/// nk_widget(...);
+/// nk_widget(...);
+/// nk_widget(...);
+/// nk_widget(...);
+/// //
+/// // two rows with auto generated height composed of two widgets with window ratio 0.25 and 0.75
+/// const float ratio[] = {0.25, 0.75};
+/// nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio);
+/// nk_widget(...);
+/// nk_widget(...);
+/// nk_widget(...);
+/// nk_widget(...);
+/// }
+/// nk_end(...);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// 5. __nk_layout_row_template_xxx__
+/// The most complex and second most flexible API is a simplified flexbox version without
+/// line wrapping and weights for dynamic widgets. It is an immediate mode API but
+/// unlike `nk_layout_row_xxx` it has auto repeat behavior and needs to be called
+/// before calling the templated widgets.
+/// The row template layout has three different per widget size specifier. The first
+/// one is the `nk_layout_row_template_push_static` with fixed widget pixel width.
+/// They do not grow if the row grows and will always stay the same.
+/// The second size specifier is `nk_layout_row_template_push_variable`
+/// which defines a minimum widget size but it also can grow if more space is available
+/// not taken by other widgets.
+/// Finally there are dynamic widgets with `nk_layout_row_template_push_dynamic`
+/// which are completely flexible and unlike variable widgets can even shrink
+/// to zero if not enough space is provided.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// if (nk_begin_xxx(...) {
+/// // two rows with height: 30 composed of three widgets
+/// nk_layout_row_template_begin(ctx, 30);
+/// nk_layout_row_template_push_dynamic(ctx);
+/// nk_layout_row_template_push_variable(ctx, 80);
+/// nk_layout_row_template_push_static(ctx, 80);
+/// nk_layout_row_template_end(ctx);
+/// //
+/// // first row
+/// nk_widget(...); // dynamic widget can go to zero if not enough space
+/// nk_widget(...); // variable widget with min 80 pixel but can grow bigger if enough space
+/// nk_widget(...); // static widget with fixed 80 pixel width
+/// //
+/// // second row same layout
+/// nk_widget(...);
+/// nk_widget(...);
+/// nk_widget(...);
+/// }
+/// nk_end(...);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// 6. __nk_layout_space_xxx__
+/// Finally the most flexible API directly allows you to place widgets inside the
+/// window. The space layout API is an immediate mode API which does not support
+/// row auto repeat and directly sets position and size of a widget. Position
+/// and size hereby can be either specified as ratio of allocated space or
+/// allocated space local position and pixel size. Since this API is quite
+/// powerful there are a number of utility functions to get the available space
+/// and convert between local allocated space and screen space.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// if (nk_begin_xxx(...) {
+/// // static row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered)
+/// nk_layout_space_begin(ctx, NK_STATIC, 500, INT_MAX);
+/// nk_layout_space_push(ctx, nk_rect(0,0,150,200));
+/// nk_widget(...);
+/// nk_layout_space_push(ctx, nk_rect(200,200,100,200));
+/// nk_widget(...);
+/// nk_layout_space_end(ctx);
+/// //
+/// // dynamic row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered)
+/// nk_layout_space_begin(ctx, NK_DYNAMIC, 500, INT_MAX);
+/// nk_layout_space_push(ctx, nk_rect(0.5,0.5,0.1,0.1));
+/// nk_widget(...);
+/// nk_layout_space_push(ctx, nk_rect(0.7,0.6,0.1,0.1));
+/// nk_widget(...);
+/// }
+/// nk_end(...);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// #### Reference
+/// Function | Description
+/// ----------------------------------------|------------------------------------
+/// nk_layout_set_min_row_height | Set the currently used minimum row height to a specified value
+/// nk_layout_reset_min_row_height | Resets the currently used minimum row height to font height
+/// nk_layout_widget_bounds | Calculates current width a static layout row can fit inside a window
+/// nk_layout_ratio_from_pixel | Utility functions to calculate window ratio from pixel size
+//
+/// nk_layout_row_dynamic | Current layout is divided into n same sized growing columns
+/// nk_layout_row_static | Current layout is divided into n same fixed sized columns
+/// nk_layout_row_begin | Starts a new row with given height and number of columns
+/// nk_layout_row_push | Pushes another column with given size or window ratio
+/// nk_layout_row_end | Finished previously started row
+/// nk_layout_row | Specifies row columns in array as either window ratio or size
+//
+/// nk_layout_row_template_begin | Begins the row template declaration
+/// nk_layout_row_template_push_dynamic | Adds a dynamic column that dynamically grows and can go to zero if not enough space
+/// nk_layout_row_template_push_variable | Adds a variable column that dynamically grows but does not shrink below specified pixel width
+/// nk_layout_row_template_push_static | Adds a static column that does not grow and will always have the same size
+/// nk_layout_row_template_end | Marks the end of the row template
+//
+/// nk_layout_space_begin | Begins a new layouting space that allows to specify each widgets position and size
+/// nk_layout_space_push | Pushes position and size of the next widget in own coordinate space either as pixel or ratio
+/// nk_layout_space_end | Marks the end of the layouting space
+//
+/// nk_layout_space_bounds | Callable after nk_layout_space_begin and returns total space allocated
+/// nk_layout_space_to_screen | Converts vector from nk_layout_space coordinate space into screen space
+/// nk_layout_space_to_local | Converts vector from screen space into nk_layout_space coordinates
+/// nk_layout_space_rect_to_screen | Converts rectangle from nk_layout_space coordinate space into screen space
+/// nk_layout_space_rect_to_local | Converts rectangle from screen space into nk_layout_space coordinates
+*/
+/*/// #### nk_layout_set_min_row_height
+/// Sets the currently used minimum row height.
+/// !!! WARNING
+/// The passed height needs to include both your preferred row height
+/// as well as padding. No internal padding is added.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_layout_set_min_row_height(struct nk_context*, float height);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
+/// __height__ | New minimum row height to be used for auto generating the row height
+*/
+void nk_layout_set_min_row_height(struct nk_context*, float height);
+/*/// #### nk_layout_reset_min_row_height
+/// Reset the currently used minimum row height back to `font_height + text_padding + padding`
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_layout_reset_min_row_height(struct nk_context*);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
+*/
+void nk_layout_reset_min_row_height(struct nk_context*);
+/*/// #### nk_layout_widget_bounds
+/// Returns the width of the next row allocate by one of the layouting functions
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_rect nk_layout_widget_bounds(struct nk_context*);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
+///
+/// Return `nk_rect` with both position and size of the next row
+*/
+struct nk_rect nk_layout_widget_bounds(struct nk_context*);
+/*/// #### nk_layout_ratio_from_pixel
+/// Utility functions to calculate window ratio from pixel size
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
+/// __pixel__ | Pixel_width to convert to window ratio
+///
+/// Returns `nk_rect` with both position and size of the next row
+*/
+float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width);
+/*/// #### nk_layout_row_dynamic
+/// Sets current row layout to share horizontal space
+/// between @cols number of widgets evenly. Once called all subsequent widget
+/// calls greater than @cols will allocate a new row with same layout.
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
+/// __height__ | Holds height of each widget in row or zero for auto layouting
+/// __columns__ | Number of widget inside row
+*/
+void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols);
+/*/// #### nk_layout_row_static
+/// Sets current row layout to fill @cols number of widgets
+/// in row with same @item_width horizontal size. Once called all subsequent widget
+/// calls greater than @cols will allocate a new row with same layout.
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
+/// __height__ | Holds height of each widget in row or zero for auto layouting
+/// __width__ | Holds pixel width of each widget in the row
+/// __columns__ | Number of widget inside row
+*/
+void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols);
+/*/// #### nk_layout_row_begin
+/// Starts a new dynamic or fixed row with given height and columns.
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
+/// __fmt__ | either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
+/// __height__ | holds height of each widget in row or zero for auto layouting
+/// __columns__ | Number of widget inside row
+*/
+void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols);
+/*/// #### nk_layout_row_push
+/// Specifies either window ratio or width of a single column
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_layout_row_push(struct nk_context*, float value);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
+/// __value__ | either a window ratio or fixed width depending on @fmt in previous `nk_layout_row_begin` call
+*/
+void nk_layout_row_push(struct nk_context*, float value);
+/*/// #### nk_layout_row_end
+/// Finished previously started row
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_layout_row_end(struct nk_context*);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
+*/
+void nk_layout_row_end(struct nk_context*);
+/*/// #### nk_layout_row
+/// Specifies row columns in array as either window ratio or size
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
+/// __fmt__ | Either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
+/// __height__ | Holds height of each widget in row or zero for auto layouting
+/// __columns__ | Number of widget inside row
+*/
+void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio);
+/*/// #### nk_layout_row_template_begin
+/// Begins the row template declaration
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_layout_row_template_begin(struct nk_context*, float row_height);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
+/// __height__ | Holds height of each widget in row or zero for auto layouting
+*/
+void nk_layout_row_template_begin(struct nk_context*, float row_height);
+/*/// #### nk_layout_row_template_push_dynamic
+/// Adds a dynamic column that dynamically grows and can go to zero if not enough space
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_layout_row_template_push_dynamic(struct nk_context*);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
+/// __height__ | Holds height of each widget in row or zero for auto layouting
+*/
+void nk_layout_row_template_push_dynamic(struct nk_context*);
+/*/// #### nk_layout_row_template_push_variable
+/// Adds a variable column that dynamically grows but does not shrink below specified pixel width
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_layout_row_template_push_variable(struct nk_context*, float min_width);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
+/// __width__ | Holds the minimum pixel width the next column must always be
+*/
+void nk_layout_row_template_push_variable(struct nk_context*, float min_width);
+/*/// #### nk_layout_row_template_push_static
+/// Adds a static column that does not grow and will always have the same size
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_layout_row_template_push_static(struct nk_context*, float width);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
+/// __width__ | Holds the absolute pixel width value the next column must be
+*/
+void nk_layout_row_template_push_static(struct nk_context*, float width);
+/*/// #### nk_layout_row_template_end
+/// Marks the end of the row template
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_layout_row_template_end(struct nk_context*);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
+*/
+void nk_layout_row_template_end(struct nk_context*);
+/*/// #### nk_layout_space_begin
+/// Begins a new layouting space that allows to specify each widgets position and size.
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
+/// __fmt__ | Either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
+/// __height__ | Holds height of each widget in row or zero for auto layouting
+/// __columns__ | Number of widgets inside row
+*/
+void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count);
+/*/// #### nk_layout_space_push
+/// Pushes position and size of the next widget in own coordinate space either as pixel or ratio
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_layout_space_push(struct nk_context *ctx, struct nk_rect bounds);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
+/// __bounds__ | Position and size in laoyut space local coordinates
+*/
+void nk_layout_space_push(struct nk_context*, struct nk_rect bounds);
+/*/// #### nk_layout_space_end
+/// Marks the end of the layout space
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_layout_space_end(struct nk_context*);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
+*/
+void nk_layout_space_end(struct nk_context*);
+/*/// #### nk_layout_space_bounds
+/// Utility function to calculate total space allocated for `nk_layout_space`
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_rect nk_layout_space_bounds(struct nk_context*);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
+///
+/// Returns `nk_rect` holding the total space allocated
+*/
+struct nk_rect nk_layout_space_bounds(struct nk_context*);
+/*/// #### nk_layout_space_to_screen
+/// Converts vector from nk_layout_space coordinate space into screen space
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_vec2 nk_layout_space_to_screen(struct nk_context*, struct nk_vec2);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
+/// __vec__ | Position to convert from layout space into screen coordinate space
+///
+/// Returns transformed `nk_vec2` in screen space coordinates
+*/
+struct nk_vec2 nk_layout_space_to_screen(struct nk_context*, struct nk_vec2);
+/*/// #### nk_layout_space_to_local
+/// Converts vector from layout space into screen space
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
+/// __vec__ | Position to convert from screen space into layout coordinate space
+///
+/// Returns transformed `nk_vec2` in layout space coordinates
+*/
+struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2);
+/*/// #### nk_layout_space_rect_to_screen
+/// Converts rectangle from screen space into layout space
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_rect nk_layout_space_rect_to_screen(struct nk_context*, struct nk_rect);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
+/// __bounds__ | Rectangle to convert from layout space into screen space
+///
+/// Returns transformed `nk_rect` in screen space coordinates
+*/
+struct nk_rect nk_layout_space_rect_to_screen(struct nk_context*, struct nk_rect);
+/*/// #### nk_layout_space_rect_to_local
+/// Converts rectangle from layout space into screen space
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct nk_rect);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
+/// __bounds__ | Rectangle to convert from layout space into screen space
+///
+/// Returns transformed `nk_rect` in layout space coordinates
+*/
+struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct nk_rect);
+/* =============================================================================
+ *
+ * GROUP
+ *
+ * =============================================================================
+/// ### Groups
+/// Groups are basically windows inside windows. They allow to subdivide space
+/// in a window to layout widgets as a group. Almost all more complex widget
+/// layouting requirements can be solved using groups and basic layouting
+/// fuctionality. Groups just like windows are identified by an unique name and
+/// internally keep track of scrollbar offsets by default. However additional
+/// versions are provided to directly manage the scrollbar.
+///
+/// #### Usage
+/// To create a group you have to call one of the three `nk_group_begin_xxx`
+/// functions to start group declarations and `nk_group_end` at the end. Furthermore it
+/// is required to check the return value of `nk_group_begin_xxx` and only process
+/// widgets inside the window if the value is not 0.
+/// Nesting groups is possible and even encouraged since many layouting schemes
+/// can only be achieved by nesting. Groups, unlike windows, need `nk_group_end`
+/// to be only called if the corosponding `nk_group_begin_xxx` call does not return 0:
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// if (nk_group_begin_xxx(ctx, ...) {
+/// // [... widgets ...]
+/// nk_group_end(ctx);
+/// }
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// In the grand concept groups can be called after starting a window
+/// with `nk_begin_xxx` and before calling `nk_end`:
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// struct nk_context ctx;
+/// nk_init_xxx(&ctx, ...);
+/// while (1) {
+/// // Input
+/// Event evt;
+/// nk_input_begin(&ctx);
+/// while (GetEvent(&evt)) {
+/// if (evt.type == MOUSE_MOVE)
+/// nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
+/// else if (evt.type == [...]) {
+/// nk_input_xxx(...);
+/// }
+/// }
+/// nk_input_end(&ctx);
+/// //
+/// // Window
+/// if (nk_begin_xxx(...) {
+/// // [...widgets...]
+/// nk_layout_row_dynamic(...);
+/// if (nk_group_begin_xxx(ctx, ...) {
+/// //[... widgets ...]
+/// nk_group_end(ctx);
+/// }
+/// }
+/// nk_end(ctx);
+/// //
+/// // Draw
+/// const struct nk_command *cmd = 0;
+/// nk_foreach(cmd, &ctx) {
+/// switch (cmd->type) {
+/// case NK_COMMAND_LINE:
+/// your_draw_line_function(...)
+/// break;
+/// case NK_COMMAND_RECT
+/// your_draw_rect_function(...)
+/// break;
+/// case ...:
+/// // [...]
+/// }
+/// nk_clear(&ctx);
+/// }
+/// nk_free(&ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+/// #### Reference
+/// Function | Description
+/// --------------------------------|-------------------------------------------
+/// nk_group_begin | Start a new group with internal scrollbar handling
+/// nk_group_begin_titled | Start a new group with separeted name and title and internal scrollbar handling
+/// nk_group_end | Ends a group. Should only be called if nk_group_begin returned non-zero
+/// nk_group_scrolled_offset_begin | Start a new group with manual separated handling of scrollbar x- and y-offset
+/// nk_group_scrolled_begin | Start a new group with manual scrollbar handling
+/// nk_group_scrolled_end | Ends a group with manual scrollbar handling. Should only be called if nk_group_begin returned non-zero
+/// nk_group_get_scroll | Gets the scroll offset for the given group
+/// nk_group_set_scroll | Sets the scroll offset for the given group
+*/
+/*/// #### nk_group_begin
+/// Starts a new widget group. Requires a previous layouting function to specify a pos/size.
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_group_begin(struct nk_context*, const char *title, nk_flags);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __title__ | Must be an unique identifier for this group that is also used for the group header
+/// __flags__ | Window flags defined in the nk_panel_flags section with a number of different group behaviors
+///
+/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
+*/
+nk_bool nk_group_begin(struct nk_context*, const char *title, nk_flags);
+/*/// #### nk_group_begin_titled
+/// Starts a new widget group. Requires a previous layouting function to specify a pos/size.
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_group_begin_titled(struct nk_context*, const char *name, const char *title, nk_flags);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __id__ | Must be an unique identifier for this group
+/// __title__ | Group header title
+/// __flags__ | Window flags defined in the nk_panel_flags section with a number of different group behaviors
+///
+/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
+*/
+nk_bool nk_group_begin_titled(struct nk_context*, const char *name, const char *title, nk_flags);
+/*/// #### nk_group_end
+/// Ends a widget group
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_group_end(struct nk_context*);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+*/
+void nk_group_end(struct nk_context*);
+/*/// #### nk_group_scrolled_offset_begin
+/// starts a new widget group. requires a previous layouting function to specify
+/// a size. Does not keep track of scrollbar.
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __x_offset__| Scrollbar x-offset to offset all widgets inside the group horizontally.
+/// __y_offset__| Scrollbar y-offset to offset all widgets inside the group vertically
+/// __title__ | Window unique group title used to both identify and display in the group header
+/// __flags__ | Window flags from the nk_panel_flags section
+///
+/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
+*/
+nk_bool nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags);
+/*/// #### nk_group_scrolled_begin
+/// Starts a new widget group. requires a previous
+/// layouting function to specify a size. Does not keep track of scrollbar.
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, const char *title, nk_flags);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __off__ | Both x- and y- scroll offset. Allows for manual scrollbar control
+/// __title__ | Window unique group title used to both identify and display in the group header
+/// __flags__ | Window flags from nk_panel_flags section
+///
+/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
+*/
+nk_bool nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, const char *title, nk_flags);
+/*/// #### nk_group_scrolled_end
+/// Ends a widget group after calling nk_group_scrolled_offset_begin or nk_group_scrolled_begin.
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_group_scrolled_end(struct nk_context*);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+*/
+void nk_group_scrolled_end(struct nk_context*);
+/*/// #### nk_group_get_scroll
+/// Gets the scroll position of the given group.
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_group_get_scroll(struct nk_context*, const char *id, nk_uint *x_offset, nk_uint *y_offset);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// -------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __id__ | The id of the group to get the scroll position of
+/// __x_offset__ | A pointer to the x offset output (or NULL to ignore)
+/// __y_offset__ | A pointer to the y offset output (or NULL to ignore)
+*/
+void nk_group_get_scroll(struct nk_context*, const char *id, nk_uint *x_offset, nk_uint *y_offset);
+/*/// #### nk_group_set_scroll
+/// Sets the scroll position of the given group.
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_group_set_scroll(struct nk_context*, const char *id, nk_uint x_offset, nk_uint y_offset);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// -------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __id__ | The id of the group to scroll
+/// __x_offset__ | The x offset to scroll to
+/// __y_offset__ | The y offset to scroll to
+*/
+void nk_group_set_scroll(struct nk_context*, const char *id, nk_uint x_offset, nk_uint y_offset);
+/* =============================================================================
+ *
+ * TREE
+ *
+ * =============================================================================
+/// ### Tree
+/// Trees represent two different concept. First the concept of a collapsable
+/// UI section that can be either in a hidden or visibile state. They allow the UI
+/// user to selectively minimize the current set of visible UI to comprehend.
+/// The second concept are tree widgets for visual UI representation of trees.
+///
+/// Trees thereby can be nested for tree representations and multiple nested
+/// collapsable UI sections. All trees are started by calling of the
+/// `nk_tree_xxx_push_tree` functions and ended by calling one of the
+/// `nk_tree_xxx_pop_xxx()` functions. Each starting functions takes a title label
+/// and optionally an image to be displayed and the initial collapse state from
+/// the nk_collapse_states section.
+///
+/// The runtime state of the tree is either stored outside the library by the caller
+/// or inside which requires a unique ID. The unique ID can either be generated
+/// automatically from `__FILE__` and `__LINE__` with function `nk_tree_push`,
+/// by `__FILE__` and a user provided ID generated for example by loop index with
+/// function `nk_tree_push_id` or completely provided from outside by user with
+/// function `nk_tree_push_hashed`.
+///
+/// #### Usage
+/// To create a tree you have to call one of the seven `nk_tree_xxx_push_xxx`
+/// functions to start a collapsable UI section and `nk_tree_xxx_pop` to mark the
+/// end.
+/// Each starting function will either return `false(0)` if the tree is collapsed
+/// or hidden and therefore does not need to be filled with content or `true(1)`
+/// if visible and required to be filled.
+///
+/// !!! Note
+/// The tree header does not require and layouting function and instead
+/// calculates a auto height based on the currently used font size
+///
+/// The tree ending functions only need to be called if the tree content is
+/// actually visible. So make sure the tree push function is guarded by `if`
+/// and the pop call is only taken if the tree is visible.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// if (nk_tree_push(ctx, NK_TREE_TAB, "Tree", NK_MINIMIZED)) {
+/// nk_layout_row_dynamic(...);
+/// nk_widget(...);
+/// nk_tree_pop(ctx);
+/// }
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// #### Reference
+/// Function | Description
+/// ----------------------------|-------------------------------------------
+/// nk_tree_push | Start a collapsable UI section with internal state management
+/// nk_tree_push_id | Start a collapsable UI section with internal state management callable in a look
+/// nk_tree_push_hashed | Start a collapsable UI section with internal state management with full control over internal unique ID use to store state
+/// nk_tree_image_push | Start a collapsable UI section with image and label header
+/// nk_tree_image_push_id | Start a collapsable UI section with image and label header and internal state management callable in a look
+/// nk_tree_image_push_hashed | Start a collapsable UI section with image and label header and internal state management with full control over internal unique ID use to store state
+/// nk_tree_pop | Ends a collapsable UI section
+//
+/// nk_tree_state_push | Start a collapsable UI section with external state management
+/// nk_tree_state_image_push | Start a collapsable UI section with image and label header and external state management
+/// nk_tree_state_pop | Ends a collapsabale UI section
+///
+/// #### nk_tree_type
+/// Flag | Description
+/// ----------------|----------------------------------------
+/// NK_TREE_NODE | Highlighted tree header to mark a collapsable UI section
+/// NK_TREE_TAB | Non-highighted tree header closer to tree representations
+*/
+/*/// #### nk_tree_push
+/// Starts a collapsable UI section with internal state management
+/// !!! WARNING
+/// To keep track of the runtime tree collapsable state this function uses
+/// defines `__FILE__` and `__LINE__` to generate a unique ID. If you want
+/// to call this function in a loop please use `nk_tree_push_id` or
+/// `nk_tree_push_hashed` instead.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// #define nk_tree_push(ctx, type, title, state)
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
+/// __title__ | Label printed in the tree header
+/// __state__ | Initial tree state value out of nk_collapse_states
+///
+/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
+*/
+nk_bool nk_tree_push(struct nk_context*ctx, enum nk_tree_type type, const char *title, enum nk_collapse_states initial_state);
+/*/// #### nk_tree_push_id
+/// Starts a collapsable UI section with internal state management callable in a look
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// #define nk_tree_push_id(ctx, type, title, state, id)
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
+/// __title__ | Label printed in the tree header
+/// __state__ | Initial tree state value out of nk_collapse_states
+/// __id__ | Loop counter index if this function is called in a loop
+///
+/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
+*/
+nk_bool nk_tree_push_id(struct nk_context* ctx, enum nk_tree_type type, const char *title, enum nk_collapse_states initial_state, int seed);
+/*/// #### nk_tree_push_hashed
+/// Start a collapsable UI section with internal state management with full
+/// control over internal unique ID used to store state
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_tree_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
+/// __title__ | Label printed in the tree header
+/// __state__ | Initial tree state value out of nk_collapse_states
+/// __hash__ | Memory block or string to generate the ID from
+/// __len__ | Size of passed memory block or string in __hash__
+/// __seed__ | Seeding value if this function is called in a loop or default to `0`
+///
+/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
+*/
+nk_bool nk_tree_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
+/*/// #### nk_tree_image_push
+/// Start a collapsable UI section with image and label header
+/// !!! WARNING
+/// To keep track of the runtime tree collapsable state this function uses
+/// defines `__FILE__` and `__LINE__` to generate a unique ID. If you want
+/// to call this function in a loop please use `nk_tree_image_push_id` or
+/// `nk_tree_image_push_hashed` instead.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// #define nk_tree_image_push(ctx, type, img, title, state)
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
+/// __img__ | Image to display inside the header on the left of the label
+/// __title__ | Label printed in the tree header
+/// __state__ | Initial tree state value out of nk_collapse_states
+///
+/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
+*/
+
+/*/// #### nk_tree_image_push_id
+/// Start a collapsable UI section with image and label header and internal state
+/// management callable in a look
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// #define nk_tree_image_push_id(ctx, type, img, title, state, id)
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
+/// __img__ | Image to display inside the header on the left of the label
+/// __title__ | Label printed in the tree header
+/// __state__ | Initial tree state value out of nk_collapse_states
+/// __id__ | Loop counter index if this function is called in a loop
+///
+/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
+*/
+
+/*/// #### nk_tree_image_push_hashed
+/// Start a collapsable UI section with internal state management with full
+/// control over internal unique ID used to store state
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_tree_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct
+/// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
+/// __img__ | Image to display inside the header on the left of the label
+/// __title__ | Label printed in the tree header
+/// __state__ | Initial tree state value out of nk_collapse_states
+/// __hash__ | Memory block or string to generate the ID from
+/// __len__ | Size of passed memory block or string in __hash__
+/// __seed__ | Seeding value if this function is called in a loop or default to `0`
+///
+/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
+*/
+nk_bool nk_tree_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
+/*/// #### nk_tree_pop
+/// Ends a collapsabale UI section
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_tree_pop(struct nk_context*);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx`
+*/
+void nk_tree_pop(struct nk_context*);
+/*/// #### nk_tree_state_push
+/// Start a collapsable UI section with external state management
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx`
+/// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
+/// __title__ | Label printed in the tree header
+/// __state__ | Persistent state to update
+///
+/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
+*/
+nk_bool nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state);
+/*/// #### nk_tree_state_image_push
+/// Start a collapsable UI section with image and label header and external state management
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx`
+/// __img__ | Image to display inside the header on the left of the label
+/// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node
+/// __title__ | Label printed in the tree header
+/// __state__ | Persistent state to update
+///
+/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise
+*/
+nk_bool nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state);
+/*/// #### nk_tree_state_pop
+/// Ends a collapsabale UI section
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_tree_state_pop(struct nk_context*);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// ------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx`
+*/
+void nk_tree_state_pop(struct nk_context*);
+
+nk_bool nk_tree_element_push(struct nk_context*ctx, enum nk_tree_type type, const char *title, enum nk_collapse_states initial_state, nk_bool *selected) ;
+nk_bool nk_tree_element_push_id(struct nk_context*ctx, enum nk_tree_type type, const char *title, enum nk_collapse_states initial_state, nk_bool *selected, int seed) ;
+
+nk_bool nk_tree_element_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, nk_bool *selected, const char *hash, int len, int seed);
+nk_bool nk_tree_element_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, nk_bool *selected, const char *hash, int len,int seed);
+void nk_tree_element_pop(struct nk_context*);
+
+/* =============================================================================
+ *
+ * LIST VIEW
+ *
+ * ============================================================================= */
+struct nk_list_view {
+/* public: */
+ int begin, end, count;
+/* private: */
+ int total_height;
+ struct nk_context *ctx;
+ nk_uint *scroll_pointer;
+ nk_uint scroll_value;
+};
+nk_bool nk_list_view_begin(struct nk_context*, struct nk_list_view *out, const char *id, nk_flags, int row_height, int row_count);
+void nk_list_view_end(struct nk_list_view*);
+/* =============================================================================
+ *
+ * WIDGET
+ *
+ * ============================================================================= */
+enum nk_widget_layout_states {
+ NK_WIDGET_INVALID, /* The widget cannot be seen and is completely out of view */
+ NK_WIDGET_VALID, /* The widget is completely inside the window and can be updated and drawn */
+ NK_WIDGET_ROM /* The widget is partially visible and cannot be updated */
+};
+enum nk_widget_states {
+ NK_WIDGET_STATE_MODIFIED = 2,
+ NK_WIDGET_STATE_INACTIVE = 4, /* widget is neither active nor hovered */
+ NK_WIDGET_STATE_ENTERED = 8, /* widget has been hovered on the current frame */
+ NK_WIDGET_STATE_HOVER = 16, /* widget is being hovered */
+ NK_WIDGET_STATE_ACTIVED = 32,/* widget is currently activated */
+ NK_WIDGET_STATE_LEFT = 64, /* widget is from this frame on not hovered anymore */
+ NK_WIDGET_STATE_HOVERED = NK_WIDGET_STATE_HOVER|NK_WIDGET_STATE_MODIFIED, /* widget is being hovered */
+ NK_WIDGET_STATE_ACTIVE = NK_WIDGET_STATE_ACTIVED|NK_WIDGET_STATE_MODIFIED /* widget is currently activated */
+};
+enum nk_widget_layout_states nk_widget(struct nk_rect*, const struct nk_context*);
+enum nk_widget_layout_states nk_widget_fitting(struct nk_rect*, struct nk_context*, struct nk_vec2);
+struct nk_rect nk_widget_bounds(struct nk_context*);
+struct nk_vec2 nk_widget_position(struct nk_context*);
+struct nk_vec2 nk_widget_size(struct nk_context*);
+float nk_widget_width(struct nk_context*);
+float nk_widget_height(struct nk_context*);
+nk_bool nk_widget_is_hovered(struct nk_context*);
+nk_bool nk_widget_is_mouse_clicked(struct nk_context*, enum nk_buttons);
+nk_bool nk_widget_has_mouse_click_down(struct nk_context*, enum nk_buttons, nk_bool down);
+void nk_spacing(struct nk_context*, int cols);
+/* =============================================================================
+ *
+ * TEXT
+ *
+ * ============================================================================= */
+enum nk_text_align {
+ NK_TEXT_ALIGN_LEFT = 0x01,
+ NK_TEXT_ALIGN_CENTERED = 0x02,
+ NK_TEXT_ALIGN_RIGHT = 0x04,
+ NK_TEXT_ALIGN_TOP = 0x08,
+ NK_TEXT_ALIGN_MIDDLE = 0x10,
+ NK_TEXT_ALIGN_BOTTOM = 0x20
+};
+enum nk_text_alignment {
+ NK_TEXT_LEFT = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_LEFT,
+ NK_TEXT_CENTERED = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_CENTERED,
+ NK_TEXT_RIGHT = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_RIGHT
+};
+void nk_text(struct nk_context*, const char*, int, nk_flags);
+void nk_text_colored(struct nk_context*, const char*, int, nk_flags, struct nk_color);
+void nk_text_wrap(struct nk_context*, const char*, int);
+void nk_text_wrap_colored(struct nk_context*, const char*, int, struct nk_color);
+void nk_label(struct nk_context*, const char*, nk_flags align);
+void nk_label_colored(struct nk_context*, const char*, nk_flags align, struct nk_color);
+void nk_label_wrap(struct nk_context*, const char*);
+void nk_label_colored_wrap(struct nk_context*, const char*, struct nk_color);
+void nk_image(struct nk_context*, struct nk_image);
+void nk_image_color(struct nk_context*, struct nk_image, struct nk_color);
+
+void nk_labelf(struct nk_context*, nk_flags, const char*, ...) ;
+void nk_labelf_colored(struct nk_context*, nk_flags, struct nk_color, const char*,...) ;
+void nk_labelf_wrap(struct nk_context*, const char*,...) ;
+void nk_labelf_colored_wrap(struct nk_context*, struct nk_color, const char*,...) ;
+void nk_labelfv(struct nk_context*, nk_flags, const char*, va_list) ;
+void nk_labelfv_colored(struct nk_context*, nk_flags, struct nk_color, const char*, va_list) ;
+void nk_labelfv_wrap(struct nk_context*, const char*, va_list) ;
+void nk_labelfv_colored_wrap(struct nk_context*, struct nk_color, const char*, va_list) ;
+void nk_value_bool(struct nk_context*, const char *prefix, int);
+void nk_value_int(struct nk_context*, const char *prefix, int);
+void nk_value_uint(struct nk_context*, const char *prefix, unsigned int);
+void nk_value_float(struct nk_context*, const char *prefix, float);
+void nk_value_color_byte(struct nk_context*, const char *prefix, struct nk_color);
+void nk_value_color_float(struct nk_context*, const char *prefix, struct nk_color);
+void nk_value_color_hex(struct nk_context*, const char *prefix, struct nk_color);
+
+/* =============================================================================
+ *
+ * BUTTON
+ *
+ * ============================================================================= */
+nk_bool nk_button_text(struct nk_context*, const char *title, int len);
+nk_bool nk_button_label(struct nk_context*, const char *title);
+nk_bool nk_button_color(struct nk_context*, struct nk_color);
+nk_bool nk_button_symbol(struct nk_context*, enum nk_symbol_type);
+nk_bool nk_button_image(struct nk_context*, struct nk_image img);
+nk_bool nk_button_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags text_alignment);
+nk_bool nk_button_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
+nk_bool nk_button_image_label(struct nk_context*, struct nk_image img, const char*, nk_flags text_alignment);
+nk_bool nk_button_image_text(struct nk_context*, struct nk_image img, const char*, int, nk_flags alignment);
+nk_bool nk_button_text_styled(struct nk_context*, const struct nk_style_button*, const char *title, int len);
+nk_bool nk_button_label_styled(struct nk_context*, const struct nk_style_button*, const char *title);
+nk_bool nk_button_symbol_styled(struct nk_context*, const struct nk_style_button*, enum nk_symbol_type);
+nk_bool nk_button_image_styled(struct nk_context*, const struct nk_style_button*, struct nk_image img);
+nk_bool nk_button_symbol_text_styled(struct nk_context*,const struct nk_style_button*, enum nk_symbol_type, const char*, int, nk_flags alignment);
+nk_bool nk_button_symbol_label_styled(struct nk_context *ctx, const struct nk_style_button *style, enum nk_symbol_type symbol, const char *title, nk_flags align);
+nk_bool nk_button_image_label_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, nk_flags text_alignment);
+nk_bool nk_button_image_text_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, int, nk_flags alignment);
+void nk_button_set_behavior(struct nk_context*, enum nk_button_behavior);
+nk_bool nk_button_push_behavior(struct nk_context*, enum nk_button_behavior);
+nk_bool nk_button_pop_behavior(struct nk_context*);
+/* =============================================================================
+ *
+ * CHECKBOX
+ *
+ * ============================================================================= */
+nk_bool nk_check_label(struct nk_context*, const char*, nk_bool active);
+nk_bool nk_check_text(struct nk_context*, const char*, int, nk_bool active);
+unsigned nk_check_flags_label(struct nk_context*, const char*, unsigned int flags, unsigned int value);
+unsigned nk_check_flags_text(struct nk_context*, const char*, int, unsigned int flags, unsigned int value);
+nk_bool nk_checkbox_label(struct nk_context*, const char*, nk_bool *active);
+nk_bool nk_checkbox_text(struct nk_context*, const char*, int, nk_bool *active);
+nk_bool nk_checkbox_flags_label(struct nk_context*, const char*, unsigned int *flags, unsigned int value);
+nk_bool nk_checkbox_flags_text(struct nk_context*, const char*, int, unsigned int *flags, unsigned int value);
+/* =============================================================================
+ *
+ * RADIO BUTTON
+ *
+ * ============================================================================= */
+nk_bool nk_radio_label(struct nk_context*, const char*, nk_bool *active);
+nk_bool nk_radio_text(struct nk_context*, const char*, int, nk_bool *active);
+nk_bool nk_option_label(struct nk_context*, const char*, nk_bool active);
+nk_bool nk_option_text(struct nk_context*, const char*, int, nk_bool active);
+/* =============================================================================
+ *
+ * SELECTABLE
+ *
+ * ============================================================================= */
+nk_bool nk_selectable_label(struct nk_context*, const char*, nk_flags align, nk_bool *value);
+nk_bool nk_selectable_text(struct nk_context*, const char*, int, nk_flags align, nk_bool *value);
+nk_bool nk_selectable_image_label(struct nk_context*,struct nk_image, const char*, nk_flags align, nk_bool *value);
+nk_bool nk_selectable_image_text(struct nk_context*,struct nk_image, const char*, int, nk_flags align, nk_bool *value);
+nk_bool nk_selectable_symbol_label(struct nk_context*,enum nk_symbol_type, const char*, nk_flags align, nk_bool *value);
+nk_bool nk_selectable_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, nk_bool *value);
+
+nk_bool nk_select_label(struct nk_context*, const char*, nk_flags align, nk_bool value);
+nk_bool nk_select_text(struct nk_context*, const char*, int, nk_flags align, nk_bool value);
+nk_bool nk_select_image_label(struct nk_context*, struct nk_image,const char*, nk_flags align, nk_bool value);
+nk_bool nk_select_image_text(struct nk_context*, struct nk_image,const char*, int, nk_flags align, nk_bool value);
+nk_bool nk_select_symbol_label(struct nk_context*,enum nk_symbol_type, const char*, nk_flags align, nk_bool value);
+nk_bool nk_select_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, nk_bool value);
+
+/* =============================================================================
+ *
+ * SLIDER
+ *
+ * ============================================================================= */
+float nk_slide_float(struct nk_context*, float min, float val, float max, float step);
+int nk_slide_int(struct nk_context*, int min, int val, int max, int step);
+nk_bool nk_slider_float(struct nk_context*, float min, float *val, float max, float step);
+nk_bool nk_slider_int(struct nk_context*, int min, int *val, int max, int step);
+/* =============================================================================
+ *
+ * PROGRESSBAR
+ *
+ * ============================================================================= */
+nk_bool nk_progress(struct nk_context*, nk_size *cur, nk_size max, nk_bool modifyable);
+nk_size nk_prog(struct nk_context*, nk_size cur, nk_size max, nk_bool modifyable);
+
+/* =============================================================================
+ *
+ * COLOR PICKER
+ *
+ * ============================================================================= */
+struct nk_colorf nk_color_picker(struct nk_context*, struct nk_colorf, enum nk_color_format);
+nk_bool nk_color_pick(struct nk_context*, struct nk_colorf*, enum nk_color_format);
+/* =============================================================================
+ *
+ * PROPERTIES
+ *
+ * =============================================================================
+/// ### Properties
+/// Properties are the main value modification widgets in Nuklear. Changing a value
+/// can be achieved by dragging, adding/removing incremental steps on button click
+/// or by directly typing a number.
+///
+/// #### Usage
+/// Each property requires a unique name for identifaction that is also used for
+/// displaying a label. If you want to use the same name multiple times make sure
+/// add a '#' before your name. The '#' will not be shown but will generate a
+/// unique ID. Each propery also takes in a minimum and maximum value. If you want
+/// to make use of the complete number range of a type just use the provided
+/// type limits from `limits.h`. For example `INT_MIN` and `INT_MAX` for
+/// `nk_property_int` and `nk_propertyi`. In additional each property takes in
+/// a increment value that will be added or subtracted if either the increment
+/// decrement button is clicked. Finally there is a value for increment per pixel
+/// dragged that is added or subtracted from the value.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int value = 0;
+/// struct nk_context ctx;
+/// nk_init_xxx(&ctx, ...);
+/// while (1) {
+/// // Input
+/// Event evt;
+/// nk_input_begin(&ctx);
+/// while (GetEvent(&evt)) {
+/// if (evt.type == MOUSE_MOVE)
+/// nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
+/// else if (evt.type == [...]) {
+/// nk_input_xxx(...);
+/// }
+/// }
+/// nk_input_end(&ctx);
+/// //
+/// // Window
+/// if (nk_begin_xxx(...) {
+/// // Property
+/// nk_layout_row_dynamic(...);
+/// nk_property_int(ctx, "ID", INT_MIN, &value, INT_MAX, 1, 1);
+/// }
+/// nk_end(ctx);
+/// //
+/// // Draw
+/// const struct nk_command *cmd = 0;
+/// nk_foreach(cmd, &ctx) {
+/// switch (cmd->type) {
+/// case NK_COMMAND_LINE:
+/// your_draw_line_function(...)
+/// break;
+/// case NK_COMMAND_RECT
+/// your_draw_rect_function(...)
+/// break;
+/// case ...:
+/// // [...]
+/// }
+/// nk_clear(&ctx);
+/// }
+/// nk_free(&ctx);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// #### Reference
+/// Function | Description
+/// --------------------|-------------------------------------------
+/// nk_property_int | Integer property directly modifing a passed in value
+/// nk_property_float | Float property directly modifing a passed in value
+/// nk_property_double | Double property directly modifing a passed in value
+/// nk_propertyi | Integer property returning the modified int value
+/// nk_propertyf | Float property returning the modified float value
+/// nk_propertyd | Double property returning the modified double value
+///
+*/
+/*/// #### nk_property_int
+/// Integer property directly modifing a passed in value
+/// !!! WARNING
+/// To generate a unique property ID using the same label make sure to insert
+/// a `#` at the beginning. It will not be shown but guarantees correct behavior.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_property_int(struct nk_context *ctx, const char *name, int min, int *val, int max, int step, float inc_per_pixel);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// --------------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function
+/// __name__ | String used both as a label as well as a unique identifier
+/// __min__ | Minimum value not allowed to be underflown
+/// __val__ | Integer pointer to be modified
+/// __max__ | Maximum value not allowed to be overflown
+/// __step__ | Increment added and subtracted on increment and decrement button
+/// __inc_per_pixel__ | Value per pixel added or subtracted on dragging
+*/
+void nk_property_int(struct nk_context*, const char *name, int min, int *val, int max, int step, float inc_per_pixel);
+/*/// #### nk_property_float
+/// Float property directly modifing a passed in value
+/// !!! WARNING
+/// To generate a unique property ID using the same label make sure to insert
+/// a `#` at the beginning. It will not be shown but guarantees correct behavior.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_property_float(struct nk_context *ctx, const char *name, float min, float *val, float max, float step, float inc_per_pixel);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// --------------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function
+/// __name__ | String used both as a label as well as a unique identifier
+/// __min__ | Minimum value not allowed to be underflown
+/// __val__ | Float pointer to be modified
+/// __max__ | Maximum value not allowed to be overflown
+/// __step__ | Increment added and subtracted on increment and decrement button
+/// __inc_per_pixel__ | Value per pixel added or subtracted on dragging
+*/
+void nk_property_float(struct nk_context*, const char *name, float min, float *val, float max, float step, float inc_per_pixel);
+/*/// #### nk_property_double
+/// Double property directly modifing a passed in value
+/// !!! WARNING
+/// To generate a unique property ID using the same label make sure to insert
+/// a `#` at the beginning. It will not be shown but guarantees correct behavior.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// void nk_property_double(struct nk_context *ctx, const char *name, double min, double *val, double max, double step, double inc_per_pixel);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// --------------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function
+/// __name__ | String used both as a label as well as a unique identifier
+/// __min__ | Minimum value not allowed to be underflown
+/// __val__ | Double pointer to be modified
+/// __max__ | Maximum value not allowed to be overflown
+/// __step__ | Increment added and subtracted on increment and decrement button
+/// __inc_per_pixel__ | Value per pixel added or subtracted on dragging
+*/
+void nk_property_double(struct nk_context*, const char *name, double min, double *val, double max, double step, float inc_per_pixel);
+/*/// #### nk_propertyi
+/// Integer property modifing a passed in value and returning the new value
+/// !!! WARNING
+/// To generate a unique property ID using the same label make sure to insert
+/// a `#` at the beginning. It will not be shown but guarantees correct behavior.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// int nk_propertyi(struct nk_context *ctx, const char *name, int min, int val, int max, int step, float inc_per_pixel);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// --------------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function
+/// __name__ | String used both as a label as well as a unique identifier
+/// __min__ | Minimum value not allowed to be underflown
+/// __val__ | Current integer value to be modified and returned
+/// __max__ | Maximum value not allowed to be overflown
+/// __step__ | Increment added and subtracted on increment and decrement button
+/// __inc_per_pixel__ | Value per pixel added or subtracted on dragging
+///
+/// Returns the new modified integer value
+*/
+nk_bool nk_propertyi(struct nk_context*, const char *name, int min, int val, int max, int step, float inc_per_pixel);
+/*/// #### nk_propertyf
+/// Float property modifing a passed in value and returning the new value
+/// !!! WARNING
+/// To generate a unique property ID using the same label make sure to insert
+/// a `#` at the beginning. It will not be shown but guarantees correct behavior.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// float nk_propertyf(struct nk_context *ctx, const char *name, float min, float val, float max, float step, float inc_per_pixel);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// --------------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function
+/// __name__ | String used both as a label as well as a unique identifier
+/// __min__ | Minimum value not allowed to be underflown
+/// __val__ | Current float value to be modified and returned
+/// __max__ | Maximum value not allowed to be overflown
+/// __step__ | Increment added and subtracted on increment and decrement button
+/// __inc_per_pixel__ | Value per pixel added or subtracted on dragging
+///
+/// Returns the new modified float value
+*/
+float nk_propertyf(struct nk_context*, const char *name, float min, float val, float max, float step, float inc_per_pixel);
+/*/// #### nk_propertyd
+/// Float property modifing a passed in value and returning the new value
+/// !!! WARNING
+/// To generate a unique property ID using the same label make sure to insert
+/// a `#` at the beginning. It will not be shown but guarantees correct behavior.
+///
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c
+/// float nk_propertyd(struct nk_context *ctx, const char *name, double min, double val, double max, double step, double inc_per_pixel);
+/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///
+/// Parameter | Description
+/// --------------------|-----------------------------------------------------------
+/// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function
+/// __name__ | String used both as a label as well as a unique identifier
+/// __min__ | Minimum value not allowed to be underflown
+/// __val__ | Current double value to be modified and returned
+/// __max__ | Maximum value not allowed to be overflown
+/// __step__ | Increment added and subtracted on increment and decrement button
+/// __inc_per_pixel__ | Value per pixel added or subtracted on dragging
+///
+/// Returns the new modified double value
+*/
+double nk_propertyd(struct nk_context*, const char *name, double min, double val, double max, double step, float inc_per_pixel);
+/* =============================================================================
+ *
+ * TEXT EDIT
+ *
+ * ============================================================================= */
+enum nk_edit_flags {
+ NK_EDIT_DEFAULT = 0,
+ NK_EDIT_READ_ONLY = 1,
+ NK_EDIT_AUTO_SELECT = 2,
+ NK_EDIT_SIG_ENTER = 4,
+ NK_EDIT_ALLOW_TAB = 8,
+ NK_EDIT_NO_CURSOR = 16,
+ NK_EDIT_SELECTABLE = 32,
+ NK_EDIT_CLIPBOARD = 64,
+ NK_EDIT_CTRL_ENTER_NEWLINE = 128,
+ NK_EDIT_NO_HORIZONTAL_SCROLL = 256,
+ NK_EDIT_ALWAYS_INSERT_MODE = 512,
+ NK_EDIT_MULTILINE = 1024,
+ NK_EDIT_GOTO_END_ON_ACTIVATE = 2048
+};
+enum nk_edit_types {
+ NK_EDIT_SIMPLE = NK_EDIT_ALWAYS_INSERT_MODE,
+ NK_EDIT_FIELD = NK_EDIT_SIMPLE|NK_EDIT_SELECTABLE|NK_EDIT_CLIPBOARD,
+ NK_EDIT_BOX = NK_EDIT_ALWAYS_INSERT_MODE| NK_EDIT_SELECTABLE| NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB|NK_EDIT_CLIPBOARD,
+ NK_EDIT_EDITOR = NK_EDIT_SELECTABLE|NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB| NK_EDIT_CLIPBOARD
+};
+enum nk_edit_events {
+ NK_EDIT_ACTIVE = 1, /* edit widget is currently being modified */
+ NK_EDIT_INACTIVE = 2, /* edit widget is not active and is not being modified */
+ NK_EDIT_ACTIVATED = 4, /* edit widget went from state inactive to state active */
+ NK_EDIT_DEACTIVATED = 8, /* edit widget went from state active to state inactive */
+ NK_EDIT_COMMITED = 16 /* edit widget has received an enter and lost focus */
+};
+nk_flags nk_edit_string(struct nk_context*, nk_flags, char *buffer, int *len, int max, nk_plugin_filter);
+nk_flags nk_edit_string_zero_terminated(struct nk_context*, nk_flags, char *buffer, int max, nk_plugin_filter);
+nk_flags nk_edit_buffer(struct nk_context*, nk_flags, struct nk_text_edit*, nk_plugin_filter);
+void nk_edit_focus(struct nk_context*, nk_flags flags);
+void nk_edit_unfocus(struct nk_context*);
+/* =============================================================================
+ *
+ * CHART
+ *
+ * ============================================================================= */
+nk_bool nk_chart_begin(struct nk_context*, enum nk_chart_type, int num, float min, float max);
+nk_bool nk_chart_begin_colored(struct nk_context*, enum nk_chart_type, struct nk_color, struct nk_color active, int num, float min, float max);
+void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value);
+void nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type, struct nk_color, struct nk_color active, int count, float min_value, float max_value);
+nk_flags nk_chart_push(struct nk_context*, float);
+nk_flags nk_chart_push_slot(struct nk_context*, float, int);
+void nk_chart_end(struct nk_context*);
+void nk_plot(struct nk_context*, enum nk_chart_type, const float *values, int count, int offset);
+void nk_plot_function(struct nk_context*, enum nk_chart_type, void *userdata, float(*value_getter)(void* user, int index), int count, int offset);
+/* =============================================================================
+ *
+ * POPUP
+ *
+ * ============================================================================= */
+nk_bool nk_popup_begin(struct nk_context*, enum nk_popup_type, const char*, nk_flags, struct nk_rect bounds);
+void nk_popup_close(struct nk_context*);
+void nk_popup_end(struct nk_context*);
+void nk_popup_get_scroll(struct nk_context*, nk_uint *offset_x, nk_uint *offset_y);
+void nk_popup_set_scroll(struct nk_context*, nk_uint offset_x, nk_uint offset_y);
+/* =============================================================================
+ *
+ * COMBOBOX
+ *
+ * ============================================================================= */
+int nk_combo(struct nk_context*, const char **items, int count, int selected, int item_height, struct nk_vec2 size);
+int nk_combo_separator(struct nk_context*, const char *items_separated_by_separator, int separator, int selected, int count, int item_height, struct nk_vec2 size);
+int nk_combo_string(struct nk_context*, const char *items_separated_by_zeros, int selected, int count, int item_height, struct nk_vec2 size);
+int nk_combo_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void *userdata, int selected, int count, int item_height, struct nk_vec2 size);
+void nk_combobox(struct nk_context*, const char **items, int count, int *selected, int item_height, struct nk_vec2 size);
+void nk_combobox_string(struct nk_context*, const char *items_separated_by_zeros, int *selected, int count, int item_height, struct nk_vec2 size);
+void nk_combobox_separator(struct nk_context*, const char *items_separated_by_separator, int separator, int *selected, int count, int item_height, struct nk_vec2 size);
+void nk_combobox_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void*, int *selected, int count, int item_height, struct nk_vec2 size);
+/* =============================================================================
+ *
+ * ABSTRACT COMBOBOX
+ *
+ * ============================================================================= */
+nk_bool nk_combo_begin_text(struct nk_context*, const char *selected, int, struct nk_vec2 size);
+nk_bool nk_combo_begin_label(struct nk_context*, const char *selected, struct nk_vec2 size);
+nk_bool nk_combo_begin_color(struct nk_context*, struct nk_color color, struct nk_vec2 size);
+nk_bool nk_combo_begin_symbol(struct nk_context*, enum nk_symbol_type, struct nk_vec2 size);
+nk_bool nk_combo_begin_symbol_label(struct nk_context*, const char *selected, enum nk_symbol_type, struct nk_vec2 size);
+nk_bool nk_combo_begin_symbol_text(struct nk_context*, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size);
+nk_bool nk_combo_begin_image(struct nk_context*, struct nk_image img, struct nk_vec2 size);
+nk_bool nk_combo_begin_image_label(struct nk_context*, const char *selected, struct nk_image, struct nk_vec2 size);
+nk_bool nk_combo_begin_image_text(struct nk_context*, const char *selected, int, struct nk_image, struct nk_vec2 size);
+nk_bool nk_combo_item_label(struct nk_context*, const char*, nk_flags alignment);
+nk_bool nk_combo_item_text(struct nk_context*, const char*,int, nk_flags alignment);
+nk_bool nk_combo_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
+nk_bool nk_combo_item_image_text(struct nk_context*, struct nk_image, const char*, int,nk_flags alignment);
+nk_bool nk_combo_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
+nk_bool nk_combo_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
+void nk_combo_close(struct nk_context*);
+void nk_combo_end(struct nk_context*);
+/* =============================================================================
+ *
+ * CONTEXTUAL
+ *
+ * ============================================================================= */
+nk_bool nk_contextual_begin(struct nk_context*, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds);
+nk_bool nk_contextual_item_text(struct nk_context*, const char*, int,nk_flags align);
+nk_bool nk_contextual_item_label(struct nk_context*, const char*, nk_flags align);
+nk_bool nk_contextual_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
+nk_bool nk_contextual_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
+nk_bool nk_contextual_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
+nk_bool nk_contextual_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
+void nk_contextual_close(struct nk_context*);
+void nk_contextual_end(struct nk_context*);
+/* =============================================================================
+ *
+ * TOOLTIP
+ *
+ * ============================================================================= */
+void nk_tooltip(struct nk_context*, const char*);
+
+void nk_tooltipf(struct nk_context*, const char*, ...) ;
+void nk_tooltipfv(struct nk_context*, const char*, va_list) ;
+
+nk_bool nk_tooltip_begin(struct nk_context*, float width);
+void nk_tooltip_end(struct nk_context*);
+/* =============================================================================
+ *
+ * MENU
+ *
+ * ============================================================================= */
+void nk_menubar_begin(struct nk_context*);
+void nk_menubar_end(struct nk_context*);
+nk_bool nk_menu_begin_text(struct nk_context*, const char* title, int title_len, nk_flags align, struct nk_vec2 size);
+nk_bool nk_menu_begin_label(struct nk_context*, const char*, nk_flags align, struct nk_vec2 size);
+nk_bool nk_menu_begin_image(struct nk_context*, const char*, struct nk_image, struct nk_vec2 size);
+nk_bool nk_menu_begin_image_text(struct nk_context*, const char*, int,nk_flags align,struct nk_image, struct nk_vec2 size);
+nk_bool nk_menu_begin_image_label(struct nk_context*, const char*, nk_flags align,struct nk_image, struct nk_vec2 size);
+nk_bool nk_menu_begin_symbol(struct nk_context*, const char*, enum nk_symbol_type, struct nk_vec2 size);
+nk_bool nk_menu_begin_symbol_text(struct nk_context*, const char*, int,nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
+nk_bool nk_menu_begin_symbol_label(struct nk_context*, const char*, nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
+nk_bool nk_menu_item_text(struct nk_context*, const char*, int,nk_flags align);
+nk_bool nk_menu_item_label(struct nk_context*, const char*, nk_flags alignment);
+nk_bool nk_menu_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
+nk_bool nk_menu_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
+nk_bool nk_menu_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
+nk_bool nk_menu_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
+void nk_menu_close(struct nk_context*);
+void nk_menu_end(struct nk_context*);
+/* =============================================================================
+ *
+ * STYLE
+ *
+ * ============================================================================= */
+enum nk_style_colors {
+ NK_COLOR_TEXT,
+ NK_COLOR_WINDOW,
+ NK_COLOR_HEADER,
+ NK_COLOR_BORDER,
+ NK_COLOR_BUTTON,
+ NK_COLOR_BUTTON_HOVER,
+ NK_COLOR_BUTTON_ACTIVE,
+ NK_COLOR_TOGGLE,
+ NK_COLOR_TOGGLE_HOVER,
+ NK_COLOR_TOGGLE_CURSOR,
+ NK_COLOR_SELECT,
+ NK_COLOR_SELECT_ACTIVE,
+ NK_COLOR_SLIDER,
+ NK_COLOR_SLIDER_CURSOR,
+ NK_COLOR_SLIDER_CURSOR_HOVER,
+ NK_COLOR_SLIDER_CURSOR_ACTIVE,
+ NK_COLOR_PROPERTY,
+ NK_COLOR_EDIT,
+ NK_COLOR_EDIT_CURSOR,
+ NK_COLOR_COMBO,
+ NK_COLOR_CHART,
+ NK_COLOR_CHART_COLOR,
+ NK_COLOR_CHART_COLOR_HIGHLIGHT,
+ NK_COLOR_SCROLLBAR,
+ NK_COLOR_SCROLLBAR_CURSOR,
+ NK_COLOR_SCROLLBAR_CURSOR_HOVER,
+ NK_COLOR_SCROLLBAR_CURSOR_ACTIVE,
+ NK_COLOR_TAB_HEADER,
+ NK_COLOR_COUNT
+};
+enum nk_style_cursor {
+ NK_CURSOR_ARROW,
+ NK_CURSOR_TEXT,
+ NK_CURSOR_MOVE,
+ NK_CURSOR_RESIZE_VERTICAL,
+ NK_CURSOR_RESIZE_HORIZONTAL,
+ NK_CURSOR_RESIZE_TOP_LEFT_DOWN_RIGHT,
+ NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT,
+ NK_CURSOR_COUNT
+};
+void nk_style_default(struct nk_context*);
+void nk_style_from_table(struct nk_context*, const struct nk_color*);
+void nk_style_load_cursor(struct nk_context*, enum nk_style_cursor, const struct nk_cursor*);
+void nk_style_load_all_cursors(struct nk_context*, struct nk_cursor*);
+const char* nk_style_get_color_by_name(enum nk_style_colors);
+void nk_style_set_font(struct nk_context*, const struct nk_user_font*);
+nk_bool nk_style_set_cursor(struct nk_context*, enum nk_style_cursor);
+void nk_style_show_cursor(struct nk_context*);
+void nk_style_hide_cursor(struct nk_context*);
+
+nk_bool nk_style_push_font(struct nk_context*, const struct nk_user_font*);
+nk_bool nk_style_push_float(struct nk_context*, float*, float);
+nk_bool nk_style_push_vec2(struct nk_context*, struct nk_vec2*, struct nk_vec2);
+nk_bool nk_style_push_style_item(struct nk_context*, struct nk_style_item*, struct nk_style_item);
+nk_bool nk_style_push_flags(struct nk_context*, nk_flags*, nk_flags);
+nk_bool nk_style_push_color(struct nk_context*, struct nk_color*, struct nk_color);
+
+nk_bool nk_style_pop_font(struct nk_context*);
+nk_bool nk_style_pop_float(struct nk_context*);
+nk_bool nk_style_pop_vec2(struct nk_context*);
+nk_bool nk_style_pop_style_item(struct nk_context*);
+nk_bool nk_style_pop_flags(struct nk_context*);
+nk_bool nk_style_pop_color(struct nk_context*);
+/* =============================================================================
+ *
+ * COLOR
+ *
+ * ============================================================================= */
+struct nk_color nk_rgb(int r, int g, int b);
+struct nk_color nk_rgb_iv(const int *rgb);
+struct nk_color nk_rgb_bv(const nk_byte* rgb);
+struct nk_color nk_rgb_f(float r, float g, float b);
+struct nk_color nk_rgb_fv(const float *rgb);
+struct nk_color nk_rgb_cf(struct nk_colorf c);
+struct nk_color nk_rgb_hex(const char *rgb);
+
+struct nk_color nk_rgba(int r, int g, int b, int a);
+struct nk_color nk_rgba_u32(nk_uint);
+struct nk_color nk_rgba_iv(const int *rgba);
+struct nk_color nk_rgba_bv(const nk_byte *rgba);
+struct nk_color nk_rgba_f(float r, float g, float b, float a);
+struct nk_color nk_rgba_fv(const float *rgba);
+struct nk_color nk_rgba_cf(struct nk_colorf c);
+struct nk_color nk_rgba_hex(const char *rgb);
+
+struct nk_colorf nk_hsva_colorf(float h, float s, float v, float a);
+struct nk_colorf nk_hsva_colorfv(float *c);
+void nk_colorf_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_colorf in);
+void nk_colorf_hsva_fv(float *hsva, struct nk_colorf in);
+
+struct nk_color nk_hsv(int h, int s, int v);
+struct nk_color nk_hsv_iv(const int *hsv);
+struct nk_color nk_hsv_bv(const nk_byte *hsv);
+struct nk_color nk_hsv_f(float h, float s, float v);
+struct nk_color nk_hsv_fv(const float *hsv);
+
+struct nk_color nk_hsva(int h, int s, int v, int a);
+struct nk_color nk_hsva_iv(const int *hsva);
+struct nk_color nk_hsva_bv(const nk_byte *hsva);
+struct nk_color nk_hsva_f(float h, float s, float v, float a);
+struct nk_color nk_hsva_fv(const float *hsva);
+
+/* color (conversion nuklear --> user) */
+void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color);
+void nk_color_fv(float *rgba_out, struct nk_color);
+struct nk_colorf nk_color_cf(struct nk_color);
+void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color);
+void nk_color_dv(double *rgba_out, struct nk_color);
+
+nk_uint nk_color_u32(struct nk_color);
+void nk_color_hex_rgba(char *output, struct nk_color);
+void nk_color_hex_rgb(char *output, struct nk_color);
+
+void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color);
+void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color);
+void nk_color_hsv_iv(int *hsv_out, struct nk_color);
+void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color);
+void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color);
+void nk_color_hsv_fv(float *hsv_out, struct nk_color);
+
+void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color);
+void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color);
+void nk_color_hsva_iv(int *hsva_out, struct nk_color);
+void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color);
+void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color);
+void nk_color_hsva_fv(float *hsva_out, struct nk_color);
+/* =============================================================================
+ *
+ * IMAGE
+ *
+ * ============================================================================= */
+nk_handle nk_handle_ptr(void*);
+nk_handle nk_handle_id(int);
+struct nk_image nk_image_handle(nk_handle);
+struct nk_image nk_image_ptr(void*);
+struct nk_image nk_image_id(int);
+nk_bool nk_image_is_subimage(const struct nk_image* img);
+struct nk_image nk_subimage_ptr(void*, unsigned short w, unsigned short h, struct nk_rect sub_region);
+struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region);
+struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region);
+/* =============================================================================
+ *
+ * MATH
+ *
+ * ============================================================================= */
+nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed);
+void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading);
+
+struct nk_vec2 nk_vec2(float x, float y);
+struct nk_vec2 nk_vec2i(int x, int y);
+struct nk_vec2 nk_vec2v(const float *xy);
+struct nk_vec2 nk_vec2iv(const int *xy);
+
+struct nk_rect nk_get_null_rect(void);
+struct nk_rect nk_rect(float x, float y, float w, float h);
+struct nk_rect nk_recti(int x, int y, int w, int h);
+struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size);
+struct nk_rect nk_rectv(const float *xywh);
+struct nk_rect nk_rectiv(const int *xywh);
+struct nk_vec2 nk_rect_pos(struct nk_rect);
+struct nk_vec2 nk_rect_size(struct nk_rect);
+/* =============================================================================
+ *
+ * STRING
+ *
+ * ============================================================================= */
+int nk_strlen(const char *str);
+int nk_stricmp(const char *s1, const char *s2);
+int nk_stricmpn(const char *s1, const char *s2, int n);
+int nk_strtoi(const char *str, const char **endptr);
+float nk_strtof(const char *str, const char **endptr);
+
+int nk_strfilter(const char *text, const char *regexp);
+int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score);
+int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score);
+/* =============================================================================
+ *
+ * UTF-8
+ *
+ * ============================================================================= */
+int nk_utf_decode(const char*, nk_rune*, int);
+int nk_utf_encode(nk_rune, char*, int);
+int nk_utf_len(const char*, int byte_len);
+const char* nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len);
+/* ===============================================================
+ *
+ * FONT
+ *
+ * ===============================================================*/
+/* Font handling in this library was designed to be quite customizable and lets
+ you decide what you want to use and what you want to provide. There are three
+ different ways to use the font atlas. The first two will use your font
+ handling scheme and only requires essential data to run nuklear. The next
+ slightly more advanced features is font handling with vertex buffer output.
+ Finally the most complex API wise is using nuklear's font baking API.
+
+ 1.) Using your own implementation without vertex buffer output
+ --------------------------------------------------------------
+ So first up the easiest way to do font handling is by just providing a
+ `nk_user_font` struct which only requires the height in pixel of the used
+ font and a callback to calculate the width of a string. This way of handling
+ fonts is best fitted for using the normal draw shape command API where you
+ do all the text drawing yourself and the library does not require any kind
+ of deeper knowledge about which font handling mechanism you use.
+ IMPORTANT: the `nk_user_font` pointer provided to nuklear has to persist
+ over the complete life time! I know this sucks but it is currently the only
+ way to switch between fonts.
+
+ float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
+ {
+ your_font_type *type = handle.ptr;
+ float text_width = ...;
+ return text_width;
+ }
+
+ struct nk_user_font font;
+ font.userdata.ptr = &your_font_class_or_struct;
+ font.height = your_font_height;
+ font.width = your_text_width_calculation;
+
+ struct nk_context ctx;
+ nk_init_default(&ctx, &font);
+
+ 2.) Using your own implementation with vertex buffer output
+ --------------------------------------------------------------
+ While the first approach works fine if you don't want to use the optional
+ vertex buffer output it is not enough if you do. To get font handling working
+ for these cases you have to provide two additional parameters inside the
+ `nk_user_font`. First a texture atlas handle used to draw text as subimages
+ of a bigger font atlas texture and a callback to query a character's glyph
+ information (offset, size, ...). So it is still possible to provide your own
+ font and use the vertex buffer output.
+
+ float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
+ {
+ your_font_type *type = handle.ptr;
+ float text_width = ...;
+ return text_width;
+ }
+ void query_your_font_glyph(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
+ {
+ your_font_type *type = handle.ptr;
+ glyph.width = ...;
+ glyph.height = ...;
+ glyph.xadvance = ...;
+ glyph.uv[0].x = ...;
+ glyph.uv[0].y = ...;
+ glyph.uv[1].x = ...;
+ glyph.uv[1].y = ...;
+ glyph.offset.x = ...;
+ glyph.offset.y = ...;
+ }
+
+ struct nk_user_font font;
+ font.userdata.ptr = &your_font_class_or_struct;
+ font.height = your_font_height;
+ font.width = your_text_width_calculation;
+ font.query = query_your_font_glyph;
+ font.texture.id = your_font_texture;
+
+ struct nk_context ctx;
+ nk_init_default(&ctx, &font);
+
+ 3.) Nuklear font baker
+ ------------------------------------
+ The final approach if you do not have a font handling functionality or don't
+ want to use it in this library is by using the optional font baker.
+ The font baker APIs can be used to create a font plus font atlas texture
+ and can be used with or without the vertex buffer output.
+
+ It still uses the `nk_user_font` struct and the two different approaches
+ previously stated still work. The font baker is not located inside
+ `nk_context` like all other systems since it can be understood as more of
+ an extension to nuklear and does not really depend on any `nk_context` state.
+
+ Font baker need to be initialized first by one of the nk_font_atlas_init_xxx
+ functions. If you don't care about memory just call the default version
+ `nk_font_atlas_init_default` which will allocate all memory from the standard library.
+ If you want to control memory allocation but you don't care if the allocated
+ memory is temporary and therefore can be freed directly after the baking process
+ is over or permanent you can call `nk_font_atlas_init`.
+
+ After successfully initializing the font baker you can add Truetype(.ttf) fonts from
+ different sources like memory or from file by calling one of the `nk_font_atlas_add_xxx`.
+ functions. Adding font will permanently store each font, font config and ttf memory block(!)
+ inside the font atlas and allows to reuse the font atlas. If you don't want to reuse
+ the font baker by for example adding additional fonts you can call
+ `nk_font_atlas_cleanup` after the baking process is over (after calling nk_font_atlas_end).
+
+ As soon as you added all fonts you wanted you can now start the baking process
+ for every selected glyph to image by calling `nk_font_atlas_bake`.
+ The baking process returns image memory, width and height which can be used to
+ either create your own image object or upload it to any graphics library.
+ No matter which case you finally have to call `nk_font_atlas_end` which
+ will free all temporary memory including the font atlas image so make sure
+ you created our texture beforehand. `nk_font_atlas_end` requires a handle
+ to your font texture or object and optionally fills a `struct nk_draw_null_texture`
+ which can be used for the optional vertex output. If you don't want it just
+ set the argument to `NULL`.
+
+ At this point you are done and if you don't want to reuse the font atlas you
+ can call `nk_font_atlas_cleanup` to free all truetype blobs and configuration
+ memory. Finally if you don't use the font atlas and any of it's fonts anymore
+ you need to call `nk_font_atlas_clear` to free all memory still being used.
+
+ struct nk_font_atlas atlas;
+ nk_font_atlas_init_default(&atlas);
+ nk_font_atlas_begin(&atlas);
+ nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, 0);
+ nk_font *font2 = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font2.ttf", 16, 0);
+ const void* img = nk_font_atlas_bake(&atlas, &img_width, &img_height, NK_FONT_ATLAS_RGBA32);
+ nk_font_atlas_end(&atlas, nk_handle_id(texture), 0);
+
+ struct nk_context ctx;
+ nk_init_default(&ctx, &font->handle);
+ while (1) {
+
+ }
+ nk_font_atlas_clear(&atlas);
+
+ The font baker API is probably the most complex API inside this library and
+ I would suggest reading some of my examples `example/` to get a grip on how
+ to use the font atlas. There are a number of details I left out. For example
+ how to merge fonts, configure a font with `nk_font_config` to use other languages,
+ use another texture coordinate format and a lot more:
+
+ struct nk_font_config cfg = nk_font_config(font_pixel_height);
+ cfg.merge_mode = nk_false or nk_true;
+ cfg.range = nk_font_korean_glyph_ranges();
+ cfg.coord_type = NK_COORD_PIXEL;
+ nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, &cfg);
+
+*/
+struct nk_user_font_glyph;
+typedef float(*nk_text_width_f)(nk_handle, float h, const char*, int len);
+typedef void(*nk_query_font_glyph_f)(nk_handle handle, float font_height,
+ struct nk_user_font_glyph *glyph,
+ nk_rune codepoint, nk_rune next_codepoint);
+
+struct nk_user_font_glyph {
+ struct nk_vec2 uv[2];
+ /* texture coordinates */
+ struct nk_vec2 offset;
+ /* offset between top left and glyph */
+ float width, height;
+ /* size of the glyph */
+ float xadvance;
+ /* offset to the next glyph */
+};
+
+
+struct nk_user_font {
+ nk_handle userdata;
+ /* user provided font handle */
+ float height;
+ /* max height of the font */
+ nk_text_width_f width;
+ /* font string width in pixel callback */
+
+ nk_query_font_glyph_f query;
+ /* font glyph callback to query drawing info */
+ nk_handle texture;
+ /* texture handle to the used font atlas or texture */
+
+};
+
+
+enum nk_font_coord_type {
+ NK_COORD_UV, /* texture coordinates inside font glyphs are clamped between 0-1 */
+ NK_COORD_PIXEL /* texture coordinates inside font glyphs are in absolute pixel */
+};
+
+struct nk_font;
+struct nk_baked_font {
+ float height;
+ /* height of the font */
+ float ascent, descent;
+ /* font glyphs ascent and descent */
+ nk_rune glyph_offset;
+ /* glyph array offset inside the font glyph baking output array */
+ nk_rune glyph_count;
+ /* number of glyphs of this font inside the glyph baking array output */
+ const nk_rune *ranges;
+ /* font codepoint ranges as pairs of (from/to) and 0 as last element */
+};
+
+struct nk_font_config {
+ struct nk_font_config *next;
+ /* NOTE: only used internally */
+ void *ttf_blob;
+ /* pointer to loaded TTF file memory block.
+ * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
+ nk_size ttf_size;
+ /* size of the loaded TTF file memory block
+ * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
+
+ unsigned char ttf_data_owned_by_atlas;
+ /* used inside font atlas: default to: 0*/
+ unsigned char merge_mode;
+ /* merges this font into the last font */
+ unsigned char pixel_snap;
+ /* align every character to pixel boundary (if true set oversample (1,1)) */
+ unsigned char oversample_v, oversample_h;
+ /* rasterize at hight quality for sub-pixel position */
+ unsigned char padding[3];
+
+ float size;
+ /* baked pixel height of the font */
+ enum nk_font_coord_type coord_type;
+ /* texture coordinate format with either pixel or UV coordinates */
+ struct nk_vec2 spacing;
+ /* extra pixel spacing between glyphs */
+ const nk_rune *range;
+ /* list of unicode ranges (2 values per range, zero terminated) */
+ struct nk_baked_font *font;
+ /* font to setup in the baking process: NOTE: not needed for font atlas */
+ nk_rune fallback_glyph;
+ /* fallback glyph to use if a given rune is not found */
+ struct nk_font_config *n;
+ struct nk_font_config *p;
+};
+
+struct nk_font_glyph {
+ nk_rune codepoint;
+ float xadvance;
+ float x0, y0, x1, y1, w, h;
+ float u0, v0, u1, v1;
+};
+
+struct nk_font {
+ struct nk_font *next;
+ struct nk_user_font handle;
+ struct nk_baked_font info;
+ float scale;
+ struct nk_font_glyph *glyphs;
+ const struct nk_font_glyph *fallback;
+ nk_rune fallback_codepoint;
+ nk_handle texture;
+ struct nk_font_config *config;
+};
+
+enum nk_font_atlas_format {
+ NK_FONT_ATLAS_ALPHA8,
+ NK_FONT_ATLAS_RGBA32
+};
+
+struct nk_font_atlas {
+ void *pixel;
+ int tex_width;
+ int tex_height;
+
+ struct nk_allocator permanent;
+ struct nk_allocator temporary;
+
+ struct nk_recti custom;
+ struct nk_cursor cursors[NK_CURSOR_COUNT];
+
+ int glyph_count;
+ struct nk_font_glyph *glyphs;
+ struct nk_font *default_font;
+ struct nk_font *fonts;
+ struct nk_font_config *config;
+ int font_num;
+};
+
+/* some language glyph codepoint ranges */
+const nk_rune *nk_font_default_glyph_ranges(void);
+const nk_rune *nk_font_chinese_glyph_ranges(void);
+const nk_rune *nk_font_cyrillic_glyph_ranges(void);
+const nk_rune *nk_font_korean_glyph_ranges(void);
+
+
+void nk_font_atlas_init_default(struct nk_font_atlas*);
+
+void nk_font_atlas_init(struct nk_font_atlas*, struct nk_allocator*);
+void nk_font_atlas_init_custom(struct nk_font_atlas*, struct nk_allocator *persistent, struct nk_allocator *transient);
+void nk_font_atlas_begin(struct nk_font_atlas*);
+struct nk_font_config nk_font_config(float pixel_height);
+struct nk_font *nk_font_atlas_add(struct nk_font_atlas*, const struct nk_font_config*);
+
+struct nk_font* nk_font_atlas_add_default(struct nk_font_atlas*, float height, const struct nk_font_config*);
+
+struct nk_font* nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory, nk_size size, float height, const struct nk_font_config *config);
+
+struct nk_font* nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path, float height, const struct nk_font_config*);
+struct nk_font *nk_font_atlas_add_compressed(struct nk_font_atlas*, void *memory, nk_size size, float height, const struct nk_font_config*);
+struct nk_font* nk_font_atlas_add_compressed_base85(struct nk_font_atlas*, const char *data, float height, const struct nk_font_config *config);
+const void* nk_font_atlas_bake(struct nk_font_atlas*, int *width, int *height, enum nk_font_atlas_format);
+void nk_font_atlas_end(struct nk_font_atlas*, nk_handle tex, struct nk_draw_null_texture*);
+const struct nk_font_glyph* nk_font_find_glyph(struct nk_font*, nk_rune unicode);
+void nk_font_atlas_cleanup(struct nk_font_atlas *atlas);
+void nk_font_atlas_clear(struct nk_font_atlas*);
+
+/* ==============================================================
+ *
+ * MEMORY BUFFER
+ *
+ * ===============================================================*/
+/* A basic (double)-buffer with linear allocation and resetting as only
+ freeing policy. The buffer's main purpose is to control all memory management
+ inside the GUI toolkit and still leave memory control as much as possible in
+ the hand of the user while also making sure the library is easy to use if
+ not as much control is needed.
+ In general all memory inside this library can be provided from the user in
+ three different ways.
+
+ The first way and the one providing most control is by just passing a fixed
+ size memory block. In this case all control lies in the hand of the user
+ since he can exactly control where the memory comes from and how much memory
+ the library should consume. Of course using the fixed size API removes the
+ ability to automatically resize a buffer if not enough memory is provided so
+ you have to take over the resizing. While being a fixed sized buffer sounds
+ quite limiting, it is very effective in this library since the actual memory
+ consumption is quite stable and has a fixed upper bound for a lot of cases.
+
+ If you don't want to think about how much memory the library should allocate
+ at all time or have a very dynamic UI with unpredictable memory consumption
+ habits but still want control over memory allocation you can use the dynamic
+ allocator based API. The allocator consists of two callbacks for allocating
+ and freeing memory and optional userdata so you can plugin your own allocator.
+
+ The final and easiest way can be used by defining
+ NK_INCLUDE_DEFAULT_ALLOCATOR which uses the standard library memory
+ allocation functions malloc and free and takes over complete control over
+ memory in this library.
+*/
+struct nk_memory_status {
+ void *memory;
+ unsigned int type;
+ nk_size size;
+ nk_size allocated;
+ nk_size needed;
+ nk_size calls;
+};
+
+enum nk_allocation_type {
+ NK_BUFFER_FIXED,
+ NK_BUFFER_DYNAMIC
+};
+
+enum nk_buffer_allocation_type {
+ NK_BUFFER_FRONT,
+ NK_BUFFER_BACK,
+ NK_BUFFER_MAX
+};
+
+struct nk_buffer_marker {
+ nk_bool active;
+ nk_size offset;
+};
+
+struct nk_memory {void *ptr;nk_size size;};
+struct nk_buffer {
+ struct nk_buffer_marker marker[NK_BUFFER_MAX];
+ /* buffer marker to free a buffer to a certain offset */
+ struct nk_allocator pool;
+ /* allocator callback for dynamic buffers */
+ enum nk_allocation_type type;
+ /* memory management type */
+ struct nk_memory memory;
+ /* memory and size of the current memory block */
+ float grow_factor;
+ /* growing factor for dynamic memory management */
+ nk_size allocated;
+ /* total amount of memory allocated */
+ nk_size needed;
+ /* totally consumed memory given that enough memory is present */
+ nk_size calls;
+ /* number of allocation calls */
+ nk_size size;
+ /* current size of the buffer */
+};
+
+
+void nk_buffer_init_default(struct nk_buffer*);
+
+void nk_buffer_init(struct nk_buffer*, const struct nk_allocator*, nk_size size);
+void nk_buffer_init_fixed(struct nk_buffer*, void *memory, nk_size size);
+void nk_buffer_info(struct nk_memory_status*, struct nk_buffer*);
+void nk_buffer_push(struct nk_buffer*, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align);
+void nk_buffer_mark(struct nk_buffer*, enum nk_buffer_allocation_type type);
+void nk_buffer_reset(struct nk_buffer*, enum nk_buffer_allocation_type type);
+void nk_buffer_clear(struct nk_buffer*);
+void nk_buffer_free(struct nk_buffer*);
+void *nk_buffer_memory(struct nk_buffer*);
+const void *nk_buffer_memory_const(const struct nk_buffer*);
+nk_size nk_buffer_total(struct nk_buffer*);
+
+/* ==============================================================
+ *
+ * STRING
+ *
+ * ===============================================================*/
+/* Basic string buffer which is only used in context with the text editor
+ * to manage and manipulate dynamic or fixed size string content. This is _NOT_
+ * the default string handling method. The only instance you should have any contact
+ * with this API is if you interact with an `nk_text_edit` object inside one of the
+ * copy and paste functions and even there only for more advanced cases. */
+struct nk_str {
+ struct nk_buffer buffer;
+ int len; /* in codepoints/runes/glyphs */
+};
+
+
+void nk_str_init_default(struct nk_str*);
+
+void nk_str_init(struct nk_str*, const struct nk_allocator*, nk_size size);
+void nk_str_init_fixed(struct nk_str*, void *memory, nk_size size);
+void nk_str_clear(struct nk_str*);
+void nk_str_free(struct nk_str*);
+
+int nk_str_append_text_char(struct nk_str*, const char*, int);
+int nk_str_append_str_char(struct nk_str*, const char*);
+int nk_str_append_text_utf8(struct nk_str*, const char*, int);
+int nk_str_append_str_utf8(struct nk_str*, const char*);
+int nk_str_append_text_runes(struct nk_str*, const nk_rune*, int);
+int nk_str_append_str_runes(struct nk_str*, const nk_rune*);
+
+int nk_str_insert_at_char(struct nk_str*, int pos, const char*, int);
+int nk_str_insert_at_rune(struct nk_str*, int pos, const char*, int);
+
+int nk_str_insert_text_char(struct nk_str*, int pos, const char*, int);
+int nk_str_insert_str_char(struct nk_str*, int pos, const char*);
+int nk_str_insert_text_utf8(struct nk_str*, int pos, const char*, int);
+int nk_str_insert_str_utf8(struct nk_str*, int pos, const char*);
+int nk_str_insert_text_runes(struct nk_str*, int pos, const nk_rune*, int);
+int nk_str_insert_str_runes(struct nk_str*, int pos, const nk_rune*);
+
+void nk_str_remove_chars(struct nk_str*, int len);
+void nk_str_remove_runes(struct nk_str *str, int len);
+void nk_str_delete_chars(struct nk_str*, int pos, int len);
+void nk_str_delete_runes(struct nk_str*, int pos, int len);
+
+char *nk_str_at_char(struct nk_str*, int pos);
+char *nk_str_at_rune(struct nk_str*, int pos, nk_rune *unicode, int *len);
+nk_rune nk_str_rune_at(const struct nk_str*, int pos);
+const char *nk_str_at_char_const(const struct nk_str*, int pos);
+const char *nk_str_at_const(const struct nk_str*, int pos, nk_rune *unicode, int *len);
+
+char *nk_str_get(struct nk_str*);
+const char *nk_str_get_const(const struct nk_str*);
+int nk_str_len(struct nk_str*);
+int nk_str_len_char(struct nk_str*);
+
+/*===============================================================
+ *
+ * TEXT EDITOR
+ *
+ * ===============================================================*/
+/* Editing text in this library is handled by either `nk_edit_string` or
+ * `nk_edit_buffer`. But like almost everything in this library there are multiple
+ * ways of doing it and a balance between control and ease of use with memory
+ * as well as functionality controlled by flags.
+ *
+ * This library generally allows three different levels of memory control:
+ * First of is the most basic way of just providing a simple char array with
+ * string length. This method is probably the easiest way of handling simple
+ * user text input. Main upside is complete control over memory while the biggest
+ * downside in comparison with the other two approaches is missing undo/redo.
+ *
+ * For UIs that require undo/redo the second way was created. It is based on
+ * a fixed size nk_text_edit struct, which has an internal undo/redo stack.
+ * This is mainly useful if you want something more like a text editor but don't want
+ * to have a dynamically growing buffer.
+ *
+ * The final way is using a dynamically growing nk_text_edit struct, which
+ * has both a default version if you don't care where memory comes from and an
+ * allocator version if you do. While the text editor is quite powerful for its
+ * complexity I would not recommend editing gigabytes of data with it.
+ * It is rather designed for uses cases which make sense for a GUI library not for
+ * an full blown text editor.
+ */
+
+ enum {
+ NK_TEXTEDIT_UNDOSTATECOUNT = 99,
+ NK_TEXTEDIT_UNDOCHARCOUNT = 999
+ };
+
+struct nk_text_edit;
+struct nk_clipboard {
+ nk_handle userdata;
+ nk_plugin_paste paste;
+ nk_plugin_copy copy;
+};
+
+struct nk_text_undo_record {
+ int where;
+ short insert_length;
+ short delete_length;
+ short char_storage;
+};
+
+struct nk_text_undo_state {
+ struct nk_text_undo_record undo_rec[NK_TEXTEDIT_UNDOSTATECOUNT];
+ nk_rune undo_char[NK_TEXTEDIT_UNDOCHARCOUNT];
+ short undo_point;
+ short redo_point;
+ short undo_char_point;
+ short redo_char_point;
+};
+
+enum nk_text_edit_type {
+ NK_TEXT_EDIT_SINGLE_LINE,
+ NK_TEXT_EDIT_MULTI_LINE
+};
+
+enum nk_text_edit_mode {
+ NK_TEXT_EDIT_MODE_VIEW,
+ NK_TEXT_EDIT_MODE_INSERT,
+ NK_TEXT_EDIT_MODE_REPLACE
+};
+
+struct nk_text_edit {
+ struct nk_clipboard clip;
+ struct nk_str string;
+ nk_plugin_filter filter;
+ struct nk_vec2 scrollbar;
+
+ int cursor;
+ int select_start;
+ int select_end;
+ unsigned char mode;
+ unsigned char cursor_at_end_of_line;
+ unsigned char initialized;
+ unsigned char has_preferred_x;
+ unsigned char single_line;
+ unsigned char active;
+ unsigned char padding1;
+ float preferred_x;
+ struct nk_text_undo_state undo;
+};
+
+/* filter function */
+nk_bool nk_filter_default(const struct nk_text_edit*, nk_rune unicode);
+nk_bool nk_filter_ascii(const struct nk_text_edit*, nk_rune unicode);
+nk_bool nk_filter_float(const struct nk_text_edit*, nk_rune unicode);
+nk_bool nk_filter_decimal(const struct nk_text_edit*, nk_rune unicode);
+nk_bool nk_filter_hex(const struct nk_text_edit*, nk_rune unicode);
+nk_bool nk_filter_oct(const struct nk_text_edit*, nk_rune unicode);
+nk_bool nk_filter_binary(const struct nk_text_edit*, nk_rune unicode);
+
+/* text editor */
+
+void nk_textedit_init_default(struct nk_text_edit*);
+
+void nk_textedit_init(struct nk_text_edit*, struct nk_allocator*, nk_size size);
+void nk_textedit_init_fixed(struct nk_text_edit*, void *memory, nk_size size);
+void nk_textedit_free(struct nk_text_edit*);
+void nk_textedit_text(struct nk_text_edit*, const char*, int total_len);
+void nk_textedit_delete(struct nk_text_edit*, int where, int len);
+void nk_textedit_delete_selection(struct nk_text_edit*);
+void nk_textedit_select_all(struct nk_text_edit*);
+nk_bool nk_textedit_cut(struct nk_text_edit*);
+nk_bool nk_textedit_paste(struct nk_text_edit*, char const*, int len);
+void nk_textedit_undo(struct nk_text_edit*);
+void nk_textedit_redo(struct nk_text_edit*);
+]]
+
+ffi.cdef[[
+
+/* ===============================================================
+ *
+ * DRAWING
+ *
+ * ===============================================================*/
+/* This library was designed to be render backend agnostic so it does
+ not draw anything to screen. Instead all drawn shapes, widgets
+ are made of, are buffered into memory and make up a command queue.
+ Each frame therefore fills the command buffer with draw commands
+ that then need to be executed by the user and his own render backend.
+ After that the command buffer needs to be cleared and a new frame can be
+ started. It is probably important to note that the command buffer is the main
+ drawing API and the optional vertex buffer API only takes this format and
+ converts it into a hardware accessible format.
+
+ To use the command queue to draw your own widgets you can access the
+ command buffer of each window by calling `nk_window_get_canvas` after
+ previously having called `nk_begin`:
+
+ void draw_red_rectangle_widget(struct nk_context *ctx)
+ {
+ struct nk_command_buffer *canvas;
+ struct nk_input *input = &ctx->input;
+ canvas = nk_window_get_canvas(ctx);
+
+ struct nk_rect space;
+ enum nk_widget_layout_states state;
+ state = nk_widget(&space, ctx);
+ if (!state) return;
+
+ if (state != NK_WIDGET_ROM)
+ update_your_widget_by_user_input(...);
+ nk_fill_rect(canvas, space, 0, nk_rgb(255,0,0));
+ }
+
+ if (nk_begin(...)) {
+ nk_layout_row_dynamic(ctx, 25, 1);
+ draw_red_rectangle_widget(ctx);
+ }
+ nk_end(..)
+
+ Important to know if you want to create your own widgets is the `nk_widget`
+ call. It allocates space on the panel reserved for this widget to be used,
+ but also returns the state of the widget space. If your widget is not seen and does
+ not have to be updated it is '0' and you can just return. If it only has
+ to be drawn the state will be `NK_WIDGET_ROM` otherwise you can do both
+ update and draw your widget. The reason for separating is to only draw and
+ update what is actually necessary which is crucial for performance.
+*/
+enum nk_command_type {
+ NK_COMMAND_NOP,
+ NK_COMMAND_SCISSOR,
+ NK_COMMAND_LINE,
+ NK_COMMAND_CURVE,
+ NK_COMMAND_RECT,
+ NK_COMMAND_RECT_FILLED,
+ NK_COMMAND_RECT_MULTI_COLOR,
+ NK_COMMAND_CIRCLE,
+ NK_COMMAND_CIRCLE_FILLED,
+ NK_COMMAND_ARC,
+ NK_COMMAND_ARC_FILLED,
+ NK_COMMAND_TRIANGLE,
+ NK_COMMAND_TRIANGLE_FILLED,
+ NK_COMMAND_POLYGON,
+ NK_COMMAND_POLYGON_FILLED,
+ NK_COMMAND_POLYLINE,
+ NK_COMMAND_TEXT,
+ NK_COMMAND_IMAGE,
+ NK_COMMAND_CUSTOM
+};
+
+/* command base and header of every command inside the buffer */
+struct nk_command {
+ enum nk_command_type type;
+ nk_size next;
+
+};
+
+struct nk_command_scissor {
+ struct nk_command header;
+ short x, y;
+ unsigned short w, h;
+};
+
+struct nk_command_line {
+ struct nk_command header;
+ unsigned short line_thickness;
+ struct nk_vec2i begin;
+ struct nk_vec2i end;
+ struct nk_color color;
+};
+
+struct nk_command_curve {
+ struct nk_command header;
+ unsigned short line_thickness;
+ struct nk_vec2i begin;
+ struct nk_vec2i end;
+ struct nk_vec2i ctrl[2];
+ struct nk_color color;
+};
+
+struct nk_command_rect {
+ struct nk_command header;
+ unsigned short rounding;
+ unsigned short line_thickness;
+ short x, y;
+ unsigned short w, h;
+ struct nk_color color;
+};
+
+struct nk_command_rect_filled {
+ struct nk_command header;
+ unsigned short rounding;
+ short x, y;
+ unsigned short w, h;
+ struct nk_color color;
+};
+
+struct nk_command_rect_multi_color {
+ struct nk_command header;
+ short x, y;
+ unsigned short w, h;
+ struct nk_color left;
+ struct nk_color top;
+ struct nk_color bottom;
+ struct nk_color right;
+};
+
+struct nk_command_triangle {
+ struct nk_command header;
+ unsigned short line_thickness;
+ struct nk_vec2i a;
+ struct nk_vec2i b;
+ struct nk_vec2i c;
+ struct nk_color color;
+};
+
+struct nk_command_triangle_filled {
+ struct nk_command header;
+ struct nk_vec2i a;
+ struct nk_vec2i b;
+ struct nk_vec2i c;
+ struct nk_color color;
+};
+
+struct nk_command_circle {
+ struct nk_command header;
+ short x, y;
+ unsigned short line_thickness;
+ unsigned short w, h;
+ struct nk_color color;
+};
+
+struct nk_command_circle_filled {
+ struct nk_command header;
+ short x, y;
+ unsigned short w, h;
+ struct nk_color color;
+};
+
+struct nk_command_arc {
+ struct nk_command header;
+ short cx, cy;
+ unsigned short r;
+ unsigned short line_thickness;
+ float a[2];
+ struct nk_color color;
+};
+
+struct nk_command_arc_filled {
+ struct nk_command header;
+ short cx, cy;
+ unsigned short r;
+ float a[2];
+ struct nk_color color;
+};
+
+struct nk_command_polygon {
+ struct nk_command header;
+ struct nk_color color;
+ unsigned short line_thickness;
+ unsigned short point_count;
+ struct nk_vec2i points[1];
+};
+
+struct nk_command_polygon_filled {
+ struct nk_command header;
+ struct nk_color color;
+ unsigned short point_count;
+ struct nk_vec2i points[1];
+};
+
+struct nk_command_polyline {
+ struct nk_command header;
+ struct nk_color color;
+ unsigned short line_thickness;
+ unsigned short point_count;
+ struct nk_vec2i points[1];
+};
+
+struct nk_command_image {
+ struct nk_command header;
+ short x, y;
+ unsigned short w, h;
+ struct nk_image img;
+ struct nk_color col;
+};
+
+typedef void (*nk_command_custom_callback)(void *canvas, short x,short y,
+ unsigned short w, unsigned short h, nk_handle callback_data);
+struct nk_command_custom {
+ struct nk_command header;
+ short x, y;
+ unsigned short w, h;
+ nk_handle callback_data;
+ nk_command_custom_callback callback;
+};
+
+struct nk_command_text {
+ struct nk_command header;
+ const struct nk_user_font *font;
+ struct nk_color background;
+ struct nk_color foreground;
+ short x, y;
+ unsigned short w, h;
+ float height;
+ int length;
+ char string[1];
+};
+
+enum nk_command_clipping {
+ NK_CLIPPING_OFF = nk_false,
+ NK_CLIPPING_ON = nk_true
+};
+
+struct nk_command_buffer {
+ struct nk_buffer *base;
+ struct nk_rect clip;
+ int use_clipping;
+ nk_handle userdata;
+ nk_size begin, end, last;
+};
+
+/* shape outlines */
+void nk_stroke_line(struct nk_command_buffer *b, float x0, float y0, float x1, float y1, float line_thickness, struct nk_color);
+void nk_stroke_curve(struct nk_command_buffer*, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color);
+void nk_stroke_rect(struct nk_command_buffer*, struct nk_rect, float rounding, float line_thickness, struct nk_color);
+void nk_stroke_circle(struct nk_command_buffer*, struct nk_rect, float line_thickness, struct nk_color);
+void nk_stroke_arc(struct nk_command_buffer*, float cx, float cy, float radius, float a_min, float a_max, float line_thickness, struct nk_color);
+void nk_stroke_triangle(struct nk_command_buffer*, float, float, float, float, float, float, float line_thichness, struct nk_color);
+void nk_stroke_polyline(struct nk_command_buffer*, float *points, int point_count, float line_thickness, struct nk_color col);
+void nk_stroke_polygon(struct nk_command_buffer*, float*, int point_count, float line_thickness, struct nk_color);
+
+/* filled shades */
+void nk_fill_rect(struct nk_command_buffer*, struct nk_rect, float rounding, struct nk_color);
+void nk_fill_rect_multi_color(struct nk_command_buffer*, struct nk_rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom);
+void nk_fill_circle(struct nk_command_buffer*, struct nk_rect, struct nk_color);
+void nk_fill_arc(struct nk_command_buffer*, float cx, float cy, float radius, float a_min, float a_max, struct nk_color);
+void nk_fill_triangle(struct nk_command_buffer*, float x0, float y0, float x1, float y1, float x2, float y2, struct nk_color);
+void nk_fill_polygon(struct nk_command_buffer*, float*, int point_count, struct nk_color);
+
+/* misc */
+void nk_draw_image(struct nk_command_buffer*, struct nk_rect, const struct nk_image*, struct nk_color);
+void nk_draw_text(struct nk_command_buffer*, struct nk_rect, const char *text, int len, const struct nk_user_font*, struct nk_color, struct nk_color);
+void nk_push_scissor(struct nk_command_buffer*, struct nk_rect);
+void nk_push_custom(struct nk_command_buffer*, struct nk_rect, nk_command_custom_callback, nk_handle usr);
+
+]]
+
+ffi.cdef[[
+
+/* ===============================================================
+ *
+ * INPUT
+ *
+ * ===============================================================*/
+struct nk_mouse_button {
+ nk_bool down;
+ unsigned int clicked;
+ struct nk_vec2 clicked_pos;
+};
+struct nk_mouse {
+ struct nk_mouse_button buttons[NK_BUTTON_MAX];
+ struct nk_vec2 pos;
+ struct nk_vec2 prev;
+ struct nk_vec2 delta;
+ struct nk_vec2 scroll_delta;
+ unsigned char grab;
+ unsigned char grabbed;
+ unsigned char ungrab;
+};
+
+struct nk_key {
+ nk_bool down;
+ unsigned int clicked;
+};
+struct nk_keyboard {
+ struct nk_key keys[NK_KEY_MAX];
+ char text[NK_INPUT_MAX];
+ int text_len;
+};
+
+struct nk_input {
+ struct nk_keyboard keyboard;
+ struct nk_mouse mouse;
+};
+
+nk_bool nk_input_has_mouse_click(const struct nk_input*, enum nk_buttons);
+nk_bool nk_input_has_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
+nk_bool nk_input_has_mouse_click_down_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect, nk_bool down);
+nk_bool nk_input_is_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
+nk_bool nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, struct nk_rect b, nk_bool down);
+nk_bool nk_input_any_mouse_click_in_rect(const struct nk_input*, struct nk_rect);
+nk_bool nk_input_is_mouse_prev_hovering_rect(const struct nk_input*, struct nk_rect);
+nk_bool nk_input_is_mouse_hovering_rect(const struct nk_input*, struct nk_rect);
+nk_bool nk_input_mouse_clicked(const struct nk_input*, enum nk_buttons, struct nk_rect);
+nk_bool nk_input_is_mouse_down(const struct nk_input*, enum nk_buttons);
+nk_bool nk_input_is_mouse_pressed(const struct nk_input*, enum nk_buttons);
+nk_bool nk_input_is_mouse_released(const struct nk_input*, enum nk_buttons);
+nk_bool nk_input_is_key_pressed(const struct nk_input*, enum nk_keys);
+nk_bool nk_input_is_key_released(const struct nk_input*, enum nk_keys);
+nk_bool nk_input_is_key_down(const struct nk_input*, enum nk_keys);
+
+]]
+
+ffi.cdef[[
+/* ===============================================================
+ *
+ * DRAW LIST
+ *
+ * ===============================================================*/
+/* The optional vertex buffer draw list provides a 2D drawing context
+ with antialiasing functionality which takes basic filled or outlined shapes
+ or a path and outputs vertexes, elements and draw commands.
+ The actual draw list API is not required to be used directly while using this
+ library since converting the default library draw command output is done by
+ just calling `nk_convert` but I decided to still make this library accessible
+ since it can be useful.
+
+ The draw list is based on a path buffering and polygon and polyline
+ rendering API which allows a lot of ways to draw 2D content to screen.
+ In fact it is probably more powerful than needed but allows even more crazy
+ things than this library provides by default.
+*/
+
+typedef nk_uint nk_draw_index;
+enum nk_draw_list_stroke {
+ NK_STROKE_OPEN = nk_false,
+ /* build up path has no connection back to the beginning */
+ NK_STROKE_CLOSED = nk_true
+ /* build up path has a connection back to the beginning */
+};
+
+enum nk_draw_vertex_layout_attribute {
+ NK_VERTEX_POSITION,
+ NK_VERTEX_COLOR,
+ NK_VERTEX_TEXCOORD,
+ NK_VERTEX_ATTRIBUTE_COUNT
+};
+
+enum nk_draw_vertex_layout_format {
+ NK_FORMAT_SCHAR,
+ NK_FORMAT_SSHORT,
+ NK_FORMAT_SINT,
+ NK_FORMAT_UCHAR,
+ NK_FORMAT_USHORT,
+ NK_FORMAT_UINT,
+ NK_FORMAT_FLOAT,
+ NK_FORMAT_DOUBLE,
+
+NK_FORMAT_COLOR_BEGIN,
+ NK_FORMAT_R8G8B8 = NK_FORMAT_COLOR_BEGIN,
+ NK_FORMAT_R16G15B16,
+ NK_FORMAT_R32G32B32,
+
+ NK_FORMAT_R8G8B8A8,
+ NK_FORMAT_B8G8R8A8,
+ NK_FORMAT_R16G15B16A16,
+ NK_FORMAT_R32G32B32A32,
+ NK_FORMAT_R32G32B32A32_FLOAT,
+ NK_FORMAT_R32G32B32A32_DOUBLE,
+
+ NK_FORMAT_RGB32,
+ NK_FORMAT_RGBA32,
+NK_FORMAT_COLOR_END = NK_FORMAT_RGBA32,
+ NK_FORMAT_COUNT
+};
+
+struct nk_draw_vertex_layout_element {
+ enum nk_draw_vertex_layout_attribute attribute;
+ enum nk_draw_vertex_layout_format format;
+ nk_size offset;
+};
+
+struct nk_draw_command {
+ unsigned int elem_count;
+ /* number of elements in the current draw batch */
+ struct nk_rect clip_rect;
+ /* current screen clipping rectangle */
+ nk_handle texture;
+ /* current texture to set */
+};
+
+struct nk_draw_list {
+ struct nk_rect clip_rect;
+ struct nk_vec2 circle_vtx[12];
+ struct nk_convert_config config;
+
+ struct nk_buffer *buffer;
+ struct nk_buffer *vertices;
+ struct nk_buffer *elements;
+
+ unsigned int element_count;
+ unsigned int vertex_count;
+ unsigned int cmd_count;
+ nk_size cmd_offset;
+
+ unsigned int path_count;
+ unsigned int path_offset;
+
+ enum nk_anti_aliasing line_AA;
+ enum nk_anti_aliasing shape_AA;
+
+};
+
+/* draw list */
+void nk_draw_list_init(struct nk_draw_list*);
+void nk_draw_list_setup(struct nk_draw_list*, const struct nk_convert_config*, struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, enum nk_anti_aliasing line_aa,enum nk_anti_aliasing shape_aa);
+
+/* drawing */
+
+const struct nk_draw_command* nk__draw_list_begin(const struct nk_draw_list*, const struct nk_buffer*);
+const struct nk_draw_command* nk__draw_list_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_draw_list*);
+const struct nk_draw_command* nk__draw_list_end(const struct nk_draw_list*, const struct nk_buffer*);
+
+/* path */
+void nk_draw_list_path_clear(struct nk_draw_list*);
+void nk_draw_list_path_line_to(struct nk_draw_list*, struct nk_vec2 pos);
+void nk_draw_list_path_arc_to_fast(struct nk_draw_list*, struct nk_vec2 center, float radius, int a_min, int a_max);
+void nk_draw_list_path_arc_to(struct nk_draw_list*, struct nk_vec2 center, float radius, float a_min, float a_max, unsigned int segments);
+void nk_draw_list_path_rect_to(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, float rounding);
+void nk_draw_list_path_curve_to(struct nk_draw_list*, struct nk_vec2 p2, struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments);
+void nk_draw_list_path_fill(struct nk_draw_list*, struct nk_color);
+void nk_draw_list_path_stroke(struct nk_draw_list*, struct nk_color, enum nk_draw_list_stroke closed, float thickness);
+
+/* stroke */
+void nk_draw_list_stroke_line(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_color, float thickness);
+void nk_draw_list_stroke_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding, float thickness);
+void nk_draw_list_stroke_triangle(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_vec2 c, struct nk_color, float thickness);
+void nk_draw_list_stroke_circle(struct nk_draw_list*, struct nk_vec2 center, float radius, struct nk_color, unsigned int segs, float thickness);
+void nk_draw_list_stroke_curve(struct nk_draw_list*, struct nk_vec2 p0, struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1, struct nk_color, unsigned int segments, float thickness);
+void nk_draw_list_stroke_poly_line(struct nk_draw_list*, const struct nk_vec2 *pnts, const unsigned int cnt, struct nk_color, enum nk_draw_list_stroke, float thickness, enum nk_anti_aliasing);
+
+/* fill */
+void nk_draw_list_fill_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding);
+void nk_draw_list_fill_rect_multi_color(struct nk_draw_list*, struct nk_rect rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom);
+void nk_draw_list_fill_triangle(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_vec2 c, struct nk_color);
+void nk_draw_list_fill_circle(struct nk_draw_list*, struct nk_vec2 center, float radius, struct nk_color col, unsigned int segs);
+void nk_draw_list_fill_poly_convex(struct nk_draw_list*, const struct nk_vec2 *points, const unsigned int count, struct nk_color, enum nk_anti_aliasing);
+
+/* misc */
+void nk_draw_list_add_image(struct nk_draw_list*, struct nk_image texture, struct nk_rect rect, struct nk_color);
+void nk_draw_list_add_text(struct nk_draw_list*, const struct nk_user_font*, struct nk_rect, const char *text, int len, float font_height, struct nk_color);
+
+]]
+
+ffi.cdef[[
+/* ===============================================================
+ *
+ * GUI
+ *
+ * ===============================================================*/
+enum nk_style_item_type {
+ NK_STYLE_ITEM_COLOR,
+ NK_STYLE_ITEM_IMAGE
+};
+
+union nk_style_item_data {
+ struct nk_image image;
+ struct nk_color color;
+};
+
+struct nk_style_item {
+ enum nk_style_item_type type;
+ union nk_style_item_data data;
+};
+
+struct nk_style_text {
+ struct nk_color color;
+ struct nk_vec2 padding;
+};
+
+struct nk_style_button {
+ /* background */
+ struct nk_style_item normal;
+ struct nk_style_item hover;
+ struct nk_style_item active;
+ struct nk_color border_color;
+
+ /* text */
+ struct nk_color text_background;
+ struct nk_color text_normal;
+ struct nk_color text_hover;
+ struct nk_color text_active;
+ nk_flags text_alignment;
+
+ /* properties */
+ float border;
+ float rounding;
+ struct nk_vec2 padding;
+ struct nk_vec2 image_padding;
+ struct nk_vec2 touch_padding;
+
+ /* optional user callbacks */
+ nk_handle userdata;
+ void(*draw_begin)(struct nk_command_buffer*, nk_handle userdata);
+ void(*draw_end)(struct nk_command_buffer*, nk_handle userdata);
+};
+
+struct nk_style_toggle {
+ /* background */
+ struct nk_style_item normal;
+ struct nk_style_item hover;
+ struct nk_style_item active;
+ struct nk_color border_color;
+
+ /* cursor */
+ struct nk_style_item cursor_normal;
+ struct nk_style_item cursor_hover;
+
+ /* text */
+ struct nk_color text_normal;
+ struct nk_color text_hover;
+ struct nk_color text_active;
+ struct nk_color text_background;
+ nk_flags text_alignment;
+
+ /* properties */
+ struct nk_vec2 padding;
+ struct nk_vec2 touch_padding;
+ float spacing;
+ float border;
+
+ /* optional user callbacks */
+ nk_handle userdata;
+ void(*draw_begin)(struct nk_command_buffer*, nk_handle);
+ void(*draw_end)(struct nk_command_buffer*, nk_handle);
+};
+
+struct nk_style_selectable {
+ /* background (inactive) */
+ struct nk_style_item normal;
+ struct nk_style_item hover;
+ struct nk_style_item pressed;
+
+ /* background (active) */
+ struct nk_style_item normal_active;
+ struct nk_style_item hover_active;
+ struct nk_style_item pressed_active;
+
+ /* text color (inactive) */
+ struct nk_color text_normal;
+ struct nk_color text_hover;
+ struct nk_color text_pressed;
+
+ /* text color (active) */
+ struct nk_color text_normal_active;
+ struct nk_color text_hover_active;
+ struct nk_color text_pressed_active;
+ struct nk_color text_background;
+ nk_flags text_alignment;
+
+ /* properties */
+ float rounding;
+ struct nk_vec2 padding;
+ struct nk_vec2 touch_padding;
+ struct nk_vec2 image_padding;
+
+ /* optional user callbacks */
+ nk_handle userdata;
+ void(*draw_begin)(struct nk_command_buffer*, nk_handle);
+ void(*draw_end)(struct nk_command_buffer*, nk_handle);
+};
+
+struct nk_style_slider {
+ /* background */
+ struct nk_style_item normal;
+ struct nk_style_item hover;
+ struct nk_style_item active;
+ struct nk_color border_color;
+
+ /* background bar */
+ struct nk_color bar_normal;
+ struct nk_color bar_hover;
+ struct nk_color bar_active;
+ struct nk_color bar_filled;
+
+ /* cursor */
+ struct nk_style_item cursor_normal;
+ struct nk_style_item cursor_hover;
+ struct nk_style_item cursor_active;
+
+ /* properties */
+ float border;
+ float rounding;
+ float bar_height;
+ struct nk_vec2 padding;
+ struct nk_vec2 spacing;
+ struct nk_vec2 cursor_size;
+
+ /* optional buttons */
+ int show_buttons;
+ struct nk_style_button inc_button;
+ struct nk_style_button dec_button;
+ enum nk_symbol_type inc_symbol;
+ enum nk_symbol_type dec_symbol;
+
+ /* optional user callbacks */
+ nk_handle userdata;
+ void(*draw_begin)(struct nk_command_buffer*, nk_handle);
+ void(*draw_end)(struct nk_command_buffer*, nk_handle);
+};
+
+struct nk_style_progress {
+ /* background */
+ struct nk_style_item normal;
+ struct nk_style_item hover;
+ struct nk_style_item active;
+ struct nk_color border_color;
+
+ /* cursor */
+ struct nk_style_item cursor_normal;
+ struct nk_style_item cursor_hover;
+ struct nk_style_item cursor_active;
+ struct nk_color cursor_border_color;
+
+ /* properties */
+ float rounding;
+ float border;
+ float cursor_border;
+ float cursor_rounding;
+ struct nk_vec2 padding;
+
+ /* optional user callbacks */
+ nk_handle userdata;
+ void(*draw_begin)(struct nk_command_buffer*, nk_handle);
+ void(*draw_end)(struct nk_command_buffer*, nk_handle);
+};
+
+struct nk_style_scrollbar {
+ /* background */
+ struct nk_style_item normal;
+ struct nk_style_item hover;
+ struct nk_style_item active;
+ struct nk_color border_color;
+
+ /* cursor */
+ struct nk_style_item cursor_normal;
+ struct nk_style_item cursor_hover;
+ struct nk_style_item cursor_active;
+ struct nk_color cursor_border_color;
+
+ /* properties */
+ float border;
+ float rounding;
+ float border_cursor;
+ float rounding_cursor;
+ struct nk_vec2 padding;
+
+ /* optional buttons */
+ int show_buttons;
+ struct nk_style_button inc_button;
+ struct nk_style_button dec_button;
+ enum nk_symbol_type inc_symbol;
+ enum nk_symbol_type dec_symbol;
+
+ /* optional user callbacks */
+ nk_handle userdata;
+ void(*draw_begin)(struct nk_command_buffer*, nk_handle);
+ void(*draw_end)(struct nk_command_buffer*, nk_handle);
+};
+
+struct nk_style_edit {
+ /* background */
+ struct nk_style_item normal;
+ struct nk_style_item hover;
+ struct nk_style_item active;
+ struct nk_color border_color;
+ struct nk_style_scrollbar scrollbar;
+
+ /* cursor */
+ struct nk_color cursor_normal;
+ struct nk_color cursor_hover;
+ struct nk_color cursor_text_normal;
+ struct nk_color cursor_text_hover;
+
+ /* text (unselected) */
+ struct nk_color text_normal;
+ struct nk_color text_hover;
+ struct nk_color text_active;
+
+ /* text (selected) */
+ struct nk_color selected_normal;
+ struct nk_color selected_hover;
+ struct nk_color selected_text_normal;
+ struct nk_color selected_text_hover;
+
+ /* properties */
+ float border;
+ float rounding;
+ float cursor_size;
+ struct nk_vec2 scrollbar_size;
+ struct nk_vec2 padding;
+ float row_padding;
+};
+
+struct nk_style_property {
+ /* background */
+ struct nk_style_item normal;
+ struct nk_style_item hover;
+ struct nk_style_item active;
+ struct nk_color border_color;
+
+ /* text */
+ struct nk_color label_normal;
+ struct nk_color label_hover;
+ struct nk_color label_active;
+
+ /* symbols */
+ enum nk_symbol_type sym_left;
+ enum nk_symbol_type sym_right;
+
+ /* properties */
+ float border;
+ float rounding;
+ struct nk_vec2 padding;
+
+ struct nk_style_edit edit;
+ struct nk_style_button inc_button;
+ struct nk_style_button dec_button;
+
+ /* optional user callbacks */
+ nk_handle userdata;
+ void(*draw_begin)(struct nk_command_buffer*, nk_handle);
+ void(*draw_end)(struct nk_command_buffer*, nk_handle);
+};
+
+struct nk_style_chart {
+ /* colors */
+ struct nk_style_item background;
+ struct nk_color border_color;
+ struct nk_color selected_color;
+ struct nk_color color;
+
+ /* properties */
+ float border;
+ float rounding;
+ struct nk_vec2 padding;
+};
+
+struct nk_style_combo {
+ /* background */
+ struct nk_style_item normal;
+ struct nk_style_item hover;
+ struct nk_style_item active;
+ struct nk_color border_color;
+
+ /* label */
+ struct nk_color label_normal;
+ struct nk_color label_hover;
+ struct nk_color label_active;
+
+ /* symbol */
+ struct nk_color symbol_normal;
+ struct nk_color symbol_hover;
+ struct nk_color symbol_active;
+
+ /* button */
+ struct nk_style_button button;
+ enum nk_symbol_type sym_normal;
+ enum nk_symbol_type sym_hover;
+ enum nk_symbol_type sym_active;
+
+ /* properties */
+ float border;
+ float rounding;
+ struct nk_vec2 content_padding;
+ struct nk_vec2 button_padding;
+ struct nk_vec2 spacing;
+};
+
+struct nk_style_tab {
+ /* background */
+ struct nk_style_item background;
+ struct nk_color border_color;
+ struct nk_color text;
+
+ /* button */
+ struct nk_style_button tab_maximize_button;
+ struct nk_style_button tab_minimize_button;
+ struct nk_style_button node_maximize_button;
+ struct nk_style_button node_minimize_button;
+ enum nk_symbol_type sym_minimize;
+ enum nk_symbol_type sym_maximize;
+
+ /* properties */
+ float border;
+ float rounding;
+ float indent;
+ struct nk_vec2 padding;
+ struct nk_vec2 spacing;
+};
+
+enum nk_style_header_align {
+ NK_HEADER_LEFT,
+ NK_HEADER_RIGHT
+};
+struct nk_style_window_header {
+ /* background */
+ struct nk_style_item normal;
+ struct nk_style_item hover;
+ struct nk_style_item active;
+
+ /* button */
+ struct nk_style_button close_button;
+ struct nk_style_button minimize_button;
+ enum nk_symbol_type close_symbol;
+ enum nk_symbol_type minimize_symbol;
+ enum nk_symbol_type maximize_symbol;
+
+ /* title */
+ struct nk_color label_normal;
+ struct nk_color label_hover;
+ struct nk_color label_active;
+
+ /* properties */
+ enum nk_style_header_align align;
+ struct nk_vec2 padding;
+ struct nk_vec2 label_padding;
+ struct nk_vec2 spacing;
+};
+
+struct nk_style_window {
+ struct nk_style_window_header header;
+ struct nk_style_item fixed_background;
+ struct nk_color background;
+
+ struct nk_color border_color;
+ struct nk_color popup_border_color;
+ struct nk_color combo_border_color;
+ struct nk_color contextual_border_color;
+ struct nk_color menu_border_color;
+ struct nk_color group_border_color;
+ struct nk_color tooltip_border_color;
+ struct nk_style_item scaler;
+
+ float border;
+ float combo_border;
+ float contextual_border;
+ float menu_border;
+ float group_border;
+ float tooltip_border;
+ float popup_border;
+ float min_row_height_padding;
+
+ float rounding;
+ struct nk_vec2 spacing;
+ struct nk_vec2 scrollbar_size;
+ struct nk_vec2 min_size;
+
+ struct nk_vec2 padding;
+ struct nk_vec2 group_padding;
+ struct nk_vec2 popup_padding;
+ struct nk_vec2 combo_padding;
+ struct nk_vec2 contextual_padding;
+ struct nk_vec2 menu_padding;
+ struct nk_vec2 tooltip_padding;
+};
+
+struct nk_style {
+ const struct nk_user_font *font;
+ const struct nk_cursor *cursors[NK_CURSOR_COUNT];
+ const struct nk_cursor *cursor_active;
+ struct nk_cursor *cursor_last;
+ int cursor_visible;
+
+ struct nk_style_text text;
+ struct nk_style_button button;
+ struct nk_style_button contextual_button;
+ struct nk_style_button menu_button;
+ struct nk_style_toggle option;
+ struct nk_style_toggle checkbox;
+ struct nk_style_selectable selectable;
+ struct nk_style_slider slider;
+ struct nk_style_progress progress;
+ struct nk_style_property property;
+ struct nk_style_edit edit;
+ struct nk_style_chart chart;
+ struct nk_style_scrollbar scrollh;
+ struct nk_style_scrollbar scrollv;
+ struct nk_style_tab tab;
+ struct nk_style_combo combo;
+ struct nk_style_window window;
+};
+
+struct nk_style_item nk_style_item_image(struct nk_image img);
+struct nk_style_item nk_style_item_color(struct nk_color);
+struct nk_style_item nk_style_item_hide(void);
+]]
+
+ffi.cdef[[
+/*==============================================================
+ * PANEL
+ * =============================================================*/
+
+enum {
+ NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS = 16,
+ NK_CHART_MAX_SLOT = 4
+};
+
+enum nk_panel_type {
+ NK_PANEL_NONE = 0,
+ NK_PANEL_WINDOW = 1,
+ NK_PANEL_GROUP = 2,
+ NK_PANEL_POPUP = 4,
+ NK_PANEL_CONTEXTUAL = 8,
+ NK_PANEL_COMBO = 16,
+ NK_PANEL_MENU = 32,
+ NK_PANEL_TOOLTIP = 64
+};
+enum nk_panel_set {
+ NK_PANEL_SET_NONBLOCK = NK_PANEL_CONTEXTUAL|NK_PANEL_COMBO|NK_PANEL_MENU|NK_PANEL_TOOLTIP,
+ NK_PANEL_SET_POPUP = NK_PANEL_SET_NONBLOCK|NK_PANEL_POPUP,
+ NK_PANEL_SET_SUB = NK_PANEL_SET_POPUP|NK_PANEL_GROUP
+};
+
+struct nk_chart_slot {
+ enum nk_chart_type type;
+ struct nk_color color;
+ struct nk_color highlight;
+ float min, max, range;
+ int count;
+ struct nk_vec2 last;
+ int index;
+};
+
+struct nk_chart {
+ int slot;
+ float x, y, w, h;
+ struct nk_chart_slot slots[NK_CHART_MAX_SLOT];
+};
+
+enum nk_panel_row_layout_type {
+ NK_LAYOUT_DYNAMIC_FIXED = 0,
+ NK_LAYOUT_DYNAMIC_ROW,
+ NK_LAYOUT_DYNAMIC_FREE,
+ NK_LAYOUT_DYNAMIC,
+ NK_LAYOUT_STATIC_FIXED,
+ NK_LAYOUT_STATIC_ROW,
+ NK_LAYOUT_STATIC_FREE,
+ NK_LAYOUT_STATIC,
+ NK_LAYOUT_TEMPLATE,
+ NK_LAYOUT_COUNT
+};
+struct nk_row_layout {
+ enum nk_panel_row_layout_type type;
+ int index;
+ float height;
+ float min_height;
+ int columns;
+ const float *ratio;
+ float item_width;
+ float item_height;
+ float item_offset;
+ float filled;
+ struct nk_rect item;
+ int tree_depth;
+ float templates[NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS];
+};
+
+struct nk_popup_buffer {
+ nk_size begin;
+ nk_size parent;
+ nk_size last;
+ nk_size end;
+ nk_bool active;
+};
+
+struct nk_menu_state {
+ float x, y, w, h;
+ struct nk_scroll offset;
+};
+
+struct nk_panel {
+ enum nk_panel_type type;
+ nk_flags flags;
+ struct nk_rect bounds;
+ nk_uint *offset_x;
+ nk_uint *offset_y;
+ float at_x, at_y, max_x;
+ float footer_height;
+ float header_height;
+ float border;
+ unsigned int has_scrolling;
+ struct nk_rect clip;
+ struct nk_menu_state menu;
+ struct nk_row_layout row;
+ struct nk_chart chart;
+ struct nk_command_buffer *buffer;
+ struct nk_panel *parent;
+};
+
+]]
+
+ffi.cdef[[
+/*==============================================================
+ * WINDOW
+ * =============================================================*/
+
+struct nk_table;
+enum nk_window_flags {
+ NK_WINDOW_PRIVATE = 2048,
+ NK_WINDOW_DYNAMIC = 2048,
+ /* special window type growing up in height while being filled to a certain maximum height */
+ NK_WINDOW_ROM = 4096,
+ /* sets window widgets into a read only mode and does not allow input changes */
+ NK_WINDOW_NOT_INTERACTIVE = 5120,
+ /* prevents all interaction caused by input to either window or widgets inside */
+ NK_WINDOW_HIDDEN = 8192,
+ /* Hides window and stops any window interaction and drawing */
+ NK_WINDOW_CLOSED = 16384,
+ /* Directly closes and frees the window at the end of the frame */
+ NK_WINDOW_MINIMIZED = 32768,
+ /* marks the window as minimized */
+ NK_WINDOW_REMOVE_ROM = 65536
+ /* Removes read only mode at the end of the window */
+};
+
+struct nk_popup_state {
+ struct nk_window *win;
+ enum nk_panel_type type;
+ struct nk_popup_buffer buf;
+ nk_hash name;
+ nk_bool active;
+ unsigned combo_count;
+ unsigned con_count, con_old;
+ unsigned active_con;
+ struct nk_rect header;
+};
+
+struct nk_edit_state {
+ nk_hash name;
+ unsigned int seq;
+ unsigned int old;
+ int active, prev;
+ int cursor;
+ int sel_start;
+ int sel_end;
+ struct nk_scroll scrollbar;
+ unsigned char mode;
+ unsigned char single_line;
+};
+
+struct nk_property_state {
+ int active, prev;
+ char buffer[64];
+ int length;
+ int cursor;
+ int select_start;
+ int select_end;
+ nk_hash name;
+ unsigned int seq;
+ unsigned int old;
+ int state;
+};
+
+struct nk_window {
+ unsigned int seq;
+ nk_hash name;
+ char name_string[64];
+ nk_flags flags;
+
+ struct nk_rect bounds;
+ struct nk_scroll scrollbar;
+ struct nk_command_buffer buffer;
+ struct nk_panel *layout;
+ float scrollbar_hiding_timer;
+
+ /* persistent widget state */
+ struct nk_property_state property;
+ struct nk_popup_state popup;
+ struct nk_edit_state edit;
+ unsigned int scrolled;
+
+ struct nk_table *tables;
+ unsigned int table_count;
+
+ /* window list hooks */
+ struct nk_window *next;
+ struct nk_window *prev;
+ struct nk_window *parent;
+};
+
+struct nk_config_stack_style_item_element { struct nk_style_item *address; struct nk_style_item old_value; };
+struct nk_config_stack_float_element { float *address; float old_value; };
+struct nk_config_stack_vec2_element { struct nk_vec2 *address; struct nk_vec2 old_value; };
+struct nk_config_stack_flags_element { nk_flags *address; nk_flags old_value; };
+struct nk_config_stack_color_element { struct nk_color *address; struct nk_color old_value; };
+struct nk_config_stack_user_font_element { const struct nk_user_font* *address; const struct nk_user_font* old_value; };
+struct nk_config_stack_button_behavior_element { enum nk_button_behavior *address; enum nk_button_behavior old_value; };
+
+struct nk_config_stack_style_item { int head; struct nk_config_stack_style_item_element elements[16]; };
+struct nk_config_stack_float { int head; struct nk_config_stack_float_element elements[32]; };
+struct nk_config_stack_vec2 { int head; struct nk_config_stack_vec2_element elements[16]; };
+struct nk_config_stack_flags { int head; struct nk_config_stack_flags_element elements[32]; };
+struct nk_config_stack_color { int head; struct nk_config_stack_color_element elements[32]; };
+struct nk_config_stack_user_font { int head; struct nk_config_stack_user_font_element elements[8]; };
+struct nk_config_stack_button_behavior { int head; struct nk_config_stack_button_behavior_element elements[8]; };
+
+struct nk_configuration_stacks {
+ struct nk_config_stack_style_item style_items;
+ struct nk_config_stack_float floats;
+ struct nk_config_stack_vec2 vectors;
+ struct nk_config_stack_flags flags;
+ struct nk_config_stack_color colors;
+ struct nk_config_stack_user_font fonts;
+ struct nk_config_stack_button_behavior button_behaviors;
+};
+
+
+]]
+
+ffi.cdef[[
+/*==============================================================
+ * CONTEXT
+ * =============================================================*/
+
+struct nk_table {
+ unsigned int seq;
+ unsigned int size;
+ nk_hash keys[56];
+ nk_uint values[56];
+ struct nk_table *next, *prev;
+};
+
+union nk_page_data {
+ struct nk_table tbl;
+ struct nk_panel pan;
+ struct nk_window win;
+};
+
+struct nk_page_element {
+ union nk_page_data data;
+ struct nk_page_element *next;
+ struct nk_page_element *prev;
+};
+
+struct nk_page {
+ unsigned int size;
+ struct nk_page *next;
+ struct nk_page_element win[1];
+};
+
+struct nk_pool {
+ struct nk_allocator alloc;
+ enum nk_allocation_type type;
+ unsigned int page_count;
+ struct nk_page *pages;
+ struct nk_page_element *freelist;
+ unsigned capacity;
+ nk_size size;
+ nk_size cap;
+};
+
+struct nk_context {
+/* public: can be accessed freely */
+ struct nk_input input;
+ struct nk_style style;
+ struct nk_buffer memory;
+ struct nk_clipboard clip;
+ nk_flags last_widget_state;
+ enum nk_button_behavior button_behavior;
+ struct nk_configuration_stacks stacks;
+ float delta_time_seconds;
+
+/* private:
+ should only be accessed if you
+ know what you are doing */
+ struct nk_draw_list draw_list;
+ /* text editor objects are quite big because of an internal
+ * undo/redo stack. Therefore it does not make sense to have one for
+ * each window for temporary use cases, so I only provide *one* instance
+ * for all windows. This works because the content is cleared anyway */
+ struct nk_text_edit text_edit;
+ /* draw buffer used for overlay drawing operation like cursor */
+ struct nk_command_buffer overlay;
+
+ /* windows */
+ int build;
+ int use_pool;
+ struct nk_pool pool;
+ struct nk_window *begin;
+ struct nk_window *end;
+ struct nk_window *active;
+ struct nk_window *current;
+ struct nk_page_element *freelist;
+ unsigned int count;
+ unsigned int seq;
+};
+
+/* const struct nk_rect nk_null_rect = {-8192.0f, -8192.0f, 16384, 16384};
+enum { NK_FLOAT_PRECISION = 0.00000000000001 };
+
+const struct nk_color nk_red = {255,0,0,255};
+const struct nk_color nk_green = {0,255,0,255};
+const struct nk_color nk_blue = {0,0,255,255};
+const struct nk_color nk_white = {255,255,255,255};
+const struct nk_color nk_black = {0,0,0,255};
+const struct nk_color nk_yellow = {255,255,0,255};
+*/
+
+/* math */
+float nk_inv_sqrt(float n);
+float nk_sin(float x);
+float nk_cos(float x);
+nk_uint nk_round_up_pow2(nk_uint v);
+struct nk_rect nk_shrink_rect(struct nk_rect r, float amount);
+struct nk_rect nk_pad_rect(struct nk_rect r, struct nk_vec2 pad);
+void nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0, float x1, float y1);
+double nk_pow(double x, int n);
+int nk_ifloord(double x);
+int nk_ifloorf(float x);
+int nk_iceilf(float x);
+int nk_log10(double n);
+
+/* util */
+enum {NK_DO_NOT_STOP_ON_NEW_LINE, NK_STOP_ON_NEW_LINE};
+nk_bool nk_is_lower(int c);
+nk_bool nk_is_upper(int c);
+int nk_to_upper(int c);
+int nk_to_lower(int c);
+
+void* nk_memcopy(void *dst, const void *src, nk_size n);
+void nk_memset(void *ptr, int c0, nk_size size);
+void nk_zero(void *ptr, nk_size size);
+char *nk_itoa(char *s, long n);
+int nk_string_float_limit(char *string, int prec);
+char *nk_dtoa(char *s, double n);
+int nk_text_clamp(const struct nk_user_font *font, const char *text, int text_len, float space, int *glyphs, float *text_width, nk_rune *sep_list, int sep_count);
+struct nk_vec2 nk_text_calculate_text_bounds(const struct nk_user_font *font, const char *begin, int byte_len, float row_height, const char **remaining, struct nk_vec2 *out_offset, int *glyphs, int op);
+int nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args);
+char *nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc);
+
+/* buffer */
+void* nk_malloc(nk_handle unused, void *old,nk_size size);
+void nk_mfree(nk_handle unused, void *ptr);
+void* nk_buffer_align(void *unaligned, nk_size align, nk_size *alignment, enum nk_buffer_allocation_type type);
+void* nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type, nk_size size, nk_size align);
+void* nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size);
+
+/* draw */
+void nk_command_buffer_init(struct nk_command_buffer *cb, struct nk_buffer *b, enum nk_command_clipping clip);
+void nk_command_buffer_reset(struct nk_command_buffer *b);
+void* nk_command_buffer_push(struct nk_command_buffer* b, enum nk_command_type t, nk_size size);
+void nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type, struct nk_rect content, struct nk_color background, struct nk_color foreground, float border_width, const struct nk_user_font *font);
+
+/* buffering */
+void nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *b);
+void nk_start(struct nk_context *ctx, struct nk_window *win);
+void nk_start_popup(struct nk_context *ctx, struct nk_window *win);
+void nk_finish_popup(struct nk_context *ctx, struct nk_window*);
+void nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *b);
+void nk_finish(struct nk_context *ctx, struct nk_window *w);
+void nk_build(struct nk_context *ctx);
+
+/* text editor */
+void nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type, nk_plugin_filter filter);
+void nk_textedit_click(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height);
+void nk_textedit_drag(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height);
+void nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod, const struct nk_user_font *font, float row_height);
+
+/* window */
+enum nk_window_insert_location {
+ NK_INSERT_BACK, /* inserts window into the back of list (front of screen) */
+ NK_INSERT_FRONT /* inserts window into the front of list (back of screen) */
+};
+void *nk_create_window(struct nk_context *ctx);
+void nk_remove_window(struct nk_context*, struct nk_window*);
+void nk_free_window(struct nk_context *ctx, struct nk_window *win);
+struct nk_window *nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name);
+void nk_insert_window(struct nk_context *ctx, struct nk_window *win, enum nk_window_insert_location loc);
+
+/* pool */
+void nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc, unsigned int capacity);
+void nk_pool_free(struct nk_pool *pool);
+void nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size);
+struct nk_page_element *nk_pool_alloc(struct nk_pool *pool);
+
+/* page-element */
+struct nk_page_element* nk_create_page_element(struct nk_context *ctx);
+void nk_link_page_element_into_freelist(struct nk_context *ctx, struct nk_page_element *elem);
+void nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem);
+
+/* table */
+struct nk_table* nk_create_table(struct nk_context *ctx);
+void nk_remove_table(struct nk_window *win, struct nk_table *tbl);
+void nk_free_table(struct nk_context *ctx, struct nk_table *tbl);
+void nk_push_table(struct nk_window *win, struct nk_table *tbl);
+nk_uint *nk_add_value(struct nk_context *ctx, struct nk_window *win, nk_hash name, nk_uint value);
+nk_uint *nk_find_value(struct nk_window *win, nk_hash name);
+
+/* panel */
+void *nk_create_panel(struct nk_context *ctx);
+void nk_free_panel(struct nk_context*, struct nk_panel *pan);
+nk_bool nk_panel_has_header(nk_flags flags, const char *title);
+struct nk_vec2 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type);
+float nk_panel_get_border(const struct nk_style *style, nk_flags flags, enum nk_panel_type type);
+struct nk_color nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type);
+nk_bool nk_panel_is_sub(enum nk_panel_type type);
+nk_bool nk_panel_is_nonblock(enum nk_panel_type type);
+nk_bool nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type);
+void nk_panel_end(struct nk_context *ctx);
+
+/* layout */
+float nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type, float total_space, int columns);
+void nk_panel_layout(const struct nk_context *ctx, struct nk_window *win, float height, int cols);
+void nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt, float height, int cols, int width);
+void nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win);
+void nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, struct nk_window *win, int modify);
+void nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx);
+void nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx);
+
+/* popup */
+nk_bool nk_nonblock_begin(struct nk_context *ctx, nk_flags flags, struct nk_rect body, struct nk_rect header, enum nk_panel_type panel_type);
+
+/* text */
+struct nk_text {
+ struct nk_vec2 padding;
+ struct nk_color background;
+ struct nk_color text;
+};
+void nk_widget_text(struct nk_command_buffer *o, struct nk_rect b, const char *string, int len, const struct nk_text *t, nk_flags a, const struct nk_user_font *f);
+void nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b, const char *string, int len, const struct nk_text *t, const struct nk_user_font *f);
+
+/* button */
+nk_bool nk_button_behavior(nk_flags *state, struct nk_rect r, const struct nk_input *i, enum nk_button_behavior behavior);
+const struct nk_style_item* nk_draw_button(struct nk_command_buffer *out, const struct nk_rect *bounds, nk_flags state, const struct nk_style_button *style);
+nk_bool nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, const struct nk_style_button *style, const struct nk_input *in, enum nk_button_behavior behavior, struct nk_rect *content);
+void nk_draw_button_text(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, const char *txt, int len, nk_flags text_alignment, const struct nk_user_font *font);
+nk_bool nk_do_button_text(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *string, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_input *in, const struct nk_user_font *font);
+void nk_draw_button_symbol(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, enum nk_symbol_type type, const struct nk_user_font *font);
+nk_bool nk_do_button_symbol(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, enum nk_symbol_type symbol, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_input *in, const struct nk_user_font *font);
+void nk_draw_button_image(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, const struct nk_image *img);
+nk_bool nk_do_button_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, struct nk_image img, enum nk_button_behavior b, const struct nk_style_button *style, const struct nk_input *in);
+void nk_draw_button_text_symbol(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *label, const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style, const char *str, int len, enum nk_symbol_type type, const struct nk_user_font *font);
+nk_bool nk_do_button_text_symbol(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, enum nk_symbol_type symbol, const char *str, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_user_font *font, const struct nk_input *in);
+void nk_draw_button_text_image(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *label, const struct nk_rect *image, nk_flags state, const struct nk_style_button *style, const char *str, int len, const struct nk_user_font *font, const struct nk_image *img);
+nk_bool nk_do_button_text_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, struct nk_image img, const char* str, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_user_font *font, const struct nk_input *in);
+
+/* toggle */
+enum nk_toggle_type {
+ NK_TOGGLE_CHECK,
+ NK_TOGGLE_OPTION
+};
+nk_bool nk_toggle_behavior(const struct nk_input *in, struct nk_rect select, nk_flags *state, nk_bool active);
+void nk_draw_checkbox(struct nk_command_buffer *out, nk_flags state, const struct nk_style_toggle *style, nk_bool active, const struct nk_rect *label, const struct nk_rect *selector, const struct nk_rect *cursors, const char *string, int len, const struct nk_user_font *font);
+void nk_draw_option(struct nk_command_buffer *out, nk_flags state, const struct nk_style_toggle *style, nk_bool active, const struct nk_rect *label, const struct nk_rect *selector, const struct nk_rect *cursors, const char *string, int len, const struct nk_user_font *font);
+nk_bool nk_do_toggle(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, nk_bool *active, const char *str, int len, enum nk_toggle_type type, const struct nk_style_toggle *style, const struct nk_input *in, const struct nk_user_font *font);
+
+/* progress */
+nk_size nk_progress_behavior(nk_flags *state, struct nk_input *in, struct nk_rect r, struct nk_rect cursor, nk_size max, nk_size value, nk_bool modifiable);
+void nk_draw_progress(struct nk_command_buffer *out, nk_flags state, const struct nk_style_progress *style, const struct nk_rect *bounds, const struct nk_rect *scursor, nk_size value, nk_size max);
+nk_size nk_do_progress(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, nk_size value, nk_size max, nk_bool modifiable, const struct nk_style_progress *style, struct nk_input *in);
+
+/* slider */
+float nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor, struct nk_rect *visual_cursor, struct nk_input *in, struct nk_rect bounds, float slider_min, float slider_max, float slider_value, float slider_step, float slider_steps);
+void nk_draw_slider(struct nk_command_buffer *out, nk_flags state, const struct nk_style_slider *style, const struct nk_rect *bounds, const struct nk_rect *visual_cursor, float min, float value, float max);
+float nk_do_slider(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, float min, float val, float max, float step, const struct nk_style_slider *style, struct nk_input *in, const struct nk_user_font *font);
+
+/* scrollbar */
+float nk_scrollbar_behavior(nk_flags *state, struct nk_input *in, int has_scrolling, const struct nk_rect *scroll, const struct nk_rect *cursor, const struct nk_rect *empty0, const struct nk_rect *empty1, float scroll_offset, float target, float scroll_step, enum nk_orientation o);
+void nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state, const struct nk_style_scrollbar *style, const struct nk_rect *bounds, const struct nk_rect *scroll);
+float nk_do_scrollbarv(nk_flags *state, struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, float offset, float target, float step, float button_pixel_inc, const struct nk_style_scrollbar *style, struct nk_input *in, const struct nk_user_font *font);
+float nk_do_scrollbarh(nk_flags *state, struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, float offset, float target, float step, float button_pixel_inc, const struct nk_style_scrollbar *style, struct nk_input *in, const struct nk_user_font *font);
+
+/* selectable */
+void nk_draw_selectable(struct nk_command_buffer *out, nk_flags state, const struct nk_style_selectable *style, nk_bool active, const struct nk_rect *bounds, const struct nk_rect *icon, const struct nk_image *img, enum nk_symbol_type sym, const char *string, int len, nk_flags align, const struct nk_user_font *font);
+nk_bool nk_do_selectable(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *str, int len, nk_flags align, nk_bool *value, const struct nk_style_selectable *style, const struct nk_input *in, const struct nk_user_font *font);
+nk_bool nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *str, int len, nk_flags align, nk_bool *value, const struct nk_image *img, const struct nk_style_selectable *style, const struct nk_input *in, const struct nk_user_font *font);
+
+/* edit */
+void nk_edit_draw_text(struct nk_command_buffer *out, const struct nk_style_edit *style, float pos_x, float pos_y, float x_offset, const char *text, int byte_len, float row_height, const struct nk_user_font *font, struct nk_color background, struct nk_color foreground, nk_bool is_selected);
+nk_flags nk_do_edit(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter, struct nk_text_edit *edit, const struct nk_style_edit *style, struct nk_input *in, const struct nk_user_font *font);
+
+/* color-picker */
+nk_bool nk_color_picker_behavior(nk_flags *state, const struct nk_rect *bounds, const struct nk_rect *matrix, const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, struct nk_colorf *color, const struct nk_input *in);
+void nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix, const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, struct nk_colorf col);
+nk_bool nk_do_color_picker(nk_flags *state, struct nk_command_buffer *out, struct nk_colorf *col, enum nk_color_format fmt, struct nk_rect bounds, struct nk_vec2 padding, const struct nk_input *in, const struct nk_user_font *font);
+
+/* property */
+enum nk_property_status {
+ NK_PROPERTY_DEFAULT,
+ NK_PROPERTY_EDIT,
+ NK_PROPERTY_DRAG
+};
+enum nk_property_filter {
+ NK_FILTER_INT,
+ NK_FILTER_FLOAT
+};
+enum nk_property_kind {
+ NK_PROPERTY_INT,
+ NK_PROPERTY_FLOAT,
+ NK_PROPERTY_DOUBLE
+};
+union nk_property {
+ int i;
+ float f;
+ double d;
+};
+struct nk_property_variant {
+ enum nk_property_kind kind;
+ union nk_property value;
+ union nk_property min_value;
+ union nk_property max_value;
+ union nk_property step;
+};
+struct nk_property_variant nk_property_variant_int(int value, int min_value, int max_value, int step);
+struct nk_property_variant nk_property_variant_float(float value, float min_value, float max_value, float step);
+struct nk_property_variant nk_property_variant_double(double value, double min_value, double max_value, double step);
+
+void nk_drag_behavior(nk_flags *state, const struct nk_input *in, struct nk_rect drag, struct nk_property_variant *variant, float inc_per_pixel);
+void nk_property_behavior(nk_flags *ws, const struct nk_input *in, struct nk_rect property, struct nk_rect label, struct nk_rect edit, struct nk_rect empty, int *state, struct nk_property_variant *variant, float inc_per_pixel);
+void nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style, const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state, const char *name, int len, const struct nk_user_font *font);
+void nk_do_property(nk_flags *ws, struct nk_command_buffer *out, struct nk_rect property, const char *name, struct nk_property_variant *variant, float inc_per_pixel, char *buffer, int *len, int *state, int *cursor, int *select_begin, int *select_end, const struct nk_style_property *style, enum nk_property_filter filter, struct nk_input *in, const struct nk_user_font *font, struct nk_text_edit *text_edit, enum nk_button_behavior behavior);
+void nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant, float inc_per_pixel, const enum nk_property_filter filter);
+]]
+
+ffi.cdef[[
+/********** sokol_nuklear ****************************************************************/
+
+enum {
+ SNK_INVALID_ID = 0,
+};
+
+/*
+ snk_image_t
+
+ A combined image-sampler pair used to inject custom images and samplers into Nuklear
+
+ Create with snk_make_image(), and convert to an nk_handle via snk_nkhandle().
+*/
+typedef struct snk_image_t { uint32_t id; } snk_image_t;
+
+/*
+ snk_image_desc_t
+
+ Descriptor struct for snk_make_image(). You must provide
+ at least an sg_image handle. Keeping the sg_sampler handle
+ zero-initialized will select the builtin default sampler
+ which uses linear filtering.
+*/
+typedef struct snk_image_desc_t {
+ sg_image image;
+ sg_sampler sampler;
+} snk_image_desc_t;
+
+/*
+ snk_allocator_t
+
+ Used in snk_desc_t to provide custom memory-alloc and -free functions
+ to sokol_nuklear.h. If memory management should be overridden, both the
+ alloc_fn and free_fn function must be provided (e.g. it's not valid to
+ override one function but not the other).
+*/
+typedef struct snk_allocator_t {
+ void* (*alloc_fn)(size_t size, void* user_data);
+ void (*free_fn)(void* ptr, void* user_data);
+ void* user_data;
+} snk_allocator_t;
+
+/*
+ snk_logger
+
+ Used in snk_desc_t to provide a logging function. Please be aware
+ that without logging function, sokol-nuklear will be completely
+ silent, e.g. it will not report errors, warnings and
+ validation layer messages. For maximum error verbosity,
+ compile in debug mode (e.g. NDEBUG *not* defined) and install
+ a logger (for instance the standard logging function from sokol_log.h).
+*/
+typedef struct snk_logger_t {
+ void (*func)(
+ const char* tag, // always "snk"
+ uint32_t log_level, // 0=panic, 1=error, 2=warning, 3=info
+ uint32_t log_item_id, // SNK_LOGITEM_*
+ const char* message_or_null, // a message string, may be nullptr in release mode
+ uint32_t line_nr, // line number in sokol_imgui.h
+ const char* filename_or_null, // source filename, may be nullptr in release mode
+ void* user_data);
+ void* user_data;
+} snk_logger_t;
+
+
+typedef struct snk_desc_t {
+ int max_vertices; // default: 65536
+ int image_pool_size; // default: 256
+ sg_pixel_format color_format;
+ sg_pixel_format depth_format;
+ int sample_count;
+ float dpi_scale;
+ bool no_default_font;
+ snk_allocator_t allocator; // optional memory allocation overrides (default: malloc/free)
+ snk_logger_t logger; // optional log function override
+} snk_desc_t;
+
+void snk_setup(const snk_desc_t* desc);
+struct nk_context* snk_new_frame(void);
+void snk_render(int width, int height);
+snk_image_t snk_make_image(const snk_image_desc_t* desc);
+void snk_destroy_image(snk_image_t img);
+snk_image_desc_t snk_query_image_desc(snk_image_t img);
+nk_handle snk_nkhandle(snk_image_t img);
+snk_image_t snk_image_from_nkhandle(nk_handle handle);
+bool snk_handle_event(const sapp_event* ev);
+nk_flags snk_edit_string(struct nk_context *ctx, nk_flags flags, char *memory, int *len, int max, nk_plugin_filter filter);
+void snk_shutdown(void);
+
+]]
+
+return sokol_nuklear
\ No newline at end of file
diff --git a/ffi/uv-ffi.lua b/ffi/uv-ffi.lua
new file mode 100644
index 0000000..21bdbd8
--- /dev/null
+++ b/ffi/uv-ffi.lua
@@ -0,0 +1,1072 @@
+local ffi = require 'ffi'
+local cast = ffi.cast
+local C = ffi.C
+local UV = nil
+
+print("OS:", ffi.os)
+if ffi.os == 'Windows' then
+ UV = ffi.load('libuv')
+ ffi.cdef [[
+ typedef uint32_t ULONG;
+ typedef struct uv_buf_t {
+ ULONG len;
+ char* base;
+ } uv_buf_t;
+ ]]
+end
+if ffi.os == "Linux" then
+ UV = ffi.load('./bin/linux/x64/libuv.so')
+ ffi.cdef [[
+ typedef struct uv_buf_t {
+ char* base;
+ size_t len;
+ } uv_buf_t;
+ ]]
+end
+
+ffi.cdef [[
+ uv_buf_t uv_buf_init(const char* base, unsigned int len);
+
+ typedef enum {
+ UV_EOF = -4095
+ } uv_errno_t;
+
+ typedef enum {
+ UV_UNKNOWN_HANDLE = 0,
+ UV_ASYNC,
+ UV_CHECK,
+ UV_FS_EVENT,
+ UV_FS_POLL,
+ UV_HANDLE,
+ UV_IDLE,
+ UV_NAMED_PIPE,
+ UV_POLL,
+ UV_PREPARE,
+ UV_PROCESS,
+ UV_STREAM,
+ UV_TCP,
+ UV_TIMER,
+ UV_TTY,
+ UV_UDP,
+ UV_SIGNAL,
+ UV_FILE,
+ UV_HANDLE_TYPE_MAX
+ } uv_handle_type;
+
+ typedef enum {
+ UV_UNKNOWN_REQ = 0,
+ UV_REQ,
+ UV_CONNECT,
+ UV_WRITE,
+ UV_SHUTDOWN,
+ UV_UDP_SEND,
+ UV_FS,
+ UV_WORK,
+ UV_GETADDRINFO,
+ UV_GETNAMEINFO,
+ UV_REQ_TYPE_MAX,
+ } uv_req_type;
+
+ size_t uv_loop_size(void);
+ size_t uv_req_size(uv_req_type type);
+ size_t uv_handle_size(uv_handle_type type);
+]]
+
+ffi.cdef(
+ string.format(
+ [[
+ struct uv_loop_s {uint8_t _[%d];};
+ struct uv_connect_s {uint8_t _[%d];};
+ struct uv_write_s {uint8_t _[%d];};
+ struct uv_shutdown_s {uint8_t _[%d];};
+ struct uv_getaddrinfo_s {uint8_t _[%d];};
+ struct uv_tcp_s {uint8_t _[%d];};
+ struct uv_tty_s {uint8_t _[%d];};
+ struct uv_pipe_s {uint8_t _[%d];};
+ struct uv_timer_s {uint8_t _[%d];};
+ ]],
+ tonumber(UV.uv_loop_size()),
+ tonumber(UV.uv_req_size(UV.UV_CONNECT)),
+ tonumber(UV.uv_req_size(UV.UV_WRITE)),
+ tonumber(UV.uv_req_size(UV.UV_SHUTDOWN)),
+ tonumber(UV.uv_req_size(UV.UV_GETADDRINFO)),
+ tonumber(UV.uv_handle_size(UV.UV_TCP)),
+ tonumber(UV.uv_handle_size(UV.UV_TTY)),
+ tonumber(UV.uv_handle_size(UV.UV_NAMED_PIPE)),
+ tonumber(UV.uv_handle_size(UV.UV_TIMER))
+ )
+)
+
+ffi.cdef [[
+ typedef struct uv_loop_s uv_loop_t;
+ typedef struct uv_req_s uv_req_t;
+ typedef struct uv_write_s uv_write_t;
+ typedef struct uv_connect_s uv_connect_t;
+ typedef struct uv_shutdown_s uv_shutdown_t;
+ typedef struct uv_getaddrinfo_s uv_getaddrinfo_t;
+ typedef struct uv_handle_s uv_handle_t;
+ typedef struct uv_stream_s uv_stream_t;
+ typedef struct uv_tcp_s uv_tcp_t;
+ typedef struct uv_tty_s uv_tty_t;
+ typedef struct uv_pipe_s uv_pipe_t;
+ typedef struct uv_timer_s uv_timer_t;
+
+ typedef enum uv_run_mode_e {
+ UV_RUN_DEFAULT = 0,
+ UV_RUN_ONCE,
+ UV_RUN_NOWAIT
+ } uv_run_mode;
+
+ int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr);
+ int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr);
+ int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size);
+ int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size);
+ int uv_inet_ntop(int af, const void* src, char* dst, size_t size);
+ int uv_inet_pton(int af, const char* src, void* dst);
+
+ const char* uv_err_name(int err);
+ const char* uv_strerror(int err);
+]]
+
+local function makeCallback(type)
+ local thread, isMain = coroutine.running()
+ if not thread or isMain then return end
+ local cb
+ cb =
+ cast(
+ type,
+ function(...)
+ -- print('oncall', ...)
+ cb:free()
+ assert(coroutine.resume(thread, ...))
+ end
+ )
+ return cb
+end
+
+local function uvGetError(status)
+ return ffi.string(UV.uv_err_name(status)) .. ': ' .. ffi.string(UV.uv_strerror(status))
+end
+
+local function uvCheck(status)
+ if status < 0 then
+ error(uvGetError(status))
+ else
+ return status
+ end
+end
+
+local Loop = {}
+
+-------------------------------------------------------------------------------
+-- File
+-------------------------------------------------------------------------------
+local File = {}
+
+ffi.cdef [[
+
+ typedef uint32_t DWORD;
+
+ typedef enum {
+ UV_FS_UNKNOWN = -1,
+ UV_FS_CUSTOM,
+ UV_FS_OPEN,
+ UV_FS_CLOSE,
+ UV_FS_READ,
+ UV_FS_WRITE,
+ UV_FS_SENDFILE,
+ UV_FS_STAT,
+ UV_FS_LSTAT,
+ UV_FS_FSTAT,
+ UV_FS_FTRUNCATE,
+ UV_FS_UTIME,
+ UV_FS_FUTIME,
+ UV_FS_ACCESS,
+ UV_FS_CHMOD,
+ UV_FS_FCHMOD,
+ UV_FS_FSYNC,
+ UV_FS_FDATASYNC,
+ UV_FS_UNLINK,
+ UV_FS_RMDIR,
+ UV_FS_MKDIR,
+ UV_FS_MKDTEMP,
+ UV_FS_RENAME,
+ UV_FS_SCANDIR,
+ UV_FS_LINK,
+ UV_FS_SYMLINK,
+ UV_FS_READLINK,
+ UV_FS_CHOWN,
+ UV_FS_FCHOWN,
+ UV_FS_REALPATH,
+ UV_FS_COPYFILE,
+ UV_FS_LCHOWN,
+ UV_FS_OPENDIR,
+ UV_FS_READDIR,
+ UV_FS_CLOSEDIR,
+ UV_FS_MKSTEMP
+ } uv_fs_type;
+
+ typedef struct {
+ long tv_sec;
+ long tv_nsec;
+ } uv_timespec_t;
+
+ struct uv__work {
+ void (*work)(struct uv__work *w);
+ void (*done)(struct uv__work *w, int status);
+ struct uv_loop_s* loop;
+ void* wq[2];
+ };
+
+ typedef struct {
+ uint64_t st_dev;
+ uint64_t st_mode;
+ uint64_t st_nlink;
+ uint64_t st_uid;
+ uint64_t st_gid;
+ uint64_t st_rdev;
+ uint64_t st_ino;
+ uint64_t st_size;
+ uint64_t st_blksize;
+ uint64_t st_blocks;
+ uint64_t st_flags;
+ uint64_t st_gen;
+ uv_timespec_t st_atim;
+ uv_timespec_t st_mtim;
+ uv_timespec_t st_ctim;
+ uv_timespec_t st_birthtim;
+ } uv_stat_t;
+
+ typedef enum {
+ UV_DIRENT_UNKNOWN,
+ UV_DIRENT_FILE,
+ UV_DIRENT_DIR,
+ UV_DIRENT_LINK,
+ UV_DIRENT_FIFO,
+ UV_DIRENT_SOCKET,
+ UV_DIRENT_CHAR,
+ UV_DIRENT_BLOCK
+ } uv_dirent_type_t;
+
+ typedef struct uv_dirent_s {
+ const char* name;
+ uv_dirent_type_t type;
+ } uv_dirent_t;
+
+ typedef struct uv_statfs_s {
+ uint64_t f_type;
+ uint64_t f_bsize;
+ uint64_t f_blocks;
+ uint64_t f_bfree;
+ uint64_t f_bavail;
+ uint64_t f_files;
+ uint64_t f_ffree;
+ uint64_t f_spare[4];
+ } uv_statfs_t;
+
+ typedef struct uv_dir_s {
+ uv_dirent_t* dirents;
+ size_t nentries;
+ } uv_dir_t;
+
+ typedef struct uv_fs_s uv_fs_t;
+ typedef void (*uv_fs_cb)(uv_fs_t* req);
+
+ /* uv_fs_t is a subclass of uv_req_t. */
+ typedef struct uv_fs_s {
+ void* data;
+ uv_req_type type;
+ void* reserved[6];
+ void* data;
+ uv_req_type type;
+ void* reserved[6];
+ uv_loop_t* loop;
+ uv_fs_cb cb;
+ size_t result;
+ void* ptr;
+ const char* path;
+ uv_stat_t statbuf; /* Stores the result of uv_fs_stat() and uv_fs_fstat(). */
+ struct uv__work work_req;
+ int flags;
+ DWORD sys_errno_;
+ union {
+ uint16_t* pathw;
+ int fd;
+ } file;
+ union {
+ struct {
+ int mode;
+ uint16_t* new_pathw;
+ int file_flags;
+ int fd_out;
+ unsigned int nbufs;
+ uv_buf_t* bufs;
+ int64_t offset;
+ uv_buf_t bufsml[4];
+ } info;
+ struct {
+ double atime;
+ double mtime;
+ } time;
+ } fs;
+ };
+
+ int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
+ const char* uv_fs_get_path(const uv_fs_t* req);
+
+ int uv_exepath(char* buffer, size_t* size);
+ int uv_cwd(char* buffer, size_t* size);
+]]
+
+-------------------------------------------------------------------------------
+-- Thread
+-------------------------------------------------------------------------------
+
+local Thread = {}
+
+
+ffi.cdef [[
+
+ typedef uint32_t HANDLE;
+
+ typedef HANDLE uv_thread_t;
+ typedef void (*uv_thread_cb)(void* arg);
+
+ int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg);
+
+ typedef enum {
+ UV_THREAD_NO_FLAGS = 0x00,
+ UV_THREAD_HAS_STACK_SIZE = 0x01
+ } uv_thread_create_flags;
+
+ struct uv_thread_options_s {
+ unsigned int flags;
+ size_t stack_size;
+ /* More fields may be added at any time. */
+ };
+
+ typedef struct uv_thread_options_s uv_thread_options_t;
+
+ int uv_thread_create_ex(uv_thread_t* tid, const uv_thread_options_t* params,
+ uv_thread_cb entry, void* arg);
+ uv_thread_t uv_thread_self(void);
+ int uv_thread_join(uv_thread_t *tid);
+ int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2);
+]]
+
+-------------------------------------------------------------------------------
+-- Req
+-------------------------------------------------------------------------------
+
+ffi.cdef [[
+ int uv_cancel(uv_req_t* req);
+ uv_req_type uv_req_get_type(const uv_req_t* req);
+ const char* uv_req_type_name(uv_req_type type);
+]]
+
+local Req = {}
+
+function Req:cancel()
+ return uvCheck(UV.uv_cancel(cast('uv_req_t*', self)))
+end
+
+function Req:getType()
+ local id = UV.uv_req_get_type(cast('uv_req_t*', self))
+ return ffi.string(UV.uv_req_type_name(id))
+end
+
+-------------------------------------------------------------------------------
+-- Connect
+-------------------------------------------------------------------------------
+
+local Connect = setmetatable({}, {__index = Req})
+Connect.type = ffi.typeof 'uv_connect_t'
+ffi.metatype(Connect.type, {__index = Connect})
+function Connect.new()
+ return Connect.type()
+end
+
+-------------------------------------------------------------------------------
+-- Write
+-------------------------------------------------------------------------------
+
+local Write = setmetatable({}, {__index = Req})
+Write.type = ffi.typeof 'uv_write_t'
+ffi.metatype(Write.type, {__index = Write})
+function Write.new()
+ return Write.type()
+end
+
+-------------------------------------------------------------------------------
+-- Shutdown
+-------------------------------------------------------------------------------
+
+local Shutdown = setmetatable({}, {__index = Req})
+Shutdown.type = ffi.typeof 'uv_shutdown_t'
+ffi.metatype(Shutdown.type, {__index = Shutdown})
+function Shutdown.new()
+ return Shutdown.type()
+end
+
+-------------------------------------------------------------------------------
+-- Getaddrinfo
+-------------------------------------------------------------------------------
+
+ffi.cdef [[
+ enum {
+ AF_UNSPEC = 0,
+ AF_INET = 2,
+ AF_INET6 = 10
+ };
+ enum {
+ SOCK_STREAM = 1,
+ SOCK_DGRAM = 2
+ };
+
+ typedef int32_t socklen_t;
+
+ struct addrinfo {
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+ socklen_t ai_addrlen;
+ struct sockaddr *ai_addr;
+ char *ai_canonname;
+ struct addrinfo *ai_next;
+ };
+
+ typedef void (*uv_getaddrinfo_cb)(uv_getaddrinfo_t* req, int status, struct addrinfo* res);
+
+ int uv_getaddrinfo(
+ uv_loop_t* loop, uv_getaddrinfo_t* req, uv_getaddrinfo_cb getaddrinfo_cb,
+ const char* node, const char* service, const struct addrinfo* hints
+ );
+ void uv_freeaddrinfo(struct addrinfo* ai);
+]]
+
+local Getaddrinfo = setmetatable({}, {__index = Req})
+Getaddrinfo.type = ffi.typeof 'uv_getaddrinfo_t'
+ffi.metatype(Getaddrinfo.type, {__index = Getaddrinfo})
+function Getaddrinfo.new()
+ return Getaddrinfo.type()
+end
+
+local families = {
+ inet = UV.AF_INET,
+ inet6 = UV.AF_INET6,
+ [UV.AF_INET] = 'inet',
+ [UV.AF_INET6] = 'inet6'
+}
+
+local socktypes = {
+ stream = UV.SOCK_STREAM,
+ dgram = UV.SOCK_DGRAM,
+ [UV.SOCK_STREAM] = 'stream',
+ [UV.SOCK_DGRAM] = 'dgram'
+}
+
+function Loop:getaddrinfo(node, service, hints)
+ local req = Getaddrinfo.new()
+ p(req)
+ local opts = ffi.new('struct addrinfo')
+ if type(service) == 'number' then
+ service = tostring(service)
+ end
+ if hints then
+ if hints.family then
+ opts.ai_family = assert(families[hints.family], 'Unknown family name')
+ end
+ if hints.socktype then
+ opts.ai_socktype = assert(socktypes[hints.socktype], 'Unknown socktype name')
+ end
+ end
+ p(node, service, hints)
+ uvCheck(UV.uv_getaddrinfo(self, req, makeCallback 'uv_getaddrinfo_cb', node, service, opts))
+ local _, status, res = coroutine.yield()
+ uvCheck(status)
+ local results = {}
+ local i = 1
+ while res ~= nil do
+ local family = families[res.ai_family]
+ local socktype = socktypes[res.ai_socktype]
+ local entry = {
+ family = family,
+ socktype = socktype
+ }
+ results[i] = entry
+ i = i + 1
+ if family == 'inet' then
+ local buf = ffi.new 'char[16]'
+ local addr = cast('const struct sockaddr_in*', res.ai_addr)
+ uvCheck(UV.uv_ip4_name(addr, buf, 16))
+ entry.addr = ffi.string(buf)
+ entry.port = C.ntohs(addr.sin_port)
+ elseif family == 'inet6' then
+ local buf = ffi.new 'char[46]'
+ local addr = cast('const struct sockaddr_in6*', res.ai_addr)
+ uvCheck(UV.uv_ip6_name(addr, buf, 46))
+ entry.addr = ffi.string(buf)
+ entry.port = C.ntohs(addr.sin6_port)
+ end
+ res = res.ai_next
+ end
+ return results
+end
+
+-------------------------------------------------------------------------------
+-- Handle
+-------------------------------------------------------------------------------
+
+ffi.cdef [[
+ typedef void (*uv_walk_cb)(uv_handle_t* handle, void* arg);
+ typedef void (*uv_close_cb)(uv_handle_t* handle);
+ typedef void (*uv_alloc_cb)(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf);
+
+ struct sockaddr {
+ unsigned short sa_family;
+ char sa_data[14];
+ };
+
+ struct in_addr {
+ unsigned long s_addr;
+ };
+
+ struct sockaddr_in {
+ short sin_family;
+ unsigned short sin_port;
+ struct in_addr sin_addr;
+ char sin_zero[8];
+ };
+
+ struct in6_addr {
+ unsigned char s6_addr[16];
+ };
+
+ struct sockaddr_in6 {
+ uint16_t sin6_family;
+ uint16_t sin6_port;
+ uint32_t sin6_flowinfo;
+ struct in6_addr sin6_addr;
+ uint32_t sin6_scope_id;
+ };
+
+ typedef uint16_t sa_family_t;
+
+ struct sockaddr_storage {
+ sa_family_t ss_family;
+ char __ss_pad1[6];
+ int64_t __ss_align;
+ char __ss_pad2[112];
+ };
+
+ uint32_t htonl(uint32_t hostlong);
+ uint16_t htons(uint16_t hostshort);
+ uint32_t ntohl(uint32_t netlong);
+ uint16_t ntohs(uint16_t netshort);
+
+ void *malloc(size_t size);
+ void free(void *ptr);
+
+ typedef int uv_file;
+
+ uv_handle_type uv_guess_handle(uv_file file);
+
+ int uv_is_active(const uv_handle_t* handle);
+ int uv_is_closing(const uv_handle_t* handle);
+ void uv_close(uv_handle_t* handle, uv_close_cb close_cb);
+ void uv_ref(uv_handle_t* handle);
+ void uv_unref(uv_handle_t* handle);
+ int uv_has_ref(const uv_handle_t* handle);
+ int uv_send_buffer_size(uv_handle_t* handle, int* value);
+ int uv_recv_buffer_size(uv_handle_t* handle, int* value);
+ uv_loop_t* uv_handle_get_loop(const uv_handle_t* handle);
+ void* uv_handle_get_data(const uv_handle_t* handle);
+ void* uv_handle_set_data(uv_handle_t* handle, void* data);
+ uv_handle_type uv_handle_get_type(const uv_handle_t* handle);
+ const char* uv_handle_type_name(uv_handle_type type);
+]]
+
+local function onAlloc(handle, suggestedSize, buf)
+ local cached = cast('uv_buf_t*', UV.uv_handle_get_data(handle))
+ if cached ~= nil then
+ buf.base = cached.base
+ buf.len = cached.len
+ else
+ local base = C.malloc(suggestedSize)
+ buf.base = base
+ buf.len = suggestedSize
+ -- Store the data in handle->data as a uv_buf_t*
+ local data = cast('uv_buf_t*', C.malloc(ffi.sizeof 'uv_buf_t'))
+ data.base = base
+ data.len = suggestedSize
+ UV.uv_handle_set_data(handle, data)
+ end
+end
+
+local allocCb = cast('uv_alloc_cb', onAlloc)
+
+function Loop.guessHandle(fd)
+ return ffi.string(UV.uv_handle_type_name(UV.uv_guess_handle(fd)))
+end
+
+local Handle = {}
+
+function Handle:isActive()
+ return UV.uv_is_active(cast('uv_handle_t*', self)) ~= 0
+end
+
+function Handle:isClosing()
+ return UV.uv_is_closing(cast('uv_handle_t*', self)) ~= 0
+end
+
+function Handle:close()
+ local handle = cast('uv_handle_t*', self)
+ local _, main = coroutine.running()
+ if main then
+ UV.uv_close(handle, nil)
+ else
+ UV.uv_close(handle, makeCallback 'uv_close_cb')
+ coroutine.yield()
+ end
+ local cached = cast('uv_buf_t*', UV.uv_handle_get_data(handle))
+ if cached ~= nil then
+ C.free(cached.base)
+ C.free(cached)
+ end
+end
+
+function Handle:ref()
+ return UV.uv_ref(cast('uv_handle_t*', self))
+end
+
+function Handle:unref()
+ return UV.uv_unref(cast('uv_handle_t*', self))
+end
+
+function Handle:hasRef()
+ return UV.uv_has_ref(cast('uv_handle_t*', self)) ~= 0
+end
+
+function Handle:setSendBufferSize(value)
+ uvCheck(UV.uv_send_buffer_size(cast('uv_handle_t*', self), value))
+end
+
+function Handle:getSendBufferSize()
+ local out = ffi.new('int[1]')
+ uvCheck(UV.uv_send_buffer_size(cast('uv_handle_t*', self), out))
+ return out[0]
+end
+
+function Handle:setRecvBufferSize(value)
+ uvCheck(UV.uv_recv_buffer_size(cast('uv_handle_t*', self), value))
+end
+
+function Handle:getRecvBufferSize()
+ local out = ffi.new('int[1]')
+ uvCheck(UV.uv_recv_buffer_size(cast('uv_handle_t*', self), out))
+ return out[0]
+end
+
+function Handle:getLoop()
+ return UV.uv_handle_get_loop(cast('uv_handle_t*', self))
+end
+
+function Handle:getType()
+ local id = UV.uv_handle_get_type(cast('uv_handle_t*', self))
+ return ffi.string(UV.uv_handle_type_name(id))
+end
+
+-------------------------------------------------------------------------------
+-- Stream
+-------------------------------------------------------------------------------
+
+ffi.cdef [[
+
+ typedef struct sws_handle_req_t{
+
+ struct uv_tcp_s handle;
+ int id;
+ struct sws_parse_req_t parse_req;
+ } sws_handle_req_t;
+
+ typedef void (*uv_read_cb)(uv_stream_t* stream, int64_t nread, const uv_buf_t* buf);
+ typedef void (*uv_write_cb)(uv_write_t* req, int status);
+ typedef void (*uv_connect_cb)(uv_connect_t* req, int status);
+ typedef void (*uv_shutdown_cb)(uv_shutdown_t* req, int status);
+ typedef void (*uv_connection_cb)(uv_stream_t* server, int status);
+
+ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb);
+ int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb);
+ int uv_accept(uv_stream_t* server, uv_stream_t* client);
+ int uv_read_start(uv_stream_t* stream, uv_alloc_cb alloc_cb, uv_read_cb read_cb);
+ int uv_read_stop(uv_stream_t*);
+ int uv_write(uv_write_t* req, uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb);
+ int uv_write2(uv_write_t* req, uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs,
+ uv_stream_t* send_handle, uv_write_cb cb);
+ int uv_try_write(uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs);
+ int uv_is_readable(const uv_stream_t* handle);
+ int uv_is_writable(const uv_stream_t* handle);
+ int uv_stream_set_blocking(uv_stream_t* handle, int blocking);
+ size_t uv_stream_get_write_queue_size(const uv_stream_t* stream);
+]]
+
+local Stream = setmetatable({}, {__index = Handle})
+
+function Stream:shutdown()
+ local req = Shutdown.new()
+ uvCheck(UV.uv_shutdown(req, cast('uv_stream_t*', self), makeCallback 'uv_shutdown_cb'))
+ local _, status = coroutine.yield()
+ uvCheck(status)
+end
+
+function Stream:listen(backlog, onConnection)
+ local cb = cast('uv_connection_cb', onConnection)
+ uvCheck(UV.uv_listen(cast('uv_stream_t*', self), backlog, cb))
+ return cb
+end
+
+function Stream:accept(client)
+ uvCheck(UV.uv_accept(cast('uv_stream_t*', self), cast('uv_stream_t*', client)))
+end
+
+function Stream:readStart(onRead)
+ local function onEvent(_, status, buf)
+ print('onRead', _, status, buf)
+ if status == 0 then
+ return
+ end
+ if status == UV.UV_EOF then
+ onRead(nil)
+ elseif status < 0 then
+ return onRead(uvGetError(status))
+ else
+ onRead(nil, ffi.string(buf.base, status))
+ end
+ end
+ local cb = cast('uv_read_cb', onEvent)
+ uvCheck(UV.uv_read_start(cast('uv_stream_t*', self), allocCb, cb))
+end
+
+function Stream:readStop()
+ uvCheck(UV.uv_read_stop(cast('uv_stream_t*', self)))
+end
+
+function Stream:write(data)
+ local req = Write.new()
+ local bufs = ffi.new('uv_buf_t[1]')
+ bufs[0].base = cast('char*', data)
+ bufs[0].len = #data
+ local cb = makeCallback 'uv_write_cb'
+ uvCheck(UV.uv_write(req, cast('uv_stream_t*', self), bufs, 1, cb))
+ if cb then
+ local _, status = coroutine.yield()
+ uvCheck(status)
+ end
+end
+
+function Stream:write2(handle)
+ local req = Write.new()
+ local cb = makeCallback 'uv_write_cb'
+ uvCheck(UV.uv_write(req, cast('uv_stream_t*', self), nil, 0, cast('uv_stream_t*', handle), cb))
+ local _, status = coroutine.yield()
+ uvCheck(status)
+end
+
+function Stream:tryWrite(data)
+ local bufs = ffi.new('uv_buf_t[1]')
+ bufs[0].base = cast('char*', data)
+ bufs[0].len = #data
+ return uvCheck(UV.uv_try_write(cast('uv_stream_t*', self), bufs, 1))
+end
+
+function Stream:isReadable()
+ return UV.uv_is_readable(cast('uv_stream_t*', self)) ~= 0
+end
+
+function Stream:isWritable()
+ return UV.uv_is_writable(cast('uv_stream_t*', self)) ~= 0
+end
+
+function Stream:setBlocking(blocking)
+ uvCheck(UV.uv_set_blocking(cast('uv_stream_t*', self), blocking))
+end
+
+function Stream:getWriteQueueSize()
+ return tonumber(UV.uv_stream_get_write_queue_size(cast('uv_stream_t*', self)))
+end
+
+-------------------------------------------------------------------------------
+-- Tcp
+-------------------------------------------------------------------------------
+
+ffi.cdef [[
+ int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle);
+ int uv_tcp_bind(uv_tcp_t* handle, const struct sockaddr* addr, unsigned int flags);
+ int uv_tcp_connect(uv_connect_t* req, uv_tcp_t* handle, const struct sockaddr_in* addr, uv_connect_cb cb);
+]]
+
+local Tcp = setmetatable({}, {__index = Stream})
+Tcp.type = ffi.typeof 'uv_tcp_t'
+
+function Loop:newTcp()
+ local tcp = Tcp.type()
+ uvCheck(UV.uv_tcp_init(self, tcp))
+ return tcp
+end
+
+function Tcp:getsockname()
+ -- TODO: Improve output
+ return UV.uv_tcp_getsockname(self)
+end
+
+function Tcp:getpeername()
+ -- TODO: Improve output
+ return UV.uv_tcp_getpeername(self)
+end
+
+function Tcp:connect(host, port)
+ local req = Connect.new()
+ local addr = ffi.new("struct sockaddr_in [1]")
+ UV.uv_ip4_addr(host, port, cast("struct sockaddr_in *", addr))
+ uvCheck(UV.uv_tcp_connect(req, self, addr, makeCallback 'uv_connect_cb'))
+ local _, status = coroutine.yield()
+ uvCheck(status)
+end
+
+ffi.metatype(Tcp.type, {__index = Tcp})
+
+-------------------------------------------------------------------------------
+-- Tty
+-------------------------------------------------------------------------------
+
+ffi.cdef [[
+ typedef enum {
+ /* Initial/normal terminal mode */
+ UV_TTY_MODE_NORMAL,
+ /* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */
+ UV_TTY_MODE_RAW,
+ /* Binary-safe I/O mode for IPC (Unix-only) */
+ UV_TTY_MODE_IO
+ } uv_tty_mode_t;
+
+ int uv_tty_init(uv_loop_t* loop, uv_tty_t* handle, uv_file fd, int unused);
+ int uv_tty_set_mode(uv_tty_t* handle, uv_tty_mode_t mode);
+ int uv_tty_reset_mode(void);
+ int uv_tty_get_winsize(uv_tty_t* handle, int* width, int* height);
+]]
+
+local Tty = setmetatable({}, {__index = Stream})
+Tty.type = ffi.typeof 'uv_tty_t'
+
+function Loop:newTty(fd)
+ local tty = Tty.type()
+ uvCheck(UV.uv_tty_init(self, tty, fd, 0))
+ return tty
+end
+
+function Tty:setMode(mode)
+ uvCheck(
+ UV.uv_tty_set_mode(self, assert(UV['UV_TTY_MODE_' .. string.upper(mode)], 'Unknown tty mode'))
+ )
+end
+
+function Tty:resetMode()
+ uvCheck(UV.uv_tty_reset_mode())
+end
+
+function Tty:getWinsize()
+ local width = ffi.new('int[1]')
+ local height = ffi.new('int[1]')
+ uvCheck(UV.uv_tty_get_winsize(self, width, height))
+ return tonumber(width[0]), tonumber(height[0])
+end
+
+ffi.metatype(Tty.type, {__index = Tty})
+
+-------------------------------------------------------------------------------
+-- Pipe
+-------------------------------------------------------------------------------
+
+ffi.cdef [[
+ int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc);
+ int uv_pipe_open(uv_pipe_t* handle, uv_file file);
+ int uv_pipe_bind(uv_pipe_t* handle, const char* name);
+ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb);
+ int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size);
+ int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size);
+ void uv_pipe_pending_instances(uv_pipe_t* handle, int count);
+ int uv_pipe_pending_count(uv_pipe_t* handle);
+ uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle);
+ int uv_pipe_chmod(uv_pipe_t* handle, int flags);
+]]
+
+local Pipe = setmetatable({}, {__index = Stream})
+Pipe.type = ffi.typeof 'uv_pipe_t'
+
+function Loop:newPipe(ipc)
+ local pipe = Pipe.type()
+ uvCheck(UV.uv_pipe_init(self, pipe, ipc and 1 or 0))
+ return pipe
+end
+
+function Pipe:open(fd)
+ uvCheck(UV.uv_pipe_open(self, fd))
+end
+
+function Pipe:bind(path)
+ uvCheck(UV.uv_pipe_bind(self, path))
+end
+
+-- TODO: add more pipe functions
+
+ffi.metatype(Pipe.type, {__index = Pipe})
+
+-------------------------------------------------------------------------------
+-- Timer
+-------------------------------------------------------------------------------
+
+ffi.cdef [[
+ typedef void (*uv_timer_cb)(uv_timer_t* handle);
+
+ int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle);
+ int uv_timer_start(uv_timer_t* handle, uv_timer_cb cb, uint64_t timeout, uint64_t repeat);
+ int uv_timer_stop(uv_timer_t* handle);
+ int uv_timer_again(uv_timer_t* handle);
+ void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat);
+ uint64_t uv_timer_get_repeat(const uv_timer_t* handle);
+]]
+
+local Timer = setmetatable({}, {__index = Handle})
+Timer.Type = ffi.typeof 'uv_timer_t'
+
+function Loop:newTimer()
+ local timer = Timer.Type()
+ uvCheck(UV.uv_timer_init(self, timer))
+ return timer
+end
+
+function Timer:sleep(timeout)
+ uvCheck(UV.uv_timer_start(self, makeCallback 'uv_timer_cb', timeout, 0))
+ coroutine.yield()
+ uvCheck(UV.uv_timer_stop(self))
+end
+
+function Timer:start(callback, timeout, rep)
+ local cb = cast('uv_timer_cb', timeout)
+ uvCheck(UV.uv_timer_start(self, callback, cb, rep))
+ return cb
+end
+
+function Timer:stop()
+ uvCheck(UV.uv_timer_stop(self))
+end
+
+function Timer:again()
+ uvCheck(UV.uv_timer_again(self))
+end
+
+function Timer:setRepeat(rep)
+ uvCheck(UV.uv_timer_set_repeat(self, rep))
+end
+
+function Timer:getRepeat()
+ return UV.uv_timer_get_repeat(self)
+end
+
+local function onGc(handle)
+ if not handle:isClosing() then
+ -- We can't safely close handles here because onClose happens after the
+ -- struct is freed by lua.
+ -- Instead abort the process so the programmer can fix it early.
+ handle = cast('uv_' .. Handle.getType(handle) .. '_t*', handle)
+ error('Unclosed ' .. tostring(handle) .. ' got garbage collected')
+ end
+end
+
+ffi.metatype(Timer.Type, {__index = Timer, __gc = onGc})
+
+-------------------------------------------------------------------------------
+-- Loop
+-------------------------------------------------------------------------------
+
+ffi.cdef [[
+ uv_loop_t* uv_default_loop();
+ int uv_loop_init(uv_loop_t* loop);
+ int uv_loop_close(uv_loop_t* loop);
+ int uv_loop_alive(const uv_loop_t* loop);
+ void uv_stop(uv_loop_t* loop);
+ uint64_t uv_now(const uv_loop_t* loop);
+ void uv_update_time(uv_loop_t* loop);
+ void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg);
+ int uv_run(uv_loop_t* loop, uv_run_mode mode);
+]]
+
+local LoopType = ffi.typeof 'uv_loop_t'
+
+function Loop.new()
+ local loop = LoopType()
+ uvCheck(UV.uv_loop_init(loop))
+ return loop
+end
+
+function Loop:close()
+ uvCheck(UV.uv_loop_close(self))
+end
+
+function Loop:alive()
+ return UV.uv_loop_alive(self) ~= 0
+end
+
+function Loop:stop()
+ return UV.uv_loop_stop(self)
+end
+
+function Loop:now()
+ return UV.uv_loop_now(self)
+end
+
+function Loop:updateTime()
+ return UV.uv_update_time(self)
+end
+
+function Loop:walk(callback)
+ local function onHandle(handle)
+ callback(cast('uv_' .. Handle.getType(handle) .. '_t*', handle))
+ end
+ local cb = cast('uv_walk_cb', onHandle)
+ UV.uv_walk(self, cb, nil)
+ cb:free()
+end
+
+function Loop:run(mode)
+ mode = assert(UV['UV_RUN_' .. string.upper(mode)], 'Unknown run mode')
+ return tonumber(uvCheck(UV.uv_run(self, mode)))
+end
+
+function Loop:bind(server, host, port)
+ local addr = ffi.new("struct sockaddr_in [1]")
+ local res = UV.uv_ip4_addr(host, port, cast("struct sockaddr_in *", addr))
+ uvCheck(UV.uv_tcp_bind(server, cast("struct sockaddr *", addr), 0 ))
+end
+
+function Loop:listen(tcp, backlog, onConnect)
+ tcp:listen( backlog, onConnect )
+end
+
+
+ffi.metatype(LoopType, {__index = Loop})
+
+-------------------------------------------------------------------------------
+
+Loop.Req = Req
+Loop.Connect = Connect
+Loop.Write = Write
+Loop.Shutdown = Shutdown
+Loop.Handle = Handle
+Loop.Stream = Stream
+Loop.Tcp = Tcp
+Loop.Timer = Timer
+Loop.uv = UV
+
+return UV.uv_default_loop()