Difference between revisions of "Linkset Resizer 2"

From Second Life Wiki
Jump to navigation Jump to search
Line 19: Line 19:


'''IMPORTANT:'''  You should always make a backup copy of the object before using this script.
'''IMPORTANT:'''  You should always make a backup copy of the object before using this script.
The script below is configured to be used as a drop-in script for a user or builder that wants to resize something for themselves.  If putting into a product, you may
want to set START_ON_TOUCH to be TRUE so that your customers can just touch the object to start resizing.  You may also want to set SAY_STATUS to FALSE
so that a bunch of text doesn't get sent to the chat window (only seen by the owner, but can still be annoying to the end-user).


</div></div>
</div></div>
Line 31: Line 35:
// by Emma Nowhere
// by Emma Nowhere
//
//
// Last modified: 5/30/2010
// Last modified: 6/1/2010
//
//
// How to use with menu:
// How to use with menu:
Line 42: Line 46:
// where x is the percentage of the original size you want to resize to.
// where x is the percentage of the original size you want to resize to.
//
//
// If using in a product with no other scripts, change START_ON_TOUCH below to TRUE
// so user can initiate resizing by just touching the object.
 
integer START_ON_TOUCH = FALSE;
 
// Display status messages in chat window (to owner only)
 
integer SAY_STATUS = TRUE;
 
// Channel to listen for commands on
 
integer CHAT_CHANNEL = 1;
 
// SL constraints
 
float MIN_SIZE = .01;
float MIN_SIZE = .01;
float MAX_SIZE = 10;
float MAX_SIZE = 10;
float MAX_DISTANCE = 10;  
float MAX_DISTANCE = 10;  
float MIN_SCALE = .1;
float MIN_SCALE = .1;
 
integer CHANNEL = 1;
integer MENU_CHANNEL = -1001;
integer MENU_CHANNEL = -1001;
   
   
Line 55: Line 72:


float scale = 1.0;
float scale = 1.0;
init_menu_channel() {
    MENU_CHANNEL = ((integer)("0x" + llGetSubString((string)llGetKey(), -8, -1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF;
}
say_status(string msg) {
    if (SAY_STATUS) llOwnerSay(msg);
}


backup() {
backup() {
     if (!backupStored) {
     if (!backupStored) {
         llOwnerSay("Backing up prim positions and sizes.");
         say_status("Backing up prim positions and sizes.");
         backupPrims = [];
         backupPrims = [];
         integer p = llGetNumberOfPrims();
         integer p = llGetNumberOfPrims();
Line 78: Line 103:
         }
         }
         backupStored = TRUE;
         backupStored = TRUE;
         llOwnerSay("Prim positions and sizes backed up.");
         say_status("Prim positions and sizes backed up.");
     }
     }
}
}
Line 84: Line 109:
restore() {
restore() {
     if (backupStored) {
     if (backupStored) {
         llOwnerSay("Restoring previously backed up positions and sizes.");
         say_status("Restoring previously backed up positions and sizes.");
         integer p = llGetNumberOfPrims();
         integer p = llGetNumberOfPrims();
         integer i = 0;
         integer i = 0;
Line 98: Line 123:
             }
             }
         }
         }
         llOwnerSay("Previously backed up prim positions and sizes restored.");
         say_status("Previously backed up prim positions and sizes restored.");
     }
     }
     scale = 1;
     scale = 1;
Line 104: Line 129:
   
   
finish() {
finish() {
     llOwnerSay("Deleting Resizer script.");
     say_status("Deleting Resizer script.");
     llRemoveInventory(llGetScriptName());  
     llRemoveInventory(llGetScriptName());  
}
}
Line 135: Line 160:
     backup();
     backup();
   
   
     llOwnerSay("Resizing prims to " + (string)llRound(scale * 100) + "% of original size.");
     say_status("Resizing prims to " + (string)llRound(scale * 100) + "% of original size.");
     integer p = llGetNumberOfPrims();
     integer p = llGetNumberOfPrims();
     integer i = 0;
     integer i = 0;
Line 158: Line 183:
         }
         }
     }
     }
     llOwnerSay("Prims resized.");
     say_status("Prims resized.");
}
}


