Guide to TGUI
Installation
Basic Syntax
Advanced UI
Modals
Modals are temporary popup menus in a TGUI window that contributors generally use to enable the view to see additional information or provide an input. In order to use them in a JavaScript file one will first need to import two packages import { ComplexModal, modalOpen } from './common/ComplexModal';
Implementation
In the constant where you first define the actual window, you'll need to include the <ComplexModal />
element directly after the <Window>
declaration. This is mandatory in order for the modal to work. Here is an example usage of it:
export const ComputerUI = (props, context) => { const { act, data } = useBackend(context); const { var1, var2, } = data; return ( <Window resizable> <ComplexModal /> <Window.Content scrollable className="Layout__content--flexColumn"> <ComputerNavigation /> <ComputerPageContent /> </Window.Content> </Window> ); };
Once the complex modal element is added, then once can add further elements into the JS file in order to prompt the game to actually open the modal. This can be done through a button onClick event for example. One will need to call modalOpen(context, 'modal_action_name')
in the JS file, it will take context as the first paramater, and then this actions unique name which as been set as 'modal_action_name' here but it can be anything within reason. Here is an example where it is in a buttons onclick event.
<Button fluid textAlign="left" icon="pen" width="auto" content="Example Content" onClick={() => modalOpen(context, 'edit_title')} />
You can add these as many times as necessary! However, editing the JS file isn't enough to make these work or interact with the game.
DM Code Implementation
For this part, we'll operate under the assumption that you already have basic knowledge of /ui_act and /ui_data. Now we'll be introducing /ui_act_modal which is where we will do the bulk of our DM logic for modals. Go ahead and define that proc now /obj/machinery/computer/examplemachine/proc/ui_act_modal(action, list/params)
. Next we will add logic to our ui_act and ui_data procs.
For ui_act we will need to make sure to include all four of these parameters for our proc (action, list/params, datum/tgui/ui, datum/ui_state/state)
this is more than most machines will use however we're special (and I promise these are used later). In addition to the new parameters, you will need to add an if statement calling ui_act_modal after the parent function call and before the "action" switch statement is performed. This is demonstrated below:
/obj/machinery/computer/examplemachine/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) if(..()) return if(ui_act_modal(action, params)) return switch(action)
What we're doing here is we're checking for additional actions as part of the normal ui_act functionality. Opening a modal is the same thing as performing an action, we're just adding another proc to add ease of use and integrate special functionality already created in parent functions. We've now added a way for our DM code to actually know when the TGUI window wants to open a modal. This next part, I have no fucking idea what it does but it is critically important to making these pieces of shit work. We'll need to add one line to our ui_data proc:
data["modal"] = ui_modal_data(src)
Congratulations, we're now ready to add the final logic (and probably implement the code you've been wanting to add for the past few hours). This is where our ui_act_modal proc comes in. I'll do my best to break it down for a text/int input only (I'm sure more types of modals exist dont worry). First you will need to add some initial code, that is . = true
and then define your id and arguments vars. Essentially what we're doing here is making sure our proc knows what modal window we're working with (by knowing its id) and then getting all those lovely arguments we snatched in our ui_act proc. Once this is done
/obj/machinery/computer/library/proc/ui_act_modal(action, list/params) . = TRUE var/id = params["id"] // The modal's ID var/list/arguments = istext(params["arguments"]) ? json_decode(params["arguments"]) : params["arguments"] switch(ui_modal_act(src, action, params)) if(UI_MODAL_OPEN) switch(id) if("edit_title") ui_modal_input(src, id, "Please input the new title:", null, arguments, selected_book.title) if("edit_author") ui_modal_input(src, id, "Please input the new author:", null, arguments, selected_book.author) else return FALSE if(UI_MODAL_ANSWER) var/answer = params["answer"] switch(id) if("action_a") if(!length(answer) && length(answer) <= MAX_NAME_LEN) return selected_book.title = answer if("action_b") if(!length(answer)) return selected_book.author = answer else return FALSE else return FALSE