def write_mdl(self, stream: TokenStream, name, version=None): interpolation_type = self.interpolation_type frames = self.frames values = self.values in_tans = self.in_tans out_tans = self.out_tans tracks_count = len(frames) stream.start_block(name, len(self.frames)) token = '' if self.interpolation_type == 0: token = 'DontInterp' elif self.interpolation_type == 1: token = 'Linear' elif self.interpolation_type == 2: token = 'Hermite' elif self.interpolation_type == 3: token = 'Bezier' stream.write_flag(token) if self.global_sequence_id != -1: stream.write_number_attrib('GlobalSeqId', self.global_sequence_id) for i in range(tracks_count): self.write_mdl_value(stream, f'{frames[i]}:', values[i]) if interpolation_type > 1: stream.indent() self.write_mdl_value(stream, 'InTan', in_tans[i]) self.write_mdl_value(stream, 'OutTan', out_tans[i]) stream.unindent() stream.end_block()
def write_mdl(self, stream: TokenStream, version=None): stream.start_object_block('ParticleEmitterPopcorn', self.name) self.write_generic_header(stream) if self.flags == 0x10000: stream.write_flag('SortPrimsFarZ') if self.flags == 0x8000: stream.write_flag('Unshaded') if self.flags == 0x40000: stream.write_flag('Unfogged') if not self.write_animation(stream, 'KPPL'): stream.write_number_attrib('static LifeSpan', self.life_span) if not self.write_animation(stream, 'KPPE'): stream.write_number_attrib('static EmissionRate', self.emission_rate) if not self.write_animation(stream, 'KPPS'): stream.write_number_attrib('static Speed', self.speed) if not self.write_animation(stream, 'KPPC'): stream.write_vector_attrib('static Color', self.color) if not self.write_animation(stream, 'KPPA'): stream.write_number_attrib('static Alpha', self.alpha) self.write_animation(stream, 'KPPV') if self.replaceable_id != 0: stream.write_number_attrib('ReplaceableId', self.replaceable_id) if len(self.path): stream.write_string_attrib('Path', self.path) if len(self.animation_visibility_guide): stream.write_string_attrib('AnimVisibilityGuide', self.animation_visibility_guide) self.write_generic_animations(stream) stream.end_block()
def write_mdl(self, stream: TokenStream, version=None): stream.start_object_block('CollisionShape', self.name) self.write_generic_header(stream) _type = '' vertices = 2 bounds_radius = False if self.type == 0: _type = 'Box' elif self.type == 1: _type = 'Plane' elif self.type == 2: _type = 'Sphere' vertices = 1 bounds_radius = True elif self.type == 3: _type = 'Cylinder' bounds_radius = True stream.write_flag(_type) stream.start_block('Vertices', vertices) stream.write_vector(self.vertices[0]) if vertices == 2: stream.write_vector(self.vertices[1]) stream.end_block() if bounds_radius: stream.write_number_attrib('BoundsRadius', self.bounds_radius) self.write_generic_animations(stream) stream.end_block()
def write_mdl(self, stream: TokenStream, version=None): stream.start_object_block('Light', self.name) self.write_generic_header(stream) if self.type == 0: stream.write_flag('Omnidirectional') elif self.type == 1: stream.write_flag('Directional') elif self.type == 2: stream.write_flag('Ambient') if not self.write_animation(stream, 'KLAS'): stream.write_number_attrib('static AttenuationStart', self.attenuation[0]) if not self.write_animation(stream, 'KLAE'): stream.write_number_attrib('static AttenuationEnd', self.attenuation[1]) if not self.write_animation(stream, 'KLAI'): stream.write_number_attrib('static Intensity', self.intensity) if not self.write_animation(stream, 'KLAC'): stream.write_color('static Color', self.color) if not self.write_animation(stream, 'KLBI'): stream.write_number_attrib('static AmbIntensity', self.ambient_intensity) if not self.write_animation(stream, 'KLBC'): stream.write_color('static AmbColor', self.ambient_color) self.write_animation(stream, 'KLAV') self.write_generic_animations(stream) stream.end_block()
def write_mdl(self, stream: TokenStream, version=None): stream.start_object_block('ParticleEmitter', self.name) self.write_generic_header(stream) if self.flags == 0x8000: stream.write_flag('EmitterUsesMDL') if self.flags == 0x10000: stream.write_flag('EmitterUsesTGA') if not self.write_animation(stream, 'KPEE'): stream.write_number_attrib('static EmissionRate', self.emission_rate) if not self.write_animation(stream, 'KPEG'): stream.write_number_attrib('static Gravity', self.gravity) if not self.write_animation(stream, 'KPLN'): stream.write_number_attrib('static Longitude', self.longitude) if not self.write_animation(stream, 'KPLT'): stream.write_number_attrib('static Latitude', self.latitude) self.write_animation(stream, 'KPEV') stream.start_block('Particle', None) if not self.write_animation(stream, 'KPEL'): stream.write_number_attrib('static LifeSpan', self.life_span) if not self.write_animation(stream, 'KPES'): stream.write_number_attrib('static InitVelocity', self.speed) if (self.flags == 0x8000) or (self.flags == 0x10000): stream.write_string_attrib('Path', self.path) stream.end_block() self.write_generic_animations(stream) stream.end_block()
def save_bind_pose_block(self, stream: TokenStream): if len(self.bind_pose): stream.start_block('BindPose', None) stream.start_block('Matrices', len(self.bind_pose)) for matrix in self.bind_pose: stream.write_vector(matrix) stream.end_block() stream.end_block()
def write_mdl(self, stream: TokenStream, version=None): stream.start_object_block('Attachment', self.name) self.write_generic_header(stream) stream.write_number_attrib('AttachmentID', self.attachment_id) if len(self.path): stream.write_string_attrib('Path', self.path) self.write_animation(stream, 'KATV') self.write_generic_animations(stream) stream.end_block()
def write_mdl(self, stream: TokenStream, version=None): stream.start_block('Bitmap', None) if len(self.path): stream.write_string_attrib('Image', self.path) if self.replaceable_id != 0: stream.write_number_attrib('ReplaceableId', self.replaceable_id) if self.flags & 0x1: stream.write_flag('WrapWidth') if self.flags & 0x2: stream.write_flag('WrapHeight') stream.end_block()
def write_mdl(self, stream: TokenStream, version=None): stream.start_object_block('Anim', self.name) stream.write_vector_attrib('Interval', self.interval) if self.flags == 1: stream.write_flag('NonLooping') if self.move_speed != 0: stream.write_number_attrib('MoveSpeed', self.move_speed) if self.rarity != 0: stream.write_number_attrib('Rarity', self.rarity) self.extent.write_mdl(stream) stream.end_block()
def write_mdl(self, stream: TokenStream, version=None): stream.start_object_block('EventObject', self.name) self.write_generic_header(stream) stream.start_block('EventTrack', len(self.tracks)) if self.global_sequence_id != -1: stream.write_number_attrib('GlobalSeqId', self.global_sequence_id) for track in self.tracks: stream.write_flag(f'{track}') stream.end_block() self.write_generic_animations(stream) stream.end_block()
def write_mdl(self, stream: TokenStream, version=None): stream.start_object_block('Camera', self.name) stream.write_vector_attrib('Position', self.position) self.write_animation(stream, 'KCTR') self.write_animation(stream, 'KCRL') stream.write_number_attrib('FieldOfView', self.field_of_view) stream.write_number_attrib('FarClip', self.far_clipping_plane) stream.write_number_attrib('NearClip', self.near_clipping_plane) stream.start_block('Target', None) stream.write_vector_attrib('Position', self.target_position) self.write_animation(stream, 'KTTR') stream.end_block() stream.end_block()
def write_mdl(self, stream: TokenStream, version=None): stream.start_block('GeosetAnim', None) if self.flags & 0x1: stream.write_flag('DropShadow') if not self.write_animation(stream, 'KGAO'): stream.write_number_attrib('static Alpha', self.alpha) if self.flags & 0x2: if not self.write_animation(stream, 'KGAC') and ( self.color[0] != 1 or self.color[1] != 1 or self.color[2] != 1): stream.write_color('static Color ', self.color) stream.write_number_attrib('GeosetId', self.geoset_id) stream.end_block()
def write_mdl(self, stream: TokenStream, version=None): stream.start_object_block('Bone', self.name) self.write_generic_header(stream) if self.geoset_id == -1: stream.write_flag_attrib('GeosetId', 'Multiple') else: stream.write_number_attrib('GeosetId', self.geoset_id) if self.geoset_animation_id == -1: stream.write_flag_attrib('GeosetAnimId', 'None') else: stream.write_number_attrib('GeosetAnimId', self.geoset_animation_id) self.write_generic_animations(stream) stream.end_block()
def write_mdl(self, stream: TokenStream, version=None): stream.start_block('Geoset', None) stream.write_vector_array_block('Vertices', self.vertices, 3) stream.write_vector_array_block('Normals', self.normals, 3) for uv_set in self.uv_sets: stream.write_vector_array_block('TVertices', uv_set, 2) if version > 800 or len(self.tangents): stream.write_vector_array_block('Tangents', self.tangents, 4) if version > 800 or len(self.skin): stream.start_block('SkinWeights', len(self.skin) // 8) for i in range(0, len(self.skin), 8): stream.write_line( f'{", ".join([str(a) for a in self.skin[i:i + 8]])+","}') else: stream.start_block('VertexGroup', None) for i in range(len(self.vertex_groups)): stream.write_line(f'{self.vertex_groups[i]},') stream.end_block() stream.start_block('Faces', [str(1), str(len(self.faces))]) stream.start_block('Triangles', None) stream.write_vector(self.faces) stream.end_block() stream.end_block() stream.start_block( 'Groups', [str(len(self.matrix_groups)), str(len(self.matrix_indices))]) index = 0 for group_size in self.matrix_groups: stream.write_vector_attrib( 'Matrices', self.matrix_indices[index:index + group_size]) index += group_size stream.end_block() self.extent.write_mdl(stream) for sequence_extent in self.sequence_extents: stream.start_block('Anim', None) sequence_extent.write_mdl(stream) stream.end_block() stream.write_number_attrib('MaterialID', self.material_id) stream.write_number_attrib('SelectionGroup', self.selection_group) if self.selection_flags == 4: stream.write_flag('Unselectable') if version > 800: stream.write_number_attrib('LevelOfDetail', self.lod) if len(self.lod_name): stream.write_string_attrib('Name', self.lod_name) stream.end_block()
def write_mdl(self, stream: TokenStream, version=None): stream.start_block('Layer', None) # headers ?? stream.write_flag_attrib('FilterMode', filter_mode_to_mdl(self.filter_mode)) if self.flags & 0x1: stream.write_flag('Unshaded') if self.flags & 0x2: stream.write_flag('SphereEnvMap') if self.flags & 0x10: stream.write_flag('TwoSided') if self.flags & 0x20: stream.write_flag('Unfogged') if self.flags & 0x40: stream.write_flag('NoDepthTest') if self.flags & 0x80: stream.write_flag('NoDepthSet') if version > 800: if self.flags & 0x100: stream.write_flag('Unlit') if not self.write_animation(stream, 'KMTF'): stream.write_number_attrib('static TextureID', self.texture_id) if self.texture_animation_id != -1: stream.write_number_attrib('TVertexAnimId', self.texture_animation_id) if self.coord_id != 0: stream.write_number_attrib('CoordId', self.coord_id) if not self.write_animation(stream, 'KMTA') and self.alpha != 1: stream.write_number_attrib('static Alpha', self.alpha) if version > 800: if not self.write_animation(stream, 'KMTE') and self.emissive_gain != 1: stream.write_number_attrib('static EmissiveGain', self.emissive_gain) if not self.write_animation(stream, 'KFC3') and ( self.fresnel_color[0] != 1 or self.fresnel_color[1] != 1 or self.fresnel_color[2] != 1): stream.write_vector_attrib('static FresnelColor', self.fresnel_color) if not self.write_animation(stream, 'KFCA') and self.fresnel_opacity != 0: stream.write_number_attrib('static FresnelOpacity', self.fresnel_opacity) if not self.write_animation( stream, 'KFTC') and self.fresnel_team_color != 0: stream.write_number_attrib('static FresnelTeamColor', self.fresnel_team_color) stream.end_block()
def write_mdl(self, stream: TokenStream, version=None): stream.start_block('Material', None) if self.flags & 0x1: stream.write_flag('ConstantColor') if version > 800: if self.flags & 0x2: stream.write_flag('TwoSided') if self.flags & 0x8: stream.write_flag('SortPrimsNearZ') if self.flags & 0x10: stream.write_flag('SortPrimsFarZ') if self.flags & 0x20: stream.write_flag('FullResolution') if self.priority_plane != 0: stream.write_number_attrib('PriorityPlane', self.priority_plane) if version > 800: stream.write_string_attrib('Shader', self.shader) for layer in self.layers: layer.write_mdl(stream, version=version) stream.end_block()
def save_model_block(self, stream: TokenStream): stream.start_object_block('Model', self.name) self.mdl_num_of_chunk = [ len(self.geosets), len(self.geoset_animations), len(self.helpers), len(self.lights), len(self.bones), len(self.attachments), len(self.particle_emitters), len(self.particle_emitters2), len(self.particle_emitters_popcorn), len(self.ribbon_emitters), len(self.event_objects), len(self.face_effects) ] stream.write_number_attrib('NumGeosets', self.mdl_num_of_chunk[0]) stream.write_number_attrib('NumGeosetAnims', self.mdl_num_of_chunk[1]) stream.write_number_attrib('NumHelpers', self.mdl_num_of_chunk[2]) stream.write_number_attrib('NumLights', self.mdl_num_of_chunk[3]) stream.write_number_attrib('NumBones', self.mdl_num_of_chunk[4]) stream.write_number_attrib('NumAttachments', self.mdl_num_of_chunk[5]) stream.write_number_attrib('NumParticleEmitters', self.mdl_num_of_chunk[6]) stream.write_number_attrib('NumParticleEmitters2', self.mdl_num_of_chunk[7]) if self.version > 800: stream.write_number_attrib('NumParticleEmittersPopcorn', self.mdl_num_of_chunk[8]) stream.write_number_attrib('NumRibbonEmitters', self.mdl_num_of_chunk[9]) stream.write_number_attrib('NumEvents', self.mdl_num_of_chunk[10]) if self.version > 800: stream.write_number_attrib('NumFaceFX', self.mdl_num_of_chunk[11]) stream.write_number_attrib('BlendTime', self.blend_time) self.extent.write_mdl(stream) if len(self.animation_file): stream.write_string_attrib('AnimationFile', self.animation_file) stream.end_block()
def write_mdl(self, stream: TokenStream, version=None): stream.start_object_block('RibbonEmitter', self.name) self.write_generic_header(stream) if not self.write_animation(stream, 'KRHA'): stream.write_number_attrib('static HeightAbove', self.height_above) if not self.write_animation(stream, 'KRHB'): stream.write_number_attrib('static HeightBelow', self.height_below) if not self.write_animation(stream, 'KRAL'): stream.write_number_attrib('static Alpha', self.alpha) if not self.write_animation(stream, 'KRCO'): stream.write_color('static Color', self.color) if not self.write_animation(stream, 'KRTX'): stream.write_number_attrib('static TextureSlot', self.texture_slot) self.write_animation(stream, 'KRVS') stream.write_number_attrib('EmissionRate', self.emission_rate) stream.write_number_attrib('LifeSpan', self.lifespan) if self.gravity != 0: stream.write_number_attrib('Gravity', self.gravity) stream.write_number_attrib('Rows', self.rows) stream.write_number_attrib('Columns', self.columns) stream.write_number_attrib('MaterialID', self.material_id) self.write_generic_animations(stream) stream.end_block()
def write_mdl(self, stream: TokenStream, version=None): stream.start_object_block('Helper', self.name) self.write_generic_header(stream) self.write_generic_animations(stream) stream.end_block()
def write_mdl(self, stream: TokenStream, version=None): stream.start_object_block('FaceFX', self.type) stream.write_string_attrib('Path', self.path) stream.end_block()
def write_mdl(self, stream: TokenStream, version=None): stream.start_object_block('ParticleEmitter2', self.name) self.write_generic_header(stream) if self.flags == 0x10000: stream.write_flag('SortPrimsFarZ') if self.flags == 0x8000: stream.write_flag('Unshaded') if self.flags == 0x20000: stream.write_flag('LineEmitter') if self.flags == 0x40000: stream.write_flag('Unfogged') if self.flags == 0x80000: stream.write_flag('ModelSpace') if self.flags == 0x100000: stream.write_flag('XYQuad') if not self.write_animation(stream, 'KP2S'): stream.write_number_attrib('static Speed', self.speed) if not self.write_animation(stream, 'KP2R'): stream.write_number_attrib('static Variation', self.variation) if not self.write_animation(stream, 'KP2L'): stream.write_number_attrib('static Latitude', self.latitude) if not self.write_animation(stream, 'KP2G'): stream.write_number_attrib('static Gravity', self.gravity) self.write_animation(stream, 'KP2V') if self.squirt: stream.write_flag('Squirt') stream.write_number_attrib('LifeSpan', self.life_span) if not self.write_animation(stream, 'KP2E'): stream.write_number_attrib('static EmissionRate', self.emission_rate) if not self.write_animation(stream, 'KP2N'): stream.write_number_attrib('static Width', self.width) if not self.write_animation(stream, 'KP2W'): stream.write_number_attrib('static Length', self.length) if self.filter_mode == 0: stream.write_flag('Blend') elif self.filter_mode == 1: stream.write_flag('Additive') elif self.filter_mode == 2: stream.write_flag('Modulate') elif self.filter_mode == 3: stream.write_flag('Modulate2x') elif self.filter_mode == 4: stream.write_flag('AlphaKey') stream.write_number_attrib('Rows', self.rows) stream.write_number_attrib('Columns', self.columns) if self.head_or_tail == 0: stream.write_flag('Head') elif self.head_or_tail == 1: stream.write_flag('Tail') elif self.head_or_tail == 2: stream.write_flag('Both') stream.write_number_attrib('TailLength', self.tail_length) stream.write_number_attrib('Time', self.time_middle) stream.start_block('SegmentColor', None) stream.write_color('Color', self.segment_colors[0]) stream.write_color('Color', self.segment_colors[1]) stream.write_color('Color', self.segment_colors[2]) stream.end_block_comma() stream.write_vector_attrib('Alpha', self.segment_alphas) stream.write_vector_attrib('ParticleScaling', self.segment_scaling) stream.write_vector_attrib('LifeSpanUVAnim', self.head_intervals[0]) stream.write_vector_attrib('DecayUVAnim', self.head_intervals[1]) stream.write_vector_attrib('TailUVAnim', self.tail_intervals[0]) stream.write_vector_attrib('TailDecayUVAnim', self.tail_intervals[1]) stream.write_number_attrib('TextureID', self.texture_id) if self.replaceable_id != 0: stream.write_number_attrib('ReplaceableId', self.replaceable_id) if self.priority_plane != 0: stream.write_number_attrib('PriorityPlane', self.priority_plane) self.write_generic_animations(stream) stream.end_block()
def save_version_block(self, stream: TokenStream): stream.start_block('Version', None) stream.write_number_attrib('FormatVersion', self.version) stream.end_block()
def save_static_objects_block(self, stream: TokenStream, name, objects): if len(objects): stream.start_block(name, len(objects)) for obj in objects: obj.write_mdl(stream, version=self.version) stream.end_block()
def save_global_sequence_block(self, stream: TokenStream): if len(self.global_sequences): stream.start_block('GlobalSequences', len(self.global_sequences)) for global_sequence in self.global_sequences: stream.write_number_attrib('Duration', global_sequence) stream.end_block()
def save_pivot_point_block(self, stream: TokenStream): if len(self.pivot_points): stream.start_block('PivotPoints', len(self.pivot_points)) for pivot_point in self.pivot_points: stream.write_vector(pivot_point) stream.end_block()
def write_mdl(self, stream: TokenStream, version=None): stream.start_block('TVertexAnim', None) self.write_animation(stream, 'KTAT') self.write_animation(stream, 'KTAR') self.write_animation(stream, 'KTAS') stream.end_block()