Facebook Twitter YouTube Frictional Games | Forum | Privacy Policy | Dev Blog | Dev Wiki | Support | Gametee


Thread Rating:
  • 3 Vote(s) - 3.67 Average
  • 1
  • 2
  • 3
  • 4
  • 5
GUI Tutorial Series
Abion47 Offline
Senior Member

Posts: 369
Threads: 22
Joined: Oct 2015
Reputation: 46
#7
RE: GUI Tutorial Series

Mind Your Language

This tutorial isn't strictly about GUI development, but it covers a very important related topic. In any form of programming, it is important to keep your data and logic seperate. What this means in a nutshell is that you should code in such a way that changing one thing that your program does shouldn't involve an overhaul of how it does it. GUI development in SOMA is no different in this regard.

Table of Contents
The Basics
Getting More Advanced
Using SOMA's Built-In GUI Styles
  • StationGui (WIP)
  • UrbanGui (WIP)
  • Playing Audio (WIP)

Going Beyond Terminals
  • Setting Up a User Module (WIP)
  • Basic Heads-Up Display (WIP)
  • Target Info Module (WIP)
  • Player HUD Menu System (WIP)

Tutorial Requirements

For this tutorial, you will need the following:
  • A mod with the basic needs to be run through the ModLauncher.
  • A map with a prepared terminal, plus all the necessities.
  • A script file with a prepared OnGui terminal callback function.

Tutorial Source Files

Initial File
Completed File

The Tutorial Itself

Remember in the last tutorial how we made a TextFrame with a paragraph's worth of data? Holding that much text in your script files is bad form. For one, like I said above, it can get very tedious when you need to modify something small but need to sift through all your code to find it.

How to put your maps and such into a complete mod is outside the scope of this series, but this tutorial is going to require that your mod be able to get loaded by the ModLauncher. As such, in the Initial File I provided, I've included the complete mod setup in addition to the map files. You can use that to get started, if you don't want to bother setting it all up yourself.

What we're going to first, though, is set up a TextField in our map with a couple paragraphs of text. You know, I've gotta tell you how to do it wrong before I show you how to do it right. Or something like that.

Open up your map script file, go down to the OnGui function, and slap in the following code to create the TextField we will spend the rest of this tutorial fixing.

// Label
cImGuiLabelData labelData;
labelData.mFont.mvSize = cVector2f(100, 100);

ImGui_DoLabelExt("Example of too much text", labelData, cVector3f(80, 20, 0));

// TextFrame
cImGuiTextFrameData textFrameData;
textFrameData.mFont.mvSize = cVector2f(45, 45);
textFrameData.mColorBase = cColor(0, 0, 0, 0);

ImGui_DoTextFrameExt(
    "This is a lot of words. As you can see, we don't like putting this many words into our code field. It makes the code cumbersome and it hurts the developer's ability to maintain it. It would be better if, whenever we had to put text at all into a separate file altogether, and write our code to pull it out of that file. If we did this, then we could easily change the text whever we wanted without changing the code at all.",
    0,
    10,
    0,
    textFrameData,
    cVector3f(80, 240, 0),
    cVector2f(880, 660));

It's quite a bit of code, for sure, but's nothing you haven't seen before.

If we were to run our map through the DevBat right now, it would pretty much appear exactly how we would want it to.

[Image: u7qJsUl.jpg]

But then again, making the GUI look perfect isn't what we are after here. We are going after the goal of making our code look pretty.

What we are going to do now is take all of the text we just hard-coded into our script file and move it into what is known as a "lang file", which is short for "language file". Putting all of our text resources, be they GUI text, subtitle text, or any other text at all, into a lang file, we make it so all of our text is in a single location, which the rest of our mod will able to reference from anywhere else. This makes our mod efficient, which in turn makes it easier to code.

Another benefit to lang files is if you ever want to offer translations of your mod in different languages, lang files allow you to do so without changing any of your code. Enabling this behavior is beyond the goals of this particular tutorial, but if the interest is there, I can explore the topic in the future after all the basics are accounted for.

