Move LuaJIT compat shims into backends/imgui_impl_love.lua (COMPAT section); remove compat/
This commit is contained in:
@@ -172,11 +172,11 @@ io.Fonts:AddFontFromFileTTF("fonts/Roboto-Medium.ttf", 16.0)
|
|||||||
The same sources also build for [LÖVE](https://love2d.org) (LuaJIT), with a GPU renderer in [backends/imgui_impl_love.lua](backends/imgui_impl_love.lua):
|
The same sources also build for [LÖVE](https://love2d.org) (LuaJIT), with a GPU renderer in [backends/imgui_impl_love.lua](backends/imgui_impl_love.lua):
|
||||||
|
|
||||||
```
|
```
|
||||||
python3 tools/bundle.py --target love # -> build/imgui_love.lua (LÖVE backend + compat/luajit.lua shims)
|
python3 tools/bundle.py --target love # -> build/imgui_love.lua (LÖVE backend + shims from the LÖVE backend)
|
||||||
love examples/example_love
|
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 ([compat/luajit.lua](compat/luajit.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`).
|
[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`).
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,147 @@
|
|||||||
--- love.draw: ImGui_ImplLove.RenderDrawData(ImGui.GetDrawData())
|
--- love.draw: ImGui_ImplLove.RenderDrawData(ImGui.GetDrawData())
|
||||||
--- forward love.mousemoved/mousepressed/mousereleased/wheelmoved/keypressed/keyreleased/textinput to ImGui_ImplLove.*
|
--- forward love.mousemoved/mousepressed/mousereleased/wheelmoved/keypressed/keyreleased/textinput to ImGui_ImplLove.*
|
||||||
|
|
||||||
|
-- [SECTION] COMPAT (Luau stdlib for LuaJIT). tools/bundle.py --target love runs this section before the library.
|
||||||
|
--@compat-begin
|
||||||
local ffi = require("ffi")
|
local ffi = require("ffi")
|
||||||
|
local floor = math.floor
|
||||||
|
-- Luau standard library pieces the port uses, for LuaJIT (LÖVE). Prepended by `tools/bundle.py --target love` only:
|
||||||
|
-- the Roblox build uses Luau's native bit32/buffer/table/utf8 and never sees this file.
|
||||||
|
|
||||||
|
local bit = require("bit")
|
||||||
|
local TWO32 = 4294967296
|
||||||
|
|
||||||
|
-- bit32: unsigned 32-bit results like Luau/Lua 5.2 (LuaJIT's `bit` returns signed values)
|
||||||
|
if not bit32 then
|
||||||
|
local band, bor, bxor, bnot, lshift, rshift, arshift, tobit = bit.band, bit.bor, bit.bxor, bit.bnot, bit.lshift, bit.rshift, bit.arshift, bit.tobit
|
||||||
|
local function u(x) return x % TWO32 end
|
||||||
|
local function t(x) return tobit(x % TWO32) end -- any number -> int32 (bit.* wraps doubles >= 2^31 unreliably)
|
||||||
|
bit32 = {}
|
||||||
|
function bit32.band(a, b, ...)
|
||||||
|
if a == nil then return TWO32 - 1 end
|
||||||
|
if b == nil then return u(t(a)) end
|
||||||
|
local r = band(t(a), t(b))
|
||||||
|
if ... ~= nil then for i = 1, select("#", ...) do r = band(r, t((select(i, ...)))) end end
|
||||||
|
return u(r)
|
||||||
|
end
|
||||||
|
function bit32.bor(a, b, ...)
|
||||||
|
if a == nil then return 0 end
|
||||||
|
if b == nil then return u(t(a)) end
|
||||||
|
local r = bor(t(a), t(b))
|
||||||
|
if ... ~= nil then for i = 1, select("#", ...) do r = bor(r, t((select(i, ...)))) end end
|
||||||
|
return u(r)
|
||||||
|
end
|
||||||
|
function bit32.bxor(a, b, ...)
|
||||||
|
if a == nil then return 0 end
|
||||||
|
if b == nil then return u(t(a)) end
|
||||||
|
local r = bxor(t(a), t(b))
|
||||||
|
if ... ~= nil then for i = 1, select("#", ...) do r = bxor(r, t((select(i, ...)))) end end
|
||||||
|
return u(r)
|
||||||
|
end
|
||||||
|
function bit32.bnot(a) return u(bnot(t(a))) end
|
||||||
|
function bit32.lshift(a, n) if n >= 32 or n <= -32 then return 0 end if n < 0 then return u(rshift(t(a), -n)) end return u(lshift(t(a), n)) end
|
||||||
|
function bit32.rshift(a, n) if n >= 32 or n <= -32 then return 0 end if n < 0 then return u(lshift(t(a), -n)) end return u(rshift(t(a), n)) end
|
||||||
|
function bit32.arshift(a, n) if n >= 32 then n = 31 end return u(arshift(t(a), n)) end
|
||||||
|
function bit32.btest(...) return bit32.band(...) ~= 0 end
|
||||||
|
function bit32.extract(n, field, width) width = width or 1; return u(band(rshift(t(n), field), 2 ^ width - 1)) end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- buffer: fixed-size byte buffers (subset used by the port), on FFI memory. Little-endian like Luau.
|
||||||
|
if not buffer then
|
||||||
|
ffi.cdef("void *memmove(void *dst, const void *src, size_t n); void *memset(void *s, int c, size_t n);")
|
||||||
|
local C = ffi.C
|
||||||
|
local u8p, u32p, f64p = ffi.typeof("uint8_t*"), ffi.typeof("uint32_t*"), ffi.typeof("double*")
|
||||||
|
buffer = {}
|
||||||
|
function buffer.create(n)
|
||||||
|
local mem = ffi.new("uint8_t[?]", math.max(n, 1)) -- zero-filled
|
||||||
|
return { p = ffi.cast(u8p, mem), n = n, mem = mem }
|
||||||
|
end
|
||||||
|
function buffer.len(b) return b.n end
|
||||||
|
function buffer.readu8(b, o) return b.p[o] end
|
||||||
|
function buffer.writeu8(b, o, v) b.p[o] = v end
|
||||||
|
function buffer.readu32(b, o) return ffi.cast(u32p, b.p + o)[0] end
|
||||||
|
function buffer.writeu32(b, o, v) ffi.cast(u32p, b.p + o)[0] = v % TWO32 end
|
||||||
|
function buffer.readf64(b, o) return ffi.cast(f64p, b.p + o)[0] end
|
||||||
|
function buffer.writef64(b, o, v) ffi.cast(f64p, b.p + o)[0] = v end
|
||||||
|
function buffer.readstring(b, o, n) return ffi.string(b.p + o, n) end
|
||||||
|
function buffer.writestring(b, o, s, n) ffi.copy(b.p + o, s, n or #s) end
|
||||||
|
function buffer.copy(dst, doff, src, soff, n)
|
||||||
|
soff = soff or 0
|
||||||
|
n = n or (src.n - soff)
|
||||||
|
if n > 0 then C.memmove(dst.p + doff, src.p + soff, n) end
|
||||||
|
end
|
||||||
|
function buffer.fill(b, o, v, n) n = n or (b.n - o); if n > 0 then C.memset(b.p + o, v, n) end end
|
||||||
|
function buffer.tostring(b) return ffi.string(b.p, b.n) end
|
||||||
|
function buffer.fromstring(s) local b = buffer.create(#s); ffi.copy(b.p, s, #s); return b end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- table / math / utf8 additions from Luau / Lua 5.3
|
||||||
|
do
|
||||||
|
local ok, clear = pcall(require, "table.clear")
|
||||||
|
table.clear = table.clear or (ok and clear) or function(t) for k in pairs(t) do t[k] = nil end end
|
||||||
|
table.unpack = table.unpack or unpack
|
||||||
|
table.find = table.find or function(t, v, init) for i = init or 1, #t do if t[i] == v then return i end end end
|
||||||
|
table.move = table.move or function(a1, f, e, t, a2)
|
||||||
|
a2 = a2 or a1
|
||||||
|
if e >= f then
|
||||||
|
if t > f or t > e or a1 ~= a2 then for i = 0, e - f do a2[t + i] = a1[f + i] end
|
||||||
|
else for i = e - f, 0, -1 do a2[t + i] = a1[f + i] end end
|
||||||
|
end
|
||||||
|
return a2
|
||||||
|
end
|
||||||
|
math.pow = math.pow or function(a, b) return a ^ b end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not utf8 then
|
||||||
|
utf8 = { charpattern = "[\0-\x7F\xC2-\xFD][\x80-\xBF]*" }
|
||||||
|
function utf8.char(...)
|
||||||
|
local out = {}
|
||||||
|
for i = 1, select("#", ...) do
|
||||||
|
local c = select(i, ...)
|
||||||
|
if c < 0x80 then out[#out + 1] = string.char(c)
|
||||||
|
elseif c < 0x800 then out[#out + 1] = string.char(0xC0 + floor(c / 64), 0x80 + c % 64)
|
||||||
|
elseif c < 0x10000 then out[#out + 1] = string.char(0xE0 + floor(c / 4096), 0x80 + floor(c / 64) % 64, 0x80 + c % 64)
|
||||||
|
else out[#out + 1] = string.char(0xF0 + floor(c / 262144), 0x80 + floor(c / 4096) % 64, 0x80 + floor(c / 64) % 64, 0x80 + c % 64) end
|
||||||
|
end
|
||||||
|
return table.concat(out)
|
||||||
|
end
|
||||||
|
local function decode(s, i)
|
||||||
|
local c = s:byte(i)
|
||||||
|
if not c then return nil end
|
||||||
|
if c < 0x80 then return c, 1 end
|
||||||
|
if c < 0xE0 then return (c % 32) * 64 + s:byte(i + 1) % 64, 2 end
|
||||||
|
if c < 0xF0 then return (c % 16) * 4096 + (s:byte(i + 1) % 64) * 64 + s:byte(i + 2) % 64, 3 end
|
||||||
|
return (c % 8) * 262144 + (s:byte(i + 1) % 64) * 4096 + (s:byte(i + 2) % 64) * 64 + s:byte(i + 3) % 64, 4
|
||||||
|
end
|
||||||
|
function utf8.codes(s)
|
||||||
|
local i = 1
|
||||||
|
return function()
|
||||||
|
if i > #s then return nil end
|
||||||
|
local c, n = decode(s, i)
|
||||||
|
local p = i; i = i + n
|
||||||
|
return p, c
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function utf8.codepoint(s, i, j)
|
||||||
|
i = i or 1; j = j or i
|
||||||
|
local out = {}
|
||||||
|
while i <= j do local c, n = decode(s, i); out[#out + 1] = c; i = i + n end
|
||||||
|
return unpack(out)
|
||||||
|
end
|
||||||
|
function utf8.len(s) local n = 0; for _ in utf8.codes(s) do n = n + 1 end return n end
|
||||||
|
function utf8.offset(s, n, i)
|
||||||
|
i = i or (n >= 0 and 1 or #s + 1)
|
||||||
|
if n > 0 then
|
||||||
|
n = n - 1
|
||||||
|
while n > 0 and i <= #s do i = i + 1; while i <= #s and s:byte(i) >= 0x80 and s:byte(i) < 0xC0 do i = i + 1 end; n = n - 1 end
|
||||||
|
if n > 0 then return nil end
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--@compat-end
|
||||||
|
|
||||||
local floor, min = math.floor, math.min
|
local floor, min = math.floor, math.min
|
||||||
|
|
||||||
local ImGui_ImplLOVE_GetBackendData
|
local ImGui_ImplLOVE_GetBackendData
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
[[149, "imgui.lua"], [18609, "imgui_demo.lua"], [25894, "imgui_draw.lua"], [31132, "imgui_h.lua"], [33330, "imgui_impl_love.lua"], [33730, "imgui_internal.lua"], [36902, "imgui_tables.lua"], [41249, "imgui_widgets.lua"], [51004, "imstb_rectpack.lua"], [51450, "imstb_textedit.lua"], [52691, "imstb_truetype.lua"], [55159, "imstd_minstdio.lua"]]
|
[[149, "imgui.lua"], [18609, "imgui_demo.lua"], [25894, "imgui_draw.lua"], [31132, "imgui_h.lua"], [33330, "imgui_impl_love.lua"], [33870, "imgui_internal.lua"], [37042, "imgui_tables.lua"], [41389, "imgui_widgets.lua"], [51144, "imstb_rectpack.lua"], [51590, "imstb_textedit.lua"], [52831, "imstb_truetype.lua"], [55299, "imstd_minstdio.lua"]]
|
||||||
+142
-2
@@ -1,10 +1,10 @@
|
|||||||
-- GENERATED by tools/bundle.py --target love - do not edit
|
-- GENERATED by tools/bundle.py --target love - do not edit
|
||||||
|
local ffi = require("ffi")
|
||||||
|
local floor = math.floor
|
||||||
-- Luau standard library pieces the port uses, for LuaJIT (LÖVE). Prepended by `tools/bundle.py --target love` only:
|
-- Luau standard library pieces the port uses, for LuaJIT (LÖVE). Prepended by `tools/bundle.py --target love` only:
|
||||||
-- the Roblox build uses Luau's native bit32/buffer/table/utf8 and never sees this file.
|
-- the Roblox build uses Luau's native bit32/buffer/table/utf8 and never sees this file.
|
||||||
|
|
||||||
local ffi = require("ffi")
|
|
||||||
local bit = require("bit")
|
local bit = require("bit")
|
||||||
local floor = math.floor
|
|
||||||
local TWO32 = 4294967296
|
local TWO32 = 4294967296
|
||||||
|
|
||||||
-- bit32: unsigned 32-bit results like Luau/Lua 5.2 (LuaJIT's `bit` returns signed values)
|
-- bit32: unsigned 32-bit results like Luau/Lua 5.2 (LuaJIT's `bit` returns signed values)
|
||||||
@@ -33335,7 +33335,147 @@ __FILES['imgui_impl_love.lua'] = function()
|
|||||||
--- love.draw: ImGui_ImplLove.RenderDrawData(ImGui.GetDrawData())
|
--- love.draw: ImGui_ImplLove.RenderDrawData(ImGui.GetDrawData())
|
||||||
--- forward love.mousemoved/mousepressed/mousereleased/wheelmoved/keypressed/keyreleased/textinput to ImGui_ImplLove.*
|
--- forward love.mousemoved/mousepressed/mousereleased/wheelmoved/keypressed/keyreleased/textinput to ImGui_ImplLove.*
|
||||||
|
|
||||||
|
-- [SECTION] COMPAT (Luau stdlib for LuaJIT). tools/bundle.py --target love runs this section before the library.
|
||||||
|
--@compat-begin
|
||||||
local ffi = require("ffi")
|
local ffi = require("ffi")
|
||||||
|
local floor = math.floor
|
||||||
|
-- Luau standard library pieces the port uses, for LuaJIT (LÖVE). Prepended by `tools/bundle.py --target love` only:
|
||||||
|
-- the Roblox build uses Luau's native bit32/buffer/table/utf8 and never sees this file.
|
||||||
|
|
||||||
|
local bit = require("bit")
|
||||||
|
local TWO32 = 4294967296
|
||||||
|
|
||||||
|
-- bit32: unsigned 32-bit results like Luau/Lua 5.2 (LuaJIT's `bit` returns signed values)
|
||||||
|
if not bit32 then
|
||||||
|
local band, bor, bxor, bnot, lshift, rshift, arshift, tobit = bit.band, bit.bor, bit.bxor, bit.bnot, bit.lshift, bit.rshift, bit.arshift, bit.tobit
|
||||||
|
local function u(x) return x % TWO32 end
|
||||||
|
local function t(x) return tobit(x % TWO32) end -- any number -> int32 (bit.* wraps doubles >= 2^31 unreliably)
|
||||||
|
bit32 = {}
|
||||||
|
function bit32.band(a, b, ...)
|
||||||
|
if a == nil then return TWO32 - 1 end
|
||||||
|
if b == nil then return u(t(a)) end
|
||||||
|
local r = band(t(a), t(b))
|
||||||
|
if ... ~= nil then for i = 1, select("#", ...) do r = band(r, t((select(i, ...)))) end end
|
||||||
|
return u(r)
|
||||||
|
end
|
||||||
|
function bit32.bor(a, b, ...)
|
||||||
|
if a == nil then return 0 end
|
||||||
|
if b == nil then return u(t(a)) end
|
||||||
|
local r = bor(t(a), t(b))
|
||||||
|
if ... ~= nil then for i = 1, select("#", ...) do r = bor(r, t((select(i, ...)))) end end
|
||||||
|
return u(r)
|
||||||
|
end
|
||||||
|
function bit32.bxor(a, b, ...)
|
||||||
|
if a == nil then return 0 end
|
||||||
|
if b == nil then return u(t(a)) end
|
||||||
|
local r = bxor(t(a), t(b))
|
||||||
|
if ... ~= nil then for i = 1, select("#", ...) do r = bxor(r, t((select(i, ...)))) end end
|
||||||
|
return u(r)
|
||||||
|
end
|
||||||
|
function bit32.bnot(a) return u(bnot(t(a))) end
|
||||||
|
function bit32.lshift(a, n) if n >= 32 or n <= -32 then return 0 end if n < 0 then return u(rshift(t(a), -n)) end return u(lshift(t(a), n)) end
|
||||||
|
function bit32.rshift(a, n) if n >= 32 or n <= -32 then return 0 end if n < 0 then return u(lshift(t(a), -n)) end return u(rshift(t(a), n)) end
|
||||||
|
function bit32.arshift(a, n) if n >= 32 then n = 31 end return u(arshift(t(a), n)) end
|
||||||
|
function bit32.btest(...) return bit32.band(...) ~= 0 end
|
||||||
|
function bit32.extract(n, field, width) width = width or 1; return u(band(rshift(t(n), field), 2 ^ width - 1)) end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- buffer: fixed-size byte buffers (subset used by the port), on FFI memory. Little-endian like Luau.
|
||||||
|
if not buffer then
|
||||||
|
ffi.cdef("void *memmove(void *dst, const void *src, size_t n); void *memset(void *s, int c, size_t n);")
|
||||||
|
local C = ffi.C
|
||||||
|
local u8p, u32p, f64p = ffi.typeof("uint8_t*"), ffi.typeof("uint32_t*"), ffi.typeof("double*")
|
||||||
|
buffer = {}
|
||||||
|
function buffer.create(n)
|
||||||
|
local mem = ffi.new("uint8_t[?]", math.max(n, 1)) -- zero-filled
|
||||||
|
return { p = ffi.cast(u8p, mem), n = n, mem = mem }
|
||||||
|
end
|
||||||
|
function buffer.len(b) return b.n end
|
||||||
|
function buffer.readu8(b, o) return b.p[o] end
|
||||||
|
function buffer.writeu8(b, o, v) b.p[o] = v end
|
||||||
|
function buffer.readu32(b, o) return ffi.cast(u32p, b.p + o)[0] end
|
||||||
|
function buffer.writeu32(b, o, v) ffi.cast(u32p, b.p + o)[0] = v % TWO32 end
|
||||||
|
function buffer.readf64(b, o) return ffi.cast(f64p, b.p + o)[0] end
|
||||||
|
function buffer.writef64(b, o, v) ffi.cast(f64p, b.p + o)[0] = v end
|
||||||
|
function buffer.readstring(b, o, n) return ffi.string(b.p + o, n) end
|
||||||
|
function buffer.writestring(b, o, s, n) ffi.copy(b.p + o, s, n or #s) end
|
||||||
|
function buffer.copy(dst, doff, src, soff, n)
|
||||||
|
soff = soff or 0
|
||||||
|
n = n or (src.n - soff)
|
||||||
|
if n > 0 then C.memmove(dst.p + doff, src.p + soff, n) end
|
||||||
|
end
|
||||||
|
function buffer.fill(b, o, v, n) n = n or (b.n - o); if n > 0 then C.memset(b.p + o, v, n) end end
|
||||||
|
function buffer.tostring(b) return ffi.string(b.p, b.n) end
|
||||||
|
function buffer.fromstring(s) local b = buffer.create(#s); ffi.copy(b.p, s, #s); return b end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- table / math / utf8 additions from Luau / Lua 5.3
|
||||||
|
do
|
||||||
|
local ok, clear = pcall(require, "table.clear")
|
||||||
|
table.clear = table.clear or (ok and clear) or function(t) for k in pairs(t) do t[k] = nil end end
|
||||||
|
table.unpack = table.unpack or unpack
|
||||||
|
table.find = table.find or function(t, v, init) for i = init or 1, #t do if t[i] == v then return i end end end
|
||||||
|
table.move = table.move or function(a1, f, e, t, a2)
|
||||||
|
a2 = a2 or a1
|
||||||
|
if e >= f then
|
||||||
|
if t > f or t > e or a1 ~= a2 then for i = 0, e - f do a2[t + i] = a1[f + i] end
|
||||||
|
else for i = e - f, 0, -1 do a2[t + i] = a1[f + i] end end
|
||||||
|
end
|
||||||
|
return a2
|
||||||
|
end
|
||||||
|
math.pow = math.pow or function(a, b) return a ^ b end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not utf8 then
|
||||||
|
utf8 = { charpattern = "[\0-\x7F\xC2-\xFD][\x80-\xBF]*" }
|
||||||
|
function utf8.char(...)
|
||||||
|
local out = {}
|
||||||
|
for i = 1, select("#", ...) do
|
||||||
|
local c = select(i, ...)
|
||||||
|
if c < 0x80 then out[#out + 1] = string.char(c)
|
||||||
|
elseif c < 0x800 then out[#out + 1] = string.char(0xC0 + floor(c / 64), 0x80 + c % 64)
|
||||||
|
elseif c < 0x10000 then out[#out + 1] = string.char(0xE0 + floor(c / 4096), 0x80 + floor(c / 64) % 64, 0x80 + c % 64)
|
||||||
|
else out[#out + 1] = string.char(0xF0 + floor(c / 262144), 0x80 + floor(c / 4096) % 64, 0x80 + floor(c / 64) % 64, 0x80 + c % 64) end
|
||||||
|
end
|
||||||
|
return table.concat(out)
|
||||||
|
end
|
||||||
|
local function decode(s, i)
|
||||||
|
local c = s:byte(i)
|
||||||
|
if not c then return nil end
|
||||||
|
if c < 0x80 then return c, 1 end
|
||||||
|
if c < 0xE0 then return (c % 32) * 64 + s:byte(i + 1) % 64, 2 end
|
||||||
|
if c < 0xF0 then return (c % 16) * 4096 + (s:byte(i + 1) % 64) * 64 + s:byte(i + 2) % 64, 3 end
|
||||||
|
return (c % 8) * 262144 + (s:byte(i + 1) % 64) * 4096 + (s:byte(i + 2) % 64) * 64 + s:byte(i + 3) % 64, 4
|
||||||
|
end
|
||||||
|
function utf8.codes(s)
|
||||||
|
local i = 1
|
||||||
|
return function()
|
||||||
|
if i > #s then return nil end
|
||||||
|
local c, n = decode(s, i)
|
||||||
|
local p = i; i = i + n
|
||||||
|
return p, c
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function utf8.codepoint(s, i, j)
|
||||||
|
i = i or 1; j = j or i
|
||||||
|
local out = {}
|
||||||
|
while i <= j do local c, n = decode(s, i); out[#out + 1] = c; i = i + n end
|
||||||
|
return unpack(out)
|
||||||
|
end
|
||||||
|
function utf8.len(s) local n = 0; for _ in utf8.codes(s) do n = n + 1 end return n end
|
||||||
|
function utf8.offset(s, n, i)
|
||||||
|
i = i or (n >= 0 and 1 or #s + 1)
|
||||||
|
if n > 0 then
|
||||||
|
n = n - 1
|
||||||
|
while n > 0 and i <= #s do i = i + 1; while i <= #s and s:byte(i) >= 0x80 and s:byte(i) < 0xC0 do i = i + 1 end; n = n - 1 end
|
||||||
|
if n > 0 then return nil end
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--@compat-end
|
||||||
|
|
||||||
local floor, min = math.floor, math.min
|
local floor, min = math.floor, math.min
|
||||||
|
|
||||||
local ImGui_ImplLOVE_GetBackendData
|
local ImGui_ImplLOVE_GetBackendData
|
||||||
|
|||||||
@@ -1,137 +0,0 @@
|
|||||||
-- Luau standard library pieces the port uses, for LuaJIT (LÖVE). Prepended by `tools/bundle.py --target love` only:
|
|
||||||
-- the Roblox build uses Luau's native bit32/buffer/table/utf8 and never sees this file.
|
|
||||||
|
|
||||||
local ffi = require("ffi")
|
|
||||||
local bit = require("bit")
|
|
||||||
local floor = math.floor
|
|
||||||
local TWO32 = 4294967296
|
|
||||||
|
|
||||||
-- bit32: unsigned 32-bit results like Luau/Lua 5.2 (LuaJIT's `bit` returns signed values)
|
|
||||||
if not bit32 then
|
|
||||||
local band, bor, bxor, bnot, lshift, rshift, arshift, tobit = bit.band, bit.bor, bit.bxor, bit.bnot, bit.lshift, bit.rshift, bit.arshift, bit.tobit
|
|
||||||
local function u(x) return x % TWO32 end
|
|
||||||
local function t(x) return tobit(x % TWO32) end -- any number -> int32 (bit.* wraps doubles >= 2^31 unreliably)
|
|
||||||
bit32 = {}
|
|
||||||
function bit32.band(a, b, ...)
|
|
||||||
if a == nil then return TWO32 - 1 end
|
|
||||||
if b == nil then return u(t(a)) end
|
|
||||||
local r = band(t(a), t(b))
|
|
||||||
if ... ~= nil then for i = 1, select("#", ...) do r = band(r, t((select(i, ...)))) end end
|
|
||||||
return u(r)
|
|
||||||
end
|
|
||||||
function bit32.bor(a, b, ...)
|
|
||||||
if a == nil then return 0 end
|
|
||||||
if b == nil then return u(t(a)) end
|
|
||||||
local r = bor(t(a), t(b))
|
|
||||||
if ... ~= nil then for i = 1, select("#", ...) do r = bor(r, t((select(i, ...)))) end end
|
|
||||||
return u(r)
|
|
||||||
end
|
|
||||||
function bit32.bxor(a, b, ...)
|
|
||||||
if a == nil then return 0 end
|
|
||||||
if b == nil then return u(t(a)) end
|
|
||||||
local r = bxor(t(a), t(b))
|
|
||||||
if ... ~= nil then for i = 1, select("#", ...) do r = bxor(r, t((select(i, ...)))) end end
|
|
||||||
return u(r)
|
|
||||||
end
|
|
||||||
function bit32.bnot(a) return u(bnot(t(a))) end
|
|
||||||
function bit32.lshift(a, n) if n >= 32 or n <= -32 then return 0 end if n < 0 then return u(rshift(t(a), -n)) end return u(lshift(t(a), n)) end
|
|
||||||
function bit32.rshift(a, n) if n >= 32 or n <= -32 then return 0 end if n < 0 then return u(lshift(t(a), -n)) end return u(rshift(t(a), n)) end
|
|
||||||
function bit32.arshift(a, n) if n >= 32 then n = 31 end return u(arshift(t(a), n)) end
|
|
||||||
function bit32.btest(...) return bit32.band(...) ~= 0 end
|
|
||||||
function bit32.extract(n, field, width) width = width or 1; return u(band(rshift(t(n), field), 2 ^ width - 1)) end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- buffer: fixed-size byte buffers (subset used by the port), on FFI memory. Little-endian like Luau.
|
|
||||||
if not buffer then
|
|
||||||
ffi.cdef("void *memmove(void *dst, const void *src, size_t n); void *memset(void *s, int c, size_t n);")
|
|
||||||
local C = ffi.C
|
|
||||||
local u8p, u32p, f64p = ffi.typeof("uint8_t*"), ffi.typeof("uint32_t*"), ffi.typeof("double*")
|
|
||||||
buffer = {}
|
|
||||||
function buffer.create(n)
|
|
||||||
local mem = ffi.new("uint8_t[?]", math.max(n, 1)) -- zero-filled
|
|
||||||
return { p = ffi.cast(u8p, mem), n = n, mem = mem }
|
|
||||||
end
|
|
||||||
function buffer.len(b) return b.n end
|
|
||||||
function buffer.readu8(b, o) return b.p[o] end
|
|
||||||
function buffer.writeu8(b, o, v) b.p[o] = v end
|
|
||||||
function buffer.readu32(b, o) return ffi.cast(u32p, b.p + o)[0] end
|
|
||||||
function buffer.writeu32(b, o, v) ffi.cast(u32p, b.p + o)[0] = v % TWO32 end
|
|
||||||
function buffer.readf64(b, o) return ffi.cast(f64p, b.p + o)[0] end
|
|
||||||
function buffer.writef64(b, o, v) ffi.cast(f64p, b.p + o)[0] = v end
|
|
||||||
function buffer.readstring(b, o, n) return ffi.string(b.p + o, n) end
|
|
||||||
function buffer.writestring(b, o, s, n) ffi.copy(b.p + o, s, n or #s) end
|
|
||||||
function buffer.copy(dst, doff, src, soff, n)
|
|
||||||
soff = soff or 0
|
|
||||||
n = n or (src.n - soff)
|
|
||||||
if n > 0 then C.memmove(dst.p + doff, src.p + soff, n) end
|
|
||||||
end
|
|
||||||
function buffer.fill(b, o, v, n) n = n or (b.n - o); if n > 0 then C.memset(b.p + o, v, n) end end
|
|
||||||
function buffer.tostring(b) return ffi.string(b.p, b.n) end
|
|
||||||
function buffer.fromstring(s) local b = buffer.create(#s); ffi.copy(b.p, s, #s); return b end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- table / math / utf8 additions from Luau / Lua 5.3
|
|
||||||
do
|
|
||||||
local ok, clear = pcall(require, "table.clear")
|
|
||||||
table.clear = table.clear or (ok and clear) or function(t) for k in pairs(t) do t[k] = nil end end
|
|
||||||
table.unpack = table.unpack or unpack
|
|
||||||
table.find = table.find or function(t, v, init) for i = init or 1, #t do if t[i] == v then return i end end end
|
|
||||||
table.move = table.move or function(a1, f, e, t, a2)
|
|
||||||
a2 = a2 or a1
|
|
||||||
if e >= f then
|
|
||||||
if t > f or t > e or a1 ~= a2 then for i = 0, e - f do a2[t + i] = a1[f + i] end
|
|
||||||
else for i = e - f, 0, -1 do a2[t + i] = a1[f + i] end end
|
|
||||||
end
|
|
||||||
return a2
|
|
||||||
end
|
|
||||||
math.pow = math.pow or function(a, b) return a ^ b end
|
|
||||||
end
|
|
||||||
|
|
||||||
if not utf8 then
|
|
||||||
utf8 = { charpattern = "[\0-\x7F\xC2-\xFD][\x80-\xBF]*" }
|
|
||||||
function utf8.char(...)
|
|
||||||
local out = {}
|
|
||||||
for i = 1, select("#", ...) do
|
|
||||||
local c = select(i, ...)
|
|
||||||
if c < 0x80 then out[#out + 1] = string.char(c)
|
|
||||||
elseif c < 0x800 then out[#out + 1] = string.char(0xC0 + floor(c / 64), 0x80 + c % 64)
|
|
||||||
elseif c < 0x10000 then out[#out + 1] = string.char(0xE0 + floor(c / 4096), 0x80 + floor(c / 64) % 64, 0x80 + c % 64)
|
|
||||||
else out[#out + 1] = string.char(0xF0 + floor(c / 262144), 0x80 + floor(c / 4096) % 64, 0x80 + floor(c / 64) % 64, 0x80 + c % 64) end
|
|
||||||
end
|
|
||||||
return table.concat(out)
|
|
||||||
end
|
|
||||||
local function decode(s, i)
|
|
||||||
local c = s:byte(i)
|
|
||||||
if not c then return nil end
|
|
||||||
if c < 0x80 then return c, 1 end
|
|
||||||
if c < 0xE0 then return (c % 32) * 64 + s:byte(i + 1) % 64, 2 end
|
|
||||||
if c < 0xF0 then return (c % 16) * 4096 + (s:byte(i + 1) % 64) * 64 + s:byte(i + 2) % 64, 3 end
|
|
||||||
return (c % 8) * 262144 + (s:byte(i + 1) % 64) * 4096 + (s:byte(i + 2) % 64) * 64 + s:byte(i + 3) % 64, 4
|
|
||||||
end
|
|
||||||
function utf8.codes(s)
|
|
||||||
local i = 1
|
|
||||||
return function()
|
|
||||||
if i > #s then return nil end
|
|
||||||
local c, n = decode(s, i)
|
|
||||||
local p = i; i = i + n
|
|
||||||
return p, c
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function utf8.codepoint(s, i, j)
|
|
||||||
i = i or 1; j = j or i
|
|
||||||
local out = {}
|
|
||||||
while i <= j do local c, n = decode(s, i); out[#out + 1] = c; i = i + n end
|
|
||||||
return unpack(out)
|
|
||||||
end
|
|
||||||
function utf8.len(s) local n = 0; for _ in utf8.codes(s) do n = n + 1 end return n end
|
|
||||||
function utf8.offset(s, n, i)
|
|
||||||
i = i or (n >= 0 and 1 or #s + 1)
|
|
||||||
if n > 0 then
|
|
||||||
n = n - 1
|
|
||||||
while n > 0 and i <= #s do i = i + 1; while i <= #s and s:byte(i) >= 0x80 and s:byte(i) < 0xC0 do i = i + 1 end; n = n - 1 end
|
|
||||||
if n > 0 then return nil end
|
|
||||||
return i
|
|
||||||
end
|
|
||||||
return i
|
|
||||||
end
|
|
||||||
end
|
|
||||||
+1
-1
@@ -21,7 +21,7 @@ there, but keep this port's existing data structures and conventions. Read the s
|
|||||||
## Portability (LÖVE build)
|
## Portability (LÖVE build)
|
||||||
- Library code must stay valid **Lua 5.1/LuaJIT syntax** apart from `@native` lines (stripped for LÖVE): no `+=`, `//`,
|
- Library code must stay valid **Lua 5.1/LuaJIT syntax** apart from `@native` lines (stripped for LÖVE): no `+=`, `//`,
|
||||||
`continue`, type annotations, `if`-expressions or string interpolation. Luau library calls are fine only if
|
`continue`, type annotations, `if`-expressions or string interpolation. Luau library calls are fine only if
|
||||||
`compat/luajit.lua` shims them (`bit32`, `buffer`, `table.clear/find/move/unpack`, `utf8`).
|
the COMPAT section of `backends/imgui_impl_love.lua` shims them (`bit32`, `buffer`, `table.clear/find/move/unpack`, `utf8`).
|
||||||
- Check with `tools/test/love/run.sh` (LuaJIT draw checksums must equal the Luau ones).
|
- Check with `tools/test/love/run.sh` (LuaJIT draw checksums must equal the Luau ones).
|
||||||
|
|
||||||
## Conventions (follow what the port already does)
|
## Conventions (follow what the port already does)
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# Bundles the root *.lua (library + imgui_demo.lua), backends/ and fonts/ 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)
|
# --no-demo: library only (imgui_demo.lua left out, like not compiling imgui_demo.cpp)
|
||||||
# --target love: build/imgui_love.lua for LÖVE/LuaJIT instead (LÖVE backend, compat/luajit.lua shims, @native stripped).
|
# --target love: build/imgui_love.lua for LÖVE/LuaJIT instead (LÖVE backend, shims from the LÖVE backend's COMPAT section, @native stripped).
|
||||||
# The default (roblox) build is unaffected by it.
|
# The default (roblox) build is unaffected by it.
|
||||||
# Why: ModuleScripts don't share globals, and the setfenv() alternative turns off Luau's fast paths / native codegen.
|
# 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.
|
# Each source file becomes a function in __FILES; IM_INCLUDE(name) runs it once and caches the result.
|
||||||
@@ -34,7 +34,7 @@ for src in FILES.values():
|
|||||||
|
|
||||||
out = ["--!optimize 2", "-- GENERATED by tools/bundle.py from *.lua, backends/, fonts/ - do not edit", ""]
|
out = ["--!optimize 2", "-- GENERATED by tools/bundle.py from *.lua, backends/, fonts/ - do not edit", ""]
|
||||||
if LOVE:
|
if LOVE:
|
||||||
out = ["-- GENERATED by tools/bundle.py --target love - do not edit", open(os.path.join(ROOT, "compat", "luajit.lua")).read(), ""]
|
out = ["-- GENERATED by tools/bundle.py --target love - do not edit", re.search(r"--@compat-begin\n(.*?)--@compat-end", open(os.path.join(ROOT, "backends", "imgui_impl_love.lua")).read(), re.S).group(1), ""]
|
||||||
out += [
|
out += [
|
||||||
"local __FILES, __LOADED = {}, {}",
|
"local __FILES, __LOADED = {}, {}",
|
||||||
"function IM_INCLUDE(name)",
|
"function IM_INCLUDE(name)",
|
||||||
|
|||||||
Reference in New Issue
Block a user