Radar HUD Demo

From Second Life Wiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
screenshots

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.
  • Requires media on a prim be enabled.

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
  • Options: scan different things, use different colors.
  • Make the dots look better
  • Add direction indicator to 'me' dot.

<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;

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")
           {
               list avatars = llGetAgentList(AGENT_LIST_REGION,[]);
           
               string body = "[";
               integer i;
               integer n = llGetListLength(avatars);
               for(i=0;i<n;++i)
               {
                   if (i != 0) body += ",";
                   vector pos = llList2Vector(llGetObjectDetails(llList2Key(avatars,i),[OBJECT_POS]),0);
                   body += "[" + (string)((integer)pos.x) + "," + (string)(256 - (integer)pos.y) + "]";
               }
               body += " ]";
                llHTTPResponse(id,200,body);
           }
       }
   }

} </lsl>