イベント:control


control(key id, integer held, integer change)

一度、スクリプトがuuidで指定したアバターからコントロール入力をフックするパーミッションを得てしまえば、任意のコントロールのセットを取得すると、このイベントが発生し、得られたコントロールの状態をスクリプトへ引き渡します。
Heldパラメーターはどのコントロールが押されているかを示すビットフィールドです。
Changeパラメーターは最後に発生したコントロールイベントの状態から、現在のコントロールの状態が変化したかどうかを示すビットフィールドです。
この二つのパラメーターの組み合わせで、各コントロールの状態を把握することが出来ます。

このもっとも簡単な方法は定義済みのコントロール定数とパラメータを比較することです。

コントロール定数についてはここに示します。
コントロール名 数値 16進数 詳細
CONTROL_FWD 1 0x00000001 「↑」または「w」
CONTROL_BACK 2 0x00000002 「↓」または「s」
CONTROL_LEFT 4 0x00000004 「←」または「a」
CONTROL_RIGHT 8 0x00000008 「→」または「d」
CONTROL_UP 16 0x00000010 「PageUp」または「e」
CONTROL_DOWN 32 0x00000020 「PageDown」または「c」
未定義 64 0x00000040 未定義
未定義 128 0x00000080 未定義
CONTROL_ROT_LEFT 256 0x00000100 「Shift」+「←」または「a」
CONTROL_ROT_RIGHT 512 0x00000200 「Shift」+「→」または「d」
CONTROL_LBUTTON 268435456 0x10000000 マウスの左ボタン
CONTROL_ML_LBUTTON 1073741824 0x40000000 マウスルックにした後のマウスの左ボタン

heldとchangeのパラメーターはそれぞれ、イベントの中で受けとった複数のコントロール入力情報を持ちます。
コントロール入力が押されると、HELDパラメーターの対応するビット(コントロール定数とマッチしている各ビット)に1がセットされます。

コントロールの状態がUP→DOWN,DOWN→UPと変化したときにだけ、changeパラメータの対応するビットに1がセットされます。

Since we tend to think more of presses, holds and releases, it's useful to know how they relate.

私たちはプレス、ホールド、リリースの順に高く評価する傾向があるので
それらがどのように関係するかを知ることはとても有用です。

heldとchangeの両方のパラメーターの各コントロールに対応するビットが0ならば、それは一切の入力が無い状態を意味します。
heldとchangeの両方のパラメーターの各コントロールに対応するビットが1ならば、そのコントロール入力は「プレス」だけであることを意味します。
heldが1、changeが0の時、「ホールド」状態を意味します。
ボタンが押さえられる限り、コントロールに対応したビットを1にした状態で、持続的にコントロールイベントは発生します。
heldが0changeが1のときコントロール入力は「リリース」されたことを意味します。

各ビットのheldとchange値とコントロール入力の状態のまとめは以下の通りです。
held change
button not held 0 0
button press 1 1
button held down 1 0
button release 0 1

コントロールの検出

コードの中でコントロールをテストする幾つかの方法を列記します。
ビット演算子を使うつもりなら、”&”が論理積演算子(インターセクション)であることに注意してください。
従って、演算子の両端がともに1になっているビットだけが、結果として1に設定されます。
これは、同じビットが2つの値にセットされるかどうかをわかるので便利です
「OR」(『パイプ』オペレータ|)は論理和演算子(ユニオン)です。 どちらかの引数に1が設定されるすべてのビットが1としてセットされます。
これは、組み合わせをチェックするためにコントロール定数の値を結合するのに便利です。
けれども 複数のビットを1度にチェックするので、トリッキーな方法であることに注意してください (下で見てください)。

以下のコードは、「heldとchangeと任意のコントロール定数の論理積」を使ってフォワードボタンの押しはじめを検出します。
CONTROL_FWD定数の中ではフォワードを意味する単一のビットだけセットされている、, その定数と2つのパラメーターの論理積はTRUE値 を返す。
(つまり、フォワードボタンがプレスされたと判定される)。
if (held & change & CONTROL_FWD) llOwnerSay("forward pressed");
このコードはボタンのリリースを検出します。
if (~held & change & CONTROL_FWD) llOwnerSay("forward released");
"~"はNOTのビット演算子を意味します。
つまり、0→1、1→0へと全てのビットを反転させます。

~heldのCONTROL_FWDのビット位置の値が1であれば、本来のheldでは0です。
それは実際にはCONTROL_FWDが押されて無いことを意味します。
(しかし、それは入力が無いことを意味しません。入力がないか、リリースのどちらかであることを意味するだけです。)

このコードはボタンが押されているかを(真値であれば、それは最初のボタンの押し下げもを含むでしょう。)検出します。

if (held & CONTROL_FWD) llOwnerSay("forward held");

上記のコードの働きをいくらか理解しやすいと思われる別表現:

if ((held & CONTROL_LBUTTON) && (change & CONTROL_LBUTTON))
{
llOwnerSay("mouse press");
}
if ((~held & CONTROL_LBUTTON) && (change & CONTROL_LBUTTON)) 
{
llOwnerSay("mouse release");
}

If there's a 0 in the row you want for one of the parameters put a tilde ~ in front of it in the if statement.
あなたがパラメータの1つに対してその列の中に0があることを期待するなら。
「ifステートメント」でそれの前に「~」(チルダ)を置いてください
それが1であることを期待するなら、それを「~」をつけずにそのままにしてください。

