CameraSynch2

From Second Life Wiki
Revision as of 15:21, 6 July 2009 by BETLOG Hax (talk | contribs)
Jump to navigation Jump to search

CameraSynch2 v1.0.0

Synchronization of multiple avatar cameras.
This script initially needs to be dropped individually into numerous linked prims.
However because the script adds a PIN, after its been added once the owner can issue the "update" command to automatically propogate any changes made to the root script into the child prims/scripts.

TO USE:
1] Rez a bunch of prims, one for each bum you want to sit on them.
2] Link them together.
3] Drop a copy of this script in each prim.
4] Sit one person on the controller seat, and some persons on the other seats.
5] Read the spam when you sit down.

<lsl> // // BELOG Hax // AEST 20071221 0452 [SLT: 20071220 1152] // https://wiki.secondlife.com/wiki/CameraSynch2 // // VERSION: // v1.0.0 revised and wikified from my previous: 'CameraSynch v0.3.1' // Not really well tested, but seems good. // Timer frequency could do with some moderation... Possibly with dynamic adjustment. // // CREDITS: // Meyermagic Salome and Nomad Padar for // http://wiki.secondlife.com/wiki/Camera_Sync // I drew some inspiration from theirs some time after I wrote the first iteration of this script. // I don't think I actually derived anything from it... // but theirs was the original..and Nomad is awesome. //========================================================================= // ---LICENCE START--- // http://creativecommons.org/licenses/by-sa/3.0/ // ie: Attribution licence: // Give me credit by leaving it in the script I created. // Supply my original script with your modified version. // Refer to the wiki URL from which you copied this script. // https://wiki.secondlife.com/wiki/CameraSynch2 // ---LICENCE END--- //=========================================================================

