Difference between revisions of "Guide to TGUI"

From Paradise Station Wiki
Jump to navigation Jump to search
(added info about TGUI installation)
Line 15: Line 15:


This should properly install everything, you can check if this worked by running '''<code>yarn run build</code>''' and it should spit out a console log that look something like this:
This should properly install everything, you can check if this worked by running '''<code>yarn run build</code>''' and it should spit out a console log that look something like this:
[[File:TGUI Build Success Log.png]]
 
<br>
[[File:TGUI Build Success Log.png|500px]]
<br>
 
If you are getting a bunch of errors, you should count your blessings and go ask somebody in #coding_chat to help you.
If you are getting a bunch of errors, you should count your blessings and go ask somebody in #coding_chat to help you.
==Basic Syntax==
==Basic Syntax==



Revision as of 16:05, 18 July 2022

TGUI is a user interface library that Paradise (and many other ss13) servers use to create modern, responsive user interfaces for players to interact with various in-game objects and mechanics. TGUI is JavaScript based and uses the InfernoJS and ReactJS frameworks. Unlike general code contributions, a contributor will need to go through extra steps to make TGUI changes such as installing package managers and performing extra compilations using yarn. TGUI can be hell to get working and compile the first time, however, it's worth it to keep trying until you can actually make a successful change, I promise!


Note: Please read through the README.md file in the TGUI directory on your copy of the codebase, it will provide all necessary instructions to setup TGUI.

Installation Process

Make sure to follow these steps chronologically and ensure you have proper dependencies installed

Prerequisites

You will need to download and install the following dependencies:

  1. Node v12.13+
  2. Yarn v1.19+

Final Installation

If you are running MSys2, Git Bash, WSL, Linux or macOS please see the README.md for proper installation, for everyone else use this.

You will need to open a terminal, command window, powershell window, etc in the TGUI directory. If you are in vscode and have a terminal open to your codebase directory, you can use cd tgui to set the directory to the TGUI folder of your codebase. Now if your directory is correctly set to the base TGUI folder, you can now run yarn install

This should properly install everything, you can check if this worked by running yarn run build and it should spit out a console log that look something like this:


TGUI Build Success Log.png

If you are getting a bunch of errors, you should count your blessings and go ask somebody in #coding_chat to help you.

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