Chapter13:
タイムラインを使うオブジェクトの書き方

Max の Timeline オブジェクトは、最も基本的なレベルで、あらかじめ決められた時刻にメッセージを送信するシステムです。タイムラインは、イベントの編集ウィンドウと、多くの補助的なオブジェクトからできていますが、この補助的オブジェクトはパッチャーとウィンドウ内のイベントのコミュニケーションを可能にしています。

エクスターナルオブジェクトによって Max の Timeline オブジェクトの可能性を広げることができますが、これにはいくつかの方法があります。第1に、パッチャー内にあって、タイムラインアクションとして使用されるオブジェクトを書くことができます。エクスターナルオブジェクト tiCmd はその例ですが、そのソースは SDK の中で提供されています。このオブジェクトは自分自身をTimeline に「登録」し、それによってタイムライントラックにあるイベントが保持しているデータを受け取るようになります。その後、そのデータをアウトレットから他の Max オブジェクトに渡します。

第2の可能性は、thisTimeline や thisTrack のような、タイムラインをコントロールするオブジェクトを書くことです。これは、オブジェクトが作られたときに、特定のシンボルにバインドされたオブジェクトの検索だけを行ないます。そして、このオブジェクトにメッセージを送ってコントロールします。第3の可能性は、それ自身がアクションであるようなエクスターナルを書くことです。これは、tiCmd のようなオブジェクトを書くことと似ていますが、タイムラインウィンドウの中でアイコンを表示するという余分なステップが必要になります。そして、オブションとして、ユーザがこのアイコンをダブルクリックした場合に、一種のコンフィギュレーションウィンドウ、あるいはダイアログが必要になります。タイムラインとのインターフェイスを持つオブジェクトを作る上で必要となるすべての作業で注意すべき重要な点はこのセクションで説明していますが、これらすべての機能は既存のノーマルオブジェクトに追加することができます。 オブジェクトがタイムラインのコンテキストで使われていない場合には、オブジェクトのそれまで通りの機能を持ち、タイムラインインターフェイスを無効にするようなオブジェクトを書くことができます。

次の章では タイムラインのエディタオブジェクトを描いていくプロセスを述べます。エディタは Timeline の世界に特化され、パッチャーウィンドウ内のユーザインターフェイスオブジェクトの機能を併せ持つことはできません。しかし、エディタが動作する方法は、パッチャーのためにユーザインターフェイスオブジェクトを書いたことのある方にとっては馴染みやすいものでしょう。

レジストレーション(登録)

Timeline へのインターフェイスを持つオブジェクトを書くためのキーとなる概念は、レジストレーション(登録)です。これは、あなたのオブジェクトがあるシンボルをメッセージとして受け入れることを告知するプロセスです。1つ、またはそれ以上のメッセージを登録することによって、Timelineは登録されたこれらのメッセージだけをあなたのオブジェクトに送るイベントを作るように、ユーザを誘導することができるようになります。レジストレーションはあなたのオブジェクト生成関数で message_patcherRegister を使うことによって実行されます(あなたのオブジェクトが、アクションとして直接ロードされる場合は、message_register を使います。これは後述します)。あなたは複数のメッセージを登録することができます。オブジェクトの free 関数の中では、すでに登録した全てのメッセージについて、 message_patcherUnregister を使って登録を抹消しなければなりません。これによって、あなたのオブジェクトは、メッセージを送る可能性を持つすべてのタイムラインイベントから切り離されます。

登録されるメッセージは2つの重要な構成要素を持っています。第1はメッセージの名前で、これによってイベントが送り返してくるシンボルが決定されます。これはどんなシンボルでも可能で、コマンドやパラメータが記述されています。 tiCmd オブジェクトでは、メッセージ名がアーギュメントとして渡されます。第2の重要な構成要素は、メッセージのデータ型です。これもまたシンボルですが、タイムラインウィンドウの中で、メッセージを保持しているイベントを表示するために使うことができるエディタの種類を決定します。これはまた、タイムラインの中のイベントの左端を時間が通過した時にあなたのオブジェクトが受け取るメッセージへのアーギュメントを決定します。Timeline オブジェクトには、いくつかの標準のエディタがありますが、同様に若干のエクスターナルオブジェクトによるエディタもあります。標準のメッセージボックスは一般的なデータ型のメッセージを編集します。そして、Timeline 版のナンバーボックスは int および float データ型を編集します。エクスターナルエディタである etableefunc は int データ型を、edetonate は list データ型を編集します。

