User:Clarknova Helvetic/Clone Primitive v2.0

From Second Life Wiki
< User:Clarknova Helvetic
Revision as of 01:41, 6 January 2008 by Clarknova Helvetic (talk | contribs) (Page created with silly not enough sleep text)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Clone Primitive v2.0 is a Total, End-2-End virtual object replication solution for the simulated cyberspace known to its tecnocrati "netziens" as Second Life.

Shoot me.

Drop this script into a prim and it spits out a complete script in owner chat.

Paste that script into a completely blank script, strip out the Timestamps with find/replace, and drop that into any other prim. Viola! You have a copy of the first prim.

Both scripts self-delete from object inventory after doing their thing.

Why would you need this? You don't. Maybe. It does essentially the same thing as shift-copy, which most people learn on their third day.

However, it does one nice thing, which is to print out all your primitive params in a format that's easy to plug into other scripts scripts with llSetPrimitiveParams() or llSetLinkPrimitiveParam() transformation functions.

Tip: comment out the PRIM_SCALE in the output script and drop it in a megaprim after you've built your scale model.

I'm sure people like Cubey or Horizons have scripts like these that spit out parameter codeblocks for use in thier morphing rezzer gizmos.

I'm including the script with its huge comment header. Below that a sample output script.

GPL v3.0 and Yes, I'm a Nazi about it. If you redistribute my code you make it full perms and leave my name in. Period.


    ///////////////////////////////////////////////////////////////////
   //
   //           END - TO - END PRIM CLONER  v 2.0
   //
   //
   //   This script chats out lines of text that can be pasted back 
   //   into a blank script to clone the original prim.
   //
   //    
    ////////////////////////////////////////////////////////////////////
   //
   //                    HOW TO USE
   //
   //
   //   Drag 'n Drop this script into the prim you want to copy.   
   //
   //   It will output a complete script for replicating the object
   //   in Owner-Only chat.  Then it will delete itself.
   //  
   //   Copy and paste the chatted script into a *completly blank*
   //   new script
   //
   //   Then use the  Search/Replace function under the Edit menu 
   //   to replace the "[HH:MM]  :" line prefixes with a blank.
   //
   //   Just hit the 'Replace All' button.
   //
   //   It can take 2 minutes or more to print out, so you may have to 
   //   do this a few times.
   //
   //
   //   The Primitve Paramaters will be chatted out in the oder that 
   //   they're featured on the offical Wiki:
   //
   //   http://wiki.secondlife.com/wiki/LlGetPrimitiveParams   
   //
    ///////////////////////////////////////////////////////////////////
   //
   //                       WHY?
   //
   //   Chances are you're not going to need an end-to-end
   //   script to dupe your prim. Shift-drag copy is a lot easier.
   //
   //   But if you're reading this you probably want some of the code,
   //   so carve out what you need from the output.
   //
   //   The output code is also commented where appropriate. If you want 
   //   To know more about what's going on, read the comments here and 
   //   check out the wiki.  The wiki's good.
   //
   //   Many advanced items on the grid transform from one object to 
   //   another.  Builders have used scrips like this to generate the 
   //   code that goes into those products.
   //
   //   Consider the use of both of llSetPrimitiveParams([]) and 
   //   llSetLinkPrimitiveParams([]).  An entire 30 prim object can be 
   //   metamorphed with a single scipt.
   //
   //
    ///////////////////////////////////////////////////////////////////
   //
   //              Released nder the terms of the 
   //              GNU General Public Liscence v3
   //
   //  This source code is free to use / modify / resell 
   //  with the following restrictions:
   //
   //  If you include any portion of -this- script in a product you 
   //  distribute you must make the script fully mod/copy/trans for 
   //  the next user/owner.  You must also liscence it under the GPL 
   //  and give attribution to the contributors.
   //
   //  This does not extend to the code this script generates.  That
   //  is yours to liscense as you see fit.
   //
   //             No warantee expressed or implied.
   //   
   //  For more info see http://www.gnu.org/copyleft/gpl.html
   //
    ///////////////////////////////////////////////////////////////////
   //
   //      Written by          
   //      Clarknova Helvetic [2008.01.04]
   //      w/ thanks to Bopete Yossarian
   //
   ////////////////////////////////////////////////////////////////////
   
   
   ///  Global Functions & Vars to make life easier
   
   
   // Object-Specific parameters 2 string
   string osp(integer p) {return llDumpList2String(llGetPrimitiveParams([p]),","); }
   
   // Face-Specific parameters 2 string
   string fsp(integer p, integer f) { return llDumpList2String(llGetPrimitiveParams([p,f]),","); }
   
   // Parameter prefixed and formatted for output
   string param(string p , integer q) { return "[ " + p + "," + osp(q); }
   
   // General owner chat w\ Sleep function to stop chat lag from  screwing up the line order
   say(string c) { llSleep(1.); llOwnerSay(c); } 
   
   // Printing out next element to add to the parameter list
   sayn(string c) { say("          " + c + " ] + (params = []) +"); }
   
   // Printing out the last element to add to the parameter list
   saynd(string c) { say("          " + c + " ]  ;"); }
   
   // Print out the code to apply the parameters to the object
   define() {  say("       llSetPrimitiveParams(params);\n         params = [];"); }
   
   // Handle to insert comments
   comment(string c) { say("         // " + c ); }
   
   
   
   /// On with the show...
   
   
   
   default
   {
       state_entry()
       {
   
       
       say("COPY/PASTE THE CODE BELOW INTO A *BLANK* SCRIPT TO CLONE THIS PRIM: \n\n");  // Announce what we're doing
       
       // We're going to change the object's name to a null string to make the output easier to read.
       string object_name = llGetObjectName(); // Store the object's name so we can set it back when done
       llSetObjectName("");
       
       
       //  Print the script header up to state_entry
       say("\ndefault\n{   state_entry()\n     {\n         list params;\n           params =\n");
        
        
   
        
       // Add some comments to the script 
       comment("Be aware that the  \"  + (params = []) +  \" bit is a funny little hack that makes lists ");
       comment("concatenate faster, and has nothing to do with the Paramaters themselves.");
       say("\n"); 
       // [12:56]  Tali Rosca: It uses the C-style thing about an assignment also being an expression with a value.
       // [12:56]  Tali Rosca: Why it actually saves memory still baffles my mind, though.
       
       // list of the the first: paramater constants as strings, then thier integer value.
       list Param_Names = ["PRIM_TYPE",PRIM_TYPE,"PRIM_MATERIAL",PRIM_MATERIAL,"PRIM_PHYSICS",PRIM_PHYSICS,"PRIM_TEMP_ON_REZ",PRIM_TEMP_ON_REZ,"PRIM_PHANTOM",PRIM_PHANTOM,"PRIM_POSITION",PRIM_POSITION,"PRIM_ROTATION",PRIM_ROTATION,"PRIM_SIZE",PRIM_SIZE];
   
   
               // ASIDE:
               // Prim params are of two types: Object-Specific and Face-Specific.
               //
               // I'd Like to group them together according to type, but LsL doesn't
               // nor does wiki.secondlife, and I am sworn to complete my destiny...
               //
               // This is probably for historical reasons (the param order, not my 
               // ultimate destiny).
               
       
       integer i; // You're going to see a lot of use, integer i!
       integer length; // So are you, integer length!
       
       length = (llGetListLength(Param_Names)); // I'm way lazy.  Let's make LsL do basic math for us.
       
       for ( i = 0 ; i < length ; i = i +2) // This is may answer to list strides.  Take that!
       {
           if (i > length -3 ) 
           {
               saynd(param(llList2String(Param_Names,length -2), llList2Integer(Param_Names,length -1))) ; // It don't get any lazier, folks.
               i = length;
           }
           else if (i < length -3 && i != length -6 ) sayn(param( llList2String(Param_Names,i), llList2Integer(Param_Names,i+1)) ) ;
           else if (i < length -3 && i == length -6 )
           {
               say("           // It's probably not a god idea to have your new prim jump to the old one\n           // " + param( llList2String(Param_Names,i), llList2Integer(Param_Names,i+1)) + " ] + (params = []) +"); 
           
           }
       }
       
       Param_Names = []; // Free up some memory
   
       // I reallllly want our script to set all of the paramaters at once, with one llSetPrimitiveParams() 
       // call at the end of the script but we can't because of bugs in LsL.  
       //
       // See  https://jira.secondlife.com/browse/SVC-38  for more info.  Please vote to fix it.
       
       say(""); 
       
       comment("Set all of the above paramaters in a chunk 'o junk");
       define();
       
       say("");
       comment("We are breaking the llSetPtimitiveParam([]) calls into blocks, because some params are incompatible with others");
       comment("during the same call. This is an LsL bug.  See https://jira.secondlife.com/browse/SVC-38 for more info.");
       comment("Please vote to fix it. \n");
               
                                 
        //// Okay, now for the hard stuff: 4 out of 5 of the Face-Specific params, starting with the hardest:
        //// PRIM_TEXTURE.  Why is PRIM_TEXTURE a pain?  Because llSetPrimitiveParams wants it in qoutes, but
        //// llGetPrimitiveParams doesn't give it to us in quotes.  It's a pickle.
        ////
        //// The Face-Specific params each need thier own For loop because the number of faces is variable
        //// from prim to prim.  A simple sphere only has one.  A tube can have up to 9.
        
        
       integer sides = llGetNumberOfSides();  // So here we find out how many faces we've got
           
       comment("This prim has " + (string)sides + " faces.\n"); // Don't care enough to correct for the singular :)
   
   
           ///  PRIM_TEXTURE ///
   
           say( "      params =");
           for (i = 0 ; i < sides ; ++i)  
           {   
               
               list r =llGetPrimitiveParams([PRIM_TEXTURE,i]);
               string s = 
               "\""  + llList2String(r,0) + "\"" // First element is the texture key.
               + ","
               + llList2String(r,1)
               + ","
               + llList2String(r,2)
               + ","
               + llList2String(r,3)
              + " ]";
               
               if (i < sides -1) s = s + " + (params = []) + ";
               if (i == sides -1) s = s + " ;";
               
               
               say("       [ PRIM_TEXTURE," + (string)i + "," + s );    
   
   
               // They say local variables aren't cleared when we leave thier scope.  Can you believe that crap?
               r = []; s = ""; 
       
           }
           
   
           
           define();
           
           comment("Note that you -cannot- define textures and colors in the same call!\n       // If you're cutting out these params for your custom code watch out for this.\n");   
       
           
           ///  PRIM_COLOR ///
           say( "      params =");
           for (i = 0 ; i < sides ; ++i)  
           {   
               if (i < sides -1 ) sayn("[ PRIM_COLOR," + (string)i + "," + fsp(PRIM_COLOR,i));
               if (i == sides -1 ) saynd("       [ PRIM_COLOR," + (string)i + "," + fsp(PRIM_COLOR,i)); 
       
           }
           define();
           
           
           ///  PRIM_BUMP_SHINY ///
           say( "      params =");
           for (i = 0 ; i < sides ; ++i)  
           {   
               if (i < sides -1 ) sayn("[ PRIM_BUMP_SHINY," + (string)i + "," + fsp(PRIM_BUMP_SHINY,i) );
               if (i == sides -1 ) saynd("       [ PRIM_BUMP_SHINY," + (string)i + "," + fsp(PRIM_BUMP_SHINY,i)); 
       
           }
           define();
   
           ///  PRIM_FULLBRIGHT ///
           
           say( "      params =");
           
           for (i = 0 ; i < sides ; ++i)  
           {   
               sayn("[ PRIM_FULLBRIGHT," + (string)i + "," + fsp(PRIM_FULLBRIGHT,i)); 
       
           }
           
           
       ////   Now back to an Object-Specific paramaters : Flexible & Shadows
       ////   Remember that I'm going in this screwy order so that our
       ////   Code matches the table on http://wiki.secondlife.com/wiki/LlSetPrimitiveParams
       
           
       Param_Names = ["PRIM_FLEXIBLE",21,"PRIM_CAST_SHADOWS",24];
           
       length = (llGetListLength(Param_Names)); 
       
       for ( i = 0 ; i < length ; i = i +2) 
       {
           sayn(param( llList2String(Param_Names,i), llList2Integer(Param_Names,i+1)) );
           if (i > length -3 ) i = length;
       }
       
       //// Now for one more Face-Specific paramater
       
           ///  PRIM_TEXGEN ///     Planar mapping?  I don't even know what that is!
   
           for (i = 0 ; i < sides ; ++i)  
           {   
               sayn("[ PRIM_TEXGEN," + (string)i + "," + fsp(PRIM_TEXGEN,i) );
       
           }
           
       /// The last paramater is Object-Specific
       
       
       saynd("[ PRIM_POINT_LIGHT," + osp(PRIM_POINT_LIGHT) );
       
       say("       llSetPrimitiveParams(params);");  //  Print the final function call, braces & some blank lines
           
       say("\n      llSetObjectName(\"" + object_name + "\");\n");  // Make the target's name match this one
       
       comment("This next line deletes the script.  Comment it out if you want the script to persist");
       
       say("\n      llRemoveInventory(llGetScriptName());\n }\n}\n\n\n");  // Remove the cloning script when done 
       
   
       llSetObjectName(object_name); // Change our object's name back.
       
       say("Don't forget to remove the \" [HH:MM]  :\" prefix at the beginning of each line.  Use Find/replace. :)"); // Remind us to remove prefixes.
       
       llRemoveInventory(llGetScriptName());  // Delete this script.
       }
   }


