Difference between revisions of "User:Becky Pippen/New LSL Functions"

From Second Life Wiki
Jump to navigation Jump to search
m (typos)
m
Line 7: Line 7:
LSL functions:
LSL functions:


llGetLinkPrimitiveParams()
<lsl> llGetLinkPrimitiveParams()
  llSetLinkPrimitiveParamsNoDelay()
  llSetLinkPrimitiveParamsFast() </lsl>


===History===
===History===
Line 14: Line 14:
Some content creators prefer to distribute their objects no-mod, yet still allow customers to resize or
Some content creators prefer to distribute their objects no-mod, yet still allow customers to resize or
retexture the linkset. Scripts can do that in a no-mod linkset, but the obvious solution using
retexture the linkset. Scripts can do that in a no-mod linkset, but the obvious solution using
llSetLinkPrimitiveParams() doesn't work well because of the 0.2-second delay built into the function.
[[llSetLinkPrimitiveParams]]() doesn't work well because of the 0.2-second delay built into the function.
To work around the delay, we have had to put a script in every child prim that can respond immediately
To work around the delay, we have had to put a script in every child prim that can respond immediately
to a message from the root prim. When these functions become available, we will be able to do this kind of thing with a single script.
to a message from the root prim. When these functions become available, we will be able to do this kind of thing with a single script.
Line 20: Line 20:
===Fixing Existing Scripts===
===Fixing Existing Scripts===


To fix such a script, locate the call to llMessageLinked() in the master script where it sends the link
To fix such a script, locate the call to [[llMessageLinked]]() in the master script where it sends the link
message to the individual prims. It might look something vaguely like this:
message to the individual prims. It might look something vaguely like this:


llMessageLinked(LINK_whatever, command_resize, (string)newSize, NULL_KEY);
<lsl>llMessageLinked(LINK_whatever, command_resize, (string)newSize, NULL_KEY);</lsl>


Replace that with a loop that applies whatever changes you need to each prim using
Replace that with a loop that applies whatever changes you need to each prim using
llSetLinkPrimitiveParamsNoDelay(). The prims have link numbers from 1 through llGetNumberOfPrims(),
[[llSetLinkPrimitiveParamsFast]](). The prims have link numbers from 1 through [[llGetNumberOfPrims]](),
so you can make an efficient loop as shown here; just add any additional processing you
so you can make an efficient loop as shown here; just add any additional processing you
need for each prim inside the loop:
need for each prim inside the loop:


applyChildParams(list ruleSet)
<lsl> applyChildParams(list ruleSet)
  {
  {
     integer linkNum;
     integer linkNum;
     for (linkNum = llGetNumberOfPrims(); linkNum >= 1; --linkNum) {
     for (linkNum = llGetNumberOfPrims(); linkNum >= 1; --linkNum) {
         llSetLinkPrimitiveParamsNoDelay(linkNum, ruleSet);
         llSetLinkPrimitiveParamsFast(linkNum, ruleSet);
     }
     }
  }
  } </lsl>


For example, to use this function to set the color and alpha of all the prims, build the parameter
For example, to use this function to set the color and alpha of all the prims, build the parameter
list and pass it to applyChildParams() like this:
list and pass it to applyChildParams() like this:


applyChildParams([PRIM_COLOR, ALL_SIDES, <0.9, 0.8, 0.2>, 1.0]);
<lsl>applyChildParams([PRIM_COLOR, ALL_SIDES, <0.9, 0.8, 0.2>, 1.0]);</lsl>


However, when you only need to apply a constant rule set like this to every prim in the linkset,
However, when you only need to apply a constant rule set like this to every prim in the linkset,
then the loop above can be simplified to a single statement;
then the loop above can be simplified to a single statement;


llSetLinkPrimitiveParamsNoDelay(LINK_SET, ruleSet);
<lsl>llSetLinkPrimitiveParamsFast(LINK_SET, ruleSet);</lsl>


Or use LINK_ALL_OTHERS or LINK_ALL_CHILDREN instead of LINK_SET as appropriate.
Or use [[LINK_ALL_OTHERS]] or [[LINK_ALL_CHILDREN]] instead of [[LINK_SET]] as appropriate.


For another example, you can make a resizer script apply relative instead of absolute size changes by
For another example, you can make a resizer script apply relative instead of absolute size changes by
using the new function llGetLinkPrimitiveParams(). The script can read each child's current size,
using the new function [[llGetLinkPrimitiveParams]](). The script can read each child's current size,
then apply a resize factor and use llSetLinkPrimitiveParamsNoDelay() to set a new size. This can help
then apply a resize factor and use [[llSetLinkPrimitiveParamsFast]]() to set a new size. This can help
make it easy for the script to do the right thing even if reset and all its variables get reinitialized. The
make it easy for the script to do the right thing even if reset and all its variables get reinitialized. The
following function will resize all the prims (including the root itself) by a factor:
following function will resize all the prims (including the root itself) by a factor:


rescaleLinksetByFactor(float factor)
<lsl> rescaleLinksetByFactor(float factor)
  {
  {
     integer linkNum;
     integer linkNum;
     for (linkNum = llGetNumberOfPrims(); linkNum >= 1; --linkNum) {
     for (linkNum = llGetNumberOfPrims(); linkNum >= 1; --linkNum) {
         list params = llGetLinkPrimitiveParams(linkNum, [PRIM_SIZE]);
         list params = llGetLinkPrimitiveParams(linkNum, [PRIM_SIZE]);
         llSetLinkPrimitiveParamsNoDelay(linkNum,
         llSetLinkPrimitiveParamsFast(linkNum,
             [PRIM_SIZE, factor * llList2Vector(params, 0)]);
             [PRIM_SIZE, factor * llList2Vector(params, 0)]);
     }
     }
  }
  } </lsl>


But what if the function above encounters a prim that, after resized, would have a dimension outside
But what if the function above encounters a prim that, after resized, would have a dimension outside
Line 72: Line 72:
any prim would go out of those bounds, the function will return FALSE without resizing anything:
any prim would go out of those bounds, the function will return FALSE without resizing anything:


// Returns TRUE if successful, or FALSE if resizing would have set a prim size out of bounds:
<lsl> // Returns TRUE if successful, or FALSE if resizing would have set a prim size out of bounds:
  //
  //
  float MinPrimSize = 0.01;
  float MinPrimSize = 0.01;
Line 96: Line 96:
     for (linkNum = llGetNumberOfPrims(); linkNum >= 1; --linkNum) {
     for (linkNum = llGetNumberOfPrims(); linkNum >= 1; --linkNum) {
         list params = llGetLinkPrimitiveParams(linkNum, [PRIM_SIZE]);
         list params = llGetLinkPrimitiveParams(linkNum, [PRIM_SIZE]);
         llSetLinkPrimitiveParamsNoDelay(linkNum,
         llSetLinkPrimitiveParamsFast(linkNum,
             [PRIM_SIZE, factor * llList2Vector(params, 0)]);
             [PRIM_SIZE, factor * llList2Vector(params, 0)]);
     }
     }
   
   
     return TRUE;
     return TRUE;
  }
  } </lsl>


Here's a silly example of how it's used:
Here's a silly example of how it's used:


default
<lsl> default
  {
  {
     touch_start(integer num)
     touch_start(integer num)
Line 116: Line 116:
         }
         }
     }
     }
  }
  } </lsl>

Revision as of 13:56, 31 December 2009

New LSL Functions

The information in this section is preliminary and predictive, based on information given by Babbage Linden at his Office Hours.

To help reduce the number of scripts needed for certain common operations, we will have these new LSL functions:

<lsl> llGetLinkPrimitiveParams()

llSetLinkPrimitiveParamsFast() </lsl>

History

Some content creators prefer to distribute their objects no-mod, yet still allow customers to resize or retexture the linkset. Scripts can do that in a no-mod linkset, but the obvious solution using llSetLinkPrimitiveParams() doesn't work well because of the 0.2-second delay built into the function. To work around the delay, we have had to put a script in every child prim that can respond immediately to a message from the root prim. When these functions become available, we will be able to do this kind of thing with a single script.

Fixing Existing Scripts

