def create_avalon_container(container, path): """ Helper function to create Avalon Asset Container class on given path. This Avalon Asset Class helps to mark given path as Avalon Container and enable asset version control on it. Args: name (str): Asset Container name path (str): Path where to create Asset Container. This path should point into container folder Returns: :class:`unreal.Object`: instance of created asset Example: AvalonHelpers().create_avalon_container( "/Game/modelingFooCharacter_CON", "modelingFooCharacter_CON" ) """ factory = unreal.AssetContainerFactory() tools = unreal.AssetToolsHelpers().get_asset_tools() asset = tools.create_asset(container, path, None, factory) return asset
def create_publish_instance(instance, path): """ Helper function to create Avalon Publish Instance on given path. This behaves similary as :func:`create_avalon_container`. Args: path (str): Path where to create Avalon Publish Instance. This path should point into container folder name (str): Avalon Publish Instance name Returns: :class:`unreal.Object`: instance of created asset Example: AvalonHelpers().create_publish_instance( "/Game/modelingFooCharacter_INST", "modelingFooCharacter_INST" ) """ factory = unreal.AvalonPublishInstanceFactory() tools = unreal.AssetToolsHelpers().get_asset_tools() asset = tools.create_asset(instance, path, None, factory) return asset
def load(self, context, name, namespace, data): """ Load and containerise representation into Content Browser. This is two step process. First, import FBX to temporary path and then call `containerise()` on it - this moves all content to new directory and then it will create AssetContainer there and imprint it with metadata. This will mark this path as container. Args: context (dict): application context name (str): subset name namespace (str): in Unreal this is basically path to container. This is not passed here, so namespace is set by `containerise()` because only then we know real path. data (dict): Those would be data to be imprinted. This is not used now, data are imprinted by `containerise()`. Returns: list(str): list of container content """ tools = unreal.AssetToolsHelpers().get_asset_tools() temp_dir, temp_name = tools.create_unique_asset_name( "/Game/{}".format(name), "_TMP") unreal.EditorAssetLibrary.make_directory(temp_dir) task = unreal.AssetImportTask() task.filename = self.fname task.destination_path = temp_dir task.destination_name = name task.replace_existing = False task.automated = True task.save = True # set import options here task.options = unreal.FbxImportUI() task.options.import_animations = False unreal.AssetToolsHelpers.get_asset_tools().import_asset_tasks( [task]) # noqa: E501 imported_assets = unreal.EditorAssetLibrary.list_assets( temp_dir, recursive=True, include_folder=True) new_dir = avalon_unreal.containerise(name, namespace, imported_assets, context, self.__class__.__name__) asset_content = unreal.EditorAssetLibrary.list_assets( new_dir, recursive=True, include_folder=True) unreal.EditorAssetLibrary.delete_directory(temp_dir) return asset_content
def load(self, context, name, namespace, data): """ Load and containerise representation into Content Browser. This is two step process. First, import FBX to temporary path and then call `containerise()` on it - this moves all content to new directory and then it will create AssetContainer there and imprint it with metadata. This will mark this path as container. Args: context (dict): application context name (str): subset name namespace (str): in Unreal this is basically path to container. This is not passed here, so namespace is set by `containerise()` because only then we know real path. data (dict): Those would be data to be imprinted. This is not used now, data are imprinted by `containerise()`. Returns: list(str): list of container content """ # Create directory for asset and avalon container root = "/Game/Avalon/Assets" asset = context.get('asset').get('name') suffix = "_CON" if asset: asset_name = "{}_{}".format(asset, name) else: asset_name = "{}".format(name) tools = unreal.AssetToolsHelpers().get_asset_tools() asset_dir, container_name = tools.create_unique_asset_name( "{}/{}/{}".format(root, asset, name), suffix="") container_name += suffix unreal.EditorAssetLibrary.make_directory(asset_dir) task = unreal.AssetImportTask() task.set_editor_property('filename', self.fname) task.set_editor_property('destination_path', asset_dir) task.set_editor_property('destination_name', asset_name) task.set_editor_property('replace_existing', False) task.set_editor_property('automated', True) task.set_editor_property('save', False) # set import options here options = unreal.FbxImportUI() options.set_editor_property('import_as_skeletal', True) options.set_editor_property('import_animations', False) options.set_editor_property('import_mesh', True) options.set_editor_property('import_materials', True) options.set_editor_property('import_textures', True) options.set_editor_property('skeleton', None) options.set_editor_property('create_physics_asset', False) options.set_editor_property('mesh_type_to_import', unreal.FBXImportType.FBXIT_SKELETAL_MESH) options.skeletal_mesh_import_data.set_editor_property( 'import_content_type', unreal.FBXImportContentType.FBXICT_ALL) # set to import normals, otherwise Unreal will compute them # and it will take a long time, depending on the size of the mesh options.skeletal_mesh_import_data.set_editor_property( 'normal_import_method', unreal.FBXNormalImportMethod.FBXNIM_IMPORT_NORMALS) task.options = options unreal.AssetToolsHelpers.get_asset_tools().import_asset_tasks( [task]) # noqa: E501 # Create Asset Container lib.create_avalon_container(container=container_name, path=asset_dir) data = { "schema": "openpype:container-2.0", "id": pipeline.AVALON_CONTAINER_ID, "asset": asset, "namespace": asset_dir, "container_name": container_name, "asset_name": asset_name, "loader": str(self.__class__.__name__), "representation": context["representation"]["_id"], "parent": context["representation"]["parent"], "family": context["representation"]["context"]["family"] } unreal_pipeline.imprint("{}/{}".format(asset_dir, container_name), data) asset_content = unreal.EditorAssetLibrary.list_assets( asset_dir, recursive=True, include_folder=True) for a in asset_content: unreal.EditorAssetLibrary.save_asset(a) return asset_content
def load(self, context, name, namespace, options): from avalon import api, pipeline from avalon.unreal import lib from avalon.unreal import pipeline as unreal_pipeline import unreal # Create directory for asset and avalon container root = "/Game/Avalon/Assets" asset = context.get('asset').get('name') suffix = "_CON" tools = unreal.AssetToolsHelpers().get_asset_tools() asset_dir, container_name = tools.create_unique_asset_name( "{}/{}".format(root, asset), suffix="") container_name += suffix unreal.EditorAssetLibrary.make_directory(asset_dir) libpath = self.fname with open(libpath, "r") as fp: data = json.load(fp) all_loaders = api.discover(api.Loader) for element in data: reference = element.get('_id') loaders = api.loaders_from_representation(all_loaders, reference) loader = None for l in loaders: if l.__name__ == "AnimationFBXLoader": loader = l break if not loader: continue instance_name = element.get('instance_name') api.load(loader, reference, namespace=instance_name, options=element) # Create Asset Container lib.create_avalon_container(container=container_name, path=asset_dir) data = { "schema": "openpype:container-2.0", "id": pipeline.AVALON_CONTAINER_ID, "asset": asset, "namespace": asset_dir, "container_name": container_name, "loader": str(self.__class__.__name__), "representation": context["representation"]["_id"], "parent": context["representation"]["parent"], "family": context["representation"]["context"]["family"] } unreal_pipeline.imprint("{}/{}".format(asset_dir, container_name), data) asset_content = unreal.EditorAssetLibrary.list_assets( asset_dir, recursive=True, include_folder=True) return asset_content
def load(self, context, name, namespace, options=None): """ Load and containerise representation into Content Browser. This is two step process. First, import FBX to temporary path and then call `containerise()` on it - this moves all content to new directory and then it will create AssetContainer there and imprint it with metadata. This will mark this path as container. Args: context (dict): application context name (str): subset name namespace (str): in Unreal this is basically path to container. This is not passed here, so namespace is set by `containerise()` because only then we know real path. data (dict): Those would be data to be imprinted. This is not used now, data are imprinted by `containerise()`. Returns: list(str): list of container content """ # Create directory for asset and avalon container root = "/Game/Avalon/Assets" asset = context.get('asset').get('name') suffix = "_CON" if asset: asset_name = "{}_{}".format(asset, name) else: asset_name = "{}".format(name) tools = unreal.AssetToolsHelpers().get_asset_tools() asset_dir, container_name = tools.create_unique_asset_name( "{}/{}/{}".format(root, asset, name), suffix="") container_name += suffix unreal.EditorAssetLibrary.make_directory(asset_dir) automated = False actor = None task = unreal.AssetImportTask() task.options = unreal.FbxImportUI() # If there are no options, the process cannot be automated if options: automated = True actor_name = 'PersistentLevel.' + options.get('instance_name') actor = unreal.EditorLevelLibrary.get_actor_reference(actor_name) skeleton = actor.skeletal_mesh_component.skeletal_mesh.skeleton task.options.set_editor_property('skeleton', skeleton) if not actor: return None task.set_editor_property('filename', self.fname) task.set_editor_property('destination_path', asset_dir) task.set_editor_property('destination_name', asset_name) task.set_editor_property('replace_existing', False) task.set_editor_property('automated', automated) task.set_editor_property('save', False) # set import options here task.options.set_editor_property('automated_import_should_detect_type', True) task.options.set_editor_property('original_import_type', unreal.FBXImportType.FBXIT_ANIMATION) task.options.set_editor_property('import_mesh', False) task.options.set_editor_property('import_animations', True) task.options.skeletal_mesh_import_data.set_editor_property( 'import_content_type', unreal.FBXImportContentType.FBXICT_SKINNING_WEIGHTS) unreal.AssetToolsHelpers.get_asset_tools().import_asset_tasks([task]) # Create Asset Container lib.create_avalon_container(container=container_name, path=asset_dir) data = { "schema": "avalon-core:container-2.0", "id": pipeline.AVALON_CONTAINER_ID, "asset": asset, "namespace": asset_dir, "container_name": container_name, "asset_name": asset_name, "loader": str(self.__class__.__name__), "representation": context["representation"]["_id"], "parent": context["representation"]["parent"], "family": context["representation"]["context"]["family"] } unreal_pipeline.imprint("{}/{}".format(asset_dir, container_name), data) asset_content = unreal.EditorAssetLibrary.list_assets( asset_dir, recursive=True, include_folder=True) animation = None for a in asset_content: unreal.EditorAssetLibrary.save_asset(a) imported_asset_data = unreal.EditorAssetLibrary.find_asset_data(a) imported_asset = unreal.AssetRegistryHelpers.get_asset( imported_asset_data) if imported_asset.__class__ == unreal.AnimSequence: animation = imported_asset break if animation: animation.set_editor_property('enable_root_motion', True) actor.skeletal_mesh_component.set_editor_property( 'animation_mode', unreal.AnimationMode.ANIMATION_SINGLE_NODE) actor.skeletal_mesh_component.animation_data.set_editor_property( 'anim_to_play', animation) return asset_content