Line 164: Line 189:
     llDialog(llGetOwner(),
     llDialog(llGetOwner(),
     "Resizer\n\nMake a backup of your object first.\n\nPlease choose an option:\n",
     "Resizer\n\nMake a backup of your object first.\n\nPlease choose an option:\n",
     ["Restore", "-", "Finish", "-1%", "-5%", "-10%", "+1%", "+5%", "+10%"], MENU_CHANNEL);
     ["Revert", "-", "Finish", "-1%", "-5%", "-10%", "+1%", "+5%", "+10%"], MENU_CHANNEL);
}
}
 
default
handle_message(integer channel, string name, key id, string message)
{
{
     state_entry()
     if (channel == CHAT_CHANNEL) {
    {
        llListen(CHANNEL, "", llGetOwner(), "");
        llListen(MENU_CHANNEL, "", llGetOwner(), "");
        llOwnerSay("Resizer Ready");
        llOwnerSay("Type /" + (string)CHANNEL + "resizer for menu.");
    }
    on_rez(integer start_param) {
        llOwnerSay("Resizer Installed");
        llOwnerSay("Type /" + (string)CHANNEL + "resizer for menu.");
    }   
    listen(integer channel, string name, key id, string message)  
    {
         if (message == "resizer") {
         if (message == "resizer") {
             menu();
             menu();
        }
        else if (message == "Restore") {
            restore();
            menu();
        }
        else if (message == "Finish") {       
            finish();                   
         }
         }
         else if (llSubStringIndex(message, "resizer") == 0) {   
         else if (llSubStringIndex(message, "resizer") == 0) {   
Line 204: Line 208:
                 }
                 }
             }
             }
        }
    }
    else if (channel == MENU_CHANNEL) {
        if (message == "Revert") {
            restore();
            menu();
        }
        else if (message == "Finish") {       
            finish();                   
         }
         }
         else if (llGetSubString(message, -1, -1) == "%") {
         else if (llGetSubString(message, -1, -1) == "%") {
Line 211: Line 224:
             menu();
             menu();
         }
         }
    }
}
default
{
    state_entry()
    {
        if (START_ON_TOUCH) {
            // we only want a touch_start handler if we're going to use it
            // so change state rather than just testing inside touch_start
            // for START_ON_TOUCH to be true.
            state start_on_touch;
        }
        else {
            llListen(CHAT_CHANNEL, "", llGetOwner(), "");
           
            init_menu_channel();
            llListen(MENU_CHANNEL, "", llGetOwner(), "");
           
            llOwnerSay("Resizer Ready");
            llOwnerSay("Type /" + (string)CHAT_CHANNEL + "resizer for menu.");
        }
    }
    on_rez(integer start_param) {
        llOwnerSay("Resizer Installed");
        llOwnerSay("Type /" + (string)CHAT_CHANNEL + "resizer for menu.");
    }   
   
   
    listen(integer channel, string name, key id, string message)
    {
        handle_message(channel, name, id, message);
     }
     }
}
}
state start_on_touch
{
    state_entry()
    {
        llListen(CHAT_CHANNEL, "", llGetOwner(), "");
       
        init_menu_channel();
        llListen(MENU_CHANNEL, "", llGetOwner(), "");
       
        llOwnerSay("Resizer Ready");
        llOwnerSay("Touch for resizer menu.");
    }
    on_rez(integer start_param) {
        llOwnerSay("Resizer Installed");
        llOwnerSay("Touch for resizer menu.");
    }   
    listen(integer channel, string name, key id, string message)
    {
        handle_message(channel, name, id, message);
    }
   
    touch_start(integer num_detected)
    {
        menu();
    }
}


