Over on the
v2 feature request thread @TimShark suggested that we have the ability to make links within a text object that could specifically be clicked on and do something.
Since it was something I've been meaning to implement in
Wordspionage for the "Message from HQ" messages we send out I decided to go ahead and work up an example to show folks how this can be achieved.
What this does is it takes a specially formatted string, parses it for a URL and it's accompanying tag, then colors it and underlines it so it looks like an html markup link <a href>. It includes some handy color functions that I commonly use, a function to test for hits on the link part of the text. It stores the position of the link within the text object by use of a UDT. I'm certain other methods, maybe even simpler ones, are available.
This is all in v2 so some minor adjustments may be needed for v1.
It is also in percentage mode, if you want to do it with virtual resolution then modify as needed!
Main:
SetWindowTitle( "clickable_text" )
SetScreenResolution( 1024, 768, 0 )
`-------------------------------------------------
#include "clickable_text.agc"
//ASCII code 29 indicates begining and end of link object
//code 30 separates URL from the link text
msg$ = "Welcome to Wordspionage! To see this week's leaders " + chr(29) + "http://www.wordspionage.com/leaderboards.php" + chr(30) + "click here" + chr(29) + ". Thanks for playing!"
myText as clickableTextObject
myText = CreateClickableText(msg$, "255,255,200" , "0,255,255" , 1 , 4.0 , 5.0 , 20.0 , 90.0)
//debug
setprintsize(2)
do
if GetPointerPressed() = 1
p_x# = GetPointerX()
p_y# = GetPointerY()
pass = GetClickableTextHit(myText , p_x# , p_y#)
if pass = 1
OpenBrowser(myText.URL$)
endif
endif
//debug
remstart
print(pass)
print(str(p_x# , 3) + "," + str(p_y# , 3))
print(str(myText.minX# , 3) + "," + str(myText.minY#))
print(str(myText.maxX# , 3) + "," + str(myText.maxY#))
remend
Sync()
loop
#include "clickable_text.agc"
type clickableTextObject
textID as integer
minX# as float
maxX# as float
minY# as float
maxY# as float
URL$ as string
underlineID as integer
clickableIndex as integer
endtype
//ASCII code 29 indicates begining and end of link object
//code 30 separates URL from the link text
//example:
// "Welcome to Wordspionage! To see this week's leaders " + chr(29) + "http://www.wordspionage.com/leaderboards.php" + chr(30) + "click here" + chr(29) + ". Thanks for playing!"
function CreateClickableText(msg$ as string , textColor$ as string , linkColor$ as string , underline as integer , textSize# as float , textX# as float , textY# as float , textMaxW# as float)
clickableText as clickableTextObject
linkDelimiter$ = chr(29)
URLDelimiter$ = chr(30)
if underline < 0 or underline > 1
Message("Underline parameter out of range - should be 0 or 1 but it is " + str(underline))
endif
//Parse the URL and clickable text
sectionCount = CountStringTokens(msg$ , linkDelimiter$)
linkCount = 0
new$ = ""
if sectionCount > 1
for i = 1 to sectionCount
token$ = ""
URLCount = 0
token$ = GetStringToken(msg$ , linkDelimiter$ , i)
URLCount = CountStringTokens(token$ , URLDelimiter$)
if URLCount = 2
if doOnce = 0
doOnce = 1
url$ = GetStringToken(token$ , URLDelimiter$ , 1)
clickable$ = GetStringToken(token$ , URLDelimiter$ , 2)
token$ = clickable$
else
Message("Sorry, you can only have 1 clickable per text object at this time.")
endif
endif
new$ = new$ + token$
next i
endif
//find the position of the clickable text in the string
clickableLength = len(clickable$)
clickableIndex = -1 //set to -1 since it could start at position 0 in the string
for i = 0 to len(new$)
c$ = Mid(new$ , i , clickableLength)
if c$ = clickable$
clickableIndex = i - 1
EXIT
endif
next i
//create the text object
textID = CreateText(new$)
_SetTextColor(textID , textColor$)
//set the clickable's color
newLength = len(new$)
for i = clickableIndex to (clickableIndex + clickableLength - 1)
if i < newLength + 1
_SetTextCharColor(textID , i , linkColor$)
endif
next i
//position, size, and max width the text
SetTextSize(textID , textSize#)
SetTextMaxWidth(textID , textMaxW#)
SetTextPosition(textID , textX# , textY#)
//get the postion of the clickable
//not sure why we have to add on the text object's x & y
//position even though it has already been positioned. Maybe you don't have to after sync()?
//if something breaks after an AGK update then it is likely here.
minX# = GetTextCharX(textID , clickableIndex) + textX#
minY# = GetTextCharY(textID , clickableIndex) + textY#
maxX# = GetTextCharX(textID , clickableIndex + clickableLength) + textX#
maxY# = GetTextCharY(textID , clickableIndex + clickableLength) + textSize# + textY#
//set up the underline
underlineID = 0
if underline = 1
underlineID = CreateSprite(0)
_SetSpriteColor(underlineID , linkColor$)
w# = maxX# - minX#
h# = 100.0 / GetDeviceHeight()
SetSpriteSize(underlineID , w# , h#)
x# = minX#
y# = maxY#
SetSpritePosition(underlineID , x# , y#)
endif
//output the object
clickableText.URL$ = url$
clickableText.clickableIndex = clickableIndex
clickableText.textID = textID
clickableText.minX# = minX#
clickableText.maxX# = maxX#
clickableText.minY# = minY#
clickableText.maxY# = maxY#
clickableText.underlineID = 0
endfunction clickableText
function GetClickableTextHit(clickableText as clickableTextObject , pointerX# as float , pointerY# as float)
pass = 0
if pointerX# > clickableText.minX# and pointerX# < clickableText.maxX# and pointerY# > clickableText.minY# and pointerY# < clickableText.maxY#
pass = 1
endif
endfunction pass
function _SetTextColor(iID , sColor$)
if GetTextExists(iID) = 1
r = val(GetStringToken(sColor$ , "," , 1))
g = val(GetStringToken(sColor$ , "," , 2))
b = val(GetStringToken(sColor$ , "," , 3))
SetTextColor(iID , r , g , b , 255)
endif
endfunction
function _SetTextCharColor(iID , iCharIndex , sColor$)
if GetTextExists(iID) = 1
r = val(GetStringToken(sColor$ , "," , 1))
g = val(GetStringToken(sColor$ , "," , 2))
b = val(GetStringToken(sColor$ , "," , 3))
SetTextCharColor(iID , iCharIndex , r , g , b , 255)
endif
endfunction
function _SetSpriteColor(iID , sColor$)
if GetSpriteExists(iID) = 1
r = val(GetStringToken(sColor$ , "," , 1))
g = val(GetStringToken(sColor$ , "," , 2))
b = val(GetStringToken(sColor$ , "," , 3))
SetSpriteColor(iID , r , g , b , 255)
endif
endfunction
Other items to consider:
If you want to BOLD some text you could employ a similar method of finding the position of the text to be bolded, setting the alpha on the characters in the original text to 0 and overlaying them with a new text object using a bold font. Same with italics. Not too painful, took me less than an hour to work this up. I can only imagine what some of you can do with it!
It'd be nice to see a more complete library of text formatting functions like this, but everyone has their own needs and those are difficult to predict. So if you do make functions like this it might be nice to save a fellow dev some time and post them up in the forum.
I hope this helps some of you