Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Library: Public Morph

Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
05-16-2008 09:07
This set of scripts can be used in a single prim to have it toggle (on touch) between two saved prim states. A simple example would be... plain wall... click... hole appears in wall... click... plain wall again. It's not fantastically quick - more a triumph of flexibility over efficiency - so if you want to do a specific transformation you'd be better off coding for just the one case.

Put the control script and a pair of memory scripts into the prim that you want to morph.

The memory scripts are used in pairs. One script must end with the number 1, and the other with the number 2, for example: Memory 1, and Memory 2.

The control script has two types of trigger. Clicking once will flip between the two morph states. Clicking twice will invite you to save the current prim configuration.

Put the memory scripts in first, followed by the control script (the memory scripts are initialised by the control script's state_entry).

So, once your prim is loaded with the scripts you can:

Edit prim. Double click... Save (first morph).
Click (switches to second morph).
Edit prim. Double click... Save (second morph).
Single click (switch back to first morph)
Single click (switch to second morph)
...and so on.

Double click at any time to save a new morph over an existing morph.


Firstly the Control Script - straight forward enough:
From: someone
CODE

key uKey;
integer click;
integer mnuChannel;
integer mnuHandle;
integer iSet = 1;
string sDebug = "On";

dialogSave()
{
llListenRemove(mnuHandle);
mnuChannel = llRound(llFrand(900000) + 100000) * -1;
mnuHandle = llListen(mnuChannel, "", uKey, "");
llDialog(uKey, "\nSave Morph", ["Save","Debug " + sDebug ,"Cancel"], mnuChannel);
}

morfAction()
{
if (iSet == 1) iSet = 2;
else iSet = 1;

llMessageLinked(LINK_THIS, iSet, "morf", NULL_KEY);
}

default
{
state_entry()
{
llMessageLinked(LINK_THIS, 1, "save", NULL_KEY);
llMessageLinked(LINK_THIS, 2, "save", NULL_KEY);
}

touch_start(integer total_number)
{
uKey = llDetectedKey(0);

if (click)
{
llSetTimerEvent(0.0);
click = FALSE;

if (uKey == llGetOwner()) dialogSave();
else morfAction();
}
else
{
llSetTimerEvent(0.5);
click = TRUE;
}
}

timer()
{
llSetTimerEvent(0.0);
click = FALSE;
morfAction();
}

listen(integer channel, string name, key id, string message)
{
llListenRemove(mnuHandle);

if (message == "Save") llMessageLinked(LINK_THIS, iSet, "save", NULL_KEY);
else if (message == "Debug On")
{
sDebug = "Off";
llMessageLinked(LINK_THIS, 0, "debug on", NULL_KEY);
}
else if (message == "Debug Off")
{
sDebug = "On";
llMessageLinked(LINK_THIS, 0, "debug off", NULL_KEY);
}
}
}


Taming the Beast (aka llSetPrimitiveParams). The memory script looks intimidating because it is. :)

I've found this script to be pretty reliable. However, llSetPrimitiveParams can be quite a hit on a sim (do some work with a couple of hundred prims at the same time and listen to the sim scream!). Because llSetPrimitiveParams can be so aggressive the script goes to considerable effort to only change those aspects of the prim that need to change - it doesn't gratuitously change every setting with every morph.

From testing, this approach didn't seem to particularly speed up, or slow down, the execution time of the script, but it does reduce the scream to a grumble. Seriously, if you link several hundred prims and perform a massive number of changes across all the prims, it can hugely impact the ips of a sim.

The Memory Script - study it too long and it will make your eyes bleed:
From: someone
CODE

//integer PRIM_GLOW = 25;
rotation ROTATION;
integer SIDES;
list POSITION;
list SIZE;
list TYPE;
list FLEXIBLE;
list MATERIAL;
list POINT_LIGHT;
list PHANTOM;
list PHYSICS;
list TEMP_ON_REZ;
list BUMP_SHINY;
list COLOR;
list FULLBRIGHT;
list GLOW;
list TEXTURE;
list MORF;

integer iMorfNumber;
integer iSides;
integer iRoot;
integer iDebug;
integer i;
integer j;

