2007年05月13日
ノートカードを読むモジュール(1)
notecardReadModule links

ノートカード(外部テキスト)の内容を読み込んでくれるモジュールを作りました。
ノートカードを読み込むサンプルはたくさんあるものの
けっこうややこしい処理だったので、
かなり前にモジュール(もどき)として作ってあったのですが
正式なモジュールとして整理しなおしたので公開します。
NotecardReaderModuleという名前です。
しかしながらモジュール自体の使い方がややこしいため
ややこしさの回避にはなりませんでした...。
自分が作っているモジュールの方式に慣れてしまえば
モジュールとの命令送信、イベント受信というやり取りで
一貫したノートカード読み込みができ、ノートカードを読み込むロジックを
組みなおす必要はなくなるので
複雑な物を作る際はモジュールを使う意味もあると思います。

動作サンプル用にモジュールはこのノートの形のプリムに貼り付けてみました。
(ノートの見た目である必要は全くありません。)

ノートカード(外部テキスト)の内容を読み込んでくれるモジュールを作りました。
ノートカードを読み込むサンプルはたくさんあるものの
けっこうややこしい処理だったので、
かなり前にモジュール(もどき)として作ってあったのですが
正式なモジュールとして整理しなおしたので公開します。
NotecardReaderModuleという名前です。
しかしながらモジュール自体の使い方がややこしいため
ややこしさの回避にはなりませんでした...。
自分が作っているモジュールの方式に慣れてしまえば
モジュールとの命令送信、イベント受信というやり取りで
一貫したノートカード読み込みができ、ノートカードを読み込むロジックを
組みなおす必要はなくなるので
複雑な物を作る際はモジュールを使う意味もあると思います。

動作サンプル用にモジュールはこのノートの形のプリムに貼り付けてみました。
(ノートの見た目である必要は全くありません。)

プリムにはこのようにノートカード、NotecardReaderModule本体、
それを利用するサンプルscriptが仕込まれています。

ノートカードの中にはこのような文章が書かれています。
(SL公式ページよりコピペ 日本語部分はテストのため追記)
モジュール利用サンプルコードはこのようになります。
プリムにタッチするとノートカードを読み込むようにしてみました。
//NotecardReader Sample
integer IsEvent(string s,string ev){
return (llSubStringIndex(s+" ",ev)==0);
}
string dataSeparator = "|||";
ReadNotecard(){
string AutoRead = "TRUE";//"TRUE" or "FALSE"
llMessageLinked(LINK_THIS,0,"harayoki.notecardRead "+dataSeparator+" "+AutoRead,NULL_KEY);
}
OnNotecardRead(list l){
integer len = llGetListLength(l);
integer i=0;
for(i=0;i<len;i++){
llOwnerSay("line "+(string)i+" : '"+llList2String(l,i)+"'");
}
}
default{
state_entry(){
}
touch_start(integer num){
ReadNotecard();
}
link_message(integer sender,integer num,string str,key id){
string noteCardReadEvent = "harayoki.event.notecardRead";
if(IsEvent(str,noteCardReadEvent)) OnNotecardRead(llParseString2List(llGetSubString(str,llStringLength(noteCardReadEvent)+1,-1),[dataSeparator],[]));
}
}
ちょい長く見えますが、ノートカードの読み込み自体は数行ですんでおり、
dataserverイベントの記述も無い事に注目してください。
使う際のポイントをかいつまんで説明します。
◆下準備
string dataSeparator = "|||";
dataSeparatorはモジュールの内部処理において
配列の区切りとして使う文字列です。
とにかく、ノートカードの文章内に1つも含まれていない文字列であれば
何でもいいので適当に設定しておいて下さい。
長い文字でも平気です。日本語はダメです。
◆ノートカードを読み込む命令
string AutoRead = "TRUE";//"TRUE" or "FALSE"この2行です。
llMessageLinked(LINK_THIS,0
,"harayoki.notecardRead "+dataSeparator+" "+AutoRead,NULL_KEY);
このままコピペしてください。
AutoReadの値を"TRUE"にするとノートカードの内容が書き換わった際
(Contentの内容が変化した際)自動的にノートカードを読み込みなおします。
1回読み込めばよい場合はAutoReadの値を"FALSE"など"TRUE"以外に設定してください。
◆ノートカードを読み込こまれ終わった時
このサンプルコードではOnNotecardRead関数にノートカードの内容がリストで渡されるようになっています。
実際にモジュール使用の際もサンプルコードを生かし、
このままの形で使うことをお勧めします。
ややこしい部分も解説すると、
string noteCardReadEvent = "harayoki.event.notecardRead";
if(IsEvent(str,noteCardReadEvent)) OnNotecardRead(
llParseString2List(llGetSubString(str,llStringLength(noteCardReadEvent)+1,-1)
,[dataSeparator],[]));
ノートカードが読み込み終わるとlink_message経由でノートカードの内容が引数strに含まれて渡されます。
linkMessageには他モジュールなどからのメッセージも渡ってきますので、まずIsEvent関数で、
これがノートカード読み込み完了の通知なのかどうか調べます。
これは他モジュールを利用する際にも行う共通の処理です。
ノートカードの内容はstrの中に各行がdataSeparatorで区切られた文字列となって渡されます。
そのままでは使いづらいのでこれを配列に変換しているのが
そのあとのややこしい処理です。
意味がわからなくともこのままコピペしてしまえば良いです。
strの頭部分にはノートカードが読み込まれたよという合図である"harayoki.event.notecardRead"+半角スペースという文字列も含まれるのでllGetSubString(str,llStringLength(NOTECARD_EVENT)+1,-1)
でそこを取り除き、それをllParseString2Listを用いて配列に変換しています。
このサンプルscriptを実行し、
プリムをクリックすると↓このように表示されました。

正しく1行ずつチャットで発言されています。
ちなみに、日本語部分は無いことになってしまってますね。
最後の"!"だけ表示されています。
日本語対応したらこういう部分も直るのでしょうか?
という事でモジュールを利用する際、ノートカード内に日本語は記述しないで下さい。
モジュールのソースコードは次のエントリーで公開します。
モジュール考察
どのモジュールを利用する場合でも
引数の分解は本当にややこしいのですが、
ほぼ共通な方法で処理できるのでコピペして使いつつ慣れてしまってください。
linkMessageで配列をやり取りする事ができれば、このややこしさは
回避できるのですが...それができないので
モジュール側で配列をいったん文字列に直してmessage送信
モジュール利用側では受け取った文字列を配列に変換、
というややこしいステップを踏んでいます。
Posted by harayoki at 21:37│Comments(0)
│ノートカード読込