複数のコントロールをハンドリングするには

この関数へのシングルコールバックは複数のコントロール入力の状態に関する情報を含むことができます。
それらをより詳細なアクションのために組み合わせることが出来ます。

複数のキーの組み合わせの変化を1度に検出したいなら、あなたが探しているすべてのビットがセットされることを検出したいかもしれませんがこれはトリッキーなので、以下のようなステートメントでは、予想通りに働きません:
if (held & change & (CONTROL_FWD | CONTROL_LEFT)) 
llOwnerSay("forward and/or left"); 
// Might not be what you want!

問題は、指定されたコントロールのうちの1つだけが押されるケース(例えばフォワードボタン)で発生します。
上のコントロール定義表を見るとCONTROL_FORWARDは1(0x1)の値を持ち,
CONTROL_LEFTは4(0x100)の値を持ちます。
したがって、(CONTROL_FWD | CONTROL_LEFT)は5(0x101)という値を持ちます。
もし、FORWARDキーだけが単独で押されるとheldとchangeは両方とも1の値を持ちます。
この場合、3つの引数全てに最初のビット(つまり1)がセットされるので(0x001 & 0x001 & 0x101)は1と評価される。
1がTRUEであるので、コンボとして検出します。

あなたが指定されたコントロールの組み合わせを探しているならば、これはすばらしいです、しかし、あなたがすべての任意のコントロールが同時に押されることを確認したいならば、コードを以下のように記述する必要があります

integer secret_style = CONTROL_DOWN | CONTROL_UP | CONTROL_FWD;
if ((held & change & secret_style) == secret_style) {
   llOwnerSay("five point palm exploding heart technique");
}
これは、secret_styleでセットされるすべてのビットがheldとchangeの両方に存在してれば、TRUEと評価するだけです。
この方法は、押されことを検出するためのキーをさらに追加することを許します。また、コンボも検出されます。

あなたがこのようなより多くの厳密なコードを使用したい場合:
if ((held & change) == secret_style) llOwnerSay("very strict");

これは指定されたコントロールが押されれば、TRUEと評価する。また他のものには反応しません。
しかし、1つのコントロールイベントの中で同時にに3個のキーを押すことを検出するには少し荷が重いかもしれません。

次の例は少なくとも1つが押され、正確な3つが押されていることを検出するものす。
if ((held & change) && (held == secret_style)) llOwnerSay("ouch");

This is saying, "If any key has been pressed and the keys that are down are exactly the right ones, then cause some pain."
これは、「どのようなキーでも押されたキーが正確に正しいのものであるならば、負荷の原因となる」と言い換えることが出来ます。。

パラメーター変換
複雑なスクリプトでは、heldとchangeの扱い方で経過を追うのが難しくなります。

あなたが「プレス」「ホールド」「リリース」についてのアイディアを使いたいならば、すべてのロジックを見つけ出すためにこのようなコードを使用することができます:

control(key id, integer held, integer change) {
       integer pressed = held & change;
       integer down = held & ~change;
       integer released = ~held & change;
       integer inactive = ~held & ~change;
       if (pressed & CONTROL_LBUTTON) llOwnerSay("click");
   }

キーを押したとしても、直前に押されたキーを含まないことを心にとめておいてください。
あなたがそれを望まないならば、ホールドだけを使うべきです。

マウスルック VS. 通常モード
マウスモードでは移動キーのキーアサインがノーマルモードとは異なります。
マウスルックモードではCONTROL_LBUTTONの代わりにCONTROL_ML_LBUTTONが再定義されます。

The left/right keys are now used for strafing,
左右の移動キーは現在、銃撃時の平行移動で使われています。
CONTROL_ROT_LEFTとCONTROL_ROT_RIGHT(方向転換のためです)の代わりに CONTROL_LEFTとCONTROL_RIGHTが引き起こされます。

In "normal" mode CONTROL_LEFT and CONTROL_RIGHT can be triggered by holding down shift and using the left/right keys.

ノーマルモードではCONTROL_LEFTとCONTROL_RIGHTはシフトキーを押しながら左右の移動をすることで引き起こされます。

Example
default {
   [[state_entry]]() {
       llRequestPermissions(llGetOwner()
     , PERMISSION_TAKE_CONTROLS);
// get permission to take controls
   }
   [[run_time_permissions]](integer perm) {
// permissions dialog answered
       if (perm & PERMISSION_TAKE_CONTROLS) { 
// we got a yes
         llTakeControls(CONTROL_UP | CONTROL_DOWN,
                                      TRUE, FALSE);
// take up and down controls
       }
   }
   control(key id, integer held, integer change) {
// something happened to one of our controls
       if (held & CONTROL_UP) { 
// the "fly up" key is held
           llSetPos(llGetPos() + <0, 0, 0.25>);
// move up
       } else if (change & held & CONTROL_DOWN) {
// the "fly down" key was pressed
           llSetPos(llGetPos() + <0, 0, -0.25>);
// move down
       }
   }
}

Q:CONTROL_LEFTとCONTROL_RIGHTに対応するキーは何ですか?本当に存在してますか?

A: ノーマルモードのときはシフトキーを押しながら左右移動キーを押してください。マウスルックの場合は左右移動キーを押してください。
左右移動キーはそれぞれ「A」と「D」でも代用できます。
最終更新:2008年02月23日 17:14