From 48d99a674f9bcbedba98ae12a41990940e4e287c Mon Sep 17 00:00:00 2001 From: Alex Headley Date: Sat, 23 Apr 2011 14:02:00 -0400 Subject: [PATCH 1/7] moving style stuff out of index.html --- web_assets/index.html | 2 +- web_assets/style.css | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/web_assets/index.html b/web_assets/index.html index 89554e8..961dd75 100644 --- a/web_assets/index.html +++ b/web_assets/index.html @@ -14,6 +14,6 @@ -
+
diff --git a/web_assets/style.css b/web_assets/style.css index 8585eb3..19b9b34 100644 --- a/web_assets/style.css +++ b/web_assets/style.css @@ -1,6 +1,18 @@ -html { height: 100% } -body { height: 100%; margin: 0px; padding: 0px ; background-color: #000; } -#mcmap { height: 100% } +html { + height: 100%; +} + +body { + height: 100%; + margin: 0px; + padding: 0px; + background-color: #000; +} + +#mcmap { + width: 100%; + height: 100%; +} .infoWindow { height: 100px; From df2117544d603c0331038aac1aef658b26525a95 Mon Sep 17 00:00:00 2001 From: aheadley Date: Sat, 23 Apr 2011 18:54:12 -0400 Subject: [PATCH 2/7] new js stuff ready for testing --- web_assets/index.html | 12 +- web_assets/overviewer.js | 706 +++++++++++++++++++++++++++++++++ web_assets/overviewerConfig.js | 38 ++ 3 files changed, 748 insertions(+), 8 deletions(-) create mode 100644 web_assets/overviewer.js create mode 100644 web_assets/overviewerConfig.js diff --git a/web_assets/index.html b/web_assets/index.html index 961dd75..14c6666 100644 --- a/web_assets/index.html +++ b/web_assets/index.html @@ -3,17 +3,13 @@ - - - - - + + + - +
diff --git a/web_assets/overviewer.js b/web_assets/overviewer.js new file mode 100644 index 0000000..3b10189 --- /dev/null +++ b/web_assets/overviewer.js @@ -0,0 +1,706 @@ +var overviewer = { + 'map': null, + 'collections': { + 'markerDatas': [], + 'markers': {}, + 'regionDatas': [], + 'regions': {}, + 'overlays': [], + 'mapTypes': {}, + 'infoWindow': null + }, + 'util': { + 'initialize': function() { + overviewer.util.initializeClassPrototypes(); + overviewer.util.initializeMapTypes(); + overviewer.util.initializeMap(); + overviewer.util.initializeMarkers(); + overviewer.util.initializeRegions(); + overviewer.util.createMapControls(); + }, + 'initializeClassPrototypes': function() { + overviewer.classes.MapProjection.prototype.fromLatLngToPoint = function(latLng) { + var x = latLng.lng() * overviewerConfig.CONST.tileSize; + var y = latLng.lat() * overviewerConfig.CONST.tileSize; + return new google.maps.Point(x, y); + }; + + overviewer.classes.MapProjection.prototype.fromPointToLatLng = function(point) { + var lng = point.x * this.inverseTileSize; + var lat = point.y * this.inverseTileSize; + return new google.maps.LatLng(lat, lng); + }; + + overviewer.classes.CoordMapType.prototype.getTile = function(coord, zoom, ownerDocument) { + var div = ownerDocument.createElement('DIV'); + div.innerHTML = '(' + coord.x + ', ' + coord.y + ', ' + zoom + ')'; + div.innerHTML += '
'; + div.innerHTML += overviewer.collections.mapTypes[0].getTileUrl(coord, zoom); + div.style.width = this.tileSize.width + 'px'; + div.style.height = this.tileSize.height + 'px'; + div.style.fontSize = '10'; + div.style.borderStyle = 'solid'; + div.style.borderWidth = '1px'; + div.style.borderColor = '#AAAAAA'; + return div; + }; + }, + /** + * I think this was old code that was replaced by stuff that is now + * in initializeMap() + */ + 'initializeMapTypes': function() { + var mapOptions = {}; + for (i in overviewerConfig.mapTypes) { + var view = overviewerConfig.mapTypes[i]; + var imageFormat = view.imgformat ? view.imgformat : 'png'; + mapOptions[view.label] = { + 'getTileUrl': overviewer.gmap.getTileUrlGenerator(view.path, + view.base, imageFormat), + 'tileSize': new google.maps.Size( + overviewerConfig.CONST.tileSize, + overviewerConfig.CONST.tileSize), + 'maxZoom': overviewerConfig.map.maxZoom, + 'minZoom': overviewerConfig.map.minZoom, + 'isPng': imageFormat.toLowerCase() == 'png' + } + overviewer.collections.mapTypes[view.label] = new google.maps.ImageMapType( + mapOptions[view.label]); + overviewer.collections.mapTypes[view.label].name = view.label; + overviewer.collections.mapTypes[view.label].alt = 'Minecraft ' + + view.label + ' Map'; + overviewer.collections.mapTypes[view.label].projection = + new overviewer.classes.MapProjection(); + if (view.overlay) { + overviewer.collections.overlays.push( + overviewer.collections.mapTypes[view.label]); + } else { + overviewer.collections.mapTypeIds.push( + overviewerConfig.CONST.mapDivId + view.label); + } + } + }, + 'initilizeMap': function() { + var defaultCenter = overviewer.util.fromWorldToLatLng( + overviewerConfig.map.center[0], overviewerConfig.map.center[1], + overviewerConfig.map.center[2]); + var lat = defaultCenter.lat(); + var lng = defaultCenter.lng(); + var zoom = overviewerConfig.map.defaultZoom; + var mapcenter; + queryParams = overviewer.util.parseQueryString(); + if (queryParams.lat) { + lat = parseFloat(queryParams.lat); + } + if (queryParams.lng) { + lng = parseFloat(queryParams.lng); + } + if (queryParams.zoom) { + if (queryParams.zoom == 'max') { + zoom = overviewerConfig.map.maxZoom; + } else if (queryParams.zoom == 'min') { + zoom = overviewerConfig.map.minZoom; + } else { + zoom = parseInt(queryParams.zoom); + if (zoom < 0 && zoom + overvierConfig.map.maxZoom >= 0) { + //if zoom is negative, try to treat as "zoom out from max zoom" + zoom += overviewerConfig.map.maxZoom; + } else { + //fall back to default zoom + zoom = overviewerConfig.map.defaultZoom; + } + } + } + if (queryParams.x && queryParams.y && queryParams.z) { + mapcenter = overviewer.util.fromWorldToLatLng(queryParams.x, + queryParams.y, queryParams.z); + // Add a market indicating the user-supplied position + overviewer.collections.markers.push({ + 'msg': 'Coordinates ' + queryParams.x + ', ' + + queryParams.y + ', ' + queryParams.z, + 'y': parseFloat(queryParams.y), + 'x': parseFloat(queryParams.x), + 'z': parseFloat(queryParams.z), + 'type': 'querypos'}); + } else { + mapcenter = new google.maps.LatLng(lat, lng); + } + var mapOptions = { + zoom: zoom, + center: mapcenter, + navigationControl: overviewerConfig.map.controls.navigation, + scaleControl: false, + mapTypeControl: overviewer.collections.mapTypeIds.length > 1, + mapTypeControlOptions: { + mapTypeIds: overviewer.collections.mapTypeIds + }, + mapTypeId: overviewer.util.getDefaultMapTypeId(), + streetViewControl: false + }; + overviewer.map = new google.maps.Map(document.getElementById( + overviewerConfig.CONST.mapDivId), mapOptions); + + if (overviewerConfig.map.debug) { + overviewer.map.overlayMapTypes.insertAt(0, + new CoordMapType(new google.maps.Size( + overviewerConfig.CONST.tileSize, + overviewerConfig.CONST.tileSize))); + google.maps.event.addListener(overviewer.map, 'click', function(event) { + overviewer.util.debug('latLng: (' + event.latLng.lat() + + ', ' + event.latLng.lng() + ')'); + var pnt = overviewer.map.getProjection().fromLatLngToPoint(event.latLng); + overviewer.util.debug('point: ' + pnt); + var pxx = pnt.x * config.tileSize * Math.pow(2, config.maxZoom); + var pxy = pnt.y * config.tileSize * Math.pow(2, config.maxZoom); + overviewer.util.debug('pixel: (' + pxx + ', ' + pxy + ')'); + }); + } + + // Now attach the coordinate map type to the map's registry + for (i in overviewer.collections.mapTypes) { + overviewer.map.mapTypes.set(overviewerConfig.CONST.mapDivId + + overviewer.collections.mapTypes[i].name, + overviewer.collections.mapTypes[i]); + } + + // Make the link again whenever the map changes + google.maps.event.addListener(overviewer.map, 'zoom_changed', function() { + overviewer.util.setViewUrl(); + }); + google.maps.event.addListener(overviewer.map, 'center_changed', function() { + overviewer.util.setViewUrl(); + }); + google.maps.event.addListener(overviewer.map, 'maptypeid_changed', function() { + var newType = overviewer.map.getMapTypeId(); + for(i in overviewerConfig.mapTypes) { + if( overviewerConfig.CONST.mapDivId + + overviewerConfig.mapTypes[i].label == newType ) { + $('#'+overviewerConfig.CONST.mapDivId).css( + 'background-color', overviewerConfig.mapTypes[i].bg_color); + break; + } + } + }); + // We can now set the map to use the 'coordinate' map type + overviewer.map.setMapTypeId(overviewer.util.getDefaultMapTypeId()); + }, + 'initializeMarkers': function() { + //first, give all collections an empty array to work with + for (i in overviewerConfig.objectGroups.markers) { + overviewer.collections.markers[ + overviewerConfig.objectGroups.markers[i].label] = []; + } + for (i in overviewer.collections.markerDatas) { + var markerData = overviewer.collections.markerDatas[i]; + for (j in markerData) { + var item = markerData[j]; + // a default: + var iconURL = ''; + if (item.type == 'spawn') { + // don't filter spawn, always display + var marker = new google.maps.Marker({ + 'position': overviewer.util.fromWorldToLatLng(item.x, + item.y, item.z), + 'map': overviewer.map, + 'title': jQuery.trim(item.msg), + 'icon': overviewerConfig.CONST.image.spawnMarker + }); + continue; + } + + if (item.type == 'querypos') { + // Set on page load if MC x/y/z coords are given in the + // query string + var marker = new google.maps.Marker({ + 'position': overviewer.util.fromWorldToLatLng(item.x, + item.y, item.z), + 'map': overviewer.map, + 'title': jQuery.trim(item.msg), + 'icon': overviewerConfig.CONST.image.queryMarker + }); + continue; + } + + var matched = false; + for (j in overviewerConfig.objectGroups.signs) { + var signGroup = overviewerConfig.objectGroups.signs[j]; + var label = signGroup.label; + if (signGroup.match(item)) { + matched = true; + // can add custom types of images for externally defined + // item types, like 'command' here. + if (item.type == 'sign') { + iconURL = overviewerConfig.CONST.image.signMarker; + } + overviewer.util.debug('Sign icon: ' + signGroup.icon); + if (signGroup.icon) { + iconURL = signGroup.icon; + } + var converted = fromWorldToLatLng(item.x, item.y, item.z); + var marker = new google.maps.Marker({ + 'position': overviewer.util.fromWorldToLatLng(item.x, + item.y, item.z), + 'map': overviewer.map, + 'title': jQuery.trim(item.msg), + 'icon': iconURL, + 'visible': false + }); + overviewer.collections.markers[label].push(marker); + if (item.type == 'sign') { + overviewer.util.createMarkerInfoWindow(marker); + } + } + } + + if (!matched) { + // is this signpost doesn't match any of the groups in + // config.js, add it automatically to the "__others__" group + if (item.type == 'sign') { + iconURL = overviewerConfig.CONST.image.signMarker; + } + var marker = new google.maps.Marker({position: converted, + 'position': overviewer.util.fromWorldToLatLng(item.x, + item.y, item.z), + 'map': overviewer.map, + 'title': jQuery.trim(item.msg), + 'icon': iconURL, + 'visible': false + }); + if (overviewer.collections.markers['__others__']) { + overviewer.collections.markers['__others__'].push(marker); + } else { + overviewer.collections.markers['__others__'] = [marker]; + } + if (item.type == 'sign') { + overviewer.util.createMarkerInfoWindow(marker, item); + } + } + } + } + }, + 'initializeRegions': function() { + for (i in overviewerConfig.objectGroups.regions) { + overviewer.collections.regions[overviewerConfig.objectGroups.regions[i].label] = []; + } + for (i in overviewer.collections.regionDatas) { + var regionData = overviewer.collections.regionDatas[i]; + for (j in regionData) { + var region = regionData[j]; + // pull all the points out of the regions file. + var converted = new google.maps.MVCArray(); + for (k in region.path) { + var point = region.path[k]; + converted.push(overviewer.util.fromWorldToLatLng( + point.x, point.y, point.z)); + + } + for (k in overviewerConfig.objectGroups.regions) { + var regionGroup = overviewerConfig.objectGroups.regions[k]; + var clickable = regionGroup.clickable; + var label = regionGroup.label; + + if(region.label) { + var name = region.label + } else { + var name = 'rawr'; + clickable = false; // if it doesn't have a name, we dont have to show it. + } + + if (region.closed) { + var shape = new google.maps.Polygon({ + 'name': name, + 'clickable': clickable, + 'geodesic': false, + 'map': null, + 'strokeColor': region.color, + 'strokeOpacity': region.opacity, + 'strokeWeight': overviewerConfig.CONST.regionStrokeWeight, + 'fillColor': region.color, + 'fillOpacity': region.opacity * 0.25, + 'zIndex': j, + 'paths': converted + }); + } else { + var shape = new google.maps.Polyline({ + 'name': name, + 'clickable': clickable, + 'geodesic': false, + 'map': null, + 'strokeColor': region.color, + 'strokeOpacity': region.opacity, + 'strokeWeight': overviewerConfig.CONST.regionStrokeWeight, + 'zIndex': j, + 'path': converted + }); + } + overviewer.collections.regions[label].push(shape); + + if (clickable) { + overviewer.util.createRegionInfoWindow(shape); + } + } + } + } + }, + 'debug': function(msg) { + if (overviewerConfig.map.debug) { + console.log(msg); + } + }, + 'parseQueryString': function() { + var results = {}; + var queryString = location.search.substring(1); + var pairs = queryString.split('&'); + for (i in pairs) { + var pos = pairs[i].indexOf('='); + var key = pairs[i].substring(0,pos).toLowerCase(); + var value = pairs[i].substring(pos+1).toLowerCase(); + overviewer.util.debug( 'Found GET paramter: ' + key + ' = ' + value); + results[key] = value; + } + return results; + }, + 'setViewUrl': function() { + var displayZoom = overviewer.map.getZoom(); + if (displayZoom == overviewerConfig.map.maxZoom) { + displayZoom = 'max'; + } else { + displayZoom -= overviewerConfig.map.maxZoom; + } + var point; + var point = overviewer.util.fromLatLngToWorld( + overviewer.map.getCenter().lat(), overviewer.map.getCenter().lng()); + var viewUrl = location.href.substring(0, location.href.lastIndexOf( + location.search)) + + '?x=' + Math.floor(point.x) + + '&y=' + Math.floor(point.y) + + '&z=' + Math.floor(point.z) + + '&zoom=' + displayZoom; + document.getElementById('link').innerHTML = viewUrl; + + }, + 'getDefaultMapTypeId': function() { + return overviewer.collections.mapTypeIds[0]; + }, + 'fromWorldToLatLng': function(x, z, y) { + // the width and height of all the highest-zoom tiles combined, + // inverted + var perPixel = 1.0 / (overviewerConfig.CONST.tileSize * + Math.pow(2, overviewerConfig.map.maxZoom)); + + // This information about where the center column is may change with + // a different drawing implementation -- check it again after any + // drawing overhauls! + + // point (0, 0, 127) is at (0.5, 0.0) of tile (tiles/2 - 1, tiles/2) + // so the Y coordinate is at 0.5, and the X is at 0.5 - + // ((tileSize / 2) / (tileSize * 2^maxZoom)) + // or equivalently, 0.5 - (1 / 2^(maxZoom + 1)) + var lng = 0.5 - (1.0 / Math.pow(2, overviewerConfig.map.maxZoom + 1)); + var lat = 0.5; + + // the following metrics mimic those in ChunkRenderer.chunk_render + // in "chunk.py" or, equivalently, chunk_render in src/iterate.c + + // each block on X axis adds 12px to x and subtracts 6px from y + lng += 12 * x * perPixel; + lat -= 6 * x * perPixel; + + // each block on Y axis adds 12px to x and adds 6px to y + lng += 12 * y * perPixel; + lat += 6 * y * perPixel; + + // each block down along Z adds 12px to y + lat += 12 * (128 - z) * perPixel; + + // add on 12 px to the X coordinate to center our point + lng += 12 * perPixel; + + return new google.maps.LatLng(lat, lng); + }, + 'fromLatLngToWorld': function(lat, lng) { + // Initialize world x/y/z object to be returned + var point = Array(); + point.x = 0; + point.y = 64; + point.z = 0; + + // the width and height of all the highest-zoom tiles combined, + // inverted + var perPixel = 1.0 / (overviewerConfig.CONST.tileSize * + Math.pow(2, overviewerConfig.map.maxZoom)); + + // Revert base positioning + // See equivalent code in fromWorldToLatLng() + lng -= 0.5 - (1.0 / Math.pow(2, overviewerConfig.map.maxZoom + 1)); + lat -= 0.5; + + // I'll admit, I plugged this into Wolfram Alpha: + // a = (x * 12 * r) + (z * 12 * r), b = (z * 6 * r) - (x * 6 * r) + // And I don't know the math behind solving for for X and Z given + // A (lng) and B (lat). But Wolfram Alpha did. :) I'd welcome + // suggestions for splitting this up into long form and documenting + // it. -RF + point.x = (lng - 2 * lat) / (24 * perPixel) + point.z = (lng + 2 * lat) / (24 * perPixel) + + // Adjust for the fact that we we can't figure out what Y is given + // only latitude and longitude, so assume Y=64. + point.x += 64 + 1; + point.z -= 64 + 2; + + return point; + }, + 'createMapControls': function() { + // viewstate link (little link to where you're looking at the map, + // normally bottom left) + var viewStateDiv = document.createElement('DIV'); + viewStateDiv.id='link'; + // add it to the map, bottom left. + map.controls[google.maps.ControlPosition.BOTTOM_LEFT].push(viewStateDiv); + + // compass rose, in the top right corner + var compassDiv = document.createElement('DIV'); + compassDiv.style.padding = '5px'; + var compassImg = document.createElement('IMG'); + compassImg.src = overviewerConfig.CONST.image.compass; + compassDiv.appendChild(compassImg); + compassDiv.index = 0; + // add it to the map, top right. + map.controls[google.maps.ControlPosition.TOP_RIGHT].push(compassDiv); + + // Spawn button + var homeControlDiv = document.createElement('DIV'); + var homeControl = new overviewer.classes.HomeControl(homeControlDiv); + homeControlDiv.id = 'customControl'; + homeControlDiv.index = 1; + overviewer.map.controls[google.maps.ControlPosition.TOP_RIGHT].push(homeControlDiv); + + // only need to create the control if there are items in the list. + // as defined in config.js + if (overviewerConfig.objectGroups.signs.length > 0) { + // signpost display control + var items = []; + for (i in overviewerConfig.objectGroups.signs) { + var signGroup = overviewerConfig.objectGroups.signs[i]; + var iconURL = signGroup.icon; + if(!iconURL) { + iconURL = overviewerConfig.CONST.image.defaultMarker; + } + items.push({ + 'label': signGroup.label, + 'checked': signGroup.checked, + 'icon': iconURL, + 'action': function(n, item, checked) { + jQuery.each(overviewer.collections.markers[item.label], + function(i,elem) { + elem.setVisible(checked); + } + ); + overviewer.util.debug('Adding sign item: ' + item.label); + } + }); + } + overviewer.util.createDropDown('Signposts', items); + } + + // if there are any regions data, lets show the option to hide/show them. + if (overviewerConfig.objectGroups.regions.length > 0) { + // region display control + var items = []; + for (i in overviewerConfig.objectGroups.regions) { + var regionGroup = overviewerConfig.objectGroups.regions[i]; + items.push({ + 'label': regionGroup.label, + 'checked': regionGroup.checked, + 'action': function(n, item, checked) { + jQuery.each(overviewer.collections.regions[item.label], + function(i,elem) { + // Thanks to LeastWeasel for this line! + elem.setMap(checked ? overviewer.map : null); + } + ); + } + }); + } + overviewer.util.createDropDown('Regions', items); + } + + if (overviewer.collections.overlays.length > 0) { + // overlay maps control + var items = []; + for (i in overviewer.collections.overlays) { + var overlay = overviewer.collections.overlays[i]; + items.push({ + 'label': overlay.name, + 'checked': false, + 'overlay': overlay, + 'action': function(i, item, checked) { + if (checked) { + overviewer.map.overlayMapTypes.push(item.overlay); + } else { + var idx_to_delete = -1; + overviewer.map.overlayMapTypes.forEach(function(e, j) { + if (e == item.overlay) { idx_to_delete = j; } + }); + if (idx_to_delete >= 0) { + overviewer.map.overlayMapTypes.removeAt(idx_to_delete); + } + } + } + }); + } + overviewer.util.createDropDown('Overlays', items); + } + }, + 'createDropDown': function(title, items) { + var control = document.createElement('DIV'); + // let's let a style sheet do most of the styling here + control.id = 'customControl'; + + var controlText = document.createElement('DIV'); + controlText.innerHTML = title; + + var controlBorder = document.createElement('DIV'); + controlBorder.id='top'; + control.appendChild(controlBorder); + controlBorder.appendChild(controlText); + + var dropdownDiv = document.createElement('DIV'); + dropdownDiv.id='dropDown'; + control.appendChild(dropdownDiv); + dropdownDiv.innerHTML=''; + + // add the functionality to toggle visibility of the items + $(controlText).click(function() { + $(dropdownDiv).toggle(); + }); + + // add that control box we've made back to the map. + overviewer.map.controls[google.maps.ControlPosition.TOP_RIGHT].push(control); + + for(i in items) { + // create the visible elements of the item + var item = items[i]; + overviewer.util.debug(item); + var itemDiv = document.createElement('div'); + var itemInput = document.createElement('input'); + itemInput.type='checkbox'; + + // give it a name + $(itemInput).data('label',item.label); + jQuery(itemInput).click((function(local_idx, local_item) { + return function(e) { + item.action(local_idx, local_item, e.target.checked); + }; + })(i, item)); + + // if its checked, its gotta do something, do that here. + if (item.checked) { + itemInput.checked = true; + item.action(i, item.label, item.checked); + } + dropdownDiv.appendChild(itemDiv); + itemDiv.appendChild(itemInput); + var textNode = document.createElement('text'); + if(item.icon) { + textNode.innerHTML = '' + item.label + '
'; + } else { + textNode.innerHTML = item.label + '
'; + } + + itemDiv.appendChild(textNode); + } + }, + 'createRegionInfoWindow': function(shape) { + var infowindow = new google.maps.InfoWindow(); + google.maps.event.addListener(shape, 'click', function(event, i) { + if (overviewer.collections.infoWindow) { + overviewer.collections.infoWindow.close(); + } + // Replace our Info Window's content and position + var contentString = 'Region: ' + shape.name + '
' + + 'Clicked Location:
' + event.latLng.lat() + ', ' + + event.latLng.lng() + '
'; + infowindow.setContent(contentString); + infowindow.setPosition(event.latLng); + infowindow.open(overviewer.map); + overviewer.collections.infoWindow = infowindow; + }); + }, + 'createMarkerInfoWindow': function(marker) { + var windowContent = '

' + marker.title.replace(/\n/g,'
') + '

'; + var infowindow = new google.maps.InfoWindow({ + 'content': windowContent + }); + google.maps.event.addListener(marker, 'click', function() { + if (overviewer.collections.infoWindow) { + overviewer.collections.infoWindow.close(); + } + infowindow.open(overviewer.map, marker); + overviewer.collections.infoWindow = infowindow; + }); + } + }, + 'classes': { + 'HomeControl': function(controlDiv) { + controlDiv.style.padding = '5px'; + // Set CSS for the control border + var control = document.createElement('DIV'); + control.id='top'; + control.title = 'Click to center the map on the Spawn'; + controlDiv.appendChild(control); + + // Set CSS for the control interior + var controlText = document.createElement('DIV'); + controlText.innerHTML = 'Spawn'; + controlText.id='button'; + control.appendChild(controlText); + + // Setup the click event listeners: simply set the map to map center + // as definned below + google.maps.event.addDomListener(control, 'click', function() { + overviewer.map.panTo(fromWorldToLatLng( + overviewerConfig.map.center[0], + overviewerConfig.map.center[1], + overviewerConfig.map.center[2])); + }); + }, + 'MapProjection' : function() { + this.inverseTileSize = 1.0 / overviewerConfig.CONST.tileSize; + }, + //Looks like this is only used for debugging + 'CoordMapType': function(tileSize) { + this.tileSize = tileSize; + } + }, + 'gmap': { + 'getTileUrlGenerator': function(path, pathBase, pathExt) { + return function(tile, zoom) { + var url = path; + var urlBase = ( pathBase ? pathBase : '' ); + if(tile.x < 0 || tile.x >= Math.pow(2, zoom) || + tile.y < 0 || tile.y >= Math.pow(2, zoom)) { + url += '/blank'; + } else if(zoom == 0) { + url += '/base'; + } else { + for(var z = zoom - 1; z >= 0; --z) { + var x = Math.floor(tile.x / Math.pow(2, z)) % 2; + var y = Math.floor(tile.y / Math.pow(2, z)) % 2; + url += '/' + (x + 2 * y); + } + } + url = url + '.' + pathExt; + if(overviewerConfig.map.cacheMinutes > 0) { + var d = new Date(); + url += '?c=' + Math.floor(d.getTime() / + (1000 * 60 * overviewerConfig.map.cacheMinutes)); + } + return(urlBase + url); + } + } + } +}; \ No newline at end of file diff --git a/web_assets/overviewerConfig.js b/web_assets/overviewerConfig.js new file mode 100644 index 0000000..a0e8f33 --- /dev/null +++ b/web_assets/overviewerConfig.js @@ -0,0 +1,38 @@ +var overviewerConfig = { + //These will probably never change + 'CONST': { + 'tileSize': 384, + 'image': { + 'defaultMarker': 'signpost.png', + 'signMarker': 'signpost_icon.png', + 'compass': 'compass.png', + 'spawnMarker': 'http://google-maps-icons.googlecode.com/files/home.png', + 'queryMarker': 'http://google-maps-icons.googlecode.com/files/regroup.png' + }, + 'mapDivId': 'mcmap', + 'regionStrokeWeight': 2 + }, + 'map': { + 'controls': { + 'navigation': true + }, + 'defaultZoom': 0, + 'minZoom': {minzoom}, + 'maxZoom': {maxzoom}, + 'center': {spawn_coords}, + 'cacheMinutes': 0, + 'debug': false, + }, + 'objectGroups': { + 'signs': [ + { + 'label': 'All', + 'match': function(sign) { + return true; + } + } + ], + 'regions': [] + }, + 'mapTypes': {maptypedata} +}; \ No newline at end of file From 37a7b28bc8104f4362852c8ce3fac59c03afe4ca Mon Sep 17 00:00:00 2001 From: Alex Headley Date: Sat, 23 Apr 2011 20:21:59 -0400 Subject: [PATCH 3/7] fixes from testing --- web_assets/overviewer.js | 70 ++++++++++++++++++---------------- web_assets/overviewerConfig.js | 12 +++++- 2 files changed, 48 insertions(+), 34 deletions(-) diff --git a/web_assets/overviewer.js b/web_assets/overviewer.js index 3b10189..4b0d986 100644 --- a/web_assets/overviewer.js +++ b/web_assets/overviewer.js @@ -7,6 +7,7 @@ var overviewer = { 'regions': {}, 'overlays': [], 'mapTypes': {}, + 'mapTypeIds': [], 'infoWindow': null }, 'util': { @@ -35,10 +36,10 @@ var overviewer = { var div = ownerDocument.createElement('DIV'); div.innerHTML = '(' + coord.x + ', ' + coord.y + ', ' + zoom + ')'; div.innerHTML += '
'; - div.innerHTML += overviewer.collections.mapTypes[0].getTileUrl(coord, zoom); + //div.innerHTML += overviewer.collections.mapTypes[0].getTileUrl(coord, zoom); div.style.width = this.tileSize.width + 'px'; div.style.height = this.tileSize.height + 'px'; - div.style.fontSize = '10'; + div.style.fontSize = '10px'; div.style.borderStyle = 'solid'; div.style.borderWidth = '1px'; div.style.borderColor = '#AAAAAA'; @@ -80,7 +81,7 @@ var overviewer = { } } }, - 'initilizeMap': function() { + 'initializeMap': function() { var defaultCenter = overviewer.util.fromWorldToLatLng( overviewerConfig.map.center[0], overviewerConfig.map.center[1], overviewerConfig.map.center[2]); @@ -142,7 +143,7 @@ var overviewer = { if (overviewerConfig.map.debug) { overviewer.map.overlayMapTypes.insertAt(0, - new CoordMapType(new google.maps.Size( + new overviewer.classes.CoordMapType(new google.maps.Size( overviewerConfig.CONST.tileSize, overviewerConfig.CONST.tileSize))); google.maps.event.addListener(overviewer.map, 'click', function(event) { @@ -150,8 +151,10 @@ var overviewer = { ', ' + event.latLng.lng() + ')'); var pnt = overviewer.map.getProjection().fromLatLngToPoint(event.latLng); overviewer.util.debug('point: ' + pnt); - var pxx = pnt.x * config.tileSize * Math.pow(2, config.maxZoom); - var pxy = pnt.y * config.tileSize * Math.pow(2, config.maxZoom); + var pxx = pnt.x * overviewerConfig.CONST.tileSize * + Math.pow(2, overviewerConfig.map.maxZoom); + var pxy = pnt.y * overviewerConfig.CONST.tileSize * + Math.pow(2, overviewerConfig.map.maxZoom); overviewer.util.debug('pixel: (' + pxx + ', ' + pxy + ')'); }); } @@ -186,9 +189,11 @@ var overviewer = { }, 'initializeMarkers': function() { //first, give all collections an empty array to work with - for (i in overviewerConfig.objectGroups.markers) { + for (i in overviewerConfig.objectGroups.signs) { + overviewer.util.debug('Found sign group: ' + + overviewerConfig.objectGroups.signs[i].label); overviewer.collections.markers[ - overviewerConfig.objectGroups.markers[i].label] = []; + overviewerConfig.objectGroups.signs[i].label] = []; } for (i in overviewer.collections.markerDatas) { var markerData = overviewer.collections.markerDatas[i]; @@ -236,7 +241,6 @@ var overviewer = { if (signGroup.icon) { iconURL = signGroup.icon; } - var converted = fromWorldToLatLng(item.x, item.y, item.z); var marker = new google.maps.Marker({ 'position': overviewer.util.fromWorldToLatLng(item.x, item.y, item.z), @@ -245,6 +249,7 @@ var overviewer = { 'icon': iconURL, 'visible': false }); + overviewer.util.debug(label); overviewer.collections.markers[label].push(marker); if (item.type == 'sign') { overviewer.util.createMarkerInfoWindow(marker); @@ -258,7 +263,7 @@ var overviewer = { if (item.type == 'sign') { iconURL = overviewerConfig.CONST.image.signMarker; } - var marker = new google.maps.Marker({position: converted, + var marker = new google.maps.Marker({ 'position': overviewer.util.fromWorldToLatLng(item.x, item.y, item.z), 'map': overviewer.map, @@ -457,7 +462,7 @@ var overviewer = { var viewStateDiv = document.createElement('DIV'); viewStateDiv.id='link'; // add it to the map, bottom left. - map.controls[google.maps.ControlPosition.BOTTOM_LEFT].push(viewStateDiv); + overviewer.map.controls[google.maps.ControlPosition.BOTTOM_LEFT].push(viewStateDiv); // compass rose, in the top right corner var compassDiv = document.createElement('DIV'); @@ -467,7 +472,7 @@ var overviewer = { compassDiv.appendChild(compassImg); compassDiv.index = 0; // add it to the map, top right. - map.controls[google.maps.ControlPosition.TOP_RIGHT].push(compassDiv); + overviewer.map.controls[google.maps.ControlPosition.TOP_RIGHT].push(compassDiv); // Spawn button var homeControlDiv = document.createElement('DIV'); @@ -493,7 +498,7 @@ var overviewer = { 'icon': iconURL, 'action': function(n, item, checked) { jQuery.each(overviewer.collections.markers[item.label], - function(i,elem) { + function(i, elem) { elem.setVisible(checked); } ); @@ -514,14 +519,13 @@ var overviewer = { 'label': regionGroup.label, 'checked': regionGroup.checked, 'action': function(n, item, checked) { - jQuery.each(overviewer.collections.regions[item.label], - function(i,elem) { - // Thanks to LeastWeasel for this line! - elem.setMap(checked ? overviewer.map : null); - } - ); - } - }); + jQuery.each(overviewer.collections.regions[item.label], + function(i,elem) { + // Thanks to LeastWeasel for this line! + elem.setMap(checked ? overviewer.map : null); + }); + } + }); } overviewer.util.createDropDown('Regions', items); } @@ -536,17 +540,19 @@ var overviewer = { 'checked': false, 'overlay': overlay, 'action': function(i, item, checked) { - if (checked) { - overviewer.map.overlayMapTypes.push(item.overlay); - } else { - var idx_to_delete = -1; - overviewer.map.overlayMapTypes.forEach(function(e, j) { - if (e == item.overlay) { idx_to_delete = j; } - }); - if (idx_to_delete >= 0) { - overviewer.map.overlayMapTypes.removeAt(idx_to_delete); + if (checked) { + overviewer.map.overlayMapTypes.push(item.overlay); + } else { + var idx_to_delete = -1; + overviewer.map.overlayMapTypes.forEach(function(e, j) { + if (e == item.overlay) { + idx_to_delete = j; } + }); + if (idx_to_delete >= 0) { + overviewer.map.overlayMapTypes.removeAt(idx_to_delete); } + } } }); } @@ -662,7 +668,7 @@ var overviewer = { // Setup the click event listeners: simply set the map to map center // as definned below google.maps.event.addDomListener(control, 'click', function() { - overviewer.map.panTo(fromWorldToLatLng( + overviewer.map.panTo(overviewer.util.fromWorldToLatLng( overviewerConfig.map.center[0], overviewerConfig.map.center[1], overviewerConfig.map.center[2])); @@ -703,4 +709,4 @@ var overviewer = { } } } -}; \ No newline at end of file +}; diff --git a/web_assets/overviewerConfig.js b/web_assets/overviewerConfig.js index a0e8f33..841841e 100644 --- a/web_assets/overviewerConfig.js +++ b/web_assets/overviewerConfig.js @@ -32,7 +32,15 @@ var overviewerConfig = { } } ], - 'regions': [] + 'regions': [ + { + 'label': 'All', + 'clickable':true, + 'match': function(region) { + return true; + } + } + ] }, 'mapTypes': {maptypedata} -}; \ No newline at end of file +}; From 1c92776e41d5923a798ae7fd2486f6e4b56ea02c Mon Sep 17 00:00:00 2001 From: aheadley Date: Sat, 23 Apr 2011 21:46:41 -0400 Subject: [PATCH 4/7] fixed minor bugs, added comments, made python aware of new files, removed old js files --- config.js | 78 ---- googlemap.py | 12 +- overviewerConfig.js | 138 +++++++ quadtree.py | 4 +- web_assets/functions.js | 702 --------------------------------- web_assets/overviewer.js | 173 +++++++- web_assets/overviewerConfig.js | 46 --- 7 files changed, 313 insertions(+), 840 deletions(-) delete mode 100644 config.js create mode 100644 overviewerConfig.js delete mode 100644 web_assets/functions.js delete mode 100644 web_assets/overviewerConfig.js diff --git a/config.js b/config.js deleted file mode 100644 index 839d724..0000000 --- a/config.js +++ /dev/null @@ -1,78 +0,0 @@ - - var config = { - tileSize: 384, - defaultZoom: 2, - minZoom: {minzoom}, - maxZoom: {maxzoom}, - // center on this point, in world coordinates, ex: - //center: [0,0,0], - center: {spawn_coords}, - cacheMinutes: 0, // Change this to have browsers automatically request new images every x minutes - debug: false - }; - - -/* signGroups -- A list of signpost groups. A signpost can fall into zero, one, or more than one - * group. See below for some examples. - * - * Required: - * label : string. Displayed in the drop down menu control. - * match : function. Applied to each marker (from markers.js). It is returns true if the marker - * Should be part of the group. - * - * Optional: - * checked : boolean. Set to true to have the group visible by default - * icon : string. Used to specify an icon url. - */ -var signGroups = [ -// {label: "'To'", checked: false, match: function(s) {return s.msg.match(/to/)}}, -// {label: "Storage", match: function(s) {return s.msg.match(/storage/i) || s.msg.match(/dirt/i) || s.msg.match(/sand/)}}, -// {label: "Below Sealevel", match: function(s) { return s.y<64;}}, -// {label: "Info", match: function(s) { return s.msg.match("\\[info\\]");}, icon:"http://google-maps-icons.googlecode.com/files/info.png"}, - {label: "All", match: function(s) {return true}}, -]; - -/* regionGroups -- A list of region groups. A region can fall into zero, one, or more than one - * group. See below for some examples. - * regions have been designed to work with the - * WorldGuard Overviewer Region importer at https://github.com/pironic/WG2OvR But your host must support php in order - * to run WG2OvR. You can also continue to use any other region format. - * - * Required: - * label : string. Displayed in the drop down menu control. - * clickable : boolean. Will determine if we should generate an experimental info window - * that shows details about the clicked region. - * NOTE: if a region (as definned in region.js) does not have a label, this will default to false. - * match : function. Applied to each region (from region.js). It returns true if the region - * Should be part of the group. - * - * Optional: - * checked : boolean. Set to true to have the group visible by default - */ -var regionGroups = [ - //{label: "All", clickable: false, checked: false, match: function(s) {return true}}, -]; - -/* mapTypeData -- a list of alternate map renderings available. At least one rendering must be - * listed. When more than one are provided, controls to switch between them are provided, with - * the first one being the default. - * - * Required: - * label : string. Displayed on the control. - * path : string. Location of the rendered tiles. - * Optional: - * base : string. Base of the url path for tile locations, useful for serving tiles from a different server than the js/html server. - * imgformat : string. File extension used for these tiles. Defaults to png. - * overlay : bool. If true, this tile set will be treated like an overlay - -var mapTypeData=[ - {'label': 'Unlit', 'path': 'tiles'}, -// {'label': 'Day', 'path': 'lighting/tiles'}, -// {'label': 'Night', 'path': 'night/tiles', 'imgformat': 'jpg'}, -// {'label': 'Spawn', 'path': 'spawn/tiles', 'base': 'http://example.cdn.amazon.com/'}, -// {'label': 'Overlay', 'path': 'overlay/tiles', 'overlay': true} -]; - */ - -var mapTypeData = {maptypedata}; - diff --git a/googlemap.py b/googlemap.py index 25b5c70..af56fbe 100644 --- a/googlemap.py +++ b/googlemap.py @@ -86,7 +86,7 @@ class MapGen(object): """Writes out config.js, marker.js, and region.js Copies web assets into the destdir""" zoomlevel = self.p - configpath = os.path.join(util.get_program_path(), "config.js") + configpath = os.path.join(util.get_program_path(), "overviewerConfig.js") config = open(configpath, 'r').read() config = config.replace( @@ -108,7 +108,7 @@ class MapGen(object): self.quadtrees) config = config.replace("{maptypedata}", json.dumps(maptypedata)) - with open(os.path.join(self.destdir, "config.js"), 'w') as output: + with open(os.path.join(self.destdir, "overviewerConfig.js"), 'w') as output: output.write(config) bgcolor = (int(self.bg_color[1:3],16), int(self.bg_color[3:5],16), int(self.bg_color[5:7],16), 0) @@ -151,13 +151,13 @@ class MapGen(object): # write out the default marker table with open(os.path.join(self.destdir, "markers.js"), 'w') as output: - output.write("var markerData=[\n") + output.write("overviewer.collections.markerDatas.push([\n") for marker in self.world.POI: output.write(json.dumps(marker)) if marker != self.world.POI[-1]: output.write(",") output.write("\n") - output.write("]\n") + output.write("]);\n") # save persistent data self.world.persistentData['POI'] = self.world.POI @@ -166,11 +166,11 @@ class MapGen(object): # write out the default (empty, but documented) region table with open(os.path.join(self.destdir, "regions.js"), 'w') as output: - output.write('var regionData=[\n') + output.write('overviewer.collections.regionDatas.push([\n') output.write(' // {"color": "#FFAA00", "opacity": 0.5, "closed": true, "path": [\n') output.write(' // {"x": 0, "y": 0, "z": 0},\n') output.write(' // {"x": 0, "y": 10, "z": 0},\n') output.write(' // {"x": 0, "y": 0, "z": 10}\n') output.write(' // ]},\n') - output.write('];') + output.write(']);') diff --git a/overviewerConfig.js b/overviewerConfig.js new file mode 100644 index 0000000..1ceb336 --- /dev/null +++ b/overviewerConfig.js @@ -0,0 +1,138 @@ +var overviewerConfig = { + /** + * These are things that will probably not need to be changed by the user, + * but are there because otherwise changing them is a giant PITA. + */ + 'CONST': { + /** + * Height and width of the tiles in pixels (I think). + */ + 'tileSize': 384, + /** + * Various images used for markers and stuff. + */ + 'image': { + 'defaultMarker': 'signpost.png', + 'signMarker': 'signpost_icon.png', + 'compass': 'compass.png', + 'spawnMarker': 'http://google-maps-icons.googlecode.com/files/home.png', + 'queryMarker': 'http://google-maps-icons.googlecode.com/files/regroup.png' + }, + 'mapDivId': 'mcmap', + 'regionStrokeWeight': 2 + }, + /** + * General map settings. + */ + 'map': { + /** + * Control the visibility of various controls. + */ + 'controls': { + /** + * Navigation controls are the pan and zoom typically on the upper + * left. + */ + 'navigation': true + }, + /** + * The zoom level when the page is loaded without a specific zoom setting + */ + 'defaultZoom': 0, + /** + * This controls how far you can zoom out. + */ + 'minZoom': {minzoom}, + /** + * This controls how close you can zoom in. + */ + 'maxZoom': {maxzoom}, + /** + * Center on this point, in world coordinates. Should be an array, ex: + * [0,0,0] + */ + 'center': {spawn_coords}, + /** + * Set this to tell browsers how long they should cache tiles in minutes. + */ + 'cacheMinutes': 0, + /** + * Set to true to turn on debug mode, which adds a grid to the map along + * with co-ordinates and a bunch of console output. + */ + 'debug': false, + }, + /** + * Group definitions for objects that are partially selectable (signs and + * regions). + */ + 'objectGroups': { + /* signs -- A list of signpost groups. A signpost can fall into zero, + * one, or more than one group. See below for some examples. + * + * Required: + * label : string. Displayed in the drop down menu control. + * match : function. Applied to each marker (from markers.js). It + * is returns true if the marker should be part + * of the group. + * + * Optional: + * checked : boolean. Set to true to have the group visible by default + * icon : string. Used to specify an icon url. + */ + 'signs': [ + //{label: "'To'", checked: false, match: function(s) {return s.msg.match(/to/)}}, + //{label: "Storage", match: function(s) {return s.msg.match(/storage/i) || s.msg.match(/dirt/i) || s.msg.match(/sand/)}}, + //{label: "Below Sealevel", match: function(s) { return s.y<64;}}, + //{label: "Info", match: function(s) { return s.msg.match("\\[info\\]");}, icon:"http://google-maps-icons.googlecode.com/files/info.png"}, + {'label':'All', 'match':function(sign){return true;}} + ], + /* regions -- A list of region groups. A region can fall into zero, + * one, or more than one group. See below for some examples. + * Regions have been designed to work with the WorldGuard Overviewer + * Region importer at @link https://github.com/pironic/WG2OvR but your + * host must support php in order to run WG2OvR. You can also continue + * to use any other region format. + * + * Required: + * label : string. Displayed in the drop down menu control. + * clickable : boolean. Will determine if we should generate an + * experimental info window that shows details + * about the clicked region. + * NOTE: if a region (as defined in region.js) + * does not have a label, this will default to + * false. + * match : function. Applied to each region (from region.js). It + * returns true if the region should be part of + * the group. + * + * Optional: + * checked : boolean. Set to true to have the group visible by default + */ + 'regions': [ + //{'label':'All','clickable':true,'match':function(region){return true;}} + ] + }, + /* mapTypes -- a list of alternate map renderings available. At least one + * rendering must be listed. When more than one are provided, controls to + * switch between them are provided, with the first one being the default. + * + * Required: + * label : string. Displayed on the control. + * path : string. Location of the rendered tiles. + * Optional: + * base : string. Base of the url path for tile locations, useful + * for serving tiles from a different server than + * the js/html server. + * imgformat : string. File extension used for these tiles. Defaults to png. + * overlay : bool. If true, this tile set will be treated like an overlay + * Example: + * 'mapTypes': [ + * {'label': 'Day', 'path': 'lighting/tiles'}, + * {'label': 'Night', 'path': 'night/tiles', 'imgformat': 'jpg'}, + * {'label': 'Spawn', 'path': 'spawn/tiles', 'base': 'http://example.cdn.amazon.com/'}, + * {'label': 'Overlay', 'path': 'overlay/tiles', 'overlay': true} + * ] + */ + 'mapTypes': {maptypedata} +}; \ No newline at end of file diff --git a/quadtree.py b/quadtree.py index 58fef1b..701aa27 100644 --- a/quadtree.py +++ b/quadtree.py @@ -115,10 +115,10 @@ class QuadtreeGen(object): returns -1 if it couldn't be detected, file not found, or nothing in config.js matched """ - indexfile = os.path.join(self.destdir, "config.js") + indexfile = os.path.join(self.destdir, "overviewerConfig.js") if not os.path.exists(indexfile): return -1 - matcher = re.compile(r"maxZoom:\s*(\d+)") + matcher = re.compile(r"maxZoom.*:\s*(\d+)") p = -1 for line in open(indexfile, "r"): res = matcher.search(line) diff --git a/web_assets/functions.js b/web_assets/functions.js deleted file mode 100644 index 847fba9..0000000 --- a/web_assets/functions.js +++ /dev/null @@ -1,702 +0,0 @@ -// var def -var map; // god of the overviewer... bow before the google api. -var markerCollection = {}; // holds groups of markers -var markersInit = false; // only have to load the markers once, this just makes sure we only do it once -var regionCollection = {}; // holds groups of regions -var regionsInit = false; // only have to load the regions once, this just makes sure we only do it once - -var prevInfoWindow = null; - -// add a popup info window to the marker and then the marker to the map. -// marker is the clickable image on the map with all data. -// item is just the same item in the markers.js -function prepareSignMarker(marker, item) { - var c = "

" + item.msg.replace(/\n/g,"
") + "

"; - var infowindow = new google.maps.InfoWindow({content: c - }); - google.maps.event.addListener(marker, 'click', function() { - if (prevInfoWindow) - prevInfoWindow.close() - infowindow.open(map,marker); - prevInfoWindow = infowindow - }); -} - -// reusable function for making drop down menus. -// title = string -// items = array -function createDropDown(title, items) { - var control = document.createElement("DIV"); - control.id = "customControl"; // let's let a style sheet do most of the styling here - - var controlText = document.createElement("DIV"); - controlText.innerHTML = title; - - var controlBorder = document.createElement("DIV"); - controlBorder.id="top"; - control.appendChild(controlBorder); - controlBorder.appendChild(controlText); - - var dropdownDiv = document.createElement("DIV"); - dropdownDiv.id="dropDown"; - control.appendChild(dropdownDiv); - dropdownDiv.innerHTML=""; - - // add the functionality to toggle visibility of the items - $(controlText).click(function() { - $(dropdownDiv).toggle(); - }); - - // add that control box we've made back to the map. - map.controls[google.maps.ControlPosition.TOP_RIGHT].push(control); - - for (idx in items) { - // create the visible elements of the item - var item = items[idx]; - //console.log(item); // debug - var d = document.createElement("div"); - var n = document.createElement("input"); - n.type="checkbox"; - - // give it a name - $(n).data("label",item.label); - jQuery(n).click((function(local_idx, local_item) { - return function(e) { - item.action(local_idx, local_item, e.target.checked); - }; - })(idx, item)); - - // if its checked, its gotta do something, do that here. - if (item.checked) { - n.checked = true; - item.action(idx, item.label, item.checked); - } - dropdownDiv.appendChild(d); - d.appendChild(n) - var textNode = document.createElement("text"); - if(item.icon) { - textNode.innerHTML = "" + item.label + "
"; - } else { - textNode.innerHTML = item.label + "
"; - } - - d.appendChild(textNode); - } -} - -function HomeControl(controlDiv, map) { - - controlDiv.style.padding = '5px'; - - // Set CSS for the control border - var control = document.createElement('DIV'); - control.id='top'; - control.title = 'Click to center the map on the Spawn'; - controlDiv.appendChild(control); - - // Set CSS for the control interior - var controlText = document.createElement('DIV'); - controlText.innerHTML = 'Spawn'; - controlText.id='button'; - control.appendChild(controlText); - - // Setup the click event listeners: simply set the map to map center as definned below - google.maps.event.addDomListener(control, 'click', function() { - map.panTo(fromWorldToLatLng(config.center[0], - config.center[1], - config.center[2])); - }); - -} - - -// need to define the controls including the compass and layer controls. top right! -// input variables are for chumps... and reusable functions. this is neither. -function drawMapControls() { - - // viewstate link (little link to where you're looking at the map, normally bottom left) - var viewStateDiv = document.createElement('DIV'); - viewStateDiv.id="link"; - // add it to the map, bottom left. - map.controls[google.maps.ControlPosition.BOTTOM_LEFT].push(viewStateDiv); - - // compass rose, in the top right corner - var compassDiv = document.createElement('DIV'); - compassDiv.style.padding = '5px'; - var compassImg = document.createElement('IMG'); - compassImg.src="compass.png"; - compassDiv.appendChild(compassImg); - compassDiv.index = 0; - // add it to the map, top right. - map.controls[google.maps.ControlPosition.TOP_RIGHT].push(compassDiv); - - // Spawn button - var homeControlDiv = document.createElement('DIV'); - var homeControl = new HomeControl(homeControlDiv, map); - homeControlDiv.id = "customControl"; - homeControlDiv.index = 1; - map.controls[google.maps.ControlPosition.TOP_RIGHT].push(homeControlDiv); - - - // only need to create the control if there are items in the list. as definned in config.js - if (signGroups.length > 0) { - // signpost display control - - var items = []; - for (idx in signGroups) { - var signGroup = signGroups[idx]; - var iconURL = signGroup.icon; - if (!iconURL) { iconURL = 'signpost.png'; } - items.push({ - "label": signGroup.label, - "checked": signGroup.checked, - "icon": iconURL, - "action": function(n, item, checked) { - jQuery.each(markerCollection[item.label], function(i,elem) { - elem.setVisible(checked); - }); - //alert(item.label); - } - }); - } - createDropDown("Signposts", items); - } - - // if there are any regions data, lets show the option to hide/show them. - if (regionGroups.length > 0) { - // region display control - - var items = []; - for (idx in regionGroups) { - var regionGroup = regionGroups[idx]; - items.push({ - "label": regionGroup.label, - "checked": regionGroup.checked, - "action": function(n, item, checked) { - jQuery.each(regionCollection[item.label], function(i,elem) { - elem.setMap(checked ? map : null); // Thanks to LeastWeasel for this line! - }); - } - }); - } - createDropDown("Regions", items); - } - - if (overlayMapTypes.length > 0) { - // overlay maps control - - var items = []; - for (idx in overlayMapTypes) { - var overlay = overlayMapTypes[idx]; - items.push({"label": overlay.name, "checked": false, "overlay": overlay, - "action": function(i, item, checked) { - if (checked) { - map.overlayMapTypes.push(item.overlay); - } else { - var idx_to_delete = -1; - map.overlayMapTypes.forEach(function(e, j) { - if (e == item.overlay) { idx_to_delete = j; } - }); - if (idx_to_delete >= 0) { - map.overlayMapTypes.removeAt(idx_to_delete); - } - } - }}); - } - createDropDown("Overlays", items); - } -} - -// will be recoded by pi, currently always displays all regions all the time. -// parse the data as definned in the regions.js -function initRegions() { - if (regionsInit) { return; } - if (typeof(regionData) == "undefined") { return; } // skip this if we have no region.js file - regionsInit = true; - - for (i in regionGroups) { - regionCollection[regionGroups[i].label] = []; - } - - for (i in regionData) { - var region = regionData[i]; - - // pull all the points out of the regions file. - var converted = new google.maps.MVCArray(); - var infoPoint = ""; - for (j in region.path) { - var point = region.path[j]; - converted.push(fromWorldToLatLng(point.x, point.y, point.z)); - - } - - for (idx in regionGroups) { - var regionGroup = regionGroups[idx]; - var testfunc = regionGroup.match; - var clickable = regionGroup.clickable - var label = regionGroup.label; - - if(region.label) { - var name = region.label - } else { - var name = 'rawr'; - clickable = false; // if it doesn't have a name, we dont have to show it. - } - - if (region.closed) { - var shape = new google.maps.Polygon({ - name: name, - clickable: clickable, - geodesic: false, - map: null, - strokeColor: region.color, - strokeOpacity: region.opacity, - strokeWeight: 2, - fillColor: region.color, - fillOpacity: region.opacity * 0.25, - zIndex: i, - paths: converted - }); - } else { - var shape = new google.maps.Polyline({ - name: name, - clickable: clickable, - geodesic: false, - map: null, - strokeColor: region.color, - strokeOpacity: region.opacity, - strokeWeight: 2, - zIndex: i, - path: converted - }); - } - regionCollection[label].push(shape); - - if (clickable) { - // add the region infowindow popup - infowindow = new google.maps.InfoWindow(); - google.maps.event.addListener(shape, 'click', function(e,i) { - - var contentString = "Region: "+this.name+"
"; - contentString += "Clicked Location:
" + e.latLng.lat() + "," + e.latLng.lng() + "
"; - - // Replace our Info Window's content and position - infowindow.setContent(contentString); - infowindow.setPosition(e.latLng); - - infowindow.open(map); - - }); - } - } - } -} - -// will initalize all the markers data as found in markers.js -// may need to be reviewed by agrif or someone else... little finicky right now. -function initMarkers() { - if (markersInit) { return; } // oh, we've already done this? nevermind, exit the function. - if (typeof(markerData) == "undefined") { return; } // no markers.js file, so skip this. - markersInit = true; // now that we've started, dont have to do it twice. - - // first, give all collections an empty array to work with - for (i in signGroups) { - markerCollection[signGroups[i].label] = []; - } - - - for (i in markerData) { - var item = markerData[i]; - - // a default: - var iconURL = ''; - if (item.type == 'spawn') { - // don't filter spawn, always display - - iconURL = 'http://google-maps-icons.googlecode.com/files/home.png'; - var converted = fromWorldToLatLng(item.x, item.y, item.z); - var marker = new google.maps.Marker({position: converted, - map: map, - title: jQuery.trim(item.msg), - icon: iconURL - }); - continue; - } - - if (item.type == 'querypos') { - // Set on page load if MC x/y/z coords are given in the query string - - iconURL = 'http://google-maps-icons.googlecode.com/files/regroup.png'; - var converted = fromWorldToLatLng(item.x, item.y, item.z); - var marker = new google.maps.Marker({position: converted, - map: map, - title: jQuery.trim(item.msg), - icon: iconURL - }); - - continue; - } - - var matched = false; - for (idx in signGroups) { - var signGroup = signGroups[idx]; - var testfunc = signGroup.match; - var label = signGroup.label; - - if (testfunc(item)) { - matched = true; - - // can add custom types of images for externally definned item types, like 'command' here. - if (item.type == 'sign') { iconURL = 'signpost_icon.png'; } - - //console.log(signGroup.icon); //debug - if (signGroup.icon) { iconURL = signGroup.icon; } - - var converted = fromWorldToLatLng(item.x, item.y, item.z); - var marker = new google.maps.Marker({position: converted, - map: map, - title: jQuery.trim(item.msg), - icon: iconURL, - visible: false - }); - - markerCollection[label].push(marker); - - if (item.type == 'sign') { - prepareSignMarker(marker, item); - } - } - } - - if (!matched) { - // is this signpost doesn't match any of the groups in config.js, add it automatically to the "__others__" group - if (item.type == 'sign') { iconURL = 'signpost_icon.png';} - - var converted = fromWorldToLatLng(item.x, item.y, item.z); - var marker = new google.maps.Marker({position: converted, - map: map, - title: jQuery.trim(item.msg), - icon: iconURL, - visible: false - }); - if (markerCollection["__others__"]) { - markerCollection["__others__"].push(marker); - } else { - markerCollection["__others__"] = [marker]; - } - - if (item.type == 'sign') { - prepareSignMarker(marker, item); - } - } - - - - } -} - -// update the link in the viewstate. -function makeLink() { - var displayZoom = map.getZoom(); - if (displayZoom == config.maxZoom) { - displayZoom = "max"; - } else { - displayZoom -= config.maxZoom; - } - var xyz; - var xyz = fromLatLngToWorld(map.getCenter().lat(), map.getCenter().lng()); - var a=location.href.substring(0,location.href.lastIndexOf(location.search)) - + "?x=" + Math.floor(xyz.x) - + "&y=" + Math.floor(xyz.y) - + "&z=" + Math.floor(xyz.z) - + "&zoom=" + displayZoom; - document.getElementById("link").innerHTML = a; -} - -// load the map up and add all the functions relevant stuff to the map. -function initialize() { - - var query = location.search.substring(1); - - var defaultCenter = fromWorldToLatLng(config.center[0], - config.center[1], - config.center[2]); - var lat = defaultCenter.lat(); - var lng = defaultCenter.lng(); - - var zoom = config.defaultZoom; - var hasquerypos = false; - var queryx = 0; - var queryy = 64; - var queryz = 0; - var mapcenter; - var pairs = query.split("&"); - for (var i=0; i 1) { - mapTyepControlToggle = true - } - var mapOptions = { - zoom: zoom, - center: mapcenter, - navigationControl: true, - scaleControl: false, - mapTypeControl: mapTyepControlToggle, - mapTypeControlOptions: { - mapTypeIds: mapTypeIds - }, - mapTypeId: mapTypeIdDefault, - streetViewControl: false, - }; - map = new google.maps.Map(document.getElementById('mcmap'), mapOptions); - - if(config.debug) { - map.overlayMapTypes.insertAt(0, new CoordMapType(new google.maps.Size(config.tileSize, config.tileSize))); - - google.maps.event.addListener(map, 'click', function(event) { - //console.log("latLng; " + event.latLng.lat() + ", " + event.latLng.lng()); - - var pnt = map.getProjection().fromLatLngToPoint(event.latLng); - //console.log("point: " + pnt); - - var pxx = pnt.x * config.tileSize * Math.pow(2, config.maxZoom); - var pxy = pnt.y * config.tileSize * Math.pow(2, config.maxZoom); - //console.log("pixel: " + pxx + ", " + pxy); - }); - } - - // Now attach the coordinate map type to the map's registry - for (idx in MCMapType) { - map.mapTypes.set('mcmap' + MCMapType[idx].name, MCMapType[idx]); - } - - // initialize the markers and regions - initMarkers(); - initRegions(); - drawMapControls(); - - //makeLink(); - - // Make the link again whenever the map changes - google.maps.event.addListener(map, 'zoom_changed', function() { - makeLink(); - }); - google.maps.event.addListener(map, 'center_changed', function() { - makeLink(); - }); - google.maps.event.addListener(map, 'maptypeid_changed', function() { - var newType = map.getMapTypeId(); - for(i in mapTypeData) { - if( 'mcmap' + mapTypeData[i].label == newType ) { - $('#mcmap').css('background-color', mapTypeData[i].bg_color); - break; - } - } - }); - // We can now set the map to use the 'coordinate' map type - map.setMapTypeId(mapTypeIdDefault); -} - - -// our custom projection maps Latitude to Y, and Longitude to X as normal, -// but it maps the range [0.0, 1.0] to [0, tileSize] in both directions -// so it is easier to position markers, etc. based on their position -// (find their position in the lowest-zoom image, and divide by tileSize) -function MCMapProjection() { - this.inverseTileSize = 1.0 / config.tileSize; -} - -MCMapProjection.prototype.fromLatLngToPoint = function(latLng) { - var x = latLng.lng() * config.tileSize; - var y = latLng.lat() * config.tileSize; - return new google.maps.Point(x, y); -}; - -MCMapProjection.prototype.fromPointToLatLng = function(point) { - var lng = point.x * this.inverseTileSize; - var lat = point.y * this.inverseTileSize; - return new google.maps.LatLng(lat, lng); -}; - -// helper to get map LatLng from world coordinates -// takes arguments in X, Y, Z order -// (arguments are *out of order*, because within the function we use -// the axes like the rest of Minecraft Overviewer -- with the Z and Y -// flipped from normal minecraft usage.) -function fromWorldToLatLng(x, z, y) -{ - // the width and height of all the highest-zoom tiles combined, inverted - var perPixel = 1.0 / (config.tileSize * Math.pow(2, config.maxZoom)); - - // This information about where the center column is may change with a different - // drawing implementation -- check it again after any drawing overhauls! - - // point (0, 0, 127) is at (0.5, 0.0) of tile (tiles/2 - 1, tiles/2) - // so the Y coordinate is at 0.5, and the X is at 0.5 - ((tileSize / 2) / (tileSize * 2^maxZoom)) - // or equivalently, 0.5 - (1 / 2^(maxZoom + 1)) - var lng = 0.5 - (1.0 / Math.pow(2, config.maxZoom + 1)); - var lat = 0.5; - - // the following metrics mimic those in ChunkRenderer.chunk_render in "chunk.py" - // or, equivalently, chunk_render in src/iterate.c - - // each block on X axis adds 12px to x and subtracts 6px from y - lng += 12 * x * perPixel; - lat -= 6 * x * perPixel; - - // each block on Y axis adds 12px to x and adds 6px to y - lng += 12 * y * perPixel; - lat += 6 * y * perPixel; - - // each block down along Z adds 12px to y - lat += 12 * (128 - z) * perPixel; - - // add on 12 px to the X coordinate to center our point - lng += 12 * perPixel; - - return new google.maps.LatLng(lat, lng); -} - -// NOTE: X, Y and Z in this function are Minecraft world definitions -// (that is, X is horizontal, Y is altitude and Z is vertical). -function fromLatLngToWorld(lat, lng) -{ - // Initialize world x/y/z object to be returned - var xyz = Array(); - xyz.x = 0; - xyz.y = 64; - xyz.z = 0; - - // the width and height of all the highest-zoom tiles combined, inverted - var perPixel = 1.0 / (config.tileSize * Math.pow(2, config.maxZoom)); - - // Revert base positioning - // See equivalent code in fromWorldToLatLng() - lng -= 0.5 - (1.0 / Math.pow(2, config.maxZoom + 1)); - lat -= 0.5; - - // I'll admit, I plugged this into Wolfram Alpha: - // a = (x * 12 * r) + (z * 12 * r), b = (z * 6 * r) - (x * 6 * r) - // And I don't know the math behind solving for for X and Z given - // A (lng) and B (lat). But Wolfram Alpha did. :) I'd welcome - // suggestions for splitting this up into long form and documenting - // it. -RF - xyz.x = (lng - 2 * lat) / (24 * perPixel) - xyz.z = (lng + 2 * lat) / (24 * perPixel) - - // Adjust for the fact that we we can't figure out what Y is given - // only latitude and longitude, so assume Y=64. - xyz.x += 64 + 1; - xyz.z -= 64 + 2; - - return xyz; -} - -function getTileUrlGenerator(path, path_base, path_ext) { - return function(tile, zoom) { - var url = path; - var url_base = ( path_base ? path_base : '' ); - if(tile.x < 0 || tile.x >= Math.pow(2, zoom) || tile.y < 0 || tile.y >= Math.pow(2, zoom)) { - url += '/blank'; - } else if(zoom == 0) { - url += '/base'; - } else { - for(var z = zoom - 1; z >= 0; --z) { - var x = Math.floor(tile.x / Math.pow(2, z)) % 2; - var y = Math.floor(tile.y / Math.pow(2, z)) % 2; - url += '/' + (x + 2 * y); - } - } - url = url + '.' + path_ext; - if(config.cacheMinutes > 0) { - var d = new Date(); - url += '?c=' + Math.floor(d.getTime() / (1000 * 60 * config.cacheMinutes)); - } - return(url_base + url); - } -} - -var MCMapOptions = new Array; -var MCMapType = new Array; -var mapTypeIdDefault = null; -var mapTypeIds = []; -var overlayMapTypes = []; -for (idx in mapTypeData) { - var view = mapTypeData[idx]; - var imgformat = view.imgformat ? view.imgformat : 'png'; - - MCMapOptions[view.label] = { - getTileUrl: getTileUrlGenerator(view.path, view.base, imgformat), - tileSize: new google.maps.Size(config.tileSize, config.tileSize), - maxZoom: config.maxZoom, - minZoom: config.minZoom, - isPng: !(imgformat.match(/^png$/i) == null) - }; - - MCMapType[view.label] = new google.maps.ImageMapType(MCMapOptions[view.label]); - MCMapType[view.label].name = view.label; - MCMapType[view.label].alt = "Minecraft " + view.label + " Map"; - MCMapType[view.label].projection = new MCMapProjection(); - - if (view.overlay) { - overlayMapTypes.push(MCMapType[view.label]); - } else { - if (mapTypeIdDefault == null) { - mapTypeIdDefault = 'mcmap' + view.label; - } - mapTypeIds.push('mcmap' + view.label); - } -} - -function CoordMapType() { -} - -function CoordMapType(tileSize) { - this.tileSize = tileSize; -} - -CoordMapType.prototype.getTile = function(coord, zoom, ownerDocument) { - var div = ownerDocument.createElement('DIV'); - div.innerHTML = "(" + coord.x + ", " + coord.y + ", " + zoom + ")"; - div.innerHTML += "
"; - div.innerHTML += MCMapOptions.getTileUrl(coord, zoom); - div.style.width = this.tileSize.width + 'px'; - div.style.height = this.tileSize.height + 'px'; - div.style.fontSize = '10'; - div.style.borderStyle = 'solid'; - div.style.borderWidth = '1px'; - div.style.borderColor = '#AAAAAA'; - return div; -}; diff --git a/web_assets/overviewer.js b/web_assets/overviewer.js index 4b0d986..a298bf0 100644 --- a/web_assets/overviewer.js +++ b/web_assets/overviewer.js @@ -1,16 +1,56 @@ var overviewer = { + /** + * This holds the map, probably the most important var in this file + */ 'map': null, + /** + * These are collections of data used in various places + */ 'collections': { + /** + * A list of lists of raw marker data objects, this will allow for an + * arbitrary number of marker data sources. This replaces the old + * markerData var from markers.js. Now you can add markers by including + * a file with: + * overviewer.collections.markerDatas.push([]); + */ 'markerDatas': [], + /** + * The actual Marker objects are stored here. + */ 'markers': {}, + /** + * Same as markerDatas, list of lists of raw region objects. + */ 'regionDatas': [], + /** + * The actual Region objects. + */ 'regions': {}, + /** + * Overlay mapTypes (like Spawn) will go in here. + */ 'overlays': [], + /** + * MapTypes that aren't overlays will end up in here. + */ 'mapTypes': {}, + /** + * The mapType names are in here. + */ 'mapTypeIds': [], + /** + * This is the current infoWindow object, we keep track of it so that + * there is only one open at a time. + */ 'infoWindow': null }, 'util': { + /** + * General initialization function, called when the page is loaded. + * Probably shouldn't need changing unless some very different kind of new + * feature gets added. + */ 'initialize': function() { overviewer.util.initializeClassPrototypes(); overviewer.util.initializeMapTypes(); @@ -19,6 +59,11 @@ var overviewer = { overviewer.util.initializeRegions(); overviewer.util.createMapControls(); }, + /** + * This adds some methods to these classes because Javascript is stupid + * and this seems like the best way to avoid re-creating the same methods + * on each object at object creation time. + */ 'initializeClassPrototypes': function() { overviewer.classes.MapProjection.prototype.fromLatLngToPoint = function(latLng) { var x = latLng.lng() * overviewerConfig.CONST.tileSize; @@ -34,9 +79,14 @@ var overviewer = { overviewer.classes.CoordMapType.prototype.getTile = function(coord, zoom, ownerDocument) { var div = ownerDocument.createElement('DIV'); - div.innerHTML = '(' + coord.x + ', ' + coord.y + ', ' + zoom + ')'; - div.innerHTML += '
'; + div.innerHTML = '(' + coord.x + ', ' + coord.y + ', ' + zoom + + ')' + '
'; + //TODO: figure out how to get the current mapType, I think this + //will add the maptile url to the grid thing once it works + //div.innerHTML += overviewer.collections.mapTypes[0].getTileUrl(coord, zoom); + + //this should probably just have a css class div.style.width = this.tileSize.width + 'px'; div.style.height = this.tileSize.height + 'px'; div.style.fontSize = '10px'; @@ -47,8 +97,8 @@ var overviewer = { }; }, /** - * I think this was old code that was replaced by stuff that is now - * in initializeMap() + * Setup the varous mapTypes before we actually create the map. This used + * to be a bunch of crap down at the bottom of functions.js */ 'initializeMapTypes': function() { var mapOptions = {}; @@ -81,6 +131,12 @@ var overviewer = { } } }, + /** + * This is where the magic happens. We setup the map with all it's + * options. The query string is also parsed here so we can know if + * we should be looking at a particular point on the map or just use + * the default view. + */ 'initializeMap': function() { var defaultCenter = overviewer.util.fromWorldToLatLng( overviewerConfig.map.center[0], overviewerConfig.map.center[1], @@ -103,7 +159,7 @@ var overviewer = { zoom = overviewerConfig.map.minZoom; } else { zoom = parseInt(queryParams.zoom); - if (zoom < 0 && zoom + overvierConfig.map.maxZoom >= 0) { + if (zoom < 0 && zoom + overviewerConfig.map.maxZoom >= 0) { //if zoom is negative, try to treat as "zoom out from max zoom" zoom += overviewerConfig.map.maxZoom; } else { @@ -187,6 +243,12 @@ var overviewer = { // We can now set the map to use the 'coordinate' map type overviewer.map.setMapTypeId(overviewer.util.getDefaultMapTypeId()); }, + /** + * Read through overviewer.collections.markerDatas and create Marker + * objects and stick them in overviewer.collections.markers . This + * should probably be done differently at some point so that we can + * support markers that change position more easily. + */ 'initializeMarkers': function() { //first, give all collections an empty array to work with for (i in overviewerConfig.objectGroups.signs) { @@ -283,6 +345,9 @@ var overviewer = { } } }, + /** + * Same as initializeMarkers() for the most part. + */ 'initializeRegions': function() { for (i in overviewerConfig.objectGroups.regions) { overviewer.collections.regions[overviewerConfig.objectGroups.regions[i].label] = []; @@ -347,11 +412,22 @@ var overviewer = { } } }, + /** + * Gee, I wonder what this does. + * + * @param string msg + */ 'debug': function(msg) { if (overviewerConfig.map.debug) { console.log(msg); } }, + /** + * Simple helper function to split the query string into key/value + * pairs. Doesn't do any type conversion but both are lowercase'd. + * + * @return Object + */ 'parseQueryString': function() { var results = {}; var queryString = location.search.substring(1); @@ -365,6 +441,10 @@ var overviewer = { } return results; }, + /** + * Set the link (at the bottom of the screen) to the current view. + * TODO: make this preserve the mapTypeId as well + */ 'setViewUrl': function() { var displayZoom = overviewer.map.getZoom(); if (displayZoom == overviewerConfig.map.maxZoom) { @@ -387,6 +467,18 @@ var overviewer = { 'getDefaultMapTypeId': function() { return overviewer.collections.mapTypeIds[0]; }, + /** + * helper to get map LatLng from world coordinates takes arguments in + * X, Y, Z order (arguments are *out of order*, because within the + * function we use the axes like the rest of Minecraft Overviewer -- + * with the Z and Y flipped from normal minecraft usage.) + * + * @param int x + * @param int z + * @param int y + * + * @return google.maps.LatLng + */ 'fromWorldToLatLng': function(x, z, y) { // the width and height of all the highest-zoom tiles combined, // inverted @@ -423,6 +515,16 @@ var overviewer = { return new google.maps.LatLng(lat, lng); }, + /** + * The opposite of fromWorldToLatLng + * NOTE: X, Y and Z in this function are Minecraft world definitions + * (that is, X is horizontal, Y is altitude and Z is vertical). + * + * @param float lat + * @param float lng + * + * @return Array + */ 'fromLatLngToWorld': function(lat, lng) { // Initialize world x/y/z object to be returned var point = Array(); @@ -456,6 +558,10 @@ var overviewer = { return point; }, + /** + * Create and draw the various map controls and other related things + * like the compass, current view link, etc. + */ 'createMapControls': function() { // viewstate link (little link to where you're looking at the map, // normally bottom left) @@ -559,6 +665,12 @@ var overviewer = { overviewer.util.createDropDown('Overlays', items); } }, + /** + * Reusable method for creating drop-down menus + * + * @param string title + * @param array items + */ 'createDropDown': function(title, items) { var control = document.createElement('DIV'); // let's let a style sheet do most of the styling here @@ -619,6 +731,13 @@ var overviewer = { itemDiv.appendChild(textNode); } }, + /** + * Create the pop-up infobox for when you click on a region, this can't + * be done in-line because of stupid Javascript scoping problems with + * closures or something. + * + * @param google.maps.Polygon|google.maps.Polyline shape + */ 'createRegionInfoWindow': function(shape) { var infowindow = new google.maps.InfoWindow(); google.maps.event.addListener(shape, 'click', function(event, i) { @@ -635,6 +754,11 @@ var overviewer = { overviewer.collections.infoWindow = infowindow; }); }, + /** + * Same as createRegionInfoWindow() + * + * @param google.maps.Marker marker + */ 'createMarkerInfoWindow': function(marker) { var windowContent = '

' + marker.title.replace(/\n/g,'
') + '

'; @@ -650,7 +774,16 @@ var overviewer = { }); } }, + /** + * The various classes needed in this file. + */ 'classes': { + /** + * This is the button that centers the map on spawn. Not sure why we + * need a separate class for this and not some of the other controls. + * + * @param documentElement controlDiv + */ 'HomeControl': function(controlDiv) { controlDiv.style.padding = '5px'; // Set CSS for the control border @@ -674,15 +807,43 @@ var overviewer = { overviewerConfig.map.center[2])); }); }, + /** + * Our custom projection maps Latitude to Y, and Longitude to X as + * normal, but it maps the range [0.0, 1.0] to [0, tileSize] in both + * directions so it is easier to position markers, etc. based on their + * position (find their position in the lowest-zoom image, and divide + * by tileSize) + */ 'MapProjection' : function() { this.inverseTileSize = 1.0 / overviewerConfig.CONST.tileSize; }, - //Looks like this is only used for debugging + /** + * This is a mapType used only for debugging, to draw a grid on the screen + * showing the tile co-ordinates and tile path. Currently the tile path + * part does not work. + * + * @param google.maps.Size tileSize + */ 'CoordMapType': function(tileSize) { this.tileSize = tileSize; } }, + /** + * Stuff that we give to the google maps code instead of using ourselves + * goes in here. + * + * Also, why do I keep writing these comments as if I'm multiple people? I + * should probably stop that. + */ 'gmap': { + /** + * Generate a function to get the path to a tile at a particular location + * and zoom level. + * + * @param string path + * @param string pathBase + * @param string pathExt + */ 'getTileUrlGenerator': function(path, pathBase, pathExt) { return function(tile, zoom) { var url = path; diff --git a/web_assets/overviewerConfig.js b/web_assets/overviewerConfig.js deleted file mode 100644 index 841841e..0000000 --- a/web_assets/overviewerConfig.js +++ /dev/null @@ -1,46 +0,0 @@ -var overviewerConfig = { - //These will probably never change - 'CONST': { - 'tileSize': 384, - 'image': { - 'defaultMarker': 'signpost.png', - 'signMarker': 'signpost_icon.png', - 'compass': 'compass.png', - 'spawnMarker': 'http://google-maps-icons.googlecode.com/files/home.png', - 'queryMarker': 'http://google-maps-icons.googlecode.com/files/regroup.png' - }, - 'mapDivId': 'mcmap', - 'regionStrokeWeight': 2 - }, - 'map': { - 'controls': { - 'navigation': true - }, - 'defaultZoom': 0, - 'minZoom': {minzoom}, - 'maxZoom': {maxzoom}, - 'center': {spawn_coords}, - 'cacheMinutes': 0, - 'debug': false, - }, - 'objectGroups': { - 'signs': [ - { - 'label': 'All', - 'match': function(sign) { - return true; - } - } - ], - 'regions': [ - { - 'label': 'All', - 'clickable':true, - 'match': function(region) { - return true; - } - } - ] - }, - 'mapTypes': {maptypedata} -}; From 219fa3e7a975a1887be5327e1c417f479f794158 Mon Sep 17 00:00:00 2001 From: Alex Headley Date: Sat, 23 Apr 2011 23:36:29 -0400 Subject: [PATCH 5/7] fixed remaining known bugs made zoom/pan controls independently toggle-able re-added markers.js and regions.js to index.html fixed adding marker from query string fixed initial bg_color setting --- overviewerConfig.js | 11 +++++---- web_assets/index.html | 2 ++ web_assets/overviewer.js | 49 +++++++++++++++++++++++++--------------- 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/overviewerConfig.js b/overviewerConfig.js index 1ceb336..8b34a0f 100644 --- a/overviewerConfig.js +++ b/overviewerConfig.js @@ -30,10 +30,13 @@ var overviewerConfig = { */ 'controls': { /** - * Navigation controls are the pan and zoom typically on the upper - * left. + * Pan control is the hand with the arrows around it in the upper left. */ - 'navigation': true + 'pan': true, + /** + * Zoom control is the zoom slider bar in the upper left. + */ + 'zoom': true }, /** * The zoom level when the page is loaded without a specific zoom setting @@ -135,4 +138,4 @@ var overviewerConfig = { * ] */ 'mapTypes': {maptypedata} -}; \ No newline at end of file +}; diff --git a/web_assets/index.html b/web_assets/index.html index 14c6666..b3cb596 100644 --- a/web_assets/index.html +++ b/web_assets/index.html @@ -7,6 +7,8 @@ + + diff --git a/web_assets/overviewer.js b/web_assets/overviewer.js index a298bf0..37b465b 100644 --- a/web_assets/overviewer.js +++ b/web_assets/overviewer.js @@ -172,27 +172,30 @@ var overviewer = { mapcenter = overviewer.util.fromWorldToLatLng(queryParams.x, queryParams.y, queryParams.z); // Add a market indicating the user-supplied position - overviewer.collections.markers.push({ + overviewer.collections.markerDatas.push([{ 'msg': 'Coordinates ' + queryParams.x + ', ' + queryParams.y + ', ' + queryParams.z, 'y': parseFloat(queryParams.y), 'x': parseFloat(queryParams.x), 'z': parseFloat(queryParams.z), - 'type': 'querypos'}); + 'type': 'querypos'}]); } else { mapcenter = new google.maps.LatLng(lat, lng); } var mapOptions = { - zoom: zoom, - center: mapcenter, - navigationControl: overviewerConfig.map.controls.navigation, - scaleControl: false, - mapTypeControl: overviewer.collections.mapTypeIds.length > 1, + zoom: zoom, + center: mapcenter, + panControl: overviewerConfig.map.controls.pan, + scaleControl: false, + mapTypeControl: overviewer.collections.mapTypeIds.length > 1, mapTypeControlOptions: { mapTypeIds: overviewer.collections.mapTypeIds }, - mapTypeId: overviewer.util.getDefaultMapTypeId(), - streetViewControl: false + mapTypeId: overviewer.util.getDefaultMapTypeId(), + streetViewControl: false, + zoomControl: overviewerConfig.map.controls.zoom, + backgroundColor: overviewer.util.getMapTypeBackgroundColor( + overviewer.util.getDefaultMapTypeId()) }; overviewer.map = new google.maps.Map(document.getElementById( overviewerConfig.CONST.mapDivId), mapOptions); @@ -230,15 +233,9 @@ var overviewer = { overviewer.util.setViewUrl(); }); google.maps.event.addListener(overviewer.map, 'maptypeid_changed', function() { - var newType = overviewer.map.getMapTypeId(); - for(i in overviewerConfig.mapTypes) { - if( overviewerConfig.CONST.mapDivId + - overviewerConfig.mapTypes[i].label == newType ) { - $('#'+overviewerConfig.CONST.mapDivId).css( - 'background-color', overviewerConfig.mapTypes[i].bg_color); - break; - } - } + $('#'+overviewerConfig.CONST.mapDivId).css( + 'background-color', overviewer.util.getMapTypeBackgroundColor( + overviewer.map.getMapTypeId())); }); // We can now set the map to use the 'coordinate' map type overviewer.map.setMapTypeId(overviewer.util.getDefaultMapTypeId()); @@ -412,6 +409,22 @@ var overviewer = { } } }, + /** + * Change the map's div's background color according to the mapType's bg_color setting + * + * @param string mapTypeId + * @return string + */ + 'getMapTypeBackgroundColor': function(mapTypeId) { + for(i in overviewerConfig.mapTypes) { + if( overviewerConfig.CONST.mapDivId + + overviewerConfig.mapTypes[i].label == mapTypeId ) { + overviewer.util.debug('Found background color for: ' + + overviewerConfig.mapTypes[i].bg_color); + return overviewerConfig.mapTypes[i].bg_color; + } + } + }, /** * Gee, I wonder what this does. * From 4d76e106e0c39d875594df95641ac473b73f4daa Mon Sep 17 00:00:00 2001 From: Alex Headley Date: Sun, 24 Apr 2011 00:37:37 -0400 Subject: [PATCH 6/7] added some more toggle-able controls --- overviewerConfig.js | 18 +++++++++++++++++- web_assets/overviewer.js | 27 +++++++++++++++++---------- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/overviewerConfig.js b/overviewerConfig.js index 8b34a0f..fd12c49 100644 --- a/overviewerConfig.js +++ b/overviewerConfig.js @@ -36,7 +36,23 @@ var overviewerConfig = { /** * Zoom control is the zoom slider bar in the upper left. */ - 'zoom': true + 'zoom': true, + /** + * Spawn control is the "Spawn" button that centers the map on spawn. + */ + 'spawn': true, + /** + * The compass in the upper right. + */ + 'compass': true, + /** + * The mapType control is the slider for selecting different map types. + */ + 'mapType': true, + /** + * The small box at the bottom that displays the link to the current map view. + */ + 'link': true }, /** * The zoom level when the page is loaded without a specific zoom setting diff --git a/web_assets/overviewer.js b/web_assets/overviewer.js index 37b465b..f927625 100644 --- a/web_assets/overviewer.js +++ b/web_assets/overviewer.js @@ -187,7 +187,8 @@ var overviewer = { center: mapcenter, panControl: overviewerConfig.map.controls.pan, scaleControl: false, - mapTypeControl: overviewer.collections.mapTypeIds.length > 1, + mapTypeControl: overviewerConfig.map.controls.mapType && + overviewer.collections.mapTypeIds.length > 1, mapTypeControlOptions: { mapTypeIds: overviewer.collections.mapTypeIds }, @@ -226,12 +227,6 @@ var overviewer = { } // Make the link again whenever the map changes - google.maps.event.addListener(overviewer.map, 'zoom_changed', function() { - overviewer.util.setViewUrl(); - }); - google.maps.event.addListener(overviewer.map, 'center_changed', function() { - overviewer.util.setViewUrl(); - }); google.maps.event.addListener(overviewer.map, 'maptypeid_changed', function() { $('#'+overviewerConfig.CONST.mapDivId).css( 'background-color', overviewer.util.getMapTypeBackgroundColor( @@ -581,7 +576,15 @@ var overviewer = { var viewStateDiv = document.createElement('DIV'); viewStateDiv.id='link'; // add it to the map, bottom left. - overviewer.map.controls[google.maps.ControlPosition.BOTTOM_LEFT].push(viewStateDiv); + if (overviewerConfig.map.controls.link) { + google.maps.event.addListener(overviewer.map, 'zoom_changed', function() { + overviewer.util.setViewUrl(); + }); + google.maps.event.addListener(overviewer.map, 'center_changed', function() { + overviewer.util.setViewUrl(); + }); + overviewer.map.controls[google.maps.ControlPosition.BOTTOM_LEFT].push(viewStateDiv); + } // compass rose, in the top right corner var compassDiv = document.createElement('DIV'); @@ -591,14 +594,18 @@ var overviewer = { compassDiv.appendChild(compassImg); compassDiv.index = 0; // add it to the map, top right. - overviewer.map.controls[google.maps.ControlPosition.TOP_RIGHT].push(compassDiv); + if (overviewerConfig.map.controls.compass) { + overviewer.map.controls[google.maps.ControlPosition.TOP_RIGHT].push(compassDiv); + } // Spawn button var homeControlDiv = document.createElement('DIV'); var homeControl = new overviewer.classes.HomeControl(homeControlDiv); homeControlDiv.id = 'customControl'; homeControlDiv.index = 1; - overviewer.map.controls[google.maps.ControlPosition.TOP_RIGHT].push(homeControlDiv); + if (overviewerConfig.map.controls.spawn) { + overviewer.map.controls[google.maps.ControlPosition.TOP_RIGHT].push(homeControlDiv); + } // only need to create the control if there are items in the list. // as defined in config.js From b44df77405b4883bc0a9b5be9ca33b60b7121564 Mon Sep 17 00:00:00 2001 From: aheadley Date: Mon, 25 Apr 2011 17:02:04 -0400 Subject: [PATCH 7/7] renamed style.css to be consistent with overviewer.js --- web_assets/index.html | 2 +- web_assets/{style.css => overviewer.css} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename web_assets/{style.css => overviewer.css} (100%) diff --git a/web_assets/index.html b/web_assets/index.html index b3cb596..3798f17 100644 --- a/web_assets/index.html +++ b/web_assets/index.html @@ -2,7 +2,7 @@ - + diff --git a/web_assets/style.css b/web_assets/overviewer.css similarity index 100% rename from web_assets/style.css rename to web_assets/overviewer.css