【asa】ネタ製作とその実現3 ぱーみっしょん

mina Cookie

2007年04月25日 17:20


そんなわけで第3段ですが、ハンカチ王子を目指すのはちょっとだけお休みにして「ぱーみっしょん」(permission)の話をしておこうかと。
まあ、この手の話もあちこちで語られてるとは思いますけどね。
 
SLで出てくる「ぱーみっしょん」という語は、以下の2つのいずれかを指します。
1.Object(モノ)の、複製(COPY)、編集(MOD)、譲渡(TRANS)の設定のこと(Asset Permissionと呼ぶようです)
2.スクリプトに仕込まれたアニメ、キー操作変更等の許可設定のこと(Script Permissionと呼ぶようです)

1.は、既にモノ作りをされている方でそれを誰かに渡したとか誰かから貰ったことがある方にはお馴染みだと思います。
COPY, MOD(MODIFY), TRANS(TRANSFER=Resale/Giveaway)のほか、Allow anyone to moveのチェックボックス設定もこの仲間のようです。
作ったモノの特性、使わせ方によって適宜設定する必要があります。
COPY, MOD, TRANSの3点セットを許可(フルパーミッション)すると、貰った人も色々な人に渡したい放題になります。つまり転売されたりってこともでてきますので、気をつけておきたいところですね。
 
2.は、たとえば何かにSitしたりWearした時に右上に青い確認用のダイアログが出ることがありますが、それのことです。
どんな時にこれが出るのか案外知らない方もいらっしゃるようなので、ちょっと解説なのです。
この確認作業は、オブジェクト等に仕込まれたスクリプトが以下のことを自動実行しようとする際に行われることがあります。
・アニメーションを発動させる(Animation)
・キー操作の動作内容を変更する(Take Controls)
・Payによる支払い(Debit)
・オブジェクトのアタッチ、デタッチ(Attach)
・オブジェクトのリンク操作(Change Links)
・カメラの移動/回転(Track Camera)
・カメラの制御(Control Camera)
でも、この確認ダイアログは常に出るわけじゃありません。出る時と出ない時とがある。何故か?
実はこれらの許可/不許可は、Agent毎に内部情報として持っています。
最初から許可された状態であればわざわざ確認する必要もないので確認しない、というような感じになっているものが多いのです。
毎回聞いてこられてもうっとーしー!ということもありますしね。
 
でもこの確認、意味はちゃんとあります。
それはもしもこの許可設定がなかったら、たとえば悪意のある人が自由に貴方をあんなポーズこんなポーズにしてしまうこともできちゃうということです。
他の操作も同様に、悪意をもってすれば迷惑行為に繋がるようなことなんです。
なので、右上に確認用の青いダイアログが出たとき、それに心辺りがなければ許可しないようにしましょう^^
 
