diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..a83d836 --- /dev/null +++ b/__init__.py @@ -0,0 +1,389 @@ +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("