Hierarchics2
Jump to navigation
Jump to search
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 );
}
}