bl_info = { "name": "Export Event Horizon Model (.ehm)", "author": "Arron Nelson (AKA Karutoh)", "version": (1, 0, 0), "blender": (3, 1, 0), "location": "File > Export > EHM", "description": "The script exports Blender geometry to a Event Horizon Model file format.", "category": "Import-Export" } import sys import struct import mathutils import bmesh import bpy from bpy_extras.io_utils import ExportHelper, axis_conversion from bpy.props import StringProperty, BoolProperty, EnumProperty from bpy.types import Operator, Mesh """ PropertyChange.type == 0 //X-Axis Position PropertyChange.type == 1 //Y-Axis Position PropertyChange.type == 2 //Z-Axis Position PropertyChange.type == 3 //X-Axis Scale PropertyChange.type == 4 //Y-Axis Scale PropertyChange.type == 5 //Z-Axis Scale PropertyChange.type == 6 //X-Axis Rotation (Quat) PropertyChange.type == 7 //Y-Axis Rotation (Quat) PropertyChange.type == 8 //Z-Axis Rotation (Quat) PropertyChange.type == 9 //W-Axis Rotation (Quat) """ class KeyFrame: def __init__(self, num, timeStamp): self.num = num self.timeStamp = timeStamp self.pos = mathutils.Vector((0.0, 0.0, 0.0)) self.rot = mathutils.Quaternion() self.scale = mathutils.Vector((0.0, 0.0, 0.0)) class BoneAnimation: def __init__(self, id): self.id = id self.keyFrames = [] def GetKeyFrame(self, num): for frame in self.keyFrames: if frame.num == num: return frame return None def AddKeyFrame(self, keyFrame): if self.GetKeyFrame(keyFrame.num) != None: return None self.keyFrames.append(keyFrame) return self.keyFrames[len(self.keyFrames) - 1] def Triangulate(mesh): #mesh.update_from_editmode() #mesh.data.calc_normals_split() edit = bmesh.new() edit.from_mesh(mesh.data) bmesh.ops.triangulate(edit, faces = edit.faces, quad_method='BEAUTY', ngon_method='BEAUTY') edit.to_mesh(mesh.data) edit.free() def FindBIndexByGIndex(mesh, gi, skeletons): for s in skeletons: for bi, b in enumerate(s.data.bones): if mesh.vertex_groups.find(b.name) == gi: return bi return 0xFF def ExportSkeletons(bytes, skeletons): if len(skeletons) >= 1: #Bone Count bytes.extend(struct.pack("= 1: fps = bpy.context.scene.render.fps / bpy.context.scene.render.fps_base #Animation Count bytes.extend(struct.pack(" duration: duration = keyFrame.timeStamp if f.array_index == 0: keyFrame.pos.x = k.co.y elif f.array_index == 1: keyFrame.pos.z = k.co.y elif f.array_index == 2: keyFrame.pos.y = k.co.y elif f.data_path == f'pose.bones["{b.name}"].scale': result = None for ba in boneAnims: if ba.id == i: result = ba if result == None: boneAnims.append(BoneAnimation(i)) result = boneAnims[len(boneAnims) - 1] for k in f.keyframe_points: keyFrame = result.GetKeyFrame(k.co.x) if keyFrame == None: keyFrame = result.AddKeyFrame(KeyFrame(k.co.x, k.co.x / fps)) if keyFrame.timeStamp > duration: duration = keyFrame.timeStamp if f.array_index == 0: keyFrame.scale.x = k.co.y elif f.array_index == 1: keyFrame.scale.z = k.co.y elif f.array_index == 2: keyFrame.scale.y = k.co.y elif f.data_path == f'pose.bones["{b.name}"].rotation_quaternion': result = None for ba in boneAnims: if ba.id == i: result = ba if result == None: boneAnims.append(BoneAnimation(i)) result = boneAnims[len(boneAnims) - 1] for k in f.keyframe_points: keyFrame = result.GetKeyFrame(k.co.x) if keyFrame == None: keyFrame = result.AddKeyFrame(KeyFrame(k.co.x, k.co.x / fps)) if keyFrame.timeStamp > duration: duration = keyFrame.timeStamp if f.array_index == 0: keyFrame.rot.w = k.co.y elif f.array_index == 1: keyFrame.rot.x = k.co.y elif f.array_index == 2: keyFrame.rot.y = k.co.y elif f.array_index == 3: keyFrame.rot.z = k.co.y #Duration bytes.extend(struct.pack("