HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

TextSplat Library

10-01-2006, 04:35 PM#1
PitzerMike
Zoom (requires log in)

Since floating texts have a few problems (for example you can only have a max of 100 at a time) I've created my own floating text type.

You can have:
  • mono and gradient text splats,
  • custom fonts,
  • moving text splats,
  • text splats attached to units,
  • running text,
  • fading text splats.

Try the attached demo map, and if you like it you'll find a tutorial right below ;)
Atm this uses game cache, I'll change it to use SmartAttach or Pipe's array system in the next version to speed it up.





=====================================================================================

Setting up the System

First copy the code from the custom text header of the sample map to the cusotm text header of your map. Copy the two gamecache variables, namely udg_ArrayCache and udg_TextSplatCache to your map. Before creating any TextSplats we need to initialize the system. That is we need to import the images of the font we are going to use into the map and call TextSplatInitializeCache at map initialization.

Collapse JASS:
function TextSplatInitializeCache takes nothing returns nothing

The path for the images is Fonts\FontName\, so in my example I've imported them to Fonts\Trebuchet\. You may of course import as many fonts as you wish. I've supplied a tool that automatically creates these images and the required initialization code for a given font. You can read more about this tool later on.

Creating a TextSplat

After initializing the system you may create TextSplats. To do that there are two functions available:

Collapse JASS:
function TextSplatCreateGradient takes string text, real baseX, real baseY, string font, integer size, integer valign, integer halign, integer colorFrom, integer colorTo returns integer
function TextSplatCreateMono takes string text, real baseX, real baseY, string font, integer size, integer valign, integer halign, integer color returns integer

As you can see there are two types of TextSplats. In mono TextSplats all letters have the same color whereas the color of gradient TextSplats runs from start color, which is used for the first letter, to end color which is used for the last letter.
In the text of the TextSplat you may use |n for linebreaks and ordinary color tags like |cffffffffText|r to manually change the color of certain areas. In gradient TextSplats these color tags will be ignored, however, mono TextSplats will use them. The here specified font name needs to comply with the path to which you imported the images. For horizontal and vertical alignment we have these constants at our disposal:

Collapse JASS:
constant function TS_ALIGN_LEFT takes nothing returns integer
constant function TS_ALIGN_TOP takes nothing returns integer
constant function TS_ALIGN_CENTER takes nothing returns integer
constant function TS_ALIGN_RIGHT takes nothing returns integer
constant function TS_ALIGN_BOTTOM takes nothing returns integer

To specify the colors I've chosen to use Peppar's ColorInteger functions. All you need to know about it is how to create a ColorInteger:

Collapse JASS:
function CreateColorInteger takes integer red, integer green, integer blue, integer alpha returns integer

Here's an example of mono and gradient TextSplats:

Collapse JASS:
local integer mono = TextSplatCreateMono("This is a mono |cFFFFCC00TextSplat|r", 0.0, 0.0, "Trebuchet", 18, TS_ALIGN_TOP(), TS_ALIGN_LEFT(), CreateColorInteger(255, 0, 0, 255))
local integer gradient = TextSplatCreateGradient("This is a multiline|ngradient TextSplat", 0.0, 200.0, "Trebuchet", 12, TS_ALIGN_TOP(), TS_ALIGN_CENTER(), CreateColorInteger(0, 255, 255, 32), CreateColorInteger(255, 204, 0, 255))

Zoom (requires log in)

The integer returned by TextSplatCreateMono and TextSplatCreateGradient will be our handle to the created TextSplat. If 0 is returned you have probably exceeded the max string length for TextSplats, which is 255 characters.

Funny things with TextSplats

You can attach TextSplats to units. The left border of the TextSplat will align with the unit's x coordinate. However you can use the SetTextSplatOffset function to adjust the alignment. For a fluid impression the update interval should be set to something like 0.05. The timer which updates the TextSplat's position will be returned.

Collapse JASS:
function TextSplatAttachToUnit takes integer textSplat, unit target, real updateWait returns timer

Another fun thing to do with TextSplats is fading them in and out. You can either fade from a specific source alpha value to a target alpha value with TextSplatFade or use existing utility functions to completely fade them in/out. Alternatively you can specify a callback function that will be called after the fade. This must be the name of an existing function that takes no parameters or "", otherwise it will cause a game crash. Use GetTriggeringTextSplat in the callback to get a reference to the TextSplat.

Collapse JASS:
function TextSplatFade takes integer textSplat, real time, real updateWait, integer startAlpha, integer endAlpha, string callback returns timer
function TextSplatFadeIn takes integer textSplat, real time, real updateWait, string callback returns timer
function TextSplatFadeOut takes integer textSplat, real time, real updateWait, string callback returns timer

