fixed minor bugs, added comments, made python aware of new files, removed old js files
This commit is contained in:
78
config.js
78
config.js
@@ -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};
|
|
||||||
|
|
||||||
12
googlemap.py
12
googlemap.py
@@ -86,7 +86,7 @@ class MapGen(object):
|
|||||||
"""Writes out config.js, marker.js, and region.js
|
"""Writes out config.js, marker.js, and region.js
|
||||||
Copies web assets into the destdir"""
|
Copies web assets into the destdir"""
|
||||||
zoomlevel = self.p
|
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 = open(configpath, 'r').read()
|
||||||
config = config.replace(
|
config = config.replace(
|
||||||
@@ -108,7 +108,7 @@ class MapGen(object):
|
|||||||
self.quadtrees)
|
self.quadtrees)
|
||||||
config = config.replace("{maptypedata}", json.dumps(maptypedata))
|
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)
|
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)
|
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
|
# write out the default marker table
|
||||||
with open(os.path.join(self.destdir, "markers.js"), 'w') as output:
|
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:
|
for marker in self.world.POI:
|
||||||
output.write(json.dumps(marker))
|
output.write(json.dumps(marker))
|
||||||
if marker != self.world.POI[-1]:
|
if marker != self.world.POI[-1]:
|
||||||
output.write(",")
|
output.write(",")
|
||||||
output.write("\n")
|
output.write("\n")
|
||||||
output.write("]\n")
|
output.write("]);\n")
|
||||||
|
|
||||||
# save persistent data
|
# save persistent data
|
||||||
self.world.persistentData['POI'] = self.world.POI
|
self.world.persistentData['POI'] = self.world.POI
|
||||||
@@ -166,11 +166,11 @@ class MapGen(object):
|
|||||||
|
|
||||||
# write out the default (empty, but documented) region table
|
# write out the default (empty, but documented) region table
|
||||||
with open(os.path.join(self.destdir, "regions.js"), 'w') as output:
|
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(' // {"color": "#FFAA00", "opacity": 0.5, "closed": true, "path": [\n')
|
||||||
output.write(' // {"x": 0, "y": 0, "z": 0},\n')
|
output.write(' // {"x": 0, "y": 0, "z": 0},\n')
|
||||||
output.write(' // {"x": 0, "y": 10, "z": 0},\n')
|
output.write(' // {"x": 0, "y": 10, "z": 0},\n')
|
||||||
output.write(' // {"x": 0, "y": 0, "z": 10}\n')
|
output.write(' // {"x": 0, "y": 0, "z": 10}\n')
|
||||||
output.write(' // ]},\n')
|
output.write(' // ]},\n')
|
||||||
output.write('];')
|
output.write(']);')
|
||||||
|
|
||||||
|
|||||||
138
overviewerConfig.js
Normal file
138
overviewerConfig.js
Normal file
@@ -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}
|
||||||
|
};
|
||||||
@@ -115,10 +115,10 @@ class QuadtreeGen(object):
|
|||||||
returns -1 if it couldn't be detected, file not found, or nothing in
|
returns -1 if it couldn't be detected, file not found, or nothing in
|
||||||
config.js matched
|
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):
|
if not os.path.exists(indexfile):
|
||||||
return -1
|
return -1
|
||||||
matcher = re.compile(r"maxZoom:\s*(\d+)")
|
matcher = re.compile(r"maxZoom.*:\s*(\d+)")
|
||||||
p = -1
|
p = -1
|
||||||
for line in open(indexfile, "r"):
|
for line in open(indexfile, "r"):
|
||||||
res = matcher.search(line)
|
res = matcher.search(line)
|
||||||
|
|||||||
@@ -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 = "<div class=\"infoWindow\"><img src=\"signpost.png\" /><p>" + item.msg.replace(/\n/g,"<br/>") + "</p></div>";
|
|
||||||
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 = "<img width='15' height='15' src='"+item.icon+"'>" + item.label + "<br/>";
|
|
||||||
} else {
|
|
||||||
textNode.innerHTML = item.label + "<br/>";
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = "<b>Region: "+this.name+"</b><br />";
|
|
||||||
contentString += "Clicked Location: <br />" + e.latLng.lat() + "," + e.latLng.lng() + "<br />";
|
|
||||||
|
|
||||||
// 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<pairs.length; i++) {
|
|
||||||
// break each pair at the first "=" to obtain the argname and value
|
|
||||||
var pos = pairs[i].indexOf("=");
|
|
||||||
var argname = pairs[i].substring(0,pos).toLowerCase();
|
|
||||||
var value = pairs[i].substring(pos+1).toLowerCase();
|
|
||||||
|
|
||||||
// process each possible argname
|
|
||||||
if (argname == "lat") {lat = parseFloat(value);}
|
|
||||||
if (argname == "lng") {lng = parseFloat(value);}
|
|
||||||
if (argname == "zoom") {
|
|
||||||
if (value == "max") {
|
|
||||||
zoom = config.maxZoom;
|
|
||||||
} else {
|
|
||||||
zoom = parseInt(value);
|
|
||||||
// If negative, treat as a "zoom out from max zoom" value
|
|
||||||
if (zoom < 0) {zoom = config.maxZoom + zoom;}
|
|
||||||
// If still negative, fall back to default zoom
|
|
||||||
if (zoom < 0) {zoom = config.defaultZoom;}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (argname == "x") {queryx = parseFloat(value); hasquerypos = true;}
|
|
||||||
if (argname == "y") {queryy = parseFloat(value); hasquerypos = true;}
|
|
||||||
if (argname == "z") {queryz = parseFloat(value); hasquerypos = true;}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasquerypos) {
|
|
||||||
mapcenter = fromWorldToLatLng(queryx, queryy, queryz);
|
|
||||||
// Add a market indicating the user-supplied position
|
|
||||||
markerData.push({"msg": "Coordinates " + queryx + ", " + queryy + ", " + queryz, "y": queryy, "x": queryx, "z": queryz, "type": "querypos"})
|
|
||||||
} else {
|
|
||||||
mapcenter = new google.maps.LatLng(lat, lng);
|
|
||||||
}
|
|
||||||
|
|
||||||
var mapTyepControlToggle = false
|
|
||||||
if (mapTypeIds.length > 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 += "<br />";
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
@@ -1,16 +1,56 @@
|
|||||||
var overviewer = {
|
var overviewer = {
|
||||||
|
/**
|
||||||
|
* This holds the map, probably the most important var in this file
|
||||||
|
*/
|
||||||
'map': null,
|
'map': null,
|
||||||
|
/**
|
||||||
|
* These are collections of data used in various places
|
||||||
|
*/
|
||||||
'collections': {
|
'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([<your list of markers>]);
|
||||||
|
*/
|
||||||
'markerDatas': [],
|
'markerDatas': [],
|
||||||
|
/**
|
||||||
|
* The actual Marker objects are stored here.
|
||||||
|
*/
|
||||||
'markers': {},
|
'markers': {},
|
||||||
|
/**
|
||||||
|
* Same as markerDatas, list of lists of raw region objects.
|
||||||
|
*/
|
||||||
'regionDatas': [],
|
'regionDatas': [],
|
||||||
|
/**
|
||||||
|
* The actual Region objects.
|
||||||
|
*/
|
||||||
'regions': {},
|
'regions': {},
|
||||||
|
/**
|
||||||
|
* Overlay mapTypes (like Spawn) will go in here.
|
||||||
|
*/
|
||||||
'overlays': [],
|
'overlays': [],
|
||||||
|
/**
|
||||||
|
* MapTypes that aren't overlays will end up in here.
|
||||||
|
*/
|
||||||
'mapTypes': {},
|
'mapTypes': {},
|
||||||
|
/**
|
||||||
|
* The mapType names are in here.
|
||||||
|
*/
|
||||||
'mapTypeIds': [],
|
'mapTypeIds': [],
|
||||||
|
/**
|
||||||
|
* This is the current infoWindow object, we keep track of it so that
|
||||||
|
* there is only one open at a time.
|
||||||
|
*/
|
||||||
'infoWindow': null
|
'infoWindow': null
|
||||||
},
|
},
|
||||||
'util': {
|
'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() {
|
'initialize': function() {
|
||||||
overviewer.util.initializeClassPrototypes();
|
overviewer.util.initializeClassPrototypes();
|
||||||
overviewer.util.initializeMapTypes();
|
overviewer.util.initializeMapTypes();
|
||||||
@@ -19,6 +59,11 @@ var overviewer = {
|
|||||||
overviewer.util.initializeRegions();
|
overviewer.util.initializeRegions();
|
||||||
overviewer.util.createMapControls();
|
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() {
|
'initializeClassPrototypes': function() {
|
||||||
overviewer.classes.MapProjection.prototype.fromLatLngToPoint = function(latLng) {
|
overviewer.classes.MapProjection.prototype.fromLatLngToPoint = function(latLng) {
|
||||||
var x = latLng.lng() * overviewerConfig.CONST.tileSize;
|
var x = latLng.lng() * overviewerConfig.CONST.tileSize;
|
||||||
@@ -34,9 +79,14 @@ var overviewer = {
|
|||||||
|
|
||||||
overviewer.classes.CoordMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
|
overviewer.classes.CoordMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
|
||||||
var div = ownerDocument.createElement('DIV');
|
var div = ownerDocument.createElement('DIV');
|
||||||
div.innerHTML = '(' + coord.x + ', ' + coord.y + ', ' + zoom + ')';
|
div.innerHTML = '(' + coord.x + ', ' + coord.y + ', ' + zoom +
|
||||||
div.innerHTML += '<br />';
|
')' + '<br />';
|
||||||
|
//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);
|
//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.width = this.tileSize.width + 'px';
|
||||||
div.style.height = this.tileSize.height + 'px';
|
div.style.height = this.tileSize.height + 'px';
|
||||||
div.style.fontSize = '10px';
|
div.style.fontSize = '10px';
|
||||||
@@ -47,8 +97,8 @@ var overviewer = {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* I think this was old code that was replaced by stuff that is now
|
* Setup the varous mapTypes before we actually create the map. This used
|
||||||
* in initializeMap()
|
* to be a bunch of crap down at the bottom of functions.js
|
||||||
*/
|
*/
|
||||||
'initializeMapTypes': function() {
|
'initializeMapTypes': function() {
|
||||||
var mapOptions = {};
|
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() {
|
'initializeMap': function() {
|
||||||
var defaultCenter = overviewer.util.fromWorldToLatLng(
|
var defaultCenter = overviewer.util.fromWorldToLatLng(
|
||||||
overviewerConfig.map.center[0], overviewerConfig.map.center[1],
|
overviewerConfig.map.center[0], overviewerConfig.map.center[1],
|
||||||
@@ -103,7 +159,7 @@ var overviewer = {
|
|||||||
zoom = overviewerConfig.map.minZoom;
|
zoom = overviewerConfig.map.minZoom;
|
||||||
} else {
|
} else {
|
||||||
zoom = parseInt(queryParams.zoom);
|
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"
|
//if zoom is negative, try to treat as "zoom out from max zoom"
|
||||||
zoom += overviewerConfig.map.maxZoom;
|
zoom += overviewerConfig.map.maxZoom;
|
||||||
} else {
|
} else {
|
||||||
@@ -187,6 +243,12 @@ var overviewer = {
|
|||||||
// We can now set the map to use the 'coordinate' map type
|
// We can now set the map to use the 'coordinate' map type
|
||||||
overviewer.map.setMapTypeId(overviewer.util.getDefaultMapTypeId());
|
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() {
|
'initializeMarkers': function() {
|
||||||
//first, give all collections an empty array to work with
|
//first, give all collections an empty array to work with
|
||||||
for (i in overviewerConfig.objectGroups.signs) {
|
for (i in overviewerConfig.objectGroups.signs) {
|
||||||
@@ -283,6 +345,9 @@ var overviewer = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Same as initializeMarkers() for the most part.
|
||||||
|
*/
|
||||||
'initializeRegions': function() {
|
'initializeRegions': function() {
|
||||||
for (i in overviewerConfig.objectGroups.regions) {
|
for (i in overviewerConfig.objectGroups.regions) {
|
||||||
overviewer.collections.regions[overviewerConfig.objectGroups.regions[i].label] = [];
|
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) {
|
'debug': function(msg) {
|
||||||
if (overviewerConfig.map.debug) {
|
if (overviewerConfig.map.debug) {
|
||||||
console.log(msg);
|
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() {
|
'parseQueryString': function() {
|
||||||
var results = {};
|
var results = {};
|
||||||
var queryString = location.search.substring(1);
|
var queryString = location.search.substring(1);
|
||||||
@@ -365,6 +441,10 @@ var overviewer = {
|
|||||||
}
|
}
|
||||||
return results;
|
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() {
|
'setViewUrl': function() {
|
||||||
var displayZoom = overviewer.map.getZoom();
|
var displayZoom = overviewer.map.getZoom();
|
||||||
if (displayZoom == overviewerConfig.map.maxZoom) {
|
if (displayZoom == overviewerConfig.map.maxZoom) {
|
||||||
@@ -387,6 +467,18 @@ var overviewer = {
|
|||||||
'getDefaultMapTypeId': function() {
|
'getDefaultMapTypeId': function() {
|
||||||
return overviewer.collections.mapTypeIds[0];
|
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) {
|
'fromWorldToLatLng': function(x, z, y) {
|
||||||
// the width and height of all the highest-zoom tiles combined,
|
// the width and height of all the highest-zoom tiles combined,
|
||||||
// inverted
|
// inverted
|
||||||
@@ -423,6 +515,16 @@ var overviewer = {
|
|||||||
|
|
||||||
return new google.maps.LatLng(lat, lng);
|
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) {
|
'fromLatLngToWorld': function(lat, lng) {
|
||||||
// Initialize world x/y/z object to be returned
|
// Initialize world x/y/z object to be returned
|
||||||
var point = Array();
|
var point = Array();
|
||||||
@@ -456,6 +558,10 @@ var overviewer = {
|
|||||||
|
|
||||||
return point;
|
return point;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Create and draw the various map controls and other related things
|
||||||
|
* like the compass, current view link, etc.
|
||||||
|
*/
|
||||||
'createMapControls': function() {
|
'createMapControls': function() {
|
||||||
// viewstate link (little link to where you're looking at the map,
|
// viewstate link (little link to where you're looking at the map,
|
||||||
// normally bottom left)
|
// normally bottom left)
|
||||||
@@ -559,6 +665,12 @@ var overviewer = {
|
|||||||
overviewer.util.createDropDown('Overlays', items);
|
overviewer.util.createDropDown('Overlays', items);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Reusable method for creating drop-down menus
|
||||||
|
*
|
||||||
|
* @param string title
|
||||||
|
* @param array items
|
||||||
|
*/
|
||||||
'createDropDown': function(title, items) {
|
'createDropDown': function(title, items) {
|
||||||
var control = document.createElement('DIV');
|
var control = document.createElement('DIV');
|
||||||
// let's let a style sheet do most of the styling here
|
// let's let a style sheet do most of the styling here
|
||||||
@@ -619,6 +731,13 @@ var overviewer = {
|
|||||||
itemDiv.appendChild(textNode);
|
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) {
|
'createRegionInfoWindow': function(shape) {
|
||||||
var infowindow = new google.maps.InfoWindow();
|
var infowindow = new google.maps.InfoWindow();
|
||||||
google.maps.event.addListener(shape, 'click', function(event, i) {
|
google.maps.event.addListener(shape, 'click', function(event, i) {
|
||||||
@@ -635,6 +754,11 @@ var overviewer = {
|
|||||||
overviewer.collections.infoWindow = infowindow;
|
overviewer.collections.infoWindow = infowindow;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Same as createRegionInfoWindow()
|
||||||
|
*
|
||||||
|
* @param google.maps.Marker marker
|
||||||
|
*/
|
||||||
'createMarkerInfoWindow': function(marker) {
|
'createMarkerInfoWindow': function(marker) {
|
||||||
var windowContent = '<div class="infoWindow"><img src="' + marker.icon +
|
var windowContent = '<div class="infoWindow"><img src="' + marker.icon +
|
||||||
'"/><p>' + marker.title.replace(/\n/g,'<br/>') + '</p></div>';
|
'"/><p>' + marker.title.replace(/\n/g,'<br/>') + '</p></div>';
|
||||||
@@ -650,7 +774,16 @@ var overviewer = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* The various classes needed in this file.
|
||||||
|
*/
|
||||||
'classes': {
|
'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) {
|
'HomeControl': function(controlDiv) {
|
||||||
controlDiv.style.padding = '5px';
|
controlDiv.style.padding = '5px';
|
||||||
// Set CSS for the control border
|
// Set CSS for the control border
|
||||||
@@ -674,15 +807,43 @@ var overviewer = {
|
|||||||
overviewerConfig.map.center[2]));
|
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() {
|
'MapProjection' : function() {
|
||||||
this.inverseTileSize = 1.0 / overviewerConfig.CONST.tileSize;
|
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) {
|
'CoordMapType': function(tileSize) {
|
||||||
this.tileSize = 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': {
|
'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) {
|
'getTileUrlGenerator': function(path, pathBase, pathExt) {
|
||||||
return function(tile, zoom) {
|
return function(tile, zoom) {
|
||||||
var url = path;
|
var url = path;
|
||||||
|
|||||||
@@ -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}
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user