Difference between revisions of "HTML HUD Demo"
Kireji Haiku (talk | contribs) m (Reformatted script and deleted copy.) |
(Added missing line so that HUD would work) |
||
Line 23: | Line 23: | ||
// their respective owners under their own respective copyright and other licenses. | // their respective owners under their own respective copyright and other licenses. | ||
// original by Kelly Linden and reformatted by Kireji Haiku, 2011. | // original by Kelly Linden and reformatted by Kireji Haiku, 2011. | ||
key owner; | key owner; | ||
string ownerName; | string ownerName; | ||
string url; | string url; | ||
key currentRequestID; | key currentRequestID; | ||
integer responseStatus; | integer responseStatus; | ||
string responseBody; | string responseBody; | ||
list lastPath; | list lastPath; | ||
string video_url; | string video_url; | ||
string header; | string header; | ||
string footer; | string footer; | ||
string currentAnimation; | string currentAnimation; | ||
integer isVisible; | integer isVisible; | ||
string exceptions; | string exceptions; | ||
// user-function: init | // user-function: init | ||
// - does not return anything | // - does not return anything | ||
Line 53: | Line 53: | ||
// - sets object's name and textures | // - sets object's name and textures | ||
// - request a url to use the HUD | // - request a url to use the HUD | ||
init() | init() | ||
{ | { | ||
Line 59: | Line 59: | ||
ownerName = llKey2Name(owner); | ownerName = llKey2Name(owner); | ||
llSetObjectName(ownerName+"'s HUD"); | llSetObjectName(ownerName+"'s HUD"); | ||
video_url = "http://www.youtube.com/embed/m7p9IEpPu-c?rel=0"; | video_url = "http://www.youtube.com/embed/m7p9IEpPu-c?rel=0"; | ||
//header set in set_link_media(url) | //header set in set_link_media(url) | ||
//footer set in set_link_media(url) | //footer set in set_link_media(url) | ||
llSetLinkPrimitiveParamsFast(LINK_THIS, [ | llSetLinkPrimitiveParamsFast(LINK_THIS, [ | ||
PRIM_TEXTURE, ALL_SIDES, TEXTURE_BLANK, <1.0, 1.0, 1.0>, ZERO_VECTOR, (float)FALSE, | PRIM_TEXTURE, ALL_SIDES, TEXTURE_BLANK, <1.0, 1.0, 1.0>, ZERO_VECTOR, (float)FALSE, | ||
PRIM_TEXTURE, 2, "0b815b79-c8f5-fc98-91fc-e77b53a468e2", <1.0, 1.0, 1.0>, ZERO_VECTOR, (float)FALSE]); | PRIM_TEXTURE, 2, "0b815b79-c8f5-fc98-91fc-e77b53a468e2", <1.0, 1.0, 1.0>, ZERO_VECTOR, (float)FALSE]); | ||
toggle_visibility_of_HUD_button(); | toggle_visibility_of_HUD_button(); | ||
request_url(); | request_url(); | ||
} | } | ||
// user-function: toggle_visibility_of_HUD_button | // user-function: toggle_visibility_of_HUD_button | ||
// - does not return anything | // - does not return anything | ||
// - toggle the visibility of the prim | // - toggle the visibility of the prim | ||
// - will rotate, position and scale the prim | // - will rotate, position and scale the prim | ||
toggle_visibility_of_HUD_button() | toggle_visibility_of_HUD_button() | ||
{ | { | ||
Line 90: | Line 90: | ||
PRIM_ROT_LOCAL, <0.0, 0.0, -1.0, 0.0>, | PRIM_ROT_LOCAL, <0.0, 0.0, -1.0, 0.0>, | ||
PRIM_SIZE, <0.05, 0.05, 0.05>]); | PRIM_SIZE, <0.05, 0.05, 0.05>]); | ||
isVisible = !isVisible; | isVisible = !isVisible; | ||
} | } | ||
// user-function: request url | // user-function: request url | ||
// - does not return anything | // - does not return anything | ||
// - make sure we drop the old url before requesting a new one | // - make sure we drop the old url before requesting a new one | ||
request_url() | request_url() | ||
{ | { | ||
Line 103: | Line 103: | ||
llRequestURL(); | llRequestURL(); | ||
} | } | ||
// user-function: set_link_media | // user-function: set_link_media | ||
// - does not return anything | // - does not return anything | ||
// - set the values for the string variables 'header' and 'footer' | // - set the values for the string variables 'header' and 'footer' | ||
// - prepare face 4 for media on a prim | // - prepare face 4 for media on a prim | ||
set_link_media(string scriptUrl) | set_link_media(string scriptUrl) | ||
{ | { | ||
url = scriptUrl; | url = scriptUrl; | ||
header = "<html><head><link href='" | header = "<html><head><link href='" | ||
+ "https://d1979ns0fqtj19.cloudfront.net/assets/common-103828347986224535963905120979424958961.css'" | + "https://d1979ns0fqtj19.cloudfront.net/assets/common-103828347986224535963905120979424958961.css'" | ||
+ " media='all' rel='stylesheet' type='text/css' />" | + " media='all' rel='stylesheet' type='text/css' />" | ||
+ "<base href='" + scriptUrl + "/' /></head><body>"; | + "<base href='" + scriptUrl + "/' /></head><body>"; | ||
footer = "<div align='center' style='position:absolute;top:93%;left:8%;'><a href=''>Scan</a> | " | 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='anims'>Anims</a> | <a href='video'>Video</a> | <a href='config'>Config</a> | " | ||
Line 123: | Line 123: | ||
+ "https://d2mjw3k7q9u8rb.cloudfront.net/assets/common-170919042270376442559931151451605602726.js" | + "https://d2mjw3k7q9u8rb.cloudfront.net/assets/common-170919042270376442559931151451605602726.js" | ||
+ "' type='text/javascript'></script></body></html>"; | + "' type='text/javascript'></script></body></html>"; | ||
llSetLinkMedia(LINK_THIS, 4, [ | llSetLinkMedia(LINK_THIS, 4, [ | ||
PRIM_MEDIA_AUTO_PLAY, TRUE, | PRIM_MEDIA_AUTO_PLAY, TRUE, | ||
Line 132: | Line 132: | ||
PRIM_MEDIA_PERMS_CONTROL, PRIM_MEDIA_PERM_NONE]); | PRIM_MEDIA_PERMS_CONTROL, PRIM_MEDIA_PERM_NONE]); | ||
} | } | ||
// user-function: | // user-function: | ||
// - does not return anything | // - does not return anything | ||
// - used if there's not a request to the homepage of our website | // - used if there's not a request to the homepage of our website | ||
// - check where on the site we are and prepare variables for the response | // - check where on the site we are and prepare variables for the response | ||
http_get(key requestID, list path) | http_get(key requestID, list path) | ||
{ | { | ||
currentRequestID = requestID; | currentRequestID = requestID; | ||
integer numOfPathsParts = llGetListLength(path); | integer numOfPathsParts = llGetListLength(path); | ||
string firstPathPart = llList2String(path, 0); | string firstPathPart = llList2String(path, 0); | ||
if (firstPathPart == "hide") | if (firstPathPart == "hide") | ||
{ | { | ||
Line 151: | Line 151: | ||
return; | return; | ||
} | } | ||
lastPath = path; | lastPath = path; | ||
if (firstPathPart == "agent") | if (firstPathPart == "agent") | ||
{ | { | ||
Line 171: | Line 171: | ||
if (llList2String(path, 2) != "give") | if (llList2String(path, 2) != "give") | ||
return; | return; | ||
key id = (key)llList2String(path, 1); | key id = (key)llList2String(path, 1); | ||
string name = llKey2Name(id); | string name = llKey2Name(id); | ||
string itemName = llUnescapeURL(llList2String(path, 3)); | string itemName = llUnescapeURL(llList2String(path, 3)); | ||
llOwnerSay("Giving '" + itemName + "' to '" + name + "'."); | llOwnerSay("Giving '" + itemName + "' to '" + name + "'."); | ||
llGiveInventory(id, itemName); | llGiveInventory(id, itemName); | ||
Line 202: | Line 202: | ||
+ video_url + "' frameborder='0' allowfullscreen></iframe>" | + video_url + "' frameborder='0' allowfullscreen></iframe>" | ||
+ footer; | + footer; | ||
return; | return; | ||
} | } | ||
Line 224: | Line 224: | ||
if (variable == "video") | if (variable == "video") | ||
video_url = value; | video_url = value; | ||
//because: var,val,&,var,val,&,... | //because: var,val,&,var,val,&,... | ||
index = index + 3; | index = index + 3; | ||
Line 231: | Line 231: | ||
} | } | ||
} | } | ||
responseStatus = 404; | responseStatus = 404; | ||
responseBody = header + "<h1>404 Page Not Found.</h1>" + footer; | responseBody = header + "<h1>404 Page Not Found.</h1>" + footer; | ||
Line 237: | Line 237: | ||
+ "Please check the path of the request for mistakes."); | + "Please check the path of the request for mistakes."); | ||
} | } | ||
// user-function: prepare_profile_overview_page | // user-function: prepare_profile_overview_page | ||
// - does not return anything | // - does not return anything | ||
// - prepares a response for a page with information about a certain avatar | // - prepares a response for a page with information about a certain avatar | ||
// - includes profile thumbnail, name, script info, give menu | // - includes profile thumbnail, name, script info, give menu | ||
prepare_profile_overview_page(key requestID, key id) | prepare_profile_overview_page(key requestID, key id) | ||
{ | { | ||
Line 250: | Line 250: | ||
OBJECT_SCRIPT_MEMORY, | OBJECT_SCRIPT_MEMORY, | ||
OBJECT_SCRIPT_TIME]); | OBJECT_SCRIPT_TIME]); | ||
responseStatus = 200; | responseStatus = 200; | ||
responseBody = header | responseBody = header | ||
Line 265: | Line 265: | ||
+ "us</li></ul></li></ul></td></tr></table>" + footer; | + "us</li></ul></li></ul></td></tr></table>" + footer; | ||
} | } | ||
// user-function: html_body_with_formatted_avatar_name | // user-function: html_body_with_formatted_avatar_name | ||
// - returns the name of the avatar in html format | // - returns the name of the avatar in html format | ||
// - removes the lastname if it is Resident | // - removes the lastname if it is Resident | ||
// - adds a line-break for long names | // - adds a line-break for long names | ||
string html_body_with_formatted_avatar_name(key id) | string html_body_with_formatted_avatar_name(key id) | ||
{ | { | ||
string stringToReturn = llKey2Name(id); | string stringToReturn = llKey2Name(id); | ||
if (llGetSubString(stringToReturn, -9, -1) == " Resident") | if (llGetSubString(stringToReturn, -9, -1) == " Resident") | ||
stringToReturn = llDeleteSubString(stringToReturn, -9, -1); | stringToReturn = llDeleteSubString(stringToReturn, -9, -1); | ||
if (15 < llStringLength(stringToReturn)) | if (15 < llStringLength(stringToReturn)) | ||
stringToReturn = llDumpList2String(llParseString2List(stringToReturn,[" "], []), "<br>"); | stringToReturn = llDumpList2String(llParseString2List(stringToReturn,[" "], []), "<br>"); | ||
return stringToReturn; | return stringToReturn; | ||
} | } | ||
// user-function: html_body_with_links_for_interaction_with_certain_avatar | // user-function: html_body_with_links_for_interaction_with_certain_avatar | ||
// - returns html text with links for an avatar to interact with who has a certain uuid | // - returns html text with links for an avatar to interact with who has a certain uuid | ||
string html_body_with_links_for_interaction_with_certain_avatar(key id) | string html_body_with_links_for_interaction_with_certain_avatar(key id) | ||
{ | { | ||
Line 298: | Line 298: | ||
+ (string)id + "/pay'>Pay</a></li></ul></div>"; | + (string)id + "/pay'>Pay</a></li></ul></div>"; | ||
} | } | ||
// user-function: html_body_with_inventory_overview_for_give_menu | // user-function: html_body_with_inventory_overview_for_give_menu | ||
// - returns html text with inventory item lists | // - returns html text with inventory item lists | ||
string html_body_with_inventory_overview_for_give_menu(key id) | string html_body_with_inventory_overview_for_give_menu(key id) | ||
{ | { | ||
string stringToReturn = "<div class='menu_button'><a class='button call_to_action'>Give</a>" | string stringToReturn = "<div class='menu_button'><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'>"; | ||
integer sizeOfStringBefore = llStringLength(stringToReturn); | integer sizeOfStringBefore = llStringLength(stringToReturn); | ||
stringToReturn += inventory_list_in_html_format_for_give_menu(id, INVENTORY_NOTECARD); | stringToReturn += inventory_list_in_html_format_for_give_menu(id, INVENTORY_NOTECARD); | ||
stringToReturn += inventory_list_in_html_format_for_give_menu(id, INVENTORY_OBJECT); | stringToReturn += inventory_list_in_html_format_for_give_menu(id, INVENTORY_OBJECT); | ||
if (llStringLength(stringToReturn) == sizeOfStringBefore) | if (llStringLength(stringToReturn) == sizeOfStringBefore) | ||
stringToReturn += "<li>(no objects or notecards found)</li>"; | stringToReturn += "<li>(no objects or notecards found)</li>"; | ||
stringToReturn += "</ul></div>"; | stringToReturn += "</ul></div>"; | ||
return stringToReturn; | return stringToReturn; | ||
} | } | ||
// user-function: bytes2str | // user-function: bytes2str | ||
// - returns a string with script memory info in readable format | // - returns a string with script memory info in readable format | ||
string bytes2str(integer bytes) | string bytes2str(integer bytes) | ||
{ | { | ||
// 1024² = 1048576 | // 1024² = 1048576 | ||
if (bytes < 1048576) | if (bytes < 1048576) | ||
return (string)(bytes / 1024) + " KB"; | return (string)(bytes / 1024) + " KB"; | ||
Line 332: | Line 332: | ||
return (string)(bytes / 1048576) + " MB"; | return (string)(bytes / 1048576) + " MB"; | ||
} | } | ||
// user-function: html_body_avatar_profile_pic_thumbnail | // user-function: html_body_avatar_profile_pic_thumbnail | ||
// - returns html text with urls to someone's profile pic | // - returns html text with urls to someone's profile pic | ||
string html_body_avatar_profile_pic_thumbnail(key id) | string html_body_avatar_profile_pic_thumbnail(key id) | ||
{ | { | ||
Line 343: | Line 343: | ||
+ llGetUsername(id) + "/sl_image.png' /></a>"; | + llGetUsername(id) + "/sl_image.png' /></a>"; | ||
} | } | ||
// user-function: inventory_list_in_html_format_for_give_menu | // user-function: inventory_list_in_html_format_for_give_menu | ||
// - returns html text with inventory item list of given type | // - returns html text with inventory item list of given type | ||
string inventory_list_in_html_format_for_give_menu(key id, integer type) | string inventory_list_in_html_format_for_give_menu(key id, integer type) | ||
{ | { | ||
string stringToReturn; | string stringToReturn; | ||
integer index = llGetInventoryNumber(type); | integer index = llGetInventoryNumber(type); | ||
while (index) | while (index) | ||
{ | { | ||
--index; | --index; | ||
string name = llGetInventoryName(type, index); | string name = llGetInventoryName(type, index); | ||
stringToReturn += "<li><a href='agent/" + (string)id + "/give/" + name + "'>" + name + "</a></li>"; | stringToReturn += "<li><a href='agent/" + (string)id + "/give/" + name + "'>" + name + "</a></li>"; | ||
} | } | ||
return stringToReturn; | return stringToReturn; | ||
} | } | ||
// user-function: anims_page | // user-function: anims_page | ||
// - does not return anything | // - does not return anything | ||
// - prepares an html text overview page of animations | // - prepares an html text overview page of animations | ||
anims_page() | anims_page() | ||
{ | { | ||
Line 374: | Line 374: | ||
+ html_body_animations_overview() + "</div><br><br>" + footer; | + html_body_animations_overview() + "</div><br><br>" + footer; | ||
} | } | ||
// user-function: html_body_animations_overview | // user-function: html_body_animations_overview | ||
// - returns html text with a list of included animations | // - returns html text with a list of included animations | ||
string html_body_animations_overview() | string html_body_animations_overview() | ||
{ | { | ||
string stringToReturn = "<div class='menu_button' style='align:center'><a class='button call_to_action'>Animate" | string stringToReturn = "<div class='menu_button' style='align:center'><a class='button call_to_action'>Animate" | ||
+ "<b class='actions_dropdown'> </b></a><ul style='list-style-type:none;text-align:left' class='menu'>"; | + "<b class='actions_dropdown'> </b></a><ul style='list-style-type:none;text-align:left' class='menu'>"; | ||
integer index = llGetInventoryNumber(INVENTORY_ANIMATION); | integer index = llGetInventoryNumber(INVENTORY_ANIMATION); | ||
if (!index) | if (!index) | ||
stringToReturn += "<li>(no animations found)</li>"; | stringToReturn += "<li>(no animations found)</li>"; | ||
else while (index) | else while (index) | ||
{ | { | ||
--index; | --index; | ||
string name = llGetInventoryName(INVENTORY_ANIMATION, index); | string name = llGetInventoryName(INVENTORY_ANIMATION, index); | ||
stringToReturn += "<li><a href='anims/" + name + "'>" + name + "</a></li>"; | stringToReturn += "<li><a href='anims/" + name + "'>" + name + "</a></li>"; | ||
} | } | ||
stringToReturn += "</ul></div>"; | stringToReturn += "</ul></div>"; | ||
return stringToReturn; | return stringToReturn; | ||
} | } | ||
// user-function: play_anim | // user-function: play_anim | ||
// - does not return anything | // - does not return anything | ||
// - prompts a perms request to animate owner | // - prompts a perms request to animate owner | ||
play_anim(string anim) | play_anim(string anim) | ||
{ | { | ||
Line 411: | Line 411: | ||
currentAnimation = llUnescapeURL(anim); | currentAnimation = llUnescapeURL(anim); | ||
} | } | ||
// user-function: config_page | // user-function: config_page | ||
// - does not return anything | // - does not return anything | ||
// - prepares page to configure youtube video link | // - prepares page to configure youtube video link | ||
config_page() | config_page() | ||
{ | { | ||
Line 423: | Line 423: | ||
+ "' /><input type='submit' value='Set' /></form>" + footer; | + "' /><input type='submit' value='Set' /></form>" + footer; | ||
} | } | ||
// user-function: throw_exception | // user-function: throw_exception | ||
// - does not return anything | // - does not return anything | ||
// - logs errors into cache for later viewing and debugging | // - logs errors into cache for later viewing and debugging | ||
throw_exception(string inputString) | throw_exception(string inputString) | ||
{ | { | ||
if (exceptions == "") | if (exceptions == "") | ||
exceptions = "The following un-handled exception(s) occurred that are preventing this device's operation:\n"; | exceptions = "The following un-handled exception(s) occurred that are preventing this device's operation:\n"; | ||
exceptions += "\t"+inputString+"\n"; | exceptions += "\t"+inputString+"\n"; | ||
} | } | ||
default | default | ||
{ | { | ||
Line 443: | Line 443: | ||
llResetScript(); | llResetScript(); | ||
} | } | ||
changed(integer change) | changed(integer change) | ||
{ | { | ||
Line 451: | Line 451: | ||
llResetScript(); | llResetScript(); | ||
} | } | ||
if (change & (CHANGED_REGION | CHANGED_REGION_START | CHANGED_TELEPORT)) | if (change & (CHANGED_REGION | CHANGED_REGION_START | CHANGED_TELEPORT)) | ||
request_url(); | request_url(); | ||
} | } | ||
state_entry() | state_entry() | ||
{ | { | ||
init(); | init(); | ||
} | } | ||
touch_start(integer num_detected) | touch_start(integer num_detected) | ||
{ | { | ||
toggle_visibility_of_HUD_button(); | toggle_visibility_of_HUD_button(); | ||
} | } | ||
http_request(key id, string method, string body) | http_request(key id, string method, string body) | ||
{ | { | ||
integer sendResponseNow = TRUE; | integer sendResponseNow = TRUE; | ||
responseStatus = 400; | responseStatus = 400; | ||
responseBody = "Unsupported method"; | responseBody = "Unsupported method"; | ||
if (method == URL_REQUEST_GRANTED) | if (method == URL_REQUEST_GRANTED) | ||
{ | { | ||
responseStatus = 200; | responseStatus = 200; | ||
responseBody = "OK"; | responseBody = "OK"; | ||
set_link_media(body); | set_link_media(body); | ||
} | } | ||
Line 484: | Line 484: | ||
responseStatus = 400; | responseStatus = 400; | ||
responseBody = "Bad request"; | responseBody = "Bad request"; | ||
throw_exception("The following error occurred while attempting to get a free URL for this device:\n \n" + body); | throw_exception("The following error occurred while attempting to get a free URL for this device:\n \n" + body); | ||
} | } | ||
Line 491: | Line 491: | ||
responseStatus = 200; | responseStatus = 200; | ||
responseBody = "GET"; | responseBody = "GET"; | ||
string pathInfoHeader = llGetHTTPHeader(id, "x-path-info"); | string pathInfoHeader = llGetHTTPHeader(id, "x-path-info"); | ||
list path = llParseString2List(pathInfoHeader, ["/"], []); | list path = llParseString2List(pathInfoHeader, ["/"], []); | ||
if (path == []) | if (path == []) | ||
{ | { | ||
sendResponseNow = FALSE; | sendResponseNow = FALSE; | ||
currentRequestID = id; | |||
llSensor("", NULL_KEY, AGENT_BY_LEGACY_NAME, 96.0, PI); | llSensor("", NULL_KEY, AGENT_BY_LEGACY_NAME, 96.0, PI); | ||
lastPath = []; | lastPath = []; | ||
Line 504: | Line 505: | ||
http_get(id, path); | http_get(id, path); | ||
} | } | ||
// check if doing a sensor sweep and if so don't send a response | // check if doing a sensor sweep and if so don't send a response | ||
// but send the response in 'sensor event' or 'no_sensor event' | // but send the response in 'sensor event' or 'no_sensor event' | ||
// | // | ||
// (time-out 30.0 seconds for response) | // (time-out 30.0 seconds for response) | ||
if (sendResponseNow) | if (sendResponseNow) | ||
{ | { | ||
Line 515: | Line 516: | ||
llHTTPResponse(id, responseStatus, responseBody); | llHTTPResponse(id, responseStatus, responseBody); | ||
} | } | ||
if (exceptions != "") | if (exceptions != "") | ||
state error; | state error; | ||
} | } | ||
run_time_permissions(integer perm) | run_time_permissions(integer perm) | ||
{ | { | ||
Line 529: | Line 530: | ||
throw_exception("This HUD has tried to animate your avatar WITHOUT having the permissions to do so. " | throw_exception("This HUD has tried to animate your avatar WITHOUT having the permissions to do so. " | ||
+ "You must grant this HUD permissions to animate your avatar for this feature to work."); | + "You must grant this HUD permissions to animate your avatar for this feature to work."); | ||
if (exceptions != "") | if (exceptions != "") | ||
state error; | state error; | ||
} | } | ||
sensor(integer num_detected) | sensor(integer num_detected) | ||
{ | { | ||
responseStatus = 200; | responseStatus = 200; | ||
responseBody = header + "<h2>Scan Results:</h2><ul style='list-style-type:circle;margin-left:20px'>"; | responseBody = header + "<h2>Scan Results:</h2><ul style='list-style-type:circle;margin-left:20px'>"; | ||
if (14 < num_detected) | if (14 < num_detected) | ||
num_detected = 14; | num_detected = 14; | ||
while (num_detected) | while (num_detected) | ||
{ | { | ||
--num_detected; | --num_detected; | ||
key id = llDetectedKey(num_detected); | key id = llDetectedKey(num_detected); | ||
responseBody += "<li><a href='agent/" + (string)id + "'>" | responseBody += "<li><a href='agent/" + (string)id + "'>" | ||
+ html_body_with_formatted_avatar_name(id) + "</a></li>"; | + html_body_with_formatted_avatar_name(id) + "</a></li>"; | ||
} | } | ||
responseBody += "</ul>" + footer; | responseBody += "</ul>" + footer; | ||
llSetContentType(currentRequestID, CONTENT_TYPE_HTML); | llSetContentType(currentRequestID, CONTENT_TYPE_HTML); | ||
llHTTPResponse(currentRequestID, responseStatus, responseBody); | llHTTPResponse(currentRequestID, responseStatus, responseBody); | ||
} | } | ||
no_sensor() | no_sensor() | ||
{ | { | ||
Line 564: | Line 565: | ||
+ "<li>No one near by.</li><li>Owner: <a href='agent/" + (string)owner + "'>" | + "<li>No one near by.</li><li>Owner: <a href='agent/" + (string)owner + "'>" | ||
+ ownerName + "</a></li></ul>" + footer; | + ownerName + "</a></li></ul>" + footer; | ||
llSetContentType(currentRequestID, CONTENT_TYPE_HTML); | llSetContentType(currentRequestID, CONTENT_TYPE_HTML); | ||
llHTTPResponse(currentRequestID, responseStatus, responseBody); | llHTTPResponse(currentRequestID, responseStatus, responseBody); | ||
} | } | ||
state_exit() | state_exit() | ||
{ | { | ||
Line 574: | Line 575: | ||
} | } | ||
} | } | ||
state error | state error | ||
{ | { | ||
Line 581: | Line 582: | ||
llResetScript(); | llResetScript(); | ||
} | } | ||
changed(integer change) | changed(integer change) | ||
{ | { | ||
Line 587: | Line 588: | ||
llResetScript(); | llResetScript(); | ||
} | } | ||
state_entry() | state_entry() | ||
{ | { |
Revision as of 09:04, 17 June 2013
<lsl> // Suggest a "Stop All Animations" button be added to Animations selection frame for convenience. </lsl>
<lsl> //HTML-based, single script HUD // // To use: // - create a default prim (cube) // - wear it as a HUD on top_left (script needs tweaking for other attachment points) // - edit the cube while wearing // - add animations you want to use // - add notecards and objects you want to hand out // - add this script // // 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. // original by Kelly Linden and reformatted by Kireji Haiku, 2011.
key owner;
string ownerName;
string url;
key currentRequestID;
integer responseStatus; string responseBody;
list lastPath;
string video_url;
string header; string footer;
string currentAnimation;
integer isVisible;
string exceptions;
// user-function: init // - does not return anything // - sets initial variable values // - sets object's name and textures // - request a url to use the HUD
init() {
owner = llGetOwner(); ownerName = llKey2Name(owner); llSetObjectName(ownerName+"'s HUD"); video_url = "http://www.youtube.com/embed/m7p9IEpPu-c?rel=0"; //header set in set_link_media(url) //footer set in set_link_media(url) llSetLinkPrimitiveParamsFast(LINK_THIS, [ PRIM_TEXTURE, ALL_SIDES, TEXTURE_BLANK, <1.0, 1.0, 1.0>, ZERO_VECTOR, (float)FALSE, PRIM_TEXTURE, 2, "0b815b79-c8f5-fc98-91fc-e77b53a468e2", <1.0, 1.0, 1.0>, ZERO_VECTOR, (float)FALSE]); toggle_visibility_of_HUD_button(); request_url();
}
// user-function: toggle_visibility_of_HUD_button // - does not return anything // - toggle the visibility of the prim // - will rotate, position and scale the prim
toggle_visibility_of_HUD_button() {
if (isVisible) llSetLinkPrimitiveParamsFast(LINK_THIS, [ PRIM_POS_LOCAL, <0.0, -0.13, -0.13>, PRIM_ROT_LOCAL, <0.0, 0.0, 0.0, 1.0>, PRIM_SIZE, <0.01, 0.25, 0.25>]); else llSetLinkPrimitiveParamsFast(LINK_THIS, [ PRIM_POS_LOCAL, <0.0, -0.04, -0.04>, PRIM_ROT_LOCAL, <0.0, 0.0, -1.0, 0.0>, PRIM_SIZE, <0.05, 0.05, 0.05>]); isVisible = !isVisible;
}
// user-function: request url // - does not return anything // - make sure we drop the old url before requesting a new one
request_url() {
llReleaseURL(url); llRequestURL();
}
// user-function: set_link_media // - does not return anything // - set the values for the string variables 'header' and 'footer' // - prepare face 4 for media on a prim
set_link_media(string scriptUrl) {
url = scriptUrl; header = "<html><head><link href='" + "https://d1979ns0fqtj19.cloudfront.net/assets/common-103828347986224535963905120979424958961.css'" + " media='all' rel='stylesheet' type='text/css' />" + "<base href='" + scriptUrl + "/' /></head><body>";
footer = "
+ "<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_THIS, 4, [ PRIM_MEDIA_AUTO_PLAY, TRUE, PRIM_MEDIA_CURRENT_URL, url, PRIM_MEDIA_HOME_URL, url, PRIM_MEDIA_HEIGHT_PIXELS, 256, PRIM_MEDIA_WIDTH_PIXELS, 256, PRIM_MEDIA_PERMS_CONTROL, PRIM_MEDIA_PERM_NONE]);
}
// user-function: // - does not return anything // - used if there's not a request to the homepage of our website // - check where on the site we are and prepare variables for the response
http_get(key requestID, list path) {
currentRequestID = requestID; integer numOfPathsParts = llGetListLength(path); string firstPathPart = llList2String(path, 0); if (firstPathPart == "hide") { toggle_visibility_of_HUD_button(); http_get(requestID, lastPath); return; } lastPath = path; if (firstPathPart == "agent") { if (numOfPathsParts == 1) { prepare_profile_overview_page(requestID, owner); return; } else if (numOfPathsParts == 2) { key id = (key)llList2String(path, 1); prepare_profile_overview_page(requestID, id); return; } else if (numOfPathsParts == 4) { if (llList2String(path, 2) != "give") return; key id = (key)llList2String(path, 1); string name = llKey2Name(id); string itemName = llUnescapeURL(llList2String(path, 3)); llOwnerSay("Giving '" + itemName + "' to '" + name + "'."); llGiveInventory(id, itemName); prepare_profile_overview_page(requestID, id); return; } } else if (firstPathPart == "anims") { if (numOfPathsParts == 1) { anims_page(); return; } else if (numOfPathsParts == 2) { play_anim(llList2String(path, 1)); anims_page(); return; } } else if (firstPathPart == "video") { responseStatus = 200; responseBody = header + "
<iframe width='255' height='173' src='" + video_url + "' frameborder='0' allowfullscreen></iframe>" + footer; return; } else if (firstPathPart == "config") { if (numOfPathsParts == 1) { config_page(); return; } else if (llList2String(path, 1) == "set") { string queryString = llGetHTTPHeader(requestID, "x-query-string"); list args = llParseString2List(queryString, ["="], ["&"]); integer index = -llGetListLength(args); while (index) { string variable = llList2String(args, index); string value = llUnescapeURL(llList2String(args, index + 1)); if (variable == "video") video_url = value; //because: var,val,&,var,val,&,... index = index + 3; } config_page(); } } responseStatus = 404;
responseBody = header + "
404 Page Not Found.
" + footer;
throw_exception("There has been a HTTP-request to a non-existant page on your HUD's website. " + "Please check the path of the request for mistakes.");
}
// user-function: prepare_profile_overview_page // - does not return anything // - prepares a response for a page with information about a certain avatar // - includes profile thumbnail, name, script info, give menu
prepare_profile_overview_page(key requestID, key id) {
list avatarDetails = llGetObjectDetails(id, [ OBJECT_POS, OBJECT_TOTAL_SCRIPT_COUNT, OBJECT_SCRIPT_MEMORY, OBJECT_SCRIPT_TIME]); responseStatus = 200; responseBody = header
+ "
"
+ "" + html_body_with_formatted_avatar_name(id) + "" + llGetUsername(id) + " | "
+ html_body_with_links_for_interaction_with_certain_avatar(id) + "+ html_body_with_inventory_overview_for_give_menu(id) + " | |
"
+ html_body_avatar_profile_pic_thumbnail(id)+ " |
|
" + footer;
}
// user-function: html_body_with_formatted_avatar_name // - returns the name of the avatar in html format // - removes the lastname if it is Resident // - adds a line-break for long names
string html_body_with_formatted_avatar_name(key id) {
string stringToReturn = llKey2Name(id); if (llGetSubString(stringToReturn, -9, -1) == " Resident") stringToReturn = llDeleteSubString(stringToReturn, -9, -1); if (15 < llStringLength(stringToReturn)) stringToReturn = llDumpList2String(llParseString2List(stringToReturn,[" "], []), "
"); return stringToReturn;
}
// user-function: html_body_with_links_for_interaction_with_certain_avatar // - returns html text with links for an avatar to interact with who has a certain uuid
string html_body_with_links_for_interaction_with_certain_avatar(key id) {
return "
";
}
// user-function: html_body_with_inventory_overview_for_give_menu // - returns html text with inventory item lists
string html_body_with_inventory_overview_for_give_menu(key id) {
string stringToReturn = "
";
return stringToReturn;
}
// user-function: bytes2str // - returns a string with script memory info in readable format
string bytes2str(integer bytes) {
// 1024² = 1048576 if (bytes < 1048576) return (string)(bytes / 1024) + " KB"; //else return (string)(bytes / 1048576) + " MB";
}
// user-function: html_body_avatar_profile_pic_thumbnail // - returns html text with urls to someone's profile pic
string html_body_avatar_profile_pic_thumbnail(key id) {
return "<a href='secondlife:///app/agent/" + (string)id + "/about' 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(id) + "/sl_image.png' /></a>";
}
// user-function: inventory_list_in_html_format_for_give_menu // - returns html text with inventory item list of given type
string inventory_list_in_html_format_for_give_menu(key id, integer type) {
string stringToReturn; integer index = llGetInventoryNumber(type); while (index) { --index; string name = llGetInventoryName(type, index);
stringToReturn += "
"; } return stringToReturn; } // user-function: anims_page // - does not return anything // - prepares an html text overview page of animations anims_page() { responseStatus = 200; responseBody = header + "
Animations
Choose an animation:
" + footer;
}
// user-function: html_body_animations_overview // - returns html text with a list of included animations
string html_body_animations_overview() {
string stringToReturn = "
";
return stringToReturn;
}
// user-function: play_anim // - does not return anything // - prompts a perms request to animate owner
play_anim(string anim) {
llRequestPermissions(owner, PERMISSION_TRIGGER_ANIMATION); currentAnimation = llUnescapeURL(anim);
}
// user-function: config_page // - does not return anything // - prepares page to configure youtube video link
config_page() {
responseStatus = 200;
responseBody = header + "
Options:
<form action='config/set' method='get'>Video URL: "
+ "<input type='text' name='video' value='" + video_url + "' /><input type='submit' value='Set' /></form>" + footer;
}
// user-function: throw_exception // - does not return anything // - logs errors into cache for later viewing and debugging
throw_exception(string inputString) {
if (exceptions == "") exceptions = "The following un-handled exception(s) occurred that are preventing this device's operation:\n"; exceptions += "\t"+inputString+"\n";
}
default {
on_rez(integer start_param) { llReleaseURL(url); llResetScript(); } changed(integer change) { if (change & (CHANGED_OWNER | CHANGED_INVENTORY)) { llReleaseURL(url); llResetScript(); } if (change & (CHANGED_REGION | CHANGED_REGION_START | CHANGED_TELEPORT)) request_url(); } state_entry() { init(); } touch_start(integer num_detected) { toggle_visibility_of_HUD_button(); } http_request(key id, string method, string body) { integer sendResponseNow = TRUE; responseStatus = 400; responseBody = "Unsupported method"; if (method == URL_REQUEST_GRANTED) { responseStatus = 200; responseBody = "OK"; set_link_media(body); } else if (method == URL_REQUEST_DENIED) { responseStatus = 400; responseBody = "Bad request"; throw_exception("The following error occurred while attempting to get a free URL for this device:\n \n" + body); } else if (method == "GET") { responseStatus = 200; responseBody = "GET"; string pathInfoHeader = llGetHTTPHeader(id, "x-path-info"); list path = llParseString2List(pathInfoHeader, ["/"], []); if (path == []) { sendResponseNow = FALSE; currentRequestID = id; llSensor("", NULL_KEY, AGENT_BY_LEGACY_NAME, 96.0, PI); lastPath = []; } else http_get(id, path); }
// check if doing a sensor sweep and if so don't send a response // but send the response in 'sensor event' or 'no_sensor event' // // (time-out 30.0 seconds for response)
if (sendResponseNow) { llSetContentType(id, CONTENT_TYPE_HTML); llHTTPResponse(id, responseStatus, responseBody); } if (exceptions != "") state error; } run_time_permissions(integer perm) { if (perm & PERMISSION_TRIGGER_ANIMATION) { llStartAnimation(currentAnimation); } else throw_exception("This HUD has tried to animate your avatar WITHOUT having the permissions to do so. " + "You must grant this HUD permissions to animate your avatar for this feature to work."); if (exceptions != "") state error; } sensor(integer num_detected) { responseStatus = 200;
responseBody = header + "
Scan Results:
- ";
if (14 < num_detected) num_detected = 14; while (num_detected) { --num_detected; key id = llDetectedKey(num_detected);responseBody += "
" + footer;
llSetContentType(currentRequestID, CONTENT_TYPE_HTML); llHTTPResponse(currentRequestID, responseStatus, responseBody); } no_sensor() { responseStatus = 200;
responseBody = header + "
Scan Results:
- "
+ "
- No one near by.
- Owner: <a href='agent/" + (string)owner + "'>" + ownerName + "</a>
" + footer;
llSetContentType(currentRequestID, CONTENT_TYPE_HTML); llHTTPResponse(currentRequestID, responseStatus, responseBody); } state_exit() { llReleaseURL(url); }
}
state error {
on_rez(integer start_param) { llResetScript(); } changed(integer change) { if (change & (CHANGED_OWNER | CHANGED_INVENTORY)) llResetScript(); } state_entry() { llOwnerSay("========== ERROR REPORT START =========="); llOwnerSay(exceptions); llOwnerSay("========== ERROR REPORT END =========="); llOwnerSay("Resetting now..."); llResetScript(); }
} </lsl>