Go into your mod files (which I will work under the assumption is the files that I provided above). Under the root directory "GuiTutorial04", there should be a folder called "config". In this folder should be three files. What we will be using is the file called "english.lang". Go ahead and open it in the text editor of your choice.

A lang file is essentially an XML file, so there isn't any complicated syntax to learn here. All you need to know is how a lang file is structured.

<LANGUAGE>
    <RESOURCES>
        <Directory Path="fonts/" />
        <Directory Path="lang/eng" />
    </RESOURCES>
  
    <CATEGORY Name="ExampleCategory">
        <Entry Name="TextEntry">This is the text inside this entry.</Entry>
    </CATEGORY>
</LANGUAGE>

First, you have the resources at the top under the "Resource" tag. In this case, the resources are already be completed in the lang file for you, and typically you won't ever have to mess with this.

Second you have your categories. Each of these categories represents a different "section" of your mod. Each section will typically be a particular map, if your mod spans multiple maps. It can also be a section of your GUI, if your GUI is going to be overly complex.

Finally, within the categories, you have your entries. Each entry stores a particular chunk of text that your code will be retrieving.

As you can see, categories and entries both have an attribute called "Name". This is what your code will be using to actually get the text, so it's important that each category you have is given a unique name, and each entry within a given category has a unique name. (While it is allowed to have two entries within different categories to have the same name, it is advised to not do this for the sake of your sanity.)

Now that we have the explanations out of the way, it's time to actually write us some language.

Near the bottom of your language file, just above the "</LANGUAGE>" tag, let's create a new category. Type in the following text:

<CATEGORY Name="GuiTutorial04">

This line creates a new category section named "GuiTutorial04". Every entry you create in this category will be tied to the category, so you will need to use this name in your code when you need those entries. As such, it's a good idea to name your category something easy to read and remember. (For example, "Office_Laptop_Terminal" is a better category name than "GUI_001_A4".)

Enter a new line after the previous code. It's time for us to create an entry. Let's start with the entry for our Label text:

<Entry Name="Label_Text">Example of too much text</Entry>

This creates a new entry with the name "Label_Text". Inside the "Entry" tags, you can see the text that we used earlier when creating our Label. We can use this entry name later on when we revisit our code.

We've got our Label entry, so now let's make our TextField entry:

<Entry Name="TextFrame_Text">This is a lot of words. As you can see, we don't like putting this many words into our code field. It makes the code cumbersome and it hurts the developer's ability to maintain it. It would be better if, whenever we had to put text at all into a separate file altogether, and write our code to pull it out of that file. If we did this, then we could easily change the text whever we wanted without changing the code at all.</Entry>

Just like above, we've made our entry called "TextFrame_Text" to hold the text that we used in our GUI code before.

Before we go back to our code, there's one more thing we have to do in our lang file. Put the following text in a new line after your entries:

</CATEGORY>

In XML, every tag you open must also be closed. Because we made our category above, we now have to close it. If you don't do this, the game won't necessarily cause errors to pop-up, so instead you might end up with bizarre bugs, and it won't be immediately obvious what is causing them.

Alright, that should wrap up everything we need to do in the lang file, so let's go back to our map script.

The first thing we need to do is tell ImGui that we want to be using a lang file as our text source rather than using the text we give it directly. To do this, put in the following code to the top of your OnGui function:

ImGui_SetTransCategory("GuiTutorial04");

What the function ImGui_SetTransCategory does is it tells ImGui that, for all the text widgets that we will be creating afterwards, we want ImGui to be using our lang file, and specifically the category "GuiTutorial04".

Now we just have to change up our Label and TextField creation code. Update the ImGui_DoLabelExt and ImGui_DoTextFrameExt lines of code to show the following:

ImGui_DoLabelExt("Label_Text", labelData, cVector3f(80, 20, 0));
// ...
ImGui_DoTextFrameExt(
    "TextFrame_Text",
    0,
    10,
    0,
    textFrameData,
    cVector3f(80, 240, 0),
    cVector2f(880, 660));

