Difference between revisions of "Hierarchics"

From Second Life Wiki
Jump to navigation Jump to search
(oops ^^;)
(Ran through lslint, fixed bugs, removed CheckValidity)
Line 46: Line 46:
// http://creativecommons.org/licenses/by-sa/3.0/
// http://creativecommons.org/licenses/by-sa/3.0/
///////////////////////////
///////////////////////////
 
list hNm  = [];
list hNm  = [];
list hLnk = [];
list hLnk = [];
Line 52: Line 52:
list hRot = [];
list hRot = [];
list hRef = [];
list hRef = [];
 
vector  lastPos;
vector  lastPos;
rotation lastRot;
rotation lastRot;
 
integer Link_HierarchicsRot    = 660333;
integer Link_HierarchicsRot    = 660333;
integer Link_HierarchicsPos    = 660334;
integer Link_HierarchicsPos    = 660334;
Line 63: Line 63:
integer Link_HierarchicsGet    = 660338;
integer Link_HierarchicsGet    = 660338;
integer Link_HierarchicsEdit    = 660339;
integer Link_HierarchicsEdit    = 660339;
integer Link_Delete            = 1337;
 
integer Commanded = FALSE;
integer Commanded = FALSE;
integer Report = FALSE;
integer Report = FALSE;
integer EditMode = FALSE;
integer EditMode = FALSE;
 
float  CheckTimer = 0.3;
float  CheckTimer = 0.3;
 
Update(){
Update(){
     vector Pos = llList2Vector( hPos, 0 );
     vector Pos = llList2Vector( hPos, 0 );
     rotation Rot;
     rotation Rot;
   
     integer x = ( hNm != [] ) - 0; integer y; string z;
     integer x = ( hNm != [] ) - 0; integer y;
     for( y = 1; y < x; ++y ){
     for( y = 1; y < x; ++y ){
         Rot = llList2Rot( hRot, y - 1) * Rot;
         Rot = llList2Rot( hRot, y - 1) * Rot;
         Pos += llList2Vector( hPos, y ) * Rot;
         Pos += llList2Vector( hPos, y ) * Rot;
     }
     }
   
     Rot = llList2Rot( hRef,-1 ) * llList2Rot( hRot, -1 ) * Rot;
     Rot = llList2Rot( hRef,-1 ) * llList2Rot( hRot, -1 ) * Rot;
     Commanded = TRUE;
     Commanded = TRUE;
     llSetPrimitiveParams([ PRIM_POSITION, Pos, PRIM_ROTATION, Rot / llGetRootRotation() ]);
     llSetPrimitiveParams([ PRIM_POSITION, Pos, PRIM_ROTATION, Rot / llGetRootRotation() ]);
}
}
 
