Iris - Immediate Mode UI library, based on Dear ImGui

Try the demo: Iris - Demonstration - Roblox

View on GitHub: GitHub - SirMallard/Iris: Iris is an Immediate-Mode GUI Library for Roblox for creating debug and visualisation UI and tools and based on Dear ImGui.

Iris

Iris is an Immediate mode GUI Library for Roblox, Based on Dear 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: Iris Demonstration - Roblox

Usage

Iris can be installed as a package using Wally, as an rbxm file from the latest GitHub release or building from source. 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:

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:

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.

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 section if you want to understand the core principles behind the IMGUI paradigm.

Credits

Created originally by Michael_48 and now maintained by SirMallard.

Many thanks to JakeyWasTaken, OverHash and everyone else who has contributed to Iris in any way.

Inspriation and design: Omar Cornut, Evaera.

Thanks!

515 Likes

I like the example uis, very similar-ish.

10 Likes

Thanks! The widgets are made to look and feel as similar to Dear ImGui’s as possible.

4 Likes

can you open source the game? it would be great if you did!

2 Likes

Absolutley! The place’s source should now be available. I also added the place file (.rbxl) in the releases page

2 Likes

Docs for the library are now available at: https://SirMallard.github.io/Iris

5 Likes

Nice module! Albeit there’s one big issue: Game UI can and will appear on top of the windows:
image

1 Like

Thanks for letting me know! I just commit the fix for this in Iris v1.0.1 -
config.DisplayOrderOffset allows the user to customize the DisplayOrder of Iris Windows, relative to the rest of the UI. The default value is now 127, and can be increased or lowered if necessary.

What I was originally going to post

This is an amazing UI library, however, I receive a lot of type warnings in my scripts:

image

I’m not sure if there’s something I may have overlooked? (This doesn’t affect the actual functionality of the library)


After looking around in the source code for a few minutes, I noticed that the parameters use (typename | nil) as opposed to (typename?). The former makes it manual that the developer needs to inserts nil into the argument list in order to satisfy the type requirement but the latter doesn’t require the developer to manually insert nil.

TL;DR: (typename | nil) ≠ typename?

I fixed one of the type warnings in the script by changing the parameter list to:

Which silenced the type warning for Iris.Init:

image


Other than that, once again, this is a fantastic resource!

2 Likes

I wasn’t able to replicate the type warnings for Iris.Window or Iris.Text but nonetheless the typings should be fixed for v1.0.2. Thanks for letting me know!

3 Likes

I looked through the examples again and the other type warnings were my own fault as I was calling Window and Text from the ModuleScript itself instead of from the returned value of the Init function

4 Likes

I’m definitely planning on using this but how would I go about adding my own widgets such as a color picker? Although it seems pretty easy to use, it would be very helpful to have some docs to refer to. Also what would be the correct way to scale a window?

1 Like

Creating custom widgets is a pretty elaborate process, so right now i am working on a docs page specifically on that topic.
As for scaling a window, you can use the size field of the Window’s State.

local myWindowSize = Iris.State(Vector2.new(300, 400)) -- can be any value
Iris.Window({"Window"}, {size = myWindowSize})
Iris.End()

to change this value from your code, you can use the :set() method of State

if Iris.Button({"Change Window Size to 250, 250"}).clicked then
    myWindowSize:set(Vector2.new(250, 250))
end

to disable users of the window from resizing the window you can enable the NoResize field of Window’s Arguments

Iris.Window({"Window", [Iris.Args.Window.NoResize] = true})
Iris.End()
3 Likes

Loving this resource so far, my only complaint is when you respawn your ui disappears permanently. Is there a way to toggle that or is it an unintended feature?

3 Likes

Great job, looks clean and accurate. A nice addition would be graphs.

3 Likes

I suggest turning off the screen gui’s ResetOnSpawn property

2 Likes

Great library!

For anyone that does not certainly like how this library formats, I can show you a way to format your iris code:

Iris.Window{"First Window"} do
	Iris.InputNum{"Hello, World"}
	Iris.Button{"Save"}
end Iris.End()

By putting a “do” after creating windows and tables and such it will add an end which makes lua format it nicely! This also makes your iris code feel more like lua if you will.

10 Likes

Did you really post a exploit gui framework on the devforum :sob: cool library but wild

4 Likes

So I’ve looked into the incorrect button formatting problem, and the source of the issue is actually very interesting.

Iris uses as few formatting updates as possible, so when text is updated its actually the Button Instances’ AutomaticSize property which adjusts the size of the Button.

I think the intentions of the AutomaticSize code were to consolidate updates to size, but the behavior is very strange (this is all that i can understand from what i’ve tested):

  1. Strings with only 1 or 0 sequence of whitespace will not update AutomaticSize When their whiespace is increased or decreased
    abcdef → abc def
  2. Strings with only 1 whitespace character will not update AutomaticSize when an even character is appended or an odd character is removed
    abc dd → abc eee

Because this is a bug with Roblox’s UI, I’m not sure that i can reasonably patch Iris to mitigate it, but thanks for mentioning it!

2 Likes

Just fixed this! check the releases for Iris v1.0.3

1 Like