ソラマメブログ

2008年05月21日

【スクリプト】表情アニメの確認用サンプル

SLのデフォルトで用意されている表情のアニメーションをポーズボールのように切り替えて、表情を確認するサンプルです。

デフォルトの表情は19種類あって、アニメーションの名前を指定してllStartAnimationすれば、アバターの表情が変わりますが、なかなかアニメーションの名前が一般的に知れ渡っていないと思われます。
スクリプト中のリスト変数の中にアニメーション名が記述されていますので、気に入った表情があれば、その名前を使ってください。
(コメントに私が感じた表情を書いておきました)

ポーズボールなので、まずオブジェクトを作ります。
どんな形でもいいのですが、本体と切り替えボタン2つの最低3プリムが必要です。
この3プリムをリンクするわけですが、リンクする順番も重要です。画像のようなリンク番号になるようにリンクしてください。


(オブジェクトはこんな感じ。番号はリンク番号です。選択する順番は逆順ですから注意してください)


リンクする時に選択する順番で各プリムのリンク番号が決まります。先に選んだプリムのリンク番号が大きい番号となり、最後に選択したプリムがルートプリムになります。
ですので、リンク番号の大きいほうから順番に選択していくことになります。

オブジェクトを右クリックしてパイメニューからFaceを選択すると、オブジェクトの下に立ち、カメラ(視点)は自分の顔を見るように回り込みます。
オブジェクトの切り替えボタンをタッチすれば、表情は順番に切り替わります。
何もしなければ同じ表情が5秒間隔で繰り返されます。


(こんな感じ)

//==================================================
// Face Animation Test
// 表情のポーズボール
// 2008.05.20
// created by sasapy Beck

//--------------------------------------------------
// Define
    list FACE_ANIMATION = [ "express_afraid_emote", // うへぇ→
                                        "express_anger_emote", // えぁぁぁぁ↑
                                        "express_bored_emote", // ふーーん
                                        "express_cry_emote", // えーーーん
                                        "express_embarrassed_emote", // いぃぃ↑
                                        "express_laugh_emote", // あぁぁぁぁ
                                        "express_repulsed_emote", // んんんん
                                        "express_sad_emote", // うーーーん↓
                                        "express_shrug_emote", // んっ?
                                        "express_surprise_emote", // えぇぇ!
                                        "express_wink_emote", // にっ(ういんく)
                                        "express_worry_emote", // (へっ)
                                        "express_disdain", // ちっ
                                        "express_frown", // むっ
                                        "express_kiss", // ちゅう
                                        "express_open_mouth", // おぉぉ
                                        "express_smile", // (にや)
                                        "express_tongue_out", // べぇ
                                        "express_toothsmile" // いっ
                                    ];

    list FACE_NAME = [ "恐れる", // "afraid",
                                        "怒る", // "anger",
                                        "うんざりする", // "bored",
                                        "泣く", // "cry",
                                        "とまどう", // "embarrassed",
                                        "笑う", // "laugh",
                                        "拒否する", // "repulsed",
                                        "悲しむ", // "sad",
                                        "肩をすくめる", // "shrug",
                                        "驚く", // "surprise",
                                        "ウィンクする", // "wink",
                                        "心配する", // "worry",
                                        "軽蔑する", // "disdain",
                                        "眉をひそめる", // "frown",
                                        "キスする", // "kiss",
                                        "口を開く", // "open mouth",
                                        "微笑む", // "smile",
                                        "舌を出す", // "tongue out",
                                        "笑う" // "toothsmile"
                                    ];

    string animation_name = ""; // アニメーション名
    string animation_text = ""; // テキスト用アニメーション名
    integer animation_count = 0; // アニメーション番号
    integer animation_max = 0; // アニメーション最大数

    list avatar_animation_list = []; // 現在行っているアニメーションの取得
    integer avatar_animation_max = 0; // その数を取得

    key avatar_key = NULL_KEY; // その時々のアバターのキー
    key sitting_key = NULL_KEY; // 座っているアバターのキー

    integer LINK_FORWARD = 2; // リンク番号
    integer LINK_REVIEW = 3; // リンク番号

    integer i = 0; // ループ用

    vector TEXT_COLOR = <1.0, 1.0, 1.0>; // テキストの色
    float TEXT_ALPHA = 1.0; // テキストの透明度

    vector SIT_POSITION = <0.0, 0.0, -1.5>; // 座る位置
    vector SIT_ROTATION = <0.0, 0.0, 0.0>; // 座る回転
    vector CAMERA_OFFSET = <1.0, 0.0, -0.3>; // カメラ始点位置
    vector CAMERA_AT = <0.0, 0.0, -0.3>; // カメラの見る方向

