User talk:Void Singer

From Second Life Wiki
Revision as of 23:29, 2 November 2007 by Void Singer (talk | contribs) (Added Code Examples Section + Rotations)
Jump to navigation Jump to search

About

  • Born: 1975
  • Name: Void is fine, "Your Majesty" works too ;)
  • Location: Utah, for the moment
  • History: Started off making webpages, then scripting for webpages (jscript), went to college for 3 years, studied programming and networking. I do a little of everything, from digital art, to running my own web & streaming media servers, to anything you can think of in SL.
I'm easy-going, love to help, pretty non-judgmental, and love interesting scripting challenges =)I know a little about alot, and alot about very little. I'm also kinda random, rather shy, and occasionally bouncy so.... beware!

Coding Practices: part 1 (formatting)

this is a listing of how I format code, for readability and self documentation, not everyone likes it, but if you use something and stick with it, others will thank you, and you'll thank yourself later when you look at it and your eyes want to glaze over thinking "WTF was I doing?"

  1. variables:
    • all user variables are prefixed with "v" (for variable) [so we can quickly Id variables]
    • all variables have their type included in 3 letters (eg. vStrData) [so we know the type, saves debugging typcast problems]
    • all variables denote what they are for (eg. key vKeyOwner = llGetOwner();) [saves on comments, makes it esay to know what we're doing]
    • all States prefixed "vs" -eg vsStateName [so we can id states]
    • all user defined functions prefixed "vf" and return type -eg vfFunctionName [so we can Id functions and their return types]
    • All Globals are prefixed with "vg" (for variable-global) [makes it easy to spot globals]
    • All Constants are prefixed "c" and placed in all caps to distinguish from ll -eg cSTR_TITLE [easier to spot non ll constants]
    • Bitmasks and booleans are given type "vBit" and "vBoo" [so we know how they are being used]
  2. Comments: [use lots of them to help us remember/see what code is trying to do]
    • Sections/Headers: "//--// text //--//"
    • Code: " //-- the line below does X" (note the extra space indent
    • Edit/Notes: " //-- the line to the left is editable or could use changes"
  3. Brackets/Whitespace:
    • Functions: space away from the container -eg. llRound( vIntNumber ); [makes it different from grouping]
    • math: always separate math -eg 2 + 2, exception increments --x, ++x [easier to read/debug]
    • Grouping: do not space inside, or out -eg. ((vIntNumber + 2) * 5 ) [makes it different from functions]
    • Events: follow function rules + { -eg state_entry(){
    • If/Loop: follows grouping rules with a space before group, and trailing { -eg if (TRUE){
    • loops, if/else, events, states, functions: "{" goes on the same line as the calling body, "}" after the last entry, and are ALWAYS used (even where optional) [for readability & debugging]
Note:
Apparently Strife and I disagree about placing "{" on the same line as the originating
section, so for the sake of not fighting over edits, they will be on the line following the
origin for WIKI examples... it's a matter of personal taste and practice for me, so I'll
let it go =) [however I cannot forgive the changing of comment formatting =P]
  1. General WhiteSpace:
    • blank line between event [easier to read]
    • blank line between sections of code doing different things [groups like actions]
    • tabs are 2 spaces, to reduce wrapping for nested items. any items inside a loop, if/else, event, state, or function recieves a tab [saves wrapping, eaiser to read/debug]
  2. Special Cases:
    • Long tests/function calls: wrap each variable/container to the next line with level spacing -eg see below [easier to read, less sloppy than built in wrapping]
//--// this is an example script //--//

string   cSTR_TITLE = "example script" //-- something to tell the user later
integer  vgIntTotalTouches = 0;

string vfStrFunctionExample( key vKeyOwner ){
  return llKey2Name( vKeyOwner );
}

default{
  state_entry(){
    llOwnerSay( "Hi, " + vfStrFunctionExample( llGetOwner() ) );
  }

  touch_start( integer vIntTouchCount ){
    do{
       //-- below is the example of wrapping functions parameters
      llSay( 0,
             cSTR_TITLE + " has been touched "           //-- this is an example of
                        + (string)(++vgIntTotalTouches)  //-- string wrapping, always
                        + " times" );                    //-- has + in the front
    }while (--vIntTouchCount > -1);
  }

  changed( integer vBitChanged ){
    if (vBitChanged & CHANGED_OWNER){
      state vsReset
    }
  }
}

state vsReset{
  state_entry(){
    llSay( 0, "New Owner " + vfStrFunctionExample( llGetOwner() ) + " detected; reseting" );
    llResetScript();
  }
}

Coding Practices Part 2 (optimizations)

This is a list of current coding optimizations and "hacks" I use in LSL and in examples They are all tested personally

  1. when testing a function that returns -1 on NOT_FOUND
    • use (~test_function) -[eg. if (~llSubStringIndex( "abcdef", "t")){
    • instead of (test_function != -1) -[eg. if (llSubStringIndex( "abcdef", "t") != -1){
    • because it runs faster -[(!~test_function) also works for FOUND
  2. when testing a list for a specific single entry
    • use llListFindList( vLstBase, (list)"test" )
    • instead of llListFindList( vLstBase, ["test"] )
    • because it runs faster -[eg. if (llListFindList( vLstBase, (list)"test" )){
  3. when incrementing counters or variables
    • use (++vIntCount)
    • instead of (vIntCount++) or (vIntCount += 1) or (vIntCount = vIntCount + 1)
    • because it runs faster
  4. Other Useful Optimizations

Code Examples:

Rotations

these are a few simplifications of common rotation tasks for those (like me) who get a bit glassy eyed and overwhelmed reading the 'official' version...

  • forward rotation vs reverse rotation
    • same as counter-clockwise vs clockwise (viewed from the positive end of the axis)
    • same as left turn vs right turn (viewed as if standing in the axis w/ head at positive end)
 //-- 2 ways to reverse rotation
 //-- use negative numbers in original variable, good for rotation that won't change
vector   vgVecLeftRotation = <.0, .0, 90.0>; //-- left 90 degrees around z-axis
vector   vgVecRightRotation = <.0, .0, -90.0>; //-- right 90 degrees around z-axis
 //-- use quaternion inversion, good for rotations that will reverse dynamically
vector   vgVecDegreesRotation = <.0, .0, 90>; //-- left 90 degrees around the z-axis
rotation vgRotConvertedDegrees = llEuler2Rot( vgVecDegreeRotation * DEG_TO_RAD ); //-- still left
vgRotConvertedDegrees.s *= -1; //-- reverses the rotation direction each time called
  • rotating in global axis vs local
    • Global axis is the world, up, down, north, east, south, west
    • Local axis is the object, top, bottom, left-side, right-side, fron-sidet, back-side.. imagine writing on a cardboard box
 //-- to rotate around the global axis (think stationary carousel)
llSetRot( llGetLocalRot() * vgRotConvertedDegrees );
 //-- to rotate around the local axis (think spinning tilted top) just reverse the order
llSetRot( vgRotConvertedDegrees  * llGetRot() );
  • roatating a given point to match objects position/rotation
    • Do this to find where a point is in relation to an object (good for rezzors)
    • for instance if you want to know the point 1m from the top of an object, and 2m right..
vector vVecOffset = <2.0, .0, 1.0>;
 //-- even after rotating your object this will give the point in relation to it's new rotation
vector vVecCurrentOffset = llGetPos() + vVecOffset * llGetLocalRot();
  • rotatating an objects POSITION around a given offset point
    • same idea as planets orbiting the sun
vector vVecOffset = <.0, .0, 1.0>; //-- the point we are rotating around in relation to our object
vector   vgVecArc = <.0, .0, 60.0>; //-- how far around the circle to travel each move
rotation vgRotArc = llEuler2Rot( vgVecArc * DEG_TO_RAD );
 //-- notice you have to move AND rotate, or else the new
 //-- position becomes a diagonal line instead of a circle
llSetPrimitiveParams( [PRIM_POSITION, llGetPos() + (vVecOffset - vVecOffset * vRotArc) * llGetLocalRot(),
                        PRIM_ROTATION, vRotArc * llGetLocalRot] );
  • Warnings:
    • do NOT use rotation division to reverse direction
    • llSetPrimitiveParams does not work correctly for rotations in child prims
 //-- this might work in some cases, but fails in most, so don't use it!
llSetRot( llGetRot() / vgRotConvertedDegrees  );
 //-- this works in a child prim
llSetRot( vgRotConvertedDegrees  * llGetLocalRot() );
 //-- this works incorrectly
llSetPrimitiveParams( [PRIM_ROTATION, vgRotConvertedDegrees  * llGetLocalRot()] );
 //-- see jira article SVC-93 for details + possible workaround

Comments:

Sample Comment

Please leave all comments here, (format below)

=== Comment Title ===
this is my comment

~~~~ <-- will be replaced by User Name + Time Stamp automatically

Thanks =)

Void Singer 21:59, 16 October 2007 (PDT)