GUI Tutorial: Difference between revisions

From Dyrdex.com
Jump to navigation Jump to search
 
(34 intermediate revisions by the same user not shown)
Line 2: Line 2:


The GUI is set up using the #SPLIT and #DRAW commands, often using #FORMAT, and using your #VAR's.  
The GUI is set up using the #SPLIT and #DRAW commands, often using #FORMAT, and using your #VAR's.  
(I strongly suggest enabling MSDP so you receive all the variables the mud sends automatically so you can start building things to display those. See [[MSDP Script|HERE]])


=Split Your Screen=
=Split Your Screen=


First, establish your desired top/bottom screen #SPLIT. Run your #SPLIT command manually or make an alias that might be handy later for resetting.  
First, establish your desired top/bottom screen #SPLIT with some room to print data into. I go 4 or 5 lines top and bottom.
 
The #BUFFER command reprints the scrolling region after splitting:


*Run your #SPLIT command manually or make an alias that might be handy later for resetting.
**The #BUFFER command reprints the scrolling region after splitting:
  #ALIAS {split} {
  #ALIAS {split} {
   #SPLIT 5 5;
   #SPLIT 5 5;
Line 14: Line 15:
   }
   }


=Draw Stuff=
Second, you can draw tiles or boxes of data into your split region, using the coordinate system.
*'''Coordinate System'''
**The coordinate system is "Row Col Row Col" with the first Row-Col pair being the 'upper left' point of box, and the second Row-Col pair being the lower right corner of the box.
**Negative values can be used to mean 'rows from end'. This is used by the #draw command to either "#draw box' or "#draw tile".
*'''Boxes vs. Tiles:'''
**'''Tile:''' Can be a single space, one character high/wide. If you have data that is exactly 2x3 characters, you can draw a 2x3 tile for example. If your data exceeds that tile space, it is truncated.
**'''Box:''' Can be a large space, typically good for drawing lists into, like affects or communications lines, etc. Lines that may vary in size so you don't know the exact required space and wouldn't want to use a tile.


=Draw Tiles=
'''Example:''' 1 1 -5 -5
Second, you can draw tiles of all the vars you want to populate your split region however you want. Here I'm formatting an existing var, then drawing its tile:
*Box will be from the upper-most left corner (row 1 column 1) to the point 5 rows from the right end of your screen, and 5 rows above the bottom row on your screen)
 
*To learn how these work, I would suggest just playing around with them in a blank tintin session, you don't even have to be connected to a mud.
*You can do #screen clear all to wipe the screen after each command to wipe the slate
#draw box 1 1 -10 -10 hellooooooo
#draw box 10 10 25 25 hellooooooo  (So box starts upper left corner row 10 down from the top, column 10 in from the left side. Goes to row 25, column 25 for lower right corner).
#draw tile 30 20 30 25 123456 (tile drawn on the 30th row, from columns 20 to 25 (so 6 spaces). If you try to draw 1234567 you'll see it gets wrapped/truncated and only prints '7')
 
You can also play with lots of colors and formatting options. See #help draw.
 
 
 
 
Here we are printing the room/area name on line 3 (down from the top) and it will go the upper left corner (


  #ALIAS {draw} {
  #ALIAS {draw} {
  #FORMAT {room_string} {%c%.44s} {<ddd>}{$msdp_info[ROOM_NAME]};
   #DRAW red tile 3 2 3 44 $msdp_info[ROOM_NAME];
   #DRAW tile 3 2 3 44 $room_string;
   #DRAW blue tile 2 2 2 44 $msdp_info[AREA_NAME];
  #FORMAT {area_string} {%c%.40s} {<bbb>}{$msdp_info[AREA_NAME]};
   #DRAW tile 2 2 2 43 $area_string;
   }
   }
To clarify, the coordinates are <row> <column> <row> <column> and set the upper-left point, and lower-right point.
   
   
Just add every var you want to draw to screen into that draw alias really. You'll have to read #Help draw to understand all your options, and how to use the coordinate system to place those into exact positions on screen. You'll also want to learn #FORMAT so you can align those and specify their lengths to avoid overrun.
You'll have to read #Help draw to understand all your options, and get good at the coordinate system to place those into exact positions on screen. You'll also want to learn #FORMAT so you can add additional controls and style to those.
 
==Format Tiles==
 
Using #format we can set more colors, and more importantly lengths/aligns to your tiles. Here, we format the msdp vars into our own stylized vars first, then draw those.
 
