Merge branch 'overlays' into dtt-c-render
Conflicts: quadtree.py web_assets/functions.js
This commit is contained in:
4
chunk.py
4
chunk.py
@@ -120,7 +120,7 @@ transparent_blocks = set([0, 6, 8, 9, 18, 20, 37, 38, 39, 40, 44, 50, 51, 52, 53
|
||||
# This set holds block ids that are solid blocks
|
||||
solid_blocks = set([1, 2, 3, 4, 5, 7, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
|
||||
23, 24, 25, 35, 41, 42, 43, 44, 45, 46, 47, 48, 49, 53, 54, 56, 57, 58, 60,
|
||||
61, 62, 64, 65, 66, 67, 71, 73, 74, 78, 79, 80, 81, 82, 84, 86, 87, 88, 89, 91, 92])
|
||||
61, 62, 67, 73, 74, 78, 79, 80, 81, 82, 84, 86, 87, 88, 89, 91])
|
||||
|
||||
# This set holds block ids that are fluid blocks
|
||||
fluid_blocks = set([8,9,10,11])
|
||||
@@ -463,7 +463,7 @@ def generate_facemasks():
|
||||
return (top, left, right)
|
||||
facemasks = generate_facemasks()
|
||||
black_color = Image.new("RGB", (24,24), (0,0,0))
|
||||
red_color = Image.new("RGB", (24,24), (229,36,38))
|
||||
white_color = Image.new("RGB", (24,24), (255,255,255))
|
||||
|
||||
# Render 128 different color images for color coded depth blending in cave mode
|
||||
def generate_depthcolors():
|
||||
|
||||
29
config.js
29
config.js
@@ -1,6 +1,5 @@
|
||||
|
||||
var config = {
|
||||
fileExt: '{imgformat}',
|
||||
tileSize: 384,
|
||||
defaultZoom: 2,
|
||||
maxZoom: {maxzoom},
|
||||
@@ -33,6 +32,27 @@ var signGroups = [
|
||||
{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.
|
||||
@@ -42,12 +62,15 @@ var signGroups = [
|
||||
* 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'},
|
||||
// {'label': 'Spawn', 'path': 'spawn/tiles', 'base': 'http://example.cdn.amazon.com/'}
|
||||
// {'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}
|
||||
];
|
||||
*/
|
||||
|
||||
|
||||
16
googlemap.py
16
googlemap.py
@@ -23,6 +23,7 @@ from time import strftime, gmtime
|
||||
import json
|
||||
|
||||
import util
|
||||
from c_overviewer import get_render_mode_inheritance
|
||||
|
||||
"""
|
||||
This module has routines related to generating a Google Maps-based
|
||||
@@ -73,12 +74,11 @@ class MapGen(object):
|
||||
raise ValueError("there must be at least one quadtree to work on")
|
||||
|
||||
self.destdir = quadtrees[0].destdir
|
||||
self.imgformat = quadtrees[0].imgformat
|
||||
self.world = quadtrees[0].world
|
||||
self.p = quadtrees[0].p
|
||||
for i in quadtrees:
|
||||
if i.destdir != self.destdir or i.imgformat != self.imgformat or i.world != self.world:
|
||||
raise ValueError("all the given quadtrees must have the same destdir")
|
||||
if i.destdir != self.destdir or i.world != self.world:
|
||||
raise ValueError("all the given quadtrees must have the same destdir and world")
|
||||
|
||||
self.quadtrees = quadtrees
|
||||
|
||||
@@ -86,14 +86,11 @@ class MapGen(object):
|
||||
"""Writes out config.js, marker.js, and region.js
|
||||
Copies web assets into the destdir"""
|
||||
zoomlevel = self.p
|
||||
imgformat = self.imgformat
|
||||
configpath = os.path.join(util.get_program_path(), "config.js")
|
||||
|
||||
config = open(configpath, 'r').read()
|
||||
config = config.replace(
|
||||
"{maxzoom}", str(zoomlevel))
|
||||
config = config.replace(
|
||||
"{imgformat}", str(imgformat))
|
||||
|
||||
config = config.replace("{spawn_coords}",
|
||||
json.dumps(list(self.world.spawn)))
|
||||
@@ -102,7 +99,10 @@ class MapGen(object):
|
||||
|
||||
# create generated map type data, from given quadtrees
|
||||
maptypedata = map(lambda q: {'label' : q.rendermode.capitalize(),
|
||||
'path' : q.tiledir}, self.quadtrees)
|
||||
'path' : q.tiledir,
|
||||
'overlay' : 'overlay' in get_render_mode_inheritance(q.rendermode),
|
||||
'imgformat' : q.imgformat},
|
||||
self.quadtrees)
|
||||
config = config.replace("{maptypedata}", json.dumps(maptypedata))
|
||||
|
||||
with open(os.path.join(self.destdir, "config.js"), 'w') as output:
|
||||
@@ -114,7 +114,7 @@ class MapGen(object):
|
||||
for quadtree in self.quadtrees:
|
||||
tileDir = os.path.join(self.destdir, quadtree.tiledir)
|
||||
if not os.path.exists(tileDir): os.mkdir(tileDir)
|
||||
blank.save(os.path.join(tileDir, "blank."+self.imgformat))
|
||||
blank.save(os.path.join(tileDir, "blank."+quadtree.imgformat))
|
||||
|
||||
# copy web assets into destdir:
|
||||
mirror_dir(os.path.join(util.get_program_path(), "web_assets"), self.destdir)
|
||||
|
||||
@@ -34,6 +34,7 @@ from PIL import Image
|
||||
|
||||
import nbt
|
||||
import chunk
|
||||
from c_overviewer import get_render_mode_inheritance
|
||||
from optimizeimages import optimize_image
|
||||
import composite
|
||||
|
||||
@@ -62,12 +63,12 @@ class QuadtreeGen(object):
|
||||
self.imgformat = imgformat
|
||||
self.optimizeimg = optimizeimg
|
||||
self.bgcolor = bgcolor
|
||||
|
||||
self.lighting = rendermode in ("lighting", "night", "spawn")
|
||||
self.night = rendermode in ("night", "spawn")
|
||||
self.spawn = rendermode in ("spawn",)
|
||||
self.rendermode = rendermode
|
||||
|
||||
# force png renderformat if we're using an overlay mode
|
||||
if 'overlay' in get_render_mode_inheritance(rendermode):
|
||||
self.imgformat = "png"
|
||||
|
||||
# Make the destination dir
|
||||
if not os.path.exists(destdir):
|
||||
os.makedirs(os.path.abspath(destdir))
|
||||
|
||||
8
setup.py
8
setup.py
@@ -54,10 +54,14 @@ try:
|
||||
except:
|
||||
pil_include = []
|
||||
|
||||
c_overviewer_files = ['src/main.c', 'src/composite.c', 'src/iterate.c', 'src/endian.c']
|
||||
c_overviewer_files += ['src/rendermodes.c', 'src/rendermode-normal.c', 'src/rendermode-lighting.c', 'src/rendermode-night.c', 'src/rendermode-spawn.c', 'src/rendermode-cave.c']
|
||||
# used to figure out what files to compile
|
||||
render_modes = ['normal', 'overlay', 'lighting', 'night', 'spawn', 'cave']
|
||||
|
||||
c_overviewer_files = ['src/main.c', 'src/composite.c', 'src/iterate.c', 'src/endian.c', 'src/rendermodes.c']
|
||||
c_overviewer_files += map(lambda mode: 'src/rendermode-%s.c' % (mode,), render_modes)
|
||||
c_overviewer_files += ['src/Draw.c']
|
||||
c_overviewer_includes = ['src/overviewer.h', 'src/rendermodes.h']
|
||||
|
||||
setup_kwargs['ext_modules'].append(Extension('c_overviewer', c_overviewer_files, include_dirs=['.', numpy_include] + pil_include, depends=c_overviewer_includes, extra_link_args=[]))
|
||||
|
||||
# tell build_ext to build the extension in-place
|
||||
|
||||
@@ -273,7 +273,8 @@ alpha_over_wrap(PyObject *self, PyObject *args)
|
||||
* also, it multiplies instead of doing an over operation
|
||||
*/
|
||||
PyObject *
|
||||
tint_with_mask(PyObject *dest, unsigned char sr, unsigned char sg, unsigned char sb,
|
||||
tint_with_mask(PyObject *dest, unsigned char sr, unsigned char sg,
|
||||
unsigned char sb, unsigned char sa,
|
||||
PyObject *mask, int dx, int dy, int xsize, int ysize) {
|
||||
/* libImaging handles */
|
||||
Imaging imDest, imMask;
|
||||
@@ -332,9 +333,11 @@ tint_with_mask(PyObject *dest, unsigned char sr, unsigned char sg, unsigned char
|
||||
out++;
|
||||
*out = MULDIV255(*out, sb, tmp1);
|
||||
out++;
|
||||
*out = MULDIV255(*out, sa, tmp1);
|
||||
out++;
|
||||
} else if (*inmask == 0) {
|
||||
/* do nothing -- source is fully transparent */
|
||||
out += 3;
|
||||
out += 4;
|
||||
} else {
|
||||
/* general case */
|
||||
|
||||
@@ -345,9 +348,10 @@ tint_with_mask(PyObject *dest, unsigned char sr, unsigned char sg, unsigned char
|
||||
out++;
|
||||
*out = MULDIV255(*out, (255 - *inmask) + MULDIV255(sb, *inmask, tmp1), tmp2);
|
||||
out++;
|
||||
*out = MULDIV255(*out, (255 - *inmask) + MULDIV255(sa, *inmask, tmp1), tmp2);
|
||||
out++;
|
||||
}
|
||||
|
||||
out++;
|
||||
inmask += mask_stride;
|
||||
}
|
||||
}
|
||||
|
||||
10
src/main.c
10
src/main.c
@@ -25,14 +25,24 @@ PyObject *get_extension_version(PyObject *self, PyObject *args) {
|
||||
static PyMethodDef COverviewerMethods[] = {
|
||||
{"alpha_over", alpha_over_wrap, METH_VARARGS,
|
||||
"alpha over composite function"},
|
||||
|
||||
{"render_loop", chunk_render, METH_VARARGS,
|
||||
"Renders stuffs"},
|
||||
|
||||
{"get_render_modes", get_render_modes, METH_VARARGS,
|
||||
"returns available render modes"},
|
||||
{"get_render_mode_info", get_render_mode_info, METH_VARARGS,
|
||||
"returns info for a particular render mode"},
|
||||
{"get_render_mode_parent", get_render_mode_parent, METH_VARARGS,
|
||||
"returns parent for a particular render mode"},
|
||||
{"get_render_mode_inheritance", get_render_mode_inheritance, METH_VARARGS,
|
||||
"returns inheritance chain for a particular render mode"},
|
||||
{"get_render_mode_children", get_render_mode_children, METH_VARARGS,
|
||||
"returns (direct) children for a particular render mode"},
|
||||
|
||||
{"extension_version", get_extension_version, METH_VARARGS,
|
||||
"Returns the extension version"},
|
||||
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
|
||||
@@ -48,7 +48,8 @@ PyObject *alpha_over(PyObject *dest, PyObject *src, PyObject *mask,
|
||||
PyObject *alpha_over_full(PyObject *dest, PyObject *src, PyObject *mask, float overall_alpha,
|
||||
int dx, int dy, int xsize, int ysize);
|
||||
PyObject *alpha_over_wrap(PyObject *self, PyObject *args);
|
||||
PyObject *tint_with_mask(PyObject *dest, unsigned char sr, unsigned char sg, unsigned char sb,
|
||||
PyObject *tint_with_mask(PyObject *dest, unsigned char sr, unsigned char sg,
|
||||
unsigned char sb, unsigned char sa,
|
||||
PyObject *mask, int dx, int dy, int xsize, int ysize);
|
||||
|
||||
/* in iterate.c */
|
||||
|
||||
@@ -219,12 +219,13 @@ rendermode_cave_draw(void *data, RenderState *state, PyObject *src, PyObject *ma
|
||||
g = PyInt_AsLong(PyList_GetItem(self->depth_colors, 1 + z*3));
|
||||
b = PyInt_AsLong(PyList_GetItem(self->depth_colors, 2 + z*3));
|
||||
|
||||
tint_with_mask(state->img, r, g, b, mask, state->imgx, state->imgy, 0, 0);
|
||||
tint_with_mask(state->img, r, g, b, 255, mask, state->imgx, state->imgy, 0, 0);
|
||||
|
||||
}
|
||||
|
||||
RenderModeInterface rendermode_cave = {
|
||||
"cave", "render only caves in normal mode",
|
||||
&rendermode_normal,
|
||||
sizeof(RenderModeCave),
|
||||
rendermode_cave_start,
|
||||
rendermode_cave_finish,
|
||||
|
||||
@@ -229,6 +229,7 @@ rendermode_lighting_draw(void *data, RenderState *state, PyObject *src, PyObject
|
||||
|
||||
RenderModeInterface rendermode_lighting = {
|
||||
"lighting", "draw shadows from the lighting data",
|
||||
&rendermode_normal,
|
||||
sizeof(RenderModeLighting),
|
||||
rendermode_lighting_start,
|
||||
rendermode_lighting_finish,
|
||||
|
||||
@@ -61,6 +61,7 @@ rendermode_night_draw(void *data, RenderState *state, PyObject *src, PyObject *m
|
||||
|
||||
RenderModeInterface rendermode_night = {
|
||||
"night", "like \"lighting\", except at night",
|
||||
&rendermode_lighting,
|
||||
sizeof(RenderModeNight),
|
||||
rendermode_night_start,
|
||||
rendermode_night_finish,
|
||||
|
||||
@@ -169,7 +169,7 @@ rendermode_normal_draw(void *data, RenderState *state, PyObject *src, PyObject *
|
||||
b = PyInt_AsLong(PyTuple_GET_ITEM(color, 2));
|
||||
Py_DECREF(color);
|
||||
|
||||
tint_with_mask(state->img, r, g, b, facemask, state->imgx, state->imgy, 0, 0);
|
||||
tint_with_mask(state->img, r, g, b, 255, facemask, state->imgx, state->imgy, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,6 +221,7 @@ rendermode_normal_draw(void *data, RenderState *state, PyObject *src, PyObject *
|
||||
|
||||
RenderModeInterface rendermode_normal = {
|
||||
"normal", "nothing special, just render the blocks",
|
||||
NULL,
|
||||
sizeof(RenderModeNormal),
|
||||
rendermode_normal_start,
|
||||
rendermode_normal_finish,
|
||||
|
||||
137
src/rendermode-overlay.c
Normal file
137
src/rendermode-overlay.c
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* This file is part of the Minecraft Overviewer.
|
||||
*
|
||||
* Minecraft Overviewer is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Minecraft Overviewer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with the Overviewer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "overviewer.h"
|
||||
|
||||
static void get_color(void *data, RenderState *state,
|
||||
unsigned char *r, unsigned char *g, unsigned char *b, unsigned char *a) {
|
||||
*r = 200;
|
||||
*g = 200;
|
||||
*b = 255;
|
||||
*a = 155;
|
||||
}
|
||||
|
||||
static int
|
||||
rendermode_overlay_start(void *data, RenderState *state) {
|
||||
PyObject *facemasks_py;
|
||||
RenderModeOverlay *self = (RenderModeOverlay *)data;
|
||||
|
||||
facemasks_py = PyObject_GetAttrString(state->chunk, "facemasks");
|
||||
/* borrowed reference, needs to be incref'd if we keep it */
|
||||
self->facemask_top = PyTuple_GetItem(facemasks_py, 0);
|
||||
Py_INCREF(self->facemask_top);
|
||||
Py_DECREF(facemasks_py);
|
||||
|
||||
self->white_color = PyObject_GetAttrString(state->chunk, "white_color");
|
||||
|
||||
self->solid_blocks = PyObject_GetAttrString(state->chunk, "solid_blocks");
|
||||
self->fluid_blocks = PyObject_GetAttrString(state->chunk, "fluid_blocks");
|
||||
|
||||
self->get_color = get_color;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rendermode_overlay_finish(void *data, RenderState *state) {
|
||||
RenderModeOverlay *self = (RenderModeOverlay *)data;
|
||||
|
||||
Py_DECREF(self->facemask_top);
|
||||
Py_DECREF(self->white_color);
|
||||
Py_DECREF(self->solid_blocks);
|
||||
Py_DECREF(self->fluid_blocks);
|
||||
}
|
||||
|
||||
static int
|
||||
rendermode_overlay_occluded(void *data, RenderState *state) {
|
||||
int x = state->x, y = state->y, z = state->z;
|
||||
|
||||
if ( (x != 0) && (y != 15) && (z != 127) &&
|
||||
!is_transparent(getArrayByte3D(state->blocks, x-1, y, z)) &&
|
||||
!is_transparent(getArrayByte3D(state->blocks, x, y, z+1)) &&
|
||||
!is_transparent(getArrayByte3D(state->blocks, x, y+1, z))) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rendermode_overlay_draw(void *data, RenderState *state, PyObject *src, PyObject *mask) {
|
||||
RenderModeOverlay *self = (RenderModeOverlay *)data;
|
||||
unsigned char r, g, b, a;
|
||||
PyObject *top_block_py, *block_py;
|
||||
|
||||
// exactly analogous to edge-line code for these special blocks
|
||||
int increment=0;
|
||||
if (state->block == 44) // half-step
|
||||
increment=6;
|
||||
else if (state->block == 78) // snow
|
||||
increment=9;
|
||||
|
||||
/* clear the draw space -- set alpha to 0 within mask */
|
||||
tint_with_mask(state->img, 255, 255, 255, 0, mask, state->imgx, state->imgy, 0, 0);
|
||||
|
||||
/* skip rendering the overlay if we can't see it */
|
||||
if (state->z != 127) {
|
||||
unsigned char top_block = getArrayByte3D(state->blocks, state->x, state->y, state->z+1);
|
||||
if (!is_transparent(top_block)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* check to be sure this block is solid/fluid */
|
||||
top_block_py = PyInt_FromLong(top_block);
|
||||
if (PySequence_Contains(self->solid_blocks, top_block_py) ||
|
||||
PySequence_Contains(self->fluid_blocks, top_block_py)) {
|
||||
|
||||
/* top block is fluid or solid, skip drawing */
|
||||
Py_DECREF(top_block_py);
|
||||
return;
|
||||
}
|
||||
Py_DECREF(top_block_py);
|
||||
}
|
||||
|
||||
/* check to be sure this block is solid/fluid */
|
||||
block_py = PyInt_FromLong(state->block);
|
||||
if (!PySequence_Contains(self->solid_blocks, block_py) &&
|
||||
!PySequence_Contains(self->fluid_blocks, block_py)) {
|
||||
|
||||
/* not fluid or solid, skip drawing the overlay */
|
||||
Py_DECREF(block_py);
|
||||
return;
|
||||
}
|
||||
Py_DECREF(block_py);
|
||||
|
||||
/* get our color info */
|
||||
self->get_color(data, state, &r, &g, &b, &a);
|
||||
|
||||
/* do the overlay */
|
||||
if (a > 0) {
|
||||
alpha_over(state->img, self->white_color, self->facemask_top, state->imgx, state->imgy + increment, 0, 0);
|
||||
tint_with_mask(state->img, r, g, b, a, self->facemask_top, state->imgx, state->imgy + increment, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
RenderModeInterface rendermode_overlay = {
|
||||
"overlay", "base rendermode for informational overlays",
|
||||
NULL,
|
||||
sizeof(RenderModeOverlay),
|
||||
rendermode_overlay_start,
|
||||
rendermode_overlay_finish,
|
||||
rendermode_overlay_occluded,
|
||||
rendermode_overlay_draw,
|
||||
};
|
||||
@@ -18,21 +18,66 @@
|
||||
#include "overviewer.h"
|
||||
#include <math.h>
|
||||
|
||||
static void get_color(void *data, RenderState *state,
|
||||
unsigned char *r, unsigned char *g, unsigned char *b, unsigned char *a) {
|
||||
|
||||
RenderModeSpawn* self = (RenderModeSpawn *)data;
|
||||
int x = state->x, y = state->y, z = state->z;
|
||||
int z_light = z + 1;
|
||||
unsigned char blocklight, skylight;
|
||||
PyObject *block_py;
|
||||
|
||||
/* set a nice, pretty red color */
|
||||
*r = 229;
|
||||
*g = 36;
|
||||
*b = 38;
|
||||
|
||||
/* default to no overlay, until told otherwise */
|
||||
*a = 0;
|
||||
|
||||
block_py = PyInt_FromLong(state->block);
|
||||
if (PySequence_Contains(self->nospawn_blocks, block_py)) {
|
||||
/* nothing can spawn on this */
|
||||
Py_DECREF(block_py);
|
||||
return;
|
||||
}
|
||||
Py_DECREF(block_py);
|
||||
|
||||
blocklight = getArrayByte3D(self->blocklight, x, y, MIN(127, z_light));
|
||||
|
||||
/* if we're at the top, force 15 (brightest!) skylight */
|
||||
if (z_light == 128) {
|
||||
skylight = 15;
|
||||
} else {
|
||||
skylight = getArrayByte3D(self->skylight, x, y, z_light);
|
||||
}
|
||||
|
||||
if (MAX(blocklight, skylight) <= 7) {
|
||||
/* hostile mobs spawn in daylight */
|
||||
*a = 240;
|
||||
} else if (MAX(blocklight, skylight - 11) <= 7) {
|
||||
/* hostile mobs spawn at night */
|
||||
*a = 150;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
rendermode_spawn_start(void *data, RenderState *state) {
|
||||
RenderModeSpawn* self;
|
||||
|
||||
/* first, chain up */
|
||||
int ret = rendermode_night.start(data, state);
|
||||
int ret = rendermode_overlay.start(data, state);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
/* now do custom initializations */
|
||||
self = (RenderModeSpawn *)data;
|
||||
self->solid_blocks = PyObject_GetAttrString(state->chunk, "solid_blocks");
|
||||
self->nospawn_blocks = PyObject_GetAttrString(state->chunk, "nospawn_blocks");
|
||||
self->fluid_blocks = PyObject_GetAttrString(state->chunk, "fluid_blocks");
|
||||
self->red_color = PyObject_GetAttrString(state->chunk, "red_color");
|
||||
self->blocklight = PyObject_GetAttrString(state->self, "blocklight");
|
||||
self->skylight = PyObject_GetAttrString(state->self, "skylight");
|
||||
|
||||
/* setup custom color */
|
||||
self->parent.get_color = get_color;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -42,83 +87,29 @@ rendermode_spawn_finish(void *data, RenderState *state) {
|
||||
/* first free all *our* stuff */
|
||||
RenderModeSpawn* self = (RenderModeSpawn *)data;
|
||||
|
||||
Py_DECREF(self->solid_blocks);
|
||||
Py_DECREF(self->nospawn_blocks);
|
||||
Py_DECREF(self->fluid_blocks);
|
||||
Py_DECREF(self->blocklight);
|
||||
Py_DECREF(self->skylight);
|
||||
|
||||
/* now, chain up */
|
||||
rendermode_night.finish(data, state);
|
||||
rendermode_overlay.finish(data, state);
|
||||
}
|
||||
|
||||
static int
|
||||
rendermode_spawn_occluded(void *data, RenderState *state) {
|
||||
/* no special occlusion here */
|
||||
return rendermode_night.occluded(data, state);
|
||||
return rendermode_overlay.occluded(data, state);
|
||||
}
|
||||
|
||||
static void
|
||||
rendermode_spawn_draw(void *data, RenderState *state, PyObject *src, PyObject *mask) {
|
||||
/* different versions of self (spawn, lighting) */
|
||||
RenderModeSpawn* self = (RenderModeSpawn *)data;
|
||||
RenderModeLighting *lighting = (RenderModeLighting *)self;
|
||||
|
||||
int x = state->x, y = state->y, z = state->z;
|
||||
PyObject *old_black_color = NULL;
|
||||
|
||||
/* figure out the appropriate darkness:
|
||||
this block for transparents, the block above for non-transparent */
|
||||
float darkness = 0.0;
|
||||
if (is_transparent(state->block)) {
|
||||
darkness = get_lighting_coefficient((RenderModeLighting *)self, state, x, y, z, NULL);
|
||||
} else {
|
||||
darkness = get_lighting_coefficient((RenderModeLighting *)self, state, x, y, z+1, NULL);
|
||||
}
|
||||
|
||||
/* if it's dark enough... */
|
||||
if (darkness > 0.8) {
|
||||
PyObject *block_py = PyInt_FromLong(state->block);
|
||||
|
||||
/* make sure it's solid */
|
||||
if (PySequence_Contains(self->solid_blocks, block_py)) {
|
||||
int spawnable = 1;
|
||||
|
||||
/* not spawnable if its in the nospawn list */
|
||||
if (PySequence_Contains(self->nospawn_blocks, block_py))
|
||||
spawnable = 0;
|
||||
|
||||
/* check the block above for solid or fluid */
|
||||
if (spawnable && z != 127) {
|
||||
PyObject *top_block_py = PyInt_FromLong(getArrayByte3D(state->blocks, x, y, z+1));
|
||||
if (PySequence_Contains(self->solid_blocks, top_block_py) ||
|
||||
PySequence_Contains(self->fluid_blocks, top_block_py)) {
|
||||
|
||||
spawnable = 0;
|
||||
}
|
||||
|
||||
Py_DECREF(top_block_py);
|
||||
}
|
||||
|
||||
/* if we passed all the checks, replace black_color with red_color */
|
||||
if (spawnable) {
|
||||
old_black_color = lighting->black_color;
|
||||
lighting->black_color = self->red_color;
|
||||
}
|
||||
}
|
||||
|
||||
Py_DECREF(block_py);
|
||||
}
|
||||
|
||||
/* draw normally */
|
||||
rendermode_night.draw(data, state, src, mask);
|
||||
|
||||
/* reset black_color, if needed */
|
||||
if (old_black_color != NULL) {
|
||||
lighting->black_color = old_black_color;
|
||||
}
|
||||
rendermode_overlay.draw(data, state, src, mask);
|
||||
}
|
||||
|
||||
RenderModeInterface rendermode_spawn = {
|
||||
"spawn", "draws red where monsters can spawn at night",
|
||||
"spawn", "draws a red overlay where monsters can spawn at night",
|
||||
&rendermode_overlay,
|
||||
sizeof(RenderModeSpawn),
|
||||
rendermode_spawn_start,
|
||||
rendermode_spawn_finish,
|
||||
|
||||
@@ -98,5 +98,87 @@ PyObject *get_render_mode_info(PyObject *self, PyObject *args) {
|
||||
}
|
||||
|
||||
Py_DECREF(info);
|
||||
Py_RETURN_NONE;
|
||||
return PyErr_Format(PyExc_ValueError, "invalid rendermode: \"%s\"", rendermode);
|
||||
}
|
||||
|
||||
/* bindings -- get parent's name */
|
||||
PyObject *get_render_mode_parent(PyObject *self, PyObject *args) {
|
||||
const char *rendermode;
|
||||
unsigned int i;
|
||||
if (!PyArg_ParseTuple(args, "s", &rendermode))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; render_modes[i] != NULL; i++) {
|
||||
if (strcmp(render_modes[i]->name, rendermode) == 0) {
|
||||
if (render_modes[i]->parent) {
|
||||
/* has parent */
|
||||
return PyString_FromString(render_modes[i]->parent->name);
|
||||
} else {
|
||||
/* no parent */
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PyErr_Format(PyExc_ValueError, "invalid rendermode: \"%s\"", rendermode);
|
||||
}
|
||||
|
||||
/* bindings -- get list of inherited parents */
|
||||
PyObject *get_render_mode_inheritance(PyObject *self, PyObject *args) {
|
||||
const char *rendermode;
|
||||
PyObject *parents;
|
||||
unsigned int i;
|
||||
RenderModeInterface *iface = NULL;
|
||||
if (!PyArg_ParseTuple(args, "s", &rendermode))
|
||||
return NULL;
|
||||
|
||||
parents = PyList_New(0);
|
||||
if (!parents)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; render_modes[i] != NULL; i++) {
|
||||
if (strcmp(render_modes[i]->name, rendermode) == 0) {
|
||||
iface = render_modes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!iface) {
|
||||
Py_DECREF(parents);
|
||||
return PyErr_Format(PyExc_ValueError, "invalid rendermode: \"%s\"", rendermode);
|
||||
}
|
||||
|
||||
while (iface) {
|
||||
PyObject *name = PyString_FromString(iface->name);
|
||||
PyList_Append(parents, name);
|
||||
Py_DECREF(name);
|
||||
|
||||
iface = iface->parent;
|
||||
}
|
||||
|
||||
PyList_Reverse(parents);
|
||||
return parents;
|
||||
}
|
||||
|
||||
/* bindings -- get list of (direct) children */
|
||||
PyObject *get_render_mode_children(PyObject *self, PyObject *args) {
|
||||
const char *rendermode;
|
||||
PyObject *children;
|
||||
unsigned int i;
|
||||
if (!PyArg_ParseTuple(args, "s", &rendermode))
|
||||
return NULL;
|
||||
|
||||
children = PyList_New(0);
|
||||
if (!children)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; render_modes[i] != NULL; i++) {
|
||||
if (render_modes[i]->parent && strcmp(render_modes[i]->parent->name, rendermode) == 0) {
|
||||
PyObject *child_name = PyString_FromString(render_modes[i]->name);
|
||||
PyList_Append(children, child_name);
|
||||
Py_DECREF(child_name);
|
||||
}
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
@@ -38,12 +38,15 @@
|
||||
#include <Python.h>
|
||||
|
||||
/* rendermode interface */
|
||||
typedef struct {
|
||||
typedef struct _RenderModeInterface RenderModeInterface;
|
||||
struct _RenderModeInterface {
|
||||
/* the name of this mode */
|
||||
const char* name;
|
||||
/* the short description of this render mode */
|
||||
const char* description;
|
||||
|
||||
/* the rendermode this is derived from, or NULL */
|
||||
RenderModeInterface *parent;
|
||||
/* the size of the local storage for this rendermode */
|
||||
unsigned int data_size;
|
||||
|
||||
@@ -54,13 +57,16 @@ typedef struct {
|
||||
int (*occluded)(void *, RenderState *);
|
||||
/* last two arguments are img and mask, from texture lookup */
|
||||
void (*draw)(void *, RenderState *, PyObject *, PyObject *);
|
||||
} RenderModeInterface;
|
||||
};
|
||||
|
||||
/* figures out the render mode to use from the given ChunkRenderer */
|
||||
RenderModeInterface *get_render_mode(RenderState *state);
|
||||
/* python bindings */
|
||||
PyObject *get_render_modes(PyObject *self, PyObject *args);
|
||||
PyObject *get_render_mode_info(PyObject *self, PyObject *args);
|
||||
PyObject *get_render_mode_parent(PyObject *self, PyObject *args);
|
||||
PyObject *get_render_mode_inheritance(PyObject *self, PyObject *args);
|
||||
PyObject *get_render_mode_children(PyObject *self, PyObject *args);
|
||||
|
||||
/* individual rendermode interface declarations follow */
|
||||
|
||||
@@ -79,6 +85,20 @@ typedef struct {
|
||||
} RenderModeNormal;
|
||||
extern RenderModeInterface rendermode_normal;
|
||||
|
||||
/* OVERLAY */
|
||||
typedef struct {
|
||||
/* top facemask and white color image, for drawing overlays */
|
||||
PyObject *facemask_top, *white_color;
|
||||
/* only show overlay on top of solid or fluid blocks */
|
||||
PyObject *solid_blocks, *fluid_blocks;
|
||||
/* can be overridden in derived classes to control
|
||||
overlay alpha and color
|
||||
last four vars are r, g, b, a out */
|
||||
void (*get_color)(void *, RenderState *,
|
||||
unsigned char *, unsigned char *, unsigned char *, unsigned char *);
|
||||
} RenderModeOverlay;
|
||||
extern RenderModeInterface rendermode_overlay;
|
||||
|
||||
/* LIGHTING */
|
||||
typedef struct {
|
||||
/* inherits from normal render mode */
|
||||
@@ -109,13 +129,12 @@ extern RenderModeInterface rendermode_night;
|
||||
|
||||
/* SPAWN */
|
||||
typedef struct {
|
||||
/* inherits from night */
|
||||
RenderModeNight parent;
|
||||
/* inherits from overlay */
|
||||
RenderModeOverlay parent;
|
||||
|
||||
/* used to figure out which blocks are spawnable */
|
||||
PyObject *solid_blocks, *nospawn_blocks, *fluid_blocks;
|
||||
/* replacement for black_color */
|
||||
PyObject *red_color;
|
||||
PyObject *nospawn_blocks;
|
||||
PyObject *skylight, *blocklight;
|
||||
} RenderModeSpawn;
|
||||
extern RenderModeInterface rendermode_spawn;
|
||||
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
// var def
|
||||
var map; // god of the overviewer... bow before the google api.
|
||||
var markerCollection = {}; // holds groups of markers
|
||||
|
||||
var map;
|
||||
|
||||
var markersInit = false;
|
||||
var regionsInit = false;
|
||||
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
|
||||
});
|
||||
@@ -18,120 +20,234 @@ function prepareSignMarker(marker, item) {
|
||||
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
|
||||
|
||||
function drawMapControls() {
|
||||
|
||||
// viewstate link
|
||||
var viewStateDiv = document.createElement('DIV');
|
||||
|
||||
//<div id="link" style="border:1px solid black;background-color:white;color:black;position:absolute;top:5px;right:5px"></div>
|
||||
|
||||
viewStateDiv.id="link";
|
||||
|
||||
|
||||
map.controls[google.maps.ControlPosition.BOTTOM_RIGHT].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;
|
||||
map.controls[google.maps.ControlPosition.TOP_RIGHT].push(compassDiv);
|
||||
|
||||
|
||||
if (signGroups.length > 0) {
|
||||
// signpost display control
|
||||
//
|
||||
|
||||
var signControl = document.createElement("DIV");
|
||||
signControl.id = "signControl"; // 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";
|
||||
signControl.appendChild(controlBorder);
|
||||
|
||||
var controlText = document.createElement("DIV");
|
||||
|
||||
control.appendChild(controlBorder);
|
||||
controlBorder.appendChild(controlText);
|
||||
|
||||
controlText.innerHTML = "Signposts";
|
||||
|
||||
var dropdownDiv = document.createElement("DIV");
|
||||
|
||||
|
||||
$(controlText).click(function() {
|
||||
$(dropdownDiv).toggle();
|
||||
|
||||
});
|
||||
|
||||
|
||||
dropdownDiv.id="dropDown";
|
||||
signControl.appendChild(dropdownDiv);
|
||||
control.appendChild(dropdownDiv);
|
||||
dropdownDiv.innerHTML="";
|
||||
|
||||
map.controls[google.maps.ControlPosition.TOP_RIGHT].push(signControl);
|
||||
// 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);
|
||||
|
||||
|
||||
var hasSignGroup = false;
|
||||
for (idx in signGroups) {
|
||||
var item = signGroups[idx];
|
||||
//console.log(item);
|
||||
label = item.label;
|
||||
hasSignGroup = true;
|
||||
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";
|
||||
|
||||
$(n).data("label",label);
|
||||
jQuery(n).click(function(e) {
|
||||
var t = $(e.target);
|
||||
jQuery.each(markerCollection[t.data("label")], function(i,elem) {elem.setVisible(e.target.checked);});
|
||||
});
|
||||
|
||||
// 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;
|
||||
jQuery.each(markerCollection[label], function(i,elem) {elem.setVisible(n.checked);});
|
||||
item.action(idx, item.label, item.checked);
|
||||
}
|
||||
dropdownDiv.appendChild(d);
|
||||
d.appendChild(n)
|
||||
var textNode = document.createElement("text");
|
||||
textNode.innerHTML = label + "<br/>";
|
||||
d.appendChild(textNode);
|
||||
|
||||
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; }
|
||||
|
||||
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) {
|
||||
new google.maps.Polygon({clickable: false,
|
||||
var shape = new google.maps.Polygon({
|
||||
name: name,
|
||||
clickable: clickable,
|
||||
geodesic: false,
|
||||
map: map,
|
||||
map: null,
|
||||
strokeColor: region.color,
|
||||
strokeOpacity: region.opacity,
|
||||
strokeWeight: 2,
|
||||
@@ -141,9 +257,11 @@ function initRegions() {
|
||||
paths: converted
|
||||
});
|
||||
} else {
|
||||
new google.maps.Polyline({clickable: false,
|
||||
var shape = new google.maps.Polyline({
|
||||
name: name,
|
||||
clickable: clickable,
|
||||
geodesic: false,
|
||||
map: map,
|
||||
map: null,
|
||||
strokeColor: region.color,
|
||||
strokeOpacity: region.opacity,
|
||||
strokeWeight: 2,
|
||||
@@ -151,21 +269,40 @@ function initRegions() {
|
||||
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; }
|
||||
|
||||
markersInit = true;
|
||||
if (markersInit) { return; } // oh, we've already done this? nevermind, exit the function.
|
||||
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];
|
||||
|
||||
@@ -181,7 +318,6 @@ function initMarkers() {
|
||||
title: jQuery.trim(item.msg),
|
||||
icon: iconURL
|
||||
});
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -208,11 +344,11 @@ function initMarkers() {
|
||||
if (testfunc(item)) {
|
||||
matched = true;
|
||||
|
||||
if (item.type == 'sign') { iconURL = 'signpost_icon.png';}
|
||||
// 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);
|
||||
if (signGroup.icon) { iconURL = signGroup.icon;
|
||||
}
|
||||
//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,
|
||||
@@ -227,10 +363,7 @@ function initMarkers() {
|
||||
if (item.type == 'sign') {
|
||||
prepareSignMarker(marker, item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (!matched) {
|
||||
@@ -256,10 +389,11 @@ function initMarkers() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// update the link in the viewstate.
|
||||
function makeLink() {
|
||||
var displayZoom = map.getZoom();
|
||||
if (displayZoom == config.maxZoom) {
|
||||
@@ -277,6 +411,7 @@ function makeLink() {
|
||||
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);
|
||||
@@ -387,33 +522,33 @@ function initialize() {
|
||||
}
|
||||
|
||||
|
||||
// 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() {
|
||||
// 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) {
|
||||
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) {
|
||||
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)
|
||||
{
|
||||
// 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));
|
||||
|
||||
@@ -444,12 +579,12 @@ function initialize() {
|
||||
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)
|
||||
{
|
||||
// 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;
|
||||
@@ -479,9 +614,9 @@ function initialize() {
|
||||
xyz.z -= 64 + 2;
|
||||
|
||||
return xyz;
|
||||
}
|
||||
}
|
||||
|
||||
function getTileUrlGenerator(path, path_base) {
|
||||
function getTileUrlGenerator(path, path_base, path_ext) {
|
||||
return function(tile, zoom) {
|
||||
var url = path;
|
||||
var url_base = ( path_base ? path_base : '' );
|
||||
@@ -496,7 +631,7 @@ function getTileUrlGenerator(path, path_base) {
|
||||
url += '/' + (x + 2 * y);
|
||||
}
|
||||
}
|
||||
url = url + '.' + config.fileExt;
|
||||
url = url + '.' + path_ext;
|
||||
if(config.cacheMinutes > 0) {
|
||||
var d = new Date();
|
||||
url += '?c=' + Math.floor(d.getTime() / (1000 * 60 * config.cacheMinutes));
|
||||
@@ -509,35 +644,42 @@ 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),
|
||||
getTileUrl: getTileUrlGenerator(view.path, view.base, imgformat),
|
||||
tileSize: new google.maps.Size(config.tileSize, config.tileSize),
|
||||
maxZoom: config.maxZoom,
|
||||
minZoom: 0,
|
||||
isPng: !(config.fileExt.match(/^png$/i) == null)
|
||||
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() {
|
||||
}
|
||||
|
||||
function CoordMapType(tileSize) {
|
||||
function CoordMapType(tileSize) {
|
||||
this.tileSize = tileSize;
|
||||
}
|
||||
}
|
||||
|
||||
CoordMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
|
||||
CoordMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
|
||||
var div = ownerDocument.createElement('DIV');
|
||||
div.innerHTML = "(" + coord.x + ", " + coord.y + ", " + zoom + ")";
|
||||
div.innerHTML += "<br />";
|
||||
@@ -549,4 +691,4 @@ for (idx in mapTypeData) {
|
||||
div.style.borderWidth = '1px';
|
||||
div.style.borderColor = '#AAAAAA';
|
||||
return div;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -17,13 +17,13 @@ body { height: 100%; margin: 0px; padding: 0px ; background-color: #000; }
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
#signControl {
|
||||
#customControl {
|
||||
padding: 5px;
|
||||
height: 15px;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
#signControl > div#top {
|
||||
#customControl > div#top {
|
||||
background-color: #fff;
|
||||
border: 2px solid #000;
|
||||
text-align: center;
|
||||
@@ -33,7 +33,14 @@ body { height: 100%; margin: 0px; padding: 0px ; background-color: #000; }
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#signControl > div#dropDown {
|
||||
#customControl > div#dropDown {
|
||||
border: 1px solid #000;
|
||||
font-size: 12px;
|
||||
background-color: #fff;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#customControl > div#button {
|
||||
border: 1px solid #000;
|
||||
font-size: 12px;
|
||||
background-color: #fff;
|
||||
|
||||
Reference in New Issue
Block a user