Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
    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
Ejemplo n.º 5
0
    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
Ejemplo n.º 6
0
    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