
2008年03月17日
NumberPad
これは電卓ではありません。
ちょっと、スクリプトに数字を送るのに作ってみたんです。
関数の変数を試すのに使ってみました。
タッチして数字を入れて、↵(Enter)で数字を送りこみます。
スクリプトに入力値を渡す方法としては、チャット・ダイアログ・ノート等がありますが、
これだと画面からのタッチなのでわかりやすいと思ったんです。
SIMの状態がいいときは、そこそこの反応なんですが、
SIMが重いとタッチした後にラグがあってマウスの反応がしばらくありません。
重いって感じます。遅いときは数秒ぐらいラグがあります。
SIMのラグが手に取るようにわかるような感じです。
とても電卓には向きません。
それでも、カメラのパラメータを試すのに活躍してくれました。
SLのタッチの反応が遅いので、軽快な反応ものは作れませんね。
ちょっと、スクリプトに数字を送るのに作ってみたんです。
関数の変数を試すのに使ってみました。
タッチして数字を入れて、↵(Enter)で数字を送りこみます。
スクリプトに入力値を渡す方法としては、チャット・ダイアログ・ノート等がありますが、
これだと画面からのタッチなのでわかりやすいと思ったんです。
SIMの状態がいいときは、そこそこの反応なんですが、
SIMが重いとタッチした後にラグがあってマウスの反応がしばらくありません。
重いって感じます。遅いときは数秒ぐらいラグがあります。
SIMのラグが手に取るようにわかるような感じです。
とても電卓には向きません。
それでも、カメラのパラメータを試すのに活躍してくれました。
SLのタッチの反応が遅いので、軽快な反応ものは作れませんね。
2008年03月14日
2008年03月14日
2008年03月14日
llSensor(Repeat)からは一度に16件まで。
llSensorRepeatを使ってるんですが、一度に16件までしかデータが返ってこないので調べて見るとここに情報がありました。
http://cheesefactory.us/lslwm/TutorialRobotics.htm
自立して動くオブジェクト(ロボット)のスクリプトみたいなんですが、それにセンサーを使ってるようです。
Sensors
There are a couple of 'gotcha's' with sensors.
* Only the nearest 16 objects are detected
検知されるのは最寄の16件だけとあります。
ですが、オブジェクトのサーチで試して見たところ一度に16件のまま表示が変わらない場合と、
16件と残りと思われる数件を表示するのを交互に繰り返してチラついて見える場合もありました。
先日訳した
http://tanakaakio.slmame.com/e171230.html
なんですがちょっと訂正しました。すいません。
それでちょうど訂正したとこの記述で、
「・llSensorとllSensorRepeatはllSensorとllSensorRepeatを含むオブジェクトを検知しない。アタッチメントもそうでありセンサースクリプトがあれば装着しているエージェントを検知しない。ただし、センサースクリプトが子プリムにある場合を除く。(色の付いてるところを追加)」
とあるんですが、私が試したところ、llSensorRepeatがオブジェクト中にあってもちゃんと検知しました。
llSensorについては試してませんけど。
それにしても自立ロボットか、おもしろそうだな。
http://cheesefactory.us/lslwm/TutorialRobotics.htm
自立して動くオブジェクト(ロボット)のスクリプトみたいなんですが、それにセンサーを使ってるようです。
Sensors
There are a couple of 'gotcha's' with sensors.
* Only the nearest 16 objects are detected
検知されるのは最寄の16件だけとあります。
ですが、オブジェクトのサーチで試して見たところ一度に16件のまま表示が変わらない場合と、
16件と残りと思われる数件を表示するのを交互に繰り返してチラついて見える場合もありました。
先日訳した
http://tanakaakio.slmame.com/e171230.html
なんですがちょっと訂正しました。すいません。
それでちょうど訂正したとこの記述で、
「・llSensorとllSensorRepeatはllSensorとllSensorRepeatを含むオブジェクトを検知しない。アタッチメントもそうでありセンサースクリプトがあれば装着しているエージェントを検知しない。ただし、センサースクリプトが子プリムにある場合を除く。(色の付いてるところを追加)」
とあるんですが、私が試したところ、llSensorRepeatがオブジェクト中にあってもちゃんと検知しました。
llSensorについては試してませんけど。
それにしても自立ロボットか、おもしろそうだな。
2008年03月11日
llSensorの訳(旧LSL wiki)
http://rpgstats.com/wiki/index.php?title=LlSensorの訳です。
訂正:装着しているエージェントを
の部分を追加(2008.03.14)。
慣れないことをしてしまいました。
LSL Wikiの新しいドメインのもありますが、古いドメインの方です。
本家リンデンのWikiと新旧LSL Wiki、似たような機能のllSensorとllSensorRepeatがあり、
混乱しました。というか今でも混乱していますが。
センサーについてちょっと調べてるんですが、翻訳してますます訳が分からなくなったようなw
なんでこんな妙な仕様なんだろな。
一晩寝たら少しは頭に入ってることを期待してますけど。
llSensor
llSensor(string name, key id, integer type, float range, float arc)
range(範囲:メートル)とarc(X軸に沿った前方ベクトルのラジアン弧)の範囲内で、
指定したtype(AGENT, ACTIVE, PASSIE, および/または SCRIPTED)で、
nameとidを探すセンサースキャンを一つ実行する。
PIラジアンは全方向をサーチする。0.0rangeではスキャンは行われないので注意。
nameとidのフィルターを必要としない。
nameがnull stringなら(""のこと)、llSensor()はあらゆる名前のオブジェクトを探す。idがNULL_KEYならば、llSensor()はあらゆるidをサーチする。
rangeの上限は96mである。値が96mを超えても受け付けるが96mとして扱われる。
rangeが0.0ならスキャンは実行されないので注意。
センサースキャンを繰り返すllSensorRepeatと比較のこと。
条件にマッチしたものが見つかるとsensor eventが発生し、何も見つからないとno_sensorが発生する。
sensorのところに実例があるので参照のこと。
type(タイプ)の定数 :
内容
注釈
SCRIPTEDと他のフラグとの組み合わせ
検知範囲円錐
センサーの視覚化
注釈
・値をビット演算のOR(|)で組み合わせて複数のカテゴリーをサーチできる。
例えば、llSensor("", NULL_KEY, AGENT | ACTIVE, 25, PI)は、agentと物理オブジェクトの両方をサーチする。
・PASSIVE、ACTIVE、および/またはSCRIPTEDオブジェクトが検知された後に、
llDetectedTypeをACTIVEフラグ(物理)とPASSIVEフラグ(非物理、オブジェクトにアクティブなスクリプトがあったとしても)のチェックに使うことができる。
SCRIPTEDフラグはいつもアクティブスクリプトを単に検知、適合させるだけでのようである。よってllSensorとllDetectedTypeではPASSIVEフラグとACTIVEフラグの使い方が違うようである。
検知オブジェクトのタイプについてもっと情報があるObject Typeを参照。
・センサーは、オブジェクトの中心(center)が検知範囲円錐(下を参照)内にあるときにだけ、オブジェクトを検知する。このため特に壁のような大きなオブジェクトを避けて、センサーを探索に使うのが難しくなっている。
・センサーは他のオブジェクトの子プリムを検知するのに使用できない。
・llSensorとllSensorRepeatはllSensorとllSensorRepeatを含むオブジェクトを検知しない。アタッチメントもそうでありセンサースクリプトがあれば装着しているエージェントを検知しない。ただし、センサースクリプトが子プリムにある場合を除く。
・nameパラメータは大文字と小文字を区別し、名前の一部だけでは検知しない。例えば、オブジェクトの名前が「Object」だとすると、「object」や「Obj」ではマッチせず「Object」だけがマッチする。
・llSensorは同じsim内にあるオブジェクトだけを検知する。もし隣接のsimにあるオブジェクトを検知する必要があるならllSensorRepeatを使用する。
・SCRIPTEDを他のフラグと組み合わせたときは奇妙である。下記参照。
SCRIPTEDと他のフラグとの組み合わせ
SCRIPTEDと他のフラグとの組み合わせは、少し直感的にわかりにくい結果になる可能性がある。
・SCRIPTEDはアクティブスクリプトまたはスクリプト(アクティブであろうとなかろうと)が動いている物理オブジェクトを検知する。がある、または動いている物理オブジェクトを検知する。(20080502訂正)
・AGENT | SCRIPTEDはアクティブスクリプトまたはスクリプト(アクティブであろうとなかろうと)がある動いている物理オブジェクトを検知する。agentは検知しない!
・ACTIVE | SCRIPTEDはアクティブスクリプトまたはスクリプト(アクティブであろうとなかろうと)がある動いている物理オブジェクトを検知するが、スクリプトのない動くオブジェクトは検知しない。
・PASSIVE | SCRIPTEDはアクティブスクリプト、スクリプトのない非物理オブジェクトとスクリプト(アクティブであろうとなかろうと)のある物理オブジェクトを検知する。スクリプトのない静止している物理オブジェクトは検知しない。
検知範囲円錐(arc)
・arcがxラジアンなら、センサーはオブジェクトの前方ベクトルの周りのxラジアン内を探す(これはオブジェクトのローカルx座標、プラスの方向)、よって実際サーチの振りは2 * xラジアンであり、だからPIラジアンだとオブジェクトのまわり全てをサーチする。
・SLの表現では、球の半径で定義されたrangeとarcはそれ自身くぼんでおり、それが描くセンサーの振るエリアもくぼんだ球である。
・アタッチメントでのセンサーはアバタの向いている前面のベクトル方向を使用する。
マウスルックではどこでもアバタが見ている所であり、マウスルックでないときは何処であろうとアバタの向いている方向である。これは、アバタの頭がどっちを向いているのかということではない。
そうでないとアニメーションをアバタが行っていると、前に向かって歩いていたとしても方向が動いてしまう。
どこにオブジェクトをアタッチしているかに関係なくそうである。
センサーの視覚化
これは arc = PI / 4 でこのようにX軸の周りを45度で半径内をスキャンする:

video (MPEG, 630KB) of it rotating
arc = PI_BY_TWO (X軸の周り90度、球の半分=半球に向けた場合)である:

そして arc = PI (X軸の周り180度の場合は球となる):

Q:アタッチメントを検知するのにセンサーを使えますか?
A:いいえ。しかし、llGetAgentInfoでアバタがアタッチメントを持っているかどうか、スクリプトを使っているかどうかはわかります。いくつアタッチメントを持っているか、どこに何を装着しているかは分かりませんが。
Q:どの軸からセンサーの検知範囲円錐を始めるか指定することはできますか(オブジェクトをX軸ではなくてY軸で使わないとならないのです)?
訂正:装着しているエージェントを
の部分を追加(2008.03.14)。
慣れないことをしてしまいました。
LSL Wikiの新しいドメインのもありますが、古いドメインの方です。
本家リンデンのWikiと新旧LSL Wiki、似たような機能のllSensorとllSensorRepeatがあり、
混乱しました。というか今でも混乱していますが。
センサーについてちょっと調べてるんですが、翻訳してますます訳が分からなくなったようなw
なんでこんな妙な仕様なんだろな。
一晩寝たら少しは頭に入ってることを期待してますけど。
llSensor
llSensor(string name, key id, integer type, float range, float arc)
range(範囲:メートル)とarc(X軸に沿った前方ベクトルのラジアン弧)の範囲内で、
指定したtype(AGENT, ACTIVE, PASSIE, および/または SCRIPTED)で、
nameとidを探すセンサースキャンを一つ実行する。
PIラジアンは全方向をサーチする。0.0rangeではスキャンは行われないので注意。
nameとidのフィルターを必要としない。
nameがnull stringなら(""のこと)、llSensor()はあらゆる名前のオブジェクトを探す。idがNULL_KEYならば、llSensor()はあらゆるidをサーチする。
rangeの上限は96mである。値が96mを超えても受け付けるが96mとして扱われる。
rangeが0.0ならスキャンは実行されないので注意。
センサースキャンを繰り返すllSensorRepeatと比較のこと。
条件にマッチしたものが見つかるとsensor eventが発生し、何も見つからないとno_sensorが発生する。
sensorのところに実例があるので参照のこと。
type(タイプ)の定数 :
| 定数 | 値 | 探索 |
| AGENT | 1 | |
| ACTIVE | 2 | 動いているphysical(物理)オブジェクトまたはactive(アクティブ)な script(スクリプト)のあるオブジェクト[1] |
| PASSIVE | 4 | スクリプトがないまたはスクリプトがinactive(インアクティブ)[2]でnon-physical(非物理)または、止まっている物理オブジェクト |
| SCRIPTED | 8 | active(アクティブ)[3]なスクリプトがあるオブジェクト |
[1] Active(アクティブ): スクリプトが実行されていて今何かしている。簡単なデフォルトのスクリプトが実行中でもアクティブにはならないが、llListenのようなモニタリング命令があるスクリプトは常にアクティブである。
アクティブとはより多くのsimリソースを使用しているということである。
[2] Inactive(インアクティブ): 実行中のスクリプトがイベントを待っている状態で、いかなるモニタリング(llListenのような)もしていない。ごく僅かなsimリソースしか使われていない。
[3] Running(実行中)のスクリプトはアクティブまたはインアクティブの可能性がある。 (SL流にいえば, アクティブまたはパッシブ)。
内容
注釈
SCRIPTEDと他のフラグとの組み合わせ
検知範囲円錐
センサーの視覚化
注釈
・値をビット演算のOR(|)で組み合わせて複数のカテゴリーをサーチできる。
例えば、llSensor("", NULL_KEY, AGENT | ACTIVE, 25, PI)は、agentと物理オブジェクトの両方をサーチする。
・PASSIVE、ACTIVE、および/またはSCRIPTEDオブジェクトが検知された後に、
llDetectedTypeをACTIVEフラグ(物理)とPASSIVEフラグ(非物理、オブジェクトにアクティブなスクリプトがあったとしても)のチェックに使うことができる。
SCRIPTEDフラグはいつもアクティブスクリプトを単に検知、適合させるだけでのようである。よってllSensorとllDetectedTypeではPASSIVEフラグとACTIVEフラグの使い方が違うようである。
検知オブジェクトのタイプについてもっと情報があるObject Typeを参照。
・センサーは、オブジェクトの中心(center)が検知範囲円錐(下を参照)内にあるときにだけ、オブジェクトを検知する。このため特に壁のような大きなオブジェクトを避けて、センサーを探索に使うのが難しくなっている。
・センサーは他のオブジェクトの子プリムを検知するのに使用できない。
・llSensorとllSensorRepeatはllSensorとllSensorRepeatを含むオブジェクトを検知しない。アタッチメントもそうでありセンサースクリプトがあれば装着しているエージェントを検知しない。ただし、センサースクリプトが子プリムにある場合を除く。
・nameパラメータは大文字と小文字を区別し、名前の一部だけでは検知しない。例えば、オブジェクトの名前が「Object」だとすると、「object」や「Obj」ではマッチせず「Object」だけがマッチする。
・llSensorは同じsim内にあるオブジェクトだけを検知する。もし隣接のsimにあるオブジェクトを検知する必要があるならllSensorRepeatを使用する。
・SCRIPTEDを他のフラグと組み合わせたときは奇妙である。下記参照。
SCRIPTEDと他のフラグとの組み合わせ
SCRIPTEDと他のフラグとの組み合わせは、少し直感的にわかりにくい結果になる可能性がある。
・SCRIPTEDはアクティブスクリプトまたはスクリプト(アクティブであろうとなかろうと)
・AGENT | SCRIPTEDはアクティブスクリプトまたはスクリプト(アクティブであろうとなかろうと)がある動いている物理オブジェクトを検知する。agentは検知しない!
・ACTIVE | SCRIPTEDはアクティブスクリプトまたはスクリプト(アクティブであろうとなかろうと)がある動いている物理オブジェクトを検知するが、スクリプトのない動くオブジェクトは検知しない。
・PASSIVE | SCRIPTEDはアクティブスクリプト、スクリプトのない非物理オブジェクトとスクリプト(アクティブであろうとなかろうと)のある物理オブジェクトを検知する。スクリプトのない静止している物理オブジェクトは検知しない。
検知範囲円錐(arc)
・arcがxラジアンなら、センサーはオブジェクトの前方ベクトルの周りのxラジアン内を探す(これはオブジェクトのローカルx座標、プラスの方向)、よって実際サーチの振りは2 * xラジアンであり、だからPIラジアンだとオブジェクトのまわり全てをサーチする。
・SLの表現では、球の半径で定義されたrangeとarcはそれ自身くぼんでおり、それが描くセンサーの振るエリアもくぼんだ球である。
・アタッチメントでのセンサーはアバタの向いている前面のベクトル方向を使用する。
マウスルックではどこでもアバタが見ている所であり、マウスルックでないときは何処であろうとアバタの向いている方向である。これは、アバタの頭がどっちを向いているのかということではない。
そうでないとアニメーションをアバタが行っていると、前に向かって歩いていたとしても方向が動いてしまう。
どこにオブジェクトをアタッチしているかに関係なくそうである。
センサーの視覚化
これは arc = PI / 4 でこのようにX軸の周りを45度で半径内をスキャンする:

video (MPEG, 630KB) of it rotating
arc = PI_BY_TWO (X軸の周り90度、球の半分=半球に向けた場合)である:

そして arc = PI (X軸の周り180度の場合は球となる):

Q:アタッチメントを検知するのにセンサーを使えますか?
A:いいえ。しかし、llGetAgentInfoでアバタがアタッチメントを持っているかどうか、スクリプトを使っているかどうかはわかります。いくつアタッチメントを持っているか、どこに何を装着しているかは分かりませんが。
Q:どの軸からセンサーの検知範囲円錐を始めるか指定することはできますか(オブジェクトをX軸ではなくてY軸で使わないとならないのです)?
2008年03月08日
分割してテクスチャを貼るためのスクリプト3
タグ(名前)を付けて、テクスチャグリッドを貼るスクリプト。
すいません。
101行目訂正しました。
誤: llSetTexture(tex, ALL_SIDES);
正:llSetTexture(tex, face);
これが前回使用した数字テクスチャです。

これが前々回使用した絵柄テクスチャです。

これらを今回も使って、テクスチャグリッドに名前を付けて貼り付けてみます。
listの登録がだらだらと続きますが、それさえすめば名前だけでテクスチャグリッドを貼れます。
それはそれで面倒ですが、電卓を片手に細かい小数計算をして入力しなくてすみます。
ちょっと見難いかもしれませんが、テクスチャのライブラリのような感じでもあります。
ありがちなミスとしては、
・テクスチャを再アップしたけどスクリプトのUUIDを変えてなくてテクスチャが変わらない。
・同じ名前を登録してしまって、思ったものと違うものが表示される。
・名前に余計なスペースが入っていて、ありませんといわれる。
・各listの登録数があっていない。
・各listの数が同じように見えたが、目の錯覚で実際数えてみると数が違っていた。
・リストが長いので、コンマや括弧が分かりにくくて入れ間違え、狭いスクリプトコンソールでシンタックスエラー(構文エラー)で苦しむ。
自分だけかなこんなミスをするのは・・・
すいません。
101行目訂正しました。
誤:
正:llSetTexture(tex, face);
これが前回使用した数字テクスチャです。
string tex1 = "f4bb40ac-b9c6-1019-0b59-cffa8fb12b68";

