Linden Lab Official talk:Map API - Second Life Wiki

Linden Lab Official talk:Map API

From Second Life Wiki

Jump to: navigation, search

Previously, SIM images were available in-world if you knew their UUID, is this going to be the case with the new images, or is there any other way to get a SIM image onto a prim (without using the web page on a prim stuff)?

-- Talwyn Mills.



Will SLPoint be implemented again since the changes made to the API?

The removal of this crucial function has broken most of the user interface at bloghud.com, used by many to blog their Second lives to meatspace. Also many other sites which used this have also broken now. —The preceding unsigned comment was added on 20:18, 3 October 2007 by Koz Farina

Contents

Alternate version of the webmap API

Just a headsup that I've been working on an alternate API for the Second Life webmap: User:SignpostMarv Martin/Webmap API - SignpostMarv Martin 12:06, 28 December 2007 (PST)

disableVoiceInfo and In-World map tiles.

I know on the old Map API you could display an icon showing if that region supported voice chat or not. Not all regions choose to do so, and apparently the map API was able to determine how the estate owner had set that option. I believe that is what the disableVoiceInfo indicated,whether this information was shown or not.

I would like to echo Talwyn Mills' concern about the future of in-world map tile textures. Having the ability to display maps in-world is a feature that shouldn't be forgotten in this endeavor. Darien Caldwell 23:47, 27 January 2009 (UTC)

SLPoint hack

by Sasun Steinbeck

Not having an SLPoint function is a serious roadblock if you want to map a bunch of SLURLs. For my needs I simply wanted to plot markers based on a database of art gallery SLURLs. I implemented my own SLPoint and it works great. Here's what I did:

Since I'm programming in asp.net, it was easiest for me to load a hidden gridview control with my data, which can easily be accessed by javascript as a normal table element after the grid is bound, but you can change the code below to get data from other sources as needed. In my case, the SLURL is not really a slurl but just a string in the format region/x/y/z and is the first column of my table. You can modify the code below to account for different format location parameters.

First create your own "mymaps.js" file, which is also where I implemented my loadmap() function and set up my marker flags

var gallery_flag = new Img("your_graphic.gif", 16, 16, false);
var gallery_icon = new Icon(gallery_flag);
var all_images = [gallery_icon, gallery_icon, gallery_icon, gallery_icon, gallery_icon, gallery_icon];
var mapInstance;
var markerCount; //holds a count of markers loaded for debugging/informational purposes
 
function loadmap(){
	if (mapInstance == null)
	{
		mapInstance = new SLMap(document.getElementById('map-element'));
	}
	mapInstance.centerAndZoomAtSLCoord(new XYPoint(1000, 1000), 6);
	var grid = document.getElementById('GridView1'); //get my gridview table
	markerCount = 0;
	for (i = 1; i < grid.rows.length; i++)
	{
		params = grid.rows[i].cells; //pass in whole row of data. SLURL MUST be first parameter, others are optional.
		SLPoint(params, SLPointCallback); //calls my custom SLPoint defined below
	}
}
 
function SLPoint(params, callback)
{
	var s = params[0].innerHTML.split("/"); //first element of params must be this format: region/x/y/z
	var regionName = s[0];
	var localX = s[1];
	var localY = s[2];
	var varName = "slRegionPos_result";
	var scriptURL = "https://cap.secondlife.com/cap/0/d661249b-2b5a-4436-966a-3d3b8d7a574f?var=" + varName + "&sim_name=" + encodeURIComponent(regionName);
	var onLoadHandler = function () 
	{
		if (slRegionPos_result.error)
		{
			//alert("The region name '" + regionName + "' was not recognised.");
		}
		else
		{
			callback(params, regionName, slRegionPos_result.x + (localX/slTileSize), slRegionPos_result.y + (localY/slTileSize));
		}
	};
	slAddDynamicScript(scriptURL, onLoadHandler);
}