例として、メッセージのデータ型が int であるようなオブジェクトを作る場合、標準の環境設定であると仮定すると、ユーザはイベントを作成するために、intefunc、または etable のいずれかのエディタを選択することができます。メッセージとデータ型の違いを理解しておくことは重要です。データ型はあなたが受け取るメッセージのフォーマットを決定しません。タイムラインからあなたのオブジェクトへの全てのメッセージは、関数 typedmess によって送信されます。この関数は、あなたが addmess 関数に提供したアーギュメントリストに忠実です。int データ型のためのエディタは、常に、引数として1つの整数を持ったメッセージを送ることが確かなので、他のデータ型はあなた自身の規則によって定義することができます。

メッセージ登録での最後のオプションは、メッセージにレシーバ名を与えることです。movie オブジェクトはmovie データ型の start メッセージを登録する際にこれを行います。

エクスターナルオブジェクトのメッセージのそれ以外の仕様と同じように、登録したシンボルに対してバインドされたメソッドを書くか、何かのメソッドを提供する必要があります。登録済みの、データ型が int を伴うメッセージ foo がある場合、それに伴ったメソッドを次のように書くことができます。

void myobject_foo (myObject *x, long n);

…そして、初期化の際にそれを次のようにバインドします。

addmess(myobject_foo, "foo", A_LONG, 0);

複数のメッセージアーギュメントによる、それ以外のデータ型では、多くの場合 A_GIMME 型が使われます。

eventEnd

     
  eventEnd メッセージは、イベントを表す矩形領域の後端を時間が通過したときに、メッセージエディタによって送られます。
     
バインディング
     
  addmess (myobject_eventEnd, "eventEnd", A_CANT, 0);
   
宣言
   
  void myobject_eventEnd (myObject *x, t_symbol *message);
     
  message 時間がこのイベント長方形領域の先端を通過した時に、同じメッセージがメッセージエディタによって送られます。
     
 

この メッセージエディタによって送られるeventEnd メッセージと、タイムラインがエディタに送る eventEnd メッセージを混同しないようにして下さい。。メッセージエディタの eventEnd メッセージは実際にタイムラインからの eventEnd メッセージを受け取った際に、それに応答するものです。


message_patcherRegister

     
  特定のメッセージとデータ型に対してオブジェクトを登録する場合に、message_patcherRegister を使います。
     
 

void message_patcherRegister (t_symbol *message, t_symbol *dataType, t_object *theObject, t_symbol* objectName, t_patcher *p);

     
  messsage あなたのオブジェクトが受け取りたいメッセージ。ユーザがタイムライントラックに新しいイベントを作った際に、ポップアップメニューに表示されます。
  dataType 標準のメッセージデータ型: int、 float、または一般的なメッセージ。これによって、タイムラインウィンドウに表示される、あなたのオブジェクトにデータを送ることが可能なエディタが決定されます。
  theObject あなたのオブジェクトへのポインタ, またはこのメッセージのレシーバ
  objectName あなたのオブジェクトが名前を持っていなければ 0L を渡します。そうでない場合、シンボルとしてあなたのオブジェクトの名前を渡します。タイムラインエディタはこの名前を受け取りますが、名前を送り返すためには特に明記しなければなりません。
  p あなたのオブジェクトの親パッチャー。これは、インスタンス生成関数でシンボル #P にバインドされているものです。このパッチャーの値は、あなたのオブジェクトに保存しておかなければなりません。あなたのオブジェクトが解放される際、メッセージの登録を抹消する場合にこの値が必要になります。
     
 

この関数は、タイムラインアクションとして使用するパッチャー内で作られるオブジェクトのために、タイムラインからオブジェクトへ送ることができるメッセージを登録します。これは通常、オブジェクトのインスタンス生成関数から呼び出されます。パッチャー p が タイムラインに接続されていない場合、 message_patcherRegister は何も行いません。

これは、message_patcherRegister を使って。データ型が int であるメッセージ foo の登録を行っている例です。

message_patcherRegister(gensym("foo"), gensym("int"), myObject, 0L, myObject->m_patcher = gensym("#P")->s_thing);


message_patcherUnregister

     
  message_patcherRegister によって既に登録されているオブジェクトの登録を抹消する場合に、 message_patcherUnregister を使います。
     
 

void message_patcherUnregister (t_symbol *message, t_symbol *dataType, t_object *theObject, t_symbol *objectName, t_patcher *p);

     
  messsage あなたのオブジェクトが登録したメッセージ
  dataType 標準のメッセージデータ型: int, float, または一般的なメッセージ.
  theObject あなたのオブジェクトへのポインタ, またはこのメッセージのレシーバ.
  objectName message_patcherRegister から渡された引数 objectName
  p インスタンス生成関数でシンボル #P にバインドされたあなたのオブジェクトの親パッチャー。
     
 

