Difference between revisions of "Dear ImGui Examples"

From GiderosMobile
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
__TOC__
 
__TOC__
 +
'''The below are fully functional working demo you can copy/paste'''.
  
'''note''': you may have to provide your own assets (fonts, gfx, …).
+
'''note''': you may have to provide your own assets (fonts, gfx, …)
  
=== Dear ImGui Custom Font ===
+
== Dear ImGui Custom Font ==
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
 
require "ImGui"
 
require "ImGui"
Line 39: Line 40:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
=== Dear ImGui Fullscreen Window ===
+
== Start a Window at a given position ==
 +
<syntaxhighlight lang="lua">
 +
require "ImGui"
 +
 
 +
application:setBackgroundColor(0x323232)
 +
 
 +
local imgui = ImGui.new()
 +
stage:addChild(imgui)
 +
 
 +
local window01 = true -- this window can be closed
 +
local windowdrawn = false -- boolean to hold our windows status
 +
 
 +
local posx, posy = 32*8, 32*4 -- starting window position
 +
local offsetx, offsety = 0, 0 -- new window position
 +
local dragflag = false
 +
 
 +
function onEnterFrame(e)
 +
-- 1. we start ImGui
 +
imgui:newFrame(e.deltaTime)
 +
 
 +
-- 2. we add some windows
 +
if window01 then -- if window exists (not closed)
 +
imgui:setNextWindowPos(posx, posy)
 +
window01, windowdrawn = imgui:beginWindow("window01", window01)
 +
-- update window new position
 +
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
 +
posx = (mx - offsetx)
 +
posy = (my - offsety)
 +
else
 +
dragflag = false
 +
end
 +
end
 +
-- window widgets
 +
if windowdrawn then -- the variable is false when main window is collapsed
 +
imgui:text("Hello Dear ImGui!")
 +
imgui:newLine()
 +
imgui:textColored("This window can be moved, resized and closed!", 0x00ff7f, 1)
 +
imgui:text("its position is: "..posx..", "..posy)
 +
end
 +
imgui:endWindow()
 +
end
 +
 
 +
-- 3. we end ImGui frame and render to screen
 +
imgui:endFrame()
 +
imgui:render()
 +
end
 +
 
 +
stage:addEventListener(Event.ENTER_FRAME, onEnterFrame)
 +
</syntaxhighlight>
 +
 
 +
== Dear ImGui Fullscreen Window ==
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
 
require "ImGui"
 
require "ImGui"
Line 76: Line 137:
 
-- a colored text
 
-- a colored text
 
imgui:textColored(text2, 0xff00ff)
 
imgui:textColored(text2, 0xff00ff)
-- Window end
 
imgui:endWindow()
 
 
end
 
end
 +
imgui:endWindow()
  
 
-- 3. we end ImGui frame and render to screen
 
-- 3. we end ImGui frame and render to screen
Line 89: Line 149:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
=== Dear ImGui Buttons ===
+
== Dear ImGui Buttons ==
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
 
require "ImGui"
 
require "ImGui"
Line 165: Line 225:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
=== File open/save dialog project example ===
+
== File Open/Save Dialog Project Demo ==
[https://github.com/MultiPain/Gideros_examples/tree/master/ImGuiFileDialogDemo GitHub]
+
[[File:Dear_ImGui_FileDialog_Demo.png|300px]]
 +
'''[https://github.com/MultiPain/Gideros_examples/tree/master/ImGuiFileDialogDemo GitHub project]''' (a little bit outdated, fix below!)
 +
<syntaxhighlight lang="lua">
 +
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()
  
=== Dear ImGui Snap to Grid ===
+
UI:render()
'''Here is a grid snaped window snippet'''<br/>
+
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())
 +
</syntaxhighlight>
 +
 
 +
== Dear ImGui Snap to Grid ==
 
[[File:Imgui sample03.png|200px]]
 
[[File:Imgui sample03.png|200px]]
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
 
require "ImGui"
 
require "ImGui"
  
GRID_CELL @ 64
+
GRID_CELL = 64
 
application:setBackgroundColor(0x323232)
 
application:setBackgroundColor(0x323232)
 
local CW = application:getContentWidth()
 
local CW = application:getContentWidth()
Line 198: Line 540:
 
local dragFlag = false
 
local dragFlag = false
  
