diff --git a/.gitignore b/.gitignore index 1918894..ffd3ba6 100644 --- a/.gitignore +++ b/.gitignore @@ -22,8 +22,9 @@ overviewer_core/c_overviewer.pyd overviewer_core/c_overviewer_d.pyd overviewer_core/c_overviewer.dylib -# generated version file +# generated files overviewer_core/overviewer_version.py +overviewer_core/src/primitives.h # Mac OS X noise .DS_Store diff --git a/overviewer_core/src/rendermodes.c b/overviewer_core/src/rendermodes.c index 3e75073..9a70ba1 100644 --- a/overviewer_core/src/rendermodes.c +++ b/overviewer_core/src/rendermodes.c @@ -19,29 +19,13 @@ #include #include -extern RenderPrimitiveInterface primitive_base; -extern RenderPrimitiveInterface primitive_nether; -extern RenderPrimitiveInterface primitive_height_fading; -extern RenderPrimitiveInterface primitive_depth; -extern RenderPrimitiveInterface primitive_edge_lines; - -/* list of all render primitives, ending in NULL +/* 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. */ -static RenderPrimitiveInterface *render_primitives[] = { - &primitive_base, - &primitive_nether, - &primitive_height_fading, - &primitive_depth, - &primitive_edge_lines, - //&rendermode_lighting, - //&rendermode_smooth_lighting, - //&rendermode_cave, - - //&rendermode_spawn, - //&rendermode_mineral, - NULL -}; + that are only useful as a base for other primitives. + + this file is auto-generated by setup.py */ +#include "primitives.h" /* rendermode encapsulation */ diff --git a/overviewer_core/src/rendermodes.h b/overviewer_core/src/rendermodes.h index add5bf9..d10acff 100644 --- a/overviewer_core/src/rendermodes.h +++ b/overviewer_core/src/rendermodes.h @@ -15,15 +15,27 @@ * with the Overviewer. If not, see . */ -/* - * To make a new render primitive (the C part, at least): +/* To make a new render primitive: * - * * add a data struct and extern'd interface declaration below + * * add a new class to rendermodes.py + * there are a ton of examples there, the syntax is pretty simple. If + * you need any extra objects that are easy to create in python, this + * is where you put them. * - * * fill in this interface struct in primitives/(yourmode).c - * (see primitives/base.c for an example: the "base" primitive) + * * create a file in src/primitives with the same name + * so, Nether (named "nether") goes in `nether.c`. * - * * add your primitive to the list in rendermodes.c + * * declare a RenderPrimitiveInterface with the name primitive_name + * if you have an underscore in the name, replace it with a + * hyphen. height-fading uses primitive_height_fading. + * + * * fill in the entries of this struct + * the name should match, and you should declare an 'instance' struct + * to use as the self argument to each function. See nether.c and + * height-fading.c for simple examples. + * + * setup.py will pick up your primitive, add it to the global list, and build + * it for you if you follow these conventions. */ #ifndef __RENDERMODES_H_INCLUDED__ diff --git a/setup.py b/setup.py index 3c82fc2..7a20a3d 100755 --- a/setup.py +++ b/setup.py @@ -15,6 +15,7 @@ import glob import platform import time import overviewer_core.util as util +import numpy try: import py2exe @@ -133,7 +134,6 @@ if py2exe is None: # # Third-party modules - we depend on numpy for everything -import numpy # Obtain the numpy include directory. This logic works across numpy versions. try: numpy_include = numpy.get_include() @@ -149,9 +149,13 @@ except Exception: # used to figure out what files to compile -#render_modes = ['normal', 'lighting', 'smooth-lighting', 'cave'] -#render_modes += ['overlay', 'spawn', 'mineral'] -primitives = ['base', 'nether', 'height-fading', 'depth', 'edge-lines'] +# auto-created from files in primitives/, but we need the raw names so +# we can use them later. +primitives = [] +for name in glob.glob("overviewer_core/src/primitives/*.c"): + name = os.path.split(name)[-1] + name = os.path.splitext(name)[0] + primitives.append(name) c_overviewer_files = ['main.c', 'composite.c', 'iterate.c', 'endian.c', 'rendermodes.c'] c_overviewer_files += map(lambda mode: 'primitives/%s.c' % (mode,), primitives) @@ -169,7 +173,7 @@ setup_kwargs['ext_modules'].append(Extension('overviewer_core.c_overviewer', c_o setup_kwargs['options']['build_ext'] = {'inplace' : 1} # custom clean command to remove in-place extension -# and the version file +# and the version file, primitives header class CustomClean(clean): def run(self): # do the normal cleanup @@ -178,31 +182,24 @@ class CustomClean(clean): # try to remove '_composite.{so,pyd,...}' extension, # regardless of the current system's extension name convention build_ext = self.get_finalized_command('build_ext') - pretty_fname = build_ext.get_ext_filename('overviewer_core.c_overviewer') - fname = pretty_fname - if os.path.exists(fname): - try: - if not self.dry_run: - os.remove(fname) - log.info("removing '%s'", pretty_fname) - except OSError: - log.warn("'%s' could not be cleaned -- permission denied", - pretty_fname) - else: - log.debug("'%s' does not exist -- can't clean it", - pretty_fname) - + ext_fname = build_ext.get_ext_filename('overviewer_core.c_overviewer') versionpath = os.path.join("overviewer_core", "overviewer_version.py") - if os.path.exists(versionpath): - try: - if not self.dry_run: - os.remove(versionpath) - log.info("removing '%s'", versionpath) - except OSError: - log.warn("'%s' could not be cleaned -- permission denied", versionpath) - else: - log.debug("'%s' does not exist -- can't clean it", versionpath) - + primspath = os.path.join("overviewer_core", "src", "primitives.h") + + for fname in [ext_fname, versionpath, primspath]: + if os.path.exists(fname): + try: + log.info("removing '%s'", fname) + if not self.dry_run: + os.remove(fname) + + except OSError: + log.warn("'%s' could not be cleaned -- permission denied", + fname) + else: + log.debug("'%s' does not exist -- can't clean it", + fname) + # now try to purge all *.pyc files for root, dirs, files in os.walk(os.path.join(os.path.dirname(__file__), ".")): for f in files: @@ -226,16 +223,34 @@ def generate_version_py(): except Exception: print "WARNING: failed to build overviewer_version file" +def generate_primitives_h(): + global primitives + prims = [p.lower().replace('-', '_') for p in primitives] + + outstr = "/* this file is auto-generated by setup.py */\n" + for p in prims: + outstr += "extern RenderPrimitiveInterface primitive_{0};\n".format(p) + outstr += "static RenderPrimitiveInterface *render_primitives[] = {\n" + for p in prims: + outstr += " &primitive_{0},\n".format(p) + outstr += " NULL\n" + outstr += "};\n" + + with open("overviewer_core/src/primitives.h", "w") as f: + f.write(outstr) + class CustomSDist(sdist): def run(self): # generate the version file generate_version_py() + generate_primitives_h() sdist.run(self) class CustomBuild(build): def run(self): # generate the version file generate_version_py() + generate_primitives_h() build.run(self) print "\nBuild Complete"