これが前々回使用した絵柄テクスチャです。
string tex0 = "0c5fb359-7ca3-00f2-8362-a6c2f0e5e8e9";

これらを今回も使って、テクスチャグリッドに名前を付けて貼り付けてみます。
listの登録がだらだらと続きますが、それさえすめば名前だけでテクスチャグリッドを貼れます。
それはそれで面倒ですが、電卓を片手に細かい小数計算をして入力しなくてすみます。
ちょっと見難いかもしれませんが、テクスチャのライブラリのような感じでもあります。
ありがちなミスとしては、
・テクスチャを再アップしたけどスクリプトのUUIDを変えてなくてテクスチャが変わらない。
・同じ名前を登録してしまって、思ったものと違うものが表示される。
・名前に余計なスペースが入っていて、ありませんといわれる。
・各listの登録数があっていない。
・各listの数が同じように見えたが、目の錯覚で実際数えてみると数が違っていた。
・リストが長いので、コンマや括弧が分かりにくくて入れ間違え、狭いスクリプトコンソールでシンタックスエラー(構文エラー)で苦しむ。
自分だけかなこんなミスをするのは・・・
//TaggedTexGridSample.lsl
//テクスチャグリッドにタグ(名前)をつけてリストに登録し、タグでテクスチャグリッドを貼れるようにする。
//各タグのグリッドの分割数(列行)、グリッド番号とテクスチャもリストに登録する。
//テクスチャのUUIDかオブジェクトコンテンツでの名前を指定する。
//これらのサンプルテクスチャにはフルパーミッションを与えてあるので、誰でもこのテクスチャで実行できるはず。
//絵柄サンプルテクスチャ
string tex0 = "0c5fb359-7ca3-00f2-8362-a6c2f0e5e8e9";
//数字サンプルテクスチャ
string tex1 = "f4bb40ac-b9c6-1019-0b59-cffa8fb12b68";
//***グリッドのタグ(名前)。
list tag = [
//絵柄テクスチャを8(2x4)分割。
"Board" , "Ice"
,"Lily" , "Warning"
,"Ribbon" , "Whiteboard"
,"Blue" , "Celt"
//数字テクスチャを4(2x2)分割。
,"0" , "1"
,"2" , "3"
//数字テクスチャを16(4x4)分割。
,"00" , "01" , "02" , "03"
,"04" , "05" , "06" , "07"
,"08" , "09" , "10" , "11"
,"12" , "13" , "14" , "15"
];
//***各グリッドタグのテクスチャを設定する。
list tagTex = [
//絵柄テクスチャを8(2x4)分割。
tex0 , tex0
,tex0 , tex0
,tex0 , tex0
,tex0 , tex0
//数字テクスチャを4(2x2)分割。
,tex1 , tex1
,tex1 , tex1
//数字テクスチャを16(4x4)分割。
,tex1 , tex1 , tex1 , tex1
,tex1 , tex1 , tex1 , tex1
,tex1 , tex1 , tex1 , tex1
,tex1 , tex1 , tex1 , tex1
];
//***各グリッドタグの分割数と番号を設定する。<列数, 行数, グリッド番号(0から始まる)>
list tagGrid = [
//絵柄テクスチャを8(2x4)分割。
<2, 4, 0> , <2, 4, 1>
,<2, 4, 2> , <2, 4, 3>
,<2, 4, 4> , <2, 4, 5>
,<2, 4, 6> , <2, 4, 7>
//数字テクスチャを4(2x2)分割。
,<2, 2, 0> , <2, 2, 1>
,<2, 2, 2> , <2, 2, 3>
//数字テクスチャを16(4x4)分割。
,<4, 4, 0> , <4, 4, 1> , <4, 4, 2> , <4, 4, 3>
,<4, 4, 4> , <4, 4, 5> , <4, 4, 6> , <4, 4, 7>
,<4, 4, 8> , <4, 4, 9> , <4, 4, 10> , <4, 4, 11>
,<4, 4, 12> , <4, 4, 13> , <4, 4, 14> , <4, 4, 15>
];
//テクスチャグリッドのオフセットを返す。
//index:テクスチャのグリッド番号(0から始まる)。
//numOfCol:テクスチャのグリッド列数。
//numOfRow:テクスチャのグリッド行数。
vector getGridTexOffset(integer index, integer numOfCol, integer numOfRow) {
integer Col = index % numOfCol;
integer Row = index / numOfCol;
float pitchCol = 1 / (float)numOfCol;
float pitchRow = 1 / (float)numOfRow;
float offX = -0.5 + pitchCol / 2 + Col * pitchCol;
float offY = 0.5 - pitchRow / 2 - Row * pitchRow;
return < offX, offY, 0.0>;
}
//テクスチャグリッドのスケールを返す。
//numOfCol:テクスチャのグリッド列数。
//numOfRow:テクスチャのグリッド行数。
vector getGridTexScale(integer numOfCol, integer numOfRow) {
return < 1/(float)numOfCol, 1/(float)numOfRow, 0.0>;
}
//タグ名のテクスチャグリッドを指定面に貼り付ける。
//name:タグ名。
//face:貼り付ける面番号。
setTaggedGridTex(string name, integer face) {
integer pos = llListFindList(tag, [name]);
if (pos==-1) {
string s = "*** " + name + " is not found. ***";
llOwnerSay(s);
llSetText("tag=" + s, <1.0,1.0,1.0>, 1.0);
} else {
vector grid = llList2Vector(tagGrid, pos);
vector scale = getGridTexScale((integer)grid.x, (integer)grid.y);
llScaleTexture(scale.x, scale.y, face);
vector offset = getGridTexOffset((integer)grid.z, (integer)grid.x, (integer)grid.y);
llOffsetTexture(offset.x, offset.y, face);
key tex = llList2Key(tagTex, pos );
llSetTexture(tex, face);
}
}
//登録されているタグ名のテクスチャグリッドを順にすべて貼りつけていく。チェック用。
demo() {
integer i;
for (i=0; i < llGetListLength(tag) ; i++) {
string s = llList2String(tag, i);
// llOwnerSay("tag=" + s);
llSetText("tag=" + s, <1.0,1.0,1.0>, 1.0);
setTaggedGridTex(s, ALL_SIDES);
llSleep(2);
}
llSetText("", <1.0,1.0,1.0>, 1.0);
}
default {
state_entry() {
//デモ表示
demo();//
//登録されてないのでエラー表示が出る
setTaggedGridTex("foo", ALL_SIDES);
//テクスチャを実際に貼り付ける時は、この部分だけタグと面を変えて各プリムで実行する。
setTaggedGridTex("Whiteboard", ALL_SIDES);
}
}
2008年03月08日
分割してテクスチャを貼るためのスクリプト2
スクリプトの前にちょっとTipsを・・・
オブジェクトのフェイス番号をチャットウィンドウに表示する。
オブジェクトフェイスの番号をチャットウィンドウに表示するには、
テクスチャのフェイスを選択してから「ctrl+shift+alt」を押しながら「T」を押します。
テクスチャのサイズとアルファ値も出ます(どうせなら、編集ボックスに表示すればいいと思うのですが)。