local function myResizeCallback(x,y,cw,ch,dw,dh)
+
local function myResizeCallback(x, y, cw, ch, dw, dh)
return (dw // GRID_CELL) * GRID_CELL, (dh // GRID_CELL) * GRID_CELL
+
return (dw//GRID_CELL)*GRID_CELL, (dh//GRID_CELL)*GRID_CELL
 
end
 
end
  
 +
-- loop
 
function enterFrame(e)
 
function enterFrame(e)
 
imgui:newFrame(e.deltaTime)
 
imgui:newFrame(e.deltaTime)
if (mainWindowOpen) then
+
if mainWindowOpen then
 
imgui:setNextWindowPos(snapX, snapY)
 
imgui:setNextWindowPos(snapX, snapY)
 
imgui:setNextWindowSizeConstraints(GRID_CELL*2, GRID_CELL*1, GRID_CELL*8, GRID_CELL*8)
 
imgui:setNextWindowSizeConstraints(GRID_CELL*2, GRID_CELL*1, GRID_CELL*8, GRID_CELL*8)
 
mainWindowOpen, drawMainWindowOpen = imgui:beginWindow("My window", mainWindowOpen, nil, myResizeCallback)
 
mainWindowOpen, drawMainWindowOpen = imgui:beginWindow("My window", mainWindowOpen, nil, myResizeCallback)
 
local mouseClicked = imgui:isMouseClicked(KeyCode.MOUSE_LEFT)
 
local mouseClicked = imgui:isMouseClicked(KeyCode.MOUSE_LEFT)
if not dragFlag and mouseClicked and imgui:isWindowHovered() then dragFlag=true end
+
if not dragFlag and mouseClicked and imgui:isWindowHovered() then
 +
dragFlag = true
 +
end
 
if imgui:isWindowFocused() and dragFlag then
 
if imgui:isWindowFocused() and dragFlag then
local mx,my = imgui:getMousePos()
+
local mx, my = imgui:getMousePos()
 
local wx, wy = imgui:getWindowPos()
 
local wx, wy = imgui:getWindowPos()
 
if mouseClicked or imgui:isMouseReleased(KeyCode.MOUSE_LEFT) then
 
if mouseClicked or imgui:isMouseReleased(KeyCode.MOUSE_LEFT) then
offsetX, offsetY = mx - wx, my - wy
+
offsetX, offsetY = mx-wx, my-wy
 
end
 
end
 
if imgui:isMouseDragging(KeyCode.MOUSE_LEFT, 0) then
 
if imgui:isMouseDragging(KeyCode.MOUSE_LEFT, 0) then
snapX = ((mx - offsetX) // GRID_CELL) * GRID_CELL
+
snapX = ((mx-offsetX)//GRID_CELL)*GRID_CELL
snapY = ((my - offsetY) // 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
 
else
 
dragFlag = false
 
dragFlag = false
 
end
 
end
 
end
 
end
if (drawMainWindowOpen) then  
+
if drawMainWindowOpen then
 
-- do stuff
 
-- do stuff
 
end
 
end
Line 232: Line 582:
 
end
 
end
  
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)
 
 
stage:addEventListener("enterFrame", enterFrame)
 
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)
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
 +
'''More to come God's willing...'''
  
  
 
'''[[Dear ImGui]]'''
 
'''[[Dear ImGui]]'''
 
{{GIDEROS IMPORTANT LINKS}}
 
{{GIDEROS IMPORTANT LINKS}}

Latest revision as of 01:50, 9 October 2024

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)

Start a Window at a given position

require "ImGui"

application:setBackgroundColor(0x323232)

local imgui = ImGui.new()
stage:addChild(imgui)

local window01 = true -- this window can be closed
local windowdrawn = false -- boolean to hold our windows status

local posx, posy = 32*8, 32*4 -- starting window position
local offsetx, offsety = 0, 0 -- new window position
local dragflag = false

function onEnterFrame(e)
	-- 1. we start ImGui
	imgui:newFrame(e.deltaTime)

	-- 2. we add some windows
	if window01 then -- if window exists (not closed)
		imgui:setNextWindowPos(posx, posy)
		window01, windowdrawn = imgui:beginWindow("window01", window01)
		-- update window new position
		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
				posx = (mx - offsetx)
				posy = (my - offsety)
			else
				dragflag = false
			end
		end
		-- window widgets
		if windowdrawn then -- the variable is false when main window is collapsed
			imgui:text("Hello Dear ImGui!")
			imgui:newLine()
			imgui:textColored("This window can be moved, resized and closed!", 0x00ff7f, 1)
			imgui:text("its position is: "..posx..", "..posy)
		end
		imgui:endWindow()
	end

	-- 3. we end ImGui frame and render to screen
	imgui:endFrame()
	imgui:render()
end

stage:addEventListener(Event.ENTER_FRAME, 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

Dear ImGui FileDialog Demo.png

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

Imgui sample03.png

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...


Dear ImGui