Mercurial > touhou-blender
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:8265ef6db380 |
---|---|
1 # ##### BEGIN GPL LICENSE BLOCK ##### | |
2 # | |
3 # This program is free software; you can redistribute it and/or | |
4 # modify it under the terms of the GNU General Public License | |
5 # as published by the Free Software Foundation; either version 2 | |
6 # of the License, or (at your option) any later version. | |
7 # | |
8 # This program is distributed in the hope that it will be useful, | |
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 # GNU General Public License for more details. | |
12 # | |
13 # You should have received a copy of the GNU General Public License | |
14 # along with this program; if not, write to the Free Software Foundation, | |
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
16 # | |
17 # ##### END GPL LICENSE BLOCK ##### | |
18 | |
19 # <pep8-80 compliant> | |
20 | |
21 """ | |
22 This script imports Touhou EoSD stages files to Blender. | |
23 | |
24 Usage: | |
25 Execute this script from the "File->Import" menu and choose a Touhou | |
26 stage file to open. | |
27 """ | |
28 | |
29 | |
30 from pytouhou.formats.std import Stage | |
31 from pytouhou.formats.anm0 import ANM0 | |
32 from pytouhou.resource.anmwrapper import AnmWrapper | |
33 from pytouhou.vm.anmrunner import ANMRunner | |
34 from pytouhou.game.sprite import Sprite | |
35 from pytouhou.ui.sprite import get_sprite_rendering_data | |
36 import bpy | |
37 import os.path | |
38 | |
39 | |
40 def build_models(stage, anm_wrapper): | |
41 """Taken from pytouhou.game.background.""" | |
42 models = [] | |
43 for obj in stage.models: | |
44 quads = [] | |
45 for script_index, ox, oy, oz, width_override, height_override in obj.quads: | |
46 sprite = Sprite(width_override, height_override) | |
47 anm_runner = ANMRunner(anm_wrapper, script_index, sprite) | |
48 anm_runner.run_frame() | |
49 quads.append((ox, oy, oz, sprite)) | |
50 models.append(quads) | |
51 return models | |
52 | |
53 | |
54 def read_mesh(obj_name, stage, model, image): | |
55 verts = [] | |
56 texcoords = [] | |
57 cols = [] | |
58 nb_vertices = 0 | |
59 faces_indices = [] | |
60 | |
61 for ox, oy, oz, sprite in model: | |
62 key, (vertices, uvs, colors) = get_sprite_rendering_data(sprite) | |
63 (x1, y1, z1), (x2, y2, z2), (x3, y3, z3), (x4, y4, z4) = vertices | |
64 left, right, bottom, top = uvs | |
65 r, g, b, a = colors | |
66 | |
67 #verts.extend(((x1 + ox, y1 + oy, z1 + oz), | |
68 # (x2 + ox, y2 + oy, z2 + oz), | |
69 # (x3 + ox, y3 + oy, z3 + oz), | |
70 # (x4 + ox, y4 + oy, z4 + oz))) | |
71 | |
72 # Blender coordinates are z-inverted. | |
73 verts.extend(((x1 + ox, y1 + oy, -(z1 + oz)), | |
74 (x2 + ox, y2 + oy, -(z2 + oz)), | |
75 (x3 + ox, y3 + oy, -(z3 + oz)), | |
76 (x4 + ox, y4 + oy, -(z4 + oz)))) | |
77 | |
78 texcoords.extend(((left, bottom), | |
79 (right, bottom), | |
80 (right, top), | |
81 (left, top))) | |
82 | |
83 #TODO: use them. | |
84 cols.append((r, g, b, a)) | |
85 | |
86 faces_indices.append((nb_vertices, nb_vertices + 1, nb_vertices + 2, nb_vertices + 3)) | |
87 | |
88 nb_vertices += 4 | |
89 | |
90 mesh = bpy.data.meshes.new(obj_name) | |
91 mesh.from_pydata(verts, [], faces_indices) | |
92 | |
93 texture = mesh.uv_textures.new('Texture') | |
94 for tex in texture.data: | |
95 tex.image = image | |
96 | |
97 uvs = mesh.uv_layers[0] | |
98 for i, uv_loop in enumerate(uvs.data): | |
99 uv_loop.uv = texcoords[i] | |
100 | |
101 return mesh | |
102 | |
103 | |
104 def add_object(name, mesh, position): | |
105 scene = bpy.context.scene | |
106 | |
107 for obj in scene.objects: | |
108 obj.select = False | |
109 | |
110 mesh.update() | |
111 mesh.validate() | |
112 | |
113 obj = bpy.data.objects.new(name, mesh) | |
114 obj.location = position | |
115 scene.objects.link(obj) | |
116 obj.select = True | |
117 | |
118 if scene.objects.active is None or scene.objects.active.mode == 'OBJECT': | |
119 scene.objects.active = obj | |
120 | |
121 | |
122 def read(stage_path): | |
123 dirname = os.path.dirname(stage_path) | |
124 | |
125 obj_name = bpy.path.display_name_from_filepath(stage_path) | |
126 assert obj_name[:5] == 'stage' | |
127 stage_number = int(obj_name[5]) | |
128 | |
129 with open(stage_path, "rb") as filehandle: | |
130 stage = Stage.read(filehandle) | |
131 | |
132 anm_path = os.path.join(dirname, 'stg{}bg.anm'.format(stage_number)) | |
133 with open(anm_path, "rb") as filehandle: | |
134 anm = ANM0.read(filehandle) | |
135 anm_wrapper = AnmWrapper((anm,), (0,)) | |
136 | |
137 models = build_models(stage, anm_wrapper) | |
138 | |
139 texture_path = os.path.join(dirname, 'stg{}bg.png'.format(stage_number)) | |
140 image = bpy.data.images.load(texture_path) | |
141 | |
142 meshes = [] | |
143 for i, model in enumerate(models): | |
144 name = '{}-mesh{}'.format(obj_name, i) | |
145 mesh = read_mesh(name, stage, model, image) | |
146 meshes.append(mesh) | |
147 | |
148 for i, (model_id, ox, oy, oz) in enumerate(stage.object_instances): | |
149 name = '{}-object{}'.format(obj_name, i) | |
150 add_object(name, meshes[model_id], (ox, oy, -oz)) |