def load(context, filepath, name_suffix="", suppress_reports=False): """ :param context: Blender Context currently used for window_manager.update_progress and bpy_object_utils.object_data_add :type context: bpy.types.Context :param filepath: File path to be imported :type filepath: str :param name_suffix: files name suffix (exchange format is using .ef) :type name_suffix: str :param suppress_reports: True if you don't want for reports to be flushed & summaries to be printed out; False otherwise :type suppress_reports: bool :return: Return state statuses (Usually 'FINISHED') :rtype: set """ import time t = time.time() bpy.context.window.cursor_modal_set('WAIT') scs_globals = _get_scs_globals() if not suppress_reports: lprint("", report_errors=-1, report_warnings=-1 ) # Clear the 'error_messages' and 'warning_messages' collision_locators = [] prefab_locators = [] loaded_variants = [] loaded_looks = [] objects = [] locators = [] mats_info = [] scs_root_object = skeleton = bones = armature = None # TRANSITIONAL STRUCTURES terrain_points = TerrainPntsTrans() # IMPORT PIP -> has to be loaded before PIM because of terrain points if scs_globals.import_pip_file: lprint("I Importing PIP ...") pip_filepath = filepath + ".pip" + name_suffix if os.path.isfile(pip_filepath): lprint('\nD PIP filepath:\n %s', (pip_filepath, )) # print('PIP filepath:\n %s' % pip_filepath) result, prefab_locators = _pip.load(pip_filepath, terrain_points) else: lprint('\nI No PIP file.') # print('INFO - No PIP file.') # IMPORT PIM if scs_globals.import_pim_file or scs_globals.import_pis_file: lprint("I Importing PIM ...") pim_filepath = filepath + ".pim" + name_suffix if pim_filepath: if os.path.isfile(pim_filepath): lprint('\nD PIM filepath:\n %s', (_path_utils.readable_norm(pim_filepath), )) if pim_filepath.endswith(".pim"): result, objects, locators, armature, skeleton, mats_info = _pim.load( context, pim_filepath, terrain_points_trans=terrain_points) elif pim_filepath.endswith(".pim.ef"): result, objects, locators, armature, skeleton, mats_info = _pim_ef.load( context, pim_filepath, terrain_points_trans=terrain_points) else: lprint( "\nE Unknown PIM file extension! Shouldn't happen...") else: lprint('\nI No file found at %r!' % (_path_utils.readable_norm(pim_filepath), )) else: lprint('\nI No filepath provided!') # IMPORT PIT bpy.context.view_layer.objects.active = None if scs_globals.import_pit_file: lprint("I Importing PIT ...") pit_filepath = filepath + ".pit" + name_suffix if os.path.isfile(pit_filepath): lprint('\nD PIT filepath:\n %s', (pit_filepath, )) # print('PIT filepath:\n %s' % pit_filepath) result, loaded_variants, loaded_looks = _pit.load(pit_filepath) else: lprint('\nI No PIT file.') # print('INFO - No PIT file.') # IMPORT PIC if scs_globals.import_pic_file: lprint("I Importing PIC ...") pic_filepath = filepath + ".pic" + name_suffix if os.path.isfile(pic_filepath): lprint('\nD PIC filepath:\n %s', (pic_filepath, )) # print('PIC filepath:\n %s' % pic_filepath) result, collision_locators = _pic.load(pic_filepath) else: lprint('\nI No PIC file.') # print('INFO - No PIC file.') # SETUP 'SCS GAME OBJECTS' lprint("I Setup of SCS game object ...") for item in collision_locators: locators.append(item) for item in prefab_locators: locators.append(item) path, filename = os.path.split(filepath) if objects or locators or (armature and skeleton): scs_root_object = _create_scs_root_object(filename, loaded_variants, loaded_looks, mats_info, objects, locators, armature) # Additionally if user wants to have automatically set custom export path, then let him have it :P if scs_globals.import_preserve_path_for_export: relative_export_path = _path_utils.relative_path( scs_globals.scs_project_path, path) if path.startswith(scs_globals.scs_project_path ) and relative_export_path != path: scs_root_object.scs_props.scs_root_object_export_filepath = relative_export_path scs_root_object.scs_props.scs_root_object_allow_custom_path = True else: lprint( "W Can not preserve import path for export on import SCS Root %r, " "as import was done from outside of current SCS Project Base Path!", (scs_root_object.name, )) # IMPORT PIS if scs_globals.import_pis_file: lprint("I Importing PIS ...") # pis file path is created from directory of pim file and skeleton definition inside pim header pis_filepath = os.path.dirname(filepath) + os.sep + skeleton if os.path.isfile(pis_filepath): lprint('\nD PIS filepath:\n %s', (pis_filepath, )) # strip off name suffix from skeleton path skeleton = skeleton[:-len(name_suffix)] # fill in custom data if PIS file is from other directory if skeleton[:-4] != scs_root_object.name: armature.scs_props.scs_skeleton_custom_export_dirpath = "//" + os.path.relpath( os.path.dirname(pis_filepath), scs_globals.scs_project_path) armature.scs_props.scs_skeleton_custom_name = os.path.basename( skeleton[:-4]) bones = _pis.load(pis_filepath, armature) else: bones = None lprint('\nI No PIS file.') # IMPORT PIA if scs_globals.import_pia_file and bones: lprint("I Importing PIAs ...") basepath = os.path.dirname(filepath) # Search for PIA files in model's directory and its subdirectiories... lprint('\nD Searching the directory for PIA files:\n %s', (basepath, )) # print('\nSearching the directory for PIA files:\n %s' % str(basepath)) pia_files = [] index = 0 for root, dirs, files in os.walk(basepath): if not scs_globals.import_include_subdirs_for_pia: if index > 0: break # print(' root: %s - dirs: %s - files: %s' % (str(root), str(dirs), str(files))) for file in files: if file.endswith(".pia" + name_suffix): pia_filepath = os.path.join(root, file) pia_files.append(pia_filepath) index += 1 if len(pia_files) > 0: lprint('D PIA files found:') for pia_filepath in pia_files: lprint('D %r', pia_filepath) # print('armature: %s\nskeleton: %r\nbones: %s\n' % (str(armature), str(skeleton), str(bones))) _pia.load(scs_root_object, pia_files, armature, pis_filepath, bones) else: lprint('\nI No PIA files.') # fix scene objects count so it won't trigger copy cycle bpy.context.scene.scs_cached_num_objects = len(bpy.context.scene.objects) # FINAL FEEDBACK bpy.context.window.cursor_modal_restore() if suppress_reports: lprint('\nI Import compleeted in %.3f sec.', time.time() - t) else: lprint('\nI Import compleeted in %.3f sec.', time.time() - t, report_errors=True, report_warnings=True) return True
def load(context, filepath): """ :param context: Blender Context currently used for window_manager.update_progress and bpy_object_utils.object_data_add :type context: bpy.types.Context :param filepath: File path to be imported :type filepath: str :return: Return state statuses (Usually 'FINISHED') :rtype: dict """ import time t = time.time() bpy.context.window.cursor_modal_set('WAIT') scs_globals = _get_scs_globals() lprint("", report_errors=-1, report_warnings=-1) # Clear the 'error_messages' and 'warning_messages' collision_locators = [] prefab_locators = [] loaded_variants = [] loaded_looks = [] objects = [] locators = [] mats_info = [] scs_root_object = skeleton = bones = armature = None # TRANSITIONAL STRUCTURES terrain_points = TerrainPntsTrans() # IMPORT PIP -> has to be loaded before PIM because of terrain points if scs_globals.import_pip_file: pip_filepath = str(filepath[:-1] + 'p') if os.path.isfile(pip_filepath): lprint('\nD PIP filepath:\n %s', (pip_filepath,)) # print('PIP filepath:\n %s' % pip_filepath) result, prefab_locators = _pip.load(pip_filepath, terrain_points) else: lprint('\nI No PIP file.') # print('INFO - No PIP file.') # IMPORT PIM if scs_globals.import_pim_file or scs_globals.import_pis_file: if filepath: if os.path.isfile(filepath): lprint('\nD PIM filepath:\n %s', (_path_utils.readable_norm(filepath),)) result, objects, locators, armature, skeleton, mats_info = _pim.load( context, filepath, terrain_points_trans=terrain_points ) # print(' armature:\n%s\n skeleton:\n%s' % (str(armature), str(skeleton))) else: lprint('\nI No file found at %r!' % (_path_utils.readable_norm(filepath),)) else: lprint('\nI No filepath provided!') # IMPORT PIT bpy.context.scene.objects.active = None if scs_globals.import_pit_file: pit_filepath = str(filepath[:-1] + 't') if os.path.isfile(pit_filepath): lprint('\nD PIT filepath:\n %s', (pit_filepath,)) # print('PIT filepath:\n %s' % pit_filepath) result, loaded_variants, loaded_looks = _pit.load(pit_filepath) else: lprint('\nI No PIT file.') # print('INFO - No PIT file.') # IMPORT PIC if scs_globals.import_pic_file: pic_filepath = str(filepath[:-1] + 'c') if os.path.isfile(pic_filepath): lprint('\nD PIC filepath:\n %s', (pic_filepath,)) # print('PIC filepath:\n %s' % pic_filepath) result, collision_locators = _pic.load(pic_filepath) else: lprint('\nI No PIC file.') # print('INFO - No PIC file.') # SETUP 'SCS GAME OBJECTS' for item in collision_locators: locators.append(item) for item in prefab_locators: locators.append(item) path, file = os.path.split(filepath) # print(' path: %r\n file: %r' % (path, file)) lod_name, ext = os.path.splitext(file) if objects or locators or (armature and skeleton): scs_root_object = _create_scs_root_object(lod_name, loaded_variants, loaded_looks, mats_info, objects, locators, armature) # IMPORT PIS if scs_globals.import_pis_file: # pis file path is created from directory of pim file and skeleton definition inside pim header pis_filepath = os.path.dirname(filepath) + os.sep + skeleton if os.path.isfile(pis_filepath): lprint('\nD PIS filepath:\n %s', (pis_filepath,)) # fill in custom data if PIS file is from other directory if skeleton[:-4] != scs_root_object.name: armature.scs_props.scs_skeleton_custom_export_dirpath = "//" + os.path.relpath(os.path.dirname(pis_filepath), scs_globals.scs_project_path) armature.scs_props.scs_skeleton_custom_name = os.path.basename(skeleton[:-4]) bones = _pis.load(pis_filepath, armature) else: bones = None lprint('\nI No PIS file.') # IMPORT PIA if scs_globals.import_pia_file and bones: basepath = os.path.dirname(filepath) # Search for PIA files in model's directory and its subdirectiories... lprint('\nD Searching the directory for PIA files:\n %s', (basepath,)) # print('\nSearching the directory for PIA files:\n %s' % str(basepath)) pia_files = [] index = 0 for root, dirs, files in os.walk(basepath): if not scs_globals.include_subdirs_for_pia: if index > 0: break # print(' root: %s - dirs: %s - files: %s' % (str(root), str(dirs), str(files))) for file in files: if file.endswith(".pia"): pia_filepath = os.path.join(root, file) pia_files.append(pia_filepath) index += 1 if len(pia_files) > 0: lprint('D PIA files found:') for pia_filepath in pia_files: lprint('D %r', pia_filepath) # print('armature: %s\nskeleton: %r\nbones: %s\n' % (str(armature), str(skeleton), str(bones))) _pia.load(scs_root_object, pia_files, armature, pis_filepath, bones) else: lprint('\nI No PIA files.') # fix scene objects count so it won't trigger copy cycle bpy.context.scene.scs_cached_num_objects = len(bpy.context.scene.objects) # Turn on Textured Solid in 3D view... for bl_screen in bpy.data.screens: for bl_area in bl_screen.areas: for bl_space in bl_area.spaces: if bl_space.type == 'VIEW_3D': bl_space.show_textured_solid = True # Turn on GLSL in 3D view... bpy.context.scene.game_settings.material_mode = 'GLSL' # Turn on "Frame Dropping" for animation playback... bpy.context.scene.use_frame_drop = True # FINAL FEEDBACK bpy.context.window.cursor_modal_restore() lprint('\nI Import compleeted in %.3f sec.', time.time() - t, report_errors=True, report_warnings=True) return True
def load(context, filepath): """ :param context: Blender Context currently used for window_manager.update_progress and bpy_object_utils.object_data_add :type context: bpy.types.Context :param filepath: File path to be imported :type filepath: str :return: Return state statuses (Usually 'FINISHED') :rtype: dict """ import time t = time.time() bpy.context.window.cursor_modal_set('WAIT') scs_globals = _get_scs_globals() lprint("", report_errors=-1, report_warnings=-1 ) # Clear the 'error_messages' and 'warning_messages' collision_locators = [] prefab_locators = [] loaded_variants = [] loaded_looks = [] objects = [] locators = [] mats_info = [] scs_root_object = skeleton = bones = armature = None # TRANSITIONAL STRUCTURES terrain_points = TerrainPntsTrans() # IMPORT PIP -> has to be loaded before PIM because of terrain points if scs_globals.import_pip_file: pip_filepath = str(filepath[:-1] + 'p') if os.path.isfile(pip_filepath): lprint('\nD PIP filepath:\n %s', (pip_filepath, )) # print('PIP filepath:\n %s' % pip_filepath) result, prefab_locators = _pip.load(pip_filepath, terrain_points) else: lprint('\nI No PIP file.') # print('INFO - No PIP file.') # IMPORT PIM if scs_globals.import_pim_file or scs_globals.import_pis_file: if filepath: if os.path.isfile(filepath): lprint('\nD PIM filepath:\n %s', (_path_utils.readable_norm(filepath), )) result, objects, locators, armature, skeleton, mats_info = _pim.load( context, filepath, terrain_points_trans=terrain_points) # print(' armature:\n%s\n skeleton:\n%s' % (str(armature), str(skeleton))) else: lprint('\nI No file found at %r!' % (_path_utils.readable_norm(filepath), )) else: lprint('\nI No filepath provided!') # IMPORT PIT bpy.context.scene.objects.active = None if scs_globals.import_pit_file: pit_filepath = str(filepath[:-1] + 't') if os.path.isfile(pit_filepath): lprint('\nD PIT filepath:\n %s', (pit_filepath, )) # print('PIT filepath:\n %s' % pit_filepath) result, loaded_variants, loaded_looks = _pit.load(pit_filepath) else: lprint('\nI No PIT file.') # print('INFO - No PIT file.') # IMPORT PIC if scs_globals.import_pic_file: pic_filepath = str(filepath[:-1] + 'c') if os.path.isfile(pic_filepath): lprint('\nD PIC filepath:\n %s', (pic_filepath, )) # print('PIC filepath:\n %s' % pic_filepath) result, collision_locators = _pic.load(pic_filepath) else: lprint('\nI No PIC file.') # print('INFO - No PIC file.') # SETUP 'SCS GAME OBJECTS' for item in collision_locators: locators.append(item) for item in prefab_locators: locators.append(item) path, file = os.path.split(filepath) # print(' path: %r\n file: %r' % (path, file)) lod_name, ext = os.path.splitext(file) if objects or locators or (armature and skeleton): scs_root_object = _create_scs_root_object(lod_name, loaded_variants, loaded_looks, mats_info, objects, locators, armature) # Additionally if user wants to have automatically set custom export path, then let him have it :P if scs_globals.import_preserve_path_for_export: relative_export_path = _path_utils.relative_path( scs_globals.scs_project_path, path) if path.startswith(scs_globals.scs_project_path ) and relative_export_path != path: scs_root_object.scs_props.scs_root_object_export_filepath = relative_export_path scs_root_object.scs_props.scs_root_object_allow_custom_path = True else: lprint( "W Can not preserve import path for export on import SCS Root %r, " "as import was done from outside of current SCS Project Base Path!", (scs_root_object.name, )) # IMPORT PIS if scs_globals.import_pis_file: # pis file path is created from directory of pim file and skeleton definition inside pim header pis_filepath = os.path.dirname(filepath) + os.sep + skeleton if os.path.isfile(pis_filepath): lprint('\nD PIS filepath:\n %s', (pis_filepath, )) # fill in custom data if PIS file is from other directory if skeleton[:-4] != scs_root_object.name: armature.scs_props.scs_skeleton_custom_export_dirpath = "//" + os.path.relpath( os.path.dirname(pis_filepath), scs_globals.scs_project_path) armature.scs_props.scs_skeleton_custom_name = os.path.basename( skeleton[:-4]) bones = _pis.load(pis_filepath, armature) else: bones = None lprint('\nI No PIS file.') # IMPORT PIA if scs_globals.import_pia_file and bones: basepath = os.path.dirname(filepath) # Search for PIA files in model's directory and its subdirectiories... lprint('\nD Searching the directory for PIA files:\n %s', (basepath, )) # print('\nSearching the directory for PIA files:\n %s' % str(basepath)) pia_files = [] index = 0 for root, dirs, files in os.walk(basepath): if not scs_globals.import_include_subdirs_for_pia: if index > 0: break # print(' root: %s - dirs: %s - files: %s' % (str(root), str(dirs), str(files))) for file in files: if file.endswith(".pia"): pia_filepath = os.path.join(root, file) pia_files.append(pia_filepath) index += 1 if len(pia_files) > 0: lprint('D PIA files found:') for pia_filepath in pia_files: lprint('D %r', pia_filepath) # print('armature: %s\nskeleton: %r\nbones: %s\n' % (str(armature), str(skeleton), str(bones))) _pia.load(scs_root_object, pia_files, armature, pis_filepath, bones) else: lprint('\nI No PIA files.') # fix scene objects count so it won't trigger copy cycle bpy.context.scene.scs_cached_num_objects = len(bpy.context.scene.objects) # Turn on Textured Solid in 3D view... for bl_screen in bpy.data.screens: for bl_area in bl_screen.areas: for bl_space in bl_area.spaces: if bl_space.type == 'VIEW_3D': bl_space.show_textured_solid = True # Turn on GLSL in 3D view... bpy.context.scene.game_settings.material_mode = 'GLSL' # Turn on "Frame Dropping" for animation playback... bpy.context.scene.use_frame_drop = True # FINAL FEEDBACK bpy.context.window.cursor_modal_restore() lprint('\nI Import compleeted in %.3f sec.', time.time() - t, report_errors=True, report_warnings=True) return True
def load(root_object, pia_files, armature, pis_filepath=None, bones=None): scs_globals = _get_scs_globals() print("\n************************************") print("** SCS PIA Importer **") print("** (c)2014 SCS Software **") print("************************************\n") import_scale = scs_globals.import_scale ind = ' ' imported_count = 0 for pia_filepath in pia_files: # Check if PIA file is for the actual skeleton... if pis_filepath and bones: skeleton_match = _pix_container.fast_check_for_pia_skeleton( pia_filepath, pis_filepath) else: skeleton_match, pia_skeleton = _pix_container.utter_check_for_pia_skeleton( pia_filepath, armature) if skeleton_match: path = os.path.split(pia_filepath)[0] pia_skeleton = os.path.join(path, pia_skeleton) if os.path.isfile(pia_skeleton): bones = _pis.load(pia_skeleton, armature, get_only=True) else: lprint("\nE The filepath %r doesn't exist!", (_path_utils.readable_norm(pia_skeleton), )) else: lprint( str("E Animation doesn't match the skeleton. Animation won't be loaded!\n\t " "Animation file: %r"), (pia_filepath, )) if skeleton_match: lprint('I ++ "%s" IMPORTING animation data...', (os.path.basename(pia_filepath), )) pia_container = _pix_container.get_data_from_file( pia_filepath, ind) if not pia_container: lprint('\nE File "%s" is empty!', (_path_utils.readable_norm(pia_filepath), )) continue # TEST PRINTOUTS # ind = ' ' # for section in pia_container: # print('SEC.: "%s"' % section.type) # for prop in section.props: # print('%sProp: %s' % (ind, prop)) # for data in section.data: # print('%sdata: %s' % (ind, data)) # for sec in section.sections: # print_section(sec, ind) # print('\nTEST - Source: "%s"' % pia_container[0].props[1][1]) # print('') # TEST EXPORT # path, file = os.path.splitext(pia_filepath) # export_filepath = str(path + '_reex' + file) # result = pix_write.write_data(pia_container, export_filepath, ind) # if result == {'FINISHED'}: # Print(dump_level, '\nI Test export succesful! The new file:\n "%s"', export_filepath) # else: # Print(dump_level, '\nE Test export failed! File:\n "%s"', export_filepath) # LOAD HEADER format_version, source, f_type, animation_name, source_filename, author = _get_header( pia_container) if format_version != 3 or f_type != "Animation": continue # LOAD GLOBALS skeleton, total_time, bone_channel_count, custom_channel_count = _get_globals( pia_container) # CREATE ANIMATION ACTIONS anim_action = bpy.data.actions.new(animation_name + "_action") anim_action.use_fake_user = True anim_data = armature.animation_data if armature.animation_data else armature.animation_data_create( ) anim_data.action = anim_action # LOAD BONE CHANNELS bone_channels = _get_anim_channels(pia_container, section_name="BoneChannel") if len(bone_channels) > 0: for bone_name in bone_channels: if bone_name in armature.data.bones: ''' NOTE: skipped for now as no data needs to be readed stream_count = bone_channels[bone_name][0] keyframe_count = bone_channels[bone_name][1] ''' streams = bone_channels[bone_name][2] # CREATE ANIMATION GROUP anim_group = anim_action.groups.new(bone_name) armature.pose.bones[ bone_name].rotation_mode = 'XYZ' # Set rotation mode. # use pose bone scale set on PIS import init_scale = Vector((1, 1, 1)) if _BONE_consts.init_scale_key in armature.pose.bones[ bone_name]: init_scale = armature.pose.bones[bone_name][ _BONE_consts.init_scale_key] # CREATE FCURVES (pos_fcurves, rot_fcurves, sca_fcurves) = _create_fcurves(anim_action, anim_group, str('pose.bones["' + bone_name + '"]'), rot_euler=True) # GET BONE REST POSITION MATRIX bone_rest_matrix_scs = bones[bone_name][1].transposed() parent_bone_name = bones[bone_name][0] if parent_bone_name in bones: parent_bone_rest_matrix_scs = bones[ parent_bone_name][1].transposed() else: parent_bone_rest_matrix_scs = Matrix() parent_bone_rest_matrix_scs.identity() for key_time_i, key_time in enumerate(streams[0]): keyframe = key_time_i + 1 # GET BONE ANIMATION MATRIX bone_animation_matrix_scs = streams[1][ key_time_i].transposed() # CREATE DELTA MATRIX delta_matrix = _get_delta_matrix( bone_rest_matrix_scs, parent_bone_rest_matrix_scs, bone_animation_matrix_scs, import_scale) # DECOMPOSE ANIMATION MATRIX location, rotation, scale = delta_matrix.decompose( ) # CALCULATE CURRENT SCALE - subtract difference between initial bone scale and current scale from 1 # NOTE: if imported PIS had initial bone scale different than 1, # initial scale was saved into pose bones custom properties and # has to be used here as bones after import in Blender always have scale of 1 scale = Vector((1 + scale[0] - init_scale[0], 1 + scale[1] - init_scale[1], 1 + scale[2] - init_scale[2])) # NOTE: this scaling rotation switch came from UK variants which had scale -1 loc, rot, sca = bone_rest_matrix_scs.decompose() if sca.y < 0: rotation.y *= -1 if sca.z < 0: rotation.z *= -1 rotation = rotation.to_euler('XYZ') # BUILD TRANSFORMATION CURVES for i in range(0, 3): pos_fcurves[i].keyframe_points.insert( frame=float(keyframe), value=location[i], options={'FAST'}) rot_fcurves[i].keyframe_points.insert( frame=float(keyframe), value=rotation[i], options={'FAST'}) sca_fcurves[i].keyframe_points.insert( frame=float(keyframe), value=scale[i], options={'FAST'}) # SET LINEAR INTERPOLATION FOR ALL CURVES color_mode = 'AUTO_RAINBOW' # Or better 'AUTO_RGB'? for curve in pos_fcurves: curve.color_mode = color_mode for keyframe in curve.keyframe_points: keyframe.interpolation = 'LINEAR' for curve in rot_fcurves: curve.color_mode = color_mode for keyframe in curve.keyframe_points: keyframe.interpolation = 'LINEAR' for curve in sca_fcurves: curve.color_mode = color_mode for keyframe in curve.keyframe_points: keyframe.interpolation = 'LINEAR' for curve in rot_fcurves: _animation_utils.apply_euler_filter(curve) # LOAD CUSTOM CHANNELS (ARMATURE OFFSET ANIMATION) custom_channels = _get_anim_channels(pia_container, section_name="CustomChannel") if len(custom_channels) > 0: for channel_name in custom_channels: # print(' >>> channel %r - %s' % (channel_name, str(custom_channels[channel_name]))) if channel_name == 'Prism Movement': ''' NOTE: skipped for now as no data needs to be readed stream_count = custom_channels[channel_name][0] keyframe_count = custom_channels[channel_name][1] ''' streams = custom_channels[channel_name][2] # print(' channel %r - streams %s - keyframes %s' % (channel_name, stream_count, keyframe_count)) # CREATE ANIMATION GROUP # anim_group = anim_action.groups.new(channel_name) anim_group = anim_action.groups.new('Location') # armature.[channel_name].rotation_mode = 'XYZ' ## Set rotation mode. # active_bone = armature.data.bones[channel_name] # parent_bone = active_bone.parent # CREATE FCURVES # pos_fcurves, rot_fcurves, sca_fcurves = _create_fcurves(anim_action, anim_group, anim_curve, rot_euler=True, # types='LocRotSca') # pos_fcurves, rot_fcurves, sca_fcurves = _create_fcurves(anim_action, anim_group, anim_curve, types='Loc') fcurve_pos_x = anim_action.fcurves.new('location', 0) fcurve_pos_y = anim_action.fcurves.new('location', 1) fcurve_pos_z = anim_action.fcurves.new('location', 2) fcurve_pos_x.group = anim_group fcurve_pos_y.group = anim_group fcurve_pos_z.group = anim_group pos_fcurves = (fcurve_pos_x, fcurve_pos_y, fcurve_pos_z) location = None for key_time_i, key_time in enumerate(streams[0]): # print(' key_time: %s' % str(key_time[0])) # keyframe = key_time_i * (key_time[0] * 10) ## TODO: Do proper timing... keyframe = key_time_i + 1 scs_offset = _convert_utils.change_to_scs_xyz_coordinates( custom_channels[channel_name][2][1] [key_time_i], import_scale) offset = Vector(scs_offset) if location is None: location = offset else: location = location + offset # print(' > location: %s' % str(location)) # BUILD TRANSLATION CURVES pos_fcurves[0].keyframe_points.insert( frame=float(keyframe), value=location[0], options={'FAST'}) pos_fcurves[1].keyframe_points.insert( frame=float(keyframe), value=location[1], options={'FAST'}) pos_fcurves[2].keyframe_points.insert( frame=float(keyframe), value=location[2], options={'FAST'}) # SET LINEAR INTERPOLATION FOR ALL CURVES for curve in pos_fcurves: for keyframe in curve.keyframe_points: keyframe.interpolation = 'LINEAR' else: lprint('W Unknown channel %r in "%s" file.', (channel_name, os.path.basename(pia_filepath))) # CREATE SCS ANIMATION animation = _animation_utils.add_animation_to_root( root_object, animation_name) animation.export = True animation.action = anim_action.name animation.anim_start = anim_action.frame_range[0] animation.anim_end = anim_action.frame_range[1] if total_time: animation.length = total_time # WARNING PRINTOUTS # if piece_count < 0: Print(dump_level, '\nW More Pieces found than were declared!') # if piece_count > 0: Print(dump_level, '\nW Some Pieces not found, but were declared!') # if dump_level > 1: print('') imported_count += 1 else: lprint('I "%s" file REJECTED', (os.path.basename(pia_filepath), )) # at the end of batch import make sure to select last animation always if imported_count > 0: root_object.scs_props.active_scs_animation = len( root_object.scs_object_animation_inventory) - 1 print("************************************") return imported_count
def load(root_object, pia_files, armature, skeleton=None, bones=None): if not bones: bones = {} scs_globals = _get_scs_globals() print("\n************************************") print("** SCS PIA Importer **") print("** (c)2014 SCS Software **") print("************************************\n") import_scale = scs_globals.import_scale ind = ' ' for pia_filepath in pia_files: # Check if PIA file is for the actual skeleton... if skeleton: skeleton_match = _fast_check_for_pia_skeleton(pia_filepath, skeleton) else: skeleton_match, skeleton = _utter_check_for_pia_skeleton(pia_filepath, armature) # print('%r - %s' %(os.path.basename(pia_filepath), skeleton_match)) # print(' skeleton: %r' % skeleton) if skeleton_match: path = os.path.split(pia_filepath)[0] pis_filepath = os.path.join(path, skeleton) if os.path.isfile(pis_filepath): # print(' pis_filepath: %r' % pis_filepath) bones = _pis.load(pis_filepath, armature) else: lprint("""\nE The filepath "%s" doesn't exist!""", (pis_filepath.replace("\\", "/"),)) if skeleton_match: lprint('I ++ "%s" IMPORTING animation data...', (os.path.basename(pia_filepath),)) pia_container, state = _pix_parser.read_data(pia_filepath, ind) if not pia_container: lprint('\nE File "%s" is empty!', (pia_filepath.replace("\\", "/"),)) return {'CANCELLED'} if state == 'ERR': lprint('\nE File "%s" is not SCS Animation file!', (pia_filepath.replace("\\", "/"),)) return {'CANCELLED'} # TEST PRINTOUTS # ind = ' ' # for section in pia_container: # print('SEC.: "%s"' % section.type) # for prop in section.props: # print('%sProp: %s' % (ind, prop)) # for data in section.data: # print('%sdata: %s' % (ind, data)) # for sec in section.sections: # print_section(sec, ind) # print('\nTEST - Source: "%s"' % pia_container[0].props[1][1]) # print('') # TEST EXPORT # path, file = os.path.splitext(pia_filepath) # export_filepath = str(path + '_reex' + file) # result = pix_write.write_data(pia_container, export_filepath, ind) # if result == {'FINISHED'}: # Print(dump_level, '\nI Test export succesful! The new file:\n "%s"', export_filepath) # else: # Print(dump_level, '\nE Test export failed! File:\n "%s"', export_filepath) # LOAD HEADER format_version, source, f_type, animation_name, source_filename, author = _get_header(pia_container) if format_version != 3 or f_type != "Animation": return {'CANCELLED'} # LOAD GLOBALS skeleton, total_time, bone_channel_count, custom_channel_count = _get_globals(pia_container) # CREATE ANIMATION ACTIONS anim_action = bpy.data.actions.new(animation_name) anim_action.use_fake_user = True if total_time: anim_action.scs_props.action_length = total_time anim_data = armature.animation_data_create() anim_data.action = anim_action # LOAD BONE CHANNELS # print(' * armature: %r' % armature.name) if bone_channel_count > 0: bone_channels = _get_anim_channels(pia_container, section_name="BoneChannel") # ... for bone_name in bone_channels: # bone_name = channel[0] if bone_name in armature.data.bones: # print('%r is in armature %r' % (bone_name, armature.name)) ''' NOTE: skipped for now as no data needs to be readed stream_count = bone_channels[bone_name][0] keyframe_count = bone_channels[bone_name][1] ''' streams = bone_channels[bone_name][2] # print(' channel %r - streams %s - keyframes %s' % (bone_name, stream_count, keyframe_count)) # CREATE ANIMATION GROUP anim_group = anim_action.groups.new(bone_name) armature.pose.bones[bone_name].rotation_mode = 'XYZ' # Set rotation mode. active_bone = armature.data.bones[bone_name] # parent_bone = active_bone.parent # CREATE FCURVES (pos_fcurves, rot_fcurves, sca_fcurves) = _create_fcurves(anim_action, anim_group, str('pose.bones["' + bone_name + '"]')) # GET BONE REST POSITION MATRIX bone_rest_matrix = active_bone.matrix_local bone_rest_matrix_scs = bones[bone_name][1].transposed() parent_bone_name = bones[bone_name][0] if parent_bone_name in bones: parent_bone_rest_matrix_scs = bones[parent_bone_name][1].transposed() else: parent_bone_rest_matrix_scs = Matrix() parent_bone_rest_matrix_scs.identity() # if bone_name in ('LeftHand1', 'LeftHand'): # print('\n %r - bone_rest_matrix_scs:\n%s' % (bone_name, bone_rest_matrix_scs)) # print(' %r - bone_rest_matrix:\n%s' % (bone_name, bone_rest_matrix)) # print(' %r - parent_bone_rest_matrix_scs:\n%s' % (bone_name, parent_bone_rest_matrix_scs)) for key_time_i, key_time in enumerate(streams[0]): # print(' key_time: %s' % str(key_time[0])) # keyframe = key_time_i * (key_time[0] * 10) ## TODO: Do proper timing... keyframe = key_time_i + 1 # GET BONE ANIMATION MATRIX bone_animation_matrix_scs = streams[1][key_time_i].transposed() # if bone_name in ('LeftHand1', 'LeftHand') and key_time_i == 0: print(' %r - bone_animation_matrix_scs (%i):\n%s' % ( # bone_name, key_time_i, bone_animation_matrix_scs)) # CREATE DELTA MATRIX delta_matrix = _get_delta_matrix(bone_rest_matrix, bone_rest_matrix_scs, parent_bone_rest_matrix_scs, bone_animation_matrix_scs, import_scale) # DECOMPOSE ANIMATION MATRIX location, rotation, scale = delta_matrix.decompose() # if bone_name in ('left_leg', 'root') and key_time_i == 0: print(' location:\n%s' % str(location)) rotation = rotation.to_euler('XYZ') # BUILD TRANSLATION CURVES pos_fcurves[0].keyframe_points.insert(frame=float(keyframe), value=location[0], options={'FAST'}) pos_fcurves[1].keyframe_points.insert(frame=float(keyframe), value=location[1], options={'FAST'}) pos_fcurves[2].keyframe_points.insert(frame=float(keyframe), value=location[2], options={'FAST'}) # BUILD ROTATION CURVES rot_fcurves[0].keyframe_points.insert(frame=float(keyframe), value=rotation[0], options={'FAST'}) rot_fcurves[1].keyframe_points.insert(frame=float(keyframe), value=rotation[1], options={'FAST'}) rot_fcurves[2].keyframe_points.insert(frame=float(keyframe), value=rotation[2], options={'FAST'}) # BUILD SCALE CURVES sca_fcurves[0].keyframe_points.insert(frame=float(keyframe), value=scale[0], options={'FAST'}) sca_fcurves[1].keyframe_points.insert(frame=float(keyframe), value=scale[1], options={'FAST'}) sca_fcurves[2].keyframe_points.insert(frame=float(keyframe), value=scale[2], options={'FAST'}) # SET LINEAR INTERPOLATION FOR ALL CURVES color_mode = 'AUTO_RAINBOW' # Or better 'AUTO_RGB'? for curve in pos_fcurves: curve.color_mode = color_mode for keyframe in curve.keyframe_points: keyframe.interpolation = 'LINEAR' for curve in rot_fcurves: curve.color_mode = color_mode for keyframe in curve.keyframe_points: keyframe.interpolation = 'LINEAR' for curve in sca_fcurves: curve.color_mode = color_mode for keyframe in curve.keyframe_points: keyframe.interpolation = 'LINEAR' # LOAD CUSTOM CHANNELS (ARMATURE OFFSET ANIMATION) # if custom_channel_count > 0: ## NOTE: Can't be used because exporter from Maya saves always 0 even if there are Custom Channels. custom_channels = _get_anim_channels(pia_container, section_name="CustomChannel") if len(custom_channels) > 0: for channel_name in custom_channels: # print(' >>> channel %r - %s' % (channel_name, str(custom_channels[channel_name]))) if channel_name == 'Prism Movement': ''' NOTE: skipped for now as no data needs to be readed stream_count = custom_channels[channel_name][0] keyframe_count = custom_channels[channel_name][1] ''' streams = custom_channels[channel_name][2] # print(' channel %r - streams %s - keyframes %s' % (channel_name, stream_count, keyframe_count)) # CREATE ANIMATION GROUP # anim_group = anim_action.groups.new(channel_name) anim_group = anim_action.groups.new('Location') # armature.[channel_name].rotation_mode = 'XYZ' ## Set rotation mode. # active_bone = armature.data.bones[channel_name] # parent_bone = active_bone.parent # CREATE FCURVES # pos_fcurves, rot_fcurves, sca_fcurves = _create_fcurves(anim_action, anim_group, anim_curve, rot_euler=True, # types='LocRotSca') # pos_fcurves, rot_fcurves, sca_fcurves = _create_fcurves(anim_action, anim_group, anim_curve, types='Loc') fcurve_pos_x = anim_action.fcurves.new('location', 0) fcurve_pos_y = anim_action.fcurves.new('location', 1) fcurve_pos_z = anim_action.fcurves.new('location', 2) fcurve_pos_x.group = anim_group fcurve_pos_y.group = anim_group fcurve_pos_z.group = anim_group pos_fcurves = (fcurve_pos_x, fcurve_pos_y, fcurve_pos_z) location = None for key_time_i, key_time in enumerate(streams[0]): # print(' key_time: %s' % str(key_time[0])) # keyframe = key_time_i * (key_time[0] * 10) ## TODO: Do proper timing... keyframe = key_time_i + 1 scs_offset = _convert_utils.change_to_scs_xyz_coordinates(custom_channels[channel_name][2][1][key_time_i], import_scale) offset = Vector(scs_offset) if location is None: location = offset else: location = location + offset # print(' > location: %s' % str(location)) # BUILD TRANSLATION CURVES pos_fcurves[0].keyframe_points.insert(frame=float(keyframe), value=location[0], options={'FAST'}) pos_fcurves[1].keyframe_points.insert(frame=float(keyframe), value=location[1], options={'FAST'}) pos_fcurves[2].keyframe_points.insert(frame=float(keyframe), value=location[2], options={'FAST'}) # SET LINEAR INTERPOLATION FOR ALL CURVES for curve in pos_fcurves: for keyframe in curve.keyframe_points: keyframe.interpolation = 'LINEAR' else: lprint('W Unknown channel %r in "%s" file.', (channel_name, os.path.basename(pia_filepath))) # CREATE SCS ANIMATION animation = _animation_utils.add_animation_to_root(root_object, animation_name) animation.export = True animation.action = anim_action.name animation.anim_start = anim_action.frame_range[0] animation.anim_end = anim_action.frame_range[1] # animation.anim_export_step = # animation.anim_export_filepath = if total_time: animation.length = total_time # WARNING PRINTOUTS # if piece_count < 0: Print(dump_level, '\nW More Pieces found than were declared!') # if piece_count > 0: Print(dump_level, '\nW Some Pieces not found, but were declared!') # if dump_level > 1: print('') else: lprint('I "%s" file REJECTED', (os.path.basename(pia_filepath),)) print("************************************") return {'FINISHED'}
def load(root_object, pia_files, armature, pis_filepath=None, bones=None): scs_globals = _get_scs_globals() print("\n************************************") print("** SCS PIA Importer **") print("** (c)2014 SCS Software **") print("************************************\n") import_scale = scs_globals.import_scale ind = ' ' imported_count = 0 for pia_filepath in pia_files: # Check if PIA file is for the actual skeleton... if pis_filepath and bones: skeleton_match = _pix_container.fast_check_for_pia_skeleton(pia_filepath, pis_filepath) else: skeleton_match, pia_skeleton = _pix_container.utter_check_for_pia_skeleton(pia_filepath, armature) if skeleton_match: path = os.path.split(pia_filepath)[0] pia_skeleton = os.path.join(path, pia_skeleton) if os.path.isfile(pia_skeleton): bones = _pis.load(pia_skeleton, armature, get_only=True) else: lprint("\nE The filepath %r doesn't exist!", (pia_skeleton.replace("\\", "/"),)) else: lprint(str("E Animation doesn't match the skeleton. Animation won't be loaded!\n\t " "Animation file: %r"), (pia_filepath,)) if skeleton_match: lprint('I ++ "%s" IMPORTING animation data...', (os.path.basename(pia_filepath),)) pia_container = _pix_container.get_data_from_file(pia_filepath, ind) if not pia_container: lprint('\nE File "%s" is empty!', (pia_filepath.replace("\\", "/"),)) continue # TEST PRINTOUTS # ind = ' ' # for section in pia_container: # print('SEC.: "%s"' % section.type) # for prop in section.props: # print('%sProp: %s' % (ind, prop)) # for data in section.data: # print('%sdata: %s' % (ind, data)) # for sec in section.sections: # print_section(sec, ind) # print('\nTEST - Source: "%s"' % pia_container[0].props[1][1]) # print('') # TEST EXPORT # path, file = os.path.splitext(pia_filepath) # export_filepath = str(path + '_reex' + file) # result = pix_write.write_data(pia_container, export_filepath, ind) # if result == {'FINISHED'}: # Print(dump_level, '\nI Test export succesful! The new file:\n "%s"', export_filepath) # else: # Print(dump_level, '\nE Test export failed! File:\n "%s"', export_filepath) # LOAD HEADER format_version, source, f_type, animation_name, source_filename, author = _get_header(pia_container) if format_version != 3 or f_type != "Animation": continue # LOAD GLOBALS skeleton, total_time, bone_channel_count, custom_channel_count = _get_globals(pia_container) # CREATE ANIMATION ACTIONS anim_action = bpy.data.actions.new(animation_name + "_action") anim_action.use_fake_user = True anim_data = armature.animation_data if armature.animation_data else armature.animation_data_create() anim_data.action = anim_action # LOAD BONE CHANNELS bone_channels = _get_anim_channels(pia_container, section_name="BoneChannel") if len(bone_channels) > 0: for bone_name in bone_channels: if bone_name in armature.data.bones: ''' NOTE: skipped for now as no data needs to be readed stream_count = bone_channels[bone_name][0] keyframe_count = bone_channels[bone_name][1] ''' streams = bone_channels[bone_name][2] # CREATE ANIMATION GROUP anim_group = anim_action.groups.new(bone_name) armature.pose.bones[bone_name].rotation_mode = 'XYZ' # Set rotation mode. # use pose bone scale set on PIS import init_scale = Vector((1, 1, 1)) if _BONE_consts.init_scale_key in armature.pose.bones[bone_name]: init_scale = armature.pose.bones[bone_name][_BONE_consts.init_scale_key] # CREATE FCURVES (pos_fcurves, rot_fcurves, sca_fcurves) = _create_fcurves(anim_action, anim_group, str('pose.bones["' + bone_name + '"]'), rot_euler=True) # GET BONE REST POSITION MATRIX bone_rest_matrix_scs = bones[bone_name][1].transposed() parent_bone_name = bones[bone_name][0] if parent_bone_name in bones: parent_bone_rest_matrix_scs = bones[parent_bone_name][1].transposed() else: parent_bone_rest_matrix_scs = Matrix() parent_bone_rest_matrix_scs.identity() for key_time_i, key_time in enumerate(streams[0]): keyframe = key_time_i + 1 # GET BONE ANIMATION MATRIX bone_animation_matrix_scs = streams[1][key_time_i].transposed() # CREATE DELTA MATRIX delta_matrix = _get_delta_matrix(bone_rest_matrix_scs, parent_bone_rest_matrix_scs, bone_animation_matrix_scs, import_scale) # DECOMPOSE ANIMATION MATRIX location, rotation, scale = delta_matrix.decompose() # CALCULATE CURRENT SCALE - subtract difference between initial bone scale and current scale from 1 # NOTE: if imported PIS had initial bone scale different than 1, # initial scale was saved into pose bones custom properties and # has to be used here as bones after import in Blender always have scale of 1 scale = Vector((1 + scale[0] - init_scale[0], 1 + scale[1] - init_scale[1], 1 + scale[2] - init_scale[2])) # NOTE: this scaling rotation switch came from UK variants which had scale -1 loc, rot, sca = bone_rest_matrix_scs.decompose() if sca.y < 0: rotation.y *= -1 if sca.z < 0: rotation.z *= -1 rotation = rotation.to_euler('XYZ') # BUILD TRANSFORMATION CURVES for i in range(0, 3): pos_fcurves[i].keyframe_points.insert(frame=float(keyframe), value=location[i], options={'FAST'}) rot_fcurves[i].keyframe_points.insert(frame=float(keyframe), value=rotation[i], options={'FAST'}) sca_fcurves[i].keyframe_points.insert(frame=float(keyframe), value=scale[i], options={'FAST'}) # SET LINEAR INTERPOLATION FOR ALL CURVES color_mode = 'AUTO_RAINBOW' # Or better 'AUTO_RGB'? for curve in pos_fcurves: curve.color_mode = color_mode for keyframe in curve.keyframe_points: keyframe.interpolation = 'LINEAR' for curve in rot_fcurves: curve.color_mode = color_mode for keyframe in curve.keyframe_points: keyframe.interpolation = 'LINEAR' for curve in sca_fcurves: curve.color_mode = color_mode for keyframe in curve.keyframe_points: keyframe.interpolation = 'LINEAR' for curve in rot_fcurves: _animation_utils.apply_euler_filter(curve) # LOAD CUSTOM CHANNELS (ARMATURE OFFSET ANIMATION) custom_channels = _get_anim_channels(pia_container, section_name="CustomChannel") if len(custom_channels) > 0: for channel_name in custom_channels: # print(' >>> channel %r - %s' % (channel_name, str(custom_channels[channel_name]))) if channel_name == 'Prism Movement': ''' NOTE: skipped for now as no data needs to be readed stream_count = custom_channels[channel_name][0] keyframe_count = custom_channels[channel_name][1] ''' streams = custom_channels[channel_name][2] # print(' channel %r - streams %s - keyframes %s' % (channel_name, stream_count, keyframe_count)) # CREATE ANIMATION GROUP # anim_group = anim_action.groups.new(channel_name) anim_group = anim_action.groups.new('Location') # armature.[channel_name].rotation_mode = 'XYZ' ## Set rotation mode. # active_bone = armature.data.bones[channel_name] # parent_bone = active_bone.parent # CREATE FCURVES # pos_fcurves, rot_fcurves, sca_fcurves = _create_fcurves(anim_action, anim_group, anim_curve, rot_euler=True, # types='LocRotSca') # pos_fcurves, rot_fcurves, sca_fcurves = _create_fcurves(anim_action, anim_group, anim_curve, types='Loc') fcurve_pos_x = anim_action.fcurves.new('location', 0) fcurve_pos_y = anim_action.fcurves.new('location', 1) fcurve_pos_z = anim_action.fcurves.new('location', 2) fcurve_pos_x.group = anim_group fcurve_pos_y.group = anim_group fcurve_pos_z.group = anim_group pos_fcurves = (fcurve_pos_x, fcurve_pos_y, fcurve_pos_z) location = None for key_time_i, key_time in enumerate(streams[0]): # print(' key_time: %s' % str(key_time[0])) # keyframe = key_time_i * (key_time[0] * 10) ## TODO: Do proper timing... keyframe = key_time_i + 1 scs_offset = _convert_utils.change_to_scs_xyz_coordinates(custom_channels[channel_name][2][1][key_time_i], import_scale) offset = Vector(scs_offset) if location is None: location = offset else: location = location + offset # print(' > location: %s' % str(location)) # BUILD TRANSLATION CURVES pos_fcurves[0].keyframe_points.insert(frame=float(keyframe), value=location[0], options={'FAST'}) pos_fcurves[1].keyframe_points.insert(frame=float(keyframe), value=location[1], options={'FAST'}) pos_fcurves[2].keyframe_points.insert(frame=float(keyframe), value=location[2], options={'FAST'}) # SET LINEAR INTERPOLATION FOR ALL CURVES for curve in pos_fcurves: for keyframe in curve.keyframe_points: keyframe.interpolation = 'LINEAR' else: lprint('W Unknown channel %r in "%s" file.', (channel_name, os.path.basename(pia_filepath))) # CREATE SCS ANIMATION animation = _animation_utils.add_animation_to_root(root_object, animation_name) animation.export = True animation.action = anim_action.name animation.anim_start = anim_action.frame_range[0] animation.anim_end = anim_action.frame_range[1] if total_time: animation.length = total_time # WARNING PRINTOUTS # if piece_count < 0: Print(dump_level, '\nW More Pieces found than were declared!') # if piece_count > 0: Print(dump_level, '\nW Some Pieces not found, but were declared!') # if dump_level > 1: print('') imported_count += 1 else: lprint('I "%s" file REJECTED', (os.path.basename(pia_filepath),)) # at the end of batch import make sure to select last animation always if imported_count > 0: root_object.scs_props.active_scs_animation = len(root_object.scs_object_animation_inventory) - 1 print("************************************") return imported_count
def load(root_object, pia_files, armature, skeleton=None, bones=None): if not bones: bones = {} scs_globals = _get_scs_globals() print("\n************************************") print("** SCS PIA Importer **") print("** (c)2014 SCS Software **") print("************************************\n") import_scale = scs_globals.import_scale ind = ' ' for pia_filepath in pia_files: # Check if PIA file is for the actual skeleton... if skeleton: skeleton_match = _fast_check_for_pia_skeleton( pia_filepath, skeleton) else: skeleton_match, skeleton = _utter_check_for_pia_skeleton( pia_filepath, armature) # print('%r - %s' %(os.path.basename(pia_filepath), skeleton_match)) # print(' skeleton: %r' % skeleton) if skeleton_match: path = os.path.split(pia_filepath)[0] pis_filepath = os.path.join(path, skeleton) if os.path.isfile(pis_filepath): # print(' pis_filepath: %r' % pis_filepath) bones = _pis.load(pis_filepath, armature) else: lprint("""\nE The filepath "%s" doesn't exist!""", (pis_filepath.replace("\\", "/"), )) if skeleton_match: lprint('I ++ "%s" IMPORTING animation data...', (os.path.basename(pia_filepath), )) pia_container, state = _pix_parser.read_data(pia_filepath, ind) if not pia_container: lprint('\nE File "%s" is empty!', (pia_filepath.replace("\\", "/"), )) return {'CANCELLED'} if state == 'ERR': lprint('\nE File "%s" is not SCS Animation file!', (pia_filepath.replace("\\", "/"), )) return {'CANCELLED'} # TEST PRINTOUTS # ind = ' ' # for section in pia_container: # print('SEC.: "%s"' % section.type) # for prop in section.props: # print('%sProp: %s' % (ind, prop)) # for data in section.data: # print('%sdata: %s' % (ind, data)) # for sec in section.sections: # print_section(sec, ind) # print('\nTEST - Source: "%s"' % pia_container[0].props[1][1]) # print('') # TEST EXPORT # path, file = os.path.splitext(pia_filepath) # export_filepath = str(path + '_reex' + file) # result = pix_write.write_data(pia_container, export_filepath, ind) # if result == {'FINISHED'}: # Print(dump_level, '\nI Test export succesful! The new file:\n "%s"', export_filepath) # else: # Print(dump_level, '\nE Test export failed! File:\n "%s"', export_filepath) # LOAD HEADER format_version, source, f_type, animation_name, source_filename, author = _get_header( pia_container) if format_version != 3 or f_type != "Animation": return {'CANCELLED'} # LOAD GLOBALS skeleton, total_time, bone_channel_count, custom_channel_count = _get_globals( pia_container) # CREATE ANIMATION ACTIONS anim_action = bpy.data.actions.new(animation_name) anim_action.use_fake_user = True if total_time: anim_action.scs_props.action_length = total_time anim_data = armature.animation_data_create() anim_data.action = anim_action # LOAD BONE CHANNELS # print(' * armature: %r' % armature.name) if bone_channel_count > 0: bone_channels = _get_anim_channels(pia_container, section_name="BoneChannel") # ... for bone_name in bone_channels: # bone_name = channel[0] if bone_name in armature.data.bones: # print('%r is in armature %r' % (bone_name, armature.name)) ''' NOTE: skipped for now as no data needs to be readed stream_count = bone_channels[bone_name][0] keyframe_count = bone_channels[bone_name][1] ''' streams = bone_channels[bone_name][2] # print(' channel %r - streams %s - keyframes %s' % (bone_name, stream_count, keyframe_count)) # CREATE ANIMATION GROUP anim_group = anim_action.groups.new(bone_name) armature.pose.bones[ bone_name].rotation_mode = 'XYZ' # Set rotation mode. active_bone = armature.data.bones[bone_name] # parent_bone = active_bone.parent # CREATE FCURVES (pos_fcurves, rot_fcurves, sca_fcurves) = _create_fcurves( anim_action, anim_group, str('pose.bones["' + bone_name + '"]')) # GET BONE REST POSITION MATRIX bone_rest_matrix = active_bone.matrix_local bone_rest_matrix_scs = bones[bone_name][1].transposed() parent_bone_name = bones[bone_name][0] if parent_bone_name in bones: parent_bone_rest_matrix_scs = bones[ parent_bone_name][1].transposed() else: parent_bone_rest_matrix_scs = Matrix() parent_bone_rest_matrix_scs.identity() # if bone_name in ('LeftHand1', 'LeftHand'): # print('\n %r - bone_rest_matrix_scs:\n%s' % (bone_name, bone_rest_matrix_scs)) # print(' %r - bone_rest_matrix:\n%s' % (bone_name, bone_rest_matrix)) # print(' %r - parent_bone_rest_matrix_scs:\n%s' % (bone_name, parent_bone_rest_matrix_scs)) for key_time_i, key_time in enumerate(streams[0]): # print(' key_time: %s' % str(key_time[0])) # keyframe = key_time_i * (key_time[0] * 10) ## TODO: Do proper timing... keyframe = key_time_i + 1 # GET BONE ANIMATION MATRIX bone_animation_matrix_scs = streams[1][ key_time_i].transposed() # if bone_name in ('LeftHand1', 'LeftHand') and key_time_i == 0: print(' %r - bone_animation_matrix_scs (%i):\n%s' % ( # bone_name, key_time_i, bone_animation_matrix_scs)) # CREATE DELTA MATRIX delta_matrix = _get_delta_matrix( bone_rest_matrix, bone_rest_matrix_scs, parent_bone_rest_matrix_scs, bone_animation_matrix_scs, import_scale) # DECOMPOSE ANIMATION MATRIX location, rotation, scale = delta_matrix.decompose( ) # if bone_name in ('left_leg', 'root') and key_time_i == 0: print(' location:\n%s' % str(location)) rotation = rotation.to_euler('XYZ') # BUILD TRANSLATION CURVES pos_fcurves[0].keyframe_points.insert( frame=float(keyframe), value=location[0], options={'FAST'}) pos_fcurves[1].keyframe_points.insert( frame=float(keyframe), value=location[1], options={'FAST'}) pos_fcurves[2].keyframe_points.insert( frame=float(keyframe), value=location[2], options={'FAST'}) # BUILD ROTATION CURVES rot_fcurves[0].keyframe_points.insert( frame=float(keyframe), value=rotation[0], options={'FAST'}) rot_fcurves[1].keyframe_points.insert( frame=float(keyframe), value=rotation[1], options={'FAST'}) rot_fcurves[2].keyframe_points.insert( frame=float(keyframe), value=rotation[2], options={'FAST'}) # BUILD SCALE CURVES sca_fcurves[0].keyframe_points.insert( frame=float(keyframe), value=scale[0], options={'FAST'}) sca_fcurves[1].keyframe_points.insert( frame=float(keyframe), value=scale[1], options={'FAST'}) sca_fcurves[2].keyframe_points.insert( frame=float(keyframe), value=scale[2], options={'FAST'}) # SET LINEAR INTERPOLATION FOR ALL CURVES color_mode = 'AUTO_RAINBOW' # Or better 'AUTO_RGB'? for curve in pos_fcurves: curve.color_mode = color_mode for keyframe in curve.keyframe_points: keyframe.interpolation = 'LINEAR' for curve in rot_fcurves: curve.color_mode = color_mode for keyframe in curve.keyframe_points: keyframe.interpolation = 'LINEAR' for curve in sca_fcurves: curve.color_mode = color_mode for keyframe in curve.keyframe_points: keyframe.interpolation = 'LINEAR' # LOAD CUSTOM CHANNELS (ARMATURE OFFSET ANIMATION) # if custom_channel_count > 0: ## NOTE: Can't be used because exporter from Maya saves always 0 even if there are Custom Channels. custom_channels = _get_anim_channels(pia_container, section_name="CustomChannel") if len(custom_channels) > 0: for channel_name in custom_channels: # print(' >>> channel %r - %s' % (channel_name, str(custom_channels[channel_name]))) if channel_name == 'Prism Movement': ''' NOTE: skipped for now as no data needs to be readed stream_count = custom_channels[channel_name][0] keyframe_count = custom_channels[channel_name][1] ''' streams = custom_channels[channel_name][2] # print(' channel %r - streams %s - keyframes %s' % (channel_name, stream_count, keyframe_count)) # CREATE ANIMATION GROUP # anim_group = anim_action.groups.new(channel_name) anim_group = anim_action.groups.new('Location') # armature.[channel_name].rotation_mode = 'XYZ' ## Set rotation mode. # active_bone = armature.data.bones[channel_name] # parent_bone = active_bone.parent # CREATE FCURVES # pos_fcurves, rot_fcurves, sca_fcurves = _create_fcurves(anim_action, anim_group, anim_curve, rot_euler=True, # types='LocRotSca') # pos_fcurves, rot_fcurves, sca_fcurves = _create_fcurves(anim_action, anim_group, anim_curve, types='Loc') fcurve_pos_x = anim_action.fcurves.new('location', 0) fcurve_pos_y = anim_action.fcurves.new('location', 1) fcurve_pos_z = anim_action.fcurves.new('location', 2) fcurve_pos_x.group = anim_group fcurve_pos_y.group = anim_group fcurve_pos_z.group = anim_group pos_fcurves = (fcurve_pos_x, fcurve_pos_y, fcurve_pos_z) location = None for key_time_i, key_time in enumerate(streams[0]): # print(' key_time: %s' % str(key_time[0])) # keyframe = key_time_i * (key_time[0] * 10) ## TODO: Do proper timing... keyframe = key_time_i + 1 scs_offset = _convert_utils.change_to_scs_xyz_coordinates( custom_channels[channel_name][2][1] [key_time_i], import_scale) offset = Vector(scs_offset) if location is None: location = offset else: location = location + offset # print(' > location: %s' % str(location)) # BUILD TRANSLATION CURVES pos_fcurves[0].keyframe_points.insert( frame=float(keyframe), value=location[0], options={'FAST'}) pos_fcurves[1].keyframe_points.insert( frame=float(keyframe), value=location[1], options={'FAST'}) pos_fcurves[2].keyframe_points.insert( frame=float(keyframe), value=location[2], options={'FAST'}) # SET LINEAR INTERPOLATION FOR ALL CURVES for curve in pos_fcurves: for keyframe in curve.keyframe_points: keyframe.interpolation = 'LINEAR' else: lprint('W Unknown channel %r in "%s" file.', (channel_name, os.path.basename(pia_filepath))) # CREATE SCS ANIMATION animation = _animation_utils.add_animation_to_root( root_object, animation_name) animation.export = True animation.action = anim_action.name animation.anim_start = anim_action.frame_range[0] animation.anim_end = anim_action.frame_range[1] # animation.anim_export_step = # animation.anim_export_filepath = if total_time: animation.length = total_time # WARNING PRINTOUTS # if piece_count < 0: Print(dump_level, '\nW More Pieces found than were declared!') # if piece_count > 0: Print(dump_level, '\nW Some Pieces not found, but were declared!') # if dump_level > 1: print('') else: lprint('I "%s" file REJECTED', (os.path.basename(pia_filepath), )) print("************************************") return {'FINISHED'}
def load(context, filepath): """ :param context: Blender Context currently used for window_manager.update_progress and bpy_object_utils.object_data_add :type context: bpy.types.Context :param filepath: File path to be imported :type filepath: str :return: Return state statuses (Usually 'FINISHED') :rtype: dict """ import time t = time.time() bpy.context.window.cursor_modal_set('WAIT') # import_scale = _get_scs_globals().import_scale # load_textures = _get_scs_globals().load_textures # mesh_creation_type = _get_scs_globals().mesh_creation_type scs_globals = _get_scs_globals() dump_level = int(scs_globals.dump_level) lprint("", report_errors=-1, report_warnings=-1 ) # Clear the 'error_messages' and 'warning_messages' collision_locators = [] prefab_locators = [] loaded_variants = [] objects = [] skinned_objects = [] locators = [] mats_info = [] scs_root_object = skeleton = bones = armature = None # ## NEW SCENE CREATION # if _get_scs_globals().scs_lod_definition_type == 'scenes': # if context.scene.name != 'Scene': # bpy.ops.scene.new(type='NEW') # IMPORT PIM if scs_globals.import_pim_file or scs_globals.import_pis_file: if filepath: if os.path.isfile(filepath): lprint('\nD PIM filepath:\n %s', (filepath.replace("\\", "/"), )) result, objects, skinned_objects, locators, armature, skeleton, mats_info = _pim.load( context, filepath) # print(' armature:\n%s\n skeleton:\n%s' % (str(armature), str(skeleton))) else: lprint('\nI No file found at %r!' % (filepath.replace("\\", "/"), )) else: lprint('\nI No filepath provided!') # IMPORT PIT bpy.context.scene.objects.active = None if scs_globals.import_pit_file: pit_filepath = str(filepath[:-1] + 't') if os.path.isfile(pit_filepath): lprint('\nD PIT filepath:\n %s', (pit_filepath, )) # print('PIT filepath:\n %s' % pit_filepath) result, loaded_variants = _pit.load(pit_filepath, mats_info) else: lprint('\nI No PIT file.') # print('INFO - No PIT file.') # IMPORT PIC if scs_globals.import_pic_file: pic_filepath = str(filepath[:-1] + 'c') if os.path.isfile(pic_filepath): lprint('\nD PIC filepath:\n %s', (pic_filepath, )) # print('PIC filepath:\n %s' % pic_filepath) result, collision_locators = _pic.load(pic_filepath) else: lprint('\nI No PIC file.') # print('INFO - No PIC file.') # IMPORT PIP if scs_globals.import_pip_file: pip_filepath = str(filepath[:-1] + 'p') if os.path.isfile(pip_filepath): lprint('\nD PIP filepath:\n %s', (pip_filepath, )) # print('PIP filepath:\n %s' % pip_filepath) result, prefab_locators = _pip.load(pip_filepath) else: lprint('\nI No PIP file.') # print('INFO - No PIP file.') # SETUP 'SCS GAME OBJECTS' for item in collision_locators: locators.append(item) for item in prefab_locators: locators.append(item) path, file = os.path.split(filepath) # print(' path: %r\n file: %r' % (path, file)) lod_name, ext = os.path.splitext(file) if objects or locators or (armature and skeleton): scs_root_object = _create_scs_root_object(lod_name, loaded_variants, objects, skinned_objects, locators, armature) # IMPORT PIS if scs_globals.import_pis_file: pis_filepath = str(filepath[:-1] + 's') if os.path.isfile(pis_filepath): lprint('\nD PIS filepath:\n %s', (pis_filepath, )) # print('PIS filepath:\n %s' % pis_filepath) bones = _pis.load(pis_filepath, armature) else: bones = None lprint('\nI No PIS file.') # print('INFO - No PIS file.') # IMPORT PIA if scs_globals.import_pis_file and scs_globals.import_pia_file: basepath = os.path.dirname(filepath) # Search for PIA files in model's directory and its subdirectiories... lprint('\nD Searching the directory for PIA files:\n %s', (basepath, )) # print('\nSearching the directory for PIA files:\n %s' % str(basepath)) pia_files = [] index = 0 for root, dirs, files in os.walk(basepath): if not scs_globals.include_subdirs_for_pia: if index > 0: break # print(' root: %s - dirs: %s - files: %s' % (str(root), str(dirs), str(files))) for file in files: if file.endswith(".pia"): pia_filepath = os.path.join(root, file) pia_files.append(pia_filepath) index += 1 if len(pia_files) > 0: lprint('D PIA files found:') for pia_filepath in pia_files: lprint('D %r', pia_filepath) # print('armature: %s\nskeleton: %r\nbones: %s\n' % (str(armature), str(skeleton), str(bones))) _pia.load(scs_root_object, pia_files, armature, skeleton, bones) else: lprint('\nI No PIA files.') # ## SETUP 'SCS GAME OBJECTS' # for item in collision_locators: # locators.append(item) # for item in prefab_locators: # locators.append(item) # path, file = os.path.split(filepath) # print(' path: %r\n file: %r' % (path, file)) # lod_name, ext = os.path.splitext(file) # if objects: # scs_root_object = create_scs_root_object(lod_name, loaded_variants, objects, skinned_objects, locators, armature) # SET OPTIMAL SETTINGS AND DRAW MODES # fix scene objects count so it won't trigger copy cycle bpy.context.scene.scs_cached_num_objects = len(bpy.context.scene.objects) # Turn on Textured Solid in 3D view... for bl_screen in bpy.data.screens: for bl_area in bl_screen.areas: for bl_space in bl_area.spaces: if bl_space.type == 'VIEW_3D': bl_space.show_textured_solid = True # Turn on GLSL in 3D view... bpy.context.scene.game_settings.material_mode = 'GLSL' # Turn on "Frame Dropping" for animation playback... bpy.context.scene.use_frame_drop = True # FINAL FEEDBACK bpy.context.window.cursor_modal_restore() lprint('\nI Import compleeted in %.3f sec.', time.time() - t, report_errors=True, report_warnings=True) return True