この関数は、既に message_patcherRegister に渡したものと同じ引数を期待します。この関数は、パッチャー p に連結されたトラックからオブジェクト theObject に送られるメッセージ message のデータ型 dataType への全ての参照を取り除きます。これによって、タイムラインが動作する際に、このメッセージを送信しないようになります。message_patcherRegister の呼出しを行った場合には、その各々に対して message_patcherUnregister を呼び出さなければなりません。パッチャー p が タイムラインに接続されていない場合、この関数は何も行いません。


アクションエクスターナルの書き方

タイムラインのユーザは、アクションとして使うパッチャーを読み込む代わりに、エクスターナルオブジェクトを tiAction フォルダに置き、それを Track メニューから選択することができます。このようなオブジェクトは通常のパッチャーでオブジェクトとして使用することも可能です。別の考え方をすれば、既存のエクスターナルオブジェクトにアクションの機能を追加することが可能であるということです。アクションエクスターナルを書くために追加する手段は比較的シンプルです。一般的なコンセプトは、既に述べた、タイムライン互換のエクスターナルオブジェクトと同様なものです。それは、addmess によってシンボルにバインドされたメソッドを書き、そのシンボルを タイムラインに登録するというものです。

追加するステップの最初は、あなたのオブジェクト生成関数で、シンボル #A にバインドされているものがあるかどうかを確認することです。存在した場合、それは、あなたのエクスターナルオブジェクトがアクションとなるタイムライントラックへのポインタになります。この値を関数 message_register (パッチャーを介さないアクションのためにある、 message_patcherRegister と類似した関数)に渡す必要があります。

次に、actionIcon メッセージに応答して、タイムラインウィンドウにあなたのアクションのためのアイコンを表示するするメソッドを実装しなければなりません。

actionIcon

     
  actionIcon メッセージは、タイムラインがあなたのアクションを表すアイコンを描画するよう要請するものです。
     
バインディング
     
  addmess (myobject_actionIcon, "actionIcon", A_CANT, 0);
   
宣言
   
  void myobject_actionIcon (myObject *x, Rect *drawHere);
     
  drawHere この 16x16 の正方形領域にアイコン(のようなものを何か)描画します。

message_register

     
  アクションオブジェクトを登録するために、message_register を使います。
     
 

void message_register (t_symbol *message, t_symbol *dataType, t_object *theObject, t_symbol *objectName, void *track);

     
  messsage あなたのオブジェクトが受け取りたいメッセージ。これは、ユーザが タイムライントラックで新しいイベントを作る時に、ポップアップメニューに現れます。
  dataType 標準のメッセージデータ型: int、 float、 または一般的なメッセージ。これによって、タイムラインウィンドウに表示される、あなたのオブジェクトにデータを送ることが可能なエディタが決定されます。
  theObject あなたのオブジェクトへのポインタ, またはこのメッセージのレシーバ
  objectName あなたのオブジェクトが名前を持っていなければ 0L を渡します。そうでない場合、シンボルとしてあなたのオブジェクトの名前を渡します。タイムラインエディタはこの名前を受け取りますが、名前を送り返すためには特に明記しなければなりません。
  track あなたのオブジェクトの親トラック。インスタンス生成関数の中で、シンボル #A にバインドされているものです。この値は、あなたのオブジェクトに保存されなければなりません。その理由は、あなたのオブジェクトが解放されるときに、メッセージの登録を抹消するために必要になるからです。#A にバインドされた値が0の場合、messege_register を呼び出してはいけません。
     
 

この関数は、アクションであるオブジェクトのインスタンスのためのメッセージを登録します。


message_unregister

     
  すでに message_register によって登録されているオブジェクトの登録を抹消する場合に、 message_unregister を使います。
     
 

void message_unregister (t_symbol *message,t_symbol *dataType, t_object *theObject,
t_symbol *objectName, void *track);

     
  messsage あなたのオブジェクトが登録したメッセージ.
  dataType 標準のメッセージデータ型: int、 float、 または一般的なメッセージ.
  theObject あなたのオブジェクトへのポインタ, またはこのメッセージのレシーバ.
  objectName message_register から渡された引数 objectName.
  track あなたのオブジェクトの親トラック。これは、インスタンス生成関数でシンボル #A にバインドされているものです。
     
 

この関数は、すでに message_register によって登録されている全てのメッセージに対して、インスタンスの free 関数で呼び出されなければなりません。