diff 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 diff
new file mode 100644
--- /dev/null
+++ b/io_scene_touhou/import_std.py
@@ -0,0 +1,150 @@
+# ##### 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))