Reorganize like upstream: library at root (docking/dragdrop/debug tools merged into imgui.lua, tabs into imgui_widgets.lua), single imgui_demo.lua, backends/, fonts/, examples/, docs/; --no-demo build

This commit is contained in:
4DBug
2026-10-08 16:47:42 -05:00
parent 7c2a37a5d5
commit 8421bb5475
41 changed files with 19109 additions and 55555 deletions
+1 -1
View File
@@ -1 +1 @@
[[12, "imgui.lua"], [13808, "imgui_demo.lua"], [14741, "imgui_demo_2.lua"], [17816, "imgui_demo_apps.lua"], [19075, "imgui_demo_tools.lua"], [20401, "imgui_demo_widgets.lua"], [22334, "imgui_docking.lua"], [25462, "imgui_dragdrop.lua"], [25754, "imgui_draw.lua"], [30992, "imgui_h.lua"], [33190, "imgui_impl_roblox.lua"], [34316, "imgui_impl_roblox_fonts.lua"], [40719, "imgui_internal.lua"], [43891, "imgui_tables.lua"], [48238, "imgui_tabs.lua"], [49405, "imgui_widgets.lua"], [57980, "imstb_rectpack.lua"], [58426, "imstb_textedit.lua"], [59667, "imstb_truetype.lua"], [62135, "imstd_minstdio.lua"]]
[[12, "imgui.lua"], [18472, "imgui_demo.lua"], [25757, "imgui_draw.lua"], [30995, "imgui_h.lua"], [33193, "imgui_impl_roblox.lua"], [34319, "imgui_impl_roblox_fonts.lua"], [40722, "imgui_internal.lua"], [43894, "imgui_tables.lua"], [48241, "imgui_widgets.lua"], [57982, "imstb_rectpack.lua"], [58428, "imstb_textedit.lua"], [59669, "imstb_truetype.lua"], [62137, "imstd_minstdio.lua"]]
+5940 -5942
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -7,7 +7,7 @@
},
"StarterPlayer": {
"StarterPlayerScripts": {
"ImGuiMain": { "$path": "main.client.luau" }
"ImGuiMain": { "$path": "examples/example_roblox/main.client.luau" }
}
}
}
+10 -5
View File
@@ -6,8 +6,13 @@ there, but keep this port's existing data structures and conventions. Read the s
## Runtime
- Target is **Luau (Roblox)** only. All files are concatenated into one ModuleScript by `tools/bundle.py`; every
file shares one global namespace. Globals defined by one file are visible to the others at call time.
- Each `imgui/*.lua` file is a function body in the bundle. New files must be loaded with `IM_INCLUDE"file.lua"`
from an existing file (files named `imgui_demo*.lua` are loaded automatically, after `imgui.lua`).
- Layout mirrors upstream: library at the repo root (`imgui.lua` incl. docking, drag & drop and the debug tools,
`imgui_widgets.lua` incl. tab bars, `imgui_draw.lua`, `imgui_tables.lua`, `imgui_internal.lua`, `imgui_h.lua`,
`imstb_*.lua`), demo in `imgui_demo.lua` only, backend in `backends/`, fonts in `fonts/`, the example LocalScript in
`examples/example_roblox/`. The library must never call into `imgui_demo.lua` (`tools/bundle.py --no-demo`,
`tools/test/undefined.py --no-demo`, `NO_DEMO=1 run.py --main tools/test/scripts/t_nodemo.luau`).
- Each `.lua` file is a function body in the bundle. New files must be loaded with `IM_INCLUDE"file.lua"` from an
existing file. Merged-in sections are wrapped in `do ... end` so their locals stay private.
- No `goto`, no `::labels::`, no `setfenv/getfenv`, no LuaJIT `bit`/`ffi`. Use `bit32`. For `continue` use
`repeat ... until true` with `break`, and an explicit flag when the loop itself must break out of the wrapper.
- Luau has a limit of 200 locals per function and 255 upvalues; split huge functions (like demo sections) into
@@ -17,7 +22,7 @@ there, but keep this port's existing data structures and conventions. Read the s
- `ImVector`: 1-based `.Data`, `.Size`, methods `push_back/pop_back/resize/back/iter/erase/...` (imgui_h.lua).
Indices that C++ stores as 0-based *values* (e.g. column index, tab order) stay 0-based unless the surrounding
port code already shifted them; document `-- 0-based` / `-- 1-based` next to anything ambiguous.
- `ImVec2(x, y)` stores `[1],[2]` with `.x/.y` aliases (metatable). Arithmetic operators exist. Prefer
- `ImVec2(x, y)` stores named fields `.x/.y` (`[1],[2]` go through the metatable, slower). Arithmetic operators exist. Prefer
`ImVec2_Copy(dst, src)` / `ImVec2_CopyV(dst, x, y)` when C++ assigns into an existing struct field.
`ImVec4`, `ImRect` (`.Min/.Max`) likewise.
- Structs: constructor function `ImGuiFoo()` returning a table, methods on `MT.ImGuiFoo` with
@@ -42,8 +47,8 @@ there, but keep this port's existing data structures and conventions. Read the s
widgets that cannot work.
## Testing
- `python3 tools/test/run.py` — runs main.client.luau 400 frames with scripted random input (mouse, clicks,
keys, typing). Errors print with `imgui/<file>.lua:<line>` mapped stack traces.
- `python3 tools/test/run.py` — runs examples/example_roblox/main.client.luau 400 frames with scripted random input (mouse, clicks,
keys, typing). Errors print with `<file>.lua:<line>` mapped stack traces.
- `--open` forces every CollapsingHeader/TreeNode open (exercises the whole demo). `--big` makes the demo
incremental renderer is pixel identical to a full redraw. `--main file.luau` runs your own test LocalScript
(copy main.client.luau as a template: `local G = require(ReplicatedStorage:WaitForChild("ImGui"))`, all
@@ -70,7 +70,7 @@ style.FontScaleDpi = main_scale
-- Fonts: ProggyClean stays the default (added first); the rest show up in Style Editor > Fonts
io.Fonts:AddFontDefault()
for _, name in ipairs({ "Cousine-Regular", "DroidSans", "Karla-Regular", "ProggyTiny", "Roboto-Medium" }) do
io.Fonts:AddFontFromFileTTF("resource/fonts/" .. name .. ".ttf", 13.0)
io.Fonts:AddFontFromFileTTF("fonts/" .. name .. ".ttf", 13.0)
end
ImGui_ImplRoblox.Init(nil, render_scale)
@@ -1,7 +1,7 @@
-- [Roblox] Embedded copies of resource/fonts/*.ttf (Roblox can't read files). Generated: hex encoded bytes.
-- [Roblox] Embedded copies of fonts/*.ttf (Roblox can't read files). Generated: hex encoded bytes.
-- Add your own fonts the same way, or at runtime with ImGui_ImplRoblox.AddFile(path, bytes).
return {
["resource/fonts/ProggyClean.ttf"] = [[
["fonts/ProggyClean.ttf"] = [[
00010000000c0080000300404f532f3288eb7490000001480000004e636d617002122375000003a0000001526376742000000000000004fc00000002676c796612af8956000007040000928068656164
d79166d3000000cc0000003668686561084201c30000010400000024686d74788a007e8000000198000002066c6f63618c73b0d800000500000002046d61787001ae00da00000128000000206e616d65
2559bb96000099840000019e706f7374a6ac83ef00009b24000005d27072657069020112000004f40000000800010000000100003c55e9d55f0f3cf50003080000000000b767778400000000bd92a6d7
@@ -519,7 +519,7 @@ fe008080800400808080808080808080808080808080808080808080808080808080808080808080
636f6465233078303039610e756e69636f6465233078303039620e756e69636f6465233078303039630e756e69636f6465233078303039640e756e69636f6465233078303039650e756e69636f646523
3078303039660000
]],
["resource/fonts/ProggyForever.ttf"] = [[
["fonts/ProggyForever.ttf"] = [[
00010000000d0080000300504646544db071471100004e180000001c474445460027001800004df8000000204f532f326861dc280000015800000060636d61709393e3be000003440000018a67617370
ffff000300004df000000008676c7966789d738700000658000041a8686561642c3ad262000000dc0000003668686561043e00e60000011400000024686d747817821441000001b80000018c6c6f6361
99df8a52000004d0000001866d617870010900e400000138000000206e616d65b5c86e22000048000000041a706f7374a844032500004c1c000001d10001000000010000e47302ad5f0f3cf5000b03e8
@@ -772,7 +772,7 @@ f4f034343b32eb33830000000002003dfff6017b023b0017001b000001331123270e042322263d01
76657273636f726507616d6163726f6e044575726f07756e696539313200000000000001ffff000200010000000c00000010001800020000000400000002000000010000000100000000000100000000
e50db79300000000e5afbb4200000000e5b3d43b
]],
["resource/fonts/Cousine-Regular.ttf"] = [[
["fonts/Cousine-Regular.ttf"] = [[
00010000001101000004001044534947000000010000ab44000000084646544d4ee467c80000ab6c0000001c47444546010500040000ab4c000000204f532f32f9269e4f0000019800000060636d6170
5d08ad9f000003b00000027a637674204d165eb5000011a00000023c6670676d73d323b00000062c0000070567617370001800090000ab3400000010676c796639545d7f000015900000894468656164
f6dda5880000011c00000036686865610b7802620000015400000024686d74784f0a46ca000001f8000001b86c6f63616c1a4dd2000013dc000001b26d617870047c026700000178000000206e616d65
@@ -1323,7 +1323,7 @@ fe230054000000010000000000000000000000000000000000d80000000100020003000400050006
4239044575726f07756e69323231390b6f6e656672616374696f6e0b74776f6672616374696f6e0d74687265656672616369746f6e0c666f75726672616374696f6e0000000000030008000200110001
ffff0003000000010000000000010000000e000000180000000000020001000100d7000100040000000200000000000100000000c7feb0df00000000bd76892400000000c96f2dc4
]],
["resource/fonts/DroidSans.ttf"] = [[
["fonts/DroidSans.ttf"] = [[
000100000013010000040030474445460026038700023d200000001e47504f5394bda2f000023d400000a8fa475355426c91748f0002e63c000000204c545348c99bb9200000101c000003864f532f32
a0cb958b000001b800000060636d6170ce11d4a2000056780000079e63767420397e3e4c0000680c000001fc6670676d73d323b000005e1800000705676173700004000700023d140000000c676c7966
c293c651000071100001a81e68646d78ef0efaab000013a4000042d468656164ebc60a350000013c00000036686865610c5309a40000017400000024686d7478d2d72e270000021800000e046c6f6361
@@ -3701,7 +3701,7 @@ ffec03180014031affec031cffc300da00050052000a00520010ff5c0026ffec002affec0032ffec
0342034201cc0344034501cd0347034701cf0349035601d00358035801de035a035a01df035c035c01e0035e035e01e10360036101e20363036301e40366036601e50368036801e6036a036a01e7036c
036c01e8036e037401e9000000010000000a001c001e00016c61746e0008000400000000ffff000000000000
]],
["resource/fonts/Karla-Regular.ttf"] = [[
["fonts/Karla-Regular.ttf"] = [[
0001000000110100000400104453494700000001000041c8000000084646544d5e5927d200003d280000001c47444546002800cc00003d440000002847504f5303802f7500003d6c0000040047535542
dc42ea3b0000416c0000005c4f532f3284373af00000019800000060636d61702dfec69900000494000001e2676173700000001000003d2000000008676c796674bfc695000007d000002e5068656164
f88661be0000011c000000366868656106c003300000015400000024686d74784b84229d000001f80000029c6c6f63618bbf97a400000680000001506d61787000ee004200000178000000206e616d65
@@ -3914,7 +3914,7 @@ ffc70049ffe4005cffec0001003cffdb00020037ffc7003cffcf00050024ffe8002dffcb0037ffc4
fff4002dffe80037ffc8003cffe4004afff800020037ffe8003cffd700010000000a001e002c00016c61746e0008000400000000ffff0001000000016f6e756d00080000000100000001000400010000
000100080002001a000a0000000000000000000000000000000000000000000200010013001c00000000000100000000
]],
["resource/fonts/ProggyTiny.ttf"] = [[
["fonts/ProggyTiny.ttf"] = [[
00010000000c0080000300404f532f3287eb7310000001480000004e636d617002122375000003a0000001526376742000000000000004fc00000002676c7966d3ee60d00000070400007cd468656164
d71168b2000000cc000000366868656106c201c30000010400000024686d747858804c8000000198000002066c6f636145f364f400000500000002046d61787001a600ba00000128000000206e616d65
01fc6ebc000083d80000019b706f7374a6ac83ef00008574000005d27072657069020112000004f4000000080001000000010000f6a410ea5f0f3cf50003080000000000b767778400000000bd92a933
@@ -4362,7 +4362,7 @@ fd8080018080fd8080018080fe00808080808080fe00808080030080808080ff0080808080808080
756e69636f6465233078303039370e756e69636f6465233078303039380e756e69636f6465233078303039390e756e69636f6465233078303039610e756e69636f6465233078303039620e756e69636f
6465233078303039630e756e69636f6465233078303039640e756e69636f6465233078303039650e756e69636f6465233078303039660000
]],
["resource/fonts/Roboto-Medium.ttf"] = [[
["fonts/Roboto-Medium.ttf"] = [[
00010000001101000004001047504f537daa718c000208a80000590c475355424c9c28e0000261b4000019684f532f32a10bb1b60000019800000060636d61704026487200001a6c000012c863767420
04972b4a00002fbc000000566670676d7bf961ab00002d34000001bc67617370000800130002089c0000000c676c7966ae9e62e9000039dc0001cbcc68646d783d3f3c2000001580000004ec68656164
f87bab080000011c00000036686865610aef0a9b0000015400000024686d747824f344f5000001f8000013886c6f6361ddde66ad00003014000009c66d617870071202f500000178000000206e616d65
File diff suppressed because it is too large Load Diff
-930
View File
@@ -1,930 +0,0 @@
--- ImGui Sincerely WIP
-- (Demo Code) Port of imgui_demo.cpp (docking branch)
-- This file: shared demo helpers, ShowDemoWindow(), DemoWindowMenuBar(), DemoWindowWidgets() dispatcher, example tree/image viewer helpers.
-- Other parts (all global functions, loaded from the same bundle):
-- imgui_demo_w1.lua : DemoWindowWidgets{Basic,Bullets,CollapsingHeaders,ColorAndPickers,ComboBoxes,DataTypes,...}
-- imgui_demo_w2.lua : DemoWindowWidgets{QueryingStatuses,Selectables,SelectionAndMultiSelect}
-- imgui_demo_w3.lua : DemoWindowWidgets{Tabs,Text,TextInput,Tooltips,TreeNodes,VerticalSliders}
-- imgui_demo_style.lua : ShowAboutWindow, ShowStyleEditor, ShowUserGuide, ShowExampleMenuFile, ...
-- imgui_demo_2.lua : Layout, Popups, Tables, Columns, Inputs + example apps
local _
----------------------------------------------------------------
-- Shared helpers (globals)
----------------------------------------------------------------
function IMGUI_DEMO_MARKER(_) end -- upstream hook, no-op here
--- Helper to display a little (?) mark which shows a tooltip when hovered.
function HelpMarker(desc)
ImGui.TextDisabled("(?)")
if ImGui.BeginItemTooltip() then
ImGui.PushTextWrapPos(ImGui.GetFontSize() * 35.0)
ImGui.TextUnformatted(desc)
ImGui.PopTextWrapPos()
ImGui.EndTooltip()
end
end
function ShowDockingDisabledMessage()
local io = ImGui.GetIO()
ImGui.Text("ERROR: Docking is not enabled! See Demo > Configuration.")
ImGui.Text("Set io.ConfigFlags |= ImGuiConfigFlags_DockingEnable in your code, or ")
ImGui.SameLine(0.0, 0.0)
if ImGui.SmallButton("click here") then
io.ConfigFlags = bit32.bor(io.ConfigFlags, ImGuiConfigFlags.DockingEnable)
end
end
function DemoNotSupported() ImGui.TextDisabled("(not supported on Roblox)") end
function DemoNotPorted(what) ImGui.TextDisabled("(not ported yet%s)", what and (": " .. what) or "") end
function DemoB2I(b) return b and 1 or 0 end
function DemoHas(flags, f) return bit32.band(flags, f) ~= 0 end
function DemoClamp(v, mn, mx) return (v < mn) and mn or (v > mx) and mx or v end
--- `char buf[size] = "str"` -> zero-terminated byte table
function DemoBuf(str, size)
local t = {}
for i = 1, #str do t[i] = string.byte(str, i) end
t[#str + 1] = 0
if size then for i = #str + 2, size do t[i] = 0 end end
return t
end
--- byte table -> Lua string (up to the zero terminator)
function DemoBufStr(buf)
local n = 0
while buf[n + 1] ~= nil and buf[n + 1] ~= 0 do n = n + 1 end
if n == 0 then return "" end
return ImGui._ByteArrayToString(buf, 1, n + 1)
end
--- "a\0b\0c\0\0" -> { "a", "b", "c" }
function DemoItems(s)
if type(s) == "table" then return s end
local t = {}
for item in string.gmatch(s, "([^%z]+)") do t[#t + 1] = item end
return t
end
--- Combo() one-liner. `idx` is 0-based; `items` is a table of strings (1-based) or a "\0"-separated string.
--- Uses ImGui.Combo if it exists, falls back to BeginCombo/Selectable.
--- @return int idx, bool changed
function DemoCombo(label, idx, items, popup_max_height_in_items)
items = DemoItems(items)
if ImGui.Combo then
return ImGui.Combo(label, idx, items, #items, popup_max_height_in_items or -1)
end
local changed = false
local preview = (idx >= 0 and idx < #items) and items[idx + 1] or ""
if ImGui.BeginCombo(label, preview) then
for n = 0, #items - 1 do
local is_selected = (idx == n)
if ImGui.Selectable(items[n + 1], is_selected) then
idx = n
changed = true
end
if is_selected then ImGui.SetItemDefaultFocus() end
end
ImGui.EndCombo()
end
return idx, changed
end
--- ListBox() one-liner (see DemoCombo)
function DemoListBox(label, idx, items, height_in_items)
items = DemoItems(items)
if ImGui.ListBox then
return ImGui.ListBox(label, idx, items, #items, height_in_items or -1)
end
local changed = false
if height_in_items == nil or height_in_items < 0 then height_in_items = math.min(#items, 7) end
local height_in_items_f = height_in_items + 0.25
local height_in_pixels = math.floor(ImGui.GetTextLineHeightWithSpacing() * height_in_items_f + ImGui.GetStyle().FramePadding.y * 2.0)
if ImGui.BeginListBox and ImGui.BeginListBox(label, ImVec2(0.0, height_in_pixels)) then
for n = 0, #items - 1 do
local is_selected = (idx == n)
if ImGui.Selectable(items[n + 1], is_selected) then
idx = n
changed = true
end
if is_selected then ImGui.SetItemDefaultFocus() end
end
ImGui.EndListBox()
elseif not ImGui.BeginListBox then
DemoNotPorted("ListBox")
end
return idx, changed
end
--- Closable header: CollapsingHeader(label, &p_open). Returns visible, open.
function DemoCollapsingHeaderClosable(label, open)
return ImGui.CollapsingHeader(label, open)
end
--- ImColor::HSV() as ImVec4
function DemoHSV(h, s, v, a)
local r, g, b = ImGui.ColorConvertHSVtoRGB(h, s, v)
return ImVec4(r, g, b, a or 1.0)
end
--- Minimal ImGuiTextFilter when the library one isn't available (Draw/DrawWithHint/PassFilter/Clear/IsActive)
function DemoTextFilter()
if ImGuiTextFilter then return ImGuiTextFilter() end
local f = { InputBuf = DemoBuf("", 256) }
local function parse(self)
local inc, exc = {}, {}
for tok in string.gmatch(string.lower(DemoBufStr(self.InputBuf)), "[^,%s]+") do
if string.sub(tok, 1, 1) == "-" then
if #tok > 1 then exc[#exc + 1] = string.sub(tok, 2) end
else
inc[#inc + 1] = tok
end
end
return inc, exc
end
function f:Draw(label, width)
if width and width ~= 0 then ImGui.SetNextItemWidth(width) end
return ImGui.InputText(label or "Filter (inc,-exc)", self.InputBuf, 256)
end
function f:DrawWithHint(label, hint, width)
if width and width ~= 0 then ImGui.SetNextItemWidth(width) end
return ImGui.InputTextWithHint(label, hint, self.InputBuf, 256)
end
function f:Clear() self.InputBuf[1] = 0 end
function f:IsActive() return self.InputBuf[1] ~= 0 and self.InputBuf[1] ~= nil end
function f:PassFilter(text)
local inc, exc = parse(self)
text = string.lower(text)
for _, e in ipairs(exc) do if string.find(text, e, 1, true) then return false end end
if #inc == 0 then return true end
for _, i in ipairs(inc) do if string.find(text, i, 1, true) then return true end end
return false
end
return f
end
----------------------------------------------------------------
-- [SECTION] Demo Window data
----------------------------------------------------------------
--- Data to be shared across different functions of the demo.
function ImGuiDemoWindowData()
return {
-- Examples Apps (accessible from the "Examples" menu)
ShowMainMenuBar = false,
ShowAppAssetsBrowser = false,
ShowAppConsole = false,
ShowAppCustomRendering = false,
ShowAppDocuments = false,
ShowAppDockSpace = false,
ShowAppImageViewer = false,
ShowAppLog = false,
ShowAppLayout = false,
ShowAppPropertyEditor = false,
ShowAppSimpleOverlay = false,
ShowAppAutoResize = false,
ShowAppConstrainedResize = false,
ShowAppFullscreen = false,
ShowAppLongText = false,
ShowAppWindowTitles = false,
-- Dear ImGui Tools (accessible from the "Tools" menu)
ShowMetrics = false,
ShowDebugLog = false,
ShowIDStackTool = false,
ShowStyleEditor = false,
ShowAbout = false,
-- Other data
DisableSections = false,
LiveEditOverride = false,
LiveEditFlags = ImGuiItemFlags.LiveEditOnInputText or 0,
DemoTree = nil,
}
end
----------------------------------------------------------------
-- [SECTION] Helpers: ExampleTreeNode, ExampleMemberInfo (for use by Property Editor & Multi-Select demos)
----------------------------------------------------------------
function ExampleTreeNode()
return {
-- Tree structure
Name = "",
UID = 0,
Parent = nil,
Childs = {}, -- 1-based
IndexInParent = 0, -- 0-based
-- Leaf Data
HasData = false, -- All leaves have data
DataMyBool = true,
DataMyInt = 128,
DataMyVec2 = ImVec2(0.0, 3.141592),
}
end
function ExampleTree_CreateNode(name, uid, parent)
local node = ExampleTreeNode()
node.Name = string.sub(name, 1, 27)
node.UID = uid
node.Parent = parent
node.IndexInParent = parent and #parent.Childs or 0
if parent then
parent.Childs[#parent.Childs + 1] = node
end
return node
end
function ExampleTree_DestroyNode(node) end -- GC
--- Create example tree data
function ExampleTree_CreateDemoTree()
local ROOT_ITEMS_COUNT = 20
local category_names = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pear", "Pineapple", "Strawberry", "Watermelon" }
local category_count = #category_names
local uid = 0
uid = uid + 1
local node_L0 = ExampleTree_CreateNode("<ROOT>", uid, nil)
for idx_L0 = 0, ROOT_ITEMS_COUNT - 1 do
local name_buf = string.format("%s %d", category_names[idx_L0 // (ROOT_ITEMS_COUNT // category_count) + 1], idx_L0 % (ROOT_ITEMS_COUNT // category_count))
uid = uid + 1
local node_L1 = ExampleTree_CreateNode(name_buf, uid, node_L0)
local number_of_childs = #node_L1.Name
for idx_L1 = 0, number_of_childs - 1 do
uid = uid + 1
local node_L2 = ExampleTree_CreateNode(string.format("Child %d", idx_L1), uid, node_L1)
node_L2.HasData = true
if idx_L1 == 0 then
uid = uid + 1
local node_L3 = ExampleTree_CreateNode(string.format("Sub-child %d", 0), uid, node_L2)
node_L3.HasData = true
end
end
end
return node_L0
end
----------------------------------------------------------------
-- [SECTION] Helpers: ExampleImageViewer
----------------------------------------------------------------
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), -- in image space
Zoom = 10.0,
ZoomMin = 1.0,
ZoomMax = 10000.0,
}
end
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
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)
-- Layout canvas
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) -- Add half a pixel padding
end
data.ViewReset = false
-- Handle inputs
if ImGui.SetItemKeyOwner(ImGuiKey.MouseWheelY) then
if io.MouseWheel ~= 0.0 then
data.Zoom = DemoClamp(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
-- Display image
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
-- Display grid lines for visible pixels
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
----------------------------------------------------------------
-- [SECTION] Demo Window / ShowDemoWindow()
----------------------------------------------------------------
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
--- Shows an example app: `if X then X.open = X(open) end`. Example apps return the new p_open.
local function RunApp(fn, key, ...)
if fn then
demo_data[key] = fn(demo_data[key], ...)
if demo_data[key] == nil then demo_data[key] = false end
else
demo_data[key] = false
end
end
local function DemoWindowMenuBar(data)
if ImGui.BeginMenuBar() then
if ImGui.BeginMenu("Menu") then
IMGUI_DEMO_MARKER("Menu/File")
ShowExampleMenuFile()
ImGui.EndMenu()
end
if ImGui.BeginMenu("Examples") then
IMGUI_DEMO_MARKER("Menu/Examples")
_, data.ShowMainMenuBar = ImGui.MenuItem("Main menu bar", nil, data.ShowMainMenuBar)
ImGui.SeparatorText("Mini apps")
_, data.ShowAppAssetsBrowser = ImGui.MenuItem("Assets Browser", nil, data.ShowAppAssetsBrowser)
_, data.ShowAppConsole = ImGui.MenuItem("Console", nil, data.ShowAppConsole)
_, data.ShowAppCustomRendering = ImGui.MenuItem("Custom rendering", nil, data.ShowAppCustomRendering)
_, data.ShowAppDocuments = ImGui.MenuItem("Documents", nil, data.ShowAppDocuments)
_, data.ShowAppDockSpace = ImGui.MenuItem("Dockspace", nil, data.ShowAppDockSpace)
_, data.ShowAppImageViewer = ImGui.MenuItem("Image Viewer", nil, data.ShowAppImageViewer)
_, data.ShowAppLog = ImGui.MenuItem("Log", nil, data.ShowAppLog)
_, data.ShowAppPropertyEditor = ImGui.MenuItem("Property editor", nil, data.ShowAppPropertyEditor)
_, data.ShowAppLayout = ImGui.MenuItem("Simple layout", nil, data.ShowAppLayout)
_, data.ShowAppSimpleOverlay = ImGui.MenuItem("Simple overlay", nil, data.ShowAppSimpleOverlay)
ImGui.SeparatorText("Concepts")
_, data.ShowAppAutoResize = ImGui.MenuItem("Auto-resizing window", nil, data.ShowAppAutoResize)
_, data.ShowAppConstrainedResize = ImGui.MenuItem("Constrained-resizing window", nil, data.ShowAppConstrainedResize)
_, data.ShowAppFullscreen = ImGui.MenuItem("Fullscreen window", nil, data.ShowAppFullscreen)
_, data.ShowAppLongText = ImGui.MenuItem("Long text display", nil, data.ShowAppLongText)
_, data.ShowAppWindowTitles = ImGui.MenuItem("Manipulating window titles", nil, data.ShowAppWindowTitles)
ImGui.EndMenu()
end
if ImGui.BeginMenu("Tools") then
IMGUI_DEMO_MARKER("Menu/Tools")
local io = ImGui.GetIO()
local has_debug_tools = not IMGUI_DISABLE_DEBUG_TOOLS
_, data.ShowMetrics = ImGui.MenuItem("Metrics/Debugger", nil, data.ShowMetrics, has_debug_tools and ImGui.ShowMetricsWindow ~= nil)
if ImGui.BeginMenu("Debug Options") then
ImGui.BeginDisabled(not has_debug_tools)
_, io.ConfigDebugHighlightIdConflicts = ImGui.Checkbox("Highlight ID Conflicts", io.ConfigDebugHighlightIdConflicts)
ImGui.EndDisabled()
_, io.ConfigErrorRecoveryEnableAssert = ImGui.Checkbox("Assert on error recovery", io.ConfigErrorRecoveryEnableAssert)
ImGui.TextDisabled("(see Demo->Configuration for more)")
ImGui.EndMenu()
end
_, data.ShowDebugLog = ImGui.MenuItem("Debug Log", nil, data.ShowDebugLog, has_debug_tools and ImGui.ShowDebugLogWindow ~= nil)
_, data.ShowIDStackTool = ImGui.MenuItem("ID Stack Tool", nil, data.ShowIDStackTool, has_debug_tools and ImGui.ShowIDStackToolWindow ~= nil)
local is_debugger_present = io.ConfigDebugIsDebuggerPresent
if ImGui.MenuItem("Item Picker", nil, false, has_debug_tools and ImGui.DebugStartItemPicker ~= nil) then
ImGui.DebugStartItemPicker()
end
if not is_debugger_present then
ImGui.SetItemTooltip("Requires io.ConfigDebugIsDebuggerPresent=true to be set.\n\nWe otherwise disable some extra features to avoid casual users crashing the application.")
end
_, data.ShowStyleEditor = ImGui.MenuItem("Style Editor", nil, data.ShowStyleEditor)
_, data.ShowAbout = ImGui.MenuItem("About ImGui Sincerely", nil, data.ShowAbout)
ImGui.EndMenu()
end
ImGui.EndMenuBar()
end
end
--- Configuration header contents (split from ShowDemoWindow to keep the function small)
local function DemoWindowConfiguration(io)
local F = ImGuiConfigFlags
local function CF(label, flag)
local pressed
pressed, io.ConfigFlags = ImGui.CheckboxFlags(label, io.ConfigFlags, flag)
return pressed
end
local function CB(label, field)
local pressed
pressed, io[field] = ImGui.Checkbox(label, io[field])
return pressed
end
local function HM(desc) ImGui.SameLine(); HelpMarker(desc) end
if ImGui.TreeNode("Configuration##2") then
IMGUI_DEMO_MARKER("Configuration")
ImGui.SeparatorText("General")
CF("io.ConfigFlags: NavEnableKeyboard", F.NavEnableKeyboard)
HM("Enable keyboard controls.")
CF("io.ConfigFlags: NavEnableGamepad", F.NavEnableGamepad)
HM("Enable gamepad controls. Require backend to set io.BackendFlags |= ImGuiBackendFlags_HasGamepad.\n\nRead instructions in imgui.cpp for details.")
CF("io.ConfigFlags: NoMouse", F.NoMouse)
HM("Instruct dear imgui to disable mouse inputs and interactions.")
-- The "NoMouse" option can get us stuck with a disabled mouse! Let's provide an alternative way to fix it:
if DemoHas(io.ConfigFlags, F.NoMouse) then
if (ImGui.GetTime() % 0.40) < 0.20 then
ImGui.SameLine()
ImGui.Text("<<PRESS SPACE TO DISABLE>>")
end
-- Prevent both being checked
if ImGui.IsKeyPressed(ImGuiKey.Space) or DemoHas(io.ConfigFlags, F.NoKeyboard) then
io.ConfigFlags = bit32.band(io.ConfigFlags, bit32.bnot(F.NoMouse))
end
end
CF("io.ConfigFlags: NoMouseCursorChange", F.NoMouseCursorChange)
HM("Instruct backend to not alter mouse cursor shape and visibility.")
CF("io.ConfigFlags: NoKeyboard", F.NoKeyboard)
HM("Instruct dear imgui to disable keyboard inputs and interactions.")
CB("io.ConfigInputTrickleEventQueue", "ConfigInputTrickleEventQueue")
HM("Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.")
CB("io.MouseDrawCursor", "MouseDrawCursor")
HM("Instruct Dear ImGui to render a mouse cursor itself. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something).")
ImGui.SeparatorText("Keyboard/Gamepad Navigation")
CB("io.ConfigNavSwapGamepadButtons", "ConfigNavSwapGamepadButtons")
CB("io.ConfigNavMoveSetMousePos", "ConfigNavMoveSetMousePos")
HM("Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult")
CB("io.ConfigNavCaptureKeyboard", "ConfigNavCaptureKeyboard")
CB("io.ConfigNavEscapeClearFocusItem", "ConfigNavEscapeClearFocusItem")
HM("Pressing Escape clears focused item.")
CB("io.ConfigNavEscapeClearFocusWindow", "ConfigNavEscapeClearFocusWindow")
HM("Pressing Escape clears focused window.")
CB("io.ConfigNavCursorVisibleAuto", "ConfigNavCursorVisibleAuto")
HM("Using directional navigation key makes the cursor visible. Mouse click hides the cursor.")
CB("io.ConfigNavCursorVisibleAlways", "ConfigNavCursorVisibleAlways")
HM("Navigation cursor is always visible.")
ImGui.SeparatorText("Docking")
CF("io.ConfigFlags: DockingEnable", F.DockingEnable)
ImGui.SameLine()
if io.ConfigDockingWithShift then
HelpMarker("Drag from window title bar or their tab to dock/undock. Hold SHIFT to enable docking.\n\nDrag from window menu button (upper-left button) to undock an entire node (all windows).")
else
HelpMarker("Drag from window title bar or their tab to dock/undock. Hold SHIFT to disable docking.\n\nDrag from window menu button (upper-left button) to undock an entire node (all windows).")
end
if DemoHas(io.ConfigFlags, F.DockingEnable) then
ImGui.Indent()
CB("io.ConfigDockingNoSplit", "ConfigDockingNoSplit")
HM("Simplified docking mode: disable window splitting, so docking is limited to merging multiple windows together into tab-bars.")
CB("io.ConfigDockingNoDockingOver", "ConfigDockingNoDockingOver")
HM("Simplified docking mode: disable window merging into a same tab-bar, so docking is limited to splitting windows.")
CB("io.ConfigDockingWithShift", "ConfigDockingWithShift")
HM("Enable docking when holding Shift only (allow to drop in wider space, reduce visual noise)")
CB("io.ConfigDockingAlwaysTabBar", "ConfigDockingAlwaysTabBar")
HM("Create a docking node and tab-bar on single floating windows.")
CB("io.ConfigDockingTransparentPayload", "ConfigDockingTransparentPayload")
HM("Make window or viewport transparent when docking and only display docking boxes on the target viewport. Useful if rendering of multiple viewport cannot be synced. Best used with ConfigViewportsNoAutoMerge.")
ImGui.Unindent()
end
ImGui.SeparatorText("Multi-viewports")
CF("io.ConfigFlags: ViewportsEnable", F.ViewportsEnable)
HM("[beta] Enable beta multi-viewports support. See ImGuiPlatformIO for details.")
if DemoHas(io.ConfigFlags, F.ViewportsEnable) then
ImGui.Indent()
DemoNotSupported()
ImGui.Unindent()
end
ImGui.SeparatorText("Windows")
CB("io.ConfigWindowsResizeFromEdges", "ConfigWindowsResizeFromEdges")
HM("Enable resizing of windows from their edges and from the lower-left corner.\nThis requires ImGuiBackendFlags_HasMouseCursors for better mouse cursor feedback.")
CB("io.ConfigWindowsMoveFromTitleBarOnly", "ConfigWindowsMoveFromTitleBarOnly")
CB("io.ConfigWindowsCopyContentsWithCtrlC", "ConfigWindowsCopyContentsWithCtrlC") -- [EXPERIMENTAL]
HM("*EXPERIMENTAL* Ctrl+C copy the contents of focused window into the clipboard.\n\nExperimental because:\n- (1) has known issues with nested Begin/End pairs.\n- (2) text output quality varies.\n- (3) text output is in submission order rather than spatial order.")
CB("io.ConfigScrollbarScrollByPage", "ConfigScrollbarScrollByPage")
HM("Enable scrolling page by page when clicking outside the scrollbar grab.\nWhen disabled, always scroll to clicked location.\nWhen enabled, Shift+Click scrolls to clicked location.")
ImGui.SeparatorText("Widgets")
CB("io.ConfigInputTextCursorBlink", "ConfigInputTextCursorBlink")
HM("Enable blinking cursor (optional as some users consider it to be distracting).")
CB("io.ConfigInputTextEnterKeepActive", "ConfigInputTextEnterKeepActive")
HM("Pressing Enter will reactivate item and select all text (single-line only).")
CB("io.ConfigDragClickToInputText", "ConfigDragClickToInputText")
HM("Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving).")
CB("io.ConfigMacOSXBehaviors", "ConfigMacOSXBehaviors")
HM("Swap Cmd<>Ctrl keys, enable various MacOS style behaviors.")
ImGui.Text("Also see Style->Rendering for rendering options.")
ImGui.SeparatorText("Settings")
CB("io.ConfigIniSettingsSaveLastUsedDate", "ConfigIniSettingsSaveLastUsedDate")
-- Also read: https://github.com/ocornut/imgui/wiki/Error-Handling
ImGui.SeparatorText("Error Handling")
CB("io.ConfigErrorRecovery", "ConfigErrorRecovery")
HM(
"Options to configure how we handle recoverable errors.\n" ..
"- Error recovery is not perfect nor guaranteed! It is a feature to ease development.\n" ..
"- You not are not supposed to rely on it in the course of a normal application run.\n" ..
"- Possible usage: facilitate recovery from errors triggered from a scripting language or after specific exceptions handlers.\n" ..
"- Always ensure that on programmers seat you have at minimum Asserts or Tooltips enabled when making direct imgui API call! " ..
"Otherwise it would severely hinder your ability to catch and correct mistakes!")
CB("io.ConfigErrorRecoveryEnableAssert", "ConfigErrorRecoveryEnableAssert")
CB("io.ConfigErrorRecoveryEnableDebugLog", "ConfigErrorRecoveryEnableDebugLog")
CB("io.ConfigErrorRecoveryEnableTooltip", "ConfigErrorRecoveryEnableTooltip")
if not io.ConfigErrorRecoveryEnableAssert and not io.ConfigErrorRecoveryEnableDebugLog and not io.ConfigErrorRecoveryEnableTooltip then
io.ConfigErrorRecoveryEnableAssert = true
io.ConfigErrorRecoveryEnableDebugLog = true
io.ConfigErrorRecoveryEnableTooltip = true
end
-- Also read: https://github.com/ocornut/imgui/wiki/Debug-Tools
ImGui.SeparatorText("Debug")
CB("io.ConfigDebugIsDebuggerPresent", "ConfigDebugIsDebuggerPresent")
HM("Enable various tools calling IM_DEBUG_BREAK().\n\nRequires a debugger being attached, otherwise IM_DEBUG_BREAK() options will appear to crash your application.")
CB("io.ConfigDebugHighlightIdConflicts", "ConfigDebugHighlightIdConflicts")
HM("Highlight and show an error message when multiple items have conflicting identifiers.")
ImGui.BeginDisabled()
CB("io.ConfigDebugBeginReturnValueOnce", "ConfigDebugBeginReturnValueOnce")
ImGui.EndDisabled()
HM("First calls to Begin()/BeginChild() will return false.\n\nTHIS OPTION IS DISABLED because it needs to be set at application boot-time to make sense. Showing the disabled option is a way to make this feature easier to discover.")
CB("io.ConfigDebugBeginReturnValueLoop", "ConfigDebugBeginReturnValueLoop")
HM("Some calls to Begin()/BeginChild() will return false.\n\nWill cycle through window depths then repeat. Windows should be flickering while running.")
CB("io.ConfigDebugIgnoreFocusLoss", "ConfigDebugIgnoreFocusLoss")
HM("Option to deactivate io.AddFocusEvent(false) handling. May facilitate interactions with a debugger when focus loss leads to clearing inputs data.")
CB("io.ConfigDebugDrawListDefaultsToStrokeLegacy", "ConfigDebugDrawListDefaultsToStrokeLegacy")
HM("Option to default all ImDrawList to ImDrawFlags_StrokeLegacy mode, mimicking pre-1.93.0 rendering.")
CB("io.ConfigDebugIniSettings", "ConfigDebugIniSettings")
HM("Option to save .ini data with extra comments (particularly helpful for Docking, but makes saving slower).")
ImGui.TreePop()
ImGui.Spacing()
end
if ImGui.TreeNode("Backend Flags") then
IMGUI_DEMO_MARKER("Configuration/Backend Flags")
HelpMarker(
"Those flags are set by the backends (imgui_impl_xxx files) to specify their capabilities.\n" ..
"Here we expose them as read-only fields to avoid breaking interactions with your backend.")
-- Make a local copy to avoid modifying actual backend flags.
local B = ImGuiBackendFlags
local backend_flags = io.BackendFlags
ImGui.BeginDisabled()
_, backend_flags = ImGui.CheckboxFlags("io.BackendFlags: HasGamepad", backend_flags, B.HasGamepad)
_, backend_flags = ImGui.CheckboxFlags("io.BackendFlags: HasMouseCursors", backend_flags, B.HasMouseCursors)
_, backend_flags = ImGui.CheckboxFlags("io.BackendFlags: HasSetMousePos", backend_flags, B.HasSetMousePos)
_, backend_flags = ImGui.CheckboxFlags("io.BackendFlags: PlatformHasViewports", backend_flags, B.PlatformHasViewports)
_, backend_flags = ImGui.CheckboxFlags("io.BackendFlags: HasMouseHoveredViewport", backend_flags, B.HasMouseHoveredViewport)
_, backend_flags = ImGui.CheckboxFlags("io.BackendFlags: HasParentViewport", backend_flags, B.HasParentViewport)
_, backend_flags = ImGui.CheckboxFlags("io.BackendFlags: RendererHasVtxOffset", backend_flags, B.RendererHasVtxOffset)
_, backend_flags = ImGui.CheckboxFlags("io.BackendFlags: RendererHasTextures", backend_flags, B.RendererHasTextures)
_, backend_flags = ImGui.CheckboxFlags("io.BackendFlags: RendererHasViewports", backend_flags, B.RendererHasViewports)
ImGui.EndDisabled()
ImGui.TreePop()
ImGui.Spacing()
end
if ImGui.TreeNode("Style, Fonts") then
IMGUI_DEMO_MARKER("Configuration/Style, Fonts")
_, demo_data.ShowStyleEditor = ImGui.Checkbox("Style Editor", demo_data.ShowStyleEditor)
ImGui.SameLine()
HelpMarker("The same contents can be accessed in 'Tools->Style Editor' or by calling the ShowStyleEditor() function.")
ImGui.TreePop()
ImGui.Spacing()
end
if ImGui.TreeNode("Capture/Logging") then
IMGUI_DEMO_MARKER("Configuration/Capture, Logging")
HelpMarker(
"The logging API redirects all text output so you can easily capture the content of " ..
"a window or a block. Tree nodes can be automatically expanded.\n" ..
"Try opening any of the contents below in this window and then click one of the \"Log To\" button.")
if ImGui.LogButtons then
ImGui.LogButtons()
else
DemoNotPorted("LogButtons")
end
HelpMarker("You can also call ImGui::LogText() to output directly to the log without a visual output.")
if ImGui.Button("Copy \"Hello, world!\" to clipboard") then
if ImGui.LogToClipboard then
ImGui.LogToClipboard()
ImGui.LogText("Hello, world!")
ImGui.LogFinish()
else
ImGui.SetClipboardText("Hello, world!") -- internal clipboard only on Roblox
end
end
ImGui.TreePop()
end
end
--- Demonstrate most Dear ImGui features (this is big function!)
--- @param p_open? bool
--- @return bool? p_open
function ImGui.ShowDemoWindow(p_open)
IM_ASSERT(ImGui.GetCurrentContext() ~= nil, "Missing Dear ImGui context. Refer to examples app!")
local data = demo_data
-- Examples Apps (accessible from the "Examples" menu)
if data.ShowMainMenuBar then
if ShowExampleAppMainMenuBar then ShowExampleAppMainMenuBar() end
end
if data.ShowAppDockSpace then RunApp(ShowExampleAppDockSpace, "ShowAppDockSpace") end -- Important: Process the Docking app first, as explicit DockSpace() nodes needs to be submitted early (read comments near the DockSpace function)
if data.ShowAppDocuments then RunApp(ShowExampleAppDocuments, "ShowAppDocuments") end -- ...process the Document app next, as it may also use a DockSpace()
if data.ShowAppAssetsBrowser then RunApp(ShowExampleAppAssetsBrowser, "ShowAppAssetsBrowser") end
if data.ShowAppConsole then RunApp(ShowExampleAppConsole, "ShowAppConsole") end
if data.ShowAppCustomRendering then RunApp(ShowExampleAppCustomRendering, "ShowAppCustomRendering") end
if data.ShowAppImageViewer then RunApp(ShowExampleAppImageViewer, "ShowAppImageViewer") end
if data.ShowAppLog then RunApp(ShowExampleAppLog, "ShowAppLog") end
if data.ShowAppLayout then RunApp(ShowExampleAppLayout, "ShowAppLayout") end
if data.ShowAppPropertyEditor then RunApp(ShowExampleAppPropertyEditor, "ShowAppPropertyEditor", data) end
if data.ShowAppSimpleOverlay then RunApp(ShowExampleAppSimpleOverlay, "ShowAppSimpleOverlay") end
if data.ShowAppAutoResize then RunApp(ShowExampleAppAutoResize, "ShowAppAutoResize") end
if data.ShowAppConstrainedResize then RunApp(ShowExampleAppConstrainedResize, "ShowAppConstrainedResize") end
if data.ShowAppFullscreen then RunApp(ShowExampleAppFullscreen, "ShowAppFullscreen") end
if data.ShowAppLongText then RunApp(ShowExampleAppLongText, "ShowAppLongText") end
if data.ShowAppWindowTitles then RunApp(ShowExampleAppWindowTitles, "ShowAppWindowTitles") end
-- Dear ImGui Tools (accessible from the "Tools" menu)
if data.ShowMetrics then RunApp(ImGui.ShowMetricsWindow, "ShowMetrics") end
if data.ShowDebugLog then RunApp(ImGui.ShowDebugLogWindow, "ShowDebugLog") end
if data.ShowIDStackTool then RunApp(ImGui.ShowIDStackToolWindow, "ShowIDStackTool") end
if data.ShowAbout then RunApp(ImGui.ShowAboutWindow, "ShowAbout") end
if data.ShowStyleEditor then
local visible
data.ShowStyleEditor, visible = ImGui.Begin("ImGui Sincerely Style Editor", data.ShowStyleEditor)
if visible then
ImGui.ShowStyleEditor()
end
ImGui.End()
end
-- Demonstrate the various window flags. Typically you would just use the default!
local W = ImGuiWindowFlags
local window_flags = 0
if no_titlebar then window_flags = bit32.bor(window_flags, W.NoTitleBar) end
if no_scrollbar then window_flags = bit32.bor(window_flags, W.NoScrollbar) end
if not no_menu then window_flags = bit32.bor(window_flags, W.MenuBar) end
if no_move then window_flags = bit32.bor(window_flags, W.NoMove) end
if no_resize then window_flags = bit32.bor(window_flags, W.NoResize) end
if no_collapse then window_flags = bit32.bor(window_flags, W.NoCollapse) end
if no_nav then window_flags = bit32.bor(window_flags, W.NoNav) end
if no_background then window_flags = bit32.bor(window_flags, W.NoBackground) end
if no_bring_to_front then window_flags = bit32.bor(window_flags, W.NoBringToFrontOnFocus) end
if no_docking then window_flags = bit32.bor(window_flags, W.NoDocking) end
if unsaved_document then window_flags = bit32.bor(window_flags, W.UnsavedDocument) end
if no_close then p_open = nil end -- Don't pass our bool* to Begin
-- We specify a default position/size in case there's no data in the .ini file.
local main_viewport = ImGui.GetMainViewport()
ImGui.SetNextWindowPos(ImVec2(main_viewport.WorkPos.x + 650, main_viewport.WorkPos.y + 20), ImGuiCond.FirstUseEver)
ImGui.SetNextWindowSize(ImVec2(550, 680), ImGuiCond.FirstUseEver)
-- Main body of the Demo window starts here.
local visible
p_open, visible = ImGui.Begin("ImGui Sincerely Demo", p_open, window_flags)
if no_close then p_open = nil end
if not visible then
-- Early out if the window is collapsed, as an optimization.
ImGui.End()
return p_open
end
-- Most framed widgets share a common width settings. Remaining width is used for the label.
local label_width_base = ImGui.GetFontSize() * 12 -- Some amount of width for label, based on font size.
local label_width_max = ImGui.GetContentRegionAvail().x * 0.40 -- ...but always leave some room for framed widgets.
local label_width = math.min(label_width_base, label_width_max)
ImGui.PushItemWidth(-label_width) -- Right-align: framed items will leave 'label_width' available for the label.
-- Menu Bar
DemoWindowMenuBar(data)
ImGui.Text("ImGui Sincerely says hello! (%s) (%d)", IMGUI_VERSION or "WIP", IMGUI_VERSION_NUM or 0)
ImGui.Spacing()
if ImGui.CollapsingHeader("Help") then
IMGUI_DEMO_MARKER("Help")
ImGui.SeparatorText("ABOUT THIS DEMO:")
ImGui.BulletText("Sections below are demonstrating many aspects of the library.")
ImGui.BulletText("The \"Examples\" menu above leads to more demo contents.")
ImGui.BulletText("The \"Tools\" menu above gives access to: About Box, Style Editor,\n" ..
"and Metrics/Debugger (general purpose Dear ImGui debugging tool).")
ImGui.BulletText("Web demo (w/ source code browser): ")
ImGui.SameLine(0, 0)
ImGui.TextLinkOpenURL("https://pthom.github.io/imgui_explorer")
ImGui.SeparatorText("PROGRAMMER GUIDE:")
ImGui.BulletText("See the ShowDemoWindow() code in imgui_demo.lua. <- you are here!")
ImGui.BulletText("See comments in imgui.lua.")
ImGui.BulletText("See example applications in the examples/ folder.")
ImGui.BulletText("Read the FAQ at ")
ImGui.SameLine(0, 0)
ImGui.TextLinkOpenURL("https://www.dearimgui.com/faq/")
ImGui.BulletText("Set 'io.ConfigFlags |= NavEnableKeyboard' for keyboard controls.")
ImGui.BulletText("Set 'io.ConfigFlags |= NavEnableGamepad' for gamepad controls.")
ImGui.SeparatorText("USER GUIDE:")
ImGui.ShowUserGuide()
end
if ImGui.CollapsingHeader("Configuration") then
DemoWindowConfiguration(ImGui.GetIO())
end
if ImGui.CollapsingHeader("Window options") then
IMGUI_DEMO_MARKER("Window options")
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
-- All demo contents
DemoWindowWidgets(data)
if DemoWindowLayout then DemoWindowLayout() end
if DemoWindowPopups then DemoWindowPopups() end
if DemoWindowTables then DemoWindowTables() end
if DemoWindowInputs then DemoWindowInputs() end
-- End of ShowDemoWindow()
ImGui.PopItemWidth()
ImGui.End()
return p_open
end
----------------------------------------------------------------
-- [SECTION] DemoWindowWidgets()
----------------------------------------------------------------
--- Calls a (global) demo section if it exists, otherwise shows a placeholder
local function Sub(fn, title, ...)
if fn then fn(...) else
if ImGui.TreeNode(title) then DemoNotPorted(title) ImGui.TreePop() end
end
end
function DemoWindowWidgets(data)
if not ImGui.CollapsingHeader("Widgets") then
return
end
-- IMGUI_DEMO_MARKER("Widgets")
local disable_all = data.DisableSections -- The Checkbox for that is inside the "Disabled" section at the bottom
local override_liveedit = data.LiveEditOverride
if disable_all then
ImGui.BeginDisabled()
end
if override_liveedit then
ImGui.PushItemFlag(ImGuiItemFlags.LiveEditOnInputText, DemoHas(data.LiveEditFlags, ImGuiItemFlags.LiveEditOnInputText))
ImGui.PushItemFlag(ImGuiItemFlags.LiveEditOnInputScalar, DemoHas(data.LiveEditFlags, ImGuiItemFlags.LiveEditOnInputScalar))
end
Sub(DemoWindowWidgetsBasic, "Basic")
Sub(DemoWindowWidgetsBullets, "Bullets")
Sub(DemoWindowWidgetsCollapsingHeaders, "Collapsing Headers")
Sub(DemoWindowWidgetsComboBoxes, "Combo")
Sub(DemoWindowWidgetsColorAndPickers, "Color/Picker Widgets")
Sub(DemoWindowWidgetsDataTypes, "Data Types")
if disable_all then
ImGui.EndDisabled()
end
Sub(DemoWindowWidgetsDisableBlocks, "Disable Blocks", data)
if disable_all then
ImGui.BeginDisabled()
end
Sub(DemoWindowWidgetsDragAndDrop, "Drag and Drop")
Sub(DemoWindowWidgetsDragsAndSliders, "Drag/Slider Flags")
Sub(DemoWindowWidgetsFonts, "Fonts")
Sub(DemoWindowWidgetsImages, "Images")
Sub(DemoWindowWidgetsListBoxes, "List Boxes")
Sub(DemoWindowWidgetsLiveEdit, "Live Edit Flags", data)
Sub(DemoWindowWidgetsMixedValues, "Mixed Values")
Sub(DemoWindowWidgetsMultiComponents, "Multi-component Widgets")
Sub(DemoWindowWidgetsPlotting, "Plotting")
Sub(DemoWindowWidgetsProgressBars, "Progress Bars")
Sub(DemoWindowWidgetsQueryingStatuses, "Querying Item Status (Edited/Active/Hovered etc.)")
Sub(DemoWindowWidgetsSelectables, "Selectables")
Sub(DemoWindowWidgetsSelectionAndMultiSelect, "Selection State & Multi-Select", data)
Sub(DemoWindowWidgetsTabs, "Tabs")
Sub(DemoWindowWidgetsText, "Text")
Sub(DemoWindowWidgetsTextFilter, "Text Filter")
Sub(DemoWindowWidgetsTextInput, "Text Input")
Sub(DemoWindowWidgetsTooltips, "Tooltips")
Sub(DemoWindowWidgetsTreeNodes, "Tree Nodes")
Sub(DemoWindowWidgetsVerticalSliders, "Vertical Sliders")
if override_liveedit then
ImGui.PopItemFlag()
ImGui.PopItemFlag()
end
if disable_all then
ImGui.EndDisabled()
end
end
----------------------------------------------------------------
-- [SECTION] User Guide / ShowUserGuide()
----------------------------------------------------------------
function ImGui.ShowUserGuide()
local io = ImGui.GetIO()
ImGui.BulletText("Double-click on title bar to collapse window.")
ImGui.BulletText(
"Click and drag on lower corner or border to resize window.\n" ..
"(double-click to auto fit window to its contents)")
ImGui.BulletText("Ctrl+Click on a slider or drag box to input value as text.")
ImGui.BulletText("Tab/Shift+Tab to cycle through keyboard editable fields.")
ImGui.BulletText("Ctrl+Tab/Ctrl+Shift+Tab to focus windows.")
if io.FontAllowUserScaling then
ImGui.BulletText("Ctrl+Mouse Wheel to zoom window contents.")
end
ImGui.BulletText("While inputting text:\n")
ImGui.Indent()
ImGui.BulletText("Ctrl+Left/Right to word jump.")
ImGui.BulletText("Ctrl+A or double-click to select all.")
ImGui.BulletText("Ctrl+X/C/V to use clipboard cut/copy/paste.")
ImGui.BulletText("Ctrl+Z to undo, Ctrl+Y/Ctrl+Shift+Z to redo.")
ImGui.BulletText("Escape to revert.")
ImGui.Unindent()
ImGui.BulletText("With Keyboard controls enabled:")
ImGui.Indent()
ImGui.BulletText("Arrow keys or Home/End/PageUp/PageDown to navigate.")
ImGui.BulletText("Space to activate a widget.")
ImGui.BulletText("Return to input text into a widget.")
ImGui.BulletText("Escape to deactivate a widget, close popup,\nexit a child window or the menu layer, clear focus.")
ImGui.BulletText("Alt to jump to the menu layer of a window.")
ImGui.BulletText("Menu or Shift+F10 to open a context menu.")
ImGui.Unindent()
ImGui.BulletText("With Gamepad controls enabled:")
ImGui.Indent()
ImGui.BulletText("D-Pad: Navigate / Tweak / Resize (in Windowing mode).")
ImGui.BulletText("%s Face button: Activate / Open / Toggle. Hold: activate with text input.", io.ConfigNavSwapGamepadButtons and "East" or "South")
ImGui.BulletText("%s Face button: Cancel / Close / Exit.", io.ConfigNavSwapGamepadButtons and "South" or "East")
ImGui.BulletText("West Face button: Toggle Menu. Hold for Windowing mode (Focus/Move/Resize windows).")
ImGui.BulletText("North Face button: Open Context Menu.")
ImGui.BulletText("L1/R1: Tweak Slower/Faster, Focus Previous/Next (in Windowing Mode).")
ImGui.Unindent()
end
return true -- [Roblox] ModuleScripts must return exactly one value
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-289
View File
@@ -1,289 +0,0 @@
--- ImGui Sincerely
-- Drag and drop: 1:1 port of imgui.cpp [SECTION] DRAG AND DROP (docking branch)
-- Payload `Data` is any Lua value (no copy is made). `data_size` is optional and only kept for API parity.
function ImGui.IsDragDropActive()
return ImGui.GetCurrentContext().DragDropActive
end
function ImGui.ClearDragDrop()
local g = ImGui.GetCurrentContext()
g.DragDropActive = false
ImGuiPayload_Clear(g.DragDropPayload)
g.DragDropAcceptFlagsCurr = ImGuiDragDropFlags.None
g.DragDropAcceptIdCurr = 0
g.DragDropAcceptIdPrev = 0
g.DragDropAcceptIdCurrRectSurface = FLT_MAX
g.DragDropAcceptFrameCount = -1
end
function ImGui.BeginDragDropSource(flags)
if flags == nil then flags = 0 end
local g = ImGui.GetCurrentContext()
local window = g.CurrentWindow
local mouse_button = ImGuiMouseButton.Left
local source_drag_active = false
local source_id = 0
local source_parent_id = 0
if bit32.band(flags, ImGuiDragDropFlags.SourceExtern) == 0 then
source_id = g.LastItemData.ID
if source_id ~= 0 then
if g.ActiveId ~= source_id then return false end
if g.ActiveIdMouseButton ~= -1 then mouse_button = g.ActiveIdMouseButton end
if g.IO.MouseDown[mouse_button] == false or window.SkipItems then return false end
g.ActiveIdAllowOverlap = false
else
if g.IO.MouseDown[mouse_button] == false or window.SkipItems then return false end
if bit32.band(g.LastItemData.StatusFlags, ImGuiItemStatusFlags.HoveredRect) == 0 and (g.ActiveId == 0 or g.ActiveIdWindow ~= window) then
return false
end
if bit32.band(flags, ImGuiDragDropFlags.SourceAllowNullID) == 0 then
IM_ASSERT(false, "Use ImGuiDragDropFlags.SourceAllowNullID for items without an ID")
return false
end
source_id = window:GetIDFromRectangle(g.LastItemData.Rect)
g.LastItemData.ID = source_id
ImGui.KeepAliveID(source_id)
local is_hovered = ImGui.ItemHoverable(g.LastItemData.Rect, source_id, g.LastItemData.ItemFlags)
if is_hovered and g.IO.MouseClicked[mouse_button] then
ImGui.SetActiveID(source_id, window)
ImGui.FocusWindow(window)
end
if g.ActiveId == source_id then g.ActiveIdAllowOverlap = is_hovered end
end
if g.ActiveId ~= source_id then return false end
source_parent_id = window.IDStack.Data[window.IDStack.Size]
source_drag_active = ImGui.IsMouseDragging(mouse_button)
ImGui.SetActiveIdUsingAllKeyboardKeys()
else
window = nil
source_id = ImHashStr("#SourceExtern")
source_drag_active = true
mouse_button = g.IO.MouseDown[0] and 0 or -1
ImGui.KeepAliveID(source_id)
ImGui.SetActiveID(source_id, nil)
end
IM_ASSERT(g.DragDropWithinTarget == false)
if not source_drag_active then return false end
if not g.DragDropActive then
IM_ASSERT(source_id ~= 0)
ImGui.ClearDragDrop()
local payload = g.DragDropPayload
payload.SourceId = source_id
payload.SourceParentId = source_parent_id
g.DragDropActive = true
g.DragDropSourceFlags = flags
g.DragDropMouseButton = mouse_button
if payload.SourceId == g.ActiveId then g.ActiveIdNoClearOnFocusLoss = true end
end
g.DragDropSourceFrameCount = g.FrameCount
g.DragDropWithinSource = true
if bit32.band(flags, ImGuiDragDropFlags.SourceNoPreviewTooltip) == 0 then
local ret
if g.DragDropAcceptIdPrev ~= 0 and bit32.band(g.DragDropAcceptFlagsPrev, ImGuiDragDropFlags.AcceptNoPreviewTooltip) ~= 0 then
ret = ImGui.BeginTooltipHidden()
else
ret = ImGui.BeginTooltip()
end
IM_ASSERT(ret)
end
if bit32.band(flags, ImGuiDragDropFlags.SourceNoDisableHover) == 0 and bit32.band(flags, ImGuiDragDropFlags.SourceExtern) == 0 then
g.LastItemData.StatusFlags = bit32.band(g.LastItemData.StatusFlags, bit32.bnot(ImGuiItemStatusFlags.HoveredRect))
end
return true
end
function ImGui.EndDragDropSource()
local g = ImGui.GetCurrentContext()
IM_ASSERT(g.DragDropActive)
IM_ASSERT(g.DragDropWithinSource, "Not after a BeginDragDropSource()?")
if bit32.band(g.DragDropSourceFlags, ImGuiDragDropFlags.SourceNoPreviewTooltip) == 0 then
ImGui.EndTooltip()
end
if g.DragDropPayload.DataFrameCount == -1 then ImGui.ClearDragDrop() end
g.DragDropWithinSource = false
end
--- @param data any # any Lua value
--- @return bool accepted
function ImGui.SetDragDropPayload(type, data, data_size, cond)
local g = ImGui.GetCurrentContext()
local payload = g.DragDropPayload
if cond == nil or cond == 0 then cond = ImGuiCond.Always end
IM_ASSERT(type ~= nil)
IM_ASSERT(#type < 32, "Payload type can be at most 32 characters long")
IM_ASSERT(cond == ImGuiCond.Always or cond == ImGuiCond.Once)
IM_ASSERT(payload.SourceId ~= 0)
if cond == ImGuiCond.Always or payload.DataFrameCount == -1 then
payload.DataType = type
payload.Data = data
payload.DataSize = data_size or ((data ~= nil) and 1 or 0)
end
payload.DataFrameCount = g.FrameCount
return (g.DragDropAcceptFrameCount == g.FrameCount) or (g.DragDropAcceptFrameCount == g.FrameCount - 1)
end
function ImGui.BeginDragDropTargetCustom(bb, id)
local g = ImGui.GetCurrentContext()
if not g.DragDropActive then return false end
local window = g.CurrentWindow
local hovered_window = g.HoveredWindowUnderMovingWindow
if hovered_window == nil or window.RootWindowDockTree ~= hovered_window.RootWindowDockTree then return false end
IM_ASSERT(id ~= 0)
if not ImGui.IsMouseHoveringRect(bb.Min, bb.Max) or (id == g.DragDropPayload.SourceId) then return false end
if window.SkipItems then return false end
IM_ASSERT(g.DragDropWithinTarget == false and g.DragDropWithinSource == false)
g.DragDropTargetRect = ImRect(bb.Min, bb.Max)
g.DragDropTargetClipRect = ImRect(window.ClipRect.Min, window.ClipRect.Max)
g.DragDropTargetId = id
g.DragDropTargetFullViewport = 0
g.DragDropWithinTarget = true
return true
end
function ImGui.BeginDragDropTargetViewport(viewport, p_bb)
local g = ImGui.GetCurrentContext()
if not g.DragDropActive then return false end
local bb = p_bb or viewport:GetWorkRect()
local id = viewport.ID
if g.MouseViewport ~= viewport or not ImGui.IsMouseHoveringRect(bb.Min, bb.Max, false) or (id == g.DragDropPayload.SourceId) then
return false
end
IM_ASSERT(g.DragDropWithinTarget == false and g.DragDropWithinSource == false)
g.DragDropTargetRect = ImRect(bb.Min, bb.Max)
g.DragDropTargetClipRect = ImRect(bb.Min, bb.Max)
g.DragDropTargetId = id
g.DragDropTargetFullViewport = id
g.DragDropWithinTarget = true
return true
end
function ImGui.BeginDragDropTarget()
local g = ImGui.GetCurrentContext()
if not g.DragDropActive then return false end
local window = g.CurrentWindow
if bit32.band(g.LastItemData.StatusFlags, ImGuiItemStatusFlags.HoveredRect) == 0 then return false end
local hovered_window = g.HoveredWindowUnderMovingWindow
if hovered_window == nil or window.RootWindowDockTree ~= hovered_window.RootWindowDockTree or window.SkipItems then return false end
local display_rect = (bit32.band(g.LastItemData.StatusFlags, ImGuiItemStatusFlags.HasDisplayRect) ~= 0) and g.LastItemData.DisplayRect or g.LastItemData.Rect
local id = g.LastItemData.ID
if id == 0 then
id = window:GetIDFromRectangle(display_rect)
ImGui.KeepAliveID(id)
end
if g.DragDropPayload.SourceId == id then return false end
IM_ASSERT(g.DragDropWithinTarget == false and g.DragDropWithinSource == false)
g.DragDropTargetRect = ImRect(display_rect.Min, display_rect.Max)
local clip = (bit32.band(g.LastItemData.StatusFlags, ImGuiItemStatusFlags.HasClipRect) ~= 0) and g.LastItemData.ClipRect or window.ClipRect
g.DragDropTargetClipRect = ImRect(clip.Min, clip.Max)
g.DragDropTargetId = id
g.DragDropWithinTarget = true
return true
end
function ImGui.IsDragDropPayloadBeingAccepted()
local g = ImGui.GetCurrentContext()
return g.DragDropActive and g.DragDropAcceptIdPrev ~= 0
end
--- @return ImGuiPayload?
function ImGui.AcceptDragDropPayload(type, flags)
if flags == nil then flags = 0 end
local g = ImGui.GetCurrentContext()
local payload = g.DragDropPayload
IM_ASSERT(g.DragDropActive)
IM_ASSERT(payload.DataFrameCount ~= -1)
if type ~= nil and not ImGuiPayload_IsDataType(payload, type) then return nil end
local was_accepted_previously = (g.DragDropAcceptIdPrev == g.DragDropTargetId)
local r = g.DragDropTargetRect
local r_surface = r:GetWidth() * r:GetHeight()
if r_surface > g.DragDropAcceptIdCurrRectSurface then return nil end
g.DragDropAcceptFlagsCurr = flags
g.DragDropAcceptIdCurr = g.DragDropTargetId
g.DragDropAcceptIdCurrRectSurface = r_surface
payload.Preview = was_accepted_previously
flags = bit32.bor(flags, bit32.band(g.DragDropSourceFlags, ImGuiDragDropFlags.AcceptNoDrawDefaultRect))
local draw_target_rect = payload.Preview and bit32.band(flags, ImGuiDragDropFlags.AcceptNoDrawDefaultRect) == 0
if draw_target_rect and g.DragDropTargetFullViewport ~= 0 then
ImGui.RenderDragDropTargetRectForViewport(g.DragDropTargetFullViewport, g.DragDropTargetRect)
elseif draw_target_rect then
ImGui.RenderDragDropTargetRectForItem(r)
end
g.DragDropAcceptFrameCount = g.FrameCount
if bit32.band(g.DragDropSourceFlags, ImGuiDragDropFlags.SourceExtern) ~= 0 and g.DragDropMouseButton == -1 then
payload.Delivery = was_accepted_previously and (g.DragDropSourceFrameCount < g.FrameCount)
else
payload.Delivery = was_accepted_previously and not ImGui.IsMouseDown(g.DragDropMouseButton)
end
if not payload.Delivery and bit32.band(flags, ImGuiDragDropFlags.AcceptBeforeDelivery) == 0 then return nil end
return payload
end
function ImGui.RenderDragDropTargetRectForItem(bb)
local g = ImGui.GetCurrentContext()
local window = g.CurrentWindow
local bb_display = ImRect(bb.Min, bb.Max)
bb_display:ClipWith(g.DragDropTargetClipRect)
bb_display:Expand(g.Style.DragDropTargetPadding)
local push_clip_rect = not window.ClipRect:Contains(bb_display)
if push_clip_rect then window.DrawList:PushClipRectFullScreen() end
ImGui.RenderDragDropTargetRectEx(window.DrawList, bb_display, g.Style.DragDropTargetRounding)
if push_clip_rect then window.DrawList:PopClipRect() end
end
function ImGui.RenderDragDropTargetRectForViewport(viewport_id, bb)
local g = ImGui.GetCurrentContext()
local viewport = ImGui.FindViewportByID(viewport_id)
IM_ASSERT(viewport ~= nil)
local bb_padded = ImRect(bb.Min, bb.Max)
bb_padded:Expand(-g.Style.DragDropTargetPadding)
ImGui.RenderDragDropTargetRectEx(ImGui.GetForegroundDrawList(viewport), bb_padded, g.Style.DragDropTargetRounding)
end
function ImGui.RenderDragDropTargetRectEx(draw_list, bb, rounding)
local g = ImGui.GetCurrentContext()
draw_list:AddRectFilled(bb.Min, bb.Max, ImGui.GetColorU32(ImGuiCol.DragDropTargetBg), rounding, 0)
draw_list:AddRect(bb.Min, bb.Max, ImGui.GetColorU32(ImGuiCol.DragDropTarget), rounding, g.Style.DragDropTargetBorderSize)
end
--- @return ImGuiPayload?
function ImGui.GetDragDropPayload()
local g = ImGui.GetCurrentContext()
return (g.DragDropActive and g.DragDropPayload.DataFrameCount ~= -1) and g.DragDropPayload or nil
end
function ImGui.EndDragDropTarget()
local g = ImGui.GetCurrentContext()
IM_ASSERT(g.DragDropActive)
IM_ASSERT(g.DragDropWithinTarget)
g.DragDropWithinTarget = false
if g.DragDropPayload.Delivery then ImGui.ClearDragDrop() end
end
-- Payload methods (C++ ImGuiPayload members): payload:IsDataType(t) etc. also work through these globals
function ImGui.PayloadIsDataType(payload, t) return ImGuiPayload_IsDataType(payload, t) end
return true
-1164
View File
File diff suppressed because it is too large Load Diff
+7282
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -2953,11 +2953,11 @@ function MT.ImFontAtlas:AddFontFromFileTTF(filename, size_pixels, font_cfg_templ
end
function GetDefaultFontDataProggyClean()
return ImStd.ImFileLoadToMemory("resource/fonts/ProggyClean.ttf", "rb")
return ImStd.ImFileLoadToMemory("fonts/ProggyClean.ttf", "rb")
end
function GetDefaultFontDataProggyForever()
return ImStd.ImFileLoadToMemory("resource/fonts/ProggyForever.ttf", "rb")
return ImStd.ImFileLoadToMemory("fonts/ProggyForever.ttf", "rb")
end
-- TODO: IMGUI_DISABLE_DEFAULT_FONT, IMGUI_DISABLE_DEFAULT_FONT_BITMAP
View File
File diff suppressed because it is too large Load Diff
+11 -8
View File
@@ -1,26 +1,29 @@
#!/usr/bin/env python3
# Bundles imgui/*.lua + backend into ONE ModuleScript: build/ImGui.luau
# Bundles the root *.lua (library + imgui_demo.lua), backends/ and fonts/ into ONE ModuleScript: build/ImGui.luau
# --no-demo: library only (imgui_demo.lua left out, like not compiling imgui_demo.cpp)
# Why: ModuleScripts don't share globals, and the setfenv() alternative turns off Luau's fast paths / native codegen.
# Each source file becomes a function in __FILES; IM_INCLUDE(name) runs it once and caches the result.
# The module returns a table with every global the library defines (ImGui, ImVec2, ImGuiConfigFlags, ImGui_ImplRoblox, ...).
import os, re
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SRC = os.path.join(ROOT, "imgui")
import sys
NO_DEMO = "--no-demo" in sys.argv
sys.argv = [a for a in sys.argv if a != "--no-demo"]
FILES = {}
for dp, _, fn in os.walk(SRC):
for f in sorted(fn):
if f.endswith(".lua"):
FILES[f] = open(os.path.join(dp, f)).read()
for d in (ROOT, os.path.join(ROOT, "backends"), os.path.join(ROOT, "fonts")):
for f in sorted(os.listdir(d)):
if f.endswith(".lua") and not (NO_DEMO and f == "imgui_demo.lua"):
FILES[f] = open(os.path.join(d, f)).read()
ENTRY = ["imgui.lua", "imgui_impl_roblox.lua"] + sorted(f for f in FILES if f.startswith("imgui_demo")) # run order
ENTRY = ["imgui.lua", "imgui_impl_roblox.lua"] + ([] if NO_DEMO else ["imgui_demo.lua"]) # run order
names = set()
for src in FILES.values():
names.update(re.findall(r"^function ([A-Za-z_]\w*)\s*\(", src, re.M))
names.update(re.findall(r"^([A-Za-z_]\w*)\s*=[^=]", src, re.M))
out = ["--!optimize 2", "-- GENERATED by tools/bundle.py from imgui/*.lua - do not edit", "",
out = ["--!optimize 2", "-- GENERATED by tools/bundle.py from *.lua, backends/, fonts/ - do not edit", "",
"local __FILES, __LOADED = {}, {}",
"function IM_INCLUDE(name)",
" local r = __LOADED[name]",
+2 -2
View File
@@ -7,9 +7,9 @@ import os, re, sys
HERE = os.path.dirname(os.path.abspath(__file__))
ROOT = os.path.dirname(os.path.dirname(HERE))
port = set()
for f in os.listdir(os.path.join(ROOT, "imgui")):
for f in os.listdir(ROOT):
if f.endswith(".lua"):
port.update(re.findall(r"function ImGui[.:](\w+)", open(os.path.join(ROOT, "imgui", f)).read()))
port.update(re.findall(r"function ImGui[.:](\w+)", open(os.path.join(ROOT, f)).read()))
filt = sys.argv[1] if len(sys.argv) > 1 else None
for f in sorted(os.listdir(os.path.join(HERE, "upstream"))):
if not f.endswith(".cpp") or f == "imgui_demo.cpp": continue
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# Summarise profile.out from `run.py --profile`: top functions by self and inclusive samples, mapped to imgui/*.lua lines
# Summarise profile.out from `run.py --profile`: top functions by self and inclusive samples, mapped to source file lines
import collections, json, os, re, sys, glob
path = sys.argv[1] if len(sys.argv) > 1 else "profile.out"
tmp = max(glob.glob("/tmp/imgui_test_*/ImGui.linemap.json"), key=os.path.getmtime)
+2 -2
View File
@@ -180,10 +180,10 @@ G.ImGui.TreeNode = function(...)
if ARG_OPEN == true or (type(ARG_OPEN) == "table" and ARG_OPEN[(...)]) then G.ImGui.SetNextItemOpen(true, G.ImGuiCond.Always) end
return realTN(...)
end
G.ImGui.ShowDemoWindow = function(...)
if realDemo then G.ImGui.ShowDemoWindow = function(...)
if ARG_BIG then G.ImGui.SetNextWindowSize(G.ImVec2(900, 1000), G.ImGuiCond.Always) end
return realDemo(...)
end
end end
local realRender = G.ImGui_ImplRoblox.RenderDrawData
G.ImGui_ImplRoblox.RenderDrawData = function(dd)
if FORCE then G.ImGui.GetIO().BackendPlatformUserData.ForceRedraw = true end
-36490
View File
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -2,7 +2,7 @@
"""Headless test harness: runs build/ImGui.luau + a main script in the Luau CLI against a mocked Roblox
(roblox_mock.luau). Rebuilds the bundle first.
python3 tools/test/run.py # 400 frames of main.client.luau, scripted random input
python3 tools/test/run.py # 400 frames of examples/example_roblox/main.client.luau, scripted random input
python3 tools/test/run.py --open # force every CollapsingHeader/TreeNode open (exercises whole demo)
python3 tools/test/run.py --main my_test.luau # different LocalScript
"""
@@ -15,7 +15,7 @@ LUAU = shutil.which("luau") or "/nix/store/2m2ja613nndihc8qm10f2rhq6znp1nh4-luau
G = "game, workspace, Instance, Enum, Vector2, Vector3, UDim2, Color3, Content, warn, require, script, os"
def build_run(args, flags):
subprocess.run([sys.executable, os.path.join(ROOT, "tools", "bundle.py"), TMP], check=True, stdout=subprocess.DEVNULL)
subprocess.run([sys.executable, os.path.join(ROOT, "tools", "bundle.py"), TMP] + (["--no-demo"] if os.environ.get("NO_DEMO") else []), check=True, stdout=subprocess.DEVNULL)
out = ["--" if args.roblox else "--!native", "--!optimize 2", flags, "local SOURCE_FNS = {}"]
def add(key, path):
s = "\n".join(l for l in open(path).read().split("\n") if not l.startswith("--!"))
@@ -39,7 +39,7 @@ def run(args, extra=""):
return p.returncode, remap(p.stdout + p.stderr)
def remap(text):
"""run.luau:N -> imgui/<file>.lua:M"""
"""run.luau:N -> <file>.lua:M"""
import json, re
lm = json.load(open(os.path.join(TMP, "ImGui.linemap.json")))
def sub(m):
@@ -56,7 +56,7 @@ def remap(text):
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--frames", type=int, default=400)
ap.add_argument("--main", default=os.path.join(ROOT, "main.client.luau"))
ap.add_argument("--main", default=os.path.join(ROOT, "examples", "example_roblox", "main.client.luau"))
ap.add_argument("--big", action="store_true", help="demo window forced to 900x1000")
ap.add_argument("--roblox", action="store_true", help="like Studio: only @native functions get native code (default: whole bundle native)")
ap.add_argument("--open-only", default="", help="comma list of CollapsingHeader/TreeNode labels to force open, e.g. Widgets,Basic")
+14
View File
@@ -0,0 +1,14 @@
-- Library without imgui_demo.lua: run with NO_DEMO=1 (bundle --no-demo). Window + Metrics/Debug Log/ID Stack tools must work.
local G = require(game:GetService("ReplicatedStorage"):WaitForChild("ImGui"))
local ImGui = G.ImGui
ImGui.CreateContext(); G.ImGui_ImplRoblox.Init()
assert(ImGui.ShowDemoWindow == nil, "demo was bundled")
local f = 0
game:GetService("RunService").Stepped:Connect(function()
f += 1
G.ImGui_ImplRoblox.NewFrame(); ImGui.NewFrame()
ImGui.Begin("W"); ImGui.Text("hi"); ImGui.Button("b"); ImGui.End()
ImGui.ShowMetricsWindow(); ImGui.ShowDebugLogWindow(); ImGui.ShowIDStackToolWindow()
ImGui.Render(); G.ImGui_ImplRoblox.RenderDrawData(ImGui.GetDrawData())
if f == 20 then print("NODEMO OK") end
end)
+6 -4
View File
@@ -1,14 +1,16 @@
#!/usr/bin/env python3
"""Static check: ImGui.X / ImGui:X / global ImFoo() calls in imgui/*.lua that nothing defines.
"""Static check: ImGui.X / ImGui:X / global ImFoo() calls in the library *.lua files that nothing defines.
python3 tools/test/undefined.py
"""
import os, re, collections
ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
SRC = os.path.join(ROOT, "imgui")
SRC = ROOT # library *.lua at the root + backends/ (--no-demo: leave imgui_demo.lua out to check the library never needs it)
import sys
NO_DEMO = "--no-demo" in sys.argv
files = {}
for dp, _, fn in os.walk(SRC):
for dp, fn in ((ROOT, os.listdir(ROOT)), (os.path.join(ROOT, "backends"), os.listdir(os.path.join(ROOT, "backends")))):
for f in fn:
if f.endswith(".lua"):
if f.endswith(".lua") and not (NO_DEMO and f == "imgui_demo.lua"):
files[os.path.relpath(os.path.join(dp, f), SRC)] = open(os.path.join(dp, f)).read()
def strip(s): # drop comments and strings (roughly) so we don't report text