IGI, the Immediate Gizmo Interface, is a GUI you draw on top of your game: pause and options menus, HUDs, debug panels, level editors and the like. It's built on Dear ImGui, the GUI library used in a great many game tools, and it looks and works the same on the desktop and on the web.
BambooBasic has two GUI toolkits, for two different jobs:
| BGI | IGI | |
| For | Tools and applications: real windows, dialogs and forms | Menus, HUDs, debug panels and editors inside a game |
| How you use it | Create gizmos once, keep their handles, handle their events | Call it every frame; each call answers straight away |
| Look | Fixed: classic Windows, the same everywhere | Yours to change: themes, every colour, roundings, fonts |
| Drawn | In its own windows | Over your game, as the last thing in each frame |
The reference for every function is in Runtime Commands > IGI, and there are four examples in examples/BambooRuntime/27 - IGI, each with a desktop and a web version.
There's nothing to set up. In your game loop, after drawing the game and before b2dFlip, call the igi functions:
Function Main()
b2dGraphics(800, 600, 1)
Local speed:Int = 2
Local paused:Int = False
Local running:Int = True
While running
sysUpdateEvents()
b2dCls()
; ... draw your game ...
igiBegin("Options")
speed = igiSliderInt("Speed", speed, 0, 10)
paused = igiCheckbox("Paused", paused)
If igiButton("Quit") Then running = False
igiEnd()
b2dFlip()
Wend
b2dEnd()
Return False
EndFunction
That's the whole idea: igiBegin opens a window, everything until igiEnd goes in it, and IGI draws it when you call b2dFlip. Next frame you call the same functions again — that's what "immediate" means. If you stop calling them, the window is gone.
A widget that edits something is given the current value and hands back the new one:
volume = igiSliderInt("Volume", volume, 0, 100)
name = igiInputText("Name", name)
difficulty = igiCombo("Difficulty", difficulty, "Easy|Normal|Hard")
If the user didn't touch it this frame, you get the same value back. Buttons and menu items return 1 on the frame they're clicked:
If igiButton("Save") Then SaveGame()
Lists (drop-downs and list boxes) are given as one string with | between the items, and the choice comes back as a number counting from 0.
Some functions open something that has to be closed again:
If igiBeginTabBar("tabs") Then
If igiBeginTabItem("Audio") Then
music = igiCheckbox("Music", music)
igiEndTabItem()
EndIf
igiEndTabBar()
EndIf
If one is forgotten, IGI tidies up and shows a warning rather than stopping your program.
; A HUD in the corner: no title, can't be moved, fits its text
igiSetNextWindowPos(10, 10)
igiBeginEx("HUD", -1, -1, 0, 0, IGI_WINDOW_NOTITLEBAR + IGI_WINDOW_NOMOVE + IGI_WINDOW_AUTORESIZE)
igiText("Score: " & ToString(score))
igiText("Lives: " & ToString(lives))
igiEnd()
Your game still gets every click and key press. When the pointer is over an IGI window, igiWantsMouse() is 1; when an IGI text box has the keyboard, igiWantsKeyboard() is 1. Check them so a click on a button doesn't also fire your gun:
If inpIsMouseHit(VMOUSE_LBUTTON) And Not igiWantsMouse() Then Fire()
IGI tells widgets apart by their label, so two buttons called "Buy" would be the same button. In a loop, put igiPushID / igiPopID round them, or hide a unique part after ## in the label (it isn't shown):
For i = 0 To 4
igiPushID(ToString(i))
If igiButton("Buy") Then BuyItem(i)
igiPopID()
Next
If igiButton("Buy##sword") Then BuySword()
igiOpenPopup(name) asks for a pop-up to open; it opens the next time igiBeginPopup or igiBeginPopupModal with that name is called. So you can open it from anywhere — a button, a menu item, a key:
If igiMenuItem("About") Then igiOpenPopup("About")
If igiBeginPopupModal("About") Then
igiText("My Game, version 1.0")
If igiButton("Close") Then igiCloseCurrentPopup()
igiEndPopup()
EndIf
igiImage and igiImageButton draw any image you loaded with b2dLoadImage — icons in an inventory, a portrait in a dialogue box, a minimap.
This is where IGI is yours. Styling stays until you change it, so you normally set it up once, before your loop:
igiSetStyle(IGI_STYLE_WINDOWROUNDING, 8.0)
igiSetStyle(IGI_STYLE_FRAMEROUNDING, 4.0)
igiSetColour(IGI_COL_WINDOWBG, 20, 20, 30, 240)
igiSetColour(IGI_COL_TITLEBGACTIVE, 20, 120, 120, 255)
igiSetColour(IGI_COL_BUTTON, 20, 120, 120, 200)
igiSetColour(IGI_COL_BUTTONHOVERED, 30, 160, 160, 255)
titleFont = igiLoadFont("Media/MyFont.ttf", 28)
Using a Dear ImGui theme from the internet: the colour names match ImGui's, so
ImGuiCol_WindowBg is IGI_COL_WINDOWBG, ImGuiCol_ButtonHovered is
IGI_COL_BUTTONHOVERED, and so on. ImGui themes give colours from 0.0 to 1.0: multiply by
255. So colors[ImGuiCol_WindowBg] = ImVec4(0.10f, 0.10f, 0.12f, 0.94f) becomes
igiSetColour(IGI_COL_WINDOWBG, 26, 26, 31, 240).
Example 04_Styling is a live editor to try it all out.
IGI has a code editor: a text box for code with syntax colouring, line numbers, undo and the usual editing keys. Use it for an in-game console, a script editor in a level editor, a shader tweaker, or a game where the player writes code.
It's the one IGI widget with a handle, because it keeps its own text. Make it once, then draw it every frame inside a window:
Global editor:Int
Global basic:Int
; In Main
basic = igiLoadLanguage("Media/bamboobasic.lang")
editor = igiCreateCodeEditor()
igiCodeEditorSetLanguage(editor, basic)
igiCodeEditorSetText(editor, "Print " & Chr(34) & "Hello" & Chr(34))
; Every frame
igiBegin("Script")
igiText("Line " & ToString(igiCodeEditorLine(editor)))
igiCodeEditor(editor, 0, 0) ; 0, 0 = fill the window
If igiCodeEditorChanged(editor) Then CheckScript()
igiEnd()
Languages are files you can write. How a language is coloured — its comments, strings, numbers, keywords and colours — is described in a small text file, a .lang file. Load one with igiLoadLanguage, or build one from text with igiDefineLanguage (handy for a language your game makes up). Ready-made ones are in userlibs\languages: bamboobasic.lang (coloured like the IDE), cpp.lang, lua.lang, wgsl.lang and hlsl.lang. Copy the one you want next to your program, as with any other media file.
To show problems, igiCodeEditorMarkLine colours a line and gives it a tooltip; igiCodeEditorClearMarks takes them all away. igiCodeEditorGotoLine jumps to a line, and igiCodeEditorInsertText types text in at the caret. There are settings for read-only, tab size and line numbers. The reference lists every function.
Example 05_CodeEditor is a turtle-graphics script editor that checks the script as you type.
IGI works the same in the browser, with three small differences that come from how browsers work:
In a web program the loop body lives in WebLoop(), as always — see Building for the Web.
BambooBasic © 2026 Michael Denathorn