view io_scene_touhou/import_std.py @ 0:8265ef6db380

Hello Gensokyo _o/
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Tue, 05 Mar 2013 20:10:10 +0100
parents
children ba73c663a227
line wrap: on
line source

# ##### BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####

# <pep8-80 compliant>

"""
This script imports Touhou EoSD stages files to Blender.

Usage:
Execute this script from the "File->Import" menu and choose a Touhou
stage file to open.
"""


from pytouhou.formats.std import Stage
from pytouhou.formats.anm0 import ANM0
from pytouhou.resource.anmwrapper import AnmWrapper
from pytouhou.vm.anmrunner import ANMRunner
from pytouhou.game.sprite import Sprite
from pytouhou.ui.sprite import get_sprite_rendering_data
import bpy
import os.path


def build_models(stage, anm_wrapper):
    """Taken from pytouhou.game.background."""
    models = []
    for obj in stage.models:
        quads = []
        for script_index, ox, oy, oz, width_override, height_override in obj.quads:
            sprite = Sprite(width_override, height_override)
            anm_runner = ANMRunner(anm_wrapper, script_index, sprite)
            anm_runner.run_frame()
            quads.append((ox, oy, oz, sprite))
        models.append(quads)
    return models


def read_mesh(obj_name, stage, model, image):
    verts = []
    texcoords = []
    cols = []
    nb_vertices = 0
    faces_indices = []

    for ox, oy, oz, sprite in model:
        key, (vertices, uvs, colors) = get_sprite_rendering_data(sprite)
        (x1, y1, z1), (x2, y2, z2), (x3, y3, z3), (x4, y4, z4) = vertices
        left, right, bottom, top = uvs
        r, g, b, a = colors

        #verts.extend(((x1 + ox, y1 + oy, z1 + oz),
        #              (x2 + ox, y2 + oy, z2 + oz),
        #              (x3 + ox, y3 + oy, z3 + oz),
        #              (x4 + ox, y4 + oy, z4 + oz)))

        # Blender coordinates are z-inverted.
        verts.extend(((x1 + ox, y1 + oy, -(z1 + oz)),
                      (x2 + ox, y2 + oy, -(z2 + oz)),
                      (x3 + ox, y3 + oy, -(z3 + oz)),
                      (x4 + ox, y4 + oy, -(z4 + oz))))

        texcoords.extend(((left, bottom),
                          (right, bottom),
                          (right, top),
                          (left, top)))

        #TODO: use them.
        cols.append((r, g, b, a))

        faces_indices.append((nb_vertices, nb_vertices + 1, nb_vertices + 2, nb_vertices + 3))

        nb_vertices += 4

    mesh = bpy.data.meshes.new(obj_name)
    mesh.from_pydata(verts, [], faces_indices)

    texture = mesh.uv_textures.new('Texture')
    for tex in texture.data:
        tex.image = image

    uvs = mesh.uv_layers[0]
    for i, uv_loop in enumerate(uvs.data):
        uv_loop.uv = texcoords[i]

    return mesh


def add_object(name, mesh, position):
    scene = bpy.context.scene

    for obj in scene.objects:
        obj.select = False

    mesh.update()
    mesh.validate()

    obj = bpy.data.objects.new(name, mesh)
    obj.location = position
    scene.objects.link(obj)
    obj.select = True

    if scene.objects.active is None or scene.objects.active.mode == 'OBJECT':
        scene.objects.active = obj


def read(stage_path):
    dirname = os.path.dirname(stage_path)

    obj_name = bpy.path.display_name_from_filepath(stage_path)
    assert obj_name[:5] == 'stage'
    stage_number = int(obj_name[5])

    with open(stage_path, "rb") as filehandle:
        stage = Stage.read(filehandle)

    anm_path = os.path.join(dirname, 'stg{}bg.anm'.format(stage_number))
    with open(anm_path, "rb") as filehandle:
        anm = ANM0.read(filehandle)
    anm_wrapper = AnmWrapper((anm,), (0,))

    models = build_models(stage, anm_wrapper)

    texture_path = os.path.join(dirname, 'stg{}bg.png'.format(stage_number))
    image = bpy.data.images.load(texture_path)

    meshes = []
    for i, model in enumerate(models):
        name = '{}-mesh{}'.format(obj_name, i)
        mesh = read_mesh(name, stage, model, image)
        meshes.append(mesh)

    for i, (model_id, ox, oy, oz) in enumerate(stage.object_instances):
        name = '{}-object{}'.format(obj_name, i)
        add_object(name, meshes[model_id], (ox, oy, -oz))