I'm sure you know running texts from clocks or advertisement boards. Use the TextSplatEnableRunningText function to enable running texts. A positive vertical step width will make the lines of a TextSplat run from the bottom up. A positive horizontal step width will make the letters of the TextSplat run from right to left. An update interval of 0.25 should be sufficient for running texts.

Collapse JASS:
function TextSplatEnableRunningText takes integer textSplat, integer vStep, integer hStep, real updateWait returns timer
function TextSplatDisableRunningText takes integer textSplat, timer runTimer returns nothing

It's possible to apply the TextSplatEnableRunningText function more then one time to a TextSplat. If you do that, don't forget to store the returned update timer as a reference for the TextSplatDisableRunningText function. Pass null to the timer argument to disable all running text timers of the TextSplat.


Sometimes you might want to move your TextSplat along a certain path. You can do that with the TextSplatFloat function. For example you could move the TextSplat straight towards a certain direction, move it in a sine curve or maybe in a circle. Specify 0 as duration if you want the movement to loop forever.

Collapse JASS:
function TextSplatFloat takes integer textSplat, real time, real updateWait, code fX, code fY, string callback returns timer

You'll have to specify callback functions that describe the movement for both, the x and y axis. The movement can be dependant on the elapsed time since the start of the movement or the number of times the update timer has expired. Since the callback needs to take nothing and return nothing the following functions will provide the necessary information and let you set the return value of your function.

Collapse JASS:
function TextSplatGetMovementTimeElapsed takes nothing returns real
function TextSplatGetMovementExecCount takes nothing returns integer
function TextSplatSetMovementResult takes real value returns nothing

For example here's a callback function that will move the TextSplat up/down or left/right in a sine curve:

Collapse JASS:
function Movement9Sin100 takes nothing returns nothing
    call TextSplatSetMovementResult(Sin(TextSplatGetMovementExecCount() * 9.0 * bj_DEGTORAD) * 100.0)
endfunction

Zoom (requires log in)

Here's another set of functions used to change existing TextSplats. I think their effect is pretty obvious.

Collapse JASS:
function SetTextSplatPosition takes integer textSplat, real x, real y returns nothing
function SetTextSplatOffset takes integer textSplat, real offX, real offY returns nothing
function SetTextSplatVisible takes integer textSplat, boolean visible returns nothing
function SetTextSplatColorMono takes integer textSplat, integer color, boolean overrideTags returns nothing
function SetTextSplatColorGradient takes integer textSplat, integer colorFrom, integer colorTo returns nothing

The SetTextSplatColorMono function lets you also lets you decide if you want to override color tags like |cffffffffText|r. Finally there are a few utility functions to find out the more important properties of TextSplats and ColorIntegers:

Collapse JASS:
function GetTextSplatAttachedUnit takes integer textSplat returns unit
function GetTextSplatColor takes integer textSplat returns integer
function GetTextSplatBaseX takes integer textSplat returns real
function GetTextSplatBaseY takes integer textSplat returns real
function GetTextSplatOffsetX takes integer textSplat returns real
function GetTextSplatOffsetY takes integer textSplat returns real
function GetTextSplatX takes integer textSplat returns real
function GetTextSplatY takes integer textSplat returns real
function IsTextSplatFading takes integer textSplat returns boolean
function IsTextSplatAttached takes integer textSplat returns boolean
function IsTextSplatRunning takes integer textSplat returns boolean
function IsTextSplatFloating takes integer textSplat returns boolean
function IsTextSplatVisible takes integer textSplat returns Boolean

function ColorIntegerGetRed takes integer i returns integer
function ColorIntegerGetGreen takes integer i returns integer
function ColorIntegerGetBlue takes integer i returns integer
function ColorIntegerGetAlpha takes integer i returns integer

Destroying a TextSplat

This is easy, just call TextSplatDestroy when you don't need a TextSplat any more.

Collapse JASS:
function TextSplatDestroy takes integer textSplat returns nothing

Importing custom Fonts

First you'll need to open the provided FontConv.psd file in Photoshop. Zoom in until you can see the text box. Mark the whole text in the text box and change the font to the font you'd like to have in game. Now adjust the text height so it fits just fine within the blue borders. None of the letters should go above the upper border or below the lower border. Then adjust the text width accordingly, so the letters don't look stretched. Now save the file as 32-bit tga. I named it like the font, so the file I had was Trebuchet.tga.

Zoom (requires log in)

