//primset+++ - Includes support for llGet/SetLinkPrimitiveParams, linkset resize, llLinkParticleSystem, and
//llSetKeyframeMotion
// Used by the primcontrol HUD.
//This function typecasts a list of strings, into the types they appear to be.
//Extremely useful for feeding user data into llSetPrimitiveParams
//It takes a list as an input, and returns that list, with all elements correctly typecast, as output
//Written by Fractured Crystal, 27 Jan 2010, Commissioned by WarKirby Magojiro, this function is Public Domain
//Modified by Rufus Darkfold to keep strings like <foo> instead of discarding them entirely from the output
list list_cast(list in)
{
list out;
integer i;
integer l= llGetListLength(in);
for (i=0; i < l; i++)
{
string d= llStringTrim(llList2String(in,i),STRING_TRIM);
if (d == "") out += "";
else
{
if (llGetSubString(d,0,0) == "<")
{
if (llGetSubString(d,-1,-1) == ">")
{
list s = llParseString2List(d,[","],[]);
integer sl= llGetListLength(s);
if (sl == 3) {
out += (vector)d;
} else if(sl == 4) {
out += (rotation)d;
} else
out += [d];
} else
out += [d];
} else if (~llSubStringIndex(d,".")) {
out += (float)d;
} else {
integer lold = (integer)d;
if ((string)lold == d) out += lold;
else
{
key kold = (key)d;
if (kold) out += [kold];
else out += [d];
}
}
}
}
//for (i = 0; i< llGetListLength(out); i++){
// llOwnerSay("Element " + (string)i + " type is " + (string)llGetListEntryType(out, i)
// + " value is «" + llList2String(out,i) + "»");
//}
return out;
}
integer dimTest( vector vr )
{
return !( vr.x<0.01 || vr.y<0.01 || vr.z<0.01 || vr.x>64.0 || vr.y>64.0 || vr.z>64.0 );
}
resize_linkset( vector scal )
{
integer primindx;
list primP;
vector s = llGetScale();
integer validDim = dimTest( <scal.x*s.x,scal.y*s.y,scal.z*s.z> );
for ( primindx = 2; primindx <= llGetNumberOfPrims(); primindx++ )
{
primP = llGetLinkPrimitiveParams( primindx, [PRIM_SIZE]);
s = llList2Vector( primP, 0 );
validDim = validDim && dimTest( <scal.x*s.x,scal.y*s.y,scal.z*s.z> );
}
if ( validDim )
{
s = llGetScale();
llSetScale( <scal.x*s.x,scal.y*s.y,scal.z*s.z> );
for ( primindx = 2; primindx <= llGetNumberOfPrims(); primindx++ )
{
primP = llGetLinkPrimitiveParams( primindx, [PRIM_SIZE, PRIM_POSITION]);
vector primScale = llList2Vector( primP, 0 );
primScale = <primScale.x*scal.x, primScale.y*scal.y, primScale.z*scal.z>;
vector primPos = llList2Vector( primP, 1 ) - llGetPos();
primPos = <primPos.x*scal.x, primPos.y*scal.y, primPos.z*scal.z>;
llSetLinkPrimitiveParamsFast( primindx, [PRIM_SIZE, primScale, PRIM_POSITION, primPos/llGetRootRotation()]);
}
}
else llOwnerSay("No resize! Out of limit sizes are not accepted");
}
debugout(string msg)
{
llOwnerSay(msg);
}
integer outchan =0;
reply(string msg)
{
llRegionSayTo(llGetOwner(), outchan, msg);
if (outchan) {
debugout(msg);
}
}
integer channel = 884;
list subset;
integer hlis;
float timeout = 300; // stop listening after 5 minutes of inactivity
vector lastpos;
rotation lastrot;
default
{
timer()
{
if (hlis){
llOwnerSay("Deslecting " + llGetObjectName());
llListenRemove(hlis);
hlis = 0;
}
}
touch_start(integer num)
{
llSetTimerEvent(timeout);
llResetTime();
if (!hlis) {
hlis = llListen(channel, "", "", "");
llOwnerSay(llGetObjectName() + " selected. Listening on channel " + (string)channel);
return;
}
while (num--) {
integer child=llDetectedLinkNumber(num);
integer j = llListFindList(subset,[child]);
if (~j) {
llOwnerSay("Deselecting #" + (string)child);
subset = llDeleteSubList(subset, j, j);
} else {
llOwnerSay("Selecting #" + (string)child);
subset += child;
}
}
}
listen(integer ch, string name, key id, string msg)
{
//llOwnerSay(msg + " from " + (string)id + " owned by " + (string)llGetObjectDetails(id, [OBJECT_OWNER]));
if (llGetOwner() != id) {
if (llList2Key(llGetObjectDetails(id, [OBJECT_OWNER]),0) != llGetOwner())
return;
}
outchan = 0;
if (msg == "") {
subset = [];
llSetTimerEvent(0.1); // empty message = disconnect right away;
return;
}
llSetTimerEvent(timeout);
if (llGetSubString(msg, 0, 0) == "/") { // specify response channel
integer endch = llSubStringIndex(msg, " ");
outchan = (integer)llGetSubString(msg, 1, endch);
msg = llGetSubString(msg, endch+1, -1);
}
if (llGetSubString(msg,0,0) == "[") {
integer e = llSubStringIndex(msg, "]");
if (e > 1)
subset = list_cast(llCSV2List(llGetSubString(msg, 1, e-1)));
else
subset = [];
msg = llStringTrim(llGetSubString(msg, e+1, -1), STRING_TRIM_HEAD);
if (llList2String(subset,0) == "*") {
integer i;
subset = [];
for (i=1; i<=llGetNumberOfPrims(); i++) subset += i;
}
}
list sub;
list cmds;
if (llGetSubString(msg,0,0) == "?") {
cmds = list_cast(llCSV2List(llGetSubString(msg, 1, -1)));
integer i;
list curr;
if (subset == []) // If not specified use root (or only) prim
sub = [ (llGetNumberOfPrims() > 1) ];
else
sub = subset;
debugout(llList2CSV(cmds));
for (i = 0; i<llGetListLength(sub); i++) {
if (llGetListEntryType(sub,i) == TYPE_INTEGER){
integer j = llList2Integer(sub,i);
curr = llGetLinkPrimitiveParams(j, cmds);
reply("[" + (string)j + "] " + llList2CSV(curr));
}
else //if (llGetListEntryType(subset,i) == TYPE_STRING)
{
integer k;
string x=llList2String(sub,i);
list exp;
for (k=1; k<=llGetNumberOfPrims(); k++) {
if (~llListFindList(llGetLinkPrimitiveParams(k,[PRIM_NAME,PRIM_DESC]),
[x]))
{
curr = llGetLinkPrimitiveParams(k, cmds);
exp += k;
reply("[" + (string)k + "] " + llList2CSV(curr));
}
}
debugout(x + " is " + llList2CSV(exp));
}
}
return;
}
if (llGetSubString(msg,0,0) == "$") {
msg = llDeleteSubString(msg,0,0);
vector v = (vector)msg;
if (v == ZERO_VECTOR) {
float scal=(float)msg;
v = <scal,scal,scal>;
}
resize_linkset(v);
return;
} else if (llGetSubString(msg,0,0) == "%") {
msg = llDeleteSubString(msg,0,0);
cmds = list_cast(llCSV2List(msg));
if (subset == [])
sub = [LINK_SET];
else
sub = subset;
debugout("ParticleSystem On " + llList2CSV(subset) +":\nCmds: "+ llDumpList2String(cmds,"; "));
integer i;
for (i = 0; i<llGetListLength(sub); i++) {
if (llGetListEntryType(sub,i) == TYPE_INTEGER)
llLinkParticleSystem(llList2Integer(sub,i), cmds);
else //if (llGetListEntryType(subset,i) == TYPE_STRING)
{
integer k;
string x=llList2String(sub,i);
list exp;
for (k=llGetNumberOfPrims(); k; k--) {
if (~llListFindList(llGetLinkPrimitiveParams(k,[PRIM_NAME,PRIM_DESC]),[x]))
{
llLinkParticleSystem(k, cmds);
exp += k;
}
}
debugout(x + " is " + llList2CSV(exp));
}
}
return;
} else if (llGetSubString(msg,0,0) == "@") {
if (subset != []) {
if (!~llListFindList(subset,[llGetNumberOfPrims() > 1]) && !~llListFindList(subset,[llGetObjectName()])) {
return;
}
}
integer direction = KFM_FORWARD;
msg = llDeleteSubString(msg,0,0);
string pfx2 = llGetSubString(msg,0,0);
if ( pfx2 == "%") {
direction = KFM_PING_PONG;
msg = llDeleteSubString(msg,0,0);
} else if (pfx2 == "^") {
direction = KFM_REVERSE;
msg = llDeleteSubString(msg,0,0);
} else if (pfx2 == "@") {
if (msg == "@@") {
llSetKeyframedMotion([], [KFM_COMMAND, KFM_CMD_STOP]);
llSetPos(lastpos);
llSetRot(lastrot);
return;
}
llSetKeyframedMotion([], [KFM_COMMAND, KFM_CMD_PAUSE]);
return;
} else if (pfx2 == "!") {
lastpos = llGetPos();
lastrot = llGetRot();
llSetKeyframedMotion([], [KFM_COMMAND, KFM_CMD_PLAY]);
llSetTimerEvent(0.0); // stop the timer while animation is running
return;
} else if (msg == "") {
llSetKeyframedMotion([], [KFM_COMMAND, KFM_CMD_STOP]);
return;
}
lastpos = llGetPos();
lastrot = llGetRot();
cmds = list_cast(llCSV2List(msg));
llSetKeyframedMotion(cmds, [KFM_MODE, direction]);
llSetTimerEvent(0.0); // stop the timer while animation is running
return;
}
cmds = list_cast(llCSV2List(msg));
if (subset == [])
sub = [LINK_SET];
else
sub = subset;
debugout("On " + llList2CSV(subset) +":\nCmds: "+ llDumpList2String(cmds,"; "));
integer i;
for (i = 0; i<llGetListLength(sub); i++) {
if (llGetListEntryType(sub,i) == TYPE_INTEGER)
llSetLinkPrimitiveParamsFast(llList2Integer(sub,i), cmds);
else //if (llGetListEntryType(subset,i) == TYPE_STRING)
{
integer k;
string x=llList2String(sub,i);
list exp;
for (k=llGetNumberOfPrims(); k; k--) {
if (~llListFindList(llGetLinkPrimitiveParams(k,[PRIM_NAME,PRIM_DESC]),[x]))
{
llSetLinkPrimitiveParamsFast(k, cmds);
exp += k;
}
}
debugout(x + " is " + llList2CSV(exp));
}
}
}
}