Radar HUD Demo

From Second Life Wiki
Jump to navigation Jump to search
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>