さて、ハンカチ王子ネタにもこの話を絡めておきましょう。
ハンカチ王子になるためには「野球の投球フォームを実現するアニメーション」が必要でした。
すなわち、上で説明した通り、アニメーションを発動させるための許可が必要になります。
このアニメーションは、玉オブジェクトをwearした時に発動する、という仕様にすることにします。
wearした時に発生するイベントはattachイベントです。
attach(key avid){
  
}
wearされたら、まずは「今現在は、許可されてるの?」という確認をします。
許可されているかどうか?という状態値は、integer型の変数でbit imageとして持ちます。
この状態値を、permという変数で持つことにします。
attach(key avid){
  integer perm ;
  
}
次、状態値をとってきます。llGetPermissions()というfunctionを用います。
attach(key avid){
  integer perm = llGetPermissions();
  
}
そして許可があるかどうかの判定。
permという変数は、色々な許可の情報を含んでいます。
たとえば、Debit=2, Take Controls=4, Animation=16, ...で、許可された値のこれらの合算値が入ってます。
ちょっと電算機的な論理演算(ブール代数)ぽい話が入りますが、この合算値から必要な部分をとってくるには、AND演算を用います。
Animationは16ですので、
(perm & 16)
この値が0かどうかで、Animationの許可があるかどうかがわかります。0なら不許可状態。
あと、実際にLSLを書くときは、この部分には2とか4とか16とかは書きません。そのかわり、見た目にわかりやすい定数が用意されています。
たとえばAnimation(16)は、PERMISSION_TRIGGER_ANIMATIONという定数。つまり、
(perm & PERMISSION_TRIGGER_ANIMATION)
こう書きます。というか、こう書くのが流儀です。
さて、こいつが0かどうかを判断することになるので、以下のような分岐分が登場します。
attach(key avid){
  integer perm = llGetPermissions();
  if(!(perm & PERMISSION_TRIGGER_ANIMATION)){
    // if文の値が0。つまりアニメの許可はされていない!
  }
}
上の例は、ちょっと説明が面倒なので詳細説明は省きますが、LSLでは、これで「0の時」という表現ができます。
もっとわかりやすく書くならば、
  if((perm & PERMISSION_TRIGGER_ANIMATION) == 0){
とかです。
このif文は、アニメの許可がされていない時にほにゃららしなさい、という意味ですので、つまり、
アニメの許可がされていない→アニメの許可をするための操作
という手順になります。
Script Permissionの許可は、llRequestPermissions()というfunctionで実現します。
また、「許可されている」時の動作も合わせて書いておきます。
attach(key avid){
  integer perm = llGetPermissions();
  if(!(perm & PERMISSION_TRIGGER_ANIMATION)){
    // if文の値が0。つまりアニメの許可はされていない!
    llRequestPermissions(avid, PERMISSION_TRIGGER_ANIMATION);
  }
  else{
    // if文の値が0以外。アニメの許可はされているのでアニメ発動!
    llStartAnimation("pitching");
  }
}
ここで気付いた方も多いんじゃないかと思いますが、あの、右上に出てくる青い許可設定のダイアログは、
llRequestPermissions(avid, PERMISSION_TRIGGER_ANIMATION); ←こいつ
が出しているんです。
さて、続けます。
あれ?llRequestPermissions()で許可のダイアログ出したはいいけど、その後許可されたり許可されなかったりした場合はどうなるの?
という疑問が湧いてくると思います。いや、湧かなかったら湧かせてくださいw
llRequestPermissions()による許可が行われると、run_time_permissionsというイベントが発生します。
このイベントには、llRequestPermissions()で与えられた許可の状態値が渡されてきます。以下のpermがそれです。
run_time_permissions(integer perm){
  
}
さて、上記と似ていますね。llRequestPermissions()で許可されたら、と、許可されなかったら、の2つのケースがあります。
許可されなかったらアニメは発動できませんので、まあ、無視しておきましょうw
今度は上のものとは別です。
if(perm & PERMISSION_TRIGGER_ANIMATION){
で、この値が「0以外である」という判断ができます。
run_time_permissions(integer perm){
  if(perm & PERMISSION_TRIGGER_ANIMATION){
    // if文の値が0以外。アニメの許可はされているのでアニメ発動!
    llStartAnimation("pitching");
  }
}
さて、全て繋げてみましょう。
LSLとしてはstate内でイベントハンドラが定義されていなければなりません。ていうか、default stateでいいんですけど。
default{
  attach(key avid){
    integer perm = llGetPermissions();
    if(!(perm & PERMISSION_TRIGGER_ANIMATION)){
      // if文の値が0。つまりアニメの許可はされていない!
      llRequestPermissions(avid, PERMISSION_TRIGGER_ANIMATION);
    }
    else{
      // if文の値が0以外。アニメの許可はされているのでアニメ発動!
      llStartAnimation("pitching");
    }
  }
  run_time_permissions(integer perm){
    if(perm & PERMISSION_TRIGGER_ANIMATION){
      // if文の値が0以外。アニメの許可はされているのでアニメ発動!
      llStartAnimation("pitching");
    }
  }
}
こんな感じで「Wearするとアニメーションが発動する」というスクリプトができあがります。
ま、実際はもっと細かなテクニック的なところだとかなんとかでいくつか手を加える必要はあるのですが、いちおうこれはこれで動きます。
 
あともうひとつ、余計なお節介を付け加えておきます。
1: default{
2:   attach(key avid){
3:     integer perm = llGetPermissions();
4:     if(!(perm & PERMISSION_TRIGGER_ANIMATION)){
5:       // if文の値が0。つまりアニメの許可はされていない!
6:       llRequestPermissions(avid, PERMISSION_TRIGGER_ANIMATION);
7:     }
8:     else{
9:       // if文の値が0以外。アニメの許可はされているのでアニメ発動!
10:       llStartAnimation("pitching");
11:     }
12:   }
13:   run_time_permissions(integer perm){
14:     if(perm & PERMISSION_TRIGGER_ANIMATION){
15:       // if文の値が0以外。アニメの許可はされているのでアニメ発動!
16:       llStartAnimation("pitching");
17:     }
18:   }
19: }
9行目10行目と、15行目16行目はまったく同じことをしています。
こんなふうに全く同じ処理をするのに別々のところに書いてあると、ここに手を加える時に両方ともやらないといけなくなります。
これは面倒ですね。
そんな時に、functionの定義です。
functionの存在意義とか使い方はこれに限らず他にもありますが、このように同じ処理を1つにまとめる(=サブル-チン的な使い方)も立派なfunction定義の理由です。
integer Animation()
{
  // if文の値が0以外。アニメの許可はされているのでアニメ発動!
  llStartAnimation("pitching");
  return TRUE;
}
default{
  attach(key avid){
    integer perm = llGetPermissions();
    if(!(perm & PERMISSION_TRIGGER_ANIMATION)){
      // if文の値が0。つまりアニメの許可はされていない!
      llRequestPermissions(avid, PERMISSION_TRIGGER_ANIMATION);
    }
    else{
      Animation();
    }
  }
  run_time_permissions(integer perm){
    if(perm & PERMISSION_TRIGGER_ANIMATION){
      Animation();
    }
  }
}
学習