diff --git a/overviewer.py b/overviewer.py index 1bf6790..565e279 100755 --- a/overviewer.py +++ b/overviewer.py @@ -97,6 +97,7 @@ def main(): parser.add_option("--forcerender", dest="forcerender", help="Force re-rendering the entire map (or the given regionlist). Useful for re-rendering without deleting the entire map with --delete.", action="store_true") parser.add_option("--rendermodes", dest="rendermode", help="Specifies the render types, separated by commas. Use --list-rendermodes to list them all.", type="choice", choices=avail_rendermodes, required=True, default=avail_rendermodes[0], listify=True) parser.add_option("--list-rendermodes", dest="list_rendermodes", action="store_true", help="List available render modes and exit.", commandLineOnly=True) + parser.add_option("--rendermode-options", dest="rendermode_options", default={}, configFileOnly=True) parser.add_option("--imgformat", dest="imgformat", help="The image output format to use. Currently supported: png(default), jpg.", configFileOnly=True ) parser.add_option("--imgquality", dest="imgquality", default=95, help="Specify the quality of image output when using imgformat=\"jpg\".", type="int", configFileOnly=True) parser.add_option("--bg_color", dest="bg_color", help="Configures the background color for the GoogleMap output. Specify in #RRGGBB format", configFileOnly=True, type="string", default="#1A1A1A") @@ -217,7 +218,7 @@ def main(): logging.info("Welcome to Minecraft Overviewer!") logging.debug("Current log level: {0}".format(logging.getLogger().level)) - + useBiomeData = os.path.exists(os.path.join(worlddir, 'biomes')) if not useBiomeData: logging.info("Notice: Not using biome data for tinting") diff --git a/rendernode.py b/rendernode.py index 6f6c76e..f2b9bfb 100644 --- a/rendernode.py +++ b/rendernode.py @@ -68,6 +68,10 @@ def pool_initializer(rendernode): textures.generate(path=rendernode.options.get('textures_path', None)) c_overviewer.init_chunk_render() + # setup c_overviewer rendermode options + for mode in rendernode.options.rendermode_options: + c_overviewer.set_render_mode_options(mode, rendernode.options.rendermode_options[mode]) + # load biome data in each process, if needed for quadtree in rendernode.quadtrees: if quadtree.world.useBiomeData: diff --git a/src/main.c b/src/main.c index 19d3612..a001be1 100644 --- a/src/main.c +++ b/src/main.c @@ -42,6 +42,9 @@ static PyMethodDef COverviewerMethods[] = { {"get_render_mode_children", get_render_mode_children, METH_VARARGS, "returns (direct) children for a particular render mode"}, + {"set_render_mode_options", set_render_mode_options, METH_VARARGS, + "sets the default options for a given render mode"}, + {"extension_version", get_extension_version, METH_VARARGS, "Returns the extension version"}, diff --git a/src/rendermode-cave.c b/src/rendermode-cave.c index c5a2e07..88ee1e7 100644 --- a/src/rendermode-cave.c +++ b/src/rendermode-cave.c @@ -161,13 +161,13 @@ rendermode_cave_occluded(void *data, RenderState *state) { } static int -rendermode_cave_start(void *data, RenderState *state) { +rendermode_cave_start(void *data, RenderState *state, PyObject *options) { RenderModeCave* self; int ret; self = (RenderModeCave *)data; /* first, chain up */ - ret = rendermode_normal.start(data, state); + ret = rendermode_normal.start(data, state, options); if (ret != 0) return ret; diff --git a/src/rendermode-lighting.c b/src/rendermode-lighting.c index d0d4c64..f1dc6c7 100644 --- a/src/rendermode-lighting.c +++ b/src/rendermode-lighting.c @@ -169,11 +169,11 @@ do_shading_with_mask(RenderModeLighting *self, RenderState *state, } static int -rendermode_lighting_start(void *data, RenderState *state) { +rendermode_lighting_start(void *data, RenderState *state, PyObject *options) { RenderModeLighting* self; /* first, chain up */ - int ret = rendermode_normal.start(data, state); + int ret = rendermode_normal.start(data, state, options); if (ret != 0) return ret; diff --git a/src/rendermode-night.c b/src/rendermode-night.c index 81fc38f..35c4476 100644 --- a/src/rendermode-night.c +++ b/src/rendermode-night.c @@ -26,11 +26,11 @@ static float calculate_darkness(unsigned char skylight, unsigned char blocklight } static int -rendermode_night_start(void *data, RenderState *state) { +rendermode_night_start(void *data, RenderState *state, PyObject *options) { RenderModeNight* self; /* first, chain up */ - int ret = rendermode_lighting.start(data, state); + int ret = rendermode_lighting.start(data, state, options); if (ret != 0) return ret; diff --git a/src/rendermode-normal.c b/src/rendermode-normal.c index b112192..f5fb124 100644 --- a/src/rendermode-normal.c +++ b/src/rendermode-normal.c @@ -18,7 +18,7 @@ #include "overviewer.h" static int -rendermode_normal_start(void *data, RenderState *state) { +rendermode_normal_start(void *data, RenderState *state, PyObject *options) { PyObject *chunk_x_py, *chunk_y_py, *world, *use_biomes, *worlddir; RenderModeNormal *self = (RenderModeNormal *)data; diff --git a/src/rendermode-overlay.c b/src/rendermode-overlay.c index 04c87bf..7807f66 100644 --- a/src/rendermode-overlay.c +++ b/src/rendermode-overlay.c @@ -26,7 +26,7 @@ static void get_color(void *data, RenderState *state, } static int -rendermode_overlay_start(void *data, RenderState *state) { +rendermode_overlay_start(void *data, RenderState *state, PyObject *options) { PyObject *facemasks_py; RenderModeOverlay *self = (RenderModeOverlay *)data; diff --git a/src/rendermode-spawn.c b/src/rendermode-spawn.c index 2781a2a..20f81dd 100644 --- a/src/rendermode-spawn.c +++ b/src/rendermode-spawn.c @@ -62,11 +62,11 @@ static void get_color(void *data, RenderState *state, } static int -rendermode_spawn_start(void *data, RenderState *state) { +rendermode_spawn_start(void *data, RenderState *state, PyObject *options) { RenderModeSpawn* self; /* first, chain up */ - int ret = rendermode_overlay.start(data, state); + int ret = rendermode_overlay.start(data, state, options); if (ret != 0) return ret; diff --git a/src/rendermodes.c b/src/rendermodes.c index 4eac913..8c11c83 100644 --- a/src/rendermodes.c +++ b/src/rendermodes.c @@ -30,8 +30,41 @@ static RenderModeInterface *render_modes[] = { NULL }; +static PyObject *render_mode_options = NULL; + +/* rendermode encapsulation */ + +/* helper to recursively find options for a given mode */ +static inline PyObject * +render_mode_create_options(RenderModeInterface *iface) { + PyObject *base_options, *ret, *parent_options; + if (render_mode_options == NULL) + return PyDict_New(); + + base_options = PyDict_GetItemString(render_mode_options, iface->name); + if (base_options) { + ret = PyDict_Copy(base_options); + } else { + ret = PyDict_New(); + } + + if (iface->parent) { + parent_options = render_mode_create_options(iface->parent); + if (parent_options) { + if (PyDict_Merge(ret, parent_options, 0) == -1) { + Py_DECREF(parent_options); + return NULL; + } + Py_DECREF(parent_options); + } + } + + return ret; +} + RenderMode *render_mode_create(const char *mode, RenderState *state) { unsigned int i; + PyObject *options; RenderMode *ret = NULL; RenderModeInterface *iface = NULL; for (i = 0; render_modes[i] != NULL; i++) { @@ -44,12 +77,19 @@ RenderMode *render_mode_create(const char *mode, RenderState *state) { if (iface == NULL) return NULL; - ret = malloc(sizeof(RenderMode)); - if (ret == NULL) + options = render_mode_create_options(iface); + if (options == NULL) return NULL; + ret = malloc(sizeof(RenderMode)); + if (ret == NULL) { + Py_DECREF(options); + return NULL; + } + ret->mode = malloc(iface->data_size); if (ret->mode == NULL) { + Py_DECREF(options); free(ret); return NULL; } @@ -57,12 +97,14 @@ RenderMode *render_mode_create(const char *mode, RenderState *state) { ret->iface = iface; ret->state = state; - if (iface->start(ret->mode, state)) { + if (iface->start(ret->mode, state, options)) { + Py_DECREF(options); free(ret->mode); free(ret); return NULL; } + Py_DECREF(options); return ret; } @@ -213,3 +255,19 @@ PyObject *get_render_mode_children(PyObject *self, PyObject *args) { return children; } + +/* python rendermode options bindings */ +PyObject *set_render_mode_options(PyObject *self, PyObject *args) { + const char *rendermode; + PyObject *opts; + if (!PyArg_ParseTuple(args, "sO!", &rendermode, &PyDict_Type, &opts)) + return NULL; + + /* check options here */ + + if (render_mode_options == NULL) + render_mode_options = PyDict_New(); + + PyDict_SetItemString(render_mode_options, rendermode, opts); + Py_RETURN_NONE; +} diff --git a/src/rendermodes.h b/src/rendermodes.h index 5be98eb..a369d77 100644 --- a/src/rendermodes.h +++ b/src/rendermodes.h @@ -50,8 +50,8 @@ struct _RenderModeInterface { /* the size of the local storage for this rendermode */ unsigned int data_size; - /* may return non-zero on error */ - int (*start)(void *, RenderState *); + /* may return non-zero on error, last arg is options */ + int (*start)(void *, RenderState *, PyObject *); void (*finish)(void *, RenderState *); /* returns non-zero to skip rendering this block */ int (*occluded)(void *, RenderState *); @@ -72,13 +72,16 @@ void render_mode_destroy(RenderMode *self); int render_mode_occluded(RenderMode *self); void render_mode_draw(RenderMode *self, PyObject *img, PyObject *mask, PyObject *mask_light); -/* python bindings */ +/* python metadata 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); +/* python rendermode options bindings */ +PyObject *set_render_mode_options(PyObject *self, PyObject *args); + /* individual rendermode interface declarations follow */ /* NORMAL */