Dear ImGui Examples
From GiderosMobile
The below are fully functional working demo you can copy/paste.
note: you may have to provide your own assets (fonts, gfx, …)
Dear ImGui Custom Font
require "ImGui"
local imgui = ImGui.new()
stage:addChild(imgui)
local IO = imgui:getIO()
local fontatlas = IO:getFonts()
local myfont = fontatlas:addFont("fonts/Cabin-Regular-TTF.ttf", 16) -- your custom font here
IO:setFontDefault(myfont)
fontatlas:build()
-- imgui style
local style = imgui:getStyle()
style:setWindowMinSize(64*4, 64*1.5)
function onEnterFrame(e)
-- imgui start
imgui:newFrame(e.deltaTime)
-- window
if imgui:beginWindow("Window") then
-- widgets
imgui:text("This is using 'myfont' to write text.")
end
imgui:endWindow()
-- imgui end
imgui:render()
imgui:endFrame()
end
stage:addEventListener("enterFrame", onEnterFrame)
Dear ImGui Fullscreen Window
require "ImGui"
local imgui = ImGui.new()
stage:addChild(imgui)
-- some imgui params
local IO = imgui:getIO()
IO:setFontGlobalScale(2)
--imgui:setLightStyle()
--imgui:setClassicStyle()
imgui:setDarkStyle()
-- some vars
local CW = application:getContentWidth()
local text, text2 = "Centered Text", "Colored Text"
-- the loop
function enterFrame(e)
-- 1. we start ImGui
imgui:newFrame(e.deltaTime)
-- 2. our GUI
if imgui:beginFullScreenWindow("Hello ImGui") then
-- some spacing
imgui:dummy(CW, 32 * 2) -- imgui:dummy(w, h)
-- a centered text
local textW = imgui:calcTextSize(text)
local textMid = (CW - textW) / 2
imgui:dummy(textMid, 0)
imgui:sameLine(0, 0) -- puts the next element on the same line with no gap, for gaps use imgui:sameLine()
imgui:text(text)
-- some spacing
imgui:dummy(CW, 32 * 4)
-- a colored text
imgui:textColored(text2, 0xff00ff)
end
imgui:endWindow()
-- 3. we end ImGui frame and render to screen
imgui:endFrame()
imgui:render()
end
-- the listeners
stage:addEventListener("enterFrame", enterFrame)
Dear ImGui Buttons
require "ImGui"
local imgui = ImGui.new()
stage:addChild(imgui)
-- some imgui params
local IO = imgui:getIO()
IO:setFontGlobalScale(2)
imgui:setClassicStyle()
-- some vars
local CW = application:getContentWidth()
local text = "Centered Text"
local imageTex = Texture.new("gfx/100 (2).png")
-- loop
function enterFrame(e)
-- 1. we start ImGui
imgui:newFrame(e.deltaTime)
-- 2. our GUI
if imgui:beginFullScreenWindow("Hello ImGui") then
-- some spacing
imgui:dummy(CW, 32*2)
-- a centered text
local textW = imgui:calcTextSize(text)
local textMid = (CW - textW) / 2
imgui:dummy(textMid, 0)
imgui:sameLine(0, 0)
imgui:text(text)
-- some spacing
imgui:dummy(CW, 32*2)
-- a button
imgui:text("A button")
imgui:pushStyleVar(ImGui.StyleVar_ButtonTextAlign, 0.5, 0.5)
imgui:button(("x"), 128, 64) -- "text", w, h
imgui:popStyleVar()
-- some spacing
imgui:dummy(CW, 32*1)
-- a grid of buttons
imgui:text("A grid of buttons")
local i = 0
for x = 0, 1, 0.5 do
for y = 0, 1, 0.5 do
imgui:pushStyleVar(ImGui.StyleVar_ButtonTextAlign, x, y)
if imgui:button(("[%.1f, %.1f]"):format(x,y), application:getContentWidth()//3, 100) then
print(x, y)
end
imgui:popStyleVar()
-- count elements
i += 1
-- make new line on 3d element
if (i % 3 ~= 0) then imgui:sameLine() end
end
end
-- some spacing
imgui:dummy(application:getContentWidth(), 32*1)
-- an image button with text
imgui:text("An image button \nwith text")
if imgui:scaledImageButtonWithText(imageTex, "button", 32*1, 32*1, 32*4.5, 32*1.5) then
print("pressed")
end
end
imgui:endWindow()
-- 3. we end ImGui frame and render to screen
imgui:endFrame()
imgui:render()
end
-- add listener to draw GUI
stage:addEventListener("enterFrame", enterFrame)
File Open/Save Dialog Project Demo
GitHub project (a little bit outdated, fix below!)
TestScene = Core.class(Sprite)
local function dummyConstraints(x,y, w,h, dw,dh) return dw,dh end
function TestScene:init()
self.imgui = ImGui.new()
self:addChild(self.imgui)
local IO = self.imgui:getIO()
IO:setIniFilename(nil)
IO:setLogFilename("|D|log.txt")
self:appResize()
self:addEventListener("enterFrame", self.drawGUI, self)
self:addEventListener("applicationResize", self.appResize, self)
------------------------------------------------------------------
self.cachedDirs = {} -- cached dirs and files (refilled only when directory is changed)
self.fileName = "" -- current file name in open/save dialog
self.openModalType = "" -- type of modal window ("Save file" or "Open file")
self.currentItem = 0 -- current selected item in open dialog
end
-- callbacks
function TestScene:onSaveDialogOK(dir)
self.imgui:logToFile() -- (auto_open_depth = -1, filename = nil)
end
function TestScene:onSaveDialogError(errorMessage)
self.imgui:logToFile() -- (auto_open_depth = -1, filename = nil)
end
function TestScene:onOpenDialogOK(dir)
self.imgui:logToFile() -- (auto_open_depth = -1, filename = nil)
end
function TestScene:onOpenDialogError(errorMessage)
self.imgui:logToFile() -- (auto_open_depth = -1, filename = nil)
end
function TestScene:updateDirCache(dir)
if (self.cachedDirs.isUpdated) then return end
self.cachedDirs.isUpdated = true
self.cachedDirs.file = {}
self.cachedDirs.directory = {}
-- scan directory
for entry in lfs.dir(dir) do
if (entry ~= "." and entry ~= "..") then
local path = dir.."\\"..entry
local attributes = lfs.attributes(path)
local t = self.cachedDirs[attributes.mode] -- pick "self.cachedDirs.file" or "self.cachedDirs.directory" table
if (t) then
t[#t+1] = {
path = path,
name = entry,
attr = attributes,
selected = false,
}
end
end
end
end
function TestScene:drawFileDialog(UI)
-- setup min and max sizes
UI:setNextWindowSizeConstraints(800, 400, 1920, 1080)
UI:setNextFrameWantCaptureMouse(true)
-- draw window
-- 2nd argument draws "X" on window
if UI:beginPopupModal(self.openModalType, true, 0, dummyConstraints) then
local isOpenMode = self.openModalType == "Open file"
local currentDir = lfs.currentdir()
if UI:button("Back") then
-- reset selected item and selected filename
self.currentItem = 0
self.fileName = ""
-- change dir
currentDir = currentDir:match("(.*[/\\])")
lfs.chdir(currentDir)
-- force to rewrite dirs
self.cachedDirs.isUpdated = false
end
UI:sameLine()
-- show path, write dir to tmp variable
local tmp, flag = UI:inputText("Path", currentDir, 256, ImGui.InputTextFlags_EnterReturnsTrue)
-- if input ends
if flag then
-- check if dir exists
local status = lfs.chdir(tmp)
if status then
-- change dir
currentDir = tmp
lfs.chdir(currentDir)
-- force to rewrite dirs
self.cachedDirs.isUpdated = false
end
end
UI:separator()
self:updateDirCache(currentDir)
-- draw folders as buttons
local frameHeightWithSpacing = UI:getFrameHeightWithSpacing()
-- UI:beginChild("DIRS", 300, -frameHeightWithSpacing, ImGui.WindowFlags_HorizontalScrollbar)
UI:beginChild("DIRS", 300, -frameHeightWithSpacing, true)
for _, data in ipairs(self.cachedDirs.directory) do
if UI:button(data.name, -1, 0) then
lfs.chdir(data.path)
self.cachedDirs.isUpdated = false
end
end
UI:endChild()
UI:sameLine()
UI:beginChild("FILES", 0, -frameHeightWithSpacing)
-- draw table of files
UI:columns(4)
UI:text("Name") UI:nextColumn()
UI:text("Change") UI:nextColumn()
UI:text("Modification") UI:nextColumn()
UI:text("Size") UI:nextColumn()
UI:separator()
for i, data in ipairs(self.cachedDirs.file) do
-- files are selectables
if ImGui:selectable(data.name, self.currentItem == i) then
self.currentItem = i
self.fileName = data.name
end
-- draw last change date
UI:nextColumn()
UI:text(os.date('%c', data.attr.change))
UI:nextColumn()
-- draw last modification date
UI:text(os.date('%c', data.attr.modification))
UI:nextColumn()
-- calculate text object position aligned to the right edge
local text = ("%.2f KB"):format(data.attr.size / 1024)
local spaceX = UI:getStyle():getItemSpacing()
local tw, _th = UI:calcTextSize(text)
UI:setCursorPosX(UI:getCursorPosX()+UI:getColumnWidth()-tw-UI:getScrollX()-(2*spaceX))
-- draw file size
UI:text(text)
UI:nextColumn()
end
UI:endChild()
UI:text("File name:")
UI:sameLine()
local w = UI:getContentRegionAvail()
-- leave 150 pixels for buttons
UI:setNextItemWidth(w-150)
local inputFlag = false
-- draw filename input box
self.fileName, inputFlag = UI:inputText("##x", self.fileName, 64, ImGui.InputTextFlags_EnterReturnsTrue)
UI:sameLine()
w = UI:getContentRegionAvail()
if isOpenMode then
-- search and highlight filename
if self.fileName ~= "" then
local itemFound = false
for i, data in ipairs(self.cachedDirs.file) do
if data.name == self.fileName then
itemFound = true
self.currentItem = i
break
end
end
if (not itemFound) then
self.currentItem = 0
end
end
-- if ENTER (on input box) or button was pressed
if (UI:button("Open", w*.5) or inputFlag) then
-- try to open file
if (self.fileName ~= "") then
local status, error = pcall(self.onOpenDialogOK, self, currentDir .."\\"..self.fileName)
if (not status) then
self:onOpenDialogError(error)
end
end
UI:closeCurrentPopup()
self.fileName = ""
end
else
if (UI:button("Save", w*.5) or inputFlag) then
local status, error = pcall(self.onSaveDialogOK, self, currentDir.."\\"..self.fileName)
if (not status) then
self:onSaveDialogError(error)
else
self.cachedDirs.isUpdated = false
end
UI:closeCurrentPopup()
self.fileName = ""
end
end
UI:sameLine()
w = UI:getContentRegionAvail()
if (UI:button("Cancel", w) or UI:isKeyPressed(KeyCode.ESC)) then
UI:closeCurrentPopup()
self.fileName = ""
end
UI:endPopup()
end
end
-- loop
function TestScene:drawGUI(e)
local UI = self.imgui
UI:newFrame(e.deltaTime)
UI:pushStyleColor(ImGui.Col_WindowBg, 0, 0)
if UI:beginFullScreenWindow("File dialog demo", nil, ImGui.WindowFlags_MenuBar) then
UI:popStyleColor()
if UI:beginMenuBar() then
local openModal = false
if UI:beginMenu("File") then
if UI:menuItem("Open", "CTRL+O") then
openModal = true -- you can't open popups from menu bars (ImGui problem)
self.openModalType = "Open file"
end
if UI:menuItem("Save as", "CTRL+SHIFT+S") then
openModal = true -- you can't open popups from menu bars (ImGui problem)
self.openModalType = "Save file"
end
UI:endMenu()
end
-- see: https://github.com/ocornut/imgui/issues/331
if openModal then
self.currentItem = 0
UI:openPopup(self.openModalType)
end
self:drawFileDialog(UI)
UI:endMenuBar()
end
end
UI:endWindow()
UI:render()
UI:endFrame()
end
-- adapt ImGui to fill window size
function TestScene:appResize()
local minX, minY, maxX, maxY = application:getLogicalBounds()
local sx = application:getLogicalScaleX()
local sy = application:getLogicalScaleY()
self.imgui:setScale(1/sx, 1/sy)
self.imgui:setPosition(minX, minY)
local IO = self.imgui:getIO()
IO:setDisplaySize((maxX-minX)*sx, (maxY-minY)*sy)
end
-- START THE DEMO
require "lfs" -- don't forget to add the plugin in your project
require "ImGui" -- don't forget to add the plugin in your project
application:setBackgroundColor(0x323232)
stage:addChild(TestScene.new())
Dear ImGui Snap to Grid
require "ImGui"
GRID_CELL = 64
application:setBackgroundColor(0x323232)
local CW = application:getContentWidth()
local CH = application:getContentHeight()
for i = 1, CW, GRID_CELL do
local line = Pixel.new(0xffffff, 1, 1, CH)
line:setX(i)
stage:addChild(line)
end
for i = 1, CH, GRID_CELL do
local line = Pixel.new(0xffffff, 1, CW, 1)
line:setY(i)
stage:addChild(line)
end
local imgui = ImGui.new()
stage:addChild(imgui)
local mainWindowOpen, drawMainWindowOpen = true, false
local snapX,snapY = 0, 0
local offsetX, offsetY = 0, 0
local dragFlag = false
local function myResizeCallback(x, y, cw, ch, dw, dh)
return (dw//GRID_CELL)*GRID_CELL, (dh//GRID_CELL)*GRID_CELL
end
-- loop
function enterFrame(e)
imgui:newFrame(e.deltaTime)
if mainWindowOpen then
imgui:setNextWindowPos(snapX, snapY)
imgui:setNextWindowSizeConstraints(GRID_CELL*2, GRID_CELL*1, GRID_CELL*8, GRID_CELL*8)
mainWindowOpen, drawMainWindowOpen = imgui:beginWindow("My window", mainWindowOpen, nil, myResizeCallback)
local mouseClicked = imgui:isMouseClicked(KeyCode.MOUSE_LEFT)
if not dragFlag and mouseClicked and imgui:isWindowHovered() then
dragFlag = true
end
if imgui:isWindowFocused() and dragFlag then
local mx, my = imgui:getMousePos()
local wx, wy = imgui:getWindowPos()
if mouseClicked or imgui:isMouseReleased(KeyCode.MOUSE_LEFT) then
offsetX, offsetY = mx-wx, my-wy
end
if imgui:isMouseDragging(KeyCode.MOUSE_LEFT, 0) then
snapX = ((mx-offsetX)//GRID_CELL)*GRID_CELL
snapY = ((my-offsetY)//GRID_CELL)*GRID_CELL
-- restrict
if snapX <= 0 then snapX = 0 end
if snapY <= 0 then snapY = 0 end
if snapX >= CW-GRID_CELL then snapX = CW-GRID_CELL end
if snapY >= CH-GRID_CELL then snapY = CH-GRID_CELL end
else
dragFlag = false
end
end
if drawMainWindowOpen then
-- do stuff
end
imgui:endWindow()
end
imgui:endFrame()
imgui:render()
end
stage:addEventListener("enterFrame", enterFrame)
--stage:addEventListener("mouseDown", function(e) imgui:onMouseDown(e) end)
--stage:addEventListener("mouseUp", function(e) imgui:onMouseUp(e) end)
--stage:addEventListener("mouseHover", function(e) imgui:onMouseHover(e) end)
--stage:addEventListener("mouseMove", function(e) imgui:onMouseMove(e) end)
--stage:addEventListener("mouseWheel", function(e) imgui:onMouseWheel(e) end)
--stage:addEventListener("keyDown", function(e) imgui:onKeyDown(e) end)
--stage:addEventListener("keyUp", function(e) imgui:onKeyUp(e) end)
--stage:addEventListener("keyChar", function(e) imgui:onKeyChar(e) end)
More to come God's willing...