Hierarchics2
Revision as of 07:26, 26 August 2010 by Nexii Malthus (talk | contribs)
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.
<lsl> /*/
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 ); }
} </lsl>