// デフォルトの立ちポーズにしていますが、首が動かないポーズにすれば、表情が確認しやすいです
    string STAND = "stand"; // 立ちポーズ

    float POSE_TIME = 5.0; // 繰り返し間隔(秒)
//--------------------------------------------------
// Main
    default
    {
        state_entry()
        {
            animation_max = llGetListLength(FACE_ANIMATION); // アニメーション最大数の取得
            llSetSitText("Face"); // パイメニュー変更
            llSetText("Face : " + (string)(animation_count+1) + "/" + (string)animation_max, TEXT_COLOR, TEXT_ALPHA);
            llSitTarget(SIT_POSITION, llEuler2Rot(SIT_ROTATION * DEG_TO_RAD)); // sit位置設定
            llSetCameraEyeOffset(CAMERA_OFFSET); // カメラ始点位置
            llSetCameraAtOffset(CAMERA_AT); // カメラ見る方向位置
        }

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

// Change Event
        changed(integer change)
        {
            if(change & CHANGED_LINK)
            {
                avatar_key = llAvatarOnSitTarget(); // 座っているアバターのキー取得

                if(avatar_key == NULL_KEY) // NULL_KEY(立った)場合
                {
                    llStopAnimation(animation_name); // 現在のアニメーションの停止
                    llStopAnimation(STAND); // 現在のアニメーションの停止
                    sitting_key = NULL_KEY; // キーの初期化
                    llSetTimerEvent(0.0); // タイマー停止
                }
                else // キーがある場合(座った)
                {
                    sitting_key = avatar_key; // キーの更新
                    llRequestPermissions(sitting_key, PERMISSION_TRIGGER_ANIMATION); // パーミッション要求
                }
            }
        }

// Permission Event
        run_time_permissions(integer permissions)
        {
            if(permissions & PERMISSION_TRIGGER_ANIMATION) // アニメーションの許可
            {
                avatar_animation_list = llGetAnimationList(sitting_key); // アバターが現在行っているアニメーションの取得
                avatar_animation_max = llGetListLength(avatar_animation_list); // その数を取得
                for(i = 0; i < avatar_animation_max; i++)
                {
                    llStopAnimation(llList2Key(avatar_animation_list, i)); // 順にアニメーションを停止
                }

                llStartAnimation(STAND); // 立ちアニメーション開始

                animation_name = llList2String(FACE_ANIMATION, animation_count); // アニメーション名取得
                llStartAnimation(animation_name); // アニメーション開始

                animation_text = llList2String(FACE_NAME, animation_count);

                llSetText("Face : " + (string)(animation_count + 1) + "/" + (string)animation_max + "\n" + animation_text, TEXT_COLOR, TEXT_ALPHA);
                llSetTimerEvent(POSE_TIME); // 繰り返し時間の設定
            }
        }

// Touch Event
        touch_start(integer total_number)
        {
            avatar_key = llDetectedKey(0); // タッチしたアバターのキー取得
            if(avatar_key == sitting_key) // 座っているアバターと同一か
            {
                integer touch_prim = llDetectedLinkNumber(0); // タッチしたプリムのリンク番号取得
                if(touch_prim == LINK_FORWARD) // リンク番号が「進む」の場合
                {
                    llStopAnimation(animation_name); // 現在のアニメーション停止

                    animation_count ++; // 番号の更新
                    if(animation_count >= animation_max) // 番号が最大値以上の場合
                    {
                        animation_count = 0; // 番号を0に戻す
                    }

                    animation_name = llList2String(FACE_ANIMATION, animation_count); // アニメーション名取得
                    llStartAnimation(animation_name); // アニメーション開始

                    animation_text = llList2String(FACE_NAME, animation_count);

                    llSetText("Face : " + (string)(animation_count + 1) + "/" + (string)animation_max + "\n" + animation_text, TEXT_COLOR, TEXT_ALPHA);
                    llSetTimerEvent(POSE_TIME); // 繰り返し時間の設定
                }
                else if(touch_prim == LINK_REVIEW) // タッチしたプリムが「戻る」の場合
                {
                    llStopAnimation(animation_name); // 現在のアニメーション停止

                    animation_count --; // 番号の更新
                    if(animation_count < 0) // 番号が0より小さい場合
                    {
                        animation_count = animation_max - 1; // 番号を最大値-1に戻す
                    }

                    animation_name = llList2String(FACE_ANIMATION, animation_count); // アニメーション名取得
                    llStartAnimation(animation_name); // アニメーション開始

                    animation_text = llList2String(FACE_NAME, animation_count);

                    llSetText("Face : " + (string)(animation_count + 1) + "/" + (string)animation_max + "\n" + animation_text, TEXT_COLOR, TEXT_ALPHA);
                    llSetTimerEvent(POSE_TIME); // 繰り返し時間の設定
                }
            }
        }

// Timer Event
        timer()
        {
            llStartAnimation(animation_name); // アニメーション開始
        }
    }
