Hierarchics2
Jump to navigation
Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
This is a script for creating parametrically driven hierarchies within a linked object.
The use-cases are varied and diverse, for example: User Interfaces (HUD/Vendor/Others..), Limbs (Robotic/Organic), Turrets, Machinery...
Scaling may be buggy, but position and rotation should work fine.
/*/
Hierarchics2
created by Nexii
Released into Public Domain
/*/
//////////////////////
// Hierarchics2
list hName;
list hLink;
list hPtrs;
list hPos;
list hRot;
list hScl;
BuildTree() {
list Names; list Links; hName = hLink = hPtrs = hPos = hRot = hScl = [];
integer x = llGetNumberOfPrims();
do {
string Name = llGetLinkName(x);
if( llGetSubString(Name,0,0) == "h" ) {
Names += Name; Links += x; }
} while( --x > 1 );
integer z = x = llGetListLength(Names); integer y;
while( x-- ) {
string rootName = llList2String(Names,x);
integer rootLink = llList2Integer(Links,x);
list rootTier = llParseString2List(rootName, ["."], []);
integer rootTiers = llGetListLength(rootTier);
integer PtrA; integer PtrB;
integer Children; y = z;
while( y-- ) {
// Is the same? Skip.
if(y == x) jump skip;
string childName = llList2String(Names,y);
list childTier = llParseString2List(childName, ["."], []);
integer childTiers = llGetListLength(childTier);
// Isn't directly below? Skip.
if(rootTiers+1 != childTiers) jump skip;
integer lastTier = rootTiers-1;
// Isn't same root? Skip.
if(llList2String(rootTier,lastTier) != llList2String(childTier,lastTier)) jump skip;
// Otherwise, add as child
if(Children >= 4)
PtrB = PtrB | ( (y+1) << (Children-4)*8 );
else PtrA = PtrA | ( (y+1) << Children*8 );
++Children;
@skip;
}
hName = [rootName] + hName;
hLink = [rootLink] + hLink;
hPtrs = [0,PtrA,PtrB] + hPtrs;
}
x = z;
while( x-- ) {
string Name = llList2String(hName,x);
integer cLink = llList2Integer(hLink,x);
list Tier = llParseString2List(Name,["."],[]);
integer Tiers = llGetListLength(Tier);
vector cPos = (llList2Vector(llGetLinkPrimitiveParams(cLink,[PRIM_POSITION]),0)-llGetRootPosition())/llGetRootRotation();
rotation cRot = llList2Rot(llGetLinkPrimitiveParams(cLink,[PRIM_ROTATION]),0)/llGetRootRotation();
if(Tiers > 1) {
integer Find = llListFindList( hName, [llDumpList2String(llList2List(Tier,0,Tiers-2),".")] );
hPtrs = llListReplaceList(hPtrs,[Find+1],x*3,x*3);
integer rLink = llList2Integer(hLink,Find);
vector rPos = (llList2Vector(llGetLinkPrimitiveParams(rLink,[PRIM_POSITION]),0)-llGetRootPosition())/llGetRootRotation();
rotation rRot = llList2Rot(llGetLinkPrimitiveParams(rLink,[PRIM_ROTATION]),0)/llGetRootRotation();
cPos = (cPos-rPos)/rRot; cRot /= rRot;
}
hPos = [cPos] + hPos;
hRot = [cRot] + hRot;
hScl = llGetLinkPrimitiveParams(cLink,[PRIM_SIZE]) + hScl;
}
}
// Usage: UpdateTree([PRIM_POSITION,"Turret",<1,2,3>]);
UpdateTree( list Input ) {
integer Find; integer Root;
integer Operation = llList2Integer(Input,0);
if(llGetListEntryType(Input,1) == TYPE_STRING) {
Root = TRUE;
Find = llListFindList( hName, [llList2String(Input,1)]);
if(Find == -1) return;
} else Find = llList2Integer(Input,1);
list Params;
if(Root) {
vector rPos; rotation rRot;
list lPos; list lRot;
integer Lookup = llList2Integer(hPtrs,Find*3);
integer x; integer y;
while( Lookup-- ) {
lPos = [llList2Vector(hPos,Lookup)] + lPos;
lRot = [llList2Rot(hRot,Lookup)] + lRot;
Lookup = llList2Integer(hPtrs,Lookup*3); ++y;
} rPos = llList2Vector( lPos,0);
for( x = 1; x < y; ++x ) {
rRot = llList2Rot(lRot, x-1) * rRot;
rPos += llList2Vector(lPos,x) * rRot; }
if(y>1) rRot = llList2Rot(lRot,-1) * rRot;
if(Operation == PRIM_POSITION) {
vector cPos = llList2Vector(hPos,Find);
vector tPos = llList2Vector(Input,2);
Params = [PRIM_POSITION, rPos+(tPos*rRot)];
hPos = llListReplaceList(hPos,[tPos],Find,Find);
Input = [rPos+(tPos*rRot), llList2Rot(hRot,Find)*rRot];
} else if(Operation == PRIM_ROTATION) {
rotation tRot = llList2Rot(Input,2);
Params = [PRIM_ROTATION, (tRot*rRot)/llGetRootRotation()];
hRot = llListReplaceList(hRot,[tRot],Find,Find);
Input = [rPos+(llList2Vector(hPos,Find)*rRot), tRot*rRot];
} else if(Operation == PRIM_SIZE) {
vector cScl = llList2Vector(hScl,Find);
vector tScl = llList2Vector(Input,2);
Params = [PRIM_SIZE, tScl];
hScl = llListReplaceList(hScl,[tScl],Find,Find);
Input = [rPos+(llList2Vector(hPos,Find)*rRot), llList2Rot(hRot,Find)*rRot,
<tScl.x/cScl.x,tScl.y/cScl.y,tScl.z/cScl.z>];
}
} else {
Root = llList2Integer(Input,2);
vector rPos = llList2Vector(Input,3);
rotation rRot = llList2Rot(Input,4);
if(Operation == PRIM_POSITION) {
vector cPos = llList2Vector(hPos,Find);
Params = [PRIM_POSITION, rPos+(cPos*rRot)];
Input = [rPos+(cPos*rRot),llList2Rot(hRot,Find)*rRot];
} else if(Operation == PRIM_ROTATION) {
rotation cRot = llList2Rot(hRot,Find);
vector cPos = llList2Vector(hPos,Find);
Params = [PRIM_POSITION, rPos+(cPos*rRot), PRIM_ROTATION, (cRot*rRot)/llGetRootRotation()];
Input = [rPos+(cPos*rRot), cRot*rRot];
} else if(Operation == PRIM_SIZE) {
vector cScl = llList2Vector(hScl,Find);
vector dScl = llList2Vector(Input,5);
vector tScl = <cScl.x*dScl.x, cScl.y*dScl.y, cScl.z*dScl.z>;
vector cPos = llList2Vector(hPos,Find);
cPos = <cPos.x*dScl.x, cPos.y*dScl.y, cPos.z*dScl.z>;
Params = [PRIM_POSITION, rPos+(cPos*rRot), PRIM_SIZE, tScl];
hPos = llListReplaceList(hPos,[cPos],Find,Find);
hScl = llListReplaceList(hScl,[tScl],Find,Find);
Input = [rPos+(cPos*rRot),llList2Rot(hRot,Find)*rRot]+llList2List(Input,5,5);
}
}
integer PtrA = llList2Integer(hPtrs,(Find*3)+1);
integer PtrB = llList2Integer(hPtrs,(Find*3)+2);
integer Children; integer x = 4;
while(x--) {
integer ChildA = (PtrA >> (x*8))&0xFF;
integer ChildB = (PtrB >> (x*8))&0xFF;
if(ChildA) UpdateTree([Operation,--ChildA,Find]+ Input);
if(ChildB) UpdateTree([Operation,--ChildB,Find]+ Input);
}
llSetLinkPrimitiveParamsFast( llList2Integer(hLink,Find), Params );
}
default {
state_entry() {
llOwnerSay("Building Tree..");
BuildTree();
llOwnerSay("Updating Tree..");
vector Pos = <1.5,-.0,-.6>;
float x;
for( x = 0; x > -1.0; x -= .1 ) {
UpdateTree([PRIM_POSITION,"hA",<Pos.x,x,Pos.z>]);
llSleep(.1);
}
UpdateTree([PRIM_ROTATION,"hA",llEuler2Rot(<0,0,11.25>*DEG_TO_RAD)]); llSleep( 1.0 );
UpdateTree([PRIM_SIZE,"hA.A",<.5,.6,.3>]); llSleep( 1.0 );
UpdateTree([PRIM_ROTATION,"hA.B.A",llEuler2Rot(<0,0,0>*DEG_TO_RAD)]); llSleep( 1.0 );
UpdateTree([PRIM_ROTATION,"hA",llEuler2Rot(<0,0,0>*DEG_TO_RAD)]); llSleep( 1.0 );
UpdateTree([PRIM_ROTATION,"hA.B.A",llEuler2Rot(<0,11.25,0>*DEG_TO_RAD)]); llSleep( 1.0 );
UpdateTree([PRIM_SIZE,"hA.A",<.5,.5,.5>]); llSleep( 1.0 );
}
}