Duet/converters.py

127 lines
3.8 KiB
Python

import fxconv
import struct
def float_to_bytes(f):
return struct.pack('>f', f)
def convert(input, output, params, target):
if params["custom-type"] == "level":
convert_level(input, output, params, target)
return 0
else:
return 1
def convert_level(input, output, params, target):
with open(input, "r") as fp:
raw = fp.read().split("\n")
lines = [tempo.split(",") for tempo in raw
if not tempo.startswith("#") and not tempo.startswith("!")]
messages = [l[1:].strip() for l in raw if l.startswith("#")]
message = "\n".join(l.replace("\\n", "\n") for l in messages)
speed = 1.0
for line in raw:
if line.startswith("!"):
speed = float(line[1:])
blocks = bytes()
block_count = 0
for (tempo, rects) in enumerate(lines):
for r in [r for r in rects if r]:
r = r.strip().split()
shape, action, fadeout, position = -1, 0, 0, -1
# Anti-bad-notation
if "middle" in r and "rotate" in r and ("left" in r or "right" in r):
raise fxconv.FxconvError("Bad rotation in '" + " ".join(r) + "'")
# Shape
if "square" in r:
shape = 0
if "small" in r:
shape = 2
if "medium" in r:
shape = 3
if "normal" in r:
shape = 4
if "long" in r:
shape = 5
if "huge" in r:
shape = 6
if "long_vertical" in r:
shape = 7
# Position
if "left" in r:
position = 0
if "right" in r:
position = 1
if "middle" in r:
position = 2
# Action
if "rotate_left" in r:
action = 1
if "rotate_right" in r:
action = 2
if "fast_1" in r:
action = 3
if "outer_rotate_left" in r:
action = 5
if "outer_rotate_right" in r:
action = 6
if "slide" in r:
action = 7
if "fast_2" in r:
action = 8
if "fast_3" in r:
action = 9
if "slow" in r:
action = 10
if "rotate" in r and position == 0:
action = 6
if "rotate" in r and position == 1:
action = 5
# Fadeout
if "fadeout_1" in r:
fadeout = 1
if "fadeout_2" in r:
fadeout = 2
if "fadeout_3" in r:
fadeout = 3
# Implicit rules
# Rotating in the middle -> long
if shape < 0 and position == 2 and action in [1, 2]:
shape = 5
# Rotating on the side -> huge
if shape < 0 and position in [0, 1] and action in [5, 6]:
shape = 6
# In the middle -> medium
if shape < 0 and position == 2:
shape = 3
# No special properties -> normal
if shape < 0 and action in [0, 3, 7, 8, 9, 10]:
shape = 4
if shape < 0 or action < 0 or position < 0:
raise fxconv.FxconvError("Incomplete data: '" + " ".join(r) + "'")
blocks += fxconv.u32(tempo)
blocks += fxconv.u32(shape)
blocks += fxconv.u32(position)
blocks += fxconv.u32(action)
blocks += fxconv.u32(fadeout)
block_count += 1
o = fxconv.ObjectData()
o += float_to_bytes(speed)
o += fxconv.ref(bytes(message, 'utf-8') + bytes(1), padding=4)
o += fxconv.u32(block_count)
o += fxconv.ref(blocks)
fxconv.elf(o, output, "_" + params["name"], **target)