テクスチャのフェイスを選択してない場合は、オブジェクトにあるフェイス番号がすべて表示されます。

分割してテクスチャを貼るためのスクリプト2
今回使用しているサンプルテクスチャです。

前回は、1つのテクスチャを8(2x4)分割して貼り付けましたが、
今回は、1つのテクスチャを4(2x2)分割と16(4x4)分割で貼ってみます。
実際には、絵が重ならないようにして配置します。
そうすれば、1枚のテクスチャでいろいろ使えます。
特にHUDなんかでこまごましたボタンがいっぱいあるときにいいかもと思います。
スクリプトの関数は変更なしで、テクスチャの指定と呼び出し方とを少し変えるだけです。
変更箇所1:テクスチャの変更。
変更箇所2: 関数の呼び出し部分。state_entryをすべて入れ替えます。
こうゆう感じになります。
オブジェクトのフェイス番号をチャットウィンドウに表示する。
オブジェクトフェイスの番号をチャットウィンドウに表示するには、
テクスチャのフェイスを選択してから「ctrl+shift+alt」を押しながら「T」を押します。
テクスチャのサイズとアルファ値も出ます(どうせなら、編集ボックスに表示すればいいと思うのですが)。

テクスチャのフェイスを選択してない場合は、オブジェクトにあるフェイス番号がすべて表示されます。

分割してテクスチャを貼るためのスクリプト2
今回使用しているサンプルテクスチャです。