#ALIAS {draw} {
  #FORMAT {room_string} {%c%.44s} {<acf>}{$msdp_info[ROOM_NAME]};
  #DRAW tile 3 2 3 46 $room_string;
  #FORMAT {area_string} {%c%.40s} {<ffa>}{$msdp_info[AREA_NAME]};
  #DRAW tile 2 2 2 46 $area_string;
  }
 
The format commands are saying we want to format a new variable named "room_string" that will be comprised of an rgb color code (%c), and then a 44 character string (%.44s). We then define the color code as the <acf> color (blue) and the string as the room name we get from msdp.


This approach can become a problem when it comes to auto-updating the screen however. You'll want to read this entire page, especially the very bottom, before you go ahead setting up something like the above and wasting time adding more data to it.
So, first we format the room name string to be exactly 44 characters. Then we draw a tile of the exact size to contain that 44 characters (between columns 2 - 46 in this example).
 
However - having a singular alias like this 'draw' example can become a problem when it comes to auto-updating the screen however. It works well for updating one tile or box, but, you don't want to be re-drawing your entire gui every time any part of it needs updating. Bear that in mind. Maybe make an alias like draw_area_info to draw the room/area/geo and that's it. Make several commands to draw different parts of your gui, and trigger each individually, not the whole screen all at once.


=Draw Lists=
=Draw Lists=
Instead of drawing individual tiles, you can also generate a list and draw that all at once.  
Instead of drawing individual tiles, you can also generate a list and draw that all at once.  


Here, we will generate such a list, and then also create a sidebar box, and draw the whole list in there:
For example:
#list example add example text blablabla stuff
 
Looks like:
#VARIABLE {example}
{
    {1} {example}
    {2} {text}
    {3} {blablabla}
    {4} {stuff}
}
 
Can use #draw to print that all inside a box like this:
 
#draw box 10 10 20 40 $example[1..-1]
 
If you set those coordinates into a SPLIT region, the box will remain in place until it is redrawn at some point (perhaps by an alias you have, or scripted #event or #action).
 
If you set those coordinates into the scrolling region, the box will scroll away with the rest of the game text.
 
Note that when using a list, you can choose which list indexes (lines) you want to draw with the numbers inside the brackets. So 1..-1 is the first var (1) to the one before the end of the var (i.e. the last thing in the list) (-1), if you only want the last 5 you would just use -5..-1, etc.
 
If you capture all speech/tells/etc to a list, you can see the last 10 things sent to you with values like -10 -1 for example.


==Format a List==
==Format a List==
First, format your vars into a list:
We can also of course use #format to stylize the contents of our list. This alias takes your full affects list from msdp, and sets a color based on how many ticks remaining the spell is.
 
<pre>
<pre>
#alias get_affects {
#alias get_affects {
Line 52: Line 114:
</pre>
</pre>


That will generate a $affects var. Do #VAR affects to look at that.
That will generate a var named $affects. Type "#VAR affects" to see what it looks like. Once you get that looking how you want, you can draw that list anywhere.  


 
For example, here we can just print it into a box in the scrolling region:
Now, you can draw that list anywhere. For example, here we can just print it into a box in the scrolling region (it'll move when the screen scrolls next):


  #draw box 10 60 50 90 $affects[1..-1]
  #draw box 10 60 50 90 $affects[1..-1]


If you have short lists, those could probably fit in your top/bottom split. For long lists, you'll probably want a sidebar.
If you have short lists, those could probably fit in your top/bottom split. For long lists, you'll probably want to use #split to add a sidebar and draw it there. See my other sidebar script.
 
 
==Add a Sidebar==
So now let's do a sidebar, and draw a whole $affects list there.
 
First, use the #SCREEN command to get information about your existing #SPLIT, we know its '5 5' but, this can come in handy in some cases so figured I'd include it. Then we set a new split to have the original top/bottom but also a right-sidebar (24 spaces in this example). We also need to do #BUFFER end to reprint the scrolling region, and our original 'draw' alias to draw the normal top/bottom split data into place. Finally we will set a #var sidebar 1 just to track that the sidebar is indeed turned off, so we can use that info later.
 
#ALIAS {side_split} {
        #SCREEN get split_top_bar screen[split_top];
        #SCREEN get split_bot_bar screen[split_bot];
        #SCREEN get split_left_bar screen[split_left];
        #SCREEN get split_right_bar screen[split_right];
        #SPLIT  $screen[split_top] $screen[split_bot] 0 24;
        #BUFFER end;
        draw;
        #VAR sidebar 1;
        }
 
Second, draw a box with your list data into the new side split region. I'm drawing the box 'blue' here so you can see it, can change that to 'blanked' to make the outline invisible if you desire. We set the box top/bottom values by modifying the existing top/bottom split data, so the box doesn't draw on top of the top/bottom split lines (it will cause them to blank out or flicker). We also set the box left/right values to correspond to our right-hand split value (24) and -1 (last column of the right side of the screen)
 
#alias draw_sidebar {
        #MATH {mod_top} {$screen[split_top] + 1};
        #MATH {mod_bottom} {$screen[split_bot] + 2};
        #draw blue box $mod_top -24 -$mod_bottom -1 $affects[1..-1];
        };
 
 
 