Well That shoor is a lotta code! Most of it whitespace and comments.

Here's an example of the output. This will make a shiny, metallic mobius strip.


   default
   {   state_entry()
        {
            list params;
              params =
   
            // Be aware that the  "  + (params = []) +  " bit is a funny little hack that makes lists 
            // concatenate faster, and has nothing to do with the Paramaters themselves.
   
   
             [ PRIM_TYPE,4,0,<0.000000, 1.000000, 0.000000>,0.000000,<0.500000, -0.500000, 0.000000>,<0.250000, 0.050000, 0.000000>,<0.000000, -0.100000, 0.000000>,<0.000000, 1.000000, 0.000000>,<0.000000, 0.000000, 0.000000>,1.000000,0.000000,0.000000 ] + (params = []) +
             [ PRIM_MATERIAL,2 ] + (params = []) +
             [ PRIM_PHYSICS,0 ] + (params = []) +
             [ PRIM_TEMP_ON_REZ,0 ] + (params = []) +
             [ PRIM_PHANTOM,1 ] + (params = []) +
              // It's probably not a god idea to have your new prim jump to the old one
              // [ PRIM_POSITION,<92.500000, 46.000000, 122.952721> ] + (params = []) +
             [ PRIM_ROTATION,<-0.069309, -0.703702, 0.069309, 0.703702> ] + (params = []) +
             [ PRIM_SIZE,<1.555556, 1.750001, 1.555556> ]  ;
   
            // Set all of the above paramaters in a chunk 'o junk
          llSetPrimitiveParams(params);
            params = [];
   
            // We are breaking the llSetPtimitiveParam([]) calls into blocks, because some params are incompatible with others
            // during the same call. This is an LsL bug.  See https://jira.secondlife.com/browse/SVC-38 for more info.
            // Please vote to fix it. 
   
            // This prim has 3 faces.
   
         params =
          [ PRIM_TEXTURE,0,"5748decc-f629-461c-9a36-a35a221fe21f",<1.000000, 1.000000, 0.000000>,<0.000000, 0.000000, 0.000000>,0.000000 ] + (params = []) + 
          [ PRIM_TEXTURE,1,"5748decc-f629-461c-9a36-a35a221fe21f",<1.000000, 1.000000, 0.000000>,<0.000000, 0.000000, 0.000000>,0.000000 ] + (params = []) + 
          [ PRIM_TEXTURE,2,"5748decc-f629-461c-9a36-a35a221fe21f",<1.000000, 1.000000, 0.000000>,<0.000000, 0.000000, 0.000000>,0.000000 ] ;
          llSetPrimitiveParams(params);
            params = [];
            // Note that you -cannot- define textures and colors in the same call!
          // If you're cutting out these params for your custom code watch out for this.
   
         params =
             [ PRIM_COLOR,0,<0.054902, 0.654902, 0.062745>,1.000000 ] + (params = []) +
             [ PRIM_COLOR,1,<0.054902, 0.654902, 0.062745>,1.000000 ] + (params = []) +
                    [ PRIM_COLOR,2,<0.054902, 0.654902, 0.062745>,1.000000 ]  ;
          llSetPrimitiveParams(params);
            params = [];
         params =
             [ PRIM_BUMP_SHINY,0,3,0 ] + (params = []) +
             [ PRIM_BUMP_SHINY,1,3,0 ] + (params = []) +
                    [ PRIM_BUMP_SHINY,2,3,0 ]  ;
           llSetPrimitiveParams(params);
            params = [];
          params =
   
              [ PRIM_FULLBRIGHT,0,1 ] + (params = []) +
              [ PRIM_FULLBRIGHT,1,1 ] + (params = []) +
              [ PRIM_FULLBRIGHT,2,1 ] + (params = []) +
              [ PRIM_FLEXIBLE,0,2,0.300000,2.000000,0.000000,1.000000,<0.000000, 0.000000, 0.000000> ] + (params = []) +
              [ PRIM_CAST_SHADOWS,0 ] + (params = []) +
              [ PRIM_TEXGEN,0,0 ] + (params = []) +
              [ PRIM_TEXGEN,1,0 ] + (params = []) +
              [ PRIM_TEXGEN,2,0 ] + (params = []) +
              [ PRIM_POINT_LIGHT,1,<1.000000, 1.000000, 1.000000>,0.200000,20.000000,0.000000 ]  ;
           llSetPrimitiveParams(params);
    
         llSetObjectName("Mobius Torus");
   
             // This next line deletes the script.  Comment it out if you want the script to persist
    
         llRemoveInventory(llGetScriptName());
    }
   }

See? Easy to deal with. Comment out what you don't want, restructure, etc. I use this script mainly for finding what the horizontal texture offset on face 666 of my tortured tube dong is. Easy peasy to read, too.

Tip: Bad chat lag will sometimes re-order your code for you. Reduce your draw distance or wait for SL to stop sucking.

P.S. This output code isn't, and probably can't be GPL'd. It's yours free and clear. I may be a Nazi, but I'm not a jerk.