前回は、1つのテクスチャを8(2x4)分割して貼り付けましたが、
今回は、1つのテクスチャを4(2x2)分割と16(4x4)分割で貼ってみます。
実際には、絵が重ならないようにして配置します。
そうすれば、1枚のテクスチャでいろいろ使えます。
特にHUDなんかでこまごましたボタンがいっぱいあるときにいいかもと思います。
スクリプトの関数は変更なしで、テクスチャの指定と呼び出し方とを少し変えるだけです。
変更箇所1:テクスチャの変更。
//テクスチャのUUIDかオブジェクトコンテンツでの名前を指定する。
//このサンプルテクスチャにはフルパーミッションを与えてあるので、誰でもこのテクスチャで実行できるはず。
string myTex = "f4bb40ac-b9c6-1019-0b59-cffa8fb12b68";
変更箇所2: 関数の呼び出し部分。state_entryをすべて入れ替えます。
state_entry() {
//繰り返したとき変化が分かりやすいようにデフォルトにする。
setDefaultTex();
llSleep(2);
//テクスチャを2列2行で分割し、0番目(0から始まる)のグリッドを第0面に貼る。
setTex(0, 2, 2, myTex, 0);
llSleep(2);
//テクスチャを2列2行で分割し、1番目(0から始まる)のグリッドを第1面に貼る。
setTex(1, 2, 2, myTex, 1);
llSleep(2);
//テクスチャを2列2行で分割し、2番目(0から始まる)のグリッドを第2面に貼る。
setTex(2, 2, 2, myTex, 2);
llSleep(2);
//テクスチャを4列4行で分割し、3番目(0から始まる)のグリッドを第3面に貼る
setTex(3, 4, 4, myTex, 3);
llSleep(2);
//テクスチャを4列4行で分割し、4番目(0から始まる)のグリッドを第4面に貼る。
setTex(4, 4, 4, myTex, 4);
llSleep(2);
//テクスチャを4列4行で分割し、5番目(0から始まる)のグリッドを第5面に貼る
setTex(5, 4, 4, myTex, 5);
llSleep(2);
}
こうゆう感じになります。
2008年03月08日
分割してテクスチャを貼るためのスクリプト
アップ代を節約するためにテクスチャを分割したりしますが、
けっこう計算とか面倒ですね。
そのためのスクリプトです。
使用しているサンプルテクスチャ。

けっこう計算とか面倒ですね。
そのためのスクリプトです。
使用しているサンプルテクスチャ。

