sokol-luajit/engine/nuklear.lua
2026-07-25 15:21:07 +09:30

203 lines
7.6 KiB
Lua

local nk = sg
local stb = require("stb")
local ffi = require("ffi")
-- --------------------------------------------------------------------------------------
local function checkstring(val)
local t = type(val)
if t == "string" then
return val
elseif t == "number" then
return tostring(val)
elseif t == "cdata" then
return ffi.string(val)
else
error("bad argument: string or number expected, got " .. t, 2)
end
end
-- --------------------------------------------------------------------------------------
nuklear_renderer = {}
-- --------------------------------------------------------------------------------------
nuklear_renderer.get_size = function()
local r = renderer.rect
-- print("get_size", r.w, r.h)
return r.w, r.h
end
-- --------------------------------------------------------------------------------------
nuklear_renderer.set_clip_rect = function(x, y, w, h)
local canvas = renderer.canvas
local r = renderer.rect
local rect = nk.nk_rect(x + r.x, y + r.y, w, h)
-- print("set_clip_rect", rect.x, rect.y, rect.w, rect.h)
nk.nk_push_scissor(canvas, rect)
end
-- --------------------------------------------------------------------------------------
nuklear_renderer.draw_rect = function(x, y, w, h, color)
local canvas = renderer.canvas
local r = renderer.rect
-- local ncol = nk.nk_rgba(color.r, color.g, color.b, color.a)
local ncol = nk.nk_rgba(color[1], color[2], color[3], color[4])
-- print("draw_rect", x, y, w, h)
-- nk.nk_layout_space_begin(renderer.ctx, nk.NK_STATIC, r.w, 1)
-- nk.nk_layout_space_push(renderer.ctx, r)
nk.nk_fill_rect(canvas, nk.nk_rect( x+r.x, y+r.y, w, h), 0, ncol)
-- nk.nk_layout_space_end(renderer.ctx)
end
-- --------------------------------------------------------------------------------------
nuklear_renderer.draw_text = function(font, text, x, y, color)
local canvas = renderer.canvas
-- local hcolor = nk.nk_rgba(color.r, color.g, color.b, color.a)
local hcolor = nk.nk_rgba(color[1], color[2], color[3], color[4])
local r = renderer.rect
local w = font:get_width(text)
local h = font:get_height()
local rect = nk.nk_rect(x+r.x, y+r.y, w, h)
local font_handle = font.font.handle
local text = checkstring(text)
local text_len = #text
-- print("draw_text", x, y, text)
if(text == "CRLF" or #text == 0) then return x end
if(string.byte(text, -1, -1) == 10) then text_len = text_len - 1 end
-- nk.nk_layout_space_begin(renderer.ctx, nk.NK_STATIC, r.w, 1)
-- nk.nk_layout_space_push(renderer.ctx, r)
-- font:set_tab_width( font.tab_width )
nk.nk_draw_text(canvas, rect, text, text_len, font_handle, hcolor, hcolor)
-- nk.nk_layout_space_end(renderer.ctx)
return w + x, h
end
-- --------------------------------------------------------------------------------------
nuklear_renderer.load_image = function(filename, no_ui)
local x = ffi.new("int[1]", {0})
local y = ffi.new("int[1]", {0})
local n = ffi.new("int[1]", {4})
local data = stb.stbi_load(filename, x, y, n, 4)
if (data == nil) then error("[STB]: failed to load image: "..filename); return nil end
-- print("Original channels in file:", n[0])
print("Image Loaded: "..filename.." Width: "..x[0].." Height: "..y[0].." Channels: "..n[0])
-- Auto free when data handles are released
ffi.gc(data, stb.stbi_image_free)
local pixformat = sg.SG_PIXELFORMAT_RGBA8
local sg_img_desc = ffi.new("sg_image_desc[1]", {})
sg_img_desc[0].width = x[0]
sg_img_desc[0].height = y[0]
sg_img_desc[0].pixel_format = pixformat
sg_img_desc[0].sample_count = 1
sg_img_desc[0].data.subimage[0][0].ptr = data
sg_img_desc[0].data.subimage[0][0].size = x[0] * y[0] * 4
if(sg.sg_isvalid() == false) then return nil, sg_img_desc, data end
local new_img = sg.sg_make_image(sg_img_desc)
if(no_ui) then return new_img, sg_img_desc, data end
-- // create a sokol-nuklear image object which associates an sg_image with an sg_sampler
local img_desc = ffi.new("snk_image_desc_t[1]")
img_desc[0].image = new_img
local snk_img = nk.snk_make_image(img_desc)
local nk_hnd = nk.snk_nkhandle(snk_img)
local nk_img = nk.nk_image_handle(nk_hnd);
return nk_img, sg_img_desc
end
-- --------------------------------------------------------------------------------------
nuklear_renderer.load_image_buffer = function( name, buf, bufsize, no_ui )
name = name or "image"
local x = ffi.new("int[1]", {0})
local y = ffi.new("int[1]", {0})
local n = ffi.new("int[1]", {4})
local data = stb.stbi_load_from_memory(buf, bufsize, x, y, n, 4)
if (data == nil) then
print("[STB]: failed to load image: ", name)
return nil, nil
end
print("Original channels in file:", n[0])
print("Image Buffer Loaded: "..name.." Width: "..x[0].." Height: "..y[0].." Channels: "..n[0])
local pixformat = sg.SG_PIXELFORMAT_RGBA8
local sg_img_desc = ffi.new("sg_image_desc[1]")
sg_img_desc[0].width = x[0]
sg_img_desc[0].height = y[0]
sg_img_desc[0].pixel_format = pixformat
sg_img_desc[0].sample_count = 1
sg_img_desc[0].data.subimage[0][0].ptr = data
sg_img_desc[0].data.subimage[0][0].size = x[0] * y[0] * 4
if(sg.sg_isvalid() == false) then return nil, sg_img_desc, data end
local new_img = sg.sg_make_image(sg_img_desc)
if(no_ui) then return new_img, sg_img_desc, data end
-- // create a sokol-nuklear image object which associates an sg_image with an sg_sampler
local img_desc = ffi.new("snk_image_desc_t[1]")
img_desc[0].image = new_img
local snk_img = nk.snk_make_image(img_desc)
local nk_hnd = nk.snk_nkhandle(snk_img)
local nk_img = nk.nk_image_handle(nk_hnd);
stb.stbi_image_free(data)
return nk_img, sg_img_desc
end
-- --------------------------------------------------------------------------------------
nuklear_renderer.draw_image = function(img, x, y, w, h, color)
color = color or {0xff, 0xff, 0xff, 0xff}
local canvas = renderer.canvas
local r = renderer.rect
local rect = nk.nk_rect(x+r.x, y+r.y, w, h)
local icolor = nk.nk_rgba(color[1], color[2], color[3], color[4])
nk.nk_draw_image(canvas, rect, img, icolor )
end
-- --------------------------------------------------------------------------------------
nuklear_renderer.set_cursor = function()
if(renderer.ctx == nil) then return end
local cursor_name, rect = renderer.cursor.name, renderer.cursor.rect
local r = nk.nk_rect(rect.position.x, rect.position.y, rect.size.x, rect.size.y)
nk.nk_layout_space_begin(renderer.ctx, nk.NK_STATIC, 27, 1)
nk.nk_layout_space_push(renderer.ctx, r)
if (nk.nk_widget_is_hovered(renderer.ctx) == true) then
if(cursor_name == "arrow") then
nk.nk_style_set_cursor(renderer.ctx, nk.NK_CURSOR_ARROW)
elseif(cursor_name == "ibeam") then
nk.nk_style_set_cursor(renderer.ctx, nk.NK_CURSOR_TEXT)
elseif(cursor_name == "hsplit") then
nk.nk_style_set_cursor(renderer.ctx, nk.NK_CURSOR_RESIZE_HORIZONTAL)
elseif(cursor_name == "sizeh") then
nk.nk_style_set_cursor(renderer.ctx, nk.NK_CURSOR_RESIZE_HORIZONTAL)
elseif(cursor_name == "sizev") then
nk.nk_style_set_cursor(renderer.ctx, nk.NK_CURSOR_RESIZE_VERTICAL)
end
else
nk.nk_style_set_cursor(renderer.ctx, nk.NK_CURSOR_ARROW);
end
nk.nk_layout_space_end(renderer.ctx)
end
-- --------------------------------------------------------------------------------------