def read_generic_block(self, stream: TokenStream): self.name = stream.read() for token in self.read_animated_block(stream): if token == 'ObjectId': self.object_id = stream.read_int() elif token == 'Parent': self.parent_id = stream.read_int() elif token == 'BillboardedLockZ': self.flags |= 0x40 elif token == 'BillboardedLockY': self.flags |= 0x20 elif token == 'BillboardedLockX': self.flags |= 0x10 elif token == 'Billboarded': self.flags |= 0x8 elif token == 'CameraAnchored': self.flags |= 0x80 elif token == 'DontInherit': for token in stream.read_block(): if token == 'Rotation': self.flags |= 0x2 elif token == 'Translation': self.flags |= 0x1 elif token == 'Scaling': self.flags |= 0x4 elif token == 'Translation': self.read_animation(stream, 'KGTR') elif token == 'Rotation': self.read_animation(stream, 'KGRT') elif token == 'Scaling': self.read_animation(stream, 'KGSC') else: yield token
def read_mdl(self, stream: TokenStream, version=None): self.type = stream.read() for token in stream.read_block(): if token == 'Path': self.path = stream.read() else: raise TokenStreamError('FaceEffect', token)
def load_global_sequence_block(self, stream: TokenStream): stream.read() for token in stream.read_block(): if token == 'Duration': self.global_sequences.append(stream.read_int()) else: raise TokenStreamError('GlobalSequences', token)
def load_numbered_object_block(self, out, class_name, name, stream: TokenStream): stream.read() for token in stream.read_block(): if token == name: obj = class_name() obj.read_mdl(stream) out.append(obj) else: raise TokenStreamError(name, token)
def read_mdl(self, stream: TokenStream): for token in super().read_generic_block(stream): if token == 'AttachmentID': self.attachment_id = stream.read_int() elif token == 'Path': self.path = stream.read() elif token == 'Visibility': self.read_animation(stream, 'KATV') else: raise TokenStreamError('Attachment', token, want_name=self.name)
def read_mdl(self, stream: TokenStream): for token in stream.read_block(): if token == 'Image': self.path = stream.read() elif token == 'ReplaceableId': self.replaceable_id = stream.read_int() elif token == 'WrapWidth': self.flags |= 0x1 elif token == 'WrapHeight': self.flags |= 0x2 else: raise TokenStreamError('Texture', token)
def read_mdl(self, stream: TokenStream): for token in super().read_generic_block(stream): if token == 'EventTrack': count = stream.read_int() stream.read() if stream.peek() == 'GlobalSeqId': stream.read() self.global_sequence_id = stream.read_int() for i in range(count): self.tracks.append(stream.read_int()) stream.read() else: raise TokenStreamError('EventObject', token)
def read_mdl(self, stream: TokenStream): self.name = stream.read() for token in stream.read_block(): if token == 'Position': self.position = stream.read_vector(3) elif token == 'Translation': self.read_animation(stream, 'KCTR') elif token == 'Rotation': self.read_animation(stream, 'KCRL') elif token == 'FieldOfView': self.field_of_view = stream.read_float() elif token == 'FarClip': self.far_clipping_plane = stream.read_float() elif token == 'NearClip': self.near_clipping_plane = stream.read_float() elif token == 'Target': for token in stream.read_block(): if token == 'Position': self.target_position = stream.read_vector(3) elif token == 'Translation': self.read_animation(stream, 'KTTR') else: raise TokenStreamError('Camera', token, want_name=self.name, want_target=1) else: raise TokenStreamError('Camera', token, want_name=self.name)
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 load(self): if isinstance(self.buffer, str): self.stream = TokenStream(buffer=self.buffer) self.load_mdl(self.stream) elif isinstance(self.buffer, (bytearray, bytes)): self.stream = BinaryStream(self.buffer) self.load_mdx()
def read_mdl(self, stream: TokenStream): for token in super().read_generic_block(stream): if token == 'GeosetId': token = stream.read() if token == 'Multiple': self.geoset_id = -1 else: self.geoset_id = int(token) elif token == 'GeosetAnimId': token = stream.read() if token == 'None': self.geoset_animation_id = -1 else: self.geoset_animation_id = int(token) else: raise TokenStreamError('Bone', token, want_name=self.name)
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 read_mdl(self, stream: TokenStream, version=None): for token in super().read_animated_block(stream): if token == 'DropShadow': self.flags |= 0x1 elif token == 'static Alpha': self.alpha = stream.read_float() elif token == 'Alpha': self.read_animation(stream, 'KGAO') elif token == 'static Color': self.flags |= 0x2 self.color = stream.read_color() elif token == 'Color': self.flags |= 0x2 self.read_animation(stream, 'KGAC') elif token == 'GeosetId': self.geoset_id = stream.read_int() else: raise TokenStreamError('GeosetAnimation', token)
def read_mdl(self, stream: TokenStream): for token in super().read_animated_block(stream): if token == 'FilterMode': self.filter_mode = filter_mode_to_mdx(stream.read()) elif token == 'Unshaded': self.flags |= 0x1 elif token == 'SphereEnvMap': self.flags |= 0x2 elif token == 'TwoSided': self.flags |= 0x10 elif token == 'Unfogged': self.flags |= 0x20 elif token == 'NoDepthTest': self.flags |= 0x40 elif token == 'NoDepthSet': self.flags |= 0x80 elif token == 'Unlit': self.flags |= 0x100 elif token == 'static TextureID': self.texture_id = stream.read_int() elif token == 'TextureID': self.read_animation(stream, 'KMTF') elif token == 'TVertexAnimId': self.texture_animation_id = stream.read_int() elif token == 'CoordId': self.coord_id = stream.read_int() elif token == 'static Alpha': self.alpha = stream.read_float() elif token == 'Alpha': self.read_animation(stream, 'KMTA') elif token == 'static EmissiveGain': self.emissive_gain = stream.read_float() elif token == 'EmissiveGain': self.read_animation(stream, 'KMTE') elif token == 'static FresnelColor': self.fresnel_color = stream.read_vector(3) elif token == 'FresnelColor': self.read_animation(stream, 'KFC3') elif token == 'static FresnelOpacity': self.fresnel_opacity = stream.read_float() elif token == 'FresnelOpacity': self.read_animation(stream, 'KFCA') elif token == 'static FresnelTeamColor': self.fresnel_team_color = stream.read_float() elif token == 'FresnelTeamColor': self.read_animation(stream, 'KFTC') else: raise TokenStreamError('Layer', token)
def read_mdl(self, stream: TokenStream): for token in stream.read_block(): if token == 'Translation': self.read_animation(stream, 'KTAT') elif token == 'Rotation': self.read_animation(stream, 'KTAR') elif token == 'Scaling': self.read_animation(stream, 'KTAS') else: raise TokenStreamError('TextureAnimation', token)
def load_model_block(self, stream: TokenStream): self.name = stream.read() for token in stream.read_block(): if token.startswith('Num'): stream.read() elif token == 'BlendTime': self.blend_time = stream.read_int() elif token == 'MinimumExtent': self.extent.min = stream.read_vector(3) elif token == 'MaximumExtent': self.extent.max = stream.read_vector(3) elif token == 'BoundsRadius': self.extent.bounds_radius = stream.read_float() elif token == 'AnimationFile': self.animation_file = stream.read() else: raise TokenStreamError('Model', token)
def load_bind_pose_block(self, stream: TokenStream): for token in stream.read_block(): if token == 'Matrices': matrices = stream.read_int() stream.read() for i in range(matrices): self.bind_pose.append(stream.read_vector(12)) stream.read() else: raise TokenStreamError('BindPose', token)
def write_mdl(self, stream: TokenStream, version=None): if self.min[0] != 0 or self.min[1] != 0 or self.min[2] != 0: stream.write_vector_attrib('MinimumExtent', self.min) if self.max[0] != 0 or self.max[1] != 0 or self.max[2] != 0: stream.write_vector_attrib('MaximumExtent', self.max) if self.bounds_radius != 0: stream.write_number_attrib('BoundsRadius', self.bounds_radius)
def read_mdl(self, stream: TokenStream, version=None): for token in stream.read_block(): if token == 'ConstantColor': self.flags |= 0x1 elif token == 'TwoSided': self.flags |= 0x2 elif token == 'SortPrimsNearZ': self.flags |= 0x8 elif token == 'SortPrimsFarZ': self.flags |= 0x10 elif token == 'FullResolution': self.flags |= 0x20 elif token == 'PriorityPlane': self.priority_plane = stream.read_int() elif token == 'Shader': self.shader = stream.read() elif token == 'Layer': layer = Layer() layer.read_mdl(stream) self.layers.append(layer) else: raise TokenStreamError('Material', token)
def read_mdl(self, stream: TokenStream): self.name = stream.read() for token in stream.read_block(): if token == 'Interval': self.interval = stream.read_vector(2) elif token == 'NonLooping': self.flags = 1 elif token == 'MoveSpeed': self.move_speed = stream.read_float() elif token == 'Rarity': self.rarity = stream.read_float() elif token == 'MinimumExtent': self.extent.min = stream.read_vector(3) elif token == 'MaximumExtent': self.extent.max = stream.read_vector(3) elif token == 'BoundsRadius': self.extent.bounds_radius = stream.read_float() else: raise TokenStreamError('Sequence', token)
def read_mdl(self, stream: TokenStream): for token in super().read_generic_block(stream): if token == 'Box': self.type = 0 elif token == 'Plane': self.type = 1 elif token == 'Sphere': self.type = 2 elif token == 'Cylinder': self.type = 3 elif token == 'Vertices': count = stream.read_int() stream.read() self.vertices[0] = stream.read_vector(3) if count == 2: self.vertices[1] = stream.read_vector(3) stream.read() elif token == 'BoundsRadius': self.bounds_radius = stream.read_float() else: raise TokenStreamError('CollisionShape', token)
def read_mdl(self, stream: TokenStream): for token in super().read_generic_block(stream): if token == 'SortPrimsFarZ': self.flags = 0x10000 elif token == 'Unshaded': self.flags = 0x8000 elif token == 'Unfogged': self.flags = 0x40000 elif token == 'static LifeSpan': self.life_span = stream.read_float() elif token == 'LifeSpan': self.read_animation(stream, 'KPPL') elif token == 'static EmissionRate': self.emission_rate = stream.read_float() elif token == 'EmissionRate': self.read_animation(stream, 'KPPE') elif token == 'static Speed': self.speed = stream.read_float() elif token == 'Speed': self.read_animation(stream, 'KPPS') elif token == 'static Color': self.color = stream.read_vector(3) elif token == 'Color': self.read_animation(stream, 'KPPC') elif token == 'static Alpha': self.alpha = stream.read_float() elif token == 'Alpha': self.read_animation(stream, 'KPPA') elif token == 'Visibility': self.read_animation(stream, 'KPPV') elif token == 'ReplaceableId': self.replaceable_id = stream.read_int() elif token == 'Path': self.path = stream.read() elif token == 'AnimVisibilityGuide': self.animation_visibility_guide = stream.read() else: raise TokenStreamError('ParticleEmitterPopcorn', token)
def read_mdl(self, stream: TokenStream, version=None): for token in super().read_generic_block(stream): if token == 'EmitterUsesMDL': self.flags = 0x8000 elif token == 'EmitterUsesTGA': self.flags = 0x10000 elif token == 'static EmissionRate': self.emission_rate = stream.read_float() elif token == 'EmissionRate': self.read_animation(stream, 'KPEE') elif token == 'static Gravity': self.gravity = stream.read_float() elif token == 'Gravity': self.read_animation(stream, 'KPEG') elif token == 'static Longitude': self.longitude = stream.read_float() elif token == 'Longitude': self.read_animation(stream, 'KPLN') elif token == 'static Latitude': self.latitude = stream.read_float() elif token == 'Latitude': self.read_animation(stream, 'KPLT') elif token == 'Visibility': self.read_animation(stream, 'KPEV') elif token == 'Particle': for token in self.read_animated_block(stream): if token == 'static LifeSpan': self.life_span = stream.read_float() elif token == 'LifeSpan': self.read_animation(stream, 'KPEL') elif token == 'static InitVelocity': self.speed = stream.read_float() elif token == 'InitVelocity': self.read_animation(stream, 'KPES') elif token == 'Path': self.path = stream.read() else: raise TokenStreamError('ParticleEmitter', token)
def save_mdl(self, comment=None): stream = TokenStream() tmp_file = open('tmp.data', 'a') stream.tmp_file = tmp_file if comment: # comment[-1:] += Model.get_current_date_with_time_format() stream.write_comment(comment) self.save_version_block(stream) self.save_model_block(stream) self.save_static_objects_block(stream, 'Sequences', self.sequences) self.save_global_sequence_block(stream) self.save_static_objects_block(stream, 'Textures', self.textures) self.save_static_objects_block(stream, 'Materials', self.materials) self.save_static_objects_block(stream, 'TextureAnims', self.texture_animations) self.save_objects(stream, self.geosets) self.save_objects(stream, self.geoset_animations) self.save_objects(stream, self.bones) self.save_objects(stream, self.lights) self.save_objects(stream, self.helpers) self.save_objects(stream, self.attachments) self.save_pivot_point_block(stream) self.save_objects(stream, self.particle_emitters) self.save_objects(stream, self.particle_emitters2) if self.version > 800: self.save_objects(stream, self.particle_emitters_popcorn) self.save_objects(stream, self.ribbon_emitters) self.save_objects(stream, self.cameras) self.save_objects(stream, self.event_objects) self.save_objects(stream, self.collision_shapes) if self.version > 800: self.save_objects(stream, self.face_effects) self.save_bind_pose_block(stream) stream.tmp_file.close() with open('tmp.data', 'r') as f: stream.buffer = f.read() os.remove('tmp.data') return stream.buffer
def read_mdl(self, stream: TokenStream): for token in super().read_generic_block(stream): if token == 'Omnidirectional': self.type = 0 elif token == 'Directional': self.type = 1 elif token == 'Ambient': self.type = 2 elif token == 'static AttenuationStart': self.attenuation[0] = stream.read_float() elif token == 'AttenuationStart': self.read_animation(stream, 'KLAS') elif token == 'static AttenuationEnd': self.attenuation[1] = stream.read_float() elif token == 'AttenuationEnd': self.read_animation(stream, 'KLAE') elif token == 'static Intensity': self.intensity = stream.read_float() elif token == 'Intensity': self.read_animation(stream, 'KLAI') elif token == 'static Color': self.color = stream.read_color() elif token == 'Color': self.read_animation(stream, 'KLAC') elif token == 'static AmbIntensity': self.ambient_intensity = stream.read_float() elif token == 'AmbIntensity': self.read_animation(stream, 'KLBI') elif token == 'static AmbColor': self.ambient_color = stream.read_color() elif token == 'AmbColor': self.read_animation(stream, 'KLBC') elif token == 'Visibility': self.read_animation(stream, 'KLAV') else: raise TokenStreamError('Light', token)
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('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('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 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('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()