def __init__(self): self.endframeIndex = 0 self.motionFlags = 0 self.v0 = 0.0 self.v1 = 0.0 self.angle = 0.0 self.vector = SourceVector() self.position = SourceVector()
def write_attachment(self, fileh): for attachment in self.mdl.file_data.attachments: # type: SourceMdlAttachment # $attachment "eyes" "bip_head" 4.63 - 8.34 - 0.51 rotate 0.12 - 3.73 89.99 bone = self.mdl.file_data.bones[attachment.localBoneIndex] fileh.write('$attachment "{}" "{}" {} rotate {}\n'.format( attachment.name, bone.name, SourceVector([ attachment.localM14, attachment.localM24, attachment.localM34 ]).as_rounded(2), SourceVector( convert_rotation_matrix_to_degrees( attachment.localM11, attachment.localM21, attachment.localM31, attachment.localM12, attachment.localM22, attachment.localM32, attachment.localM33)).to_degrees().as_rounded(2))) fileh.write('\n')
class SourceMdlBone: def __init__(self): self.boneOffset = 0 self.name = "" self.parentBoneIndex = 0 self.flags = 0 self.boneControllerIndex = [] self.position = SourceVector() self.rotation = SourceVector() self.pos_scale = SourceVector() self.rot_scale = SourceVector() def read(self, reader: ByteIO, mdl: SourceMdlFileDataV10): self.boneOffset = reader.tell() self.name = reader.read_ascii_string(32) self.parentBoneIndex = reader.read_int32() self.flags = reader.read_int32() self.boneControllerIndex = [reader.read_int32() for _ in range(6)] self.position.read(reader) self.rotation.read(reader) self.scale = [reader.read_float() for _ in range(6)] mdl.bones.append(self) def __repr__(self): return '<Bone "{}" pos:{} rot: {}>'.format( self.name, self.position.as_rounded(2), self.rotation.as_rounded(2), )
class SourceMdlMovement: def __init__(self): self.endframeIndex = 0 self.motionFlags = 0 self.v0 = 0.0 self.v1 = 0.0 self.angle = 0.0 self.vector = SourceVector() self.position = SourceVector() def read(self, reader: ByteIO): self.endframeIndex = reader.read_uint32() self.motionFlags = reader.read_uint32() self.v0 = reader.read_float() self.v1 = reader.read_float() self.angle = reader.read_float() self.vector.read(reader) self.position.read(reader) return self def __repr__(self): return "<Movement angle:{} vector:{} position:{}>".format(self.angle, self.vector, self.position)
def __init__(self): self.boneOffset = 0 self.name = "" self.parentBoneIndex = 0 self.flags = 0 self.boneControllerIndex = [] self.position = SourceVector() self.rotation = SourceVector() self.pos_scale = SourceVector() self.rot_scale = SourceVector()
def __init__(self): self.id = '' self.version = 0 self.name = '' self.file_size = 0 self.eye_position = SourceVector() self.hull_min_position = SourceVector() self.hull_max_position = SourceVector() self.view_bounding_box_min_position = SourceVector() self.view_bounding_box_max_position = SourceVector() self.flags = 0 self.bone_count = 0 self.bone_offset = 0 self.bone_controller_count = 0 self.bone_controller_offset = 0 self.hitbox_set_count = 0 self.hitbox_set_offset = 0 self.local_sequence_count = 0 self.local_sequence_offset = 0 self.sequence_group_count = 0 self.sequence_group_offset = 0 self.texture_count = 0 self.texture_offset = 0 self.texture_data_offset = 0 self.skin_reference_count = 0 self.skin_family_count = 0 self.skin_family_offset = 0 self.body_part_count = 0 self.body_part_offset = 0 self.local_attachment_count = 0 self.local_attachment_offset = 0 self.sound_table = 0 self.sound_index = 0 self.sound_groups = 0 self.sound_group_offset = 0 self.transitions_count = 0 self.transition_offset = 0 self.reserved = [] self.animation_descs = [] self.anim_blocks = [] self.anim_block_relative_path_file_name = "" self.attachments = [] # type: List[SourceMdlAttachment] self.body_parts = [] # type: List[SourceMdlBodyPart] self.bones = [] # type: List[SourceMdlBone] self.bone_controllers = [] # type: List[SourceMdlBoneController] self.bone_table_by_name = [] self.flex_descs = [] # type: List[SourceMdlFlexDesc] self.flex_controllers = [] # type: List[SourceMdlFlexController] self.flex_rules = [] # type: List[SourceMdlFlexRule] self.hitbox_sets = [] self.ik_chains = [] self.ik_locks = [] self.key_values_text = "" self.local_node_names = [] self.mouths = [] # type: List[SourceMdlMouth] self.pose_param_descs = [] self.sequence_descs = [] self.skin_families = [] # type: List[List[int]] self.surface_prop_name = "" self.texture_paths = [] # type: List[str] self.textures = [] # type: List[SourceMdlTexture] self.section_frame_count = 0 self.section_frame_min_frame_count = 0 self.actual_file_size = 0 self.flex_frames = [] # type: List[FlexFrame] self.bone_flex_drivers = [] # type: List[SourceBoneFlexDriver] self.flex_controllers_ui = [] # type: List[SourceFlexControllerUI] self.eyelid_flex_frame_indexes = [] self.first_animation_desc = None self.first_animation_desc_frame_lines = {} self.mdl_file_only_has_animations = False self.procedural_bones_command_is_used = False self.weight_lists = [] self.name_offset = 0 self.bodypart_frames = [ ] # type: List[List[Tuple[int,SourceMdlBodyPart]]]
class SourceMdlFileDataV10: def __init__(self): self.id = '' self.version = 0 self.name = '' self.file_size = 0 self.eye_position = SourceVector() self.hull_min_position = SourceVector() self.hull_max_position = SourceVector() self.view_bounding_box_min_position = SourceVector() self.view_bounding_box_max_position = SourceVector() self.flags = 0 self.bone_count = 0 self.bone_offset = 0 self.bone_controller_count = 0 self.bone_controller_offset = 0 self.hitbox_set_count = 0 self.hitbox_set_offset = 0 self.local_sequence_count = 0 self.local_sequence_offset = 0 self.sequence_group_count = 0 self.sequence_group_offset = 0 self.texture_count = 0 self.texture_offset = 0 self.texture_data_offset = 0 self.skin_reference_count = 0 self.skin_family_count = 0 self.skin_family_offset = 0 self.body_part_count = 0 self.body_part_offset = 0 self.local_attachment_count = 0 self.local_attachment_offset = 0 self.sound_table = 0 self.sound_index = 0 self.sound_groups = 0 self.sound_group_offset = 0 self.transitions_count = 0 self.transition_offset = 0 self.reserved = [] self.animation_descs = [] self.anim_blocks = [] self.anim_block_relative_path_file_name = "" self.attachments = [] # type: List[SourceMdlAttachment] self.body_parts = [] # type: List[SourceMdlBodyPart] self.bones = [] # type: List[SourceMdlBone] self.bone_controllers = [] # type: List[SourceMdlBoneController] self.bone_table_by_name = [] self.flex_descs = [] # type: List[SourceMdlFlexDesc] self.flex_controllers = [] # type: List[SourceMdlFlexController] self.flex_rules = [] # type: List[SourceMdlFlexRule] self.hitbox_sets = [] self.ik_chains = [] self.ik_locks = [] self.key_values_text = "" self.local_node_names = [] self.mouths = [] # type: List[SourceMdlMouth] self.pose_param_descs = [] self.sequence_descs = [] self.skin_families = [] # type: List[List[int]] self.surface_prop_name = "" self.texture_paths = [] # type: List[str] self.textures = [] # type: List[SourceMdlTexture] self.section_frame_count = 0 self.section_frame_min_frame_count = 0 self.actual_file_size = 0 self.flex_frames = [] # type: List[FlexFrame] self.bone_flex_drivers = [] # type: List[SourceBoneFlexDriver] self.flex_controllers_ui = [] # type: List[SourceFlexControllerUI] self.eyelid_flex_frame_indexes = [] self.first_animation_desc = None self.first_animation_desc_frame_lines = {} self.mdl_file_only_has_animations = False self.procedural_bones_command_is_used = False self.weight_lists = [] self.name_offset = 0 self.bodypart_frames = [ ] # type: List[List[Tuple[int,SourceMdlBodyPart]]] def read(self, reader: ByteIO): self.read_header00(reader) self.read_header01(reader) def read_header00(self, reader: ByteIO): self.id = ''.join(list([chr(reader.read_uint8()) for _ in range(4)])) self.version = reader.read_uint32() print('Found MDL version', self.version) # self.checksum = reader.read_uint32() self.name = reader.read_ascii_string(64) self.file_size = reader.read_uint32() def read_header01(self, reader: ByteIO): self.eye_position.read(reader) self.hull_min_position.read(reader) self.hull_max_position.read(reader) self.view_bounding_box_min_position.read(reader) self.view_bounding_box_max_position.read(reader) self.flags = reader.read_uint32() self.bone_count = reader.read_uint32() self.bone_offset = reader.read_uint32() self.bone_controller_count = reader.read_uint32() self.bone_controller_offset = reader.read_uint32() self.hitbox_set_count = reader.read_uint32() self.hitbox_set_offset = reader.read_uint32() self.local_sequence_count = reader.read_uint32() self.local_sequence_offset = reader.read_uint32() self.sequence_group_count = reader.read_uint32() self.sequence_group_offset = reader.read_uint32() self.texture_count = reader.read_uint32() self.texture_offset = reader.read_uint32() self.texture_data_offset = reader.read_int32() self.skin_reference_count = reader.read_uint32() self.skin_family_count = reader.read_uint32() self.skin_family_offset = reader.read_uint32() self.body_part_count = reader.read_uint32() self.body_part_offset = reader.read_uint32() self.local_attachment_count = reader.read_uint32() self.local_attachment_offset = reader.read_uint32() self.sound_table = reader.read_uint32() self.sound_index = reader.read_uint32() self.sound_groups = reader.read_uint32() self.sound_group_offset = reader.read_uint32() self.transitions_count = reader.read_uint32() self.transition_offset = reader.read_uint32() if self.body_part_count == 0 and self.local_sequence_count > 0: self.mdl_file_only_has_animations = True def print_info(self, indent=0): def iprint(indent2, arg, fname=''): if indent + indent2: print( '\t' * (indent + indent2), *(get_class_var_name(self, arg).title().replace('_', ' '), ':', arg) if not fname else (fname, ':', arg)) else: print(*(get_class_var_name(self, arg).title(), ':', arg) if not fname else (fname, ':', arg)) print('SourceMdlFileData:') iprint(1, self.id) iprint(1, self.version) iprint(1, self.name) iprint(1, self.file_size) iprint(1, self.flags, 'Flags') iprint(1, self.bone_count) iprint(1, self.texture_count) iprint(1, self.body_part_count, 'Body part count') pass def __repr__(self): return pformat(self.__dict__)
def __init__(self): self.baseHeaderOffset = 0 self.nameOffset = 0 self.activityNameOffset = 0 # int flags; // looping/non-looping flags self.flags = 0 # int activity; // initialized at loadtime to game DLL values self.activity = 0 # int actweight; self.activityWeight = 0 # int numevents; self.eventCount = 0 # int eventindex; # inline mstudioevent_t *pEvent( int i ) const { Assert( i >= 0 && i < numevents); return (mstudioevent_t *)(((byte *)this) + eventindex) + i; }; self.eventOffset = 0 # Vector bbmin; // per sequence bounding box self.bbMin = SourceVector() # Vector bbmax; self.bbMax = SourceVector() # int numblends; self.blendCount = 0 # // Index into array of shorts which is groupsize[0] x groupsize[1] in length # int animindexindex; self.animIndexOffset = 0 # int movementindex; // [blend] float array for blended movement self.movementIndex = 0 # int groupsize[2]; self.groupSize = [] # int paramindex[2]; // X, Y, Z, XR, YR, ZR self.paramIndex = [] # float paramstart[2]; // local (0..1) starting value self.paramStart = [] # float paramend[2]; // local (0..1) ending value self.paramEnd = [] # int paramparent; self.paramParent = 0 # float fadeintime; // ideal cross fate in time (0.2 default) self.fadeInTime = 0.0 # float fadeouttime; // ideal cross fade out time (0.2 default) self.fadeOutTime = 0.0 # int localentrynode; // transition node at entry self.localEntryNodeIndex = 0 # int localexitnode; // transition node at exit self.localExitNodeIndex = 0 # int nodeflags; // transition rules self.nodeFlags = 0 # float entryphase; // used to match entry gait self.entryPhase = 0.0 # float exitphase; // used to match exit gait self.exitPhase = 0.0 # float lastframe; // frame that should generation EndOfSequence self.lastFrame = 0.0 # int nextseq; // auto advancing sequences self.nextSeq = 0 # int pose; // index of delta animation between end and nextseq self.pose = 0 # int numikrules; self.ikRuleCount = 0 # int numautolayers; // self.autoLayerCount = 0 # int autolayerindex; # inline mstudioautolayer_t *pAutolayer( int i ) const { Assert( i >= 0 && i < numautolayers); return (mstudioautolayer_t *)(((byte *)this) + autolayerindex) + i; }; self.autoLayerOffset = 0 # int weightlistindex; self.weightOffset = 0 # inline float *pBoneweight( int i ) const { return ((float *)(((byte *)this) + weightlistindex) + i); }; # // FIXME: make this 2D instead of 2x1D arrays # int posekeyindex; self.poseKeyOffset = 0 # float *pPoseKey( int iParam, int iAnim ) const { return (float *)(((byte *)this) + posekeyindex) + iParam * groupsize[0] + iAnim; } # int numiklocks; self.ikLockCount = 0 # int iklockindex; # inline mstudioiklock_t *pIKLock( int i ) const { Assert( i >= 0 && i < numiklocks); return (mstudioiklock_t *)(((byte *)this) + iklockindex) + i; }; self.ikLockOffset = 0 # // Key values # int keyvalueindex; self.keyValueOffset = 0 # int keyvaluesize; # inline const char * KeyValueText( void ) const { return keyvaluesize != 0 ? ((char *)this) + keyvalueindex : NULL; } self.keyValueSize = 0 # int cycleposeindex; // index of pose parameter to use as cycle index self.cyclePoseIndex = 0 # int unused[7]; // remove/add as appropriate (grow back to 8 ints on version change!) #====== #FROM: VERSION 49 # int activitymodifierindex; # int numactivitymodifiers; # inline mstudioactivitymodifier_t *pActivityModifier( int i ) const { Assert( i >= 0 && i < numactivitymodifiers); return activitymodifierindex != 0 ? (mstudioactivitymodifier_t *)(((byte *)this) + activitymodifierindex) + i : NULL; }; # int unused[5]; // remove/add as appropriate (grow back to 8 ints on version change!) self.activityModifierOffset = 0 self.activityModifierCount = 0 self.unused = [] self.theName = "" self.theActivityName = "" self.thePoseKeys = [] self.theEvents = [] self.theAutoLayers = [] self.theIkLocks = [] #NOTE: In the file, a bone weight is a 32-bit float, i.e. a Single, but is stored as Double for better writing to file. self.theBoneWeights = [] self.theWeightListIndex = 0 self.theAnimDescIndexes = [] self.theKeyValues = "" self.theActivityModifiers = [] self.theBoneWeightsAreDefault = []
def __init__(self): self.theAnimPosition = SourceVector48bits() self.theAnimRotation = SourceQuaternion48bits() self.theFullAnimPosition = SourceVector() self.theFullAnimUnknown01 = 0 self.theFullAnimUnknown02 = SourceQuaternion64bits()