Don't click here unless you want to be banned.

LSL Wiki : llTakeControls

HomePage :: PageIndex :: RecentChanges :: RecentlyCommented :: UserSettings :: You are crawling22.us.archive.org
llTakeControls(integer controls, integer accept, integer pass_on)

The control functions allow an object to respond to user interface input that normally controls the avatar. For example, this allows creation of a scripted vehicle that moves in response to the keyboard commands that normally move the avatar. Also, a gun can be created that fires in response to mouse button activity.

The controls parameter is an integer bitfield which is used to specify which user-interface controls the script is interested in. Possible values are:

Constant Hex Integer Description
CONTROL_FWD 0x00000001 1 forward control (W or up arrow)
CONTROL_BACK 0x00000002 2 back control (S or down arrow)
CONTROL_LEFT 0x00000004 4 move left control (shift + A or left arrow)
CONTROL_RIGHT 0x00000008 8 move right control (shift + D or right arrow)
CONTROL_UP 0x00000010 16 up control (E or PgUp)
CONTROL_DOWN 0x00000020 32 down control (C or PgDn)
CONTROL_ROT_LEFT 0x00000100 256 rotate left control (A or left arrow)
CONTROL_ROT_RIGHT 0x00000200 512 rotate right control ( D or right arrow)
CONTROL_LBUTTON 0x10000000 268,435,456 left mouse button control
CONTROL_ML_LBUTTON 0x40000000 1,073,741,824 left mouse button control with the avatar in MouseLook See ^Note

To filter multiple button presses, combine these values using the | (bitwise OR) operator. (See below for an example.)


The accept and pass_on parameters take a TRUE or FALSE value and have different effects:

accept pass_on effect
0 0 only specified controls functional...no script events
0 1 no apparent effect (all controls functional)...no script events
1 0 other controls functional no events...specified controls non-functional but generate events
1 1 all controls normal...specified controls also generate events


An object must have permission to take controls. Call llGetPermissions to see if the object has the PERMISSION_TAKE_CONTROLS permission. If it does not, you must first call llRequestPermissions to request permissions from the user.

After this function has been called and depending on the other parameters, the scripts's control event handler will be invoked whenever a specified input is received. The code you place in the control event handler determines how your object behaves in response to captured user input.

Each call to this function replaces the settings for any previous call. Unfortunately, that means a script can't completely control some inputs and let others continue to function while getting events. Fortunately there's a small glitch that is extremely handy since we can't rotate an avatar with a script. See below for more info.

When done with the controls (for example, when an attachment is removed) it is a good idea to clean up with a call to llReleaseControls.

CONTROL_ML_LBUTTON will cause a "Mouselook" button to appear on the bottom of the SL window, but only if pass_on is set to FALSE.

llTakeControls(CONTROL_ML_LBUTTON, TRUE, FALSE); // this works.
llTakeControls(CONTROL_ML_LBUTTON, TRUE, TRUE); // this doesn't.

Note: There seems to be a bug when taking CONTROL_ML_LBUTTON where it does not produce a MouseLook button after re-attaching even though permitted. Solution:
llReleaseControls();
llRequestPermissions(llGetOwner(), PERMISSION_TAKE_CONTROLS);
llTakeControls(CONTROL_ML_LBUTTON,TRUE,FALSE);


Example (see ExampleControls for a functioning script):

run_time_permissions(integer perms)
    {
        integer desired_controls = 
                CONTROL_FWD |
                CONTROL_BACK |
                CONTROL_LEFT |
                CONTROL_RIGHT |
                CONTROL_ROT_LEFT |
                CONTROL_ROT_RIGHT |
                CONTROL_UP |
                CONTROL_DOWN |
                CONTROL_LBUTTON |
                CONTROL_ML_LBUTTON; 

        if (perms & PERMISSION_TAKE_CONTROLS) {
            llTakeControls(desired_controls, TRUE, FALSE);
        }
    }


Taking Complete Control

There is a handy glitch that can be used to work around a major shortcoming of the control() system. There are many reasons why you might want to grab all the user input and not allow the standard av motion to take effect. For example, creating a custom movement solution.

The problem is that avs can not be scripted to rotate so normally using this function to grab all the input controls with accept set to 1 and pass to 0 will prevent a user from turning their av in normal non-mouselook view. You can leave out the right and left rotations but then you won't get events for them.

The trick is to make two calls to this function with the correct parameters. Using the following example, you'll take complete control (no normal movement) of all input except for left and right rotation which will behave normally and also generate control() events:

run_time_permissions(integer perms) {
        if (perms & PERMISSION_TAKE_CONTROLS) {
            llTakeControls(1, 1, 0); // glitch the rotation
            llTakeControls(desired_controls, 1, 0);
        }
    }