default
{
state_entry()
{
iMorfNumber = (integer)llGetSubString(llGetScriptName(), -1, -1);
}

link_message(integer sender_number, integer iSet, string sCmd, key id)
{
if (iSet == 0)
{
if (sCmd == "debug on")
{
iDebug = TRUE;
llSetText("Debug Ready " + (string)iMorfNumber, <1,1,1>, 1);
}
else
{
iDebug = FALSE;
llSetText("", <1,1,1>, 1);
}
}
else if (iSet != iMorfNumber) return;

if (llGetNumberOfPrims() > 1 && llGetLinkNumber() > 1) iRoot = FALSE;
else iRoot = TRUE;

if (sCmd == "save")
{
if (iDebug) llSetText("Saving..." + (string)iMorfNumber, <1,1,1>, 1);
POSITION = [];
SIZE = [];
TYPE = [];
FLEXIBLE = [];
MATERIAL = [];
POINT_LIGHT = [];
PHANTOM = [];
PHYSICS = [];
TEMP_ON_REZ = [];
BUMP_SHINY = [];
COLOR = [];
FULLBRIGHT = [];
GLOW = [];
TEXTURE = [];

if (iRoot == 1) ROTATION = llGetRot();
else ROTATION = llGetLocalRot();

if (iRoot == FALSE) POSITION = [llGetLocalPos()];
SIZE = llGetPrimitiveParams([PRIM_SIZE]);
TYPE = llGetPrimitiveParams([PRIM_TYPE]);
FLEXIBLE = llGetPrimitiveParams([PRIM_FLEXIBLE]);
MATERIAL = llGetPrimitiveParams([PRIM_MATERIAL]);
POINT_LIGHT = llGetPrimitiveParams([PRIM_POINT_LIGHT]);

if (iRoot == TRUE)
{
PHANTOM = llGetPrimitiveParams([PRIM_PHANTOM]);
PHYSICS = llGetPrimitiveParams([PRIM_PHYSICS]);
TEMP_ON_REZ = llGetPrimitiveParams([PRIM_TEMP_ON_REZ]);
}

SIDES = llGetNumberOfSides() - 1;
i = 0;
for (0; i <= SIDES; i++)
{
BUMP_SHINY += llGetPrimitiveParams([PRIM_BUMP_SHINY, i]);
COLOR += llGetPrimitiveParams([PRIM_COLOR, i]);
FULLBRIGHT += llGetPrimitiveParams([PRIM_FULLBRIGHT, i]);
GLOW += llGetPrimitiveParams([PRIM_GLOW, i]);
TEXTURE += llGetPrimitiveParams([PRIM_TEXTURE, i]);
}
if (iDebug) llSetText("Saved " + (string)iMorfNumber, <1,1,1>, 1);
}

else if (sCmd == "morf")
{
MORF = [];

if (iDebug) llSetText("Morfing..." + (string)iMorfNumber, <1,1,1>, 1);
if (iRoot == 1 && ROTATION != llGetRot()) MORF += [PRIM_ROTATION] + [ROTATION];
else if (ROTATION != llGetLocalRot()) MORF += [PRIM_ROTATION] + [ROTATION / llGetRootRotation()];

if (iRoot == FALSE && llList2Vector(POSITION, 0) - llGetLocalPos() != <0, 0, 0>) MORF += [PRIM_POSITION] + POSITION;
if ((string)SIZE != (string)llGetPrimitiveParams([PRIM_SIZE])) MORF += [PRIM_SIZE] + SIZE;
if ((string)TYPE != (string)llGetPrimitiveParams([PRIM_TYPE])) MORF += [PRIM_TYPE] + TYPE;
if ((string)FLEXIBLE != (string)llGetPrimitiveParams([PRIM_FLEXIBLE])) MORF += [PRIM_FLEXIBLE] + FLEXIBLE;
if ((string)MATERIAL != (string)llGetPrimitiveParams([PRIM_MATERIAL])) MORF += [PRIM_MATERIAL] + MATERIAL;
if ((string)POINT_LIGHT != (string)llGetPrimitiveParams([PRIM_POINT_LIGHT])) MORF += [PRIM_POINT_LIGHT] + POINT_LIGHT;

if (iRoot == TRUE)
{
if ((string)PHANTOM != (string)llGetPrimitiveParams([PRIM_PHANTOM])) MORF += [PRIM_PHANTOM] + PHANTOM;
if ((string)PHYSICS != (string)llGetPrimitiveParams([PRIM_PHYSICS])) MORF += [PRIM_PHYSICS] + PHYSICS;
if ((string)TEMP_ON_REZ != (string)llGetPrimitiveParams([PRIM_TEMP_ON_REZ])) MORF += [PRIM_TEMP_ON_REZ] + TEMP_ON_REZ;
}

iSides = llGetNumberOfSides() - 1;
i = 0;
for (0; i <= SIDES; i++)
{
if (iSides == SIDES)
{
if ((string)llList2ListStrided(BUMP_SHINY, i * 2, (i * 2) + 1, 1) != (string)llGetPrimitiveParams([PRIM_BUMP_SHINY, i]))
MORF += [PRIM_BUMP_SHINY] + + llList2ListStrided(BUMP_SHINY, i * 2, (i * 2) + 1, 1);
if ((string)llList2ListStrided(COLOR, i * 2, (i * 2) + 1, 1) != (string)llGetPrimitiveParams([PRIM_COLOR, i]))
MORF += [PRIM_COLOR] + + llList2ListStrided(COLOR, i * 2, (i * 2) + 1, 1);
if ((string)llList2List(FULLBRIGHT, i, i) != (string)llGetPrimitiveParams([PRIM_FULLBRIGHT, i]))
MORF += [PRIM_FULLBRIGHT] + + llList2List(FULLBRIGHT, i, i);
if ((string)llList2List(GLOW, i, i) != (string)llGetPrimitiveParams([PRIM_GLOW, i]))
MORF += [PRIM_GLOW] + + llList2List(GLOW, i, i);
if ((string)llList2ListStrided(TEXTURE, i * 4, (i * 4) + 3, 1) != (string)llGetPrimitiveParams([PRIM_TEXTURE, i]))
MORF += [PRIM_TEXTURE] + + llList2ListStrided(TEXTURE, i * 4, (i * 4) + 3, 1);
}
else
{
MORF += [PRIM_BUMP_SHINY] + + llList2ListStrided(BUMP_SHINY, i * 2, (i * 2) + 1, 1);
MORF += [PRIM_COLOR] + + llList2ListStrided(COLOR, i * 2, (i * 2) + 1, 1);
MORF += [PRIM_FULLBRIGHT] + + llList2List(FULLBRIGHT, i, i);
MORF += [PRIM_GLOW] + + llList2List(GLOW, i, i);
MORF += [PRIM_TEXTURE] + + llList2ListStrided(TEXTURE, i * 4, (i * 4) + 3, 1);
}
}

if (MORF != [])
{
if (iDebug) llSetText("Accepted " + (string)iMorfNumber, <1,1,1>, 1);
llSetPrimitiveParams(MORF);
}
else if (iDebug) llSetText("Ignored " + (string)iMorfNumber, <1,1,1>, 1);
}
}
}


