CI/releases: drop the nodemo bundles (--no-demo build flag kept); remove examples/example_shared; Roblox backend RenderRate defaults to 60 (0 = every frame); README + TODO.txt updated
This commit is contained in:
+3
-5
@@ -151,7 +151,7 @@ Backend options:
|
|||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `ImGui_ImplRoblox.Init(parent, render_scale)` | `render_scale` = your OS display scale renders at physical-pixel resolution (crisper, same size as desktop imgui). |
|
| `ImGui_ImplRoblox.Init(parent, render_scale)` | `render_scale` = your OS display scale renders at physical-pixel resolution (crisper, same size as desktop imgui). |
|
||||||
| `ImGui_ImplRoblox.SetRenderScale(scale)` | Change it at runtime. |
|
| `ImGui_ImplRoblox.SetRenderScale(scale)` | Change it at runtime. |
|
||||||
| `ImGui_ImplRoblox.SetRenderRate(hz)` | Max tile redraws per second (default `0` = every frame). Your code still runs every frame. |
|
| `ImGui_ImplRoblox.SetRenderRate(hz)` | Max tile redraws per second (default `60`; `0` = every frame). Your code still runs every frame. |
|
||||||
| `ImGui_ImplRoblox.SetRedrawBudget(ms)` | Max milliseconds per frame spent redrawing changed tiles (opt-in; default `0` = no limit, every change is drawn the same frame). With a budget, tiles over it keep their old pixels for a few frames, so big changes are spread over frames instead of one long frame (parts of the UI may update a frame or two apart). |
|
| `ImGui_ImplRoblox.SetRedrawBudget(ms)` | Max milliseconds per frame spent redrawing changed tiles (opt-in; default `0` = no limit, every change is drawn the same frame). With a budget, tiles over it keep their old pixels for a few frames, so big changes are spread over frames instead of one long frame (parts of the UI may update a frame or two apart). |
|
||||||
| `ImGui_ImplRoblox.SetBusyRenderRate(hz)` | Optional lower redraw rate while scrolling, resizing or moving windows (default off). |
|
| `ImGui_ImplRoblox.SetBusyRenderRate(hz)` | Optional lower redraw rate while scrolling, resizing or moving windows (default off). |
|
||||||
| `ImGui_ImplRoblox.SetProfiling(true)` | MicroProfiler (Ctrl+F6) labels for every backend stage. |
|
| `ImGui_ImplRoblox.SetProfiling(true)` | MicroProfiler (Ctrl+F6) labels for every backend stage. |
|
||||||
@@ -179,7 +179,7 @@ The cost is CPU time in Luau, so the backend is built around **not drawing**:
|
|||||||
3. **Scrolling reuses pixels.** Window content is a separate layer inside a `ClipsDescendants` frame sized to the window's visible area, positioned at the scroll offset. Scrolling moves it like dragging moves a window; only rows entering view are drawn. Decorations (title bar, borders, scrollbar) stay in their own layers.
|
3. **Scrolling reuses pixels.** Window content is a separate layer inside a `ClipsDescendants` frame sized to the window's visible area, positioned at the scroll offset. Scrolling moves it like dragging moves a window; only rows entering view are drawn. Decorations (title bar, borders, scrollbar) stay in their own layers.
|
||||||
4. **Skipping unchanged windows.** Vertices are stored in a flat Luau `buffer` (36 bytes each) instead of tables. Before any per-tile work, a window's raw vertex/index bytes are compared with last frame's; if identical, its layers are just restacked.
|
4. **Skipping unchanged windows.** Vertices are stored in a flat Luau `buffer` (36 bytes each) instead of tables. Before any per-tile work, a window's raw vertex/index bytes are compared with last frame's; if identical, its layers are just restacked.
|
||||||
5. **Fast rasterizer.** `@native` functions; axis-aligned quads (most rects and every glyph) take a span-fill path, flat rows are copied instead of re-blended, gradient rects (color pickers) are filled per row, and only real triangles (anti-aliased edges, curves) use the generic edge-function rasterizer.
|
5. **Fast rasterizer.** `@native` functions; axis-aligned quads (most rects and every glyph) take a span-fill path, flat rows are copied instead of re-blended, gradient rects (color pickers) are filled per row, and only real triangles (anti-aliased edges, curves) use the generic edge-function rasterizer.
|
||||||
6. **Redraw budget.** Changed tiles are redrawn in the frame they change. Optionally, `SetRedrawBudget(ms)` caps the redraw time per frame; tiles over it keep their old pixels and follow on the next frames. Optionally capped with `SetRenderRate(hz)` / `SetBusyRenderRate(hz)`. Your UI code and Dear ImGui's logic still run every frame, so input is never dropped.
|
6. **Redraw budget.** Changed tiles are redrawn in the frame they change. Optionally, `SetRedrawBudget(ms)` caps the redraw time per frame; tiles over it keep their old pixels and follow on the next frames. Redraws are capped at 60 per second by default (`SetRenderRate(hz)`, `0` = uncapped), optionally lower while busy with `SetBusyRenderRate(hz)`. Your UI code and Dear ImGui's logic still run every frame, so input is never dropped.
|
||||||
|
|
||||||
**Input.** Mouse and keys come from `UserInputService`. While the mouse is over Dear ImGui (`io.WantCaptureMouse`), the tiles are `Active`, so clicks and the wheel don't reach the game (camera zoom). Typing comes from key codes by default (printable ASCII). Call `ImGui_ImplRoblox.SetTextProxy(true)` to opt in to a hidden `TextBox` that holds focus while a text field is active: the OS then delivers typing (any layout), paste and copy/cut through it, and its text mirrors Dear ImGui's current selection. Fonts are TTFs rasterized by the ported stb_truetype into the font atlas, which becomes a backend texture like any image (`CreateTexture` works for your own pixels too).
|
**Input.** Mouse and keys come from `UserInputService`. While the mouse is over Dear ImGui (`io.WantCaptureMouse`), the tiles are `Active`, so clicks and the wheel don't reach the game (camera zoom). Typing comes from key codes by default (printable ASCII). Call `ImGui_ImplRoblox.SetTextProxy(true)` to opt in to a hidden `TextBox` that holds focus while a text field is active: the OS then delivers typing (any layout), paste and copy/cut through it, and its text mirrors Dear ImGui's current selection. Fonts are TTFs rasterized by the ported stb_truetype into the font atlas, which becomes a backend texture like any image (`CreateTexture` works for your own pixels too).
|
||||||
|
|
||||||
@@ -205,12 +205,10 @@ love examples/example_love
|
|||||||
|
|
||||||
Roblox stays the primary target: the Roblox build is untouched by this (no shims, `@native` kept); the LÖVE build strips `@native` and adds small `bit32`/`buffer`/`utf8`/`table` shims (the COMPAT section of [backends/imgui_impl_love.lua](/backends/imgui_impl_love.lua)). `tools/test/love/run.sh` checks that LuaJIT produces exactly the same draw data as Luau.
|
Roblox stays the primary target: the Roblox build is untouched by this (no shims, `@native` kept); the LÖVE build strips `@native` and adds small `bit32`/`buffer`/`utf8`/`table` shims (the COMPAT section of [backends/imgui_impl_love.lua](/backends/imgui_impl_love.lua)). `tools/test/love/run.sh` checks that LuaJIT produces exactly the same draw data as Luau.
|
||||||
|
|
||||||
[examples/example_shared/app.lua](/examples/example_shared/app.lua) is one UI that runs unchanged on both: `roblox.client.luau` (Rojo: `examples/example_shared/default.project.json`) and `main.lua` (`love examples/example_shared`) are the only platform code. Write shared UI code in plain Lua 5.1 syntax (no `+=`, `//`, `continue`).
|
|
||||||
|
|
||||||
#### Prebuilt releases
|
#### Prebuilt releases
|
||||||
|
|
||||||
Every push to `master` publishes a rolling `latest` release, and every `v*` tag a versioned release ([.github/workflows/release.yml](/.github/workflows/release.yml)), with:
|
Every push to `master` publishes a rolling `latest` release, and every `v*` tag a versioned release ([.github/workflows/release.yml](/.github/workflows/release.yml)), with:
|
||||||
`ImGui.luau` / `ImGui-nodemo.luau` (Roblox ModuleScript), `imgui_love.lua` / `imgui_love-nodemo.lua` (LÖVE), and `imgui-luau-roblox-*.zip` / `imgui-luau-love-*.zip` (bundle + examples).
|
`ImGui.luau` (Roblox ModuleScript), `imgui_love.lua` (LÖVE), their minified `.min` variants, and `imgui-luau-roblox-*.zip` / `imgui-luau-love-*.zip` (bundle + examples). For a library-only build without the demo, build it yourself with `--no-demo`.
|
||||||
|
|
||||||
### Differences from C++ Dear ImGui
|
### Differences from C++ Dear ImGui
|
||||||
|
|
||||||
|
|||||||
@@ -35,28 +35,20 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir -p dist
|
mkdir -p dist
|
||||||
python3 tools/bundle.py dist/roblox # ImGui.luau (library + demo)
|
python3 tools/bundle.py dist/roblox # ImGui.luau (library + demo)
|
||||||
python3 tools/bundle.py --no-demo dist/roblox-nodemo # ImGui.luau (library only)
|
|
||||||
python3 tools/bundle.py --target love dist/love # imgui_love.lua (library + demo)
|
python3 tools/bundle.py --target love dist/love # imgui_love.lua (library + demo)
|
||||||
python3 tools/bundle.py --target love --no-demo dist/love-nodemo
|
|
||||||
# minified variants (comments/whitespace stripped, same code): tools/minify.py
|
# minified variants (comments/whitespace stripped, same code): tools/minify.py
|
||||||
python3 tools/minify.py dist/roblox/ImGui.luau dist/ImGui.min.luau
|
python3 tools/minify.py dist/roblox/ImGui.luau dist/ImGui.min.luau
|
||||||
python3 tools/minify.py dist/roblox-nodemo/ImGui.luau dist/ImGui-nodemo.min.luau
|
|
||||||
python3 tools/minify.py dist/love/imgui_love.lua dist/imgui_love.min.lua
|
python3 tools/minify.py dist/love/imgui_love.lua dist/imgui_love.min.lua
|
||||||
python3 tools/minify.py dist/love-nodemo/imgui_love.lua dist/imgui_love-nodemo.min.lua
|
|
||||||
|
|
||||||
- name: Check
|
- name: Check
|
||||||
run: |
|
run: |
|
||||||
python3 tools/sync_github_readme.py --check
|
python3 tools/sync_github_readme.py --check
|
||||||
luau-compile --null dist/roblox/ImGui.luau
|
luau-compile --null dist/roblox/ImGui.luau
|
||||||
luau-compile --null dist/roblox-nodemo/ImGui.luau
|
|
||||||
sed 's|require(script:WaitForChild("Impl"))|nil|' dist/roblox/ImGuiTyped.luau > /tmp/ImGuiTyped.luau && luau-analyze /tmp/ImGuiTyped.luau
|
sed 's|require(script:WaitForChild("Impl"))|nil|' dist/roblox/ImGuiTyped.luau > /tmp/ImGuiTyped.luau && luau-analyze /tmp/ImGuiTyped.luau
|
||||||
luajit -bl dist/love/imgui_love.lua > /dev/null
|
luajit -bl dist/love/imgui_love.lua > /dev/null
|
||||||
luajit -bl dist/love-nodemo/imgui_love.lua > /dev/null
|
|
||||||
python3 tools/minify.py --test
|
python3 tools/minify.py --test
|
||||||
luau-compile --null dist/ImGui.min.luau
|
luau-compile --null dist/ImGui.min.luau
|
||||||
luau-compile --null dist/ImGui-nodemo.min.luau
|
|
||||||
luajit -bl dist/imgui_love.min.lua > /dev/null
|
luajit -bl dist/imgui_love.min.lua > /dev/null
|
||||||
luajit -bl dist/imgui_love-nodemo.min.lua > /dev/null
|
|
||||||
python3 tools/test/run.py --main tools/test/scripts/t_readme.luau --frames 30 --quiet --roblox --timeout 300 | tee /tmp/r.txt
|
python3 tools/test/run.py --main tools/test/scripts/t_readme.luau --frames 30 --quiet --roblox --timeout 300 | tee /tmp/r.txt
|
||||||
grep -q "README OK" /tmp/r.txt
|
grep -q "README OK" /tmp/r.txt
|
||||||
python3 tools/test/run.py --main tools/test/scripts/t_cached_window.luau --frames 130 --quiet --roblox --timeout 300 | tee /tmp/c.txt
|
python3 tools/test/run.py --main tools/test/scripts/t_cached_window.luau --frames 130 --quiet --roblox --timeout 300 | tee /tmp/c.txt
|
||||||
@@ -78,16 +70,14 @@ jobs:
|
|||||||
V="${GITHUB_REF_NAME}"
|
V="${GITHUB_REF_NAME}"
|
||||||
cd dist
|
cd dist
|
||||||
cp roblox/ImGui.luau ImGui.luau
|
cp roblox/ImGui.luau ImGui.luau
|
||||||
cp roblox-nodemo/ImGui.luau ImGui-nodemo.luau
|
|
||||||
cp love/imgui_love.lua imgui_love.lua
|
cp love/imgui_love.lua imgui_love.lua
|
||||||
cp love-nodemo/imgui_love.lua imgui_love-nodemo.lua
|
|
||||||
# Roblox: module + example LocalScript + Rojo project
|
# Roblox: module + example LocalScript + Rojo project
|
||||||
mkdir -p pkg-roblox/build && cp ImGui.luau roblox/ImGuiTyped.luau pkg-roblox/build/ && cp ../default.project.json pkg-roblox/
|
mkdir -p pkg-roblox/build && cp ImGui.luau roblox/ImGuiTyped.luau pkg-roblox/build/ && cp ../default.project.json pkg-roblox/
|
||||||
mkdir -p pkg-roblox/examples && cp -r ../examples/example_roblox ../examples/example_shared pkg-roblox/examples/
|
mkdir -p pkg-roblox/examples && cp -r ../examples/example_roblox pkg-roblox/examples/
|
||||||
(cd pkg-roblox && zip -qr ../imgui-luau-roblox-$V.zip .)
|
(cd pkg-roblox && zip -qr ../imgui-luau-roblox-$V.zip .)
|
||||||
# LÖVE: bundle + fonts + examples (run: love examples/example_love)
|
# LÖVE: bundle + fonts + examples (run: love examples/example_love)
|
||||||
mkdir -p pkg-love/build && cp imgui_love.lua pkg-love/build/ && cp -r ../fonts pkg-love/ && rm -f pkg-love/fonts/*.lua
|
mkdir -p pkg-love/build && cp imgui_love.lua pkg-love/build/ && cp -r ../fonts pkg-love/ && rm -f pkg-love/fonts/*.lua
|
||||||
mkdir -p pkg-love/examples && cp -r ../examples/example_love ../examples/example_shared pkg-love/examples/
|
mkdir -p pkg-love/examples && cp -r ../examples/example_love pkg-love/examples/
|
||||||
(cd pkg-love && zip -qr ../imgui-luau-love-$V.zip .)
|
(cd pkg-love && zip -qr ../imgui-luau-love-$V.zip .)
|
||||||
ls -la
|
ls -la
|
||||||
|
|
||||||
@@ -97,9 +87,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
dist/ImGui.luau
|
dist/ImGui.luau
|
||||||
dist/ImGui-nodemo.luau
|
|
||||||
dist/imgui_love.lua
|
dist/imgui_love.lua
|
||||||
dist/imgui_love-nodemo.lua
|
|
||||||
dist/*.min.luau
|
dist/*.min.luau
|
||||||
dist/*.min.lua
|
dist/*.min.lua
|
||||||
dist/*.zip
|
dist/*.zip
|
||||||
@@ -127,4 +115,4 @@ jobs:
|
|||||||
gh release delete latest --yes --cleanup-tag || true
|
gh release delete latest --yes --cleanup-tag || true
|
||||||
gh release create latest --latest --title "Latest build (${GITHUB_SHA::7})" \
|
gh release create latest --latest --title "Latest build (${GITHUB_SHA::7})" \
|
||||||
--notes "Automatic build of ${GITHUB_SHA} on ${GITHUB_REF_NAME}. Tag a commit v* for a versioned release." \
|
--notes "Automatic build of ${GITHUB_SHA} on ${GITHUB_REF_NAME}. Tag a commit v* for a versioned release." \
|
||||||
dist/ImGui.luau dist/ImGui-nodemo.luau dist/imgui_love.lua dist/imgui_love-nodemo.lua dist/*.min.luau dist/*.min.lua dist/*.zip
|
dist/ImGui.luau dist/imgui_love.lua dist/*.min.luau dist/*.min.lua dist/*.zip
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ Backend options:
|
|||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `ImGui_ImplRoblox.Init(parent, render_scale)` | `render_scale` = your OS display scale renders at physical-pixel resolution (crisper, same size as desktop imgui). |
|
| `ImGui_ImplRoblox.Init(parent, render_scale)` | `render_scale` = your OS display scale renders at physical-pixel resolution (crisper, same size as desktop imgui). |
|
||||||
| `ImGui_ImplRoblox.SetRenderScale(scale)` | Change it at runtime. |
|
| `ImGui_ImplRoblox.SetRenderScale(scale)` | Change it at runtime. |
|
||||||
| `ImGui_ImplRoblox.SetRenderRate(hz)` | Max tile redraws per second (default `0` = every frame). Your code still runs every frame. |
|
| `ImGui_ImplRoblox.SetRenderRate(hz)` | Max tile redraws per second (default `60`; `0` = every frame). Your code still runs every frame. |
|
||||||
| `ImGui_ImplRoblox.SetRedrawBudget(ms)` | Max milliseconds per frame spent redrawing changed tiles (opt-in; default `0` = no limit, every change is drawn the same frame). With a budget, tiles over it keep their old pixels for a few frames, so big changes are spread over frames instead of one long frame (parts of the UI may update a frame or two apart). |
|
| `ImGui_ImplRoblox.SetRedrawBudget(ms)` | Max milliseconds per frame spent redrawing changed tiles (opt-in; default `0` = no limit, every change is drawn the same frame). With a budget, tiles over it keep their old pixels for a few frames, so big changes are spread over frames instead of one long frame (parts of the UI may update a frame or two apart). |
|
||||||
| `ImGui_ImplRoblox.SetBusyRenderRate(hz)` | Optional lower redraw rate while scrolling, resizing or moving windows (default off). |
|
| `ImGui_ImplRoblox.SetBusyRenderRate(hz)` | Optional lower redraw rate while scrolling, resizing or moving windows (default off). |
|
||||||
| `ImGui_ImplRoblox.SetProfiling(true)` | MicroProfiler (Ctrl+F6) labels for every backend stage. |
|
| `ImGui_ImplRoblox.SetProfiling(true)` | MicroProfiler (Ctrl+F6) labels for every backend stage. |
|
||||||
@@ -176,7 +176,7 @@ The cost is CPU time in Luau, so the backend is built around **not drawing**:
|
|||||||
3. **Scrolling reuses pixels.** Window content is a separate layer inside a `ClipsDescendants` frame sized to the window's visible area, positioned at the scroll offset. Scrolling moves it like dragging moves a window; only rows entering view are drawn. Decorations (title bar, borders, scrollbar) stay in their own layers.
|
3. **Scrolling reuses pixels.** Window content is a separate layer inside a `ClipsDescendants` frame sized to the window's visible area, positioned at the scroll offset. Scrolling moves it like dragging moves a window; only rows entering view are drawn. Decorations (title bar, borders, scrollbar) stay in their own layers.
|
||||||
4. **Skipping unchanged windows.** Vertices are stored in a flat Luau `buffer` (36 bytes each) instead of tables. Before any per-tile work, a window's raw vertex/index bytes are compared with last frame's; if identical, its layers are just restacked.
|
4. **Skipping unchanged windows.** Vertices are stored in a flat Luau `buffer` (36 bytes each) instead of tables. Before any per-tile work, a window's raw vertex/index bytes are compared with last frame's; if identical, its layers are just restacked.
|
||||||
5. **Fast rasterizer.** `@native` functions; axis-aligned quads (most rects and every glyph) take a span-fill path, flat rows are copied instead of re-blended, gradient rects (color pickers) are filled per row, and only real triangles (anti-aliased edges, curves) use the generic edge-function rasterizer.
|
5. **Fast rasterizer.** `@native` functions; axis-aligned quads (most rects and every glyph) take a span-fill path, flat rows are copied instead of re-blended, gradient rects (color pickers) are filled per row, and only real triangles (anti-aliased edges, curves) use the generic edge-function rasterizer.
|
||||||
6. **Redraw budget.** Changed tiles are redrawn in the frame they change. Optionally, `SetRedrawBudget(ms)` caps the redraw time per frame; tiles over it keep their old pixels and follow on the next frames. Optionally capped with `SetRenderRate(hz)` / `SetBusyRenderRate(hz)`. Your UI code and Dear ImGui's logic still run every frame, so input is never dropped.
|
6. **Redraw budget.** Changed tiles are redrawn in the frame they change. Optionally, `SetRedrawBudget(ms)` caps the redraw time per frame; tiles over it keep their old pixels and follow on the next frames. Redraws are capped at 60 per second by default (`SetRenderRate(hz)`, `0` = uncapped), optionally lower while busy with `SetBusyRenderRate(hz)`. Your UI code and Dear ImGui's logic still run every frame, so input is never dropped.
|
||||||
|
|
||||||
**Input.** Mouse and keys come from `UserInputService`. While the mouse is over Dear ImGui (`io.WantCaptureMouse`), the tiles are `Active`, so clicks and the wheel don't reach the game (camera zoom). Typing comes from key codes by default (printable ASCII). Call `ImGui_ImplRoblox.SetTextProxy(true)` to opt in to a hidden `TextBox` that holds focus while a text field is active: the OS then delivers typing (any layout), paste and copy/cut through it, and its text mirrors Dear ImGui's current selection. Fonts are TTFs rasterized by the ported stb_truetype into the font atlas, which becomes a backend texture like any image (`CreateTexture` works for your own pixels too).
|
**Input.** Mouse and keys come from `UserInputService`. While the mouse is over Dear ImGui (`io.WantCaptureMouse`), the tiles are `Active`, so clicks and the wheel don't reach the game (camera zoom). Typing comes from key codes by default (printable ASCII). Call `ImGui_ImplRoblox.SetTextProxy(true)` to opt in to a hidden `TextBox` that holds focus while a text field is active: the OS then delivers typing (any layout), paste and copy/cut through it, and its text mirrors Dear ImGui's current selection. Fonts are TTFs rasterized by the ported stb_truetype into the font atlas, which becomes a backend texture like any image (`CreateTexture` works for your own pixels too).
|
||||||
|
|
||||||
@@ -202,12 +202,10 @@ love examples/example_love
|
|||||||
|
|
||||||
Roblox stays the primary target: the Roblox build is untouched by this (no shims, `@native` kept); the LÖVE build strips `@native` and adds small `bit32`/`buffer`/`utf8`/`table` shims (the COMPAT section of [backends/imgui_impl_love.lua](backends/imgui_impl_love.lua)). `tools/test/love/run.sh` checks that LuaJIT produces exactly the same draw data as Luau.
|
Roblox stays the primary target: the Roblox build is untouched by this (no shims, `@native` kept); the LÖVE build strips `@native` and adds small `bit32`/`buffer`/`utf8`/`table` shims (the COMPAT section of [backends/imgui_impl_love.lua](backends/imgui_impl_love.lua)). `tools/test/love/run.sh` checks that LuaJIT produces exactly the same draw data as Luau.
|
||||||
|
|
||||||
[examples/example_shared/app.lua](examples/example_shared/app.lua) is one UI that runs unchanged on both: `roblox.client.luau` (Rojo: `examples/example_shared/default.project.json`) and `main.lua` (`love examples/example_shared`) are the only platform code. Write shared UI code in plain Lua 5.1 syntax (no `+=`, `//`, `continue`).
|
|
||||||
|
|
||||||
#### Prebuilt releases
|
#### Prebuilt releases
|
||||||
|
|
||||||
Every push to `master` publishes a rolling `latest` release, and every `v*` tag a versioned release ([.github/workflows/release.yml](.github/workflows/release.yml)), with:
|
Every push to `master` publishes a rolling `latest` release, and every `v*` tag a versioned release ([.github/workflows/release.yml](.github/workflows/release.yml)), with:
|
||||||
`ImGui.luau` / `ImGui-nodemo.luau` (Roblox ModuleScript), `imgui_love.lua` / `imgui_love-nodemo.lua` (LÖVE), and `imgui-luau-roblox-*.zip` / `imgui-luau-love-*.zip` (bundle + examples).
|
`ImGui.luau` (Roblox ModuleScript), `imgui_love.lua` (LÖVE), their minified `.min` variants, and `imgui-luau-roblox-*.zip` / `imgui-luau-love-*.zip` (bundle + examples). For a library-only build without the demo, build it yourself with `--no-demo`.
|
||||||
|
|
||||||
### Differences from C++ Dear ImGui
|
### Differences from C++ Dear ImGui
|
||||||
|
|
||||||
|
|||||||
@@ -1353,7 +1353,7 @@ function ImGui_ImplRoblox_Init(parent, render_scale)
|
|||||||
local bd = {
|
local bd = {
|
||||||
Time = os.clock(), Gui = gui, Connections = {},
|
Time = os.clock(), Gui = gui, Connections = {},
|
||||||
Textures = {}, TextureCount = 0, MouseX = -1, MouseY = -1,
|
Textures = {}, TextureCount = 0, MouseX = -1, MouseY = -1,
|
||||||
Layers = {}, Overlays = {}, OverlayHolders = {}, OverlayShown = {}, FrameNo = 0, Scale = render_scale or 1, TilesActive = false, RenderRate = 0, BusyRenderRate = 0, RedrawBudget = 0, HB = 0, NextRender = 0, LastPrimCount = 0, ForceRedraw = true,
|
Layers = {}, Overlays = {}, OverlayHolders = {}, OverlayShown = {}, FrameNo = 0, Scale = render_scale or 1, TilesActive = false, RenderRate = 60, BusyRenderRate = 0, RedrawBudget = 0, HB = 0, NextRender = 0, LastPrimCount = 0, ForceRedraw = true,
|
||||||
}
|
}
|
||||||
io.BackendPlatformUserData = bd
|
io.BackendPlatformUserData = bd
|
||||||
io.BackendPlatformName = "imgui_impl_roblox"
|
io.BackendPlatformName = "imgui_impl_roblox"
|
||||||
@@ -1605,7 +1605,7 @@ function ImGui_ImplRoblox_SetRedrawBudget(ms)
|
|||||||
ImGui_ImplRoblox_GetBackendData().RedrawBudget = (ms or 0) / 1000
|
ImGui_ImplRoblox_GetBackendData().RedrawBudget = (ms or 0) / 1000
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Max tile redraws per second (default 0 = every frame, limited by the redraw budget instead). imgui logic still runs every frame.
|
--- Max tile redraws per second (default 60; 0 = every frame, limited by the redraw budget instead). imgui logic still runs every frame.
|
||||||
function ImGui_ImplRoblox_SetRenderRate(hz)
|
function ImGui_ImplRoblox_SetRenderRate(hz)
|
||||||
ImGui_ImplRoblox_GetBackendData().RenderRate = hz or 0
|
ImGui_ImplRoblox_GetBackendData().RenderRate = hz or 0
|
||||||
end
|
end
|
||||||
|
|||||||
+2
-2
@@ -47209,7 +47209,7 @@ function ImGui_ImplRoblox_Init(parent, render_scale)
|
|||||||
local bd = {
|
local bd = {
|
||||||
Time = os.clock(), Gui = gui, Connections = {},
|
Time = os.clock(), Gui = gui, Connections = {},
|
||||||
Textures = {}, TextureCount = 0, MouseX = -1, MouseY = -1,
|
Textures = {}, TextureCount = 0, MouseX = -1, MouseY = -1,
|
||||||
Layers = {}, Overlays = {}, OverlayHolders = {}, OverlayShown = {}, FrameNo = 0, Scale = render_scale or 1, TilesActive = false, RenderRate = 0, BusyRenderRate = 0, RedrawBudget = 0, HB = 0, NextRender = 0, LastPrimCount = 0, ForceRedraw = true,
|
Layers = {}, Overlays = {}, OverlayHolders = {}, OverlayShown = {}, FrameNo = 0, Scale = render_scale or 1, TilesActive = false, RenderRate = 60, BusyRenderRate = 0, RedrawBudget = 0, HB = 0, NextRender = 0, LastPrimCount = 0, ForceRedraw = true,
|
||||||
}
|
}
|
||||||
io.BackendPlatformUserData = bd
|
io.BackendPlatformUserData = bd
|
||||||
io.BackendPlatformName = "imgui_impl_roblox"
|
io.BackendPlatformName = "imgui_impl_roblox"
|
||||||
@@ -47461,7 +47461,7 @@ function ImGui_ImplRoblox_SetRedrawBudget(ms)
|
|||||||
ImGui_ImplRoblox_GetBackendData().RedrawBudget = (ms or 0) / 1000
|
ImGui_ImplRoblox_GetBackendData().RedrawBudget = (ms or 0) / 1000
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Max tile redraws per second (default 0 = every frame, limited by the redraw budget instead). imgui logic still runs every frame.
|
--- Max tile redraws per second (default 60; 0 = every frame, limited by the redraw budget instead). imgui logic still runs every frame.
|
||||||
function ImGui_ImplRoblox_SetRenderRate(hz)
|
function ImGui_ImplRoblox_SetRenderRate(hz)
|
||||||
ImGui_ImplRoblox_GetBackendData().RenderRate = hz or 0
|
ImGui_ImplRoblox_GetBackendData().RenderRate = hz or 0
|
||||||
end
|
end
|
||||||
|
|||||||
+19
-26
@@ -1,40 +1,33 @@
|
|||||||
Dear ImGui for Roblox - not yet ported / known gaps
|
Dear ImGui for Roblox - not yet ported / known gaps
|
||||||
====================================================
|
====================================================
|
||||||
Upstream reference: tools/test/upstream/ (ocornut/imgui docking branch, 1.93 WIP).
|
Upstream reference: tools/test/upstream/ (ocornut/imgui docking branch, 1.93 WIP).
|
||||||
Re-check with: python3 tools/test/missing.py [imgui|widgets|tables|draw] and python3 tools/test/undefined.py --no-demo
|
Re-check with: python3 tools/compare_upstream.py (writes docs/PORT_STATUS.txt: [ ] = not ported, [=] = replaced by a
|
||||||
(missing.py also lists names the port defines differently, e.g. the *V printf variants and DragFloat2..4 / DragInt2..4,
|
Lua equivalent, "missing:" = enum values / struct fields) and python3 tools/test/undefined.py --no-demo
|
||||||
which exist as ImGui.DragFloat2 = DragFloatN(2) etc. Those are NOT gaps.)
|
|
||||||
|
|
||||||
|
|
||||||
FEATURES NOT PORTED / PARTIAL
|
NOT PORTED / PARTIAL
|
||||||
-----------------------------
|
--------------------
|
||||||
- ImFont::AddRemapCodepointToGlyphIndex / FontSrcGetGlyphIndexFromCodepoint (needs the 1.93 font loader split).
|
- ImFont::AddRemapCodepointToGlyphIndex / ImGui_ImplStbTrueType_FontSrcGetGlyphIndexFromCodepoint (the port's font
|
||||||
- Default compressed font data (GetDefaultCompressedFontDataTTF / ProggyClean/ProggyForever embedded data):
|
loader still checks glyphs by codepoint; 1.93 split this into codepoint -> glyph index -> glyph).
|
||||||
AddFontFromMemoryCompressedTTF works, but the default font comes from fonts/ instead.
|
- ImGui_GetDefaultCompressedFontDataProggyClean/ProggyForever: AddFontFromMemoryCompressedTTF works, but the default
|
||||||
- DebugLogSkippedErrors / DebugDrawIdConflicts* (Metrics error-recovery and ID-conflict debug tools).
|
fonts are loaded from fonts/ instead of embedded compressed data.
|
||||||
- ImGuiDataType.S64/U64: supported, but values are Luau doubles: exact only within +-2^53 (LLONG_MAX/ULLONG_MAX
|
- ImFontAtlasDebugLogTextureRequests, ImHashSkipUncontributingPrefix.
|
||||||
round up to 2^63/2^64; U64 max prints as 18446744073709551615 via a special case).
|
- DebugLogSkippedErrors / DebugDrawIdConflicts* (error-recovery and ID-conflict debug tools).
|
||||||
- ImDrawList::AddCallback(userdata_size > 0): "copy" = shallow copy of a table userdata (no raw bytes in Lua).
|
|
||||||
- stb_truetype: cmap format 2 (high-byte mapping) asserts -- same as upstream stb_truetype ("@TODO").
|
LUA LIMITATIONS
|
||||||
- GetAllocatorFunctions (n/a in Luau).
|
---------------
|
||||||
|
- ImGuiDataType.S64/U64: values are Luau doubles, exact only within +-2^53 (LLONG_MAX/ULLONG_MAX round up).
|
||||||
|
- ImDrawList::AddCallback(userdata_size > 0): the "copy" is a shallow copy of a table userdata (no raw bytes).
|
||||||
|
|
||||||
WON'T DO (platform)
|
WON'T DO (platform)
|
||||||
-------------------
|
-------------------
|
||||||
- Multi-viewports / platform windows: Roblox has one window. Viewport API exists for the main viewport only.
|
- Multi-viewports / platform windows: Roblox has one window. The viewport API covers the main viewport only.
|
||||||
- Gamepad navigation via a real gamepad backend (keyboard navigation works).
|
- Gamepad navigation via a real gamepad backend (keyboard navigation works).
|
||||||
- IME / non-ASCII keyboard text input (backend sends printable ASCII only).
|
- IME / non-ASCII keyboard text input (backend sends printable ASCII only).
|
||||||
|
|
||||||
NOT VERIFIED LINE BY LINE AGAINST UPSTREAM
|
|
||||||
------------------------------------------
|
|
||||||
- Demo: Layout & Scrolling, Popups & Modal windows, Inputs & Focus.
|
|
||||||
|
|
||||||
KNOWN ISSUES
|
KNOWN ISSUES
|
||||||
------------
|
------------
|
||||||
- Tables > "Columns flags": disabling every column asserts in TableUpdateLayout (upstream asserts too).
|
- Tables > "Columns flags": disabling every column asserts in TableUpdateLayout (upstream asserts too).
|
||||||
- ImTriangulator ([Luau] deviation, imgui_draw.lua ImTriangulator_IsReflex): only strictly counter-clockwise corners are
|
- stb_truetype: cmap format 2 (high-byte mapping) asserts (same "@TODO" as upstream stb_truetype).
|
||||||
reflex (upstream: also collinear/duplicate points), so polygons with duplicate points triangulate differently (no
|
- ImTriangulator differs from upstream (imgui_draw.lua, [Luau]): CCW input is reversed first and only strictly
|
||||||
overlapping-triangle fallback).
|
counter-clockwise corners are reflex, so CCW and duplicate-point polygons triangulate differently from upstream.
|
||||||
|
|
||||||
PLANNED EXTENSIONS
|
|
||||||
------------------
|
|
||||||
- ImGuizmo, ImNodes, ImGuiColorTextEdit, ImPlot, ImPlot3D (as separate extensions/, built with a --with flag).
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ setfenv(1, setmetatable({}, {
|
|||||||
|
|
||||||
local MainScale = 1.0
|
local MainScale = 1.0
|
||||||
local RenderScale = 1.0
|
local RenderScale = 1.0
|
||||||
local RenderRate = 0 -- 0 = every frame (tile redraws are limited by the redraw budget instead)
|
local RenderRate = 60 -- max tile redraws per second (0 = every frame, limited by the redraw budget instead)
|
||||||
local ThumbnailSize = 420
|
local ThumbnailSize = 420
|
||||||
local FontSize = 13.0
|
local FontSize = 13.0
|
||||||
local FontNames = { "Cousine-Regular", "DroidSans", "Karla-Regular", "ProggyTiny", "Roboto-Medium" }
|
local FontNames = { "Cousine-Regular", "DroidSans", "Karla-Regular", "ProggyTiny", "Roboto-Medium" }
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
-- One UI that runs unchanged on Roblox and LÖVE: only the Dear ImGui API is used, and the code is plain Lua 5.1
|
|
||||||
-- (no Luau-only syntax), so both Luau and LuaJIT run it. The platform launchers are roblox.client.luau and main.lua.
|
|
||||||
-- local App = require(app)(G) -- G = the table returned by the ImGui bundle
|
|
||||||
-- every frame, between ImGui.NewFrame() and ImGui.Render(): App.Frame()
|
|
||||||
return function(G)
|
|
||||||
local ImGui, ImVec2, ImVec4 = G.ImGui, G.ImVec2, G.ImVec4
|
|
||||||
local App = {
|
|
||||||
Platform = "?", -- set by the launcher ("Roblox" / "LÖVE")
|
|
||||||
ClearColor = ImVec4(0.45, 0.55, 0.60, 1.00), -- launchers may use it as the background colour
|
|
||||||
}
|
|
||||||
local show_demo, show_table = false, true
|
|
||||||
local counter, speed = 0, 1.0
|
|
||||||
local name = ImGui.NewTextBuffer("Player", 64)
|
|
||||||
local samples, t = {}, 0.0
|
|
||||||
local items = { { "Sword", 1, 120 }, { "Potion", 5, 15 }, { "Arrow", 64, 1 }, { "Shield", 1, 80 } }
|
|
||||||
|
|
||||||
function App.Frame()
|
|
||||||
local io = ImGui.GetIO()
|
|
||||||
t = t + io.DeltaTime * speed
|
|
||||||
for i = 1, 90 do samples[i] = math.sin(i / 90 * math.pi * 4 + t * 3) end
|
|
||||||
|
|
||||||
ImGui.SetNextWindowPos(ImVec2(20, 20), G.ImGuiCond.FirstUseEver)
|
|
||||||
ImGui.SetNextWindowSize(ImVec2(420, 360), G.ImGuiCond.FirstUseEver)
|
|
||||||
ImGui.Begin("Shared Example")
|
|
||||||
ImGui.Text("Running on %s (%.1f FPS)", App.Platform, io.Framerate)
|
|
||||||
ImGui.Separator()
|
|
||||||
ImGui.InputText("name", name, 64)
|
|
||||||
if ImGui.Button("Click me") then counter = counter + 1 end
|
|
||||||
ImGui.SameLine(); ImGui.Text("%s clicked %d times", ImGui.TextBufferToString(name), counter)
|
|
||||||
speed = ImGui.SliderFloat("speed", speed, 0.0, 4.0)
|
|
||||||
ImGui.ColorEdit3("background", App.ClearColor)
|
|
||||||
ImGui.PlotLines("wave", samples, nil, #samples, 0, nil, -1.0, 1.0, ImVec2(0, 60))
|
|
||||||
local _
|
|
||||||
_, show_table = ImGui.Checkbox("Inventory table", show_table)
|
|
||||||
ImGui.SameLine(); _, show_demo = ImGui.Checkbox("Demo window", show_demo)
|
|
||||||
if show_table and ImGui.BeginTable("inv", 3, bit32.bor(G.ImGuiTableFlags.Borders, G.ImGuiTableFlags.RowBg, G.ImGuiTableFlags.Sortable)) then
|
|
||||||
ImGui.TableSetupColumn("Item"); ImGui.TableSetupColumn("Count"); ImGui.TableSetupColumn("Value")
|
|
||||||
ImGui.TableHeadersRow()
|
|
||||||
for _, it in ipairs(items) do
|
|
||||||
ImGui.TableNextRow()
|
|
||||||
ImGui.TableNextColumn(); ImGui.Text(it[1])
|
|
||||||
ImGui.TableNextColumn(); ImGui.Text("%d", it[2])
|
|
||||||
ImGui.TableNextColumn(); ImGui.Text("%d", it[3])
|
|
||||||
end
|
|
||||||
ImGui.EndTable()
|
|
||||||
end
|
|
||||||
ImGui.End()
|
|
||||||
|
|
||||||
if show_demo and ImGui.ShowDemoWindow then show_demo = ImGui.ShowDemoWindow(show_demo) end
|
|
||||||
end
|
|
||||||
|
|
||||||
return App
|
|
||||||
end
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
function love.conf(t)
|
|
||||||
t.window.title = "Dear ImGui - shared example (LÖVE)"
|
|
||||||
t.window.width, t.window.height = 1280, 800
|
|
||||||
t.window.resizable = true
|
|
||||||
end
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "imgui-shared-example",
|
|
||||||
"tree": {
|
|
||||||
"$className": "DataModel",
|
|
||||||
"ReplicatedStorage": {
|
|
||||||
"ImGui": { "$path": "../../build/ImGuiTyped.luau", "Impl": { "$path": "../../build/ImGui.luau" } },
|
|
||||||
"SharedApp": { "$path": "app.lua" }
|
|
||||||
},
|
|
||||||
"StarterPlayer": {
|
|
||||||
"StarterPlayerScripts": {
|
|
||||||
"SharedExample": { "$path": "roblox.client.luau" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
-- LÖVE launcher for app.lua: python3 tools/bundle.py --target love then love examples/example_shared
|
|
||||||
local ROOT = love.filesystem.getSource() .. "/../../" -- repo root (build/, fonts/)
|
|
||||||
local function load_bundle()
|
|
||||||
local f = assert(io.open(ROOT .. "build/imgui_love.lua", "rb"), "run: python3 tools/bundle.py --target love")
|
|
||||||
local src = f:read("*a"); f:close()
|
|
||||||
return assert(loadstring(src, "@imgui_love.lua"))()
|
|
||||||
end
|
|
||||||
|
|
||||||
local G, ImGui, App
|
|
||||||
|
|
||||||
function love.load()
|
|
||||||
G = load_bundle()
|
|
||||||
ImGui = G.ImGui
|
|
||||||
ImGui.CreateContext()
|
|
||||||
local io = ImGui.GetIO()
|
|
||||||
io.ConfigFlags = bit32.bor(io.ConfigFlags, G.ImGuiConfigFlags.NavEnableKeyboard, G.ImGuiConfigFlags.DockingEnable)
|
|
||||||
io.IniFilename = nil
|
|
||||||
G.ImGui_ImplLove.Init({ root = ROOT })
|
|
||||||
App = love.filesystem.load("app.lua")()(G)
|
|
||||||
App.Platform = "LÖVE"
|
|
||||||
end
|
|
||||||
|
|
||||||
function love.update(dt)
|
|
||||||
G.ImGui_ImplLove.NewFrame()
|
|
||||||
ImGui.NewFrame()
|
|
||||||
App.Frame()
|
|
||||||
ImGui.Render()
|
|
||||||
end
|
|
||||||
|
|
||||||
function love.draw()
|
|
||||||
local c = App.ClearColor
|
|
||||||
love.graphics.clear(c.x, c.y, c.z, 1)
|
|
||||||
G.ImGui_ImplLove.RenderDrawData(ImGui.GetDrawData())
|
|
||||||
end
|
|
||||||
|
|
||||||
function love.mousemoved(x, y) G.ImGui_ImplLove.MouseMoved(x, y) end
|
|
||||||
function love.mousepressed(x, y, b) G.ImGui_ImplLove.MousePressed(x, y, b) end
|
|
||||||
function love.mousereleased(x, y, b) G.ImGui_ImplLove.MouseReleased(x, y, b) end
|
|
||||||
function love.wheelmoved(x, y) G.ImGui_ImplLove.WheelMoved(x, y) end
|
|
||||||
function love.keypressed(k) G.ImGui_ImplLove.KeyPressed(k) end
|
|
||||||
function love.keyreleased(k) G.ImGui_ImplLove.KeyReleased(k) end
|
|
||||||
function love.textinput(t) G.ImGui_ImplLove.TextInput(t) end
|
|
||||||
function love.focus(f) G.ImGui_ImplLove.Focus(f) end
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
-- Roblox launcher for app.lua (sync with examples/example_shared/default.project.json).
|
|
||||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
|
||||||
local RunService = game:GetService("RunService")
|
|
||||||
local G = require(ReplicatedStorage:WaitForChild("ImGui"))
|
|
||||||
local ImGui = G.ImGui
|
|
||||||
|
|
||||||
ImGui.CreateContext()
|
|
||||||
local io = ImGui.GetIO()
|
|
||||||
io.ConfigFlags = bit32.bor(io.ConfigFlags, G.ImGuiConfigFlags.NavEnableKeyboard, G.ImGuiConfigFlags.DockingEnable)
|
|
||||||
G.ImGui_ImplRoblox.Init()
|
|
||||||
|
|
||||||
local App = require(ReplicatedStorage:WaitForChild("SharedApp"))(G)
|
|
||||||
App.Platform = "Roblox"
|
|
||||||
|
|
||||||
RunService.Stepped:Connect(function()
|
|
||||||
G.ImGui_ImplRoblox.NewFrame()
|
|
||||||
ImGui.NewFrame()
|
|
||||||
App.Frame()
|
|
||||||
ImGui.Render()
|
|
||||||
G.ImGui_ImplRoblox.RenderDrawData(ImGui.GetDrawData())
|
|
||||||
end)
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
-- Runs examples/example_love and examples/example_shared main.lua headless under LuaJIT (mock love) for some frames.
|
-- Runs examples/example_love main.lua headless under LuaJIT (mock love) for some frames.
|
||||||
for _, ex in ipairs({ "examples/example_love", "examples/example_shared" }) do
|
for _, ex in ipairs({ "examples/example_love" }) do
|
||||||
dofile("tools/test/love/mock_love.lua")
|
dofile("tools/test/love/mock_love.lua")
|
||||||
love.filesystem.getSource = function() return ex end
|
love.filesystem.getSource = function() return ex end
|
||||||
love.filesystem.load = function(p) return assert(loadfile(ex .. "/" .. p)) end
|
love.filesystem.load = function(p) return assert(loadfile(ex .. "/" .. p)) end
|
||||||
|
|||||||
Reference in New Issue
Block a user