Hopefully if a 'fix' is made that changes this, the fix will include the functionality we all want and need.

Detecting loss of control
If someone releases controls after they have been granted, a Call to llGetPermissions compared with PERMISSION_TAKE_CONTROLS will show that the object no longer has permission. This can be done with a timer event.

default
{
    touch_start(integer start_param)
    {
        llRequestPermissions(llDetectedKey(0), PERMISSION_TAKE_CONTROLS);
    }
    run_time_permissions(integer perm)
    {
        if(perm & PERMISSION_TAKE_CONTROLS)
            state controlled;
    }
}
state controlled
{
    state_entry()
    {
        integer controls = 
            CONTROL_FWD | CONTROL_BACK
            | CONTROL_LEFT | CONTROL_RIGHT
            | CONTROL_UP | CONTROL_DOWN;

        llTakeControls(controls, TRUE, FALSE);
        
        llSetTimerEvent(5);
    }
    timer()
    {
        if(llGetPermissions() & PERMISSION_TAKE_CONTROLS)
            return;
        state default;
    }
}


Functions | Agent/Avatar | Control
Comments [Hide comments/form]
I tested that: You can call this function again at any time (once you have permissions) to change which controls get handled. Each call completely replaces the previous one. For example, you can choose to ignore all the controls by saying llTakeControls(<any combination, or zero>,FALSE,TRUE), and the Release Keys button remains in effect. You can later call llTakeControls(<some controls>,TRUE,FALSE) to use them again. Any control that wasn't specified in the bitmask of the most recent llTakeControl will, of course, be passed_on as normal.
-- DavanCamus (2005-10-15 20:30:47)
CONTROL_LEFT/ CONTROL_RIGHT seen to fire X2 on the control event, but all others only fire once. Anyone have any ideas on this?
-- MaxCase (2006-01-16 14:37:10)
I'm not seeing that Max. I'm seeing one press, zero or more helds and one release for a quick tap with all controls. Maybe it's the way you're testing for events. This example may make more sense for some people:

control(key id, integer down, integer change)
    {
        integer pressed = down & change;
        integer held = down & ~change;
        integer released = ~down & change;

        if (pressed & CONTROL_ROT_LEFT) llOwnerSay("rotate left pressed");
    }

I am bummed that calls supercede each other :-( typical LSL blowage. So no way to take full controls for some and pass through others...like ROT_LEFT/RIGHT. Guess we wouldn't need it if we could script av rotation! I know...two scripts!

Bah.
-- ReadyJack (2006-01-21 18:18:32)
Found a workaround ;-)

I'm a happy camper.
-- ReadyJack (2006-01-21 21:45:32)
to rotate an av, wouldnt you use llPushObject and use the ang_impulse parm?
-- MaxCase (2006-01-22 11:08:45)
Did you try it? If it works let me know ;-)

I definitely tried it in the past and no go. As far as I know there's no way to do it. All the functions you'd expect might work don't affect the av and unless LL's changed something recently it's probably still that way.
-- ReadyJack (2006-01-22 13:53:59)
One workaround if you want to take multiple controls and pass some but block others is to use separate scripts. Different scripts can take controls without conflicting with each other. Even in the same prim. So if you use one script as a master and take one set and then use a slave script to pass control events to the master with a link message for a second set of controls it should work fine.

I need to experiment a bit more and see what the impact of various pass through and accept have when dealing with multiple scripts taking controls. Once I have that info I'll update the page.
-- ReadyJack (2006-03-18 17:53:31)
You were right about the double fires Max. I put some info on the known bugs page about it.
-- ReadyJack (2006-08-27 03:57:56)
How can a script tell that the user has clicked "release keys"?
-- PlowboyLifestyle (2006-10-28 12:49:05)
I don't think there is an easy way.
-- BlindWanderer (2006-10-31 18:12:25)
You can probably infer it by checking the current permissions for the control flag. Though I haven't tested that so could be wrong.
-- ReadyJack (2006-12-03 03:01:14)
You can detect it via checking current permissions as ReadyJack has mentioned. I find it easier to use states in this case, and hook in a timer event to verify if the object still has permission. It would be nice if the run_time_permissions event was fired when controls were released so a timer wouldn't be needed to continuously check this.
-- DedricMauriac (2006-12-25 00:40:15)
aparently llTakecontrols(controls, FALSE, TRUE) (controls can be any controls) will not let a mouse click trigger touch( as well touch_start/end) while in mouselook mode, can anyone confirm that plz?
-- TigroSpottystripesKatsu (2007-11-01 20:54:01)
Attach a comment to this page: