### Define Widget Arguments Source: https://sirmallard.github.io/Iris/docs/about/widgets Examples of defining string-indexed tables for widget arguments. ```lua -- Button arguments Args = { ["Text"] = 1, ["Size"] = 2, } ``` ```lua -- Window arguments Args = { ["Title"] = 1, ["NoTitleBar"] = 2, ["NoBackground"] = 3, ["NoCollapse"] = 4, ["NoClose"] = 5, ["NoMove"] = 6, ["NoScrollbar"] = 7, ["NoResize"] = 8, ["NoNav"] = 9, ["NoMenu"] = 10, } ``` -------------------------------- ### Initialize Iris and Show Demo Window Source: https://sirmallard.github.io/Iris/docs/getting_started Use this script in a client-side location to verify that Iris is installed and functioning correctly. ```lua local Iris = require(path.to.Iris) Iris.Init() Iris:Connect(Iris.ShowDemoWindow) ``` -------------------------------- ### Initialize Iris correctly Source: https://sirmallard.github.io/Iris/docs/common_issues Initialize Iris at the start of a script, preferably in ReplicatedFirst, to ensure it is ready before other scripts require it. ```lua ---------------------------------- --- ReplicatedFirst/client.lua or StarterPlayer/StarterPlayerScripts/client.lua ---------------------------------- 1| -- code in ReplicatedFirst will execute before other code, so it is best practice 2| -- to initialise Iris here even if you are not going to use it. 3| require(game.ReplicatedStorage.Iris).Init() 4| 5| ... ---------------------------------------- --- StarterPlayer/StarterPlayerScripts/raycast.lua ---------------------------------------- 1| -- therefore, when you require it any scripts elsewhere it is already initialised 2| -- and ready to go and you do not need to worry about where to init 3| local Iris = require(game.ReplicatedStorage.Iris) 4| 5| -- wrong, you have initialised it twice here 6| local Iris = require(game.ReplicatedStorage.Iris).Init() 7| 8| ... ``` -------------------------------- ### Define Widget Events Source: https://sirmallard.github.io/Iris/docs/about/widgets Example of defining custom events for a Window widget, including manual event definitions and macro utilities for common events like hovering. ```lua Events = { ["closed"] = { ["Init"] = function(_thisWidget: Types.Window) end, ["Get"] = function(thisWidget: Types.Window) return thisWidget.lastClosedTick == Iris._cycleTick end, }, ["opened"] = { ["Init"] = function(_thisWidget: Types.Window) end, ["Get"] = function(thisWidget: Types.Window) return thisWidget.lastOpenedTick == Iris._cycleTick end, }, ["collapsed"] = { ["Init"] = function(_thisWidget: Types.Window) end, ["Get"] = function(thisWidget: Types.Window) return thisWidget.lastCollapsedTick == Iris._cycleTick end, }, ["uncollapsed"] = { ["Init"] = function(_thisWidget: Types.Window) end, ["Get"] = function(thisWidget: Types.Window) return thisWidget.lastUncollapsedTick == Iris._cycleTick end, }, ["hovered"] = widgets.EVENTS.hover(function(thisWidget: Types.Widget) local Window = thisWidget.Instance :: Frame return Window.WindowButton end), } ``` -------------------------------- ### Create a Basic Iris Window Source: https://sirmallard.github.io/Iris/docs/intro Initializes Iris and creates a simple window containing text, a button, and a number input field. ```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) ``` ```lua local StarterPlayerScripts = game.StarterPlayer.StarterPlayerScripts -- We first need to initialise Iris once before it is used anywhere. `Init()` will -- begin the main loop and set up the root widgets. Init can only be called once per -- client and returns Iris when called. local Iris = require(StarterPlayerScripts.Client.Iris).Init() -- 'Connect()' will run the provided function every frame. Iris code will need to run -- every frame to appear but you can use any other event and place your code anywhere Iris:Connect(function() -- We create a window and give it a title of 'My First Window!'. All widgets will -- be descended from a window which can be moved and scaled around the screen. Iris.Window({"My First Window!"}) -- A text widget can show any text we want, including support for RichText. Iris.Text({"Hello, World"}) -- A button has a clicked event which we can use to detech when the user -- activates it and handle that any way we want. Iris.Button({"Save"}) -- Iris has input, slider and drag widgets for each of the core datatype -- with support for min, max and increments. Iris.InputNum({"Input"}) -- Any widget which has children must end with an 'End()'. This includes -- windows, trees, tables and a few others. To make it easier to see, we can use -- a do-end loop wrapped around every parent widget. Iris.End() end) ``` -------------------------------- ### Calling Iris Window with Arguments Source: https://sirmallard.github.io/Iris/docs/getting_started Demonstrates different ways to pass arguments to the Iris Window widget, including positional arrays and index-based tables. ```lua local Iris = require(Iris) -- These are all equivalent: Iris.Window({"Title", nil, nil, nil, true, nil, nil, true}) Iris.Window({ [1] = "Title", [5] = true, [8] = true }) Iris.Window({ [Iris.Args.Window.Title] = "Title", [Iris.Args.Window.NoClose] = true, [Iris.Args.Window.NoResize] = true }) ``` -------------------------------- ### Providing State to a Widget Source: https://sirmallard.github.io/Iris/docs/getting_started Shows how to create a state object and pass it to a widget to enable bidirectional data synchronization. ```lua local positionState = Iris.State(Vector2.new(100, 100)) Iris.Window({ "Positioned Window" }, { position = positionState }) ``` -------------------------------- ### Iris Window API Documentation Source: https://sirmallard.github.io/Iris/docs/getting_started Reference for the Window widget properties, events, and state management. ```lua hasChildren = true hasState = true Arguments = { Title: string, NoTitleBar: boolean? = false, NoBackground: boolean? = false, -- the background behind the widget container. NoCollapse: boolean? = false, NoClose: boolean? = false, NoMove: boolean? = false, NoScrollbar: boolean? = false, -- the scrollbar if the window is too short for all widgets. NoResize: boolean? = false, NoNav: boolean? = false, -- unimplemented. NoMenu: boolean? = false -- whether the menubar will show if created. } Events = { opened: () -> boolean, -- once when opened. closed: () -> boolean, -- once when closed. collapsed: () -> boolean, -- once when collapsed. uncollapsed: () -> boolean, -- once when uncollapsed. hovered: () -> boolean -- fires when the mouse hovers over any of the window. } States = { size = State? = Vector2.new(400, 300), position = State?, isUncollapsed = State? = true, isOpened = State? = true, scrollDistance = State? -- vertical scroll distance, if too short. } ``` -------------------------------- ### Apply Per-Widget Configuration Source: https://sirmallard.github.io/Iris/docs/about/config Use PushConfig and PopConfig to apply specific settings to a block of widgets. This configuration stacks, allowing child widgets to override parent settings. ```lua Iris.PushConfig({ TextWrapped = true, ContentWidth = UDim.new(0.8, 0), FrameBgColor = Color3.fromRGB(41, 74, 122), FrameBgHoveredColor = Color3.fromRGB(66, 150, 250), FrameBgActiveColor = Color3.fromRGB(66, 150, 250), }) do -- create any widgets with this config end Iris.PopConfig() ``` -------------------------------- ### Complex Iris UI with State and Trees Source: https://sirmallard.github.io/Iris/docs/intro Demonstrates using Iris.State for dynamic values, handling button clicks, and organizing UI elements within a tree structure. ```lua local StarterPlayerScripts = game.StarterPlayer.StarterPlayerScripts local Iris = require(StarterPlayerScripts.Client.Iris).Init() Iris:Connect(function() 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) ``` -------------------------------- ### Instantiate a Text widget using Iris.Internal Source: https://sirmallard.github.io/Iris/docs/about/widgets Use the _Insert API to create a new widget instance by providing the widget type and optional arguments. ```lua Iris.Internal._Insert("Text", { "Text label" }) ``` -------------------------------- ### Integrating Iris into Weapon Service and Weapon Classes Source: https://sirmallard.github.io/Iris/docs/about/cycle Demonstrates placing Iris widgets directly within existing update methods of a service and a weapon class instead of using Iris:Connect(). ```lua ------------------------------------------------------------------------ --- game.ReplicatedStorage.Modules.Client.Weaopns.WeaponsService.lua ------------------------------------------------------------------------ local WeaponsService = { maxWeapons = 10, activeWeapon = nil, weapons = {} } function WeaponsService.init() end -- called every frame to update all weapons function WeaponsService.update(deltaTime: number) Iris.Window({ "Weapons Service" }) WeaponsService.doSomething() Iris.CollapsingHeader({ "Global Variables" }) Iris.DragNum({ "Max Weapons", 1, 0 }, { number = Iris.TableState(WeaponsService.maxWeapons) }) Iris.End() Iris.CollapsingHeader({ "Weapons" }) Iris.Tree({ `Active Weapon: {WeaponsService.activeWeapon.name}` }) WeaponsService.activeWeapon:update() Iris.End() Iris.SeparatorText({ "All Weapons" }) for _, weapon: weapon in WeaponsService.weapons do Iris.Tree({ weapon.name }) weapon:update() Iris.End() end Iris.End() WeaponsService.doSomethingElse() Iris.End() end function WeaponsService.terminate() end return WeaponsService ------------------------------------------------------------------------ --- game.ReplicatedStorage.Modules.Client.Weaopns.Weapon.lua ------------------------------------------------------------------------ local Weapon = {} Weapon.__index = Weapon function Weapon.new(...) end function Weapon.update(self, deltaTime: number) Iris.Text({ `ID: {self.id}` }) Iris.Text({ `Bullets: {self.bullets}/{self.capacity}" }) Iris.Checkbox({ "No reload" }, { isChecked = Iris.TableState(self.noreload) }) ... self:updateInputs() self:updateTransforms() ... end function Weapon.destroy(self) end ``` -------------------------------- ### Accessing Widget State Source: https://sirmallard.github.io/Iris/docs/getting_started Demonstrates how to retrieve a state object directly from an existing widget instance. ```lua local window = Iris.Window({ "Positioned Window" }) local positionState = window.state.position ``` -------------------------------- ### Listen to a button click event Source: https://sirmallard.github.io/Iris/docs/about/events Use the clicked() method on a widget instance to detect user interaction within the frame loop. ```lua local button = Iris.Button({ "Please click me!" }) if button.clicked() then print("The button was clicked!") end ``` -------------------------------- ### Create a TableState Source: https://sirmallard.github.io/Iris/docs/about/states Links a specific table index to a state object, handling updates internally without requiring a manual callback. ```Luau local data = { myNumber = 5 } local state = Iris.TableState(data, "myNumber") Iris.DragNum({ "My number" }, { number = state }) ``` -------------------------------- ### Create a VariableState Source: https://sirmallard.github.io/Iris/docs/about/states Links a local variable to a state object using a callback function to synchronize changes. ```Luau local myNumber = 5 local state = Iris.VariableState(myNumber, function(value) myNumber = value end) Iris.DragNum({ "My number" }, { number = state }) ``` -------------------------------- ### Initialize Widget State with GenerateState Source: https://sirmallard.github.io/Iris/docs/about/widgets Uses Iris._widgetState to construct and link a new state object to the widget if it does not already exist. ```lua GenerateState = function(thisWidget: Types.Checkbox) if thisWidget.state.isChecked == nil then thisWidget.state.isChecked = Iris._widgetState(thisWidget, "checked", false) end end ``` -------------------------------- ### Implement Generate function for a Button widget Source: https://sirmallard.github.io/Iris/docs/about/widgets The Generate function creates the UI instances for a widget, sets initial styles, and configures interaction events. It must return the root instance named with the Iris prefix. ```lua Generate = function(thisWidget: Types.Button) -- a TextButton is the best option here because it has the correct events local Button: TextButton = Instance.new("TextButton") -- we rely on auomatic size Button.Size = UDim2.fromOfset(0, 0) -- using the config values Button.BackgroundColor3 = Iris._config.ButtonColor Button.BackgroundTransparency = Iris._config.ButtonTransparency Button.AutoButtonColor = false Button.AutomaticSize = Enum.AutomaticSize.XY -- utility functions exist such as this one which correctly sets the text -- style for the widget widgets.applyTextStyle(Button) Button.TextXAlignment = Enum.TextXAlignment.Center -- another utility function which adds any borders or padding dependent -- on the config widgets.applyFrameStyle(Button) -- an utility event which uses clicks and hovers to colour the button -- when the mouse interacts with it: normal, hovered and clicked widgets.applyInteractionHighlights("Background", Button, Button, { Color = Iris._config.ButtonColor, Transparency = Iris._config.ButtonTransparency, HoveredColor = Iris._config.ButtonHoveredColor, HoveredTransparency = Iris._config.ButtonHoveredTransparency, ActiveColor = Iris._config.ButtonActiveColor, ActiveTransparency = Iris._config.ButtonActiveTransparency, }) -- set the correct layout order and zindex to ensure it stays in the -- correct order. Iris relies heavily on UIListLayouts to automatically -- position the UI, and therefore relies on the LayoutOrder property. Button.ZIndex = thisWidget.ZIndex Button.LayoutOrder = thisWidget.ZIndex -- we finally return the instance, which is correctly parented and -- Iris sets the widget.instance property to this root element return Button end, ``` -------------------------------- ### Structure Iris widgets with do-end blocks Source: https://sirmallard.github.io/Iris/docs/common_issues Use do-end blocks to clearly define parent-child relationships and ensure Iris.End() is called correctly. ```lua 4| Iris.Window({ "Do-End Block" }) 5| do 6| Iris.Text({ "Text goes here." }) 7| end 8| Iris.End() ``` -------------------------------- ### Standard Game Loop Structure Source: https://sirmallard.github.io/Iris/docs/about/cycle A typical game loop implementation that handles input, state updates, physics, and rendering sequentially. ```pseudo-code while(not_closed) { poll_input(); update_game_state(); step_physics(); render_content(); wait(); // for a 60 fps limit } ``` -------------------------------- ### Update Global Configuration Source: https://sirmallard.github.io/Iris/docs/about/config Updates the global UI configuration using templates or custom key-value pairs. This function should be called sparingly as it triggers a full redraw of all widgets. ```lua Iris.UpdateGlobalConfig(Iris.TemplateConfig.colorLight) -- change to the template light mode Iris.UpdateGlobalConfig({ RichText = true, IgnoreGuiInset = true, ScreenInsets = Enum.ScreenInsets.None, TextColor = Color3.fromRGB(85, 49, 218), TextSize = 16, FramePadding = Vector2.new(2, 1), }) -- specify the specific properties to change -- this can be specified before Iris is even initialised Iris.Init() ``` -------------------------------- ### Handle asynchronous operations in Iris Source: https://sirmallard.github.io/Iris/docs/common_issues Avoid yielding inside Iris widgets by using task.spawn to handle asynchronous operations like HTTP requests. ```lua ----------------------- --- bad_example.lua ----------------------- 4| Iris.Window({"Async Window"}) 5| -- this code yields which will prevent Iris from finishing before the next frame 6| local response = httpService:GetAsync(...) 7| Iris.Text(response) 8| Iris.End() ------------------------ --- good_example.lua ------------------------ 4| local response = "NONE" 5| 6| Iris.Window({"Async Window"}) 7| -- we use another thread to ensure the thread Iris is in will finish before the next frame 8| task.spawn(function() 9| response = httpService:GetAsync(...) 10| end) 11| Iris.Text(response) 12| Iris.End() ``` -------------------------------- ### Roblox Task Scheduler Event Loop Source: https://sirmallard.github.io/Iris/docs/about/cycle An event-driven loop representation using Roblox RunService events to execute code within the engine's task scheduler. ```lua while not_closed do update(UserInputService) update(ContextActionService) event(RunService.BindToRenderStepped) event(RunService.RenderStepped) render() event(wait) event(RunService.Stepped) update(PhysicsService) event(RunService.Heartbeat) update(ReplicationService) delay() -- for a 60 fps limit end ``` -------------------------------- ### WidgetConstructor Source: https://sirmallard.github.io/Iris/docs/about/widgets Registers a new widget class with the Iris system, associating a specific type string with a set of functional behaviors. ```APIDOC ## WidgetConstructor(type: string, widgetClass: WidgetClass) ### Description Registers a widget class to the Iris system. This function defines how a widget of a specific type is generated, updated, and discarded. ### Parameters - **type** (string) - Required - The identifier for the widget (e.g., "Text", "InputVector2"). - **widgetClass** (WidgetClass) - Required - A table containing the required functions and properties for the widget's lifecycle and behavior. ``` -------------------------------- ### Define a WidgetClass structure Source: https://sirmallard.github.io/Iris/docs/about/widgets The WidgetClass type definition outlines the required and optional functions and properties needed to implement a custom widget. ```lua export type WidgetClass = { -- Required Generate: (thisWidget: Widget) -> GuiObject, Discard: (thisWidget: Widget) -> (), Update: (thisWidget: Widget, ...any) -> (), Args: { [string]: number }, Events: Events, hasChildren: boolean, hasState: boolean, -- Generated on construction ArgNames: { [number]: string }, -- Required for widgets with state GenerateState: (thisWidget: Widget) -> (), UpdateState: (thisWidget: Widget) -> (), -- Required for widgets with children ChildAdded: (thisWidget: Widget, thisChild: Widget) -> GuiObject, -- Optional for widgets with children ChildDiscarded: (thisWidget: Widget, thisChild: Widget) -> (), } ``` -------------------------------- ### Listen to widget events in Iris Source: https://sirmallard.github.io/Iris/docs/getting_started Check widget state and interaction events by calling event functions directly on the widget object. This approach ensures code only executes when specific conditions are met. ```lua local window = Iris.Window({"Window"}) -- the window has opened and uncollapsed events, which return booleans if window.opened() and window.uncollapsed() then -- run the window code only if the window is actually open and uncollapsed, -- which is more efficient. -- the button has a clicked event, returning true when it is pressed if Iris.Button({"Click me"}).clicked() then -- run code if we click the button end end Iris.End() ``` -------------------------------- ### Avoid errors and yielding before Iris.End() Source: https://sirmallard.github.io/Iris/docs/common_issues Errors or yielding within a widget block can prevent Iris.End() from executing, leading to structural errors. ```lua 4| Iris.Window({ "Valid Code with Error" }) 5| error("Something has gone wrong. :(") -- errors within Iris 6| Iris.End() 7| Iris.Window({ "Asynchronous Code" }) 8| task.wait(1) -- yields within Iris 9| Iris.End() ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.