Difference between revisions of "Radar HUD Demo"

From Second Life Wiki
Jump to navigation Jump to search
 
(4 intermediate revisions by the same user not shown)
Line 1: Line 1:
[[File:Radar hud.jpg|200px|thumb|top|screenshots]]
[[File:Radar hud.png|200px|thumb|top|screenshots]]


What:
What:
Line 17: Line 17:
* Rotate the map
* Rotate the map
* Zoom the map
* Zoom the map
* Better scans (>16 people)
* Options: scan different things, use different colors.
* Options: scan different things, use different colors.
* Make the dots look better
* Add direction indicator to 'me' dot.
<lsl>
<lsl>
// License:  
// License:  
Line 24: Line 25:
// 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.  
// 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.
// Created by Kelly Linden, 2011.
 
integer display_face = 4;
integer display_face = 4;
 
string index_html;
string index_html;
 
key request_id = NULL_KEY;
 
build_index(string url)
build_index(string url)
{
{
     vector rc = llGetRegionCorner();
     vector rc = llGetRegionCorner();
     string bg_url = "http://map.secondlife.com/map-1-" + (string)((integer)(rc.x / 256)) + "-" + (string)((integer)(rc.y / 256))  + "-objects.jpg";
     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.
     // Build the index page.
     index_html =  
     index_html =  
Line 43: Line 42:
var me;var req_me = false;
var me;var req_me = false;
var people;var req_people = false;
var people;var req_people = false;
 
function plot(ctx, points, color, border, size) {
function plot(ctx, points, color, border, size) {
   if (points != undefined) {
   if (points != undefined) {
Line 55: Line 54:
   }
   }
}
}
 
function updateMap() {
function updateMap() {
   canvas = document.getElementById( 'myCanvas' );
   canvas = document.getElementById( 'myCanvas' );
Line 61: Line 60:
   img = new Image();
   img = new Image();
   img.src = '" + bg_url + "';
   img.src = '" + bg_url + "';
 
   if (!req_me) {
   if (!req_me) {
       req_me = true;
       req_me = true;
       $.getJSON('mypos',function(data){me = data;req_me=false;});
       $.getJSON('mypos',function(data){me = data;req_me=false;});
   }
   }
 
   if (!req_people) {
   if (!req_people) {
     req_people = true;
     req_people = true;
     $.getJSON('avatars',function(data){people = data;req_people=false;});
     $.getJSON('avatars',function(data){people = data;req_people=false;});
   }
   }
 
   ctx.save();
   ctx.save();
   if (img.complete) {
   if (img.complete) {
     ctx.drawImage( img, 0, 0, canvas.getAttribute('width'), canvas.getAttribute('height') );
     ctx.drawImage( img, 0, 0, canvas.getAttribute('width'), canvas.getAttribute('height') );
   }
   }
 
   plot(ctx,people,'#FF0000','#FFFFFF',5);
   plot(ctx,people,'#FF0000','#FFFFFF',5);
   plot(ctx,me,'#FFFFFF','#000000',7);
   plot(ctx,me,'#FFFFFF','#000000',7);
Line 88: Line 87:
</canvas></body></html>";   
</canvas></body></html>";   
}
}
 
set_url(string url)
set_url(string url)
{
{
     build_index(url);
     build_index(url);
 
     llSetLinkMedia(LINK_THIS, display_face,              // Side to display the media on.
     llSetLinkMedia(LINK_THIS, display_face,              // Side to display the media on.
             [PRIM_MEDIA_AUTO_PLAY,TRUE,    // Show this page immediately
             [PRIM_MEDIA_AUTO_PLAY,TRUE,    // Show this page immediately
Line 100: Line 99:
             PRIM_MEDIA_WIDTH_PIXELS,256,  //  rounded up to nearest power of 2.
             PRIM_MEDIA_WIDTH_PIXELS,256,  //  rounded up to nearest power of 2.
             PRIM_MEDIA_PERMS_CONTROL, PRIM_MEDIA_PERM_NONE]);
             PRIM_MEDIA_PERMS_CONTROL, PRIM_MEDIA_PERM_NONE]);
           
     llOwnerSay("Mem: " + (string)llGetUsedMemory());
     llOwnerSay("Mem: " + (string)llGetUsedMemory());
}
}
 
default
default
{
{
Line 113: Line 112:
         { llResetScript(); }
         { llResetScript(); }
     }
     }
 
     http_request(key id, string method, string body)
     http_request(key id, string method, string body)
     {
     {
Line 124: Line 123:
             llOwnerSay("Failed to get url: " + body);
             llOwnerSay("Failed to get url: " + body);
         }
         }
       
         if (method == "GET")
         if (method == "GET")
         {
         {
             list path = llParseString2List(llGetHTTPHeader(id,"x-path-info"),["/"],[]);
             list path = llParseString2List(llGetHTTPHeader(id,"x-path-info"),["/"],[]);
           
             if (llGetListLength(path) == 0)
             if (llGetListLength(path) == 0)
             {
             {
                 llSetContentType(id,CONTENT_TYPE_HTML);
                 llSetContentType(id,CONTENT_TYPE_HTML);
               
                 llHTTPResponse(id,200,index_html);
                 llHTTPResponse(id,200,index_html);
             }
             }
Line 142: Line 141:
             else if (llList2String(path,0) == "avatars")
             else if (llList2String(path,0) == "avatars")
             {
             {
                 if (request_id == NULL_KEY)
                 list avatars = llGetAgentList(AGENT_LIST_REGION,[]);
           
                string body = "[";
                integer i;
                integer n = llGetListLength(avatars);
                for(i=0;i<n;++i)
                 {
                 {
                     // If there is a request_id then we are already scanning.
                     if (i != 0) body += ",";
                    // Only start a scan if there is no request in process.
                     vector pos = llList2Vector(llGetObjectDetails(llList2Key(avatars,i),[OBJECT_POS]),0);
                     llSensor("",NULL_KEY,AGENT,64,PI);
                    body += "[" + (string)((integer)pos.x) + "," + (string)(256 - (integer)pos.y) + "]";
                 }
                 }
                 // Always set the id so we respond to the most recent request.
                 body += " ]";
                request_id = id;
                llHTTPResponse(id,200,body);
             }
             }
         }
         }
    }
   
    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>
</lsl>

Latest revision as of 09:21, 25 June 2012

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>