diff --git a/blender-for-unrealengine/bfu_import_module/__init__.py b/blender-for-unrealengine/bfu_import_module/__init__.py index 6e6e1994..a7355cce 100644 --- a/blender-for-unrealengine/bfu_import_module/__init__.py +++ b/blender-for-unrealengine/bfu_import_module/__init__.py @@ -18,22 +18,27 @@ import importlib +from . import bps +from . import import_module_utils +from . import import_module_unreal_utils from . import asset_import from . import sequencer_import +if "bps" in locals(): + importlib.reload(bps) +if "import_module_utils" in locals(): + importlib.reload(import_module_utils) +if "import_module_unreal_utils" in locals(): + importlib.reload(import_module_unreal_utils) if "asset_import" in locals(): importlib.reload(asset_import) if "sequencer_import" in locals(): importlib.reload(sequencer_import) - - -print("Import module loaded.") - def run_asset_import(assets_data): - pass - asset_import.ImportAllAssets(assets_data) + if asset_import.ready_for_asset_import(): + return asset_import.ImportAllAssets(assets_data) def run_sequencer_import(sequence_data): - pass - sequencer_import.CreateSequencer(sequence_data) \ No newline at end of file + if sequencer_import.ready_for_sequence_import(): + return sequencer_import.CreateSequencer(sequence_data) \ No newline at end of file diff --git a/blender-for-unrealengine/bfu_import_module/asset_import.py b/blender-for-unrealengine/bfu_import_module/asset_import.py index 9469a76c..b94ba569 100644 --- a/blender-for-unrealengine/bfu_import_module/asset_import.py +++ b/blender-for-unrealengine/bfu_import_module/asset_import.py @@ -1,15 +1,26 @@ -# This script was generated with the addons Blender for UnrealEngine : https://github.com/xavier150/Blender-For-UnrealEngine-Addons -# It will import into Unreal Engine all the assets of type StaticMesh, SkeletalMesh, Animation and Pose -# The script must be used in Unreal Engine Editor with Python plugins : https://docs.unrealengine.com/en-US/Engine/Editor/ScriptingAndAutomation/Python -# Use this command in Unreal cmd consol: py "[ScriptLocation]\ImportSequencerScript.py" +# ====================== BEGIN GPL LICENSE BLOCK ============================ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# All rights reserved. +# +# ======================= END GPL LICENSE BLOCK ============================= - -import sys import os.path -import json -import string -from unittest import result +from . import bps +from . import import_module_utils +from . import import_module_unreal_utils try: # TO DO: Found a better way to check that. import unreal @@ -17,503 +28,463 @@ import unreal_engine as unreal -def CheckTasks(): - if is_unreal_version_greater_or_equal(4,20): # TO DO: EditorAssetLibrary was added in witch version exactly? + +def ready_for_asset_import(): + if import_module_unreal_utils.is_unreal_version_greater_or_equal(4,20): # TO DO: EditorAssetLibrary was added in witch version exactly? if not hasattr(unreal, 'EditorAssetLibrary'): - print('--------------------------------------------------') - print('WARNING: Editor Scripting Utilities should be activated.') - print('Edit > Plugin > Scripting > Editor Scripting Utilities.') + message = 'WARNING: Editor Scripting Utilities should be activated.' + "\n" + message += 'Edit > Plugin > Scripting > Editor Scripting Utilities.' + import_module_unreal_utils.show_warning_message("Editor Scripting Utilities not activated.", message) return False return True -def JsonLoad(json_file): - # Changed in Python 3.9: The keyword argument encoding has been removed. - if sys.version_info >= (3, 9): - return json.load(json_file) - else: - return json.load(json_file, encoding="utf8") -def JsonLoadFile(json_file_path): - if sys.version_info[0] < 3: - with open(json_file_path, "r") as json_file: - return JsonLoad(json_file) - else: - with open(json_file_path, "r", encoding="utf8") as json_file: - return JsonLoad(json_file) +def ImportAsset(asset_data): -def get_unreal_version(): - version_info = unreal.SystemLibrary.get_engine_version().split('-')[0] - version_numbers = version_info.split('.') - major = int(version_numbers[0]) - minor = int(version_numbers[1]) - patch = int(version_numbers[2]) - return major, minor, patch + if asset_data["asset_type"] == "StaticMesh" or asset_data["asset_type"] == "SkeletalMesh": + if "lod" in asset_data: + if asset_data["lod"] > 0: # Lod should not be imported here so return if lod is not 0. + return -def is_unreal_version_greater_or_equal(target_major, target_minor=0, target_patch=0): - major, minor, patch = get_unreal_version() - - if major > target_major or (major == target_major and minor >= target_minor) or (major == target_major and minor == target_minor and patch >= target_patch): - return True + if asset_data["asset_type"] == "Alembic": + FileType = "ABC" else: - return False + FileType = "FBX" + def GetAdditionalData(): + if "additional_tracks_path" in asset_data: + if asset_data["additional_tracks_path"] is not None: + return import_module_utils.JsonLoadFile(asset_data["additional_tracks_path"]) + return None -def ImportAllAssets(assets_data): + additional_data = GetAdditionalData() - # Prepare process import - json_data_file = 'ImportAssetData.json' - dir_path = os.path.dirname(os.path.realpath(__file__)) - assets_data - bfu_unreal_import_location = assets_data['bfu_unreal_import_location'] - ImportedList = [] - ImportFailList = [] + if asset_data["asset_type"] == "Animation" or asset_data["asset_type"] == "SkeletalMesh": + find_asset = unreal.find_asset(asset_data["animation_skeleton_path"]) + if isinstance(find_asset, unreal.Skeleton): + OriginSkeleton = find_asset + elif isinstance(find_asset, unreal.SkeletalMesh): + OriginSkeleton = find_asset.skeleton + else: + OriginSkeleton = None + if OriginSkeleton: + pass + #print("Setting skeleton asset: " + OriginSkeleton.get_full_name()) + else: + message = "Could not find skeleton at the path: " + asset_data["animation_skeleton_path"] + import_module_unreal_utils.show_warning_message("Skeleton not found.", message) - def ValidUnrealAssetsName(filename): - # Normalizes string, removes non-alpha characters - # Asset name in Unreal use + # docs.unrealengine.com/4.26/en-US/PythonAPI/class/AssetImportTask.html + task = unreal.AssetImportTask() - filename = filename.replace('.', '_') - filename = filename.replace('(', '_') - filename = filename.replace(')', '_') - filename = filename.replace(' ', '_') - valid_chars = "-_%s%s" % (string.ascii_letters, string.digits) - filename = ''.join(c for c in filename if c in valid_chars) - return filename + def GetStaticMeshImportData(): + if asset_data["asset_type"] == "StaticMesh": + return task.get_editor_property('options').static_mesh_import_data + return None - def GetAssetByType(type): - target_assets = [] - for asset in assets_data["assets"]: - if asset["asset_type"] == type: - target_assets.append(asset) - return target_assets + def GetSkeletalMeshImportData(): + if asset_data["asset_type"] == "SkeletalMesh": + return task.get_editor_property('options').skeletal_mesh_import_data + return None - def ImportAsset(asset_data): - - counter = str(len(ImportedList)+1) + "/" + str(len(assets_data["assets"])) - print("Import asset " + counter + ": ", asset_data["asset_name"]) - - if asset_data["asset_type"] == "StaticMesh" or asset_data["asset_type"] == "SkeletalMesh": - if "lod" in asset_data: - if asset_data["lod"] > 0: # Lod should not be imported here so return if lod is not 0. - return + def GetAnimationImportData(): + if asset_data["asset_type"] == "Animation": + return task.get_editor_property('options').anim_sequence_import_data + return None + def GetAlembicImportData(): if asset_data["asset_type"] == "Alembic": - FileType = "ABC" - else: - FileType = "FBX" - - def GetAdditionalData(): - if "additional_tracks_path" in asset_data: - if asset_data["additional_tracks_path"] is not None: - return JsonLoadFile(asset_data["additional_tracks_path"]) - return None + return task.get_editor_property('options') + return None - additional_data = GetAdditionalData() + def GetMeshImportData(): + if asset_data["asset_type"] == "StaticMesh": + return GetStaticMeshImportData() + if asset_data["asset_type"] == "SkeletalMesh": + return GetSkeletalMeshImportData() + return None - def ImportTask(): - # New import task - # Property + if asset_data["asset_type"] == "Alembic": + task.filename = asset_data["abc_path"] + else: + task.filename = asset_data["fbx_path"] + task.destination_path = os.path.normpath(asset_data["full_import_path"]).replace('\\', '/') + task.automated = True + # task.automated = False #Debug for show dialog + task.save = True + task.replace_existing = True + + if asset_data["asset_type"] == "Alembic": + task.set_editor_property('options', unreal.AbcImportSettings()) + else: + task.set_editor_property('options', unreal.FbxImportUI()) + + # Alembic + if GetAlembicImportData(): + GetAlembicImportData().static_mesh_settings.set_editor_property("merge_meshes", True) + GetAlembicImportData().set_editor_property("import_type", unreal.AlembicImportType.SKELETAL) + GetAlembicImportData().conversion_settings.set_editor_property("flip_u", False) + GetAlembicImportData().conversion_settings.set_editor_property("flip_v", True) + scale = asset_data["scene_unit_scale"] * asset_data["asset_global_scale"] + ue_scale = unreal.Vector(scale * 100, scale * -100, scale * 100) # Unit scale * object scale * 100 + rotation = unreal.Vector(90, 0, 0) + GetAlembicImportData().conversion_settings.set_editor_property("scale", ue_scale) + GetAlembicImportData().conversion_settings.set_editor_property("rotation", rotation) + + # Vertex color + vertex_override_color = None + vertex_color_import_option = None + if additional_data: + + vertex_color_import_option = unreal.VertexColorImportOption.REPLACE # Default + if "vertex_color_import_option" in additional_data: + if additional_data["vertex_color_import_option"] == "IGNORE": + vertex_color_import_option = unreal.VertexColorImportOption.IGNORE + elif additional_data["vertex_color_import_option"] == "OVERRIDE": + vertex_color_import_option = unreal.VertexColorImportOption.OVERRIDE + elif additional_data["vertex_color_import_option"] == "REPLACE": + vertex_color_import_option = unreal.VertexColorImportOption.REPLACE + + if "vertex_override_color" in additional_data: + vertex_override_color = unreal.LinearColor( + additional_data["vertex_override_color"][0], + additional_data["vertex_override_color"][1], + additional_data["vertex_override_color"][2] + ) + + # #################################[Change] + + # unreal.FbxImportUI + # https://docs.unrealengine.com/4.26/en-US/PythonAPI/class/FbxImportUI.html + + # Import transform + anim_sequence_import_data = GetAnimationImportData() + if anim_sequence_import_data: + anim_sequence_import_data.import_translation = unreal.Vector(0, 0, 0) + + # Vertex color + if vertex_color_import_option and GetMeshImportData(): + GetMeshImportData().set_editor_property('vertex_color_import_option', vertex_color_import_option) + + if vertex_override_color and GetMeshImportData(): + GetMeshImportData().set_editor_property('vertex_override_color', vertex_override_color.to_rgbe()) + + if asset_data["asset_type"] == "Alembic": + task.get_editor_property('options').set_editor_property('import_type', unreal.AlembicImportType.SKELETAL) - if asset_data["asset_type"] == "Animation" or asset_data["asset_type"] == "SkeletalMesh": - find_asset = unreal.find_asset(asset_data["animation_skeleton_path"]) - if isinstance(find_asset, unreal.Skeleton): - OriginSkeleton = find_asset - elif isinstance(find_asset, unreal.SkeletalMesh): - OriginSkeleton = find_asset.skeleton - else: - OriginSkeleton = None - if OriginSkeleton: - print("Setting skeleton asset: " + OriginSkeleton.get_full_name()) + else: + if asset_data["asset_type"] == "Animation" or asset_data["asset_type"] == "SkeletalMesh": + if OriginSkeleton: + task.get_editor_property('options').set_editor_property('Skeleton', OriginSkeleton) + else: + if asset_data["asset_type"] == "Animation": + fail_reason = 'Skeleton ' + asset_data["animation_skeleton_path"] + ' Not found for ' + asset_data["asset_name"] + ' asset.' + return fail_reason else: - print("Could not find skeleton at the path: " + asset_data["animation_skeleton_path"]) + print("Skeleton is not set, a new skeleton asset will be created...") - # docs.unrealengine.com/4.26/en-US/PythonAPI/class/AssetImportTask.html - task = unreal.AssetImportTask() - def GetStaticMeshImportData(): - if asset_data["asset_type"] == "StaticMesh": - return task.get_editor_property('options').static_mesh_import_data - return None + if asset_data["asset_type"] == "StaticMesh": + task.get_editor_property('options').set_editor_property('original_import_type', unreal.FBXImportType.FBXIT_STATIC_MESH) + elif asset_data["asset_type"] == "Animation": + task.get_editor_property('options').set_editor_property('original_import_type', unreal.FBXImportType.FBXIT_ANIMATION) + else: + task.get_editor_property('options').set_editor_property('original_import_type', unreal.FBXImportType.FBXIT_SKELETAL_MESH) - def GetSkeletalMeshImportData(): - if asset_data["asset_type"] == "SkeletalMesh": - return task.get_editor_property('options').skeletal_mesh_import_data - return None + if asset_data["asset_type"] == "Animation": + task.get_editor_property('options').set_editor_property('import_materials', False) + else: + task.get_editor_property('options').set_editor_property('import_materials', True) - def GetAnimationImportData(): - if asset_data["asset_type"] == "Animation": - return task.get_editor_property('options').anim_sequence_import_data - return None + task.get_editor_property('options').set_editor_property('import_textures', False) - def GetAlembicImportData(): - if asset_data["asset_type"] == "Alembic": - return task.get_editor_property('options') - return None + if asset_data["asset_type"] == "Animation": - def GetMeshImportData(): - if asset_data["asset_type"] == "StaticMesh": - return GetStaticMeshImportData() - if asset_data["asset_type"] == "SkeletalMesh": - return GetSkeletalMeshImportData() + task.get_editor_property('options').set_editor_property('import_animations', True) + task.get_editor_property('options').set_editor_property('import_mesh', False) + task.get_editor_property('options').set_editor_property('create_physics_asset',False) + else: + task.get_editor_property('options').set_editor_property('import_animations', False) + task.get_editor_property('options').set_editor_property('import_mesh', True) + if "create_physics_asset" in asset_data: + task.get_editor_property('options').set_editor_property('create_physics_asset', asset_data["create_physics_asset"]) - return None + # unreal.FbxMeshImportData - if asset_data["asset_type"] == "Alembic": - task.filename = asset_data["abc_path"] - else: - task.filename = asset_data["fbx_path"] - task.destination_path = os.path.normpath(asset_data["full_import_path"]).replace('\\', '/') - task.automated = True - # task.automated = False #Debug for show dialog - task.save = True - task.replace_existing = True - - if asset_data["asset_type"] == "Alembic": - task.set_editor_property('options', unreal.AbcImportSettings()) + if asset_data["asset_type"] == "StaticMesh" or asset_data["asset_type"] == "SkeletalMesh": + if "material_search_location" in asset_data: + # unreal.FbxTextureImportData + if asset_data["material_search_location"] == "Local": + task.get_editor_property('options').texture_import_data.set_editor_property('material_search_location', unreal.MaterialSearchLocation.LOCAL) + if asset_data["material_search_location"] == "UnderParent": + task.get_editor_property('options').texture_import_data.set_editor_property('material_search_location', unreal.MaterialSearchLocation.UNDER_PARENT) + if asset_data["material_search_location"] == "UnderRoot": + task.get_editor_property('options').texture_import_data.set_editor_property('material_search_location', unreal.MaterialSearchLocation.UNDER_ROOT) + if asset_data["material_search_location"] == "AllAssets": + task.get_editor_property('options').texture_import_data.set_editor_property('material_search_location', unreal.MaterialSearchLocation.ALL_ASSETS) + + if asset_data["asset_type"] == "StaticMesh": + # unreal.FbxStaticMeshImportData + task.get_editor_property('options').static_mesh_import_data.set_editor_property('combine_meshes', True) + if "auto_generate_collision" in asset_data: + task.get_editor_property('options').static_mesh_import_data.set_editor_property('auto_generate_collision', asset_data["auto_generate_collision"]) + if "static_mesh_lod_group" in asset_data: + if asset_data["static_mesh_lod_group"]: + task.get_editor_property('options').static_mesh_import_data.set_editor_property('static_mesh_lod_group', asset_data["static_mesh_lod_group"]) + if "generate_lightmap_u_vs" in asset_data: + task.get_editor_property('options').static_mesh_import_data.set_editor_property('generate_lightmap_u_vs', asset_data["generate_lightmap_u_vs"]) + + if asset_data["asset_type"] == "SkeletalMesh" or asset_data["asset_type"] == "Animation": + # unreal.FbxSkeletalMeshImportData + task.get_editor_property('options').skeletal_mesh_import_data.set_editor_property('import_morph_targets', True) + task.get_editor_property('options').skeletal_mesh_import_data.set_editor_property('convert_scene', True) + task.get_editor_property('options').skeletal_mesh_import_data.set_editor_property('normal_import_method', unreal.FBXNormalImportMethod.FBXNIM_IMPORT_NORMALS_AND_TANGENTS) + + # ###############[ pre import ]################ + + # Check is the file alredy exit + if additional_data: + if "preview_import_path" in additional_data: + task_asset_full_path = task.destination_path+"/"+additional_data["preview_import_path"]+"."+additional_data["preview_import_path"] + find_asset = unreal.find_asset(task_asset_full_path) + if find_asset: + + # Vertex color + + asset_import_data = find_asset.get_editor_property('asset_import_data') + if vertex_color_import_option: + asset_import_data.set_editor_property('vertex_color_import_option', vertex_color_import_option) + + if vertex_override_color: + asset_import_data.set_editor_property('vertex_override_color', vertex_override_color.to_rgbe()) + + # ###############[ import asset ]################ + + if asset_data["asset_type"] == "Animation": + # For animation the script will import a skeletal mesh and remove after. + # If the skeletal mesh alredy exist try to remove. + + + AssetName = asset_data["asset_name"] + AssetName = import_module_unreal_utils.ValidUnrealAssetsName(AssetName) + AssetPath = "SkeletalMesh'"+asset_data["full_import_path"]+"/"+AssetName+"."+AssetName+"'" + + if unreal.EditorAssetLibrary.does_asset_exist(AssetPath): + oldAsset = unreal.EditorAssetLibrary.find_asset_data(AssetPath) + if oldAsset.asset_class == "SkeletalMesh": + unreal.EditorAssetLibrary.delete_asset(AssetPath) + + unreal.AssetToolsHelpers.get_asset_tools().import_asset_tasks([task]) + + if len(task.imported_object_paths) > 0: + asset = unreal.find_asset(task.imported_object_paths[0]) + else: + asset = None + + if asset is None: + fail_reason = 'Error zero imported object for: ' + asset_data["asset_name"] + return fail_reason + + if asset_data["asset_type"] == "Animation": + # For animation remove the extra mesh + p = task.imported_object_paths[0] + if type(unreal.find_asset(p)) is not unreal.AnimSequence: + animAssetName = p.split('.')[0]+'_anim.'+p.split('.')[1]+'_anim' + animAssetNameDesiredPath = p.split('.')[0]+'.'+p.split('.')[1] + animAsset = unreal.find_asset(animAssetName) + if animAsset is not None: + unreal.EditorAssetLibrary.delete_asset(p) + unreal.EditorAssetLibrary.rename_asset(animAssetName, animAssetNameDesiredPath) + asset = animAsset else: - task.set_editor_property('options', unreal.FbxImportUI()) - - # Alembic - if GetAlembicImportData(): - GetAlembicImportData().static_mesh_settings.set_editor_property("merge_meshes", True) - GetAlembicImportData().set_editor_property("import_type", unreal.AlembicImportType.SKELETAL) - GetAlembicImportData().conversion_settings.set_editor_property("flip_u", False) - GetAlembicImportData().conversion_settings.set_editor_property("flip_v", True) - scale = asset_data["scene_unit_scale"] * asset_data["asset_global_scale"] - ue_scale = unreal.Vector(scale * 100, scale * -100, scale * 100) # Unit scale * object scale * 100 - rotation = unreal.Vector(90, 0, 0) - GetAlembicImportData().conversion_settings.set_editor_property("scale", ue_scale) - GetAlembicImportData().conversion_settings.set_editor_property("rotation", rotation) - - # Vertex color - vertex_override_color = None - vertex_color_import_option = None - if additional_data: - - vertex_color_import_option = unreal.VertexColorImportOption.REPLACE # Default - if "vertex_color_import_option" in additional_data: - if additional_data["vertex_color_import_option"] == "IGNORE": - vertex_color_import_option = unreal.VertexColorImportOption.IGNORE - elif additional_data["vertex_color_import_option"] == "OVERRIDE": - vertex_color_import_option = unreal.VertexColorImportOption.OVERRIDE - elif additional_data["vertex_color_import_option"] == "REPLACE": - vertex_color_import_option = unreal.VertexColorImportOption.REPLACE - - if "vertex_override_color" in additional_data: - vertex_override_color = unreal.LinearColor( - additional_data["vertex_override_color"][0], - additional_data["vertex_override_color"][1], - additional_data["vertex_override_color"][2] - ) - - # #################################[Change] - - # unreal.FbxImportUI - # https://docs.unrealengine.com/4.26/en-US/PythonAPI/class/FbxImportUI.html - - # Import transform - anim_sequence_import_data = GetAnimationImportData() - if anim_sequence_import_data: - anim_sequence_import_data.import_translation = unreal.Vector(0, 0, 0) - - # Vertex color - if vertex_color_import_option and GetMeshImportData(): - GetMeshImportData().set_editor_property('vertex_color_import_option', vertex_color_import_option) - - if vertex_override_color and GetMeshImportData(): - GetMeshImportData().set_editor_property('vertex_override_color', vertex_override_color.to_rgbe()) - - if asset_data["asset_type"] == "Alembic": - task.get_editor_property('options').set_editor_property('import_type', unreal.AlembicImportType.SKELETAL) + fail_reason = 'animAsset ' + asset_data["asset_name"] + ' not found for after inport: ' + animAssetName + return fail_reason + + # ###############[ Post treatment ]################ + asset_import_data = asset.get_editor_property('asset_import_data') + if asset_data["asset_type"] == "StaticMesh": + if "static_mesh_lod_group" in asset_data: + if asset_data["static_mesh_lod_group"]: + asset.set_editor_property('lod_group', asset_data["static_mesh_lod_group"]) + if "use_custom_light_map_resolution" in asset_data: + if asset_data["use_custom_light_map_resolution"]: + if "light_map_resolution" in asset_data: + asset.set_editor_property('light_map_resolution', asset_data["light_map_resolution"]) + build_settings = unreal.EditorStaticMeshLibrary.get_lod_build_settings(asset, 0) + build_settings.min_lightmap_resolution = asset_data["light_map_resolution"] + unreal.EditorStaticMeshLibrary.set_lod_build_settings(asset, 0, build_settings) + + if "collision_trace_flag" in asset_data: + collision_data = asset.get_editor_property('body_setup') + if collision_data: + if asset_data["collision_trace_flag"] == "CTF_UseDefault": + collision_data.set_editor_property('collision_trace_flag', unreal.CollisionTraceFlag.CTF_USE_DEFAULT) + elif asset_data["collision_trace_flag"] == "CTF_UseSimpleAndComplex": + collision_data.set_editor_property('collision_trace_flag', unreal.CollisionTraceFlag.CTF_USE_SIMPLE_AND_COMPLEX) + elif asset_data["collision_trace_flag"] == "CTF_UseSimpleAsComplex": + collision_data.set_editor_property('collision_trace_flag', unreal.CollisionTraceFlag.CTF_USE_SIMPLE_AS_COMPLEX) + elif asset_data["collision_trace_flag"] == "CTF_UseComplexAsSimple": + collision_data.set_editor_property('collision_trace_flag', unreal.CollisionTraceFlag.CTF_USE_COMPLEX_AS_SIMPLE) + + + if asset_data["asset_type"] == "StaticMesh": + if "generate_lightmap_u_vs" in asset_data: + asset_import_data.set_editor_property('generate_lightmap_u_vs', asset_data["generate_lightmap_u_vs"]) # Import data + unreal.EditorStaticMeshLibrary.set_generate_lightmap_uv(asset, asset_data["generate_lightmap_u_vs"]) # Build settings at lod + + if asset_data["asset_type"] == "SkeletalMesh": + asset_import_data.set_editor_property('normal_import_method', unreal.FBXNormalImportMethod.FBXNIM_IMPORT_NORMALS_AND_TANGENTS) + if OriginSkeleton is None: + #Unreal create a new skeleton when no skeleton was selected, so addon rename it. + p = task.imported_object_paths[0] + old_skeleton_name = p.split('.')[0]+'_Skeleton.'+p.split('.')[1]+'_Skeleton' + new_skeleton_name = asset_data["animation_skeleton_path"] + unreal.EditorAssetLibrary.rename_asset(old_skeleton_name, new_skeleton_name) + + if "enable_skeletal_mesh_per_poly_collision" in asset_data: + asset.set_editor_property('enable_per_poly_collision', asset_data["enable_skeletal_mesh_per_poly_collision"]) + + + # Socket + if asset_data["asset_type"] == "SkeletalMesh": + # Import the SkeletalMesh socket(s) + sockets_to_add = additional_data["Sockets"] + for socket in sockets_to_add: + old_socket = asset.find_socket(socket["SocketName"]) + if old_socket: + # Edit socket + pass + # old_socket.relative_location = socket["Location"] + # old_socket.relative_rotation = socket["Rotation"] + # old_socket.relative_scale = socket["Scale"] else: - if asset_data["asset_type"] == "Animation" or asset_data["asset_type"] == "SkeletalMesh": - if OriginSkeleton: - task.get_editor_property('options').set_editor_property('Skeleton', OriginSkeleton) - else: - if asset_data["asset_type"] == "Animation": - ImportFailList.append('Skeleton ' + asset_data["animation_skeleton_path"] + ' Not found for ' + asset_data["asset_name"] + ' asset.') - return + # Create socket + pass + # new_socket = unreal.SkeletalMeshSocket(asset) + # new_socket.socket_name = socket["SocketName"] + # new_socket.bone_name = socket["BoneName"] + # new_socket.relative_location = socket["Location"] + # new_socket.relative_rotation = socket["Rotation"] + # new_socket.relative_scale = socket["Scale"] + # NEED UNREAL ENGINE IMPLEMENTATION IN PYTHON API. + # skeleton.add_socket(new_socket) + + # Lod + if asset_data["asset_type"] == "StaticMesh" or asset_data["asset_type"] == "SkeletalMesh": + if asset_data["asset_type"] == "StaticMesh": + unreal.EditorStaticMeshLibrary.remove_lods(asset) # Import the StaticMesh lod(s) + + if asset_data["asset_type"] == "SkeletalMesh" or asset_data["asset_type"] == "StaticMesh": + + def ImportStaticLod(lod_name, lod_number): + if "LevelOfDetail" in additional_data: + if lod_name in additional_data["LevelOfDetail"]: + lodTask = unreal.AssetImportTask() + lodTask.filename = additional_data["LevelOfDetail"][lod_name] + destination_path = os.path.normpath(asset_data["full_import_path"]).replace('\\', '/') + lodTask.destination_path = destination_path + lodTask.automated = True + lodTask.replace_existing = True + + # Set vertex color import settings to replicate base StaticMesh's behaviour + if asset_data["asset_type"] == "Alembic": + lodTask.set_editor_property('options', unreal.AbcImportSettings()) else: - print("Skeleton is not set, a new skeleton asset will be created...") + lodTask.set_editor_property('options', unreal.FbxImportUI()) + lodTask.get_editor_property('options').static_mesh_import_data.set_editor_property('vertex_color_import_option', vertex_color_import_option) + lodTask.get_editor_property('options').static_mesh_import_data.set_editor_property('vertex_override_color', vertex_override_color.to_rgbe()) - if asset_data["asset_type"] == "StaticMesh": - task.get_editor_property('options').set_editor_property('original_import_type', unreal.FBXImportType.FBXIT_STATIC_MESH) - elif asset_data["asset_type"] == "Animation": - task.get_editor_property('options').set_editor_property('original_import_type', unreal.FBXImportType.FBXIT_ANIMATION) - else: - task.get_editor_property('options').set_editor_property('original_import_type', unreal.FBXImportType.FBXIT_SKELETAL_MESH) + unreal.AssetToolsHelpers.get_asset_tools().import_asset_tasks([lodTask]) + if len(lodTask.imported_object_paths) > 0: + lodAsset = unreal.find_asset(lodTask.imported_object_paths[0]) + slot_replaced = unreal.EditorStaticMeshLibrary.set_lod_from_static_mesh(asset, lod_number, lodAsset, 0, True) + unreal.EditorAssetLibrary.delete_asset(lodTask.imported_object_paths[0]) - if asset_data["asset_type"] == "Animation": - task.get_editor_property('options').set_editor_property('import_materials', False) - else: - task.get_editor_property('options').set_editor_property('import_materials', True) + def ImportSkeletalLod(lod_name, lod_number): + if "LevelOfDetail" in additional_data: + if lod_name in additional_data["LevelOfDetail"]: + # Unreal python no longer support Skeletal mesh LODS import. + pass - task.get_editor_property('options').set_editor_property('import_textures', False) + if asset_data["asset_type"] == "StaticMesh": + ImportStaticLod("lod_1", 1) + ImportStaticLod("lod_2", 2) + ImportStaticLod("lod_3", 3) + ImportStaticLod("lod_4", 4) + ImportStaticLod("lod_5", 5) - if asset_data["asset_type"] == "Animation": + elif asset_data["asset_type"] == "SkeletalMesh": + ImportSkeletalLod("lod_1", 1) + ImportSkeletalLod("lod_2", 2) + ImportSkeletalLod("lod_3", 3) + ImportSkeletalLod("lod_4", 4) + ImportSkeletalLod("lod_5", 5) - task.get_editor_property('options').set_editor_property('import_animations', True) - task.get_editor_property('options').set_editor_property('import_mesh', False) - task.get_editor_property('options').set_editor_property('create_physics_asset',False) - else: - task.get_editor_property('options').set_editor_property('import_animations', False) - task.get_editor_property('options').set_editor_property('import_mesh', True) - if "create_physics_asset" in asset_data: - task.get_editor_property('options').set_editor_property('create_physics_asset', asset_data["create_physics_asset"]) - - # unreal.FbxMeshImportData - - if asset_data["asset_type"] == "StaticMesh" or asset_data["asset_type"] == "SkeletalMesh": - if "material_search_location" in asset_data: - # unreal.FbxTextureImportData - if asset_data["material_search_location"] == "Local": - task.get_editor_property('options').texture_import_data.set_editor_property('material_search_location', unreal.MaterialSearchLocation.LOCAL) - if asset_data["material_search_location"] == "UnderParent": - task.get_editor_property('options').texture_import_data.set_editor_property('material_search_location', unreal.MaterialSearchLocation.UNDER_PARENT) - if asset_data["material_search_location"] == "UnderRoot": - task.get_editor_property('options').texture_import_data.set_editor_property('material_search_location', unreal.MaterialSearchLocation.UNDER_ROOT) - if asset_data["material_search_location"] == "AllAssets": - task.get_editor_property('options').texture_import_data.set_editor_property('material_search_location', unreal.MaterialSearchLocation.ALL_ASSETS) - - if asset_data["asset_type"] == "StaticMesh": - # unreal.FbxStaticMeshImportData - task.get_editor_property('options').static_mesh_import_data.set_editor_property('combine_meshes', True) - if "auto_generate_collision" in asset_data: - task.get_editor_property('options').static_mesh_import_data.set_editor_property('auto_generate_collision', asset_data["auto_generate_collision"]) - if "static_mesh_lod_group" in asset_data: - if asset_data["static_mesh_lod_group"]: - task.get_editor_property('options').static_mesh_import_data.set_editor_property('static_mesh_lod_group', asset_data["static_mesh_lod_group"]) - if "generate_lightmap_u_vs" in asset_data: - task.get_editor_property('options').static_mesh_import_data.set_editor_property('generate_lightmap_u_vs', asset_data["generate_lightmap_u_vs"]) - - if asset_data["asset_type"] == "SkeletalMesh" or asset_data["asset_type"] == "Animation": - # unreal.FbxSkeletalMeshImportData - task.get_editor_property('options').skeletal_mesh_import_data.set_editor_property('import_morph_targets', True) - task.get_editor_property('options').skeletal_mesh_import_data.set_editor_property('convert_scene', True) - task.get_editor_property('options').skeletal_mesh_import_data.set_editor_property('normal_import_method', unreal.FBXNormalImportMethod.FBXNIM_IMPORT_NORMALS_AND_TANGENTS) - - # ###############[ pre import ]################ - - # Check is the file alredy exit - if additional_data: - if "preview_import_path" in additional_data: - task_asset_full_path = task.destination_path+"/"+additional_data["preview_import_path"]+"."+additional_data["preview_import_path"] - find_asset = unreal.find_asset(task_asset_full_path) - if find_asset: - - # Vertex color - - asset_import_data = find_asset.get_editor_property('asset_import_data') - if vertex_color_import_option: - asset_import_data.set_editor_property('vertex_color_import_option', vertex_color_import_option) - - if vertex_override_color: - asset_import_data.set_editor_property('vertex_override_color', vertex_override_color.to_rgbe()) - - # ###############[ import asset ]################ - - print("Import task") - if asset_data["asset_type"] == "Animation": - # For animation the script will import a skeletal mesh and remove after. - # If the skeletal mesh alredy exist try to remove. - - - AssetName = asset_data["asset_name"] - AssetName = ValidUnrealAssetsName(AssetName) - AssetPath = "SkeletalMesh'"+asset_data["full_import_path"]+"/"+AssetName+"."+AssetName+"'" - - if unreal.EditorAssetLibrary.does_asset_exist(AssetPath): - oldAsset = unreal.EditorAssetLibrary.find_asset_data(AssetPath) - if oldAsset.asset_class == "SkeletalMesh": - unreal.EditorAssetLibrary.delete_asset(AssetPath) - - unreal.AssetToolsHelpers.get_asset_tools().import_asset_tasks([task]) - - if len(task.imported_object_paths) > 0: - asset = unreal.find_asset(task.imported_object_paths[0]) - else: - asset = None + # Vertex color + if vertex_override_color: + asset_import_data.set_editor_property('vertex_override_color', vertex_override_color.to_rgbe()) - if asset is None: - ImportFailList.append('Error zero imported object for: ' + asset_data["asset_name"]) - return + if vertex_color_import_option: + asset_import_data.set_editor_property('vertex_color_import_option', vertex_color_import_option) - if asset_data["asset_type"] == "Animation": - # For animation remove the extra mesh - p = task.imported_object_paths[0] - if type(unreal.find_asset(p)) is not unreal.AnimSequence: - animAssetName = p.split('.')[0]+'_anim.'+p.split('.')[1]+'_anim' - animAssetNameDesiredPath = p.split('.')[0]+'.'+p.split('.')[1] - animAsset = unreal.find_asset(animAssetName) - if animAsset is not None: - unreal.EditorAssetLibrary.delete_asset(p) - unreal.EditorAssetLibrary.rename_asset(animAssetName, animAssetNameDesiredPath) - asset = animAsset - else: - ImportFailList.append('animAsset ' + asset_data["asset_name"] + ' not found for after inport: ' + animAssetName) - return - - # ###############[ Post treatment ]################ - asset_import_data = asset.get_editor_property('asset_import_data') - if asset_data["asset_type"] == "StaticMesh": - if "static_mesh_lod_group" in asset_data: - if asset_data["static_mesh_lod_group"]: - asset.set_editor_property('lod_group', asset_data["static_mesh_lod_group"]) - if "use_custom_light_map_resolution" in asset_data: - if asset_data["use_custom_light_map_resolution"]: - if "light_map_resolution" in asset_data: - asset.set_editor_property('light_map_resolution', asset_data["light_map_resolution"]) - build_settings = unreal.EditorStaticMeshLibrary.get_lod_build_settings(asset, 0) - build_settings.min_lightmap_resolution = asset_data["light_map_resolution"] - unreal.EditorStaticMeshLibrary.set_lod_build_settings(asset, 0, build_settings) - - if "collision_trace_flag" in asset_data: - collision_data = asset.get_editor_property('body_setup') - if collision_data: - if asset_data["collision_trace_flag"] == "CTF_UseDefault": - collision_data.set_editor_property('collision_trace_flag', unreal.CollisionTraceFlag.CTF_USE_DEFAULT) - elif asset_data["collision_trace_flag"] == "CTF_UseSimpleAndComplex": - collision_data.set_editor_property('collision_trace_flag', unreal.CollisionTraceFlag.CTF_USE_SIMPLE_AND_COMPLEX) - elif asset_data["collision_trace_flag"] == "CTF_UseSimpleAsComplex": - collision_data.set_editor_property('collision_trace_flag', unreal.CollisionTraceFlag.CTF_USE_SIMPLE_AS_COMPLEX) - elif asset_data["collision_trace_flag"] == "CTF_UseComplexAsSimple": - collision_data.set_editor_property('collision_trace_flag', unreal.CollisionTraceFlag.CTF_USE_COMPLEX_AS_SIMPLE) + # #################################[EndChange] + if asset_data["asset_type"] == "StaticMesh" or asset_data["asset_type"] == "SkeletalMesh": + unreal.EditorAssetLibrary.save_loaded_asset(asset) + return "SUCCESS", asset, asset_data["asset_type"] - if asset_data["asset_type"] == "StaticMesh": - if "generate_lightmap_u_vs" in asset_data: - asset_import_data.set_editor_property('generate_lightmap_u_vs', asset_data["generate_lightmap_u_vs"]) # Import data - unreal.EditorStaticMeshLibrary.set_generate_lightmap_uv(asset, asset_data["generate_lightmap_u_vs"]) # Build settings at lod - - if asset_data["asset_type"] == "SkeletalMesh": - asset_import_data.set_editor_property('normal_import_method', unreal.FBXNormalImportMethod.FBXNIM_IMPORT_NORMALS_AND_TANGENTS) - if OriginSkeleton is None: - #Unreal create a new skeleton when no skeleton was selected, so addon rename it. - p = task.imported_object_paths[0] - old_skeleton_name = p.split('.')[0]+'_Skeleton.'+p.split('.')[1]+'_Skeleton' - new_skeleton_name = asset_data["animation_skeleton_path"] - unreal.EditorAssetLibrary.rename_asset(old_skeleton_name, new_skeleton_name) - - if "enable_skeletal_mesh_per_poly_collision" in asset_data: - asset.set_editor_property('enable_per_poly_collision', asset_data["enable_skeletal_mesh_per_poly_collision"]) - - - # Socket - if asset_data["asset_type"] == "SkeletalMesh": - # Import the SkeletalMesh socket(s) - sockets_to_add = additional_data["Sockets"] - for socket in sockets_to_add: - old_socket = asset.find_socket(socket["SocketName"]) - if old_socket: - # Edit socket - pass - # old_socket.relative_location = socket["Location"] - # old_socket.relative_rotation = socket["Rotation"] - # old_socket.relative_scale = socket["Scale"] - else: - # Create socket - pass - # new_socket = unreal.SkeletalMeshSocket(asset) - # new_socket.socket_name = socket["SocketName"] - # new_socket.bone_name = socket["BoneName"] - # new_socket.relative_location = socket["Location"] - # new_socket.relative_rotation = socket["Rotation"] - # new_socket.relative_scale = socket["Scale"] - # NEED UNREAL ENGINE IMPLEMENTATION IN PYTHON API. - # skeleton.add_socket(new_socket) - - # Lod - if asset_data["asset_type"] == "StaticMesh" or asset_data["asset_type"] == "SkeletalMesh": - if asset_data["asset_type"] == "StaticMesh": - unreal.EditorStaticMeshLibrary.remove_lods(asset) # Import the StaticMesh lod(s) - - if asset_data["asset_type"] == "SkeletalMesh" or asset_data["asset_type"] == "StaticMesh": - - def ImportStaticLod(lod_name, lod_number): - if "LevelOfDetail" in additional_data: - if lod_name in additional_data["LevelOfDetail"]: - lodTask = unreal.AssetImportTask() - lodTask.filename = additional_data["LevelOfDetail"][lod_name] - destination_path = os.path.normpath(asset_data["full_import_path"]).replace('\\', '/') - lodTask.destination_path = destination_path - lodTask.automated = True - lodTask.replace_existing = True - - # Set vertex color import settings to replicate base StaticMesh's behaviour - if asset_data["asset_type"] == "Alembic": - lodTask.set_editor_property('options', unreal.AbcImportSettings()) - else: - lodTask.set_editor_property('options', unreal.FbxImportUI()) - - lodTask.get_editor_property('options').static_mesh_import_data.set_editor_property('vertex_color_import_option', vertex_color_import_option) - lodTask.get_editor_property('options').static_mesh_import_data.set_editor_property('vertex_override_color', vertex_override_color.to_rgbe()) - - print(destination_path, additional_data["LevelOfDetail"][lod_name]) - unreal.AssetToolsHelpers.get_asset_tools().import_asset_tasks([lodTask]) - if len(lodTask.imported_object_paths) > 0: - lodAsset = unreal.find_asset(lodTask.imported_object_paths[0]) - slot_replaced = unreal.EditorStaticMeshLibrary.set_lod_from_static_mesh(asset, lod_number, lodAsset, 0, True) - unreal.EditorAssetLibrary.delete_asset(lodTask.imported_object_paths[0]) - - def ImportSkeletalLod(lod_name, lod_number): - if "LevelOfDetail" in additional_data: - if lod_name in additional_data["LevelOfDetail"]: - # Unreal python no longer support Skeletal mesh LODS import. - pass - - if asset_data["asset_type"] == "StaticMesh": - ImportStaticLod("lod_1", 1) - ImportStaticLod("lod_2", 2) - ImportStaticLod("lod_3", 3) - ImportStaticLod("lod_4", 4) - ImportStaticLod("lod_5", 5) - - elif asset_data["asset_type"] == "SkeletalMesh": - ImportSkeletalLod("lod_1", 1) - ImportSkeletalLod("lod_2", 2) - ImportSkeletalLod("lod_3", 3) - ImportSkeletalLod("lod_4", 4) - ImportSkeletalLod("lod_5", 5) - - # Vertex color - if vertex_override_color: - asset_import_data.set_editor_property('vertex_override_color', vertex_override_color.to_rgbe()) - - if vertex_color_import_option: - asset_import_data.set_editor_property('vertex_color_import_option', vertex_color_import_option) - - # #################################[EndChange] - if asset_data["asset_type"] == "StaticMesh" or asset_data["asset_type"] == "SkeletalMesh": - unreal.EditorAssetLibrary.save_loaded_asset(asset) +def ImportAllAssets(assets_data): + + + + + bfu_unreal_import_location = assets_data['bfu_unreal_import_location'] + ImportedList = [] + ImportFailList = [] + + def GetAssetByType(type): + target_assets = [] + for asset in assets_data["assets"]: + if asset["asset_type"] == type: + target_assets.append(asset) + return target_assets + + def PrepareImportAsset(asset_data): + counter = str(len(ImportedList)+1) + "/" + str(len(assets_data["assets"])) + print("Import asset " + counter + ": ", asset_data["asset_name"]) + + result, asset, asset_type = ImportAsset(asset_data) + if result == "SUCCESS": ImportedList.append([asset, asset_data["asset_type"]]) + else: + ImportFailList.append(result) - ImportTask() - # Process import + # Process import print('========================= Import started ! =========================') - print(assets_data["assets"]) + counter = bps.utils.CounterTimer() # Import assets with a specific order - for asset in GetAssetByType("Alembic"): - ImportAsset(asset) - for asset in GetAssetByType("StaticMesh"): - ImportAsset(asset) - for asset in GetAssetByType("SkeletalMesh"): - ImportAsset(asset) - for asset in GetAssetByType("Animation"): - ImportAsset(asset) + for asset_data in GetAssetByType("Alembic"): + PrepareImportAsset(asset_data) + for asset_data in GetAssetByType("StaticMesh"): + PrepareImportAsset(asset_data) + for asset_data in GetAssetByType("SkeletalMesh"): + PrepareImportAsset(asset_data) + for asset_data in GetAssetByType("Animation"): + PrepareImportAsset(asset_data) print('========================= Full import completed ! =========================') @@ -532,11 +503,16 @@ def ImportSkeletalLod(lod_name, lod_number): else: Animation_ImportedList.append(asset[0]) - print('Imported StaticMesh: '+str(len(StaticMesh_ImportedList))) - print('Imported SkeletalMesh: '+str(len(SkeletalMesh_ImportedList))) - print('Imported Alembic: '+str(len(Alembic_ImportedList))) - print('Imported Animation: '+str(len(Animation_ImportedList))) - print('Import failled: '+str(len(ImportFailList))) + import_log = [] + import_log.append('Imported StaticMesh: '+str(len(StaticMesh_ImportedList))) + import_log.append('Imported SkeletalMesh: '+str(len(SkeletalMesh_ImportedList))) + import_log.append('Imported Alembic: '+str(len(Alembic_ImportedList))) + import_log.append('Imported Animation: '+str(len(Animation_ImportedList))) + import_log.append('Import failled: '+str(len(ImportFailList))) + + for import_row in import_log: + print(import_row) + for error in ImportFailList: print(error) @@ -548,7 +524,21 @@ def ImportSkeletalLod(lod_name, lod_number): print('=========================') if len(ImportFailList) > 0: - return 'Some asset(s) could not be imported.' + message = 'Some asset(s) could not be imported.' + "\n" else: - return 'Assets imported with success !' + message = 'All assets imported with success!' + "\n" + + message += "Import finished in " + counter.get_str_time() + "\n" + message += "\n" + for import_row in import_log: + message += import_row + "\n" + if len(ImportFailList) > 0: + message += "\n" + for error in ImportFailList: + message += error + "\n" + + title = "Import finished!" + import_module_unreal_utils.show_simple_message(title, message) + + return True diff --git a/blender-for-unrealengine/bfu_import_module/asset_import_script.py b/blender-for-unrealengine/bfu_import_module/asset_import_script.py index 058827c7..ac0073cc 100644 --- a/blender-for-unrealengine/bfu_import_module/asset_import_script.py +++ b/blender-for-unrealengine/bfu_import_module/asset_import_script.py @@ -58,14 +58,11 @@ def RunImportScriptWithJsonData(): import_assets_data = JsonLoadFile(os.path.join(dir_path, json_data_file)) - import_module_path = import_assets_data["info"]["import_modiule_path"] # Module to run - print("Module path to import:", import_module_path) - + import_module_path = import_assets_data["info"]["import_modiule_path"] # Module to run imported_module, module_name = load_module(import_module_path) unload_module(module_name) imported_module.run_asset_import(import_assets_data) -print("Start importing assets.") -RunImportScriptWithJsonData() -print("Importing assets finished.") +if __name__ == "__main__": + RunImportScriptWithJsonData() diff --git a/blender-for-unrealengine/bfu_import_module/bps/__init__.py b/blender-for-unrealengine/bfu_import_module/bps/__init__.py new file mode 100644 index 00000000..b0dbec29 --- /dev/null +++ b/blender-for-unrealengine/bfu_import_module/bps/__init__.py @@ -0,0 +1,39 @@ +# ====================== BEGIN GPL LICENSE BLOCK ============================ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# All rights reserved. +# +# ======================= END GPL LICENSE BLOCK ============================= + +# ---------------------------------------------- +# BPS -> BleuRaven Python Script +# BleuRaven.fr +# XavierLoux.com +# ---------------------------------------------- + +import importlib + +from . import advprint +from . import utils +from . import math +from . import color_set + +if "advprint" in locals(): + importlib.reload(advprint) +if "utils" in locals(): + importlib.reload(utils) +if "math" in locals(): + importlib.reload(math) +if "math" in locals(): + importlib.reload(color_set) \ No newline at end of file diff --git a/blender-for-unrealengine/bfu_import_module/bps/advprint.py b/blender-for-unrealengine/bfu_import_module/bps/advprint.py new file mode 100644 index 00000000..75ac6f27 --- /dev/null +++ b/blender-for-unrealengine/bfu_import_module/bps/advprint.py @@ -0,0 +1,127 @@ +# ====================== BEGIN GPL LICENSE BLOCK ============================ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# All rights reserved. +# +# ======================= END GPL LICENSE BLOCK ============================= + +# ---------------------------------------------- +# BPS -> BleuRaven Python Script +# BleuRaven.fr +# XavierLoux.com +# ---------------------------------------------- + + +import sys +import time + + +class ProgressionBarClass(): + + def _get_name(self): + return self.__name + + def _set_name(self, value): + if not isinstance(value, str): + raise TypeError("name must be set to an String") + self.__name = value + + name = property(_get_name, _set_name) + + def _get_length(self): + return self.__length + + def _set_length(self, value): + if not isinstance(value, int): + raise TypeError("length must be set to an Integer") + self.__length = value + + length = property(_get_length, _set_length) + + previous_step = 0.0 + + def _get_total_step(self): + return self.__total_step + + def _set_total_step(self, value): + if not (isinstance(value, int) or isinstance(value, float)): + raise TypeError("total_step must be set to an Integer or Float") + + self.__total_step = value + + total_step = property(_get_total_step, _set_total_step) + + # Visual + show_block = True + show_steps = True + show_percentage = True + + def __init__(self): + self.__name = "My progression bar" + self.__length = 20 # modify this to change the length + self.__previous_step = 0.0 + self.__total_step = 1.0 # from 0 to 1 + self.__counter_start = time.perf_counter() + + def update_progress(self, progress): + job_title = self.__name + length = self.__length + total_step = self.__total_step + self.__previous_step = progress # Update the previous step. + + is_done = False + if progress >= total_step: + is_done = True + + # Write message. + msg = "\r{0}:".format(job_title) + + if self.show_block: + block = int(round(length*progress/total_step)) + msg += " [{0}]".format("#"*block + "-"*(length-block)) + + if self.show_steps: + msg += " {0}/{1}".format(progress, total_step) + + if is_done: + msg += " DONE IN {0}s\r\n".format(round(time.perf_counter()-self.__counter_start, 3)) + + else: + if self.show_percentage: + msg += " {0}%".format(round((progress*100)/total_step, 2)) + + sys.stdout.write(msg) + sys.stdout.flush() + + +def print_separation(number=60, char="-"): + """ + Prints a separation line consisting of '#' characters. + + Args: + number (int, optional): The number of '#' characters in the line. Defaults to 60. + """ + print("# {0} #".format(char * number)) + + +def print_title(text, number=60): + """ + Prints a title surrounded by a line of '#' characters. + + Args: + text (str): The text of the title. + number (int, optional): The total number of characters in the line. Defaults to 60. + """ + remain_number = len(text) - number - 2 + print("# {0} {1} {2} #".format("-" * remain_number, text, "-" * remain_number)) diff --git a/blender-for-unrealengine/bfu_import_module/bps/color_set.py b/blender-for-unrealengine/bfu_import_module/bps/color_set.py new file mode 100644 index 00000000..8d39ebe4 --- /dev/null +++ b/blender-for-unrealengine/bfu_import_module/bps/color_set.py @@ -0,0 +1,156 @@ +# ====================== BEGIN GPL LICENSE BLOCK ============================ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# All rights reserved. +# +# ======================= END GPL LICENSE BLOCK ============================= + +# ---------------------------------------------- +# BPS -> BleuRaven Python Script +# BleuRaven.fr +# XavierLoux.com +# ---------------------------------------------- + +# This use ANSI color codes. +# You can found it all here -> https://gist.github.com/JBlond/2fea43a3049b38287e5e9cefc87b2124 +# This file use the code of rene-d -> https://gist.github.com/rene-d/9e584a7dd2935d0f461904b9f2950007 + + + +# SGR color constants +# rene-d 2018 + +class Colors: + """ ANSI color codes """ + + # Color + BLACK = "\033[0;30m" + RED = "\033[0;31m" + GREEN = "\033[0;32m" + BROWN = "\033[0;33m" + BLUE = "\033[0;34m" + PURPLE = "\033[0;35m" + CYAN = "\033[0;36m" + LIGHT_GRAY = "\033[0;37m" + DARK_GRAY = "\033[1;30m" + LIGHT_RED = "\033[1;31m" + LIGHT_GREEN = "\033[1;32m" + YELLOW = "\033[1;33m" + LIGHT_BLUE = "\033[1;34m" + LIGHT_PURPLE = "\033[1;35m" + LIGHT_CYAN = "\033[1;36m" + LIGHT_WHITE = "\033[1;37m" + + #Style + BOLD = "\033[1m" + FAINT = "\033[2m" + ITALIC = "\033[3m" + UNDERLINE = "\033[4m" + BLINK = "\033[5m" + NEGATIVE = "\033[7m" + CROSSED = "\033[9m" + END = "\033[0m" + + +@staticmethod +def black(string): + return Colors.BLACK + string + Colors.END + +@staticmethod +def red(string): + return Colors.RED + string + Colors.END + +@staticmethod +def green(string): + return Colors.GREEN + string + Colors.END + +@staticmethod +def brown(string): + return Colors.BROWN + string + Colors.END + +@staticmethod +def blue(string): + return Colors.BLUE + string + Colors.END + +@staticmethod +def purple(string): + return Colors.PURPLE + string + Colors.END + +@staticmethod +def cyan(string): + return Colors.CYAN + string + Colors.END + +@staticmethod +def light_gray(string): + return Colors.LIGHT_GRAY + string + Colors.END + +@staticmethod +def dark_gray(string): + return Colors.DARK_GRAY + string + Colors.END + +@staticmethod +def light_red(string): + return Colors.LIGHT_RED + string + Colors.END + +@staticmethod +def light_green(string): + return Colors.LIGHT_GREEN + string + Colors.END + +@staticmethod +def yellow(string): + return Colors.YELLOW + string + Colors.END + +@staticmethod +def light_blue(string): + return Colors.LIGHT_BLUE + string + Colors.END + +@staticmethod +def light_purple(string): + return Colors.LIGHT_PURPLE + string + Colors.END + +@staticmethod +def light_cyan(string): + return Colors.LIGHT_CYAN + string + Colors.END + +@staticmethod +def light_white(string): + return Colors.LIGHT_WHITE + string + Colors.END + +@staticmethod +def bold(string): + return Colors.BOLD + string + Colors.END + +@staticmethod +def faint(string): + return Colors.FAINT + string + Colors.END + +@staticmethod +def italic(string): + return Colors.ITALIC + string + Colors.END + +@staticmethod +def underline(string): + return Colors.UNDERLINE + string + Colors.END + +@staticmethod +def blink(string): + return Colors.BLINK + string + Colors.END + +@staticmethod +def negative(string): + return Colors.NEGATIVE + string + Colors.END + +@staticmethod +def crossed(string): + return Colors.CROSSED + string + Colors.END \ No newline at end of file diff --git a/blender-for-unrealengine/bfu_import_module/bps/math.py b/blender-for-unrealengine/bfu_import_module/bps/math.py new file mode 100644 index 00000000..d036605a --- /dev/null +++ b/blender-for-unrealengine/bfu_import_module/bps/math.py @@ -0,0 +1,85 @@ +# ====================== BEGIN GPL LICENSE BLOCK ============================ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# All rights reserved. +# +# ======================= END GPL LICENSE BLOCK ============================= + +# ---------------------------------------------- +# BPS -> BleuRaven Python Script +# BleuRaven.fr +# XavierLoux.com +# ---------------------------------------------- + + +def next_power_of_two(n): + """ + Computes the next power of two that is greater than or equal to n. + + Args: + n (int): The input number. + + Returns: + int: The next power of two greater than or equal to n. + """ + # decrement n (to handle cases when n itself + # is a power of 2) + n = n - 1 + + # do till only one bit is left + while n & n - 1: + n = n & n - 1 # unset rightmost bit + + # n is now a power of two (less than n) + return n << 1 + + +def previous_power_of_two(n): + """ + Computes the previous power of two that is less than or equal to n. + + Args: + n (int): The input number. + + Returns: + int: The previous power of two less than or equal to n. + """ + # do till only one bit is left + while (n & n - 1): + n = n & n - 1 # unset rightmost bit + + # n is now a power of two (less than or equal to n) + return n + + +def nearest_power_of_two(value): + """ + Computes the nearest power of two to the given value. + + Args: + value (int): The input value. + + Returns: + int: The nearest power of two. + """ + if value < 2: + return 2 + + a = previous_power_of_two(value) + b = next_power_of_two(value) + + if value - a < b - value: + return a + else: + return b diff --git a/blender-for-unrealengine/bfu_import_module/bps/utils.py b/blender-for-unrealengine/bfu_import_module/bps/utils.py new file mode 100644 index 00000000..9eccd267 --- /dev/null +++ b/blender-for-unrealengine/bfu_import_module/bps/utils.py @@ -0,0 +1,62 @@ +# ====================== BEGIN GPL LICENSE BLOCK ============================ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# All rights reserved. +# +# ======================= END GPL LICENSE BLOCK ============================= + +# ---------------------------------------------- +# BPS -> BleuRaven Python Script +# BleuRaven.fr +# XavierLoux.com +# ---------------------------------------------- + +import time + + +class CounterTimer(): + """ + A simple timer. + """ + + def __init__(self): + self.start = time.perf_counter() + + def reset_time(self): + """ + Reset the timer. + """ + self.start = time.perf_counter() + + def get_time(self): + """ + Get the elapsed time since the timer started. (Class create) + """ + return time.perf_counter() - self.start + + def get_str_time(self): + """ + Get the elapsed str time since the timer started. (Class create) + """ + elapsed_time = self.get_time() + if elapsed_time < 60: + return f"{elapsed_time:.2f} secondes" + elif elapsed_time < 3600: + minutes, seconds = divmod(elapsed_time, 60) + return f"{int(minutes)} minutes et {seconds:.2f} secondes" + else: + hours, remainder = divmod(elapsed_time, 3600) + minutes, seconds = divmod(remainder, 60) + return f"{int(hours)} heures, {int(minutes)} minutes et {seconds:.2f} secondes" + diff --git a/blender-for-unrealengine/bfu_import_module/import_module_unreal_utils.py b/blender-for-unrealengine/bfu_import_module/import_module_unreal_utils.py new file mode 100644 index 00000000..2b620715 --- /dev/null +++ b/blender-for-unrealengine/bfu_import_module/import_module_unreal_utils.py @@ -0,0 +1,60 @@ +# ====================== BEGIN GPL LICENSE BLOCK ============================ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# All rights reserved. +# +# ======================= END GPL LICENSE BLOCK ============================= + +import string + +try: # TO DO: Found a better way to check that. + import unreal +except ImportError: + import unreal_engine as unreal + +def get_unreal_version(): + version_info = unreal.SystemLibrary.get_engine_version().split('-')[0] + version_numbers = version_info.split('.') + major = int(version_numbers[0]) + minor = int(version_numbers[1]) + patch = int(version_numbers[2]) + return major, minor, patch + +def is_unreal_version_greater_or_equal(target_major, target_minor=0, target_patch=0): + major, minor, patch = get_unreal_version() + + if major > target_major or (major == target_major and minor >= target_minor) or (major == target_major and minor == target_minor and patch >= target_patch): + return True + else: + return False + +def ValidUnrealAssetsName(filename): + # Normalizes string, removes non-alpha characters + # Asset name in Unreal use + + filename = filename.replace('.', '_') + filename = filename.replace('(', '_') + filename = filename.replace(')', '_') + filename = filename.replace(' ', '_') + valid_chars = "-_%s%s" % (string.ascii_letters, string.digits) + filename = ''.join(c for c in filename if c in valid_chars) + return filename + +def show_simple_message(title, message): + return unreal.EditorDialog.show_message(title, message, unreal.AppMsgType.OK) + +def show_warning_message(title, message): + print('--------------------------------------------------') + print(message) + return unreal.EditorDialog.show_message(title, message, unreal.AppMsgType.OK) \ No newline at end of file diff --git a/blender-for-unrealengine/bfu_import_module/import_module_utils.py b/blender-for-unrealengine/bfu_import_module/import_module_utils.py new file mode 100644 index 00000000..6c5d3df3 --- /dev/null +++ b/blender-for-unrealengine/bfu_import_module/import_module_utils.py @@ -0,0 +1,37 @@ +# ====================== BEGIN GPL LICENSE BLOCK ============================ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# All rights reserved. +# +# ======================= END GPL LICENSE BLOCK ============================= + +import sys +import json + +def JsonLoad(json_file): + # Changed in Python 3.9: The keyword argument encoding has been removed. + if sys.version_info >= (3, 9): + return json.load(json_file) + else: + return json.load(json_file, encoding="utf8") + + +def JsonLoadFile(json_file_path): + if sys.version_info[0] < 3: + with open(json_file_path, "r") as json_file: + return JsonLoad(json_file) + else: + with open(json_file_path, "r", encoding="utf8") as json_file: + return JsonLoad(json_file) + diff --git a/blender-for-unrealengine/bfu_import_module/sequencer_import.py b/blender-for-unrealengine/bfu_import_module/sequencer_import.py index 77cb1133..0f39a489 100644 --- a/blender-for-unrealengine/bfu_import_module/sequencer_import.py +++ b/blender-for-unrealengine/bfu_import_module/sequencer_import.py @@ -1,11 +1,25 @@ -# This script was generated with the addons Blender for UnrealEngine : https://github.com/xavier150/Blender-For-UnrealEngine-Addons -# It will import into Unreal Engine all the assets of type StaticMesh, SkeletalMesh, Animation and Pose -# The script must be used in Unreal Engine Editor with Python plugins : https://docs.unrealengine.com/en-US/Engine/Editor/ScriptingAndAutomation/Python -# Use this command in Unreal cmd consol: py "[ScriptLocation]\ImportSequencerScript.py" +# ====================== BEGIN GPL LICENSE BLOCK ============================ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# All rights reserved. +# +# ======================= END GPL LICENSE BLOCK ============================= -import sys import os.path -import json +from . import bps +from . import import_module_utils +from . import import_module_unreal_utils try: # TO DO: Found a better way to check that. import unreal @@ -13,61 +27,25 @@ import unreal_engine as unreal -def CheckTasks(): - if is_unreal_version_greater_or_equal(4,20): # TO DO: EditorAssetLibrary was added in witch version exactly? + + +def ready_for_sequence_import(): + if import_module_unreal_utils.is_unreal_version_greater_or_equal(4,20): # TO DO: EditorAssetLibrary was added in witch version exactly? if not hasattr(unreal, 'EditorAssetLibrary'): - print('--------------------------------------------------') - print('WARNING: Editor Scripting Utilities should be activated.') - print('Edit > Plugin > Scripting > Editor Scripting Utilities.') + message = 'WARNING: Editor Scripting Utilities should be activated.' + "\n" + message += 'Edit > Plugin > Scripting > Editor Scripting Utilities.' + import_module_unreal_utils.show_warning_message("Editor Scripting Utilities not activated.", message) return False if not hasattr(unreal.MovieSceneSequence, 'set_display_rate'): - print('--------------------------------------------------') - print('WARNING: Editor Scripting Utilities should be activated.') - print('Edit > Plugin > Scripting > Sequencer Scripting.') + message = 'WARNING: Editor Scripting Utilities should be activated.' + "\n" + message += 'Edit > Plugin > Scripting > Sequencer Scripting.' + import_module_unreal_utils.show_warning_message("Editor Scripting Utilities not activated.", message) return False return True - -def JsonLoad(json_file): - # Changed in Python 3.9: The keyword argument encoding has been removed. - if sys.version_info >= (3, 9): - return json.load(json_file) - else: - return json.load(json_file, encoding="utf8") - - -def JsonLoadFile(json_file_path): - if sys.version_info[0] < 3: - with open(json_file_path, "r") as json_file: - return JsonLoad(json_file) - else: - with open(json_file_path, "r", encoding="utf8") as json_file: - return JsonLoad(json_file) - - -def get_unreal_version(): - version_info = unreal.SystemLibrary.get_engine_version().split('-')[0] - version_numbers = version_info.split('.') - major = int(version_numbers[0]) - minor = int(version_numbers[1]) - patch = int(version_numbers[2]) - return major, minor, patch - -def is_unreal_version_greater_or_equal(target_major, target_minor=0, target_patch=0): - major, minor, patch = get_unreal_version() - - if major > target_major or (major == target_major and minor >= target_minor) or (major == target_major and minor == target_minor and patch >= target_patch): - return True - else: - return False - def CreateSequencer(sequence_data): - # Prepare process import - json_data_file = 'ImportSequencerData.json' - dir_path = os.path.dirname(os.path.realpath(__file__)) - spawnable_camera = sequence_data['spawnable_camera'] startFrame = sequence_data['startFrame'] endFrame = sequence_data['endFrame']+1 @@ -85,7 +63,7 @@ def AddSequencerSectionTransformKeysByIniFile(sequencer_section, track_dict): frame = unreal.FrameNumber(int(key)) - if is_unreal_version_greater_or_equal(5,0): + if import_module_utils.is_unreal_version_greater_or_equal(5,0): sequencer_section.get_all_channels()[0].add_key(frame, value["location_x"]) sequencer_section.get_all_channels()[1].add_key(frame, value["location_y"]) sequencer_section.get_all_channels()[2].add_key(frame, value["location_z"]) @@ -110,7 +88,7 @@ def AddSequencerSectionFloatKeysByIniFile(sequencer_section, track_dict): for key in track_dict.keys(): frame = unreal.FrameNumber(int(key)) value = track_dict[key] - if is_unreal_version_greater_or_equal(5,0): + if import_module_unreal_utils.is_unreal_version_greater_or_equal(5,0): sequencer_section.get_all_channels()[0].add_key(frame, value) else: sequencer_section.get_channels()[0].add_key(frame, value) @@ -119,7 +97,7 @@ def AddSequencerSectionBoolKeysByIniFile(sequencer_section, track_dict): for key in track_dict.keys(): frame = unreal.FrameNumber(int(key)) value = track_dict[key] - if is_unreal_version_greater_or_equal(5,0): + if import_module_unreal_utils.is_unreal_version_greater_or_equal(5,0): sequencer_section.get_all_channels()[0].add_key(frame, value) else: sequencer_section.get_channels()[0].add_key(frame, value) @@ -145,13 +123,13 @@ def AddSequencerSectionBoolKeysByIniFile(sequencer_section, track_dict): # Set playback range seq.set_playback_end_seconds((endFrame-secureCrop)/float(frameRateNumerator)) seq.set_playback_start_seconds(startFrame/float(frameRateNumerator)) # set_playback_end_seconds - if is_unreal_version_greater_or_equal(5,2): + if import_module_unreal_utils.is_unreal_version_greater_or_equal(5,2): camera_cut_track = seq.add_track(unreal.MovieSceneCameraCutTrack) else: camera_cut_track = seq.add_master_track(unreal.MovieSceneCameraCutTrack) camera_cut_track.set_editor_property('display_name', 'Imported Camera Cuts') - if is_unreal_version_greater_or_equal(4,26): + if import_module_unreal_utils.is_unreal_version_greater_or_equal(4,26): camera_cut_track.set_color_tint(unreal.Color(b=200, g=0, r=0, a=0)) else: pass @@ -160,7 +138,7 @@ def AddSequencerSectionBoolKeysByIniFile(sequencer_section, track_dict): # import camera print("Start camera import " + str(x+1) + "/" + str(len(sequence_data["cameras"])) + " :" + camera_data["name"]) # Import camera tracks transform - camera_tracks = JsonLoadFile(camera_data["additional_tracks_path"]) + camera_tracks = import_module_utils.JsonLoadFile(camera_data["additional_tracks_path"]) # Create spawnable camera and add camera in sequencer cine_camera_actor = unreal.EditorLevelLibrary().spawn_actor_from_class(unreal.CineCameraActor, unreal.Vector(0, 0, 0), unreal.Rotator(0, 0, 0)) @@ -209,7 +187,7 @@ def AddSequencerSectionBoolKeysByIniFile(sequencer_section, track_dict): TrackFocusDistance = camera_component_binding.add_track(unreal.MovieSceneFloatTrack) - if is_unreal_version_greater_or_equal(4,24): + if import_module_unreal_utils.is_unreal_version_greater_or_equal(4,24): TrackFocusDistance.set_property_name_and_path('FocusSettings.ManualFocusDistance', 'FocusSettings.ManualFocusDistance') TrackFocusDistance.set_editor_property('display_name', 'Manual Focus Distance (Focus Settings)') else: @@ -253,7 +231,7 @@ def AddSequencerSectionBoolKeysByIniFile(sequencer_section, track_dict): else: current_camera_binding = camera_binding - if is_unreal_version_greater_or_equal(4,26): + if import_module_unreal_utils.is_unreal_version_greater_or_equal(4,26): current_camera_binding.set_display_name(camera_data["name"]) else: pass @@ -292,11 +270,11 @@ def AddSequencerSectionBoolKeysByIniFile(sequencer_section, track_dict): for camera in ImportedCamera: if camera[0] == section["camera_name"]: camera_binding_id = unreal.MovieSceneObjectBindingID() - if is_unreal_version_greater_or_equal(5,3): + if import_module_unreal_utils.is_unreal_version_greater_or_equal(5,3): camera_binding_id = seq.get_binding_id(camera[1]) - elif is_unreal_version_greater_or_equal(4,27): + elif import_module_unreal_utils.is_unreal_version_greater_or_equal(4,27): camera_binding_id = seq.get_portable_binding_id(seq, camera[1]) - elif is_unreal_version_greater_or_equal(4,26): + elif import_module_unreal_utils.is_unreal_version_greater_or_equal(4,26): camera_binding_id = seq.make_binding_id(camera[1], unreal.MovieSceneObjectBindingSpace.LOCAL) else: camera_binding_id = seq.make_binding_id(camera[1]) @@ -314,10 +292,10 @@ def AddSequencerSectionBoolKeysByIniFile(sequencer_section, track_dict): print('=========================') # Select and open seq in content browser - if is_unreal_version_greater_or_equal(5,0): + if import_module_unreal_utils.is_unreal_version_greater_or_equal(5,0): pass #TO DO make crate the engine #unreal.AssetEditorSubsystem.open_editor_for_assets(unreal.AssetEditorSubsystem(), [unreal.load_asset(seq.get_path_name())]) - elif is_unreal_version_greater_or_equal(4,26): + elif import_module_unreal_utils.is_unreal_version_greater_or_equal(4,26): unreal.AssetEditorSubsystem.open_editor_for_assets(unreal.AssetEditorSubsystem(), [unreal.load_asset(seq.get_path_name())]) else: unreal.AssetToolsHelpers.get_asset_tools().open_editor_for_assets([unreal.load_asset(seq.get_path_name())]) diff --git a/blender-for-unrealengine/bfu_import_module/sequencer_import_script.py b/blender-for-unrealengine/bfu_import_module/sequencer_import_script.py index be7e5452..2f594607 100644 --- a/blender-for-unrealengine/bfu_import_module/sequencer_import_script.py +++ b/blender-for-unrealengine/bfu_import_module/sequencer_import_script.py @@ -58,14 +58,11 @@ def RunImportScriptWithJsonData(): sequence_data = JsonLoadFile(os.path.join(dir_path, json_data_file)) - import_module_path = sequence_data["info"]["import_modiule_path"] # Module to run - print("Module path to import:", import_module_path) - + import_module_path = sequence_data["info"]["import_modiule_path"] # Module to run imported_module, module_name = load_module(import_module_path) unload_module(module_name) imported_module.run_sequencer_import(sequence_data) -print("Start importing assets.") -RunImportScriptWithJsonData() -print("Importing assets finished.") +if __name__ == "__main__": + RunImportScriptWithJsonData()