Primset script

From Second Life Wiki
Jump to navigation Jump to search

See Primset and PrimControl HUD for explanation and the other parts of this system.

<lsl> //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. 
   // Useful for feeding user data into llSetPrimitiveParams
   // Takes list 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 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));
               }
           }
       }
   }

</lsl>