YSI:Text draws

From SA-MP Wiki

Jump to: navigation, search

Contents

Introduction.

The YSI text draw system is a complete redesign of the SA:MP system, instead of having a piece of text which you style how you want, you have what are called "styles" and "texts". A style is a description of how text should look, a text is a piece of text using a given style. The idea behind this being that you can define a style once and reuse it as many times as you like. On top of this styles are completely dynamic, if you have a style which appears red you can change it's colour to green and all texts currently using that style will be instantly updated (this behaviour can be overridden but this will be covered and explained later).

The other major advantage of the YSI system is it's handling of hiding text draws. Most importantly it tracks all active text draws to avoid crashes caused by bugs in the SA:MP server (in early 0.2 versions), but it also offers other functionality such as timed text draws which only show for a certain time and style tracking to ensure no two texts of the same style in the same place are displayed at once (again, this can be got round if required, but helps avoid a lot of problems).

One final major point to note is that position is not a fixed part of a style. You can define a style's position and all messages displayed using that style will be placed there by default however you can move a piece of text about without altering the style or other pieces of text using the style. Doing this also means that you can have two bits of text using the same style at once as long as they're not in the same position (however 0.01 pixels apart is perfectly fine and will appear to overlay them if required).

Basic example.

As usual the easiest way to explain things is with an example. This will set up a style which appears in the middle of the screen in red and then display a message in it.

new
	Style:myStyle = TD_Create(.x = 300.0, .y = 220.0, .colour = 0xFF0000AA, .name = "my style");

Note the spelling of colour in that function, for most both color and colour are fine however for that one color is not. Also note the fact that we have named the text draw, this is for reference later and for compatibility with the text system and the XML system. From here there are a few ways we can display the text to a player:

new
	Text:text1 = TD_Display("Hello there", myStyle), // Create a text instance using the style stored in myStyle
	Text:text2 = TD_DisplayNamed("How are you?", "my style"); // Create a text instance using the style called "my style"

Now we have created the style and created two texts using it, lets display them both to a player, one above the other:

TD_ShowForPlayer(playerid, text1); // Show the first piece of text
TD_TextPosition(text1, 300.0, 200.0); // Move the first text up
TD_ShowForAll(text2); // Show the second piece of text to everyone, still at 300.0, 220.0

If we didn't move the first piece of text (before or after we show it to the player, it doesn't make any difference), the second piece of text would be displayed over the top of it, thus the text draw system would hide the first message (only for playerid).

As you can see there are a few more steps to displaying text but once it's set up it's much easier to manage using existing styles.

Destruction.

There are a few ways to destroy text - the important thing to note about them is that destroying text will not destroy the style it's based on however destroying a style will destroy all the current bits of text which use the style.

Time.

The first way of destroying text is setting a time for it to be displayed, Once it has been shown for the given length of time (or another piece of text of the same style is shown over the top of it) it will vanish, same as how the gametext system works.


new
	Style:myStyle = TD_Create(.x = 300.0, .y = 220.0, .colour = 0xFF0000AA, .time = 10000),
	Text:text = TD_Display("Hello there", myStyle);
TD_ShowForPlayer(playerid, text);

A time of 0 will make the text stay forever. Time is in milliseconds so the code above will obviously display the message "Hello there" to playerid for 10 seconds (10000 milliseconds).

Hide.

The second way is to hide the text manually:

TD_HideForPlayer(playerid, text);
TD_HideForAll(text);

This will instantly hide the given text instance.

Destroy.

You can destroy a text instance, this will remove it entirely from memory and thus remove it from all players who can currently see it.

TD_Destroy(text);

Delete.

This is different to TD_Destroy. You destroy a text instance, you delete a text style, and all associated text instances using the given style too.

TD_Delete(myStyle);

Garbage,

The problem with the first two methods is that even after the text has been hidden it still exists in memory, it's just no longer being used (assuming no-one is using it). This isn't a problem if you call TD_Destroy or TD_Delete however this may not always be possible if for example you hid it with the time parameter or you just forget, that's what the garbage collection system is for. If you mark a piece of text as garbage it will be automatically destroyed, (i.e. the text instance will be removed from memory) when no-one can see it any more.

TD_ShowForPlayer(playerid, text);
TD_Garbage(text);

