HTML HUD Demo: Difference between revisions
Kelly Linden (talk | contribs) No edit summary |
Kelly Linden (talk | contribs) No edit summary |
||
| Line 5: | Line 5: | ||
// * Rich, dynamic interface (images, menus, flash) | // * Rich, dynamic interface (images, menus, flash) | ||
// Updates and improvements are welcome at http://wiki.secondlife.com/wiki/HTML_HUD_Demo | // Updates and improvements are welcome at http://wiki.secondlife.com/wiki/HTML_HUD_Demo | ||
// To Use: | // To Use: | ||
// * Create a cube and wear it as a hud on the top-left. (script will need tweaking for other spots) | // * Create a cube and wear it as a hud on the top-left. (script will need tweaking for other spots) | ||
| Line 11: | Line 11: | ||
// * Add any animations you want to play to the object | // * Add any animations you want to play to the object | ||
// * Add any notecards or objects you want to give away to the object. | // * Add any notecards or objects you want to give away to the object. | ||
// License: | // License: | ||
// This script itself is free to share, modify and use without restriction. | // This script itself is free to share, modify and use without restriction. | ||
| Line 17: | Line 17: | ||
// Created by Kelly Linden, 2011. | // Created by Kelly Linden, 2011. | ||
integer display_face = 4; | |||
integer button_face = 2; | // CONFIG PARAMS | ||
integer link = LINK_THIS; | string video_url = "http://www.youtube.com/embed/m7p9IEpPu-c?rel=0"; | ||
integer display_face = 4; // The face to display HTML on | |||
integer button_face = 2; // The face that shows when hiding the HTML | |||
integer link = LINK_THIS; // The prim with media and button. | |||
// Prim params for when media is shown. Rotates and scales to show the media. | |||
list visible = [PRIM_POS_LOCAL,<0,-0.13,-0.13>,PRIM_SIZE,<0.01,0.25,0.25>,PRIM_ROT_LOCAL,<0,0,0,1>]; | list visible = [PRIM_POS_LOCAL,<0,-0.13,-0.13>,PRIM_SIZE,<0.01,0.25,0.25>,PRIM_ROT_LOCAL,<0,0,0,1>]; | ||
// Prim params for when media is hidden. Rotates and scales to show the button. | |||
list button = [PRIM_POS_LOCAL,<0,-0.04,-0.04>,PRIM_SIZE,<0.05,0.05,0.05>,PRIM_ROT_LOCAL,<0,0,-1,0>]; | list button = [PRIM_POS_LOCAL,<0,-0.04,-0.04>,PRIM_SIZE,<0.05,0.05,0.05>,PRIM_ROT_LOCAL,<0,0,-1,0>]; | ||
// Initial setup: sets the button texture. | |||
list init = [PRIM_TEXTURE,ALL_SIDES,TEXTURE_BLANK,<1,1,1>,<1,1,1>,0,PRIM_TEXTURE,button_face,"0b815b79-c8f5-fc98-91fc-e77b53a468e2",<1,1,1>,<1,1,1>,0]; | list init = [PRIM_TEXTURE,ALL_SIDES,TEXTURE_BLANK,<1,1,1>,<1,1,1>,0,PRIM_TEXTURE,button_face,"0b815b79-c8f5-fc98-91fc-e77b53a468e2",<1,1,1>,<1,1,1>,0]; | ||
// INTERNAL VARS | |||
// These variables are set by the program. | |||
integer is_visible = FALSE; // Whether or not the hud is showing HTML side. | |||
string my_url = ""; // Current LSL base url. | |||
list last_path; // Last visited | |||
string footer; // Footer: set in set_url | |||
string header; // Header: set in set_url | |||
key current_request; // HTTP request ID for the current request. | |||
// Toggle between button and HTML | |||
toggle_show() | toggle_show() | ||
{ | { | ||
| Line 55: | Line 51: | ||
} | } | ||
// Build an image url from an avatar's key. | |||
string av_image(key id) | string av_image(key id) | ||
{ | { | ||
| Line 60: | Line 57: | ||
} | } | ||
// Build an url that opens the profile for an avatar | |||
string app_profile_url(key id) | string app_profile_url(key id) | ||
{ | { | ||
| Line 65: | Line 63: | ||
} | } | ||
// Setup required after getting an url. | |||
set_url(string url) | |||
{ | { | ||
// | // Store our base url for future link building. | ||
my_url = url; | |||
// Build the common header: | |||
// * link to the css file | |||
// * set a base url | |||
// * html boilerplate code. | |||
// TODO: Remove dependency on this css file. | |||
header = "<html><head>" | |||
+ "<link href='https://d1979ns0fqtj19.cloudfront.net/assets/common-103828347986224535963905120979424958961.css' media='all' rel='stylesheet' type='text/css' />" | |||
+ "<base href='" + url + "/' />" | |||
+ "</head><body>"; | |||
// Build the common footer | |||
// * Navigation menu | |||
// * JS helper script (for fancy buttons) | |||
// * html boilerplate code | |||
// TODO: Remove dependency on the js file | |||
footer = "<div align='center' style='position:absolute;top:93%;left:8%;'>" | |||
+ "<a href=''>Scan</a> | " | |||
+ "<a href='anims'>Anims</a> | " | |||
+ "<a href='video'>Video</a> | " | |||
+ "<a href='config'>Config</a> | " | |||
+ "<a href='hide'>Hide</a></div>" | |||
+ "<script src='https://d2mjw3k7q9u8rb.cloudfront.net/assets/common-170919042270376442559931151451605602726.js' type='text/javascript'></script></body></html>"; | |||
llSetLinkMedia(link, display_face, // Side to display the media on. | llSetLinkMedia(link, display_face, // Side to display the media on. | ||
[PRIM_MEDIA_AUTO_PLAY,TRUE, // Show this page immediately | [PRIM_MEDIA_AUTO_PLAY,TRUE, // Show this page immediately | ||
| Line 74: | Line 98: | ||
PRIM_MEDIA_HEIGHT_PIXELS,256, // Height/width of media texture will be | PRIM_MEDIA_HEIGHT_PIXELS,256, // Height/width of media texture will be | ||
PRIM_MEDIA_WIDTH_PIXELS,256, // rounded up to nearest power of 2. | PRIM_MEDIA_WIDTH_PIXELS,256, // rounded up to nearest power of 2. | ||
PRIM_MEDIA_PERMS_CONTROL, PRIM_MEDIA_PERM_NONE]) | PRIM_MEDIA_PERMS_CONTROL, PRIM_MEDIA_PERM_NONE]); | ||
} | } | ||
// Turn a number of bytes (script size) into human readable format. | |||
string bytes2str(integer b) | string bytes2str(integer b) | ||
{ | { | ||
| Line 88: | Line 108: | ||
} | } | ||
string | // Build the html for the profile thumbnail image that links to their profile. | ||
string profile_thumb_html(key agent) | |||
{ | { | ||
return "<a href='" + app_profile_url(agent) + "' class='avatar avatar_thumb' rel='#sl_image_zoom' title='Click to zoom'><img alt='Thumb_sl_image' src='https://my-secondlife.s3.amazonaws.com/users/" + llGetUsername(agent) + "/sl_image.png' /></a>"; | return "<a href='" + app_profile_url(agent) + "' class='avatar avatar_thumb' rel='#sl_image_zoom' title='Click to zoom'>" | ||
+ "<img alt='Thumb_sl_image' src='https://my-secondlife.s3.amazonaws.com/users/" + llGetUsername(agent) + "/sl_image.png' /></a>"; | |||
} | } | ||
// Build the agent options menu | |||
string agent_menu_html(key agentid) | string agent_menu_html(key agentid) | ||
{ | { | ||
return "<div class='menu_button'>" | return "<div class='menu_button'>" | ||
+ "<a class='button call_to_action'> | + "<a class='button call_to_action'>Options</a>" | ||
+ "<ul style='list-style-type:none;text-align:left' class='menu'>" | + "<ul style='list-style-type:none;text-align:left' class='menu'>" | ||
+ "<li><a href='secondlife:///app/agent/" + (string)agentid + "/im'>IM</a></li>" | + "<li><a href='secondlife:///app/agent/" + (string)agentid + "/im'>IM</a></li>" | ||
| Line 105: | Line 128: | ||
} | } | ||
// Build an html list of items of type for the Give menu | |||
string give_list(key agentid, integer type) | string give_list(key agentid, integer type) | ||
{ | { | ||
| Line 117: | Line 141: | ||
} | } | ||
// Build the html for the Give menu and fill it with notecards and objects. | |||
string give_menu_html(key agentid) | string give_menu_html(key agentid) | ||
{ | { | ||
| Line 122: | Line 147: | ||
+ "<a class='button call_to_action'>Give</a>" | + "<a class='button call_to_action'>Give</a>" | ||
+ "<ul style='list-style-type:none;text-align:left;white-space:nowrap' class='menu'>"; | + "<ul style='list-style-type:none;text-align:left;white-space:nowrap' class='menu'>"; | ||
// Give notecards and objects. | // Give notecards and objects. | ||
resp += give_list(agentid,INVENTORY_NOTECARD); | resp += give_list(agentid,INVENTORY_NOTECARD); | ||
resp += give_list(agentid,INVENTORY_OBJECT); | resp += give_list(agentid,INVENTORY_OBJECT); | ||
resp += "</ul></div>"; | resp += "</ul></div>"; | ||
return resp; | return resp; | ||
} | } | ||
// Strip the "Resident" last name, break long names into 2 lines if possible. | |||
string agent_name(key id) | |||
{ | |||
string name = llList2String(llParseString2List(llKey2Name(id),[" Resident"],[]),0); | |||
if (llStringLength(name) > 14) | |||
{ | |||
name = llDumpList2String(llParseString2List(name,[" "],[]),"<br>"); | |||
} | |||
return name; | |||
} | |||
// Build the Agent Details page. | |||
agent_details(key request, key agent) | agent_details(key request, key agent) | ||
{ | { | ||
// Get the details we want. | // Get the details we want. | ||
list r = llGetObjectDetails(agent,[OBJECT_POS,OBJECT_TOTAL_SCRIPT_COUNT,OBJECT_SCRIPT_MEMORY,OBJECT_SCRIPT_TIME]); | list r = llGetObjectDetails(agent,[OBJECT_POS,OBJECT_TOTAL_SCRIPT_COUNT,OBJECT_SCRIPT_MEMORY,OBJECT_SCRIPT_TIME]); | ||
// Build the html. | // Build the html. | ||
string resp = header + "<table border='0' cellspacing='1' cellpadding='1'>" | string resp = header + "<table border='0' cellspacing='1' cellpadding='1'>" | ||
+ "<tr><td colspan='2' style='white-space:nowrap'><div class='profile_title'>" | + "<tr><td colspan='2' style='white-space:nowrap'><div class='profile_title'>" | ||
+ "<h1 id='display_name'>" + | + "<h1 id='display_name'>" + agent_name(agent) + "</h1>" | ||
+ "<h2 id='username'>" + llGetUsername(agent) + "</h2>" | + "<h2 id='username'>" + llGetUsername(agent) + "</h2>" | ||
+ "</div></td><td><div align='right'>" + agent_menu_html(agent) + "<br>" + give_menu_html(agent) + "</div></td></tr>" | + "</div></td><td><div align='right'>" + agent_menu_html(agent) + "<br>" + give_menu_html(agent) + "</div></td></tr>" | ||
+ "<tr><td width='80'>" + | + "<tr><td width='80'>" + profile_thumb_html(agent) + "</td><td colspan='2'>" | ||
+ "<ul style='list-style-type:circle'>" | + "<ul style='list-style-type:circle'>" | ||
+ "<li>Scripts:" | + "<li>Scripts:" | ||
| Line 150: | Line 187: | ||
+ "<li>" + (string)((integer)(llList2Float(r,3) * 1000000.0)) + "us</li>" | + "<li>" + (string)((integer)(llList2Float(r,3) * 1000000.0)) + "us</li>" | ||
+ "</ul></li></ul></td></tr></table>" + footer; | + "</ul></li></ul></td></tr></table>" + footer; | ||
// Send the response. | // Send the response. | ||
llSetContentType(current_request, CONTENT_TYPE_HTML); | llSetContentType(current_request, CONTENT_TYPE_HTML); | ||
llHTTPResponse(current_request,200,resp); | llHTTPResponse(current_request,200,resp); | ||
//llOwnerSay("Memory used: " + (string)llGetUsedMemory() + ", response size: " + (string)llStringLength(resp)); | // Uncomment this to debug memory usage. | ||
// Done here as this is the largest, most complex page. | |||
// llOwnerSay("Memory used: " + (string)llGetUsedMemory() + ", response size: " + (string)llStringLength(resp)); | |||
} | } | ||
// Build up an animation menu with any animations in the object. | |||
string anim_menu_html() | string anim_menu_html() | ||
{ | { | ||
| Line 163: | Line 203: | ||
+ "<a class='button call_to_action'>Animate<b class='actions_dropdown'> </b></a>" | + "<a class='button call_to_action'>Animate<b class='actions_dropdown'> </b></a>" | ||
+ "<ul style='list-style-type:none;text-align:left' class='menu'>"; | + "<ul style='list-style-type:none;text-align:left' class='menu'>"; | ||
integer n = llGetInventoryNumber(INVENTORY_ANIMATION); | integer n = llGetInventoryNumber(INVENTORY_ANIMATION); | ||
if (n == 0) | if (n == 0) | ||
| Line 177: | Line 217: | ||
} | } | ||
} | } | ||
resp += "</ul></div>"; | resp += "</ul></div>"; | ||
return resp; | return resp; | ||
} | } | ||
// Play an animation given the name. | |||
play_anim(string anim) | play_anim(string anim) | ||
{ | { | ||
| Line 188: | Line 229: | ||
} | } | ||
// Build the anims page. | |||
anims_page() | anims_page() | ||
{ | { | ||
| Line 196: | Line 238: | ||
} | } | ||
// Build the configuration page. | |||
config_page() | |||
{ | |||
string resp = header + "<h1>Not yet implemented.</h1>" + footer; | |||
llSetContentType(current_request, CONTENT_TYPE_HTML); | |||
llHTTPResponse(current_request,200,resp); | |||
} | |||
// Process a get request with a path. | // Process a get request with a path. | ||
GET(key request, list path) | GET(key request, list path) | ||
| Line 203: | Line 253: | ||
if (path_segments == 0) | if (path_segments == 0) | ||
{ | { | ||
// Home page. | // Home page is handled in the sensor response. | ||
llSensor("",NULL_KEY,AGENT,96,PI); | llSensor("",NULL_KEY,AGENT,96,PI); | ||
// Set the last_path incase the next request is a hide | |||
last_path = []; | |||
return; | |||
} | |||
string p0 = llList2String(path,0); | |||
if (p0 == "hide") | |||
{ | |||
toggle_show(); | |||
// We need to send back a page to show otherwise the | |||
// the next time the hud is shown there will be an error. | |||
// So we loop back in here with our last path. | |||
// Effectively this just refreshes the page we were already on. | |||
GET(request,last_path); | |||
// Do *not* set the last_path here to avoid any infinite loops. | |||
return; | return; | ||
} | } | ||
// Set the last path here, after the recursive hide call. | |||
last_path = path; | |||
if (p0 == "agent") | if (p0 == "agent") | ||
{ | { | ||
if (path_segments == 1) | if (path_segments == 1) | ||
{ | { | ||
// | // <url>/agent | ||
// Show owner details. | |||
agent_details(request,llGetOwner()); | agent_details(request,llGetOwner()); | ||
return; | return; | ||
} | } | ||
// p1 should be an agent id | // p1 should be an agent id | ||
key agent = (key)llList2String(path,1); | key agent = (key)llList2String(path,1); | ||
if (path_segments == 2) | if (path_segments == 2) | ||
{ | { | ||
// | // <url>/agent/<id> | ||
// Show the details for the agent. | |||
agent_details(request,agent); | agent_details(request,agent); | ||
return; | return; | ||
} | } | ||
if (path_segments == 4) | |||
{ | { | ||
// agent/<id>/<cmd>/<option> | // <url>/agent/<id>/<cmd>/<option> | ||
string | string cmd = llList2String(path,2); | ||
if ( | if (cmd == "give") | ||
{ | { | ||
string | string object_name = llUnescapeURL(llList2String(path,3)); | ||
llOwnerSay("Giving " + | llOwnerSay("Giving " + object_name + " to " + llKey2Name((key)agent)); | ||
llGiveInventory(agent, | llGiveInventory(agent,object_name); | ||
agent_details(request,agent); | agent_details(request,agent); | ||
return; | return; | ||
} | } | ||
} | } | ||
} | } | ||
else if (p0 == "anims") | else if (p0 == "anims") | ||
| Line 250: | Line 318: | ||
if (path_segments == 1) | if (path_segments == 1) | ||
{ | { | ||
// <url>/anims | |||
// Show the animation selection page | |||
anims_page(); | anims_page(); | ||
return; | |||
} | } | ||
else if (path_segments == 2) | else if (path_segments == 2) | ||
{ | { | ||
// <url>/anims/<anim-name> | |||
// Play the specified animation | |||
play_anim(llList2String(path,1)); | play_anim(llList2String(path,1)); | ||
anims_page(); | anims_page(); | ||
return; | |||
} | } | ||
} | } | ||
else if (p0 == "video") | else if (p0 == "video") | ||
{ | { | ||
// <url>/video | |||
// Play a demo video | |||
string resp = header | string resp = header | ||
+ "<br><iframe width='255' height='173' src=' | + "<br><iframe width='255' height='173' src='" + video_url + "' frameborder='0' allowfullscreen></iframe>" | ||
+ footer; | |||
llSetContentType(current_request, CONTENT_TYPE_HTML); | llSetContentType(current_request, CONTENT_TYPE_HTML); | ||
llHTTPResponse(current_request,200,resp); | llHTTPResponse(current_request,200,resp); | ||
return; | |||
} | } | ||
else if (p0 == "config") | |||
{ | |||
config_page(); | |||
return; | |||
} | |||
// Unknown page. 404. | |||
string resp = header + "<h1>404 Page Not Found.</h1>" + footer; | |||
llSetContentType(current_request, CONTENT_TYPE_HTML); | |||
llHTTPResponse(current_request,404,resp); | |||
} | } | ||
default | default | ||
{ | { | ||
| Line 274: | Line 362: | ||
llSetLinkPrimitiveParamsFast(link,init); | llSetLinkPrimitiveParamsFast(link,init); | ||
toggle_show(); | toggle_show(); | ||
llRequestURL(); | llRequestURL(); | ||
} | } | ||
on_rez(integer n) { llResetScript();} | on_rez(integer n) { llResetScript();} | ||
changed(integer c) | changed(integer c) | ||
| Line 284: | Line 370: | ||
if (c & (CHANGED_TELEPORT | CHANGED_OWNER | CHANGED_REGION)) { llResetScript();} | if (c & (CHANGED_TELEPORT | CHANGED_OWNER | CHANGED_REGION)) { llResetScript();} | ||
} | } | ||
touch_start(integer total_number) | touch_start(integer total_number) | ||
{ | { | ||
toggle_show(); | toggle_show(); | ||
} | } | ||
http_request(key id, string method, string body) | http_request(key id, string method, string body) | ||
{ | { | ||
if (method == URL_REQUEST_GRANTED) | if (method == URL_REQUEST_GRANTED) | ||
{ | { | ||
set_url(body); | |||
return; | return; | ||
} | } | ||
| Line 308: | Line 390: | ||
return; | return; | ||
} | } | ||
if (method == "GET") | if (method == "GET") | ||
{ | { | ||
| Line 315: | Line 397: | ||
return; | return; | ||
} | } | ||
llHTTPResponse(id,400,"Unsupported method."); | llHTTPResponse(id,400,"Unsupported method."); | ||
return; | return; | ||
} | } | ||
sensor(integer n) | sensor(integer n) | ||
{ | { | ||
string resp = header + "<h2>Scan Results:</h2><ul style='list-style-type:circle;margin-left:20px'>"; | string resp = header + "<h2>Scan Results:</h2><ul style='list-style-type:circle;margin-left:20px'>"; | ||
// TODO: Only fits 14 right now. Figure out how to fit all 16. Figure out how to find more than 16. | // TODO: Only fits 14 right now. Figure out how to fit all 16. Figure out how to find more than 16. | ||
if (n > 14) n = 14; | if (n > 14) n = 14; | ||
for (--n; n >= 0; --n) | for (--n; n >= 0; --n) | ||
{ | { | ||
resp += "<li><a href='agent/" + (string)llDetectedKey(n) + "'>" + | resp += "<li><a href='agent/" + (string)llDetectedKey(n) + "'>" + agent_name(llDetectedKey(n)) + "</a></li>"; | ||
} | } | ||
resp += "</ul>" + footer; | resp += "</ul>" + footer; | ||
| Line 334: | Line 416: | ||
llHTTPResponse(current_request,200,resp); | llHTTPResponse(current_request,200,resp); | ||
} | } | ||
no_sensor() | no_sensor() | ||
{ | { | ||
| Line 344: | Line 426: | ||
llHTTPResponse(current_request,200,resp); | llHTTPResponse(current_request,200,resp); | ||
} | } | ||
} | }</lsl> | ||
Revision as of 10:34, 26 August 2011
<lsl>// HTML Based, Single Script HUD // This is intended to be a tech demo of what html on a hud allows. // * Interaction with SL world (give items, play animations, scan nearby avatars) // * Simple, low overhead (1 scripts, 1 prim) // * Rich, dynamic interface (images, menus, flash) // Updates and improvements are welcome at http://wiki.secondlife.com/wiki/HTML_HUD_Demo
// To Use: // * Create a cube and wear it as a hud on the top-left. (script will need tweaking for other spots) // * Edit the cube while wearing it and add this script to it. // * Add any animations you want to play to the object // * Add any notecards or objects you want to give away to the object.
// License: // This script itself is free to share, modify and use without restriction. // Any linked or referenced files are not included in this license and are licensed by their respective owners under their own respective copyright and other licenses. // Created by Kelly Linden, 2011.
// CONFIG PARAMS
string video_url = "http://www.youtube.com/embed/m7p9IEpPu-c?rel=0";
integer display_face = 4; // The face to display HTML on integer button_face = 2; // The face that shows when hiding the HTML integer link = LINK_THIS; // The prim with media and button.
// Prim params for when media is shown. Rotates and scales to show the media. list visible = [PRIM_POS_LOCAL,<0,-0.13,-0.13>,PRIM_SIZE,<0.01,0.25,0.25>,PRIM_ROT_LOCAL,<0,0,0,1>]; // Prim params for when media is hidden. Rotates and scales to show the button. list button = [PRIM_POS_LOCAL,<0,-0.04,-0.04>,PRIM_SIZE,<0.05,0.05,0.05>,PRIM_ROT_LOCAL,<0,0,-1,0>]; // Initial setup: sets the button texture. list init = [PRIM_TEXTURE,ALL_SIDES,TEXTURE_BLANK,<1,1,1>,<1,1,1>,0,PRIM_TEXTURE,button_face,"0b815b79-c8f5-fc98-91fc-e77b53a468e2",<1,1,1>,<1,1,1>,0];
// INTERNAL VARS // These variables are set by the program. integer is_visible = FALSE; // Whether or not the hud is showing HTML side. string my_url = ""; // Current LSL base url. list last_path; // Last visited string footer; // Footer: set in set_url string header; // Header: set in set_url key current_request; // HTTP request ID for the current request.
// Toggle between button and HTML toggle_show() {
if (is_visible)
llSetLinkPrimitiveParamsFast(link,visible);
else
llSetLinkPrimitiveParamsFast(link,button);
is_visible = !is_visible;
}
// Build an image url from an avatar's key. string av_image(key id) {
return "https://my-secondlife.s3.amazonaws.com/users/" + llGetUsername(id) + "/thumb_sl_image.png";
}
// Build an url that opens the profile for an avatar string app_profile_url(key id) {
return "secondlife:///app/agent/" + (string)id + "/about";
}
// Setup required after getting an url. set_url(string url) {
// Store our base url for future link building.
my_url = url;
// Build the common header:
// * link to the css file
// * set a base url
// * html boilerplate code.
// TODO: Remove dependency on this css file.
header = "<html><head>"
+ "<link href='https://d1979ns0fqtj19.cloudfront.net/assets/common-103828347986224535963905120979424958961.css' media='all' rel='stylesheet' type='text/css' />"
+ "<base href='" + url + "/' />"
+ "</head><body>";
// Build the common footer // * Navigation menu // * JS helper script (for fancy buttons) // * html boilerplate code // TODO: Remove dependency on the js file
footer = "
+ "<a href=>Scan</a> | "
+ "<a href='anims'>Anims</a> | "
+ "<a href='video'>Video</a> | "
+ "<a href='config'>Config</a> | "
+ "<a href='hide'>Hide</a>"
+ "<script src='https://d2mjw3k7q9u8rb.cloudfront.net/assets/common-170919042270376442559931151451605602726.js' type='text/javascript'></script></body></html>";
llSetLinkMedia(link, display_face, // Side to display the media on.
[PRIM_MEDIA_AUTO_PLAY,TRUE, // Show this page immediately
PRIM_MEDIA_CURRENT_URL,url, // The url if they hit 'home'
PRIM_MEDIA_HOME_URL,url, // The url currently showing
PRIM_MEDIA_HEIGHT_PIXELS,256, // Height/width of media texture will be
PRIM_MEDIA_WIDTH_PIXELS,256, // rounded up to nearest power of 2.
PRIM_MEDIA_PERMS_CONTROL, PRIM_MEDIA_PERM_NONE]);
}
// Turn a number of bytes (script size) into human readable format. string bytes2str(integer b) {
if (b < 1024 * 1024) return (string)(b / 1024) + "KB"; return (string)(b / (1024 * 1024)) + "MB";
}
// Build the html for the profile thumbnail image that links to their profile. string profile_thumb_html(key agent) {
return "<a href='" + app_profile_url(agent) + "' class='avatar avatar_thumb' rel='#sl_image_zoom' title='Click to zoom'>"
+ "<img alt='Thumb_sl_image' src='https://my-secondlife.s3.amazonaws.com/users/" + llGetUsername(agent) + "/sl_image.png' /></a>";
}
// Build the agent options menu string agent_menu_html(key agentid) {
return "
";
}
// Build an html list of items of type for the Give menu string give_list(key agentid, integer type) {
string resp;
integer n = llGetInventoryNumber(type);
integer i;
for (i=0;i<n;++i)
{
resp += "
"; } return resp; } // Build the html for the Give menu and fill it with notecards and objects. string give_menu_html(key agentid) { string resp = "
";
return resp;
}
// Strip the "Resident" last name, break long names into 2 lines if possible. string agent_name(key id) {
string name = llList2String(llParseString2List(llKey2Name(id),[" Resident"],[]),0);
if (llStringLength(name) > 14)
{
name = llDumpList2String(llParseString2List(name,[" "],[]),"
");
}
return name;
}
// Build the Agent Details page. agent_details(key request, key agent) {
// Get the details we want. list r = llGetObjectDetails(agent,[OBJECT_POS,OBJECT_TOTAL_SCRIPT_COUNT,OBJECT_SCRIPT_MEMORY,OBJECT_SCRIPT_TIME]); // Build the html.
string resp = header + "
" + "" + ""
+ "
" + agent_name(agent) + "" + "" + llGetUsername(agent) + "" + " | " + agent_menu_html(agent) + " " + give_menu_html(agent) + " | |
| " + profile_thumb_html(agent) + " | "
+ "
| |
" + footer;
// Send the response.
llSetContentType(current_request, CONTENT_TYPE_HTML);
llHTTPResponse(current_request,200,resp);
// Uncomment this to debug memory usage.
// Done here as this is the largest, most complex page.
// llOwnerSay("Memory used: " + (string)llGetUsedMemory() + ", response size: " + (string)llStringLength(resp));
}
// Build up an animation menu with any animations in the object. string anim_menu_html() {
string resp = "
";
return resp;
}
// Play an animation given the name. play_anim(string anim) {
llRequestPermissions(llGetOwner(),PERMISSION_TRIGGER_ANIMATION); llStartAnimation(llUnescapeURL(anim));
}
// Build the anims page. anims_page() {
string resp = header + "
Animations
Choose an animation:
" + "
" + footer;
llSetContentType(current_request, CONTENT_TYPE_HTML); llHTTPResponse(current_request,200,resp);
}
// Build the configuration page. config_page() {
string resp = header + "
Not yet implemented.
" + footer;
llSetContentType(current_request, CONTENT_TYPE_HTML); llHTTPResponse(current_request,200,resp);
}
// Process a get request with a path. GET(key request, list path) {
current_request = request;
integer path_segments = llGetListLength(path);
if (path_segments == 0)
{
// Home page is handled in the sensor response.
llSensor("",NULL_KEY,AGENT,96,PI);
// Set the last_path incase the next request is a hide
last_path = [];
return;
}
string p0 = llList2String(path,0);
if (p0 == "hide")
{
toggle_show();
// We need to send back a page to show otherwise the
// the next time the hud is shown there will be an error.
// So we loop back in here with our last path.
// Effectively this just refreshes the page we were already on.
GET(request,last_path);
// Do *not* set the last_path here to avoid any infinite loops.
return;
}
// Set the last path here, after the recursive hide call.
last_path = path;
if (p0 == "agent")
{
if (path_segments == 1)
{
// <url>/agent
// Show owner details.
agent_details(request,llGetOwner());
return;
}
// p1 should be an agent id
key agent = (key)llList2String(path,1);
if (path_segments == 2)
{
// <url>/agent/<id>
// Show the details for the agent.
agent_details(request,agent);
return;
}
if (path_segments == 4)
{
// <url>/agent/<id>/<cmd>/<option>
string cmd = llList2String(path,2);
if (cmd == "give")
{
string object_name = llUnescapeURL(llList2String(path,3));
llOwnerSay("Giving " + object_name + " to " + llKey2Name((key)agent));
llGiveInventory(agent,object_name);
agent_details(request,agent);
return;
}
}
}
else if (p0 == "anims")
{
if (path_segments == 1)
{
// <url>/anims
// Show the animation selection page
anims_page();
return;
}
else if (path_segments == 2)
{
// <url>/anims/<anim-name>
// Play the specified animation
play_anim(llList2String(path,1));
anims_page();
return;
}
}
else if (p0 == "video")
{
// <url>/video
// Play a demo video
string resp = header
+ "
<iframe width='255' height='173' src='" + video_url + "' frameborder='0' allowfullscreen></iframe>"
+ footer;
llSetContentType(current_request, CONTENT_TYPE_HTML);
llHTTPResponse(current_request,200,resp);
return;
}
else if (p0 == "config")
{
config_page();
return;
}
// Unknown page. 404.
string resp = header + "
404 Page Not Found.
" + footer;
llSetContentType(current_request, CONTENT_TYPE_HTML); llHTTPResponse(current_request,404,resp);
}
default {
state_entry()
{
llSetObjectName(llKey2Name(llGetOwner()) + "'s HUD");
llSetLinkPrimitiveParamsFast(link,init);
toggle_show();
llRequestURL();
}
on_rez(integer n) { llResetScript();}
changed(integer c)
{
if (c & (CHANGED_TELEPORT | CHANGED_OWNER | CHANGED_REGION)) { llResetScript();}
}
touch_start(integer total_number)
{
toggle_show();
}
http_request(key id, string method, string body)
{
if (method == URL_REQUEST_GRANTED)
{
set_url(body);
return;
}
else if (method == URL_REQUEST_DENIED)
{
llOwnerSay("Unable to get url: " + body);
llSleep(10);
llRequestURL();
return;
}
if (method == "GET")
{
list path = llParseString2List(llGetHTTPHeader(id,"x-path-info"),["/"],[]);
GET(id,path);
return;
}
llHTTPResponse(id,400,"Unsupported method.");
return;
}
sensor(integer n)
{
string resp = header + "
Scan Results:
- ";
// TODO: Only fits 14 right now. Figure out how to fit all 16. Figure out how to find more than 16.
if (n > 14) n = 14;
for (--n; n >= 0; --n)
{
resp += "" + footer;
llSetContentType(current_request, CONTENT_TYPE_HTML);
llHTTPResponse(current_request,200,resp);
}
no_sensor()
{
string resp = header + "
Scan Results:
- ";
resp += "
- No one near by. "; resp += "
- Owner: <a href='agent/" + (string)llGetOwner() + "'>" + llKey2Name(llGetOwner()) + "</a> "; resp += "
" + footer;
llSetContentType(current_request, CONTENT_TYPE_HTML);
llHTTPResponse(current_request,200,resp);
}
}</lsl>