User:Dora Gustafson/JSON structure facial expression
The script has 19 facial expressions that can be chosen from a menu
- The expressions can also be chosen by random and they can be played in a loop
- The script can be used in a pose ball or in an attached (HUD)prim
- When used for a pose ball the camera position is saved for next session
The script features a JSON structured dialog-menu
- In this case the menu has one main page and three child pages
- The power of JSON shows where the menu is decoded and in the navigation between menus. See the first lines in the listen event handler
<lsl> // 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. Sit on or attach // v1.02 JSON structured dialog-menu with all 19 facial expressions
// Define all menu names and menu button layouts string mDisa = "Disapproval"; list LDisa = ["Home", "Open mouth", "Disdain",
"Frown", "Tongue out", "Anger",
"Bored"];
string mChee = "Cheerful"; list LChee = ["Home", "Kiss", "Smile",
"Toothsmile", "Laugh", "Surprise",
"Wink"];
string mMis = "Miserable"; list LMis = ["Home", "Worry", "Afraid",
"Sad", "Cry", "Embarrassed",
"Repulsed", "Shrug"];
string mHom = "Home"; list LHom = ["Cheerful", "Miserable", "Disapproval",
"Loop", "Random"];
// strided list with key-value pair of button name and animation name // order of strides doesn't matter list coupling = [
"Afraid", "express_afraid_emote",
"Anger", "express_anger_emote",
"Bored", "express_bored_emote",
"Cry", "express_cry_emote",
"Disdain", "express_disdain",
"Embarrassed", "express_embarrassed_emote",
"Frown", "express_frown",
"Kiss", "express_kiss",
"Laugh", "express_laugh_emote",
"Open mouth", "express_open_mouth",
"Repulsed", "express_repulsed_emote",
"Sad", "express_sad_emote",
"Shrug", "express_shrug_emote",
"Smile", "express_smile",
"Surprise", "express_surprise_emote",
"Tongue out", "express_tongue_out",
"Toothsmile", "express_toothsmile",
"Wink", "express_wink_emote",
"Worry", "express_worry_emote"];
string JSONMenu; list BUTTONS; key sitter; integer dialogChannel = -532247677; integer haandtag; string menuHead; integer act = 0; string Fanim = "stand";
string script_info_to_string() {
string thisScript = llGetScriptName(); integer memoryUsed = llGetUsedMemory();
return thisScript
+ "\nMemory in use: " + (string)memoryUsed
+ "\n\n";
}
disable_timer() {
llSetTimerEvent(0.0);
}
default {
state_entry()
{
string s1 = llList2Json(JSON_ARRAY, LDisa);
string s2 = llList2Json(JSON_ARRAY, LChee);
string s3 = llList2Json(JSON_ARRAY, LMis);
string s4 = llList2Json(JSON_ARRAY, LHom);
JSONMenu = llList2Json(JSON_OBJECT,
[mDisa, s1, mChee, s2, mMis, s3, mHom, s4] + coupling);
BUTTONS = LHom ;
llSitTarget(<0.0, 0.0, 1.0>, ZERO_ROTATION);
llSetSitText("Animate");
llSetClickAction(CLICK_ACTION_SIT);
}
attach(key id)
{
menuHead = script_info_to_string() + "Choose any of 19 facial expressions";
llSetClickAction(CLICK_ACTION_TOUCH);
disable_timer();
act = 0;
if (id)
{
sitter = id;
llRequestPermissions(sitter , PERMISSION_TRIGGER_ANIMATION);
}
else
{
llListenRemove(haandtag);
}
}
changed(integer change)
{
integer perm = llGetPermissions();
menuHead = script_info_to_string()
+ "[Page Down] reopens this Dialog Menu\n\n"
+ "Choose any of 19 facial expressions";
act = 0;
disable_timer();
if (change & CHANGED_LINK)
{
sitter = llAvatarOnSitTarget();
if (sitter != NULL_KEY)
{
llRequestPermissions(sitter ,
PERMISSION_TRIGGER_ANIMATION|PERMISSION_TAKE_CONTROLS|PERMISSION_TRACK_CAMERA);
}
else
{
if (perm & PERMISSION_TRIGGER_ANIMATION)
{
llStopAnimation(Fanim);
}
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(Fanim);
llStopAnimation("sit");
}
if (perm & PERMISSION_TAKE_CONTROLS)
{
llTakeControls(CONTROL_DOWN , TRUE, TRUE);
llListenRemove(haandtag);
haandtag = llListen(dialogChannel, "", sitter, "");
llDialog(sitter, menuHead, BUTTONS, dialogChannel);
}
}
touch_end(integer num_detected)
{
key id = llDetectedKey(0);
if (id == sitter)
{
llListenRemove(haandtag);
haandtag = llListen(dialogChannel, "", sitter, "");
llDialog(sitter, menuHead, BUTTONS, dialogChannel);
}
}
control(key id, integer down, integer new)
{
if (down & new & CONTROL_DOWN)
{
llDialog(sitter, menuHead, BUTTONS, dialogChannel);
}
}
listen(integer channel, string name, key id, string message)
{
integer perm = llGetPermissions();
rotation rot = llGetRot();
vector pos = llGetPos();
if (JSON_ARRAY == llJsonValueType(JSONMenu, [message]))
{
BUTTONS = llParseString2List(llJsonGetValue(JSONMenu, [message]),
[",", "[", "]", "\""], []);
}
else
{
if (JSON_STRING == llJsonValueType(JSONMenu, [message]))
{
Fanim = llJsonGetValue(JSONMenu, [message]);
}
else if ("Loop" == message)
{
act = act ^ 1;
if (act & 1) llSetTimerEvent(3.0);
else disable_timer();
}
else if ("Random" == message)
{
Fanim = llList2String(llListRandomize(coupling, 2), 1);
act = act ^ 2;
}
if (perm & PERMISSION_TRIGGER_ANIMATION)
{
llStartAnimation(Fanim);
}
}
llDialog(sitter, menuHead, BUTTONS, dialogChannel);
if(perm & PERMISSION_TRACK_CAMERA)
{
rotation cam_rot = llGetCameraRot()/rot; // relative camera rotation
vector cam_pos = (llGetCameraPos() - pos)/rot;// relative camera position
llSetLinkCamera(LINK_THIS, cam_pos, cam_pos + llRot2Fwd(cam_rot));
}
}
timer()
{
integer perm = llGetPermissions();
if (act & 2)
{
Fanim = llList2String(llListRandomize(coupling, 2), 1);
}
if (perm & PERMISSION_TRIGGER_ANIMATION)
{
llStartAnimation(Fanim);
}
}
} </lsl> This code has been changed by Kireji Haiku and is not equal to my code, so I can't guarantee it's value. Dora Gustafson 14:18, 9 August 2013 (PDT)