Then, make a single alias that does the entire side operation:
#ALIAS {sidebar} {get_affects;side_split;draw_sidebar}
 
Finally, make an alias to toggle the sidebar on/off by checking the $sidebar var.
 
#ALIAS {affs} {
      #IF {"$sidebar" == "1"} {#VAR sidebar 0;#SPLIT 5 5;#BUFFER end;draw}; 
      #ELSE {get_affects;side_split;draw_sidebar};                           
      }
 
So, typing 'affs' will turn the side bar on if it was off, and then turn it off again if it was on. It's a toggle.


=Auto-Updates=
=Auto-Updates=
Now, let's say you want that to auto-update that sidebar every time your affects vars update.  
Now, let's say you want some of these tile or list draws auto-update as those vars update. Can use an #event for that, like:
 
Inside your MSDP script code, at the point where it is parsing the AFFECTS string, you can put this check:
 
#IF {"$sidebar" == "1"} {draw_sidebar};
 
 
Another approach to auto-update, for basically other than the AFFECTS string, is to use an #EVENT.
 
For example, to have your gui redrawn every time you enter a new room, and print the new room name, you can use the 'variable updated' event.
 
#EVENT {VARIABLE UPDATED msdp_info[ROOM_NAME]} {draw}


The issue here becomes, if you have a ton of gui tile elements updating, you don't want to re-draw the full screen multiple times redundantly.
#EVENT {VARIABLE UPDATED msdp_info[ROOM_NAME]} {RE-DRAW RELEVANT TILE!}


Instead, you can set EACH tile to have its own alias and set up events to update each of them. For example, you might make a specific aliases for each tile:
However, instead of writing the re-draw code right into that event, I prefer to write those as aliases and have the event fire the alias. That way, other things/scripts can also re-draw those tiles, and you don't have to keep rewriting the code for each one, they can all just call the alias.
   
   
  #ALIAS {draw_room_tile} {
  #ALIAS {draw_room_tile} {
Line 133: Line 144:


   
   
How you manage your vars, and how/when to draw/update them is up to you. I've experimented with a few approachs, and have found that handling each screen element as its own small tile, with its own draw alias, with its own event, runs quite efficiently so I'm only ever drawing tiny tiles, and not redrawing the whole screen and doing unnecessary computation to generate parts of the screen that haven't changed.
How you manage your vars, and how/when to draw/update them is up to you. I've experimented with a few approaches, and have found that handling each screen element as its own small tile, with its own draw alias, with its own event, runs quite efficiently so I'm only ever drawing tiny tiles, and not redrawing the whole screen and doing unnecessary computation to generate parts of the screen that haven't changed. You can still have a 'draw everything' type alias that may need to run sometimes, but that would just be a string of all the little tile draw aliases.
 
=Conclusion=
 
The concepts here are just the tip of the iceberg. You'll run into a lot of headscratchers along the way as far as how to properly set up your gui so it doesn't have conflicts, or draw things redundantly, and auto-updates, and doesn't fight with other sessions. Also, you'll have to put a bit of effort into how to actually integrate it into the rest of your system.
 
For me, I load my gui script after mud connection (as a module in my tt5 suite). I have some additional triggers firing in my connection script that then push gui re-draws upon things like session activation (changing characters), msdp reception updates, other variable updates, and code to limit when/where I draw to only work upon the active character session. This is kinda where things really get into the weeds, and you'll have to spend some time and thought on how best you want to handle all that sort of stuff. Session management is a bitch, you'll want to become familiar with the #events for session connection/activation/deactivated, as those are good times to draw your gui stuff, or wipe it out.
 
General advice:
*The simpler you can make each gui element, the better. You should be able to get very specific about what you want to draw, or redraw, so that the rest of your scripting can easily update your screen without too much work.
 
*As a beginner at this, I would suggest just trying to get one split region working and printing some info, for example, just set a bottom prompt and try to start putting your basic character info there, similar to your prompt, see if you can get that working. Before you draw out your entire screen in some elaborate fashion like I have, start small, one bar, and get that all working before you expand.

Latest revision as of 07:51, 22 April 2024

People keep asking how to set up the gui, so, here's some information you can expand upon.

