code from the prim it is running in. This script doesn't support prim torture, and due to limitations in SL it cannot reproduce hover text or client-side rotations that have been added to the prim with
// TLML Exporter v0.30, drop in a page's prim to get the corresponding TLML code
// ===How to get unicode characters in your llSetText_text===
// "\\uxxxx" where xxxx are 4 hex characters, unicode character 0000xxxx
// "\\Uxxxxxxxx" where xxxxxxxx are 8 hex characters, unicode character xxxxxxxx
// "\\n" new line do not use "\n"
// "\\\\" \
// "\\\"" "
// "\\t" same as "\t", which you may use
// ""
vector offset = <0.0,0.0,1.0>;
string llSetText_text = "";
vector llSetText_color = <1.0,1.0,1.0>;
float llSetText_alpha = 1.0;
vector llTargetOmega_axis = ZERO_VECTOR;
float llTargetOmega_spinrate = 0.0;
float llTargetOmega_gain = 0.0;
//ANIM_ON == 0x01
//LOOP == 0x02
//REVERSE == 0x04
//PING_PONG == 0x08
//SMOOTH == 0x10
//ROTATE == 0x20
//SCALE == 0x40
integer llSetTextureAnim_mode = 0;
integer llSetTextureAnim_face = ALL_SIDES;
integer llSetTextureAnim_x_frames = 2;
integer llSetTextureAnim_y_frames = 2;
float llSetTextureAnim_start_frame = 0;
float llSetTextureAnim_end_frame = 3;
float llSetTextureAnim_rate = 0.1;
string TLML_URL = "";
list llParticleSystem_list = [];
setParticles()
{
llParticleSystem_list += [];
}
//////////////////////////////////////////////////////////////
// DO NOT MODIFY ANYTHING BELOW //
//////////////////////////////////////////////////////////////
//This script is a nightmare, only the brave should venture deeper
//adding support for new features is pretty easy
//but don't touch the structure of the script
//because of the complexities of TLML, the data layout is complex
//the *right* was to do this would be with 3 passes
//1) determin the mask
//2) parse the masks and filling in the data
//Instead we do it with basicly a single pass
//Then as the masks become aparent we insert them into the stream.
//This saves alot of time with minimal expense
//Unfortunately it's horribly complex and incredibly hard to read
//To grok this script in it's entirety is to be avoided.
//{
//}
//{
//}
//{
string byte2hex(integer x)
{//Helper function for use with unicode characters.
integer x0 = (x & 0xF);
return llGetSubString(hexc, x0 = ((x >> 4) & 0xF), x0) + llGetSubString(hexc, x0, x0);
}
string Unescape(string a)
{
string b = a;
integer c = -1;
integer d;
integer e;
integer f = 0;
string g;
while(d = llSubStringIndex(b, "\\") + 1)
{
g = llGetSubString(b,d,d);
c += d;
if((g == "\"") || (g == "\\"))
a = llDeleteSubString(a,c,c);
else if(g == "n")
a = llInsertString(llDeleteSubString(a,c,c+1), c, "\n");
else if(g == "t")
a = llInsertString(llDeleteSubString(a,c,c+1), c, "\t");
else if(g == "r")//rx[11,22,33,44,55,66,77,88,99,AA,BB,CC,DD,EE,FF]
{
g = "";
if(d+(e = (integer)("0x"+llGetSubString(b,d+1,d+1)) * 2)+1 >= (f = llStringLength(b)))
e = (f - d - 2) & -2;
if((f = e))//this may look like a mistake, it's not $[E20002]
{
do
g = "%"+llGetSubString(b,d + e,d + e + 1) + g;
while((e-=2) > 0);
}
a = llInsertString(llDeleteSubString(a,c, c + 2 + f),c, g = llUnescapeURL(g));
c += llStringLength(g);//add to c so we don't accidentily unescape result
}
else if(g == "u" || (e = (g == "U")))// \uXXXX or \UXXXXXXXX
{
a = llDeleteSubString(a, c, c + 5 + e *= 4);
if(0 < e = (integer)("0x"+llGetSubString(b,d +1, d +4 + e)))
{
if (e >= 0x4000000)
f = 5;
else if (e >= 0x200000)
f = 4;
else if (e >= 0x10000)
f = 3;
else if (e >= 0x800)
f = 2;
else if (e >= 0x80)
f = 1;
g = "%" + byte2hex((e >> (6 * f)) | ((0x3F80 >> f) * (0 != f)));
while(f)
g += "%" + byte2hex((((e >> (6 * --f)) | 0x80) & 0xBF));
a = llInsertString(a, c++, llUnescapeURL(g));
}
}
b = llDeleteSubString(a,0,c);
}
return a;
}
//alternative licensensing exculsively granted for this script, acknowlegment is not required for use.
string Float2Hex(float a)
{// Copyright Strife Onizuka, 2006, LGPL, http://www.gnu.org/copyleft/lesser.html
if(a != 0)
{
float b = llFabs(a);
string f = "";
integer c = llFloor(llLog(b) / 0.69314718055994530941723212145818);//floor(log2(b))
integer d = (integer)((b / llPow(2.0,c)) * 0x1000000);//shift up into integer range
c -= 24;//the extra c used to make it an integer
while(!(d & 0xf))
{//strip extra zeros off before converting or they break "p"
d = d >> 4;
c+=4;
}
do
f = llGetSubString(hexc,15&d,15&d) + f;
while(d = d >> 4);
if(a < 0)
return "-0x" + f + "p"+(string)c;
return "0x" + f + "p"+(string)c;
}
return "0";//zero would screw up the log.
}
string flo(float a)
{
string b = (string)a;
while(llGetSubString(b,-1,-1) == "0")
b=llDeleteSubString(b,-1,-1);
if(llGetSubString(b,-1,-1) == ".")
return llDeleteSubString(b,-1,-1);
if(llGetSubString(b,(a<0),(a<0)+1)=="0.")
return llDeleteSubString(b,(a<0),(a<0));
return b;
}
string vec(vector a)
{
if(a == ZERO_VECTOR) return "";
return "<"+flo(a.x)+","+flo(a.y)+","+flo(a.z)+">";
}
string vecF2H(vector a)
{
if(a == ZERO_VECTOR) return "";
list b = ["<",flo(a.x),",",flo(a.y),",",flo(a.z),">"];
vector c = (vector)((string)b);
if(c.x != a.x)
b = llListReplaceList(b, [Float2Hex(a.x)], 1, 1);
if(c.y != a.y)
b = llListReplaceList(b, [Float2Hex(a.y)], 3, 3);
if(c.z != a.z)
b = llListReplaceList(b, [Float2Hex(a.z)], 5, 5);
return (string)b;
}
string rot(rotation a)
{
if(a == ZERO_ROTATION) return "";
list b = ["<",flo(a.x),",",flo(a.y),",",flo(a.z),",",flo(a.s),">"];
rotation c = (rotation)((string)b);
if(c.x != a.x)
b = llListReplaceList(b, [Float2Hex(a.x)], 1, 1);
if(c.y != a.y)
b = llListReplaceList(b, [Float2Hex(a.y)], 3, 3);
if(c.z != a.z)
b = llListReplaceList(b, [Float2Hex(a.z)], 5, 5);
if(c.s != a.s)
b = llListReplaceList(b, [Float2Hex(a.s)], 7, 7);
return (string)b;
}
string int(integer a)
{
if(a == 0) return "";
return (string)a;
}
string TightListDump(list a, string b)
{
string c = (string)a;
if(llStringLength(b)==1)
if(llSubStringIndex(c,b) == -1)
jump end;
integer d = -llStringLength(b += "|\\/?!@#$%^&*()_=:;~{}[],\n\" qQxXzZ");
while(1+llSubStringIndex(c,llGetSubString(b,d,d)) && d)
++d;
b = llGetSubString(b,d,d);
@end;
c = "";//save memory
return b + llDumpList2String(a, b+(string)(a = []));
}
string TightListTypeDump(list a, string b) {
b += "|\\/?!@#$%^&*()_=:;~{}[],\n\" qQxXzZ";
string c = (string)a;
integer d = 0;
do
if(1+llSubStringIndex(c,llGetSubString(b,d,d)))
b = llDeleteSubString(b,d,d);
else
++d;
while(d<6);
b = " " + c = llGetSubString(b,0,5);
integer e;
string f;
if((d = -llGetListLength(a)))
{
do
{
e = llGetListEntryType(a,d);
if((e > 0 && e < 3) || e > 4) f = (string)lis(llList2List(a,d,d));
else
f = llList2String(a,d);
c+= llGetSubString(b,e,e) + f;
}while(++d);
}
return c;
}
list lis(list a)
{
integer b = -llGetListLength(a) - 1;
list c;
integer d;
while(++b)
{
if((d = llGetListEntryType(a,b)) == TYPE_FLOAT)
{
float e = llList2Float(a,b);
if(e != 0.0)
c += flo(e);
else
c += "";
}
else if(d == TYPE_VECTOR)
c += vec(llList2Vector(a,b));
else if(d == TYPE_ROTATION)
c += rot(llList2Rot(a,b));
else if(d == TYPE_INTEGER)
c += int(llList2Integer(a,b));
else
c += llList2String(a,b);
}
return c;
}
string hex(integer x)
{
integer x0 = x & 0xF;
string res = llGetSubString(hexc, x0, x0);
x = (x >> 4) & 0x0FFFFFFF; //otherwise we get infinite loop on negatives.
while( x != 0 )
{
x0 = x & 0xF;
res = llGetSubString(hexc, x0, x0) + res;
x = x >> 4;
}
return res;
}
string hexc="0123456789ABCDEF";
//}
add(string value, integer mask)
{
if(llStringLength(llDumpList2String(header+params," ")+value) > 247)
{
store();
if(mode & param_mask)
mode = mode & attribute_mask;
}
mode = mode | mask;
params += value;
}
store()
{
break();
if(mode & param_mask)
{
recycle_mask = recycle_mask & ~default_mask;
++cc;
}
commands += TightListDump(llDeleteSubList(params,-1,-1),(string)(params = []));
if(llGetListLength(commands) == 1)
header = llListReplaceList(header,[""],1,1);
params = header + [sep];
}
break()
{
list s = [sep];
integer b = llListFindList(params, s);
integer a;
integer k;
if(llList2String(params,-1) != sep)//it's possible we might be on a boarder already.
params += mode;
else
params = llDeleteSubList(params,-1,-1);
if(b + 1)
{
list r = [hex(recycle_mask)];
string p = hex(a = recycle_mask & ~default_mask);
if((recycle_mask && !cc) || (a && cc))
{
if(cc)
r = [p];
k = config_mask;
}
else
r = [];
while((b = 1 + llListFindList(llDeleteSubList(params + s, 0, a = b),s)))
{
b += a;
params = llListReplaceList(llDeleteSubList(params,b - 1, b),[hex(llList2Integer(params, b - 1) | k)] + r, a, a);
if(k)
r = [p];
}
}
// llOwnerSay("a"+(string)recycle_mask+TightListDump(params,""));
params += sep;
}
burn()
{
integer a = -llGetListLength(commands);
integer k;
string m = hex(recycle_mask);
string p = hex(recycle_mask & ~default_mask);
string n;
integer j = llStringLength(sep) - 1;
if(a)
{
do
{
if(1 + k = llSubStringIndex(n = llList2String(commands,a),sep))
{
do
n = llInsertString(llDeleteSubString(n, k, k+j),k,m);
while(1 + k = llSubStringIndex(n,sep));
commands = llListReplaceList(commands, [n], a, a);
}
// llOwnerSay("b"+(string)recycle_mask+n);
m = p;
}
while(++a);
}
cc = 0;
}
//{
theFace(integer f)
{
mode = (((multiplefaces >> 32) | f) & 0xF);
if(multiplefaces & 0x40)
mode = mode | 0x40 |
(0x80 * (llList2Integer(llGetPrimitiveParams([PRIM_FULLBRIGHT, f]), 0) !=0));
string t_s;
if(multiplefaces & 0x100)
{
if((t_s = llGetTexture(f)) == "5748decc-f629-461c-9a36-a35a221fe21f")
recycle_mask = recycle_mask | 0x1;
else
add(t_s, 0x100);
}
vector t_v;
if(multiplefaces & 0x200)
{
if ((t_v = llGetColor(f)) != <1.0, 1.0, 1.0>)
add(vec(t_v), 0x200);
else
recycle_mask = recycle_mask | 0x2;
}
float t_f;
if(multiplefaces & 0x400)
{
if ((t_f = llGetAlpha(f)) != 1.0)
add(flo(t_f), 0x400);
else
recycle_mask = recycle_mask | 0x4;
}
if(multiplefaces & 0x800)
{
if ((t_v = llGetTextureScale(f)) != <1.0, 1.0, 0.0>)
add(vec(t_v), 0x800);
else
recycle_mask = recycle_mask | 0x8;
}
if(multiplefaces & 0x1000)
{
if ((t_v = llGetTextureOffset(f)) != ZERO_VECTOR)
add(vec(t_v), 0x1000);
else
recycle_mask = recycle_mask | 0x10;
}
if(multiplefaces & 0x2000)
{
if ((t_f = llGetTextureRot(f)) != 0.0)
add(flo(t_f), 0x2000);
else
recycle_mask = recycle_mask | 0x20;
}
if(multiplefaces & (0x4000 | 0x8000))
{
list t_l = llGetPrimitiveParams([PRIM_BUMP_SHINY, f]);
integer t_i;
if(multiplefaces & 0x4000)
{
if ((t_i = llList2Integer(t_l, 0)) != PRIM_SHINY_NONE)
add((string)t_i, 0x4000);
else
recycle_mask = recycle_mask | 0x40;
}
if(multiplefaces & 0x8000)
{
if ((t_i = llList2Integer(t_l, 1)) != PRIM_BUMP_NONE)
add((string)t_i, 0x8000);
else
recycle_mask = recycle_mask | 0x80;
}
}
}
checkFaces()
{
integer max = llGetNumberOfSides();
multiplefaces = FALSE;
string texture = llGetTexture(0);
vector texture_scale = llGetTextureScale(0);
vector texture_offset = llGetTextureOffset(0);
float texture_rot = llGetTextureRot(0);
vector color = llGetColor(0);
float alpha = llGetAlpha(0);
list fullbrights = llGetPrimitiveParams([PRIM_FULLBRIGHT, ALL_SIDES]);
integer fullbright = llList2Integer(fullbrights, 0);
list bump_shiny = llGetPrimitiveParams([PRIM_BUMP_SHINY, ALL_SIDES]);
integer bump = llList2Integer(bump_shiny,1);
integer shiny = llList2Integer(bump_shiny,0);
integer i = 1;
integer m = 0x40 | 0x100 | 0x200 | 0x400 | 0x800 |
0x1000 | 0x2000 | 0x4000 | 0x8000;
for (; i<max && multiplefaces != m; ++i)
{
if (llList2Integer(fullbrights, i) != fullbright)
multiplefaces = multiplefaces | 0x40;
if (llGetTexture(i) != texture)
multiplefaces = multiplefaces | 0x100;
if (llGetColor(i) != color)
multiplefaces = multiplefaces | 0x200;
if (llGetAlpha(i) != alpha)
multiplefaces = multiplefaces | 0x400;
if (llGetTextureScale(i) != texture_scale)
multiplefaces = multiplefaces | 0x800;
if (llGetTextureOffset(i) != texture_offset)
multiplefaces = multiplefaces | 0x1000;
if (llGetTextureRot(i) != texture_rot)
multiplefaces = multiplefaces | 0x2000;
if (llList2Integer(bump_shiny, i* 2 + 1) != bump)
multiplefaces = multiplefaces | 0x4000;
if (llList2Integer(bump_shiny, i* 2) != shiny)
multiplefaces = multiplefaces | 0x8000;
}
if(multiplefaces != m)
{
mode = mode | 0x1;
multiplefaces = ~(i = multiplefaces);
theFace(0);
multiplefaces = i;
}
}
checkPrim()
{
list type = llGetPrimitiveParams([PRIM_TYPE]);
if (llList2Integer(type, 0) == 0)
if (llList2Integer(type, 1) == 0)
if (llList2Vector(type, 2) == <0.0, 1.0, 0.0>)
if (llList2Float(type, 3) == 0.0)
if (llList2Vector(type, 4) == ZERO_VECTOR)
if (llList2Vector(type, 5) == <1.0, 1.0, 0.0>)
if (llList2Vector(type, 6) == ZERO_VECTOR)
{
recycle_mask = recycle_mask | 0x1;
return;
}
add(TightListDump(lis(type),"*"), 0x4);
}
//}
string sep;
integer mode;
integer multiplefaces;
list params;
list header;
integer recycle_mask;
list commands;
integer cc;
integer default_mask;
integer config_mask;
integer param_mask;
integer attribute_mask;
default
{
state_entry()
{
setParticles();
llSetText(Unescape(llSetText_text), llSetText_color, llSetText_alpha);
llTargetOmega(llTargetOmega_axis, llTargetOmega_spinrate, llTargetOmega_gain);
llParticleSystem(llParticleSystem_list);
llSetTextureAnim(llSetTextureAnim_mode, llSetTextureAnim_face, llSetTextureAnim_x_frames, llSetTextureAnim_y_frames,
llSetTextureAnim_start_frame,llSetTextureAnim_end_frame,llSetTextureAnim_rate);
llOwnerSay("--------------------------------------");
sep = llUnescapeURL("%01");
// sep = " ";
if((llGetObjectPermMask(MASK_OWNER) & 0x0000E000) != 0x0000E000)
{//If you remove this check the script will not function any better.
//Many of the functions used to gather information do the same permissions check internaly
//Those functions will cause error messages and an invalid TLML stream.
//YOU HAVE BEEN WARNED.
llOwnerSay("You cannot clone an object you do not have full permission on");
return;
}
if(TLML_URL == "")
TLML_URL = "-"+llGetObjectDesc();
header = [llGetLinkNumber(), TLML_URL];
params = header + [sep];
default_mask = 0xF;
param_mask = 0xffffFFFC;
attribute_mask = 0x0;
config_mask = 0x1;
//{
checkPrim();
add(vec(llGetScale()), 0x10);
if (llGetLinkNumber() >= 2)// || rot_offset != ZERO_ROTATION)
{
vector pos = offset + (llGetLocalPos() );//* rot_offset);
if(pos != ZERO_VECTOR)
add(vecF2H(pos), 0x20);
rotation local = llGetLocalRot();// * rot_offset; // or is it rot_offset * llGetLocalRot(); ?
if (local != ZERO_ROTATION)
add(rot(llGetLocalRot()), 0x80);
else
recycle_mask = recycle_mask | 0x2;
}
else
{
recycle_mask = recycle_mask | 0x2;
if(offset != ZERO_VECTOR)
add(vecF2H(offset), 0x20);
}
if(llSetText_text != "")
{
add(llSetText_text, 0x100);
if(llSetText_color != <1.0,1.0,1.0> || llSetText_alpha != 1.0)
add(rot(<llSetText_color.x, llSetText_color.y, llSetText_color.z, llSetText_alpha>), 0x200);
else
recycle_mask = recycle_mask | 0x8;
}
else
recycle_mask = recycle_mask | 0x4 | 0x8;
if(llParticleSystem_list != [])
{
add(TightListTypeDump(llParticleSystem_list,"*@#$%^&"), 0x400);
recycle_mask = recycle_mask | 0x10;
}
if(llTargetOmega_axis != ZERO_VECTOR || llTargetOmega_spinrate != 0.0 || llTargetOmega_gain != 0.0)// $[E20011]
{
add(TightListDump([vec(llTargetOmega_axis),flo(llTargetOmega_spinrate),flo(llTargetOmega_gain)],"*"), 0x800);
recycle_mask = recycle_mask | 0x20;
}
if(llSetTextureAnim_mode)
{
add(TightListDump([llSetTextureAnim_face, llSetTextureAnim_mode, llSetTextureAnim_x_frames, llSetTextureAnim_y_frames,
flo(llSetTextureAnim_start_frame),flo(llSetTextureAnim_end_frame),flo(llSetTextureAnim_rate)],"*"), 0x1000);
recycle_mask = recycle_mask | 0x40;
}
//}
break();
burn();
header += "-";
default_mask = 0xFF;
recycle_mask = 0;
param_mask = 0xffffFFF0;
config_mask = 0x10;
attribute_mask = 0x0CF;
checkFaces();
integer t = llGetNumberOfSides();
integer c;
if(multiplefaces)
{
while(c < t)
{
break();
burn();
recycle_mask = 0;
theFace(c++);
}
}
store();
burn();
t = -llGetListLength(commands);
// llOwnerSay("-----------------------");
while(t)
llOwnerSay("T"+llList2String(commands,t++));
llRemoveInventory(llGetScriptName());
}
}