HDS#17 MessageListener①:登録と削除

こんにちは、開発担当の杉原です。

 

暑い日が続きますがいかがお過ごしでしょうか。

私は冷房の効いた部屋で寝てた結果体調を崩すという体たらくです。

皆さんは風邪や熱中症にならないよう、気を付けてくださいね。

 

さて、今週から【How to Demo3D Scripting】を再開します。

まずはMessageListnerについて、2~3週にわたってお送りしたいと思います。

まずはMessageListenerとは何か、というお話から始めます。

 

たとえばAとB2つのVisualがDemo3Dモデル上に存在するとします。

Visual Aでは搬送後に業務処理が行われるのですが、Visual Bはその処理が終わったことを知りたいとします。

このときVisual AではOnProcessCompleteイベントが発生するのですが、これはあくまでVisual Aの中での処理であって、Visual Bはそのイベント発生を知ることができません。

こういった状況でVisual BがVisual AのOnProcessCompleteイベントの発生を知るための仕組みがMessageListenerです。

Visual AがMessageListenersというプロパティを持っており(※)、Visual Bがそこへ自身を登録することによって、Visual Aはイベントが発生したときにVisual Bに対してそれを通知するようになります。

(※厳密には、何も登録していない状態だとMessageListenersというプロパティは存在しないようです)

 

ではどのようにMessageListenerを登録するのかというのが以下のコードになります。

(ListeningToというVisual参照のプロパティで、Visual Aを参照しているものとします)

function Box1_OnReset( sender : Demo3D.Visuals.BoxVisual )
{
    var target : Visual = sender.ListeningTo;
        
    target.AddMessageListener(sender);
}
[Auto] CustomPropertyValue<VisualReference> ListeningTo;
    
[Auto] void OnReset(Visual sender) {
    Visual target = this.ListeningTo.Value.Visual;
    target.AddMessageListener(sender);
}

Visual AのAddMessageListenerメソッドを、自身を引数として呼び出す。それだけです。

このとき、注意点というほどのものではありませんが、AddMessageListenerメソッドはエディタのインテリセンス(ポップアップで表示されるプロパティやメソッドの一覧)には表示されません。しかし、メソッドはちゃんと存在しますので、インテリセンスによる補完に頼らず、きちんと「AddMessageListener」とコードが書けていれば動作しますのでご安心ください。

 

さてこのMessageListenerですが、一度登録するとリセットしても登録は解除されずに残り続けます。

ということは、上記のサンプルコードのようにOnResetイベントで都度登録する必要もないというわけですね。

じゃあどんなタイミングで登録するのがベストかというと、ListeningToプロパティの値が更新されたときになります。

これを実装すると以下のようになります。

function Box1_OnListeningToUpdated( sender : Visual, value : VisualReference, oldValue : VisualReference )
{
    if (value != null) {
        value.AddMessageListener(sender);
    }
}
[Auto] CustomPropertyValue<VisualReference> ListeningTo;
    
[Auto] void OnListeningToUpdated(Visual sender, VisualReference value, VisualReference oldValue)
{
    if (!value.IsNull)
    {
        value.Visual.AddMessageListener(sender);
    }
}

このようにListeningToプロパティが更新されたイベントであるOnListeningToUpdatedイベントで処理を行えばいいわけです。

 

しかしここで1つ問題があります。

ListeningToプロパティで参照するVisualが変更がされたとき、新しい参照先のMessageListenersへの登録はされるものの、前の参照先のMessageListenersにも登録されたままになっています。

このままでは、前の参照先で発生するイベントを引き続き受け取り続けてしまいます。

そこで、以下のようにしてMessageLisntersへの登録を削除しておく必要があります。

function Box1_OnListeningToUpdated( sender : Visual, value : VisualReference, oldValue : VisualReference )
{
    if (value != null) {
        value.AddMessageListener(sender);
    }
    if (oldValue != null) {
        oldValue.RemoveMessageListener(sender);
    }
}
[Auto] CustomPropertyValue<VisualReference> ListeningTo;
    
[Auto] void OnListeningToUpdated(Visual sender, VisualReference value, VisualReference oldValue)
{
    if (!value.IsNull)
    {
        value.Visual.AddMessageListener(sender);
    }
    if (!oldValue.IsNull)
    {
        oldValue.Visual.RemoveMessageListener(sender);
    }
}

削除するのに使うのはRemoveMessageListenerメソッドです。

前の参照先もイベントの引数として取得できますので、その値に対してRemoveMessageListenerメソッドを呼び出して登録を削除します。

これによって、イベントの取得先を切り替えることが可能になります。

 

さて、こうしてMessageListenerへの登録を行うことで、Visual BはVisual Aのイベントを知ることができるようになるわけです。ではどうやってイベントの通知を受け取るのか、というところは次回ご説明したいと思います。


 

次回の【How to Demo3D Scripting】は、「MessageListener②:検知」です。

更新は7/26(木)です。お楽しみに。