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()