Added a "crop" feature to render subsets of worlds
This commit is contained in:
@@ -334,6 +334,22 @@ values. The valid configuration keys are listed below.
|
|||||||
This is a where a specific texture pack can be found to be used during this render.
|
This is a where a specific texture pack can be found to be used during this render.
|
||||||
It can be either a folder or a directory. Its value should be a string.
|
It can be either a folder or a directory. Its value should be a string.
|
||||||
|
|
||||||
|
``crop``
|
||||||
|
You can use this to render a small subset of your map, instead of the entire
|
||||||
|
thing. The format is (min x, max x, min z, max z).
|
||||||
|
|
||||||
|
(The coordinates are block coordinates. The same you get with the debug menu
|
||||||
|
in-game)
|
||||||
|
|
||||||
|
Example that only renders a 1000 by 1000 square of land around the origin::
|
||||||
|
|
||||||
|
renders['myrender'] = {
|
||||||
|
'world': 'myworld',
|
||||||
|
'title': "Cropped Example",
|
||||||
|
'crop': (-500,500, -500,500),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.. _customrendermodes:
|
.. _customrendermodes:
|
||||||
|
|
||||||
Custom Rendermodes and Rendermode Primitives
|
Custom Rendermodes and Rendermode Primitives
|
||||||
|
|||||||
@@ -366,6 +366,10 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
|
|||||||
logging.error("Sorry, you requested dimension '%s' for %s, but I couldn't find it", render['dimension'], render_name)
|
logging.error("Sorry, you requested dimension '%s' for %s, but I couldn't find it", render['dimension'], render_name)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
# 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):
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ renders = Setting(required=True, default={},
|
|||||||
"texturepath": Setting(required=False, validator=validateTexturePath, default=None),
|
"texturepath": Setting(required=False, validator=validateTexturePath, default=None),
|
||||||
"renderchecks": Setting(required=False, validator=validateInt, default=None),
|
"renderchecks": Setting(required=False, validator=validateInt, default=None),
|
||||||
"rerenderprob": Setting(required=True, validator=validateFloat, default=0),
|
"rerenderprob": Setting(required=True, validator=validateFloat, default=0),
|
||||||
|
"crop": Setting(required=False, validator=validateCrop, default=None),
|
||||||
|
|
||||||
# Remove this eventually (once people update their configs)
|
# Remove this eventually (once people update their configs)
|
||||||
"worldname": Setting(required=False, default=None,
|
"worldname": Setting(required=False, default=None,
|
||||||
|
|||||||
@@ -166,6 +166,16 @@ def validateOutputDir(d):
|
|||||||
raise ValidationException("You must specify a valid output directory")
|
raise ValidationException("You must specify a valid output directory")
|
||||||
return os.path.abspath(d)
|
return os.path.abspath(d)
|
||||||
|
|
||||||
|
def validateCrop(value):
|
||||||
|
if len(value) != 4:
|
||||||
|
raise ValidationException("The value for the 'crop' setting must be a tuple of length 4")
|
||||||
|
value = tuple(int(x) for x in value)
|
||||||
|
if value[0] >= value[1]:
|
||||||
|
raise ValidationException("About your crop numbers, the xmax value must be greater than the xmin value")
|
||||||
|
if value[2] >= value[3]:
|
||||||
|
raise ValidationException("About your crop numbers, the zmax value must be greater than the zmin value")
|
||||||
|
return value
|
||||||
|
|
||||||
def make_dictValidator(keyvalidator, valuevalidator):
|
def make_dictValidator(keyvalidator, valuevalidator):
|
||||||
"""Compose and return a dict validator -- a validator that validates each
|
"""Compose and return a dict validator -- a validator that validates each
|
||||||
key and value in a dictionary.
|
key and value in a dictionary.
|
||||||
|
|||||||
@@ -489,7 +489,7 @@ class TileSet(object):
|
|||||||
bounds = self._find_chunk_range()
|
bounds = self._find_chunk_range()
|
||||||
|
|
||||||
# Calculate the depth of the tree
|
# Calculate the depth of the tree
|
||||||
for p in xrange(1,33): # max 32
|
for p in xrange(2,33): # max 32
|
||||||
# Will 2^p tiles wide and high suffice?
|
# Will 2^p tiles wide and high suffice?
|
||||||
|
|
||||||
# X has twice as many chunks as tiles, then halved since this is a
|
# X has twice as many chunks as tiles, then halved since this is a
|
||||||
@@ -498,8 +498,11 @@ class TileSet(object):
|
|||||||
# Y has 4 times as many chunks as tiles, then halved since this is
|
# Y has 4 times as many chunks as tiles, then halved since this is
|
||||||
# a radius
|
# a radius
|
||||||
yradius = 2*2**p
|
yradius = 2*2**p
|
||||||
|
# The +32 on the y bounds is because chunks are very tall, and in
|
||||||
|
# rare cases when the bottom of the map is close to a border, it
|
||||||
|
# could get cut off
|
||||||
if xradius >= bounds.maxcol and -xradius <= bounds.mincol and \
|
if xradius >= bounds.maxcol and -xradius <= bounds.mincol and \
|
||||||
yradius >= bounds.maxrow and -yradius <= bounds.minrow:
|
yradius >= bounds.maxrow + 32 and -yradius <= bounds.minrow:
|
||||||
break
|
break
|
||||||
self.treedepth = p
|
self.treedepth = p
|
||||||
self.xradius = xradius
|
self.xradius = xradius
|
||||||
|
|||||||
@@ -516,6 +516,40 @@ class RotatedRegionSet(RegionSetWrapper):
|
|||||||
x,z = self.rotate(x,z)
|
x,z = self.rotate(x,z)
|
||||||
yield x,z,mtime
|
yield x,z,mtime
|
||||||
|
|
||||||
|
class CroppedRegionSet(RegionSetWrapper):
|
||||||
|
def __init__(self, rsetobj, xmin, xmax, zmin, zmax):
|
||||||
|
super(CroppedRegionSet, self).__init__(rsetobj)
|
||||||
|
self.xmin = xmin//16
|
||||||
|
self.xmax = xmax//16
|
||||||
|
self.zmin = zmin//16
|
||||||
|
self.zmax = zmax//16
|
||||||
|
|
||||||
|
def get_chunk(self,x,z):
|
||||||
|
if (
|
||||||
|
self.xmin <= x <= self.xmax and
|
||||||
|
self.zmin <= z <= self.zmax
|
||||||
|
):
|
||||||
|
return super(CroppedRegionSet, self).get_chunk(x,z)
|
||||||
|
else:
|
||||||
|
raise ChunkDoesntExist("This chunk is out of the requested bounds")
|
||||||
|
|
||||||
|
def iterate_chunks(self):
|
||||||
|
return ((x,z,mtime) for (x,z,mtime) in super(CroppedRegionSet,self).iterate_chunks()
|
||||||
|
if
|
||||||
|
self.xmin <= x <= self.xmax and
|
||||||
|
self.zmin <= z <= self.zmax
|
||||||
|
)
|
||||||
|
def get_chunk_mtime(self,x,z):
|
||||||
|
if (
|
||||||
|
self.xmin <= x <= self.xmax and
|
||||||
|
self.zmin <= z <= self.zmax
|
||||||
|
):
|
||||||
|
return super(CroppedRegionSet, self).get_chunk_mtime(x,z)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_save_dir():
|
def get_save_dir():
|
||||||
"""Returns the path to the local saves directory
|
"""Returns the path to the local saves directory
|
||||||
* On Windows, at %APPDATA%/.minecraft/saves/
|
* On Windows, at %APPDATA%/.minecraft/saves/
|
||||||
|
|||||||
Reference in New Issue
Block a user