Radar HUD Demo
What:
- Single prim, single script HUD that shows dots for nearby avatars on a map image.
- Less useful than the mini map.
- Uses LSL's HTTP-In, html 5 canvas and ajax.
- Currently under 16k memory as mono.
To use:
- Create a box, attach it to a HUD point, scale and position as you like.
- Drop this script in it.
Bugs:
- Sometimes it just sits there blank. Not sure how/why. Requires a script restart usually to fix.
TODO:
- Add hover text for people (names)
- Add click action for people (profiles?)
- Rotate the map
- Zoom the map
- Better scans (>16 people)
- Options: scan different things, use different colors.
<lsl> // 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;
string index_html;
key request_id = NULL_KEY;
build_index(string url) {
vector rc = llGetRegionCorner(); string bg_url = "http://map.secondlife.com/map-1-" + (string)((integer)(rc.x / 256)) + "-" + (string)((integer)(rc.y / 256)) + "-objects.jpg"; // Build the index page. index_html =
"<html><head> <script src='http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js' /> <script type='text/javascript' language='javascript'> var me;var req_me = false; var people;var req_people = false;
function plot(ctx, points, color, border, size) {
if (points != undefined) { ctx.fillStyle=color; for ( p in points ) { ctx.fillStyle=border; ctx.fillRect(points[p][0] - 2,points[p][1] - 2,size,size); ctx.fillStyle=color; ctx.fillRect(points[p][0] - 1,points[p][1] - 1,size - 2,size -2); } }
}
function updateMap() {
canvas = document.getElementById( 'myCanvas' ); ctx = canvas.getContext( '2d' ); img = new Image(); img.src = '" + bg_url + "';
if (!req_me) { req_me = true; $.getJSON('mypos',function(data){me = data;req_me=false;}); } if (!req_people) { req_people = true; $.getJSON('avatars',function(data){people = data;req_people=false;}); }
ctx.save(); if (img.complete) { ctx.drawImage( img, 0, 0, canvas.getAttribute('width'), canvas.getAttribute('height') ); }
plot(ctx,people,'#FF0000','#FFFFFF',5); plot(ctx,me,'#FFFFFF','#000000',7); ctx.restore(); setTimeout( updateMap, 500 );
} </script><base href='" + url + "/' /></head> <body style='background: #FFFFFF; width: 100%; height: 100%; margin: 0px;' onLoad='updateMap();'> <canvas id='myCanvas' width='256' height='256' style='position:fixed; top:0px; left:0px;'> Canvas unsupported. </canvas></body></html>"; }
set_url(string url) {
build_index(url);
llSetLinkMedia(LINK_THIS, 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]); llOwnerSay("Mem: " + (string)llGetUsedMemory());
}
default {
state_entry() { llRequestURL(); } on_rez(integer i) { llResetScript(); } changed(integer c) { if (c & (CHANGED_REGION | CHANGED_TELEPORT | CHANGED_OWNER)) { llResetScript(); } }
http_request(key id, string method, string body) { if (method == URL_REQUEST_GRANTED) { set_url(body); } else if (method == URL_REQUEST_DENIED) { llOwnerSay("Failed to get url: " + body); } if (method == "GET") { list path = llParseString2List(llGetHTTPHeader(id,"x-path-info"),["/"],[]); if (llGetListLength(path) == 0) { llSetContentType(id,CONTENT_TYPE_HTML); llHTTPResponse(id,200,index_html); } else if (llList2String(path,0) == "mypos") { vector my_pos = llGetPos(); llHTTPResponse(id,200,"" + (string)((integer)my_pos.x) + "," + (string)(256 - (integer)my_pos.y) + ""); } else if (llList2String(path,0) == "avatars") { if (request_id == NULL_KEY) { // If there is a request_id then we are already scanning. // Only start a scan if there is no request in process. llSensor("",NULL_KEY,AGENT,64,PI); } // Always set the id so we respond to the most recent request. request_id = id; } } } sensor(integer n) { string body = "["; integer i; for(i=0;i<n;++i) { if (i != 0) body += ","; vector pos = llDetectedPos(i); body += "[" + (string)((integer)pos.x) + "," + (string)(256 - (integer)pos.y) + "]"; } body += " ]"; llHTTPResponse(request_id,200,body); request_id = NULL_KEY; } control(key id, integer n, integer e) {} no_sensor() { llHTTPResponse(request_id,200,"[]"); request_id = NULL_KEY; }
} </lsl>