The GUI is set up using the #SPLIT and #DRAW commands, often using #FORMAT, and using your #VAR's.

(I strongly suggest enabling MSDP so you receive all the variables the mud sends automatically so you can start building things to display those. See HERE)

Split Your Screen

First, establish your desired top/bottom screen #SPLIT with some room to print data into. I go 4 or 5 lines top and bottom.

  • Run your #SPLIT command manually or make an alias that might be handy later for resetting.
    • The #BUFFER command reprints the scrolling region after splitting:
#ALIAS {split} {
 #SPLIT 5 5;
 #BUFFER end;
 }

Draw Stuff

Second, you can draw tiles or boxes of data into your split region, using the coordinate system.

  • Coordinate System
    • The coordinate system is "Row Col Row Col" with the first Row-Col pair being the 'upper left' point of box, and the second Row-Col pair being the lower right corner of the box.
    • Negative values can be used to mean 'rows from end'. This is used by the #draw command to either "#draw box' or "#draw tile".
  • Boxes vs. Tiles:
    • Tile: Can be a single space, one character high/wide. If you have data that is exactly 2x3 characters, you can draw a 2x3 tile for example. If your data exceeds that tile space, it is truncated.
    • Box: Can be a large space, typically good for drawing lists into, like affects or communications lines, etc. Lines that may vary in size so you don't know the exact required space and wouldn't want to use a tile.

Example: 1 1 -5 -5

  • Box will be from the upper-most left corner (row 1 column 1) to the point 5 rows from the right end of your screen, and 5 rows above the bottom row on your screen)
  • To learn how these work, I would suggest just playing around with them in a blank tintin session, you don't even have to be connected to a mud.
  • You can do #screen clear all to wipe the screen after each command to wipe the slate
#draw box 1 1 -10 -10 hellooooooo
#draw box 10 10 25 25 hellooooooo  (So box starts upper left corner row 10 down from the top, column 10 in from the left side. Goes to row 25, column 25 for lower right corner).
#draw tile 30 20 30 25 123456 (tile drawn on the 30th row, from columns 20 to 25 (so 6 spaces). If you try to draw 1234567 you'll see it gets wrapped/truncated and only prints '7')

You can also play with lots of colors and formatting options. See #help draw.



Here we are printing the room/area name on line 3 (down from the top) and it will go the upper left corner (

#ALIAS {draw} {
 #DRAW red tile 3 2 3 44 $msdp_info[ROOM_NAME];
 #DRAW blue tile 2 2 2 44 $msdp_info[AREA_NAME];
 }

To clarify, the coordinates are <row> <column> <row> <column> and set the upper-left point, and lower-right point.

You'll have to read #Help draw to understand all your options, and get good at the coordinate system to place those into exact positions on screen. You'll also want to learn #FORMAT so you can add additional controls and style to those.

Format Tiles

Using #format we can set more colors, and more importantly lengths/aligns to your tiles. Here, we format the msdp vars into our own stylized vars first, then draw those.

#ALIAS {draw} {
 #FORMAT {room_string} {%c%.44s} {<acf>}{$msdp_info[ROOM_NAME]};
 #DRAW tile 3 2 3 46 $room_string;
 #FORMAT {area_string} {%c%.40s} {<ffa>}{$msdp_info[AREA_NAME]};
 #DRAW tile 2 2 2 46 $area_string;
 }

The format commands are saying we want to format a new variable named "room_string" that will be comprised of an rgb color code (%c), and then a 44 character string (%.44s). We then define the color code as the <acf> color (blue) and the string as the room name we get from msdp.

So, first we format the room name string to be exactly 44 characters. Then we draw a tile of the exact size to contain that 44 characters (between columns 2 - 46 in this example).

However - having a singular alias like this 'draw' example can become a problem when it comes to auto-updating the screen however. It works well for updating one tile or box, but, you don't want to be re-drawing your entire gui every time any part of it needs updating. Bear that in mind. Maybe make an alias like draw_area_info to draw the room/area/geo and that's it. Make several commands to draw different parts of your gui, and trigger each individually, not the whole screen all at once.

Draw Lists

Instead of drawing individual tiles, you can also generate a list and draw that all at once.

For example:

#list example add example text blablabla stuff

Looks like:

#VARIABLE {example}
{
   {1} {example}
   {2} {text}
   {3} {blablabla}
   {4} {stuff}
}

Can use #draw to print that all inside a box like this:

#draw box 10 10 20 40 $example[1..-1]

