def test_mod_bones_array(mods_from_arc): for mod in mods_from_arc: if mod.bone_count: assert len(mod.bones_array) == mod.bone_count assert get_offset(mod, 'bones_array') == mod.bones_array_offset else: assert mod.bones_array_offset == 0
def test_vertex_buffer(mods_from_arc): for mod in mods_from_arc: assert get_offset(mod, 'vertex_buffer') == mod.vertex_buffer_offset
def test_meshes_array_2(mods_from_arc): for mod in mods_from_arc: assert get_offset(mod, 'meshes_array_2') == get_offset(mod, 'meshes_array') + get_size(mod, 'meshes_array') assert get_offset(mod, 'vertex_buffer') == get_offset(mod, 'meshes_array_2') + get_size(mod, 'meshes_array_2')
def test_mod_textures_array_offset(mods_from_arc): for mod in mods_from_arc: if mod.texture_count or mod.material_count: assert mod.textures_array_offset > get_offset(mod, 'group_data_array') else: assert mod.textures_array_offset == 0
def test_mod_bones_array_offset(mods_from_arc): for mod in mods_from_arc: if mod.bone_count: assert mod.bones_array_offset >= get_offset(mod, 'unk_12') else: assert mod.bones_array_offset == 0
def export_mod156(parent_blender_object): '''The blender_object provided should have meshes as children''' try: saved_mod = Mod156( file_path=BytesIO(parent_blender_object.albam_imported_item.data)) except AttributeError: raise ExportError( "Can't export '{0}' to Mod156, the model to be exported " "wasn't imported using Albam".format(parent_blender_object.name)) children_objects = [child for child in parent_blender_object.children] empty_children = [c for c in children_objects if c.type == 'EMPTY'] meshes_children = [c for c in children_objects if c.type == 'MESH'] bounding_box = get_bounding_box_positions_from_blender_objects( children_objects) if len(meshes_children) < len(saved_mod.meshes_array) and empty_children: # There were failed meshes that were replaced as empties in the import # We need to remove the extra weight groups (or whaterver they are), # before exporting failed_indices = { i for i, obj in enumerate(parent_blender_object.children) if obj.type == 'EMPTY' } new_bytes = [] current_position = 0 for i, mesh in enumerate(saved_mod.meshes_array): size = 144 * mesh.vertex_group_count data = saved_mod.meshes_array_2[current_position:current_position + size] current_position = current_position + size if i in failed_indices: continue else: new_bytes.extend(data) # the misterious extra 4 bytes for mod.156 new_bytes.extend(saved_mod.meshes_array_2[-4:]) meshes_array_2 = (ctypes.c_ubyte * len(new_bytes))(*new_bytes) elif len(meshes_children) != len( saved_mod.meshes_array) and not empty_children: raise ExportError( "Can't import {0}, different meshes quantity ({1} vs {2}) " "Support for this will come soon".format( parent_blender_object.name, len(saved_mod.meshes_array), len(children_objects))) else: meshes_array_2 = saved_mod.meshes_array_2 textures_array, materials_array = _export_textures_and_materials( children_objects, saved_mod) meshes_array, vertex_buffer, index_buffer = _export_meshes( children_objects, bounding_box, saved_mod) bone_count = get_bone_count_from_blender_objects([parent_blender_object]) if not bone_count: bones_array_offset = 0 elif bone_count and saved_mod.unk_08: bones_array_offset = 176 + len(saved_mod.unk_12) else: bones_array_offset = 176 mod = Mod156( id_magic=b'MOD', version=156, version_rev=1, bone_count=bone_count, mesh_count=get_mesh_count_from_blender_objects(children_objects), material_count=len(materials_array), vertex_count=get_vertex_count_from_blender_objects(children_objects), face_count=(ctypes.sizeof(index_buffer) // 2) + 1, edge_count=0, # TODO: add edge_count vertex_buffer_size=ctypes.sizeof(vertex_buffer), vertex_buffer_2_size=len(saved_mod.vertex_buffer_2), texture_count=len(textures_array), group_count=saved_mod.group_count, bones_array_offset=bones_array_offset, group_data_array=saved_mod.group_data_array, bone_palette_count=saved_mod.bone_palette_count, sphere_x=saved_mod.sphere_x, sphere_y=saved_mod.sphere_y, sphere_z=saved_mod.sphere_z, sphere_w=saved_mod.sphere_w, box_min_x=saved_mod.box_min_x, box_min_y=saved_mod.box_min_y, box_min_z=saved_mod.box_min_z, box_min_w=saved_mod.box_min_w, box_max_x=saved_mod.box_max_x, box_max_y=saved_mod.box_max_y, box_max_z=saved_mod.box_max_z, box_max_w=saved_mod.box_max_w, unk_01=saved_mod.unk_01, unk_02=saved_mod.unk_02, unk_03=saved_mod.unk_03, unk_04=saved_mod.unk_04, unk_05=saved_mod.unk_05, unk_06=saved_mod.unk_06, unk_07=saved_mod.unk_07, unk_08=saved_mod.unk_08, unk_09=saved_mod.unk_09, unk_10=saved_mod.unk_10, unk_11=saved_mod.unk_11, unk_12=saved_mod.unk_12, bones_array=saved_mod.bones_array, bones_unk_matrix_array=saved_mod.bones_unk_matrix_array, bones_world_transform_matrix_array=saved_mod. bones_world_transform_matrix_array, unk_13=saved_mod.unk_13, bone_palette_array=saved_mod.bone_palette_array, textures_array=textures_array, materials_data_array=materials_array, meshes_array=meshes_array, meshes_array_2=meshes_array_2, vertex_buffer=vertex_buffer, vertex_buffer_2=saved_mod.vertex_buffer_2, index_buffer=index_buffer) mod.bones_array_offset = get_offset(mod, 'bones_array') if mod.bone_count else 0 mod.group_offset = get_offset(mod, 'group_data_array') mod.textures_array_offset = get_offset(mod, 'textures_array') mod.meshes_array_offset = get_offset(mod, 'meshes_array') mod.vertex_buffer_offset = get_offset(mod, 'vertex_buffer') mod.vertex_buffer_2_offset = get_offset(mod, 'vertex_buffer_2') mod.index_buffer_offset = get_offset(mod, 'index_buffer') return mod, get_textures_from_blender_objects(children_objects)
def export_mod156(parent_blender_object): '''The blender_object provided should have meshes as children''' try: saved_mod = Mod156(file_path=BytesIO(parent_blender_object.albam_imported_item.data)) except AttributeError: raise ExportError("Can't export '{0}' to Mod156, the model to be exported " "wasn't imported using Albam" .format(parent_blender_object.name)) children_objects = [child for child in parent_blender_object.children] empty_children = [c for c in children_objects if c.type == 'EMPTY'] meshes_children = [c for c in children_objects if c.type == 'MESH'] bounding_box = get_bounding_box_positions_from_blender_objects(children_objects) if len(meshes_children) < len(saved_mod.meshes_array) and empty_children: # There were failed meshes that were replaced as empties in the import # We need to remove the extra weight groups (or whaterver they are), # before exporting failed_indices = {i for i, obj in enumerate(parent_blender_object.children) if obj.type == 'EMPTY'} new_bytes = [] current_position = 0 for i, mesh in enumerate(saved_mod.meshes_array): size = 144 * mesh.vertex_group_count data = saved_mod.meshes_array_2[current_position:current_position + size] current_position = current_position + size if i in failed_indices: continue else: new_bytes.extend(data) # the misterious extra 4 bytes for mod.156 new_bytes.extend(saved_mod.meshes_array_2[-4:]) meshes_array_2 = (ctypes.c_ubyte * len(new_bytes))(*new_bytes) elif len(meshes_children) != len(saved_mod.meshes_array) and not empty_children: raise ExportError("Can't import {0}, different meshes quantity ({1} vs {2}) " "Support for this will come soon".format(parent_blender_object.name, len(saved_mod.meshes_array), len(children_objects))) else: meshes_array_2 = saved_mod.meshes_array_2 textures_array, materials_array = _export_textures_and_materials(children_objects, saved_mod) meshes_array, vertex_buffer, index_buffer = _export_meshes(children_objects, bounding_box, saved_mod) bone_count = get_bone_count_from_blender_objects([parent_blender_object]) if not bone_count: bones_array_offset = 0 elif bone_count and saved_mod.unk_08: bones_array_offset = 176 + len(saved_mod.unk_12) else: bones_array_offset = 176 mod = Mod156(id_magic=b'MOD', version=156, version_rev=1, bone_count=bone_count, mesh_count=get_mesh_count_from_blender_objects(children_objects), material_count=len(materials_array), vertex_count=get_vertex_count_from_blender_objects(children_objects), face_count=(ctypes.sizeof(index_buffer) // 2) + 1, edge_count=0, # TODO: add edge_count vertex_buffer_size=ctypes.sizeof(vertex_buffer), vertex_buffer_2_size=len(saved_mod.vertex_buffer_2), texture_count=len(textures_array), group_count=saved_mod.group_count, bones_array_offset=bones_array_offset, group_data_array=saved_mod.group_data_array, bone_palette_count=saved_mod.bone_palette_count, sphere_x=saved_mod.sphere_x, sphere_y=saved_mod.sphere_y, sphere_z=saved_mod.sphere_z, sphere_w=saved_mod.sphere_w, box_min_x=saved_mod.box_min_x, box_min_y=saved_mod.box_min_y, box_min_z=saved_mod.box_min_z, box_min_w=saved_mod.box_min_w, box_max_x=saved_mod.box_max_x, box_max_y=saved_mod.box_max_y, box_max_z=saved_mod.box_max_z, box_max_w=saved_mod.box_max_w, unk_01=saved_mod.unk_01, unk_02=saved_mod.unk_02, unk_03=saved_mod.unk_03, unk_04=saved_mod.unk_04, unk_05=saved_mod.unk_05, unk_06=saved_mod.unk_06, unk_07=saved_mod.unk_07, unk_08=saved_mod.unk_08, unk_09=saved_mod.unk_09, unk_10=saved_mod.unk_10, unk_11=saved_mod.unk_11, unk_12=saved_mod.unk_12, bones_array=saved_mod.bones_array, bones_unk_matrix_array=saved_mod.bones_unk_matrix_array, bones_world_transform_matrix_array=saved_mod.bones_world_transform_matrix_array, unk_13=saved_mod.unk_13, bone_palette_array=saved_mod.bone_palette_array, textures_array=textures_array, materials_data_array=materials_array, meshes_array=meshes_array, meshes_array_2=meshes_array_2, vertex_buffer=vertex_buffer, vertex_buffer_2=saved_mod.vertex_buffer_2, index_buffer=index_buffer ) mod.bones_array_offset = get_offset(mod, 'bones_array') if mod.bone_count else 0 mod.group_offset = get_offset(mod, 'group_data_array') mod.textures_array_offset = get_offset(mod, 'textures_array') mod.meshes_array_offset = get_offset(mod, 'meshes_array') mod.vertex_buffer_offset = get_offset(mod, 'vertex_buffer') mod.vertex_buffer_2_offset = get_offset(mod, 'vertex_buffer_2') mod.index_buffer_offset = get_offset(mod, 'index_buffer') return mod, get_textures_from_blender_objects(children_objects)