HTML HUD Demo
<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. // * 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.
integer display_face = 4; integer button_face = 2; integer link = LINK_THIS; 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 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 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]; integer is_visible = FALSE; string my_url = "";
string footer; string header; key current_request;
set_header() {
// 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='" + my_url + "/' />" + "</head><body>";
}
set_footer() {
// TODO: Remove dependency on the js file
footer = "
"
+ "<script src='https://d2mjw3k7q9u8rb.cloudfront.net/assets/common-170919042270376442559931151451605602726.js' type='text/javascript'></script></body></html>";
}
toggle_show() {
if (is_visible) llSetLinkPrimitiveParamsFast(link,visible); else llSetLinkPrimitiveParamsFast(link,button); is_visible = !is_visible;
}
string av_image(key id) {
return "https://my-secondlife.s3.amazonaws.com/users/" + llGetUsername(id) + "/thumb_sl_image.png";
}
string app_profile_url(key id) {
return "secondlife:///app/agent/" + (string)id + "/about";
}
set_media(string url) {
//llClearLinkMedia(link,display_face); 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]);
}
string vec2str(vector v) {
return "<" + (string)((integer)v.x) + "," + (string)((integer)v.y) + "," + (string)((integer)v.z) + ">";
}
string bytes2str(integer b) {
if (b < 1024 * 1024) return (string)(b / 1024) + "KB"; return (string)(b / (1024 * 1024)) + "MB";
}
string img_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>";
}
string agent_menu_html(key agentid) {
return "
";
}
string give_list(key agentid, integer type) {
string resp; integer n = llGetInventoryNumber(type); integer i; for (i=0;i<n;++i) {
resp += "
"; } return resp; } string give_menu_html(key agentid) { string resp = "
";
return resp;
}
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 + "
" + "" + ""
+ "
" + llKey2Name(agent) + "" + "" + llGetUsername(agent) + "" + " | " + agent_menu_html(agent) + " " + give_menu_html(agent) + " | |
" + img_html(agent) + " | "
+ "
|
" + footer;
// Send the response. llSetContentType(current_request, CONTENT_TYPE_HTML); llHTTPResponse(current_request,200,resp);
//llOwnerSay("Memory used: " + (string)llGetUsedMemory() + ", response size: " + (string)llStringLength(resp));
}
string anim_menu_html() {
string resp = "
";
return resp;
}
play_anim(string anim) {
llRequestPermissions(llGetOwner(),PERMISSION_TRIGGER_ANIMATION); llStartAnimation(llUnescapeURL(anim));
}
anims_page() {
string resp = header + "
Animations
Choose an animation:
" + "
" + 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. llSensor("",NULL_KEY,AGENT,96,PI); return; } string p0 = llList2String(path,0); if (p0 == "agent") { if (path_segments == 1) { // just /agent lets show stuff for the owner. agent_details(request,llGetOwner()); return; } // p1 should be an agent id key agent = (key)llList2String(path,1);
if (path_segments == 2) { // Just an agent id. Get their info. agent_details(request,agent); return; } else if (path_segments == 4) { // agent/<id>/<cmd>/<option> string p2 = llList2String(path,2); if (p2 == "give") { string p3 = llUnescapeURL(llList2String(path,3)); llOwnerSay("Giving " + p3 + " to " + llKey2Name((key)agent)); llGiveInventory(agent,p3); agent_details(request,agent); return; } } } else if (p0 == "hide") { llSensor("",NULL_KEY,AGENT,96,PI); toggle_show(); } else if (p0 == "anims") { if (path_segments == 1) { anims_page(); } else if (path_segments == 2) { play_anim(llList2String(path,1)); anims_page(); } } else if (p0 == "video") { string resp = header + "
<iframe width='255' height='173' src='http://www.youtube.com/embed/m7p9IEpPu-c?rel=0' frameborder='0' allowfullscreen></iframe>" + footer; llSetContentType(current_request, CONTENT_TYPE_HTML); llHTTPResponse(current_request,200,resp); }
}
default {
state_entry() { llSetObjectName(llKey2Name(llGetOwner()) + "'s HUD"); llSetLinkPrimitiveParamsFast(link,init); toggle_show(); //llOwnerSay(llList2CSV(llGetLinkPrimitiveParams(2,[PRIM_POS_LOCAL]))); //llSetColor(<1,0,0>,button_face); 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) { //llOwnerSay(method + ": " + llGetHTTPHeader(id,"x-path-info")); if (method == URL_REQUEST_GRANTED) { my_url = body; set_footer(); set_header(); set_media(my_url); 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>