If you set those coordinates into a SPLIT region, the box will remain in place until it is redrawn at some point (perhaps by an alias you have, or scripted #event or #action).

If you set those coordinates into the scrolling region, the box will scroll away with the rest of the game text.

Note that when using a list, you can choose which list indexes (lines) you want to draw with the numbers inside the brackets. So 1..-1 is the first var (1) to the one before the end of the var (i.e. the last thing in the list) (-1), if you only want the last 5 you would just use -5..-1, etc.

If you capture all speech/tells/etc to a list, you can see the last 10 things sent to you with values like -10 -1 for example.

Format a List

We can also of course use #format to stylize the contents of our list. This alias takes your full affects list from msdp, and sets a color based on how many ticks remaining the spell is.

#alias get_affects {
        #list affects clear;
        #foreach {*msdp_info[AFFECTS][]} {affect}
        {
                #if {$msdp_info[AFFECTS][$affect] < 50} {#var Color {<dbb>}};
                #if {$msdp_info[AFFECTS][$affect] > 49 && $msdp_info[AFFECTS][$affect] < 99} {#var Color {<ffd>}};
                #if {$msdp_info[AFFECTS][$affect] > 99} {#var Color {<ddd>}};
                #format {affect_line} {%c%+15.15s %c%-4s%c} {<bbb>}{$affect}{$Color}{$msdp_info[AFFECTS][$affect]}{<ddd>};
                #LIST {affects} {add} {$affect_line};
        };
        #unvar Color;
        #unvar affect_line;
};

That will generate a var named $affects. Type "#VAR affects" to see what it looks like. Once you get that looking how you want, you can draw that list anywhere.

For example, here we can just print it into a box in the scrolling region:

#draw box 10 60 50 90 $affects[1..-1]

If you have short lists, those could probably fit in your top/bottom split. For long lists, you'll probably want to use #split to add a sidebar and draw it there. See my other sidebar script.

Auto-Updates

Now, let's say you want some of these tile or list draws auto-update as those vars update. Can use an #event for that, like:

#EVENT {VARIABLE UPDATED msdp_info[ROOM_NAME]} {RE-DRAW RELEVANT TILE!}

However, instead of writing the re-draw code right into that event, I prefer to write those as aliases and have the event fire the alias. That way, other things/scripts can also re-draw those tiles, and you don't have to keep rewriting the code for each one, they can all just call the alias.

#ALIAS {draw_room_tile} {
      #FORMAT {room_string} {%c%.44s} {<ddd>}{$msdp_info[ROOM_NAME]};
      #DRAW tile 3 2 3 44 $room_string;
      }
 #ALIAS {draw_area_tile} {
       #FORMAT {area_string} {%c%.40s} {<bbb>}{$msdp_info[AREA_NAME]};
       #DRAW tile 2 2 2 43 $area_string;
       }

Then have an event to update each one:

 #EVENT {VARIABLE UPDATED msdp_info[ROOM_NAME]} {draw_room_tile}
 #EVENT {VARIABLE UPDATED msdp_info[AREA_NAME]} {draw_area_tile}


How you manage your vars, and how/when to draw/update them is up to you. I've experimented with a few approaches, and have found that handling each screen element as its own small tile, with its own draw alias, with its own event, runs quite efficiently so I'm only ever drawing tiny tiles, and not redrawing the whole screen and doing unnecessary computation to generate parts of the screen that haven't changed. You can still have a 'draw everything' type alias that may need to run sometimes, but that would just be a string of all the little tile draw aliases.

Conclusion

The concepts here are just the tip of the iceberg. You'll run into a lot of headscratchers along the way as far as how to properly set up your gui so it doesn't have conflicts, or draw things redundantly, and auto-updates, and doesn't fight with other sessions. Also, you'll have to put a bit of effort into how to actually integrate it into the rest of your system.

For me, I load my gui script after mud connection (as a module in my tt5 suite). I have some additional triggers firing in my connection script that then push gui re-draws upon things like session activation (changing characters), msdp reception updates, other variable updates, and code to limit when/where I draw to only work upon the active character session. This is kinda where things really get into the weeds, and you'll have to spend some time and thought on how best you want to handle all that sort of stuff. Session management is a bitch, you'll want to become familiar with the #events for session connection/activation/deactivated, as those are good times to draw your gui stuff, or wipe it out.

General advice:

  • The simpler you can make each gui element, the better. You should be able to get very specific about what you want to draw, or redraw, so that the rest of your scripting can easily update your screen without too much work.
  • As a beginner at this, I would suggest just trying to get one split region working and printing some info, for example, just set a bottom prompt and try to start putting your basic character info there, similar to your prompt, see if you can get that working. Before you draw out your entire screen in some elaborate fashion like I have, start small, one bar, and get that all working before you expand.