mirror of https://github.com/pmret/papermario.git
sprite fixes (#1230)
This commit is contained in:
parent
93c7e0fe65
commit
da808bbd17
|
@ -3,7 +3,7 @@
|
||||||
from math import floor
|
from math import floor
|
||||||
from sys import argv, path
|
from sys import argv, path
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Tuple
|
from typing import List, Dict, Tuple
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
import png # type: ignore
|
import png # type: ignore
|
||||||
|
|
||||||
|
@ -78,7 +78,9 @@ def from_dir(
|
||||||
|
|
||||||
palettes = []
|
palettes = []
|
||||||
palette_names: List[str] = []
|
palette_names: List[str] = []
|
||||||
for Palette in SpriteSheet.findall("./PaletteList/Palette"):
|
palette_map: Dict[str, int] = {}
|
||||||
|
|
||||||
|
for idx, Palette in enumerate(SpriteSheet.findall("./PaletteList/Palette")):
|
||||||
if asset_stack is not None and load_images:
|
if asset_stack is not None and load_images:
|
||||||
img_name = Palette.attrib["src"]
|
img_name = Palette.attrib["src"]
|
||||||
img_path = resolve_image_path(sprite_dir, "palettes", img_name, asset_stack)
|
img_path = resolve_image_path(sprite_dir, "palettes", img_name, asset_stack)
|
||||||
|
@ -91,11 +93,15 @@ def from_dir(
|
||||||
|
|
||||||
palettes.append(palette)
|
palettes.append(palette)
|
||||||
|
|
||||||
palette_names.append(Palette.get("name", Palette.attrib["src"].split(".png")[0]))
|
pal_name = Palette.get("name", Palette.attrib["src"].split(".png")[0])
|
||||||
|
palette_names.append(pal_name)
|
||||||
|
palette_map[pal_name] = idx
|
||||||
|
|
||||||
images = []
|
images = []
|
||||||
image_names: List[str] = []
|
image_names: List[str] = []
|
||||||
for Raster in SpriteSheet.findall("./RasterList/Raster"):
|
image_map: Dict[str, int] = {}
|
||||||
|
|
||||||
|
for idx, Raster in enumerate(SpriteSheet.findall("./RasterList/Raster")):
|
||||||
if asset_stack is not None and load_images:
|
if asset_stack is not None and load_images:
|
||||||
img_name = Raster.attrib["src"]
|
img_name = Raster.attrib["src"]
|
||||||
img_path = resolve_image_path(sprite_dir, "rasters", img_name, asset_stack)
|
img_path = resolve_image_path(sprite_dir, "rasters", img_name, asset_stack)
|
||||||
|
@ -109,14 +115,19 @@ def from_dir(
|
||||||
|
|
||||||
images.append(image)
|
images.append(image)
|
||||||
|
|
||||||
image_names.append(Raster.attrib["src"].split(".png")[0])
|
img_name = Raster.attrib["src"].split(".png")[0]
|
||||||
|
image_names.append(img_name)
|
||||||
|
image_map[img_name] = idx
|
||||||
|
|
||||||
animations = []
|
animations = []
|
||||||
animation_names: List[str] = []
|
animation_names: List[str] = []
|
||||||
for Animation in SpriteSheet.findall("./AnimationList/Animation"):
|
for Animation in SpriteSheet.findall("./AnimationList/Animation"):
|
||||||
|
# get a mapping of component names -> list indices
|
||||||
|
comp_map = {comp_xml.attrib["name"]: idx for idx, comp_xml in enumerate(Animation)}
|
||||||
|
# read each component
|
||||||
comps: List[AnimComponent] = []
|
comps: List[AnimComponent] = []
|
||||||
for comp_xml in Animation:
|
for comp_xml in Animation:
|
||||||
comp: AnimComponent = AnimComponent.from_xml(comp_xml)
|
comp: AnimComponent = AnimComponent.from_xml(comp_xml, comp_map, image_map, palette_map)
|
||||||
comps.append(comp)
|
comps.append(comp)
|
||||||
animation_names.append(Animation.attrib["name"])
|
animation_names.append(Animation.attrib["name"])
|
||||||
animations.append(comps)
|
animations.append(comps)
|
||||||
|
|
|
@ -141,20 +141,31 @@ def player_raster_from_xml(xml: ET.Element, back: bool = False) -> PlayerRaster:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def player_xml_to_bytes(xml: ET.Element, asset_stack: Tuple[Path, ...]) -> List[bytes]:
|
def player_xml_to_bytes(sprite_xml: ET.Element, asset_stack: Tuple[Path, ...]) -> List[bytes]:
|
||||||
out_bytes = b""
|
out_bytes = b""
|
||||||
back_out_bytes = b""
|
back_out_bytes = b""
|
||||||
|
|
||||||
max_components = int(xml.attrib[MAX_COMPONENTS_XML])
|
max_components = int(sprite_xml.attrib[MAX_COMPONENTS_XML])
|
||||||
num_variations = int(xml.attrib[PALETTE_GROUPS_XML])
|
num_variations = int(sprite_xml.attrib[PALETTE_GROUPS_XML])
|
||||||
has_back = xml.attrib[HAS_BACK_XML] == "true"
|
has_back = sprite_xml.attrib[HAS_BACK_XML] == "true"
|
||||||
|
|
||||||
|
anim_elems: List[ET.Element] = sprite_xml.findall("./AnimationList/Animation")
|
||||||
|
img_elems: List[ET.Element] = sprite_xml.findall("./RasterList/Raster")
|
||||||
|
pal_elems: List[ET.Element] = sprite_xml.findall("./PaletteList/Palette")
|
||||||
|
|
||||||
|
palette_map = {palette_xml.attrib["name"]: idx for idx, palette_xml in enumerate(pal_elems)}
|
||||||
|
|
||||||
|
image_map = {image_xml.attrib["name"]: idx for idx, image_xml in enumerate(img_elems)}
|
||||||
|
|
||||||
# Animations
|
# Animations
|
||||||
animations: List[List[AnimComponent]] = []
|
animations: List[List[AnimComponent]] = []
|
||||||
for anim_xml in xml[2]:
|
for anim_xml in anim_elems:
|
||||||
|
# get a mapping of component names -> list indices
|
||||||
|
comp_map = {comp_xml.attrib["name"]: idx for idx, comp_xml in enumerate(anim_xml)}
|
||||||
|
# read each component
|
||||||
comps: List[AnimComponent] = []
|
comps: List[AnimComponent] = []
|
||||||
for comp_xml in anim_xml:
|
for comp_xml in anim_xml:
|
||||||
comp: AnimComponent = AnimComponent.from_xml(comp_xml)
|
comp: AnimComponent = AnimComponent.from_xml(comp_xml, comp_map, image_map, palette_map)
|
||||||
comps.append(comp)
|
comps.append(comp)
|
||||||
animations.append(comps)
|
animations.append(comps)
|
||||||
|
|
||||||
|
@ -216,7 +227,7 @@ def player_xml_to_bytes(xml: ET.Element, asset_stack: Tuple[Path, ...]) -> List[
|
||||||
palette_list_start_back = len(back_out_bytes) + 0x10
|
palette_list_start_back = len(back_out_bytes) + 0x10
|
||||||
palette_bytes: bytes = b""
|
palette_bytes: bytes = b""
|
||||||
palette_bytes_back: bytes = b""
|
palette_bytes_back: bytes = b""
|
||||||
for palette_xml in xml[0]:
|
for palette_xml in pal_elems:
|
||||||
source = palette_xml.attrib["src"]
|
source = palette_xml.attrib["src"]
|
||||||
front_only = bool(palette_xml.get("front_only", False))
|
front_only = bool(palette_xml.get("front_only", False))
|
||||||
if source not in PALETTE_CACHE:
|
if source not in PALETTE_CACHE:
|
||||||
|
@ -252,7 +263,7 @@ def player_xml_to_bytes(xml: ET.Element, asset_stack: Tuple[Path, ...]) -> List[
|
||||||
raster_bytes: bytes = b""
|
raster_bytes: bytes = b""
|
||||||
raster_bytes_back: bytes = b""
|
raster_bytes_back: bytes = b""
|
||||||
raster_offset = 0
|
raster_offset = 0
|
||||||
for raster_xml in xml[1]:
|
for raster_xml in img_elems:
|
||||||
r = player_raster_from_xml(raster_xml, back=False)
|
r = player_raster_from_xml(raster_xml, back=False)
|
||||||
raster_bytes += struct.pack(">IBBBB", raster_offset, r.width, r.height, r.palette_idx, 0xFF)
|
raster_bytes += struct.pack(">IBBBB", raster_offset, r.width, r.height, r.palette_idx, 0xFF)
|
||||||
|
|
||||||
|
@ -260,7 +271,7 @@ def player_xml_to_bytes(xml: ET.Element, asset_stack: Tuple[Path, ...]) -> List[
|
||||||
|
|
||||||
if has_back:
|
if has_back:
|
||||||
raster_offset = 0
|
raster_offset = 0
|
||||||
for raster_xml in xml[1]:
|
for raster_xml in img_elems:
|
||||||
is_back = False
|
is_back = False
|
||||||
|
|
||||||
r = player_raster_from_xml(raster_xml, back=is_back)
|
r = player_raster_from_xml(raster_xml, back=is_back)
|
||||||
|
@ -290,7 +301,7 @@ def player_xml_to_bytes(xml: ET.Element, asset_stack: Tuple[Path, ...]) -> List[
|
||||||
# Raster file offsets
|
# Raster file offsets
|
||||||
raster_offsets_bytes = b""
|
raster_offsets_bytes = b""
|
||||||
raster_offsets_bytes_back = b""
|
raster_offsets_bytes_back = b""
|
||||||
for i in range(len(xml[1])):
|
for i in range(len(img_elems)):
|
||||||
raster_offsets_bytes += int.to_bytes(raster_list_start + i * 8, 4, "big")
|
raster_offsets_bytes += int.to_bytes(raster_list_start + i * 8, 4, "big")
|
||||||
raster_offsets_bytes_back += int.to_bytes(raster_list_start_back + i * 8, 4, "big")
|
raster_offsets_bytes_back += int.to_bytes(raster_list_start_back + i * 8, 4, "big")
|
||||||
raster_offsets_bytes += LIST_END_BYTES
|
raster_offsets_bytes += LIST_END_BYTES
|
||||||
|
@ -304,7 +315,7 @@ def player_xml_to_bytes(xml: ET.Element, asset_stack: Tuple[Path, ...]) -> List[
|
||||||
palette_list_offset_back = len(back_out_bytes) + 0x10
|
palette_list_offset_back = len(back_out_bytes) + 0x10
|
||||||
palette_offsets_bytes = b""
|
palette_offsets_bytes = b""
|
||||||
palette_offsets_bytes_back = b""
|
palette_offsets_bytes_back = b""
|
||||||
for i, palette_xml in enumerate(xml[0]):
|
for i, palette_xml in enumerate(pal_elems):
|
||||||
palette_offsets_bytes += int.to_bytes(palette_list_start + i * 0x20, 4, "big")
|
palette_offsets_bytes += int.to_bytes(palette_list_start + i * 0x20, 4, "big")
|
||||||
front_only = bool(palette_xml.attrib.get("front_only", False))
|
front_only = bool(palette_xml.attrib.get("front_only", False))
|
||||||
if not front_only:
|
if not front_only:
|
||||||
|
@ -358,17 +369,21 @@ def write_player_sprite_header(
|
||||||
sprite_xml = PLAYER_XML_CACHE[sprite_name]
|
sprite_xml = PLAYER_XML_CACHE[sprite_name]
|
||||||
has_back = sprite_xml.attrib[HAS_BACK_XML] == "true"
|
has_back = sprite_xml.attrib[HAS_BACK_XML] == "true"
|
||||||
|
|
||||||
|
anim_elems: List[ET.Element] = sprite_xml.findall("./AnimationList/Animation")
|
||||||
|
img_elems: List[ET.Element] = sprite_xml.findall("./RasterList/Raster")
|
||||||
|
pal_elems: List[ET.Element] = sprite_xml.findall("./PaletteList/Palette")
|
||||||
|
|
||||||
player_sprites[f"SPR_{sprite_name}"] = sprite_id
|
player_sprites[f"SPR_{sprite_name}"] = sprite_id
|
||||||
player_rasters[sprite_name] = {}
|
player_rasters[sprite_name] = {}
|
||||||
player_palettes[sprite_name] = {}
|
player_palettes[sprite_name] = {}
|
||||||
player_anims[sprite_name] = {}
|
player_anims[sprite_name] = {}
|
||||||
|
|
||||||
for palette_xml in sprite_xml[0]:
|
for palette_xml in pal_elems:
|
||||||
palette_id = int(palette_xml.attrib["id"], 0x10)
|
palette_id = int(palette_xml.attrib["id"], 0x10)
|
||||||
palette_name = palette_xml.attrib["name"]
|
palette_name = palette_xml.attrib["name"]
|
||||||
player_palettes[sprite_name][f"SPR_PAL_{sprite_name}_{palette_name}"] = palette_id
|
player_palettes[sprite_name][f"SPR_PAL_{sprite_name}_{palette_name}"] = palette_id
|
||||||
|
|
||||||
for anim_id, anim_xml in enumerate(sprite_xml[2]):
|
for anim_id, anim_xml in enumerate(anim_elems):
|
||||||
anim_name = anim_xml.attrib["name"]
|
anim_name = anim_xml.attrib["name"]
|
||||||
if palette_id > 0:
|
if palette_id > 0:
|
||||||
anim_name = f"{palette_name}_{anim_name}"
|
anim_name = f"{palette_name}_{anim_name}"
|
||||||
|
@ -377,7 +392,7 @@ def write_player_sprite_header(
|
||||||
)
|
)
|
||||||
|
|
||||||
max_size = 0
|
max_size = 0
|
||||||
for raster_xml in sprite_xml[1]:
|
for raster_xml in img_elems:
|
||||||
raster_id = int(raster_xml.attrib["id"], 0x10)
|
raster_id = int(raster_xml.attrib["id"], 0x10)
|
||||||
raster_name = raster_xml.attrib["name"]
|
raster_name = raster_xml.attrib["name"]
|
||||||
player_rasters[sprite_name][f"SPR_IMG_{sprite_name}_{raster_name}"] = raster_id
|
player_rasters[sprite_name][f"SPR_IMG_{sprite_name}_{raster_name}"] = raster_id
|
||||||
|
@ -393,7 +408,7 @@ def write_player_sprite_header(
|
||||||
player_sprites[f"SPR_{sprite_name}_Back"] = sprite_id
|
player_sprites[f"SPR_{sprite_name}_Back"] = sprite_id
|
||||||
|
|
||||||
max_size = 0
|
max_size = 0
|
||||||
for raster_xml in sprite_xml[1]:
|
for raster_xml in img_elems:
|
||||||
if "back" in raster_xml.attrib:
|
if "back" in raster_xml.attrib:
|
||||||
raster = RASTER_CACHE[raster_xml.attrib["back"][:-4]]
|
raster = RASTER_CACHE[raster_xml.attrib["back"][:-4]]
|
||||||
if max_size < raster.size:
|
if max_size < raster.size:
|
||||||
|
@ -513,8 +528,10 @@ def build_player_rasters(sprite_order: List[str], raster_order: List[str]) -> by
|
||||||
sheet_rtes: List[RasterTableEntry] = []
|
sheet_rtes: List[RasterTableEntry] = []
|
||||||
sheet_rtes_back: List[RasterTableEntry] = []
|
sheet_rtes_back: List[RasterTableEntry] = []
|
||||||
|
|
||||||
|
img_elems: List[ET.Element] = sprite_xml.findall("./RasterList/Raster")
|
||||||
|
|
||||||
has_back = False
|
has_back = False
|
||||||
for raster_xml in sprite_xml[1]:
|
for raster_xml in img_elems:
|
||||||
if "back" in raster_xml.attrib:
|
if "back" in raster_xml.attrib:
|
||||||
has_back = True
|
has_back = True
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,7 @@ class SetParent(Animation):
|
||||||
|
|
||||||
def get_attributes(self):
|
def get_attributes(self):
|
||||||
return {
|
return {
|
||||||
XML_ATTR_INDEX: str(self.index),
|
XML_ATTR_INDEX: f"{self.index:X}",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -214,11 +214,6 @@ class SetNotify(Animation):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Keyframe(Animation):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class AnimComponent:
|
class AnimComponent:
|
||||||
x: int
|
x: int
|
||||||
|
@ -255,7 +250,7 @@ class AnimComponent:
|
||||||
elif cmd_op == CMD.SET_SCALE:
|
elif cmd_op == CMD.SET_SCALE:
|
||||||
i += 1
|
i += 1
|
||||||
elif cmd_op == CMD.LOOP:
|
elif cmd_op == CMD.LOOP:
|
||||||
dest = command_list[i + 1]
|
dest = cmd_arg
|
||||||
if dest in boundaries and dest not in labels:
|
if dest in boundaries and dest not in labels:
|
||||||
labels[dest] = f"Pos_{dest}"
|
labels[dest] = f"Pos_{dest}"
|
||||||
i += 1
|
i += 1
|
||||||
|
@ -313,8 +308,8 @@ class AnimComponent:
|
||||||
palette = -1
|
palette = -1
|
||||||
ret.append(SetPalette(palette))
|
ret.append(SetPalette(palette))
|
||||||
elif cmd_op == CMD.LOOP:
|
elif cmd_op == CMD.LOOP:
|
||||||
count = cmd_arg
|
dest = cmd_arg
|
||||||
dest = command_list[i + 1]
|
count = command_list[i + 1]
|
||||||
if dest in labels:
|
if dest in labels:
|
||||||
lbl_name = labels[dest]
|
lbl_name = labels[dest]
|
||||||
ret.append(Loop(count, lbl_name, 0))
|
ret.append(Loop(count, lbl_name, 0))
|
||||||
|
@ -349,18 +344,27 @@ class AnimComponent:
|
||||||
return AnimComponent.parse_commands(self.commands)
|
return AnimComponent.parse_commands(self.commands)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_xml(xml: ET.Element):
|
def from_xml(xml: ET.Element, comp_map: Dict[str, int], image_map: Dict[str, int], palette_map: Dict[str, int]):
|
||||||
commands: List[int] = []
|
commands: List[int] = []
|
||||||
labels = {}
|
labels = {}
|
||||||
for cmd in xml:
|
for cmd in xml:
|
||||||
if cmd.tag == "Label":
|
if cmd.tag == "Label":
|
||||||
idx = len(commands)
|
labels[cmd.attrib[XML_ATTR_NAME]] = len(commands)
|
||||||
labels[cmd.attrib[XML_ATTR_NAME]] = idx
|
|
||||||
elif cmd.tag == "Wait":
|
elif cmd.tag == "Wait":
|
||||||
duration = int(cmd.attrib[XML_ATTR_DURATION])
|
duration = int(cmd.attrib[XML_ATTR_DURATION])
|
||||||
commands.append(duration & 0xFFF)
|
commands.append(duration & 0xFFF)
|
||||||
elif cmd.tag == "SetRaster":
|
elif cmd.tag == "SetRaster":
|
||||||
raster = int(cmd.attrib[XML_ATTR_INDEX], 0x10)
|
raster = -1
|
||||||
|
# prioritize selecting rasters by name, falling back to hardcoded IDs if name attribute is missing
|
||||||
|
if XML_ATTR_NAME in cmd.attrib:
|
||||||
|
img_name = cmd.attrib[XML_ATTR_NAME]
|
||||||
|
if img_name != "":
|
||||||
|
raster = image_map.get(img_name)
|
||||||
|
if raster is None:
|
||||||
|
raise Exception("Undefined raster name for SetRaster: " + img_name)
|
||||||
|
else:
|
||||||
|
raster = int(cmd.attrib[XML_ATTR_INDEX], 0x10)
|
||||||
|
# why is this here? necessary?
|
||||||
if raster == -1:
|
if raster == -1:
|
||||||
raster = 0xFFF
|
raster = 0xFFF
|
||||||
commands.append(0x1000 + (raster & 0xFFF))
|
commands.append(0x1000 + (raster & 0xFFF))
|
||||||
|
@ -393,7 +397,17 @@ class AnimComponent:
|
||||||
commands.append(0x5000 + mode)
|
commands.append(0x5000 + mode)
|
||||||
commands.append(percent)
|
commands.append(percent)
|
||||||
elif cmd.tag == "SetPalette":
|
elif cmd.tag == "SetPalette":
|
||||||
palette = int(cmd.attrib[XML_ATTR_INDEX], 0x10)
|
palette = -1
|
||||||
|
# prioritize selecting palettes by name, falling back to hardcoded IDs if name attribute is missing
|
||||||
|
if XML_ATTR_NAME in cmd.attrib:
|
||||||
|
pal_name = cmd.attrib[XML_ATTR_NAME]
|
||||||
|
if pal_name != "":
|
||||||
|
palette = palette_map.get(pal_name)
|
||||||
|
if palette is None:
|
||||||
|
raise Exception("Undefined palette name for SetPalette: " + pal_name)
|
||||||
|
else:
|
||||||
|
palette = int(cmd.attrib[XML_ATTR_INDEX], 0x10)
|
||||||
|
# why is this here? necessary?
|
||||||
if palette == -1:
|
if palette == -1:
|
||||||
palette = 0xFFF
|
palette = 0xFFF
|
||||||
commands.append(0x6000 + (palette & 0xFFF))
|
commands.append(0x6000 + (palette & 0xFFF))
|
||||||
|
@ -408,14 +422,90 @@ class AnimComponent:
|
||||||
if not lbl_name in labels:
|
if not lbl_name in labels:
|
||||||
raise Exception("Label missing for Loop dest: " + lbl_name)
|
raise Exception("Label missing for Loop dest: " + lbl_name)
|
||||||
pos = labels[lbl_name]
|
pos = labels[lbl_name]
|
||||||
commands.append(0x7000 + (count & 0xFFF))
|
commands.append(0x7000 + (pos & 0xFFF))
|
||||||
commands.append(pos)
|
commands.append(count)
|
||||||
elif cmd.tag == "Unknown":
|
elif cmd.tag == "Unknown":
|
||||||
commands.append(0x8000 + (int(cmd.attrib[XML_ATTR_VALUE]) & 0xFF))
|
commands.append(0x8000 + (int(cmd.attrib[XML_ATTR_VALUE]) & 0xFF))
|
||||||
elif cmd.tag == "SetParent":
|
elif cmd.tag == "SetParent":
|
||||||
commands.append(0x8100 + (int(cmd.attrib[XML_ATTR_INDEX]) & 0xFF))
|
parent = -1
|
||||||
|
# prioritize selecting palettes by name, falling back to hardcoded IDs if name attribute is missing
|
||||||
|
if XML_ATTR_NAME in cmd.attrib:
|
||||||
|
par_name = cmd.attrib[XML_ATTR_NAME]
|
||||||
|
if par_name != "":
|
||||||
|
parent = comp_map.get(par_name)
|
||||||
|
if parent is None:
|
||||||
|
raise Exception("Undefined component name for SetParent: " + par_name)
|
||||||
|
else:
|
||||||
|
parent = int(cmd.attrib[XML_ATTR_INDEX], 0x10)
|
||||||
|
if parent == -1:
|
||||||
|
raise Exception("Invalid component for SetParent: " + par_name)
|
||||||
|
commands.append(0x8100 + (parent & 0xFF))
|
||||||
elif cmd.tag == "SetNotify":
|
elif cmd.tag == "SetNotify":
|
||||||
commands.append(0x8200 + (int(cmd.attrib[XML_ATTR_VALUE]) & 0xFF))
|
commands.append(0x8200 + (int(cmd.attrib[XML_ATTR_VALUE]) & 0xFF))
|
||||||
|
elif cmd.tag == "Keyframe":
|
||||||
|
# treat keyframes as labels
|
||||||
|
labels[cmd.attrib[XML_ATTR_NAME]] = len(commands)
|
||||||
|
# check for non-default transformations
|
||||||
|
duration = int(cmd.attrib[XML_ATTR_DURATION])
|
||||||
|
if duration > 0:
|
||||||
|
if "pos" in cmd.attrib:
|
||||||
|
dx, dy, dz = map(int, cmd.attrib["pos"].split(","))
|
||||||
|
if dx != 0 or dy != 0 or dz != 0:
|
||||||
|
commands.append(0x3000)
|
||||||
|
commands.append(dx & 0xFFFF)
|
||||||
|
commands.append(dy & 0xFFFF)
|
||||||
|
commands.append(dz & 0xFFFF)
|
||||||
|
if "rot" in cmd.attrib:
|
||||||
|
rx, ry, rz = map(int, cmd.attrib["rot"].split(","))
|
||||||
|
if rx != 0 or ry != 0 or rz != 0:
|
||||||
|
commands.append(0x4000 + (rx & 0xFFF))
|
||||||
|
commands.append(ry & 0xFFFF)
|
||||||
|
commands.append(rz & 0xFFFF)
|
||||||
|
if "scale" in cmd.attrib:
|
||||||
|
sx, sy, sz = map(int, cmd.attrib["scale"].split(","))
|
||||||
|
if sx != 100 or sy != 100 or sz != 100:
|
||||||
|
# check for uniform scale before generating a command for each coord
|
||||||
|
if sx == sy == sz:
|
||||||
|
commands.append(0x5000)
|
||||||
|
commands.append(sx)
|
||||||
|
else:
|
||||||
|
if sx != 100:
|
||||||
|
commands.append(0x5001)
|
||||||
|
commands.append(sx)
|
||||||
|
if sy != 100:
|
||||||
|
commands.append(0x5002)
|
||||||
|
commands.append(sy)
|
||||||
|
if sz != 100:
|
||||||
|
commands.append(0x5003)
|
||||||
|
commands.append(sz)
|
||||||
|
# check for img
|
||||||
|
img_name = cmd.attrib.get("img")
|
||||||
|
if img_name is not None:
|
||||||
|
if img_name == "":
|
||||||
|
raster = -1
|
||||||
|
else:
|
||||||
|
raster = image_map.get(img_name)
|
||||||
|
if raster is None:
|
||||||
|
raise Exception("Undefined raster for Keyframe: " + img_name)
|
||||||
|
# why is this here? necessary?
|
||||||
|
if raster == -1:
|
||||||
|
raster = 0xFFF
|
||||||
|
commands.append(0x1000 + (raster & 0xFFF))
|
||||||
|
# check for pal
|
||||||
|
pal_name = cmd.attrib.get("pal")
|
||||||
|
if pal_name is not None:
|
||||||
|
if pal_name == "":
|
||||||
|
palette = -1
|
||||||
|
else:
|
||||||
|
palette = palette_map.get(pal_name)
|
||||||
|
if palette is None:
|
||||||
|
raise Exception("Undefined palette for Keyframe: " + pal_name)
|
||||||
|
# why is this here? necessary?
|
||||||
|
if palette == -1:
|
||||||
|
palette = 0xFFF
|
||||||
|
commands.append(0x6000 + (palette & 0xFFF))
|
||||||
|
# append wait command
|
||||||
|
commands.append(duration & 0xFFF)
|
||||||
elif cmd.tag == "Command": # old Star Rod compatibility
|
elif cmd.tag == "Command": # old Star Rod compatibility
|
||||||
commands.append(int(cmd.attrib["val"], 16))
|
commands.append(int(cmd.attrib["val"], 16))
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Reference in New Issue