</lsl>
</lsl>
</div></div>
</div></div>
{{#vardefine:sort|Fix Small Prims}}{{LSLC|Library}}
{{#vardefine:sort|Fix Small Prims}}{{LSLC|Library}}

Revision as of 09:18, 1 June 2010

About

Resizer by Emma Nowhere

Yet another object resizer script. Seeing as I was the person who originally opened the JIRA for LLGetLinkPrimitiveParams I thought I should put it to good use. I like it more than the other resizer scripts out there, but of course, I'm biased. In any case, it never hurts to have more code being shared.

How to use with menu:

  1. Install this script in the root prim of a linked set of prims (aka "linkset")
  2. Type /1resizer to show the menu
  3. Hit the appropriate buttons to scale up or down the linkset
  4. Hit the "Finish" button to remove the script and finalize prim sizes

Optionally, enter the percentage directly via chat by typing /1resizer x% where x is the percentage of the original size you want to resize to.

IMPORTANT: You should always make a backup copy of the object before using this script.

The script below is configured to be used as a drop-in script for a user or builder that wants to resize something for themselves. If putting into a product, you may want to set START_ON_TOUCH to be TRUE so that your customers can just touch the object to start resizing. You may also want to set SAY_STATUS to FALSE so that a bunch of text doesn't get sent to the chat window (only seen by the owner, but can still be annoying to the end-user).

Resizer

<lsl> /////////////////////////////////////////////////////////////////////////////// // Resizer // by Emma Nowhere // // Last modified: 6/1/2010 // // How to use with menu: // 1. Install this script in the root prim of a linked set of prims (aka "linkset") // 2. Type /1resizer to show the menu // 3. Hit the appropriate buttons to scale up or down the linkset // 4. Hit the "Finish" button to remove the script and finalize prim sizes // // Optionally, enter the percentage directly via chat by typing /1resizer x% // where x is the percentage of the original size you want to resize to. // // If using in a product with no other scripts, change START_ON_TOUCH below to TRUE // so user can initiate resizing by just touching the object.

integer START_ON_TOUCH = FALSE;

// Display status messages in chat window (to owner only)

integer SAY_STATUS = TRUE;

// Channel to listen for commands on

integer CHAT_CHANNEL = 1;

// SL constraints

float MIN_SIZE = .01; float MAX_SIZE = 10; float MAX_DISTANCE = 10; float MIN_SCALE = .1;

integer MENU_CHANNEL = -1001;

list backupPrims = []; integer backupStored = FALSE;

float scale = 1.0;

init_menu_channel() {

   MENU_CHANNEL = ((integer)("0x" + llGetSubString((string)llGetKey(), -8, -1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF;

}

say_status(string msg) {

   if (SAY_STATUS) llOwnerSay(msg);

}

backup() {

   if (!backupStored) {
       say_status("Backing up prim positions and sizes.");
       backupPrims = [];
       integer p = llGetNumberOfPrims();
       integer i = 0;
       vector root_pos = <0, 0, 0>;
       for (i = 1; i <= p; i++)
       {
           list params = llGetLinkPrimitiveParams(i, [PRIM_POSITION, PRIM_SIZE]);
           vector pos = llList2Vector(params, 0);
           vector size = llList2Vector(params, 1);
           if (i == 1)
           {
               root_pos = pos;
           }
           else {
               pos = pos - root_pos;
           }
           backupPrims = backupPrims + pos + size;
       }
       backupStored = TRUE;
       say_status("Prim positions and sizes backed up.");
   }

}

restore() {

   if (backupStored) {
       say_status("Restoring previously backed up positions and sizes.");
       integer p = llGetNumberOfPrims();
       integer i = 0;
       for (i = 1; i <= p; i++)
       {
           vector pos = llList2Vector(backupPrims, (i - 1) * 2);
           vector size = llList2Vector(backupPrims, ((i - 1) * 2) + 1);
           if (i == 1) {
               llSetLinkPrimitiveParamsFast(i, [PRIM_SIZE, size]);
           }
           else {
               llSetLinkPrimitiveParamsFast(i, [PRIM_POSITION, pos, PRIM_SIZE, size]);
           }
       }
       say_status("Previously backed up prim positions and sizes restored.");
   }
   scale = 1;

}

finish() {

   say_status("Deleting Resizer script.");
   llRemoveInventory(llGetScriptName()); 

}

float min(float a, float b) {

   if (a < b) return a;
   return b;

}

float max(float a, float b) {

   if (a > b) return a;
   return b;

}

float constrainMinMax(float value, float min, float max) {

   value = max(value, min);
   value = min(value, max);
   return value;

}

float constrainSize(float size) {

   return constrainMinMax(size, MIN_SIZE, MAX_SIZE);

}

float constrainDistance(float distance) {

   return min(distance, MAX_DISTANCE);

}

process() {

   backup();

   say_status("Resizing prims to " + (string)llRound(scale * 100) + "% of original size.");
   integer p = llGetNumberOfPrims();
   integer i = 0;
   for (i = 1; i <= p; i++)
   {
       vector pos = llList2Vector(backupPrims, (i - 1) * 2);
       vector size = llList2Vector(backupPrims, ((i - 1) * 2) + 1);

       size.x = constrainSize(size.x * scale);
       size.y = constrainSize(size.y * scale);
       size.z = constrainSize(size.z * scale);
       if (i == 1) {
           llSetLinkPrimitiveParamsFast(i, [PRIM_SIZE, size]);
       }
       else {
           pos = pos * scale;
           pos.x = constrainDistance(pos.x);
           pos.y = constrainDistance(pos.y);
           pos.z = constrainDistance(pos.z);
           llSetLinkPrimitiveParamsFast(i, [PRIM_POSITION, pos, PRIM_SIZE, size]);
       }
   }
   say_status("Prims resized.");

}

menu() {

   llDialog(llGetOwner(),
   "Resizer\n\nMake a backup of your object first.\n\nPlease choose an option:\n",
   ["Revert", "-", "Finish", "-1%", "-5%", "-10%", "+1%", "+5%", "+10%"], MENU_CHANNEL);

}

handle_message(integer channel, string name, key id, string message) {

   if (channel == CHAT_CHANNEL) {
       if (message == "resizer") {
           menu();
       }
       else if (llSubStringIndex(message, "resizer") == 0) {  
           list params = llParseString2List(message, [" "], [] );
           if (llGetListLength(params) == 2) {
               string scale_param = llList2String(params, 1);
               if (llGetSubString(scale_param, -1, -1) == "%") {
                   scale = (((float)llGetSubString(scale_param, 0, -2)) / 100);
                   scale = max(scale, MIN_SCALE);
                   process();
               }
           }
       }
   }
   else if (channel == MENU_CHANNEL) {
       if (message == "Revert") {
           restore();
           menu();
       }
       else if (message == "Finish") {        
           finish();                    
       }
       else if (llGetSubString(message, -1, -1) == "%") {
           scale = scale + (((float)llGetSubString(message, 0, -2)) / 100);
           scale = max(scale, MIN_SCALE);
           process();
           menu();
       }
   }

}

default {

   state_entry() 
   {
       if (START_ON_TOUCH) {
           // we only want a touch_start handler if we're going to use it
           // so change state rather than just testing inside touch_start
           // for START_ON_TOUCH to be true.
           state start_on_touch;
       }
       else {
           llListen(CHAT_CHANNEL, "", llGetOwner(), "");
           
           init_menu_channel();
           llListen(MENU_CHANNEL, "", llGetOwner(), "");
           
           llOwnerSay("Resizer Ready");
           llOwnerSay("Type /" + (string)CHAT_CHANNEL + "resizer for menu.");
       }
   }

   on_rez(integer start_param) {
       llOwnerSay("Resizer Installed");
       llOwnerSay("Type /" + (string)CHAT_CHANNEL + "resizer for menu.");
   }    

   listen(integer channel, string name, key id, string message) 
   {
       handle_message(channel, name, id, message);
   }

}

state start_on_touch {

   state_entry() 
   {
       llListen(CHAT_CHANNEL, "", llGetOwner(), "");
       
       init_menu_channel();
       llListen(MENU_CHANNEL, "", llGetOwner(), "");
       
       llOwnerSay("Resizer Ready");
       llOwnerSay("Touch for resizer menu.");
   }

   on_rez(integer start_param) {
       llOwnerSay("Resizer Installed");
       llOwnerSay("Touch for resizer menu.");
   }    

   listen(integer channel, string name, key id, string message) 
   {
       handle_message(channel, name, id, message);
   }
   
   touch_start(integer num_detected)
   {
       menu();
   }

}


</lsl>