XyzzyText: Difference between revisions
Jump to navigation
Jump to search
Huney Jewell (talk | contribs) No edit summary |
m making the code faster and smarter |
||
| Line 75: | Line 75: | ||
// XyzzyText v2.0 Script (5 Face, Single Texture) | // XyzzyText v2.0 Script (5 Face, Single Texture) | ||
// | // | ||
// Heavily Modified by Thraxis Epsilon | // Heavily Modified by Thraxis Epsilon, Gigs Taggart 5/2007 and Strife Onizuka 8/2007 | ||
// Rewrite to allow one-script-per-object operation w/ optional slaves | // Rewrite to allow one-script-per-object operation w/ optional slaves | ||
// Enable prim-label functionality | // Enable prim-label functionality | ||
| Line 124: | Line 124: | ||
// Used to hide the text after a fade-out. | // Used to hide the text after a fade-out. | ||
key TRANSPARENT = "701917a8-d614-471f-13dd-5f4644e36e3c"; | key TRANSPARENT = "701917a8-d614-471f-13dd-5f4644e36e3c"; | ||
key null_key = NULL_KEY; | |||
///////////// END CONSTANTS //////////////// | ///////////// END CONSTANTS //////////////// | ||
| Line 206: | Line 207: | ||
// Use these grid positions to display the correct textures/offsets. | // Use these grid positions to display the correct textures/offsets. | ||
ShowChars(link,GridOffset1, GridOffset2, GridOffset3, GridOffset4, GridOffset5); // Now turn up the alpha until it is at full strength. | ShowChars(link,GridOffset1, GridOffset2, GridOffset3, GridOffset4, GridOffset5); // Now turn up the alpha until it is at full strength. | ||
float Alpha; | float Alpha = 0.10; | ||
for ( | for (; Alpha <= 1.0; Alpha += 0.05) | ||
llSetLinkAlpha(link,Alpha, ALL_SIDES); | llSetLinkAlpha(link,Alpha, ALL_SIDES); | ||
// See if we want to fade out as well. | // See if we want to fade out as well. | ||
| Line 225: | Line 226: | ||
// Look for escape sequences. | // Look for escape sequences. | ||
integer length = 0; | integer length = 0; | ||
list Parsed = llParseString2List(str, [], | list Parsed = llParseString2List(str, [], (list)ESCAPE_SEQUENCE); | ||
integer ParsedLen = llGetListLength(Parsed); | integer ParsedLen = llGetListLength(Parsed); | ||
| Line 233: | Line 234: | ||
integer IndicesLeft = 5; | integer IndicesLeft = 5; | ||
string Token; | string Token; | ||
integer Clipped; | integer Clipped; | ||
integer LastWasEscapeSequence = FALSE; | integer LastWasEscapeSequence = FALSE; | ||
// Work from left to right. | // Work from left to right. | ||
integer i = 0; | |||
for (; i < ParsedLen && IndicesLeft > 0; ++i) { | |||
Token = llList2String(Parsed, i); | Token = llList2String(Parsed, i); | ||
| Line 251: | Line 252: | ||
// Clip if necessary. | // Clip if necessary. | ||
if (TokenLength > IndicesLeft) { | if (TokenLength > IndicesLeft) { | ||
Token = llGetSubString(Token, 0, IndicesLeft - 1) | TokenLength = llStringLength(Token = llGetSubString(Token, 0, IndicesLeft - 1)); | ||
IndicesLeft = 0; | IndicesLeft = 0; | ||
Clipped = TRUE; | Clipped = TRUE; | ||
| Line 262: | Line 262: | ||
if (LastWasEscapeSequence) { | if (LastWasEscapeSequence) { | ||
// Yes, the first character is an escape character, the rest are normal. | // Yes, the first character is an escape character, the rest are normal. | ||
length += | length += 2 + TokenLength; | ||
if(render) | if(render) | ||
{ | { | ||
// This is the extended character. | |||
Indices += (llSubStringIndex(EXTENDED_INDEX, llGetSubString(Token, 0, 0)) + 95); | |||
Indices += | // These are the normal characters. | ||
integer j = 1; | |||
for (; j < TokenLength; ++j) | |||
{ | |||
Indices += llSubStringIndex(gCharIndex, llGetSubString(Token, j, j)); | |||
} | } | ||
} | } | ||
| Line 280: | Line 278: | ||
else { // Normal string. | else { // Normal string. | ||
// Just add the characters normally. | // Just add the characters normally. | ||
length+=TokenLength; | length += TokenLength; | ||
if(render) | if(render) | ||
{ | { | ||
integer j; | integer j = 0; | ||
for ( | for (; j < TokenLength; ++j) | ||
{ | { | ||
Indices += | Indices += llSubStringIndex(gCharIndex, llGetSubString(Token, j, j)); | ||
} | } | ||
} | } | ||
| Line 330: | Line 328: | ||
PassToRender(integer render,string message, integer bank) | PassToRender(integer render,string message, integer bank) | ||
{ | { | ||
// float time; | |||
integer extendedlen = 0; | integer extendedlen = 0; | ||
integer link; | integer link; | ||
integer i = 0; | integer i = 0; | ||
integer msgLen = llStringLength(message); | integer msgLen = llStringLength(message); | ||
| Line 346: | Line 343: | ||
integer bank_highest_dirty=llList2Integer(gBankingData, (bank * BANK_STRIDE) + 2); | integer bank_highest_dirty=llList2Integer(gBankingData, (bank * BANK_STRIDE) + 2); | ||
integer x = 0; | |||
for (;x < msgLen;x = x + 5) | |||
{ | { | ||
| Line 352: | Line 350: | ||
{ | { | ||
//set the dirty to max, and bail out, we're done | //set the dirty to max, and bail out, we're done | ||
gBankingData=llListReplaceList(gBankingData, | gBankingData=llListReplaceList(gBankingData, (list)bank_length, (bank * BANK_STRIDE) + 2, (bank * BANK_STRIDE) + 2); | ||
return; | return; | ||
} | } | ||
link = unpack(gXyTextPrims,(i + bank_offset)); | link = unpack(gXyTextPrims,(i + bank_offset)); | ||
TextToRender = llGetSubString(message, x, x + 15); | TextToRender = llGetSubString(message, x, x + 15); | ||
if(gSlaveRegistered && (link % (num_slaves +1) | if(gSlaveRegistered && (link % (num_slaves +1))) | ||
{ | { | ||
slave_name=llList2String(gSlaveNames, (link % (num_slaves + 1)) - 1); | slave_name=llList2String(gSlaveNames, (link % (num_slaves + 1)) - 1); | ||
| Line 396: | Line 394: | ||
RenderWithEffects(link,TextToRender); | RenderWithEffects(link,TextToRender); | ||
} | } | ||
i | ++i; | ||
} | } | ||
| Line 417: | Line 415: | ||
RenderString(link," "); | RenderString(link," "); | ||
} | } | ||
i | ++i; | ||
} | } | ||
gBankingData=llListReplaceList(gBankingData, | gBankingData=llListReplaceList(gBankingData, (list)current_highest_dirty, (bank * BANK_STRIDE) + 2, (bank * BANK_STRIDE) + 2); | ||
} | } | ||
// Bitwise Voodoo by Gigs Taggart | // Bitwise Voodoo by Gigs Taggart and optimized by Strife Onizuka | ||
list gXyTextPrims; | list gXyTextPrims; | ||
| Line 429: | Line 427: | ||
{//ignores avatars. | {//ignores avatars. | ||
integer a = llGetNumberOfPrims(); | integer a = llGetNumberOfPrims(); | ||
while(llGetAgentSize(llGetLinkKey(a))) | |||
--a; | |||
return a; | return a; | ||
} | } | ||
//functions to pack 8-bit shorts into ints | //functions to pack 8-bit shorts into ints | ||
list pack_and_insert(list in_list, integer pos, integer value) | list pack_and_insert(list in_list, integer pos, integer value) | ||
{ | { | ||
// //figure out the bitpack position | |||
// integer pack = pos & 3; //4 bytes per int | |||
// pos=pos >> 2; | |||
// integer shifted = value << (pack << 3); | |||
// integer old_value = llList2Integer(in_list, pos); | |||
// shifted = old_value | shifted; | |||
// in_list = llListReplaceList(in_list, (list)shifted, pos, pos); | |||
return in_list; | // return in_list; | ||
//Safe optimized version | |||
integer index = pos >> 2; | |||
return llListReplaceList(in_list, (list)(llList2Integer(in_list, index) | (value << ((pos & 3) << 3))), index, index); | |||
} | } | ||
integer unpack(list in_list, integer pos) | integer unpack(list in_list, integer pos) | ||
{ | { | ||
return (llList2Integer(in_list, pos >> 2) >> ((pos & 3) << 3)) & 0x000000FF;//unsigned | |||
// return (llList2Integer(in_list, pos >> 2) << (((~pos) & 3) << 3)) >> 24;//signed | |||
} | } | ||
change_color(vector color) | change_color(vector color) | ||
{ | { | ||
integer num_prims=llGetListLength(gXyTextPrims) | integer num_prims=llGetListLength(gXyTextPrims) << 2; | ||
integer i; | integer i = 0; | ||
for ( | for (; i<=num_prims; ++i) | ||
{ | { | ||
integer link = unpack(gXyTextPrims,i); | integer link = unpack(gXyTextPrims,i); | ||
if (link | if (!link) | ||
return; | return; | ||
llSetLinkPrimitiveParams( link,[ | llSetLinkPrimitiveParams( link,[ | ||
PRIM_COLOR, FACE_1, color, 1.0, | |||
PRIM_COLOR, FACE_2, color, 1.0, | |||
PRIM_COLOR, FACE_3, color, 1.0, | |||
PRIM_COLOR, FACE_4, color, 1.0, | |||
PRIM_COLOR, FACE_5, color, 1.0 | |||
]); | ]); | ||
} | } | ||
} | } | ||
change_line_color(integer bank, vector color) | change_line_color(integer bank, vector color) | ||
| Line 487: | Line 480: | ||
//get the bank offset and length | //get the bank offset and length | ||
integer | integer i = llList2Integer(gBankingData, (bank * BANK_STRIDE)); | ||
integer bank_end= | integer bank_end = i + llList2Integer(gBankingData, (bank * BANK_STRIDE) + 1); | ||
for (; i < bank_end; ++i) | |||
for ( | |||
{ | { | ||
integer link = unpack(gXyTextPrims,i); | integer link = unpack(gXyTextPrims,i); | ||
if (link | if (!link) | ||
return; | return; | ||
llSetLinkPrimitiveParams( link,[ | llSetLinkPrimitiveParams( link,[ | ||
PRIM_COLOR, FACE_1, color, 1.0, | |||
PRIM_COLOR, FACE_2, color, 1.0, | |||
PRIM_COLOR, FACE_3, color, 1.0, | |||
PRIM_COLOR, FACE_4, color, 1.0, | |||
PRIM_COLOR, FACE_5, color, 1.0 | |||
]); | ]); | ||
} | } | ||
} | } | ||
| Line 513: | Line 503: | ||
{ | { | ||
integer num_prims=get_number_of_prims(); | integer num_prims=get_number_of_prims(); | ||
string link_name; | string link_name; | ||
integer bank=0; | integer bank=0; | ||
integer prims_pointer=0; //"pointer" to the next entry to be used in the gXyTextPrims list. | integer prims_pointer=0; //"pointer" to the next entry to be used in the gXyTextPrims list. | ||
list temp_bank; | list temp_bank = []; | ||
integer temp_bank_stride=2; | integer temp_bank_stride=2; | ||
//FIXME: font texture might should be per-bank | //FIXME: font texture might should be per-bank | ||
llMessageLinked(LINK_THIS, SET_FONT_TEXTURE, "" ,gFontTexture); | llMessageLinked(LINK_THIS, SET_FONT_TEXTURE, "", gFontTexture); | ||
gXyTextPrims=[]; | gXyTextPrims=[]; | ||
integer x=0; | |||
for (;x<64;++x) | |||
{ | { | ||
gXyTextPrims= (gXyTextPrims = []) + gXyTextPrims + | gXyTextPrims = (gXyTextPrims = []) + gXyTextPrims + 0; //we need to pad out the list to make it easier to add things in any order later | ||
} | } | ||
@loop; | |||
{ | { | ||
//loop over all prims, looking for ones in the current bank | //loop over all prims, looking for ones in the current bank | ||
for(x=0;x<=num_prims; | for(x=0;x<=num_prims;++x) | ||
{ | { | ||
link_name=llGetLinkName(x); | link_name=llGetLinkName(x); | ||
list tmp = llParseString2List(link_name, | list tmp = llParseString2List(link_name, (list)"-", []); | ||
if(llList2String(tmp,0) == "xyzzytext") | |||
{ | { | ||
if (llList2Integer(tmp,1) == bank) | |||
{ | { | ||
temp_bank += llList2Integer(tmp,2) + (list)x; | |||
} | } | ||
} | } | ||
| Line 558: | Line 537: | ||
} | } | ||
if (! | if (temp_bank != []) | ||
{ | { | ||
//sort the current bank | //sort the current bank | ||
temp_bank=llListSort(temp_bank, temp_bank_stride, TRUE); | temp_bank = llListSort(temp_bank, temp_bank_stride, TRUE); | ||
integer y; | integer y; | ||
integer temp_len=llGetListLength(temp_bank); | integer temp_len = llGetListLength(temp_bank); | ||
//store metadata | //store metadata | ||
gBankingData+=[prims_pointer | gBankingData += [prims_pointer, temp_len/temp_bank_stride, 0]; | ||
//repack the bank into the prim list | //repack the bank into the prim list | ||
| Line 575: | Line 552: | ||
{ | { | ||
gXyTextPrims = pack_and_insert(gXyTextPrims, prims_pointer, llList2Integer(temp_bank, y+1)); | gXyTextPrims = pack_and_insert(gXyTextPrims, prims_pointer, llList2Integer(temp_bank, y+1)); | ||
++prims_pointer; | |||
} | } | ||
++bank; | |||
temp_bank=[]; | |||
jump loop; | |||
} | } | ||
} | } | ||
llMessageLinked(LINK_THIS, SLAVE_RESET, "" , | llMessageLinked(LINK_THIS, SLAVE_RESET, "" , null_key); | ||
//llOwnerSay((string)llGetFreeMemory()); | //llOwnerSay((string)llGetFreeMemory()); | ||
} | } | ||
| Line 601: | Line 578: | ||
link_message(integer sender, integer channel, string data, key id) { | link_message(integer sender, integer channel, string data, key id) { | ||
if (id== | if (id==null_key) | ||
id="0"; | id="0"; | ||
if (channel == DISPLAY_STRING) { | if (channel == DISPLAY_STRING) { | ||
PassToRender(1,data, (integer)((string)id)); | |||
} | } | ||
if (channel == DISPLAY_EXTENDED) { | else if (channel == DISPLAY_EXTENDED) { | ||
PassToRender(2,data, (integer)((string)id)); | |||
} | } | ||
if (channel == REMAP_INDICES) { | else if (channel == REMAP_INDICES) { | ||
// Parse the message, splitting it up into index values. | |||
list Parsed = llCSV2List(data); | |||
integer i; | |||
// Go through the list and swap each pair of indices. | |||
for (i = 0; i < llGetListLength(Parsed); i += 2) { | |||
integer Index1 = ConvertIndex( llList2Integer(Parsed, i) ); | |||
integer Index2 = ConvertIndex( llList2Integer(Parsed, i + 1) ); | |||
// Swap these index values. | |||
string Value1 = llGetSubString(gCharIndex, Index1, Index1); | |||
string Value2 = llGetSubString(gCharIndex, Index2, Index2); | |||
gCharIndex = llDeleteSubString(gCharIndex, Index1, Index1); | |||
gCharIndex = llInsertString(gCharIndex, Index1, Value2); | |||
gCharIndex = llDeleteSubString(gCharIndex, Index2, Index2); | |||
gCharIndex = llInsertString(gCharIndex, Index2, Value1); | |||
} | |||
} | } | ||
else if (channel == RESCAN_LINKSET) | |||
{ | { | ||
init(); | init(); | ||
} | } | ||
else if (channel == RESET_INDICES) { | |||
// Restore the character index back to default settings. | |||
ResetCharIndex(); | |||
} | } | ||
if (channel == SET_FADE_OPTIONS) { | else if (channel == SET_FADE_OPTIONS) { | ||
// Change the channel we listen to for cell commands, the | |||
// starting character position to extract from, and | |||
// special effect attributes. | |||
list Parsed = llCSV2List(data); | |||
gCellUseFading = (integer) llList2String(Parsed, 0); | |||
gCellHoldDelay = (float) llList2String(Parsed, 1); | |||
} | } | ||
if (channel == SET_FONT_TEXTURE) { | else if (channel == SET_FONT_TEXTURE) { | ||
// Use the new texture instead of the current one. | |||
gFontTexture = id; | |||
} | } | ||
if (channel == SET_COLOR) { | else if (channel == SET_COLOR) { | ||
change_color((vector)data); | |||
} | } | ||
else if (channel == SET_LINE_COLOR) { | |||
change_line_color((integer)((string)id), (vector)data); | |||
change_line_color((integer)((string)id), | |||
} | } | ||
else if (channel == REGISTER_SLAVE) | |||
if (channel == REGISTER_SLAVE) | |||
{ | { | ||
if(~llListFindList(gSlaveNames, | if(!~llListFindList(gSlaveNames, (list)data)) | ||
{// | {//isn't registered yet | ||
gSlaveNames += data; | |||
//llOwnerSay((string)llGetListLength(gSlaveNames) + " Slave | gSlaveRegistered=TRUE; | ||
//llOwnerSay((string)llGetListLength(gSlaveNames) + " Slave(s) Recognized: " + data); | |||
} | } | ||
// else | |||
// {//it already exists | |||
// llOwnerSay((string)llGetListLength(gSlaveNames) + " Slave, Existing Slave Recognized: " + data); | |||
// } | |||
llMessageLinked(LINK_THIS, SLAVE_RECOGNIZED, data , null_key); | |||
} | } | ||
} | |||
| Line 689: | Line 654: | ||
if(change&CHANGED_INVENTORY) | if(change&CHANGED_INVENTORY) | ||
{ | { | ||
if( | if(gSlaveRegistered) | ||
{ | { | ||
//by using negative indexes they don't need to be adjusted when an entry is deleted. | |||
integer x = -llGetListLength(gSlaveNames); | |||
for(;x;++x) | |||
{ | { | ||
//llOwnerSay("Slave Removed: " + llList2String(gSlaveNames, x)); | if (!~llGetInventoryType(llList2String(gSlaveNames, x))) | ||
{ | |||
//llOwnerSay("Slave Removed: " + llList2String(gSlaveNames, x)); | |||
gSlaveNames = llDeleteSubList(gSlaveNames, x, x); | |||
} | |||
} | } | ||
gSlaveRegistered = !(gSlaveNames == []); | |||
} | } | ||
} | } | ||
| Line 820: | Line 783: | ||
integer IndicesLeft = 5; | integer IndicesLeft = 5; | ||
integer i; | integer i = 0; | ||
string Token; | string Token; | ||
integer Clipped; | integer Clipped; | ||
integer LastWasEscapeSequence = FALSE; | integer LastWasEscapeSequence = FALSE; | ||
// Work from left to right. | // Work from left to right. | ||
for ( | for (; i < ParsedLen && IndicesLeft > 0; ++i) { | ||
Token = llList2String(Parsed, i); | Token = llList2String(Parsed, i); | ||
| Line 851: | Line 814: | ||
// This is the extended character. | // This is the extended character. | ||
Indices += | Indices += (llSubStringIndex(EXTENDED_INDEX, llGetSubString(Token, 0, 0)) + 95); | ||
// These are the normal characters. | // These are the normal characters. | ||
integer j; | integer j = 1; | ||
for ( | for (; j < TokenLength; ++j) | ||
Indices += | Indices += llSubStringIndex(gCharIndex, llGetSubString(Token, j, j)); | ||
} | } | ||
else { // Normal string. | else { // Normal string. | ||
// Just add the characters normally. | // Just add the characters normally. | ||
integer j; | integer j; | ||
for (j = 0; j < TokenLength; | for (j = 0; j < TokenLength; ++j) | ||
Indices += | Indices += llSubStringIndex(gCharIndex, llGetSubString(Token, j, j)); | ||
} | } | ||
Revision as of 07:09, 28 August 2007
XyzzyText is a new version of Xytext with some advanced features:
- Efficiency! You can now control an entire linkset with just one script.
- Flexible Speed vs Lag. Just drop in plug-and-play slave scripts to increase rendering speed. (More than 4-5 slaves not recommended, there is diminishing returns)
- Ease of use. There is no need to know link numbers. Simply name the child prims xyzzytext-banknumber-cellnumber.
- To use, pass the bank number to use in the "key" field of the link message of DISPLAY_STRING/EXTENDED.
- Gigs Taggart hereby releases his contributions to this under the MIT license.
Example:
Display Prims named: xyzzytext-0-0 xyzzytext-0-1 xyzzytext-1-0 xyzzytext-1-1
Quickstart:
* Store all scripts in your inventory * Rez a box * Drop the prim setup script in it (You now have one unit, name it xyzzytext-0-0) * Make a row of four of these prims (xyzzytext-0-0 xyzzytext-0-1,xyzzytext-0-2,xyzzytext-0-3) * Move a copy of this row a little down, and rename the new row(xyzzytext-1-0 xyzzytext-1-1,xyzzytext-1-2,xyzzytext-1-3) * Do this for every row you make * Create a big box that serves as the board-background(mainprim) * Link all prims with the mainprim(selected last), so the mainprim keeps yellow after linking(root-prim) * Copy the main script and usage script into the root prim * Type something, and check if it all works * Flatten the prims, so the text looks straight * Consider adding slave scripts to the root prim if you have a lot of rows
Usage:
integer DISPLAY_STRING = 204000;
integer DISPLAY_EXTENDED = 204001;
integer REMAP_INDICES = 204002;
integer RESET_INDICES = 204003;
integer SET_FADE_OPTIONS = 204004;
integer SET_FONT_TEXTURE = 204005;
integer SET_LINE_COLOR = 204006;
integer SET_COLOR = 204007;
integer RESCAN_LINKSET = 204008;
integer gToggle;
default
{
state_entry()
{
llListen(0,"",NULL_KEY,"");
}
listen(integer channel,string name, key id, string message)
{
if (gToggle)
llMessageLinked(LINK_THIS,DISPLAY_STRING,name + ":"+ message,"0");
else
llMessageLinked(LINK_THIS,DISPLAY_STRING,name + ":"+ message,"1");
gToggle=!gToggle;
}
}
Main Script:
////////////////////////////////////////////
// XyzzyText v2.1 Script (Set Line Color) by Huney Jewell
// XyzzyText v2.0 Script (5 Face, Single Texture)
//
// Heavily Modified by Thraxis Epsilon, Gigs Taggart 5/2007 and Strife Onizuka 8/2007
// Rewrite to allow one-script-per-object operation w/ optional slaves
// Enable prim-label functionality
// Enabled Banking
//
// Modified by Kermitt Quirk 19/01/2006
// To add support for 5 face prim instead of 3
//
// Core XyText Originally Written by Xylor Baysklef
//
//
////////////////////////////////////////////
/////////////// CONSTANTS ///////////////////
// XyText Message Map.
integer DISPLAY_STRING = 204000;
integer DISPLAY_EXTENDED = 204001;
integer REMAP_INDICES = 204002;
integer RESET_INDICES = 204003;
integer SET_FADE_OPTIONS = 204004;
integer SET_FONT_TEXTURE = 204005;
integer SET_LINE_COLOR = 204006;
integer SET_COLOR = 204007;
integer RESCAN_LINKSET = 204008;
//internal API
integer REGISTER_SLAVE = 205000;
integer SLAVE_RECOGNIZED = 205001;
integer SLAVE_DISPLAY = 205003;
integer SLAVE_DISPLAY_EXTENDED = 205004;
integer SLAVE_RESET = 205005;
// This is an extended character escape sequence.
string ESCAPE_SEQUENCE = "\\e";
// This is used to get an index for the extended character.
string EXTENDED_INDEX = "12345";
// Face numbers.
integer FACE_1 = 3;
integer FACE_2 = 7;
integer FACE_3 = 4;
integer FACE_4 = 6;
integer FACE_5 = 1;
// Used to hide the text after a fade-out.
key TRANSPARENT = "701917a8-d614-471f-13dd-5f4644e36e3c";
key null_key = NULL_KEY;
///////////// END CONSTANTS ////////////////
///////////// GLOBAL VARIABLES ///////////////
// This is the key of the font we are displaying.
key gFontTexture = "b2e7394f-5e54-aa12-6e1c-ef327b6bed9e";
// All displayable characters. Default to ASCII order.
string gCharIndex;
// This is whether or not to use the fade in/out special effect.
integer gCellUseFading = FALSE;
// This is how long to display the text before fading out (if using
// fading special effect).
// Note: < 0 means don't fade out.
float gCellHoldDelay = 1.0;
integer gSlaveRegistered;
list gSlaveNames;
integer BANK_STRIDE=3; //offset, length, highest_dirty
list gBankingData;
/////////// END GLOBAL VARIABLES ////////////
ResetCharIndex() {
gCharIndex = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`";
gCharIndex += "abcdefghijklmnopqrstuvwxyz{|}~";
gCharIndex += "\n\n\n\n\n";
}
vector GetGridOffset(integer index) {
// Calculate the offset needed to display this character.
integer Row = index / 10;
integer Col = index % 10;
// Return the offset in the texture.
return <-0.45 + 0.1 * Col, 0.45 - 0.1 * Row, 0.0>;
}
ShowChars(integer link,vector grid_offset1, vector grid_offset2, vector grid_offset3, vector grid_offset4, vector grid_offset5) {
// Set the primitive textures directly.
// <-0.256, 0, 0>
// <0, 0, 0>
// <0.130, 0, 0>
// <0, 0, 0>
// <-0.74, 0, 0>
llSetLinkPrimitiveParams( link,[
PRIM_TEXTURE, FACE_1, (string)gFontTexture, <0.126, 0.1, 0>, grid_offset1 + <0.037, 0, 0>, 0.0,
PRIM_TEXTURE, FACE_2, (string)gFontTexture, <0.05, 0.1, 0>, grid_offset2, 0.0,
PRIM_TEXTURE, FACE_3, (string)gFontTexture, <-0.74, 0.1, 0>, grid_offset3 - <0.244, 0, 0>, 0.0,
PRIM_TEXTURE, FACE_4, (string)gFontTexture, <0.05, 0.1, 0>, grid_offset4, 0.0,
PRIM_TEXTURE, FACE_5, (string)gFontTexture, <0.126, 0.1, 0>, grid_offset5 - <0.037, 0, 0>, 0.0
]);
}
RenderString(integer link, string str) {
// Get the grid positions for each pair of characters.
vector GridOffset1 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 0, 0)) );
vector GridOffset2 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 1, 1)) );
vector GridOffset3 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 2, 2)) );
vector GridOffset4 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 3, 3)) );
vector GridOffset5 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 4, 4)) );
// Use these grid positions to display the correct textures/offsets.
ShowChars(link,GridOffset1, GridOffset2, GridOffset3, GridOffset4, GridOffset5);
}
RenderWithEffects(integer link, string str) {
// Get the grid positions for each pair of characters.
vector GridOffset1 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 0, 0)) );
vector GridOffset2 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 1, 1)) );
vector GridOffset3 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 2, 2)) );
vector GridOffset4 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 3, 3)) );
vector GridOffset5 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 4, 4)) );
// First set the alpha to the lowest possible.
llSetLinkAlpha(link,0.05, ALL_SIDES);
// Use these grid positions to display the correct textures/offsets.
ShowChars(link,GridOffset1, GridOffset2, GridOffset3, GridOffset4, GridOffset5); // Now turn up the alpha until it is at full strength.
float Alpha = 0.10;
for (; Alpha <= 1.0; Alpha += 0.05)
llSetLinkAlpha(link,Alpha, ALL_SIDES);
// See if we want to fade out as well.
if (gCellHoldDelay < 0.0)
// No, bail out. (Just keep showing the string at full strength).
return;
// Hold the text for a while.
llSleep(gCellHoldDelay);
// Now fade out.
for (Alpha = 0.95; Alpha >= 0.05; Alpha -= 0.05)
llSetLinkAlpha(link,Alpha, ALL_SIDES);
// Make the text transparent to fully hide it.
llSetLinkTexture(link,TRANSPARENT, ALL_SIDES);
}
integer RenderExtended(integer link, string str, integer render) {
// Look for escape sequences.
integer length = 0;
list Parsed = llParseString2List(str, [], (list)ESCAPE_SEQUENCE);
integer ParsedLen = llGetListLength(Parsed);
// Create a list of index values to work with.
list Indices;
// We start with room for 5 indices.
integer IndicesLeft = 5;
string Token;
integer Clipped;
integer LastWasEscapeSequence = FALSE;
// Work from left to right.
integer i = 0;
for (; i < ParsedLen && IndicesLeft > 0; ++i) {
Token = llList2String(Parsed, i);
// If this is an escape sequence, just set the flag and move on.
if (Token == ESCAPE_SEQUENCE) {
LastWasEscapeSequence = TRUE;
}
else { // Token != ESCAPE_SEQUENCE
// Otherwise this is a normal token. Check its length.
Clipped = FALSE;
integer TokenLength = llStringLength(Token);
// Clip if necessary.
if (TokenLength > IndicesLeft) {
TokenLength = llStringLength(Token = llGetSubString(Token, 0, IndicesLeft - 1));
IndicesLeft = 0;
Clipped = TRUE;
}
else
IndicesLeft -= TokenLength;
// Was the previous token an escape sequence?
if (LastWasEscapeSequence) {
// Yes, the first character is an escape character, the rest are normal.
length += 2 + TokenLength;
if(render)
{
// This is the extended character.
Indices += (llSubStringIndex(EXTENDED_INDEX, llGetSubString(Token, 0, 0)) + 95);
// These are the normal characters.
integer j = 1;
for (; j < TokenLength; ++j)
{
Indices += llSubStringIndex(gCharIndex, llGetSubString(Token, j, j));
}
}
}
else { // Normal string.
// Just add the characters normally.
length += TokenLength;
if(render)
{
integer j = 0;
for (; j < TokenLength; ++j)
{
Indices += llSubStringIndex(gCharIndex, llGetSubString(Token, j, j));
}
}
}
// Unset this flag, since this was not an escape sequence.
LastWasEscapeSequence = FALSE;
}
}
// Use the indices to create grid positions.
if(render)
{
vector GridOffset1 = GetGridOffset( llList2Integer(Indices, 0) );
vector GridOffset2 = GetGridOffset( llList2Integer(Indices, 1) );
vector GridOffset3 = GetGridOffset( llList2Integer(Indices, 2) );
vector GridOffset4 = GetGridOffset( llList2Integer(Indices, 3) );
vector GridOffset5 = GetGridOffset( llList2Integer(Indices, 4) );
// Use these grid positions to display the correct textures/offsets.
ShowChars(link,GridOffset1, GridOffset2, GridOffset3, GridOffset4, GridOffset5);
}
return length;
}
integer ConvertIndex(integer index) {
// This converts from an ASCII based index to our indexing scheme.
if (index >= 32) // ' ' or higher
index -= 32;
else { // index < 32
// Quick bounds check.
if (index > 15)
index = 15;
index += 94; // extended characters
}
return index;
}
PassToRender(integer render,string message, integer bank)
{
// float time;
integer extendedlen = 0;
integer link;
integer i = 0;
integer msgLen = llStringLength(message);
string TextToRender;
integer num_slaves=llGetListLength(gSlaveNames);
string slave_name; //avoids unnecessary casts, keeping it as a string
//get the bank offset and length
integer bank_offset=llList2Integer(gBankingData, (bank * BANK_STRIDE));
integer bank_length=llList2Integer(gBankingData, (bank * BANK_STRIDE) + 1);
integer bank_highest_dirty=llList2Integer(gBankingData, (bank * BANK_STRIDE) + 2);
integer x = 0;
for (;x < msgLen;x = x + 5)
{
if (i >= bank_length) //we don't want to run off the end of the bank
{
//set the dirty to max, and bail out, we're done
gBankingData=llListReplaceList(gBankingData, (list)bank_length, (bank * BANK_STRIDE) + 2, (bank * BANK_STRIDE) + 2);
return;
}
link = unpack(gXyTextPrims,(i + bank_offset));
TextToRender = llGetSubString(message, x, x + 15);
if(gSlaveRegistered && (link % (num_slaves +1)))
{
slave_name=llList2String(gSlaveNames, (link % (num_slaves + 1)) - 1);
if (render == 1)
llMessageLinked(LINK_THIS, SLAVE_DISPLAY, TextToRender, (key)((string)link + "," + slave_name));
if (render == 2)
{
//time = llGetAndResetTime();
if(llSubStringIndex(TextToRender,"\e") > x)
extendedlen = 5;
else
extendedlen = RenderExtended(link,TextToRender,0);
if (extendedlen > 5)
{
x += extendedlen - 5;
}
llMessageLinked(LINK_THIS, SLAVE_DISPLAY_EXTENDED, TextToRender, (key)((string)link + "," + slave_name));
// llOwnerSay((string)llGetAndResetTime());
}
//sorry, no fade effect with slave
}
else
{
if (render == 1)
RenderString(link,TextToRender);
if (render == 2)
{
extendedlen = RenderExtended(link,TextToRender,1);
if (extendedlen > 5)
{
x += extendedlen - 5;
}
}
if (render == 3)
RenderWithEffects(link,TextToRender);
}
++i;
}
if (bank_highest_dirty==0)
bank_highest_dirty=bank_length;
integer current_highest_dirty=i;
while (i < bank_highest_dirty)
{
link = unpack(gXyTextPrims,(i + bank_offset));
if(gSlaveRegistered && (link % (num_slaves+1) != 0))
{
slave_name=llList2String(gSlaveNames, (link % (num_slaves + 1)) - 1);
llMessageLinked(LINK_THIS, SLAVE_DISPLAY, " ", (key)((string)link + "," + slave_name));
//sorry, no fade effect with slave
}
else
{
RenderString(link," ");
}
++i;
}
gBankingData=llListReplaceList(gBankingData, (list)current_highest_dirty, (bank * BANK_STRIDE) + 2, (bank * BANK_STRIDE) + 2);
}
// Bitwise Voodoo by Gigs Taggart and optimized by Strife Onizuka
list gXyTextPrims;
integer get_number_of_prims()
{//ignores avatars.
integer a = llGetNumberOfPrims();
while(llGetAgentSize(llGetLinkKey(a)))
--a;
return a;
}
//functions to pack 8-bit shorts into ints
list pack_and_insert(list in_list, integer pos, integer value)
{
// //figure out the bitpack position
// integer pack = pos & 3; //4 bytes per int
// pos=pos >> 2;
// integer shifted = value << (pack << 3);
// integer old_value = llList2Integer(in_list, pos);
// shifted = old_value | shifted;
// in_list = llListReplaceList(in_list, (list)shifted, pos, pos);
// return in_list;
//Safe optimized version
integer index = pos >> 2;
return llListReplaceList(in_list, (list)(llList2Integer(in_list, index) | (value << ((pos & 3) << 3))), index, index);
}
integer unpack(list in_list, integer pos)
{
return (llList2Integer(in_list, pos >> 2) >> ((pos & 3) << 3)) & 0x000000FF;//unsigned
// return (llList2Integer(in_list, pos >> 2) << (((~pos) & 3) << 3)) >> 24;//signed
}
change_color(vector color)
{
integer num_prims=llGetListLength(gXyTextPrims) << 2;
integer i = 0;
for (; i<=num_prims; ++i)
{
integer link = unpack(gXyTextPrims,i);
if (!link)
return;
llSetLinkPrimitiveParams( link,[
PRIM_COLOR, FACE_1, color, 1.0,
PRIM_COLOR, FACE_2, color, 1.0,
PRIM_COLOR, FACE_3, color, 1.0,
PRIM_COLOR, FACE_4, color, 1.0,
PRIM_COLOR, FACE_5, color, 1.0
]);
}
}
change_line_color(integer bank, vector color)
{
//get the bank offset and length
integer i = llList2Integer(gBankingData, (bank * BANK_STRIDE));
integer bank_end = i + llList2Integer(gBankingData, (bank * BANK_STRIDE) + 1);
for (; i < bank_end; ++i)
{
integer link = unpack(gXyTextPrims,i);
if (!link)
return;
llSetLinkPrimitiveParams( link,[
PRIM_COLOR, FACE_1, color, 1.0,
PRIM_COLOR, FACE_2, color, 1.0,
PRIM_COLOR, FACE_3, color, 1.0,
PRIM_COLOR, FACE_4, color, 1.0,
PRIM_COLOR, FACE_5, color, 1.0
]);
}
}
init()
{
integer num_prims=get_number_of_prims();
string link_name;
integer bank=0;
integer prims_pointer=0; //"pointer" to the next entry to be used in the gXyTextPrims list.
list temp_bank = [];
integer temp_bank_stride=2;
//FIXME: font texture might should be per-bank
llMessageLinked(LINK_THIS, SET_FONT_TEXTURE, "", gFontTexture);
gXyTextPrims=[];
integer x=0;
for (;x<64;++x)
{
gXyTextPrims = (gXyTextPrims = []) + gXyTextPrims + 0; //we need to pad out the list to make it easier to add things in any order later
}
@loop;
{
//loop over all prims, looking for ones in the current bank
for(x=0;x<=num_prims;++x)
{
link_name=llGetLinkName(x);
list tmp = llParseString2List(link_name, (list)"-", []);
if(llList2String(tmp,0) == "xyzzytext")
{
if (llList2Integer(tmp,1) == bank)
{
temp_bank += llList2Integer(tmp,2) + (list)x;
}
}
}
if (temp_bank != [])
{
//sort the current bank
temp_bank = llListSort(temp_bank, temp_bank_stride, TRUE);
integer y;
integer temp_len = llGetListLength(temp_bank);
//store metadata
gBankingData += [prims_pointer, temp_len/temp_bank_stride, 0];
//repack the bank into the prim list
for (y=0; y < temp_len; y+=temp_bank_stride)
{
gXyTextPrims = pack_and_insert(gXyTextPrims, prims_pointer, llList2Integer(temp_bank, y+1));
++prims_pointer;
}
++bank;
temp_bank=[];
jump loop;
}
}
llMessageLinked(LINK_THIS, SLAVE_RESET, "" , null_key);
//llOwnerSay((string)llGetFreeMemory());
}
default {
state_entry() {
// Initialize the character index.
ResetCharIndex();
init();
}
on_rez(integer num)
{
llResetScript();
}
link_message(integer sender, integer channel, string data, key id) {
if (id==null_key)
id="0";
if (channel == DISPLAY_STRING) {
PassToRender(1,data, (integer)((string)id));
}
else if (channel == DISPLAY_EXTENDED) {
PassToRender(2,data, (integer)((string)id));
}
else if (channel == REMAP_INDICES) {
// Parse the message, splitting it up into index values.
list Parsed = llCSV2List(data);
integer i;
// Go through the list and swap each pair of indices.
for (i = 0; i < llGetListLength(Parsed); i += 2) {
integer Index1 = ConvertIndex( llList2Integer(Parsed, i) );
integer Index2 = ConvertIndex( llList2Integer(Parsed, i + 1) );
// Swap these index values.
string Value1 = llGetSubString(gCharIndex, Index1, Index1);
string Value2 = llGetSubString(gCharIndex, Index2, Index2);
gCharIndex = llDeleteSubString(gCharIndex, Index1, Index1);
gCharIndex = llInsertString(gCharIndex, Index1, Value2);
gCharIndex = llDeleteSubString(gCharIndex, Index2, Index2);
gCharIndex = llInsertString(gCharIndex, Index2, Value1);
}
}
else if (channel == RESCAN_LINKSET)
{
init();
}
else if (channel == RESET_INDICES) {
// Restore the character index back to default settings.
ResetCharIndex();
}
else if (channel == SET_FADE_OPTIONS) {
// Change the channel we listen to for cell commands, the
// starting character position to extract from, and
// special effect attributes.
list Parsed = llCSV2List(data);
gCellUseFading = (integer) llList2String(Parsed, 0);
gCellHoldDelay = (float) llList2String(Parsed, 1);
}
else if (channel == SET_FONT_TEXTURE) {
// Use the new texture instead of the current one.
gFontTexture = id;
}
else if (channel == SET_COLOR) {
change_color((vector)data);
}
else if (channel == SET_LINE_COLOR) {
change_line_color((integer)((string)id), (vector)data);
}
else if (channel == REGISTER_SLAVE)
{
if(!~llListFindList(gSlaveNames, (list)data))
{//isn't registered yet
gSlaveNames += data;
gSlaveRegistered=TRUE;
//llOwnerSay((string)llGetListLength(gSlaveNames) + " Slave(s) Recognized: " + data);
}
// else
// {//it already exists
// llOwnerSay((string)llGetListLength(gSlaveNames) + " Slave, Existing Slave Recognized: " + data);
// }
llMessageLinked(LINK_THIS, SLAVE_RECOGNIZED, data , null_key);
}
}
changed(integer change)
{
if(change&CHANGED_INVENTORY)
{
if(gSlaveRegistered)
{
//by using negative indexes they don't need to be adjusted when an entry is deleted.
integer x = -llGetListLength(gSlaveNames);
for(;x;++x)
{
if (!~llGetInventoryType(llList2String(gSlaveNames, x)))
{
//llOwnerSay("Slave Removed: " + llList2String(gSlaveNames, x));
gSlaveNames = llDeleteSubList(gSlaveNames, x, x);
}
}
gSlaveRegistered = !(gSlaveNames == []);
}
}
}
}
Slave Script:
////////////////////////////////////////////
// XyText v2.0 SLAVE Script (5 Face, Single Texture)
//
// Modified by Thraxis Epsilon and Gigs Taggart 5/2007
// Rewrite to allow one-script-per-object operation
//
// Modified by Kermitt Quirk 19/01/2006
// To add support for 5 face prim instead of 3
//
// Originally Written by Xylor Baysklef
//
//
////////////////////////////////////////////
integer REMAP_INDICES = 204002;
integer RESET_INDICES = 204003;
//internal API
integer REGISTER_SLAVE = 205000;
integer SLAVE_RECOGNIZED = 205001;
integer SLAVE_DISPLAY = 205003;
integer SET_FONT_TEXTURE = 204005;
integer SLAVE_DISPLAY_EXTENDED = 205004;
integer SLAVE_RESET = 205005;
// This is an extended character escape sequence.
string ESCAPE_SEQUENCE = "\\e";
// This is used to get an index for the extended character.
string EXTENDED_INDEX = "12345";
// Face numbers.
integer FACE_1 = 3;
integer FACE_2 = 7;
integer FACE_3 = 4;
integer FACE_4 = 6;
integer FACE_5 = 1;
///////////// GLOBAL VARIABLES ///////////////
// This is the key of the font we are displaying.
key gFontTexture = "b2e7394f-5e54-aa12-6e1c-ef327b6bed9e";
// All displayable characters. Default to ASCII order.
string gCharIndex;
integer gActive; //if we are recognized, this is true
/////////// END GLOBAL VARIABLES ////////////
ResetCharIndex() {
gCharIndex = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`";
gCharIndex += "abcdefghijklmnopqrstuvwxyz{|}~";
gCharIndex += "\n\n\n\n\n";
}
vector GetGridOffset(integer index) {
// Calculate the offset needed to display this character.
integer Row = index / 10;
integer Col = index % 10;
// Return the offset in the texture.
return <-0.45 + 0.1 * Col, 0.45 - 0.1 * Row, 0.0>;
}
ShowChars(integer link,vector grid_offset1, vector grid_offset2, vector grid_offset3, vector grid_offset4, vector grid_offset5) {
// Set the primitive textures directly.
// <-0.256, 0, 0>
// <0, 0, 0>
// <0.130, 0, 0>
// <0, 0, 0>
// <-0.74, 0, 0>
llSetLinkPrimitiveParams( link,[
PRIM_TEXTURE, FACE_1, (string)gFontTexture, <0.126, 0.1, 0>, grid_offset1 + <0.037, 0, 0>, 0.0,
PRIM_TEXTURE, FACE_2, (string)gFontTexture, <0.05, 0.1, 0>, grid_offset2, 0.0,
PRIM_TEXTURE, FACE_3, (string)gFontTexture, <-0.74, 0.1, 0>, grid_offset3 - <0.244, 0, 0>, 0.0,
PRIM_TEXTURE, FACE_4, (string)gFontTexture, <0.05, 0.1, 0>, grid_offset4, 0.0,
PRIM_TEXTURE, FACE_5, (string)gFontTexture, <0.126, 0.1, 0>, grid_offset5 - <0.037, 0, 0>, 0.0
]);
}
RenderString(integer link, string str) {
// Get the grid positions for each pair of characters.
vector GridOffset1 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 0, 0)) );
vector GridOffset2 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 1, 1)) );
vector GridOffset3 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 2, 2)) );
vector GridOffset4 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 3, 3)) );
vector GridOffset5 = GetGridOffset( llSubStringIndex(gCharIndex, llGetSubString(str, 4, 4)) );
// Use these grid positions to display the correct textures/offsets.
ShowChars(link,GridOffset1, GridOffset2, GridOffset3, GridOffset4, GridOffset5);
}
RenderExtended(integer link, string str) {
// Look for escape sequences.
list Parsed = llParseString2List(str, [], [ESCAPE_SEQUENCE]);
integer ParsedLen = llGetListLength(Parsed);
// Create a list of index values to work with.
list Indices;
// We start with room for 5 indices.
integer IndicesLeft = 5;
integer i = 0;
string Token;
integer Clipped;
integer LastWasEscapeSequence = FALSE;
// Work from left to right.
for (; i < ParsedLen && IndicesLeft > 0; ++i) {
Token = llList2String(Parsed, i);
// If this is an escape sequence, just set the flag and move on.
if (Token == ESCAPE_SEQUENCE) {
LastWasEscapeSequence = TRUE;
}
else { // Token != ESCAPE_SEQUENCE
// Otherwise this is a normal token. Check its length.
Clipped = FALSE;
integer TokenLength = llStringLength(Token);
// Clip if necessary.
if (TokenLength > IndicesLeft) {
Token = llGetSubString(Token, 0, IndicesLeft - 1);
TokenLength = llStringLength(Token);
IndicesLeft = 0;
Clipped = TRUE;
}
else
IndicesLeft -= TokenLength;
// Was the previous token an escape sequence?
if (LastWasEscapeSequence) {
// Yes, the first character is an escape character, the rest are normal.
// This is the extended character.
Indices += (llSubStringIndex(EXTENDED_INDEX, llGetSubString(Token, 0, 0)) + 95);
// These are the normal characters.
integer j = 1;
for (; j < TokenLength; ++j)
Indices += llSubStringIndex(gCharIndex, llGetSubString(Token, j, j));
}
else { // Normal string.
// Just add the characters normally.
integer j;
for (j = 0; j < TokenLength; ++j)
Indices += llSubStringIndex(gCharIndex, llGetSubString(Token, j, j));
}
// Unset this flag, since this was not an escape sequence.
LastWasEscapeSequence = FALSE;
}
}
// Use the indices to create grid positions.
vector GridOffset1 = GetGridOffset( llList2Integer(Indices, 0) );
vector GridOffset2 = GetGridOffset( llList2Integer(Indices, 1) );
vector GridOffset3 = GetGridOffset( llList2Integer(Indices, 2) );
vector GridOffset4 = GetGridOffset( llList2Integer(Indices, 3) );
vector GridOffset5 = GetGridOffset( llList2Integer(Indices, 4) );
// Use these grid positions to display the correct textures/offsets.
ShowChars(link,GridOffset1, GridOffset2, GridOffset3, GridOffset4, GridOffset5);
}
integer ConvertIndex(integer index) {
// This converts from an ASCII based index to our indexing scheme.
if (index >= 32) // ' ' or higher
index -= 32;
else { // index < 32
// Quick bounds check.
if (index > 15)
index = 15;
index += 94; // extended characters
}
return index;
}
default
{
state_entry()
{
// Initialize the character index.
ResetCharIndex();
llMessageLinked(LINK_THIS, REGISTER_SLAVE, llGetScriptName() , NULL_KEY);
}
on_rez(integer num)
{
llResetScript();
}
link_message(integer sender, integer channel, string data, key id)
{
if (channel == SLAVE_RECOGNIZED)
{
if (data == llGetScriptName())
{
gActive=TRUE;
}
return;
}
if (channel == SLAVE_DISPLAY)
{
if (!gActive)
return;
list params=llCSV2List((string)id);
if (llList2String(params, 1) != llGetScriptName())
return;
RenderString(llList2Integer(params, 0),data);
return;
}
if (channel == SLAVE_DISPLAY_EXTENDED)
{
if (!gActive)
return;
list params=llCSV2List((string)id);
if (llList2String(params, 1) != llGetScriptName())
return;
RenderExtended(llList2Integer(params, 0),data);
}
if (channel == SET_FONT_TEXTURE)
{
gFontTexture = id;
return;
}
if (channel == REMAP_INDICES) {
// Parse the message, splitting it up into index values.
list Parsed = llCSV2List(data);
integer i;
// Go through the list and swap each pair of indices.
for (i = 0; i < llGetListLength(Parsed); i += 2) {
integer Index1 = ConvertIndex( llList2Integer(Parsed, i) );
integer Index2 = ConvertIndex( llList2Integer(Parsed, i + 1) );
// Swap these index values.
string Value1 = llGetSubString(gCharIndex, Index1, Index1);
string Value2 = llGetSubString(gCharIndex, Index2, Index2);
gCharIndex = llDeleteSubString(gCharIndex, Index1, Index1);
gCharIndex = llInsertString(gCharIndex, Index1, Value2);
gCharIndex = llDeleteSubString(gCharIndex, Index2, Index2);
gCharIndex = llInsertString(gCharIndex, Index2, Value1);
}
return;
}
if (channel == RESET_INDICES) {
// Restore the character index back to default settings.
ResetCharIndex();
return;
}
if (channel == SLAVE_RESET)
{
ResetCharIndex();
gActive=FALSE;
llMessageLinked(LINK_THIS, REGISTER_SLAVE, llGetScriptName() , NULL_KEY);
}
}
}
Prim Setup (Caution! Not compatible with 5 face double texture Xytext):
////////////////////////////////////////////
// XyzzyText Prim Setup Script (5 Face)
//
// Modified by Thraxis Epsilon
//
////////////////////////////////////////////
default
{
state_entry()
{
llSetPrimitiveParams([
PRIM_TYPE, PRIM_TYPE_PRISM, PRIM_HOLE_DEFAULT, <0.199, 0.8, 0.0>, 0.68, <0.0, 0.0, 0.0>, <1.0, 1.0, 0.0>, <0.0, 0.0, 0.0>,
PRIM_SIZE, <0.03, 2.89, 0.5>,
PRIM_TEXTURE, 1, "09b04244-9569-d21f-6de0-4bbcf5552222", <0.126, 0.10, 0.0>, <-0.740013, 0.0, 0.0>, 0.0,
PRIM_TEXTURE, 6, "09b04244-9569-d21f-6de0-4bbcf5552222", <0.050, 0.100, 0.00>, <0.0, 0.0, 0.0>, 0.0,
PRIM_TEXTURE, 4, "09b04244-9569-d21f-6de0-4bbcf5552222", <-0.740, 0.10, 0.00>, <0.130009, 0.0, 0.0>, 0.0,
PRIM_TEXTURE, 7, "09b04244-9569-d21f-6de0-4bbcf5552222", <0.050, 0.100, 0.00>, <0.0, 0.0, 0.0>, 0.0,
PRIM_TEXTURE, 3, "09b04244-9569-d21f-6de0-4bbcf5552222", <0.126, 0.10, 0.0>, <-0.255989, 0.0, 0.0>, 0.0]);
llRemoveInventory(llGetScriptName());
}
}