Second Lifeで気に入ったアイテムの記録です あ、ウソです。スクリプトとか他のことも書いてます

2009/05/02

shadow test(snapshot)

やあ、影だ影だとエロ写真を撮っていたり
別にステレオグラムなエロ写真を撮ったわけではないです。
なんかいろいろやってるうちに、なんか影が変わったりしたので
比較写真です。

これ影で見ると左の方が荒いです。
Flickrのオリジナルサイズで見ないとわからないくらいです。
ただ、これ画面ではもっとヒドイのです。

shadow test(print screen)

これは一目でわかりますよね。
上の方が粗いです。
これ撮影時間もほとんど一緒で、
設定は完全に同じです。















AVにマウスのカーソルが乗ってるかどうかで、影が変わるようです。
注目すべきオブジェクトはコレだ!みたいな判断になってるんでしょうか。
確かに、常時細かい描画してたら死ねますよね。

ということで、こんなこともあったよーという話でした。
影が思ったよりもキレイにでてるので、びっくりしました。

ちなみに、Helpのとこのやつは、こんな感じです。

Shadow Viewer 1.23.0 (1) Apr 1 2009 15:44:35 (Cool Viewer)
Release Notes

Built with MSVC version 1400

CPU: Intel Core 2 Series Processor (2666 MHz)
Memory: 3583 MB
OS Version: Microsoft Windows XP Service Pack 3 (Build 2600)
Graphics Card Vendor: NVIDIA Corporation
Graphics Card: GeForce 8800 GTS/PCI/SSE2
OpenGL Version: 3.0.0

Link系の関数をもっと使ってみるの4

さて、これでルートのスクリプトだけで
ある程度のことができるようになりました。
これで最後です。

では、こういう処理と、llMessageLinkedを使った処理
どっちがいいのかという話。

まず、長々と書いてきた、ルートからの操作の方を考えてみます。

1つのスクリプトにすることで無駄なメモリを減らせます。
※スクリプトを減らすことで、
 コーディング時の注意を一箇所に向けられるというおまけもあります

また、llMessageLinkedの情報送信はprimを指定して行います(リンク番号やLINK_SET等)。
スクリプト指定ではありません。
そのため、ルートに複数のスクリプトがあれば、
子primからルートに情報を送った時に
全てのスクリプトのlink_messageイベントが発生します。
(link_messageがなければ問題ナシ)
これは意外とイラっとさせられます。

一方、llMessageLinkedの使用にも、変えがたい魅力もあります。
たとえば、タッチで処理を行った時に、その処理が少し時間がかかるとします。
その場合、その処理が終わるまで、スクリプト全体が無反応になります。
llMessageLinkedを使って複数のスクリプトを並行に動かせば
これは軽減することも可能です。

と、このように「どうしたいか」によって
処理の仕方を変える必要があります。

"ボタン→スクリプトいれておこう"ではなく
「どうしたら、もっとコンパクトになるかな」とか考えることは、
ある種、パズルのような楽しさがあります。
楽しいだけでなく、コンパクトになるなら、
使う人や周りの人にとってもお得です。

今回の投稿は、どうせスクリプトを書くなら、
その選択肢の幅が広がればいいなというのが動機でした。

LSLについては、みんな手探りでやっている状態です。
こんなやり方あるよーとか、いろいろ出し合って腕を磨いていきませんか

※今回のコード部分には、これを使ってみました
http://lsl-users.jp/codehighlight/

Link系の関数をもっと使ってみるの3

さて、これまで、タッチ→処理ということでしたが
その処理部分で何ができるかも、少し考えてみます。

ルートから子を操作する関数は今のところ以下の通りです。
llSetLinkAlpha
llSetLinkColor
llSetLinkTexture
llSetLinkPrimitiveParams
※漏れてたら教えてください

まあ、llSetLinkPrimitiveParamsがあるので
かなりのことができます。
ただし、Delayも考えると、単純にllSetLinkPrimitiveParamsだけとはなりませんが。

※蛇足ですが、jiraにはllSetLinkTextを求める声もでています。
"llSetLinkText or a FLOATING_TEXT option for llSetLinkPrimitiveParams"
http://jira.secondlife.com/browse/SVC-2367

でも、お気づきの通り、ルートから子primの情報を取得するための
Get系がありません。これはセキュリティ等が考慮されているのかもしれません。

むりやり、なにか情報をとろうとするとllGetObjectDetailsなんかも
有効なケースもあります。

default
{
state_entry()
{
integer i_lnkno = llGetNumberOfPrims();
list l_detail = [];
for (;i_lnkno>=2;--i_lnkno){
l_detail = llGetObjectDetails(llGetLinkKey(i_lnkno)
,[OBJECT_NAME
,OBJECT_DESC
,OBJECT_POS
,OBJECT_ROT
,OBJECT_VELOCITY
,OBJECT_OWNER
,OBJECT_GROUP
,OBJECT_CREATOR]);
llOwnerSay((string)i_lnkno+":"+llList2CSV(l_detail));
}
}
}

と、まあこんな感じで、あまり有効なものはとれません。
※というか、この部分は半分ネタとしてみてもらってもいいです

こんな時はどうするかってことですが、
初期化時に、ルートから各primの設定を行い
実行中にその状態を更新していくことが考えられます。

処理:ボタンAを押すたびにボタンの色が赤と黒に交互に変わる

【初期化】
ボタンAを黒くする
  →管理用変数に黒をセット
【実行】
ボタンAが押される
  →管理用変数が黒なら赤くする
    →管理用変数を赤に更新
  →管理用変数が赤なら黒くする
    →管理用変数を黒に更新