Now we will use the provided FontConv tool to convert this image to blp format and generate the required initialization code. Put the tga you just created in the same folder as the FontConv.exe application. This is a command line tool, so you better start the command prompt, navigate to said folder and type FontConv FontName.tga FontName 34. So in my case I typed FontConv Trebuchet.tga Trebuchet 34. The 34 at the end is the ascii value of the " character. This is so the tool knows that the two ' symbols are not separate characters but part of one and the same character. This can be different from font to font. Some fonts may have a connection between the two ' symbols, in that case remove the 34 from your command. Some fonts may also have more characters that have to be listed here, but usually we should be fine with just 34. After successfully processing the image the tool should spit out a whole bunch of blp files and a j file that contains the required initialization code. Check back if 34.blp has both ' symbols in Wc3Viewer, otherwise run the tool again with adjusted parameters.

Zoom (requires log in)

Now let's import both, the images and the code into our map. The path for the images is Fonts\FontName\, so in my case that was Fonts\Trebuchet\. Since it's quite a lot of work to rename every single file in the import manager, I've used WEU to import all images at once. However be sure to make a backup of your map before using WEU, just in case. Now in the trigger editor find the custom text header and simply append the generated initialization code at the end of the TextSplatInitializeCache function.

Congratulations, now you're ready to use your custom font.
Attached Images
File type: jpgtextsplat.jpg (10.1 KB)
File type: jpgtextsplats.jpg (47.8 KB)
File type: jpgmonovsgradient.jpg (15.1 KB)
File type: gifphotoshop.gif (10.2 KB)
File type: giffiles.gif (9.3 KB)
Attached Files
File type: w3xTextSplatLib1.0b.w3x (56.9 KB)
File type: rarFontConv.rar (123.7 KB)
10-01-2006, 04:39 PM#2
WindowSmasher
Haha! That is super cool! +rep
10-01-2006, 05:43 PM#3
Vexorian
Pipe's arrays are for temporal stuff, smart attach might work but require that preprocessor, you could also stick to gamecache and be happy, how often is the storage actually required for this?, I am gonna test it when I boot to windows but it seems and sounds kickass right now

edit: oh it has animations and fading, I see that gamecache is used really often.
10-01-2006, 05:44 PM#4
karukef
Super Cool? Nuh-uh. Can't possibly express the coolness of this system.

Very VERY solid job! I've been wanting something like this for a long time. :)

Side notes for PitzerMike:
Hidden information:
I would also love to make this an external system that can be automatically included by my WeWarlock, so that anyone using that tool can easily include it with no installation procedures and simplified importing of .blps. Also, once I finish the callback system (currently working), stuff like TextSplatFloat would work much more intuitively by allowing the user to supply a function that is given and can return the proper values automatically.
10-01-2006, 07:08 PM#5
PitzerMike
Thanks, everyone. I think SmartAttach would be appropriate. Game cache really isn't a good choice here since I'm reading very frequently (for example the width of each character) in the update functions.

Uber secret information for Karukef only ... really:
Hidden information:

Yep, the callback thing would really help. Not to forget the speedup.
And it could be good to promote your tool a bit ;)
10-01-2006, 08:09 PM#6
PipeDream
This is painfully badass
---
dynamic arrays are a bad choice since you've got fixed size structures. smart attach / parallel arrays with 1 at a time allocator is the way to go. since having the user add 30 arrays wouldn't be that userfriendly, smartattach is really the only option.
10-02-2006, 07:14 AM#7
Tim.
Finally! Glad to see it finished.
10-02-2006, 01:46 PM#8
arpha_storm
This is freakishly delicious. :P
Nice job.
10-02-2006, 03:07 PM#9
The)TideHunter(
Truely amazing, really.
10-02-2006, 04:41 PM#10
Chuckle_Brother
Sex....just....pure sex.

This gets a huge thumbs up and probably an "ehhh!" from me.
10-02-2006, 08:09 PM#11
PitzerMike
Cheers for the "eeeh" :P
10-02-2006, 11:10 PM#12
Chuckle_Brother
Sadly, the Fonz just doesn't work in a forum environment.
10-04-2006, 11:06 AM#13
Preskooldude
WoooooooW... exactly what I needed to finish the MainScreen I'm working on... +Rep and credits to ya if I can use it in my map!
10-04-2006, 03:16 PM#14
blu_da_noob
You sir, win the internet. *goes off to clean the drool off his keyboard*
10-04-2006, 09:56 PM#15
PitzerMike
Thanks :)
What I forgot to mention: You can of course remove the images for the characters that you don't use in your map. This will reduce the size which is normally around 18 kb per font (which is already quite affordable i guess).
Use an ASCII table as reference for the numbers.