0

added support for "custom" rendermodes created in python

This commit is contained in:
Aaron Griffith
2011-06-11 04:01:40 -04:00
parent bfb92de7b7
commit bd9b1873e3
6 changed files with 239 additions and 89 deletions

View File

@@ -166,7 +166,7 @@ class ConfigOptionParser(object):
elif a['type'] == "long": elif a['type'] == "long":
return long(value) return long(value)
elif a['type'] == "choice": elif a['type'] == "choice":
if value not in a['choices']: if ('choices' in a) and (value not in a['choices']):
logging.error("The value '%s' is not valid for config parameter '%s'" % (value, a['dest'])) logging.error("The value '%s' is not valid for config parameter '%s'" % (value, a['dest']))
sys.exit(1) sys.exit(1)
return value return value

View File

@@ -95,9 +95,10 @@ def main():
parser.add_option("-d", "--delete", dest="delete", help="Clear all caches. Next time you render your world, it will have to start completely over again. This is probably not a good idea for large worlds. Use this if you change texture packs and want to re-render everything.", action="store_true", commandLineOnly=True) parser.add_option("-d", "--delete", dest="delete", help="Clear all caches. Next time you render your world, it will have to start completely over again. This is probably not a good idea for large worlds. Use this if you change texture packs and want to re-render everything.", action="store_true", commandLineOnly=True)
parser.add_option("--regionlist", dest="regionlist", help="A file containing, on each line, a path to a regionlist to update. Instead of scanning the world directory for regions, it will just use this list. Normal caching rules still apply.") parser.add_option("--regionlist", dest="regionlist", help="A file containing, on each line, a path to a regionlist to update. Instead of scanning the world directory for regions, it will just use this list. Normal caching rules still apply.")
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("--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("--rendermodes", dest="rendermode", help="Specifies the render types, separated by commas. Use --list-rendermodes to list them all.", type="choice", 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("--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("--rendermode-options", dest="rendermode_options", default={}, configFileOnly=True)
parser.add_option("--custom-rendermodes", dest="custom_rendermodes", 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("--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("--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") 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")
@@ -127,6 +128,12 @@ def main():
pass pass
sys.exit(0) sys.exit(0)
# setup c_overviewer rendermode customs / options
for mode in options.custom_rendermodes:
c_overviewer.add_custom_render_mode(mode, options.custom_rendermodes[mode])
for mode in options.rendermode_options:
c_overviewer.set_render_mode_options(mode, options.rendermode_options[mode])
if options.list_rendermodes: if options.list_rendermodes:
rendermode_info = map(c_overviewer.get_render_mode_info, avail_rendermodes) rendermode_info = map(c_overviewer.get_render_mode_info, avail_rendermodes)
name_width = max(map(lambda i: len(i['name']), rendermode_info)) name_width = max(map(lambda i: len(i['name']), rendermode_info))

View File

@@ -68,7 +68,9 @@ def pool_initializer(rendernode):
textures.generate(path=rendernode.options.get('textures_path', None)) textures.generate(path=rendernode.options.get('textures_path', None))
c_overviewer.init_chunk_render() c_overviewer.init_chunk_render()
# setup c_overviewer rendermode options # setup c_overviewer rendermode customs / options
for mode in rendernode.options.custom_rendermodes:
c_overviewer.add_custom_render_mode(mode, rendernode.options.custom_rendermodes[mode])
for mode in rendernode.options.rendermode_options: for mode in rendernode.options.rendermode_options:
c_overviewer.set_render_mode_options(mode, rendernode.options.rendermode_options[mode]) c_overviewer.set_render_mode_options(mode, rendernode.options.rendermode_options[mode])

View File

@@ -35,17 +35,15 @@ static PyMethodDef COverviewerMethods[] = {
"returns available render modes"}, "returns available render modes"},
{"get_render_mode_info", get_render_mode_info, METH_VARARGS, {"get_render_mode_info", get_render_mode_info, METH_VARARGS,
"returns info for a particular render mode"}, "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, {"get_render_mode_inheritance", get_render_mode_inheritance, METH_VARARGS,
"returns inheritance chain for a particular render mode"}, "returns inheritance chain for a particular render mode"},
{"get_render_mode_children", get_render_mode_children, METH_VARARGS, {"get_render_mode_children", get_render_mode_children, METH_VARARGS,
"returns (direct) children for a particular render mode"}, "returns (direct) children for a particular render mode"},
{"get_render_mode_options", get_render_mode_options, METH_VARARGS,
"returns a list of options for this render mode"},
{"set_render_mode_options", set_render_mode_options, METH_VARARGS, {"set_render_mode_options", set_render_mode_options, METH_VARARGS,
"sets the default options for a given render mode"}, "sets the default options for a given render mode"},
{"add_custom_render_mode", add_custom_render_mode, METH_VARARGS,
"add a new rendermode derived from an existing mode"},
{"extension_version", get_extension_version, METH_VARARGS, {"extension_version", get_extension_version, METH_VARARGS,
"Returns the extension version"}, "Returns the extension version"},

