/* * 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 . */ #include #include #include "overviewer.h" /* this file defines render_primitives, a list of all render primitives, ending in NULL all of these will be available to the user, so DON'T include primitives that are only useful as a base for other primitives. this file is auto-generated by setup.py */ #include "primitives.h" /* rendermode encapsulation */ /* helper to create a single primitive */ RenderPrimitive* render_primitive_create(PyObject* prim, RenderState* state) { RenderPrimitive* ret = NULL; RenderPrimitiveInterface* iface = NULL; uint32_t i; PyObject* pyname; const char* name; pyname = PyObject_GetAttrString(prim, "name"); if (!pyname) return NULL; name = PyUnicode_AsUTF8(pyname); for (i = 0; render_primitives[i] != NULL; i++) { if (strcmp(render_primitives[i]->name, name) == 0) { iface = render_primitives[i]; break; } } Py_DECREF(pyname); if (iface == NULL) return (RenderPrimitive*)PyErr_Format(PyExc_RuntimeError, "invalid primitive name: %s", name); ret = calloc(1, sizeof(RenderPrimitive)); if (ret == NULL) { return (RenderPrimitive*)PyErr_Format(PyExc_RuntimeError, "Failed to alloc a render primitive"); } if (iface->data_size > 0) { ret->primitive = calloc(1, iface->data_size); if (ret->primitive == NULL) { free(ret); return (RenderPrimitive*)PyErr_Format(PyExc_RuntimeError, "Failed to alloc render primitive data"); } } ret->iface = iface; if (iface->start) { if (iface->start(ret->primitive, state, prim)) { free(ret->primitive); free(ret); return NULL; } } return ret; } RenderMode* render_mode_create(PyObject* mode, RenderState* state) { RenderMode* ret = NULL; PyObject* mode_fast = NULL; uint32_t i; mode_fast = PySequence_Fast(mode, "Mode is not a sequence type"); if (!mode_fast) return NULL; ret = calloc(1, sizeof(RenderMode)); ret->state = state; ret->num_primitives = PySequence_Length(mode); ret->primitives = calloc(ret->num_primitives, sizeof(RenderPrimitive*)); for (i = 0; i < ret->num_primitives; i++) { PyObject* pyprim = PySequence_Fast_GET_ITEM(mode_fast, i); RenderPrimitive* prim = render_primitive_create(pyprim, state); if (!prim) { render_mode_destroy(ret); Py_DECREF(mode_fast); return NULL; } ret->primitives[i] = prim; } return ret; } void render_mode_destroy(RenderMode* self) { uint32_t i; for (i = 0; i < self->num_primitives; i++) { RenderPrimitive* prim = self->primitives[i]; /* we may be destroying a half-constructed mode, so we need this check */ if (prim) { if (prim->iface->finish) { prim->iface->finish(prim->primitive, self->state); } if (prim->primitive) { free(prim->primitive); } free(prim); } } free(self->primitives); free(self); } bool render_mode_occluded(RenderMode* self, int32_t x, int32_t y, int32_t z) { uint32_t i; bool occluded = false; for (i = 0; i < self->num_primitives; i++) { RenderPrimitive* prim = self->primitives[i]; if (prim->iface->occluded) { occluded |= prim->iface->occluded(prim->primitive, self->state, x, y, z); } if (occluded) return occluded; } return occluded; } bool render_mode_hidden(RenderMode* self, int32_t x, int32_t y, int32_t z) { uint32_t i; bool hidden = false; for (i = 0; i < self->num_primitives; i++) { RenderPrimitive* prim = self->primitives[i]; if (prim->iface->hidden) { hidden |= prim->iface->hidden(prim->primitive, self->state, x, y, z); } if (hidden) return hidden; } return hidden; } void render_mode_draw(RenderMode* self, PyObject* img, PyObject* mask, PyObject* mask_light) { uint32_t i; for (i = 0; i < self->num_primitives; i++) { RenderPrimitive* prim = self->primitives[i]; if (prim->iface->draw) { prim->iface->draw(prim->primitive, self->state, img, mask, mask_light); } } } /* options parse helper */ bool render_mode_parse_option(PyObject* support, const char* name, const char* format, ...) { va_list ap; PyObject *item, *dict; bool ret; if (support == NULL || name == NULL) return false; dict = PyObject_GetAttrString(support, "option_values"); if (!dict) return false; item = PyDict_GetItemString(dict, name); if (item == NULL) { Py_DECREF(dict); return false; }; /* make sure the item we're parsing is a tuple for VaParse to work correctly */ if (!PyTuple_Check(item)) { item = PyTuple_Pack(1, item); } else { Py_INCREF(item); } va_start(ap, format); ret = PyArg_VaParse(item, format, ap); va_end(ap); Py_DECREF(item); Py_DECREF(dict); if (!ret) { PyObject *errtype, *errvalue, *errtraceback, *errstring; PyErr_Fetch(&errtype, &errvalue, &errtraceback); errstring = PyUnicode_AsUTF8String(errvalue); PyErr_Format(PyExc_TypeError, "rendermode option \"%s\" has incorrect type (%s)", name, errstring); Py_DECREF(errtype); Py_DECREF(errvalue); Py_XDECREF(errtraceback); } return ret; }