0

Added the ability to specify multiple crop zones.

This commit is contained in:
matrixhacker
2014-05-09 23:44:46 -04:00
parent 8881ba608d
commit b6ac54a2b6
5 changed files with 63 additions and 20 deletions

View File

@@ -709,8 +709,8 @@ values. The valid configuration keys are listed below.
.. _crop: .. _crop:
``crop`` ``crop``
You can use this to render a small subset of your map, instead of the entire You can use this to render one or more small subsets of your map, instead
thing. The format is (min x, min z, max x, max z). of the entire thing. The format is [(min x, min z, max x, max z)].
The coordinates are block coordinates. The same you get with the debug menu The coordinates are block coordinates. The same you get with the debug menu
in-game and the coordinates shown when you view a map. in-game and the coordinates shown when you view a map.
@@ -723,6 +723,14 @@ values. The valid configuration keys are listed below.
'crop': (-500, -500, 500, 500), 'crop': (-500, -500, 500, 500),
} }
Example that renders two 500 by 500 squares of land:
renders['myrender'] = {
'world': 'myworld',
'title': "Multi cropped Example",
'crop': [(-500, -500, 0, 0), (0, 0, 500, 500)]
}
This option performs a similar function to the old ``--regionlist`` option This option performs a similar function to the old ``--regionlist`` option
(which no longer exists). It is useful for example if someone has wandered (which no longer exists). It is useful for example if someone has wandered
really far off and made your map too large. You can set the crop for the really far off and made your map too large. You can set the crop for the

View File

@@ -488,16 +488,20 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
# regionset cache pulls from the same underlying cache object. # regionset cache pulls from the same underlying cache object.
rset = world.CachedRegionSet(rset, caches) rset = world.CachedRegionSet(rset, caches)
# If a crop is requested, wrap the regionset here
if "crop" in render:
rset = world.CroppedRegionSet(rset, *render['crop'])
# If this is to be a rotated regionset, wrap it in a RotatedRegionSet # If this is to be a rotated regionset, wrap it in a RotatedRegionSet
# object # object
if (render['northdirection'] > 0): if (render['northdirection'] > 0):
rset = world.RotatedRegionSet(rset, render['northdirection']) rset = world.RotatedRegionSet(rset, render['northdirection'])
logging.debug("Using RegionSet %r", rset) logging.debug("Using RegionSet %r", rset)
# If a crop is requested, wrap the regionset here
if "crop" in render:
rsets = []
for zone in render['crop']:
rsets.append(world.CroppedRegionSet(rset, *zone))
else:
rsets = [rset]
############################### ###############################
# Do the final prep and create the TileSet object # Do the final prep and create the TileSet object
@@ -508,8 +512,9 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
render['name'] = render_name # perhaps a hack. This is stored here for the asset manager render['name'] = render_name # perhaps a hack. This is stored here for the asset manager
tileSetOpts = util.dict_subset(render, ["name", "imgformat", "renderchecks", "rerenderprob", "bgcolor", "defaultzoom", "imgquality", "optimizeimg", "rendermode", "worldname_orig", "title", "dimension", "changelist", "showspawn", "overlay", "base", "poititle", "maxzoom", "showlocationmarker", "minzoom"]) tileSetOpts = util.dict_subset(render, ["name", "imgformat", "renderchecks", "rerenderprob", "bgcolor", "defaultzoom", "imgquality", "optimizeimg", "rendermode", "worldname_orig", "title", "dimension", "changelist", "showspawn", "overlay", "base", "poititle", "maxzoom", "showlocationmarker", "minzoom"])
tileSetOpts.update({"spawn": w.find_true_spawn()}) # TODO find a better way to do this tileSetOpts.update({"spawn": w.find_true_spawn()}) # TODO find a better way to do this
tset = tileset.TileSet(w, rset, assetMrg, tex, tileSetOpts, tileset_dir) for rset in rsets:
tilesets.append(tset) tset = tileset.TileSet(w, rset, assetMrg, tex, tileSetOpts, tileset_dir)
tilesets.append(tset)
# Do tileset preprocessing here, before we start dispatching jobs # Do tileset preprocessing here, before we start dispatching jobs
logging.info("Preprocessing...") logging.info("Preprocessing...")

View File

@@ -19,6 +19,7 @@ import tempfile
import shutil import shutil
import logging import logging
import stat import stat
import errno
default_caps = {"chmod_works": True, "rename_works": True} default_caps = {"chmod_works": True, "rename_works": True}
@@ -150,6 +151,20 @@ class FileReplacer(object):
else: else:
# copy permission bits, if needed # copy permission bits, if needed
if self.caps.get("chmod_works") and os.path.exists(self.destname): if self.caps.get("chmod_works") and os.path.exists(self.destname):
shutil.copymode(self.destname, self.tmpname) try:
shutil.copymode(self.destname, self.tmpname)
except OSError, e:
# Ignore errno ENOENT: file does not exist. Due to a race
# condition, two processes could conceivably try and update
# the same temp file at the same time
if e.errno != errno.ENOENT:
raise
# atomic rename into place # atomic rename into place
os.rename(self.tmpname, self.destname) try:
os.rename(self.tmpname, self.destname)
except OSError, e:
# Ignore errno ENOENT: file does not exist. Due to a race
# condition, two processes could conceivably try and update
# the same temp file at the same time
if e.errno != errno.ENOENT:
raise

View File

@@ -225,15 +225,23 @@ def validateOutputDir(d):
return expand_path(d) return expand_path(d)
def validateCrop(value): def validateCrop(value):
if len(value) != 4: if not isinstance(value, list):
raise ValidationException("The value for the 'crop' setting must be a tuple of length 4") value = [value]
a, b, c, d = tuple(int(x) for x in value)
cropZones = []
if a >= c: for zone in value:
a, c = c, a if len(zone) != 4:
if b >= d: raise ValidationException("The value for the 'crop' setting must be an array of tuples of length 4")
b, d = d, b a, b, c, d = tuple(int(x) for x in zone)
return (a, b, c, d)
if a >= c:
a, c = c, a
if b >= d:
b, d = d, b
cropZones.append((a, b, c, d))
return cropZones
def validateObserver(observer): def validateObserver(observer):
if all(map(lambda m: hasattr(observer, m), ['start', 'add', 'update', 'finish'])): if all(map(lambda m: hasattr(observer, m), ['start', 'add', 'update', 'finish'])):

View File

@@ -947,7 +947,14 @@ class TileSet(object):
if self.options['optimizeimg']: if self.options['optimizeimg']:
optimize_image(tmppath, imgformat, self.options['optimizeimg']) optimize_image(tmppath, imgformat, self.options['optimizeimg'])
os.utime(tmppath, (max_mtime, max_mtime)) try:
os.utime(tmppath, (max_mtime, max_mtime))
except OSError, e:
# Ignore errno ENOENT: file does not exist. Due to a race
# condition, two processes could conceivably try and update
# the same temp file at the same time
if e.errno != errno.ENOENT:
raise
def _render_rendertile(self, tile): def _render_rendertile(self, tile):
"""Renders the given render-tile. """Renders the given render-tile.