//==================================================
(青文字はお好みで調整してください)


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

http://sasapy.slmame.com/t247567
この記事へのコメント
はじめまして^^いつも見て勉強させていただいております。^^
丁度表情AOを使ったアイテムをちまちまつくっていたとこなので、これは大変便利そうでたすかりました。早速使わせていただきます。^^

質問なのですが、寝るときというか、目を閉じるというのは表情アニメでできるものなんでしょうか?アニメーション名がわからなくて・・もし、知ってましたらぜひ教えてください。
Posted by ファルコンファルコン at 2008年05月22日 19:28
ファルコンさん、こんにちは。
お役に立ちそうでよかったです。

「目を閉じる」表情のアニメーションですが、デフォルトのアニメーションで表情単体では、分かりません。
デフォルトの表情単体アニメーションは、サンプルにある19種類だけだと思います。

ちなみに、他のアニメーション(体全体)で目を閉じているアニメーションがあるかもしれません。その場合は、そのアニメーションを動かした後に優先度が高いアニメーションを動かすと、表情だけが残るかもしれません(実験していないので確実かどうかわかりません。ごめんなさい)

ちなみにSLのデフォルト(内部で持っている)のアニメーションの一覧は
http://wiki.secondlife.com/wiki/Internal_Animations/ja
にありますので参照してください。

サンプルのアニメーションを書き換える場合は、FACE_ANIMATIONで定義しているアニメーション名を書き換えれば、そのアニメーションをするポーズボールになります。
フローティングテキストに表示するアニメーション名ですが、いちいち定義するのが面倒であれば、

llSetText("Face : " + (string)(animation_count + 1) + "/" + (string)animation_max + "\n" + animation_text, TEXT_COLOR, TEXT_ALPHA);

としているところのanimation_textをanimation_nameに書き換えれば、オリジナルのアニメーション名が表示されます。
(3箇所あります)
Posted by ささぴささぴ at 2008年05月23日 09:07
おお、そうでしたか^^早速しらべてみます。ありがとうございました^^
また色々お勉強させていただきます^^
Posted by ファルコンファルコン at 2008年05月23日 18:18