ちょっとめんどくさそうですが
子prim内で処理する場合でも、llGetColorなどで
いまの色を取得して処理するのではなく
なんらかのフラグで処理しているはずです。
あまり変わりません。

こんなふうにルートから子primの操作も
制限があるとはいえ、工夫次第で可能ですよね。

4に続く

Link系の関数をもっと使ってみるの2

さて、この名前とリンク番号ですが、
この対応は、リンク順を変えた時しか変わりません。
※当たり前のようですが、AVが座った場合を考えると
 よく考えられているなと思います。


ということは、先に名前からリンク番号を取得しておいて
タッチした時には、リンク番号だけで判断すればいいのではないでしょうか。

では、スクリプトリセット時にprim名からリンク番号を取得しておいて
それを使って分岐する例です。

integer gl_i_primA = -1;
integer gl_i_primB = -1;

integer f_init()
{
gl_i_primA = gl_i_primB = -1;
integer i_lnkno = llGetNumberOfPrims();
string s_primnm = "";
for (;i_lnkno>=2;--i_lnkno){
s_primnm = llToUpper(llGetLinkName(i_lnkno));
if (s_primnm=="A"){
gl_i_primA = i_lnkno;
}else if (s_primnm=="B"){
gl_i_primB = i_lnkno;
}
}
if(gl_i_primA<0)
return FALSE;
if(gl_i_primB<0)
return FALSE;
return TRUE;
}

default
{
state_entry()
{
if(f_init()==FALSE)
llOwnerSay("設定エラー");
}
touch_start(integer total_number)
{
integer i_lnkno = llDetectedLinkNumber(0);
if(i_lnkno==gl_i_primA){
llOwnerSay("A");
}else if(i_lnkno==gl_i_primB){
llOwnerSay("B");
}else{
llOwnerSay("ELSE");
}
}
}


一応、求める名前が全てない場合は、エラーとするようにしています。
この処理にはいくつか問題があるかもしれませんが
基本の考え方は、こんなふうになると思います。
※no modアイテムとして配布するような場合は
 これでも問題ないかもしれません。


ひとまず、これで各primにスクリプトを仕込まなくても
ルートに1つスクリプトがあれば、処理ができることがわかります。

リンクprimがいっぱいあれば、それなりに初期化に時間がかかります。
 ※リンクできる上限までリンクして、試してみてください。
初期化時の時間が気になるなら、
必要な名前のprimが出揃ったらループを中断するようにしましょう。
また、同じ名前のprimをうっかりリンクした場合などの
エラーチェックもあってもいいかもしれません。

他にも製作過程では、リンクなんてしょっちゅう変えるので
Changedイベントを設定しておくのもありでしょう。

    changed( integer change )
{
if (change & CHANGED_LINK){
if(f_init()==FALSE)
llOwnerSay("設定エラー");
//llResetScript()でもいい
}
}

※リンクを変えなくてもAVが座った時にも、このイベントは発生します。

今回の例では、integerの変数にリンク番号を格納しましたが
押されたprimに対してメッセージを返すだけならListを使うことも考えられます。

作りたい処理にあわせて、工夫してみると楽しいです。

また、touch系の関数も組み合わせると
タッチされた子primの面や位置なども取得できます。

3に続く

Link系の関数をもっと使ってみるの1

最近、見たり聞いたり買ったりするオブジェクトが
子primにみっしりとスクリプトが入っていることが多く、
これは意識的にしてるのかなという疑問がおこりました。

ということで、4回にわけて、スクリプトをまとめることについて書いてみます。
わりと一般的なことしか書いていませんので、
Hack的な内容は期待しないでください。

では。


LSLのプログラムを書いていると
llMessageLinkedを使うことがあります。
というか、これナシには話が進まないほどです。

これは大きく2つの用途があります。
A)他のprimとの通信
B)他のスクリプトとの通信
(メモリ制限のため/機能をスクリプト単位で分けるためなど)

B)の場合は、自主的に選択してスクリプトを分けていますが
A)の場合は、「これしか方法がないから」という人も多いのではないでしょうか。
たとえば、ボタンがたくさんあって、それぞれに機能が違うので
各ボタンにスクリプトを仕込んで、押されたよということを
ルートprimに伝えるとかですね。

でも、条件によっては、llMessageLinkedを使わなくていい場合があります。
たとえば、単純にタッチされたprimに応じて処理を行いたい場合です。

一番単純な方法では、llDetectedLinkNumberだけを使います。
    touch_start(integer total_number)
{
llOwnerSay((string)llDetectedLinkNumber(0));
}


これで、どのprimがタッチされか区別できます。
試してみるとわかるのですが、
子primでは2~の番号
ルートprimでは、1が返ってきます。
(※リンクされていない場合、タッチすると、0が返ってきます)

さて、これでなんかできそうな気がしてきます。
ただ、この状態では、どのprimがどのリンク番号なのかぴんときません。
任意のリンク番号がつくようにリンク順を調整するなんてやってられませんし。

ということで、次にllGetLinkNameを使ってみます。
これは、指定されたリンク番号のprimの名前を返します。

    touch_start(integer total_number)
{
integer i_lnkno = llDetectedLinkNumber(0);
string s_primnm = llGetLinkName(i_lnkno);
llOwnerSay((string)i_lnkno+":"+s_primnm);
}

各primに名前をつけておくと、それをルートから取得できるわけです。
これなら、リンク順に関わらず一定の結果を得られます。
これでかなり実用的になります。

この段階でも、単純に名前で処理を分岐させることもできます。
ただ、タッチするたびに、この処理をしてから
名前で分岐するのかと考えると少し気が重くなりますよね。

2に続く