Fontext for free - Merry Christmas blitzers

Community Forums/Developer Stations/Fontext for free - Merry Christmas blitzers

Beaker(Posted 2006) [#1]
Fontext is now free for all users. Thank you to all those that purchased it over the years. Enjoy.

What is Fontext?
Fontext is an application for creating great looking packed bitmap fonts for 2D & 3D games. It also comes with some excellent code libraries to use bitmap fonts in your games (Blitz3D & BlitzPlus - BlitzMax library in a post below).

The Blitz3D library has some extended features including:
Save Fontext text mesh
Create clickable GUI objects
Create curved text

Fontext application and codelibs:
http://www.mediafire.com/?24ng952x3dm

Plugin to create Fontext mesh directly in gile[s] (v1.36 only I think?):
http://www.mediafire.com/?5y31ol6zvbl

If you make any changes to the libraries that others might enjoy then please share them.


Grey Alien(Posted 2006) [#2]
Wow thanks, very generous (shame I've got it already) ;-)

I'll be using this for my next game for sure.


caff_(Posted 2006) [#3]
That is very generous. A great application and library I have used for a couple of years now.

Thanks :)


GfK(Posted 2006) [#4]
Yep Fontext is good. Used it for a couple years now. Was pretty easy to get some basic Fontext functionality up and running in Blitzmax, too.


trb(Posted 2006) [#5]
Awesome, thanks so much!


slenkar(Posted 2006) [#6]
thanks,


bregors(Posted 2006) [#7]
.


popcade(Posted 2006) [#8]
Thanks, it's a great product I'vs ued til now :)


Rook Zimbabwe(Posted 2006) [#9]
I have always wanted this! Beaker is d best!


Dragon57(Posted 2006) [#10]
Very generous. I thank you!


IPete2(Posted 2006) [#11]
Many thanks,

IPete2.


Pineapple(Posted 2006) [#12]
Very generous, thank you, and have a great christmas! :)

Dabz


Ricky Smith(Posted 2006) [#13]
Many thanks Beaker and Happy Christamas to you too !


big10p(Posted 2006) [#14]
Free font tool? You b*****d!!!

j/k :)

Most generous, Beaks! ;)


BlitzSupport(Posted 2006) [#15]
Nice, thanks Beaker!


degac(Posted 2006) [#16]
Many thanks!
Merry Christmas!


smilertoo(Posted 2006) [#17]
Its not just for blitz3d, i used it last week to make the fonts for my bmax game.


TeaVirus(Posted 2006) [#18]
Thanks Beaker!


thelizardking(Posted 2007) [#19]
sa-weet!


Dustin(Posted 2007) [#20]
Very nice! Thank you so much.


Dock(Posted 2007) [#21]
Just found this thread - much thanks to Beaker! Fontext is awesome, I'll be sure to use this.

I wonder which is better for rendering text in Blitz 3D, the Fontext library or the SwiftGUI library.


Barnabius(Posted 2007) [#22]
Purchased it years ago and enjoyed it very much.

Very generous of Beaker to let all Blitzers have it. :-)

Barney


MGE(Posted 2007) [#23]
The links end up at a dead page. Any Bmax source to use the fonts?


t3K|Mac(Posted 2007) [#24]
no they work. just tried em.


tonyg(Posted 2007) [#25]
no they work. just tried em.


Even this one : http://www.tomspeed.com/fontext/ ?


MGE(Posted 2007) [#26]
Dead. At least the ones pointing to the BlitzMax framework to use the fonts is.


t3K|Mac(Posted 2007) [#27]
tomspeed.com has expired ;(


blade007(Posted 2007) [#28]
is it christmas in july or was the topic bumped?


gweedo767(Posted 2007) [#29]
Does anyone have these files still since all the links are dead?


Beaker(Posted 2007) [#30]
Sorry for the delay. The files are now available again from the first post.


MikeT(Posted 2007) [#31]
Does anyone have the BMax files? The link is dead.


Beaker(Posted 2007) [#32]
The problem is that the one that was originally written used some low level stuff and no longer works in the current version of Bmax. I'm sure there are others out there.

I can post the old one if someone wants to have a go at updating it.


tonyg(Posted 2007) [#33]
Beaker, I *think* it was pretty straightforward. Do you just mean the DX references in FontTextType.bmx? If so, I believe I have it working for DX.
Can I post it?


Beaker(Posted 2007) [#34]
Of course.


tonyg(Posted 2007) [#35]
OK, any problems let me know :
format_codebox('
Strict
Framework BRL.Basic

?win32
Import BRL.D3D7Max2D
?
Import BRL.GLMax2D
Import BRL.Retro
Import BRL.TGALoader
Import BRL.PNGLoader


'Local DX_Driver = D3D7Max2DDriver()
'Local GL_Driver:TGLMax2DDriver = GLMax2DDriver()
SetGraphicsDriver GLMax2DDriver()

Graphics 1024,768,0

'Create a FonText Type
'The function will expect to find the accompanying .ini that was created when you
'made your bitmap font in FonText. It should reside in the same folder as the bitmap
Local myFT:FonText = FonText.Create("f.png", FILTEREDIMAGE)


Local rot# = 0
Local i:Int
Local cen:Byte = False
Local scale:Float = 1.0
Local time:Int
Local text:String
Local angle:Float = 0
Local lbToggle:Byte = False


text = "Justified Text!"+Chr(13)+Chr(13)
text:+ "This text is drawn using DrawJustified(), the text is automatically wrapped at a user "
text:+ "specified pixel width. Spaces are not drawn if they're at the beginning of a line, and words are "
text:+ "wrapped properly so they don't get split!"+Chr(13)+Chr(13)
text:+ "The line break width can be optionally scaled (press RETURN to see it in action)"+Chr(13)
text:+ "Also..."+Chr(13)
text:+ "Line breaks..."+Chr(13)
text:+ "Are..."+Chr(13)
text:+ "Supported!"


SeedRnd(MilliSecs())
While Not KeyHit(KEY_ESCAPE)
Cls
If 0

For i=1 To 100
SetColor Rand(50,100),Rand(50,100),Rand(50,100)
DrawRect Rand(600),Rand(400),200,200
Next
SetColor 255,255,255
End If

SetRotation rot
SetScale scale,scale

If KeyHit(KEY_T) 'create an animated fontext routine
Local mx=MouseX()
Local my=MouseY()
Local cr#=Cos(rot+90)
Local cs#=Sin(rot+90)
afonText.Create("Wouldn't it be nice...", myFT, mx, my, 0, 2000, 4000, 2000, 2, 1,0)
afonText.Create("To be able to automate..", myFT, mx+cr*40, my+cs*40*scale, 1000, 2000, 3000, 2000, 2, 1,-1)
afonText.Create("Text fading onto the screen..", myFT, mx+cr*80, my+cs*80*scale, 2000, 2000, 2000, 2000, 2, 1,1)
afonText.Create("?", myFT, mx+cr*150, my+cs*150*scale, 4000, 2000, 2000, 2000, 0, 1,0)
afontext.Create("..Well now you can!", myFT, mx+cr*200, my+cs*200*scale, 5000, 2000, 2000, 2000, 2, 1,0)
End If

SetRotation 0
SetScale scale*.5,scale*.5
myFT.DrawJustified(text,60,60,False,2,800,lbToggle)

SetBlend ALPHABLEND
SetScale scale,scale

Local x#=MouseX()
Local y#=MouseY()

time = MilliSecs()

SetRotation 0
'SetScale 1,1
myFT.Draw("FonText Rocks!",GraphicsWidth()/2,0,True,4)

myFT.DrawVertical("Vertical Text",0,0,cen,-20)


SetScale scale,scale
SetRotation rot
'myFT.DrawVertical("Draw Vertical",0,0,cen,-25) '* working
myFT.DrawWave("Drawn with DrawWave()",x,y,angle,45,8,cen,8) '* working
myFT.DrawWiggle("Drawn with DrawWiggle()",x,y+60,angle,45,8,cen,8) '* working
myFT.DrawBouncy("Drawn with DrawBouncy()",x,y+120,angle,15,24,cen,6) '* working
myFT.DrawWobble("Drawn with DrawWobble()",x,y+180,-angle,-45,10,cen,6) '* working
myFT.DrawSineSize("Drawn with DrawSineSize()",x,y+240,-angle,-45,30,cen,6) '* working
myFT.DrawSwing("Drawn with DrawSwing()",x,y+300,-angle,5,20,cen,6) '* working

aFonText.Update()

time = MilliSecs() - time
angle:- 5
SetScale 1,1
SetRotation 0

If KeyHit(KEY_RETURN) lbToggle = Not lbToggle
If KeyDown(KEY_LEFT) scale:- .01
If KeyDown(KEY_RIGHT) scale:+ .01
If KeyHit(KEY_SPACE) cen=Not cen
If MouseDown(1) rot:- 1
If MouseDown(2) rot:+ 1

SetScale .3,.3
myFT.Draw("FonText draw time: "+time+"ms",0,728,False,2)
myFT.Draw("LMB/RMB rotate, cursor LEFT/RIGHT adjust scale, SPACE toggle center, 't' for a special FX",0,748,False,2)
'DrawText MemAlloced(),0,0
Flip
Wend
EndGraphics()




Type FonText
Field image:TImage
Field blockHeight:Int
Field char:Byte[255] 'Boolean for each ASCII character, True if the FonText includes it, False if not
Field maskColor:Int
Field packed:Int

Field pX:Float[255] 'Position X
Field pY:Float[255] 'Position Y
Field cW:Int[255] 'Width

Field sinL:Float[360] 'not used yet
Field cosL:Float[360] ' ""

Field iwM:Float 'Image width & height multipliers used in
Field ihM:Float 'functions to optimise UV calculation speed

Field u0:Float[255]
Field v0:Float[255]

Field u1:Float[255]
Field v1:Float[255]

Function Create:FonText(file:String,flags:Int = -1)
Local img:TImage = LoadImage(file,flags)
If Not img RuntimeError "Could not load Image "+file
SetImageHandle(img,0,0)

Local ini:TStream = OpenFile(Left$(file,file.length - 3)+"ini")
If Not ini RuntimeError "Could not find "+Left$(file,file.length - 3)+"ini"

Local f:FonText = New FonText
f.image = img

f.iwM = 1.0 / img.width
f.ihM = 1.0 / img.height

'Get BlockSize (height)
Local r:String

'Ignore first 3 lines
ReadLine(ini)
ReadLine(ini)
ReadLine(ini)

'Get MaskColor (needed?)
r = ReadLine(ini)
f.maskColor = Int(Right$(r,r.length-10))

'Packed Font?
r = ReadLine(ini)
f.packed = Int(Right$(r,1))

'Find [text] line
r = ReadLine(ini)
While r<>"[text]"
r = ReadLine(ini)
Wend

'Block Height
r = ReadLine(ini)
f.blockHeight = Int(Right$(r,r.length - 10))

'Count Characters
r = ReadLine(ini)
While r<>"[charset]"
r = ReadLine(ini)
Wend

'Store this location
Local location:Int = StreamPos(ini)

'do the count
Local count:Int = 0
While Not Eof(ini)
r = ReadLine(ini)
count:+ 1
Wend

'Back to the Characters...
SeekStream(ini,location)

Local i:Int,j:Int,s:String,t:String
Local cur:Byte

'Parse each characters position & width
For i = 0 Until count
r = ReadLine(ini)
cur = Asc(Left$(r,1))
f.char[cur] = True

'Position X
j = 3
s = ""
t = Mid$(r,j,1)
While t<>","
s:+ t
j:+1
t = Mid$(r,j,1)
Wend
f.pX[cur] = Float(s)

'Position Y
j:+1
s = ""
t = Mid$(r,j,1)
While t<>","
s:+ t
j:+1
t = Mid$(r,j,1)
Wend
f.pY[cur] = Float(s)

'Character Width
j:+ 1
s = ""
t = Mid$(r,j,1)
While t<>","
s:+ t
j:+1
If j>r.length Exit
t = Mid$(r,j,1)
Wend
f.cW[cur] = Int(s)

'Adjust packing if the font isn't packed (trim space either side of character)
If Not f.packed
f.pX[cur]:+ (f.blockheight - f.cW[cur]) * .5
End If

f.u0[cur] = f.pX[cur] * f.iwM
f.v0[cur] = f.pY[cur] * f.ihM
f.u1[cur] = (f.pX[cur]+f.cW[cur]) * f.iwM
f.v1[cur] = (f.pY[cur]+f.blockHeight) * f.ihM
Next

CloseStream ini
Return f
End Function

Method DrawJustified(s:String, x:Float, y:Float, centered:Byte, spacing:Float, lineBreak:Float, scaleLB:Byte)
Local i:Int,t:String

Local scaleX#,scaleY#
Local oX#,oY#
Local rot#
Local sinR#,cosR#,sinP90#,cosP90#
Local areaW#,areaH#

Local curChar:Byte
Local isGL:Byte 'Boolean
Local GLframe:TGLImageFrame
Local DXframe:TD3D7ImageFrame
Local frame:Int = 0
Local xDrawn:Float = 0

GetOrigin oX,oY
GetScale scaleX,scaleY

rot = GetRotation()
sinR = Sin(rot)
cosR = Cos(rot)
sinP90 = Sin(rot+90)
cosP90 = Cos(rot+90)

If TGLImageFrame(image.frame(frame))
isGL = True
GLframe = TGLImageFrame(image.frame(frame))
Else
isGL = False
DXframe = TD3D7ImageFrame(image.frame(frame))
End If

If scaleLB Then lineBreak:* scaleX

'Center text horizontally?
Local ln:Float = 0
If centered
x:- cosR * lineBreak * .5
y:- sinR * lineBreak * .5
End If

Local newWord:Int = 0
Local wordLen:Float
Local tw:Int
Local lastLen:Int = 0

Local vSpacing = blockHeight * .8

'Draw each letter in the string...
For i = 0 Until s.length
'Check for whole word, we don't want to break them up
If lastLen <= 0 And s[i]<>32 And lineBreak>0
lastLen = 0
For newWord = i Until s.length
lastLen:+ 1
If s[newWord]=32 Or s[newWord]=13 Exit
Next

wordLen = 0
'Was there a word?
If newWord>0
For tw = i Until newWord
wordLen:+ (cW[s[tw]] + spacing)*scaleX
Next
End If

'Check the length doesn't go over the lineBreak limit
If xDrawn + wordLen > lineBreak
'goto next line

'move back to beginning
x:- cosR * xDrawn
y:- sinR * xDrawn

'move down
x:+ cosP90 * vSpacing * scaleX
y:+ sinP90 * vSpacing * scaleY
lastLen = 0
xDrawn = 0
End If
End If


'Space character?
'blockHeight/3 *seems* to be an ok value for spaces
If s[i] = 32' And xDrawn>2
x:+ cosR * blockHeight*.3 * scaleX
y:+ sinR * blockHeight*.3 * scaleY
xDrawn:+ blockHeight*.3 * scaleX
End If

'Linebreak?
If s[i] = 13

'goto next line

'move back to beginning
x:- cosR * xDrawn
y:- sinR * xDrawn

'move down
x:+ cosP90 * vSpacing * scaleX
y:+ sinP90 * vSpacing * scaleY
lastLen = 0
xDrawn = 0

End If

'If our loaded bitmap font has this character...
If char[s[i]]' And s[i]<>32
curChar = s[i]

lastLen:- 1

areaW = cW[curChar]
areaH = blockHeight

'Draw this character
If isGL
'Point UVs to character in FonText Bitmap..
GLframe.u0 = u0[curChar]
GLframe.v0 = v0[curChar]
GLframe.u1 = u1[curChar]
GLframe.v1 = v1[curChar]

GLframe.Draw 0, 0, areaW, areaH, x+oX, y+oY

Else 'Same as above, but using DX variation
DXframe.setUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
DXframe.Draw 0, 0, areaW, areaH, x+oX, y+oY
End If

'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
x:+ cosR * (cW[curChar]+spacing) * scaleX
y:+ sinR * (cW[curChar]+spacing) * scaleY
xDrawn:+ (cW[curChar]+spacing) * scaleX
End If
Next


'Restore UVs
If isGL
GLframe.u0 = 0
GLframe.v0 = 0
GLframe.u1 = 1
GLframe.v1 = 1
Else
DXframe.SetUV (0,0,1,1)
End If
End Method


Method Draw(s:String, x:Float, y:Float, centered:Byte = False, spacing:Float = 0)
Local i:Int,t:String

Local scaleX#,scaleY#
Local oX#,oY# 'Current Max2D Origin
Local rot# 'Current Max2D Rotation
Local sinR#,cosR#,sinP90#,cosP90#
Local areaW#,areaH#

Local curChar:Byte
Local isGL:Byte 'Boolean
Local GLframe:TGLImageFrame
Local DXframe:TD3D7ImageFrame
Local frame:Int = 0

GetOrigin oX,oY
GetScale scaleX,scaleY

rot = GetRotation()
sinR = Sin(rot)
cosR = Cos(rot)
sinP90 = Sin(rot+90)
cosP90 = Cos(rot+90)


If TGLImageFrame(image.frame(frame))
isGL = True
GLframe = TGLImageFrame(image.frame(frame))
Else
isGL = False
DXframe = TD3D7ImageFrame(image.frame(frame))
End If

'Center text horizontally?
Local ln:Float = 0
If centered
'Get string length
For i = 0 Until s.length
If s[i] = 32
ln:+ blockHeight*.3
Else If char[s[i]]
ln:+ cW[s[i]]+spacing
End If
Next
ln:- spacing 'remove last unwanted space

ln = ln*scaleX *.5
x:- cosR*ln
y:- sinR*ln
End If

Local spaceValX# = cosR * blockHeight * .3 * scaleX
Local spaceValY# = sinR * blockHeight * .3 * scaleY

'Draw each letter in the string...
For i = 0 Until s.length

'Space character?
'blockHeight*.3 *seems* to be an ok value for spaces
If s[i] = 32
x:+ spaceValX
y:+ spaceValY
End If

'If our loaded bitmap font has this character...
If char[s[i]] And s[i]<>32
curChar = s[i]

areaW = cW[curChar]
areaH = blockHeight

'Draw this character
If isGL
'Point UVs to character in FonText Bitmap..
GLframe.u0 = u0[curChar]
GLframe.v0 = v0[curChar]
GLframe.u1 = u1[curChar]
GLframe.v1 = v1[curChar]

GLframe.Draw 0, 0, areaW, areaH, x+oX, y+oY

Else 'Same as above, but using DX variation
DXframe.setUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
DXframe.Draw 0, 0, areaW, areaH, x+oX, y+oY
End If

'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
x:+ CosR * (cW[curChar]+spacing) * scaleX
y:+ SinR * (cW[curChar]+spacing) * scaleY

End If
Next

'Restore UVs
If isGL
GLframe.u0 = 0
GLframe.v0 = 0
GLframe.u1 = 1
GLframe.v1 = 1
Else
DXframe.SetUV (0,0,1,1)
End If
End Method


Method DrawWave(s$, x#, y#, angle#, angleStep#, mag#, centered:Byte = False, spacing# = 0)
Local i:Int,t:String

Local scaleX#,scaleY#
Local oX#,oY# 'Current Max2D Origin
Local rot# 'Current Max2D Rotation
Local sinR#,cosR#,sinP90#,cosP90#
Local areaW#,areaH#

Local curChar:Byte
Local isGL:Byte 'Boolean
Local GLframe:TGLImageFrame
Local DXframe:TD3D7ImageFrame
Local frame:Int = 0

GetOrigin oX,oY
GetScale scaleX,scaleY

rot = GetRotation()
sinR = Sin(rot)
cosR = Cos(rot)
sinP90 = Sin(rot+90)
cosP90 = Cos(rot+90)


If TGLImageFrame(image.frame(frame))
isGL = True
GLframe = TGLImageFrame(image.frame(frame))
Else
isGL = False
DXframe = TD3D7ImageFrame(image.frame(frame))
End If

'Center text horizontally?
Local ln:Float = 0
If centered
'Get string length
For i = 0 Until s.length
If s[i] = 32
ln:+ blockHeight*.3
Else If char[s[i]]
ln:+ cW[s[i]]+spacing
End If
Next
ln:- spacing 'remove last unwanted space

ln = ln*scaleX *.5
x:- cosR*ln
y:- sinR*ln
End If

Local spaceValX# = cosR * blockHeight * .3 * scaleX
Local spaceValY# = sinR * blockHeight * .3 * scaleY

Local bx#,by#,bMag#

'Draw each letter in the string...
For i = 0 Until s.length

'Space character?
'blockHeight*.3 *seems* to be an ok value for spaces
If s[i] = 32
x:+ spaceValX
y:+ spaceValY
End If

'If our loaded bitmap font has this character...
If char[s[i]] And s[i]<>32
curChar = s[i]

bMag = Sin(angle) * mag * scaleY
bx = x - cosP90 * bMag
by = y - sinP90 * bMag

areaW = cW[curChar]
areaH = blockHeight

'Draw this character
If isGL
'Point UVs to character in FonText Bitmap..
GLframe.u0 = u0[curChar]
GLframe.v0 = v0[curChar]
GLframe.u1 = u1[curChar]
GLframe.v1 = v1[curChar]

GLframe.Draw 0, 0, areaW, areaH, bx+oX, by+oY

Else 'Same as above, but using DX variation
DXframe.setUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
DXframe.Draw 0, 0, areaW, areaH, bx+oX, by+oY
End If

angle:+ angleStep
'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
x:+ CosR * (cW[curChar]+spacing) * scaleX
y:+ SinR * (cW[curChar]+spacing) * scaleY

End If
Next

'Restore UVs
If isGL
GLframe.u0 = 0
GLframe.v0 = 0
GLframe.u1 = 1
GLframe.v1 = 1
Else
DXframe.SetUV (0,0,1,1)
End If
End Method

Method DrawWiggle(s$, x#, y#, angle#, angleStep#, mag#, centered:Byte = False, spacing# = 0)
Local i:Int,t:String

Local scaleX#,scaleY#
Local oX#,oY# 'Current Max2D Origin
Local rot# 'Current Max2D Rotation
Local sinR#,cosR#,sinP90#,cosP90#
Local areaW#,areaH#

Local curChar:Byte
Local isGL:Byte 'Boolean
Local GLframe:TGLImageFrame
Local DXframe:TD3D7ImageFrame
Local frame:Int = 0

GetOrigin oX,oY
GetScale scaleX,scaleY

rot = GetRotation()
sinR = Sin(rot)
cosR = Cos(rot)
sinP90 = Sin(rot+90)
cosP90 = Cos(rot+90)


If TGLImageFrame(image.frame(frame))
isGL = True
GLframe = TGLImageFrame(image.frame(frame))
Else
isGL = False
DXframe = TD3D7ImageFrame(image.frame(frame))
End If

'Center text horizontally?
Local ln:Float = 0
If centered
'Get string length
For i = 0 Until s.length
If s[i] = 32
ln:+ blockHeight*.3
Else If char[s[i]]
ln:+ cW[s[i]]+spacing
End If
Next
ln:- spacing 'remove last unwanted space

ln = ln*scaleX *.5
x:- cosR*ln
y:- sinR*ln
End If

Local spaceValX# = cosR * blockHeight * .3 * scaleX
Local spaceValY# = sinR * blockHeight * .3 * scaleY

Local bx#,by#,bMag#

'Draw each letter in the string...
For i = 0 Until s.length

'Space character?
'blockHeight*.3 *seems* to be an ok value for spaces
If s[i] = 32
x:+ spaceValX
y:+ spaceValY
End If

'If our loaded bitmap font has this character...
If char[s[i]] And s[i]<>32
curChar = s[i]

bMag = Sin(angle) * mag * scaleX
bx = x - cosR * bMag
by = y - sinR * bMag

areaW = cW[curChar]
areaH = blockHeight

'Draw this character
If isGL
'Point UVs to character in FonText Bitmap..
GLframe.u0 = u0[curChar]
GLframe.v0 = v0[curChar]
GLframe.u1 = u1[curChar]
GLframe.v1 = v1[curChar]

GLframe.Draw 0, 0, areaW, areaH, bx+oX, by+oY

Else 'Same as above, but using DX variation
DXframe.setUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
DXframe.Draw 0, 0, areaW, areaH, bx+oX, by+oY
End If

angle:+ angleStep
'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
x:+ CosR * (cW[curChar]+spacing) * scaleX
y:+ SinR * (cW[curChar]+spacing) * scaleY

End If
Next

'Restore UVs
If isGL
GLframe.u0 = 0
GLframe.v0 = 0
GLframe.u1 = 1
GLframe.v1 = 1
Else
DXframe.SetUV (0,0,1,1)
End If
End Method

Method DrawBouncy(s$, x#, y#, angle#, angleStep#, mag#, centered:Byte = False, spacing# = 0)
Local i:Int,t:String

Local scaleX#,scaleY#
Local oX#,oY# 'Current Max2D Origin
Local rot# 'Current Max2D Rotation
Local sinR#,cosR#,sinP90#,cosP90#
Local areaW#,areaH#

Local curChar:Byte
Local isGL:Byte 'Boolean
Local GLframe:TGLImageFrame
Local DXframe:TD3D7ImageFrame
Local frame:Int = 0

GetOrigin oX,oY
GetScale scaleX,scaleY

rot = GetRotation()
sinR = Sin(rot)
cosR = Cos(rot)
sinP90 = Sin(rot+90)
cosP90 = Cos(rot+90)


If TGLImageFrame(image.frame(frame))
isGL = True
GLframe = TGLImageFrame(image.frame(frame))
Else
isGL = False
DXframe = TD3D7ImageFrame(image.frame(frame))
End If

'Center text horizontally?
Local ln:Float = 0
If centered
'Get string length
For i = 0 Until s.length
If s[i] = 32
ln:+ blockHeight*.3
Else If char[s[i]]
ln:+ cW[s[i]]+spacing
End If
Next
ln:- spacing 'remove last unwanted space

ln = ln*scaleX *.5
x:- cosR*ln
y:- sinR*ln
End If

Local spaceValX# = cosR * blockHeight * .3 * scaleX
Local spaceValY# = sinR * blockHeight * .3 * scaleY

Local bx#,by#,bMag#

'Draw each letter in the string...
For i = 0 Until s.length

'Space character?
'blockHeight*.3 *seems* to be an ok value for spaces
If s[i] = 32
x:+ spaceValX
y:+ spaceValY
End If

'If our loaded bitmap font has this character...
If char[s[i]] And s[i]<>32
curChar = s[i]

bMag = Abs(Sin(angle)) * mag * scaleY
bx = x - cosP90 * bMag
by = y - sinP90 * bMag

areaW = cW[curChar]
areaH = blockHeight

'Draw this character
If isGL
'Point UVs to character in FonText Bitmap..
GLframe.u0 = u0[curChar]
GLframe.v0 = v0[curChar]
GLframe.u1 = u1[curChar]
GLframe.v1 = v1[curChar]

GLframe.Draw 0, 0, areaW, areaH, bx+oX, by+oY

Else 'Same as above, but using DX variation
DXframe.setUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
DXframe.Draw 0, 0, areaW, areaH, bx+oX, by+oY
End If

angle:+ angleStep
'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
x:+ CosR * (cW[curChar]+spacing) * scaleX
y:+ SinR * (cW[curChar]+spacing) * scaleY

End If
Next

'Restore UVs
If isGL
GLframe.u0 = 0
GLframe.v0 = 0
GLframe.u1 = 1
GLframe.v1 = 1
Else
DXframe.SetUV (0,0,1,1)
End If
End Method


Method DrawVertical(s:String, x:Float, y:Float, centered:Byte = False, spacing:Float = 0)
Local i:Int,t:String
Local scaleX#,scaleY#
Local oX#,oY# 'Current Max2D Origin
Local rot# 'Current Max2D Rotation

'Look UPs
Local sinR#,cosR#,sinP90#,cosP90#
Local areaW#,areaH#

Local curChar:Byte
Local isGL:Byte 'Boolean
Local GLframe:TGLImageFrame
Local DXframe:TD3D7ImageFrame
Local frame:Int = 0

GetOrigin oX,oY
GetScale scaleX,scaleY

rot = GetRotation()
sinR = Sin(rot)
cosR = Cos(rot)
sinP90# = Sin(rot+90)
cosP90# = Cos(rot+90)


If TGLImageFrame(image.frame(frame))
isGL = True
GLframe = TGLImageFrame(image.frame(frame))
Else
isGL = False
DXframe = TD3D7ImageFrame(image.frame(frame))
End If

'Center the Vertical text so it appears
'nicely centered

'Find widest character
Local bc:Float = 0
For i = 0 Until s.length
If cW[s[i]] > bc Then bc = cW[s[i]]
Next

'build an offset array based of widest char
Local ofs:Float[255]
For i = 0 Until s.length
ofs[s[i]] = (bc - cW[s[i]]) * .5
Next


'ln = bc*scaleX *.5
If centered
x:- cosR*(bc*.5) * scaleX
y:- sinR*(bc*.5) * scaleY
End If

Local spaceX# = cosP90 * (blockHeight+spacing) * scaleX
Local spaceY# = sinP90 * (blockHeight+spacing) * scaleY

Local bx#,by#

'Draw each letter in the string...
For i = 0 Until s.length

'Space character?
'blockHeight/3 *seems* to be an ok value for spaces
'for Vertical text, move the position down
If s[i] = 32
x:+ spaceX
y:+ spaceY
End If

If char[s[i]] And s[i]<>32
curChar = s[i]

areaW = cW[curChar]
areaH = blockHeight

bx = x
by = y

bx:+ cosR* ofs[curChar] * scaleX
by:+ sinR* ofs[curChar] * scaleY

'Draw this character
If isGL
'Point UVs to character in FonText Bitmap..
GLframe.u0 = u0[curChar]
GLframe.v0 = v0[curChar]
GLframe.u1 = u1[curChar]
GLframe.v1 = v1[curChar]

GLframe.Draw 0, 0, areaW, areaH, x+oX, y+oY

Else 'Same as above, but using DX variation
DXframe.setUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
DXframe.Draw 0, 0, areaW, areaH, bx+oX, by+oY
End If

'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
x:+ spaceX
y:+ spaceY

End If
Next

'Restore UVs
If isGL
GLframe.u0 = 0
GLframe.v0 = 0
GLframe.u1 = 1
GLframe.v1 = 1
Else
DXframe.SetUV (0,0,1,1)
End If
End Method

Method DrawWobble(s$, x#, y#, angle#, angleStep#, mag#, centered:Byte = False, spacing# = 0)
Local i:Int,t:String

Local scaleX#,scaleY#
Local oX#,oY# 'Current Max2D Origin
Local rot# 'Current Max2D Rotation
Local sinR#,cosR#,sinP90#,cosP90#
Local areaW#,areaH#

Local curChar:Byte
Local isGL:Byte 'Boolean
Local GLframe:TGLImageFrame
Local DXframe:TD3D7ImageFrame
Local frame:Int = 0

GetOrigin oX,oY
GetScale scaleX,scaleY

rot = GetRotation()
sinR = Sin(rot)
cosR = Cos(rot)
sinP90 = Sin(rot+90)
cosP90 = Cos(rot+90)


If TGLImageFrame(image.frame(frame))
isGL = True
GLframe = TGLImageFrame(image.frame(frame))
Else
isGL = False
DXframe = TD3D7ImageFrame(image.frame(frame))
End If

'Center text horizontally?
Local ln:Float = 0
If centered
'Get string length
For i = 0 Until s.length
If s[i] = 32
ln:+ blockHeight*.3
Else If char[s[i]]
ln:+ cW[s[i]]+spacing
End If
Next
ln:- spacing 'remove last unwanted space

ln = ln*scaleX *.5
x:- cosR*ln
y:- sinR*ln
End If

Local spaceValX# = cosR * blockHeight * .3 * scaleX
Local spaceValY# = sinR * blockHeight * .3 * scaleY

Local bx#,by#

'Draw each letter in the string...
For i = 0 Until s.length

'Space character?
'blockHeight*.3 *seems* to be an ok value for spaces
If s[i] = 32
x:+ spaceValX
y:+ spaceValY
End If

'If our loaded bitmap font has this character...
If char[s[i]] And s[i]<>32
curChar = s[i]

bx = x + Cos(angle) * mag * scaleX
by = y + Sin(angle) * mag * scaleY

areaW = cW[curChar]
areaH = blockHeight

'Draw this character
If isGL
'Point UVs to character in FonText Bitmap..
GLframe.u0 = u0[curChar]
GLframe.v0 = v0[curChar]
GLframe.u1 = u1[curChar]
GLframe.v1 = v1[curChar]
GLframe.Draw 0, 0, areaW, areaH, bx+oX, by+oY

Else 'Same as above, but using DX variation
DXframe.setUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
DXframe.Draw 0, 0, areaW, areaH, bx+oX, by+oY
End If

angle:+ angleStep
'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
x:+ CosR * (cW[curChar]+spacing) * scaleX
y:+ SinR * (cW[curChar]+spacing) * scaleY

End If
Next

'Restore UVs
If isGL
GLframe.u0 = 0
GLframe.v0 = 0
GLframe.u1 = 1
GLframe.v1 = 1
Else
DXframe.SetUV (0,0,1,1)
End If
End Method


Method DrawSineSize(s$, x#, y#, angle#, angleStep#, mag#, centered:Byte = False, spacing# = 0)
Local i:Int,t:String

Local scaleX#,scaleY#
Local oX#,oY# 'Current Max2D Origin
Local rot# 'Current Max2D Rotation
Local sinR#,cosR#,sinP90#,cosP90#
Local areaW#,areaH#

Local curChar:Byte
Local isGL:Byte 'Boolean
Local GLframe:TGLImageFrame
Local DXframe:TD3D7ImageFrame
Local frame:Int = 0

GetOrigin oX,oY
GetScale scaleX,scaleY

rot = GetRotation()
sinR = Sin(rot)
cosR = Cos(rot)
sinP90 = Sin(rot+90)
cosP90 = Cos(rot+90)


If TGLImageFrame(image.frame(frame))
isGL = True
GLframe = TGLImageFrame(image.frame(frame))
Else
isGL = False
DXframe = TD3D7ImageFrame(image.frame(frame))
End If

'Center text horizontally?
Local ln:Float = 0
If centered
'Get string length
For i = 0 Until s.length
If s[i] = 32
ln:+ blockHeight*.3
Else If char[s[i]]
ln:+ cW[s[i]]+spacing
End If
Next
ln:- spacing 'remove last unwanted space

ln = ln*scaleX *.5
x:- cosR*ln
y:- sinR*ln
End If

Local spaceValX# = cosR * blockHeight * .3 * scaleX
Local spaceValY# = sinR * blockHeight * .3 * scaleY

Local bx#,by#
Local sizeX#,sizeY#
mag:* .01
Local ah#,aw#

'Draw each letter in the string...
For i = 0 Until s.length

'Space character?
'blockHeight*.3 *seems* to be an ok value for spaces
If s[i] = 32
x:+ spaceValX
y:+ spaceValY
End If

'If our loaded bitmap font has this character...
If char[s[i]] And s[i]<>32
curChar = s[i]

areaW = cW[curChar]' +
areaH = blockHeight' +
aw = areaW + (Sin(angle)*cW[curChar]*mag)
ah = areaH + (Sin(angle)*blockHeight * mag)

bx=x
by=y

bx:+ cosR* (areaW - aw) * .5 * scaleX
by:+ sinR* (areaW - aw) * .5 * scaleX

bx:+ cosP90* (areaH - ah) * .5 * scaleY
by:+ sinP90* (areaH - ah) * .5 * scaleY


'Draw this character
If isGL
'Point UVs to character in FonText Bitmap..
GLframe.u0 = pX[curChar] * iwM
GLframe.v0 = pY[curChar] * ihM
GLframe.u1 = (pX[curChar]+areaW) * iwM
GLframe.v1 = (pY[curChar]+areaH) * ihM

GLframe.Draw 0, 0, aw, ah, bx+oX, by+oY

Else 'Same as above, but using DX variation
DXframe.setUV(pX[curChar]*iwM, pY[curChar]*ihM, (pX[curChar]+areaW)*iwM, (pY[curChar]+areaH)*ihM)
DXframe.Draw 0, 0, aw, ah, bx+oX, by+oY
End If

angle:+ angleStep
'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
x:+ CosR * (cW[s[i]]+spacing) * scaleX
y:+ SinR * (cW[s[i]]+spacing) * scaleY

End If
Next

SetScale scaleX,scaleY

'Restore UVs
If isGL
GLframe.u0 = 0
GLframe.v0 = 0
GLframe.u1 = 1
GLframe.v1 = 1
Else
DXframe.SetUV (0,0,1,1)
End If
End Method

Method DrawSwing(s$, x#, y#, angle#, angleStep#, mag#, centered:Byte = False, spacing# = 0)
Local i:Int,t:String

Local scaleX#,scaleY#
Local oX#,oY# 'Current Max2D Origin
Local rot# 'Current Max2D Rotation
Local sinR#,cosR#,sinP90#,cosP90#
Local areaW#,areaH#

Local curchar:Byte
Local isGL:Byte 'Boolean
Local GLframe:TGLImageFrame
Local DXframe:TD3D7ImageFrame
Local frame:Int = 0
Local hX#,hY#

GetOrigin oX,oY
GetScale scaleX,scaleY

rot = GetRotation()
sinR = Sin(rot)
cosR = Cos(rot)
sinP90 = Sin(rot+90)
cosP90 = Cos(rot+90)


If TGLImageFrame(image.frame(frame))
isGL = True
GLframe = TGLImageFrame(image.frame(frame))
Else
isGL = False
DXframe = TD3D7ImageFrame(image.frame(frame))
End If

'Center text horizontally?
Local ln:Float = 0
If centered
'Get string length
For i = 0 Until s.length
If s[i] = 32
ln:+ blockHeight*.3
Else If char[s[i]]
ln:+ cW[s[i]]+spacing
End If
Next
ln:- spacing 'remove last unwanted space

ln:* scaleX *.5
x:- cosR*ln
y:- sinR*ln
End If

Local spaceValX# = cosR * blockHeight * .3 * scaleX
Local spaceValY# = sinR * blockHeight * .3 * scaleY
Local bx#,by#

'Draw each letter in the string...
For i = 0 Until s.length

'Space character?
'blockHeight*.3 *seems* to be an ok value for spaces
If s[i] = 32
x:+ spaceValX
y:+ spaceValY
End If

SetRotation rot+Sin(angle)*mag
'If our loaded bitmap font has this character...
If char[s[i]] And s[i]<>32
curChar = s[i]

hX = -cW[curChar]*.5
hY = 0

bx = x - cosR*hX*scaleX '- cosR * bMag
by = y - sinR*hX*scaleY'- sinR * bMag

areaW = cW[curChar]
areaH = blockHeight

'Draw this character
If isGL
'Point UVs to character in FonText Bitmap..
GLframe.u0 = u0[curChar]
GLframe.v0 = v0[curChar]
GLframe.u1 = u1[curChar]
GLframe.v1 = v1[curChar]

GLframe.Draw hX, hY, areaW+hX, areaH, bx+oX, by+oY

Else 'Same as above, but using DX variation
DXframe.setUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
DXframe.Draw hX, hY, areaW+hX, areaH, bx+oX, by+oY
End If

angle:+ angleStep
'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
x:+ cosR * (cW[curChar]+spacing) * scaleX
y:+ sinR * (cW[curChar]+spacing) * scaleY

End If
Next

SetRotation rot
'Restore UVs
If isGL
GLframe.u0 = 0
GLframe.v0 = 0
GLframe.u1 = 1
GLframe.v1 = 1
Else
DXframe.SetUV (0,0,1,1)
End If
End Method
End Type

Type aFonText
Global list:TList

Field link:TLink

Field sX#,sY#
Field sT%
Field aT%
Field dT%
Field rT%
Field str$

Field srcX:Float[],srcY:Float[]
Field dstX:Float[],dstY:Float[]
Field vX:Float[],vY:Float[]

Field f:FonText

Field thisScaleX#,thisScaleY#
Field thisOriginX#,thisOriginY#
Field thisRotation#
Field textCenter#
Field textLength#

Method New()
If Not list Then list = CreateList()
link = ListAddLast(list,Self)
End Method

Method Destroy()
RemoveLink link
End Method

Function Create(text$, ft:FonText, pX#, pY#, start%, attack%,..
duration%, _release%, spacing#, centered:Byte,dir:Int)

Local a:aFonText = New aFonText
Local time% = MilliSecs()
a.str = text
a.f = ft
a.sX = pX
a.sY = pY
a.sT = time + start
a.aT = time + start + attack
a.dT = time + start + attack + duration
a.rT = time + start + attack + duration + _release

a.thisRotation = GetRotation()
GetOrigin a.thisOriginX,a.thisOriginY
GetScale a.thisScaleX,a.thisScaleY

Local sLen% = text.length
a.srcX = New Float[sLen]
a.srcY = New Float[sLen]

a.dstX = New Float[sLen]
a.dstY = New Float[sLen]

a.vX = New Float[sLen]
a.vY = New Float[sLen]



Local i:Int,t:String

Local sinR#,cosR#,sinP90#,cosP90#
Local areaW#,areaH#

Local curChar:Byte

sinR = Sin(a.thisRotation)
cosR = Cos(a.thisRotation)
sinP90 = Sin(a.thisRotation+90)
cosP90 = Cos(a.thisRotation+90)


'Center text horizontally?
Local ln:Float = 0
'If centered
'Get string length
For i = 0 Until text.length
If text[i] = 32
ln:+ a.f.blockHeight*.3
Else If a.f.char[text[i]]
ln:+ a.f.cW[text[i]]+spacing
End If
Next

ln:- spacing 'remove last unwanted space

a.textLength = ln
'ln = ln * a.thisScaleX *.5
ln:* .5
If centered
pX:- cosR*ln * a.thisScaleX
pY:- sinR*ln * a.thisScaleY
End If

Local spaceValX# = cosR * a.f.blockHeight * .3 * a.thisScaleX
Local spaceValY# = sinR * a.f.blockHeight * .3 * a.thisScaleY

'Calc each characters destination, and store it
For i = 0 Until text.length

'Space character?
'blockHeight*.3 *seems* to be an ok value for spaces
If text[i] = 32
pX:+ spaceValX
pY:+ spaceValY
End If

'If our loaded bitmap font has this character...
If a.f.char[text[i]] And text[i]<>32
curChar = text[i]

areaW = a.f.cW[curChar]
areaH = a.f.blockHeight

a.dstX[i] = pX+a.thisOriginX
a.dstY[i] = pY+a.thisOriginY
'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
pX:+ CosR * (a.f.cW[curChar]+spacing) * a.thisScaleX
pY:+ SinR * (a.f.cW[curChar]+spacing) * a.thisScaleY

End If
Next


'setup src & velocity vectors
For i = 0 Until text.length
Select dir
Case 0
Local ix:Int = Int(a.str.length*.5-.5)
If ix < 0 ix = 0
a.srcX[i] = a.dstX[ix]'a.sX + cosR * a.textCenter
a.srcY[i] = a.dstY[ix]'sY + sinR * a.textCenter
Case -1
a.srcX[i] = a.dstX[0]
a.srcY[i] = a.dstY[0]
Case 1
a.srcX[i] = a.dstX[a.str.length-1]
a.srcY[i] = a.dstY[a.str.length-1]
End Select

a.vX[i] = a.srcX[i]-a.dstX[i]
a.vY[i] = a.srcY[i]-a.dstY[i]

Next
End Function



Function Update()
If Not list Then Return

Local time%
Local a:aFonText
Local oldRot#,oldScaleX#,oldScaleY#,oldOriginX#,oldOriginY#
Local oldAlpha# = GetAlpha()
Local oldBlend% = GetBlend()

oldRot = GetRotation()
GetScale oldScaleX,oldScaleY
GetOrigin oldOriginX,oldOriginY

Local i:Int
Local isGL:Byte

Local tx#,ty#,areaw#,areah#
Local curChar:Byte
Local GLframe:TGLImageFrame
Local DXframe:TD3D7ImageFrame

SetBlend ALPHABLEND
For a = EachIn aFonText.list
SetRotation a.thisRotation
SetScale a.thisScaleX,a.thisScaleY
SetOrigin a.thisOriginX,a.thisOriginY

If TGLImageFrame(a.f.image.frame(0))
isGL = True
GLframe = TGLImageFrame(a.f.image.frame(0))
Else
isGL = False
DXframe = TD3D7ImageFrame(a.f.image.frame(0))
End If

If time > a.rT
a.Destroy()
a = Null
End If

time = MilliSecs()
If a And time >= a.sT And time <= a.rT
Local elap#
Local al#

For i = 0 Until a.str.length
If time >= a.sT And time < a.aT
elap = (Float((time - a.sT)) / (a.aT-a.sT))
al = elap
elap = 1.0 - elap
elap = 1.0 - Cos(elap*90)

tx = a.dstX[i] + a.vX[i]*elap
tY = a.dstY[i] + a.vY[i]*elap'srcY[i]*elap'dstY[i] - a.srcY[i]*elap '+ a.vY[i]*elap

SetAlpha 1.0 - elap
'DrawText "Attack",0,0
Else If time >=a.aT And time <= a.dT
SetAlpha 1
'pause
tx = a.dstX[i]
ty = a.dstY[i]
'DrawText "Duration",0,0
Else If time > a.dT And time <= a.rT
tx = a.dstX[i]
ty = a.dstY[i]' + (Abs(time - a.dT) * .05)

elap = 1.0 - (Float(time - a.dT)) / (a.rT-a.dT)
SetAlpha elap
'DrawText "Release",0,0

End If

curChar = a.str[i]

areaW = a.f.cW[curChar]
areaH = a.f.blockHeight
If isGL
'Point UVs to character in FonText Bitmap..
GLframe.u0 = a.f.u0[curChar]
GLframe.v0 = a.f.v0[curChar]
GLframe.u1 = a.f.u1[curChar]
GLframe.v1 = a.f.v1[curChar]

GLframe.Draw 0, 0, areaW, areaH, tx, ty

Else 'Same as above, but using DX variation
DXframe.setUV(a.f.u0[curchar], a.f.v0[curChar], a.f.u1[curChar], a.f.v1[curChar])
DXframe.Draw 0, 0, areaW, areaH, tx, ty
End If
Next
End If
Next

SetBlend oldBlend
SetAlpha oldAlpha
SetRotation oldRot
SetScale oldScaleX,oldScaleY
SetOrigin oldOriginX,oldOriginY
End Function

End Type


')


Beaker(Posted 2007) [#36]
It's that time of year once again, so *bump*. :)


slenkar(Posted 2007) [#37]
thanks, ill be able to use it on christmas day


jhocking(Posted 2007) [#38]
oo I should try using FONText in BlitzMax. I've been using it for years with Blitz3D and it worked excellent; meanwhile in BlitzMax the Max2D text commands are great for my needs so far, but I will probably want snazzier text eventually.


Beaker(Posted 2008) [#39]
Merry Christmas again!


GaryV(Posted 2008) [#40]
Wow! This is going to be very useful! Thank you.


Kev(Posted 2008) [#41]
I missed this 2 years ago ;) so thanks 2 years later

kev


LineOf7s(Posted 2008) [#42]
That
Plugin to create Fontext mesh directly in gile[s]
has a shiny new appeal this Christmas, so that deserves a thankyou too.

Nice one, Mr Beaker. :o)

PS: This is gonna sound scroungy in this context, but whatever happened to that fancy schmancy "dissolve" code (based on greyscale gradients, IIRC) you were playing with waaaay back in the 2D days? Did you ever end up using it something like you were planning to?


Beaker(Posted 2008) [#43]
LineOf7s - I did use it for a presentation display thing a few years back. But not really had much use for it otherwise. The problem with it for games is that you have to set your screen res in stone beforehand and then never change it, which could be a problem for distributed fullscreen games etc. There are several ways to make it more flexible but I never bothered. You are welcome to it if you want it.

Please note that the gile[s] plugin probably only works in v1.36. I've never tried it in the newer 2.0 beta version, if anyone wants to give it a go.


LineOf7s(Posted 2008) [#44]
Thankyou for the offer, but apart from noting that it was an especially cool effect, I haven't yet been able to think what I'd use it for. :o) I'm just glad you did actually use it at some stage, because you were quite chuffed with it at the time and it was, after all, especially cool.


plash(Posted 2008) [#45]
Did I miss a working link to the BlitzMax module?


tonyg(Posted 2008) [#46]
The source is listed earlier.


plash(Posted 2008) [#47]
Thanks, I'll turn the code into a SuperStrict module and repost..


plash(Posted 2008) [#48]
SuperStrict module (note the changes from FonText to TFonText and aFonText to TAnimFonText):
format_codebox('
SuperStrict

?win32
Import brl.D3D7Max2D
?
Import brl.GLMax2D

Rem
bbdoc: FonText
End Rem
Module beaker.FonText

ModuleInfo "Version: 1.00"
ModuleInfo "Author: Beaker (converted to standard SuperStrict module by Plash)"

ModuleInfo "History: Changed FonText to TFonText, and aFonText to TAnimFonText"
ModuleInfo "History: Removed dependency on BRL.Retro by using slicing, changed all variable type definitions to full-length."

Type TFonText
Field image:TImage
Field blockHeight:Int
Field char:Byte[255] 'Boolean for each ASCII character, True if the FonText includes it, False if not
Field maskColor:Int
Field packed:Int

Field pX:Float[255] 'Position X
Field pY:Float[255] 'Position Y
Field cW:Int[255] 'Width

Field sinL:Float[360] 'not used yet
Field cosL:Float[360] '""

Field iwM:Float 'Image width & height multipliers used in
Field ihM:Float 'functions to optimise UV calculation speed

Field u0:Float[255]
Field v0:Float[255]

Field u1:Float[255]
Field v1:Float[255]

Function Create:TFonText(file:String, Flags:Int = -1)
Local img:TImage = LoadImage(file, Flags)
If Not img RuntimeError("Could not load Image " + file)
SetImageHandle(img, 0, 0)

Local ini:TStream = OpenFile(file[..file.Length - 3] + "ini")
If Not ini RuntimeError("Could not find " + file[..file.Length - 3] + "ini")

Local f:TFonText = New(TFonText)
f.Image = img

f.iwM = 1.0 / img.width
f.ihM = 1.0 / img.height

'Get BlockSize (height)
Local r:String

'Ignore first 3 lines
ini.ReadLine()
ini.ReadLine()
ini.ReadLine()

'Get MaskColor (needed?)
r = ini.ReadLine()
f.maskColor = Int(r[10..])

'Packed Font?
r = ini.ReadLine()
f.packed = Int(r[r.Length - 1..])

'Find [text] line
r = ReadLine(ini)
While r <> "[text]"
r = ini.ReadLine()
Wend

'Block Height
r = ini.ReadLine()
f.blockHeight = Int(r[10..])

'Count Characters
r = ini.ReadLine()
While r<>"[charset]"
r = ini.ReadLine()
Wend

'Store this location
Local location:Int = ini.Pos() 'StreamPos(ini)

'do the count
Local count:Int = 0
While Not Eof(ini)
r = ini.ReadLine()
count:+1
Wend

'Back to the Characters...
'SeekStream(ini, location)
ini.seek(location)

Local i:Int,j:Int,s:String,t:String
Local cur:Byte

'Parse each characters position & width
For i = 0 Until count
r = ini.ReadLine()
cur = r[0]
f.char[cur] = True

'Position X
j = 3
s = ""
t = r[j - 1..j]
While t<>","
s:+ t
j:+1
t = r[j - 1..j]
Wend
f.pX[cur] = Float(s)

'Position Y
j:+1
s = ""
t = r[j - 1..j]
While t<>","
s:+t
j:+1
t = r[j - 1..j]
Wend
f.pY[cur] = Float(s)

'Character Width
j:+1
s = ""
t = r[j - 1..j]
While t <> ","
s:+t
j:+1
If j > r.Length Exit
t = r[j - 1..j]
Wend
f.cW[cur] = Int(s)

'Adjust packing if the font isn't packed (trim space either side of character)
If Not f.packed
f.pX[cur]:+(f.blockheight - f.cW[cur]) *.5
End If

f.u0[cur] = f.pX[cur] * f.iwM
f.v0[cur] = f.pY[cur] * f.ihM
f.u1[cur] = (f.pX[cur] + f.cW[cur]) * f.iwM
f.v1[cur] = (f.pY[cur] + f.blockHeight) * f.ihM
Next

ini.Close()

Return(f)

End Function

Method DrawJustified(s:String, X:Float, Y:Float, centered:Byte, spacing:Float, lineBreak:Float, scaleLB:Byte)
Local i:Int, t:String

Local ScaleX:Float, ScaleY:Float
Local oX:Float, oY:Float
Local rot:Float
Local sinR:Float, cosR:Float, sinP90:Float, cosP90:Float
Local areaW:Float, areaH:Float

Local curChar:Byte
Local isGL:Byte 'Boolean
Local GLframe:TGLImageFrame
?win32
Local DXframe:TD3D7ImageFrame
?
Local frame:Int = 0
Local xDrawn:Float = 0

GetOrigin(oX, oY)
GetScale(ScaleX, ScaleY)

rot = GetRotation()
sinR = Sin(rot)
cosR = Cos(rot)
sinP90 = Sin(rot + 90)
cosP90 = Cos(rot + 90)

If TGLImageFrame(image.frame(frame))
isGL = True
GLframe = TGLImageFrame(Image.Frame(Frame))
?win32
Else
isGL = False
DXframe = TD3D7ImageFrame(Image.Frame(Frame))
?
End If

If scaleLB Then lineBreak:*ScaleX

'Center text horizontally?
Local ln:Float = 0
If centered
X:-cosR * lineBreak *.5
Y:-sinR * lineBreak *.5
End If

Local newWord:Int = 0
Local wordLen:Float
Local tw:Int
Local lastLen:Int = 0

Local vSpacing:Int = blockHeight *.8

'Draw each letter in the string...
For i = 0 Until s.Length
'Check for whole word, we don't want to break them up
If lastLen <= 0 And s[i] <> 32 And lineBreak > 0
lastLen = 0
For newWord = i Until s.Length
lastLen:+1
If s[newWord] = 32 Or s[newWord] = 13 Exit
Next

wordLen = 0
'Was there a word?
If newWord > 0
For tw = i Until newWord
wordLen:+(cW[s[tw] ] + spacing) * ScaleX
Next
End If

'Check the length doesn't go over the lineBreak limit
If xDrawn + wordLen > lineBreak
'goto next line

'move back to beginning
X:-cosR * xDrawn
Y:-sinR * xDrawn

'move down
X:+cosP90 * vSpacing * ScaleX
Y:+sinP90 * vSpacing * ScaleY
lastLen = 0
xDrawn = 0
End If
End If

'Space character?
'blockHeight/3 *seems* to be an ok value for spaces
If s[i] = 32 ' And xDrawn>2
X:+cosR * blockHeight *.3 * ScaleX
Y:+sinR * blockHeight *.3 * ScaleY
xDrawn:+blockHeight *.3 * ScaleX
End If

'Linebreak?
If s[i] = 13

'goto next line

'move back to beginning
X:-cosR * xDrawn
Y:-sinR * xDrawn

'move down
X:+cosP90 * vSpacing * ScaleX
Y:+sinP90 * vSpacing * ScaleY
lastLen = 0
xDrawn = 0

End If

'If our loaded bitmap font has this character...
If char[s[i] ] ' And s[i]<>32
curChar = s[i]

lastLen:-1

areaW = cW[curChar]
areaH = blockHeight

'Draw this character
If isGL
'Point UVs to character in FonText Bitmap..
GLframe.u0 = u0[curChar]
GLframe.v0 = v0[curChar]
GLframe.u1 = u1[curChar]
GLframe.v1 = v1[curChar]

GLframe.Draw(0, 0, areaW, areaH, X + oX, Y + oY)

?win32
Else 'Same as above, but using DX variation
DXframe.SetUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
DXframe.Draw(0, 0, areaW, areaH, X + oX, Y + oY)
?
End If

'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
x:+ cosR * (cW[curChar]+spacing) * scaleX
y:+ sinR * (cW[curChar]+spacing) * scaleY
xDrawn:+ (cW[curChar]+spacing) * scaleX
End If
Next

'Restore UVs
If isGL
GLframe.u0 = 0
GLframe.v0 = 0
GLframe.u1 = 1
GLframe.v1 = 1
Else
DXframe.SetUV(0, 0, 1, 1)
End If
End Method

Method Draw(s:String, X:Float, Y:Float, centered:Byte = False, spacing:Float = 0)
Local i:Int, t:String

Local ScaleX:Float, ScaleY:Float
Local oX:Float, oY:Float 'Current Max2D Origin
Local rot:Float 'Current Max2D Rotation
Local sinR:Float, cosR:Float, sinP90:Float, cosP90:Float
Local areaW:Float, areaH:Float

Local curChar:Byte
Local isGL:Byte 'Boolean
Local GLframe:TGLImageFrame
?win32
Local DXframe:TD3D7ImageFrame
?
Local frame:Int = 0

GetOrigin(oX, oY)
GetScale(ScaleX, ScaleY)

rot = GetRotation()
sinR = Sin(rot)
cosR = Cos(rot)
sinP90 = Sin(rot + 90)
cosP90 = Cos(rot + 90)

If TGLImageFrame(Image.Frame(Frame))
isGL = True
GLframe = TGLImageFrame(Image.Frame(Frame))
?win32
Else
isGL = False
DXframe = TD3D7ImageFrame(Image.Frame(Frame))
?
End If

'Center text horizontally?
Local ln:Float = 0
If centered
'Get string length
For i = 0 Until s.length
If s[i] = 32
ln:+ blockHeight*.3
Else If char[s[i]]
ln:+ cW[s[i]]+spacing
End If
Next
Ln:-spacing 'remove last unwanted space

Ln = Ln * ScaleX *.5
X:-cosR * Ln
Y:-sinR * Ln
End If

Local spaceValX:Float = cosR * blockHeight *.3 * ScaleX
Local spaceValY:Float = sinR * blockHeight *.3 * ScaleY

'Draw each letter in the string...
For i = 0 Until s.length

'Space character?
'blockHeight*.3 *seems* to be an ok value for spaces
If s[i] = 32
X:+spaceValX
Y:+spaceValY
End If

'If our loaded bitmap font has this character...
If char[s[i] ] And s[i] <> 32
curChar = s[i]

areaW = cW[curChar]
areaH = blockHeight

'Draw this character
If isGL
'Point UVs to character in FonText Bitmap..
GLframe.u0 = u0[curChar]
GLframe.v0 = v0[curChar]
GLframe.u1 = u1[curChar]
GLframe.v1 = v1[curChar]

GLframe.Draw(0, 0, areaW, areaH, X + oX, Y + oY)

?win32
Else 'Same as above, but using DX variation
DXframe.setUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
DXframe.Draw(0, 0, areaW, areaH, X + oX, Y + oY)
?
End If

'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
X:+CosR * (cW[curChar] + spacing) * ScaleX
Y:+SinR * (cW[curChar] + spacing) * ScaleY

End If
Next

'Restore UVs
If isGL
GLframe.u0 = 0
GLframe.v0 = 0
GLframe.u1 = 1
GLframe.v1 = 1
?win32
Else
DXframe.SetUV(0, 0, 1, 1)
?
End If
End Method

Method DrawWave(s:String, X:Float, Y:Float, angle:Float, angleStep:Float, mag:Float, centered:Byte = False, spacing:Float = 0)
Local i:Int, t:String

Local ScaleX:Float, ScaleY:Float
Local oX:Float, oY:Float 'Current Max2D Origin
Local rot:Float 'Current Max2D Rotation
Local sinR:Float, cosR:Float, sinP90:Float, cosP90:Float
Local areaW:Float, areaH:Float

Local curChar:Byte
Local isGL:Byte 'Boolean
Local GLframe:TGLImageFrame
?win32
Local DXframe:TD3D7ImageFrame
?
Local frame:Int = 0

GetOrigin(oX, oY)
GetScale(ScaleX, ScaleY)

rot = GetRotation()
sinR = Sin(rot)
cosR = Cos(rot)
sinP90 = Sin(rot + 90)
cosP90 = Cos(rot + 90)

If TGLImageFrame(Image.Frame(Frame))
isGL = True
GLframe = TGLImageFrame(Image.Frame(Frame))
?win32
Else
isGL = False
DXframe = TD3D7ImageFrame(Image.Frame(Frame))
?
End If

'Center text horizontally?
Local ln:Float = 0
If centered
'Get string length
For i = 0 Until s.length
If s[i] = 32
Ln:+blockHeight *.3
Else If char[s[i] ]
Ln:+cW[s[i] ] + spacing
End If
Next
ln:- spacing 'remove last unwanted space

Ln = Ln * ScaleX *.5
X:-cosR * Ln
Y:-sinR * Ln
End If

Local spaceValX:Float = cosR * blockHeight *.3 * ScaleX
Local spaceValY:Float = sinR * blockHeight *.3 * ScaleY

Local bx:Float, by:Float, bMag:Float

'Draw each letter in the string...
For i = 0 Until s.length

'Space character?
'blockHeight*.3 *seems* to be an ok value for spaces
If s[i] = 32
X:+spaceValX
Y:+spaceValY
End If

'If our loaded bitmap font has this character...
If char[s[i] ] And s[i] <> 32
curChar = s[i]

bMag = Sin(angle) * mag * ScaleY
bx = X - cosP90 * bMag
by = Y - sinP90 * bMag

areaW = cW[curChar]
areaH = blockHeight

'Draw this character
If isGL
'Point UVs to character in FonText Bitmap..
GLframe.u0 = u0[curChar]
GLframe.v0 = v0[curChar]
GLframe.u1 = u1[curChar]
GLframe.v1 = v1[curChar]

GLframe.Draw(0, 0, areaW, areaH, bx + oX, by + oY)

?win32
Else 'Same as above, but using DX variation
DXframe.SetUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
DXframe.Draw(0, 0, areaW, areaH, bx + oX, by + oY)
?
End If

angle:+angleStep
'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
X:+CosR * (cW[curChar] + spacing) * ScaleX
Y:+SinR * (cW[curChar] + spacing) * ScaleY

End If
Next

'Restore UVs
If isGL
GLframe.u0 = 0
GLframe.v0 = 0
GLframe.u1 = 1
GLframe.v1 = 1
?win32
Else
DXframe.SetUV(0, 0, 1, 1)
?
End If
End Method

Method DrawWiggle(s:String, X:Float, Y:Float, angle:Float, angleStep:Float, mag:Float, centered:Byte = False, spacing:Float = 0)
Local i:Int, t:String

Local ScaleX:Float, ScaleY:Float
Local oX:Float, oY:Float 'Current Max2D Origin
Local rot:Float 'Current Max2D Rotation
Local sinR:Float, cosR:Float, sinP90:Float, cosP90:Float
Local areaW:Float, areaH:Float

Local curChar:Byte
Local isGL:Byte 'Boolean
Local GLframe:TGLImageFrame
?win32
Local DXframe:TD3D7ImageFrame
?
Local frame:Int = 0

GetOrigin(oX, oY)
GetScale(ScaleX, ScaleY)

rot = GetRotation()
sinR = Sin(rot)
cosR = Cos(rot)
sinP90 = Sin(rot + 90)
cosP90 = Cos(rot + 90)

If TGLImageFrame(Image.Frame(Frame))
isGL = True
GLframe = TGLImageFrame(Image.Frame(Frame))
?win32
Else
isGL = False
DXframe = TD3D7ImageFrame(Image.Frame(Frame))
?
End If

'Center text horizontally?
Local ln:Float = 0
If centered
'Get string length
For i = 0 Until s.Length
If s[i] = 32
Ln:+blockHeight *.3
Else If char[s[i] ]
Ln:+cW[s[i] ] + spacing
End If
Next
Ln:-spacing 'remove last unwanted space

Ln = Ln * ScaleX *.5
X:-cosR * Ln
Y:-sinR * Ln
End If

Local spaceValX:Float = cosR * blockHeight *.3 * ScaleX
Local spaceValY:Float = sinR * blockHeight *.3 * ScaleY

Local bx:Float, by:Float, bMag:Float

'Draw each letter in the string...
For i = 0 Until s.length

'Space character?
'blockHeight*.3 *seems* to be an ok value for spaces
If s[i] = 32
X:+spaceValX
Y:+spaceValY
End If

'If our loaded bitmap font has this character...
If char[s[i] ] And s[i] <> 32
curChar = s[i]

bMag = Sin(angle) * mag * ScaleX
bx = X - cosR * bMag
by = Y - sinR * bMag

areaW = cW[curChar]
areaH = blockHeight

'Draw this character
If isGL
'Point UVs to character in FonText Bitmap..
GLframe.u0 = u0[curChar]
GLframe.v0 = v0[curChar]
GLframe.u1 = u1[curChar]
GLframe.v1 = v1[curChar]

GLframe.Draw(0, 0, areaW, areaH, bx + oX, by + oY)

?win32
Else 'Same as above, but using DX variation
DXframe.SetUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
DXframe.Draw(0, 0, areaW, areaH, bx + oX, by + oY)
?
End If

angle:+ angleStep
'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
X:+CosR * (cW[curChar] + spacing) * ScaleX
Y:+SinR * (cW[curChar] + spacing) * ScaleY

End If
Next

'Restore UVs
If isGL
GLframe.u0 = 0
GLframe.v0 = 0
GLframe.u1 = 1
GLframe.v1 = 1
?win32
Else
DXframe.SetUV(0, 0, 1, 1)
?
End If
End Method

Method DrawBouncy(s:String, X:Float, Y:Float, angle:Float, angleStep:Float, mag:Float, centered:Byte = False, spacing:Float = 0)
Local i:Int, t:String

Local ScaleX:Float, ScaleY:Float
Local oX:Float, oY:Float 'Current Max2D Origin
Local rot:Float 'Current Max2D Rotation
Local sinR:Float, cosR:Float, sinP90:Float, cosP90:Float
Local areaW:Float, areaH:Float

Local curChar:Byte
Local isGL:Byte 'Boolean
Local GLframe:TGLImageFrame
?win32
Local DXframe:TD3D7ImageFrame
?
Local frame:Int = 0

GetOrigin(oX, oY)
GetScale(ScaleX, ScaleY)

rot = GetRotation()
sinR = Sin(rot)
cosR = Cos(rot)
sinP90 = Sin(rot + 90)
cosP90 = Cos(rot + 90)

If TGLImageFrame(Image.Frame(Frame))
isGL = True
GLframe = TGLImageFrame(Image.Frame(Frame))
?win32
Else
isGL = False
DXframe = TD3D7ImageFrame(Image.Frame(Frame))
?
End If

'Center text horizontally?
Local ln:Float = 0
If centered
'Get string length
For i = 0 Until s.length
If s[i] = 32
Ln:+blockHeight *.3
Else If char[s[i] ]
Ln:+cW[s[i] ] + spacing
End If
Next
ln:- spacing 'remove last unwanted space

Ln = Ln * ScaleX *.5
X:-cosR * Ln
Y:-sinR * Ln
End If

Local spaceValX:Float = cosR * blockHeight *.3 * ScaleX
Local spaceValY:Float = sinR * blockHeight *.3 * ScaleY

Local bx:Float, by:Float, bMag:Float

'Draw each letter in the string...
For i = 0 Until s.length

'Space character?
'blockHeight*.3 *seems* to be an ok value for spaces
If s[i] = 32
X:+spaceValX
Y:+spaceValY
End If

'If our loaded bitmap font has this character...
If char[s[i] ] And s[i] <> 32
curChar = s[i]

bMag = Abs(Sin(angle)) * mag * ScaleY
bx = X - cosP90 * bMag
by = Y - sinP90 * bMag

areaW = cW[curChar]
areaH = blockHeight

'Draw this character
If isGL
'Point UVs to character in FonText Bitmap..
GLframe.u0 = u0[curChar]
GLframe.v0 = v0[curChar]
GLframe.u1 = u1[curChar]
GLframe.v1 = v1[curChar]

GLframe.Draw(0, 0, areaW, areaH, bx + oX, by + oY)

?win32
Else 'Same as above, but using DX variation
DXframe.SetUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
DXframe.Draw(0, 0, areaW, areaH, bx + oX, by + oY)
?
End If

angle:+ angleStep
'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
X:+CosR * (cW[curChar] + spacing) * ScaleX
Y:+SinR * (cW[curChar] + spacing) * ScaleY

End If
Next

'Restore UVs
If isGL
GLframe.u0 = 0
GLframe.v0 = 0
GLframe.u1 = 1
GLframe.v1 = 1
?win32
Else
DXframe.SetUV(0, 0, 1, 1)
?
End If
End Method

Method DrawVertical(s:String, X:Float, Y:Float, centered:Byte = False, spacing:Float = 0)
Local i:Int, t:String
Local ScaleX:Float, ScaleY:Float
Local oX:Float, oY:Float 'Current Max2D Origin
Local rot:Float 'Current Max2D Rotation

'Look UPs
Local sinR:Float, cosR:Float, sinP90:Float, cosP90:Float
Local areaW:Float, areaH:Float

Local curChar:Byte
Local isGL:Byte 'Boolean
Local GLframe:TGLImageFrame
?win32
Local DXframe:TD3D7ImageFrame
?

Local frame:Int = 0

GetOrigin(oX, oY)
GetScale(ScaleX, ScaleY)

rot = GetRotation()
sinR = Sin(rot)
cosR = Cos(rot)
sinP90:Float = Sin(rot + 90)
cosP90:Float = Cos(rot + 90)

If TGLImageFrame(Image.Frame(Frame))
isGL = True
GLframe = TGLImageFrame(Image.Frame(Frame))
?win32
Else
isGL = False
DXframe = TD3D7ImageFrame(Image.Frame(Frame))
?
End If

'Center the Vertical text so it appears
'nicely centered

'Find widest character
Local bc:Float = 0
For i = 0 Until s.length
If cW[s[i] ] > bc Then bc = cW[s[i] ]
Next

'build an offset array based of widest char
Local ofs:Float[255]
For i = 0 Until s.Length
ofs[s[i] ] = (bc - cW[s[i] ]) *.5
Next

'ln = bc*scaleX *.5
If centered
X:-cosR * (bc *.5) * ScaleX
Y:-sinR * (bc *.5) * ScaleY
End If

Local spaceX:Float = cosP90 * (blockHeight + spacing) * ScaleX
Local spaceY:Float = sinP90 * (blockHeight + spacing) * ScaleY

Local bx:Float, by:Float

'Draw each letter in the string...
For i = 0 Until s.length

'Space character?
'blockHeight/3 *seems* to be an ok value for spaces
'for Vertical text, move the position down
If s[i] = 32
X:+spaceX
Y:+spaceY
End If

If char[s[i] ] And s[i] <> 32
curChar = s[i]

areaW = cW[curChar]
areaH = blockHeight

bx = X
by = y

bx:+cosR * ofs[curChar] * ScaleX
by:+sinR * ofs[curChar] * ScaleY

'Draw this character
If isGL
'Point UVs to character in FonText Bitmap..
GLframe.u0 = u0[curChar]
GLframe.v0 = v0[curChar]
GLframe.u1 = u1[curChar]
GLframe.v1 = v1[curChar]

GLframe.Draw(0, 0, areaW, areaH, X + oX, Y + oY)

?win32
Else 'Same as above, but using DX variation
DXframe.SetUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
DXframe.Draw(0, 0, areaW, areaH, bx + oX, by + oY)
?
End If

'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
x:+ spaceX
y:+ spaceY

End If
Next

'Restore UVs
If isGL
GLframe.u0 = 0
GLframe.v0 = 0
GLframe.u1 = 1
GLframe.v1 = 1
?win32
Else
DXframe.SetUV(0, 0, 1, 1)
?
End If
End Method

Method DrawWobble(s:String, X:Float, Y:Float, angle:Float, angleStep:Float, mag:Float, centered:Byte = False, spacing:Float = 0)
Local i:Int,t:String

Local ScaleX:Float, ScaleY:Float
Local oX:Float, oY:Float 'Current Max2D Origin
Local rot:Float 'Current Max2D Rotation
Local sinR:Float, cosR:Float, sinP90:Float, cosP90:Float
Local areaW:Float, areaH:Float

Local curChar:Byte
Local isGL:Byte 'Boolean
Local GLframe:TGLImageFrame
?win32
Local DXframe:TD3D7ImageFrame
?
Local frame:Int = 0

GetOrigin(oX, oY)
GetScale(ScaleX, ScaleY)

rot = GetRotation()
sinR = Sin(rot)
cosR = Cos(rot)
sinP90 = Sin(rot + 90)
cosP90 = Cos(rot + 90)

If TGLImageFrame(image.frame(frame))
isGL = True
GLframe = TGLImageFrame(Image.Frame(Frame))
?win32
Else
isGL = False
DXframe = TD3D7ImageFrame(Image.Frame(Frame))
?
End If

'Center text horizontally?
Local ln:Float = 0
If centered
'Get string length
For i = 0 Until s.Length
If s[i] = 32
Ln:+blockHeight *.3
Else If char[s[i] ]
Ln:+cW[s[i] ] + spacing
End If
Next
Ln:-spacing 'remove last unwanted space

Ln = Ln * ScaleX *.5
X:-cosR * Ln
Y:-sinR * Ln
End If

Local spaceValX:Float = cosR * blockHeight *.3 * ScaleX
Local spaceValY:Float = sinR * blockHeight *.3 * ScaleY

Local bx:Float, by:Float

'Draw each letter in the string...
For i = 0 Until s.length

'Space character?
'blockHeight*.3 *seems* to be an ok value for spaces
If s[i] = 32
X:+spaceValX
Y:+spaceValY
End If

'If our loaded bitmap font has this character...
If char[s[i] ] And s[i] <> 32
curChar = s[i]

bx = X + Cos(angle) * mag * ScaleX
by = Y + Sin(angle) * mag * ScaleY

areaW = cW[curChar]
areaH = blockHeight

'Draw this character
If isGL
'Point UVs to character in FonText Bitmap..
GLframe.u0 = u0[curChar]
GLframe.v0 = v0[curChar]
GLframe.u1 = u1[curChar]
GLframe.v1 = v1[curChar]
GLframe.Draw(0, 0, areaW, areaH, bx + oX, by + oY)

?win32
Else 'Same as above, but using DX variation
DXframe.SetUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
DXframe.Draw(0, 0, areaW, areaH, bx + oX, by + oY)
?
End If

angle:+angleStep
'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
X:+CosR * (cW[curChar] + spacing) * ScaleX
Y:+SinR * (cW[curChar] + spacing) * ScaleY

End If
Next

'Restore UVs
If isGL
GLframe.u0 = 0
GLframe.v0 = 0
GLframe.u1 = 1
GLframe.v1 = 1
?win32
Else
DXframe.SetUV(0, 0, 1, 1)
?
End If
End Method

Method DrawSineSize(s:String, X:Float, Y:Float, angle:Float, angleStep:Float, mag:Float, centered:Byte = False, spacing:Float = 0)
Local i:Int, t:String

Local ScaleX:Float, ScaleY:Float
Local oX:Float, oY:Float 'Current Max2D Origin
Local rot:Float 'Current Max2D Rotation
Local sinR:Float, cosR:Float, sinP90:Float, cosP90:Float
Local areaW:Float, areaH:Float

Local curChar:Byte
Local isGL:Byte 'Boolean
Local GLframe:TGLImageFrame
?win32
Local DXframe:TD3D7ImageFrame
?
Local frame:Int = 0

GetOrigin(oX, oY)
GetScale(ScaleX, ScaleY)

rot = GetRotation()
sinR = Sin(rot)
cosR = Cos(rot)
sinP90 = Sin(rot + 90)
cosP90 = Cos(rot + 90)

If TGLImageFrame(image.frame(frame))
isGL = True
GLframe = TGLImageFrame(Image.Frame(Frame))
?win32
Else
isGL = False
DXframe = TD3D7ImageFrame(Image.Frame(Frame))
?
End If

'Center text horizontally?
Local ln:Float = 0
If centered
'Get string length
For i = 0 Until s.Length
If s[i] = 32
Ln:+blockHeight *.3
Else If char[s[i] ]
Ln:+cW[s[i] ] + spacing
End If
Next
Ln:-spacing 'remove last unwanted space

Ln = Ln * ScaleX *.5
X:-cosR * Ln
Y:-sinR * Ln
End If

Local spaceValX:Float = cosR * blockHeight *.3 * ScaleX
Local spaceValY:Float = sinR * blockHeight *.3 * ScaleY

Local bx:Float, by:Float
Local sizeX:Float, sizeY:Float
mag:*.01
Local ah:Float, aw:Float

'Draw each letter in the string...
For i = 0 Until s.Length

'Space character?
'blockHeight*.3 *seems* to be an ok value for spaces
If s[i] = 32
X:+spaceValX
Y:+spaceValY
End If

'If our loaded bitmap font has this character...
If char[s[i] ] And s[i] <> 32
curChar = s[i]

areaW = cW[curChar] ' +
areaH = blockHeight ' +
aw = areaW + (Sin(angle) * cW[curChar] * mag)
ah = areaH + (Sin(angle) * blockHeight * mag)

bx = X
by = Y

bx:+cosR * (areaW - aw) *.5 * ScaleX
by:+sinR * (areaW - aw) *.5 * ScaleX

bx:+cosP90 * (areaH - ah) *.5 * ScaleY
by:+sinP90 * (areaH - ah) *.5 * ScaleY

'Draw this character
If isGL
'Point UVs to character in FonText Bitmap..
GLframe.u0 = pX[curChar] * iwM
GLframe.v0 = pY[curChar] * ihM
GLframe.u1 = (pX[curChar] + areaW) * iwM
GLframe.v1 = (pY[curChar] + areaH) * ihM

GLframe.Draw(0, 0, aw, ah, bx + oX, by + oY)

?win32
Else 'Same as above, but using DX variation
DXframe.SetUV(pX[curChar] * iwM, pY[curChar] * ihM, (pX[curChar] + areaW) * iwM, (pY[curChar] + areaH) * ihM)
DXframe.Draw(0, 0, aw, ah, bx + oX, by + oY)
?
End If

angle:+angleStep
'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
X:+CosR * (cW[s[i] ] + spacing) * ScaleX
Y:+SinR * (cW[s[i] ] + spacing) * ScaleY

End If
Next

SetScale(ScaleX, ScaleY)

'Restore UVs
If isGL
GLframe.u0 = 0
GLframe.v0 = 0
GLframe.u1 = 1
GLframe.v1 = 1
?win32
Else
DXframe.SetUV(0, 0, 1, 1)
?
End If
End Method

Method DrawSwing(s:String, X:Float, Y:Float, angle:Float, angleStep:Float, mag:Float, centered:Byte = False, spacing:Float = 0)
Local i:Int, t:String

Local ScaleX:Float, ScaleY:Float
Local oX:Float, oY:Float 'Current Max2D Origin
Local rot:Float 'Current Max2D Rotation
Local sinR:Float, cosR:Float, sinP90:Float, cosP90:Float
Local areaW:Float, areaH:Float

Local curchar:Byte
Local isGL:Byte 'Boolean
Local GLframe:TGLImageFrame
?win32
Local DXframe:TD3D7ImageFrame
?

Local frame:Int = 0
Local hX:Float, hY:Float

GetOrigin(oX, oY)
GetScale(ScaleX, ScaleY)

rot = GetRotation()
sinR = Sin(rot)
cosR = Cos(rot)
sinP90 = Sin(rot+90)
cosP90 = Cos(rot+90)

If TGLImageFrame(Image.Frame(Frame))
isGL = True
GLframe = TGLImageFrame(Image.Frame(Frame))
?win32
Else
isGL = False
DXframe = TD3D7ImageFrame(Image.Frame(Frame))
?
End If

'Center text horizontally?
Local ln:Float = 0
If centered
'Get string length
For i = 0 Until s.length
If s[i] = 32
Ln:+blockHeight *.3
Else If char[s[i] ]
Ln:+cW[s[i] ] + spacing
End If
Next
Ln:-spacing 'remove last unwanted space

Ln:*ScaleX *.5
X:-cosR * Ln
Y:-sinR * Ln
End If

Local spaceValX:Float = cosR * blockHeight *.3 * ScaleX
Local spaceValY:Float = sinR * blockHeight *.3 * ScaleY
Local bx:Float, by:Float

'Draw each letter in the string...
For i = 0 Until s.length

'Space character?
'blockHeight*.3 *seems* to be an ok value for spaces
If s[i] = 32
X:+spaceValX
Y:+spaceValY
End If

SetRotation(rot + Sin(angle) * mag)
'If our loaded bitmap font has this character...
If char[s[i] ] And s[i] <> 32
curChar = s[i]

hX = -cW[curChar] *.5
hY = 0

bx = X - cosR * hX * ScaleX '- cosR * bMag
by = Y - sinR * hX * ScaleY '- sinR * bMag

areaW = cW[curChar]
areaH = blockHeight

'Draw this character
If isGL
'Point UVs to character in FonText Bitmap..
GLframe.u0 = u0[curChar]
GLframe.v0 = v0[curChar]
GLframe.u1 = u1[curChar]
GLframe.v1 = v1[curChar]

GLframe.Draw(hX, hY, areaW + hX, areaH, bx + oX, by + oY)

?win32
Else 'Same as above, but using DX variation
DXframe.SetUV(u0[curchar], v0[curChar], u1[curChar], v1[curChar])
DXframe.Draw(hX, hY, areaW + hX, areaH, bx + oX, by + oY)
?
End If

angle:+ angleStep
'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
X:+cosR * (cW[curChar] + spacing) * ScaleX
Y:+sinR * (cW[curChar] + spacing) * ScaleY

End If
Next

SetRotation(rot)
'Restore UVs
If isGL
GLframe.u0 = 0
GLframe.v0 = 0
GLframe.u1 = 1
GLframe.v1 = 1
?win32
Else
DXframe.SetUV(0, 0, 1, 1)
?
End If
End Method
End Type

Type TAnimFonText
Global list:TList = New(TList)

Field link:TLink

Field sX:Float, sY:Float
Field sT:Int
Field aT:Int
Field dT:Int
Field rT:Int
Field str:String

Field srcX:Float[],srcY:Float[]
Field dstX:Float[],dstY:Float[]
Field vX:Float[],vY:Float[]

Field f:TFonText

Field thisScaleX:Float, thisScaleY:Float
Field thisOriginX:Float, thisOriginY:Float
Field thisRotation:Float
Field textCenter:Float
Field textLength:Float

Method New()

Link = list.AddLast(Self)

End Method

Method Destroy()

Link.Remove()

End Method

Function Create(Text:String, ft:TFonText, pX:Float, pY:Float, start:Int, attack:Int, ..
duration:Int, _release:Int, spacing:Float, centered:Byte, dir:Int)

Local a:TAnimFonText = New(TAnimFonText)
Local Time:Int = MilliSecs()
a.str = text
a.f = ft
a.sX = pX
a.sY = pY
a.sT = time + start
a.aT = time + start + attack
a.dT = time + start + attack + duration
a.rT = time + start + attack + duration + _release

a.thisRotation = GetRotation()
GetOrigin(a.thisOriginX, a.thisOriginY)
GetScale(a.thisScaleX, a.thisScaleY)

Local sLen:Int = Text.Length
a.srcX = New Float[sLen]
a.srcY = New Float[sLen]

a.dstX = New Float[sLen]
a.dstY = New Float[sLen]

a.vX = New Float[sLen]
a.vY = New Float[sLen]

Local i:Int, t:String

Local sinR:Float, cosR:Float, sinP90:Float, cosP90:Float
Local areaW:Float, areaH:Float

Local curChar:Byte

sinR = Sin(a.thisRotation)
cosR = Cos(a.thisRotation)
sinP90 = Sin(a.thisRotation + 90)
cosP90 = Cos(a.thisRotation + 90)

'Center text horizontally?
Local ln:Float = 0
'If centered
'Get string length
For i = 0 Until text.length
If Text[i] = 32
Ln:+a.f.blockHeight *.3
Else If a.f.char[Text[i] ]
Ln:+a.f.cW[Text[i] ] + spacing
End If
Next

Ln:-spacing 'remove last unwanted space

a.textLength = Ln
'ln = ln * a.thisScaleX *.5
Ln:*.5
If centered
pX:-cosR * Ln * a.thisScaleX
pY:-sinR * Ln * a.thisScaleY
End If

Local spaceValX:Float = cosR * a.f.blockHeight *.3 * a.thisScaleX
Local spaceValY:Float = sinR * a.f.blockHeight *.3 * a.thisScaleY

'Calc each characters destination, and store it
For i = 0 Until text.length

'Space character?
'blockHeight*.3 *seems* to be an ok value for spaces
If text[i] = 32
pX:+spaceValX
pY:+spaceValY
End If

'If our loaded bitmap font has this character...
If a.f.char[text[i]] And text[i]<>32
curChar = Text[i]

areaW = a.f.cW[curChar]
areaH = a.f.blockHeight

a.dstX[i] = pX + a.thisOriginX
a.dstY[i] = pY + a.thisOriginY
'Increase position of Next letter... +90 = DOWN, +180 = LEFT, -90 = UP
pX:+CosR * (a.f.cW[curChar] + spacing) * a.thisScaleX
pY:+SinR * (a.f.cW[curChar] + spacing) * a.thisScaleY

End If
Next


'setup src & velocity vectors
For i = 0 Until text.length
Select dir
Case 0
Local ix:Int = Int(a.str.Length *.5 -.5)
If ix < 0 ix = 0
a.srcX[i] = a.dstX[ix] 'a.sX + cosR * a.textCenter
a.srcY[i] = a.dstY[ix] 'sY + sinR * a.textCenter
Case - 1
a.srcX[i] = a.dstX[0]
a.srcY[i] = a.dstY[0]
Case 1
a.srcX[i] = a.dstX[a.str.Length - 1]
a.srcY[i] = a.dstY[a.str.Length - 1]
End Select

a.vX[i] = a.srcX[i] - a.dstX[i]
a.vY[i] = a.srcY[i] - a.dstY[i]

Next

End Function

Function Update()
If Not list Then Return

Local Time:Int
Local a:TAnimFonText
Local oldRot:Float, oldScaleX:Float, oldScaleY:Float, oldOriginX:Float, oldOriginY:Float
Local oldAlpha:Float = GetAlpha()
Local oldBlend:Int = GetBlend()

oldRot = GetRotation()
GetScale(oldScaleX, oldScaleY)
GetOrigin(oldOriginX, oldOriginY)

Local i:Int
Local isGL:Byte

Local tx:Float, ty:Float, areaw:Float, areah:Float
Local curChar:Byte
Local GLframe:TGLImageFrame
?win32
Local DXframe:TD3D7ImageFrame
?

SetBlend(ALPHABLEND)
For a = EachIn TAnimFonText.list
SetRotation(a.thisRotation)
SetScale(a.thisScaleX, a.thisScaleY)
SetOrigin(a.thisOriginX, a.thisOriginY)

If TGLImageFrame(a.f.Image.Frame(0))
isGL = True
GLframe = TGLImageFrame(a.f.Image.Frame(0))
?win32
Else
isGL = False
DXframe = TD3D7ImageFrame(a.f.Image.Frame(0))
?
End If

If Time > a.rT
a.Destroy()
a = Null
End If

time = MilliSecs()
If a And Time >= a.sT And Time <= a.rT
Local elap:Float
Local al:Float

For i = 0 Until a.str.Length
If Time >= a.sT And Time < a.aT
elap = (Float((Time - a.sT)) / (a.aT - a.sT))
al = elap
elap = 1.0 - elap
elap = 1.0 - Cos(elap * 90)

tx = a.dstX[i] + a.vX[i] * elap
tY = a.dstY[i] + a.vY[i] * elap 'srcY[i]*elap'dstY[i] - a.srcY[i]*elap '+ a.vY[i]*elap

SetAlpha(1.0 - elap)
'DrawText "Attack",0,0
Else If Time >= a.aT And Time <= a.dT
SetAlpha(1)
'pause
tx = a.dstX[i]
ty = a.dstY[i]
'DrawText "Duration",0,0
Else If Time > a.dT And Time <= a.rT
tx = a.dstX[i]
ty = a.dstY[i] ' + (Abs(time - a.dT) * .05)

elap = 1.0 - (Float(Time - a.dT)) / (a.rT - a.dT)
SetAlpha(elap)
'DrawText "Release",0,0

End If

curChar = a.str[i]

areaW = a.f.cW[curChar]
areaH = a.f.blockHeight
If isGL
'Point UVs to character in FonText Bitmap..
GLframe.u0 = a.f.u0[curChar]
GLframe.v0 = a.f.v0[curChar]
GLframe.u1 = a.f.u1[curChar]
GLframe.v1 = a.f.v1[curChar]

GLframe.Draw(0, 0, areaW, areaH, tx, ty)

?win32
Else 'Same as above, but using DX variation
DXframe.setUV(a.f.u0[curchar], a.f.v0[curChar], a.f.u1[curChar], a.f.v1[curChar])
DXframe.Draw(0, 0, areaW, areaH, tx, ty)
?
End If
Next
End If
Next

SetBlend(oldBlend)
SetAlpha(oldAlpha)
SetRotation(oldRot)
SetScale(oldScaleX, oldScaleY)
SetOrigin(oldOriginX, oldOriginY)
End Function

End Type
')

It should work cross-platform (but I haven't tested it).
I plan on integrating it with my duct modules, and loading FonText data by using a script (quake/c-style) instead of an ini.


Trader3564(Posted 2009) [#49]
wow, this looks awesome.

uhm, Plash, you sure that works cross platform?
Did anyone test?


Robert Cummings(Posted 2009) [#50]
doesn't appear to work on mac :)


beanage(Posted 2009) [#51]
This is great. I will fix the code for mac. Can I deliver the font creation tools you created with my application? (of course youll be credited wherever possible and explicitely excluded from apps license etc.)


_Skully(Posted 2009) [#52]
Scoop! lol

Thanks for this beaker (2 years ago lol)


Beaker(Posted 2010) [#53]
Ok it's not Christmas, but..

Use fontext in iMiniB3d:
BlitzMax Modules Forums/MiniB3D/bitmap fonts in iminib3d

:)


GaryV(Posted 2013) [#54]
Forgive the thread necromancy, but this post deserves a bump. People will be starting Christmas shopping soon and FONText is one of the best Christmas gifts ever bestowed upon the community. Lots of new folks here who may not know about this and the links in the first post are still active.


Rick Nasher(Posted 2013) [#55]
Thanks. Might come in handy.