LlSetCameraParams Test

=Scripted Camera Test=
== Specs ==
Scripted Camera is intended as a way to modify the camera's view of your avatar. The best example of the power of Scripted Camera is as a vehicle camera. Turn on the Scripted Camera when you sit in a vehicle, and set the two lag values to about 0.1, and the behindness angle to 180, and notice the looseness. You can also use Scripted Camera on attachments. One possible use would be to have users put on a special hat when they come into your house, which causes their cameras to lock to a special place on the wall that allows all avatars to be in view, and focuses on the center of the room. Scripted Camera can also be used to flying views. For instance, you can set up a FlyCam which allows you to look down from bird's-eye-view to see the terrain as you fly along.
== Expectations ==
Attachments are automatically granted permissions when you attach them. Hitting escape will revert to the most recently set llSetCameraParams. Detaching the object will revoke permissions.
Vehicles are automatically granted permissions when you sit. Hitting escape will revert to the most recently set llSetCameraParams. Standing up will revoke permissions.
Stand-alone object must request scripted camera permissions via a dialog. Hitting escape will revert your view to your normal camera view (and revoke permissions?).
== The LL Script calls ==
llRequestPermissions(agent_key, PERMISSION_CONTROL_CAMERA);
Follow by any set of calls to modify the camera. This makes camera control behave like keyboard control, animation control, any other set of "overrides" that a script can perform. Note that the user will automatically cede control of the camera to attachments and objects he is sitting on, so the user experience will be pretty seamless in those cases. PERMISSION_CONTROL_CAMERA permissions are only supported for attachments and vehicles at this time. Accepting permissions via a dialog is not currently implemented.
llClearCameraParams();
Resets all camera values to their default.
llReleaseCamera();
Returns camera to agent.
llSetCameraParams([]); 
Sets up the camera movement rules based on the parameter list
CAMERA_ACTIVE (TRUE or FALSE) Default = FALSE
Turns on or off scripting control of Scripted Camera
CAMERA_DISTANCE (0.5 to 10.0 meters) Default = 3.0
Sets how far away the Scripted Camera wants to be from its subject
CAMERA_PITCH (-45.0 to 80.0 degrees) Default = 0.0
Adjusts the angular amount that the Scripted Camera aims straight ahead vs. straight down, maintaining the same distance. Analogous to 'incidence'
CAMERA_FOCUS_OFFSET (<-10,-10,-10> to <10,10,10> meters) Default = <0.0, 0.0, 0.0>
Adjusts the position of the Scripted Camera focus position relative to the subject
CAMERA_POSITION_LAG (0.0 to 3.0 seconds) Default = 0.1
How much the Scripted Camera lags as it tries to move towards its 'ideal' position
CAMERA_FOCUS_LAG (0.0 to 3.0 seconds) Default = 0.1
How much the Scripted Camera lags as it tries to aim towards the subject
CAMERA_BEHINDNESS_ANGLE (0.0 to 180.0 degrees) Default = 10.0
Sets the angle in degrees within which the Scripted Camera is not constrained by changes in subject rotation. 180 effectively turns behindness off.
CAMERA_BEHINDNESS_LAG (0.0 to 3.0 seconds) Default = 0.0
How much the Scripted Camera lags as it tries to stay behind the target if outside of behindness angle
CAMERA_POSITION_THRESHOLD (0.0 to 4.0 meters) Default = 1.0
Sets the radius of a sphere around the Scripted Camera's ideal position within which it is not affected by subject motion
CAMERA_FOCUS_THRESHOLD (0.0 to 4.0 meters) Default = 1.0
Sets the radius of a sphere around the Scripted Camera's subject position within which its focus is not affected by subject motion
CAMERA_POSITION (vector position within the region)
Sets the position of the Scripted Camera
CAMERA_FOCUS (vector position within the region)
Sets the focus position of the Scripted Camera
CAMERA_POSITION_LOCKED (TRUE or FALSE) Default = FALSE
Locks the camera position so it will not move
CAMERA_FOCUS_LOCKED (TRUE or FALSE) Default = FALSE
Locks the camera focus so it will not move
== Test ==
integer CHANNEL; // dialog channel
list MENU_MAIN = ["Default", "Overhead Cam", "Spin Cam", "Trap Toggle", "Spaz Cam", "Drop Cam", "Worm Cam", "Side Cam", "Driving Cam", "More...", "Cam ON", "Cam OFF"]; // the main menu
list MENU_2 = ["More...", "...Back"]; // menu 2
 
