1 # SPDX-FileCopyrightText: 2011-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
6 "name": "NewTek MDD format",
7 "author": "Bill L.Nieuwendorp",
10 "location": "File > Import-Export",
11 "description": "Import-Export MDD as mesh shape keys",
13 "doc_url": "{BLENDER_MANUAL_URL}/addons/import_export/shape_mdd.html",
14 "support": 'OFFICIAL',
15 "category": "Import-Export",
20 if "import_mdd" in locals():
21 importlib
.reload(import_mdd
)
22 if "export_mdd" in locals():
23 importlib
.reload(export_mdd
)
27 from bpy
.props
import (
33 from bpy_extras
.io_utils
import ExportHelper
, ImportHelper
36 class ImportMDD(bpy
.types
.Operator
, ImportHelper
):
37 """Import MDD vertex keyframe file to shape keys"""
38 bl_idname
= "import_shape.mdd"
39 bl_label
= "Import MDD"
44 filter_glob
: StringProperty(
48 frame_start
: IntProperty(
50 description
="Start frame for inserting animation",
51 min=-300000, max=300000,
54 frame_step
: IntProperty(
61 def poll(cls
, context
):
62 obj
= context
.active_object
63 return (obj
and obj
.type == 'MESH')
65 def invoke(self
, context
, event
):
67 self
.frame_start
= scene
.frame_start
69 return super().invoke(context
, event
)
71 def execute(self
, context
):
72 keywords
= self
.as_keywords(ignore
=("filter_glob",))
74 from . import import_mdd
75 return import_mdd
.load(context
, **keywords
)
78 class ExportMDD(bpy
.types
.Operator
, ExportHelper
):
79 """Animated mesh to MDD vertex keyframe file"""
80 bl_idname
= "export_shape.mdd"
81 bl_label
= "Export MDD"
84 filter_glob
: StringProperty(default
="*.mdd", options
={'HIDDEN'})
86 # get first scene to get min and max properties for frames, fps
93 # List of operator properties, the attributes will be assigned
94 # to the class instance from the operator settings before calling.
96 name
="Frames Per Second",
97 description
="Number of frames/second",
98 min=minfps
, max=maxfps
,
101 frame_start
: IntProperty(
103 description
="Start frame for baking",
104 min=minframe
, max=maxframe
,
107 frame_end
: IntProperty(
109 description
="End frame for baking",
110 min=minframe
, max=maxframe
,
113 use_rest_frame
: BoolProperty(
115 description
="Write the rest state at the first frame",
120 def poll(cls
, context
):
121 obj
= context
.active_object
122 return (obj
and obj
.type == 'MESH')
124 def invoke(self
, context
, event
):
125 scene
= context
.scene
126 self
.frame_start
= scene
.frame_start
127 self
.frame_end
= scene
.frame_end
128 self
.fps
= scene
.render
.fps
/ scene
.render
.fps_base
130 return super().invoke(context
, event
)
132 def execute(self
, context
):
133 keywords
= self
.as_keywords(ignore
=("check_existing", "filter_glob"))
135 from . import export_mdd
136 return export_mdd
.save(context
, **keywords
)
139 def menu_func_import(self
, context
):
140 self
.layout
.operator(ImportMDD
.bl_idname
,
141 text
="Lightwave Point Cache (.mdd)",
145 def menu_func_export(self
, context
):
146 self
.layout
.operator(ExportMDD
.bl_idname
,
147 text
="Lightwave Point Cache (.mdd)",
158 bpy
.utils
.register_class(cls
)
160 bpy
.types
.TOPBAR_MT_file_import
.append(menu_func_import
)
161 bpy
.types
.TOPBAR_MT_file_export
.append(menu_func_export
)
166 bpy
.utils
.unregister_class(cls
)
168 bpy
.types
.TOPBAR_MT_file_import
.remove(menu_func_import
)
169 bpy
.types
.TOPBAR_MT_file_export
.remove(menu_func_export
)
171 if __name__
== "__main__":