ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 표정 허드(Facial Expressions HUD) 만들기 - 세컨드라이&오픈심
    웹프로그래밍/LSL(세컨드라이프) 2015. 7. 30. 00:34
    반응형

    사진촬영 할때 유용한 "표정 허드" 만드는 방법 입니다.

    스크립트 소스는 "Dora Gustafson, Studio Dora 2012" 의 소스를 사용 하였습니다.


    1. 바닥에 아무 프림 하나를 만든다.


    2. 그 프림을 "Shift+드래그"로 복사해서 Y축(녹색) 방향으로 나란히 놓는다.

    - HUD는 장착했을때 X축(빨강) 방향이 정면이 되므로
       Y축/Z축 방향으로 정렬을 해주어야 합니다.


    3. 밝은표정 모음과 어두운 표정 모음 구분을 위해 각 프림의 텍스쳐 색상을 변경해 준다.
    - 저는 파랑/빨강 으로 나누었습니다.


    4. 밝은표정(파랑)쪽 프림에 스크립트를 넣어 줍니다.
    - "Edit"창의 [Content]탭을 누릅니다.

    - [New Script] 버튼을 누르면 "New Script"라는 파일이 생깁니다.

    - "New Script"를 더블클릭 하여 스크립트 편집창을 엽니다.

    - 안에있는 스크립트를 다 지우고 아래의 스크립트를 넣어주고 밑부분의 [Save]버튼을 눌러줍니다.

    // Pose ball and facial expressions, script by Dora Gustafson, Studio Dora 2012

    // build on Basic pose ball script. by Dora Gustafson, Studio Dora 2010

    // v1.00 Has 10 facial expressions that can be chosen from a menu, chosen by random,

    // ... looped, has menu reopen and saves camera position

    // v1.01 wearable


    string animation = "stand"; // name of built-in animation or animation in prim inventory

    list FACIALS = [ 

    "express_open_mouth",

    "express_tongue_out",

    "express_kiss",

    "express_smile",

    "express_toothsmile",

    "express_laugh_emote",

    "express_shrug_emote",

    "express_surprise_emote",

    "express_wink_emote"

    ];

    list BUTTONS = [

    "Open mouth",

    "Tongue out",

    "Kiss",

    "Smile",

    "Toothsmile",

    "Laugh",

    "Shrug",

    "Surprise",

    "Wink",

    "Loop", "Random"];

    key sitter;

    integer dialogChanal=-532247676;

    integer haandtag;

    string menuHead;

    integer act=0;

    string Fanim;


    default

    {

        state_entry()

        {

            llSitTarget( <0.0, 0.0, 1.0>, ZERO_ROTATION );

            llSetSitText("Animate");

            llSetClickAction(CLICK_ACTION_SIT);

        }

        attach(key id)

        {

            menuHead = llGetScriptName( )+"\nMemory in use: "+(string)llGetUsedMemory()+"\n\nChoose facial expression";

            llSetClickAction(CLICK_ACTION_TOUCH);

            llSetTimerEvent( 0.0 );

            act = 0;

            if (id)

            {

                sitter = id;

                llRequestPermissions( sitter , PERMISSION_TRIGGER_ANIMATION);

            }

            else llListenRemove( haandtag);

        }

        changed(integer change)

        {

            menuHead = llGetScriptName( )+"\nMemory in use: "+(string)llGetUsedMemory()+"\n\n[Page Down] reopens this Dialog Menu\n\nChoose facial expression";

            llSetTimerEvent( 0.0 );

            act = 0;

            if (change & CHANGED_LINK)

            {

                sitter = llAvatarOnSitTarget() ;

                if(sitter != NULL_KEY) llRequestPermissions( sitter , PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS | PERMISSION_TRACK_CAMERA);

                else

                {

                    if (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) llStopAnimation(animation);

                    llSetAlpha(1.0, ALL_SIDES); // show prim

                    llListenRemove( haandtag);

                }

            }

        }

        run_time_permissions(integer perm)

        {

            if ( (perm & PERMISSION_TRIGGER_ANIMATION) && (llAvatarOnSitTarget() != NULL_KEY) )

            {

                llSetAlpha(0.0, ALL_SIDES); // hide prim

                llStartAnimation(animation);

                llStopAnimation("sit");

            }

            if ( perm & PERMISSION_TAKE_CONTROLS )

            {

                llTakeControls( CONTROL_DOWN , TRUE, TRUE);

                llListenRemove( haandtag);

                haandtag = llListen( dialogChanal, "", sitter, "");

                llDialog( sitter, menuHead, BUTTONS, dialogChanal);

            }

        }

        touch_end( integer num )

        {

            if ( llDetectedKey(0) == sitter )

            {

                llListenRemove( haandtag);

                haandtag = llListen( dialogChanal, "", sitter, "");

                llDialog( sitter, menuHead, BUTTONS, dialogChanal);

            }

        }

        control(key id, integer down, integer new)

        {

            if ( down & new & CONTROL_DOWN ) llDialog( sitter, menuHead, BUTTONS, dialogChanal);

        }

        listen( integer channel, string name, key id, string message)

        {

            if ( "Loop" == message )

            {

                act = act ^ 1;

                if ( act & 1 ) llSetTimerEvent( 1.0 );

                else llSetTimerEvent( 0.0 );

            }

            else

            {

                if ( "Random" == message )

                {

                    Fanim = llList2String( llListRandomize( FACIALS, 1), 0);

                    act = act ^ 2;

                }

                else

                {

                    integer n = llListFindList( BUTTONS, [message]);

                    if ( n >= 0 ) Fanim = llList2String( FACIALS, n);

                }

                if ( llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) llStartAnimation( Fanim);

            }

            llDialog( sitter, menuHead, BUTTONS, dialogChanal);

            if( llGetPermissions() & PERMISSION_TRACK_CAMERA)

            {

                rotation cam_rot=llGetCameraRot()/llGetRot(); // relative camera rotation

                vector cam_pos=(llGetCameraPos()-llGetPos())/llGetRot(); // relative camera position

                llSetLinkCamera( LINK_THIS, cam_pos, cam_pos + llRot2Fwd(cam_rot));

            }

        }

        timer()

        {

             if ( act & 2 ) Fanim = llList2String( llListRandomize( FACIALS, 1), 0);

             if ( llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) llStartAnimation( Fanim);

        }

    }


    5. 어두운 표정(빨간)쪽에 같은방법으로 아래의 스크립트를 넣어 줍니다.

    // Pose ball and facial expressions, script by Dora Gustafson, Studio Dora 2012

    // build on Basic pose ball script. by Dora Gustafson, Studio Dora 2010

    // v1.00 Has 10 facial expressions that can be chosen from a menu, chosen by random,

    // ... looped, has menu reopen and saves camera position

    // v1.01 wearable


    string animation = "stand"; // name of built-in animation or animation in prim inventory

    list FACIALS = [ 

    "express_afraid_emote",

    "express_worry_emote",

    "express_sad_emote",

    "express_disdain",

    "express_frown",

    "express_anger_emote",

    "express_bored_emote",

    "express_cry_emote",

    "express_embarrased_emote",

    "express_repulsed_emote"

    ];

    list BUTTONS = [

    "Afraid",

    "Worry",

    "Sad",

    "Disdain",

    "Frown",

    "Angry",

    "Bored",

    "Cry",

    "Embarrase",

    "Repulsed",

    "Loop", "Random"];

    key sitter;

    integer dialogChanal=-532247677;

    integer haandtag;

    string menuHead;

    integer act=0;

    string Fanim;


    default

    {

        state_entry()

        {

            llSitTarget( <0.0, 0.0, 1.0>, ZERO_ROTATION );

            llSetSitText("Animate");

            llSetClickAction(CLICK_ACTION_SIT);

        }

        attach(key id)

        {

            menuHead = llGetScriptName( )+"\nMemory in use: "+(string)llGetUsedMemory()+"\n\nChoose facial expression";

            llSetClickAction(CLICK_ACTION_TOUCH);

            llSetTimerEvent( 0.0 );

            act = 0;

            if (id)

            {

                sitter = id;

                llRequestPermissions( sitter , PERMISSION_TRIGGER_ANIMATION);

            }

            else llListenRemove( haandtag);

        }

        changed(integer change)

        {

            menuHead = llGetScriptName( )+"\nMemory in use: "+(string)llGetUsedMemory()+"\n\n[Page Down] reopens this Dialog Menu\n\nChoose facial expression";

            llSetTimerEvent( 0.0 );

            act = 0;

            if (change & CHANGED_LINK)

            {

                sitter = llAvatarOnSitTarget() ;

                if(sitter != NULL_KEY) llRequestPermissions( sitter , PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS | PERMISSION_TRACK_CAMERA);

                else

                {

                    if (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) llStopAnimation(animation);

                    llSetAlpha(1.0, ALL_SIDES); // show prim

                    llListenRemove( haandtag);

                }

            }

        }

        run_time_permissions(integer perm)

        {

            if ( (perm & PERMISSION_TRIGGER_ANIMATION) && (llAvatarOnSitTarget() != NULL_KEY) )

            {

                llSetAlpha(0.0, ALL_SIDES); // hide prim

                llStartAnimation(animation);

                llStopAnimation("sit");

            }

            if ( perm & PERMISSION_TAKE_CONTROLS )

            {

                llTakeControls( CONTROL_DOWN , TRUE, TRUE);

                llListenRemove( haandtag);

                haandtag = llListen( dialogChanal, "", sitter, "");

                llDialog( sitter, menuHead, BUTTONS, dialogChanal);

            }

        }

        touch_end( integer num )

        {

            if ( llDetectedKey(0) == sitter )

            {

                llListenRemove( haandtag);

                haandtag = llListen( dialogChanal, "", sitter, "");

                llDialog( sitter, menuHead, BUTTONS, dialogChanal);

            }

        }

        control(key id, integer down, integer new)

        {

            if ( down & new & CONTROL_DOWN ) llDialog( sitter, menuHead, BUTTONS, dialogChanal);

        }

        listen( integer channel, string name, key id, string message)

        {

            if ( "Loop" == message )

            {

                act = act ^ 1;

                if ( act & 1 ) llSetTimerEvent( 1.0 );

                else llSetTimerEvent( 0.0 );

            }

            else

            {

                if ( "Random" == message )

                {

                    Fanim = llList2String( llListRandomize( FACIALS, 1), 0);

                    act = act ^ 2;

                }

                else

                {

                    integer n = llListFindList( BUTTONS, [message]);

                    if ( n >= 0 ) Fanim = llList2String( FACIALS, n);

                }

                if ( llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) llStartAnimation( Fanim);

            }

            llDialog( sitter, menuHead, BUTTONS, dialogChanal);

            if( llGetPermissions() & PERMISSION_TRACK_CAMERA)

            {

                rotation cam_rot=llGetCameraRot()/llGetRot(); // relative camera rotation

                vector cam_pos=(llGetCameraPos()-llGetPos())/llGetRot(); // relative camera position

                llSetLinkCamera( LINK_THIS, cam_pos, cam_pos + llRot2Fwd(cam_rot));

            }

        }

        timer()

        {

             if ( act & 2 ) Fanim = llList2String( llListRandomize( FACIALS, 1), 0);

             if ( llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) llStartAnimation( Fanim);

        }

    }



    6. 두개의 프림을 드래그 또는 "한프림 클릭+Shift+한프림 클릭" 으로 둘다 선택하고
       Edit 창의 [link] 버튼을 눌러줍니다.
       그리고 [General]탭으로 가서 Name 에 이름을 적어 줍니다.
       저는 "
    face_Expression_hud"라고 적었습니다.


    7. Edit 창을 닫고 프림을 마우스 오른클릭 하고 "Take" 해 줍니다.

    8. 허드장착
      - 인벤토리(단축키 : Ctrl+I)를 열고 방금만든 "face_Expression_hud"를 찾아 마우스 오른클릭을 합니다.
      - Attach to HUD > 적당한 위치 선택(저는 Top Right)를 선택 했습니다.

    9. 허드가 장착된 모습

    - 허드가 장착된 상태에서 허드를 마우스 오른클릭 하여 크기조정/위치조정을 할수 있습니다.


    10. 사용방법
    - 각 버튼(밝은표정/어두운표정)을 누르면 해당하는 표정목록이 있는 대화창이 뜹니다.

    - "Toothsmile"을 눌러봤습니다.

    - 몇초가 지나면 다시 무표정으로 돌아옵니다.
    - [Loop]버튼으로 해당표정을 지속적으로 짓고 있도록 할수 있습니다.
       [Loop]버튼을 다시한번 누르면 해제 됩니다.
    - [Random] 버튼은 아무 표정이나 랜덤으로 한번 선택됩니다.


    10. 대화창 닫기
    - 대화창 윗부분의 [x]를 누르거나 아래의 [Ignore]버튼을 누릅니다.
    - 만약 [Block]버튼으로 창을 닫으면, 다음부턴 대화창이 열리지 않습니다.
       이럴경우엔 허드를 벗었다가 다시 착용하면 됩니다.





    반응형

    댓글

Designed by Tistory.