poll() as a python '@staticmethod' was too limiting and didnt allow useful base class...
[blender.git] / release / scripts / io / import_shape_mdd.py
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16 #
17 # ***** END GPL LICENCE BLOCK *****
18
19 # <pep8 compliant>
20
21 # mdd importer by Bill L.Nieuwendorp
22 # conversion to blender 2.5: Ivo Grigull (loolarge)
23 #
24 # Warning if the vertex order or vertex count differs from the
25 # origonal model the mdd was Baked out from their will be Strange
26 # behavior
27 #
28 # vertex animation to ShapeKeys with ipo  and gives the frame a value of 1.0
29 # A modifier to read mdd files would be Ideal but thats for another day :)
30 #
31 # Please send any fixes,updates,bugs to Slow67_at_Gmail.com
32 # Bill Niewuendorp
33
34 import bpy
35 from struct import unpack
36
37
38 def mdd_import(filepath, ob, scene, PREF_START_FRAME=0, PREF_JUMP=1):
39
40     print('\n\nimporting mdd "%s"' % filepath)
41
42     bpy.ops.object.mode_set(mode='OBJECT')
43
44     file = open(filepath, 'rb')
45     frames, points = unpack(">2i", file.read(8))
46     time = unpack((">%df" % frames), file.read(frames * 4))
47
48     print('\tpoints:%d frames:%d' % (points, frames))
49
50     # If target object doesn't have Basis shape key, create it.
51     try:
52         num_keys = len(ob.data.shape_keys.keys)
53     except:
54         basis = ob.add_shape_key()
55         basis.name = "Basis"
56         ob.data.update()
57
58     scene.frame_current = PREF_START_FRAME
59
60     def UpdateMesh(ob, fr):
61
62         # Insert new shape key
63         new_shapekey = ob.add_shape_key()
64         new_shapekey.name = ("frame_%.4d" % fr)
65         new_shapekey_name = new_shapekey.name
66
67         ob.active_shape_key_index = len(ob.data.shape_keys.keys)-1
68         index = len(ob.data.shape_keys.keys)-1
69         ob.shape_key_lock = True
70
71         verts = ob.data.shape_keys.keys[len(ob.data.shape_keys.keys)-1].data
72
73
74         for v in verts: # 12 is the size of 3 floats
75             v.co[:] = unpack('>3f', file.read(12))
76         #me.update()
77         ob.shape_key_lock = False
78
79
80         # insert keyframes
81         shape_keys = ob.data.shape_keys
82
83         scene.frame_current -= 1
84         ob.data.shape_keys.keys[index].value = 0.0
85         shape_keys.keys[len(ob.data.shape_keys.keys)-1].keyframe_insert("value")
86
87         scene.frame_current += 1
88         ob.data.shape_keys.keys[index].value = 1.0
89         shape_keys.keys[len(ob.data.shape_keys.keys)-1].keyframe_insert("value")
90
91         scene.frame_current += 1
92         ob.data.shape_keys.keys[index].value = 0.0
93         shape_keys.keys[len(ob.data.shape_keys.keys)-1].keyframe_insert("value")
94
95         ob.data.update()
96
97
98     for i in range(frames):
99         UpdateMesh(ob, i)
100
101
102 from bpy.props import *
103
104
105 class importMDD(bpy.types.Operator):
106     '''Import MDD vertex keyframe file to shape keys'''
107     bl_idname = "import_shape.mdd"
108     bl_label = "Import MDD"
109
110     # get first scene to get min and max properties for frames, fps
111
112     minframe = 1
113     maxframe = 300000
114     minfps = 1
115     maxfps = 120
116
117     # List of operator properties, the attributes will be assigned
118     # to the class instance from the operator settings before calling.
119     filepath = StringProperty(name="File Path", description="Filepath used for importing the MDD file", maxlen=1024)
120     #fps = IntProperty(name="Frames Per Second", description="Number of frames/second", min=minfps, max=maxfps, default=25)
121     frame_start = IntProperty(name="Start Frame", description="Start frame for inserting animation", min=minframe, max=maxframe, default=0)
122
123     @classmethod
124     def poll(cls, context):
125         ob = context.active_object
126         return (ob and ob.type == 'MESH')
127
128     def execute(self, context):
129         if not self.properties.filepath:
130             raise Exception("filename not set")
131
132         mdd_import(self.properties.filepath, bpy.context.active_object, context.scene, self.properties.frame_start, 1)
133
134         return {'FINISHED'}
135
136     def invoke(self, context, event):
137         wm = context.manager
138         wm.add_fileselect(self)
139         return {'RUNNING_MODAL'}
140
141
142 def menu_func(self, context):
143     self.layout.operator(importMDD.bl_idname, text="Lightwave Point Cache (.mdd)")
144
145
146 def register():
147     bpy.types.INFO_MT_file_import.append(menu_func)
148
149
150 def unregister():
151     bpy.types.INFO_MT_file_import.remove(menu_func)
152
153 if __name__ == "__main__":
154     register()