ソラマメブログ

2008年07月09日

【スクリプト】テクスチャー表示、タッチで切り替え

「おしえて!セカンドライフ!」に上がった
  「テクスチャーの変更(http://oshiete.slmame.com/e296168.html)」
  「長押しクリック(http://oshiete.slmame.com/e293031.html)」
にインスパイアーされて作ってみました。

同じコンテンツ内にあるテクスチャーを表示し、タッチするとテクスチャーが切り替わるという、ありがちなスクリプトですが、ちょっと機能的に寂しいので、「長押し(タッチし続ける)」すると表示テクスチャーを戻す機能を入れました。押しっぱなしにしているとドンドン戻ります。

プリムのコンテンツに表示したいテクスチャーとこのスクリプトを入れます。
先にスクリプトを入れると、コンテンツ内にテクスチャーがないのでエラーになりますが、テクスチャーを入れてからタッチするとリセットされますので、気にしないで作業を続けてください。

リスト変数を使ってテクスチャー名を『管理していない』ので、テクスチャー数が多かったり、テクスチャー名が長かったりしても、メモリーが足りなくなってエラーになったりしません。

だいたいコメントとして書いているので、それを参照してください。

//==================================================
// texture_changer_by_touch
// スクリプトでコンテンツ内のテクスチャー名を自動取得
// コンテンツに変化があればテクスチャー数をチェックし、テクスチャー数に変化があれば最初から表示し直します
// タッチでテクスチャー切り替え
// 「長押し」でテクスチャー切り替え(リバース)
// 「長押し」しっぱなしにしているとどんどん戻ります。
// コンテンツ内にテクスチャーが無い場合はエラーステートに入る
// オーナータッチのみに反応するか、誰にでも反応するか選択可(変数OWNER_ONLY)

// 1.0.0
// 2008/07/07
// created by sasapy Beck

// Define
    integer AVATAR_DROP = TRUE; // 他のアバターのドロップを許可するか
    integer OWNER_ONLY = FALSE; // オーナーのタッチにのみ反応する

    key owner_key = NULL_KEY; // オーナーキー
    key avatar_key = NULL_KEY; // アバターキー

    string texture_name = ""; // テクスチャー名
    integer texture_index = 0; // 表示テクスチャー番号
    integer texture_max = 0; // テクスチャー数

    integer FACE = ALL_SIDES; // 表示する面番号
    vector COLOR = <0.0, 1.0, 0.0>; // テキストの色
    float ALPHA = 1.0; // テキストの透明度

    integer touch_count = 0; // 長押し用カウンター
    integer LONG_PUSH = 20; // 長押し検出閾値(20で約1秒)

//--------------------------------------------------
// Main
    default
    {
        state_entry()
        {
            owner_key = llGetOwner(); // オーナーのキー取得

            llAllowInventoryDrop(AVATAR_DROP); // ドロップの許可

            texture_max = llGetInventoryNumber(INVENTORY_TEXTURE); // テクスチャー数取得
            if(texture_max <= 0) // テクスチャー数が0以下の場合
            {
                llOwnerSay("テクスチャーが見つかりません"); // 表示
                state error; // エラーステートへ
            }

            texture_name = llGetInventoryName(INVENTORY_TEXTURE, texture_index); // テクスチャー名取得
            llSetTexture(texture_name, FACE); // テクスチャー表示
            llSetText((string)(texture_index + 1) + "/" + (string)texture_max + "\n" + texture_name, COLOR, ALPHA); // フローティングテキスト表示
        }

// Touch Event
// タッチ開始
        touch_start(integer total_number)
        {
            touch_count = 0; // カウンター初期化
        }

// タッチ最中
        touch(integer total_number)
        {
            avatar_key = llDetectedKey(0); // タッチしたアバターのキー取得

            if(!OWNER_ONLY || (avatar_key == owner_key)) // タッチしたアバターは有効か?
            {
                touch_count ++; // カウンター更新

                if((touch_count % LONG_PUSH) == 0) // 定数回の剰余が0の場合(毎回)
                {
                    texture_index --; // 番号の更新
                    if(texture_index < 0) // 0より小さくなったら
                    {
                        texture_index = texture_max - 1; // 最大値-1に戻す
                    }

                    texture_name = llGetInventoryName(INVENTORY_TEXTURE, texture_index); // テクスチャー名取得
                    llSetTexture(texture_name, FACE); // テクスチャー表示
                    llSetText((string)(texture_index + 1) + "/" + (string)texture_max + "\n" + texture_name, COLOR, ALPHA); // フローティングテキスト表示
                }
            }
        }

// タッチ終了
        touch_end(integer total_number)
        {
            avatar_key = llDetectedKey(0); // タッチしたアバターのキー取得

            if(!OWNER_ONLY || (avatar_key == owner_key)) // タッチしたアバターは有効か?
            {
                if(touch_count < LONG_PUSH) // 通常のタッチ
                {
                    texture_index ++; // 番号の更新
                    if(texture_index >= texture_max) // 最大値以上になった場合
                    {
                        texture_index = 0; // 0に戻す
                    }

                    texture_name = llGetInventoryName(INVENTORY_TEXTURE, texture_index); // テクスチャー名取得
                    llSetTexture(texture_name, FACE); // テクスチャー表示
                    llSetText((string)(texture_index + 1) + "/" + (string)texture_max + "\n" + texture_name, COLOR, ALPHA); // フローティングテキスト表示
                }
            }
        }

// Change Event
        changed(integer change)
        {
            integer temp_max;

            if((change & CHANGED_INVENTORY) || (change & CHANGED_ALLOWED_DROP)) // インベントリーに変化があった場合
            {
                temp_max = llGetInventoryNumber(INVENTORY_TEXTURE); // テクスチャー数の取得
                if(texture_max != temp_max) // テクスチャー数が変わった場合
                {
                    texture_max = temp_max; // テクスチャー数の更新

                    if(texture_max <= 0) // テクスチャー数が0以下の場合
                    {
                        llOwnerSay("テクスチャーが見つかりません"); // 表示
                        state error; // エラーステートへ
                    }

                    texture_index = 0; // 0に戻す
                    texture_name = llGetInventoryName(INVENTORY_TEXTURE, texture_index); // テクスチャー名取得
                    llSetTexture(texture_name, FACE); // テクスチャー表示
                    llSetText((string)(texture_index + 1) + "/" + (string)texture_max + "\n" + texture_name, COLOR, ALPHA); // フローティングテキスト表示
                }
            }
        }
    }

//--------------------------------------------------
// エラーが発生した場合
state error
    {
        state_entry()
        {
            llOwnerSay("エラーを解消してタッチしてください"); // 表示
        }

        touch_start(integer total_number) // タッチしたら
        {
            llResetScript(); // スクリプトのリセット
        }
    }
//==================================================
青文字:お好みで変更してください


この記事へのトラックバックURL

http://sasapy.slmame.com/t299762
この記事へのコメント
うは、これは実用的ですね!!
さっそく今日の夜、試してみようっと…
Posted by redzaku Kayo こと 赤ザクredzaku Kayo こと 赤ザク at 2008年07月09日 11:12
初めまして。

紹介してるテクスチャ表示スクリプトについて、
お聞きしたいことがあります。

オーナーのタッチのみに反応させたいのですが、この
スクリプトを組み込んだオブジェクトを人に譲渡すると
(オーナーが変わります)新オーナーのタッチには反応せず、
元オーナーのタッチにのみ反応するのです・・・。
※ちゃんとオーナーは変わっています。テクスも入ってます。

integer OWNER_ONLY = FALSE;にすると誰でもOKなので
問題ないのですが、TRUEにすると新オーナーは駄目なんです。
integer OWNER_ONLY 以外は上記スクリプトのままです。

何度も試してみたんですが、どうも上手くいかず・・・思い切って
書き込みしました~。時間あるときでいいので教えていただけると
大変嬉しいです~>< お忙しい中すみません;;
どうぞ宜しくお願いします---。
Posted by yuki★ at 2008年08月18日 22:18
yuki★さん、こんにちは。

譲渡するとそうなりますね。
原因はスクリプト中の変数owner_keyを取得する場所の関係です。
現状ではdefaultステートのstate_entryで取得していますので、スクリプトをリセットしないと取得しません。
yuki★さんがスクリプトを動かした時点でyuki★さんのキーが変数owner_keyに入りますが、その後、譲渡しても変数の中身は更新されません。譲渡された側でスクリプトのリセットをしないとなりません。

スクリプト自体を変更するならば、

if(!OWNER_ONLY || (avatar_key == owner_key)) // タッチしたアバターは有効か?

という部分(2カ所あります)のowner_keyをllGetOwner()に書き換えてください。

もしくは適当なところに、

// Rez Event
on_rez(integer start_param)
{
llResetScript();
}

を入れてREZしたらリセットするようにしてください。

スクリプトを公開しているので、譲渡するということは考えていませんでした。
Posted by ささぴ at 2008年08月19日 13:00
ささぴさん、こんにちわ。

教えてくれてどうもありがとうございます^^
全く見当違いのことをしていました^^;
教えてもらわなかったら、多分できなかったと思います・・・。

凄く分かりやすい説明でした^^直ぐできました。しかも早く
教えてくれて、めちゃくちゃ助かりました!有難うございます。
絵画とか写真、家などに使わせてもらいます^^

私のブログにリンクさせて頂いても良いでしょうか?

では又見に来ます~☆
Posted by yuki★ at 2008年08月20日 09:59
リンクしていただくのは大歓迎です。
よろしくお願いします。
Posted by ささぴ at 2008年08月20日 21:45