changeset 0:8265ef6db380

Hello Gensokyo _o/
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Tue, 05 Mar 2013 20:10:10 +0100
parents
children ba73c663a227
files io_scene_touhou/__init__.py io_scene_touhou/import_std.py
diffstat 2 files changed, 232 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/io_scene_touhou/__init__.py
@@ -0,0 +1,82 @@
+# ##### 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>
+
+
+bl_info = {
+    "name": "Touhou stage format (.std)",
+    "author": "Emmanuel Gil Peyrot",
+    "version": (0, 0),
+    "blender": (2, 66, 0),
+    "location": "File > Import-Export > Touhou Stage (.std) ",
+    "description": "Import-Export Touhou Stage",
+    "warning": "",
+    "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/"
+                "Scripts/Import-Export/Raw_Mesh_IO",
+    "tracker_url": "https://projects.blender.org/tracker/index.php?"
+                   "func=detail&aid=25692",
+    "category": "Import-Export"}
+
+if "bpy" in locals():
+    import imp
+    if "import_std" in locals():
+        imp.reload(import_std)
+else:
+    import bpy
+
+from bpy.props import StringProperty
+
+
+class StageImporter(bpy.types.Operator):
+    """Load Touhou triangle mesh data"""
+    bl_idname = "import_mesh.std"
+    bl_label = "Import Touhou"
+    bl_options = {'UNDO'}
+
+    filepath = StringProperty(
+            subtype='FILE_PATH',
+            )
+    filter_glob = StringProperty(default="stage*.std", options={'HIDDEN'})
+
+    def execute(self, context):
+        from . import import_std
+        import_std.read(self.filepath)
+        return {'FINISHED'}
+
+    def invoke(self, context, event):
+        wm = context.window_manager
+        wm.fileselect_add(self)
+        return {'RUNNING_MODAL'}
+
+
+def menu_import(self, context):
+    self.layout.operator(StageImporter.bl_idname, text="Touhou Stage (.std)")
+
+
+def register():
+    bpy.utils.register_module(__name__)
+    bpy.types.INFO_MT_file_import.append(menu_import)
+
+
+def unregister():
+    bpy.utils.unregister_module(__name__)
+    bpy.types.INFO_MT_file_import.remove(menu_import)
+
+if __name__ == "__main__":
+    register()
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))