File headers: use SPDX license identifiers
[blender-addons.git] / io_anim_nuke_chan / import_nuke_chan.py
blob0fabca81bbe73c3d2c3bc4af97c0d82208e0ac39
1 # SPDX-License-Identifier: GPL-2.0-or-later
3 # <pep8-80 compliant>
5 """ This script is an importer for the nuke's .chan files"""
7 from mathutils import Vector, Matrix, Euler
8 from math import radians
11 def read_chan(context, filepath, z_up, rot_ord, sensor_width, sensor_height):
13 # get the active object
14 scene = context.scene
15 obj = context.active_object
16 camera = obj.data if obj.type == 'CAMERA' else None
18 # prepare the correcting matrix
19 rot_mat = Matrix.Rotation(radians(90.0), 4, 'X').to_4x4()
21 # read the file
22 filehandle = open(filepath, 'r')
24 # iterate through the files lines
25 for line in filehandle:
26 # reset the target objects matrix
27 # (the one from which one we'll extract the final transforms)
28 m_trans_mat = Matrix()
30 # strip the line
31 data = line.split()
33 # test if the line is not commented out
34 if data and not data[0].startswith("#"):
36 # set the frame number basing on the chan file
37 scene.frame_set(int(data[0]))
39 # read the translation values from the first three columns of line
40 v_transl = Vector((float(data[1]),
41 float(data[2]),
42 float(data[3])))
43 translation_mat = Matrix.Translation(v_transl)
44 translation_mat.to_4x4()
46 # read the rotations, and set the rotation order basing on the
47 # order set during the export (it's not being saved in the chan
48 # file you have to keep it noted somewhere
49 # the actual objects rotation order doesn't matter since the
50 # rotations are being extracted from the matrix afterwards
51 e_rot = Euler((radians(float(data[4])),
52 radians(float(data[5])),
53 radians(float(data[6]))))
54 e_rot.order = rot_ord
55 mrot_mat = e_rot.to_matrix()
56 mrot_mat.resize_4x4()
58 # merge the rotation and translation
59 m_trans_mat = translation_mat @ mrot_mat
61 # correct the world space
62 # (nuke's and blenders scene spaces are different)
63 if z_up:
64 m_trans_mat = rot_mat @ m_trans_mat
66 # break the matrix into a set of the coordinates
67 trns = m_trans_mat.decompose()
69 # set the location and the location's keyframe
70 obj.location = trns[0]
71 obj.keyframe_insert("location")
73 # convert the rotation to euler angles (or not)
74 # basing on the objects rotation mode
75 if obj.rotation_mode == 'QUATERNION':
76 obj.rotation_quaternion = trns[1]
77 obj.keyframe_insert("rotation_quaternion")
78 elif obj.rotation_mode == 'AXIS_ANGLE':
79 tmp_rot = trns[1].to_axis_angle()
80 obj.rotation_axis_angle = (tmp_rot[1], *tmp_rot[0])
81 obj.keyframe_insert("rotation_axis_angle")
82 del tmp_rot
83 else:
84 obj.rotation_euler = trns[1].to_euler(obj.rotation_mode)
85 obj.keyframe_insert("rotation_euler")
87 # check if the object is camera and fov data is present
88 if camera and len(data) > 7:
89 camera.sensor_fit = 'HORIZONTAL'
90 camera.sensor_width = sensor_width
91 camera.sensor_height = sensor_height
92 camera.angle_y = radians(float(data[7]))
93 camera.keyframe_insert("lens")
94 filehandle.close()
96 return {'FINISHED'}