//ParameterForGridTexture.lsl
//グリッド(格子状)に分割してテクスチャを貼る、もしくはそのときのスケールとオフセットの値を得る。
//テクスチャは、オブジェクトのサイズとは関係なく比率で貼り付けられる。
//デフォルトテクスチャ
string defaultTex = "89556747-24cb-43ed-920b-47caed15465f";
//テクスチャのUUIDかオブジェクトコンテンツでの名前を指定する。
//このサンプルテクスチャにはフルパーミッションを与えてあるので、誰でもこのテクスチャで実行できるはず。
string myTex = "0c5fb359-7ca3-00f2-8362-a6c2f0e5e8e9";
//テクスチャグリッドのオフセットを返す。
//index:テクスチャのグリッド番号(0から始まる)。
//numOfCol:テクスチャのグリッド列数。
//numOfRow:テクスチャのグリッド行数。
vector getGridTexOffset(integer index, integer numOfCol, integer numOfRow) {
integer Col = index % numOfCol;
integer Row = index / numOfCol;
float pitchCol = 1 / (float)numOfCol;
float pitchRow = 1 / (float)numOfRow;
float offX = -0.5 + pitchCol / 2 + Col * pitchCol;
float offY = 0.5 - pitchRow / 2 - Row * pitchRow;
return < offX, offY, 0.0>;
}
//テクスチャグリッドのスケールを返す。
//numOfCol:テクスチャのグリッド列数。
//numOfRow:テクスチャのグリッド行数。
vector getGridTexScale(integer numOfCol, integer numOfRow) {
return < 1/(float)numOfCol, 1/(float)numOfRow, 0.0>;
}
//テクスチャのスケールとオフセットをオーナーにSayする。
//index:テクスチャのグリッド番号(0から始まる)。
//numOfCol:テクスチャのグリッド列数。
//numOfRow:テクスチャのグリッド行数。
sayPara(integer index, integer numOfCol, integer numOfRow) {
vector scale = getGridTexScale(numOfCol, numOfRow);
llOwnerSay("顔ごとに繰り返す(scale) 水平(u)=" + (string)scale.x + ", 垂直(v)=" + (string)scale.y);
vector offset = getGridTexOffset(index, numOfCol, numOfRow);
llOwnerSay("ずれ(offset) 水平(u)=" + (string)offset.x + ", 垂直(v)=" + (string)offset.y);
}
//スケールとオフセットを設定してからテクスチャを指定面に貼り付ける。
//index:テクスチャのグリッド番号(0から始まる)。
//numOfCol:テクスチャのグリッド列数。
//numOfRow:テクスチャのグリッド行数。
//tex:テクスチャ名またはテクスチャのUUID
//face:貼り付ける面番号。
setTex(integer index, integer numOfCol, integer numOfRow, string tex, integer face) {
vector scale = getGridTexScale(numOfCol, numOfRow);
llScaleTexture(scale.x, scale.y, face);
vector offset = getGridTexOffset(index, numOfCol, numOfRow);
llOffsetTexture(offset.x, offset.y, face);
llSetTexture(tex, face);
}
//テクスチャの状態をデフォルトにする。
setDefaultTex() {
llSetTexture(defaultTex, ALL_SIDES);
llScaleTexture(1.0, 1.0, ALL_SIDES);
llOffsetTexture(0.0, 0.0, ALL_SIDES);
}
default {
state_entry() {
//繰り返したとき変化が分かりやすいようにデフォルトにする。
setDefaultTex();
llSleep(2);
//テクスチャを2列4行で分割し、3番目(0から始まる)のグリッドを貼るときのスケールとオフセットをオーナーにSayする。
sayPara(3, 2, 4);
//テクスチャを2列4行で分割し、3番目(0から始まる)のグリッドが全面に表示されるようにテクスチャを貼る。
setTex(3, 2, 4, myTex, ALL_SIDES);
llSleep(2);
//変化が分かりやすいようにデフォルトにする。
setDefaultTex();
llSleep(2);
//テクスチャを2列4行で分割し、0~5番目のグリッドのスケールとオフセットをオーナーにSayしながら、0~5番の面にテクスチャを貼る。
integer i;
for (i=0; i<6 ;i++) {
llOwnerSay(" *** face:" + (string)i + " ***");
sayPara(i, 2, 4);
setTex(i, 2, 4, myTex, i);
llSleep(2);
}
}
}
2008年03月05日
便利で危険なObjectZoomer
オブジェクトのサイズを自在に変更できるスクリプトです。
便利かなと思って使って見ましたが・・・
ちょっと使い方を間違うとオブジェクトがボコボコになってしまうこともw
大事なものに使うときはコピーをとってからにしてください。
まったく責任は持てませんので・・・
使い方は、プリムのコンテンツにこのスクリプトを入れて、
チャットからコマンドを入力します。
複数のプリムから成るオブジェクトでは、全部のプリムのコンテンツの中に入れます。
(プリム数が多いと実はこれがけっこう大変です。)
たくさん子プリムがあるときは、一度持ち物の中にスクリプトを作っておいて、
それをプリムのコンテンツにドラッグした方が便利そうです。
コマンドは、チャットから
/22 magnify=数値
指定した倍率で拡大縮小します。2は2倍、0.5は半分になります。
/22 size=数値
親プリムのサイズx,y,zで一番大きいものが指定した数値(メートル)になるようにします。
0.3は30センチ、5は5メートルです。
/22 remove
このスクリプトをプリムから取り除きます。
/22 info
含まれるすべてのプリムの番号、サイズ、位置、ローテーションなどの情報をオーナーにsayします。
/22 ch=番号
入力チャンネルを変更します。
ミスが起こりやすい点。
・このスクリプトをremoveするのを忘れて、
他のオブジェクトにコマンドを出したつもりが違うもののサイズも変わってビックリ。
・拡大とサイズ指定を勘違いしてとんでもなく大きく(小さく)してしまう。
・親プリムを基準にして拡大縮小するが、親といいながら実はオブジェクトの中で
一番小さかったりする場合は勘違いしやすい。
・縮小で小さいプリムが計算上1cm未満なるときや、
拡大で大きいプリムが計算上10メートルを超えるときに、
拡大縮小がうまくいかずに各オブジェクトの比率がおかしくなってしまう。
指定を勘違いしたときに起こしやすいが警告もなにも出ない。
しかもオブジェクトはボコボコに。
便利かなと思って使って見ましたが・・・
ちょっと使い方を間違うとオブジェクトがボコボコになってしまうこともw
大事なものに使うときはコピーをとってからにしてください。
まったく責任は持てませんので・・・
使い方は、プリムのコンテンツにこのスクリプトを入れて、
チャットからコマンドを入力します。
複数のプリムから成るオブジェクトでは、全部のプリムのコンテンツの中に入れます。
(プリム数が多いと実はこれがけっこう大変です。)
たくさん子プリムがあるときは、一度持ち物の中にスクリプトを作っておいて、
それをプリムのコンテンツにドラッグした方が便利そうです。
コマンドは、チャットから
/22 magnify=数値
指定した倍率で拡大縮小します。2は2倍、0.5は半分になります。
/22 size=数値
親プリムのサイズx,y,zで一番大きいものが指定した数値(メートル)になるようにします。
0.3は30センチ、5は5メートルです。
/22 remove
このスクリプトをプリムから取り除きます。
/22 info
含まれるすべてのプリムの番号、サイズ、位置、ローテーションなどの情報をオーナーにsayします。
/22 ch=番号
入力チャンネルを変更します。
ミスが起こりやすい点。
・このスクリプトをremoveするのを忘れて、
他のオブジェクトにコマンドを出したつもりが違うもののサイズも変わってビックリ。
・拡大とサイズ指定を勘違いしてとんでもなく大きく(小さく)してしまう。
・親プリムを基準にして拡大縮小するが、親といいながら実はオブジェクトの中で
一番小さかったりする場合は勘違いしやすい。
・縮小で小さいプリムが計算上1cm未満なるときや、
拡大で大きいプリムが計算上10メートルを超えるときに、
拡大縮小がうまくいかずに各オブジェクトの比率がおかしくなってしまう。
指定を勘違いしたときに起こしやすいが警告もなにも出ない。
しかもオブジェクトはボコボコに。
//ObjectZoomer.lsl ver1.0
integer LMN_SAY_INF = -9990010;
integer LMN_REMOVE_INVENTORY = -9990020;
integer LMN_MAGNIFY = -9990030;
integer chatcomandchannel = 22;
integer chatHandle;
integer isIntOrFloat(string s) {
s = llStringTrim(s,STRING_TRIM);
integer decimalPoint = llSubStringIndex(s,".");
integer sLen = llStringLength(s);
if (decimalPoint == -1) {
return isNum(s);
} else {
if (decimalPoint==0 ) { // e.g. .123
return isNum(llGetSubString(s, decimalPoint+1,sLen-1));
} else if (decimalPoint ==sLen-1) { // e.g. 123.
return isNum(llGetSubString(s, 0,decimalPoint-1));
} else {
string s1 = llGetSubString(s, 0, decimalPoint-1);
if (llSubStringIndex(s1," ")!=-1) { //search invalid sapces
return FALSE;
}
string s2 = llGetSubString(s, decimalPoint+1,sLen-1);
if (llSubStringIndex(s2," ")!=-1) { //search invalid sapces
return FALSE;
}
return isNum(s1) && isNum(s2);
}
}
}
integer isNum(string str){
integer int = (integer)str;
if(str == (string)int ) {
return TRUE;
} else {
return FALSE;
}
}
startListen() {
removeListen(); //append
llOwnerSay("PrimName=" + llGetObjectName()
+ " channel=" + (string)chatcomandchannel +" is opened." );
chatHandle = llListen(chatcomandchannel , "", llGetOwner(), "");
}
removeListen() {
if (chatHandle!=0) {
llOwnerSay("PrimName=" + llGetObjectName() + " channel="
+ (string)chatcomandchannel + " is closed.");
llListenRemove(chatHandle);
chatHandle = 0;
}
}
command(string message) {
if (llToLower(llGetSubString(message,0, 7))=="magnify=") {
string operand = llGetSubString(message, 8, llStringLength(message)-1);
if (isIntOrFloat(operand)) {
llMessageLinked(LINK_SET, LMN_MAGNIFY, operand, NULL_KEY);
return;
}
} else if (llToLower(llGetSubString(message,0, 4))=="size=") {
string operand = llGetSubString(message, 5, llStringLength(message)-1);
if (isIntOrFloat(operand)) {
float size = (float)operand;
vector v = llGetScale();
float max = v.x;
if (v.y > max) max=v.y;
if (v.z > max) max=v.z;
float mag = size / max;
llMessageLinked(LINK_SET, LMN_MAGNIFY,(string)mag , NULL_KEY);
return;
}
} else if (llToLower(llGetSubString(message,0, 5))=="remove") {
llMessageLinked(LINK_SET, LMN_REMOVE_INVENTORY, "", NULL_KEY);
return;
} else if (llToLower(llGetSubString(message,0, 3))=="info") {
llMessageLinked(LINK_SET, LMN_SAY_INF, "", NULL_KEY);
return;
} else if (llToLower(llGetSubString(message,0, 2))=="ch=") {
string operand = llGetSubString(message, 3, llStringLength(message)-1);
if (isNum(operand)) {
chatcomandchannel = (integer)operand;
if ( chatcomandchannel >=1 && chatcomandchannel<=99) {
startListen();
return;
}
}
}
llOwnerSay("\"" + message + "\"" + " is an invalid command. ");
}
integer getLastNumericIdx(string s) {
integer i;
integer j;
integer idx = -1;
for (j=0;j< llStringLength(s);j++) {
for (i=0;i<10;i++) {
string ss =llGetSubString(s, j, j);
integer pos = llSubStringIndex(ss, (string)i);
if (pos!=-1) {
idx = pos+j;
}
}
}
return idx;
}
string getCoreScriptName(string s) {
integer idx = llStringLength(s);
while (idx!=-1) {
s = llGetSubString(s, 0, idx-1);
idx = getLastNumericIdx(s);
}
return llStringTrim(s, STRING_TRIM_TAIL);
}
default {
state_entry() {
//Prevent duplicate of this script in a prim. When this script is dragged, previous same script will be removed.
//When same name script put into a content of prims, new script name will be "foo 1".
string scriptName = llGetScriptName();
string coreName = getCoreScriptName(scriptName);
integer i;
for (i=0;i<2;i++) {
string tail = " " + (string)i;
if (i==0) {
tail = "";
}
string name = coreName + tail;
if ( (scriptName!=name) && ( llGetInventoryType(name) == INVENTORY_SCRIPT) ) {
llRemoveInventory(name);
}
}
llMessageLinked(llGetLinkNumber(), LMN_SAY_INF, "", NULL_KEY);
// 0 is single prime object. 1 is parent prim of an object. Greater Equal 2 is child prim of an object.
// Child prims does not listen. Parent prim listens a chat command. A Parent prim notify a command to child prim by a message link.
if (llGetLinkNumber()<2) {
startListen();
}
}
on_rez(integer sparam) { //rez, attach, log in
// 0 is single prime object. 1 is parent prim of an object. Greater Equal 2 is child prim of an object.
if ( llGetLinkNumber()<2) {
startListen();
}
}
listen(integer channel, string name, key id, string message) {
if (channel == chatcomandchannel ) {
command(message);
}
}
//In the case of an object has many prims, if many links are breaked, many child prims will be parents and listeners.
//Many listeners burden a SIM. So these codes are removed.
//~ changed(integer change) {
//~ // linked/unlinked/sat on
//~ if (change & CHANGED_LINK) {
//~ // 0 is single prime object. 1 is parent prim of an object. Greater Equal 2 is a child prim of an object.
//~ if (llGetLinkNumber()<2) {
//~ startListen();
//~ } else {
//~ removeListen();
//~ }
//~ }
//~ }
link_message(integer sender_num, integer num, string str, key id) {
if (num==LMN_SAY_INF) {
llOwnerSay("info\n**PrimName=" + llGetObjectName() + " Script=" + llGetScriptName() + " LinkNo="
+ (string)llGetLinkNumber()
+ "\n**Gpos " + (string)llGetPos()
+ "\n**Lpos " + (string)llGetLocalPos()
+ "\n**Scale " + (string)llGetScale()
+ "\n**Rot " + (string)(llRot2Euler(llGetRot())*RAD_TO_DEG)
);
} else if (num==LMN_REMOVE_INVENTORY) {
llOwnerSay("Script \"" + llGetScriptName() + "\" is removed from " + llGetObjectName());
removeListen();
llRemoveInventory(llGetScriptName());
} else if (num==LMN_MAGNIFY) {
float mag = (float)str;
vector s = llGetScale();
s.x *= mag;
s.y *= mag;
s.z *= mag;
llSetScale(s);
if (llGetLinkNumber()>1) {
vector p = llGetLocalPos();
p.x *= mag;
p.y *= mag;
p.z *= mag;
llSetPos(p);
}
}
}
}
2008年03月01日
メッセージボード販売中

販売場所
http://slurl.com/secondlife/Harbeng/221/98/104
ベンダー設置場所
東京ピッグサイトのオープンスペース 4F
コピー可ですので、まずバックアップ用にコピーをおとりください。
地面に置いても装着してもご使用していただけます。
装着しているときは文字数が変わる変更はできません。
他の変更(パネル、サイズ、フォントの変更など)は装着したままでもできます。
タッチするとダイアログが出て入力できるようになります。
入力制限がオーナーのみの場合はチャンネル権が変わらないので、
入力毎にタッチしなくても入力できます。
簡単設定、文字数の変更、初期化は地面に置いてから行ってください。
SIMの状態によっては、文字数の変更ができなくて失敗することがあります。
そのときは他のサンドボックス等で試してください。
スクリプト禁止のところでは、入力や各種操作はできないのでご注意ください。
メッセージボード仕様


