Mercurial > touhou
changeset 608:725bd24235a2
Make ANM0 pure-python again, by moving the Cython-dependent ANM class into its own module.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Wed, 26 Nov 2014 14:00:17 +0100 |
parents | 9dbc234ea087 |
children | 23b9418e4b2f |
files | pytouhou/formats/animation.pxd pytouhou/formats/animation.pyx pytouhou/formats/anm0.pxd pytouhou/formats/anm0.py pytouhou/formats/anm0.pyx pytouhou/game/sprite.pxd setup.py |
diffstat | 5 files changed, 9 insertions(+), 247 deletions(-) [+] |
line wrap: on
line diff
rename from pytouhou/formats/anm0.pxd rename to pytouhou/formats/animation.pxd --- a/pytouhou/formats/anm0.pxd +++ b/pytouhou/formats/animation.pxd @@ -1,4 +1,4 @@ -cdef class ANM: +cdef class Animation: cdef public long version cdef public unicode first_name, secondary_name cdef public dict sprites, scripts
rename from pytouhou/formats/anm0.pyx rename to pytouhou/formats/animation.pyx --- a/pytouhou/formats/anm0.pyx +++ b/pytouhou/formats/animation.pyx @@ -1,6 +1,6 @@ # -*- encoding: utf-8 -*- ## -## Copyright (C) 2011 Thibaut Girka <thib@sitedethib.com> +## Copyright (C) 2014 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published @@ -12,34 +12,7 @@ ## GNU General Public License for more details. ## -"""ANM0 files handling. - -This module provides classes for handling the ANM0 file format. -The ANM0 format is a format used in Touhou 6: EoSD to describe sprites -and animations. -Almost everything rendered in the game is described by an ANM0 file. -""" - -from struct import pack, unpack -from pytouhou.utils.helpers import read_string, get_logger - -from pytouhou.formats import WrongFormatError -from pytouhou.formats.thtx import Texture - - -logger = get_logger(__name__) - -#TODO: refactor/clean up - - -class Script(list): - def __init__(self): - list.__init__(self) - self.interrupts = {} - - - -cdef class ANM: +cdef class Animation: def __init__(self): self.version = 0 self.size_inv[:] = [0, 0] @@ -52,199 +25,3 @@ cdef class ANM: def __set__(self, tuple value): width, height = value self.size_inv[:] = [1. / <double>width, 1. / <double>height] - - - -class ANM0(object): - _instructions = {0: {0: ('', 'delete'), - 1: ('I', 'set_sprite'), - 2: ('ff', 'set_scale'), - 3: ('I', 'set_alpha'), - 4: ('BBBx', 'set_color'), - 5: ('I', 'jump'), - 7: ('', 'toggle_mirrored'), - 9: ('fff', 'set_3d_rotations'), - 10: ('fff', 'set_3d_rotations_speed'), - 11: ('ff', 'set_scale_speed'), - 12: ('ii', 'fade'), - 13: ('', 'set_blendmode_add'), - 14: ('', 'set_blendmode_alphablend'), - 15: ('', 'keep_still'), - 16: ('ii', 'set_random_sprite'), - 17: ('fff', 'set_3d_translation'), - 18: ('fffi', 'move_to_linear'), - 19: ('fffi', 'move_to_decel'), - 20: ('fffi', 'move_to_accel'), - 21: ('', 'wait'), - 22: ('i', 'interrupt_label'), - 23: ('', 'set_corner_relative_placement'), - 24: ('', 'wait_ex'), - 25: ('i', 'set_allow_offset'), #TODO: better name - 26: ('i', 'set_automatic_orientation'), - 27: ('f', 'shift_texture_x'), - 28: ('f', 'shift_texture_y'), - 29: ('i', 'set_visible'), - 30: ('ffi', 'scale_in'), - 31: ('i', None)}, - - 2: {0: ('', 'noop'), - 1: ('', 'delete'), - 2: ('', 'keep_still'), - 3: ('I', 'set_sprite'), - 4: ('II', 'jump_bis'), - 5: ('III', 'jump_ex'), - 6: ('fff', 'set_3d_translation'), - 7: ('ff', 'set_scale'), - 8: ('I', 'set_alpha'), - 9: ('BBBx', 'set_color'), - 10: ('', 'toggle_mirrored'), - 12: ('fff', 'set_3d_rotations'), - 13: ('fff', 'set_3d_rotations_speed'), - 14: ('ff', 'set_scale_speed'), - 15: ('ii', 'fade'), - 16: ('I', 'set_blendmode'), - 17: ('fffi', 'move_to_linear'), - 18: ('fffi', 'move_to_decel'), - 19: ('fffi', 'move_to_accel'), - 20: ('', 'wait'), - 21: ('i', 'interrupt_label'), - 22: ('', 'set_corner_relative_placement'), - 23: ('', 'wait_ex'), - 24: ('i', 'set_allow_offset'), #TODO: better name - 25: ('i', 'set_automatic_orientation'), - 26: ('f', 'shift_texture_x'), - 27: ('f', 'shift_texture_y'), - 28: ('i', 'set_visible'), - 29: ('ffi', 'scale_in'), - 30: ('i', None), - 31: ('I', None), - 32: ('IIfff', 'move_in_linear_bis'), - 33: ('IIBBBx', 'change_color_in'), - 34: ('III', 'fade_bis'), - 35: ('IIfff', 'rotate_in_bis'), - 36: ('IIff', 'scale_in_bis'), - 37: ('II', 'set_int'), - 38: ('ff', 'set_float'), - 42: ('ff', 'decrement_float'), - 50: ('fff', 'add_float'), - 52: ('fff', 'substract_float'), - 55: ('III', 'divide_int'), - 59: ('II', 'set_random_int'), - 60: ('ff', 'set_random_float'), - 69: ('IIII', 'branch_if_not_equal'), - 79: ('I', 'wait_duration'), - 80: ('I', None)}} - - - @classmethod - def read(cls, file): - anm_list = [] - start_offset = 0 - while True: - file.seek(start_offset) - nb_sprites, nb_scripts, zero1 = unpack('<III', file.read(12)) - width, height, fmt, unknown1 = unpack('<IIII', file.read(16)) - first_name_offset, unused, secondary_name_offset = unpack('<III', file.read(12)) - version, unknown2, texture_offset, has_data, next_offset, unknown3 = unpack('<IIIIII', file.read(24)) - - if version == 0: - assert zero1 == 0 - assert unknown3 == 0 - assert has_data == 0 - elif version == 2: - assert zero1 == 0 - assert secondary_name_offset == 0 - assert has_data == 1 # Can be false but we don’t support that yet. - else: - raise WrongFormatError(version) - - instructions = cls._instructions[version] - - sprite_offsets = [unpack('<I', file.read(4))[0] for i in range(nb_sprites)] - script_offsets = [unpack('<II', file.read(8)) for i in range(nb_scripts)] - - self = ANM() - - self.size = (width, height) - self.version = version - - # Names - if first_name_offset: - file.seek(start_offset + first_name_offset) - self.first_name = read_string(file, 32, 'ascii') #TODO: 32, really? - if secondary_name_offset: - file.seek(start_offset + secondary_name_offset) - self.secondary_name = read_string(file, 32, 'ascii') #TODO: 32, really? - - - # Sprites - for offset in sprite_offsets: - file.seek(start_offset + offset) - idx, x, y, width, height = unpack('<Iffff', file.read(20)) - self.sprites[idx] = x, y, width, height - - - # Scripts - for i, offset in script_offsets: - self.scripts[i] = Script() - instruction_offsets = [] - file.seek(start_offset + offset) - while True: - instruction_offsets.append(file.tell() - (start_offset + offset)) - if version == 0: - time, opcode, size = unpack('<HBB', file.read(4)) - elif version == 2: - opcode, size, time, mask = unpack('<HHHH', file.read(8)) - if opcode == 0xffff: - break - size -= 8 - data = file.read(size) - if opcode in instructions: - args = unpack('<%s' % instructions[opcode][0], data) - else: - args = (data,) - logger.warn('unknown opcode %d', opcode) - - self.scripts[i].append((time, opcode, args)) - if version == 0 and opcode == 0: - break - - # Translate offsets to instruction pointers and register interrupts - for instr_offset, (j, instr) in zip(instruction_offsets, enumerate(self.scripts[i])): - time, opcode, args = instr - if version == 0: - if opcode == 5: - args = (instruction_offsets.index(args[0]),) - elif opcode == 22: - interrupt = args[0] - self.scripts[i].interrupts[interrupt] = j + 1 - elif version == 2: - if opcode == 4: - args = (instruction_offsets.index(args[0]), args[1]) - elif opcode == 5: - args = (args[0], instruction_offsets.index(args[1]), args[2]) - elif opcode == 21: - interrupt = args[0] - self.scripts[i].interrupts[interrupt] = j + 1 - elif opcode == 69: - args = (args[0], args[1], instruction_offsets.index(args[2]), args[3]) - self.scripts[i][j] = time, opcode, args - - # Texture - if has_data: - file.seek(start_offset + texture_offset) - magic = file.read(4) - assert magic == b'THTX' - zero, fmt, width, height, size = unpack('<HHHHI', file.read(12)) - assert zero == 0 - data = file.read(size) - self.texture = Texture(width, height, fmt, data) - - anm_list.append(self) - - if next_offset: - start_offset += next_offset - else: - break - - return anm_list
copy from pytouhou/formats/anm0.pyx copy to pytouhou/formats/anm0.py --- a/pytouhou/formats/anm0.pyx +++ b/pytouhou/formats/anm0.py @@ -24,6 +24,7 @@ from struct import pack, unpack from pytouhou.utils.helpers import read_string, get_logger from pytouhou.formats import WrongFormatError +from pytouhou.formats.animation import Animation from pytouhou.formats.thtx import Texture @@ -39,23 +40,7 @@ class Script(list): -cdef class ANM: - def __init__(self): - self.version = 0 - self.size_inv[:] = [0, 0] - self.first_name = None - self.secondary_name = None - self.sprites = {} - self.scripts = {} - - property size: - def __set__(self, tuple value): - width, height = value - self.size_inv[:] = [1. / <double>width, 1. / <double>height] - - - -class ANM0(object): +class ANM0(Animation): _instructions = {0: {0: ('', 'delete'), 1: ('I', 'set_sprite'), 2: ('ff', 'set_scale'), @@ -163,7 +148,7 @@ class ANM0(object): sprite_offsets = [unpack('<I', file.read(4))[0] for i in range(nb_sprites)] script_offsets = [unpack('<II', file.read(8)) for i in range(nb_scripts)] - self = ANM() + self = cls() self.size = (width, height) self.version = version
--- a/pytouhou/game/sprite.pxd +++ b/pytouhou/game/sprite.pxd @@ -1,5 +1,5 @@ from pytouhou.utils.interpolator cimport Interpolator -from pytouhou.formats.anm0 cimport ANM +from pytouhou.formats.animation cimport Animation cdef class Sprite: cdef public long blendfunc, frame @@ -10,7 +10,7 @@ cdef class Sprite: cdef public Interpolator scale_interpolator, fade_interpolator cdef public Interpolator offset_interpolator, rotation_interpolator cdef public Interpolator color_interpolator - cdef public ANM anm + cdef public Animation anm cdef void *_rendering_data
--- a/setup.py +++ b/setup.py @@ -122,7 +122,7 @@ for directory, _, files in os.walk('pyto elif extension_name == 'pytouhou.ui.anmrenderer' and not anmviewer: extension_names.pop() continue - elif package == 'pytouhou.formats' and extension_name != 'pytouhou.formats.anm0': + elif package == 'pytouhou.formats' and extension_name != 'pytouhou.formats.animation': continue else: compile_args = package_args