--- ImGui Sincerely WIP -- (internal structures/api) --- @meta local type = ImGui._GetTypeFunc() local rawget = rawget local mathMin = math.min; local mathMax = math.max local mathFloor = math.floor; local mathCeil = math.ceil local bitNot = bit32.bnot local bitAnd = bit32.band; local bitOr = bit32.bor local bitLShift = bit32.lshift; local bitRShift = bit32.rshift local t_sort = table.sort --- @alias ImGuiTableColumnIdx ImS16 -- TODO: Implement actual ImString type --- @alias ImString char[]|string --- @alias ImStringBuffer char[] -- NOTE: temporary solution --- @param buf char[] --- @param buf_begin int --- @param buf_end int # exclusive function ImGui._ByteArrayToString(buf, buf_begin, buf_end) local str = {} for i = buf_begin, buf_end - 1 do table.insert(str, string.char(buf[i])) end return table.concat(str) end --- ImPool: pool of objects keyed by ID. Public indices are 0-based like upstream (Buf is stored 1-based). --- `ctor` creates a new element. Removed slots are recycled via FreeIdx (-1 = none; free slots chain through `_NextFree`). local IM_POOL = {} IM_POOL.__index = IM_POOL function ImPool(ctor) return setmetatable({ Buf = {}, Map = {}, FreeIdx = 0, AliveCount = 0, BufSize = 0, _Ctor = ctor }, IM_POOL) end function IM_POOL:GetByKey(key) local i = self.Map[key]; return i and self.Buf[i + 1] or nil end function IM_POOL:GetByIndex(n) return self.Buf[n + 1] end function IM_POOL:GetIndex(p) return p._PoolIdx end function IM_POOL:Contains(p) return p ~= nil and self.Buf[(p._PoolIdx or -1) + 1] == p end function IM_POOL:GetMapSize() return self.BufSize end function IM_POOL:Clear() self.Buf = {}; self.Map = {}; self.FreeIdx = 0; self.AliveCount = 0; self.BufSize = 0 end function IM_POOL:Add() local idx if self._Free and #self._Free > 0 then idx = table.remove(self._Free) else idx = self.BufSize; self.BufSize = self.BufSize + 1 end local p = self._Ctor and self._Ctor() or {} p._PoolIdx = idx self.Buf[idx + 1] = p self.AliveCount = self.AliveCount + 1 return p end function IM_POOL:GetOrAddByKey(key) local i = self.Map[key] if i then return self.Buf[i + 1] end local p = self:Add(); self.Map[key] = p._PoolIdx; return p end function IM_POOL:Remove(key, p) if type(key) == "table" then p = key; key = nil end if key == nil then for k, i in pairs(self.Map) do if i == p._PoolIdx then key = k break end end end if key ~= nil then self.Map[key] = nil end self.Buf[p._PoolIdx + 1] = false self._Free = self._Free or {} table.insert(self._Free, p._PoolIdx) self.AliveCount = self.AliveCount - 1 end function IM_POOL:Reserve(n) end -- NOTE: removed slots hold `false`; iterate with `for i = 0, pool:GetMapSize() - 1 do local t = pool:GetByIndex(i) if t then ... end end` --- @type ImGuiContext? local GImGui -- Sets local `GImGui` in this file(imgui_internal.lua). -- This is currently only used in main code `ImGui.SetCurrentContext()` --- @param ctx ImGuiContext? function ImGui._SetCurrentContext_Internal(ctx) GImGui = ctx end local setmetatable = setmetatable local MT = ImGui.GetMetatables() IM_TABSIZE = 4 FLT_MIN = 1.1754943508223e-38 FLT_MAX = 3.4028234663853e+38 DBL_MAX = 1.7976931348623e+308 INT_MIN = -0x7fffffff - 1 INT_MAX = 0x7fffffff UINT_MAX = 0x7fffffff * 2 + 1 NAV_WINDOWING_HIGHLIGHT_DELAY = 0.5 NAV_ACTIVATE_HIGHLIGHT_TIMER = 0.10 NAV_ACTIVATE_INPUT_WITH_GAMEPAD_DELAY = 0.60 IM_PI = math.pi ImPow = math.pow ImLog = math.log ImAbs = math.abs ImFabs = math.abs ImFmod = function(a, b) if b < 0 then b = -b end; if a < 0 then return -(-a % b) else return a % b end; end ImRound64 = function(val) return math.floor(val + 0.5) end -- FIXME: Positive values only ImCeil = math.ceil ImSin = math.sin ImCos = math.cos ImAcos = math.acos ImAtan2 = math.atan2 ImSqrt = math.sqrt --- @generic T: number --- @param a T --- @param b T --- @param mn T --- @param mx T --- @return T function ImAddClampOverflow(a, b, mn, mx) if b < 0 and (a < mn - b) then return mn end if b > 0 and (a > mx - b) then return mx end return a + b end --- @generic T: number --- @param a T --- @param b T --- @param mn T --- @param mx T --- @return T function ImSubClampOverflow(a, b, mn, mx) if b > 0 and (a < mn + b) then return mn end if b < 0 and (a > mx + b) then return mx end return a - b end --- @overload fun(lhs: number, rhs: number): number --- @overload fun(lhs: ImVec2, rhs: ImVec2): ImVec2 function ImMin(lhs, rhs) if type(lhs) == "number" and type(rhs) == "number" then return mathMin(lhs, rhs) elseif type(lhs) == "table" and type(rhs) == "table" then return ImVec2(mathMin(lhs[1], rhs[1]), mathMin(lhs[2], rhs[2])) end end --- @overload fun(lhs: number, rhs: number): number --- @overload fun(lhs: ImVec2, rhs: ImVec2): ImVec2 function ImMax(lhs, rhs) if type(lhs) == "number" and type(rhs) == "number" then return mathMax(lhs, rhs) elseif type(lhs) == "table" and type(rhs) == "table" then return ImVec2(mathMax(lhs[1], rhs[1]), mathMax(lhs[2], rhs[2])) end end --- @param base table --- @param count int --- @param cmp_func fun(lhs, rhs): bool ImStd.ImQsort = function(base, count, cmp_func) if count > 0 then t_sort(base, cmp_func) end end --- @overload fun(v: number, mn: number, mx: number): number --- @overload fun(v: ImVec2, mn: ImVec2, mx: ImVec2): ImVec2 function ImClamp(v, mn, mx) if type(v) == "number" and type(mn) == "number" and type(mx) == "number" then return mathMin(mathMax(v, mn), mx) elseif type(v) == "table" and type(mn) == "table" and type(mx) == "table" then return ImVec2(mathMax(mn[1], mathMin(v[1], mx[1])), mathMax(mn[2], mathMin(v[2], mx[2]))) end end --- @overload fun(a: number, b: number, t: number): number --- @overload fun(a: ImVec2, b: ImVec2, t: number): ImVec2 --- @overload fun(a: ImVec2, b: ImVec2, t: ImVec2): ImVec2 function ImLerp(a, b, t) if type(a) == "number" and type(b) == "number" and type(t) == "number" then return ((a) + ((b) - (a)) * (t)) elseif type(a) == "table" and type(b) == "table" and type(t) == "number" then return ImVec2(a[1] + (b[1] - a[1]) * t, a[2] + (b[2] - a[2]) * t) elseif type(a) == "table" and type(b) == "table" and type(t) == "table" then return ImVec2(a[1] + (b[1] - a[1]) * t[1], a[2] + (b[2] - a[2]) * t[2]) end end local function _Trunc(val) if val >= 0 then return mathFloor(val) else return mathCeil(val) end end --- @overload fun(v: float): float --- @overload fun(v: ImVec2): ImVec2 function ImTrunc(v) if type(v) == "number" then return _Trunc(v) elseif type(v) == "table" then return ImVec2(_Trunc(v[1]), _Trunc(v[2])) end end ImTrunc64 = _Trunc --- @param f float function ImCeilFast(f) local i if f >= 0 then i = math.floor(f) else i = math.ceil(f) end -- same as `ImTrunc()` if f > i then return i + 1 end return i end function IM_ROUNDUP_TO_EVEN(n) return (ImCeil((n) / 2) * 2) end function ImRsqrt(x) return (1 / ImSqrt(x)) end function IM_TRUNC(VAL) return math.floor(VAL) end -- Positive values only! function IM_ROUND(VAL) return math.floor(VAL + 0.5) end function ImFloor(f) if f >= 0 or math.floor(f) == f then return math.floor(f) else return math.floor(f) - 1 end end --- @param v int function ImIsPowerOfTwo(v) return (v ~= 0) and (bitAnd(v, (v - 1)) == 0) end function ImUpperPowerOfTwo(v) if v <= 0 then return 0 end if v <= 1 then return 1 end v = v - 1 v = bitOr(v, bitRShift(v, 1)) v = bitOr(v, bitRShift(v, 2)) v = bitOr(v, bitRShift(v, 4)) v = bitOr(v, bitRShift(v, 8)) v = bitOr(v, bitRShift(v, 16)) return v + 1 end --- @param v unsigned_int --- @return unsigned_int function ImCountSetBits(v) local count = 0 while v > 0 do v = bitAnd(v, v - 1) count = count + 1 end return count end --- @param avg float --- @param sample float --- @param n int --- @return float function ImStd.ImExponentialMovingAverage(avg, sample, n) avg = avg - avg / n avg = avg + sample / n return avg end -- Uses `string.match` internally --- @param str string function ImAtof(str) return tonumber(string.match(str, "[+-]?%d*%.?%d+")) end --- @param s table # 1-based --- @param c any --- @param n int function ImStd.memset(s, c, n) for i = 1, n do s[i] = c end end do local _memmove = function(dest, dest_start, src, src_start, count) if count <= 0 then return end -- more compact instead of writing separate if-else and for loops local c = (dest == src and dest_start >= src_start) for i = (c and count - 1 or 0), (c and 0 or count - 1), (c and -1 or 1) do dest[dest_start + i] = src[src_start + i] end end if table.move then --- [GMod] Platform specific: the `table.move` polyfill in non-x86-64 currently uses `unpack` which will break if too many elements -- Remove this check when the polyfill is fixed or removed if not gmod or (gmod and BRANCH == "x86-64") then _memmove = function(dest, dest_start, src, src_start, count) table.move(src, src_start, src_start + count - 1, dest_start, dest) end end end ImStd.memmove = _memmove end --- @param str1 ImStringBuffer --- @param str2 ImStringBuffer function ImStd.strcmp(str1, str2) local i = 1 while true do local c1 = str1[i] or 0 local c2 = str2[i] or 0 if c1 ~= c2 then return c1 - c2 end if c1 == 0 then return 0 end i = i + 1 end end --- @param str1 ImStringBuffer --- @param str2 ImStringBuffer --- @param max_count int function ImStd.strncmp(str1, str2, max_count) for i = 1, max_count do local c1 = str1[i] or 0 local c2 = str2[i] or 0 if c1 ~= c2 then return c1 - c2 end if c1 == 0 then return 0 end end return 0 end function ImSaturate(f) return ((f < 0.0 and 0.0) or (f > 1.0 and 1.0) or f) end IM_F32_TO_INT8_UNBOUND = function(val) return math.floor(val * 255.0 + (val >= 0 and 0.5 or -0.5)) end IM_F32_TO_INT8_SAT = function(val) return math.floor(ImSaturate(val) * 255.0 + 0.5) end --- @param s ImString --- @param i int --- @return char function ImStrByte(s, i) if type(s) == "string" then return string.byte(s, i, i) else --- @cast s char[] return s[i] end end --- @class ImGuiColorMod --- @field Col ImGuiCol --- @field BackupValue ImVec4 --- @param col ImGuiCol --- @param backup_value ImVec4 --- @return ImGuiColorMod function ImGuiColorMod(col, backup_value) local this = { Col = col, BackupValue = ImVec4() } ImVec4_Copy(this.BackupValue, backup_value) return this end --- @param lhs ImVec2 --- @return float function ImLengthSqr(lhs) return (lhs.x * lhs.x) + (lhs.y * lhs.y) end --- @param v ImVec2 --- @param cos_a float --- @param sin_a float --- @return ImVec2 --- @nodiscard function ImRotate(v, cos_a, sin_a) return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a) end --- @param a ImVec2 --- @param b ImVec2 function ImDot(a, b) return a.x * b.x + a.y * b.y end --- @param lhs ImVec2 --- @param rhs ImVec2 --- @nodiscard function ImMul(lhs, rhs) return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y) end --- @param str char[] --- @param begin? int function ImStd.ImStrlen(str, begin) if begin == nil then begin = 1 end local l = #str for i = begin, l do if str[i] == 0 then return i - begin end end IM_ASSERT(false) end -- FIXME: should also accept count? -- FIXME: avoid dynamic type checking? -- string.find with patterns disabled --- @param str string|char[] --- @param s string|char --- @param start_pos? int --- @return int? function ImMemchr(str, s, start_pos) local start = start_pos or 1 if start < 1 then start = 1 end if type(str) == "table" then for i = start, #str do if str[i] == 0 then break end if str[i] == s then return i end end return nil end --- @cast str string local pos = string.find(str, s, start, true) return pos end IMGUI_FONT_SIZE_MAX = 512.0 IMGUI_FONT_SIZE_THRESHOLD_FOR_LOADADVANCEXONLYMODE = 128.0 IMGUI_WINDOW_HARD_MIN_SIZE = 4.0 IM_DRAWLIST_ARCFAST_TABLE_SIZE = 48 IM_DRAWLIST_ARCFAST_SAMPLE_MAX = IM_DRAWLIST_ARCFAST_TABLE_SIZE function IM_ASSERT_USER_ERROR(_EXPR, _MSG) if not (_EXPR) or (_EXPR) == 0 then error(_MSG, 2) end end function IM_ASSERT_USER_ERROR_RET(_EXPR, _MSG) if not (_EXPR) or (_EXPR) == 0 then error(_MSG, 2) end end function IMGUI_DEBUG_LOG_ACTIVEID(_str, ...) local g = GImGui if bitAnd(g.DebugLogFlags, ImGuiDebugLogFlags.EventActiveId) ~= 0 then print(string.format(_str, ...)) end end function IMGUI_DEBUG_LOG_POPUP(_str, ...) local g = GImGui if bitAnd(g.DebugLogFlags, ImGuiDebugLogFlags.EventPopup) ~= 0 then print(string.format(_str, ...)) end end function IMGUI_DEBUG_LOG_FONT(_str, ...) local g2 = GImGui if g2 and bitAnd(g2.DebugLogFlags, ImGuiDebugLogFlags.EventFont) ~= 0 then print(string.format(_str, ...)) end end function IMGUI_DEBUG_LOG_VIEWPORT(_str, ...) local g = GImGui if bitAnd(g.DebugLogFlags, ImGuiDebugLogFlags.EventViewport) ~= 0 then print(string.format(_str, ...)) end end --- @alias ImGuiSelectionUserData any ImGuiSelectionUserData_Invalid = -1 ImGuiKeyOwner_Any = 0 ImGuiKeyOwner_NoOwner = 4294967295 --- @param button ImGuiMouseButton --- @return ImGuiKey function ImGui.MouseButtonToKey(button) IM_ASSERT(button >= 0 and button < ImGuiMouseButton.COUNT) return ImGuiKey.MouseLeft + button end --- @param key ImGuiKey function ImGui.IsNamedKey(key) return key >= ImGuiKey.NamedKey_BEGIN and key < ImGuiKey.NamedKey_END end --- @param key ImGuiKey function ImGui.IsKeyboardKey(key) return key >= ImGuiKey_Keyboard_BEGIN and key < ImGuiKey_Keyboard_END end --- @param key ImGuiKey function ImGui.IsGamepadKey(key) return key >= ImGuiKey_Gamepad_BEGIN and key < ImGuiKey_Gamepad_END end --- @param key ImGuiKey function ImGui.IsMouseKey(key) return key >= ImGuiKey_Mouse_BEGIN and key < ImGuiKey_Mouse_END end --- @param key ImGuiKey function ImGui.IsAliasKey(key) return key >= ImGuiKey_Aliases_BEGIN and key < ImGuiKey_Aliases_END end --- @param key ImGuiKey function ImGui.IsLRModKey(key) return key >= ImGuiKey.LeftCtrl and key <= ImGuiKey.RightSuper end --- @param key ImGuiKey --- @return bool function ImGui.IsNamedKeyOrMod(key) return (key >= ImGuiKey.NamedKey_BEGIN and key < ImGuiKey.NamedKey_END) or key == ImGuiMod_Ctrl or key == ImGuiMod_Shift or key == ImGuiMod_Alt or key == ImGuiMod_Super end --- @param key ImGuiKey --- @return ImGuiKey function ImGui.ConvertSingleModFlagToKey(key) if key == ImGuiMod_Ctrl then return ImGuiKey.ReservedForModCtrl elseif key == ImGuiMod_Shift then return ImGuiKey.ReservedForModShift elseif key == ImGuiMod_Alt then return ImGuiKey.ReservedForModAlt elseif key == ImGuiMod_Super then return ImGuiKey.ReservedForModSuper end return key end --- @param ctx ImGuiContext --- @param key ImGuiKey function ImGui.GetKeyOwnerData(ctx, key) if bitAnd(key, ImGuiMod_Mask_) ~= 0 then key = ImGui.ConvertSingleModFlagToKey(key) end IM_ASSERT(ImGui.IsNamedKey(key)) return ctx.KeysOwnerData[key - ImGuiKey.NamedKey_BEGIN] end --- @class ImGuiKeyOwnerData --- @return ImGuiKeyOwnerData --- @nodiscard function ImGuiKeyOwnerData() return { OwnerCurr = ImGuiKeyOwner_NoOwner, OwnerNext = ImGuiKeyOwner_NoOwner, LockThisFrame = false, LockUntilRelease = false } end --- @param size float --- @return float function ImGui.GetRoundedFontSize(size) return IM_ROUND(size) end --- @param window ImGuiWindow --- @param r ImRect --- @return ImRect --- @nodiscard function ImGui.WindowRectAbsToRel(window, r) local off = window.DC.CursorStartPos return ImRect(r.Min.x - off.x, r.Min.y - off.y, r.Max.x - off.x, r.Max.y - off.y) end --- @param window ImGuiWindow --- @param r ImRect --- @nodiscard function ImGui.WindowRectRelToAbs(window, r) local off = window.DC.CursorStartPos return ImRect(r.Min.x + off.x, r.Min.y + off.y, r.Max.x + off.x, r.Max.y + off.y) end --- @param dir ImGuiDir --- @return bool function ImGui.IsActiveIdUsingNavDir(dir) local g = GImGui return bit32.band(g.ActiveIdUsingNavDirMask, bit32.lshift(1, dir)) ~= 0 end --- @param window ImGuiWindow --- @param p ImVec2 --- @return ImVec2 --- @nodiscard function ImGui.WindowPosAbsToRel(window, p) local off = window.DC.CursorStartPos return ImVec2(p.x - off.x, p.y - off.y) end --- @param c char --- @return bool # True if this character is a ' ' or '\t' function ImCharIsBlankA(c) return c == 32 or c == 9 end --- @param c char function ImCharIsBlankW(c) return c == 32 or c == 9 or c == 0x3000 end --- @enum ImGuiNavMoveFlags ImGuiNavMoveFlags = { None = 0, LoopX = bitLShift(1, 0), LoopY = bitLShift(1, 1), WrapX = bitLShift(1, 2), WrapY = bitLShift(1, 3), AllowCurrentNavId = bitLShift(1, 4), AlsoScoreVisibleSet = bitLShift(1, 5), ScrollToEdgeY = bitLShift(1, 6), Forwarded = bitLShift(1, 7), DebugNoResult = bitLShift(1, 8), FocusApi = bitLShift(1, 9), IsTabbing = bitLShift(1, 10), IsPageMove = bitLShift(1, 11), Activate = bitLShift(1, 12), NoSelect = bitLShift(1, 13), NoSetNavCursorVisible = bitLShift(1, 14), NoClearActiveId = bitLShift(1, 15), } ImGuiNavMoveFlags.WrapMask_ = bitOr(ImGuiNavMoveFlags.LoopX, ImGuiNavMoveFlags.LoopY, ImGuiNavMoveFlags.WrapX, ImGuiNavMoveFlags.WrapY) --- @enum ImGuiNavLayer ImGuiNavLayer = { Main = 0, Menu = 1, COUNT = 2 } ImGuiItemFlags.ReadOnly = bitLShift(1, 11) ImGuiItemFlags.MixedValue = bitLShift(1, 12) ImGuiItemFlags.NoWindowHoverableCheck = bitLShift(1, 13) ImGuiItemFlags.AllowOverlap = bitLShift(1, 14) ImGuiItemFlags.NoNavDisableMouseHover = bitLShift(1, 15) ImGuiItemFlags.NoMarkEdited = bitLShift(1, 16) ImGuiItemFlags.NoFocus = bitLShift(1, 17) ImGuiItemFlags.Inputable = bitLShift(1, 20) ImGuiItemFlags.HasSelectionUserData = bitLShift(1, 21) ImGuiItemFlags.IsMultiSelect = bitLShift(1, 22) ImGuiItemFlags.Default_ = bitOr(ImGuiItemFlags.AutoClosePopups, ImGuiItemFlags.LiveEditOnInputText) --- @enum ImDrawTextFlags ImDrawTextFlags = { None = 0, CpuFineClip = bitLShift(1, 0), WrapKeepBlanks = bitLShift(1, 1), StopOnNewLine = bitLShift(1, 2) } --- @enum ImGuiFocusRequestFlags ImGuiFocusRequestFlags = { None = 0, RestoreFocusedChild = bitLShift(1, 0), UnlessBelowModal = bitLShift(1, 1) } --- @enum ImGuiTextFlags ImGuiTextFlags = { None = 0, NoWidthForLargeClippedText = bitLShift(1, 0) } --- @enum ImWcharClass ImWcharClass = { Blank = 0, Punct = 1, Other = 2 } --- @class ImVec1 --- @field x number local IM_VEC1 = {} IM_VEC1.__index = IM_VEC1 local function ImVec1(x) return setmetatable({x = x or 0}, IM_VEC1) end function IM_VEC1:__tostring() return string.format("ImVec1(%g)", self.x) end --- @param dest ImVec1 --- @param src ImVec1 function ImVec1_Copy(dest, src) dest.x = src.x end --- @class ImRect --- @field [1] ImVec2 --- @field [2] ImVec2 --- @field Min ImVec2 --- @field Max ImVec2 local IM_RECT = {} --- @param t ImRect --- @param k string IM_RECT.__index = function(t, k) local method = IM_RECT[k] if method ~= nil then return method end if k == "Min" then return rawget(t, 1) elseif k == "Max" then return rawget(t, 2) end end --- @param t ImRect --- @param k string --- @param v ImVec2 IM_RECT.__newindex = function(t, k, v) if k == "Min" then ImVec2_Copy(rawget(t, 1), v) elseif k == "Max" then ImVec2_Copy(rawget(t, 2), v) else IM_ASSERT(false) end end --- @return ImRect --- @nodiscard function ImRect(a, b, c, d) if c and d then return setmetatable({ ImVec2(a, b), ImVec2(c, d) }, IM_RECT) end return setmetatable({ ImVec2(a and a.x or 0, a and a.y or 0), ImVec2(b and b.x or 0, b and b.y or 0) }, IM_RECT) end function IM_RECT:__eq(other) return self[1] == other[1] and self[2] == other[2] end function IM_RECT:__tostring() return string.format("ImRect(Min: %g,%g, Max: %g,%g)", self.Min.x, self.Min.y, self.Max.x, self.Max.y) end --- @param p ImRect|ImVec2 function IM_RECT:Contains(p) if p.Min then --- @cast p ImRect return p[1][1] >= self[1][1] and p[2][1] <= self[2][1] and p[1][2] >= self[1][2] and p[2][2] <= self[2][2] else --- @cast p ImVec2 return p[1] >= self[1][1] and p[2] >= self[1][2] and p[1] < self[2][1] and p[2] < self[2][2] end end --- @param p ImVec2 --- @param pad ImVec2 function IM_RECT:ContainsWithPad(p, pad) return p[1] >= self[1][1] - pad[1] and p[2] >= self[1][2] - pad[2] and p[1] < self[2][1] + pad[1] and p[2] < self[2][2] + pad[2] end --- @param r ImRect function IM_RECT:Overlaps(r) return self[1][1] <= r[2][1] and self[2][1] >= r[1][1] and self[1][2] <= r[2][2] and self[2][2] >= r[1][2] end --- @nodiscard function IM_RECT:GetCenter() return ImVec2((self[1][1] + self[2][1]) * 0.5, (self[1][2] + self[2][2]) * 0.5) end function IM_RECT:GetWidth() return self[2][1] - self[1][1] end function IM_RECT:GetHeight() return self[2][2] - self[1][2] end --- @nodiscard function IM_RECT:GetSize() return ImVec2(self[2][1] - self[1][1], self[2][2] - self[1][2]) end --- @nodiscard function IM_RECT:GetTL() return ImVec2(self[1][1], self[1][2]) end --- @nodiscard function IM_RECT:GetTR() return ImVec2(self[2][1], self[1][2]) end --- @nodiscard function IM_RECT:GetBL() return ImVec2(self[1][1], self[2][2]) end --- @nodiscard function IM_RECT:GetBR() return ImVec2(self[2][1], self[2][2]) end --- @param r ImRect function IM_RECT:ClipWith(r) ImVec2_Copy(self[1], ImMax(self[1], r[1])); ImVec2_Copy(self[2], ImMin(self[2], r[2])) end --- @param r ImRect function IM_RECT:ClipWithFull(r) ImVec2_Copy(self[1], ImClamp(self[1], r[1], r[2])); ImVec2_Copy(self[2], ImClamp(self[2], r[1], r[2])) end --- @param p ImRect|ImVec2 function IM_RECT:Add(p) if p.Min then --- @cast p ImRect if (self[1][1] > p[1][1]) then self[1][1] = p[1][1] end if (self[1][2] > p[1][2]) then self[1][2] = p[1][2] end if (self[2][1] < p[2][1]) then self[2][1] = p[2][1] end if (self[2][2] < p[2][2]) then self[2][2] = p[2][2] end else --- @cast p ImVec2 if p[1] < self[1][1] then self[1][1] = p[1] end if p[2] < self[1][2] then self[1][2] = p[2] end if p[1] > self[2][1] then self[2][1] = p[1] end if p[2] > self[2][2] then self[2][2] = p[2] end end end --- @param amount float|ImVec2 function IM_RECT:Expand(amount) if type(amount) == "number" then self[1][1] = self[1][1] - amount; self[1][2] = self[1][2] - amount self[2][1] = self[2][1] + amount; self[2][2] = self[2][2] + amount elseif type(amount) == "table" then self[1][1] = self[1][1] - amount[1]; self[1][2] = self[1][2] - amount[2] self[2][1] = self[2][1] + amount[1]; self[2][2] = self[2][2] + amount[2] end end --- @nodiscard function IM_RECT:ToVec4() return ImVec4(self[1][1], self[1][2], self[2][1], self[2][2]) end --- @param d ImVec2 function IM_RECT:Translate(d) self[1][1] = self[1][1] + d[1]; self[1][2] = self[1][2] + d[2] self[2][1] = self[2][1] + d[1]; self[2][2] = self[2][2] + d[2] end --- @param dy float function IM_RECT:TranslateY(dy) self[1][2] = self[1][2] + dy; self[2][2] = self[2][2] + dy end function IM_RECT:IsInverted() return self[1][1] > self[2][1] or self[1][2] > self[2][2] end function IM_RECT:GetArea() return (self[2][1] - self[1][1]) * (self[2][2] - self[1][2]) end --- @nodiscard function IM_RECT:AsVec4() return ImVec4(self[1][1], self[1][2], self[2][1], self[2][2]) end --- @param dest ImRect --- @param src ImRect function ImRect_Copy(dest, src) dest[1][1] = src[1][1]; dest[1][2] = src[1][2] dest[2][1] = src[2][1]; dest[2][2] = src[2][2] end --- @param dest ImRect --- @param src ImVec4 function ImRect_CopyFromV4(dest, src) dest[1][1] = src[1]; dest[1][2] = src[2] dest[2][1] = src[3]; dest[2][2] = src[4] end --- @param _ARRAY ImU32[] --- @param _N int function IM_BITARRAY_TESTBIT(_ARRAY, _N) return bitAnd(_ARRAY[bitRShift(_N - 1, 5) + 1], bitLShift(1, bitAnd(_N - 1, 31))) ~= 0 end --- @param _ARRAY ImU32[] --- @param _N int function IM_BITARRAY_CLEARBIT(_ARRAY, _N) local idx = bitRShift(_N - 1, 5) + 1 _ARRAY[idx] = bitAnd(_ARRAY[idx], bitNot(bitLShift(1, bitAnd(_N - 1, 31)))) end --- @param arr ImU32[] --- @param n int function ImBitArraySetBit(arr, n) local mask = bitLShift(1, bitAnd(n - 1, 31)) local idx = bitRShift(n - 1, 5) + 1 arr[idx] = bitOr(arr[idx], mask) end --- @alias ImBitArrayForNamedKeys ImBitArray --- NOTE: This struct is expensive to create --- @class ImBitArray --- @field Data ImU32[] --- @param BITCOUNT int --- @param OFFSET? int --- @return ImBitArray function ImBitArray(BITCOUNT, OFFSET) if OFFSET == nil then OFFSET = 0 end local this = { Data = {} } local size = bitRShift(BITCOUNT + 31, 5) this.ClearAllBits = function(self) local data = self.Data; for i = 1, size do data[i] = 0 end end this.SetAllBits = function(self) local data = self.Data; for i = 1, size do data[i] = 0xFFFFFFFF end end --- @param n int # 1-based --- @return boolean this.TestBit = function(self, n) n = n + OFFSET; IM_ASSERT(n >= 1 and n <= BITCOUNT); return IM_BITARRAY_TESTBIT(self.Data, n); end --- @param n int # 1-based this.SetBit = function(self, n) n = n + OFFSET; IM_ASSERT(n >= 1 and n <= BITCOUNT); ImBitArraySetBit(self.Data, n); end this:ClearAllBits() return this end function MT.ImDrawList:PathClear() self._Path:clear() end --- @param pos ImVec2 function MT.ImDrawList:PathLineTo(pos) self._Path:push_back(pos) end function MT.ImDrawList:PathLineToMergeDuplicate(pos) local path_size = self._Path.Size if path_size == 0 or self._Path.Data[path_size].x ~= pos.x or self._Path.Data[path_size].y ~= pos.y then self._Path:push_back(pos) end end function MT.ImDrawList:PathFillConvex(col) self:AddConvexPolyFilled(self._Path.Data, self._Path.Size, col) self._Path.Size = 0 end --- @param col ImU32 --- @param thickness? float --- @param flags? ImDrawFlags function MT.ImDrawList:PathStroke(col, thickness, flags) if not thickness then thickness = 1.0 end if not flags then flags = 0 end self:AddPolyline(self._Path.Data, self._Path.Size, col, thickness, flags) self._Path.Size = 0 end --- @param col ImU32 function ImGui.SetNextItemColorMarker(col) local g = GImGui g.NextItemData.HasFlags = bitOr(g.NextItemData.HasFlags, ImGuiNextItemDataFlags.HasColorMarker) g.NextItemData.ColorMarker = col end --- @class ImDrawListSharedData --- @field TexUvWhitePixel ImVec2 --- @field TexUvLines ImVec4[] --- @field FontAtlas ImFontAtlas --- @field Font ImFont --- @field FontSize float --- @field FontScale float --- @field CurveTessellationTol float --- @field CircleTessellationMaxError float --- @field InitialFringeScale float --- @field InitialFlags ImDrawListFlags --- @field ClipRectFullscreen? ImVec4 --- @field TempBuffer ImVector --- @field DrawLists ImVector --- @field Context? ImGuiContext --- @field ArcFastVtx table # 1-based table --- @field ArcFastRadiusCutoff float --- @field CircleSegmentCounts table # 1-based table MT.ImDrawListSharedData = {} MT.ImDrawListSharedData.__index = MT.ImDrawListSharedData --- @return ImDrawListSharedData --- @nodiscard function ImDrawListSharedData() local this = setmetatable({ TexUvWhitePixel = nil, TexUvLines = nil, FontAtlas = nil, Font = nil, FontSize = 0, FontScale = 0, CurveTessellationTol = 0, CircleTessellationMaxError = 0, InitialFringeScale = 1, InitialFlags = 0, ClipRectFullscreen = nil, TempBuffer = ImVector(ImVec2), DrawLists = ImVector(), ArcFastVtx = {}, ArcFastRadiusCutoff = nil, CircleSegmentCounts = {}, Context = nil }, MT.ImDrawListSharedData) for i = 1, IM_DRAWLIST_ARCFAST_TABLE_SIZE do local a = ((i - 1) * 2 * IM_PI) / IM_DRAWLIST_ARCFAST_TABLE_SIZE this.ArcFastVtx[i] = ImVec2(ImCos(a), ImSin(a)) end return this end --- @class ImFontAtlasBuilder --- @field PackContext stbrp_context --- @field PackNodes ImVector --- @field Rects ImVector --- @field RectsIndex ImVector --- @field TempBuffer ImVector --- @field RectsIndexFreeListStart int --- @field RectsPackedCount int --- @field RectsPackedSurface int --- @field RectsDiscardedCount int --- @field RectsDiscardedSurface int --- @field FrameCount int --- @field MaxRectSize ImVec2 --- @field MaxRectBounds ImVec2 --- @field LockDisableResize bool --- @field PreloadedAllGlyphsRanges bool --- @field BakedPool ImVector --- @field BakedMap table # LUA: No ImGuiStorage --- @field BakedDiscardedCount int --- @field PackIdMouseCursors ImFontAtlasRectId --- @field PackIdLinesTexData ImFontAtlasRectId MT.ImFontAtlasBuilder = {} MT.ImFontAtlasBuilder.__index = MT.ImFontAtlasBuilder --- @return ImFontAtlasBuilder function ImFontAtlasBuilder() --- @type ImFontAtlasBuilder local this = setmetatable({}, MT.ImFontAtlasBuilder) this.PackContext = nil -- struct stbrp_context_opaque { char data[80]; }; this.PackNodes = ImVector() this.Rects = ImVector() this.RectsIndex = ImVector() this.TempBuffer = ImVector() this.RectsIndexFreeListStart = -1 this.RectsPackedCount = 0 this.RectsPackedSurface = 0 this.RectsDiscardedCount = 0 this.RectsDiscardedSurface = 0 this.FrameCount = -1 this.MaxRectSize = ImVec2() this.MaxRectBounds = ImVec2() this.LockDisableResize = false this.PreloadedAllGlyphsRanges = false this.BakedPool = ImVector() -- ImStableVector this.BakedMap = {} this.BakedDiscardedCount = 0 this.PackIdMouseCursors = -1 this.PackIdLinesTexData = -1 return this end --- @class ImFontStackData --- @field Font ImFont --- @field FontSizeBeforeScaling float --- @field FontSizeAfterScaling float --- @return ImFontStackData --- @param font ImFont --- @param font_size_before_scaling float --- @param font_size_after_scaling float --- @nodiscard function ImFontStackData(font, font_size_before_scaling, font_size_after_scaling) return { Font = font, FontSizeBeforeScaling = font_size_before_scaling, FontSizeAfterScaling = font_size_after_scaling } end --- `GetVarPtr()` is currently only used on `g.Style` in Dear ImGui, and we don't have pointers! --- @class ImGuiStyleVarInfo --- @field Count ImU32 --- @field DataType ImGuiDataType --- @field Key string # key in parent structure. Note that the cpp Dear ImGui uses `ImU32 Offset`! --- @param count ImU32 --- @param data_type ImGuiDataType --- @param key string --- @return ImGuiStyleVarInfo --- @nodiscard function ImGuiStyleVarInfo(count, data_type, key) return { Count = count, DataType = data_type, Key = key } end --- @class ImGuiStyleMod --- @field VarIdx ImGuiStyleVar --- @field BackupVal table --- @param idx ImGuiStyleVar --- @param v int|float|ImVec2 function ImGuiStyleMod(idx, v) local this = { VarIdx = idx, BackupVal = {nil, nil} } --- @cast this ImGuiStyleMod if type(v) == "number" then this.BackupVal[1] = v else -- ImVec2 this.BackupVal[1] = v.x; this.BackupVal[2] = v.y end return this end --- Type information associated to one ImGuiDataType. Retrieve with DataTypeGetInfo() --- @class ImGuiDataTypeInfo --- @field Size size_t # Size in bytes --- @field Name string # Short descriptive name for the type, for debugging --- @field PrintFmt string # Default printf format for the type --- @field ScanFmt string # Default scanf format for the type --- @class ImGuiLastItemData --- @field ID ImGuiID --- @field ItemFlags ImGuiItemFlags --- @field StatusFlags ImGuiItemStatusFlags --- @field Rect ImRect --- @field NavRect ImRect --- @field DisplayRect ImRect --- @field ClipRect ImRect --- @field Shortcut ImGuiKeyChord --- @return ImGuiLastItemData --- @nodiscard function ImGuiLastItemData() return { ID = 0, ItemFlags = 0, StatusFlags = 0, Rect = ImRect(), NavRect = ImRect(), DisplayRect = ImRect(), ClipRect = ImRect(), Shortcut = 0 } end --- @param dest ImGuiLastItemData --- @param src ImGuiLastItemData function ImGuiLastItemData_Copy(dest, src) dest.ID = src.ID dest.ItemFlags = src.ItemFlags dest.StatusFlags = src.StatusFlags ImRect_Copy(dest.Rect, src.Rect) ImRect_Copy(dest.NavRect, src.NavRect) ImRect_Copy(dest.DisplayRect, src.DisplayRect) ImRect_Copy(dest.ClipRect, src.ClipRect) dest.Shortcut = src.Shortcut end --- @class ImGuiTreeNodeStackData --- @field ID ImGuiID --- @field TreeFlags ImGuiTreeNodeFlags --- @field ItemFlags ImGuiItemFlags --- @field NavRect ImRect --- @field DrawLinesX1 float --- @field DrawLinesToNodesY2 float --- @field DrawLinesTableColumn ImGuiTableColumnIdx --- @return ImGuiTreeNodeStackData --- @nodiscard local function ImGuiTreeNodeStackData() return { ID = nil, TreeFlags = nil, ItemFlags = nil, NavRect = ImRect(), DrawLinesX1 = nil, DrawLinesToNodesY2 = nil, DrawLinesTableColumn = nil } end --- @class ImGuiNextItemData --- @field HasFlags ImGuiNextItemDataFlags --- @field ItemFlagsSet ImGuiItemFlags --- @field FocusScopeId ImGuiID --- @field SelectionUserData any --- @field Width number --- @field Shortcut ImGuiKeyChord --- @field ShortcutFlags ImGuiInputFlags --- @field OpenVal boolean --- @field OpenCond ImGuiCond --- @field RefVal any --- @field StorageId ImGuiID --- @field ColorMarker ImU32 local IMGUI_NEXT_ITEM_DATA = {} IMGUI_NEXT_ITEM_DATA.__index = IMGUI_NEXT_ITEM_DATA function IMGUI_NEXT_ITEM_DATA:ClearFlags() self.HasFlags = ImGuiNextItemDataFlags.None self.ItemFlagsSet = ImGuiItemFlags.None end --- @return ImGuiNextItemData --- @nodiscard function ImGuiNextItemData() return setmetatable({ HasFlags = 0, ItemFlagsSet = 0, FocusScopeId = 0, SelectionUserData = -1, Width = 0.0, Shortcut = 0, ShortcutFlags = 0, OpenVal = false, OpenCond = 0, RefVal = 0, StorageId = 0, ColorMarker = 0 }, IMGUI_NEXT_ITEM_DATA) end --- @class ImGuiNextWindowData --- @field HasFlags ImGuiNextWindowDataFlags --- @field PosCond ImGuiCond --- @field SizeCond ImGuiCond --- @field CollapsedCond ImGuiCond --- @field PosVal ImVec2? --- @field PosPivotVal ImVec2? --- @field SizeVal ImVec2? --- @field ContentSizeVal ImVec2? --- @field ScrollVal ImVec2? --- @field WindowFlags ImGuiWindowFlags? --- @field ChildFlags ImGuiChildFlags? --- @field CollapsedVal boolean? --- @field SizeConstraintRect ImRect? --- @field SizeCallback function? --- @field SizeCallbackUserData any --- @field BgAlphaVal number? --- @field MenuBarOffsetMinVal ImVec2? --- @field RefreshFlagsVal int? local IMGUI_NEXT_WINDOW_DATA = {} IMGUI_NEXT_WINDOW_DATA.__index = IMGUI_NEXT_WINDOW_DATA function IMGUI_NEXT_WINDOW_DATA:ClearFlags() self.HasFlags = ImGuiNextWindowDataFlags.None end --- @return ImGuiNextWindowData --- @nodiscard function ImGuiNextWindowData() return setmetatable({ HasFlags = 0, PosCond = 0, SizeCond = 0, CollapsedCond = 0, PosVal = ImVec2(), PosPivotVal = ImVec2(), SizeVal = ImVec2(), ContentSizeVal = ImVec2(), ScrollVal = ImVec2(), WindowFlags = nil, ChildFlags = nil, WindowFlagsSet = 0, WindowFlagsClear = 0, ChildFlagsSet = 0, ChildFlagsClear = 0, ViewportId = 0, DockId = 0, DockCond = 0, PosUndock = false, WindowClass = nil, CollapsedVal = nil, SizeConstraintRect = nil, SizeCallback = nil, SizeCallbackUserData = nil, BgAlphaVal = nil, MenuBarOffsetMinVal = ImVec2(), RefreshFlagsVal = nil }, IMGUI_NEXT_WINDOW_DATA) end --- @enum ImGuiWindowBgClickFlags ImGuiWindowBgClickFlags = { None = 0, Move = bitLShift(1, 0), } --- @enum ImGuiNextWindowDataFlags ImGuiNextWindowDataFlags = { None = 0, HasPos = bitLShift(1, 0), HasSize = bitLShift(1, 1), HasContentSize = bitLShift(1, 2), HasCollapsed = bitLShift(1, 3), HasSizeConstraint = bitLShift(1, 4), HasFocus = bitLShift(1, 5), HasBgAlpha = bitLShift(1, 6), HasScroll = bitLShift(1, 7), HasWindowFlags = bitLShift(1, 8), HasChildFlags = bitLShift(1, 9), HasRefreshPolicy = bitLShift(1, 10), HasViewport = bitLShift(1, 11), HasDock = bitLShift(1, 12), HasWindowClass = bitLShift(1, 13) } --- @enum ImGuiLayoutType ImGuiLayoutType = { Horizontal = 0, Vertical = 1 } --- @enum ImGuiSeparatorFlags ImGuiSeparatorFlags = { None = 0, Horizontal = bitLShift(1, 0), -- Axis default to current layout type, so generally Horizontal unless e.g. in a menu bar Vertical = bitLShift(1, 1), SpanAllColumns = bitLShift(1, 2) -- Make separator cover all columns of a legacy Columns() set } --- @class ImGuiStyle MT.ImGuiStyle = {} MT.ImGuiStyle.__index = MT.ImGuiStyle --- @return ImGuiStyle --- @nodiscard function ImGuiStyle() --- @type ImGuiStyle local this = { FontSizeBase = 0.0, FontScaleMain = 1.0, FontScaleDpi = 1.0, Alpha = 1.0, DisabledAlpha = 0.60, FramePadding = ImVec2(4, 3), FrameRounding = 0.0, FrameBorderSize = 0.0, WindowPadding = ImVec2(8, 8), TouchExtraPadding = ImVec2(0, 0), IndentSpacing = 21.0, WindowRounding = 0, WindowBorderSize = 1, ScrollbarSize = 14.0, ScrollbarRounding = 9.0, ScrollbarPadding = 2.0, GrabMinSize = 12.0, GrabRounding = 0.0, ImageRounding = 0.0, ImageBorderSize = 0.0, WindowBorderHoverPadding = 4.0, TreeLinesFlags = ImGuiTreeNodeFlags.DrawLinesNone, TreeLinesSize = 1.0, TreeLinesRounding = 0.0, MenuItemRounding = 0.0, SelectableRounding = 0.0, ColorMarkerSize = 3.0, ColorButtonPosition = ImGuiDir.Right, InputTextCursorSize = 1.0, SeparatorSize = 1.0, SeparatorTextBorderSize = 3.0, SeparatorTextAlign = ImVec2(0.0, 0.5), SeparatorTextPadding = ImVec2(20.0, 3.0), DisplaySafeAreaPadding = ImVec2(3, 3), DisplayWindowPadding = ImVec2(19, 19), AntiAliasedLines = true, AntiAliasedLinesUseTex = true, AntiAliasedFill = true, CurveTessellationTol = 1.25, CircleTessellationMaxError = 0.30, HoverStationaryDelay = 0.15, HoverDelayShort = 0.15, HoverDelayNormal = 0.40, Colors = {}, ButtonTextAlign = ImVec2(0.5, 0.5), SelectableTextAlign = ImVec2(0.0, 0.0), WindowMinSize = ImVec2(32, 32), WindowTitleAlign = ImVec2(0.0, 0.5), WindowMenuButtonPosition = ImGuiDir.Left, ChildRounding = 0.0, ChildBorderSize = 1.0, PopupRounding = 0.0, PopupBorderSize = 1.0, DockingSeparatorSize = 2.0, DockingNodeHasCloseButton = true, MouseCursorScale = 1.0, ItemSpacing = ImVec2(8, 4), ItemInnerSpacing = ImVec2(4, 4), CellPadding = ImVec2(4, 2), ColumnsMinSpacing = 6.0, LogSliderDeadzone = 4.0, TabRounding = 5.0, TabBorderSize = 0.0, TabMinWidthBase = 1.0, TabMinWidthShrink = 80.0, TabCloseButtonMinWidthSelected = -1.0, TabCloseButtonMinWidthUnselected = 0.0, TabBarBorderSize = 1.0, TabBarOverlineSize = 1.0, TableAngledHeadersAngle = 35.0 * (IM_PI / 180.0), TableAngledHeadersTextAlign = ImVec2(0.5, 0.0), DragDropTargetRounding = 0.0, DragDropTargetBorderSize = 2.0, DragDropTargetPadding = 3.0, HoverFlagsForTooltipMouse = bitOr(ImGuiHoveredFlags.Stationary, ImGuiHoveredFlags.DelayShort, ImGuiHoveredFlags.AllowWhenDisabled), HoverFlagsForTooltipNav = bitOr(ImGuiHoveredFlags.NoSharedDelay, ImGuiHoveredFlags.DelayNormal, ImGuiHoveredFlags.AllowWhenDisabled), -- [Internal] _MainScale = 1.0, _NextFrameFontSizeBase = 0.0 } ImGui.StyleColorsDark(this) setmetatable(this, MT.ImGuiStyle) return this end --- @class ImGuiWindowStackData --- @return ImGuiWindowStackData --- @nodiscard function ImGuiWindowStackData() return { Window = nil, ParentLastItemDataBackup = ImGuiLastItemData(), StackSizesInBegin = nil, DisabledOverrideReenable = nil, DisabledOverrideReenableAlphaBackup = nil } end --- @class ImGuiComboPreviewData --- @field PreviewRect ImRect --- @field BackupCursorPos ImVec2 --- @field BackupCursorMaxPos ImVec2 --- @field BackupCursorPosPrevLine ImVec2 --- @field BackupPrevLineTextBaseOffset float --- @field BackupLayout ImGuiLayoutType --- @return ImGuiComboPreviewData --- @nodiscard local function ImGuiComboPreviewData() return { PreviewRect = ImRect(), BackupCursorPos = ImVec2(), BackupCursorMaxPos = ImVec2(), BackupCursorPosPrevLine = ImVec2(), BackupPrevLineTextBaseOffset = 0.0, BackupLayout = 0 } end --- @alias IMSTB_TEXTEDIT_STRING ImGuiInputTextState --- @alias ImStbTexteditState STB_TexteditState --- @class ImGuiInputTextState --- @field Ctx ImGuiContext # parent UI context (needs to be set explicitly by parent) --- @field Stb ImStbTexteditState # State for stb_textedit.lua --- @field Flags ImGuiInputTextFlags --- @field ID ImGuiID # widget id owning the text state --- @field TextLen int # UTF-8 length of the string in TextA (in bytes) --- @field TextSrc ImStringBuffer # == TextA.Data unless read-only, in which case == buf passed to InputText(). For _ReadOnly fields, pointer will be null outside the InputText() call --- @field TextA ImVector # main UTF8 buffer. TextA.Size is a buffer size! Should always be >= buf_size passed by user (and of course >= CurLenA + 1) --- @field TextToRevertTo ImVector # value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered) --- @field CallbackTextBackup ImVector # temporary storage for callback to support automatic reconcile of undo-stack --- @field BufCapacity int # end-user buffer capacity (include zero terminator) --- @field Scroll ImVec2 # horizontal offset (managed manually) + vertical scrolling (pulled from child window's own Scroll.y) --- @field LineCount int # last line count (solely for debugging) --- @field WrapWidth float # word-wrapping width --- @field CursorAnim float # timer for cursor blink, reset on every user action so the cursor reappears immediately --- @field CursorFollow bool # set when we want scrolling to follow the current cursor position (not always!) --- @field CursorCenterY bool # set when we want scrolling to be centered over the cursor position (while resizing a word-wrapping field) --- @field SelectedAllMouseLock bool # after a double-click to select all, we ignore further mouse drags to update selection --- @field EditedBefore bool # edited since activated --- @field EditedThisFrame bool # edited this frame MT.ImGuiInputTextState = {} MT.ImGuiInputTextState.__index = MT.ImGuiInputTextState local function ImGuiInputTextState() local this = { Ctx = nil, Stb = STB_TexteditState(), -- FIXME: no global! Flags = 0, ID = 0, TextLen = 0, TextSrc = nil, TextA = ImVector(), TextToRevertTo = ImVector(), CallbackTextBackup = ImVector(), BufCapacity = 0, Scroll = ImVec2(), LineCount = 0, WrapWidth = 0.0, CursorAnim = 0.0, CursorFollow = false, CursorCenterY = false, SelectedAllMouseLock = false, EditedBefore = false, EditedThisFrame = false, } return setmetatable(this, MT.ImGuiInputTextState) end --- @class ImGuiInputTextDeactivatedState --- @field ID ImGuiID # widget id owning the text state (which just got deactivated) --- @field ElapseFrame int --- @field TextA ImVector # text buffer local IMGUI_INPUT_TEXT_DEACTIVATED_STATE = {} IMGUI_INPUT_TEXT_DEACTIVATED_STATE.__index = IMGUI_INPUT_TEXT_DEACTIVATED_STATE function IMGUI_INPUT_TEXT_DEACTIVATED_STATE:ClearFreeMemory() self.ID = 0 self.ElapseFrame = 0 self.TextA:clear() end --- @return ImGuiInputTextDeactivatedState --- @nodiscard local function ImGuiInputTextDeactivatedState() return setmetatable({ ID = 0, ElapseFrame = 0, TextA = ImVector() }, IMGUI_INPUT_TEXT_DEACTIVATED_STATE) end --- @alias ImGuiKeyRoutingIndex ImS16 --- @class ImGuiKeyRoutingData --- @field NextEntryIndex ImGuiKeyRoutingIndex --- @field Mods ImU16 --- @field RoutingCurrScore ImU16 --- @field RoutingNextScore ImU16 --- @field RoutingCurr ImGuiID --- @field RoutingNext ImGuiID --- @return ImGuiKeyRoutingData --- @nodiscard function ImGuiKeyRoutingData() return { NextEntryIndex = -1, Mods = 0, RoutingCurrScore = 0, RoutingNextScore = 0, RoutingCurr = ImGuiKeyOwner_NoOwner, RoutingNext = ImGuiKeyOwner_NoOwner } end --- @class ImGuiKeyRoutingTable --- @field Index ImGuiKeyRoutingIndex[] --- @field Entries ImVector --- @field EntriesNext ImVector local _ImGuiKeyRoutingTable = {} _ImGuiKeyRoutingTable.__index = _ImGuiKeyRoutingTable function _ImGuiKeyRoutingTable:Clear() for n = 1, ImGuiKey.NamedKey_COUNT do self.Index[n] = -1 end self.Entries:clear() self.EntriesNext:clear() end --- @return ImGuiKeyRoutingTable local function ImGuiKeyRoutingTable() local this = setmetatable({ Index = {}, Entries = ImVector(), EntriesNext = ImVector() }, _ImGuiKeyRoutingTable) this:Clear() return this end --- @class ImGuiTextIndex --- @field Offsets ImVector --- @field EndOffset int local IMGUI_TEXT_INDEX = {} IMGUI_TEXT_INDEX.__index = IMGUI_TEXT_INDEX function IMGUI_TEXT_INDEX:clear() self.Offsets:clear(); self.EndOffset = 0; end function IMGUI_TEXT_INDEX:get_line_begin(base, n) return base + (self.Offsets.Size ~= 0 and self.Offsets[n] or 0) end function IMGUI_TEXT_INDEX:get_line_end(base, n) return base + ((n + 1 < self.Offsets.Size) and (self.Offsets[n + 1] - 1) or self.EndOffset) end --- @return ImGuiTextIndex local function ImGuiTextIndex() return setmetatable({ Offsets = ImVector(), EndOffset = 0 }, IMGUI_TEXT_INDEX) end --- @class ImGuiDebugAllocEntry --- @field FrameCount int --- @field AllocCount int --- @field FreeCount int --- @return ImGuiDebugAllocEntry local function ImGuiDebugAllocEntry() return { FrameCount = 0, AllocCount = 0, FreeCount = 0 } end --- @class ImGuiDebugAllocInfo --- @field TotalAllocCount int --- @field TotalFreeCount int --- @field LastEntriesIdx ImS16 --- @field LastEntriesBuf ImGuiDebugAllocEntry[] --- @return ImGuiDebugAllocInfo local function ImGuiDebugAllocInfo() local this = { TotalAllocCount = 0, TotalFreeCount = 0, LastEntriesIdx = 1, LastEntriesBuf = {nil, nil, nil, nil, nil, nil}, } for i = 1, 6 do this.LastEntriesBuf[i] = ImGuiDebugAllocEntry() end return this end --- @class ImGuiMetricsConfig --- @return ImGuiMetricsConfig local function ImGuiMetricsConfig() return { HighlightMonitorIdx = -1, HighlightViewportID = 0, } end --- @class ImGuiNavItemData --- @field Window ImGuiWindow? --- @field ID ImGuiID --- @field FocusScopeId ImGuiID --- @field RectRel ImRect --- @field ItemFlags ImGuiItemFlags --- @field SelectionUserData ImGuiSelectionUserData --- @field DistBox float --- @field DistCenter float --- @field DistAxial float local IMGUI_NAV_ITEM_DATA = {} IMGUI_NAV_ITEM_DATA.__index = IMGUI_NAV_ITEM_DATA function IMGUI_NAV_ITEM_DATA:Clear() self.Window = nil self.ID = 0 self.FocusScopeId = 0 self.ItemFlags = 0 self.SelectionUserData = ImGuiSelectionUserData_Invalid self.DistBox = FLT_MAX self.DistCenter = FLT_MAX self.DistAxial = FLT_MAX end --- @return ImGuiNavItemData local function ImGuiNavItemData() local this = setmetatable({ }, IMGUI_NAV_ITEM_DATA) this.RectRel = ImRect() this:Clear() return this end --- @class ImGuiContext --- @field Initialized bool --- @field WithinFrameScope bool --- @field WithinFrameScopeWithImplicitWindow bool --- @field FrameCount int --- @field FrameCountEnded int --- @field CurrentWindow ImGuiWindow --- @field HoveredWindow ImGuiWindow --- @field Style ImGuiStyle --- @field FontAtlases ImVector --- @field Font ImFont --- @field FontBaked ImFontBaked? --- @field FontSize float --- @field FontSizeBase float --- @field FontBakedScale float --- @field FontRasterizerDensity float --- @field DrawListSharedData ImDrawListSharedData --- @field NextItemData ImGuiNextItemData --- @field LastItemData ImGuiLastItemData --- @field NextWindowData ImGuiNextWindowData --- @field WithinEndChildID ImGuiID --- @field WithinEndPopupID ImGuiID --- @field StyleVarStack ImVector --- @field AnyIdHasBeenEditedThisFrame bool --- @field ActiveId ImGuiID --- @field ActiveIdMouseButton ImS8 --- @field Windows ImVector --- @field WindowsFocusOrder ImVector --- @field WindowsTempSortBuffer ImVector --- @field CurrentWindowStack ImVector --- @field FocusScopeStack ImVector --- @field ItemFlagsStack ImVector --- @field GroupStack ImVector --- @field OpenPopupStack ImVector --- @field BeginPopupStack ImVector --- @field TreeNodeStack ImVector --- @field IO ImGuiIO --- @field PlatformIO ImGuiPlatformIO --- @field Viewports ImVector --- @field DebugLogFlags ImGuiDebugLogFlags --- @field DebugFlashStyleColorIdx ImGuiCol --- @field ColorEditCurrentID ImGuiID # Set temporarily while inside of the parent-most ColorEdit4/ColorPicker4 (because they call each others) --- @field ColorEditSavedID ImGuiID # ID we are saving/restoring HS for --- @field ColorEditSavedHue float # Backup of last Hue associated to LastColor, so we can restore Hue in lossy RGB<>HSV round trips --- @field ColorEditSavedSat float # Backup of last Saturation associated to LastColor, so we can restore Saturation in lossy RGB<>HSV round trips --- @field ColorEditSavedColor ImU32 # RGB value with alpha set to 0 --- @field ColorPickerRef ImVec4 # Initial/reference color at the time of opening the color picker --- @field MenusIdSubmittedThisFrame ImVector --- @field InputTextState ImGuiInputTextState --- @field InputTextLineIndex ImGuiTextIndex --- @field InputTextDeactivatedState ImGuiInputTextDeactivatedState --- @field InputTextPasswordFontBackupBaked ImFontBaked --- @field KeysMayBeCharInput ImBitArrayForNamedKeys --- @field KeysOwnerData ImGuiKeyOwnerData[] --- @field KeysRoutingTable ImGuiKeyRoutingTable --- @field NavFocusRoute ImVector --- @field PlatformImeData ImGuiPlatformImeData --- @field PlatformImeDataPrev ImGuiPlatformImeData --- @field UserTextures ImVector --- @field DebugMetricsConfig ImGuiMetricsConfig --- @field DebugAllocInfo ImGuiDebugAllocInfo --- @field TempBuffer ImVector ---------------------------------------------------------------- -- [SECTION] Tab bar, Tab item support (public flags from imgui.h + private extensions) ---------------------------------------------------------------- --- @enum ImGuiTabBarFlags ImGuiTabBarFlags = { None = 0, Reorderable = bitLShift(1, 0), AutoSelectNewTabs = bitLShift(1, 1), TabListPopupButton = bitLShift(1, 2), NoCloseWithMiddleMouseButton = bitLShift(1, 3), NoTabListScrollingButtons = bitLShift(1, 4), NoTooltip = bitLShift(1, 5), DrawSelectedOverline = bitLShift(1, 6), FittingPolicyMixed = bitLShift(1, 7), FittingPolicyShrink = bitLShift(1, 8), FittingPolicyScroll = bitLShift(1, 9), -- Private DockNode = bitLShift(1, 20), IsFocused = bitLShift(1, 21), SaveSettings = bitLShift(1, 22), } ImGuiTabBarFlags.FittingPolicyMask_ = bitOr(ImGuiTabBarFlags.FittingPolicyMixed, ImGuiTabBarFlags.FittingPolicyShrink, ImGuiTabBarFlags.FittingPolicyScroll) ImGuiTabBarFlags.FittingPolicyDefault_ = ImGuiTabBarFlags.FittingPolicyMixed ImGuiTabBarFlags.FittingPolicyResizeDown = ImGuiTabBarFlags.FittingPolicyShrink --- @enum ImGuiTabItemFlags ImGuiTabItemFlags = { None = 0, UnsavedDocument = bitLShift(1, 0), SetSelected = bitLShift(1, 1), NoCloseWithMiddleMouseButton = bitLShift(1, 2), NoPushId = bitLShift(1, 3), NoTooltip = bitLShift(1, 4), NoReorder = bitLShift(1, 5), Leading = bitLShift(1, 6), Trailing = bitLShift(1, 7), NoAssumedClosure = bitLShift(1, 8), -- Private NoCloseButton = bitLShift(1, 20), Button = bitLShift(1, 21), Invisible = bitLShift(1, 22), Unsorted = bitLShift(1, 23), } ImGuiTabItemFlags.SectionMask_ = bitOr(ImGuiTabItemFlags.Leading, ImGuiTabItemFlags.Trailing) -- Storage for one active tab item. In this port the label is stored in `Name` (C++ uses NameOffset into TabBar.TabsNames) --- @class ImGuiTabItem --- @return ImGuiTabItem function ImGuiTabItem() return { ID = 0, Flags = 0, Window = nil, LastFrameVisible = -1, LastFrameSelected = -1, Offset = 0.0, Width = 0.0, ContentWidth = 0.0, RequestedWidth = -1.0, NameOffset = -1, Name = nil, BeginOrder = -1, -- 0-based IndexDuringLayout = -1, -- 0-based WantClose = false, } end -- Storage for a tab bar. Tabs: ImVector of ImGuiTabItem tables (references; "pointers" stay valid across reorders) --- @class ImGuiTabBar --- @return ImGuiTabBar function ImGuiTabBar() return { Window = nil, Tabs = ImVector(), Flags = 0, ID = 0, SelectedTabId = 0, NextSelectedTabId = 0, NextScrollToTabId = 0, VisibleTabId = 0, CurrFrameVisible = -1, PrevFrameVisible = -1, BarRect = ImRect(), BarRectPrevWidth = 0.0, CurrTabsContentsHeight = 0.0, PrevTabsContentsHeight = 0.0, WidthAllTabs = 0.0, WidthAllTabsIdeal = 0.0, ScrollingAnim = 0.0, ScrollingTarget = 0.0, ScrollingTargetDistToVisibility = 0.0, ScrollingSpeed = 0.0, ScrollingRectMinX = 0.0, ScrollingRectMaxX = 0.0, SeparatorMinX = 0.0, SeparatorMaxX = 0.0, ReorderRequestTabId = 0, ReorderRequestOffset = 0, BeginCount = 0, WantLayout = false, VisibleTabWasSubmitted = false, TabsAddedNew = false, ScrollButtonEnabled = false, TabsActiveCount = 0, LastTabItemIdx = -1, -- 0-based ItemSpacingY = 0.0, FramePadding = ImVec2(), BackupCursorPos = ImVec2(), } end --- @class ImGuiShrinkWidthItem function ImGuiShrinkWidthItem() return { Index = 0, Width = 0.0, InitialWidth = 0.0 } end --- @param shared_font_atlas? ImFontAtlas --- @return ImGuiContext --- @nodiscard function ImGuiContext(shared_font_atlas) -- TODO: tidy up / complete this structure local this = { Style = ImGuiStyle(), ColorStack = ImVector(), StyleVarStack = ImVector(), Config = nil, Initialized = false, WithinFrameScope = false, WithinFrameScopeWithImplicitWindow = false, Windows = ImVector(), -- Windows sorted in display order, back to front WindowsById = {}, -- Map window's ID to window ref WindowsBorderHoverPadding = 0, WindowsActiveCount = 0, WindowsTempSortBuffer = ImVector(), CurrentWindowStack = ImVector(), CurrentWindow = nil, WindowsFocusOrder = ImVector(), IO = ImGuiIO(), PlatformIO = ImGuiPlatformIO(), ConfigFlagsCurrFrame = ImGuiConfigFlags.None, ConfigFlagsLastFrame = ImGuiConfigFlags.None, MouseLastValidPos = ImVec2(), KeysMayBeCharInput = ImBitArray(ImGuiKey.NamedKey_COUNT, -ImGuiKey.NamedKey_BEGIN), KeysOwnerData = {}, -- size = ImGuiKey.NamedKey_COUNT KeysRoutingTable = ImGuiKeyRoutingTable(), InputEventsQueue = ImVector(), InputEventsNextMouseSource = ImGuiMouseSource.Mouse, InputEventsNextEventId = 1, MovingWindow = nil, WheelingWindow = nil, WheelingWindowStartFrame = -1, WheelingWindowScrolledFrame = -1, WheelingWindowReleaseTimer = 0.0, WheelingWindowRefMousePos = ImVec2(), WheelingWindowWheelRemainder = ImVec2(), WheelingAxisAvg = ImVec2(), ActiveIdClickOffset = ImVec2(), HoveredWindow = nil, HoveredWindowUnderMovingWindow = nil, HoveredIdIsDisabled = false, ActiveIdFromShortcut = false, AnyIdHasBeenEditedThisFrame = false, ActiveId = 0, ActiveIdWindow = nil, ActiveIdMouseButton = -1, ActiveIdIsJustActivated = false, ActiveIdWasSelected = false, ActiveIdWasSoleSelected = false, LastActiveIdWasSelected = false, LastActiveIdWasSoleSelected = false, ActiveIdNoClearOnFocusLoss = false, ActiveIdHasBeenPressedBefore = false, ActiveIdIsAlive = nil, ActiveIdPreviousFrame = 0, ActiveIdTimer = 0.0, LastActiveId = 0, LastActiveIdTimer = 0.0, ActiveIdUsingNavDirMask = 0x00, ActiveIdUsingAllKeyboardKeys = false, DeactivatedItemData = { ID = 0, ElapseFrame = 0, HasBeenEditedBefore = false, IsAlive = false }, HoveredId = 0, HoveredIdTimer = 0.0, HoveredIdNotActiveTimer = 0.0, HoveredIdAllowOverlap = false, HoverItemDelayId = 0, HoverItemDelayIdPreviousFrame = 0, HoverItemUnlockedStationaryId = 0, HoverWindowUnlockedStationaryId = 0, HoverItemDelayTimer = 0.0, HoverItemDelayClearTimer = 0.0, ActiveIdAllowOverlap = false, NavLayer = ImGuiNavLayer.Main, NavId = 0, NavOpenContextMenuItemId = 0, NavOpenContextMenuWindowId = 0, NavWindow = nil, NavHighlightActivatedId = 0, NavHighlightActivatedTimer = 0.0, NavCursorVisible = false, NavCursorHideFrames = 0, NavHighlightItemUnderNav = false, NavIdIsAlive = false, NavInputSource = ImGuiInputSource.Keyboard, NavWindowingTarget = nil, NavWindowingTargetAnim = nil, NavWindowingListWindow = nil, NavWindowingTimer = 0.0, NavWindowingHighlightAlpha = 0.0, NavWindowingToggleLayer = false, NavWindowingToggleKey = ImGuiKey.None, NavWindowingInputSource = ImGuiInputSource.None, NavWindowingAccumDeltaPos = ImVec2(0.0, 0.0), NavWindowingAccumDeltaSize = ImVec2(0.0, 0.0), DimBgRatio = 0.0, LastKeyboardKeyPressTime = -1.0, LastKeyModsChangeTime = -1.0, LastKeyModsChangeFromNoneTime = -1.0, ConfigNavWindowingKeyNext = bit32.bor(ImGuiMod_Ctrl, ImGuiKey.Tab), ConfigNavWindowingKeyPrev = bit32.bor(ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey.Tab), ConfigNavWindowingWithGamepad = true, NavFocusRoute = ImVector(), NavAnyRequest = false, NavInitRequest = false, NavInitRequestFromMove = false, NavInitResult = ImGuiNavItemData(), NavMoveSubmitted = false, NavMoveScoringItems = false, NavMoveForwardToNextFrame = false, NavMoveFlags = ImGuiNavMoveFlags.None, NavMoveScrollFlags = ImGuiScrollFlags.None, NavMoveKeyMods = ImGuiMod_None, NavMoveDir = ImGuiDir.None, NavMoveDirForDebug = ImGuiDir.None, NavMoveClipDir = ImGuiDir.None, NavMoveResultLocal = ImGuiNavItemData(), NavMoveResultOther = ImGuiNavItemData(), NavMoveResultLocalVisible = ImGuiNavItemData(), NavTabbingResultFirst = ImGuiNavItemData(), NavScoringRect = ImRect(), NavScoringNoClipRect = ImRect(), ConfigNavEnableTabbing = true, NavTabbingCounter = 0, NavTabbingDir = 0, NavNextActivateId = 0, NavNextActivateFlags = ImGuiActivateFlags.None, NavActivateId = 0, NavActivateDownId = 0, NavActivatePressedId = 0, NavActivateFlags = ImGuiActivateFlags.None, FrameCount = -1, FrameCountEnded = -1, FrameCountPlatformEnded = -1, FrameCountRendered = -1, Time = 0, NextItemData = ImGuiNextItemData(), LastItemData = ImGuiLastItemData(), NextWindowData = ImGuiNextWindowData(), Viewports = ImVector(), FallbackMonitor = nil, GcCompactAll = false, CurrentViewport = nil, MouseViewport = nil, MouseLastHoveredViewport = nil, PlatformLastFocusedViewportId = 1, ViewportCreatedCount = 0, PlatformWindowsCreatedCount = 0, ViewportFocusedStampCount = 0, Font = nil, FontSize = 0.0, FontSizeBase = 0.0, CurrentDpiScale = 0.0, FontRefSize = 0.0, FontRasterizerDensity = 1.0, FontAtlases = ImVector(), FontStack = ImVector(), OpenPopupStack = ImVector(), BeginPopupStack = ImVector(), TreeNodeStack = ImVector(ImGuiTreeNodeStackData), WithinEndChildID = 0, WithinEndPopupID = 0, BeginMenuDepth = 0, BeginComboDepth = 0, ColorEditCurrentID = 0, ColorEditSavedID = 0, ColorEditSavedHue = 0.0, ColorEditSavedSat = 0.0, ColorEditSavedColor = 0, ColorPickerRef = ImVec4(), MenusIdSubmittedThisFrame = ImVector(), DrawListSharedData = ImDrawListSharedData(), StackSizesInBeginForCurrentWindow = nil, MouseCursor = ImGuiMouseCursor.Arrow, MouseStationaryTimer = 0.0, InputTextState = ImGuiInputTextState(), InputTextLineIndex = ImGuiTextIndex(), InputTextDeactivatedState = ImGuiInputTextDeactivatedState(), InputTextPasswordFontBackupBaked = ImFontBaked(), InputTextReactivateId = 0, TempInputId = 0, ActiveIdValueOnActivation = 0, DataTypeZeroValue = 0, ComboPreviewData = ImGuiComboPreviewData(), CurrentTabBar = nil, TabBars = ImPool(ImGuiTabBar), -- ImPool -- Docking DockContext = ImGuiDockContext(), DockNodeWindowMenuHandler = nil, DebugHoveredDockNode = nil, CurrentTabBarStack = ImVector(), -- holds ImGuiTabBar references directly (no ImGuiPtrOrIndex needed in Lua) ShrinkWidthBuffer = ImVector(), -- ImGuiShrinkWidthItem WindowResizeBorderExpectedRect = ImRect(), WindowResizeRelativeMode = false, ScrollbarSeekMode = 0, ScrollbarClickDeltaToGrabCenter = 0.0, SliderGrabClickOffset = 0.0, SliderCurrentAccum = 0.0, SliderCurrentAccumDirty = false, DragCurrentAccumDirty = false, DragCurrentAccum = 0.0, DragSpeedDefaultRatio = 1.0 / 100.0, TooltipOverrideCount = 0, TooltipPreviousWindow = nil, FocusScopeStack = ImVector(), CurrentFocusScopeId = 0, CurrentItemFlags = ImGuiItemFlags.None, DisabledAlphaBackup = 0.0, DisabledStackSize = 0, ItemFlagsStack = ImVector(), GroupStack = ImVector(), PlatformImeData = ImGuiPlatformImeData(), PlatformImeDataPrev = ImGuiPlatformImeData(), -- Extensions UserTextures = ImVector(), -- Settings SettingsLoaded = false, SettingsDirtyTimer = 0.0, SettingsIniData = "", -- In memory .ini settings (string) SettingsHandlers = ImVector(), -- List of .ini settings handlers SettingsWindows = ImVector(), SettingsTables = ImVector(), -- Hooks Hooks = ImVector(), HookIdNext = 0, -- Drag and Drop DragDropActive = false, DragDropWithinSource = false, DragDropWithinTarget = false, DragDropSourceFlags = 0, DragDropSourceFrameCount = -1, DragDropMouseButton = -1, DragDropPayload = ImGuiPayload(), DragDropTargetRect = ImRect(), DragDropTargetClipRect = ImRect(), DragDropTargetId = 0, DragDropTargetFullViewport = 0, DragDropAcceptFlagsCurr = 0, DragDropAcceptFlagsPrev = 0, DragDropAcceptIdCurrRectSurface = 0.0, DragDropAcceptFrameCount = -1, DragDropHoldJustPressedId = 0, DragDropAcceptIdPrev = 0, DragDropAcceptIdCurr = 0, -- Clipper ClipperTempDataStacked = 0, ClipperTempData = ImVector(), -- Logging LogEnabled = false, LogLineFirstItem = false, LogFlags = 0, LogWindow = nil, LogFile = nil, LogBuffer = ImGuiTextBuffer(), LogNextPrefix = nil, LogNextSuffix = nil, LogLinePosY = FLT_MAX, LogDepthRef = 0, LogDepthToExpand = 2, LogDepthToExpandDefault = 2, -- Error handling ErrorCallback = nil, ErrorCallbackUserData = nil, ErrorTooltipLockedPos = ImVec2(), ErrorFirst = true, ErrorCountCurrentFrame = 0, StackSizesInNewFrame = nil, ContextName = "", DebugBreakInWindow = 0, LocalizationTable = {}, DebugLogFlags = bitOr(ImGuiDebugLogFlags.EventError, ImGuiDebugLogFlags.OutputToTTY), DebugFlashStyleColorIdx = nil, DebugMetricsConfig = ImGuiMetricsConfig(), DebugAllocInfo = ImGuiDebugAllocInfo(), --- Misc FramerateSecPerFrame = {}, -- size = 60 FramerateSecPerFrameIdx = 0, FramerateSecPerFrameCount = 0, FramerateSecPerFrameAccum = 0, WantCaptureMouseNextFrame = -1, WantCaptureKeyboardNextFrame = -1, WantTextInputNextFrame = -1, TempBuffer = ImVector(), -- Tables (imgui_tables.lua) CurrentTable = nil, DebugBreakInTable = 0, TablesTempDataStacked = 0, TablesTempData = ImVector(), Tables = ImPool(), -- ImPool, 0-based indices (imgui_tables.lua) TablesLastTimeActive = ImVector(), -- [table_idx + 1] = float DrawChannelsTempMergeBuffer = ImVector(), SettingsTables = ImVector(), -- ImChunkStream: plain vector, SettingsOffset = 1-based index } for i = 0, 59 do this.FramerateSecPerFrame[i] = 0 end this.IO.Fonts = (shared_font_atlas ~= nil) and shared_font_atlas or ImFontAtlas() if shared_font_atlas == nil then this.IO.Fonts.OwnerContext = this end for i = 0, ImGuiKey.NamedKey_COUNT - 1 do this.KeysOwnerData[i] = ImGuiKeyOwnerData() end this.IO.Ctx = this this.InputTextState.Ctx = this ImVec2_Copy(this.PlatformImeDataPrev.InputPos, ImVec2(-1.0, -1.0)) return this end --- @class ImGuiWindowSettings --- @field ID int # Window ID --- @field Pos ImVec2 # Window position --- @field Size ImVec2 # Window size --- @field Collapsed bool # Whether window is collapsed --- @field IsChild bool # Whether window is a child window --- @field WantApply bool # Set when loaded from .ini data --- @field WantDelete bool # Set to invalidate/delete the settings entry --- @field Name string # Window name local IMGUI_WINDOW_SETTINGS = {} IMGUI_WINDOW_SETTINGS.__index = IMGUI_WINDOW_SETTINGS function IMGUI_WINDOW_SETTINGS:GetName() return self.Name end function ImGuiWindowSettings() return setmetatable({ ID = 0, Pos = ImVec2(0, 0), Size = ImVec2(0, 0), Collapsed = false, IsChild = false, WantApply = false, WantDelete = false, Name = "", ViewportId = 0, ViewportPos = ImVec2(0, 0), DockId = 0, DockOrder = -1, ClassId = 0, LastUsedDate = 0, }, IMGUI_WINDOW_SETTINGS) end --- @class ImGuiMenuColumns --- @field TotalWidth ImU32 --- @field NextTotalWidth ImU32 --- @field Spacing ImU16 --- @field OffsetIcon ImU16 # Always zero for now --- @field OffsetLabel ImU16 # Offsets are locked in Update() --- @field OffsetShortcut ImU16 --- @field OffsetMark ImU16 --- @field Widths ImU16[] # Width of: Icon, Label, Shortcut, Mark (accumulators for current frame) MT.ImGuiMenuColumns = {} MT.ImGuiMenuColumns.__index = MT.ImGuiMenuColumns --- @return ImGuiMenuColumns local function ImGuiMenuColumns() return setmetatable({ TotalWidth = 0, NextTotalWidth = 0, Spacing = 0, OffsetIcon = 0, OffsetLabel = 0, OffsetShortcut = 0, OffsetMark = 0, Widths = {0, 0, 0, 0} }, MT.ImGuiMenuColumns) end --- @class ImGuiWindowTempData --- @field CursorPos ImVec2 --- @field CursorPosPrevLine ImVec2 --- @field CursorStartPos ImVec2 --- @field CursorMaxPos ImVec2 --- @field IdealMaxPos ImVec2 --- @field CurrLineSize ImVec2 --- @field PrevLineSize ImVec2 --- @field CurrLineTextBaseOffset float --- @field PrevLineTextBaseOffset float --- @field IsSameLine bool --- @field IsSetPos bool --- @field Indent ImVec1 --- @field ColumnsOffset ImVec1 --- @field GroupOffset ImVec1 --- @field CursorStartPosLossyness ImVec2 --- @field TextWrapPos float --- @field TextWrapPosStack ImVector --- @field MenuBarAppending bool --- @field MenuBarOffset ImVec2 --- @field MenuColumns ImGuiMenuColumns --- @field TreeDepth int --- @field TreeHasStackDataDepthMask ImU32 --- @field TreeRecordsClippedNodesY2Mask ImU32 --- @field ChildWindows ImVector --- @field LayoutType ImGuiLayoutType --- @return ImGuiWindowTempData --- @nodiscard local function ImGuiWindowTempData() return { DockTabItemStatusFlags = 0, DockTabItemRect = ImRect(), CursorPos = ImVec2(), CursorPosPrevLine = ImVec2(), CursorStartPos = ImVec2(), CursorMaxPos = ImVec2(), IdealMaxPos = ImVec2(), CurrLineSize = ImVec2(), PrevLineSize = ImVec2(), CurrLineTextBaseOffset = 0, PrevLineTextBaseOffset = 0, IsSameLine = false, IsSetPos = false, Indent = ImVec1(), ColumnsOffset = ImVec1(), GroupOffset = ImVec1(), CursorStartPosLossyness = ImVec2(), ItemWidth = 0, ItemWidthDefault = 0, TextWrapPos = 0, ItemWidthStack = ImVector(), TextWrapPosStack = ImVector(), MenuBarAppending = false, -- FIXME: Remove this MenuBarOffset = ImVec2(), MenuColumns = ImGuiMenuColumns(), TreeDepth = 0, TreeHasStackDataDepthMask = nil, TreeRecordsClippedNodesY2Mask = nil, ChildWindows = ImVector(), CurrentTableIdx = -1, -- 0-based index into g.Tables, -1 if none CurrentColumns = nil, -- ImGuiOldColumns (legacy Columns API) StateStorage = nil, LayoutType = nil } end --- @class ImGuiWindow --- @field Ctx ImGuiContext --- @field Name string --- @field ID ImGuiID --- @field Flags ImGuiWindowFlags --- @field FlagsPreviousFrame ImGuiWindowFlags --- @field ChildFlags ImGuiChildFlags --- @field WindowClass ImGuiWindowClass --- @field Viewport ImGuiViewportP --- @field ViewportId ImGuiID --- @field ViewportPos ImVec2 --- @field ViewportAllowPlatformMonitorExtend int --- @field Pos ImVec2 --- @field Size ImVec2 --- @field SizeFull ImVec2 --- @field ContentSize ImVec2 --- @field ContentSizeIdeal ImVec2 --- @field ContentSizeExplicit ImVec2 --- @field Scroll ImVec2 --- @field IsExplicitChild bool --- @field FocusOrder short # 1-based, order within WindowsFocusOrder, altered when windows are focused. Can be -1 if invalid --- @field IDStack ImVector --- @field DC ImGuiWindowTempData --- @field OuterRectClipped ImRect --- @field InnerRect ImRect --- @field InnerClipRect ImRect --- @field WorkRect ImRect --- @field ParentWorkRect ImRect --- @field ClipRect ImRect --- @field ContentRegionRect ImRect --- @field DrawList ImDrawList # Points to DrawListInst --- @field DrawListInst ImDrawList --- @field ParentWindow? ImGuiWindow --- @field RootWindow ImGuiWindow --- @field RootWindowPopupTree ImGuiWindow --- @field RootWindowDockTree ImGuiWindow --- @field StateStorage {[ImGuiID]: bool} --- @field MemoryDrawListIdxCapacity int --- @field MemoryDrawListVtxCapacity int --- @field MemoryCompacted bool MT.ImGuiWindow = {} MT.ImGuiWindow.__index = MT.ImGuiWindow --- @return ImRect --- @nodiscard function MT.ImGuiWindow:Rect() return ImRect(self.Pos.x, self.Pos.y, self.Pos.x + self.Size.x, self.Pos.y + self.Size.y) end --- @return ImRect --- @nodiscard function MT.ImGuiWindow:TitleBarRect() return ImRect(self.Pos, ImVec2(self.Pos.x + self.SizeFull.x, self.Pos.y + self.TitleBarHeight)) end --- @return ImRect --- @nodiscard function MT.ImGuiWindow:MenuBarRect() local y1 = self.Pos.y + self.TitleBarHeight return ImRect(self.Pos.x, y1, self.Pos.x + self.SizeFull.x, y1 + self.MenuBarHeight) end --- @return ImGuiWindow --- @nodiscard function ImGuiWindow(ctx, name) local this = { ID = 0, MoveId = 0, Ctx = ctx, Name = name, Flags = 0, ChildFlags = 0, WindowClass = ImGuiWindowClass(), Pos = ImVec2(), Size = ImVec2(), -- Current size (==SizeFull or collapsed title bar size) SizeFull = ImVec2(), Active = false, WasActive = false, Collapsed = false, SkipItems = false, SkipRefresh = false, Appearing = false, Hidden = false, IsFallbackWindow = false, IsExplicitChild = nil, ResizeBorderHovered = -1, ResizeBorderHeld = -1, BeginCount = 0, BeginCountPreviousFrame = 0, BeginOrderWithinParent = 0, BeginOrderWithinContext = 0, FocusOrder = nil, HiddenFramesCanSkipItems = 0, HiddenFramesCannotSkipItems = 0, HiddenFramesForRenderOnly = 0, DisableInputsFrames = 0, WindowRounding = 0, WindowBorderSize = 1, TitleBarHeight = 0, MenuBarHeight = 0, DecoOuterSizeX1 = 0, DecoOuterSizeY1 = 0, DecoOuterSizeX2 = 0, DecoOuterSizeY2 = 0, DecoInnerSizeX1 = 0, DecoInnerSizeY1 = 0, ContentSize = ImVec2(), ContentSizeIdeal = ImVec2(), ContentSizeExplicit = ImVec2(), AutoFitFramesX = -1, AutoFitFramesY = -1, AutoFitOnlyGrows = false, HasCloseButton = true, BgClickFlags = 0, SetWindowPosAllowFlags = 0, SetWindowSizeAllowFlags = 0, SetWindowCollapsedAllowFlags = 0, SetWindowPosVal = ImVec2(FLT_MAX, FLT_MAX), SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX), SettingsOffset = -1, ScrollbarSizes = ImVec2(), Scroll = ImVec2(), ScrollbarX = false, ScrollbarY = false, ScrollMax = ImVec2(), ScrollTarget = ImVec2(FLT_MAX, FLT_MAX), ScrollTargetCenterRatio = ImVec2(0.5, 0.5), ScrollTargetEdgeSnapDist = ImVec2(), ScrollbarXStabilizeToggledHistory = 0, DrawList = nil, DrawListInst = ImDrawList(ctx.DrawListSharedData), RootWindow = nil, RootWindowPopupTree = nil, RootWindowDockTree = nil, ParentWindow = nil, ParentWindowInBeginStack = nil, IDStack = ImVector(), ViewportAllowPlatformMonitorExtend = -1, Viewport = nil, ViewportId = 0, ViewportPos = ImVec2(FLT_MAX, FLT_MAX), ViewportOwned = nil, DC = ImGuiWindowTempData(), OuterRectClipped = ImRect(), InnerRect = ImRect(), InnerClipRect = ImRect(), WorkRect = ImRect(), ParentWorkRect = ImRect(), ContentRegionRect = ImRect(), ClipRect = ImRect(), LastFrameActive = -1, LastFrameJustFocused = -1, LastTimeActive = -1.0, StateStorage = {}, ColumnsStorage = ImVector(), -- ImVector WriteAccessed = false, FontWindowScale = 1.0, FontWindowScaleParents = 1.0, HitTestHoleSize = ImVec2(), NavLastChildNavWindow = nil, NavLastIds = {[0] = 0, [1] = 0}, -- FIXME: 1-based instead NavRectRel = {[0] = ImRect(), [1] = ImRect()}, NavPreferredScoringPosRel = {[0] = ImVec2(), [1] = ImVec2()}, NavRootFocusScopeId = 0 } this.DrawList = this.DrawListInst this.DrawList._OwnerName = name setmetatable(this, MT.ImGuiWindow) this.ID = ImHashStr(name) this.IDStack:push_back(this.ID) this.MoveId = this:GetID("#MOVE") this.TabId = this:GetID("#TAB") -- Docking this.ChildId = this.ChildId or 0 this.SetWindowDockAllowFlags = 0 this.ParentWindowForFocusRoute = nil this.DockIsActive = false this.DockNodeIsVisible = false this.DockTabIsVisible = false this.DockTabWantClose = false this.DockOrder = -1 this.DockStyle = { Colors = {} } for i = 0, 8 do this.DockStyle.Colors[i] = 0 end this.DockNode = nil this.DockNodeAsHost = nil this.DockId = 0 return this end --- @class ImDrawDataBuilder --- @field Layers [ImVector?, ImVector?] --- @field LayerData1 ImVector --- @return ImDrawDataBuilder --- @nodiscard local function ImDrawDataBuilder() return { Layers = {nil, nil}, LayerData1 = ImVector() } end --- @class ImGuiViewportP : ImGuiViewport --- @field Window? ImGuiWindow --- @field Idx int # Initial value = -1, then becomes 1-based index --- @field LastFrameActive int --- @field LastFocusedStampCount int --- @field LastNameHash ImGuiID --- @field LastPos ImVec2 --- @field LastSize ImVec2 --- @field Alpha float --- @field LastAlpha float --- @field LastFocusedHadNavWindow bool --- @field PlatformMonitor short --- @field BgFgDrawListsLastTimeActive [int, int] # 1-based --- @field BgFgDrawLists [ImDrawList, ImDrawList] # 1-based --- @field DrawDataP ImDrawData --- @field DrawDataBuilder ImDrawDataBuilder --- @field LastPlatformPos ImVec2 --- @field LastPlatformSize ImVec2 --- @field LastRendererSize ImVec2 --- @field WorkInsetMin ImVec2 --- @field WorkInsetMax ImVec2 --- @field BuildWorkInsetMin ImVec2 --- @field BuildWorkInsetMax ImVec2 local IMGUI_VIEWPORT_P = {} IMGUI_VIEWPORT_P.__index = IMGUI_VIEWPORT_P setmetatable(IMGUI_VIEWPORT_P, {__index = MT.ImGuiViewport}) function IMGUI_VIEWPORT_P:ClearRequestFlags() self.PlatformRequestClose = false self.PlatformRequestMove = false self.PlatformRequestResize = false end function IMGUI_VIEWPORT_P:CalcWorkRectPos(inset_min) return ImVec2(self.Pos.x + inset_min.x, self.Pos.y + inset_min.y) end function IMGUI_VIEWPORT_P:CalcWorkRectSize(inset_min, inset_max) return ImVec2(ImMax(0.0, self.Size.x - inset_min.x - inset_max.x), ImMax(0.0, self.Size.y - inset_min.y - inset_max.y)) end function IMGUI_VIEWPORT_P:UpdateWorkRect() self.WorkPos = self:CalcWorkRectPos(self.WorkInsetMin) self.WorkSize = self:CalcWorkRectSize(self.WorkInsetMin, self.WorkInsetMax) end --- @nodiscard function IMGUI_VIEWPORT_P:GetMainRect() return ImRect(self.Pos.x, self.Pos.y, self.Pos.x + self.Size.x, self.Pos.y + self.Size.y) end --- @nodiscard function IMGUI_VIEWPORT_P:GetWorkRect() return ImRect(self.WorkPos.x, self.WorkPos.y, self.WorkPos.x + self.WorkSize.x, self.WorkPos.y + self.WorkSize.y) end --- @nodiscard function IMGUI_VIEWPORT_P:GetBuildWorkRect() local pos = self:CalcWorkRectPos(self.BuildWorkInsetMin) local size = self:CalcWorkRectSize(self.BuildWorkInsetMin, self.BuildWorkInsetMax) return ImRect(pos.x, pos.y, pos.x + size.x, pos.y + size.y) end --- @return ImGuiViewportP --- @nodiscard function ImGuiViewportP() local this = setmetatable(ImGuiViewport(), IMGUI_VIEWPORT_P) --- @cast this ImGuiViewportP this.Window = nil this.Idx = -1 this.LastFrameActive = -1 this.LastFocusedStampCount = -1 this.LastNameHash = 0 this.LastPos = ImVec2() -- ImGuiViewport() { memset(this, 0, sizeof(*this)); } this.LastSize = ImVec2() this.Alpha = 1.0 this.LastAlpha = 1.0 this.LastFocusedHadNavWindow = false this.PlatformMonitor = -1 this.BgFgDrawListsLastTimeActive = {-1, -1} this.BgFgDrawLists = {nil, nil} this.DrawDataP = ImDrawData() this.DrawDataBuilder = ImDrawDataBuilder() this.LastPlatformPos = ImVec2(FLT_MAX, FLT_MAX) this.LastPlatformSize = ImVec2(FLT_MAX, FLT_MAX) this.LastRendererSize = ImVec2(FLT_MAX, FLT_MAX) this.WorkInsetMin = ImVec2(0, 0) this.WorkInsetMax = ImVec2(0, 0) this.BuildWorkInsetMin = ImVec2(0, 0) this.BuildWorkInsetMax = ImVec2(0, 0) return this end --- @class ImFontLoader --- @field Name string --- @field LoaderInit? fun(atlas: ImFontAtlas): bool --- @field LoaderShutdown? fun(atlas: ImFontAtlas) --- @field FontSrcInit? fun(atlas: ImFontAtlas, src: ImFontConfig): bool --- @field FontSrcDestroy? fun(atlas: ImFontAtlas, src: ImFontConfig) --- @field FontSrcContainsGlyph? fun(atlas: ImFontAtlas, src: ImFontConfig, codepoint: ImWchar): bool --- @field FontBakedInit? fun(atlas: ImFontAtlas, src: ImFontConfig, baked: ImFontBaked, loader_data_for_baked_src?: any): bool --- @field FontBakedDestroy? fun(atlas: ImFontAtlas, src: ImFontConfig, baked: ImFontBaked, loader_data_for_baked_src?: any) --- @field FontBakedLoadGlyph fun(atlas: ImFontAtlas, src: ImFontConfig, baked: ImFontBaked, loader_data_for_baked_src?: any, codepoint: ImWchar, out_glyph?: ImFontGlyph, advance_x?: float): bool, float? --- @field FontBakedSrcLoaderDataSize unsigned_int MT.ImFontLoader = {} MT.ImFontLoader.__index = MT.ImFontLoader --- @return ImFontLoader --- @nodiscard function ImFontLoader() --- @type ImFontLoader local this = setmetatable({}, MT.ImFontLoader) this.Name = nil this.LoaderInit = nil this.LoaderShutdown = nil this.FontSrcInit = nil this.FontSrcDestroy = nil this.FontSrcContainsGlyph = nil this.FontBakedInit = nil this.FontBakedDestroy = nil this.FontBakedLoadGlyph = nil this.FontBakedSrcLoaderDataSize = 0 return this end --- @class ImFontAtlasRectEntry --- @field TargetIndex int # 0-based! When IsUsed = true, TargetIndex = this rect's index in Rects; IsUsed = false, TargetIndex = the next unused RectsIndex entry's index --- @field Generation unsigned_int # How many times this entry is reused --- @field IsUsed bool --- @return ImFontAtlasRectEntry --- @nodiscard function ImFontAtlasRectEntry() return { TargetIndex = 0, Generation = 0, IsUsed = false } end local ImFontAtlasRectId_IndexMask_ = 0x0007FFFF local ImFontAtlasRectId_GenerationMask_ = 0x3FF00000 local ImFontAtlasRectId_GenerationShift_ = 20 --- @param id ImFontAtlasRectId # Expects 0-based! --- @return int # 0-based! function ImFontAtlasRectId_GetIndex(id) return bitAnd(id, ImFontAtlasRectId_IndexMask_) end --- @param id ImFontAtlasRectId # Expects 0-based! --- @return unsigned_int function ImFontAtlasRectId_GetGeneration(id) return bitRShift(bitAnd(id, ImFontAtlasRectId_GenerationMask_), ImFontAtlasRectId_GenerationShift_) end --- @param index_idx int # Expects 0-based! --- @param gen_idx int --- @return ImFontAtlasRectId # 0-based! function ImFontAtlasRectId_Make(index_idx, gen_idx) IM_ASSERT(index_idx >= 0 and index_idx <= ImFontAtlasRectId_IndexMask_ and gen_idx <= bitRShift(ImFontAtlasRectId_GenerationMask_, ImFontAtlasRectId_GenerationShift_)) return bitOr(index_idx, bitLShift(gen_idx, ImFontAtlasRectId_GenerationShift_)) end --- @class ImFontAtlasPostProcessData --- @field FontAtlas ImFontAtlas --- @field Font ImFont --- @field FontSrc ImFontConfig --- @field FontBaked ImFontBaked --- @field Glyph ImFontGlyph --- @field Pixels unsigned_char[] --- @field _PixelsBase int # LUA: in cpp code the `Pixels` is a pointer. we can do this to avoid creating another custom structure to mimic it --- @field Format ImTextureFormat --- @field Pitch int --- @field Width int --- @field Height int --- @param atlas ImFontAtlas --- @param font ImFont --- @param font_src ImFontConfig --- @param font_baked ImFontBaked --- @param glyph ImFontGlyph --- @param pixels unsigned_char[] --- @param pixels_base int --- @param format ImTextureFormat --- @param pitch int --- @param width int --- @param height int --- @return ImFontAtlasPostProcessData --- @nodiscard function ImFontAtlasPostProcessData(atlas, font, font_src, font_baked, glyph, pixels, pixels_base, format, pitch, width, height) return { FontAtlas = atlas, Font = font, FontSrc = font_src, FontBaked = font_baked, Glyph = glyph, Pixels = pixels, _PixelsBase = pixels_base, Format = format, Pitch = pitch, Width = width, Height = height, } end --- @enum ImGuiInputSource ImGuiInputSource = { None = 0, Mouse = 1, Keyboard = 2, Gamepad = 3, COUNT = 4 } --- @class ImGuiInputEventMousePos --- @field PosX float --- @field PosY float --- @field MouseSource ImGuiMouseSource --- @return ImGuiInputEventMousePos --- @nodiscard function ImGuiInputEventMousePos() return { PosX = 0, PosY = 0, MouseSource = ImGuiMouseSource.Mouse } end --- @class ImGuiInputEventMouseButton --- @field Button int --- @field Down bool --- @field MouseSource ImGuiMouseSource --- @return ImGuiInputEventMouseButton --- @nodiscard function ImGuiInputEventMouseButton() return { Button = 0, Down = false, MouseSource = ImGuiMouseSource.Mouse } end --- @class ImGuiInputEventMouseWheel --- @field WheelX float --- @field WheelY float --- @field MouseSource ImGuiMouseSource --- @return ImGuiInputEventMouseWheel --- @nodiscard function ImGuiInputEventMouseWheel() return { WheelX = 0, WheelY = 0, MouseSource = ImGuiMouseSource.Mouse } end --- @class ImGuiInputEventKey --- @field Key ImGuiKey --- @field Down bool --- @field AnalogValue float --- @return ImGuiInputEventKey --- @nodiscard function ImGuiInputEventKey() return { Key = 0, Down = false, AnalogValue = 0 } end --- @class ImGuiInputEventText --- @field Char unsigned_int --- @return ImGuiInputEventText --- @nodiscard function ImGuiInputEventText() return { Char = nil } end --- @class ImGuiInputEventAppFocused --- @field Focused bool --- @return ImGuiInputEventAppFocused --- @nodiscard function ImGuiInputEventAppFocused() return { Focused = nil } end --- @class ImGuiInputEventMouseViewport --- @field HoveredViewportID ImGuiID --- @return ImGuiInputEventMouseViewport --- @nodiscard function ImGuiInputEventMouseViewport() return { HoveredViewportID = 0 } end --- @class ImGuiInputEvent --- @return ImGuiInputEvent --- @nodiscard function ImGuiInputEvent() return { Type = 0, Source = 0, EventId = 0, -- union MousePos = nil, -- if Type == ImGuiInputEventType.MousePos MouseWheel = nil, -- if Type == ImGuiInputEventType.MouseWheel MouseButton = nil, -- if Type == ImGuiInputEventType.MouseButton MouseViewport = nil, -- if Type == ImGuiInputEventType.MouseViewport Key = nil, -- if Type == ImGuiInputEventType.Key Text = nil, -- if Type == ImGuiInputEventType.Text AppFocused = nil, -- if Type == ImGuiInputEventType.Focus } end ImGuiKey_Keyboard_BEGIN = ImGuiKey.NamedKey_BEGIN ImGuiKey_Keyboard_END = ImGuiKey.GamepadStart ImGuiKey_Gamepad_BEGIN = ImGuiKey.GamepadStart ImGuiKey_Gamepad_END = ImGuiKey.GamepadRStickDown + 1 ImGuiKey_Mouse_BEGIN = ImGuiKey.MouseLeft ImGuiKey_Mouse_END = ImGuiKey.MouseWheelY + 1 ImGuiKey_Aliases_BEGIN = ImGuiKey_Mouse_BEGIN ImGuiKey_Aliases_END = ImGuiKey_Mouse_END ImGuiKey.NavKeyboardTweakSlow = ImGuiMod_Ctrl ImGuiKey.NavKeyboardTweakFast = ImGuiMod_Shift ImGuiKey.NavGamepadTweakSlow = ImGuiKey.GamepadL1 ImGuiKey.NavGamepadTweakFast = ImGuiKey.GamepadR1 ImGuiKey.NavGamepadMenu = ImGuiKey.GamepadFaceLeft ImGuiKey.NavGamepadContextMenu = ImGuiKey.GamepadFaceUp --- @enum ImGuiInputEventType ImGuiInputEventType = { None = 0, MousePos = 1, MouseWheel = 2, MouseButton = 3, MouseViewport = 4, Key = 5, Text = 6, Focus = 7, COUNT = 8 } ImGuiInputFlags.RepeatRateDefault = bitLShift(1, 1) ImGuiInputFlags.RepeatRateNavMove = bitLShift(1, 2) ImGuiInputFlags.RepeatRateNavTweak = bitLShift(1, 3) ImGuiInputFlags.RepeatUntilRelease = bitLShift(1, 4) ImGuiInputFlags.RepeatUntilKeyModsChange = bitLShift(1, 5) ImGuiInputFlags.RepeatUntilKeyModsChangeFromNone = bitLShift(1, 6) ImGuiInputFlags.RepeatUntilOtherKeyPress = bitLShift(1, 7) ImGuiInputFlags.LockThisFrame = bitLShift(1, 20) ImGuiInputFlags.LockUntilRelease = bitLShift(1, 21) ImGuiInputFlags.CondHovered = bitLShift(1, 22) ImGuiInputFlags.CondActive = bitLShift(1, 23) ImGuiInputFlags.CondDefault_ = bitOr(ImGuiInputFlags.CondHovered, ImGuiInputFlags.CondActive) ImGuiInputFlags.RepeatRateMask_ = bitOr(ImGuiInputFlags.RepeatRateDefault, ImGuiInputFlags.RepeatRateNavMove, ImGuiInputFlags.RepeatRateNavTweak) ImGuiInputFlags.RepeatUntilMask_ = bitOr(ImGuiInputFlags.RepeatUntilRelease, ImGuiInputFlags.RepeatUntilKeyModsChange, ImGuiInputFlags.RepeatUntilKeyModsChangeFromNone, ImGuiInputFlags.RepeatUntilOtherKeyPress) ImGuiInputFlags.RepeatMask_ = bitOr(ImGuiInputFlags.Repeat, ImGuiInputFlags.RepeatRateMask_, ImGuiInputFlags.RepeatUntilMask_) ImGuiInputFlags.CondMask_ = bitOr(ImGuiInputFlags.CondHovered, ImGuiInputFlags.CondActive) ImGuiInputFlags.RouteTypeMask_ = bitOr(ImGuiInputFlags.RouteActive, ImGuiInputFlags.RouteFocused, ImGuiInputFlags.RouteGlobal, ImGuiInputFlags.RouteAlways) ImGuiInputFlags.RouteOptionsMask_ = bitOr(ImGuiInputFlags.RouteOverFocused, ImGuiInputFlags.RouteOverActive, ImGuiInputFlags.RouteUnlessBgFocused, ImGuiInputFlags.RouteFromRootWindow) ImGuiInputFlags.SupportedByIsKeyPressed = ImGuiInputFlags.RepeatMask_ ImGuiInputFlags.SupportedByIsMouseClicked = ImGuiInputFlags.Repeat ImGuiInputFlags.SupportedByShortcut = bitOr(ImGuiInputFlags.RepeatMask_, ImGuiInputFlags.RouteTypeMask_, ImGuiInputFlags.RouteOptionsMask_) ImGuiInputFlags.SupportedBySetNextItemShortcut = bitOr(ImGuiInputFlags.RepeatMask_, ImGuiInputFlags.RouteTypeMask_, ImGuiInputFlags.RouteOptionsMask_, ImGuiInputFlags.Tooltip) ImGuiInputFlags.SupportedBySetKeyOwner = bitOr(ImGuiInputFlags.LockThisFrame, ImGuiInputFlags.LockUntilRelease) ImGuiInputFlags.SupportedBySetItemKeyOwner = bitOr(ImGuiInputFlags.SupportedBySetKeyOwner, ImGuiInputFlags.CondMask_) --- @enum ImGuiAxis # can be used to index ImVec2 ImGuiAxis = { None = 0, X = 1, Y = 2 } --- @enum ImGuiPlotType ImGuiPlotType = { Lines = 0, Histogram = 1 } --- @enum ImGuiActivateFlags ImGuiActivateFlags = { None = 0, PreferInput = bitLShift(1, 0), PreferTweak = bitLShift(1, 1), TryToPreserveState = bitLShift(1, 2), FromTabbing = bitLShift(1, 3), FromShortcut = bitLShift(1, 4), FromFocusApi = bitLShift(1, 5) } --- @enum ImGuiScrollFlags ImGuiScrollFlags = { None = 0, KeepVisibleEdgeX = bitLShift(1, 0), KeepVisibleEdgeY = bitLShift(1, 1), KeepVisibleCenterX = bitLShift(1, 2), KeepVisibleCenterY = bitLShift(1, 3), AlwaysCenterX = bitLShift(1, 4), AlwaysCenterY = bitLShift(1, 5), NoScrollParent = bitLShift(1, 6), } ImGuiScrollFlags.MaskX_ = bitOr(ImGuiScrollFlags.KeepVisibleEdgeX, ImGuiScrollFlags.KeepVisibleCenterX, ImGuiScrollFlags.AlwaysCenterX) ImGuiScrollFlags.MaskY_ = bitOr(ImGuiScrollFlags.KeepVisibleEdgeY, ImGuiScrollFlags.KeepVisibleCenterY, ImGuiScrollFlags.AlwaysCenterY) --- @class ImGuiGroupData --- @field WindowID ImGuiID --- @field BackupCursorPos ImVec2 --- @field BackupCursorMaxPos ImVec2 --- @field BackupCursorPosPrevLine ImVec2 --- @field BackupIndent ImVec1 --- @field BackupGroupOffset ImVec1 --- @field BackupCurrLineSize ImVec2 --- @field BackupCurrLineTextBaseOffset float --- @field BackupActiveIdIsAlive ImGuiID --- @field BackupAnyIdHasBeenEditedThisFrame bool --- @field BackupDeactivatedIdIsAlive bool --- @field BackupHoveredIdIsAlive bool --- @field BackupIsSameLine bool --- @field EmitItem bool --- @return ImGuiGroupData --- @nodiscard function ImGuiGroupData() return { WindowID = nil, BackupCursorPos = ImVec2(), BackupCursorMaxPos = ImVec2(), BackupCursorPosPrevLine = ImVec2(), BackupIndent = ImVec1(), BackupGroupOffset = ImVec1(), BackupCurrLineSize = ImVec2(), BackupCurrLineTextBaseOffset = nil, BackupActiveIdIsAlive = nil, BackupAnyIdHasBeenEditedThisFrame = nil, BackupDeactivatedIdIsAlive = nil, BackupHoveredIdIsAlive = nil, BackupIsSameLine = nil, EmitItem = nil } end --- @enum ImGuiTooltipFlags ImGuiTooltipFlags = { None = 0, OverridePrevious = bitLShift(1, 1) } --- @enum ImGuiPopupPositionPolicy ImGuiPopupPositionPolicy = { Default = 0, ComboBox = 1, Tooltip = 2 } --- @class ImGuiPopupData --- @field PopupId ImGuiID --- @field Window ImGuiWindow --- @field RestoreNavWindow ImGuiWindow --- @field ParentNavLayer int --- @field OpenFrameCount int --- @field OpenParentId ImGuiID --- @field OpenPopupPos ImVec2 --- @field OpenMousePos ImVec2 --- @return ImGuiPopupData --- @nodiscard function ImGuiPopupData() return { PopupId = 0, Window = nil, RestoreNavWindow = nil, ParentNavLayer = -1, OpenFrameCount = -1, OpenParentId = 0, OpenPopupPos = ImVec2(), OpenMousePos = ImVec2() } end --- @enum ImGuiWindowRefreshFlags ImGuiWindowRefreshFlags = { None = 0, TryToAvoidRefresh = bitLShift(1, 0), RefreshOnHover = bitLShift(1, 1), RefreshOnFocus = bitLShift(1, 2) } --- @enum ImGuiNavRenderCursorFlags ImGuiNavRenderCursorFlags = { None = 0, Compact = bitLShift(1, 1), -- Compact highlight, no padding/distance from focused item AlwaysDraw = bitLShift(1, 2), -- Draw rectangular highlight if (g.NavId == id) even when g.NavCursorVisible == false, aka even when using the mouse } --- @enum ImGuiDebugLogFlags ImGuiDebugLogFlags = { -- Event types None = 0, EventError = bitLShift(1, 0), -- Error submitted by IM_ASSERT_USER_ERROR() EventActiveId = bitLShift(1, 1), EventFocus = bitLShift(1, 2), EventPopup = bitLShift(1, 3), EventNav = bitLShift(1, 4), EventClipper = bitLShift(1, 5), EventSelection = bitLShift(1, 6), EventIO = bitLShift(1, 7), EventFont = bitLShift(1, 8), EventInputRouting = bitLShift(1, 9), EventDocking = bitLShift(1, 10), EventViewport = bitLShift(1, 11), EventTable = bitLShift(1, 12), OutputToTTY = bitLShift(1, 20), OutputToDebugger = bitLShift(1, 21), OutputToTestEngine = bitLShift(1, 22), } ImGuiDebugLogFlags.EventMask_ = bitOr( ImGuiDebugLogFlags.EventError, ImGuiDebugLogFlags.EventActiveId, ImGuiDebugLogFlags.EventFocus, ImGuiDebugLogFlags.EventPopup, ImGuiDebugLogFlags.EventNav, ImGuiDebugLogFlags.EventClipper, ImGuiDebugLogFlags.EventSelection, ImGuiDebugLogFlags.EventTable, ImGuiDebugLogFlags.EventIO, ImGuiDebugLogFlags.EventFont, ImGuiDebugLogFlags.EventInputRouting, ImGuiDebugLogFlags.EventDocking, ImGuiDebugLogFlags.EventViewport ) --- @enum ImGuiLocKey ImGuiLocKey = { VersionStr = 1, TableSizeOne = 2, TableSizeAllFit = 3, TableSizeAllDefault = 4, TableReset = 5, TableResetOrder = 6, TableResetVisibility = 7, WindowingMainMenuBar = 8, WindowingPopup = 9, WindowingUntitled = 10, OpenLink_s = 11, CopyLink = 12, DockingHideTabBar = 13, DockingHoldShiftToDock = 14, DockingDragToUndockOrMoveNode = 15, COUNT = 15 } --- @class ImGuiLocEntry --- @field Key ImGuiLocKey --- @field Text string --- @param key ImGuiLocKey --- @return string function ImGui.LocalizeGetMsg(key) local g = GImGui local msg = g.LocalizationTable[key] if msg then return msg else return "*Missing Text*" end end --- @param id ImGuiID function ImGui.TempInputIsActive(id) local g = GImGui return (g.TempInputId == id and g.ActiveId == id) or (g.InputTextDeactivatedState.ID == id) end --- @param id ImGuiID --- @return ImGuiInputTextState? function ImGui.GetInputTextState(id) local g = GImGui if id ~= 0 and g.InputTextState.ID == id then return g.InputTextState end return nil end -- Storage for PushFocusScope(), g.FocusScopeStack[], g.NavFocusRoute[] --- @class ImGuiFocusScopeData --- @field ID ImGuiID --- @field WindowID ImGuiID --- @return ImGuiFocusScopeData --- @nodiscard function ImGuiFocusScopeData() return { ID = nil, WindowID = nil } end return true -- [Roblox] ModuleScripts must return exactly one value