RefAndRot(string RefString, rotation CurrentRot){
RefAndRot(string RefString, rotation CurrentRot){
     rotation Rot = ZERO_ROTATION;
     rotation Rot = ZERO_ROTATION;
Line 94: Line 93:
             Ref = llEuler2Rot(v * DEG_TO_RAD);
             Ref = llEuler2Rot(v * DEG_TO_RAD);
         } else { //it might not even be a vector
         } else { //it might not even be a vector
             integer index = llSubStringIndex(in, "<");
             integer index = llSubStringIndex(RefString, "<");
             if(~index){//"<" was found, now insert "-"
             if(~index){//"<" was found, now insert "-"
                 RefString = llGetSubString(RefString, 0, index) + "-" +  
                 RefString = llGetSubString(RefString, 0, index) + "-" +  
Line 108: Line 107:
     hRef += Ref;
     hRef += Ref;
}//Strife Onizuka was here
}//Strife Onizuka was here
 
key Developer1 = "75078730-ebc8-4a80-adb9-1cfd2d95b5ca";
key Developer2 = "3cc2e3fa-2ab0-40fa-822b-6f4ebf66f575";
key Developer3 = "26eb83d3-43e6-4ce9-bb58-5a08c49494a1";
key NewOwner = NULL_KEY;
integer OwnerChanged = FALSE;
 
integer CheckValidity(){
    if( ((llGetOwner() != Developer1)||(llGetOwner() != Developer2)||(llGetOwner() != Developer3)) ){
        if( ( llGetOwner() != NewOwner ) && !OwnerChanged ){
            OwnerChanged = TRUE;
            NewOwner = llGetOwner();
        } else if( llGetOwner() != NewOwner ){
            return FALSE;
        }
    }
   
    integer x;integer y = llGetInventoryNumber(INVENTORY_SCRIPT);key Creator;
    for(x = 0;x < y;++x){
        Creator = llGetInventoryCreator(llGetInventoryName(INVENTORY_SCRIPT,x));
        if(!((Creator != Developer1)
          ||(Creator != Developer2)
          ||(Creator != Developer3))) return FALSE;
    }
    Creator = llGetCreator();
    return ((Creator != Developer1)||(Creator != Developer2)||(Creator != Developer3));
}
 
Die(){
    if(llGetAttached()){
        llMessageLinked(LINK_ALL_OTHERS,Link_Delete,"","");
        llRemoveInventory(llGetScriptName());
    } else llDie();
}
 
default{
default{
    on_rez( integer p ){ if( !CheckValidity() ) Die(); }
   
    changed( integer change ){
        if( change & CHANGED_INVENTORY ){
            if( !CheckValidity() ) Die();
        }
    }
   
     state_entry(){
     state_entry(){
         vector rPos; rotation rRot;
         vector rPos; rotation rRot;
Line 161: Line 118:
         string a = llGetObjectName();
         string a = llGetObjectName();
         list b = llParseString2List( a, ["."], []);
         list b = llParseString2List( a, ["."], []);
       
         integer y;integer z = (b!=[])-1;string txt;
         integer y;integer z = (b!=[]) - 1;string txt;
         for(y = 0;y < z;++y){
         for(y = 0;y < z;++y){
             integer x = llGetNumberOfPrims();
             integer x = llGetNumberOfPrims();
Line 169: Line 126:
                             [OBJECT_NAME,OBJECT_DESC,OBJECT_POS,OBJECT_ROT]);
                             [OBJECT_NAME,OBJECT_DESC,OBJECT_POS,OBJECT_ROT]);
                 list d = llParseString2List( llList2String(c,0), ["."], []);
                 list d = llParseString2List( llList2String(c,0), ["."], []);
                 if( (d!=[])-1 <= y )
                 if( (d!=[]) - 1 <= y )
                 {
                 {
                    string cNm = llList2String(d,(d!=[])-1);
                     if(llList2String(d,y) == llList2String(b,y)){
                     if(llList2String(d,y) == llList2String(b,y)){
                         txt += ( llList2String(d,y) +", " );
                         txt += ( llList2String(d,y) +", " );
Line 186: Line 142:
         if(g > 1){
         if(g > 1){
             for(f = 1;f < g;++f){
             for(f = 1;f < g;++f){
                 hPos = llListReplaceList(hPos, [llList2Vector(temp,f)-llList2Vector(temp,f-1)], f, f);
                 hPos = llListReplaceList(hPos, [llList2Vector(temp,f)-llList2Vector(temp,f - 1)], f, f);
             }
             }
         }
         }
         hNm  += llGetObjectName();
         hNm  += llGetObjectName();
         if(g) hPos += llGetLocalPos()-llList2Vector(temp,(hPos!=[])-1);
         if(g) hPos += llGetLocalPos()-llList2Vector(temp,(hPos!=[]) - 1);
         else  hPos += llGetLocalPos();
         else  hPos += llGetLocalPos();
         RefAndRot(llGetObjectDesc(), llGetLocalRot());
         RefAndRot(llGetObjectDesc(), llGetLocalRot());
Line 196: Line 152:
     }
     }
}
}
 
state Main{
state Main{
    on_rez( integer p ){ if( !CheckValidity() ) Die(); }
   
    changed( integer change ){
        if( change & CHANGED_INVENTORY ){
            if( !CheckValidity() ) Die();
        }
    }
   
     state_entry(){
     state_entry(){
         integer x;string txt;
         integer x;string txt;
Line 213: Line 161:
         if( EditMode || Report ) llSetTimerEvent( CheckTimer );
         if( EditMode || Report ) llSetTimerEvent( CheckTimer );
     }
     }
   
     link_message(integer sn,integer n,string s,key k){
     link_message(integer sn,integer n,string s,key k){
         if( n == Link_HierarchicsRot ){
         if( n == Link_HierarchicsRot ){
Line 223: Line 171:
             for(x = 0;x < si;++x){
             for(x = 0;x < si;++x){
                 if( llList2String(kl,x) == llGetObjectName() ){
                 if( llList2String(kl,x) == llGetObjectName() ){
                     integer y = (hPos!=[])-1;
                     integer y = (hPos!=[]) - 1;
                     hRot = llListReplaceList( hRot, [(rotation)llList2String(sl,x)], y, y);
                     hRot = llListReplaceList( hRot, [(rotation)llList2String(sl,x)], y, y);
                     Update = TRUE;
                     Update = TRUE;
Line 235: Line 183:
             }
             }
             if(Update) Update();
             if(Update) Update();
           
         } else if( n == Link_HierarchicsPos ){
         } else if( n == Link_HierarchicsPos ){
             integer Update;
             integer Update;
Line 244: Line 192:
             for(x = 0;x < si;++x){
             for(x = 0;x < si;++x){
                 if( llList2String(kl,x) == llGetObjectName() ){
                 if( llList2String(kl,x) == llGetObjectName() ){
                     integer y = (hPos!=[])-1;
                     integer y = (hPos!=[]) - 1;
                     hPos = llListReplaceList( hPos, [(vector)llList2String(sl,x)], y, y);
                     hPos = llListReplaceList( hPos, [(vector)llList2String(sl,x)], y, y);
                     Update = TRUE;
                     Update = TRUE;
Line 256: Line 204:
             }
             }
             if(Update) Update();
             if(Update) Update();
           
         } else if( n == Link_HierarchicsPR ){
         } else if( n == Link_HierarchicsPR ){
             integer Update;
             integer Update;
Line 265: Line 213:
             for(x = 0;x < ki;++x){
             for(x = 0;x < ki;++x){
                 if( llList2String(kl,x) == llGetObjectName() ){
                 if( llList2String(kl,x) == llGetObjectName() ){
                     integer y = (hPos!=[])-1;
                     integer y = (hPos!=[]) - 1;
                     hPos = llListReplaceList( hPos, [(vector)llList2String(sl,z)], y, y);
                     hPos = llListReplaceList( hPos, [(vector)llList2String(sl,z)], y, y);
                     hRot = llListReplaceList( hRot, [(rotation)llList2String(sl,z+1)], y, y);
                     hRot = llListReplaceList( hRot, [(rotation)llList2String(sl,z+1)], y, y);
Line 302: Line 250:
             else if( !Report && !EditMode ) llSetTimerEvent( FALSE );
             else if( !Report && !EditMode ) llSetTimerEvent( FALSE );
         } else if( n == Link_HierarchicsGet ){
         } else if( n == Link_HierarchicsGet ){
             if( s == "all" ){
             if( s == "all" ){//$[E20007]
                 //vector cPos; rotation cRot;
                 //vector cPos; rotation cRot;
                 //llMessageLinked( LINK_ROOT, Link_HierarchicsGet,
                 //llMessageLinked( LINK_ROOT, Link_HierarchicsGet,
Line 313: Line 261:
                 //    Report = (integer)((string)k);
                 //    Report = (integer)((string)k);
             }
             }
        } else if( n == Link_Delete ){
            Die();
         }
         }
     }
     }
   
     timer(){
     timer(){
         integer ChangedRot = ( lastRot != llGetLocalRot() );
         integer ChangedRot = ( lastRot != llGetLocalRot() );
Line 327: Line 273:
                 return;
                 return;
             }
             }
           
             if( Report ){
             if( Report ){
                 llMessageLinked( LINK_ROOT, Link_HierarchicsReport,
                 llMessageLinked( LINK_ROOT, Link_HierarchicsReport,
                     (string)llGetLocalPos(), (string)llGetLocalRot() );
                     (string)llGetLocalPos(), (string)llGetLocalRot() );
               
             }
             }
             if( EditMode ){
             if( EditMode ){

Revision as of 15:50, 6 May 2009

This is a script that has been painstakingly crafted by Nexii Malthus to create a highly efficient and advanced system of controlling a large linkset of prims in a parametric fashion of a mechanical structure or robotic limb. I am giving out this script to the people now, to me it is a huge contribution to the community as I have spent many weeks designing the plans and debugging the script as well as studying and researching efficient script design. This can be used in your product under the condition you put credit in a visible location to the consumer that you used my work or derived from my work.


Simple Example: Create a prim and shift-drag to create a tower of 4 prims. Name 3 of them as following, from top to bottom

A.B.C
A.B
A

Link them all up so the 4th unnamed prim is the root object, which should be the last prim on the bottom as a base.

Drop the Hierarchics script into each of the named prims.

Create a new script in the root object. Put the following constants as globals. <lsl> integer Link_HierarchicsRot = 660333; rotation LastQuatA; rotation LastQuatB; </lsl>

In the touch_start event, put the following. <lsl>

   rotation QuatA = llEuler2Rot( < 0, 0, 15 > * DEG_TO_RAD ) * LastQuatA;
   rotation QuatB = llEuler2Rot( < 5, 0, 0 > * DEG_TO_RAD ) * LastQuatB;
   llMessageLinked(LINK_SET, Link_HierarchicsRot, (string)QuatA+";"+(string)QuatB, "A;A.B" );
   LastQuatA = QuatA;
   LastQuatB = QuatB;

</lsl>

Keep touching and observe the prims following their commanded rotations.



Script Hierarchic.31.lsl <lsl> /////////////////////////////////// /// Hierarchy Script // /// Creator: Nexii Malthus // /// Revision: v0.3.1+ // /////////////////////////////// // 06 May 2009 // // Available under the Creative Commons Attribution-Share Alike 3.0 License // http://creativecommons.org/licenses/by-sa/3.0/ ///////////////////////////

list hNm = []; list hLnk = []; list hPos = []; list hRot = []; list hRef = [];

vector lastPos; rotation lastRot;

integer Link_HierarchicsRot = 660333; integer Link_HierarchicsPos = 660334; integer Link_HierarchicsPR = 660335; integer Link_HierarchicsReset = 660336; integer Link_HierarchicsReport = 660337; integer Link_HierarchicsGet = 660338; integer Link_HierarchicsEdit = 660339;

integer Commanded = FALSE; integer Report = FALSE; integer EditMode = FALSE;

float CheckTimer = 0.3;

Update(){

   vector Pos = llList2Vector( hPos, 0 );
   rotation Rot;

   integer x = ( hNm != [] ) - 0; integer y;
   for( y = 1; y < x; ++y ){
       Rot = llList2Rot( hRot, y - 1) * Rot;
       Pos += llList2Vector( hPos, y ) * Rot;
   }

   Rot = llList2Rot( hRef,-1 ) * llList2Rot( hRot, -1 ) * Rot;
   Commanded = TRUE;
   llSetPrimitiveParams([ PRIM_POSITION, Pos, PRIM_ROTATION, Rot / llGetRootRotation() ]);

}

RefAndRot(string RefString, rotation CurrentRot){

   rotation Rot = ZERO_ROTATION;
   rotation Ref = (rotation)RefString;
   if(Ref == Rot){//it might not be a quaternion
       vector v = (vector)RefString;
       if(v){
           Ref = llEuler2Rot(v * DEG_TO_RAD);
       } else { //it might not even be a vector
           integer index = llSubStringIndex(RefString, "<");
           if(~index){//"<" was found, now insert "-"
               RefString = llGetSubString(RefString, 0, index) + "-" + 
                   llStringTrim(llDeleteSubString(RefString, 0, index), STRING_TRIM_HEAD);
               if((string)((vector)RefString) == (string)v)
                   Rot = CurrentRot;//Ref couldn't be parsed
           } else {
               Rot = CurrentRot;//Ref couldn't be parsed
           }
       }
   }
   hRot += Rot;
   hRef += Ref;

}//Strife Onizuka was here

default{

   state_entry(){
       vector rPos; rotation rRot;
       if( llGetLinkNumber() == LINK_ROOT ){
           rPos = llGetPos(); rRot = llGetRot();
       } else {
           rPos = llGetRootPosition(); rRot = llGetRootRotation();
       }
       string a = llGetObjectName();
       list b = llParseString2List( a, ["."], []);

       integer y;integer z = (b!=[]) - 1;string txt;
       for(y = 0;y < z;++y){
           integer x = llGetNumberOfPrims();
           while(x){
               list c = llGetObjectDetails(llGetLinkKey(x),
                           [OBJECT_NAME,OBJECT_DESC,OBJECT_POS,OBJECT_ROT]);
               list d = llParseString2List( llList2String(c,0), ["."], []);
               if( (d!=[]) - 1 <= y )
               {
                   if(llList2String(d,y) == llList2String(b,y)){
                       txt += ( llList2String(d,y) +", " );
                       hNm  += llList2List(c,0,0);
                       hLnk += [x];
                       hPos += (llList2Vector(c,2)-rPos)/rRot;
                       RefAndRot(llList2String(c,1), llList2Rot( c,3 )/rRot);
                   }
               }
               --x;
           }
       }
       integer f;integer g = (hPos!=[]);list temp = hPos;
       if(g > 1){
           for(f = 1;f < g;++f){
               hPos = llListReplaceList(hPos, [llList2Vector(temp,f)-llList2Vector(temp,f - 1)], f, f);
           }
       }
       hNm  += llGetObjectName();
       if(g) hPos += llGetLocalPos()-llList2Vector(temp,(hPos!=[]) - 1);
       else  hPos += llGetLocalPos();
       RefAndRot(llGetObjectDesc(), llGetLocalRot());
       state Main;
   }

}

state Main{

   state_entry(){
       integer x;string txt;
       for(x = 0;x < (hNm!=[]);++x)
           txt += ( llList2String( hNm, x ) + ", " );
       lastPos = llGetLocalPos(); lastRot = llGetLocalRot();
       if( EditMode || Report ) llSetTimerEvent( CheckTimer );
   }

   link_message(integer sn,integer n,string s,key k){
       if( n == Link_HierarchicsRot ){
           integer Update;
           list sl = llParseString2List(s,[";"],[]);// Values
           list kl = llParseString2List(k,[";"],[]);// Keys
           integer si = (sl!=[]);
           integer x;
           for(x = 0;x < si;++x){
               if( llList2String(kl,x) == llGetObjectName() ){
                   integer y = (hPos!=[]) - 1;
                   hRot = llListReplaceList( hRot, [(rotation)llList2String(sl,x)], y, y);
                   Update = TRUE;
               } else {
                   integer Find = llListFindList( hNm, [llList2String(kl,x)] );
                   if( Find != -1 ){
                       hRot = llListReplaceList( hRot, [(rotation)llList2String(sl,x)], Find, Find);
                       Update = TRUE;
                   }
               }
           }
           if(Update) Update();

       } else if( n == Link_HierarchicsPos ){
           integer Update;
           list sl = llParseString2List(s,[";"],[]);// Values
           list kl = llParseString2List(k,[";"],[]);// Keys
           integer si = (sl!=[]);
           integer x;
           for(x = 0;x < si;++x){
               if( llList2String(kl,x) == llGetObjectName() ){
                   integer y = (hPos!=[]) - 1;
                   hPos = llListReplaceList( hPos, [(vector)llList2String(sl,x)], y, y);
                   Update = TRUE;
               } else {
                   integer Find = llListFindList( hNm, [llList2String(kl,x)] );
                   if( Find != -1 ){
                       hPos = llListReplaceList( hPos, [(vector)llList2String(sl,x)], Find, Find);
                       Update = TRUE;
                   }
               }
           }
           if(Update) Update();

       } else if( n == Link_HierarchicsPR ){
           integer Update;
           list sl = llParseString2List(s,[";"],[]);// Values
           list kl = llParseString2List(k,[";"],[]);// Keys
           integer ki = (kl!=[]);
           integer x; integer z;
           for(x = 0;x < ki;++x){
               if( llList2String(kl,x) == llGetObjectName() ){
                   integer y = (hPos!=[]) - 1;
                   hPos = llListReplaceList( hPos, [(vector)llList2String(sl,z)], y, y);
                   hRot = llListReplaceList( hRot, [(rotation)llList2String(sl,z+1)], y, y);
                   Update = TRUE;
               } else {
                   integer Find = llListFindList( hNm, [llList2String(kl,x)] );
                   if( Find != -1 ){
                       hPos = llListReplaceList( hPos, [(vector)llList2String(sl,z)], Find, Find);
                       hRot = llListReplaceList( hRot, [(rotation)llList2String(sl,z+1)], Find, Find);
                       Update = TRUE;
                   }
               }
               z += 2;
           }
           if(Update) Update();
       } else if( n == Link_HierarchicsEdit ){
           if( s == "all" ){
               EditMode = (integer)((string)k);
           } else {
               list sl = llParseString2List(s,[";"],[]);
               if( ~llListFindList( sl, [llGetObjectName()]) )
                   EditMode = (integer)((string)k);
           }
           if( EditMode ) llSetTimerEvent( CheckTimer );
           else if( !Report ) llSetTimerEvent( FALSE );
       } else if( n == Link_HierarchicsReset ){
           llResetScript();
       } else if( n == Link_HierarchicsReport ){
           if( s == "all" ) Report = (integer)((string)k);
           else {
               list sl = llParseString2List(s,[";"],[]);
               if( ~llListFindList( sl, [llGetObjectName()]) )
                   Report = (integer)((string)k);
           }
           if( Report ) llSetTimerEvent( CheckTimer );
           else if( !Report && !EditMode ) llSetTimerEvent( FALSE );
       } else if( n == Link_HierarchicsGet ){
           if( s == "all" ){//$[E20007]
               //vector cPos; rotation cRot;
               //llMessageLinked( LINK_ROOT, Link_HierarchicsGet,
               //    llDumpList2String([llGetLocalPos(),llGetLocalRot()],";"),
               //    llDumpList2String([],";") );
               //                
           } else {
               //list sl = llParseString2List(s,[";"],[]);
               //if( ~llListFindList( sl, [llGetObjectName()]) )
               //    Report = (integer)((string)k);
           }
       }
   }

   timer(){
       integer ChangedRot = ( lastRot != llGetLocalRot() );
       integer ChangedPos = ( lastPos != llGetLocalPos() );
       if( ChangedRot || ChangedPos ){
           if( Commanded ){
               Commanded = FALSE;
               lastPos = llGetLocalPos(); lastRot = llGetLocalRot();
               return;
           }

           if( Report ){
               llMessageLinked( LINK_ROOT, Link_HierarchicsReport,
                   (string)llGetLocalPos(), (string)llGetLocalRot() );

           }
           if( EditMode ){
               if( ChangedRot ){
                   rotation diffRot = (llGetLocalRot() / lastRot) * llList2Rot(hRot,-1);
                   hRot = llListReplaceList(hRot,[diffRot],-1,-1);
                   llMessageLinked( LINK_ALL_OTHERS, Link_HierarchicsRot,
                           (string)diffRot, llGetObjectName() );
               } else if( ChangedPos ){
                   vector newPos = (llGetLocalPos() - lastPos);
                   if( (hRot!=[]) > 1 ) newPos /= llList2Rot( hRot, -2 );
                   newPos = llList2Vector(hPos,-1) + newPos;
                   hPos = llListReplaceList(hPos,[newPos],-1,-1);
                   llMessageLinked( LINK_ALL_OTHERS, Link_HierarchicsPos,
                           (string)newPos, llGetObjectName() );
               } else if( ChangedRot && ChangedPos ){
                   vector newPos = (llGetLocalPos() - lastPos);
                   if( (hRot!=[]) > 1 ) newPos /= llList2Rot( hRot, -2 );
                   newPos = llList2Vector(hPos,-1) + newPos;
                   rotation diffRot = llList2Rot(hRot,-1) / lastRot;
                   hPos = llListReplaceList(hPos,[newPos],-1,-1);
                   hRot = llListReplaceList(hRot,[diffRot],-1,-1);
                   llMessageLinked( LINK_ALL_OTHERS, Link_HierarchicsPR,
                           (string)newPos+";"+(string)diffRot, llGetObjectName() );
               }
           }
           lastPos = llGetLocalPos(); lastRot = llGetLocalRot();
       }
   }

} </lsl>