To fix such a script, locate the call to llMessageLinked() in the master script where it sends the link message to the individual prims. It might look something vaguely like this:

<lsl>llMessageLinked(LINK_whatever, command_resize, (string)newSize, NULL_KEY);</lsl>

Replace that with a loop that applies whatever changes you need to each prim using llSetLinkPrimitiveParamsFast(). The prims have link numbers from 1 through llGetNumberOfPrims(), so you can make an efficient loop as shown here; just add any additional processing you need for each prim inside the loop:

<lsl> applyChildParams(list ruleSet)

{
    integer linkNum;
    for (linkNum = llGetNumberOfPrims(); linkNum >= 1; --linkNum) {
        llSetLinkPrimitiveParamsFast(linkNum, ruleSet);
    }
} </lsl>

For example, to use this function to set the color and alpha of all the prims, build the parameter list and pass it to applyChildParams() like this:

<lsl>applyChildParams([PRIM_COLOR, ALL_SIDES, <0.9, 0.8, 0.2>, 1.0]);</lsl>

However, when you only need to apply a constant rule set like this to every prim in the linkset, then the loop above can be simplified to a single statement;

<lsl>llSetLinkPrimitiveParamsFast(LINK_SET, ruleSet);</lsl>

Or use LINK_ALL_OTHERS or LINK_ALL_CHILDREN instead of LINK_SET as appropriate.

For another example, you can make a resizer script apply relative instead of absolute size changes by using the new function llGetLinkPrimitiveParams(). The script can read each child's current size, then apply a resize factor and use llSetLinkPrimitiveParamsFast() to set a new size. This can help make it easy for the script to do the right thing even if reset and all its variables get reinitialized. The following function will resize all the prims (including the root itself) by a factor:

<lsl> rescaleLinksetByFactor(float factor)

{
    integer linkNum;
    for (linkNum = llGetNumberOfPrims(); linkNum >= 1; --linkNum) {
        list params = llGetLinkPrimitiveParams(linkNum, [PRIM_SIZE]);
        llSetLinkPrimitiveParamsFast(linkNum,
            [PRIM_SIZE, factor * llList2Vector(params, 0)]);
    }
} </lsl>

But what if the function above encounters a prim that, after resized, would have a dimension outside the legal range of 0.01m to 10.0m? That could have unfortunate consequences, so here is a function that resizes all the prims by a specified factor but only if all the resulting dimensions in all the prims will all be in the legal range of 0.01m to 10.0m. If any dimension in any prim would go out of those bounds, the function will return FALSE without resizing anything:

<lsl> // Returns TRUE if successful, or FALSE if resizing would have set a prim size out of bounds:

//
float MinPrimSize = 0.01;
float MaxPrimSize = 10.0;

integer resizeLinksetWithBounds(float factor)
{
    // Test to see if it's safe to change all the prim sizes:

    integer linkNum;
    for (linkNum = llGetNumberOfPrims(); linkNum >= 1; --linkNum) {
        list params = llGetLinkPrimitiveParams(linkNum, [PRIM_SIZE]);
        vector sz = factor * llList2Vector(params, 0);
        if (sz.x < minPrimSize || sz.x > maxPrimSize ||
            sz.y < minPrimSize || sz.y > maxPrimSize ||
            sz.z < minPrimSize || sz.z > maxPrimSize) {
                return FALSE;
        }
    }

    // We've determined that we can safely change all the sizes, so let's do so now:

    for (linkNum = llGetNumberOfPrims(); linkNum >= 1; --linkNum) {
        list params = llGetLinkPrimitiveParams(linkNum, [PRIM_SIZE]);
        llSetLinkPrimitiveParamsFast(linkNum,
            [PRIM_SIZE, factor * llList2Vector(params, 0)]);
    }

    return TRUE;
} </lsl>

Here's a silly example of how it's used:

<lsl> default

{
    touch_start(integer num)
    {
        float factor = llPow(llFrand(2.0), 2.0);
        if (resizeLinksetWithBounds(factor)) {
            llOwnerSay("Resized successfully by factor = " + (string)factor);
        } else {
            llOwnerSay("Oops, can't resize by factor " + (string)factor);
        }
    }
} </lsl>