parent
c5b181e08c
commit
9e962f0fde
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -0,0 +1,171 @@ |
||||
-- This file is part of mimgui project |
||||
-- Licensed under the MIT License |
||||
-- Copyright (c) 2018, FYP <https://github.com/THE-FYP> |
||||
|
||||
local imgui = require 'mimgui.imgui' |
||||
local lib = imgui.lib |
||||
local ffi = require 'ffi' |
||||
|
||||
ffi.cdef [[ |
||||
typedef struct IDirect3DDevice9 *LPDIRECT3DDEVICE9, *PDIRECT3DDEVICE9; |
||||
typedef struct IDirect3DVertexBuffer9 *LPDIRECT3DVERTEXBUFFER9, *PDIRECT3DVERTEXBUFFER9; |
||||
typedef struct IDirect3DIndexBuffer9 *LPDIRECT3DINDEXBUFFER9, *PDIRECT3DINDEXBUFFER9; |
||||
typedef struct IDirect3DTexture9 *LPDIRECT3DTEXTURE9, *PDIRECT3DTEXTURE9; |
||||
typedef const char *LPCTSTR; |
||||
typedef const void *LPCVOID; |
||||
typedef unsigned int UINT; |
||||
typedef void *HWND; |
||||
typedef signed __int64 INT64, *PINT64; |
||||
typedef unsigned int UINT_PTR, *PUINT_PTR; |
||||
typedef long LONG_PTR, *PLONG_PTR; |
||||
typedef UINT_PTR WPARAM; |
||||
typedef LONG_PTR LPARAM; |
||||
typedef LONG_PTR LRESULT; |
||||
typedef struct ImGui_ImplDX9_Context |
||||
{ |
||||
LPDIRECT3DDEVICE9 pd3dDevice; |
||||
LPDIRECT3DVERTEXBUFFER9 pVB; |
||||
LPDIRECT3DINDEXBUFFER9 pIB; |
||||
LPDIRECT3DTEXTURE9 FontTexture; |
||||
int VertexBufferSize; |
||||
int IndexBufferSize; |
||||
} ImGui_ImplDX9_Context; |
||||
|
||||
bool ImGui_ImplWin32_Init(HWND hwnd, INT64* ticksPerSecond, INT64* time); |
||||
void ImGui_ImplWin32_NewFrame(HWND hwnd, INT64 ticksPerSecond, INT64* time); |
||||
LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); |
||||
|
||||
ImGui_ImplDX9_Context* ImGui_ImplDX9_Init(LPDIRECT3DDEVICE9 device); |
||||
void ImGui_ImplDX9_Shutdown(ImGui_ImplDX9_Context* context); |
||||
void ImGui_ImplDX9_NewFrame(ImGui_ImplDX9_Context* context); |
||||
void ImGui_ImplDX9_RenderDrawData(ImGui_ImplDX9_Context* context, ImDrawData* draw_data); |
||||
void ImGui_ImplDX9_InvalidateDeviceObjects(ImGui_ImplDX9_Context* context); |
||||
|
||||
bool ImGui_ImplDX9_CreateFontsTexture(ImGui_ImplDX9_Context* context); // replaces ImGui_ImplDX9_CreateDeviceObjects since they are the same |
||||
void ImGui_ImplDX9_InvalidateFontsTexture(ImGui_ImplDX9_Context* context); |
||||
|
||||
LPDIRECT3DTEXTURE9 ImGui_ImplDX9_CreateTextureFromFile(LPDIRECT3DDEVICE9 device, LPCTSTR path); |
||||
LPDIRECT3DTEXTURE9 ImGui_ImplDX9_CreateTextureFromFileInMemory(LPDIRECT3DDEVICE9 device, LPCVOID src, UINT size); |
||||
void ImGui_ImplDX9_ReleaseTexture(LPDIRECT3DTEXTURE9 tex); |
||||
|
||||
int __stdcall MultiByteToWideChar(UINT CodePage, unsigned long dwFlags, const char* lpMultiByteStr, int cbMultiByte, wchar_t* lpWideCharStr, int cchWideChar); |
||||
]] |
||||
|
||||
local ImplDX9 = {} |
||||
function ImplDX9.new(device, hwnd) |
||||
-- ImGui_ImplDX9_Context* ImGui_ImplDX9_Init(LPDIRECT3DDEVICE9 device); |
||||
local obj = {} |
||||
local d3dcontext = lib.ImGui_ImplDX9_Init(device) |
||||
if d3dcontext == nil then |
||||
return nil |
||||
end |
||||
local context = imgui.CreateContext() |
||||
obj.ticksPerSecond = ffi.new('INT64[1]', 0) |
||||
obj.time = ffi.new('INT64[1]', 0) |
||||
imgui.SetCurrentContext(context) |
||||
local imio = imgui.GetIO() |
||||
imio.BackendRendererName = 'imgui_impl_dx9_lua' |
||||
imio.BackendFlags = bit.bor(imio.BackendFlags, lib.ImGuiBackendFlags_RendererHasVtxOffset) -- We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. |
||||
-- bool ImGui_ImplWin32_Init(HWND hwnd, INT64* ticksPerSecond, INT64* time); |
||||
if not lib.ImGui_ImplWin32_Init(hwnd, obj.ticksPerSecond, obj.time) then |
||||
-- void ImGui_ImplDX9_Shutdown(ImGui_ImplDX9_Context* context); |
||||
lib.ImGui_ImplDX9_Shutdown(d3dcontext) |
||||
imgui.DestroyContext(context) |
||||
return nil |
||||
end |
||||
obj.context = context |
||||
obj.d3dcontext = d3dcontext |
||||
obj.d3ddevice = device |
||||
obj.hwnd = hwnd |
||||
-- set finalizer |
||||
ffi.gc(d3dcontext, function(cd) |
||||
imgui.SetCurrentContext(context) |
||||
-- void ImGui_ImplDX9_Shutdown(ImGui_ImplDX9_Context* context); |
||||
lib.ImGui_ImplDX9_Shutdown(cd) |
||||
imgui.DestroyContext(context) |
||||
end) |
||||
return setmetatable(obj, {__index = ImplDX9}) |
||||
end |
||||
|
||||
function ImplDX9:SwitchContext() |
||||
imgui.SetCurrentContext(self.context) |
||||
end |
||||
|
||||
function ImplDX9:NewFrame() |
||||
self:SwitchContext() |
||||
-- void ImGui_ImplDX9_NewFrame(ImGui_ImplDX9_Context* context); |
||||
lib.ImGui_ImplDX9_NewFrame(self.d3dcontext) |
||||
-- void ImGui_ImplWin32_NewFrame(HWND hwnd, INT64 ticksPerSecond, INT64* time); |
||||
lib.ImGui_ImplWin32_NewFrame(self.hwnd, self.ticksPerSecond[0], self.time) |
||||
imgui.NewFrame() |
||||
end |
||||
|
||||
function ImplDX9:EndFrame() |
||||
self:SwitchContext() |
||||
imgui.Render() |
||||
-- void ImGui_ImplDX9_RenderDrawData(ImGui_ImplDX9_Context* context, ImDrawData* draw_data); |
||||
lib.ImGui_ImplDX9_RenderDrawData(self.d3dcontext, imgui.GetDrawData()) |
||||
end |
||||
|
||||
function ImplDX9:WindowMessage(msg, wparam, lparam) |
||||
self:SwitchContext() |
||||
if msg == 0x0102 then -- WM_CHAR |
||||
if wparam < 256 then |
||||
local char = ffi.new('char[1]', wparam) |
||||
local wchar = ffi.new('wchar_t[1]', 0) |
||||
if ffi.C.MultiByteToWideChar(0, 0, char, 1, wchar, 1) > 0 then |
||||
wparam = wchar[0] |
||||
end |
||||
end |
||||
end |
||||
-- LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); |
||||
return lib.ImGui_ImplWin32_WndProcHandler(self.hwnd, msg, wparam, lparam) |
||||
end |
||||
|
||||
function ImplDX9:InvalidateDeviceObjects() |
||||
self:SwitchContext() |
||||
-- void ImGui_ImplDX9_InvalidateDeviceObjects(ImGui_ImplDX9_Context* context); |
||||
lib.ImGui_ImplDX9_InvalidateDeviceObjects(self.d3dcontext) |
||||
end |
||||
|
||||
function ImplDX9:CreateTextureFromFile(path) |
||||
-- LPDIRECT3DTEXTURE9 ImGui_ImplDX9_CreateTextureFromFile(LPDIRECT3DDEVICE9 device, LPCTSTR path); |
||||
local tex = lib.ImGui_ImplDX9_CreateTextureFromFile(self.d3ddevice, path) |
||||
if tex == nil then |
||||
return nil |
||||
end |
||||
-- void ImGui_ImplDX9_ReleaseTexture(LPDIRECT3DTEXTURE9 tex); |
||||
return ffi.gc(tex, lib.ImGui_ImplDX9_ReleaseTexture) |
||||
end |
||||
|
||||
function ImplDX9:CreateTextureFromFileInMemory(src, size) |
||||
-- LPDIRECT3DTEXTURE9 ImGui_ImplDX9_CreateTextureFromFileInMemory(LPDIRECT3DDEVICE9 device, LPCVOID src, UINT size); |
||||
if type(src) == 'number' then |
||||
src = ffi.cast('LPCVOID', src) |
||||
end |
||||
local tex = lib.ImGui_ImplDX9_CreateTextureFromFileInMemory(self.d3ddevice, src, size) |
||||
if tex == nil then |
||||
return nil |
||||
end |
||||
-- void ImGui_ImplDX9_ReleaseTexture(LPDIRECT3DTEXTURE9 tex); |
||||
return ffi.gc(tex, lib.ImGui_ImplDX9_ReleaseTexture) |
||||
end |
||||
|
||||
function ImplDX9:ReleaseTexture(tex) |
||||
ffi.gc(tex, nil) |
||||
lib.ImGui_ImplDX9_ReleaseTexture(tex) |
||||
end |
||||
|
||||
function ImplDX9:CreateFontsTexture() |
||||
self:SwitchContext() |
||||
-- bool ImGui_ImplDX9_CreateFontsTexture(ImGui_ImplDX9_Context* context); |
||||
return lib.ImGui_ImplDX9_CreateFontsTexture(self.d3dcontext) |
||||
end |
||||
|
||||
function ImplDX9:InvalidateFontsTexture() |
||||
self:SwitchContext() |
||||
-- void ImGui_ImplDX9_InvalidateFontsTexture(ImGui_ImplDX9_Context* context); |
||||
lib.ImGui_ImplDX9_InvalidateFontsTexture(self.d3dcontext) |
||||
end |
||||
|
||||
return ImplDX9 |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,368 @@ |
||||
-- This file is part of mimgui project |
||||
-- Licensed under the MIT License |
||||
-- Copyright (c) 2018, FYP <https://github.com/THE-FYP> |
||||
|
||||
assert(getMoonloaderVersion() >= 025) |
||||
|
||||
local imgui = require 'mimgui.imgui' |
||||
local DX9 = require 'mimgui.dx9' |
||||
local ffi = require 'ffi' |
||||
local winmsg = require 'windows.message' |
||||
local memory = require 'memory' |
||||
local mimgui = {} |
||||
|
||||
local renderer = nil |
||||
local subscriptionsInitialize = {} |
||||
local subscriptionsNewFrame = {} |
||||
local eventsRegistered = false |
||||
local active = false |
||||
local cursorActive = false |
||||
local playerLocked = false |
||||
local iniFilePath = nil |
||||
local defaultGlyphRanges = nil |
||||
|
||||
setmetatable(mimgui, {__index = imgui, __newindex = function(t, k, v) |
||||
if imgui[k] then |
||||
print('[mimgui] Warning! Overwriting existing key "'..k..'"!') |
||||
end |
||||
rawset(t, k, v) |
||||
end}) |
||||
|
||||
-- background "Shift" triggering fix |
||||
memory.fill(0x00531155, 0x90, 5, true) |
||||
|
||||
local function ShowCursor(show) |
||||
if show then |
||||
showCursor(true) |
||||
elseif cursorActive then |
||||
showCursor(false) |
||||
end |
||||
cursorActive = show |
||||
end |
||||
|
||||
local function LockPlayer(lock) |
||||
if lock then |
||||
lockPlayerControl(true) |
||||
elseif playerLocked then |
||||
lockPlayerControl(false) |
||||
end |
||||
playerLocked = lock |
||||
end |
||||
|
||||
-- MoonLoader v.027 |
||||
if not isCursorActive then |
||||
isCursorActive = function() return cursorActive end |
||||
end |
||||
|
||||
local function InitializeRenderer() |
||||
-- init renderer |
||||
local hwnd = ffi.cast('HWND', readMemory(0x00C8CF88, 4, false)) |
||||
local d3ddevice = ffi.cast('LPDIRECT3DDEVICE9', getD3DDevicePtr()) |
||||
renderer = assert(DX9.new(d3ddevice, hwnd)) |
||||
renderer:SwitchContext() |
||||
|
||||
-- configure imgui |
||||
imgui.GetIO().ImeWindowHandle = nil -- default causes crash. TODO: why? |
||||
imgui.GetIO().LogFilename = nil |
||||
local confdir = getWorkingDirectory() .. [[\config\mimgui\]] |
||||
if not doesDirectoryExist(confdir) then |
||||
createDirectory(confdir) |
||||
end |
||||
iniFilePath = ffi.new('char[260]', confdir .. script.this.filename .. '.ini') |
||||
imgui.GetIO().IniFilename = iniFilePath |
||||
|
||||
-- change font |
||||
local fontFile = getFolderPath(0x14) .. '\\trebucbd.ttf' |
||||
assert(doesFileExist(fontFile), '[mimgui] Font "' .. fontFile .. '" doesn\'t exist!') |
||||
local builder = imgui.ImFontGlyphRangesBuilder() |
||||
builder:AddRanges(imgui.GetIO().Fonts:GetGlyphRangesCyrillic()) |
||||
builder:AddText([[‚„…†‡€‰‹‘’“”•–—™›№]]) |
||||
defaultGlyphRanges = imgui.ImVector_ImWchar() |
||||
builder:BuildRanges(defaultGlyphRanges) |
||||
imgui.GetIO().Fonts:AddFontFromFileTTF(fontFile, 14, nil, defaultGlyphRanges[0].Data) |
||||
|
||||
-- invoke initializers |
||||
for _, cb in ipairs(subscriptionsInitialize) do |
||||
cb() |
||||
end |
||||
end |
||||
|
||||
local function RegisterEvents() |
||||
addEventHandler('onD3DPresent', function() |
||||
if active then |
||||
if not renderer then |
||||
InitializeRenderer() |
||||
end |
||||
if renderer and not renderer.lost then |
||||
renderer:SwitchContext() |
||||
for _, sub in ipairs(subscriptionsNewFrame) do |
||||
if sub._render and sub._before then |
||||
sub:_before() |
||||
end |
||||
end |
||||
renderer:NewFrame() |
||||
local hideCursor = true |
||||
for _, sub in ipairs(subscriptionsNewFrame) do |
||||
if sub._render then |
||||
sub:_draw() |
||||
hideCursor = hideCursor and sub.HideCursor |
||||
end |
||||
end |
||||
if hideCursor and not isCursorActive() then |
||||
imgui.SetMouseCursor(imgui.lib.ImGuiMouseCursor_None) |
||||
end |
||||
renderer:EndFrame() |
||||
end |
||||
end |
||||
end) |
||||
|
||||
local keyState = {} |
||||
local WM_MOUSEHWHEEL = 0x020E |
||||
local mouseMsgs = { |
||||
[WM_MOUSEHWHEEL]=true, |
||||
[winmsg.WM_LBUTTONDOWN]=true, |
||||
[winmsg.WM_LBUTTONDBLCLK]=true, |
||||
[winmsg.WM_RBUTTONDOWN]=true, |
||||
[winmsg.WM_RBUTTONDBLCLK]=true, |
||||
[winmsg.WM_MBUTTONDOWN]=true, |
||||
[winmsg.WM_MBUTTONDBLCLK]=true, |
||||
[winmsg.WM_LBUTTONUP]=true, |
||||
[winmsg.WM_RBUTTONUP]=true, |
||||
[winmsg.WM_MBUTTONUP]=true, |
||||
[winmsg.WM_MOUSEWHEEL]=true, |
||||
[winmsg.WM_SETCURSOR]=true |
||||
} |
||||
local keyboardMsgs = { |
||||
[winmsg.WM_KEYDOWN]=true, |
||||
[winmsg.WM_SYSKEYDOWN]=true, |
||||
[winmsg.WM_KEYUP]=true, |
||||
[winmsg.WM_SYSKEYUP]=true, |
||||
[winmsg.WM_CHAR]=true |
||||
} |
||||
addEventHandler('onWindowMessage', function(msg, wparam, lparam) |
||||
if not renderer then |
||||
return |
||||
end |
||||
|
||||
if not mimgui.DisableInput then |
||||
local keyboard = keyboardMsgs[msg] |
||||
local mouse = mouseMsgs[msg] |
||||
if active and (keyboard or mouse) then |
||||
renderer:SwitchContext() |
||||
local io = imgui.GetIO() |
||||
renderer:WindowMessage(msg, wparam, lparam) |
||||
if (keyboard and io.WantCaptureKeyboard) or (mouse and io.WantCaptureMouse) then |
||||
if msg == winmsg.WM_KEYDOWN or msg == winmsg.WM_SYSKEYDOWN then |
||||
keyState[wparam] = false |
||||
consumeWindowMessage(true, true, true) |
||||
elseif msg == winmsg.WM_KEYUP or msg == winmsg.WM_SYSKEYUP then |
||||
if not keyState[wparam] then |
||||
consumeWindowMessage(true, true, true) |
||||
end |
||||
else |
||||
consumeWindowMessage(true, true, true) |
||||
end |
||||
end |
||||
end |
||||
end |
||||
|
||||
-- save key states to prevent key sticking |
||||
if msg == winmsg.WM_KILLFOCUS then |
||||
keyState = {} |
||||
elseif wparam < 256 then |
||||
if msg == winmsg.WM_KEYDOWN or msg == winmsg.WM_SYSKEYDOWN then |
||||
keyState[wparam] = true |
||||
elseif msg == winmsg.WM_KEYUP or msg == winmsg.WM_SYSKEYUP then |
||||
keyState[wparam] = false |
||||
end |
||||
end |
||||
end) |
||||
|
||||
addEventHandler('onD3DDeviceLost', function() |
||||
if renderer and not renderer.lost then |
||||
renderer:InvalidateDeviceObjects() |
||||
renderer.lost = true |
||||
end |
||||
end) |
||||
|
||||
addEventHandler('onD3DDeviceReset', function() |
||||
if renderer then |
||||
renderer.lost = false |
||||
end |
||||
end) |
||||
|
||||
addEventHandler('onScriptTerminate', function(scr) |
||||
if scr == script.this then |
||||
ShowCursor(false) |
||||
LockPlayer(false) |
||||
end |
||||
end) |
||||
|
||||
local updaterThread = lua_thread.create(function() |
||||
while true do |
||||
wait(0) |
||||
local activate, hideCursor, lockPlayer = false, true, false |
||||
if #subscriptionsNewFrame > 0 then |
||||
for i, sub in ipairs(subscriptionsNewFrame) do |
||||
if type(sub.Condition) == 'function' then |
||||
sub._render = sub.Condition() |
||||
else |
||||
sub._render = sub.Condition and true |
||||
end |
||||
if sub._render then |
||||
hideCursor = hideCursor and sub.HideCursor |
||||
lockPlayer = lockPlayer or sub.LockPlayer |
||||
end |
||||
activate = activate or sub._render |
||||
end |
||||
end |
||||
active = activate |
||||
ShowCursor(active and not hideCursor) |
||||
LockPlayer(active and lockPlayer) |
||||
end |
||||
end) |
||||
updaterThread.work_in_pause = true |
||||
end |
||||
|
||||
local function Unsubscribe(t, sub) |
||||
for i, v in ipairs(t) do |
||||
if v == sub then |
||||
table.remove(t, i) |
||||
return |
||||
end |
||||
end |
||||
end |
||||
|
||||
local function ImGuiEnum(name) |
||||
return setmetatable({__name = name}, {__index = function(t, k) |
||||
return imgui.lib[t.__name .. k] |
||||
end}) |
||||
end |
||||
|
||||
--- API --- |
||||
mimgui._VERSION = '1.7.0' |
||||
mimgui.DisableInput = false |
||||
|
||||
mimgui.ComboFlags = ImGuiEnum('ImGuiComboFlags_') |
||||
mimgui.Dir = ImGuiEnum('ImGuiDir_') |
||||
mimgui.ColorEditFlags = ImGuiEnum('ImGuiColorEditFlags_') |
||||
mimgui.Col = ImGuiEnum('ImGuiCol_') |
||||
mimgui.WindowFlags = ImGuiEnum('ImGuiWindowFlags_') |
||||
mimgui.NavInput = ImGuiEnum('ImGuiNavInput_') |
||||
mimgui.FocusedFlags = ImGuiEnum('ImGuiFocusedFlags_') |
||||
mimgui.Cond = ImGuiEnum('ImGuiCond_') |
||||
mimgui.BackendFlags = ImGuiEnum('ImGuiBackendFlags_') |
||||
mimgui.TreeNodeFlags = ImGuiEnum('ImGuiTreeNodeFlags_') |
||||
mimgui.StyleVar = ImGuiEnum('ImGuiStyleVar_') |
||||
mimgui.DrawCornerFlags = ImGuiEnum('ImDrawCornerFlags_') |
||||
mimgui.DragDropFlags = ImGuiEnum('ImGuiDragDropFlags_') |
||||
mimgui.SelectableFlags = ImGuiEnum('ImGuiSelectableFlags_') |
||||
mimgui.InputTextFlags = ImGuiEnum('ImGuiInputTextFlags_') |
||||
mimgui.MouseCursor = ImGuiEnum('ImGuiMouseCursor_') |
||||
mimgui.FontAtlasFlags = ImGuiEnum('ImFontAtlasFlags_') |
||||
mimgui.HoveredFlags = ImGuiEnum('ImGuiHoveredFlags_') |
||||
mimgui.ConfigFlags = ImGuiEnum('ImGuiConfigFlags_') |
||||
mimgui.DrawListFlags = ImGuiEnum('ImDrawListFlags_') |
||||
mimgui.DataType = ImGuiEnum('ImGuiDataType_') |
||||
mimgui.Key = ImGuiEnum('ImGuiKey_') |
||||
|
||||
function mimgui.OnInitialize(cb) |
||||
assert(type(cb) == 'function') |
||||
table.insert(subscriptionsInitialize, cb) |
||||
return {Unsubscribe = function() Unsubscribe(subscriptionsInitialize, cb) end} |
||||
end |
||||
|
||||
function mimgui.OnFrame(cond, cbBeforeFrame, cbDraw) |
||||
assert(type(cond) == 'function') |
||||
assert(type(cbBeforeFrame) == 'function') |
||||
if cbDraw then assert(type(cbDraw) == 'function') end |
||||
if not eventsRegistered then |
||||
RegisterEvents() |
||||
eventsRegistered = true |
||||
end |
||||
local sub = { |
||||
Condition = cond, |
||||
LockPlayer = false, |
||||
HideCursor = false, |
||||
_before = cbDraw and cbBeforeFrame or nil, |
||||
_draw = cbDraw or cbBeforeFrame, |
||||
_render = false, |
||||
} |
||||
function sub:Unsubscribe() |
||||
Unsubscribe(subscriptionsNewFrame, self) |
||||
end |
||||
function sub:IsActive() |
||||
return self._render |
||||
end |
||||
table.insert(subscriptionsNewFrame, sub) |
||||
return sub |
||||
end |
||||
|
||||
function mimgui.SwitchContext() |
||||
return renderer:SwitchContext() |
||||
end |
||||
|
||||
function mimgui.CreateTextureFromFile(path) |
||||
return renderer:CreateTextureFromFile(path) |
||||
end |
||||
|
||||
function mimgui.CreateTextureFromFileInMemory(src, size) |
||||
return renderer:CreateTextureFromFileInMemory(src, size) |
||||
end |
||||
|
||||
function mimgui.ReleaseTexture(tex) |
||||
return renderer:ReleaseTexture(tex) |
||||
end |
||||
|
||||
function mimgui.CreateFontsTexture() |
||||
return renderer:CreateFontsTexture() |
||||
end |
||||
|
||||
function mimgui.InvalidateFontsTexture() |
||||
return renderer:InvalidateFontsTexture() |
||||
end |
||||
|
||||
function mimgui.GetRenderer() |
||||
return renderer |
||||
end |
||||
|
||||
function mimgui.IsInitialized() |
||||
return renderer ~= nil |
||||
end |
||||
|
||||
function mimgui.StrCopy(dst, src, len) |
||||
if len or tostring(ffi.typeof(dst)):find('*', 1, true) then |
||||
ffi.copy(dst, src, len) |
||||
else |
||||
len = math.min(ffi.sizeof(dst) - 1, #src) |
||||
ffi.copy(dst, src, len) |
||||
dst[len] = 0 |
||||
end |
||||
end |
||||
|
||||
local new = {} |
||||
setmetatable(new, { |
||||
__index = function(self, key) |
||||
local basetype = ffi.typeof(key) |
||||
local mt = { |
||||
__index = function(self, sz) |
||||
return setmetatable({type = ffi.typeof('$[$]', self.type, sz)}, getmetatable(self)) |
||||
end, |
||||
__call = function(self, ...) |
||||
return self.type(...) |
||||
end |
||||
} |
||||
return setmetatable({type = ffi.typeof('$[1]', basetype), basetype = basetype}, { |
||||
__index = function(self, sz) |
||||
return setmetatable({type = ffi.typeof('$[$]', self.basetype, sz)}, mt) |
||||
end, |
||||
__call = mt.__call |
||||
}) |
||||
end, |
||||
__call = function(self, t, ...) |
||||
return ffi.new(t, ...) |
||||
end |
||||
}) |
||||
mimgui.new = new |
||||
|
||||
return mimgui |
Loading…
Reference in new issue