1 # SPDX-License-Identifier: GPL-2.0-or-later
4 "name": "Nuke Animation Format (.chan)",
5 "author": "Michael Krupa",
8 "location": "File > Import/Export > Nuke (.chan)",
9 "description": "Import/Export object's animation with nuke",
11 "doc_url": "{BLENDER_MANUAL_URL}/addons/import_export/anim_nuke_chan.html",
12 "category": "Import-Export",
16 # To support reload properly, try to access a package var,
17 # if it's there, reload everything
20 if "import_nuke_chan" in locals():
21 importlib
.reload(import_nuke_chan
)
22 if "export_nuke_chan" in locals():
23 importlib
.reload(export_nuke_chan
)
27 from bpy
.types
import Operator
28 from bpy_extras
.io_utils
import ImportHelper
, ExportHelper
29 from bpy
.props
import (
36 # property shared by both operators
37 rotation_order
= EnumProperty(
38 name
="Rotation order",
39 description
="Choose the export rotation order",
40 items
=(('XYZ', "XYZ", "XYZ"),
41 ('XZY', "XZY", "XZY"),
42 ('YXZ', "YXZ", "YXZ"),
43 ('YZX', "YZX", "YZX"),
44 ('ZXY', "ZXY", "ZXY"),
45 ('ZYX', "ZYX", "ZYX"),
50 class ImportChan(Operator
, ImportHelper
):
51 """Import animation from .chan file, exported from nuke or houdini """ \
52 """(the importer uses frame numbers from the file)"""
53 bl_idname
= "import_scene.import_chan"
54 bl_label
= "Import chan file"
56 filename_ext
= ".chan"
58 filter_glob
: StringProperty(default
="*.chan", options
={'HIDDEN'})
60 rotation_order
: rotation_order
63 description
="Switch the Y and Z axis",
66 sensor_width
: FloatProperty(
67 name
="Camera sensor width",
68 description
="Imported camera sensor width",
71 sensor_height
: FloatProperty(
72 name
="Camera sensor height",
73 description
="Imported camera sensor height",
77 def poll(cls
, context
):
78 return context
.active_object
is not None
80 def execute(self
, context
):
81 from . import import_nuke_chan
82 return import_nuke_chan
.read_chan(context
,
90 class ExportChan(Operator
, ExportHelper
):
91 """Export the animation to .chan file, readable by nuke and houdini """ \
92 """(the exporter uses frames from the frames range)"""
93 bl_idname
= "export.export_chan"
94 bl_label
= "Export chan file"
96 filename_ext
= ".chan"
97 filter_glob
: StringProperty(default
="*.chan", options
={'HIDDEN'})
100 description
="Switch the Y and Z axis",
102 rotation_order
: rotation_order
105 def poll(cls
, context
):
106 return context
.active_object
is not None
108 def execute(self
, context
):
109 from . import export_nuke_chan
110 return export_nuke_chan
.save_chan(context
,
116 def menu_func_import(self
, context
):
117 self
.layout
.operator(ImportChan
.bl_idname
, text
="Nuke (.chan)")
120 def menu_func_export(self
, context
):
121 self
.layout
.operator(ExportChan
.bl_idname
, text
="Nuke (.chan)")
125 bpy
.utils
.register_class(ImportChan
)
126 bpy
.utils
.register_class(ExportChan
)
127 bpy
.types
.TOPBAR_MT_file_import
.append(menu_func_import
)
128 bpy
.types
.TOPBAR_MT_file_export
.append(menu_func_export
)
132 bpy
.utils
.unregister_class(ImportChan
)
133 bpy
.utils
.unregister_class(ExportChan
)
134 bpy
.types
.TOPBAR_MT_file_import
.remove(menu_func_import
)
135 bpy
.types
.TOPBAR_MT_file_export
.remove(menu_func_export
)
138 if __name__
== "__main__":