integer on = FALSE;
integer flying;
integer falling;
integer spaz = 0;
integer trap = 0;
take_camera_control(key agent)
{
 llOwnerSay("take_camera_control"); // say function name for debugging
 llOwnerSay( (string)agent); 
 llRequestPermissions(agent, PERMISSION_CONTROL_CAMERA);
 llSetCameraParams([CAMERA_ACTIVE, 1]); // 1 is active, 0 is inactive
 on = TRUE;
}
release_camera_control(key agent)
{
 llOwnerSay("release_camera_control"); // say function name for debugging
 llSetCameraParams([CAMERA_ACTIVE, 0]); // 1 is active, 0 is inactive
 llReleaseCamera(agent);
 on = FALSE;
} 
focus_on_me()
{
 llOwnerSay("focus_on_me"); // say function name for debugging
// llClearCameraParams(); // reset camera to default
 vector here = llGetPos();
 llSetCameraParams([
 CAMERA_ACTIVE, 1, // 1 is active, 0 is inactive
 CAMERA_BEHINDNESS_ANGLE, 0.0, // (0 to 180) degrees
 CAMERA_BEHINDNESS_LAG, 0.0, // (0 to 3) seconds
 CAMERA_DISTANCE, 0.0, // ( 0.5 to 10) meters
 CAMERA_FOCUS, here, // region relative position
 CAMERA_FOCUS_LAG, 0.0 , // (0 to 3) seconds
 CAMERA_FOCUS_LOCKED, TRUE, // (TRUE or FALSE)
 CAMERA_FOCUS_THRESHOLD, 0.0, // (0 to 4) meters
// CAMERA_PITCH, 80.0, // (-45 to 80) degrees
 CAMERA_POSITION, here + <4,4,4>, // region relative position
 CAMERA_POSITION_LAG, 0.0, // (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
 ]);
}
default_cam()
{
// llOwnerSay("default_cam"); // say function name for debugging
 llClearCameraParams(); // reset camera to default
 llSetCameraParams([CAMERA_ACTIVE, 1]);
}
driving_cam()
{
 llOwnerSay("driving_cam"); // say function name for debugging
 default_cam();
 llSetCameraParams([
 CAMERA_ACTIVE, 1, // 1 is active, 0 is inactive
 CAMERA_BEHINDNESS_ANGLE, 45.0, // (0 to 180) degrees
 CAMERA_BEHINDNESS_LAG, 0.5, // (0 to 3) seconds
 CAMERA_DISTANCE, 8.0, // ( 0.5 to 10) meters
 //CAMERA_FOCUS, <0,0,5>, // region relative position
 CAMERA_FOCUS_LAG, 0.05 , // (0 to 3) seconds
 CAMERA_FOCUS_LOCKED, FALSE, // (TRUE or FALSE)
 CAMERA_FOCUS_THRESHOLD, 0.0, // (0 to 4) meters
 CAMERA_PITCH, 20.0, // (-45 to 80) degrees
 //CAMERA_POSITION, <0,0,0>, // region relative position
 CAMERA_POSITION_LAG, 0.1, // (0 to 3) seconds
 CAMERA_POSITION_LOCKED, FALSE, // (TRUE or FALSE)
 CAMERA_POSITION_THRESHOLD, 0.0, // (0 to 4) meters
 CAMERA_FOCUS_OFFSET, <3,0,2> // <-10,-10,-10> to <10,10,10> meters
 ]);
}
side_cam()
{
 llOwnerSay("side_cam"); // say function name for debugging
 llClearCameraParams(); // reset camera to default
 llSetCameraParams([
 CAMERA_ACTIVE, 1, // 1 is active, 0 is inactive
 CAMERA_BEHINDNESS_ANGLE, 0.0, // (0 to 180) degrees
 CAMERA_BEHINDNESS_LAG, 0.0, // (0 to 3) seconds
 CAMERA_DISTANCE, 0.0, // ( 0.5 to 10) meters
 //CAMERA_FOCUS, <0,0,5>, // region relative position
 CAMERA_FOCUS_LAG, 0.0 , // (0 to 3) seconds
// CAMERA_FOCUS_LOCKED, FALSE, // (TRUE or FALSE)
 CAMERA_FOCUS_THRESHOLD, 0.0, // (0 to 4) meters
// CAMERA_PITCH, 80.0, // (-45 to 80) degrees
 //CAMERA_POSITION, <0,0,0>, // region relative position
 CAMERA_POSITION_LAG, 0.0, // (0 to 3) seconds
// CAMERA_POSITION_LOCKED, FALSE, // (TRUE or FALSE)
 CAMERA_POSITION_THRESHOLD, 0.0, // (0 to 4) meters
 CAMERA_FOCUS_OFFSET, <0,3,0> // <-10,-10,-10> to <10,10,10> meters
 ]);
}
rearview_cam()
{
 llOwnerSay("rearview_cam"); // say function name for debugging
 llSetCameraParams([
 CAMERA_ACTIVE, 1, // 1 is active, 0 is inactive
 CAMERA_BEHINDNESS_ANGLE, 180.0, // (0 to 180) degrees
 CAMERA_BEHINDNESS_LAG, 0.0, // (0 to 3) seconds
// CAMERA_DISTANCE, 10.0, // ( 0.5 to 10) meters
 //CAMERA_FOCUS, <0,0,5>, // region relative position
 CAMERA_FOCUS_LAG, 3.0 , // (0 to 3) seconds
// CAMERA_FOCUS_LOCKED, FALSE, // (TRUE or FALSE)
 CAMERA_FOCUS_THRESHOLD, 0.0, // (0 to 4) meters
// CAMERA_PITCH, 80.0, // (-45 to 80) degrees
 //CAMERA_POSITION, <0,0,0>, // region relative position
// CAMERA_POSITION_LAG, 0.0, // (0 to 3) seconds
// CAMERA_POSITION_LOCKED, FALSE, // (TRUE or FALSE)
 CAMERA_POSITION_THRESHOLD, 0.0, // (0 to 4) meters
 CAMERA_FOCUS_OFFSET, <5,2,-2> // <-10,-10,-10> to <10,10,10> meters
 ]);
}
overhead_cam()
{
 llOwnerSay("overhead_cam"); // say function name for debugging
 default_cam();
 llSetCameraParams([
 CAMERA_ACTIVE, 1, // 1 is active, 0 is inactive
 CAMERA_BEHINDNESS_ANGLE, 180.0, // (0 to 180) degrees
 CAMERA_BEHINDNESS_LAG, 0.5, // (0 to 3) seconds
 CAMERA_DISTANCE, 10.0, // ( 0.5 to 10) meters
 //CAMERA_FOCUS, <0,0,5>, // region relative position
 CAMERA_FOCUS_LAG, 0.05 , // (0 to 3) seconds
 CAMERA_FOCUS_LOCKED, FALSE, // (TRUE or FALSE)
 CAMERA_FOCUS_THRESHOLD, 0.0, // (0 to 4) meters
 CAMERA_PITCH, 80.0, // (-45 to 80) degrees
 //CAMERA_POSITION, <0,0,0>, // region relative position
 CAMERA_POSITION_LAG, 0.0, // (0 to 3) seconds
 CAMERA_POSITION_LOCKED, FALSE, // (TRUE or FALSE)
 CAMERA_POSITION_THRESHOLD, 0.0, // (0 to 4) meters
 CAMERA_FOCUS_OFFSET, <0,0,0> // <-10,-10,-10> to <10,10,10> meters
 ]);
}
drop_camera_5_seconds()
{
 llOwnerSay("drop_camera_5_seconds"); // say function name for debugging
 llSetCameraParams([
 CAMERA_ACTIVE, 1, // 1 is active, 0 is inactive
 CAMERA_BEHINDNESS_ANGLE, 0.0, // (0 to 180) degrees
 CAMERA_BEHINDNESS_LAG, 0.5, // (0 to 3) seconds
 CAMERA_DISTANCE, 3.0, // ( 0.5 to 10) meters
 //CAMERA_FOCUS, <0,0,5>, // region relative position
 CAMERA_FOCUS_LAG, 2.0, // (0 to 3) seconds
 CAMERA_FOCUS_LOCKED, FALSE, // (TRUE or FALSE)
 CAMERA_FOCUS_THRESHOLD, 0.0, // (0 to 4) meters
 CAMERA_PITCH, 0.0, // (-45 to 80) degrees
 //CAMERA_POSITION, <0,0,0>, // 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, <0,0,0> // <-10,-10,-10> to <10,10,10> meters
 ]);
 llSleep(5);
 default_cam();
}
worm_cam()
{
 llOwnerSay("worm_cam"); // say function name for debugging
 llSetCameraParams([
 CAMERA_ACTIVE, 1, // 1 is active, 0 is inactive
 CAMERA_BEHINDNESS_ANGLE, 180.0, // (0 to 180) degrees
 CAMERA_BEHINDNESS_LAG, 0.0, // (0 to 3) seconds
 CAMERA_DISTANCE, 8.0, // ( 0.5 to 10) meters
 //CAMERA_FOCUS, <0,0,5>, // region relative position
 CAMERA_FOCUS_LAG, 0.0 , // (0 to 3) seconds
 CAMERA_FOCUS_LOCKED, FALSE, // (TRUE or FALSE)
 CAMERA_FOCUS_THRESHOLD, 4.0, // (0 to 4) meters
 CAMERA_PITCH, -45.0, // (-45 to 80) degrees
 //CAMERA_POSITION, <0,0,0>, // region relative position
 CAMERA_POSITION_LAG, 1.0, // (0 to 3) seconds
 CAMERA_POSITION_LOCKED, FALSE, // (TRUE or FALSE)
 CAMERA_POSITION_THRESHOLD, 1.0, // (0 to 4) meters
 CAMERA_FOCUS_OFFSET, <0,0,0> // <-10,-10,-10> to <10,10,10> meters
 ]);
}
spaz_cam()
{
 llOwnerSay("spaz_cam for 5 seconds"); // say function name for debugging
 float i;
 for (i=0; i< 50; i+=1)
 {
 vector xyz = llGetPos() + <llFrand(80) - 40, llFrand(80) - 40, llFrand(10)>;
// llOwnerSay((string)xyz);
 vector xyz2 = llGetPos() + <llFrand(80) - 40, llFrand(80) - 40, llFrand(10)>;
 llSetCameraParams([
 CAMERA_ACTIVE, 1, // 1 is active, 0 is inactive
 CAMERA_BEHINDNESS_ANGLE, 180.0, // (0 to 180) degrees
 CAMERA_BEHINDNESS_LAG, llFrand(3), // (0 to 3) seconds
 CAMERA_DISTANCE, llFrand(10), // ( 0.5 to 10) meters
 //CAMERA_FOCUS, xyz, // region relative position
 CAMERA_FOCUS_LAG, llFrand(3), // (0 to 3) seconds
 CAMERA_FOCUS_LOCKED, TRUE, // (TRUE or FALSE)
 CAMERA_FOCUS_THRESHOLD, llFrand(4), // (0 to 4) meters
 CAMERA_PITCH, llFrand(125) - 45, // (-45 to 80) degrees
 CAMERA_POSITION, xyz2, // region relative position
 CAMERA_POSITION_LAG, llFrand(3), // (0 to 3) seconds
 CAMERA_POSITION_LOCKED, TRUE, // (TRUE or FALSE)
 CAMERA_POSITION_THRESHOLD, llFrand(4), // (0 to 4) meters
 CAMERA_FOCUS_OFFSET, <llFrand(20) - 10, llFrand(20) - 10, llFrand(20) - 10> // <-10,-10,-10> to <10,10,10> meters
 ]);
 llSleep(0.1);
 }
 default_cam();
}
spin_cam()
{
 llSetCameraParams([
 CAMERA_ACTIVE, 1, // 1 is active, 0 is inactive
 CAMERA_BEHINDNESS_ANGLE, 180.0, // (0 to 180) degrees
 CAMERA_BEHINDNESS_LAG, 0.5, // (0 to 3) seconds
 //CAMERA_DISTANCE, 10.0, // ( 0.5 to 10) meters
 //CAMERA_FOCUS, <0,0,5>, // region relative position
 CAMERA_FOCUS_LAG, 0.05 , // (0 to 3) seconds
 CAMERA_FOCUS_LOCKED, FALSE, // (TRUE or FALSE)
 CAMERA_FOCUS_THRESHOLD, 0.0, // (0 to 4) meters
 CAMERA_PITCH, 30.0, // (-45 to 80) degrees
 //CAMERA_POSITION, <0,0,0>, // region relative position
 CAMERA_POSITION_LAG, 0.0, // (0 to 3) seconds
 CAMERA_POSITION_LOCKED, FALSE, // (TRUE or FALSE)
 CAMERA_POSITION_THRESHOLD, 0.0, // (0 to 4) meters
 CAMERA_FOCUS_OFFSET, <0,0,0> // <-10,-10,-10> to <10,10,10> meters
 ]);
 
 float i;
 vector camera_position;
 for (i=0; i< 2*TWO_PI; i+=.05)
 {
 camera_position = llGetPos() + <0, 4, 0> * llEuler2Rot(<0,0,i>);
 llSetCameraParams([CAMERA_POSITION, camera_position]);
 }
 default_cam();
}
setup_listen()
{
 llListenRemove(1);
 CHANNEL = llRound(llFrand(1) * 100000);
 integer x = llListen(CHANNEL, "", "", ""); // listen for dialog answers
}
default
{
 state_entry()
 {
 setup_listen();
 llSetTimerEvent(2);
 llSitTarget(<-0.2, 0.0, 0.5>, <0.00000, -0.25882, 0.00000, 0.96593>);
 llSetCameraEyeOffset(<-6.0, 0.0, 2.00>);
 llSetCameraAtOffset(<0.0, 0.0, 1.0>);
 }
 
 touch_start(integer total_number) 
 {
integer perm = llGetPermissions();
if (perm & PERMISSION_DEBIT)
{ llOwnerSay(llGetScriptName() + " has PERMISSION_DEBIT perms for "+(string)llGetPermissionsKey()); }
if (perm & PERMISSION_TAKE_CONTROLS)
{ llOwnerSay(llGetScriptName() + " has PERMISSION_TAKE_CONTROLS perms for "+(string)llGetPermissionsKey()); }
if (perm & PERMISSION_TRIGGER_ANIMATION)
{ llOwnerSay(llGetScriptName() + " has PERMISSION_TRIGGER_ANIMATION perms for "+(string)llGetPermissionsKey()); }
if (perm & PERMISSION_ATTACH)
{ llOwnerSay(llGetScriptName() + " has PERMISSION_ATTACH perms for "+(string)llGetPermissionsKey()); }
if (perm & PERMISSION_CHANGE_LINKS)
{ llOwnerSay(llGetScriptName() + " has PERMISSION_CHANGE_LINKS perms for "+(string)llGetPermissionsKey()); }
if (perm & PERMISSION_TRACK_CAMERA)
{ llOwnerSay(llGetScriptName() + " has PERMISSION_TRACK_CAMERA perms for "+(string)llGetPermissionsKey()); }
if (perm & PERMISSION_CONTROL_CAMERA)
{ llOwnerSay(llGetScriptName() + " has PERMISSION_CONTROL_CAMERA perms for "+(string)llGetPermissionsKey()); }
if (perm == 0)
{ llOwnerSay(llGetScriptName() + " has NO perms for "+(string)llGetPermissionsKey()); }
 llDialog(llDetectedKey(0), "What do you want to do?", MENU_MAIN, CHANNEL); // present dialog on click
 }
 
 listen(integer channel, string name, key id, string message) 
 {
 if (llListFindList(MENU_MAIN + MENU_2, [message]) != -1) // verify dialog choice
// if (llListFindList(MENU_MAIN, [message]) != -1) // verify dialog choice
 {
// llOwnerSay(name + " picked the option '" + message + "'."); // output the answer
 if (message == "More...") 
 llDialog(id, "Pick an option!", MENU_2, CHANNEL); // present submenu on request
 else if (message == "...Back") 
 llDialog(id, "What do you want to do?", MENU_MAIN, CHANNEL); // present main menu on request to go back
 
 else if (message == "Cam ON")
 {
 take_camera_control(id);
 }
 else if (message == "Cam OFF") 
 {
 release_camera_control(id);
 }
 else if (message == "Default") 
 {
 default_cam();
 }
 else if (message == "Driving Cam") 
 {
 driving_cam();
 }
 else if (message == "Worm Cam") 
 {
 worm_cam();
 }
 else if (message == "Overhead Cam") 
 {
 overhead_cam();
 }
 else if (message == "Spaz Cam") 
 {
 spaz_cam();
 }
 else if (message == "Side Cam") 
 {
 side_cam();
 }
 else if (message == "Drop Cam") 
 {
 drop_camera_5_seconds();
 }
 else if (message == "Trap Toggle")
 {
 trap = !trap;
 if (trap == 1) {
 llOwnerSay("trap is on");
 }
 else {
 llOwnerSay("trap is off");
 } 
 }
 else if (message == "Spin Cam") 
 {
 spin_cam();
 }
 } else 
 llOwnerSay(name + " picked invalid option '" + llToLower(message) + "'."); // not a valid dialog choice
 }
 run_time_permissions(integer perm) {
 if ((perm & PERMISSION_CONTROL_CAMERA) == PERMISSION_CONTROL_CAMERA) {
 llSetCameraParams([CAMERA_ACTIVE, 1]); // 1 is active, 0 is inactive
 llOwnerSay("Camera permissions have been taken");
 }
 }
 
 changed(integer change)
 {
 if (change & CHANGED_LINK)
 {
 key agent = llAvatarOnSitTarget();
 if (agent)
 {
 setup_listen();
 llRequestPermissions(agent, PERMISSION_CONTROL_CAMERA);
 }
 }
 }
 
 attach(key agent)
 {
 if (agent != NULL_KEY)
 {
 setup_listen();
 llRequestPermissions(agent, PERMISSION_CONTROL_CAMERA);
 }
 }
 
 timer()
 {
 if (trap == 1)
 {
 focus_on_me();
 } 
 }
 
}
* Put the above script in a box.
* Click the box to open a dialog whereby you can control it.
* Test -45 pitch camera (Driving Cam)
** Set pitch to -45 and walk aroung the world. See if it acts in a predictable manner.
** Put the preceding script on a box.
** Attach the box, click the box and choose Worm Cam.
** Walk around and see if it acts in a predictable manner. 
* Test transitions
** Put the preceding script on a 4 x 4 x 0.5m box. Let's call it a vehicle.
** get in and out of a vehicle multiple times and see how the transitions work. 
* Scripted Cameras stack
** Get in a vehicle with one Scripted Camera setting, put on an attachment with another Scripted Camera setting, and then take off the attachment. Make sure the Scripted Camera pops back to the correct vehicle settings. 
* Scripted Cameras stack, part 2
** Wear 2 Scripted Camera attachments that have different Camera settings. Relog and verify your camera still has the same view as before you logged. (I don't think this test if valid Dan Linden 12:47, 5 August 2008 (PDT))
* Taking off scripted Camera attachments changes camera view to default
** Wear a Scripted Camera attachment, relog, detach the attachment and verify your view is the default walking camera. 
* Objects drop permissions after derez/rez from inventory
** Make an attachment that tries to take change your camera view every 2 seconds - "Trap Toggle" on the script above. Detach it to inventory, then rez to world and verify it does not control your camera.
** Verify it doesn't spam you with permissions errors in main chat. 
* Objects don't spam you
** Make an attachment that tries to take change your camera view every 2 seconds - "Trap Toggle" on the script above. Wear it, then drop it on the ground and verify it does not control your camera.
** Verify it doesn't spam you with permissions errors in main chat. 
* Escape reverts to most recent Scripted Camera view
** get in a vehicle with one Scripted Camera setting, put on an attachment with another Scripted Camera setting. Alt-zoom on the ground, then click escape. Make sure the your view reverts to using the attachment's Scripted Camera setting. 
* Set thresholds to 0 and lags to 0, and behindnessForce to 1, and explore varying behindnessAngle. Make sure it works as expected. (TODO: This needs to be a setting added to the script)
* Set Focus threshold and Position threshold as large as possible and see what happens. (TODO: This needs to be a setting added to the script)
* Lock position, and leave focus unlocked. Make sure the camera keeps focusing on avatar. (TODO: This needs to be a setting added to the script)
* Make focus lag and position lag as high as possible. Make sure it works as expected. (TODO: This needs to be a setting added to the script)
* Test how Scripted Cameras interact with llSetCameraAtOffset and llSetCameraEyeOffset. (TODO: This needs to be a setting added to the script)
* Test how Scripted Cameras interact with mouse steering?
** Apparently we can poll llGetAgentInfo to see if user is in mouselook, and if so, set the angular motor's z to 1 or some constant. 
* Test constraints on CAMERA_POSITION and CAMERA_FOCUS. Should not move your camera farther away than you can in edit mode. (TODO: This needs specific numbers and a setting added to the script)
* Test with multiple avatars on a vehicle. (TODO: This needs to be a setting added to the script)
Category:QA Portal
Category:Quality Assurance