// SHARED CONFIGURATION integer gPayloadPIN = 89876847; //---------------------------------- // CONFIGURATION float gFrequency = 0.02; integer gChan = 0; //---------------------------------- // CORE CODE - controller string gCamController = NULL_KEY; vector gOldCamPos; rotation gOldCamRot; string gOldDesc; integer gTog; // CORE CODE - spectator //-------------------------------------- f_camDefault() { llSetCameraParams([

       CAMERA_ACTIVE, FALSE, //1 is active, 0 is inactive
       CAMERA_BEHINDNESS_ANGLE, 10.0, //(0 to 180) degrees
       CAMERA_BEHINDNESS_LAG, 0.0, //(0 to 3) seconds
       CAMERA_DISTANCE, 3.0, //(0.5 to 10) meters
       CAMERA_FOCUS_LAG, 0.1 , //(0 to 3) seconds
       CAMERA_FOCUS_LOCKED, FALSE, //(TRUE or FALSE)
       CAMERA_FOCUS_THRESHOLD, 1.0, //(0 to 4) meters
       CAMERA_PITCH, 0.0, //(-45 to 80) degrees
       CAMERA_POSITION_LAG, 0.1, //(0 to 3) seconds
       CAMERA_POSITION_LOCKED, FALSE, //(TRUE or FALSE)
       CAMERA_POSITION_THRESHOLD, 1.0, //(0 to 4) meters
       CAMERA_FOCUS_OFFSET, ZERO_VECTOR //<-10,-10,-10> to <10,10,10> meters
   ]);

} //---------------------------------- default { on_rez(integer start_param)

   {   llResetScript();
   }    
   state_entry()
   {   if (gPayloadPIN)    llSetRemoteScriptAccessPin(gPayloadPIN);
       llSitTarget(<0.2, 0.0, 0.5>, <0.0, 0.0, 0.0, 1.0>);                 
       integer link = llGetLinkNumber();
       if (link>1)
       {   string name = "Spectator#"+(string)(link-1);
           llSetObjectName(name);
           llSetColor(<0.0, 1.0, 1.0>, ALL_SIDES);            
           llSetText(name, <1.0, 1.0, 1.0>, 1.0);
           state repeater;
       }
       llSetColor(<1.0, 1.0, 0.0>, ALL_SIDES);
       llSetObjectName(llGetScriptName());        
       llSetText("CONTROLLER", <1.0, 1.0, 1.0>,1.0);        
       if (gPayloadPIN)
           llListen(gChan, "", llGetOwner(), "update");        
   }
   listen(integer channel, string name, key id, string message)
   {   integer cc;
       integer c = cc = llGetNumberOfPrims();
       llOwnerSay("WAIT: Propogating scripts...");    
       while(c>1)
       {   llSetText("Updating: "+(string)(cc-c+1)+"/"+(string)(cc-1)
               , <1.0, 1.0, 1.0>, 1.0);
           llRemoteLoadScriptPin(llGetLinkKey(c--), llGetScriptName(), gPayloadPIN, TRUE, 1);   
       }
       llSetText("CONTROLLER", <1.0, 1.0, 1.0>, 1.0); 
       llOwnerSay("OK: Script propogation completed.");
   }
   changed(integer change)
   {   if (change & CHANGED_LINK)
       {   gCamController = llAvatarOnSitTarget();
           if (gCamController != NULL_KEY)
           {   llRequestPermissions(gCamController
                   , PERMISSION_TRACK_CAMERA|PERMISSION_TAKE_CONTROLS
               );
           }
           else
           {   llSetTimerEvent(0.0);
               llSetObjectDesc(gOldDesc);
               llResetScript();
           }
       }
   }
   run_time_permissions(integer perm)
   {   if(perm & PERMISSION_TAKE_CONTROLS)        
       {   llTakeControls(0| CONTROL_LBUTTON,TRUE, TRUE); //work anywhere
           llInstantMessage(llGetPermissionsKey(), 
               "\nThis device allows the spectator cameras to be controlled by YOU."
               +"\nUseful Tips:"
               +"\n1] Ensure you are NOT in mouselook."
               +"\n2] Spectators cameras track yours with a short delay, and do not move quite as smoothly "
               +"as yours does, so go slowly and avoid any sudden or disconcerting movements."
               +"\nREMEMBER: If your drawdistance is greater than a spectators, their camera may be left "
               +"behind at some point. So if you hear people say 'did we stop moving?' you should move "
               +"your camera closer to where you are all sitting."
           );
           llSetTimerEvent(gFrequency);
       }
       else //never
           llUnSit(gCamController);
   }
   timer()
   {   vector camPos = llGetCameraPos();
       rotation camRot = llGetCameraRot();
       if (llVecDist(camPos, gOldCamPos) > 0.001 
       || llAngleBetween(camRot, gOldCamRot) >= 0.0008)
       {   gTog = !gTog;
           gOldCamPos = camPos;
           gOldCamRot = camRot;
           llSetText("RELAYING..",<0.0, (float)gTog, 1.0-gTog>,1.0);
           llSetObjectDesc((string)camPos+"#"+(string)camRot);      
       }
   }

} //========================================================================= state repeater { on_rez(integer start_param)

   {   llResetScript();
   }
   state_entry()
   {   llSetTimerEvent(0.0);
   }
   changed(integer change)
   {   if (change & CHANGED_LINK)
       {   if (llGetLinkNumber() == 0)
               llResetScript();
           key av = llAvatarOnSitTarget();
           if (av != NULL_KEY && llGetPermissionsKey() == NULL_KEY)
           {   llRequestPermissions(av, PERMISSION_CONTROL_CAMERA);
           }
       }
   }
   run_time_permissions(integer perms)
   {   if (perms & PERMISSION_CONTROL_CAMERA)
       {   llInstantMessage(llGetPermissionsKey(), 
               "This device allows the spectator cameras to be centrally controlled."
               +"\nPlease : "
               +"\n1] Ensure you are NOT in mouselook."
               +"\n2] Reset your camera by pushing the escape button 3 or 4 times."
               +"\nNOTE: If the controller avatar's drawdistance is greater than yours, "
               +"you may experience being 'left behind' at some point. Either increase "
               +"your draw distance, or reset your camera again  (hit escape a few times) "
               +"after a short while and hopefully the controllers camera is closer and "
               +"tracking will resume.\nObviously it helps to let the controller know if "
               +"they are too far away, but perhaps your drawdistance could also be higher."
               +"\n[ctrl-P.... graphics tab...'custom' checkbox... 'drawdistance' slider... increase it a bit]"
           );
           llSetTimerEvent(gFrequency);
       }
   }
   timer()
   {   if (llGetPermissionsKey())
       {   string desc = llList2String(llGetObjectDetails(llGetLinkKey(LINK_ROOT), [OBJECT_DESC]),0); 
           integer index = llSubStringIndex(desc, "#");
           vector pos = (vector)llGetSubString(desc, 0, index-1);
           if (pos == ZERO_VECTOR)
           {   f_camDefault();
               return;
           }
           rotation rot = (rotation)llGetSubString(desc, index+1, -1);
           llSetCameraParams([
               CAMERA_ACTIVE, 1 //1 is active, 0 is inactive
               ,CAMERA_BEHINDNESS_ANGLE, 0.0 //(0 to 180) degrees

// ,CAMERA_BEHINDNESS_LAG, 0.05 //(0 to 3) seconds

               ,CAMERA_DISTANCE, 0.0 //(0.5 to 10) meters
               ,CAMERA_FOCUS, pos + llRot2Fwd(rot) //Region-relative
               ,CAMERA_FOCUS_LAG, 0.05 //(0 to 3) seconds
               ,CAMERA_FOCUS_LOCKED, TRUE //(TRUE or FALSE)
               ,CAMERA_FOCUS_THRESHOLD, 0.0 //(0 to 4) meters
               ,CAMERA_POSITION, pos //Region-relative position
               ,CAMERA_POSITION_LAG, 0.05 //(0 to 3) seconds
               ,CAMERA_POSITION_LOCKED, TRUE //(TRUE or FALSE)
               ,CAMERA_POSITION_THRESHOLD, 0.0 //(0 to 4) meters
               ,CAMERA_FOCUS_OFFSET, ZERO_VECTOR //<-10,-10,-10> to <10,10,10> meters
           ]);
       }
       else
       {   llSetTimerEvent(0.0);
       }
   }

} //=========================================================================

 </lsl>