+ bone.co[0] = b.head_local[0]
+ bone.co[1] = b.head_local[2]
+ bone.co[2] = -b.head_local[1]
+ bone.end[0] = b.tail_local[0] - bone.co[0]
+ bone.end[1] = b.tail_local[2] - bone.co[1]
+ bone.end[2] = -b.tail_local[1] - bone.co[2]
+ bone.pstr_name = sr_compile_string( b.name )
+
+ for c in obj.pose.bones[b.name].constraints:#{
+ if c.type == 'IK':#{
+ bone.flags |= 0x2
+ bone.ik_target = bones_names.index(c.subtarget)
+ bone.ik_pole = bones_names.index(c.pole_subtarget)
+ #}
+ #}
+
+ node.bone_count += 1
+ sr_compile.bone_data.extend(bytearray(bone))
+ #}
+
+ # Compile anims
+ #
+ if obj.animation_data and sr_compile.pack_animations: #{
+ # So we can restore later
+ #
+ previous_frame = bpy.context.scene.frame_current
+ previous_action = obj.animation_data.action
+ POSE_OR_REST_CACHE = obj.data.pose_position
+ obj.data.pose_position = 'POSE'
+
+ for NLALayer in obj.animation_data.nla_tracks:#{
+ for NLAStrip in NLALayer.strips:#{
+ # set active
+ #
+ for a in bpy.data.actions:#{
+ if a.name == NLAStrip.name:#{
+ obj.animation_data.action = a
+ break
+ #}
+ #}
+
+ # Clip to NLA settings
+ #
+ anim_start = int(NLAStrip.action_frame_start)
+ anim_end = int(NLAStrip.action_frame_end)
+
+ # Export strips
+ #
+ anim = mdl_animation()
+ anim.pstr_name = sr_compile_string( NLAStrip.action.name )
+ anim.rate = 30.0
+ anim.keyframe_start = len(sr_compile.keyframe_data)//\
+ sizeof(mdl_transform)
+ anim.length = anim_end-anim_start
+
+ i = 0
+ # Export the keyframes
+ for frame in range(anim_start,anim_end):#{
+ bpy.context.scene.frame_set(frame)
+
+ for rb in bones:#{
+ pb = obj.pose.bones[rb.name]
+
+ # relative bone matrix
+ if rb.parent is not None:#{
+ offset_mtx = rb.parent.matrix_local
+ offset_mtx = offset_mtx.inverted_safe() @ \
+ rb.matrix_local
+
+ inv_parent = pb.parent.matrix @ offset_mtx
+ inv_parent.invert_safe()
+ fpm = inv_parent @ pb.matrix
+ #}
+ else:#{
+ bone_mtx = rb.matrix.to_4x4()
+ local_inv = rb.matrix_local.inverted_safe()
+ fpm = bone_mtx @ local_inv @ pb.matrix
+ #}
+
+ loc, rot, sca = fpm.decompose()
+
+ # rotation
+ lc_m = pb.matrix_channel.to_3x3()
+ if pb.parent is not None:#{
+ smtx = pb.parent.matrix_channel.to_3x3()
+ lc_m = smtx.inverted() @ lc_m
+ #}
+ rq = lc_m.to_quaternion()
+
+ kf = mdl_transform()
+ kf.co[0] = loc[0]
+ kf.co[1] = loc[2]
+ kf.co[2] = -loc[1]
+ kf.q[0] = rq[1]
+ kf.q[1] = rq[3]
+ kf.q[2] = -rq[2]
+ kf.q[3] = rq[0]
+ kf.s[0] = sca[0]
+ kf.s[1] = sca[1]
+ kf.s[2] = sca[2]
+ sr_compile.keyframe_data.extend(bytearray(kf))
+
+ i+=1
+ #}
+ #}
+
+ # Add to animation buffer
+ #
+ sr_compile.anim_data.extend(bytearray(anim))
+ node.anim_count += 1
+
+ # Report progress
+ #
+ print( F"[SR] | anim( {NLAStrip.action.name} )" )
+ #}
+ #}
+
+ # Restore context to how it was before
+ #
+ bpy.context.scene.frame_set( previous_frame )
+ obj.animation_data.action = previous_action
+ obj.data.pose_position = POSE_OR_REST_CACHE
+ #}
+
+ sr_compile.armature_data.extend(bytearray(node))