As you can see, instead of the text we want it to render, the Label and the TextFrame now show the names of their respective entries in our lang file. Because we set our category before with ImGui_SetTransCategory, those functions will now attempt to pull the text from our lang files with those entry names rather than treat the text we give them as raw data.

You can see how this already makes our code much easier to read. Instead of manually inputting the text, we now have ImGui referencing our lang file. This leads to much more organized code and an easier time developing in general. This is especially useful if you have a number of places in your code that you want to display the same text, so now you can have them all reference the same entry rather than typing it out every time, and updating them all if you ever change the text.

(If you ever want to explicitly tell ImGui to treat the text you give it as raw text, use ImGui_SetTransCategory("").)

Alright, if we now run our map through the ModLauncher, you should see the following.

[Image: nDeBLPk.jpg]

You can see that there isn't really any visible difference, but that's okay. the fact that we now know our code is efficient and organized is plenty reward enough, let me tell you.

Now, the reason that I told you to run the map through the ModLauncher is because if you ran it through the DevBat, this is what it would look like:

[Image: w00rOq1.jpg?1]

There's nothing there! If you're wondering why, the error text at the bottom left will give you a clue.

[Image: SnVxUOb.jpg]

As you can see, the game says it can't find our lang file category. The reason for this is that when the DevBat loads your map, it doesn't load your lang file, so it will only be using the lang files for SOMA itself. And those lang files don't have our categories or our entries in them. (There are work-arounds for this of course, but they can get a tad complicated to set up, and are outside the scope of this tutorial anyway.)

That brings this tutorial to a close. From now on for future tutorials, I'm going to continue using raw text rather than lang files purely because from a tutorial series' standpoint, it's easier to follow raw text than having to frequently refer to lang files to see what the crap it is I am trying to say. Just remember, when you create your own mods, lang files are your friend, and they only want to help you succeed.

So far, our terminals have been little more than fancy over-complicated signs. In the next tutorial, we're going to look into how to make our terminals interactive.
(This post was last modified: 09-03-2016, 08:05 PM by Abion47.)
11-08-2015, 03:38 AM
Find


Messages In This Thread
GUI Tutorial Series - by Abion47 - 11-07-2015, 09:27 AM
RE: GUI Tutorial Series - by Abion47 - 11-07-2015, 10:44 AM
RE: GUI Tutorial Series - by Abion47 - 11-07-2015, 11:11 AM
RE: GUI Tutorial Series - by Kanthos - 11-07-2015, 12:38 PM
RE: GUI Tutorial Series - by RaideX - 11-07-2015, 01:28 PM
RE: GUI Tutorial Series - by Abion47 - 11-07-2015, 02:52 PM
RE: GUI Tutorial Series - by Abion47 - 11-08-2015, 03:38 AM
RE: GUI Tutorial Series - by A.M Team - 11-08-2015, 12:46 PM
RE: GUI Tutorial Series - by Abion47 - 11-09-2015, 01:28 AM
RE: GUI Tutorial Series - by Abion47 - 11-09-2015, 02:57 AM
RE: GUI Tutorial Series - by Abion47 - 11-10-2015, 05:06 AM
RE: GUI Tutorial Series - by Vale - 11-10-2015, 08:00 AM
RE: GUI Tutorial Series - by Abion47 - 11-10-2015, 08:03 AM
RE: GUI Tutorial Series - by Abion47 - 11-27-2015, 01:20 AM
RE: GUI Tutorial Series - by Abion47 - 07-12-2016, 07:52 PM
RE: GUI Tutorial Series - by Abion47 - 07-12-2016, 10:04 PM
RE: GUI Tutorial Series - by NewPueblo - 09-03-2016, 12:09 AM
RE: GUI Tutorial Series - by Abion47 - 09-03-2016, 08:02 PM



Users browsing this thread: 1 Guest(s)