Body parts in Second Life that are made from sculpted primitives frequently consist of complementary sculpt maps. That is, a left-foot sculpt object is equivalent to a right-foot sculpte object where all sculptures have the Mirror
option toggled.
The code below is a script that creates the complementary object. So for example, using this script you can create the left foot from the right foot, depending on how the sculpt maps were intended to be used.
Object Mirror
script below in the object.Confirm
to mirror and break all the links. Object Cloner
script in the left foot from step () along with the objects from step ().////////////////////////////////////////////////////////// // (C) Wizardry and Steamworks - 2011, License: GPLv3 // // // // -* OBJECT MIRROR *- // // // ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// // About: Mirrors all the sculpts in a link-set. // ////////////////////////////////////////////////////////// // Usage: Make sure you CREATE a backup first since it // // will be needed later on by the OBJECT CLONER. Then // // drop this script in an object you would like to // // mirror. After that, touch the script and wait till // // all the sculpts are mirrored. When the process ends // // the object will un-link and the script will die. // ////////////////////////////////////////////////////////// default { touch_start(integer num) { integer comChannel = ((integer)("0x"+llGetSubString((string)llDetectedKey(0),-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF; llListen(comChannel, "", llDetectedKey(0), ""); llDialog(llDetectedKey(0), "MIRROR: The following script will mirror all the sculpt maps in an object after which it will un-link the object and the script will die.Please confirm that you wish to proceed with the operations.", [ "[ Confirm ]", "[ Reject ]" ], comChannel); } listen(integer channel, string name, key id, string message) { if(message == "[ Confirm ]") { state rename; } } } state rename { state_entry() { integer itra=llGetNumberOfPrims(); do { llSetLinkPrimitiveParamsFast(itra, [PRIM_NAME, (string)itra]); } while(--itra>0); state mirror; } } state mirror { state_entry() { integer itra=llGetNumberOfPrims(); do { list lType = llGetLinkPrimitiveParams(itra, [PRIM_TYPE]); if(llList2Integer(lType, 0) == PRIM_TYPE_SCULPT) { llSetLinkPrimitiveParamsFast(itra, [PRIM_TYPE, llList2Integer(lType, 0), llList2Key(lType, 1), llList2Integer(lType, 2) | PRIM_SCULPT_FLAG_MIRROR]); } } while(--itra>0); state modify; } } state modify { state_entry() { llOwnerSay("MIRROR: Job done... Please make any changes to the primitives and then touch me again to unlink the object."); } touch_start(integer num) { llRequestPermissions(llGetOwner(), PERMISSION_CHANGE_LINKS); } run_time_permissions(integer perm) { if(perm & PERMISSION_CHANGE_LINKS) { state unlink; } } } state unlink { state_entry() { integer itra=llGetNumberOfPrims(); do { llBreakLink(itra); } while(--itra>0); llOwnerSay("MIRROR: Please pick-up your objects one by one and refer to the cloner script, kthxbye!"); llRemoveInventory(llGetScriptName()); } }
////////////////////////////////////////////////////////// // (C) Wizardry and Steamworks - 2011, License: GPLv3 // // // // -* OBJECT CLONER *- // // // ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// // About: Mirrors all the sculpts in a link-set. // ////////////////////////////////////////////////////////// // Usage: Once you have picked up all the objects from // // the object crushed by OBJECT MIRROR, rez the linked // // object again and gently drop all the little pieces // // inside the new object. After that, add this script // // and touch it once to use the wizard. // ////////////////////////////////////////////////////////// default { state_entry() { state rename; } } state rename { state_entry() { integer itra=llGetNumberOfPrims(); do { llSetLinkPrimitiveParamsFast(itra, [PRIM_NAME, (string)itra]); } while(--itra>0); state axes; } } state axes { touch_start(integer num) { integer comChannel = ((integer)("0x"+llGetSubString((string)llDetectedKey(0),-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF; llListen(comChannel, "", llDetectedKey(0), ""); llDialog(llDetectedKey(0), "CLONER: Suppose that the object O represent the object, please select the most sensible axis to on which the object will be cloned. You can see the axes by right clicking the object and selecting edit.", [ "[ X ]", "[ Y ]", "[ Z ]" ], comChannel); } listen(integer channel, string name, key id, string message) { if(message == "[ X ]") { state x; } if(message == "[ Y ]") { state y; } if(message == "[ Z ]") { state z; } } } state x { state_entry() { integer itra=llGetNumberOfPrims(); do { list scratch = llParseString2List(llList2String(llGetLinkPrimitiveParams(itra, [PRIM_POSITION]), 0), ["<", ",", ">"], []); vector vPos = ZERO_VECTOR; vPos.x = llList2Float(scratch, 0); vPos.y = llList2Float(scratch, 1); vPos.z = llList2Float(scratch, 2); scratch = llParseString2List(llList2String(llGetLinkPrimitiveParams(itra, [PRIM_ROTATION]), 0), ["<", ",", ">"], []); rotation vRot = ZERO_ROTATION; vRot.x = llList2Float(scratch, 0); vRot.y = llList2Float(scratch, 1); vRot.z = llList2Float(scratch, 2); vRot.s = llList2Float(scratch, 3); vector rPos = llGetRootPosition(); rPos.x += 1; float reflectX = rPos.x; float diffRefl = vPos.x - reflectX; llRezObject(llList2String(llGetLinkPrimitiveParams(itra, [PRIM_NAME]), 0), <reflectX - diffRefl, vPos.y, vPos.z>, ZERO_VECTOR, vRot, 0); } while(--itra>0); state complete; } } state y { state_entry() { integer itra=llGetNumberOfPrims(); do { list scratch = llParseString2List(llList2String(llGetLinkPrimitiveParams(itra, [PRIM_POSITION]), 0), ["<", ",", ">"], []); vector vPos = ZERO_VECTOR; vPos.x = llList2Float(scratch, 0); vPos.y = llList2Float(scratch, 1); vPos.z = llList2Float(scratch, 2); scratch = llParseString2List(llList2String(llGetLinkPrimitiveParams(itra, [PRIM_ROTATION]), 0), ["<", ",", ">"], []); rotation vRot = ZERO_ROTATION; vRot.x = llList2Float(scratch, 0); vRot.y = llList2Float(scratch, 1); vRot.z = llList2Float(scratch, 2); vRot.s = llList2Float(scratch, 3); vector rPos = llGetRootPosition(); rPos.y += 1; float reflectY = rPos.y; float diffRefl = vPos.y - reflectY; llRezObject(llList2String(llGetLinkPrimitiveParams(itra, [PRIM_NAME]), 0), <vPos.x, reflectY - diffRefl, vPos.z>, ZERO_VECTOR, vRot, 0); } while(--itra>0); state complete; } } state z { state_entry() { integer itra=llGetNumberOfPrims(); do { list scratch = llParseString2List(llList2String(llGetLinkPrimitiveParams(itra, [PRIM_POSITION]), 0), ["<", ",", ">"], []); vector vPos = ZERO_VECTOR; vPos.x = llList2Float(scratch, 0); vPos.y = llList2Float(scratch, 1); vPos.z = llList2Float(scratch, 2); scratch = llParseString2List(llList2String(llGetLinkPrimitiveParams(itra, [PRIM_ROTATION]), 0), ["<", ",", ">"], []); rotation vRot = ZERO_ROTATION; vRot.x = llList2Float(scratch, 0); vRot.y = llList2Float(scratch, 1); vRot.z = llList2Float(scratch, 2); vRot.s = llList2Float(scratch, 3); vector rPos = llGetRootPosition(); rPos.z += 1; float reflectZ = rPos.z; float diffRefl = vPos.z - reflectZ; llRezObject(llList2String(llGetLinkPrimitiveParams(itra, [PRIM_NAME]), 0), <vPos.x, vPos.y, reflectZ - diffRefl>, ZERO_VECTOR, vRot, 0); } while(--itra>0); state complete; } } state complete { state_entry() { llRemoveInventory(llGetScriptName()); llOwnerSay("MIRROR: Job done. Kthxbye!"); } }