move collisions in own layer
This commit is contained in:
parent
e6dd495c9a
commit
4857c999d3
6518
basement.json
6518
basement.json
File diff suppressed because one or more lines are too long
6581
first-floor.json
6581
first-floor.json
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
3682
heizhaus.tmx
3682
heizhaus.tmx
File diff suppressed because it is too large
Load diff
BIN
imgs/collisions.png
Normal file
BIN
imgs/collisions.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 74 B |
181
mapcleanup.py
181
mapcleanup.py
|
@ -1,12 +1,14 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
from argparse import ArgumentParser
|
||||
from lxml import etree
|
||||
from pathlib import Path
|
||||
from PIL import Image
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Cleanup rc3.world maps")
|
||||
parser = ArgumentParser(description="Cleanup rc3.world maps")
|
||||
parser.add_argument("map", help="map in .tmx format")
|
||||
parser.add_argument("-o", "--output", help="where to write modified map")
|
||||
parser.add_argument(
|
||||
|
@ -20,17 +22,34 @@ def main():
|
|||
help="add mapCopyright/tilesetCopyright properties",
|
||||
action="store_true",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--separate-collisions",
|
||||
help="move collisions into a separate 'collisions' layer",
|
||||
action="store_true",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--split-tilesets",
|
||||
help="split tilesets bigger than 4096x4096",
|
||||
action="store_true",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.output and not args.in_place:
|
||||
output = args.output
|
||||
if args.in_place:
|
||||
output = args.map
|
||||
if not output:
|
||||
print("Output unspecified.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
tree = ET.parse(args.map)
|
||||
tree = etree.parse(args.map)
|
||||
map = tree.getroot()
|
||||
if args.fix_copyright:
|
||||
fix_copyright(map)
|
||||
tree.write(args.output or args.map, xml_declaration=False)
|
||||
if args.separate_collisions:
|
||||
separate_collisions(map)
|
||||
if args.split_tilesets:
|
||||
split_tilesets(map)
|
||||
tree.write(output)
|
||||
|
||||
|
||||
def fix_copyright(map):
|
||||
|
@ -38,8 +57,8 @@ def fix_copyright(map):
|
|||
license = input("Map license? [CC0] ") or "CC0"
|
||||
properties = map.find("properties")
|
||||
if properties is None:
|
||||
properties = ET.SubElement(map, "properties")
|
||||
ET.SubElement(properties, "property", name="mapCopyright", value=license)
|
||||
properties = etree.SubElement(map, "properties")
|
||||
etree.SubElement(properties, "property", name="mapCopyright", value=license)
|
||||
|
||||
for tileset in map.findall("tileset"):
|
||||
if tileset.find("properties/property[@name='tilesetCopyright']") is None:
|
||||
|
@ -48,11 +67,153 @@ def fix_copyright(map):
|
|||
)
|
||||
properties = tileset.find("properties")
|
||||
if properties is None:
|
||||
properties = ET.SubElement(tileset, "properties")
|
||||
ET.SubElement(
|
||||
properties = etree.SubElement(tileset, "properties")
|
||||
etree.SubElement(
|
||||
properties, "property", name="tilesetCopyright", value=license
|
||||
)
|
||||
|
||||
|
||||
def separate_collisions(map):
|
||||
# find tiles with collides property
|
||||
colliding_tiles = set()
|
||||
firstgid = 1
|
||||
tilecount = 0
|
||||
for tileset in map.findall("tileset"):
|
||||
if tileset.attrib["name"] == "collisions":
|
||||
continue
|
||||
firstgid = int(tileset.attrib["firstgid"])
|
||||
tilecount = int(tileset.attrib["tilecount"])
|
||||
for tile in tileset.findall("tile"):
|
||||
properties = tile.find("properties")
|
||||
if properties is None:
|
||||
continue
|
||||
for collision_property in properties.findall("property[@name='collides']"):
|
||||
properties.remove(collision_property)
|
||||
if collision_property.attrib["value"] != "true":
|
||||
continue
|
||||
colliding_tiles.add(firstgid + int(tile.attrib["id"]))
|
||||
|
||||
# create/find collisions tileset (single white tile)
|
||||
collisions_tileset = map.find("tileset[@name='collisions']")
|
||||
if collisions_tileset is None:
|
||||
collisions_tileset = etree.Element(
|
||||
"tileset",
|
||||
firstgid=str(firstgid + tilecount),
|
||||
name="collisions",
|
||||
tilewidth="32",
|
||||
tileheight="32",
|
||||
tilecount="1",
|
||||
columns="1",
|
||||
)
|
||||
tileset.addnext(collisions_tileset)
|
||||
etree.SubElement(
|
||||
etree.SubElement(collisions_tileset, "properties"),
|
||||
"property",
|
||||
name="tilesetCopyright",
|
||||
value="not copyrightable",
|
||||
)
|
||||
image_source = Path("imgs") / "collisions.png"
|
||||
image_source.parent.mkdir(parents=True, exist_ok=True)
|
||||
Image.new("1", (32, 32), (1)).save(image_source)
|
||||
etree.SubElement(
|
||||
collisions_tileset,
|
||||
"image",
|
||||
source=str(image_source),
|
||||
width="32",
|
||||
height="32",
|
||||
)
|
||||
etree.SubElement(
|
||||
etree.SubElement(
|
||||
etree.SubElement(collisions_tileset, "tile", id="0"), "properties"
|
||||
),
|
||||
"property",
|
||||
name="collides",
|
||||
type="bool",
|
||||
value="true",
|
||||
)
|
||||
collisions_gid = int(collisions_tileset.attrib["firstgid"])
|
||||
|
||||
# merge collisions
|
||||
collisions = [0] * int(map.attrib["width"]) * int(map.attrib["height"])
|
||||
for layer in map.findall("layer"):
|
||||
if layer.attrib["name"] == "collisions":
|
||||
continue
|
||||
data = [int(x) for x in layer.find("data[@encoding='csv']").text.split(",")]
|
||||
for i, gid in enumerate(data):
|
||||
if gid in colliding_tiles:
|
||||
collisions[i] = collisions_gid
|
||||
|
||||
# create/find collisions layer and save collision data
|
||||
collisions_data = map.find("layer[@name='collisions']/data")
|
||||
if collisions_data is None:
|
||||
collisions_layer = etree.Element(
|
||||
"layer",
|
||||
id=map.attrib["nextlayerid"],
|
||||
name="collisions",
|
||||
width=map.attrib["width"],
|
||||
height=map.attrib["height"],
|
||||
)
|
||||
map.find("layer").addprevious(collisions_layer)
|
||||
map.attrib["nextlayerid"] = str(int(map.attrib["nextlayerid"]) + 1)
|
||||
collisions_data = etree.SubElement(
|
||||
collisions_layer,
|
||||
"data",
|
||||
encoding="csv",
|
||||
)
|
||||
collisions_data.text = ",".join([str(x) for x in collisions])
|
||||
|
||||
|
||||
def split_tilesets(map):
|
||||
# we need the offset of the tileset inside the map element to insert new tilesets correctly
|
||||
for offset, tileset in enumerate(map):
|
||||
if tileset.tag != "tileset":
|
||||
continue
|
||||
image = tileset.find("image")
|
||||
if int(image.attrib["width"]) <= 4096 and int(image.attrib["height"]) <= 4096:
|
||||
continue
|
||||
dosplit = input("Split tileset '%s'? [yN] " % tileset.attrib["name"])
|
||||
if dosplit.lower() != "y":
|
||||
continue
|
||||
properties = tileset.find("properties")
|
||||
firstgid = int(tileset.attrib["firstgid"])
|
||||
tilewidth = int(tileset.attrib["tilewidth"])
|
||||
tileheight = int(tileset.attrib["tileheight"])
|
||||
image_source = Path(image.attrib["source"])
|
||||
with Image.open(image_source) as im:
|
||||
for i, x in enumerate(range(0, im.width, 4096)):
|
||||
for j, y in enumerate(range(0, im.height, 4096)):
|
||||
croped_source = image_source.with_stem(
|
||||
"%s_%02d%02d" % (image_source.stem, i, j)
|
||||
)
|
||||
im.crop(
|
||||
(x, y, min(x + 4096, im.width), min(y + 4096, im.height))
|
||||
).save(croped_source)
|
||||
width = min(4096, im.width - x)
|
||||
height = min(4096, im.height - y)
|
||||
columns = width // tilewidth
|
||||
tilecount = columns * (height // tileheight)
|
||||
tileset_croped = etree.Element(
|
||||
"tileset",
|
||||
name="%s (%d, %d)" % (tileset.attrib["name"], i, j),
|
||||
firstgid=str(firstgid),
|
||||
tilewidth=str(tilewidth),
|
||||
tileheight=str(tileheight),
|
||||
tilecount=str(tilecount),
|
||||
columns=str(columns),
|
||||
)
|
||||
map.insert(offset + i + j, tileset_croped)
|
||||
firstgid += tilecount
|
||||
if properties is not None:
|
||||
tileset_croped.append(properties)
|
||||
etree.SubElement(
|
||||
tileset_croped,
|
||||
"image",
|
||||
source=str(croped_source),
|
||||
width=str(width),
|
||||
height=str(height),
|
||||
)
|
||||
map.remove(tileset)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
Loading…
Reference in a new issue