Initial commit
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
function love.conf(t)
|
||||||
|
t.console = true
|
||||||
|
t.window.resizable = true
|
||||||
|
t.window.msaa = 4
|
||||||
|
t.window.width = 1920
|
||||||
|
t.window.height = 960
|
||||||
|
|
||||||
|
if love._version_major > 11 then
|
||||||
|
t.window.depth = true
|
||||||
|
else
|
||||||
|
t.window.depth = 24
|
||||||
|
end
|
||||||
|
|
||||||
|
t.window.vsync = true
|
||||||
|
t.highdpi = true
|
||||||
|
end
|
||||||
@@ -0,0 +1,524 @@
|
|||||||
|
--- ImGui Backend for Love2D
|
||||||
|
--- Structurally mirrors imgui_impl_gmod.lua
|
||||||
|
|
||||||
|
local love = love
|
||||||
|
|
||||||
|
local ImGui_ImplLOVE_GetBackendData
|
||||||
|
local ImGui_ImplLOVE_UpdateTexture
|
||||||
|
local ImGui_ImplLOVE_RenderDrawData
|
||||||
|
local ImGui_ImplLOVE_Shutdown
|
||||||
|
|
||||||
|
local CURSOR_MAP = {
|
||||||
|
[ImGuiMouseCursor.None] = nil,
|
||||||
|
[ImGuiMouseCursor.Arrow] = "arrow",
|
||||||
|
[ImGuiMouseCursor.TextInput] = "ibeam",
|
||||||
|
[ImGuiMouseCursor.ResizeAll] = "sizeall",
|
||||||
|
[ImGuiMouseCursor.ResizeNS] = "sizens",
|
||||||
|
[ImGuiMouseCursor.ResizeEW] = "sizewe",
|
||||||
|
[ImGuiMouseCursor.ResizeNESW] = "sizenesw",
|
||||||
|
[ImGuiMouseCursor.ResizeNWSE] = "sizenwse",
|
||||||
|
[ImGuiMouseCursor.Hand] = "hand",
|
||||||
|
[ImGuiMouseCursor.Wait] = "wait",
|
||||||
|
[ImGuiMouseCursor.Progress] = "waitarrow",
|
||||||
|
[ImGuiMouseCursor.NotAllowed] = "no",
|
||||||
|
}
|
||||||
|
|
||||||
|
local KEY_MAP = {
|
||||||
|
["return"] = ImGuiKey.Enter, ["escape"] = ImGuiKey.Escape,
|
||||||
|
["backspace"] = ImGuiKey.Backspace, ["tab"] = ImGuiKey.Tab,
|
||||||
|
["space"] = ImGuiKey.Space, ["enter"] = ImGuiKey.KeypadEnter,
|
||||||
|
["up"] = ImGuiKey.UpArrow, ["down"] = ImGuiKey.DownArrow,
|
||||||
|
["left"] = ImGuiKey.LeftArrow, ["right"] = ImGuiKey.RightArrow,
|
||||||
|
["home"] = ImGuiKey.Home, ["end"] = ImGuiKey.End,
|
||||||
|
["pageup"] = ImGuiKey.PageUp, ["pagedown"] = ImGuiKey.PageDown,
|
||||||
|
["insert"] = ImGuiKey.Insert, ["delete"] = ImGuiKey.Delete,
|
||||||
|
["lctrl"] = ImGuiKey.LeftCtrl, ["rctrl"] = ImGuiKey.RightCtrl,
|
||||||
|
["lshift"] = ImGuiKey.LeftShift, ["rshift"] = ImGuiKey.RightShift,
|
||||||
|
["lalt"] = ImGuiKey.LeftAlt, ["ralt"] = ImGuiKey.RightAlt,
|
||||||
|
["lgui"] = ImGuiKey.LeftSuper, ["rgui"] = ImGuiKey.RightSuper,
|
||||||
|
}
|
||||||
|
for i = 0, 9 do KEY_MAP[tostring(i)] = ImGuiKey["K" .. i] end
|
||||||
|
for i = 1, 12 do KEY_MAP["f" .. i] = ImGuiKey["F" .. i] end
|
||||||
|
for c in ("abcdefghijklmnopqrstuvwxyz"):gmatch(".") do
|
||||||
|
KEY_MAP[c] = ImGuiKey[c:upper()]
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ImGui_ImplLOVE_UpdateKeyModifiers()
|
||||||
|
local io = ImGui.GetIO()
|
||||||
|
io:AddKeyEvent(ImGuiMod_Ctrl, love.keyboard.isDown("lctrl", "rctrl"))
|
||||||
|
io:AddKeyEvent(ImGuiMod_Shift, love.keyboard.isDown("lshift", "rshift"))
|
||||||
|
io:AddKeyEvent(ImGuiMod_Alt, love.keyboard.isDown("lalt", "ralt"))
|
||||||
|
io:AddKeyEvent(ImGuiMod_Super, love.keyboard.isDown("lgui", "rgui"))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @return table?
|
||||||
|
function ImGui_ImplLOVE_GetBackendData()
|
||||||
|
return ImGui.GetCurrentContext() and ImGui.GetIO().BackendPlatformUserData or nil
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
-- VIEWPORT STUBS
|
||||||
|
-- Required for ImGui BackendPlatformHasViewports logic
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
local function ImGui_ImplLOVE_CreateWindow(viewport)
|
||||||
|
-- STUB: Triggered when ImGui creates a new multi-viewport window (e.g., dragging a panel outside main window).
|
||||||
|
-- If your LÖVE fork supports multiple OS windows (or if managing internal canvases), initialize it here.
|
||||||
|
local vd = { WindowID = nil, Owned = true }
|
||||||
|
viewport.PlatformUserData = vd
|
||||||
|
viewport.PlatformHandle = vd
|
||||||
|
viewport.PlatformHandleRaw = vd
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ImGui_ImplLOVE_DestroyWindow(viewport)
|
||||||
|
-- STUB: Destroy the OS-level window or release the canvas associated with this viewport.
|
||||||
|
viewport.PlatformUserData = nil
|
||||||
|
viewport.PlatformHandle = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ImGui_ImplLOVE_ShowWindow(viewport)
|
||||||
|
-- STUB: OS-level call to make the window visible.
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ImGui_ImplLOVE_SetWindowPos(viewport, pos)
|
||||||
|
-- STUB: Set the OS-level window position (pos.x, pos.y).
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ImGui_ImplLOVE_GetWindowPos(viewport)
|
||||||
|
-- STUB: Return the OS-level window position as ImVec2(x, y).
|
||||||
|
return ImVec2(0, 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ImGui_ImplLOVE_SetWindowSize(viewport, size)
|
||||||
|
-- STUB: Resize the OS-level window to (size.x, size.y).
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ImGui_ImplLOVE_GetWindowSize(viewport)
|
||||||
|
-- STUB: Return the OS-level window size.
|
||||||
|
return ImVec2(800, 600)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ImGui_ImplLOVE_SetWindowFocus(viewport)
|
||||||
|
-- STUB: Bring the OS-level window to focus.
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ImGui_ImplLOVE_GetWindowFocus(viewport)
|
||||||
|
-- STUB: Return true if this OS-level window has focus.
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ImGui_ImplLOVE_SetWindowTitle(viewport, title)
|
||||||
|
-- STUB: Set the title of the OS-level window.
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ImGui_ImplLOVE_RenderWindow(viewport)
|
||||||
|
-- STUB: Render routine for the secondary viewport.
|
||||||
|
-- Set render target to this window's canvas/context, then call ImGui_ImplLOVE_RenderDrawData(viewport.DrawData)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ImGui_ImplLOVE_SwapBuffers(viewport)
|
||||||
|
-- STUB: OS-level call to swap buffers for this specific window context.
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ImGui_ImplGMOD_UpdateMonitors()
|
||||||
|
local bd = ImGui_ImplLOVE_GetBackendData()
|
||||||
|
local io = ImGui.GetPlatformIO()
|
||||||
|
io.Monitors:resize(0)
|
||||||
|
|
||||||
|
local imgui_monitor = ImGuiPlatformMonitor()
|
||||||
|
ImVec2_Copy(imgui_monitor.MainSize, ImVec2(800, 600))
|
||||||
|
ImVec2_Copy(imgui_monitor.WorkSize, ImVec2(800, 600))
|
||||||
|
|
||||||
|
io.Monitors:push_back(imgui_monitor)
|
||||||
|
|
||||||
|
bd.WantUpdateMonitors = false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function ImGui_ImplLOVE_InitMultiViewportSupport()
|
||||||
|
local platform_io = ImGui.GetPlatformIO()
|
||||||
|
platform_io.Platform_CreateWindow = ImGui_ImplLOVE_CreateWindow
|
||||||
|
platform_io.Platform_DestroyWindow = ImGui_ImplLOVE_DestroyWindow
|
||||||
|
platform_io.Platform_ShowWindow = ImGui_ImplLOVE_ShowWindow
|
||||||
|
platform_io.Platform_SetWindowPos = ImGui_ImplLOVE_SetWindowPos
|
||||||
|
platform_io.Platform_GetWindowPos = ImGui_ImplLOVE_GetWindowPos
|
||||||
|
platform_io.Platform_SetWindowSize = ImGui_ImplLOVE_SetWindowSize
|
||||||
|
platform_io.Platform_GetWindowSize = ImGui_ImplLOVE_GetWindowSize
|
||||||
|
platform_io.Platform_SetWindowFocus = ImGui_ImplLOVE_SetWindowFocus
|
||||||
|
platform_io.Platform_GetWindowFocus = ImGui_ImplLOVE_GetWindowFocus
|
||||||
|
platform_io.Platform_SetWindowTitle = ImGui_ImplLOVE_SetWindowTitle
|
||||||
|
|
||||||
|
platform_io.Renderer_RenderWindow = ImGui_ImplLOVE_RenderWindow
|
||||||
|
platform_io.Renderer_SwapBuffers = ImGui_ImplLOVE_SwapBuffers
|
||||||
|
|
||||||
|
local main_viewport = ImGui.GetMainViewport()
|
||||||
|
main_viewport.PlatformUserData = { Owned = false }
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
-- PLATFORM DATA & CALLBACKS
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
local function ImGui_ImplLOVE_PlatformSetImeData(ctx, vp, data)
|
||||||
|
-- Unlike GMod's invisible VGUI TextEntry workaround[cite: 1],
|
||||||
|
-- Love2D has native IME support we can toggle directly.
|
||||||
|
if data.WantVisible or data.WantTextInput then
|
||||||
|
love.keyboard.setTextInput(true, data.InputPos.x, data.InputPos.y, 1, data.InputLineHeight)
|
||||||
|
else
|
||||||
|
love.keyboard.setTextInput(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ImGui_ImplLOVE_PlatformSetClipboardText(ctx, text)
|
||||||
|
love.system.setClipboardText(text)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ImGui_ImplLOVE_PlatformGetClipboardText(ctx)
|
||||||
|
return love.system.getClipboardText()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ImGui_ImplLOVE_OpenInShellFn(ctx, path)
|
||||||
|
love.system.openURL(path)
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
-- TEXTURE MANAGEMENT
|
||||||
|
---------------------------------------------------------
|
||||||
|
local ffi = require("ffi")
|
||||||
|
|
||||||
|
function ImGui_ImplLOVE_UpdateTexture(tex)
|
||||||
|
if tex.Status == ImTextureStatus.WantCreate then
|
||||||
|
local w, h = tex.Width, tex.Height
|
||||||
|
local row, row_base = tex:GetPixelsAt(0, 0)
|
||||||
|
|
||||||
|
local imgData = love.image.newImageData(w, h)
|
||||||
|
local ptr = ffi.cast("uint8_t*", imgData:getFFIPointer())
|
||||||
|
|
||||||
|
-- Iterate through the Lua table to manually assign the bytes to the C pointer
|
||||||
|
local total_bytes = w * h * 4
|
||||||
|
for i = 0, total_bytes - 1 do
|
||||||
|
ptr[i] = row[row_base + i]
|
||||||
|
end
|
||||||
|
|
||||||
|
local loveTex = love.graphics.newImage(imgData)
|
||||||
|
loveTex:setFilter("nearest", "nearest")
|
||||||
|
|
||||||
|
tex.BackendUserData = loveTex
|
||||||
|
tex:SetTexID(1)
|
||||||
|
tex:SetStatus(ImTextureStatus.OK)
|
||||||
|
elseif tex.Status == ImTextureStatus.WantUpdates then
|
||||||
|
local loveTex = tex.BackendUserData
|
||||||
|
IM_ASSERT(loveTex ~= nil)
|
||||||
|
|
||||||
|
for _, r in tex.Updates:iter() do
|
||||||
|
local w, h = r.w, r.h
|
||||||
|
|
||||||
|
local updateData = love.image.newImageData(w, h)
|
||||||
|
local dst = ffi.cast("uint8_t*", updateData:getFFIPointer())
|
||||||
|
|
||||||
|
for y = 0, h - 1 do
|
||||||
|
local src, src_base = tex:GetPixelsAt(r.x, r.y + y)
|
||||||
|
local dst_base = y * w * 4
|
||||||
|
|
||||||
|
for i = 0, w * 4 - 1 do
|
||||||
|
dst[dst_base + i] = src[src_base + i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
loveTex:replacePixels(
|
||||||
|
updateData,
|
||||||
|
nil,
|
||||||
|
1,
|
||||||
|
r.x,
|
||||||
|
r.y,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
|
updateData:release()
|
||||||
|
end
|
||||||
|
|
||||||
|
tex:SetStatus(ImTextureStatus.OK)
|
||||||
|
elseif tex.Status == ImTextureStatus.WantDestroy then
|
||||||
|
if tex.BackendUserData then
|
||||||
|
tex.BackendUserData:release()
|
||||||
|
tex.BackendUserData = nil
|
||||||
|
end
|
||||||
|
tex:SetTexID(ImTextureID_Invalid)
|
||||||
|
tex:SetStatus(ImTextureStatus.Destroyed)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
-- RENDERING
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
local rshift, band = bit32.rshift, bit32.band
|
||||||
|
|
||||||
|
local function u32ToRGBA(col)
|
||||||
|
-- Extract bytes from u32 integer just like GMod implementation[cite: 1]
|
||||||
|
return band(col, 0xFF) / 255,
|
||||||
|
band(rshift(col, 8), 0xFF) / 255,
|
||||||
|
band(rshift(col, 16), 0xFF) / 255,
|
||||||
|
band(rshift(col, 24), 0xFF) / 255
|
||||||
|
end
|
||||||
|
|
||||||
|
function ImGui_ImplLOVE_RenderDrawData(draw_data)
|
||||||
|
if draw_data.DisplaySize.x <= 0.0 or draw_data.DisplaySize.y <= 0.0 then return end
|
||||||
|
|
||||||
|
if draw_data.Textures ~= nil then
|
||||||
|
for _, tex in draw_data.Textures:iter() do
|
||||||
|
if tex.Status ~= ImTextureStatus.OK then
|
||||||
|
ImGui_ImplLOVE_UpdateTexture(tex)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
love.graphics.push("all")
|
||||||
|
love.graphics.setBlendMode("alpha", "alphamultiply")
|
||||||
|
|
||||||
|
local format = {
|
||||||
|
{"VertexPosition", "float", 2},
|
||||||
|
{"VertexTexCoord", "float", 2},
|
||||||
|
{"VertexColor", "byte", 4},
|
||||||
|
}
|
||||||
|
|
||||||
|
local idx_data, vtx_data
|
||||||
|
for _, draw_list in draw_data.CmdLists:iter() do
|
||||||
|
idx_data = draw_list.IdxBuffer; vtx_data = draw_list.VtxBuffer
|
||||||
|
|
||||||
|
for _, pcmd in draw_list.CmdBuffer:iter() do
|
||||||
|
if pcmd.UserCallback ~= nil then
|
||||||
|
pcmd.UserCallback(draw_list, pcmd)
|
||||||
|
elseif pcmd.ElemCount > 0 and pcmd.ClipRect.z > pcmd.ClipRect.x and pcmd.ClipRect.w > pcmd.ClipRect.y then
|
||||||
|
|
||||||
|
-- LÖVE Scissor mapping
|
||||||
|
love.graphics.setScissor(pcmd.ClipRect.x, pcmd.ClipRect.y,
|
||||||
|
pcmd.ClipRect.z - pcmd.ClipRect.x, pcmd.ClipRect.w - pcmd.ClipRect.y)
|
||||||
|
|
||||||
|
-- Create a temporary table for vertices
|
||||||
|
-- Note: For production use, passing `ByteData` with an FFI pointer directly to `newMesh` is significantly faster.
|
||||||
|
local vertices = {}
|
||||||
|
for i = 0, pcmd.ElemCount - 1, 3 do
|
||||||
|
local idx0 = idx_data[pcmd.IdxOffset + 1 + i]
|
||||||
|
local idx1 = idx_data[pcmd.IdxOffset + 2 + i]
|
||||||
|
local idx2 = idx_data[pcmd.IdxOffset + 3 + i]
|
||||||
|
|
||||||
|
local vtx0 = vtx_data[pcmd.VtxOffset + idx0]
|
||||||
|
local vtx1 = vtx_data[pcmd.VtxOffset + idx1]
|
||||||
|
local vtx2 = vtx_data[pcmd.VtxOffset + idx2]
|
||||||
|
|
||||||
|
local r0, g0, b0, a0 = u32ToRGBA(vtx0[3])
|
||||||
|
table.insert(vertices, {vtx0[1][1], vtx0[1][2], vtx0[2][1], vtx0[2][2], r0, g0, b0, a0})
|
||||||
|
|
||||||
|
local r1, g1, b1, a1 = u32ToRGBA(vtx1[3])
|
||||||
|
table.insert(vertices, {vtx1[1][1], vtx1[1][2], vtx1[2][1], vtx1[2][2], r1, g1, b1, a1})
|
||||||
|
|
||||||
|
local r2, g2, b2, a2 = u32ToRGBA(vtx2[3])
|
||||||
|
table.insert(vertices, {vtx2[1][1], vtx2[1][2], vtx2[2][1], vtx2[2][2], r2, g2, b2, a2})
|
||||||
|
end
|
||||||
|
|
||||||
|
local mesh = love.graphics.newMesh(format, vertices, "triangles")
|
||||||
|
|
||||||
|
-- The Texture object is stored in BackendUserData
|
||||||
|
local tex_id = pcmd:GetTexID()
|
||||||
|
local tex = ImGui.GetPlatformIO().Textures[tex_id]
|
||||||
|
if tex and tex.BackendUserData then
|
||||||
|
mesh:setTexture(tex.BackendUserData)
|
||||||
|
end
|
||||||
|
|
||||||
|
love.graphics.draw(mesh)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
love.graphics.setScissor()
|
||||||
|
love.graphics.pop()
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
-- CORE LIFECYCLE
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
function ImGui_ImplLOVE_Init()
|
||||||
|
local io = ImGui.GetIO()
|
||||||
|
|
||||||
|
local bd = { Time = love.timer.getTime() }
|
||||||
|
io.BackendPlatformUserData = bd
|
||||||
|
|
||||||
|
--io.BackendFlags = bit32.bor(io.BackendFlags, ImGuiBackendFlags.PlatformHasViewports)
|
||||||
|
io.BackendFlags = bit32.bor(io.BackendFlags, ImGuiBackendFlags.RendererHasTextures)
|
||||||
|
io.BackendFlags = bit32.bor(io.BackendFlags, ImGuiBackendFlags.RendererHasVtxOffset)
|
||||||
|
--io.BackendFlags = bit32.bor(io.BackendFlags, ImGuiBackendFlags.RendererHasViewports)
|
||||||
|
|
||||||
|
local platform_io = ImGui.GetPlatformIO()
|
||||||
|
platform_io.Platform_SetImeDataFn = ImGui_ImplLOVE_PlatformSetImeData
|
||||||
|
platform_io.Platform_SetClipboardTextFn = ImGui_ImplLOVE_PlatformSetClipboardText
|
||||||
|
platform_io.Platform_GetClipboardTextFn = ImGui_ImplLOVE_PlatformGetClipboardText
|
||||||
|
platform_io.Platform_OpenInShellFn = ImGui_ImplLOVE_OpenInShellFn
|
||||||
|
|
||||||
|
--ImGui_ImplLOVE_InitMultiViewportSupport()
|
||||||
|
ImGui_ImplGMOD_UpdateMonitors()
|
||||||
|
end
|
||||||
|
|
||||||
|
function ImGui_ImplLOVE_Shutdown()
|
||||||
|
local io = ImGui.GetIO()
|
||||||
|
ImGui.DestroyPlatformWindows()
|
||||||
|
|
||||||
|
io.BackendPlatformUserData = nil
|
||||||
|
io.BackendFlags = bit32.band(io.BackendFlags, bit32.bnot(bit32.bor(
|
||||||
|
ImGuiBackendFlags.HasMouseCursors,
|
||||||
|
ImGuiBackendFlags.PlatformHasViewports,
|
||||||
|
ImGuiBackendFlags.RendererHasViewports
|
||||||
|
)))
|
||||||
|
end
|
||||||
|
|
||||||
|
function ImGui_ImplLOVE_NewFrame()
|
||||||
|
local io = ImGui.GetIO()
|
||||||
|
local bd = ImGui_ImplLOVE_GetBackendData()
|
||||||
|
|
||||||
|
local w, h = love.graphics.getDimensions()
|
||||||
|
ImVec2_CopyV(io.DisplaySize, w, h)
|
||||||
|
|
||||||
|
local current_time = love.timer.getTime()
|
||||||
|
io.DeltaTime = (bd.Time > 0.0) and (current_time - bd.Time) or (1.0 / 60.0)
|
||||||
|
bd.Time = current_time
|
||||||
|
|
||||||
|
-- Update Cursor
|
||||||
|
if bit32.band(io.ConfigFlags, ImGuiConfigFlags.NoMouseCursorChange) == 0 then
|
||||||
|
local cursor = CURSOR_MAP[ImGui.GetMouseCursor()]
|
||||||
|
if cursor then
|
||||||
|
love.mouse.setCursor(love.mouse.getSystemCursor(cursor))
|
||||||
|
else
|
||||||
|
love.mouse.setCursor()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
-- LOVE EVENT HOOKS (Call these from main.lua)
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
local function Hook_MouseMoved(x, y)
|
||||||
|
local io = ImGui.GetIO()
|
||||||
|
io:AddMouseSourceEvent(ImGuiMouseSource.Mouse)
|
||||||
|
io:AddMousePosEvent(x, y)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Hook_MousePressed(x, y, button)
|
||||||
|
local io = ImGui.GetIO()
|
||||||
|
io:AddMouseSourceEvent(ImGuiMouseSource.Mouse)
|
||||||
|
-- LÖVE passes buttons as 1=left, 2=right, 3=middle. ImGui uses 0=left, 1=right, 2=middle.
|
||||||
|
if button <= 3 then
|
||||||
|
local ig_btn = (button == 1) and ImGuiMouseButton.Left or (button == 2 and ImGuiMouseButton.Right or ImGuiMouseButton.Middle)
|
||||||
|
io:AddMouseButtonEvent(ig_btn, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Hook_MouseReleased(x, y, button)
|
||||||
|
local io = ImGui.GetIO()
|
||||||
|
if button <= 3 then
|
||||||
|
local ig_btn = (button == 1) and ImGuiMouseButton.Left or (button == 2 and ImGuiMouseButton.Right or ImGuiMouseButton.Middle)
|
||||||
|
io:AddMouseButtonEvent(ig_btn, false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Hook_WheelMoved(x, y)
|
||||||
|
local io = ImGui.GetIO()
|
||||||
|
io:AddMouseWheelEvent(x, y)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Hook_KeyPressed(key)
|
||||||
|
local io = ImGui.GetIO()
|
||||||
|
ImGui_ImplLOVE_UpdateKeyModifiers()
|
||||||
|
if KEY_MAP[key] then
|
||||||
|
io:AddKeyEvent(KEY_MAP[key], true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Hook_KeyReleased(key)
|
||||||
|
local io = ImGui.GetIO()
|
||||||
|
ImGui_ImplLOVE_UpdateKeyModifiers()
|
||||||
|
if KEY_MAP[key] then
|
||||||
|
io:AddKeyEvent(KEY_MAP[key], false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Hook_TextInput(text)
|
||||||
|
local io = ImGui.GetIO()
|
||||||
|
for _, code in utf8.codes(text) do
|
||||||
|
io:AddInputCharacter(code)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--Implementing some bullshit
|
||||||
|
function ImStd.ImFileOpen(_filename, _mode)
|
||||||
|
if _mode == "rb" then _mode = "r" end
|
||||||
|
local file, _ = love.filesystem.newFile(_filename, _mode)
|
||||||
|
return file
|
||||||
|
end
|
||||||
|
|
||||||
|
function ImStd.ImFileClose(f)
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function ImStd.ImFileGetSize(f)
|
||||||
|
return f:getSize()
|
||||||
|
end
|
||||||
|
|
||||||
|
function ImStd.ImFileRead(f, data, count)
|
||||||
|
local CHUNK_SIZE = 8000 -- We don't read byte by byte
|
||||||
|
local offset = 0
|
||||||
|
|
||||||
|
while offset < count do
|
||||||
|
local read_size = math.min(CHUNK_SIZE, count - offset)
|
||||||
|
local str = f:read(read_size)
|
||||||
|
|
||||||
|
-- Handle EOF or read failure gracefully
|
||||||
|
if not str or #str == 0 then break end
|
||||||
|
|
||||||
|
-- Iterate based on actual bytes read without risking stack overflow
|
||||||
|
for i = 1, #str do
|
||||||
|
data[offset + i] = string.byte(str, i)
|
||||||
|
end
|
||||||
|
|
||||||
|
offset = offset + #str
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function ImStd.ImFileLoadToMemory(filename, mode)
|
||||||
|
local f = ImStd.ImFileOpen(filename, mode)
|
||||||
|
if not f then return end
|
||||||
|
|
||||||
|
local file_size = ImStd.ImFileGetSize(f)
|
||||||
|
if file_size <= 0 then
|
||||||
|
ImStd.ImFileClose(f)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local file_data = {}
|
||||||
|
ImStd.ImFileRead(f, file_data, file_size)
|
||||||
|
if #file_data == 0 then
|
||||||
|
ImStd.ImFileClose(f)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
ImStd.ImFileClose(f)
|
||||||
|
|
||||||
|
return file_data, file_size
|
||||||
|
end
|
||||||
|
|
||||||
|
ImGui_ImplLove = {
|
||||||
|
Init = ImGui_ImplLOVE_Init,
|
||||||
|
Shutdown = ImGui_ImplLOVE_Shutdown,
|
||||||
|
NewFrame = ImGui_ImplLOVE_NewFrame,
|
||||||
|
RenderDrawData = ImGui_ImplLOVE_RenderDrawData,
|
||||||
|
|
||||||
|
-- Event hooks to connect in love.* callbacks
|
||||||
|
MouseMoved = Hook_MouseMoved,
|
||||||
|
MousePressed = Hook_MousePressed,
|
||||||
|
MouseReleased = Hook_MouseReleased,
|
||||||
|
WheelMoved = Hook_WheelMoved,
|
||||||
|
KeyPressed = Hook_KeyPressed,
|
||||||
|
KeyReleased = Hook_KeyReleased,
|
||||||
|
TextInput = Hook_TextInput,
|
||||||
|
}
|
||||||
+11284
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,974 @@
|
|||||||
|
if _G.__IMGUI_ENV then setfenv(1, _G.__IMGUI_ENV) end -- [Roblox] shared env, see init.lua
|
||||||
|
--- ImGui Sincerely WIP
|
||||||
|
-- (Demo Code)
|
||||||
|
|
||||||
|
-- NOTE: Make sure to use fields with different names inside `static`!
|
||||||
|
|
||||||
|
local IM_MIN = math.min
|
||||||
|
local IM_MAX = math.max
|
||||||
|
local function IM_CLAMP(V, MN, MX) return (V < MN) and MN or (V > MX) and MX or V end
|
||||||
|
|
||||||
|
-- TODO: HelpMarker()
|
||||||
|
-- TODO: ImColor helpers?
|
||||||
|
|
||||||
|
--- @class ImGuiDemoWindowData
|
||||||
|
|
||||||
|
--- @return ImGuiDemoWindowData
|
||||||
|
--- @nodiscard
|
||||||
|
local function ImGuiDemoWindowData()
|
||||||
|
return {
|
||||||
|
ShowAppImageViewer = false,
|
||||||
|
ShowAppFullscreen = false,
|
||||||
|
|
||||||
|
ShowMetrics = false,
|
||||||
|
ShowStyleEditor = false,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @class ExampleImageViewerData
|
||||||
|
|
||||||
|
--- @return ExampleImageViewerData
|
||||||
|
--- @nodiscard
|
||||||
|
local function ExampleImageViewerData()
|
||||||
|
return {
|
||||||
|
ImageBgColor = IM_COL32(100, 100, 100, 255),
|
||||||
|
GridColor = IM_COL32(255, 255, 255, 100),
|
||||||
|
GridEnabled = true,
|
||||||
|
ViewReset = true,
|
||||||
|
ViewOffset = ImVec2(0, 0),
|
||||||
|
Zoom = 10.0,
|
||||||
|
ZoomMin = 1.0,
|
||||||
|
ZoomMax = 10000.0
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @param data ExampleImageViewerData
|
||||||
|
local function ExampleImageViewer_DrawOptions(data)
|
||||||
|
ImGui.SetNextItemShortcut(ImGuiKey.G, ImGuiInputFlags.Tooltip)
|
||||||
|
_, data.GridEnabled = ImGui.Checkbox("Grid", data.GridEnabled)
|
||||||
|
ImGui.SameLine()
|
||||||
|
ImGui.SetNextItemWidth(ImGui.GetFontSize() * 10.0)
|
||||||
|
local zoom_100 = data.Zoom * 100.0
|
||||||
|
local changed
|
||||||
|
zoom_100, changed = ImGui.DragFloat("##Zoom", zoom_100, 5.0, data.ZoomMin * 100.0, data.ZoomMax * 100.0, "%.0f%%", ImGuiSliderFlags.AlwaysClamp)
|
||||||
|
if changed then
|
||||||
|
data.Zoom = zoom_100 / 100.0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @param data ExampleImageViewerData
|
||||||
|
--- @param canvas_size ImVec2
|
||||||
|
--- @param image_tex_ref ImTextureRef
|
||||||
|
--- @param image_w int
|
||||||
|
--- @param image_h int
|
||||||
|
local function ExampleImageViewer_DrawCanvas(data, canvas_size, image_tex_ref, image_w, image_h)
|
||||||
|
local io = ImGui.GetIO()
|
||||||
|
local platform_io = ImGui.GetPlatformIO()
|
||||||
|
local draw_list = ImGui.GetWindowDrawList()
|
||||||
|
IM_ASSERT(canvas_size.x >= 0.0 and canvas_size.y >= 0.0)
|
||||||
|
|
||||||
|
ImGui.InvisibleButton("##Canvas", canvas_size)
|
||||||
|
local canvas_min = ImGui.GetItemRectMin()
|
||||||
|
local canvas_max = ImGui.GetItemRectMax()
|
||||||
|
|
||||||
|
if data.ViewReset then
|
||||||
|
data.ViewOffset = ImVec2((canvas_size.x * 0.5 / data.Zoom) - 0.5, (canvas_size.y * 0.5 / data.Zoom) - 0.5)
|
||||||
|
end
|
||||||
|
data.ViewReset = false
|
||||||
|
|
||||||
|
if ImGui.SetItemKeyOwner(ImGuiKey.MouseWheelY) then
|
||||||
|
if io.MouseWheel ~= 0.0 then
|
||||||
|
data.Zoom = IM_CLAMP(data.Zoom * (1.0 + io.MouseWheel * 0.10), data.ZoomMin, data.ZoomMax)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local zoom = data.Zoom
|
||||||
|
if ImGui.IsItemActive() and ImGui.IsMouseDragging(0) then
|
||||||
|
data.ViewOffset.x = data.ViewOffset.x - io.MouseDelta.x / zoom
|
||||||
|
data.ViewOffset.y = data.ViewOffset.y - io.MouseDelta.y / zoom
|
||||||
|
end
|
||||||
|
|
||||||
|
local image_min = ImVec2(); local image_max = ImVec2()
|
||||||
|
image_min.x = math.floor((canvas_min.x - (data.ViewOffset.x * zoom)) + (canvas_size.x * 0.5))
|
||||||
|
image_min.y = math.floor((canvas_min.y - (data.ViewOffset.y * zoom)) + (canvas_size.y * 0.5))
|
||||||
|
image_max.x = math.floor(image_min.x + image_w * zoom)
|
||||||
|
image_max.y = math.floor(image_min.y + image_h * zoom)
|
||||||
|
|
||||||
|
draw_list:AddRect(ImVec2(canvas_min.x - 1.0, canvas_min.y - 1.0), ImVec2(canvas_max.x + 1.0, canvas_max.y + 1.0), IM_COL32(255, 255, 255, 255))
|
||||||
|
draw_list:PushClipRect(canvas_min, canvas_max, true)
|
||||||
|
draw_list:AddRectFilled(image_min, image_max, data.ImageBgColor)
|
||||||
|
if platform_io.DrawCallback_SetSamplerNearest ~= nil then
|
||||||
|
draw_list:AddCallback(platform_io.DrawCallback_SetSamplerNearest)
|
||||||
|
end
|
||||||
|
draw_list:AddImage(image_tex_ref, image_min, image_max)
|
||||||
|
if platform_io.DrawCallback_SetSamplerLinear ~= nil then
|
||||||
|
draw_list:AddCallback(ImGui.GetPlatformIO().DrawCallback_SetSamplerLinear)
|
||||||
|
end
|
||||||
|
|
||||||
|
if data.GridEnabled and zoom > 6.0 then
|
||||||
|
local step = zoom
|
||||||
|
for px = math.floor((canvas_min.x - image_min.x) / step), math.floor((canvas_max.x - image_min.x) / step) do
|
||||||
|
draw_list:AddLineV(image_min.x + px * step, canvas_min.y, canvas_max.y, data.GridColor, 1.0)
|
||||||
|
end
|
||||||
|
for py = math.floor((canvas_min.y - image_min.y) / step), math.floor((canvas_max.y - image_min.y) / step) do
|
||||||
|
draw_list:AddLineH(canvas_min.x, canvas_max.x, image_min.y + py * step, data.GridColor, 1.0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
draw_list:PopClipRect()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ShowExampleMenuFile()
|
||||||
|
ImGui.MenuItem("(demo menu)", nil, false, false)
|
||||||
|
if ImGui.MenuItem("New") then end
|
||||||
|
if ImGui.MenuItem("Open", "Ctrl+O") then end
|
||||||
|
if ImGui.BeginMenu("Open Recent") then
|
||||||
|
ImGui.MenuItem("fish_hat.c")
|
||||||
|
ImGui.MenuItem("fish_hat.inl")
|
||||||
|
ImGui.MenuItem("fish_hat.h")
|
||||||
|
if ImGui.BeginMenu("More..") then
|
||||||
|
ImGui.MenuItem("Hello")
|
||||||
|
ImGui.MenuItem("Sailor")
|
||||||
|
if ImGui.BeginMenu("Recurse..") then
|
||||||
|
ShowExampleMenuFile()
|
||||||
|
ImGui.EndMenu()
|
||||||
|
end
|
||||||
|
ImGui.EndMenu()
|
||||||
|
end
|
||||||
|
ImGui.EndMenu()
|
||||||
|
end
|
||||||
|
if ImGui.MenuItem("Save", "Ctrl+S") then end
|
||||||
|
if ImGui.MenuItem("Save As..") then end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function DemoWindowMenuBar(demo_data)
|
||||||
|
if ImGui.BeginMenuBar() then
|
||||||
|
if ImGui.BeginMenu("Menu") then
|
||||||
|
ShowExampleMenuFile()
|
||||||
|
ImGui.EndMenu()
|
||||||
|
end
|
||||||
|
if ImGui.BeginMenu("Examples") then
|
||||||
|
ImGui.SeparatorText("Concepts")
|
||||||
|
_, demo_data.ShowAppFullscreen = ImGui.MenuItem("Fullscreen window", nil, demo_data.ShowAppFullscreen)
|
||||||
|
|
||||||
|
ImGui.EndMenu()
|
||||||
|
end
|
||||||
|
if ImGui.BeginMenu("Tools") then
|
||||||
|
|
||||||
|
local has_debug_tools = false
|
||||||
|
if not IMGUI_DISABLE_DEBUG_TOOLS then
|
||||||
|
has_debug_tools = true
|
||||||
|
end
|
||||||
|
|
||||||
|
_, demo_data.ShowMetrics = ImGui.MenuItem("Metrics/Debugger", nil, demo_data.ShowMetrics, has_debug_tools)
|
||||||
|
_, demo_data.ShowStyleEditor = ImGui.MenuItem("Style Editor", nil, demo_data.ShowStyleEditor)
|
||||||
|
|
||||||
|
ImGui.EndMenu()
|
||||||
|
end
|
||||||
|
|
||||||
|
ImGui.EndMenuBar()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local DemoWindowWidgetsBasic
|
||||||
|
do
|
||||||
|
|
||||||
|
local static = {}
|
||||||
|
|
||||||
|
local clicked = 0
|
||||||
|
local checked = true
|
||||||
|
local radio_v = 0
|
||||||
|
|
||||||
|
local col0 = ImVec4(0, 0, 0, 1)
|
||||||
|
local col1 = ImVec4(0, 0, 0, 1)
|
||||||
|
local col2 = ImVec4(0, 0, 0, 1)
|
||||||
|
|
||||||
|
local counter = 0
|
||||||
|
|
||||||
|
local str0 = {string.byte("Hello, World!", 1, 13)}
|
||||||
|
table.insert(str0, 0)
|
||||||
|
|
||||||
|
local str1 = {}
|
||||||
|
str1[1] = 0
|
||||||
|
|
||||||
|
local hint0 = {string.byte("enter text here", 1, 15)}
|
||||||
|
table.insert(hint0, 0)
|
||||||
|
|
||||||
|
local vec4a = { 0.10, 0.20, 0.30, 0.44 }
|
||||||
|
|
||||||
|
local Element = { Fire = 1, Earth = 2, Air = 3, Water = 4, COUNT = 5 }
|
||||||
|
local elems_names = { "Fire", "Earth", "Air", "Water" }
|
||||||
|
|
||||||
|
function DemoWindowWidgetsBasic()
|
||||||
|
if ImGui.TreeNode("Basic") then
|
||||||
|
ImGui.SeparatorText("General")
|
||||||
|
|
||||||
|
if ImGui.Button("Button") then
|
||||||
|
clicked = clicked + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if clicked % 2 ~= 0 then
|
||||||
|
ImGui.SameLine()
|
||||||
|
ImGui.Text("Thanks for clicking me!")
|
||||||
|
end
|
||||||
|
|
||||||
|
_, check = ImGui.Checkbox("checkbox", check)
|
||||||
|
|
||||||
|
_, radio_v = ImGui.RadioButton("radio a", radio_v, 0) ImGui.SameLine()
|
||||||
|
_, radio_v = ImGui.RadioButton("radio b", radio_v, 1) ImGui.SameLine()
|
||||||
|
_, radio_v = ImGui.RadioButton("radio c", radio_v, 2)
|
||||||
|
|
||||||
|
ImGui.AlignTextToFramePadding()
|
||||||
|
ImGui.TextLinkOpenURL("Hyperlink", "https://github.com/GrayWolf64/imgui-lua")
|
||||||
|
|
||||||
|
for i = 1, 7 do
|
||||||
|
if i > 1 then
|
||||||
|
ImGui.SameLine()
|
||||||
|
end
|
||||||
|
ImGui.PushID(i)
|
||||||
|
|
||||||
|
col0.x, col0.y, col0.z = ImGui.ColorConvertHSVtoRGB(i / 7.0, 0.6, 0.6)
|
||||||
|
col1.x, col1.y, col1.z = ImGui.ColorConvertHSVtoRGB(i / 7.0, 0.7, 0.7)
|
||||||
|
col2.x, col2.y, col2.z = ImGui.ColorConvertHSVtoRGB(i / 7.0, 0.8, 0.8)
|
||||||
|
ImGui.PushStyleColor(ImGuiCol.Button, col0)
|
||||||
|
ImGui.PushStyleColor(ImGuiCol.ButtonHovered, col1)
|
||||||
|
ImGui.PushStyleColor(ImGuiCol.ButtonActive, col2)
|
||||||
|
|
||||||
|
ImGui.Button("Click")
|
||||||
|
|
||||||
|
ImGui.PopStyleColor(3)
|
||||||
|
ImGui.PopID()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Use AlignTextToFramePadding() to align text baseline to the baseline of framed widgets elements
|
||||||
|
-- (otherwise a Text+SameLine+Button sequence will have the text a little too high by default!)
|
||||||
|
-- See 'Demo->Layout->Text Baseline Alignment' for details.
|
||||||
|
ImGui.AlignTextToFramePadding()
|
||||||
|
ImGui.Text("Hold to repeat:")
|
||||||
|
ImGui.SameLine()
|
||||||
|
|
||||||
|
-- Arrow buttons with Repeater
|
||||||
|
local spacing = ImGui.GetStyle().ItemInnerSpacing.x
|
||||||
|
ImGui.PushItemFlag(ImGuiItemFlags.ButtonRepeat, true)
|
||||||
|
if ImGui.ArrowButton("##left", ImGuiDir.Left) then counter = counter - 1 end
|
||||||
|
ImGui.SameLine(0.0, spacing)
|
||||||
|
if ImGui.ArrowButton("##right", ImGuiDir.Right) then counter = counter + 1 end
|
||||||
|
ImGui.PopItemFlag()
|
||||||
|
ImGui.SameLine()
|
||||||
|
ImGui.Text("%d", counter)
|
||||||
|
|
||||||
|
ImGui.Button("Tooltip")
|
||||||
|
ImGui.SetItemTooltip("I am a tooltip")
|
||||||
|
|
||||||
|
ImGui.LabelText("label", "Value")
|
||||||
|
|
||||||
|
ImGui.SeparatorText("Inputs")
|
||||||
|
|
||||||
|
do
|
||||||
|
ImGui.InputText("input text", str0, 128)
|
||||||
|
|
||||||
|
ImGui.InputTextWithHint("input text (w/ hint)", hint0, str1, 128)
|
||||||
|
|
||||||
|
if not static.i0 then static.i0 = 233 end
|
||||||
|
static.i0 = ImGui.InputInt("input int", static.i0)
|
||||||
|
|
||||||
|
if not static.f0 then static.f0 = 0.001 end
|
||||||
|
static.f0 = ImGui.InputFloat("input float", static.f0, 0.01, 1.0)
|
||||||
|
|
||||||
|
if not static.d0 then static.d0 = 999999.00000001 end
|
||||||
|
static.d0 = ImGui.InputDouble("input double", static.d0, 0.01, 1.0, "%.8f")
|
||||||
|
-- TODO:
|
||||||
|
|
||||||
|
ImGui.InputFloat3("input float3", vec4a)
|
||||||
|
end
|
||||||
|
|
||||||
|
ImGui.SeparatorText("Drags")
|
||||||
|
|
||||||
|
do
|
||||||
|
if not static.i1 then static.i1 = 50 end
|
||||||
|
if not static.i2 then static.i2 = 42 end
|
||||||
|
if not static.i3 then static.i3 = 128 end
|
||||||
|
static.i1 = ImGui.DragInt("drag int", static.i1, 1)
|
||||||
|
static.i2 = ImGui.DragInt("drag int 0..100", static.i2, 1, 0, 100, "%d%%", ImGuiSliderFlags.AlwaysClamp)
|
||||||
|
static.i3 = ImGui.DragInt("drag int wrap 100..200", static.i3, 1, 100, 200, "%d", ImGuiSliderFlags.WrapAround)
|
||||||
|
|
||||||
|
if not static.f1 then static.f1 = 1.00 end
|
||||||
|
if not static.f2 then static.f2 = 0.0067 end
|
||||||
|
static.f1 = ImGui.DragFloat("drag float", static.f1, 0.005)
|
||||||
|
static.f2 = ImGui.DragFloat("drag small float", static.f2, 0.0001, 0.0, 0.0, "%.06f ns")
|
||||||
|
end
|
||||||
|
|
||||||
|
ImGui.SeparatorText("Sliders")
|
||||||
|
|
||||||
|
do
|
||||||
|
if not static.f01 then static.f01 = 0.123 end
|
||||||
|
if not static.f02 then static.f02 = 0.0 end
|
||||||
|
static.f01 = ImGui.SliderFloat("slider float", static.f01, 0.0, 1.0, "ratio = %.3f")
|
||||||
|
static.f02 = ImGui.SliderFloat("slider float (log)", static.f02, -10.0, 10.0, "%.4f", ImGuiSliderFlags.Logarithmic)
|
||||||
|
|
||||||
|
if not static.angle then static.angle = 0.0 end
|
||||||
|
static.angle = ImGui.SliderAngle("slider angle", static.angle)
|
||||||
|
|
||||||
|
if not static.elem then static.elem = Element.Fire end
|
||||||
|
local elem_name = (static.elem >= 1 and static.elem < Element.COUNT) and elems_names[static.elem] or "Unknown"
|
||||||
|
static.elem = ImGui.SliderInt("slider enum", static.elem, 1, Element.COUNT - 1, elem_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
ImGui.TreePop()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local function DemoWindowWidgetsBullets()
|
||||||
|
if ImGui.TreeNode("Bullets") then
|
||||||
|
ImGui.BulletText("Bullet point 1")
|
||||||
|
ImGui.BulletText("Bullet point 2\nOn multiple lines")
|
||||||
|
if ImGui.TreeNode("Tree node") then
|
||||||
|
ImGui.BulletText("Another bullet point")
|
||||||
|
ImGui.TreePop()
|
||||||
|
end
|
||||||
|
ImGui.Bullet() ImGui.Text("Bullet point 3 (two calls)")
|
||||||
|
ImGui.Bullet() ImGui.SmallButton("Button")
|
||||||
|
ImGui.TreePop()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local DemoWindowWidgetsColorAndPickers
|
||||||
|
do
|
||||||
|
|
||||||
|
local color = {114.0 / 255.0, 144.0 / 255.0, 154.0 / 255.0, 200.0 / 255.0}
|
||||||
|
local base_flags = ImGuiColorEditFlags.None
|
||||||
|
|
||||||
|
local ref_color = false
|
||||||
|
local ref_color_v = {1.0, 0.0, 1.0, 0.5}
|
||||||
|
local picker_mode = 0
|
||||||
|
local display_mode = 0
|
||||||
|
local color_picker_flags = ImGuiColorEditFlags.AlphaBar
|
||||||
|
local picker_mode_names = {"Auto/Current", "ImGuiColorEditFlags.PickerHueBar", "ImGuiColorEditFlags.PickerHueWheel"}
|
||||||
|
local display_mode_names = {"Auto/Current", "ImGuiColorEditFlags.NoInputs", "ImGuiColorEditFlags.DisplayRGB", "ImGuiColorEditFlags.DisplayHSV", "ImGuiColorEditFlags.DisplayHex"}
|
||||||
|
|
||||||
|
function DemoWindowWidgetsColorAndPickers()
|
||||||
|
if ImGui.TreeNode("Color/Picker Widgets") then
|
||||||
|
ImGui.SeparatorText("Options")
|
||||||
|
|
||||||
|
_, base_flags = ImGui.CheckboxFlags("ImGuiColorEditFlags.NoAlpha", base_flags, ImGuiColorEditFlags.NoAlpha)
|
||||||
|
_, base_flags = ImGui.CheckboxFlags("ImGuiColorEditFlags.AlphaOpaque", base_flags, ImGuiColorEditFlags.AlphaOpaque)
|
||||||
|
_, base_flags = ImGui.CheckboxFlags("ImGuiColorEditFlags.AlphaNoBg", base_flags, ImGuiColorEditFlags.AlphaNoBg)
|
||||||
|
_, base_flags = ImGui.CheckboxFlags("ImGuiColorEditFlags.AlphaPreviewHalf", base_flags, ImGuiColorEditFlags.AlphaPreviewHalf)
|
||||||
|
_, base_flags = ImGui.CheckboxFlags("ImGuiColorEditFlags.NoOptions", base_flags, ImGuiColorEditFlags.NoOptions)
|
||||||
|
_, base_flags = ImGui.CheckboxFlags("ImGuiColorEditFlags.NoDragDrop", base_flags, ImGuiColorEditFlags.NoDragDrop)
|
||||||
|
_, base_flags = ImGui.CheckboxFlags("ImGuiColorEditFlags.NoColorMarkers", base_flags, ImGuiColorEditFlags.NoColorMarkers)
|
||||||
|
_, base_flags = ImGui.CheckboxFlags("ImGuiColorEditFlags.HDR", base_flags, ImGuiColorEditFlags.HDR)
|
||||||
|
|
||||||
|
ImGui.SeparatorText("Inline color editor")
|
||||||
|
ImGui.Text("Color widget:")
|
||||||
|
ImGui.ColorEdit3("MyColor##1", color, base_flags)
|
||||||
|
|
||||||
|
ImGui.Text("Color widget HSV with Alpha:")
|
||||||
|
ImGui.ColorEdit4("MyColor##2", color, bit32.bor(ImGuiColorEditFlags.DisplayHSV, base_flags))
|
||||||
|
|
||||||
|
ImGui.Text("Color widget with Float Display:")
|
||||||
|
ImGui.ColorEdit4("MyColor##2f", color, bit32.bor(ImGuiColorEditFlags.Float, base_flags))
|
||||||
|
|
||||||
|
ImGui.Text("Color button with Picker:")
|
||||||
|
ImGui.ColorEdit4("MyColor##3", color, bit32.bor(ImGuiColorEditFlags.NoInputs, ImGuiColorEditFlags.NoLabel, base_flags))
|
||||||
|
|
||||||
|
-- TODO:
|
||||||
|
|
||||||
|
ImGui.SeparatorText("Color picker")
|
||||||
|
|
||||||
|
ImGui.PushID("Color picker")
|
||||||
|
_, color_picker_flags = ImGui.CheckboxFlags("ImGuiColorEditFlags.NoAlpha", color_picker_flags, ImGuiColorEditFlags.NoAlpha)
|
||||||
|
_, color_picker_flags = ImGui.CheckboxFlags("ImGuiColorEditFlags.AlphaBar", color_picker_flags, ImGuiColorEditFlags.AlphaBar)
|
||||||
|
_, color_picker_flags = ImGui.CheckboxFlags("ImGuiColorEditFlags.NoSidePreview", color_picker_flags, ImGuiColorEditFlags.NoSidePreview)
|
||||||
|
|
||||||
|
if bit32.band(color_picker_flags, ImGuiColorEditFlags.NoSidePreview) ~= 0 then
|
||||||
|
ImGui.SameLine()
|
||||||
|
_, ref_color = ImGui.Checkbox("With Ref Color", ref_color)
|
||||||
|
if ref_color then
|
||||||
|
ImGui.SameLine()
|
||||||
|
ImGui.ColorEdit4("##RefColor", ref_color_v, bit32.bor(ImGuiColorEditFlags.NoInputs, base_flags))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
_, color_picker_flags = ImGui.CheckboxFlags("ImGuiColorEditFlags.PickerNoRotate", color_picker_flags, ImGuiColorEditFlags.PickerNoRotate)
|
||||||
|
|
||||||
|
if ImGui.BeginCombo("Picker Mode", picker_mode_names[picker_mode + 1], ImGuiComboFlags.None) then
|
||||||
|
for mode_idx, mode_name in ipairs(picker_mode_names) do
|
||||||
|
local pressed = ImGui.Selectable(mode_name, mode_idx == picker_mode + 1)
|
||||||
|
if pressed then
|
||||||
|
picker_mode = mode_idx - 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
ImGui.EndCombo()
|
||||||
|
end
|
||||||
|
|
||||||
|
if ImGui.BeginCombo("Display Mode", display_mode_names[display_mode + 1], ImGuiComboFlags.None) then
|
||||||
|
for mode_idx, mode_name in ipairs(display_mode_names) do
|
||||||
|
local pressed = ImGui.Selectable(mode_name, mode_idx == display_mode + 1)
|
||||||
|
if pressed then
|
||||||
|
display_mode = mode_idx - 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
ImGui.EndCombo()
|
||||||
|
end
|
||||||
|
|
||||||
|
local flags = bit32.bor(base_flags, color_picker_flags)
|
||||||
|
if picker_mode == 1 then flags = bit32.bor(flags, ImGuiColorEditFlags.PickerHueBar) end
|
||||||
|
if picker_mode == 2 then flags = bit32.bor(flags, ImGuiColorEditFlags.PickerHueWheel) end
|
||||||
|
if display_mode == 1 then flags = bit32.bor(flags, ImGuiColorEditFlags.NoInputs) end -- Disable all RGB/HSV/Hex displays
|
||||||
|
if display_mode == 2 then flags = bit32.bor(flags, ImGuiColorEditFlags.DisplayRGB) end -- Override display mode
|
||||||
|
if display_mode == 3 then flags = bit32.bor(flags, ImGuiColorEditFlags.DisplayHSV) end
|
||||||
|
if display_mode == 4 then flags = bit32.bor(flags, ImGuiColorEditFlags.DisplayHex) end
|
||||||
|
|
||||||
|
ImGui.ColorPicker4("MyColor##4", color, flags, ref_color and ref_color_v or nil)
|
||||||
|
|
||||||
|
ImGui.TreePop()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local DemoWindowWidgetsImages do
|
||||||
|
|
||||||
|
local pressed_count = 0
|
||||||
|
|
||||||
|
local image_viewer = ExampleImageViewerData()
|
||||||
|
|
||||||
|
function DemoWindowWidgetsImages()
|
||||||
|
if ImGui.TreeNode("Images") then
|
||||||
|
ImGui.TextWrapped(
|
||||||
|
"Below we are displaying the font texture (which is the only texture we have access to in this demo). " ..
|
||||||
|
"Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. " ..
|
||||||
|
"Hover the texture for a zoomed view!"
|
||||||
|
)
|
||||||
|
|
||||||
|
-- Grab the current texture identifier used by the font atlas
|
||||||
|
local io = ImGui.GetIO()
|
||||||
|
|
||||||
|
local atlas = io.Fonts
|
||||||
|
local my_tex_id = atlas.TexRef
|
||||||
|
local my_tex_w = atlas.TexData.Width
|
||||||
|
local my_tex_h = atlas.TexData.Height
|
||||||
|
ImGui.Text("%.0fx%.0f", my_tex_w, my_tex_h)
|
||||||
|
|
||||||
|
ImGui.SeparatorText("Image()/ImageWithBg() function")
|
||||||
|
local uv_min = ImVec2(0.0, 0.0)
|
||||||
|
local uv_max = ImVec2(1.0, 1.0)
|
||||||
|
ImGui.PushStyleVar(ImGuiStyleVar.ImageBorderSize, IM_MAX(1.0, ImGui.GetStyle().ImageBorderSize))
|
||||||
|
ImGui.ImageWithBg(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, ImVec4(0.0, 0.0, 0.0, 1.0))
|
||||||
|
ImGui.PopStyleVar()
|
||||||
|
|
||||||
|
-- Fancy widget
|
||||||
|
ImGui.SeparatorText("Interactive Image Viewer")
|
||||||
|
|
||||||
|
local canvas_size = ImVec2(ImGui.GetContentRegionAvail().x, my_tex_h * 2.0)
|
||||||
|
ExampleImageViewer_DrawOptions(image_viewer)
|
||||||
|
ExampleImageViewer_DrawCanvas(image_viewer, canvas_size, my_tex_id, my_tex_w, my_tex_h)
|
||||||
|
|
||||||
|
ImGui.SeparatorText("Textured Buttons")
|
||||||
|
|
||||||
|
ImGui.TextWrapped("And now some textured buttons..")
|
||||||
|
for i = 1, 8 do
|
||||||
|
-- UV coordinates are often (0.0f, 0.0f) and (1.0f, 1.0f) to display an entire textures.
|
||||||
|
-- Here are trying to display only a 32x32 pixels area of the texture, hence the UV computation.
|
||||||
|
ImGui.PushID(i)
|
||||||
|
if i > 1 then
|
||||||
|
ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, ImVec2(i, i))
|
||||||
|
end
|
||||||
|
|
||||||
|
local size = ImVec2(32.0, 32.0) -- Size of the image we want to make visible
|
||||||
|
local uv0 = ImVec2(0.0, 0.0) -- UV coordinates for lower-left
|
||||||
|
local uv1 = ImVec2(32.0 / my_tex_w, 32.0 / my_tex_h) -- UV coordinates for (32,32) in our texture
|
||||||
|
local bg_col = ImVec4(0.0, 0.0, 0.0, 1.0) -- Black background
|
||||||
|
local tint_col = ImVec4(1.0, 1.0, 1.0, 1.0) -- No tint
|
||||||
|
|
||||||
|
if ImGui.ImageButton("", my_tex_id, size, uv0, uv1, bg_col, tint_col) then
|
||||||
|
pressed_count = pressed_count + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if i > 1 then
|
||||||
|
ImGui.PopStyleVar()
|
||||||
|
end
|
||||||
|
|
||||||
|
ImGui.PopID()
|
||||||
|
ImGui.SameLine()
|
||||||
|
end
|
||||||
|
|
||||||
|
ImGui.NewLine()
|
||||||
|
ImGui.Text("Pressed %d times.", pressed_count)
|
||||||
|
|
||||||
|
ImGui.TreePop()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local function DemoWindowWidgetsLiveEdit()
|
||||||
|
-- TODO:
|
||||||
|
end
|
||||||
|
|
||||||
|
local DemoWindowWidgetsPlotting
|
||||||
|
do
|
||||||
|
|
||||||
|
local animate = true
|
||||||
|
local arr = { 0.6, 0.1, 1.0, 0.5, 0.92, 0.1, 0.2 }
|
||||||
|
|
||||||
|
local values_sz = 90
|
||||||
|
local values = {} for i = 1, values_sz do values[i] = 0 end
|
||||||
|
local values_offset = 0
|
||||||
|
local refresh_time = 0.0
|
||||||
|
local phase = 0.0
|
||||||
|
|
||||||
|
function DemoWindowWidgetsPlotting()
|
||||||
|
if ImGui.TreeNode("Plotting") then
|
||||||
|
_, animate = ImGui.Checkbox("Animate", animate)
|
||||||
|
|
||||||
|
-- Plot as lines and plot as histogram
|
||||||
|
ImGui.PlotLines("Frame Times", arr, nil, #arr)
|
||||||
|
ImGui.PlotHistogram("Histogram", arr, nil, #arr, 0, nil, 0.0, 1.0, ImVec2(0, 80.0))
|
||||||
|
|
||||||
|
if not animate or refresh_time == 0.0 then
|
||||||
|
refresh_time = ImGui.GetTime()
|
||||||
|
end
|
||||||
|
while refresh_time < ImGui.GetTime() do -- Create data at fixed 60 Hz rate for the demo
|
||||||
|
values[values_offset + 1] = math.cos(phase)
|
||||||
|
values_offset = (values_offset + 1) % values_sz
|
||||||
|
phase = phase + 0.10 * values_offset
|
||||||
|
refresh_time = refresh_time + 1.0 / 60.0
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Plots can display overlay texts
|
||||||
|
-- (in this example, we will display an average value)
|
||||||
|
do
|
||||||
|
local average = 0.0
|
||||||
|
for i = 1, values_sz do
|
||||||
|
average = average + values[i]
|
||||||
|
end
|
||||||
|
average = average / values_sz
|
||||||
|
local overlay = string.format("avg %f", average)
|
||||||
|
ImGui.PlotLines("Lines", values, nil, values_sz, values_offset, overlay, -1.0, 1.0, ImVec2(0, 80.0))
|
||||||
|
end
|
||||||
|
|
||||||
|
ImGui.TreePop()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local DemoWindowWidgetsProgressBars do
|
||||||
|
|
||||||
|
local progress_accum = 0.0
|
||||||
|
local progress_dir = 1.0
|
||||||
|
|
||||||
|
function DemoWindowWidgetsProgressBars()
|
||||||
|
if ImGui.TreeNode("Progress Bars") then
|
||||||
|
-- Animate a simple progress bar
|
||||||
|
progress_accum = progress_accum + progress_dir * 0.4 * ImGui.GetIO().DeltaTime
|
||||||
|
if progress_accum >= 1.1 then
|
||||||
|
progress_accum = 1.1
|
||||||
|
progress_dir = progress_dir * -1.0
|
||||||
|
end
|
||||||
|
|
||||||
|
if progress_accum <= -0.1 then
|
||||||
|
progress_accum = -0.1
|
||||||
|
progress_dir = progress_dir * -1.0
|
||||||
|
end
|
||||||
|
|
||||||
|
local progress = IM_CLAMP(progress_accum, 0.0, 1.0)
|
||||||
|
|
||||||
|
-- Typically we would use ImVec2(-1.0,0.0) or ImVec2(-math.huge,0.0) to use all available width,
|
||||||
|
-- or ImVec2(width,0.0) for a specified width. ImVec2(0.0,0.0) uses ItemWidth
|
||||||
|
ImGui.ProgressBar(progress, ImVec2(0.0, 0.0))
|
||||||
|
ImGui.SameLine(0.0, ImGui.GetStyle().ItemInnerSpacing.x)
|
||||||
|
ImGui.Text("Progress Bar")
|
||||||
|
|
||||||
|
local buf = string.format("%d/%d", math.floor(progress * 1753), 1753)
|
||||||
|
ImGui.ProgressBar(progress, ImVec2(0.0, 0.0), buf)
|
||||||
|
|
||||||
|
-- Pass an animated negative value, e.g. -1.0 * ImGui.GetTime() is the recommended value
|
||||||
|
-- Adjust the factor if you want to adjust the animation speed
|
||||||
|
ImGui.ProgressBar(-1.0 * ImGui.GetTime(), ImVec2(0.0, 0.0), "Searching..")
|
||||||
|
ImGui.SameLine(0.0, ImGui.GetStyle().ItemInnerSpacing.x)
|
||||||
|
ImGui.Text("Indeterminate")
|
||||||
|
|
||||||
|
ImGui.TreePop()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local DemoWindowWidgetsVerticalSliders do
|
||||||
|
|
||||||
|
local int_value = 0
|
||||||
|
local values = { 0.0, 0.60, 0.35, 0.9, 0.70, 0.20, 0.0 }
|
||||||
|
local values2 = { 0.20, 0.80, 0.40, 0.25 }
|
||||||
|
|
||||||
|
local col0 = ImVec4(0, 0, 0, 1)
|
||||||
|
local col1 = ImVec4(0, 0, 0, 1)
|
||||||
|
local col2 = ImVec4(0, 0, 0, 1)
|
||||||
|
local col3 = ImVec4(0, 0, 0, 1)
|
||||||
|
|
||||||
|
function DemoWindowWidgetsVerticalSliders()
|
||||||
|
if ImGui.TreeNode("Vertical Sliders") then
|
||||||
|
local spacing = 4
|
||||||
|
ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, ImVec2(spacing, spacing))
|
||||||
|
|
||||||
|
int_value = ImGui.VSliderInt("##int", ImVec2(18, 160), int_value, 0, 5)
|
||||||
|
ImGui.SameLine()
|
||||||
|
|
||||||
|
ImGui.PushID("set1")
|
||||||
|
for i = 1, 7 do
|
||||||
|
if i > 1 then ImGui.SameLine() end
|
||||||
|
ImGui.PushID(i)
|
||||||
|
local hue = (i - 1) / 7.0
|
||||||
|
col0.x, col0.y, col0.z = ImGui.ColorConvertHSVtoRGB(hue, 0.5, 0.5)
|
||||||
|
col1.x, col1.y, col1.z = ImGui.ColorConvertHSVtoRGB(hue, 0.6, 0.5)
|
||||||
|
col2.x, col2.y, col2.z = ImGui.ColorConvertHSVtoRGB(hue, 0.7, 0.5)
|
||||||
|
col3.x, col3.y, col3.z = ImGui.ColorConvertHSVtoRGB(hue, 0.9, 0.9)
|
||||||
|
ImGui.PushStyleColor(ImGuiCol.FrameBg, col0)
|
||||||
|
ImGui.PushStyleColor(ImGuiCol.FrameBgHovered, col1)
|
||||||
|
ImGui.PushStyleColor(ImGuiCol.FrameBgActive, col2)
|
||||||
|
ImGui.PushStyleColor(ImGuiCol.SliderGrab, col3)
|
||||||
|
values[i] = ImGui.VSliderFloat("##v", ImVec2(18, 160), values[i], 0.0, 1.0, "")
|
||||||
|
if ImGui.IsItemActive() or ImGui.IsItemHovered() then
|
||||||
|
ImGui.SetTooltip("%.3f", values[i])
|
||||||
|
end
|
||||||
|
ImGui.PopStyleColor(4)
|
||||||
|
ImGui.PopID()
|
||||||
|
end
|
||||||
|
ImGui.PopID()
|
||||||
|
|
||||||
|
ImGui.SameLine()
|
||||||
|
ImGui.PushID("set2")
|
||||||
|
local rows = 3
|
||||||
|
local small_slider_size = ImVec2(18, math.floor((160.0 - (rows - 1) * spacing) / rows))
|
||||||
|
for nx = 1, 4 do
|
||||||
|
if nx > 1 then ImGui.SameLine() end
|
||||||
|
ImGui.BeginGroup()
|
||||||
|
for ny = 1, rows do
|
||||||
|
ImGui.PushID((nx - 1) * rows + ny)
|
||||||
|
values2[nx] = ImGui.VSliderFloat("##v", small_slider_size, values2[nx], 0.0, 1.0, "")
|
||||||
|
if ImGui.IsItemActive() or ImGui.IsItemHovered() then
|
||||||
|
ImGui.SetTooltip("%.3f", values2[nx])
|
||||||
|
end
|
||||||
|
ImGui.PopID()
|
||||||
|
end
|
||||||
|
ImGui.EndGroup()
|
||||||
|
end
|
||||||
|
ImGui.PopID()
|
||||||
|
|
||||||
|
ImGui.SameLine()
|
||||||
|
ImGui.PushID("set3")
|
||||||
|
for i = 1, 4 do
|
||||||
|
if i > 1 then ImGui.SameLine() end
|
||||||
|
ImGui.PushID(i)
|
||||||
|
ImGui.PushStyleVar(ImGuiStyleVar.GrabMinSize, 40)
|
||||||
|
values[i] = ImGui.VSliderFloat("##v", ImVec2(40, 160), values[i], 0.0, 1.0, "%.2f\nsec")
|
||||||
|
ImGui.PopStyleVar()
|
||||||
|
ImGui.PopID()
|
||||||
|
end
|
||||||
|
ImGui.PopID()
|
||||||
|
|
||||||
|
ImGui.PopStyleVar()
|
||||||
|
|
||||||
|
ImGui.TreePop()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local function DemoWindowWidgets()
|
||||||
|
if not ImGui.CollapsingHeader("Widgets") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
DemoWindowWidgetsBasic()
|
||||||
|
DemoWindowWidgetsBullets()
|
||||||
|
DemoWindowWidgetsColorAndPickers()
|
||||||
|
DemoWindowWidgetsImages()
|
||||||
|
DemoWindowWidgetsLiveEdit()
|
||||||
|
DemoWindowWidgetsPlotting()
|
||||||
|
DemoWindowWidgetsProgressBars()
|
||||||
|
DemoWindowWidgetsVerticalSliders()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function DemoWindowLayout()
|
||||||
|
if not ImGui.CollapsingHeader("Layout & Scrolling") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local function DemoWindowPopups()
|
||||||
|
if not ImGui.CollapsingHeader("Popups & Modal windows") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local function DemoWindowTables()
|
||||||
|
if not ImGui.CollapsingHeader("Tables & Columns") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local function DemoWindowInputs()
|
||||||
|
if not ImGui.CollapsingHeader("Inputs & Focus") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
|
||||||
|
local static = {}
|
||||||
|
|
||||||
|
local style_idx = -1
|
||||||
|
local style_names = { "Dark", "Light", "Classic" }
|
||||||
|
|
||||||
|
--- @param label string
|
||||||
|
function ImGui.ShowStyleSelector(label)
|
||||||
|
local ret = false
|
||||||
|
if ImGui.BeginCombo(label, (style_idx >= 1 and style_idx <= #style_names) and style_names[style_idx] or "") then
|
||||||
|
for n = 1, #style_names do
|
||||||
|
if ImGui.Selectable(style_names[n], style_idx == n, ImGuiSelectableFlags.SelectOnNav) then
|
||||||
|
style_idx = n
|
||||||
|
ret = true
|
||||||
|
|
||||||
|
if style_idx == 1 then ImGui.StyleColorsDark() end
|
||||||
|
if style_idx == 2 then ImGui.StyleColorsLight() end
|
||||||
|
if style_idx == 3 then ImGui.StyleColorsClassic() end
|
||||||
|
|
||||||
|
elseif style_idx == n then
|
||||||
|
ImGui.SetItemDefaultFocus()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
ImGui.EndCombo()
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @param label string
|
||||||
|
function ImGui.ShowFontSelector(label)
|
||||||
|
local io = ImGui.GetIO()
|
||||||
|
local font_current = ImGui.GetFont()
|
||||||
|
if ImGui.BeginCombo(label, font_current:GetDebugName()) then
|
||||||
|
for _, font in io.Fonts.Fonts:iter() do
|
||||||
|
ImGui.PushID(tostring(font):match("0x%x+")) -- (void*)font
|
||||||
|
if ImGui.Selectable(font:GetDebugName(), font == font_current, ImGuiSelectableFlags.SelectOnNav) then
|
||||||
|
io.FontDefault = font
|
||||||
|
end
|
||||||
|
if font == font_current then
|
||||||
|
ImGui.SetItemDefaultFocus()
|
||||||
|
end
|
||||||
|
ImGui.PopID()
|
||||||
|
end
|
||||||
|
ImGui.EndCombo()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @param ref ImGuiStyle?
|
||||||
|
function ImGui.ShowStyleEditor(ref)
|
||||||
|
local style = ImGui.GetStyle()
|
||||||
|
|
||||||
|
local default_border_size = ImTrunc(style._MainScale)
|
||||||
|
local max_border_size = ImMax(default_border_size, 2.0)
|
||||||
|
|
||||||
|
ImGui.PushItemWidth(ImGui.GetWindowWidth() * 0.50)
|
||||||
|
|
||||||
|
ImGui.SeparatorText("General")
|
||||||
|
do
|
||||||
|
if ImGui.ShowStyleSelector("Colors##Selector") then
|
||||||
|
-- TODO:
|
||||||
|
end
|
||||||
|
ImGui.ShowFontSelector("Fonts##Selector")
|
||||||
|
|
||||||
|
local ret0
|
||||||
|
style.FontSizeBase, ret0 = ImGui.DragFloat("FontSizeBase", style.FontSizeBase, 0.20, 5.0, 100.0, "%.0f")
|
||||||
|
if ret0 then
|
||||||
|
style._NextFrameFontSizeBase = style.FontSizeBase -- FIXME: Temporary hack until we finish remaining work.
|
||||||
|
end
|
||||||
|
ImGui.SameLine(0.0, 0.0); ImGui.Text(" (out %.2f)", ImGui.GetFontSize())
|
||||||
|
|
||||||
|
style.FontScaleMain = ImGui.DragFloat("FontScaleMain", style.FontScaleMain, 0.02, 0.5, 4.0)
|
||||||
|
|
||||||
|
ImGui.BeginDisabled(ImGui.GetIO().ConfigDpiScaleFonts)
|
||||||
|
style.FontScaleDpi = ImGui.DragFloat("FontScaleDpi", style.FontScaleDpi, 0.02, 0.5, 4.0)
|
||||||
|
ImGui.SetItemTooltip("When io.ConfigDpiScaleFonts is set, this value is automatically overwritten.")
|
||||||
|
ImGui.EndDisabled()
|
||||||
|
|
||||||
|
local ret1
|
||||||
|
style.FrameRounding, ret1 = ImGui.SliderFloat("FrameRounding", style.FrameRounding, 0.0, 12.0, "%.0f")
|
||||||
|
if ret1 then
|
||||||
|
style.GrabRounding = style.FrameRounding -- Make GrabRounding always the same value as FrameRounding
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local border = (style.WindowBorderSize > 0.0)
|
||||||
|
local pressed
|
||||||
|
pressed, border = ImGui.Checkbox("WindowBorder", border)
|
||||||
|
if pressed then style.WindowBorderSize = (border and default_border_size or 0.0) end
|
||||||
|
end
|
||||||
|
ImGui.SameLine()
|
||||||
|
do
|
||||||
|
local border = (style.FrameBorderSize > 0.0)
|
||||||
|
local pressed
|
||||||
|
pressed, border = ImGui.Checkbox("FrameBorder", border)
|
||||||
|
if pressed then style.FrameBorderSize = (border and default_border_size or 0.0) end
|
||||||
|
end
|
||||||
|
ImGui.SameLine()
|
||||||
|
do
|
||||||
|
local border = (style.PopupBorderSize > 0.0)
|
||||||
|
local pressed
|
||||||
|
pressed, border = ImGui.Checkbox("PopupBorder", border)
|
||||||
|
if pressed then style.PopupBorderSize = (border and default_border_size or 0.0) end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ImGui.SeparatorText("Details")
|
||||||
|
-- TODO:
|
||||||
|
|
||||||
|
ImGui.PopItemWidth()
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ShowExampleAppImageViewer()
|
||||||
|
-- TODO:
|
||||||
|
end
|
||||||
|
|
||||||
|
local ShowExampleAppFullscreen do
|
||||||
|
|
||||||
|
local use_work_area = true
|
||||||
|
local flags = bit32.bor(ImGuiWindowFlags.NoDecoration, ImGuiWindowFlags.NoMove, ImGuiWindowFlags.NoSavedSettings)
|
||||||
|
|
||||||
|
function ShowExampleAppFullscreen(open)
|
||||||
|
local viewport = ImGui.GetMainViewport()
|
||||||
|
ImGui.SetNextWindowPos(use_work_area and viewport.WorkPos or viewport.Pos)
|
||||||
|
ImGui.SetNextWindowSize(use_work_area and viewport.WorkSize or viewport.Size)
|
||||||
|
|
||||||
|
local ret
|
||||||
|
open, ret = ImGui.Begin("Example: Fullscreen window", open, flags)
|
||||||
|
if ret then
|
||||||
|
_, use_work_area = ImGui.Checkbox("Use work area instead of main area", use_work_area)
|
||||||
|
ImGui.SameLine()
|
||||||
|
|
||||||
|
_, flags = ImGui.CheckboxFlags("ImGuiWindowFlags.NoBackground", flags, ImGuiWindowFlags.NoBackground)
|
||||||
|
_, flags = ImGui.CheckboxFlags("ImGuiWindowFlags.NoDecoration", flags, ImGuiWindowFlags.NoDecoration)
|
||||||
|
ImGui.Indent()
|
||||||
|
_, flags = ImGui.CheckboxFlags("ImGuiWindowFlags.NoTitleBar", flags, ImGuiWindowFlags.NoTitleBar)
|
||||||
|
_, flags = ImGui.CheckboxFlags("ImGuiWindowFlags.NoCollapse", flags, ImGuiWindowFlags.NoCollapse)
|
||||||
|
_, flags = ImGui.CheckboxFlags("ImGuiWindowFlags.NoScrollbar", flags, ImGuiWindowFlags.NoScrollbar)
|
||||||
|
ImGui.Unindent()
|
||||||
|
|
||||||
|
if open and ImGui.Button("Close this window") then
|
||||||
|
open = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
ImGui.End()
|
||||||
|
|
||||||
|
return open
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
|
||||||
|
local demo_data = ImGuiDemoWindowData()
|
||||||
|
|
||||||
|
local no_titlebar = false
|
||||||
|
local no_scrollbar = false
|
||||||
|
local no_menu = false
|
||||||
|
local no_move = false
|
||||||
|
local no_resize = false
|
||||||
|
local no_collapse = false
|
||||||
|
local no_close = false
|
||||||
|
local no_nav = false
|
||||||
|
local no_background = false
|
||||||
|
local no_bring_to_front = false
|
||||||
|
local no_docking = false
|
||||||
|
local unsaved_document = false
|
||||||
|
|
||||||
|
function ImGui.ShowDemoWindow(open)
|
||||||
|
if demo_data.ShowAppFullscreen then demo_data.ShowAppFullscreen = ShowExampleAppFullscreen(demo_data.ShowAppFullscreen) end
|
||||||
|
|
||||||
|
if demo_data.ShowMetrics then
|
||||||
|
demo_data.ShowMetrics = ImGui.ShowMetricsWindow(demo_data.ShowMetrics)
|
||||||
|
end
|
||||||
|
if demo_data.ShowStyleEditor then
|
||||||
|
demo_data.ShowStyleEditor = ImGui.Begin("ImGui Sincerely Style Editor", demo_data.ShowStyleEditor)
|
||||||
|
ImGui.ShowStyleEditor()
|
||||||
|
ImGui.End()
|
||||||
|
end
|
||||||
|
|
||||||
|
local window_flags = 0
|
||||||
|
if no_titlebar then window_flags = bit32.bor(window_flags, ImGuiWindowFlags.NoTitleBar) end
|
||||||
|
if no_scrollbar then window_flags = bit32.bor(window_flags, ImGuiWindowFlags.NoScrollbar) end
|
||||||
|
if not no_menu then window_flags = bit32.bor(window_flags, ImGuiWindowFlags.MenuBar) end
|
||||||
|
if no_move then window_flags = bit32.bor(window_flags, ImGuiWindowFlags.NoMove) end
|
||||||
|
if no_resize then window_flags = bit32.bor(window_flags, ImGuiWindowFlags.NoResize) end
|
||||||
|
if no_collapse then window_flags = bit32.bor(window_flags, ImGuiWindowFlags.NoCollapse) end
|
||||||
|
if no_nav then window_flags = bit32.bor(window_flags, ImGuiWindowFlags.NoNav) end
|
||||||
|
if no_background then window_flags = bit32.bor(window_flags, ImGuiWindowFlags.NoBackground) end
|
||||||
|
if no_bring_to_front then window_flags = bit32.bor(window_flags, ImGuiWindowFlags.NoBringToFrontOnFocus) end
|
||||||
|
if no_docking then window_flags = bit32.bor(window_flags, ImGuiWindowFlags.NoDocking) end
|
||||||
|
if unsaved_document then window_flags = bit32.bor(window_flags, ImGuiWindowFlags.UnsavedDocument) end
|
||||||
|
if no_close then open = nil end
|
||||||
|
|
||||||
|
if not no_menu then window_flags = bit32.bor(window_flags, ImGuiWindowFlags.MenuBar) end
|
||||||
|
|
||||||
|
local ret -- is_visible
|
||||||
|
open, ret = ImGui.Begin("ImGui Sincerely Demo", open, window_flags)
|
||||||
|
if not ret then
|
||||||
|
ImGui.End()
|
||||||
|
return open
|
||||||
|
end
|
||||||
|
|
||||||
|
local label_width_base = ImGui.GetFontSize() * 12
|
||||||
|
local label_width_max = ImGui.GetContentRegionAvail().x * 0.40
|
||||||
|
local label_width = IM_MIN(label_width_base, label_width_max)
|
||||||
|
ImGui.PushItemWidth(-label_width)
|
||||||
|
|
||||||
|
DemoWindowMenuBar(demo_data)
|
||||||
|
|
||||||
|
if ImGui.CollapsingHeader("Help") then
|
||||||
|
ImGui.SeparatorText("ABOUT THIS DEMO:")
|
||||||
|
end
|
||||||
|
|
||||||
|
if ImGui.CollapsingHeader("Configuration") then
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
if ImGui.CollapsingHeader("Window Options") then
|
||||||
|
if ImGui.BeginTable("split", 3) then
|
||||||
|
ImGui.TableNextColumn() _, no_titlebar = ImGui.Checkbox("No titlebar", no_titlebar)
|
||||||
|
ImGui.TableNextColumn() _, no_scrollbar = ImGui.Checkbox("No scrollbar", no_scrollbar)
|
||||||
|
ImGui.TableNextColumn() _, no_menu = ImGui.Checkbox("No menu", no_menu)
|
||||||
|
ImGui.TableNextColumn() _, no_move = ImGui.Checkbox("No move", no_move)
|
||||||
|
ImGui.TableNextColumn() _, no_resize = ImGui.Checkbox("No resize", no_resize)
|
||||||
|
ImGui.TableNextColumn() _, no_collapse = ImGui.Checkbox("No collapse", no_collapse)
|
||||||
|
ImGui.TableNextColumn() _, no_close = ImGui.Checkbox("No close", no_close)
|
||||||
|
ImGui.TableNextColumn() _, no_nav = ImGui.Checkbox("No nav", no_nav)
|
||||||
|
ImGui.TableNextColumn() _, no_background = ImGui.Checkbox("No background", no_background)
|
||||||
|
ImGui.TableNextColumn() _, no_bring_to_front = ImGui.Checkbox("No bring to front", no_bring_to_front)
|
||||||
|
ImGui.TableNextColumn() _, no_docking = ImGui.Checkbox("No docking", no_docking)
|
||||||
|
ImGui.TableNextColumn() _, unsaved_document = ImGui.Checkbox("Unsaved document", unsaved_document)
|
||||||
|
ImGui.EndTable()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
DemoWindowWidgets()
|
||||||
|
DemoWindowLayout()
|
||||||
|
DemoWindowPopups()
|
||||||
|
DemoWindowTables()
|
||||||
|
DemoWindowInputs()
|
||||||
|
|
||||||
|
ImGui.End()
|
||||||
|
|
||||||
|
return open
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return true -- [Roblox] ModuleScripts must return exactly one value
|
||||||
File diff suppressed because it is too large
Load Diff
+2000
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,45 @@
|
|||||||
|
if _G.__IMGUI_ENV then setfenv(1, _G.__IMGUI_ENV) end -- [Roblox] shared env, see init.lua
|
||||||
|
--- ImGui Sincerely WIP
|
||||||
|
-- (Tables and Columns Code)
|
||||||
|
|
||||||
|
--- @type ImGuiContext?
|
||||||
|
local GImGui
|
||||||
|
|
||||||
|
-- Sets local `GImGui` in this file(imgui_tables.lua).
|
||||||
|
-- This is currently only used in main code `ImGui.SetCurrentContext()`
|
||||||
|
--- @param ctx ImGuiContext?
|
||||||
|
function ImGui._SetCurrentContext_Tables(ctx)
|
||||||
|
GImGui = ctx
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @param str_id string
|
||||||
|
--- @param columns_count int
|
||||||
|
--- @param flags? ImGuiTableFlags
|
||||||
|
--- @param outer_size? ImVec2
|
||||||
|
--- @param inner_width? float
|
||||||
|
function ImGui.BeginTable(str_id, columns_count, flags, outer_size, inner_width)
|
||||||
|
if flags == nil then flags = 0 end
|
||||||
|
if outer_size == nil then outer_size = ImVec2(0.0, 0.0) end
|
||||||
|
if inner_width == nil then inner_width = 0.0 end
|
||||||
|
|
||||||
|
-- TODO:
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function ImGui.EndTable()
|
||||||
|
-- TODO:
|
||||||
|
end
|
||||||
|
|
||||||
|
function ImGui.TableNextColumn()
|
||||||
|
-- TODO:
|
||||||
|
end
|
||||||
|
|
||||||
|
function ImGui.TablePushBackgroundChannel()
|
||||||
|
-- TODO:
|
||||||
|
end
|
||||||
|
|
||||||
|
function ImGui.TablePopBackgroundChannel()
|
||||||
|
-- TODO:
|
||||||
|
end
|
||||||
|
|
||||||
|
return true -- [Roblox] ModuleScripts must return exactly one value
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,444 @@
|
|||||||
|
if _G.__IMGUI_ENV then setfenv(1, _G.__IMGUI_ENV) end -- [Roblox] shared env, see init.lua
|
||||||
|
--- ImGui Sincerely
|
||||||
|
-- This is a Lua port of original `imstb_rectpack.h`
|
||||||
|
|
||||||
|
-- ALL TABLES IN THIS FILE ARE 1-BASED!
|
||||||
|
-- Avoids table creation when possible
|
||||||
|
|
||||||
|
--- The `prev_link` can be stbrp_context or stbrp_node
|
||||||
|
--- @diagnostic disable
|
||||||
|
|
||||||
|
local bit32 = bit32
|
||||||
|
|
||||||
|
local STBRP_SORT = table.sort
|
||||||
|
local STBRP_ASSERT = assert
|
||||||
|
local STBRP__NOTUSED = function(_) end
|
||||||
|
|
||||||
|
local STBRP__MAXVAL = 0x7fffffff
|
||||||
|
|
||||||
|
--- @enum STBRP_HEURISTIC_Skyline
|
||||||
|
local STBRP_HEURISTIC_Skyline = {
|
||||||
|
default = 0,
|
||||||
|
BL_sortHeight = 0,
|
||||||
|
BF_sortHeight = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
local STBRP__INIT_skyline = 1
|
||||||
|
|
||||||
|
--- @enum STBRP__PREV_LINK_TYPE
|
||||||
|
local STBRP__PREV_LINK_TYPE = {
|
||||||
|
ACTIVE_HEAD = 0,
|
||||||
|
NEXT = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
--- @alias stbrp_coord int
|
||||||
|
|
||||||
|
--- @class stbrp_rect
|
||||||
|
--- @field id int
|
||||||
|
--- @field w stbrp_coord
|
||||||
|
--- @field h stbrp_coord
|
||||||
|
--- @field x stbrp_coord
|
||||||
|
--- @field y stbrp_coord
|
||||||
|
--- @field was_packed int
|
||||||
|
|
||||||
|
--- @return stbrp_rect
|
||||||
|
--- @nodiscard
|
||||||
|
local function stbrp_rect()
|
||||||
|
return {
|
||||||
|
id = 0,
|
||||||
|
w = 0,
|
||||||
|
h = 0,
|
||||||
|
x = 0,
|
||||||
|
y = 0,
|
||||||
|
was_packed = 0
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @class stbrp_node
|
||||||
|
--- @field x stbrp_coord
|
||||||
|
--- @field y stbrp_coord
|
||||||
|
--- @field next stbrp_node
|
||||||
|
|
||||||
|
--- @return stbrp_node
|
||||||
|
--- @nodiscard
|
||||||
|
local function stbrp_node()
|
||||||
|
return {
|
||||||
|
x = 0,
|
||||||
|
y = 0,
|
||||||
|
next = nil
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @class stbrp_context
|
||||||
|
--- @field width int
|
||||||
|
--- @field height int
|
||||||
|
--- @field align int
|
||||||
|
--- @field init_mode int
|
||||||
|
--- @field heuristic int
|
||||||
|
--- @field num_nodes int
|
||||||
|
--- @field active_head stbrp_node
|
||||||
|
--- @field free_head stbrp_node
|
||||||
|
--- @field extra stbrp_node[]
|
||||||
|
|
||||||
|
--- @return stbrp_context
|
||||||
|
--- @nodiscard
|
||||||
|
local function stbrp_context()
|
||||||
|
return {
|
||||||
|
width = 0,
|
||||||
|
height = 0,
|
||||||
|
align = 0,
|
||||||
|
init_mode = 0,
|
||||||
|
heuristic = 0,
|
||||||
|
num_nodes = 0,
|
||||||
|
|
||||||
|
active_head = nil,
|
||||||
|
free_head = nil,
|
||||||
|
extra = {stbrp_node(), stbrp_node()}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @class stbrp__findresult
|
||||||
|
--- @field x int
|
||||||
|
--- @field y int
|
||||||
|
--- @field prev_link? table
|
||||||
|
--- @field prev_link_type? int
|
||||||
|
|
||||||
|
--- @return stbrp__findresult
|
||||||
|
local function stbrp__findresult()
|
||||||
|
return {
|
||||||
|
x = 0,
|
||||||
|
y = 0,
|
||||||
|
|
||||||
|
prev_link = nil,
|
||||||
|
prev_link_type = nil
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------
|
||||||
|
--------------------------
|
||||||
|
---
|
||||||
|
--- IMPLEMENTATION SECTION
|
||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
|
--- @param context stbrp_context
|
||||||
|
--- @param heuristic int
|
||||||
|
local function stbrp_setup_heuristic(context, heuristic)
|
||||||
|
if context.init_mode == STBRP__INIT_skyline then
|
||||||
|
STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline.BL_sortHeight or heuristic == STBRP_HEURISTIC_Skyline.BF_sortHeight)
|
||||||
|
context.heuristic = heuristic
|
||||||
|
else
|
||||||
|
STBRP_ASSERT(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @param context stbrp_context
|
||||||
|
--- @param allow_out_of_mem boolean
|
||||||
|
local function stbrp_setup_allow_out_of_mem(context, allow_out_of_mem)
|
||||||
|
if allow_out_of_mem then
|
||||||
|
context.align = 1
|
||||||
|
else
|
||||||
|
context.align = (context.width + context.num_nodes - 1) / context.num_nodes
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @param context stbrp_context
|
||||||
|
--- @param width int
|
||||||
|
--- @param height int
|
||||||
|
--- @param nodes stbrp_node[]
|
||||||
|
--- @param num_nodes int
|
||||||
|
function stbrp_init_target(context, width, height, nodes, num_nodes)
|
||||||
|
for i = 1, num_nodes - 1 do
|
||||||
|
nodes[i].next = nodes[i + 1]
|
||||||
|
end
|
||||||
|
nodes[num_nodes].next = nil
|
||||||
|
context.init_mode = STBRP__INIT_skyline
|
||||||
|
context.heuristic = STBRP_HEURISTIC_Skyline.default
|
||||||
|
context.free_head = nodes[1]
|
||||||
|
context.active_head = context.extra[1]
|
||||||
|
context.width = width
|
||||||
|
context.height = height
|
||||||
|
context.num_nodes = num_nodes
|
||||||
|
stbrp_setup_allow_out_of_mem(context, false)
|
||||||
|
|
||||||
|
context.extra[1].x = 0
|
||||||
|
context.extra[1].y = 0
|
||||||
|
context.extra[1].next = context.extra[2]
|
||||||
|
context.extra[2].x = width
|
||||||
|
context.extra[2].y = bit32.lshift(1, 30)
|
||||||
|
context.extra[2].next = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @param c stbrp_context
|
||||||
|
--- @param first stbrp_node
|
||||||
|
--- @param x0 int
|
||||||
|
--- @param width int
|
||||||
|
--- @return int, int
|
||||||
|
local function stbrp__skyline_find_min_y(c, first, x0, width)
|
||||||
|
local node = first
|
||||||
|
local x1 = x0 + width
|
||||||
|
|
||||||
|
STBRP__NOTUSED(c)
|
||||||
|
|
||||||
|
STBRP_ASSERT(first.x <= x0)
|
||||||
|
|
||||||
|
STBRP_ASSERT(node.next.x > x0)
|
||||||
|
|
||||||
|
STBRP_ASSERT(node.x <= x0)
|
||||||
|
|
||||||
|
local min_y = 0
|
||||||
|
local waste_area = 0
|
||||||
|
local visited_width = 0
|
||||||
|
while node.x < x1 do
|
||||||
|
if node.y > min_y then
|
||||||
|
waste_area = waste_area + visited_width * (node.y - min_y)
|
||||||
|
min_y = node.y
|
||||||
|
if node.x < x0 then
|
||||||
|
visited_width = visited_width + node.next.x - x0
|
||||||
|
else
|
||||||
|
visited_width = visited_width + node.next.x - node.x
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local under_width = node.next.x - node.x
|
||||||
|
if under_width + visited_width > width then
|
||||||
|
under_width = width - visited_width
|
||||||
|
end
|
||||||
|
waste_area = waste_area + under_width * (min_y - node.y)
|
||||||
|
visited_width = visited_width + under_width
|
||||||
|
end
|
||||||
|
node = node.next
|
||||||
|
end
|
||||||
|
|
||||||
|
return min_y, waste_area
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @param c stbrp_context
|
||||||
|
--- @param width int
|
||||||
|
--- @param height int
|
||||||
|
--- @return stbrp__findresult
|
||||||
|
local function stbrp__skyline_find_best_pos(c, width, height)
|
||||||
|
local best_waste = bit32.lshift(1, 30)
|
||||||
|
local best_x = 0
|
||||||
|
local best_y = bit32.lshift(1, 30)
|
||||||
|
local fr = stbrp__findresult()
|
||||||
|
local best_prev_link = nil
|
||||||
|
local best_prev_link_type = nil
|
||||||
|
|
||||||
|
width = width + c.align - 1
|
||||||
|
width = width - width % c.align
|
||||||
|
STBRP_ASSERT(width % c.align == 0)
|
||||||
|
|
||||||
|
if width > c.width or height > c.height then
|
||||||
|
fr.prev_link = nil
|
||||||
|
fr.prev_link_type = nil
|
||||||
|
fr.x = 0
|
||||||
|
fr.y = 0
|
||||||
|
return fr
|
||||||
|
end
|
||||||
|
|
||||||
|
local prev_link = c
|
||||||
|
local prev_link_type = STBRP__PREV_LINK_TYPE.ACTIVE_HEAD
|
||||||
|
local node = c.active_head
|
||||||
|
|
||||||
|
while (node.x + width <= c.width) do
|
||||||
|
local y, waste = stbrp__skyline_find_min_y(c, node, node.x, width)
|
||||||
|
|
||||||
|
if c.heuristic == STBRP_HEURISTIC_Skyline.BL_sortHeight then
|
||||||
|
if y < best_y then
|
||||||
|
best_y = y
|
||||||
|
best_prev_link = prev_link
|
||||||
|
best_prev_link_type = prev_link_type
|
||||||
|
best_x = node.x
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if y + height <= c.height then
|
||||||
|
if y < best_y or (y == best_y and waste < best_waste) then
|
||||||
|
best_y = y
|
||||||
|
best_waste = waste
|
||||||
|
best_prev_link = prev_link
|
||||||
|
best_prev_link_type = prev_link_type
|
||||||
|
best_x = node.x
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
prev_link = node
|
||||||
|
prev_link_type = STBRP__PREV_LINK_TYPE.NEXT
|
||||||
|
node = node.next
|
||||||
|
end
|
||||||
|
|
||||||
|
if c.heuristic == STBRP_HEURISTIC_Skyline.BF_sortHeight then
|
||||||
|
local tail = c.active_head
|
||||||
|
local node_scan = c.active_head
|
||||||
|
local prev_link_scan = c
|
||||||
|
local prev_link_scan_type = STBRP__PREV_LINK_TYPE.ACTIVE_HEAD
|
||||||
|
|
||||||
|
while tail and tail.x < width do
|
||||||
|
tail = tail.next
|
||||||
|
end
|
||||||
|
|
||||||
|
while tail do
|
||||||
|
local xpos = tail.x - width
|
||||||
|
STBRP_ASSERT(xpos >= 0)
|
||||||
|
|
||||||
|
while node_scan.next and node_scan.next.x <= xpos do
|
||||||
|
prev_link_scan = node_scan
|
||||||
|
prev_link_scan_type = STBRP__PREV_LINK_TYPE.NEXT
|
||||||
|
node_scan = node_scan.next
|
||||||
|
end
|
||||||
|
|
||||||
|
if node_scan then
|
||||||
|
STBRP_ASSERT(node_scan.next.x > xpos and node_scan.x <= xpos)
|
||||||
|
|
||||||
|
local y, waste = stbrp__skyline_find_min_y(c, node_scan, xpos, width)
|
||||||
|
|
||||||
|
if y + height <= c.height then
|
||||||
|
if y <= best_y then
|
||||||
|
if y < best_y or waste < best_waste or (waste == best_waste and xpos < best_x) then
|
||||||
|
best_x = xpos
|
||||||
|
best_y = y
|
||||||
|
best_waste = waste
|
||||||
|
best_prev_link = prev_link_scan
|
||||||
|
best_prev_link_type = prev_link_scan_type
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
tail = tail.next
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
fr.prev_link = best_prev_link
|
||||||
|
fr.prev_link_type = best_prev_link_type
|
||||||
|
fr.x = best_x
|
||||||
|
fr.y = best_y
|
||||||
|
return fr
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @param context stbrp_context
|
||||||
|
--- @param width int
|
||||||
|
--- @param height int
|
||||||
|
--- @return stbrp__findresult
|
||||||
|
local function stbrp__skyline_pack_rectangle(context, width, height)
|
||||||
|
local res = stbrp__skyline_find_best_pos(context, width, height)
|
||||||
|
|
||||||
|
if res.prev_link == nil or res.y + height > context.height or context.free_head == nil then
|
||||||
|
res.prev_link = nil
|
||||||
|
res.prev_link_type = nil
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
local node = context.free_head
|
||||||
|
node.x = res.x
|
||||||
|
node.y = res.y + height
|
||||||
|
context.free_head = node.next
|
||||||
|
|
||||||
|
local cur
|
||||||
|
if res.prev_link_type == STBRP__PREV_LINK_TYPE.ACTIVE_HEAD then
|
||||||
|
cur = res.prev_link.active_head
|
||||||
|
else
|
||||||
|
cur = res.prev_link.next
|
||||||
|
end
|
||||||
|
|
||||||
|
if cur.x < res.x then
|
||||||
|
local next = cur.next
|
||||||
|
cur.next = node
|
||||||
|
cur = next
|
||||||
|
else
|
||||||
|
if res.prev_link_type == STBRP__PREV_LINK_TYPE.ACTIVE_HEAD then
|
||||||
|
res.prev_link.active_head = node
|
||||||
|
else
|
||||||
|
res.prev_link.next = node
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
while cur.next and cur.next.x <= res.x + width do
|
||||||
|
local next = cur.next
|
||||||
|
cur.next = context.free_head
|
||||||
|
context.free_head = cur
|
||||||
|
cur = next
|
||||||
|
end
|
||||||
|
|
||||||
|
node.next = cur
|
||||||
|
|
||||||
|
if cur.x < res.x + width then
|
||||||
|
cur.x = res.x + width
|
||||||
|
end
|
||||||
|
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @param a stbrp_rect
|
||||||
|
--- @param b stbrp_rect
|
||||||
|
--- @return bool
|
||||||
|
--- @package
|
||||||
|
local function rect_height_compare(a, b)
|
||||||
|
if a.h > b.h then
|
||||||
|
return true
|
||||||
|
elseif a.h < b.h then
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
return a.w > b.w
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @param a stbrp_rect
|
||||||
|
--- @param b stbrp_rect
|
||||||
|
--- @return bool
|
||||||
|
--- @package
|
||||||
|
local function rect_original_order(a, b)
|
||||||
|
return a.was_packed < b.was_packed
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @param context stbrp_context
|
||||||
|
--- @param rects stbrp_rect[]
|
||||||
|
--- @param num_rects int
|
||||||
|
--- @return int
|
||||||
|
local function stbrp_pack_rects(context, rects, num_rects)
|
||||||
|
local all_rects_packed = 1
|
||||||
|
|
||||||
|
for i = 1, num_rects do
|
||||||
|
rects[i].was_packed = (i - 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
STBRP_SORT(rects, rect_height_compare)
|
||||||
|
|
||||||
|
for i = 1, num_rects do
|
||||||
|
if rects[i].w == 0 or rects[i].h == 0 then
|
||||||
|
rects[i].x = 0
|
||||||
|
rects[i].y = 0
|
||||||
|
else
|
||||||
|
local fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h)
|
||||||
|
if fr.prev_link then
|
||||||
|
rects[i].x = fr.x
|
||||||
|
rects[i].y = fr.y
|
||||||
|
else
|
||||||
|
rects[i].x = STBRP__MAXVAL
|
||||||
|
rects[i].y = STBRP__MAXVAL
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STBRP_SORT(rects, rect_original_order)
|
||||||
|
|
||||||
|
for i = 1, num_rects do
|
||||||
|
rects[i].was_packed = (rects[i].x == STBRP__MAXVAL and rects[i].y == STBRP__MAXVAL) and 0 or 1
|
||||||
|
if rects[i].was_packed == 0 then
|
||||||
|
all_rects_packed = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return all_rects_packed
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
context = stbrp_context,
|
||||||
|
rect = stbrp_rect,
|
||||||
|
node = stbrp_node,
|
||||||
|
|
||||||
|
pack_rects = stbrp_pack_rects,
|
||||||
|
init_target = stbrp_init_target,
|
||||||
|
setup_allow_out_of_mem = stbrp_setup_allow_out_of_mem,
|
||||||
|
setup_heuristic = stbrp_setup_heuristic
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,222 @@
|
|||||||
|
if _G.__IMGUI_ENV then setfenv(1, _G.__IMGUI_ENV) end -- [Roblox] shared env, see init.lua
|
||||||
|
--- ImGui Sincerely
|
||||||
|
-- This is a minimal Lua impl of C-like sscanf, sprintf sub-set
|
||||||
|
|
||||||
|
-- Supports:
|
||||||
|
-- - %x, %X, %nx, %nX (where n is a number)
|
||||||
|
-- - %d, %nd (where n is a number)
|
||||||
|
-- - %f, %lf (very limited)
|
||||||
|
--
|
||||||
|
-- Returns items_matched instead of EOF on error
|
||||||
|
|
||||||
|
local _byte = string.byte
|
||||||
|
|
||||||
|
local CHAR_PERCENT = _byte'%'
|
||||||
|
local CHAR_DOT = _byte'.'
|
||||||
|
local CHAR_PLUS, CHAR_MINUS = _byte'+', _byte'-'
|
||||||
|
local CHAR_0, CHAR_9 = _byte'0', _byte'9'
|
||||||
|
local CHAR_a, CHAR_A = _byte'a', _byte'A'
|
||||||
|
local CHAR_d = _byte'd'
|
||||||
|
local CHAR_l = _byte'l'
|
||||||
|
local CHAR_f, CHAR_F = _byte'f', _byte'F'
|
||||||
|
local CHAR_x, CHAR_X = _byte'x', _byte'X'
|
||||||
|
|
||||||
|
local function isspace(c) return c == 32 or c == 9 end
|
||||||
|
local function isdigit(c) return c >= CHAR_0 and c <= CHAR_9 end
|
||||||
|
local function isxdigit(c) return isdigit(c) or (c >= CHAR_a and c <= CHAR_f) or (c >= CHAR_A and c <= CHAR_F) end
|
||||||
|
|
||||||
|
local function isdigit_under_base(c, base)
|
||||||
|
if base == 10 then return isdigit(c)
|
||||||
|
elseif base == 16 then return isxdigit(c)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function hex_digit_to_int(c)
|
||||||
|
if c >= CHAR_0 and c <= CHAR_9 then return c - CHAR_0 end
|
||||||
|
if c >= CHAR_a and c <= CHAR_f then return c - CHAR_a + 10 end
|
||||||
|
if c >= CHAR_A and c <= CHAR_F then return c - CHAR_A + 10 end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- we force this behavior by default
|
||||||
|
local function clamp_if_overflow(spec, val)
|
||||||
|
if spec == CHAR_d or spec == CHAR_x or spec == CHAR_X then
|
||||||
|
if val > INT_MAX then return INT_MAX end
|
||||||
|
if val < INT_MIN then return INT_MIN end
|
||||||
|
end
|
||||||
|
|
||||||
|
return val
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @param buffer char[]
|
||||||
|
--- @param buffer_begin int
|
||||||
|
--- @param format string
|
||||||
|
--- @param result table # table to store parsed values
|
||||||
|
local function sscanf(buffer, buffer_begin, format, result)
|
||||||
|
local p = buffer_begin
|
||||||
|
local f = 1 -- format_begin
|
||||||
|
local format_len = #format
|
||||||
|
local assigned = 0
|
||||||
|
local items_matched = 0
|
||||||
|
|
||||||
|
while f <= format_len do
|
||||||
|
repeat
|
||||||
|
if isspace(_byte(format, f, f)) then
|
||||||
|
while isspace(buffer[p]) do
|
||||||
|
p = p + 1
|
||||||
|
end
|
||||||
|
f = f + 1
|
||||||
|
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
if _byte(format, f, f) ~= CHAR_PERCENT then
|
||||||
|
if buffer[p] == _byte(format, f, f) then
|
||||||
|
p = p + 1
|
||||||
|
f = f + 1
|
||||||
|
else
|
||||||
|
return items_matched
|
||||||
|
end
|
||||||
|
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
-- encountered % in fmt
|
||||||
|
f = f + 1
|
||||||
|
|
||||||
|
-- %%
|
||||||
|
if _byte(format, f, f) == CHAR_PERCENT then
|
||||||
|
if buffer[p] == CHAR_PERCENT then
|
||||||
|
p = p + 1
|
||||||
|
f = f + 1
|
||||||
|
else
|
||||||
|
return items_matched
|
||||||
|
end
|
||||||
|
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
-- handle optional width
|
||||||
|
local width = 0
|
||||||
|
while isdigit(_byte(format, f, f)) do
|
||||||
|
width = width * 10 + _byte(format, f, f) - CHAR_0
|
||||||
|
f = f + 1
|
||||||
|
end
|
||||||
|
if width == 0 then
|
||||||
|
width = math.huge
|
||||||
|
end
|
||||||
|
|
||||||
|
local spec = _byte(format, f, f)
|
||||||
|
local base
|
||||||
|
local is_float = false
|
||||||
|
if spec == CHAR_x or spec == CHAR_X then
|
||||||
|
base = 16
|
||||||
|
elseif spec == CHAR_d then
|
||||||
|
base = 10
|
||||||
|
elseif spec == CHAR_f or spec == CHAR_F then
|
||||||
|
is_float = true
|
||||||
|
elseif spec == CHAR_l then
|
||||||
|
f = f + 1
|
||||||
|
if _byte(format, f, f) == CHAR_f then
|
||||||
|
is_float = true -- TODO: distinguish from float?
|
||||||
|
else
|
||||||
|
return items_matched
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return items_matched
|
||||||
|
end
|
||||||
|
f = f + 1
|
||||||
|
|
||||||
|
while isspace(buffer[p]) do
|
||||||
|
p = p + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
local val
|
||||||
|
if is_float then
|
||||||
|
local sign = 1
|
||||||
|
if buffer[p] == CHAR_PLUS then
|
||||||
|
p = p + 1
|
||||||
|
elseif buffer[p] == CHAR_MINUS then
|
||||||
|
sign = -1
|
||||||
|
p = p + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- inf, nan are not handled
|
||||||
|
|
||||||
|
local p_start = p
|
||||||
|
local int_part = 0
|
||||||
|
|
||||||
|
while isdigit(buffer[p]) do
|
||||||
|
int_part = int_part * 10 + (buffer[p] - CHAR_0)
|
||||||
|
p = p + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
local frac_part = 0
|
||||||
|
local frac_div = 1
|
||||||
|
if buffer[p] == CHAR_DOT then
|
||||||
|
p = p + 1
|
||||||
|
while isdigit(buffer[p]) do
|
||||||
|
frac_part = frac_part * 10 + (buffer[p] - CHAR_0)
|
||||||
|
frac_div = frac_div * 10
|
||||||
|
p = p + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if p == p_start then
|
||||||
|
return items_matched
|
||||||
|
end
|
||||||
|
|
||||||
|
val = sign * (int_part + frac_part / frac_div)
|
||||||
|
else
|
||||||
|
local sign = 1
|
||||||
|
-- optional sign
|
||||||
|
if base == 10 then
|
||||||
|
if buffer[p] == CHAR_PLUS then
|
||||||
|
p = p + 1
|
||||||
|
width = width - 1
|
||||||
|
elseif buffer[p] == CHAR_MINUS then
|
||||||
|
sign = -1
|
||||||
|
p = p + 1
|
||||||
|
width = width - 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local p_start = p
|
||||||
|
while width > 0 and buffer[p] and isdigit_under_base(buffer[p], base) do
|
||||||
|
p = p + 1
|
||||||
|
width = width - 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if p == p_start then
|
||||||
|
-- failed to match
|
||||||
|
return items_matched
|
||||||
|
end
|
||||||
|
|
||||||
|
val = 0
|
||||||
|
while p_start < p do
|
||||||
|
local c = buffer[p_start]
|
||||||
|
p_start = p_start + 1
|
||||||
|
val = val * base + sign * hex_digit_to_int(c)
|
||||||
|
|
||||||
|
local old_val = val
|
||||||
|
val = clamp_if_overflow(spec, val)
|
||||||
|
if old_val ~= val then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
result[assigned + 1] = val
|
||||||
|
assigned = assigned + 1
|
||||||
|
items_matched = items_matched + 1
|
||||||
|
|
||||||
|
until true
|
||||||
|
end
|
||||||
|
|
||||||
|
return items_matched
|
||||||
|
end
|
||||||
|
|
||||||
|
local function sprintf()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return sscanf
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
require("imgui.imgui")
|
||||||
|
require("imgui.backend.imgui_impl_love")
|
||||||
|
require("imgui.imgui_demo")
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
require("imgui")
|
||||||
|
|
||||||
|
local RunService = Instance.new("RunService")
|
||||||
|
|
||||||
|
local main_scale = 1.0
|
||||||
|
local clear_color = ImVec4(0.45, 0.55, 0.60, 1.00)
|
||||||
|
local f = 0.0
|
||||||
|
local counter = 0
|
||||||
|
|
||||||
|
ImGui.CreateContext()
|
||||||
|
|
||||||
|
local io = ImGui.GetIO()
|
||||||
|
io.ConfigFlags = bit.bor(io.ConfigFlags, ImGuiConfigFlags.NavEnableKeyboard)
|
||||||
|
--io.ConfigFlags = bit.bor(io.ConfigFlags, ImGuiConfigFlags.ViewportsEnable)
|
||||||
|
|
||||||
|
local style = ImGui.GetStyle()
|
||||||
|
style:ScaleAllSizes(main_scale)
|
||||||
|
style.FontScaleDpi = main_scale
|
||||||
|
|
||||||
|
ImGui_ImplLove.Init()
|
||||||
|
|
||||||
|
RunService.Stepped:Connect(function(dt)
|
||||||
|
ImGui_ImplLove.NewFrame()
|
||||||
|
ImGui.NewFrame()
|
||||||
|
|
||||||
|
ImGui.ShowDemoWindow()
|
||||||
|
|
||||||
|
do
|
||||||
|
ImGui.Begin("Hello, world!")
|
||||||
|
|
||||||
|
ImGui.Text("This is some useful text.")
|
||||||
|
_, show_demo_window = ImGui.Checkbox("Demo Window", show_demo_window)
|
||||||
|
_, show_another_window = ImGui.Checkbox("Another Window", show_another_window)
|
||||||
|
|
||||||
|
f = ImGui.SliderFloat("float", f, 0.0, 1.0)
|
||||||
|
ImGui.ColorEdit3("clear color", clear_color)
|
||||||
|
|
||||||
|
if ImGui.Button("Button") then
|
||||||
|
counter = counter + 1
|
||||||
|
end
|
||||||
|
ImGui.SameLine()
|
||||||
|
ImGui.Text("counter = %d", counter)
|
||||||
|
|
||||||
|
ImGui.Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0 / io.Framerate, io.Framerate)
|
||||||
|
|
||||||
|
ImGui.End()
|
||||||
|
end
|
||||||
|
|
||||||
|
if show_another_window then
|
||||||
|
show_another_window = ImGui.Begin("Another Window", show_another_window)
|
||||||
|
|
||||||
|
ImGui.Text("Hello from another window!")
|
||||||
|
if ImGui.Button("Close Me") then
|
||||||
|
show_another_window = false
|
||||||
|
end
|
||||||
|
|
||||||
|
ImGui.End()
|
||||||
|
end
|
||||||
|
|
||||||
|
ImGui.EndFrame()
|
||||||
|
return ImGui.Render()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RunService.PreAnimation:Connect(function()
|
||||||
|
ImGui_ImplLove.RenderDrawData(ImGui.GetDrawData())
|
||||||
|
|
||||||
|
if bit.band(io.ConfigFlags, ImGuiConfigFlags.ViewportsEnable) ~= 0 then
|
||||||
|
ImGui.UpdatePlatformWindows()
|
||||||
|
ImGui.RenderPlatformWindowsDefault()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
function love.keypressed(k) ImGui_ImplLove.KeyPressed(k) end
|
||||||
|
function love.keyreleased(k) ImGui_ImplLove.KeyReleased(k) end
|
||||||
|
function love.mousepressed(x, y, b) ImGui_ImplLove.MousePressed(x, y, b) end
|
||||||
|
function love.mousereleased(x, y, b) ImGui_ImplLove.MouseReleased(x, y, b) end
|
||||||
|
function love.wheelmoved(x, y) ImGui_ImplLove.WheelMoved(x, y) end
|
||||||
|
function love.textinput(t) ImGui_ImplLove.TextInput(t) end
|
||||||
|
function love.mousemoved(x, y) ImGui_ImplLove.MouseMoved(x, y) end
|
||||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user