If you called TD_Destroy right after TD_ShowForPlayer the player would never see anything as the text would be instantly hidden again, however this way the text will show for 10 seconds (assuming that's the current settings for it) then be both hidden and entirely removed from memory.

Configuration.

As stated earlier all text draw styles are fully dynamic, this means they can be changed when you like and everyone with them active will see them. Every option has it's own function, as well as being settable in the TD_Create function. This is an example of a text which appears to a player and then flashes red and green.

new
	Style:gMyStyle;
 
public OnPlayerConnect(playerid)
{
	gMyStyle = TD_Create();
	TD_StylePosition(gMyStyle, 300.0, 220.0);
	TD_Colour(gMyStyle, 0xFF0000AA); // Red
	new
		Text:text = TD_Display("Hello", gMyStyle);
	TD_ShowForPlayer(playerid, text);
	TD_Garbage(text);
	SetTimer("pFlash", 1000, 1);
}
 
public pFlash()
{
	static
		sColor = 0;
	if (sColor)
	{
		TD_Colour(gMyStyle, 0x00FF00AA); // Green
	}
	else
	{
		TD_Colour(gMyStyle, 0xFF0000AA); // Red
	}
	sColor = ~sColor;
}

That will, as stated, constantly flash the colour of the text on the player's screen until they disconnect. At which point no-one will be able to see the text and thus the garbage collector will destroy it. Obviously this code will create thousands of timers but that's not the point of the tutorial.

This can be expanded to any situation, for example a scrolling message, with every message using the text scrolling in x, but each maintaining their individual y positions.

TD_StyleYPos(gMyStyle, newYPos);

Updates.

As hinted at in the introduction you can bypass the default behaviour of updating text after every modification. This is useful for speeding up processing and reducing bandwidth when you are doing a lot of modifications at once, do all the modifications, adding "false" to the end of the parameters, then call TD_Upate and all the modifications will be processed and sent at the same time.

gMyStyle = TD_Create();
	TD_StylePosition(gMyStyle, 300.0, 220.0, false);
	TD_Colour(gMyStyle, 0xFF0000AA, false);
	TD_Update(gMyStlye);

The only functions which do not update by default are the position ones. If you have modified a style's position you will need to pass an additional true parameter to update the style structure's position, as well as the text instance's positions.

XML.

Format.

The YSI text draw system has it's own XML load system, this allows you to define text draw styles in an XML file for use with both text instances defined in the script and the YSI text system through the text style configuration system (see [YSI:Using Text|Displaying Text]). The complete format is as follows:

<color name="red">
  <hex>0xFF0000AA</hex>
</color>

<textdraw name="my style" color="red">
  <x></x>
  <y></y>
  <letterx></letterx>
  <lettery></lettery>
  <textx></textx>
  <texty></texty>
  <alignment></alignment>
  <box></box>
  <shadow></shadow>
  <outline></outline>
  <background></background>
  
  <proportional></proportional>
  <time></time>
</textdraw>

x and y are the position of the style, letterx and lettery are the letter sizes and textx and texty are the box sizes.

Colours.

For background and box they are assumed on if you include the parameters and the value in the tag is the colour. This can either be a hex number, a colour name (assuming you have previously defined the colour) or a new colour tag, for example these are all valid and will make the box red:

<textdraw>
  <box>0xFF0000AA</box>
</textdraw>
<textdraw>
  <box>
    <color>
      <hex>
        0xFF0000AA
      </hex>
  </box>
</textdraw>
<color>
  <name>
    red
  </name>
  <hex>
    0xFF0000AA
  </hex>
<color>
<textdraw>
  <box>red</box>
</textdraw>
<textdraw>
  <box>
    <color>
      <name>
        red
      </name>
      <hex>
        0xFF0000AA
      </hex>
  </box>
</textdraw>

The second two examples will also both define "red" as 0xFF0000AA so you can reuse "red" in other colour statements, so assuming you have done one of the latter two definitions already the following is now valid:

<textdraw>
  <box>red</box>
</textdraw>

You can also use named colours defined in XX_format.YSI files from the [colour] section (where XX is the name of a text library).

To define the colour of the actual text is a little different, you either have to use a full <color></color> tag within the <textdraw></textdraw> structure or set color="" in the open textdraw tag, this can however still be either a name or hex value.

Name is exactly the same as the name in TD_Create and can be used to reference the text draw style from either the code itself or a XX_format.YSI file.

Loading.

To load a text draw XML definition file simply do:

TD_Parse(filename);

Extra notes.

TD_Clone()

This creates an exact copy of a text draw style, this can be used to perfectly overlay two identical bits of text, or create a green and a red but otherwise identical style, or anything else.

TD_Name().

This renames a style.

XML/code differences.

Things like boxes and backgrounds are implicitly turned on in XML files simply by setting their colour, however when setting them up from in code you have to both set their colour and turn them on explicitly.

XML also has nothing at all to do with what is displayed, only how things are displayed.

Text system.

For more information on using text draws with the text system refer to [YSI:Using Text|Displaying Text]. Because everything in the text draw format files are referenced by name you can use styles defined in XML and code equally.

Modification.

If you want to modify the appearance of a style loaded from XML in code you first need to get it's internal ID from it's name (which you should know as you set it in the file). This is very simply done by:

new
	Style:id = TD_GetID(bernstein("name"));

There is no function which takes the name directly in the default library however if you really want one:

stock Style:TD_GetFromName(name[])
{
	return TD_GetID(bernstein(name));
}

Note that having being made aware of this shortcoming writing this it will be in the next version (or at least some future version when I remember).