> [!WARNING]
> Maui has been archived & deprecated in favor of [Wax](https://github.com/latte-soft/wax), a far more polished project that isn't *dependant* on the Roblox engine, and can also run on both vanilla Lua, **and** Luau. In addition, thank you to all who used Maui in supporting both us & this project!

# Maui

    Roblox Studio Plugin for Packing Modules as Executable Luau Scripts

## About

Put short, Maui is the full idea of Roblox model/object serialization **and** script packing put together. This allows script developers to use any of the tooling or libraries they wish! You could use a workflow with [VSCode](https://code.visualstudio.com), [Aftman](https://github.com/LPGhatguy/aftman), [Rojo](https://rojo.space), [Wally](https://wally.run), [Roblox-TS](https://roblox-ts.com), [Tarmac](https://github.com/Roblox/tarmac), [Darklua](https://darklua.com), etc.. Or just good ol' Roblox Studio! If it's built down to a Roblox model, you can build it into a script with Maui.

It's very general purpose, and will pack almost any model you throw at it. Any class, any property, any attribute, and *any* Lua DataType. As long as it's configured properly in the API dump and is a Lua-accessable DataType, it'll build!

Maui is built with [LuaEncode](https://github.com/regginator/LuaEncode), another general-purpose project of mine that was a direct component of this. It will handle **any** Lua/Roblox-Lua DataType, and even supports vanilla Lua 5.1! If it weren't for making LuaEncode, Maui wouldn't be possible.

### **Also..**

**The first thing you may be wondering if you clicked on the *"Get it on Roblox"* button before reading this** is probably something along the lines of **"Why is this a paid plugin?"**. Well, it *is* and it *isn't*. Let me explain.

The plugin, and **all** of its source code, will **always** be 100% free (as-in freedom) & open source, under the MIT License. You can download & build from source on the [GitHub repository](https://github.com/latte-soft/maui) (if you're worried about security or whatnot), or install a pre-built version directly from the [releases page](https://github.com/latte-soft/maui/releases). We *also* provide the plugin on Roblox's Developer Marketplace for ~250 Robux, if you want to support us, or just want automatic updates. With a self/pre-built version of the plugin, you're responsible for keeping it up-to-date in your plugins folder.

## Installation

* Installation via Roblox Marketplace

    You can purchase the plugin directly [here](https://www.roblox.com/library/12071720464). Remember, you *can* get the plugin for free directly from GitHub, but you are responsable for maintaining the build on your local machine.

    From there, just "Install" the plugin in Studio from Roblox like normal!

* Installation via GitHub Releases

    Goto the [latest release](https://github.com/latte-soft/maui/releases/lastest) on the GitHub repository, and download whichever file suites best. (`*.rbxm` is faster to load, and `*.rbxmx` is more readable.)

    If you don't know where your specific local-plugins folder is, in Studio, goto the "Plugins" tab via the ribbon-bar, and on the left there should be a "Plugins Folder" button, opening that will prompt the local plugins folder, where you will place the plugin in.

    ![Where the plugins folder is](assets/repo/usage/where_plugins_folder_is.png)

* Building from Source

    We provide a [`build.sh`](build.sh) script, however it will only work with a POSIX-compliant shell. You need everything in [`aftman.toml`](aftman.toml) installed, preferably with [Aftman](https://github.com/LPGhatguy/aftman).

    The following instructions are just for building Maui as quickly as possible, in-case you can't use `build.sh`.

  * Clone the Repository

    ```txt
    git clone https://github.com/latte-soft/maui.git && cd maui

  * Install Packages w/ Wally

    ```txt
    wally install

  * Build Model w/ Rojo

    ```txt
    rojo build -o Maui.rbxm

    And you're done! You can place the built model file into your plugins folder

## Usage

In a new/existing Studio place, go to the *"Plugins"* tab from the ribbon menu, and you'll see the plugin:

From there, just select an object, and click "Build"! Due to LuaEncode's fast speeds and optimization, Maui usually only takes a few *milliseconds* to create the output.

After the script is built, Maui should open the output script's editor window, and Maui will store information logs in it's internal console.

From there, you're done! You can run it in a script utility, another script, place it into obfuscation, etc.. It's 100% portable, and will work in almost *any* Roblox environment!

Remember, because it **literally** packs a Roblox model, you need to have at least 1 `LocalScript` (client context) or `Script` (server context) to actually initialize what you want. You *can* configure this to ignore context like `Script.Disabled` or running a script in the wrong context in the [project format](#the-maui-project-format). By default, if you provide a `MainModule`, Maui will return the value from it with the exact same behavior as requiring a module by ID on Roblox.

## The `maui` Script Global

In all Maui script closures, a "`maui`" global is pushed into the environment. You could use it in a script like so:

```lua
if maui then -- Then the script is running under Maui's environment!
    print(maui.Version)
end

Here's the *current* API reference:

* ### Get Version

  ```lua
  <string> maui.Version

  Returns a constant of the version of Maui the script was built with.

* ### Get Real Script Object

  ```lua
   maui.Script

  Returns the REAL script global from the closure that's currently running.

* ### Get Shared Environment Table

  ```lua
   maui.Shared

  Returns a "shared" table for ALL closures in a Maui-generated script, so you don't need to the real `_G` or `shared`.

## The "`.maui`" Project Format

##### *This is really meant for more advanced projects/modules you're packing, and right now there really isn't much outside of minification options.*

You can place a module named ".maui" under the model you're building, and Maui will expect the return to be a table of options. Here's a Lua template for this:

```lua
return {
    FormatVersion = 1, -- Isn't necessary in the project file, but just for future proofing the format incase we ever change anything

    -- All output options
    Output = {
        Directory = "return script.Parent", -- A string/function/instance (supports all) denoting/returning a specific output path in the DataModel, and a string of the filename
        ScriptName = "MauiGeneratedScript", -- The actual name of the output script object, e.g. "SomeScript"
        ScriptType = "LocalScript", -- Accepts "LocalScript", "Script", and "ModuleScript"

        MinifyTable = false, -- If the codegen table itself (made from LuaEncode) is to be minified
        UseMinifiedLoader = true -- Use the pre-minified LoadModule script in the codegen, which is always predefined and not useful for debugging
    },

    -- "Flags" to be respected at runtime
    Flags = {
        ContextualExecution = true, -- If client/server context should be checked at runtime, and ignores LuaSourceContainer.Disabled (e.g. LocalScripts only run on the client, Scripts only run on the server)
        ReturnMainModule = true -- **If applicable**, return the contents of a "MainModule"-named ModuleScript from the root of the model. This behaves exactly like Roblox's MainModule system
    },

    -- Property wl/bl overrides
    Properties = {
        Whitelist = {}, -- [ClassName] = {PropertyName, ...}
        Blacklist = {} --  ^^^

You can *also* use [Rojo's JSON module feature](https://rojo.space/docs/v7/sync-details/#json-modules) (if you're using Rojo) to store this module in JSON, which would obviously be a file named ".maui.json":

```json
    "FormatVersion": 1,

    "Output": {
        "Directory": "return script.Parent",
        "ScriptName": "MauiGeneratedScript",
        "ScriptType": "LocalScript",

        "MinifyTable": false,
        "UseMinifiedLoader": true
    },

    "Flags": {
        "ContextualExecution": true,
        "ReturnMainModule": true
    },

    "Properties": {
        "Whitelist": {},
        "Blacklist": {}

Still keep in mind, you need to include this file in your `*.project.json` file, if you're using Rojo.

## Contributing

*For now*, there really isn't any specific contribution instructions to follow. We're still working on our public Luau style-guide, so if you have an idea/implementation of something, show us your idea through an [issue](https://github.com/latte-soft/maui/issues) or [pull-request](https://github.com/latte-soft/maui/pulls)!

## License

This project, and all related files/documents, are licensed under the **MIT License**. You should have recieved a copy of [`LICENSE.txt`](LICENSE.txt) in this program. If not:

```txt
MIT License

Copyright (c) 2022-2023 Latte Softworks <latte.to>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

*README social link icons by [@csqrl](https://github.com/csqrl)*


import { CollectionService } from "@rbxts/services";

    for (const obj of CollectionService.GetTagged("Lava")) {
        if (obj.IsA("BasePart")) {
            obj.Touched.Connect(part =>
                part
                    .Parent
                    ?.FindFirstChildOfClass("Humanoid")
                    ?.TakeDamage(100)
            );

### Type Safety

With static types, you'll never run into errors caused by typos, indexing an undefined value, or passing the wrong type of value into a function ever again.

### Community & Ecosystem

An active community with an ecosystem consisting of a growing number of community-made [packages](https://www.npmjs.com/org/rbxts). Many popular modules for Roblox already have typings written for roblox-ts.

### Unparalleled Tooling

Allows access to a large number of existing tools made for TypeScript. Use industry standard tools like [ESLint](https://eslint.org/), [VSCode](https://code.visualstudio.com/), [Prettier](https://prettier.io/), and more!


# DataModelPatch

Accurate decompilation of the Roblox Player's distribution of DataModelPatch.rbxm, including the universal `LuaApp`

> [!WARNING]
> This is a WIP decompilation; it is not quite yet ready for re-compilation.

### Goal

The goal of this decompilation is to achieve correct re-compilation of `LuaApp` and similar files. The core scripts are updated to upstream every 1-2 weeks aside from decompiler bug fixes.

### Credits

* [reggie](https://github.com/regginator) - `rbxm2fs` dumper ([`luauc/PatchRoot/`](luauc/PatchRoot) output)
* [TheGreatSageEqualToHeaven](https://github.com/TheGreatSageEqualToHeaven) - Outputting decompiled source code from bytecode output ([`src/PatchRoot/`](src/PatchRoot))
* Of course, the [Oracle](https://discord.gg/prHW9TA4QW) decompiler for decompilation of Luauc bytecode 🙂

## 🤝 Contributing

- Contributions to fix buggy/broken code because of decompiler bugs are accepted.
- Contributions to make `RobloxScript`-exclusive code work on `LocalScript` permissions are also accepted.
- Other contributions can be reviewed to see if they are eligible to merge.

## 🚫 Problems

* Some files may have had unhandled control flow and improperly decompiled, which would result in incorrect table and `goto` output

## 🏛 Licensing

Some of the original source code from DMPatch is/was licensed under the Apache-2.0 license, while some is also proprietary and exclusively owned by Roblox Corporation ("Roblox"). Furthermore, any source code from this decompilation should be considered unlicensed code.

## Decompiler

These files were decompiled by the Oracle decompiler.

Discord Invite: https://discord.gg/prHW9TA4QW

[![Oracle Banner](extra/oracle-banner.png)](https://discord.gg/prHW9TA4QW)


# Synthetic
Synthetic = Fusion created Material

This UI library is powered by a Fusion framework variant, and has the the goal of porting the Google Material Design framework / philosophy to Roblox.

**Disclaimer:** Should not be used in a live game until Roblox releases [Flex functionality](https://devforum.roblox.com/t/new-uilistlayout-flex-features-beta/2694081)

Currently Supports:
- Wrapper / No-Framework
- [Fusion](https://github.com/dphfox/Fusion)
- [Cold-Fusion](https://github.com/nightcycle/cold-fusion)
- [Roact](https://github.com/Roblox/roact/)

https://github.com/nightcycle/synthetic/assets/77173389/42044196-0b4a-4e76-9276-88edaf60ef55

All components can be previewed with the [Hoarcecat](https://github.com/Kampfkarren/hoarcekat) plugin. Anything named "_Config" showcases the different ways a component can be configured. Anything named "_Theme" showcases how the component looks when made with the more portable theme constructors.

# Install
Depending on the workflow you're using, you'll want to install a specific wally package:
- [No Framework](https://wally.run/package/nightcycle/synthetic-wrapper)
- [Roact](https://wally.run/package/nightcycle/synthetic-roact)
- [Fusion](https://wally.run/package/nightcycle/synthetic-fusion)
- [Cold-Fusion](https://wally.run/package/nightcycle/synthetic-cold-fusion)

If you plan to use multiple frameworks, you can install one containing all [here](https://wally.run/package/nightcycle/synthetic-roact). The one containing all the frameworks is what's used in most documentation.

# Goals

It has been iterated heavily upon since it began in 2020, with its mission statement evolving over time.

## Components Should Be Decoupled
Stylesheet solutions are inevitable, however until we have one that everyone can agree upon (so likely never), the components in this framework shouldn't require the developer buy into a whole ecosystem. If you just need a switch, or a slider, or whatever - you should be able to just take it.

That being said, stylesheet solutions exist for a reason. In the case of Synthetic the compromise was to have all root constructors (aka `.new(...)`) use only native Roblox parameters with the exception of a few simple immutable datatypes that can be created with a single function call.

From there, quality-of-life functions that have far fewer parameters would all fully embrace the framework's styling solution. If this solution ever evolves / gets swapped out with a standardized solution, the base components shouldn't need much refactoring.

## It Should Support All Major Workflows
In the past whenever I see a great UI library, I often find myself torn on whether to use it due to it not integrating cleanly into my workflow.

I use a fairly niche variant of [Fusion](https://github.com/dphfox/Fusion), called [Cold-Fusion](https://github.com/nightcycle/cold-fusion). It's an opinionated Fusion wrapper meant to make things readable by moving away from the functional elegance of Fusion, and towards an OOP direction with memory leak protections in mind. This is the language I wrote Synthetic in.

I've written interface `definition.json` files, allowing for the easy parsing of how the constructors are configured. From then I use a [python script](scripts/compile/run.py) to generate the appropriate ports for them.

## Components Should Strive to Scale Dynamically
The Roblox UI native behavior is a bit messy, with many components with overlapping control fighting for the scale / position of elements on screen. When possible, I would prefer to not get involved in that battle.

As a result, the components are designed to allow for rescaling of the root instance as desired without skewing / breaking the component. There are limits - you can't just make an element infinitely small and expect it to remain usable.

## Type Safety is Non-Negotiable
I love fusion, but the table based method all the constructors use is a headache. There are of course workaround solutions such as [Fusion Autocomplete](https://github.com/VirtualButFake/fusion_autocomplete), however this feels like a band-aid solution to the underlying problem.

I've gone and used parameter dense functions for constructors, relying on the parameter name hinting to guide me. In my experience, this reduces debugging turnaround and leads to faster implementation.

# Components
## Buttons
- [Badge](./src/Component/Button/Badge/README.md)

### Common
- [Elevated](./src/Component/Button/ElevatedButton/README.md)
- [Filled](./src/Component/Button/FilledButton/README.md)
- [Outlined](./src/Component/Button/OutlinedButton/README.md)
- [Text](./src/Component/Button/TextButton/README.md)

### Icons
- [Filled Icon](./src/Component/Button/FilledIconButton/README.md)
- [Outlined Icon](./src/Component/Button/OutlinedIconButton/README.md)

### FAB
- [FAB](./src/Component/Button/FAB/README.md)
- [Extended FAB](./src/Component/Button/ExtendedFAB/README.md)

### Chips
- [Assist Chip](./src/Component/Button/Chip/Assist/README.md)
- [Filter Chip](./src/Component/Button/Chip/Filter/README.md)

## Menu
### Row
- [Segmented](./src/Component/Menu/Row/Segmented/README.md)

### Bar
- [Bottom](./src/Component/Menu/Row/Bar/Bottom/README.md)
- [Top Center](./src/Component/Menu/Row/Bar/Top/Center/README.md)
- [Top Large](./src/Component/Menu/Row/Bar/Top/Large/README.md)
- [Top Medium](./src/Component/Menu/Row/Bar/Top/Medium/README.md)
- [Top Small](./src/Component/Menu/Row/Bar/Top/Small/README.md)

## Text Field
- [Filled](./src/Component/TextField/Filled/README.md)
- [Outlined](./src/Component/TextField/Outlined/README.md)

## Progress Indicator
- [Circular](./src/Component/ProgressIndicator/Circular/README.md)

## Snackbar
- [Small](./src/Component/Snackbar/Small/README.md)
- [Large](./src/Component/Snackbar/Large/README.md)

## Search
- [Filled](./src/Component/Search/Filled/README.md)
- [Text](./src/Component/Search/Filled/README.md)

## Misc
- [Dialog](./src/Component/Dialog/README.md)
- [Checkbox](./src/Component/Checkbox/README.md)
- [Radio Button](./src/Component/RadioButton/README.md)
- [Switch](./src/Component/Switch/README.md)
- [Slider](./src/Component/Slider)

# Style
A lot of UI coding is assigning colors, fonts, and sizing - Synthetic attempts to fix that with a new immutable datatype: "Style". It's immutable due to its intention to be swapped out within states - a case where changes are much more easily detected when the datatype is immutable.

## Usage
Construction:
```luau
-- construct style somewhere
local style = Synthetic.Style.new(
    1, -- scale applied to all components
    Enum.Font.SourceSans -- Enum.Font or Typography type,
    if isDarkMode then Enums.SchemeType.Dark else Enums.SchemeType.Light, -- used for theme engine solver
    color -- the singular color the entire theme should be built around
)

Usage:
```luau

-- here's a basic switch
local primarySwitch = Synthetic.Components.Switch.ColdFusion.primary(
    style,
    function(isSelected: boolean)
        print("is selected", isSelected)
    end, -- onSelect
    true, -- initialSelection
)

-- here's a basic switch with all optional parameters
local fullPrimarySwitch = Synthetic.Components.Switch.ColdFusion.primary(
    style,
    function(isSelected: boolean)
        print("is selected", isSelected)
    end, -- onSelect
    true, -- initialSelection,
    true, -- isEnabled
    true, -- includeIconOnSelected
    true -- includeIconOnDeselected
)

-- this constructor can be used without a style state - it's much more verbose / slower to implement
local fullSwitch = Module.ColdFusion.new(
    function(isSelected: boolean?)
        print("is selected", isSelected)
    end, -- onSelect
    true, -- initialSelection
    true, -- isEnabled
    true, -- includeIconOnSelected
    true, -- includeIconOnDeselected
    style:GetColor(Enums.ColorRoleType.SurfaceContainerHighest), -- backgroundColor
    style:GetColor(Enums.ColorRoleType.Outline), -- onBackgroundColor
    style:GetColor(Enums.ColorRoleType.Primary), -- fillColor
    style:GetColor(Enums.ColorRoleType.PrimaryContainer), -- buttonColor
    style:GetColor(Enums.ColorRoleType.OnPrimaryContainer), -- onButtonColor
    style:GetColor(Enums.ColorRoleType.Surface), -- disabledColor
    style:GetColor(Enums.ColorRoleType.OnSurface), -- onDisabledColor
    1, -- elevation
    style.SchemeType, -- schemeType
    style:GetFontData(Enums.FontType.LabelLarge), -- fontData
    style.Scale -- scale
)
A style type is mostly composed of two underlying immutable classes: Theme and Typography.

## Theme
Theme is inspired by the philosophy of the [Material Design color role system](https://m3.material.io/styles/color/roles), and powered by a manual port of their [open source color engine](https://github.com/material-foundation/material-color-utilities).

The theme engine is a bit slow due to all the crazy math (~10 ms construction), so it caches the results from prior constructions. This shouldn't be a problem if you're only constructing a handful of these and passing them around, however if you find yourself creating a new one from dynamic input multiple times a second be warned. From my own experience though, since I added caching I haven't noticed any notable performance issues.

### Construction
Should you want to define the theme manually, you can construct one and pass it as a parameter when creating the Style type.
```luau
local source: Color3 = Color3.new(1,0,0)
local customPalette: {[string]: Color3} = {
    RobloxRed = Color3.fromHex("#E2231A"),
local theme = Synthetic.Theme.new(
    source,
    customPalette -- can be nil
)

### Type Usage
![example color roles](./media/color-roles.png)
The entire goal of the theme type is to replace hours tinkering with colors, and replace them with a few context relevant tokens. The theme type will then take those tokens and return the appropriate color.
```luau
-- using official color role
local role = "Primary"
local scheme = "Light"
local elevation = 0 -- from (0-6) how much color is modified to appear close to the camera.
local color: Color3 = theme:Get(
    role,
    scheme,
    elevation -- optional, will default to 0
)

-- using custom color role
local customRole = "RobloxRed"
local colorType: "Custom" | "CustomContainer" | "OnCustom" | "OnCustomContainer" = "CustomContainer"

local customColor: Color3 = theme:GetCustom(
    customRole,
    colorType,
    scheme
    elevation
)
### Palettes
![example palette](./media/tonal-palette.png)
The theme engine also generates palettes - functions that return a color with a consistent tone, but a brightness level dependent on the provided parameter. If you're interested in going deeper into color customization, you can do so with the palettes.

```luau
local tone: "Primary" | "Secondary" | "Tertiary" | "Neutral" | "NeutralVariant" | "Error" = "Primary"
local isClampEnabled = true -- bright white and pitch black lack a tone, so on default it clamps the values to visually distinct ranges
local brightness = 0.7
local color = style.Palettes[tone](
    brightness,
    isClampEnabled -- optional, defaults to true
)

### Interface Usage
If you just want to quickly solve a color's elevation, you can do that without constructing a theme.
```luau
local sourceColor: Color3 = Color3.new(1,0,0)
local elevation: number = 3
local scheme = "Light"
local elevatedColor = Synthetic.Theme.getElevatedColor(sourceColor, elevation, scheme)

## Typography
The typography half of the style type is fairly simple. It's basically a dictionary of tokenized use cases as the keys, and FontData as the values.

### FontData
FontData is the immutable data structure that all text appearance related state is stored.
```luau
type FontData = {
    Font: Font, -- the font to apply to the text
    Size: number, -- the pixel height of the typical character
    Tracking: number, -- the letter spacing ratio. 1.0 = monospaced
    LineHeight: number, -- the pixel height of the line + the gap separating it from a neighboring line

local fontData = Synthetic.Types.FontData.new(
    Font.fromEnum(Enum.Font.Arial),
    12,
    0.4,
    14
)

This data is much easier to pass around across functions. It's used heavily internally, however you're welcome to use it externally if you like.

### Construction
To create a custom typography off of a Roblox font, you can do so like this:
```luau
local font = Font.fromEnum(Enum.Font.Arial)
local typography = Synthetic.Typography.fromFont(font)

If you want something more custom, you'll have to define all of the font-data manually
```luau
local typography = Synthetic.Typography.new({
    DisplayLarge = Synthetic.Types.FontData.new(
        Font.fromEnum(Enum.Font.Arial),
        12,
        0.4,
        14
    ),
    DisplayMedium = Synthetic.Types.FontData.new(
        Font.fromEnum(Enum.Font.Arial),
        10,
        0.35,
        12
    ),
    -- etc
})

### Usage
The goal of typography is to quickly provide fontData.
```luau
local fontData = typography:Get("DisplayLarge")

### Manual Application
If you aren't sending the fontData as a constructor parameter, you can apply it yourself.
```luau
local fontData = typography:Get("BodySmall")
local scale = 1

local textLabel = Instance.new("TextLabel")
textLabel.TextSize = Synthetic.Typography.getTextSize(fontData.Size, scale),
textLabel.LineHeight = Synthetic.Typography.getGuiLineHeight(fontData.LineHeight, fontData.Size)
textLabel.FontFace = fontData.Font

-- or, if it's just the main text property
Synthetic.Typography.apply(
    textLabel,
    fontData,
    scale -- scale is optional, defaults to 1
)

-- alternatively if you have a Typography type around
typography:Apply(
    textLabel,
    "BodySmall",
    scale -- scale is optional, defaults to 1
)

# Sounds
I've gone and uploaded [all the sounds](https://m2.material.io/design/sound/sound-resources.html) made open source by an older version of the Material Design site. They're available as a static dictionary with keys taken from the original file names. They're used throughout the components, however you're welcome to use them as well!

# Icons
All of the google icons are [imported as spritesheets](https://github.com/nightcycle/material-icons), and are recommended to use with this library. They natively support the ImageData type, and are just handy to have around.

# Utility Components
In making this framework, various patterns became apparent. To save code frequent instance use-cases were organized into internal components. You can access them under `Synthetic.Util`.

They're not really meant for developers, however you might find them handy. Currently these aren't translated into other frameworks, however if this is something people find handy then I'll definitely fast-track it.

## Containers
The container interface helps quickly construct invisible frames that scale with the contents. Very handy when dealing with flex hierarchies.

## ImageLabel
Allows for the quick construction of basic icons and images using the ImageData format

## List
Various list constructors, typically more focused on dealing with flex logic.

## Padding
Quickly add scale considerate UIPadding to instances.

## ScrollingContainer
A set of scrolling container constructors that tries to fit whatever you put into it, disappearing into a container if everything fits at once.

## TextLabel
Quickly add labels to things. Includes built in support for icons at beginning / end of text.

# Transitions
The Material Design philosophies on [motion](https://m3.material.io/styles/motion/overview) is a very interesting read - however it's not one that is currently hooked up to most components. However if you do want their expertly curated theories on motion in your game, the Transitions utility may help you.

# Contributing
If you like this framework, please feel free to contribute!

## Bug Fixes / Optimizations / Refactors
Definitely feel free to make pull requests for bug fixes, for the most part I've got no issue with those so long as they don't change any APIs or expected behaviors.

## New Components
Please make an issue before you start working on anything new. For the most part any [Material Design Components](https://m3.material.io/components) are fair game. Please rely on the specs sections of each component to make sure the port properly translates the majority of functionality.

That being said - I recognize Material Design is tackling a slightly different problem than game development, so some components such as proximity prompts, color pickers, etc just don't exist. In the cases where the component is a clear upgrade, I am more than happy to allow for its addition.

New components can be written in non [Cold Fusion](https://github.com/nightcycle/cold-fusion) frameworks, however if you can stomach it, using Cold Fusion is preferred as we want to avoid adding too many translation layers for performance reasons. If you do a fusion variant language, the public facing parameters should all be a `CanBeState<V>` type.


# luauberries
A collection of libraries for luau, lune, and roblox

> [!NOTE]
> Newsolver versions of libraries with better types can be found under the [`newsolver`](https://github.com/gaymeowing/luauberries/tree/newsolver) branch.

## Notable libraries:
- [character](<https://libs.luau.lol/character>) - a simple utility module for getting more accurate character types with character added and character removing
- [grouper](<https://libs.luau.lol/grouper>) - a module for getting accurate group ranks for players on the server, and detecting rank changes
- [pages util](<https://libs.luau.lol/pages-util>) - roblox pages utility, with an easy to use iterator function for pages instances
- [retryer](<https://libs.luau.lol/retryer>) - a nice easy to use library for retrying functions
- [random](<https://libs.luau.lol/random>) - a pure luau functional equivalent to robloxs random class
- [safe teleport](<https://libs.luau.lol/safe-teleport>) - a typed version of roblox's safe teleport function from the TeleportService docs
- [text chat](<https://libs.luau.lol/text-chat>) - utility library for working with TextChatService and its annoying quirks in behavior


# Iris

Iris is an Immediate mode GUI Library for Roblox, Based on [Dear ImGui](https://github.com/ocornut/imgui). It solves the same problems as Dear ImGui: providing a simple and bloat-free UI system, designed for visualisation and debugging. It is fast, portable, and self-contained (no external dependencies).

#### What is Dear ImGui, and why is it important?
Dear ImGui is best known for allowing developers to create content-creation and visualisation and debugging UI. Using the Dear ImGui paradigm (Immediate Mode), UI design is remarkably easy and simple. Because of this, Dear ImGui has been adopted in almost every major game engine from Unity and Unreal Engine to in-house engines from Rockstar and Ubisoft (and now Roblox!).

Iris favors simplicity and productivity; It is designed to simplify UI, streamlining the process for creating visualisation, debug, and data input tools. To accomplish this, Iris offers a different approach to Roblox UI than existing libraries, at the cost of certain features commonly found in more intricate UI libraries. Iris opts to supercede the Roblox UI API, instead having a streamlined Immediate-Mode library and a set of widgets which developers can use to build the UI and tools they need.

Demo Place: https://rblx.games/7245022703

### Usage

Iris can be installed as a [package](https://wally.run/package/sirmallard/iris) using [Wally](https://wally.run/), as an rbxm file from the [latest GitHub release](https://github.com/SirMallard/Iris/releases/latest) or building from [source](https://github.com/SirMallard/Iris/archive/refs/heads/main.zip). You can import the rbxm into any roblox project, and begin creating UI in any client side script. No external dependences are needed. Iris can be used under any kind of Roblox UI, including PlayerGui, CoreGui, BillboardGui, SurfaceGui, and PluginGui.

Heres a basic Example:

```lua
local StarterPlayerScripts = game.StarterPlayer.StarterPlayerScripts
local Iris = require(StarterPlayerScripts.Client.Iris).Init()

Iris:Connect(function()
    Iris.Window({"My First Window!"})
        Iris.Text({"Hello, World"})
        Iris.Button({"Save"})
        Iris.InputNum({"Input"})
    Iris.End()
end)

And a more complex Example:

```lua
local StarterPlayerScripts = game.StarterPlayer.StarterPlayerScripts
local Iris = require(StarterPlayerScripts.Client.Iris).Init()

Iris:Connect(function()
    -- use a unique window size, rather than default
    local windowSize = Iris.State(Vector2.new(300, 400))

    Iris.Window({"My Second Window"}, {size = windowSize})
        Iris.Text({"The current time is: " .. time()})

        Iris.InputText({"Enter Text"})

        if Iris.Button({"Click me"}).clicked() then
            print("button was clicked")
        end

        Iris.InputColor4()

        Iris.Tree()
            for i = 1,8 do
                Iris.Text({"Text in a loop: " .. i})
            end
        Iris.End()
    Iris.End()
end)

The appearance of Iris is fully customizable, including colors, fonts, transparencies and layout. By default, Iris comes with a dark theme and light theme, as well as 2 layout themes.

```lua
Iris.UpdateGlobalConfig(Iris.TemplateConfig.colorLight)
Iris.UpdateGlobalConfig(Iris.TemplateConfig.sizeClear)

Iris:Connect(Iris.ShowDemoWindow)

Finally, Iris comes with a demo window, `Iris.ShowDemoWindow`. This window demonstrates the functionality of every part of the library, and contains useful utilities, like a style editor and a runtime information window. It is a useful reference for you and other coders can to refer to.

### Learning Iris

The best way to learn Iris is to look at the `Iris.DemoWindow` example file, which showcases all of Iris' features. The code can be found under `lib\demoWindow.lua`.

### How it Works

Iris is an immediate mode UI library, as opposed to retained mode.

In a retained mode model, you might make a button and connect a clicked event, with code that is invoked when the event happens. The button is retained in the DataModel, and to change the text on it you need to store a reference to it.

In an immediate mode model, we call the button function and check if it's been clicked every frame (60 times per second). There's no need for a clicked event or to store a reference to the button.

Therefore, you are not keeping track of the UI instances, you just declare what functionality you would like and Iris manages all instances and cleanup for you.

Check out the Dear ImGuis [About the IMGUI paradigm](https://github.com/ocornut/imgui/wiki/About-the-IMGUI-paradigm) section if you want to understand the core principles behind the IMGUI paradigm.

### Extensions

Iris has an amazing community, who have created some extensions to Iris or adding new features. Check them out!
- [ImPlot](https://devforum.roblox.com/t/4301691): a range of 2D graphing and plotting widgets - [LinusKat/ImPlot](https://github.com/LinusKat/ImPlot)
- [Ceive ImGizmo](https://devforum.roblox.com/t/2470790): a 3D gizmo rendering library - [JakeyWasTaken/CeiveImGizmo](https://github.com/JakeyWasTaken/CeiveImGizmo)

### Credits

Created originally by [Michael_48](https://github.com/Michael-48) and now maintained by [SirMallard](https://github.com/SirMallard).

Many thanks to [JakeyWasTaken](https://github.com/JakeyWasTaken), [OverHash](https://github.com/OverHash) and everyone else who has contributed to Iris in any way.

Inspriation and design: [Omar Cornut](https://www.miracleworld.net/), [Evaera](https://github.com/evaera).

Thanks!
<meta name="google-site-verification" content="Ito4GceH5YJJXReIhx9JMqN0YEDdKePHaylk8H3-9Oo" />


### Fast, portable, self-contained

Iris is a standalone module, with no dependencies, designed to be as lightweight and easy on resources whilst providing a rich experience.

### Favouring simplicity and functionality

Iris favours writing as little code as possible. You describe what you want and Iris organises handles everything else.

### Wide range of widgets

Iris offers a wide assortment of widgets, from handling user interaction to displaying complex information, all with rich customisability.

Iris is an Immediate mode GUI Library for Roblox, Based on [Dear ImGui](https://github.com/ocornut/imgui). It solves the same problems as Dear ImGui: providing a simple and bloat-free UI system, designed for visualisation and debugging. It is fast, portable, and self-contained (no external dependencies).

## What is Dear ImGui, and why is it important?

Dear ImGui is best known for allowing developers to create content-creation and visualisation and debugging UI. Using the Dear ImGui paradigm (Immediate Mode), UI design is remarkably easy and simple. Because of this, Dear ImGui has been adopted in almost every major game engine from Unity and Unreal Engine to in-house engines from Rockstar and Ubisoft (and now Roblox!).

Iris favors simplicity and productivity; It is designed to simplify UI, streamlining the process for creating visualisation, debug, and data input tools. To accomplish this, Iris offers a different approach to Roblox UI than existing libraries, at the cost of certain features commonly found in more intricate UI libraries. Iris opts to supercede the Roblox UI API, instead having a streamlined Immediate-Mode library and a set of widgets which developers can use to build the UI and tools they need.

Demo Place: <https://rblx.games/7245022703>

## Usage

Iris can be installed as a [package](https://wally.run/package/sirmallard/iris) using [Wally](https://wally.run/), as an rbxm file from the [latest GitHub release](https://github.com/SirMallard/Iris/releases/latest) or building from [source](https://github.com/SirMallard/Iris/archive/refs/heads/main.zip). You can import the rbxm into any roblox project, and begin creating UI in any client side script. No external dependences are needed. Iris can be used under any kind of Roblox UI, including PlayerGui, CoreGui, BillboardGui, SurfaceGui, and PluginGui.

## Credits

Created originally by [Michael_48](https://github.com/Michael-48) and now maintained by [SirMallard](https://github.com/SirMallard).

Many thanks to [JakeyWasTaken](https://github.com/JakeyWasTaken), [OverHash](https://github.com/OverHash) and everyone else who has contributed to Iris in any way.

Inspriation and design: [Omar Cornut](https://www.miracleworld.net/), [Evaera](https://github.com/evaera).

Thanks!


[ ocornut ](https://github.com/ocornut) / ** [imgui](https://github.com/ocornut/imgui) ** Public

  * ### Uh oh!

There was an error while loading. [Please reload this page](https://github.com/ocornut/imgui/wiki/About-the-IMGUI-paradigm).

  * [ Notifications ](https://github.com/login?return_to=%2Focornut%2Fimgui) You must be signed in to change notification settings
  * [ Fork 11.6k ](https://github.com/login?return_to=%2Focornut%2Fimgui)
  * [ Star  72.2k ](https://github.com/login?return_to=%2Focornut%2Fimgui)

# About the IMGUI paradigm

Jump to bottom

omar edited this page Oct 3, 2025 · [47 revisions](https://github.com/ocornut/imgui/wiki/About-the-IMGUI-paradigm/_history)

THIS IS WIP/DRAFT / [Discuss this article](https://github.com/ocornut/imgui/issues/3815)

### Why

**This is an attempt at explaining what the IMGUI paradigm stands for, and what it could be**.

Read first: [FAQ entry: What is the difference between Dear ImGui and traditional UI toolkits?](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-what-is-the-difference-between-dear-imgui-and-traditional-ui-toolkits).
Also note References section where several good articles have been written about this topic.

Proponent of the IMGUI paradigm have noticed that it was widely misunderstood, over and over. As of ~~Feb 2021~~ January 2024, even the [IMGUI Wikipedia page](https://en.wikipedia.org/wiki/Immediate_mode_GUI) is completely off the mark and incorrect. (As of August 2024 the page seemingly have been nuked). There are reasons for that:

  * the acronym can be misleading (read below).
  * people didn't do a good enough job explaining or documenting what IMGUI means?
  * they are different interpretation of what IMGUI means?
  * many popular IMGUI implementation have made similar design choices, making it more confusing what is actually the soul and backbone of the IMGUI paradigm vs a set of implementation choices.
  * the naming and success of "Dear ImGui" blurred the line a little bit further (should have used another name).

The acronym is misleading because "immediate-mode" was initially coined as a reference to obsolete graphics API which made it very easy to render contents. Some people still incorrectly assume that IMGUIs are often rendering using those API.

From now on, IMGUI will stand for "Incredibly Magic Graphics User Interface" ;)

The second purpose of this page should be to make it clear that there is a large space to explore in UI programming.

### The Pitch of Dear ImGui

From [README](https://github.com/ocornut/imgui#the-pitch), notice the four first points:

  * "Minimize state synchronization."
  * "Minimize state storage on user side."
  * "Minimize setup and maintenance."
  * "Easy to use to create dynamic UI which are the reflection of a dynamic data set."

While they don't constitute a definition of the IMGUI paradigm, they may give a good intuition of some of the advantages usually associated with the IMGUI paradigm.

**In order to further clarify this intuition**, we'll provide an example.

Typical RMGUI:

    // editor.h
    // [...] somewhere in a class declaration
    MenuItem* m_SaveItem;

    // editor.cpp
    // [...] somewhere in an init/constructor function
    m_SaveItem = Lib_CreateMenuItem(m_ContainerMenu);
    m_SaveItem->OnActivated = &OnSave; // Bind action

    // [...] somewhere in a shutdown/destructor function
    Lib_DestroyItem(m_SaveItem);
    m_SaveItem = NULL;
    // TODO: Ensure initial dirty state is reflected

    // [...] React to item being pressed
    void OnSave()
        m_Document->Save();

    // [...] Sync enable state so item can be greyed
    // IMPORTANT: Don't forget to call otherwise update menu color won't be correct!
    void UpdateSaveEnabledState()
        m_SaveItem->SetEnabled(m_Document != NULL && m_Document->m_IsDirty);
    void SetDocumentDirty(bool dirty)
        if (m_Document)
             m_Document->m_IsDirty = dirty;
        UpdateSaveEnabledState();
    void SetDocument(Document* document)
        m_Document = document;
        UpdateSaveEnabledState();

Typical IMGUI:

    // editor.cpp
    void UpdateUI()
        bool is_save_allowed = (m_Document != NULL && m_Document->m_IsDirty);
        if (Lib_MenuItem("SAVE", is_save_allowed))
            m_Document->Save();

This is a simple and perhaps exaggerated example provided to get a better intuition about the difference of IMGUI vs RMGUI. There are lots of things to say and criticize about this example. It tends to illustrates the shortcoming of RMGUIs more than it illustrates the shortcomings of IMGUIs. But it should illustrate the core benefit that IMGUIs **tends to facilitate data binding, action binding, and creation/destruction of UI components**. It does facilitate those things because it generally doesn't need them.

### History

The acronym IMGUI was coined by Casey Muratori in this video in 2005:
<https://www.youtube.com/watch?v=Z1qyvQsjK5Y> (see also [blog](https://caseymuratori.com/blog_0001))

_"I’ve also seen lots of people getting into arguments about immediate-mode vs. retained-mode GUI APIs. I think this has something to do with how simple the IMGUI concept is, as it leads people to think they understand it, and then they proceed to get into heated arguments as if they actually know what they’re talking about. I rarely see this problem when I’m talking about anything even mildly complicated, like quaternions."_

Casey's work on formulating and popularizing research on this topic has been pivotal and invaluable. His video and the forums that followed helped people gather around the concept and talk about it. Archive.org has a [2007 Mirror of Molly Rocket's IMGUI forums](https://web.archive.org/web/20070824203105/http://www.mollyrocket.com/forums/viewforum.php?f=10&sid=9680eeedbe87034741d936cbfe319f57), including [first notable post by Casey on 2005-07-05](https://web.archive.org/web/20070824213736/http://www.mollyrocket.com/forums/viewtopic.php?t=134&start=0&sid=cb913629aa8310947c0476848a8824dd). Unfortunately the [2013 Mirror of Molly Rocket's IMGUI forums](https://web.archive.org/web/20131221233224/http://mollyrocket.com/forums/viewforum.php?f=10&sid=b7ce0b0de4493f63edd88d13c99501a9) has index but no actual posts.

Sean Barrett (@nothings) also contributed to popularizing the IMGUI paradigm by publishing [an article in the September 2005 issue of Game Developer Magazine](https://archive.org/details/GDM_September_2005) (Page 34) and [accompanying sample code](http://silverspaceship.com/inner/imgui).

The concept has been privately researched before and after. [Thierry Excoffier's Zero Memory Widget](https://web.archive.org/web/20220516003813/https://perso.univ-lyon1.fr/thierry.excoffier/ZMW/) and his [research report](https://web.archive.org/web/20220516004122/https://perso.univ-lyon1.fr/thierry.excoffier/ZMW/rr_2003_03_11.pdf) in 2003 are also very notable although they didn't reach the game development sphere back then.

### Do we need a definition?

_"I kind of wish there was more radical experimentation in this space"_ ([tweet](https://twitter.com/pervognsen/status/1361241939593416705))
_"But, the lib is storing a variable therefore it isn't IMGUI anymore!!!"_ (many people)

Nowadays I am starting to believe that the term has caused more harm than benefits, because it suggests there are two camps "IMGUI" vs "RMGUI". The reality is there is a continuum of possibilities over multiple unrelated axises. Many of them haven't been explored enough, as popular IMGUI libraries have been designed for certain needs and not others. Many of them are at reach as extension of existing popular frameworks. Some are likely to only ever exist as part of yet undeveloped IMGUI frameworks.

The existence of those two terms effectively has hindered both discussions and research. The fact that we are even trying to put an official definition to a label is hindering people's imagination about the many possible areas of researches to be done in UI space.

### Half of a definition

@ocornut's attempt for a definition.

What we care about:

  * IMGUI refers to the API: literally the interface between the application and the UI system.
    * An IMGUI API favors the application code owning its data and being the single source of truth for it.
    * An IMGUI API tries to minimize the application having to retain/manage data related to the UI system.
    * An IMGUI API tries to minimize the UI system having to retain/manage data related to the application.
    * Synchronization between application data and UI data is natural and less error-prone.
  * IMGUI does NOT refer to the implementation. Whatever happens inside the UI system doesn't matter.

This is in comparison with typical RMGUI ("retained-mode UI"):

  * RMGUI APIs often have the application retain artifacts from the UI system (e.g. maintain references to UI objects).
  * RMGUI APIs often require synchronization mechanisms because the UI system retain more application data.

What it doesn't stands for:

  * IMGUI does not mean that the library doesn't retain data.
  * IMGUI does not mean that stuff are drawn immediately or looks a certain way.
  * IMGUI does not mean it needs a continuous loop nor need to refresh continuously.
  * IMGUI does not mean it needs to refresh all-or-nothing.
  * IMGUI does not mean that states are polled.
  * IMGUI does not mean the UI doesn't look "native" or looks a certain way.
  * IMGUI does not mean it cannot animate.
  * IMGUI does not mean it needs a GPU to render.
  * IMGUI does not mean that the library can or cannot support feature x or y.
  * IMGUI does not mean that the library is more or less portable.

TL;DR; It does not matter much. Consider specific properties of each library rather than comparing two umbrella concepts.

### Modeless write-up

March 2022: <https://news.ycombinator.com/item?id=30814797>

_"Immediate mode is a style of API where important state is kept in user code instead of being retained inside the API implementation. For example, an immediate mode GUI checkbox implementation does not store a boolean value determining whether the checkbox is checked. Instead, user code passes that information as a function parameter whenever the UI needs to be drawn. Even the fact that a checkbox exists on screen is not stored in the GUI library. The checkbox is simply drawn when user code requests it each frame."_

_"Counter intuitively this is often less complicated than the traditional "retained mode" style of GUI libraries because there is no duplication of state. That means no setup or teardown of widget object trees, no syncing of state between GUI objects and application code, no hooking up or removing event handlers, no "data binding", etc. The structure and function of your UI is naturally expressed in the code of the functions that draw it, instead of in ephemeral and opaque object trees that only exist in RAM after they're constructed at runtime. You retain control over the event loop and you define the order in which everything happens rather than receiving callbacks in some uncertain order from someone else's event dispatching code."_

_"Crucially, "immediate mode" is a statement about the interface of the library, not the internals. Common objections of the form "immediate mode GUIs can't support X" or "immediate mode GUIs are inefficient because Y" are generally false and based on a misconception that immediate mode GUIs are forbidden from retaining any internal state at all. It is perfectly normal for an immediate mode library to retain various types of internal state for efficiency or other reasons, and this is fine as long as the state stored in user code remains the source of truth. This can even go as far as internally constructing a whole retained widget tree and maintaining it via React-like tree diffing."_

### Vurtun's write-up

[@vurtun](https://github.com/vurtun) said very eloquently around April 2019:

_"I usually don't like to write about immediate mode UI since there are a lot of preconceived notions about them. Addressing all of them is hard since often that is required since they all are thrown at once. For example a single implementation of a concept does not define a concept (dear imgui is a immediate mode UI not all imgui are like dear imgui)._

_Everything that can be done with "retained" gui can by definition be done by an immediate mode gui (I hate this whole divide at this point). Then we have state. For some reason like andrew already said I often see confusion that immediate mode means stateless. Immediate mode has nothing to do with how or if state is stored. Immediate mode in guis doesn't remove having two data representation. One on the calling side and one in the library. Even dear imgui and nuklear both have internal state they keep track of. Rather at its core immediate mode is about how this state is updated. In classical gui the state of the application was synchronized to the gui state by modification. On the other hand immediate mode is closer to functional programming. Instead of mutating state, all previous state is immutable and new state can only be generated by taking the previous state and applying new changes. Both in dear imgui and nuklear there is very little previous state and most is build up every "frame"._

_Next up handling widget events (press,clicked,...). Immediate mode has nothing to do with events vs polling for input changes. The famously convenient if (button(...)). You can even have retained libraries that use polling instead of events._

_Then we have "immediate mode bundles layouting, input and rendering". Once again only dear imgui and nuklear do this. At this point all my imguis have multiple passes. For example if I cache state for layouting I have (layout, input, render). Any change in the input or render pass will will jump back to layouting. If I don't cache state for layouting I still have two passes (input, render) to prevent glitches. To make sure that performance is not a problem I make sure that only those elements that are actually visible are updated, which is important for datastructures (list, trees). Invisible widgets are not only not rendered but also not layouted or have input handling. In a current implementation they are not even iterated over._

_Another argument I've read is that immediate mode cannot be used with OOP. While I try to stay away from that term since at this point it has taken so many meaning that it is basically worthless, what I hear it in context of is having composability for widgets. Once again just because dear imgui and nuklear don't have does not mean it has to be or even should be that way. For example the imgui we have at work supports composability and just like retain mode UIs you can put any widget inside any other. Want a slider inside a tab you can just compose them (not that it makes sense in this case)._

_Getting to game vs. tool ui. Disclaimer: I spend most of my time on tool ui however I played around with game ui or rather the concept behind it in my immediate/retain mode hybrid (<https://gist.github.com/vurtun/c5b0374c27d2f5e9905bfbe7431d9dc0>)._

_Personally for me tool and game ui are two completely different use cases. Interestingly at work we actually have a single immediate mode core that is used for both game as well as tool ui and it still works. However our advantage is that our UI designer can code. Immediate mode biggest advantage is that state mutation is extremely simple and easy. However in games all UI (including stuff like animations) outside datastructures likes list are know at compile time or loading time. So most advantages of immediate mode doesn't hold up (outside mentioned datastructures). Interestingly for datastructures you can even have an immediate mode API inside a retained state UI. So having the best of both worlds by having a hybrid._

_Finally state handling. For games this is easier since most state is known beforehand and can be reserved/preallocated. For tool ui it is a bit more complicated. First of it is possible to have state per widget. That is what we currently do at keen core. The state itself is lifetime tracked and freed if not used anymore. However what is actually possible as well is having a concept of an window/view and managing state outside the library. By that I mean a tabbed window with content. Like for example a log view or scene view storing all needed state for the UI and the actually data needed (log entries for the log view). Instead of trying to do state handling on the widget level it makes a lot more sense to have state management inside the view itself, since unlike the actually widgets the view itself has an easy to track lifetime. Just to clarify the view in the library API would just an handle while the actual view implementation would store the state._

_A lot in ui depends on the problem on hand so I feel there is no silver bullet. But what is actually great about UI is that it is possible to write a version fitting the problem. I hope if anything is taken from this rant is that "imgui" currently entangles a lot of concepts that however don't define it. So everytime it does not work out immediate mode as a grand concept itself is tossed aside instead of reevaluating the parts that did not work out."_

### References

  * [FAQ entry: What is the difference between Dear ImGui and traditional UI toolkits?](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-what-is-the-difference-between-dear-imgui-and-traditional-ui-toolkits).
  * [Johannes 'johno' Norneby's article](http://www.johno.se/book/imgui.html), 2007.
  * [A presentation by Rickard Gustafsson and Johannes Algelind](http://www.cse.chalmers.se/edu/year/2011/course/TDA361/Advanced%20Computer%20Graphics/IMGUI.pdf), 2011.
  * [Jari Komppa's tutorial on building an IMGUI library](http://iki.fi/sol/imgui/), @jarikomppa, 2006.
  * [Casey Muratori's original video that popularized the concept](https://mollyrocket.com/861), 2005.
    * [First notable post by Casey on 2005-07-05](https://web.archive.org/web/20070824213736/http://www.mollyrocket.com/forums/viewtopic.php?t=134&start=0&sid=cb913629aa8310947c0476848a8824dd).
    * [2007 Mirror of Molly Rocket's IMGUI forums](https://web.archive.org/web/20070824203105/http://www.mollyrocket.com/forums/viewforum.php?f=10&sid=9680eeedbe87034741d936cbfe319f57) (with posts).
    * [2013 Mirror of Molly Rocket's IMGUI forums](https://web.archive.org/web/20131221233224/http://mollyrocket.com/forums/viewforum.php?f=10&sid=b7ce0b0de4493f63edd88d13c99501a9) (index only, missing posts).
  * [Sean Barrett's article in Game Developer Magazine](https://archive.org/details/GDM_September_2005) (Page 34), September 2005.
  * [Sean Barrett's IMGUI page and sample code](http://silverspaceship.com/inner/imgui), @nothings, September 2005.
  * [Nicolas Guillemot's CppCon'16 flash-talk about Dear ImGui](https://www.youtube.com/watch?v=LSRJ1jZq90k), 2016.
  * [Thierry Excoffier's ZMV (Zero Memory Widget)](http://perso.univ-lyon1.fr/thierry.excoffier/ZMW/), 2004.
  * [Unity's IMGUI](https://docs.unity3d.com/Manual/GUIScriptingGuide.html)

### Clone this wiki locally


[ ocornut ](https://github.com/ocornut) / ** [imgui](https://github.com/ocornut/imgui) ** Public

  * ### Uh oh!

There was an error while loading. [Please reload this page](https://github.com/ocornut/imgui/wiki/Getting-Started).

  * [ Notifications ](https://github.com/login?return_to=%2Focornut%2Fimgui) You must be signed in to change notification settings
  * [ Fork 11.6k ](https://github.com/login?return_to=%2Focornut%2Fimgui)
  * [ Star  72.2k ](https://github.com/login?return_to=%2Focornut%2Fimgui)

# Getting Started

Jump to bottom

omar edited this page Mar 2, 2026 · [52 revisions](https://github.com/ocornut/imgui/wiki/Getting-Started/_history)

_(had to turn off wiki editing, see[Home](https://github.com/ocornut/imgui/wiki/Home) for details. you may post meaningful wiki diff in issues/pr)_

## Index

  * Feedback Wanted!
  * Preamble
  * What is a Game Loop?
  * Checking Out
  * Compiling/Linking
  * Setting up Dear ImGui & Backends
  * Example: If you are using Raw Win32 API + DirectX11
  * Example: If you are using Raw Win32 API + DirectX12
  * Example: If you are using GLFW + OpenGL/WebGL
  * Example: If you are using GLFW + Metal (on Apple devices)
  * Example: If you are using SDL2/SDL3 + OpenGL/WebGL
  * Example: If you are using SDL2/SDL3 + Vulkan
  * Example: If you are using SDL3 + SDL_GPU
  * Using another combination of backends?
  * Additional code to enable Docking
  * Additional code to enable Multi-viewports
  * Once you are setup...

## Feedback Wanted!

Important

After you are done setting up Dear ImGui in your application/project, please share _any feedback_ you may have in [#9040](https://github.com/ocornut/imgui/discussions/9040).
Even if you made mistakes or created yourself a problem of your own, or misread a documentation: your feedback helps tweaking documentation for future users.

## Preamble

**This is a Tutorial for getting Dear ImGui integrated in your C++ application using our standard backends.**
This is _not_ a Tutorial for _using_ the Dear ImGui API. For that, refer to the Once you are setup... section of this page.
This is _not_ a Tutorial for _implementing your own backend_. For that, refer to the [docs/BACKENDS.md](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md) file.

**If you are using a third-party backend (e.g. Godot, raylib, Sokol, Unity, Unreal Engine, etc. see [List of third-party backends](https://github.com/ocornut/imgui/wiki/Bindings#frameworkengine-backends)):** instructions will differ, but well designed backends should either (1) mimick the naming convention of our backends either (2) provide examples or instructions.

Also refer to our [FAQ](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md) and others [Wiki](https://github.com/ocornut/imgui/wiki) pages.

Before anything, **Build and run one of the examples application, play around with it.**
With Visual Studio, open `examples/imgui_examples.sln`. XCode projects and Makefiles are also often provided.
You may not have all of the corresponding SDKs installed as we support many systems, but you should get some working out of the box.

The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications demonstrating Dear ImGui with a variety of common windowing and graphics API. They are designed to be as straightforward possible. However in most cases, a majority of the example-specific code is related to setting up the windowing and graphics API (aka setting up a basic application) rather than setting up Dear ImGui itself.

If you have issues integrating Dear ImGui in your app, most of the time to easiest thing to do it refer to those [examples](https://github.com/ocornut/imgui/tree/master/examples).

For various reasons, our examples are very raw: we don't load fancy fonts and generally the Demo window cannot read anything from the filesystem, so our examples cannot showcase the use of e.g. texture.

## What is a Game Loop?

If you are already working in games you may not need to read this.

Dear ImGui comes from a game development background, where applications are expected to update continuously at interactive framerates (e.g. 60 FPS) and where it is expected that an underlying graphics-heavy application is running and showing behind Dear ImGui. This is how our examples are generally structured. While it is technically possible to lift some of those assumptions when using Dear ImGui (e.g. going idle, using variable frame rates, having no "main viewport"), those uses cases are technically possible but currently not well supported by default, requires a more intimate understanding of both the system and dear imgui, and are outside the scope of this article.

A typical game-like application taking advantage of GPU rendering would run in a loop:

    while (application_not_closed)
       // Poll events
       // Update application/game state
       // Render contents into a framebuffer
       // Swap/Present framebuffer to the screen
       // Wait some time (e.g. 1/60 of a second)

In the case of your example application, we explicitly attempt to synchronize to screen refresh on swap/present, making the application refresh at the natural screen refresh rate. A full-fledged application may use different timing mechanism to throttle framerate, but this is outside of our scope.

## Checking Out

It is preferable that your build yourself from sources.

  * (1) Decide which branch to pull:
    * `master` or `docking`, the later adds support for [Docking](https://github.com/ocornut/imgui/wiki/Docking) and [Multi-viewports](https://github.com/ocornut/imgui/wiki/Multi-Viewports).
    * Both branches are maintained, you can easily switch anytime.
  * (2) Pull the repository into a sub-module of your project, or simply download/copy the repository in yours and commit it.

## Compiling/Linking

Dear ImGui does not mandate a particular build system. It is designed to be added to your existing application with an existing build system.

  * (1) Add `imgui/` and `imgui/backends/` folders to include paths.
    * e.g. `-Irelative/path/to/imgui` with Clang/GCC.
  * (2) Add files to your project or build system of your choice, so they get compiled and linked into your app.
    * Add core: all source files from the root folder: `imgui/*.cpp` and `imgui/*.h`.
    * Add backends: add `imgui/backends/imgui_impl_xxxx.cpp`/`.h` files corresponding to the technology you use from the `imgui/backends/` folder (e.g. if your app uses SDL2 + DirectX11, add `imgui_impl_sdl2.cpp`/`.h` and `imgui_impl_dx11.cpp`/`.h` etc.). If your engine uses multiple APIs you may include multiple backends.
    * Misc: Debugger users: See [misc/debuggers](https://github.com/ocornut/imgui/tree/master/misc/debuggers) to improve your debugging experience. Visual Studio users can add `imgui.natvis` and `imgui.natstepfilter` to their project.
    * Misc: std::string users: Add `misc/cpp/imgui_stdlib.*` to easily use `InputText()` with `std::string` type.

It is recommended that you follow those steps and not attempt to build Dear ImGui as a static or shared library! It's perfectly possible to do, but if you are following a "Getting Started" guide the last thing you want to do is to create yourself more problems. Note that Dear ImGui is both small and easy to build, so adding its files directly to your project should be fine. Note that Dear ImGui is a very call-heavy API, so building as a shared library is not ideal because of increased function calling overhead.

**If your application already uses the API you pulled the backends for, things should compile and link already.**

Most users with linking problems are in fact having problems because of the underlying windowing or graphics tech they use. e.g. If you use DirectX11 you need to link with d3d11.lib, if you use SDL2 you need to obtain the library (from their website or vcpkg) and link with SDL2.lib+SDL2main.lib etc. If you already have an app running then by definition you shouldn't have a problem including corresponding header files and linking libraries.

If you are creating a new application from scratch: while it is generally outside of scope of Dear ImGui to document how to use every windowing/graphics stacks, you can refer to our [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder to see which libs/settings we are using. Some people just copy our example to start a new testbed app. For the convenience of providing easy-to-compile examples, for years our repository has included an (old) precompiled version of GLFW 3.2 for Windows.

## Setting up Dear ImGui & Backends

This list may be a little abstract. You can may skip to a dedicated "Example: If you are using XXX" section for concrete code.

  * (1) Include header files for main lib (`#include "imgui.h"`) + backends (e.g. `#include "imgui_impl_win32.h"`, `#include "imgui_impl_dx11.h"`).
  * (2) Create Dear ImGui context with `ImGui::CreateContext()`.
  * (3) Optionally set configuration flags, load fonts, setup style.
  * (4) Initialize Platform and Rendering backends (e.g. `ImGui_ImplWin32_Init()` \+ `ImGui_ImplDX11_Init()`).
  * (5) Start of main loop: poll events + call backends' `ImGui_ImplXXX_NewFrame()` functions + call `ImGui::NewFrame()`.
  * (6) End of main loop: call `ImGui::Render()` \+ call Render function of Rendering backend (e.g. `ImGui_ImplDX11_Render()`).
  * (7) Most backends require some extra steps to hook or forward events. (e.g. calling `ImGui_ImplWin32_WndProcHandler`)
  * (8) Call backend shutdown functions and destroy Dear ImGui context with `ImGui::DestroyContext()`.
  * (9) In your application's input logic: you can poll `ImGui::GetIO().WantCaptureMouse`/`WantCaptureKeyboard` to check if Dear ImGui wants to obstruct mouse/keyboard inputs from underlying apps. e.g. when hovering a window `WantCaptureMouse` will be set to true, one possible strategy would be to stop passing mouse events to your main application.

## Example: If you are using Raw Win32 API + DirectX11

Full standalone example: [example_win32_directx11/main.cpp](https://github.com/ocornut/imgui/blob/master/examples/example_win32_directx11/main.cpp)

Add to Includes:

    #include "imgui.h"
    #include "imgui_impl_win32.h"
    #include "imgui_impl_dx11.h"

Add to Initialization:

    // Setup Dear ImGui context
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO();
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls
    io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;         // IF using Docking Branch

    // Setup Platform/Renderer backends
    ImGui_ImplWin32_Init(YOUR_HWND);
    ImGui_ImplDX11_Init(YOUR_D3D_DEVICE, YOUR_D3D_DEVICE_CONTEXT);

Add to start of main loop:

    // (Your code process and dispatch Win32 messages)
    // Start the Dear ImGui frame
    ImGui_ImplDX11_NewFrame();
    ImGui_ImplWin32_NewFrame();
    ImGui::NewFrame();
    ImGui::ShowDemoWindow(); // Show demo window! :)

Add to end of main loop:

    // Rendering
    // (Your code clears your framebuffer, renders your other stuff etc.)
    ImGui::Render();
    ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
    // (Your code calls swapchain's Present() function)

Add to your WndProc handler:

    extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
    if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
        return true;
    // (Your code process Win32 messages)
    // (You should discard mouse/keyboard messages in your game/engine when io.WantCaptureMouse/io.WantCaptureKeyboard are set.)

Add to Shutdown:

    ImGui_ImplDX11_Shutdown();
    ImGui_ImplWin32_Shutdown();
    ImGui::DestroyContext();

That should be all!

## Example: If you are using Raw Win32 API + DirectX12

Full standalone example: [example_win32_directx12/main.cpp](https://github.com/ocornut/imgui/blob/master/examples/example_win32_directx12/main.cpp)

Add to Includes:

    #include "imgui.h"
    #include "imgui_impl_win32.h"
    #include "imgui_impl_dx12.h"

Add to Initialization:

    // Setup Dear ImGui context
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO();
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls
    io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;         // IF using Docking Branch

    // Setup Platform/Renderer backends
    ImGui_ImplDX12_InitInfo init_info = {};
    init_info.Device = YOUR_D3D_DEVICE;
    init_info.CommandQueue = YOUR_COMMAND_QUEUE;
    init_info.NumFramesInFlight = NUM_FRAMES_IN_FLIGHT;
    init_info.RTVFormat = DXGI_FORMAT_R8G8B8A8_UNORM; // Or your render target format.

    // Allocating SRV descriptors (for textures) is up to the application, so we provide callbacks.
    // The example_win32_directx12/main.cpp application include a simple free-list based allocator.
    init_info.SrvDescriptorHeap = YOUR_SRV_DESC_HEAP;
    init_info.SrvDescriptorAllocFn = [](ImGui_ImplDX12_InitInfo*, D3D12_CPU_DESCRIPTOR_HANDLE* out_cpu_handle, D3D12_GPU_DESCRIPTOR_HANDLE* out_gpu_handle) { return YOUR_ALLOCATOR_FUNCTION_FOR_SRV_DESCRIPTORS(...); };
    init_info.SrvDescriptorFreeFn = [](ImGui_ImplDX12_InitInfo*, D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle, D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle)            { return YOUR_FREE_FUNCTION_FOR_SRV_DESCRIPTORS(...); };

    // (before 1.91.6 the DirectX12 backend required a single SRV descriptor passed)
    // (there is a legacy version of ImGui_ImplDX12_Init() that supports those, but a future version of Dear ImGuii will requires more descriptors to be allocated)

Add to start of main loop:

    // (Your code process and dispatch Win32 messages)
    // Start the Dear ImGui frame
    ImGui_ImplDX12_NewFrame();
    ImGui_ImplWin32_NewFrame();
    ImGui::NewFrame();
    ImGui::ShowDemoWindow(); // Show demo window! :)

Add to end of main loop:

    // Rendering
    // (Your code clears your framebuffer, renders your other stuff etc.)
    ImGui::Render();
    ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), YOUR_DX12_COMMAND_LIST);
    // (Your code calls ExecuteCommandLists, swapchain's Present(), etc.)

Add to your WndProc handler:

    extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
    if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
        return true;
    (Your code process Windows messages.)
    // (You should discard mouse/keyboard messages in your game/engine when io.WantCaptureMouse/io.WantCaptureKeyboard are set.)

Add to Shutdown:

    ImGui_ImplDX12_Shutdown();
    ImGui_ImplWin32_Shutdown();
    ImGui::DestroyContext();

That should be all!

## Example: If you are using GLFW + OpenGL/WebGL

Full standalone example: [example_glfw_opengl3/main.cpp](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_opengl3/main.cpp)

Add to Includes:

    #include "imgui.h"
    #include "imgui_impl_glfw.h"
    #include "imgui_impl_opengl3.h"

Add to Initialization:

    // Setup Dear ImGui context
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO();
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls
    io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;         // IF using Docking Branch

    // Setup Platform/Renderer backends
    ImGui_ImplGlfw_InitForOpenGL(YOUR_WINDOW, true);          // Second param install_callback=true will install GLFW callbacks and chain to existing ones.
    ImGui_ImplOpenGL3_Init();

Add to start of main loop:

    // (Your code calls glfwPollEvents())
    // ...
    // Start the Dear ImGui frame
    ImGui_ImplOpenGL3_NewFrame();
    ImGui_ImplGlfw_NewFrame();
    ImGui::NewFrame();
    ImGui::ShowDemoWindow(); // Show demo window! :)

Add to end of main loop:

    // Rendering
    // (Your code clears your framebuffer, renders your other stuff etc.)
    ImGui::Render();
    ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
    // (Your code calls glfwSwapBuffers() etc.)

Add to Shutdown:

    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplGlfw_Shutdown();
    ImGui::DestroyContext();

Event handling:

  * You should discard mouse/keyboard messages in your game/engine when io.WantCaptureMouse/io.WantCaptureKeyboard are set.

That should be all!

## Example: If you are using GLFW + Metal (on Apple devices)

Full standalone example: [example_glfw_metal/main.mm](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_metal/main.mm)

    brew install glfw

Add to Includes:

    #include "imgui.h"
    #include "imgui_impl_glfw.h"
    #include "imgui_impl_metal.h"

Add to Initialization:

    // Setup Dear ImGui context
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO();
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls
    io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;         // IF using Docking Branch

    // Setup Platform/Renderer backends
    ImGui_ImplGlfw_InitForOpenGL(YOUR_WINDOW, true);          // Second param install_callback=true will install GLFW callbacks and chain to existing ones.
    ImGui_ImplMetal_Init(YOUR_METAL_DEVICE);

Add to start of main loop:

    // (Your code calls glfwPollEvents())
    // ...
    // Start the Dear ImGui frame
    ImGui_ImplMetal_NewFrame(YOUR_RENDER_PASS_DESCRIPTOR);
    ImGui_ImplGlfw_NewFrame();
    ImGui::NewFrame();
    ImGui::ShowDemoWindow(); // Show demo window! :)

Add to end of main loop:

    // Rendering
    // (Your code clears your framebuffer, renders your other stuff etc.)
    ImGui::Render();
    ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), YOUR_METAL_COMMAND_BUFFER, YOUR_METAL_RENDER_ENCODER);
    // (Your code calls endEncoding, presentDrawable, commit etc.)

Add to Shutdown:

    ImGui_ImplMetal_Shutdown();
    ImGui_ImplGlfw_Shutdown();
    ImGui::DestroyContext();

Event handling:

  * You should discard mouse/keyboard messages in your game/engine when io.WantCaptureMouse/io.WantCaptureKeyboard are set.

That should be all!

## Example: If you are using SDL2/SDL3 + OpenGL/WebGL

Full standalone example for SDL2: [example_sdl2_opengl3/main.cpp](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_opengl3/main.cpp)
Full standalone example for SDL3: [example_sdl3_opengl3/main.cpp](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_opengl3/main.cpp)

All instructions below are for SDL2. Simply replace "SDL2" with "SDL3" to get SDL3 equivalent.

Add to Includes:

    #include "imgui.h"
    #include "imgui_impl_sdl2.h"
    #include "imgui_impl_opengl3.h"

Add to Initialization:

    // Setup Dear ImGui context
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO();
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls
    io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;         // IF using Docking Branch

    // Setup Platform/Renderer backends
    ImGui_ImplSDL2_InitForOpenGL(window, YOUR_SDL_GL_CONTEXT);
    ImGui_ImplOpenGL3_Init();

Add to start of main loop:

    // (Where your code calls SDL_PollEvent())
    ImGui_ImplSDL2_ProcessEvent(&event); // Forward your event to backend
    // (You should discard mouse/keyboard messages in your game/engine when io.WantCaptureMouse/io.WantCaptureKeyboard are set.)

    // (After event loop)
    // Start the Dear ImGui frame
    ImGui_ImplOpenGL3_NewFrame();
    ImGui_ImplSDL2_NewFrame();
    ImGui::NewFrame();
    ImGui::ShowDemoWindow(); // Show demo window! :)

Add to end of main loop:

    // Rendering
    // (Your code clears your framebuffer, renders your other stuff etc.)
    ImGui::Render();
    ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
    // (Your code calls SDL_GL_SwapWindow() etc.)

Add to Shutdown:

    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplSDL2_Shutdown();
    ImGui::DestroyContext();

That should be all!

## Example: If you are using SDL2/SDL3 + Vulkan

Full standalone example for SDL2+Vulkan: [example_sdl2_vulkan/main.cpp](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_vulkan/main.cpp)
Full standalone example for SDL3+Vulkan: [example_sdl3_vulkan/main.cpp](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_vulkan/main.cpp)
Full standalone example for GLFW+Vulkan: [example_glfw_vulkan/main.cpp](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_vulkan/main.cpp)

Unfortunately this is the most complex one and may not work with all app setups. We are always working on making imgui_impl_vulkan.cpp more compatible with existing engines, so please don't hesitate to post feedback.

You must provide a Descriptor Pool with room for at least `IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE` combined image sampler (`VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER`). You may also set the ImGui_ImplVulkan_InitInfo::DescriptorPoolSize field to that or a larger value for the backend to automatically create one for you, which won't be shared with your app.

All instructions below are for SDL3. Simply replace "SDL2" with "SDL3" to get SDL3 equivalent.

Add to Includes:

    #include "imgui.h"
    #include "imgui_impl_sdl2.h"
    #include "imgui_impl_vulkan.h"

    static void check_vk_result(VkResult err)
        if (err == 0)
            return;
        fprintf(stderr, "[vulkan] Error: VkResult = %d\n", err);
        if (err < 0)
            abort();

Add to Initialization:

    // Setup Dear ImGui context
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO();
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls
    io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;         // IF using Docking Branch

    // Setup Platform/Renderer backends
    ImGui_ImplSDL2_InitForVulkan(YOUR_SDL_WINDOW);
    ImGui_ImplVulkan_InitInfo init_info = {};
    init_info.Instance = YOUR_INSTANCE;
    init_info.PhysicalDevice = YOUR_PHYSICAL_DEVICE;
    init_info.Device = YOUR_DEVICE;
    init_info.QueueFamily = YOUR_QUEUE_FAMILY;
    init_info.Queue = YOUR_QUEUE;
    init_info.PipelineCache = YOUR_PIPELINE_CACHE;
    init_info.DescriptorPool = YOUR_DESCRIPTOR_POOL;
    init_info.MinImageCount = 2;
    init_info.ImageCount = 2;
    init_info.Allocator = YOUR_ALLOCATOR;
    init_info.PipelineInfoMain.RenderPass = wd->RenderPass;
    init_info.PipelineInfoMain.Subpass = 0;
    init_info.PipelineInfoMain.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
    init_info.CheckVkResultFn = check_vk_result;
    ImGui_ImplVulkan_Init(&init_info);

Add to start of main loop:

    // (Where your code calls SDL_PollEvent())
    ImGui_ImplSDL2_ProcessEvent(&event); // Forward your event to backend
    // (You should discard mouse/keyboard messages in your game/engine when io.WantCaptureMouse/io.WantCaptureKeyboard are set.)

    // (After event loop)
    // Start the Dear ImGui frame
    ImGui_ImplVulkan_NewFrame();
    ImGui_ImplSDL2_NewFrame();
    ImGui::NewFrame();
    ImGui::ShowDemoWindow(); // Show demo window! :)

Add to end of main loop:

    // Rendering
    // (Your code clears your framebuffer, renders your other stuff etc.)
    ImGui::Render();
    ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), YOUR_COMMAND_BUFFER);
    // (Your code calls vkCmdEndRenderPass, vkQueueSubmit, vkQueuePresentKHR etc.)

Add to Shutdown:

    ImGui_ImplVulkan_Shutdown();
    ImGui_ImplSDL2_Shutdown();
    ImGui::DestroyContext();

That should be all!

## Example: If you are using SDL3 + SDL_GPU

Full standalone example [example_sdl3_sdlgpu3/main.cpp](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_sdlgpu3/main.cpp)

Add to Includes:

    #include "imgui.h"
    #include "imgui_impl_sdl3.h"
    #include "imgui_impl_sdlgpu3.h"

Add to Initialization:

    // Setup Dear ImGui context
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO();
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls
    io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;         // IF using Docking Branch

    // Setup Platform/Renderer backends
    ImGui_ImplSDL3_InitForSDLGPU(window);
    ImGui_ImplSDLGPU3_InitInfo init_info = {};
    init_info.Device = gpu_device;
    init_info.ColorTargetFormat = SDL_GetGPUSwapchainTextureFormat(gpu_device, window);
    init_info.MSAASamples = SDL_GPU_SAMPLECOUNT_1;                      // Only used in multi-viewports mode.
    init_info.SwapchainComposition = SDL_GPU_SWAPCHAINCOMPOSITION_SDR;  // Only used in multi-viewports mode.
    init_info.PresentMode = SDL_GPU_PRESENTMODE_VSYNC;
    ImGui_ImplSDLGPU3_Init(&init_info);

Add to start of main loop:

    // (Where your code calls SDL_PollEvent())
    ImGui_ImplSDL3_ProcessEvent(&event); // Forward your event to backend
    // (You should discard mouse/keyboard messages in your game/engine when io.WantCaptureMouse/io.WantCaptureKeyboard are set.)

    // (After event loop)
    // Start the Dear ImGui frame
    ImGui_ImplSDLGPU3_NewFrame();
    ImGui_ImplSDL3_NewFrame();
    ImGui::NewFrame();
    ImGui::ShowDemoWindow(); // Show demo window! :)

Add to end of main loop:

    // Rendering
    // (Your code clears your framebuffer, renders your other stuff etc.)
    ImGui::Render();

    SDL_GPUCommandBuffer* command_buffer = SDL_AcquireGPUCommandBuffer(gpu_device); // Acquire a GPU command buffer
    SDL_WaitAndAcquireGPUSwapchainTexture(command_buffer, window, &swapchain_texture, nullptr, nullptr); // Acquire a swapchain texture

    ImGui_ImplSDLGPU3_PrepareDrawData(draw_data, command_buffer);

    // Setup and start a render pass
    SDL_GPUColorTargetInfo target_info = {};
    target_info.texture = swapchain_texture;
    target_info.clear_color = SDL_FColor { clear_color.x, clear_color.y, clear_color.z, clear_color.w };
    target_info.load_op = SDL_GPU_LOADOP_CLEAR;
    target_info.store_op = SDL_GPU_STOREOP_STORE;
    target_info.mip_level = 0;
    target_info.layer_or_depth_plane = 0;
    target_info.cycle = false;
    SDL_GPURenderPass* render_pass = SDL_BeginGPURenderPass(command_buffer, &target_info, 1, nullptr);

    // Render ImGui
    ImGui_ImplSDLGPU3_RenderDrawData(draw_data, command_buffer, render_pass);

    SDL_EndGPURenderPass(render_pass);

Add to Shutdown:

    ImGui_ImplSDL3_Shutdown();
    ImGui_ImplSDLGPU3_Shutdown();
    ImGui::DestroyContext();

That should be all!

## Using another combination of backends?

The various examples above should reflect integration with a majority of backends, so you can follow the same logic. Some backends require more information from you (e.g. in particular Vulkan and DirectX12 rendering backends). When in doubt, refer to the corresponding [examples](https://github.com/ocornut/imgui/tree/master/examples) application.

## Additional code to enable Docking

To use the [Docking](https://github.com/ocornut/imgui/wiki/Docking) feature, pull the `docking` branch and enable the configuration flag:

    io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;

## Additional code to enable Multi-viewports

To use the [Multi-viewports](https://github.com/ocornut/imgui/wiki/Multi-Viewports) feature, pull the `docking` branch and enable the configuration flag:

    io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;

At the end of your render loop, generally after rendering your main viewport but before presenting/swapping it:

    if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
        // Update and Render additional Platform Windows
        ImGui::UpdatePlatformWindows();
        ImGui::RenderPlatformWindowsDefault();

        // TODO for OpenGL: restore current GL context.

Note that there may be additional calls required surrounding this depending on the backend you are using (**OpenGL in particular needs backup/restore of current GL context**). Check the [example project](https://github.com/ocornut/imgui/tree/docking/examples) appropriate to your setup for details.

## Once you are setup...

  * Run `ImGui::ShowDemoWindow()`. Browse imgui_demo.cpp to find how things are done.
  * You may also refer to @pthom's [imgui_explorer](https://pthom.github.io/imgui_explorer) which matches the output of the demo window with corresponding source code.
  * Use [Item Picker](https://github.com/ocornut/imgui/wiki/Debug-Tools) to easily debug break into the code of a given item.
  * Read [Wiki](https://github.com/ocornut/imgui/wiki) for more.
  * You may edit `imconfig.h` or use `#define IMGUI_USER_CONFIG \"my_imconfig.h\"` to use compile-time configuration features.

### Clone this wiki locally