BambooBasic Logo


IGI — the In-Game GUI

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:

BGIIGI
ForTools and applications: real windows, dialogs and formsMenus, HUDs, debug panels and editors inside a game
How you use itCreate gizmos once, keep their handles, handle their eventsCall it every frame; each call answers straight away
LookFixed: classic Windows, the same everywhereYours to change: themes, every colour, roundings, fonts
DrawnIn its own windowsOver 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.



Your first window

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.



Values go in, new values come out

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.



Begin and End

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.



Windows
; 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()


Sharing the mouse and keyboard with your game

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()


Same label, different widgets

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()


Pop-ups

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


Pictures

igiImage and igiImageButton draw any image you loaded with b2dLoadImage — icons in an inventory, a portrait in a dialogue box, a minimap.



Styling

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.



The code editor

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.



On the web

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.



The examples

BambooBasic © 2026 Michael Denathorn