2006/9/3

イベントIDの正体  VRMスクリプト禅問答

      | Hit!
      |
   ぱくっ|
     /V\
    /◎;;;,;,,,,ヽ   何見てんだ、ゴルァ!!
 _ ム::::(,,゚Д゚)::|
ヽツ.(ノ:::::::::.:::::.:..|)
  ヾソ:::::::::::::::::.:ノ
   ` ー U'"U'

いや、釣られたんじゃないんですよ。いつか書こう、書こうと思いながら、ついつい忘れてただけなんですよ。と、見るからに嘘臭い弁明ですが、そういうことは気にせずに、はりきって参りましょう!

*     *     *

まず、イベントIDの正体についてですが、これは以下のような簡単なテストコードを走らせてみるとすぐにわかります。新しいレイアウトに、ビュワー起動の最低条件となるレール1本と編成1つを置いて、レイアウトスクリプトに以下のように記述してみてください。
[レイアウトスクリプト]
Var EventID
SetEventAfter this TEST EventID 1000

BeginFunc TEST
DrawVar EventID
SetEventAfter this TEST EventID 2000
EndFunc
上掲スクリプトは、2秒毎に(最初だけ1秒後ですが、これは後で意味を持ってきます)2秒後に起きるイベントを設定し、そこで変数EventIDの中身を表示することを繰り返すものです。さて、何が起きるでしょうか?


ログウィンドウを見ると、1...2...3...と黙々と数字が1ずつ増えていくのを見ることが出来ます。実はこれがイベントIDの正体です。より、その正体を確実に暴くために、以下のようにスクリプトを改めてみましょう。
[レイアウトスクリプト]
Var EventID
SetEventAfter this TEST EventID 1000
Var EventID2
SetEventAfter this TEST2 EventID2 2000


BeginFunc TEST
DrawVar EventID
SetEventAfter this TEST EventID 2000
EndFunc

BeginFunc TEST2
SetEventAfter this TEST2 EventID2 2000
EndFunc
太字の部分が加筆部です。似たようなイベントとメソッドの組が1つ増えましたが、増えたほうにはDrawVar命令がありません。つまり、イベントは設定し続けるけれども、何も起きないことになります。さて、ビュワーのログウィンドウにご注目。今度は1...3...5...と、数字が2ずつ増えていきます。もちろん表示されない数字はメソッドTEST2を実行するイベントを設定する際に使われたのですが、DrawVar命令がないので表示されないんですね。

もう1つ実験を。上の太字部分のスクリプトを、たとえばビュワー起動のために置いた編成のスクリプトの部分に移動させてみてください。で、ビュワーを起動する。どうなるでしょうか。実は結果は変わりません。

以上の実験から、以下のことがわかります。

・イベントIDは、SetEvent〜命令が実行されるたびにイベント変数に入ってくる数字である。
・その値は、ビュワー起動時から数えたSetEvent〜命令の実行回数に等しく、どのオブジェクトで設定されたイベントであるかは関係がない。

そして、これを噛み砕くと、要するにこういうことです。つまるところ「イベント」というのは、本来であればユーザーがループ処理を組んである事柄が起きたか否かを判断すべきであるところを、SetEvent〜命令を出した時点でVRMビュワーにお願いしてしまい、その後はユーザーのプログラムがまったく別のことをしていても、設定された出来事が発生すれば決まったメソッドを実行してくれる、という仕組みです。イベントIDは、その注文番号のようなものです。

比喩でプログラミングの話をするのは本来は好きではないのですが・・・たとえばビュワーくんという便利屋さんがいて、彼は「〜くんに会ったら・・・しろ」という注文を受けてくれるとします。で、ボクは以下の注文を出します。

・45-50sくんに会ったら(イベント)クマーと言え(メソッド)。
・mokoくんに会ったら(イベント)カリカリ笑え(メソッド)。
・caldiaくんに会ったら(イベント)またお好み焼き食うかと言え(メソッド)。

一旦注文を受けると、ボクが寝ていようが妻の相手にかかりきりになっていようが、ビュワーくんは彼らに会えば決められたことをしてくれます。

さて、ここでmokoくんからメールが来ましたと。「ビュワーくんがカリカリうるさいです、もー飽きました」みたいな。で、mokoくんへの伝言を取り消したいとします。VRMビュワーくんが人間であれば「あー、あのmokoくんの件、キャンセルな」と言えば通じるはずですが、あいにくとビュワーくんはVRMビュワーです(笑)。そういう曖昧な指示では理解してくれません。実はビュワーくんは注文を受けるたびに、注文番号を書いたメモをボクに渡してくれていました。見ると、1...2...3...と連番が振られています。しかし、これではどの番号がどの注文かがわかりません。

が、実はそこは抜かりがなくてですね。ボクはそのメモを「45-50sくんへの伝言」とか「mokoくんへの伝言」とか書いた封筒(変数)に、それぞれ入れていたワケです。それぞれに何番が入ってるかは知らないですが、とりあえず「mokoくんへの伝言」と書いておいた封筒をビュワーくんに渡し「これ、キャンセルね(KillEvent)」と言うと、晴れて注文が解除される・・・とまぁ、基本はこういう仕組みです。

ただ、実際のVRMスクリプトには厄介なことが他にもあります。まず、注文の中には1回伝言が成立すればそれっきりで自動解除されるものがあること。SetEventAfterなんかがこれに当たります。そして、最もややこしいのは、封筒(変数)には注文番号が書かれたメモを1枚しか入れることが出来ず、既にメモが入った封筒に新しいメモを入れると、先に入っていたメモが消えてしまうこと、です。
変数「KeyID」を割り当てた3つのキーイベントのうち一番下に書いた、メソッド「MtdC」を呼ぶキーイベントだけが無効になり、他の2つのキーイベントは有効のままなのです。

の理由がこれでわかりましたね。
また、同じ理由から、後でキャンセルする可能性があるイベントは、グローバル変数に保存しなければならないこと、逆に言えば、後でキャンセルしないイベントはローカル変数で受け取って捨ててしまっても構わないこと、がわかります。

*     *     *

さて。
このイベントIDというのは、システムの構造上どうしても設定しなければいけないファンダメンタルなものなのか、それとも単にKillEvent命令のために後付け的に設けられたものなのでしょうか。

同上
の疑問にお答えしておくと「唯一解ではないが、最適解の中でも最も相応しいものの1つである」ということになるでしょうか。

ミソは、イベントID自身が無味乾燥な(連番である必然性はない)数字であるのに対し、変数名はユーザーが任意に意味のある連想しやすいものを付けられる、という点です。そして、ユーザーはイベントIDの値が何番であるかを意識することなく、自分にとってわかりやすい変数名でこれを管理することが出来ます。逆に、これ以外の方法では、一旦システムに預けてしまったイベントにアクセスするのが難しいか、不可能になります。

ぶっちゃけ、別に特別な仕組みじゃないんですよ。だって、列車の切符だとか、免許証だとか、何にでもユニークな番号が振られてるでしょ。列車の予約のキャンセルにしても、免許証の更新・取り消しにしても、究極的にはそのユニークな番号でしか処理できません。が、無味乾燥な連番は人間が扱うには不便なので、別途、番号と人間に理解しやすい情報(日時、行先、氏名、住所)を紐付けるデータベースを作って処理するワケで。VRMスクリプトでは、そういうデータベースを作ることが事実上困難なので(やろうとしたら、SetEventする度に住所、氏名、使用目的なんかを入力することになる・笑)ユーザーが示した任意の変数に値を記録して、イベントの処理をVRMビュワーが専任する代わりに、その始末がユーザーに委ねられておるワケですよ、ハイ。
0

2006/9/2  19:20

投稿者:45-50s
ありがとうございます、これでわかりました。
イベントIDはあとからユーザーがアクセスするためにあるんですね。つまり、システムにしてみれば別にあっても無くても困らないってことですか。
自分ははじめワケがわからず、念のために全てのイベントにユニークな変数を割り当てたりしてたのに(笑

コメントを書く

この記事にはコメントを投稿できません




teacup.ブログ “AutoPage”
AutoPage最新お知らせ