There's some interesting javascript magic going on above. Basically what is going on is that I'm calling that cap.secondlife.com function to convert a region name to coordinates, with the necessary parameters for it, one of which is a callback function, which is added to the parameters via the slAddDynamicScript function. The onLoadHandler function is defined then added with slAddDynamicScript to the scriptURL variable. Note in the onLoadHandler function I'm calling callback() with one of the parameters I passed in to SLPoint. This is a cool way to just pass along other relevant data (for example I pass in the name of the art gallery I'm mapping, as well as the type of gallery and other stuff) to your callback function that you can use when creating your marker. Following the params variable is the region name that I extracted from params (since I've already extracted it) and the results of the cap.secondlife.com call, the x and y coordinates.

Now you must download a local copy of slmapapi.js and comment OUT the dummy SLPoint function implemented there. In your main html file where you will display your map, change your code to load your LOCAL hacked copy of slmapapi.js, not from the slurl.com website. After that, specify your mymaps.js file. Like this: <script src="slmapapi.js" type="text/javascript"></script> <script src="MyMaps.js" type="text/javascript"></script>

Now you need to implement the callback specified in mymaps.js in your main html file. Be sure to define you own teleport_now_graphic.gif.

function SLPointCallback(params, region, x, y) {
	XYreturn = new XYPoint(x, y);
	var marker = new Marker(all_images, XYreturn, { centerOnClick: true });
	//make sure the SLURLs are endcoded correctly!
	var mapWindow = new MapWindow("<div style='margin:10px 0px 0px 0px;'><a href='secondlife://" + params[0].innerHTML  "'><img src='images/teleport_now_graphic.gif' align='right'></a><br>Region: " + region + "</div>", { closeOnMove: true });
	mapInstance.addMarker(marker, mapWindow);
	++markerCount;
}

following this is the body of your html file containing the map elements as per the usual way. Make sure to include the onload event for your body to run the loadmap() function in your mymaps.js file. I hope this helps!!

Click here to see the resulting map of art galleries in SL!

EXTJS Extension

This was adapted from a preexisting google map api but i added functions

API FILE

/*!
 * Ext JS Library 3.1.0
 * Copyright(c) 2006-2009 Ext JS, LLC
 * licensing@extjs.com
 * http://www.extjs.com/license
 */
/**
 * @class Ext.ux.GMapPanel
 * @extends Ext.Panel
 * @author Shea Frederick
 * @mod Dimentox Travanti
 */
Ext.ux.GMapPanel = Ext.extend(Ext.Panel, {
    initComponent : function(){
 
        var defConfig = {
           // plain: true,
           // zoomLevel: 2,
          //  yaw: 180,
          //  pitch: 0,
           // zoom: 0,
           gmapType: 'slmap',
            border: false
        };
 
        Ext.applyIf(this,defConfig);
 
        Ext.ux.GMapPanel.superclass.initComponent.call(this);        
 
    },
    afterRender : function(){
 
        var wh = this.ownerCt.getSize();
        Ext.applyIf(this, wh);
 
        Ext.ux.GMapPanel.superclass.afterRender.call(this);    
 
 
        if (this.gmapType === 'slmap'){
            this.gmap = new SLMap(this.body.dom);
 
          // this.SLPoint("DCS","229.073242","215.953217", "30",this.gmap, "Dim Got Powned HERE!")
 
        }
 
        if (typeof this.addControl == 'object' && this.gmapType === 'map') {
            this.gmap.addControl(this.addControl);
        }
 
        if (typeof this.setCenter === 'object') {
            if (typeof this.setCenter.geoCodeAddr === 'string'){
                this.geoCodeLookup(this.setCenter.geoCodeAddr);
            }else{
                if (this.gmapType === 'map'){
                    var point = new GLatLng(this.setCenter.lat,this.setCenter.lng);
                    this.gmap.setCenter(point, this.zoomLevel);    
                }
                if (typeof this.setCenter.marker === 'object' && typeof point === 'object'){
                    this.addMarker(point,this.setCenter.marker,this.setCenter.marker.clear);
                }
            }
            if (this.gmapType === 'panorama'){
                this.gmap.setLocationAndPOV(new GLatLng(this.setCenter.lat,this.setCenter.lng), {yaw: this.yaw, pitch: this.pitch, zoom: this.zoom});
            }
        }
 
        GEvent.bind(this.gmap, 'load', this, function(){
            this.onMapReady();
        });
 
    },
    onMapReady : function(){
       this.addMarkers(this.markers);
      this.addMapControls();
       this.addOptions();  
    },
 
//    onResize : function(w, h){
//
//        if (typeof this.getMap() == 'object') {
//            this.gmap.checkResize();
//        }
//        
//        Ext.ux.GMapPanel.superclass.onResize.call(this, w, h);
//
//    },
//    setSize : function(width, height, animate){
//        
//        if (typeof this.getMap() == 'object') {
//            this.gmap.checkResize();
//        }
//        
//        Ext.ux.GMapPanel.superclass.setSize.call(this, width, height, animate);
//        
//    },
    getMap : function(){
        var a = this.gmap;
        return a;
 
    },
    getCenter : function(){
 
        return this.getMap().getCenter();
 
    },
    getCenterLatLng : function(){
 
        var ll = this.getCenter();
        return {lat: ll.lat(), lng: ll.lng()};
 
    },
    addMarkers : function(markers) {
 
        if (Ext.isArray(markers)){
            for (var i = 0; i < markers.length; i++) {
                var mkr_point = new GLatLng(markers[i].lat,markers[i].lng);
                this.addMarker(mkr_point,markers[i].marker,false,markers[i].setCenter, markers[i].listeners);
            }
        }
 
    },
    SLPoint : function(regionName, localX, localY, Z, map,msg)
    {
    	//var s = params[0].innerHTML.split("/"); //first element of params must be this format: region/x/y/z
    	//var regionName = s[0];
    	//var localX = s[1];
    	//var localY = s[2];
    	callback = this.SLPointCallback;
    	var varName = "slRegionPos_result";
    	var scriptURL = "https://cap.secondlife.com/cap/0/d661249b-2b5a-4436-966a-3d3b8d7a574f?var=" + varName + "&sim_name=" + encodeURIComponent(regionName);
    	var onLoadHandler = function () 
    	{
    		if (slRegionPos_result.error)
    		{
    			//alert("The region name '" + regionName + "' was not recognised.");
    		}
    		else
    		{
    			callback(regionName, slRegionPos_result.x + (localX/slTileSize), slRegionPos_result.y + (localY/slTileSize),Z, map,msg);
    		}
    	};
    	slAddDynamicScript(scriptURL, onLoadHandler);
    },
    SLPointCallback : function( region, x, y, z, map,msg) {
 
    	XYreturn = new XYPoint(x, y);
    	var yellow_dot_image = new Img("http://www.google.com/intl/en_us/mapfiles/ms/micons/blue-dot.png", 16, 16);
    	var yellow_icon = new Icon(yellow_dot_image);
    	var all_images = [yellow_icon, yellow_icon, yellow_icon, yellow_icon, yellow_icon, yellow_icon];
 
    	//blueIcon.image.mainImage.URL = "http://www.google.com/intl/en_us/mapfiles/ms/micons/blue-dot.png";
 
    	map.centerAndZoomAtSLCoord(XYreturn , 1);
    	var marker = new Marker(all_images, XYreturn, { centerOnClick: true });
    	//make sure the SLURLs are endcoded correctly!
    	var mapWindow = new MapWindow("<div style='color: orange; margin:10px 0px 0px 0px;'>"+ msg +"<br><a href='secondlife:///" + region+ "/"+x+"/"+y+"/"+z+"'><img src='http://slurl.com/_img/teleport_btn.gif' align='left'></a> &nbsp Region: " + region + "</div>", { closeOnMove: true });
    	//var mapWindow = new MapWindow("<div style='color: orange; margin:10px 0px 0px 0px;'>This is where the welcome area fountain is!!</div>");
    	map.addMapWindow(mapWindow, XYreturn);
    	map.addMarker(marker, mapWindow);
 
    },
    addMarker : function(point, marker, clear, center, listeners){
 
        Ext.applyIf(marker,G_DEFAULT_ICON);
 
        if (clear === true){
            this.getMap().clearOverlays();
        }
        if (center === true) {
            this.getMap().setCenter(point, this.zoomLevel);
        }
 
        var mark = new GMarker(point,marker);
        if (typeof listeners === 'object'){
            for (evt in listeners) {
                GEvent.bind(mark, evt, this, listeners[evt]);
            }
        }
        this.getMap().addOverlay(mark);
 
    },
    addMapControls : function(){
 
        if (this.gmapType === 'map') {
            if (Ext.isArray(this.mapControls)) {
                for(i=0;i<this.mapControls.length;i++){
                    this.addMapControl(this.mapControls[i]);
                }
            }else if(typeof this.mapControls === 'string'){
                this.addMapControl(this.mapControls);
            }else if(typeof this.mapControls === 'object'){
                this.getMap().addControl(this.mapControls);
            }
        }
 
    },
    addMapControl : function(mc){
 
        var mcf = window[mc];
        if (typeof mcf === 'function') {
            this.getMap().addControl(new mcf());
        }    
 
    },
    addOptions : function(){
 
        if (Ext.isArray(this.mapConfOpts)) {
            var mc;
            for(i=0;i<this.mapConfOpts.length;i++){
                this.addOption(this.mapConfOpts[i]);
            }
        }else if(typeof this.mapConfOpts === 'string'){
            this.addOption(this.mapConfOpts);
        }        
 
    },
    addOption : function(mc){
 
        var mcf = this.getMap()[mc];
        if (typeof mcf === 'function') {
            this.getMap()[mc]();
        }    
 
    },
    geoCodeLookup : function(addr) {
 
        this.geocoder = new GClientGeocoder();
        this.geocoder.getLocations(addr, this.addAddressToMap.createDelegate(this));
 
    },
    addAddressToMap : function(response) {
 
        if (!response || response.Status.code != 200) {
            Ext.MessageBox.alert('Error', 'Code '+response.Status.code+' Error Returned');
        }else{
            place = response.Placemark[0];
            addressinfo = place.AddressDetails;
            accuracy = addressinfo.Accuracy;
            if (accuracy === 0) {
                Ext.MessageBox.alert('Unable to Locate Address', 'Unable to Locate the Address you provided');
            }else{
                if (accuracy < 7) {
                    Ext.MessageBox.alert('Address Accuracy', 'The address provided has a low accuracy.<br><br>Level '+accuracy+' Accuracy (8 = Exact Match, 1 = Vague Match)');
                }else{
                    point = new GLatLng(place.Point.coordinates[1], place.Point.coordinates[0]);
                    if (typeof this.setCenter.marker === 'object' && typeof point === 'object'){
                        this.addMarker(point,this.setCenter.marker,this.setCenter.marker.clear,true, this.setCenter.listeners);
                    }
                }
            }
        }
 
    }
 
});
 
Ext.reg('gmappanel', Ext.ux.GMapPanel);

Now a simple way how to use. Of course you have the standard headers. and you include this file after your extjs stuff. and you can call it like so.

var mapwin;
 
	mapwin = new Ext.Window({
                layout: 'fit',
                title: 'DCS-XC Death Map!',
                closeAction: 'hide',
                width:800,
                height:600,
                x: 40,
                y: 60,
                items: {
                	id:'dmap',
                    xtype: 'gmappanel',
                    gmapType: 'slmap'
                }
            });
mapwin.show();
	var map = Ext.getCmp('dmap');
	var rmap = map.getMap();
map.SLPoint("region","x","y", "z",rmap, "TEXT To DISPLAY");

Make sure your map has been rendered or the slpoint wont work. You can see it in use at http://www.dcs-xc.org Dimentox Travanti