Rework scripts to work for single tileset
This commit is contained in:
@@ -1,11 +1,19 @@
|
|||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
|
||||||
class ExtractFileWriter:
|
class ExtractFileWriter:
|
||||||
indent_width = 4
|
indent_width = 4
|
||||||
indent_level = 0
|
indent_level = 0
|
||||||
indention = ""
|
indention = ""
|
||||||
|
content = ""
|
||||||
|
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.name = name.upper()
|
self.name = name.upper()
|
||||||
|
|
||||||
|
def to_file(self, path):
|
||||||
|
with open(path, "w") as f:
|
||||||
|
f.write(self.content)
|
||||||
|
|
||||||
def indent(self):
|
def indent(self):
|
||||||
self.indent_level += self.indent_width
|
self.indent_level += self.indent_width
|
||||||
self.indention = " " * self.indent_level
|
self.indention = " " * self.indent_level
|
||||||
@@ -14,51 +22,274 @@ class ExtractFileWriter:
|
|||||||
self.indent_level -= self.indent_width
|
self.indent_level -= self.indent_width
|
||||||
self.indention = " " * self.indent_level
|
self.indention = " " * self.indent_level
|
||||||
|
|
||||||
|
def output_anim_sequence_struct(self):
|
||||||
|
self.output("typedef struct AnimationSequence {\n")
|
||||||
|
self.indent()
|
||||||
|
self.output("BzTile startFrame;\n")
|
||||||
|
self.output("i32 frameCount;\n")
|
||||||
|
self.unindent()
|
||||||
|
self.output("} AnimationSequence;\n")
|
||||||
|
self.empty_line()
|
||||||
|
|
||||||
|
def output_anim_frame_struct(self):
|
||||||
|
self.output("typedef struct AnimationFrame {\n")
|
||||||
|
self.indent()
|
||||||
|
self.output("BzTile frame;\n")
|
||||||
|
self.output("f32 duration;\n")
|
||||||
|
self.unindent()
|
||||||
|
self.output("} AnimationFrame;\n")
|
||||||
|
self.empty_line()
|
||||||
|
|
||||||
def header_guard_start(self):
|
def header_guard_start(self):
|
||||||
print(f"#ifndef {self.name}")
|
self.content += f"#ifndef {self.name}_H\n"
|
||||||
print(f"#define {self.name}")
|
self.content += f"#define {self.name}_H\n"
|
||||||
print()
|
self.content += "\n"
|
||||||
|
|
||||||
def header_guard_stop(self):
|
def header_guard_stop(self):
|
||||||
print(f"#endif // {self.name}")
|
self.content += f"#endif // {self.name}_H\n"
|
||||||
|
|
||||||
def include(self, header):
|
def include(self, header):
|
||||||
print(f"${self.indention}#include {header}")
|
self.content += f"{self.indention}#include {header}\n"
|
||||||
|
|
||||||
def enum_start(self, name):
|
def enum_start(self, name):
|
||||||
print(f"{self.indention}typedef enum {name} {{")
|
self.content += f"{self.indention}typedef enum {name} {{\n"
|
||||||
self.indent()
|
self.indent()
|
||||||
|
|
||||||
def enum_stop(self, name):
|
def enum_stop(self, name):
|
||||||
self.unindent()
|
self.unindent()
|
||||||
print(f"}} {name};")
|
self.content += f"}} {name};\n\n"
|
||||||
print()
|
|
||||||
|
|
||||||
def enum_list(self, name, enums):
|
def enum_list(self, name, enums):
|
||||||
self.enum_start(name)
|
self.enum_start(name)
|
||||||
for enum in enums:
|
for enum in enums:
|
||||||
print(f"{self.indention}{enum},")
|
self.content += f"{self.indention}{enum},\n"
|
||||||
self.enum_stop(name)
|
self.enum_stop(name)
|
||||||
|
|
||||||
def enum_dict(self, name, enums):
|
def enum_dict(self, name, enums):
|
||||||
self.enum_start(name)
|
self.enum_start(name)
|
||||||
for enum, v in enums.items():
|
for enum, v in enums.items():
|
||||||
print(f"{self.indention}{enum} = {v},")
|
self.content += f"{self.indention}{enum} = {v},\n"
|
||||||
self.enum_stop(name)
|
self.enum_stop(name)
|
||||||
|
|
||||||
def output(self, out):
|
def output(self, out):
|
||||||
print(f"{self.indention}{out}", end="")
|
self.content += self.indention
|
||||||
|
self.content += out
|
||||||
|
|
||||||
def output_line(self):
|
def empty_line(self):
|
||||||
print()
|
self.content += '\n'
|
||||||
|
|
||||||
def only_output(self, out):
|
def only_output(self, out):
|
||||||
print(out, end="")
|
self.content += out
|
||||||
|
|
||||||
def block_start(self):
|
def block_start(self):
|
||||||
print(f"{{")
|
self.content += f"{{\n"
|
||||||
self.indent()
|
self.indent()
|
||||||
|
|
||||||
def block_end(self):
|
def block_end(self):
|
||||||
self.unindent()
|
self.unindent()
|
||||||
print(f"{self.indention}}}")
|
self.content += f"{self.indention}}}\n"
|
||||||
|
|
||||||
|
|
||||||
|
def group_by_class(tiles):
|
||||||
|
groups = defaultdict(list)
|
||||||
|
for tile in tiles:
|
||||||
|
if 'type' not in tile:
|
||||||
|
continue
|
||||||
|
tile_class = tile['type']
|
||||||
|
groups[tile_class].append(tile)
|
||||||
|
return groups
|
||||||
|
|
||||||
|
|
||||||
|
class EnumWriter:
|
||||||
|
def __init__(self, writer: ExtractFileWriter, prefix, tiles):
|
||||||
|
self.writer = writer
|
||||||
|
self.prefix = prefix
|
||||||
|
self.all_tiles = tiles
|
||||||
|
self.tiles = group_by_class(tiles)
|
||||||
|
self.enums = []
|
||||||
|
self.enums += [self.to_enum(x) for x in self.tiles.keys()]
|
||||||
|
self.enums.append(self.to_enum("count"))
|
||||||
|
self.enums.append(self.to_enum("none"))
|
||||||
|
self.enum_type = f"{prefix.capitalize()}Type"
|
||||||
|
|
||||||
|
def to_enum(self, name):
|
||||||
|
return f"{self.prefix.upper()}_{name.upper()}"
|
||||||
|
|
||||||
|
def to_anim_enum(self, name):
|
||||||
|
return f"ANIM_{name.upper()}"
|
||||||
|
|
||||||
|
def output_enum(self):
|
||||||
|
self.writer.enum_list(self.enum_type, self.enums)
|
||||||
|
|
||||||
|
def output_tile_to_enum(self, func_name):
|
||||||
|
writer = self.writer
|
||||||
|
writer.output(f"static {self.enum_type} {func_name}(BzTile tile) ")
|
||||||
|
writer.block_start()
|
||||||
|
|
||||||
|
writer.output("switch (tile) ")
|
||||||
|
writer.block_start()
|
||||||
|
|
||||||
|
for key, tiles in self.tiles.items():
|
||||||
|
ids = [x['id'] for x in tiles]
|
||||||
|
for id in ids:
|
||||||
|
writer.output(f"case {id}:\n")
|
||||||
|
writer.output(f" return {self.to_enum(key)};\n")
|
||||||
|
writer.output(f"default:\n")
|
||||||
|
writer.output(f" return {self.enums[-1]};\n")
|
||||||
|
|
||||||
|
writer.block_end()
|
||||||
|
writer.block_end()
|
||||||
|
writer.empty_line()
|
||||||
|
|
||||||
|
def output_enum_to_tile(self, func_name):
|
||||||
|
writer = self.writer
|
||||||
|
writer.output(f"static {self.enum_type} {func_name}({self.enum_type} type) ")
|
||||||
|
writer.block_start()
|
||||||
|
|
||||||
|
writer.output("switch (type) ")
|
||||||
|
writer.block_start()
|
||||||
|
|
||||||
|
for key, tiles in self.tiles.items():
|
||||||
|
ids = sorted([x['id'] for x in tiles])
|
||||||
|
writer.output(f"case {self.to_enum(key)}: return {ids[0]};\n")
|
||||||
|
writer.output(f"default: return -1;\n")
|
||||||
|
|
||||||
|
writer.block_end()
|
||||||
|
writer.block_end()
|
||||||
|
writer.empty_line()
|
||||||
|
|
||||||
|
def output_str_to_enum(self, func_name):
|
||||||
|
writer = self.writer
|
||||||
|
writer.output(f"static {self.enum_type} {func_name}(const char *str) ")
|
||||||
|
writer.block_start()
|
||||||
|
|
||||||
|
for name in self.tiles.keys():
|
||||||
|
writer.output(f"if (strncmp(\"{name}\", str, {len(name)}) == 0) return {self.to_enum(name)};\n")
|
||||||
|
writer.output(f"return {self.enums[-1]};\n")
|
||||||
|
|
||||||
|
writer.block_end()
|
||||||
|
writer.empty_line()
|
||||||
|
|
||||||
|
def output_enum_to_str(self, func_name):
|
||||||
|
writer = self.writer
|
||||||
|
writer.output(f"static const char *{func_name}({self.enum_type} type) ")
|
||||||
|
writer.block_start()
|
||||||
|
|
||||||
|
writer.output("switch (type) ")
|
||||||
|
writer.block_start()
|
||||||
|
|
||||||
|
for name in self.tiles.keys():
|
||||||
|
writer.output(f"case {self.to_enum(name)}: return \"{name}\";\n")
|
||||||
|
writer.output(f"default: return NULL;\n")
|
||||||
|
|
||||||
|
writer.block_end()
|
||||||
|
writer.block_end()
|
||||||
|
writer.empty_line()
|
||||||
|
|
||||||
|
def output_enum_tile_size(self, func_name):
|
||||||
|
writer = self.writer
|
||||||
|
writer.output(
|
||||||
|
f"static {self.enum_type} {func_name}({self.enum_type} type, BzTile *outWidth, BzTile *outHeight) ")
|
||||||
|
writer.block_start()
|
||||||
|
|
||||||
|
writer.output("switch (type) ")
|
||||||
|
writer.block_start()
|
||||||
|
|
||||||
|
for key, tiles in self.tiles.items():
|
||||||
|
ids = [x['id'] for x in tiles]
|
||||||
|
w = 1
|
||||||
|
h = 1
|
||||||
|
for curr, next in zip(ids, ids[1:]):
|
||||||
|
if next > curr + 1:
|
||||||
|
h += 1
|
||||||
|
elif h == 1:
|
||||||
|
w += 1
|
||||||
|
writer.output(f"case {self.to_enum(key)}:\n")
|
||||||
|
writer.indent()
|
||||||
|
writer.output(f"if (outWidth) *outWidth = {w};\n")
|
||||||
|
writer.output(f"if (outHeight) *outHeight = {h};\n")
|
||||||
|
writer.output("break;\n")
|
||||||
|
writer.unindent()
|
||||||
|
writer.output("default:\n")
|
||||||
|
writer.indent()
|
||||||
|
writer.output("if (outWidth) *outWidth = 0;\n")
|
||||||
|
writer.output("if (outHeight) *outHeight = 0;\n")
|
||||||
|
writer.output("break;\n")
|
||||||
|
writer.unindent()
|
||||||
|
|
||||||
|
writer.block_end()
|
||||||
|
writer.block_end()
|
||||||
|
writer.empty_line()
|
||||||
|
|
||||||
|
def output_tile_has_anim(self, func_name):
|
||||||
|
writer = self.writer
|
||||||
|
writer.output(f"static bool {func_name}(BzTile tile) ")
|
||||||
|
writer.block_start()
|
||||||
|
|
||||||
|
writer.output("switch (tile) ")
|
||||||
|
writer.block_start()
|
||||||
|
ids = sorted([x['id'] for x in self.all_tiles if 'animation' in x])
|
||||||
|
for id in ids:
|
||||||
|
writer.output(f"case {id}:\n")
|
||||||
|
writer.indent()
|
||||||
|
writer.output("return true;\n")
|
||||||
|
writer.unindent()
|
||||||
|
writer.output("default:\n")
|
||||||
|
writer.indent()
|
||||||
|
writer.output("return false;\n")
|
||||||
|
writer.unindent()
|
||||||
|
|
||||||
|
writer.block_end()
|
||||||
|
writer.block_end()
|
||||||
|
writer.empty_line()
|
||||||
|
|
||||||
|
def output_tile_anim_sequence(self, func_name):
|
||||||
|
writer = self.writer
|
||||||
|
writer.output(f"static AnimationSequence {func_name}(BzTile tile) ")
|
||||||
|
writer.block_start()
|
||||||
|
|
||||||
|
writer.output("switch (tile) ")
|
||||||
|
writer.block_start()
|
||||||
|
anim_tiles = [x for x in self.all_tiles if 'animation' in x]
|
||||||
|
for tile in anim_tiles:
|
||||||
|
anim = tile['animation']
|
||||||
|
num_frames = len(anim)
|
||||||
|
anim_id = min([x['tileid'] for x in anim])
|
||||||
|
ret = f"(AnimationSequence) {{.startFrame = {anim_id}, .frameCount = {num_frames}}}"
|
||||||
|
writer.output(f"case {tile['id']}: return {ret};\n")
|
||||||
|
writer.output("default:\n")
|
||||||
|
writer.indent()
|
||||||
|
writer.output("BZ_ASSERT(0);\n")
|
||||||
|
writer.output("return (AnimationSequence) {0, 0};\n")
|
||||||
|
writer.unindent()
|
||||||
|
|
||||||
|
writer.block_end()
|
||||||
|
writer.block_end()
|
||||||
|
writer.empty_line()
|
||||||
|
|
||||||
|
def output_tile_anim_frame(self, func_name):
|
||||||
|
writer = self.writer
|
||||||
|
writer.output(f"static AnimationFrame {func_name}(BzTile tile, i32 frameIdx) ")
|
||||||
|
writer.block_start()
|
||||||
|
|
||||||
|
writer.output("switch (tile) ")
|
||||||
|
writer.block_start()
|
||||||
|
anim_tiles = [x for x in self.all_tiles if 'animation' in x]
|
||||||
|
for tile in anim_tiles:
|
||||||
|
anim = tile['animation']
|
||||||
|
# num_frames = len(anim)
|
||||||
|
frames = [str(x['tileid']) for x in anim]
|
||||||
|
durations = [str(x['duration']) for x in anim]
|
||||||
|
|
||||||
|
anim_frames = [f"{{{frame}, {duration}}}" for frame, duration in zip(frames, durations)]
|
||||||
|
|
||||||
|
ret = f"((AnimationFrame []) {{{', '.join(anim_frames)}}}) [frameIdx]"
|
||||||
|
writer.output(f"case {tile['id']}: return {ret};\n")
|
||||||
|
writer.output("default:\n")
|
||||||
|
writer.indent()
|
||||||
|
writer.output("BZ_ASSERT(0);\n")
|
||||||
|
writer.output("return (AnimationFrame) {0, 0};\n")
|
||||||
|
writer.unindent()
|
||||||
|
writer.block_end()
|
||||||
|
writer.block_end()
|
||||||
|
writer.empty_line()
|
||||||
|
|||||||
@@ -1,154 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
"""
|
|
||||||
Utility script that extracts entities tileset with animations
|
|
||||||
"""
|
|
||||||
|
|
||||||
import json
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
from collections import defaultdict
|
|
||||||
from extract_common import *
|
|
||||||
|
|
||||||
raw_entities = defaultdict(list)
|
|
||||||
entities = defaultdict(list)
|
|
||||||
|
|
||||||
content = open("../assets/entities.tsj").read()
|
|
||||||
tiles = json.loads(content)["tiles"]
|
|
||||||
|
|
||||||
for tile in tiles:
|
|
||||||
if "type" not in tile:
|
|
||||||
continue
|
|
||||||
raw_entities[tile["type"]].append(tile)
|
|
||||||
|
|
||||||
entity_enum_prefix = "ENTITY_"
|
|
||||||
animation_enum_prefix = "ANIM_"
|
|
||||||
|
|
||||||
entity_enums = {}
|
|
||||||
animations = set()
|
|
||||||
entity_animations = {}
|
|
||||||
|
|
||||||
|
|
||||||
def entity_enum(type):
|
|
||||||
return f"{entity_enum_prefix}{type.upper()}"
|
|
||||||
|
|
||||||
|
|
||||||
def animation_enum(value):
|
|
||||||
value = value.split("_")[0]
|
|
||||||
return f"{animation_enum_prefix}{value.upper()}"
|
|
||||||
|
|
||||||
|
|
||||||
def simple_entity(entity):
|
|
||||||
type = entity["type"]
|
|
||||||
id = entity["id"]
|
|
||||||
entity_enums[entity_enum(type)] = id
|
|
||||||
|
|
||||||
|
|
||||||
def animated_entity(entity):
|
|
||||||
simple_entity(entity[0])
|
|
||||||
entity_name = entity_enum(entity[0]["type"])
|
|
||||||
cur_animations = defaultdict(list)
|
|
||||||
for frame in entity:
|
|
||||||
assert entity_name == entity_enum(frame["type"])
|
|
||||||
for prop in frame["properties"]:
|
|
||||||
if prop["name"] != "animation":
|
|
||||||
continue
|
|
||||||
animation_name = animation_enum(prop["value"])
|
|
||||||
animations.add(animation_name)
|
|
||||||
cur_animations[animation_name].append(frame["id"])
|
|
||||||
break
|
|
||||||
entity_animations[entity_name] = cur_animations
|
|
||||||
|
|
||||||
|
|
||||||
for k, v in raw_entities.items():
|
|
||||||
num_frames = len(v)
|
|
||||||
if num_frames == 1:
|
|
||||||
simple_entity(v[0])
|
|
||||||
else:
|
|
||||||
animated_entity(v)
|
|
||||||
|
|
||||||
|
|
||||||
writer = ExtractFileWriter("entity_types")
|
|
||||||
writer.header_guard_start()
|
|
||||||
|
|
||||||
writer.include("<breeze.h>")
|
|
||||||
|
|
||||||
writer.output_line()
|
|
||||||
|
|
||||||
# ============================
|
|
||||||
|
|
||||||
writer.enum_dict("EntityType", entity_enums)
|
|
||||||
writer.enum_list("AnimationType", animations)
|
|
||||||
|
|
||||||
# ============================
|
|
||||||
|
|
||||||
writer.output("typedef struct AnimationSequence {\n")
|
|
||||||
writer.indent()
|
|
||||||
writer.output("i32 startFrame;\n")
|
|
||||||
writer.output("i32 frameCount;\n")
|
|
||||||
writer.unindent()
|
|
||||||
writer.output("} AnimationSequence;\n")
|
|
||||||
writer.output_line()
|
|
||||||
|
|
||||||
# ============================
|
|
||||||
|
|
||||||
# ============================
|
|
||||||
|
|
||||||
writer.output("static bool entityHasAnimation(EntityType entity, AnimationType anim) ")
|
|
||||||
writer.block_start()
|
|
||||||
|
|
||||||
writer.output("switch (entity) ")
|
|
||||||
writer.block_start()
|
|
||||||
|
|
||||||
for entity, anims in entity_animations.items():
|
|
||||||
writer.output(f"case {entity}: ")
|
|
||||||
writer.block_start()
|
|
||||||
|
|
||||||
writer.output("switch (anim) ")
|
|
||||||
writer.block_start()
|
|
||||||
for anim in anims:
|
|
||||||
writer.output(f"case {anim}:")
|
|
||||||
writer.output_line()
|
|
||||||
writer.indent()
|
|
||||||
writer.output("return true;\n")
|
|
||||||
writer.unindent()
|
|
||||||
writer.block_end()
|
|
||||||
|
|
||||||
writer.output("break;\n")
|
|
||||||
writer.block_end()
|
|
||||||
|
|
||||||
writer.block_end()
|
|
||||||
|
|
||||||
writer.output("return false;\n")
|
|
||||||
writer.block_end()
|
|
||||||
|
|
||||||
writer.output_line()
|
|
||||||
# ============================
|
|
||||||
|
|
||||||
writer.output("static AnimationSequence getEntityAnimation(EntityType entity, AnimationType anim) ")
|
|
||||||
writer.block_start()
|
|
||||||
writer.output("switch (entity) ")
|
|
||||||
writer.block_start()
|
|
||||||
for entity, anims in entity_animations.items():
|
|
||||||
writer.output(f"case {entity}: ")
|
|
||||||
writer.block_start()
|
|
||||||
|
|
||||||
writer.output("switch (anim) ")
|
|
||||||
writer.block_start()
|
|
||||||
for anim in anims:
|
|
||||||
ids = sorted(anims[anim])
|
|
||||||
for id0, id1 in zip(ids, ids[1:]):
|
|
||||||
assert id1 - id0 == 1
|
|
||||||
writer.output(f"case {anim}: return (AnimationSequence) {{{min(ids)}, {len(ids)}}};")
|
|
||||||
writer.output_line()
|
|
||||||
writer.block_end()
|
|
||||||
|
|
||||||
writer.block_end()
|
|
||||||
writer.block_end()
|
|
||||||
writer.output("BZ_ASSERT(0);\n")
|
|
||||||
writer.block_end()
|
|
||||||
writer.output_line()
|
|
||||||
|
|
||||||
# ============================
|
|
||||||
|
|
||||||
writer.header_guard_stop()
|
|
||||||
|
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
import json
|
import json
|
||||||
|
import os.path
|
||||||
|
|
||||||
from extract_common import *
|
from extract_common import *
|
||||||
|
|
||||||
writer = ExtractFileWriter("")
|
writer = ExtractFileWriter("game_tileset")
|
||||||
|
|
||||||
writer.include("<breeze.h>")
|
|
||||||
|
|
||||||
|
|
||||||
def extract_by_property(tiles, key):
|
def extract_by_property(tiles, key):
|
||||||
@@ -21,13 +20,39 @@ def extract_by_property(tiles, key):
|
|||||||
|
|
||||||
content = open("../rawAssets/game.tsj").read()
|
content = open("../rawAssets/game.tsj").read()
|
||||||
tiles = json.loads(content)["tiles"]
|
tiles = json.loads(content)["tiles"]
|
||||||
terrain = extract_by_property(tiles, "terrain")
|
terrain_tiles = extract_by_property(tiles, "terrain")
|
||||||
building = extract_by_property(tiles, "building")
|
building_tiles = extract_by_property(tiles, "building")
|
||||||
entity = extract_by_property(tiles, "entity")
|
entity_tiles = extract_by_property(tiles, "entity")
|
||||||
print(terrain)
|
|
||||||
|
writer.header_guard_start()
|
||||||
|
script_name = os.path.basename(__file__)
|
||||||
writer.output(f"// This file was generated by: {__file__}\n\n")
|
writer.output(f"// This file was generated by: {script_name}\n\n")
|
||||||
|
writer.include("<breeze.h>")
|
||||||
|
writer.include("<string.h>")
|
||||||
|
|
||||||
|
writer.empty_line()
|
||||||
|
writer.output_anim_sequence_struct()
|
||||||
|
writer.output_anim_frame_struct()
|
||||||
|
|
||||||
|
terrain_writer = EnumWriter(writer, "terrain", terrain_tiles)
|
||||||
|
building_writer = EnumWriter(writer, "building", building_tiles)
|
||||||
|
entity_writer = EnumWriter(writer, "entity", entity_tiles)
|
||||||
|
|
||||||
|
terrain_writer.output_enum()
|
||||||
|
terrain_writer.output_tile_has_anim("terrainHasAnimation")
|
||||||
|
terrain_writer.output_tile_anim_sequence("terrainGetAnimationSequence")
|
||||||
|
terrain_writer.output_tile_anim_frame("terrainGetAnimationFrame")
|
||||||
|
writer.empty_line()
|
||||||
|
|
||||||
|
building_writer.output_enum()
|
||||||
|
building_writer.output_tile_to_enum("getTileBuilding")
|
||||||
|
building_writer.output_enum_to_tile("getBuildingTile")
|
||||||
|
building_writer.output_str_to_enum("getBuildingFromStr")
|
||||||
|
building_writer.output_enum_to_str("getBuildingStr")
|
||||||
|
building_writer.output_enum_tile_size("getBuildingSize")
|
||||||
|
writer.empty_line()
|
||||||
|
|
||||||
|
writer.header_guard_stop()
|
||||||
|
|
||||||
|
|
||||||
|
writer.to_file("../game/game_tileset.h")
|
||||||
|
|||||||
@@ -1,199 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
"""
|
|
||||||
Utility script that extracts tiles with the same class and
|
|
||||||
outputs C enum and functions for them (so there is no string checking).
|
|
||||||
"""
|
|
||||||
|
|
||||||
import json
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
from collections import defaultdict
|
|
||||||
|
|
||||||
types = defaultdict(list)
|
|
||||||
|
|
||||||
path = sys.argv[1]
|
|
||||||
content = open(path).read()
|
|
||||||
|
|
||||||
tiles = json.loads(content)["tiles"]
|
|
||||||
|
|
||||||
for tile in tiles:
|
|
||||||
if "type" not in tile:
|
|
||||||
continue
|
|
||||||
id = tile["id"]
|
|
||||||
type = tile["type"]
|
|
||||||
types[type].append(id)
|
|
||||||
|
|
||||||
enum_type = os.path.basename(path).split(".")[0].capitalize()
|
|
||||||
enum_name = enum_type.upper()
|
|
||||||
if sys.argv[2]:
|
|
||||||
enum_type = sys.argv[2]
|
|
||||||
fun_name = enum_type
|
|
||||||
if sys.argv[3]:
|
|
||||||
fun_name = sys.argv[3]
|
|
||||||
enum_prefix = enum_name
|
|
||||||
if sys.argv[4]:
|
|
||||||
enum_prefix = sys.argv[4]
|
|
||||||
|
|
||||||
indent_level = 0
|
|
||||||
indent_offset = 4
|
|
||||||
|
|
||||||
|
|
||||||
def indent():
|
|
||||||
return ' ' * indent_level
|
|
||||||
|
|
||||||
|
|
||||||
def enum_string(name):
|
|
||||||
return f"{enum_prefix}_{name.upper()}"
|
|
||||||
|
|
||||||
|
|
||||||
# ============================
|
|
||||||
header_guard = f"{enum_type.upper()}_H"
|
|
||||||
print(f"#ifndef {header_guard}")
|
|
||||||
print(f"#define {header_guard}")
|
|
||||||
script_name = os.path.basename(__file__)
|
|
||||||
print(f"// This file was generated by: {script_name}")
|
|
||||||
print()
|
|
||||||
print("#include <breeze.h>")
|
|
||||||
print("#include <string.h>")
|
|
||||||
print()
|
|
||||||
print()
|
|
||||||
|
|
||||||
# ============================
|
|
||||||
|
|
||||||
enum_none = enum_string("none")
|
|
||||||
enum_count = enum_string("count")
|
|
||||||
|
|
||||||
print(f"{indent()}typedef enum {enum_type} {{")
|
|
||||||
indent_level += indent_offset
|
|
||||||
print(f"{indent()}{enum_none},")
|
|
||||||
for enum in types:
|
|
||||||
print(f"{indent()}{enum_string(enum)},")
|
|
||||||
print(f"{indent()}{enum_count}")
|
|
||||||
indent_level -= indent_offset
|
|
||||||
print(f"{indent()}}} {enum_type};")
|
|
||||||
|
|
||||||
print()
|
|
||||||
print()
|
|
||||||
|
|
||||||
# ============================
|
|
||||||
|
|
||||||
print(f"{indent()}static {enum_type} getTile{fun_name}(BzTile tile) {{")
|
|
||||||
indent_level += indent_offset
|
|
||||||
print(f"{indent()}switch (tile) {{")
|
|
||||||
for enum, ids in types.items():
|
|
||||||
indent_level += indent_offset
|
|
||||||
for id in ids:
|
|
||||||
print(f"{indent()}case {id}:")
|
|
||||||
|
|
||||||
indent_level += indent_offset
|
|
||||||
print(f"{indent()} return {enum_string(enum)};")
|
|
||||||
indent_level -= indent_offset
|
|
||||||
|
|
||||||
indent_level -= indent_offset
|
|
||||||
|
|
||||||
indent_level += indent_offset
|
|
||||||
print(f"{indent()}default:")
|
|
||||||
indent_level += indent_offset
|
|
||||||
print(f"{indent()}return {enum_string('none')};")
|
|
||||||
indent_level -= indent_offset
|
|
||||||
indent_level -= indent_offset
|
|
||||||
print(f"{indent()}}}")
|
|
||||||
indent_level -= indent_offset
|
|
||||||
print(f"{indent()}}}")
|
|
||||||
|
|
||||||
print()
|
|
||||||
|
|
||||||
# ============================
|
|
||||||
|
|
||||||
print(f"{indent()}static BzTile get{fun_name}Tile({enum_type} type) {{")
|
|
||||||
indent_level += indent_offset
|
|
||||||
print(f"{indent()}switch (type) {{")
|
|
||||||
indent_level += indent_offset
|
|
||||||
for type, ids in types.items():
|
|
||||||
min_id = min(ids)
|
|
||||||
print(f"{indent()}case {enum_string(type)}: return {min_id};")
|
|
||||||
|
|
||||||
print(f"{indent()}default: return -1;")
|
|
||||||
indent_level -= indent_offset
|
|
||||||
print(f"{indent()}}}")
|
|
||||||
|
|
||||||
indent_level -= indent_offset
|
|
||||||
|
|
||||||
print(f"{indent()}}}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# ============================
|
|
||||||
|
|
||||||
print(f"{indent()}static {enum_type} get{fun_name}FromStr(const char *str) {{")
|
|
||||||
indent_level += indent_offset
|
|
||||||
|
|
||||||
# trie would be much better
|
|
||||||
for type in types:
|
|
||||||
print(f"{indent()}if (strncmp(\"{type}\", str, {len(type)}) == 0) return {enum_string(type)};")
|
|
||||||
print(f"{indent()}else return {enum_string('none')};")
|
|
||||||
|
|
||||||
indent_level -= indent_offset
|
|
||||||
print(f"{indent()}}}")
|
|
||||||
|
|
||||||
# ============================
|
|
||||||
|
|
||||||
print(f"{indent()}static const char *get{fun_name}Str({enum_type} type) {{")
|
|
||||||
indent_level += indent_offset
|
|
||||||
|
|
||||||
print(f"{indent()}switch (type) {{")
|
|
||||||
indent_level += indent_offset
|
|
||||||
|
|
||||||
print(f"{indent()}case {enum_string('none')}: return \"none\";")
|
|
||||||
for type in types:
|
|
||||||
print(f"{indent()}case {enum_string(type)}: return \"{type}\";")
|
|
||||||
print(f"{indent()}default: return NULL;")
|
|
||||||
indent_level -= indent_offset
|
|
||||||
print(f"{indent()}}}")
|
|
||||||
|
|
||||||
indent_level -= indent_offset
|
|
||||||
print(f"{indent()}}}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
|
|
||||||
# ============================
|
|
||||||
|
|
||||||
print(f"{indent()}static void get{fun_name}Size({enum_type} type, BzTile *outWidth, BzTile *outHeight) {{")
|
|
||||||
indent_level += indent_offset
|
|
||||||
print(f"{indent()} switch (type) {{")
|
|
||||||
indent_level += indent_offset
|
|
||||||
for enum, ids in types.items():
|
|
||||||
print(f"{indent()}case {enum_string(enum)}:")
|
|
||||||
indent_level += indent_offset
|
|
||||||
w = 1
|
|
||||||
h = 1
|
|
||||||
for curr, next in zip(ids, ids[1:]):
|
|
||||||
if next > curr + 1:
|
|
||||||
h += 1
|
|
||||||
elif h == 1:
|
|
||||||
w += 1
|
|
||||||
print(f"{indent()}if (outWidth) *outWidth = {w};")
|
|
||||||
print(f"{indent()}if (outHeight) *outHeight = {h};")
|
|
||||||
print(f"{indent()}break;")
|
|
||||||
indent_level -= indent_offset
|
|
||||||
|
|
||||||
print(f"{indent()}default:")
|
|
||||||
indent_level += indent_offset
|
|
||||||
print(f"{indent()}if (outWidth) *outWidth = 0;")
|
|
||||||
print(f"{indent()}if (outHeight) *outHeight = 0;")
|
|
||||||
print(f"{indent()}break;")
|
|
||||||
indent_level -= indent_offset
|
|
||||||
indent_level -= indent_offset
|
|
||||||
print(f"{indent()}}}")
|
|
||||||
|
|
||||||
|
|
||||||
indent_level -= indent_offset
|
|
||||||
indent_level -= indent_offset
|
|
||||||
|
|
||||||
indent_level -= indent_offset
|
|
||||||
print(f"{indent()}}}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
|
|
||||||
# ============================
|
|
||||||
|
|
||||||
print(f"#endif //{header_guard}")
|
|
||||||
Reference in New Issue
Block a user