View File

@@ -31,25 +31,52 @@ static RenderModeInterface *render_modes[] = {
}; };
static PyObject *render_mode_options = NULL; static PyObject *render_mode_options = NULL;
static PyObject *custom_render_modes = NULL;
/* rendermode encapsulation */ /* rendermode encapsulation */
/* helper to recursively find options for a given mode */ /* helper to recursively find options for a given mode */
static inline PyObject * static inline PyObject *
render_mode_create_options(RenderModeInterface *iface) { render_mode_create_options(const char *mode) {
const char *parent = NULL;
PyObject *base_options, *ret, *parent_options; PyObject *base_options, *ret, *parent_options;
unsigned int i, found_concrete;
if (render_mode_options == NULL) if (render_mode_options == NULL)
return PyDict_New(); return PyDict_New();
base_options = PyDict_GetItemString(render_mode_options, iface->name); base_options = PyDict_GetItemString(render_mode_options, mode);
if (base_options) { if (base_options) {
ret = PyDict_Copy(base_options); ret = PyDict_Copy(base_options);
} else { } else {
ret = PyDict_New(); ret = PyDict_New();
} }
if (iface->parent) { /* figure out the parent mode name */
parent_options = render_mode_create_options(iface->parent); found_concrete = 0;
for (i = 0; render_modes[i] != NULL; i++) {
if (strcmp(render_modes[i]->name, mode) == 0) {
found_concrete = 1;
if (render_modes[i]->parent) {
parent = render_modes[i]->parent->name;
}
break;
}
}
/* check custom mode info if needed */
if (found_concrete == 1 && custom_render_modes != NULL) {
PyObject *custom = PyDict_GetItemString(custom_render_modes, mode);
if (custom) {
custom = PyDict_GetItemString(custom, "parent");
if (custom) {
parent = PyString_AsString(custom);
}
}
}
/* merge parent options, if the parent was found */
if (parent) {
parent_options = render_mode_create_options(parent);
if (parent_options) { if (parent_options) {
if (PyDict_Merge(ret, parent_options, 0) == -1) { if (PyDict_Merge(ret, parent_options, 0) == -1) {
Py_DECREF(parent_options); Py_DECREF(parent_options);
@@ -62,22 +89,45 @@ render_mode_create_options(RenderModeInterface *iface) {
return ret; return ret;
} }
RenderMode *render_mode_create(const char *mode, RenderState *state) { /* helper to find the first concrete, C interface for a given mode */
inline static RenderModeInterface *
render_mode_find_interface(const char *mode) {
PyObject *custom;
const char *custom_parent;
unsigned int i; unsigned int i;
/* if it is *itself* concrete, we're done */
for (i = 0; render_modes[i] != NULL; i++) {
if (strcmp(render_modes[i]->name, mode) == 0)
return render_modes[i];
}
/* check for custom modes */
if (custom_render_modes == NULL)
return NULL;
custom = PyDict_GetItemString(custom_render_modes, mode);
if (custom == NULL)
return NULL;
custom = PyDict_GetItemString(custom, "parent");
if (custom == NULL)
return NULL;
custom_parent = PyString_AsString(custom);
if (custom_parent == NULL)
return NULL;
return render_mode_find_interface(custom_parent);
}
RenderMode *render_mode_create(const char *mode, RenderState *state) {
PyObject *options; PyObject *options;
RenderMode *ret = NULL; RenderMode *ret = NULL;
RenderModeInterface *iface = NULL; RenderModeInterface *iface = NULL;
for (i = 0; render_modes[i] != NULL; i++) {
if (strcmp(render_modes[i]->name, mode) == 0) {
iface = render_modes[i];
break;
}
}
iface = render_mode_find_interface(mode);
if (iface == NULL) if (iface == NULL)
return NULL; return NULL;
options = render_mode_create_options(iface); options = render_mode_create_options(mode);
if (options == NULL) if (options == NULL)
return NULL; return NULL;
@@ -139,9 +189,61 @@ PyObject *get_render_modes(PyObject *self, PyObject *args) {
Py_DECREF(name); Py_DECREF(name);
} }
if (custom_render_modes != NULL) {
PyObject *key, *value;
Py_ssize_t pos = 0;
while (PyDict_Next(custom_render_modes, &pos, &key, &value)) {
PyList_Append(modes, key);
}
}
return modes; return modes;
} }
/* helper, get the list of options for a render mode */
static inline PyObject *
get_render_mode_options(const char *rendermode)
{
PyObject *options;
unsigned int i, j;
options = PyList_New(0);
if (!options)
return NULL;
for (i = 0; render_modes[i] != NULL; i++) {
if (strcmp(render_modes[i]->name, rendermode) == 0) {
if (render_modes[i]->options == NULL)
break;
for (j = 0; render_modes[i]->options[j].name != NULL; j++) {
RenderModeOption opt = render_modes[i]->options[j];
PyObject *name = PyString_FromString(opt.name);
PyObject *description = PyString_FromString(opt.description);
PyObject *option = PyDict_New();
if (!name || !description || !option) {
Py_XDECREF(name);
Py_XDECREF(description);
Py_XDECREF(option);
Py_DECREF(options);
return NULL;
}
PyDict_SetItemString(option, "name", name);
PyDict_SetItemString(option, "description", description);
PyList_Append(options, option);
Py_DECREF(name);
Py_DECREF(description);
Py_DECREF(option);
}
break;
}
}
return options;
}
/* more bindings -- return info for a given rendermode name */ /* more bindings -- return info for a given rendermode name */
PyObject *get_render_mode_info(PyObject *self, PyObject *args) { PyObject *get_render_mode_info(PyObject *self, PyObject *args) {
const char* rendermode; const char* rendermode;
@@ -166,33 +268,39 @@ PyObject *get_render_mode_info(PyObject *self, PyObject *args) {
PyDict_SetItemString(info, "description", tmp); PyDict_SetItemString(info, "description", tmp);
Py_DECREF(tmp); Py_DECREF(tmp);
tmp = get_render_mode_options(rendermode);
PyDict_SetItemString(info, "options", tmp);
Py_DECREF(tmp);
if (render_modes[i]->parent != NULL) {
tmp = PyString_FromString(render_modes[i]->parent->name);
PyDict_SetItemString(info, "parent", tmp);
Py_DECREF(tmp);
}
return info; return info;
} }
} }
Py_DECREF(info); if (custom_render_modes != NULL) {
return PyErr_Format(PyExc_ValueError, "invalid rendermode: \"%s\"", rendermode); PyObject *custom = PyDict_GetItemString(custom_render_modes, rendermode);
} if (custom) {
PyObject *tmp, *copy = PyDict_Copy(custom);
Py_DECREF(info);
/* bindings -- get parent's name */ tmp = PyString_FromString(rendermode);
PyObject *get_render_mode_parent(PyObject *self, PyObject *args) { PyDict_SetItemString(copy, "name", tmp);
const char *rendermode; Py_DECREF(tmp);
unsigned int i;
if (!PyArg_ParseTuple(args, "s", &rendermode))
return NULL;
for (i = 0; render_modes[i] != NULL; i++) { tmp = PyList_New(0);
if (strcmp(render_modes[i]->name, rendermode) == 0) { PyDict_SetItemString(copy, "options", tmp);
if (render_modes[i]->parent) { Py_DECREF(tmp);
/* has parent */
return PyString_FromString(render_modes[i]->parent->name); return copy;
} else {
/* no parent */
Py_RETURN_NONE;
}
} }
} }
Py_DECREF(info);
return PyErr_Format(PyExc_ValueError, "invalid rendermode: \"%s\"", rendermode); return PyErr_Format(PyExc_ValueError, "invalid rendermode: \"%s\"", rendermode);
} }
@@ -209,6 +317,21 @@ PyObject *get_render_mode_inheritance(PyObject *self, PyObject *args) {
if (!parents) if (!parents)
return NULL; return NULL;
/* take care of the chain of custom modes, if there are any */
if (custom_render_modes != NULL) {
PyObject *custom = PyDict_GetItemString(custom_render_modes, rendermode);
while (custom != NULL) {
PyObject *name = PyString_FromString(rendermode);
PyList_Append(parents, name);
Py_DECREF(name);
custom = PyDict_GetItemString(custom, "parent");
rendermode = PyString_AsString(custom);
custom = PyDict_GetItem(custom_render_modes, custom);
}
}
/* now handle concrete modes */
for (i = 0; render_modes[i] != NULL; i++) { for (i = 0; render_modes[i] != NULL; i++) {
if (strcmp(render_modes[i]->name, rendermode) == 0) { if (strcmp(render_modes[i]->name, rendermode) == 0) {
iface = render_modes[i]; iface = render_modes[i];
@@ -253,52 +376,21 @@ PyObject *get_render_mode_children(PyObject *self, PyObject *args) {
} }
} }
return children; if (custom_render_modes != NULL) {
} PyObject *key, *value;
Py_ssize_t pos = 0;
/* bindings -- get list of options */ while (PyDict_Next(custom_render_modes, &pos, &key, &value)) {
PyObject *get_render_mode_options(PyObject *self, PyObject *args) PyObject *pyparent = PyDict_GetItemString(value, "parent");
{ const char *parent = PyString_AsString(pyparent);
const char *rendermode;
PyObject *options;
unsigned int i, j;
if (!PyArg_ParseTuple(args, "s", &rendermode))
return NULL;
options = PyList_New(0); if (strcmp(parent, rendermode) == 0) {
if (!options) PyList_Append(children, key);
return NULL;
for (i = 0; render_modes[i] != NULL; i++) {
if (strcmp(render_modes[i]->name, rendermode) == 0) {
if (render_modes[i]->options == NULL)
break;
for (j = 0; render_modes[i]->options[j].name != NULL; j++) {
RenderModeOption opt = render_modes[i]->options[j];
PyObject *name = PyString_FromString(opt.name);
PyObject *description = PyString_FromString(opt.description);
PyObject *option = PyDict_New();
if (!name || !description || !option) {
Py_XDECREF(name);
Py_XDECREF(description);
Py_XDECREF(option);
Py_DECREF(options);
return NULL;
}
PyDict_SetItemString(option, "name", name);
PyDict_SetItemString(option, "description", description);
PyList_Append(options, option);
Py_DECREF(name);
Py_DECREF(description);
Py_DECREF(option);
} }
break;
} }
} }
return options; return children;
} }
/* helper to decide if a rendermode supports a given option */ /* helper to decide if a rendermode supports a given option */
@@ -326,16 +418,10 @@ PyObject *set_render_mode_options(PyObject *self, PyObject *args) {
PyObject *opts, *key, *value; PyObject *opts, *key, *value;
Py_ssize_t pos = 0; Py_ssize_t pos = 0;
RenderModeInterface *iface = NULL; RenderModeInterface *iface = NULL;
unsigned int i;
if (!PyArg_ParseTuple(args, "sO!", &rendermode, &PyDict_Type, &opts)) if (!PyArg_ParseTuple(args, "sO!", &rendermode, &PyDict_Type, &opts))
return NULL; return NULL;
for (i = 0; render_modes[i] != NULL; i++) { iface = render_mode_find_interface(rendermode);
if (strcmp(render_modes[i]->name, rendermode) == 0) {
iface = render_modes[i];
break;
}
}
if (iface == NULL) { if (iface == NULL) {
return PyErr_Format(PyExc_ValueError, "'%s' is not a valid rendermode name", rendermode); return PyErr_Format(PyExc_ValueError, "'%s' is not a valid rendermode name", rendermode);
@@ -358,3 +444,61 @@ PyObject *set_render_mode_options(PyObject *self, PyObject *args) {
PyDict_SetItemString(render_mode_options, rendermode, opts); PyDict_SetItemString(render_mode_options, rendermode, opts);
Py_RETURN_NONE; Py_RETURN_NONE;
} }
PyObject *add_custom_render_mode(PyObject *self, PyObject *args) {
const char *rendermode, *parentmode;
PyObject *opts, *options, *pyparent;
if (!PyArg_ParseTuple(args, "sO!", &rendermode, &PyDict_Type, &opts))
return NULL;
if (custom_render_modes == NULL)
custom_render_modes = PyDict_New();
/* first, make sure the parent is set correctly */
pyparent = PyDict_GetItemString(opts, "parent");
if (pyparent == NULL)
return PyErr_Format(PyExc_ValueError, "'%s' does not have a parent mode", rendermode);
parentmode = PyString_AsString(pyparent);
if (parentmode == NULL)
return PyErr_Format(PyExc_ValueError, "'%s' does not have a valid parent", rendermode);
/* check that parentmode exists */
if (PyDict_GetItemString(custom_render_modes, parentmode) == NULL) {
unsigned int parent_valid = 0, i;
for (i = 0; render_modes[i] != NULL; i++) {
if (strcmp(render_modes[i]->name, parentmode) == 0) {
parent_valid = 1;
}
}
if (parent_valid == 0)
return PyErr_Format(PyExc_ValueError, "'%s' parent '%s' is not valid", rendermode, parentmode);
}
/* remove and handle options seperately, if needed */
options = PyDict_GetItemString(opts, "options");
if (options != NULL) {
PyObject *opts_copy, *set_opts_args;
opts_copy = PyDict_Copy(opts);
if (opts_copy == NULL)
return NULL;
PyDict_DelItemString(opts_copy, "options");
PyDict_SetItemString(custom_render_modes, rendermode, opts_copy);
Py_DECREF(opts_copy);
/* call set_render_mode_options */
set_opts_args = Py_BuildValue("sO", rendermode, options);
if (set_opts_args == NULL)
return NULL;
if (set_render_mode_options(NULL, set_opts_args) == NULL) {
Py_DECREF(set_opts_args);
return NULL;
}
Py_DECREF(set_opts_args);
} else {
PyDict_SetItemString(custom_render_modes, rendermode, opts);
}
Py_RETURN_NONE;
}

View File

@@ -83,13 +83,12 @@ void render_mode_draw(RenderMode *self, PyObject *img, PyObject *mask, PyObject
/* python metadata bindings */ /* python metadata bindings */
PyObject *get_render_modes(PyObject *self, PyObject *args); PyObject *get_render_modes(PyObject *self, PyObject *args);
PyObject *get_render_mode_info(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_inheritance(PyObject *self, PyObject *args);
PyObject *get_render_mode_children(PyObject *self, PyObject *args); PyObject *get_render_mode_children(PyObject *self, PyObject *args);
PyObject *get_render_mode_options(PyObject *self, PyObject *args);
/* python rendermode options bindings */ /* python rendermode options bindings */
PyObject *set_render_mode_options(PyObject *self, PyObject *args); PyObject *set_render_mode_options(PyObject *self, PyObject *args);
PyObject *add_custom_render_mode(PyObject *self, PyObject *args);
/* individual rendermode interface declarations follow */ /* individual rendermode interface declarations follow */