In this example the control script communicates via llMessageLinked with LINK_THIS, this restricts the scope of the control to only the single prim (it does not necessarily need to be the root prim). Clearly, without much effort it is possible to have the morph work across the entire linkset. It is also possible to load many more than 2 memory scripts into each prim (although a more complex control script is needed to support more than a pair of memory scripts).

At one time I did sell a product that would support up to 9 morph states across the whole linkset - it was never a big seller. Personally, I've found this single prim, 2 morph, set up more useful, but it's still a bit of a geek tool. :)

In any event, it's not really the Control script that's of interest here, it's the memory script. Use it as you will but please refrain from morphing several hundred scripts in a sim that I'm in (and yes, I apologise to anyone who was in the sandbox at the time :p).
Nada Epoch
The Librarian
Join date: 4 Nov 2002
Posts: 1,423
Library bump
05-21-2008 07:11
:)
_____________________
i've got nothing. ;)
pyro Seriman
Registered User
Join date: 6 Aug 2008
Posts: 1
09-13-2008 10:42
i cant get it to work for some reason there is an eror mesage
Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
09-13-2008 11:17
Was it a secret error message? :p

The line...

integer PRIM_GLOW = 25;

...is not required any more and can be discarded. It was a transitional thing required while the SL Client was playing catch-up with changes being made to the SL Server code.

HTH. :)