From 0a2b676713ec5a88a4e1dee82dea5a22f07a9bc9 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 8 Mar 2024 12:46:16 +0100 Subject: [PATCH] unreal uses representation entity and forgetten changes --- client/ayon_core/hosts/unreal/api/pipeline.py | 2 +- .../plugins/load/load_alembic_animation.py | 23 ++--- .../unreal/plugins/load/load_animation.py | 32 ++++--- .../hosts/unreal/plugins/load/load_camera.py | 37 +++++--- .../plugins/load/load_geometrycache_abc.py | 72 ++++++++++----- .../hosts/unreal/plugins/load/load_layout.py | 74 +++++++-------- .../plugins/load/load_layout_existing.py | 89 ++++++++++--------- .../plugins/load/load_skeletalmesh_abc.py | 56 ++++++++---- .../plugins/load/load_skeletalmesh_fbx.py | 56 ++++++++---- .../plugins/load/load_staticmesh_abc.py | 65 ++++++++++---- .../plugins/load/load_staticmesh_fbx.py | 55 ++++++++---- .../hosts/unreal/plugins/load/load_uasset.py | 27 +++--- .../unreal/plugins/load/load_yeticache.py | 27 +++--- .../unreal/plugins/publish/extract_layout.py | 8 +- 14 files changed, 393 insertions(+), 230 deletions(-) diff --git a/client/ayon_core/hosts/unreal/api/pipeline.py b/client/ayon_core/hosts/unreal/api/pipeline.py index eb093a2e6f..1f937437a4 100644 --- a/client/ayon_core/hosts/unreal/api/pipeline.py +++ b/client/ayon_core/hosts/unreal/api/pipeline.py @@ -262,7 +262,7 @@ def containerise(name, namespace, nodes, context, loader=None, suffix="_CON"): "name": new_name, "namespace": namespace, "loader": str(loader), - "representation": context["representation"]["_id"], + "representation": context["representation"]["id"], } # 3 - imprint data imprint(f"{path}/{container_name}", data) diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_alembic_animation.py b/client/ayon_core/hosts/unreal/plugins/load/load_alembic_animation.py index d75cf207b5..9b8d22fb5e 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_alembic_animation.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_alembic_animation.py @@ -78,12 +78,12 @@ class AnimationAlembicLoader(plugin.Loader): asset_name = "{}_{}".format(folder_name, name) else: asset_name = "{}".format(name) - version = context.get('version') + version = context["version"]["version"] # Check if version is hero version and use different name - if not version.get("name") and version.get('type') == "hero_version": + if version < 0: name_version = f"{name}_hero" else: - name_version = f"{name}_v{version.get('name'):03d}" + name_version = f"{name}_v{version:03d}" tools = unreal.AssetToolsHelpers().get_asset_tools() asset_dir, container_name = tools.create_unique_asset_name( @@ -107,16 +107,17 @@ class AnimationAlembicLoader(plugin.Loader): data = { "schema": "ayon:container-2.0", "id": AYON_CONTAINER_ID, - "asset": folder_path, "folder_path": folder_path, "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": product_type, + "representation": context["representation"]["id"], + "parent": context["representation"]["versionId"], "product_type": product_type, + # TODO these should be probably removed + "asset": folder_path, + "family": product_type, } unreal_pipeline.imprint( f"{asset_dir}/{container_name}", data) @@ -132,8 +133,8 @@ class AnimationAlembicLoader(plugin.Loader): def update(self, container, context): folder_name = container["asset_name"] - repre_doc = context["representation"] - source_path = get_representation_path(repre_doc) + repre_entity = context["representation"] + source_path = get_representation_path(repre_entity) destination_path = container["namespace"] task = self.get_task( @@ -150,8 +151,8 @@ class AnimationAlembicLoader(plugin.Loader): unreal_pipeline.imprint( container_path, { - "representation": str(repre_doc["_id"]), - "parent": str(repre_doc["parent"]) + "representation": repre_entity["id"], + "parent": repre_entity["versionId"], }) asset_content = unreal.EditorAssetLibrary.list_assets( diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_animation.py b/client/ayon_core/hosts/unreal/plugins/load/load_animation.py index 1832841ef0..b2c066c871 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_animation.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_animation.py @@ -140,14 +140,17 @@ class AnimationFBXLoader(plugin.Loader): list(str): list of container content """ # Create directory for asset and Ayon container - hierarchy = context.get('asset').get('data').get('parents') root = "/Game/Ayon" - asset = context.get('asset').get('name') + folder_path = context["folder"]["path"] + hierarchy = folder_path.lstrip("/").split("/") + folder_name = hierarchy.pop(-1) + product_type = context["product"]["productType"] + suffix = "_CON" - asset_name = f"{asset}_{name}" if asset else f"{name}" + asset_name = f"{folder_name}_{name}" if folder_name else f"{name}" tools = unreal.AssetToolsHelpers().get_asset_tools() asset_dir, container_name = tools.create_unique_asset_name( - f"{root}/Animations/{asset}/{name}", suffix="") + f"{root}/Animations/{folder_name}/{name}", suffix="") ar = unreal.AssetRegistryHelpers.get_asset_registry() @@ -161,7 +164,7 @@ class AnimationFBXLoader(plugin.Loader): hierarchy_dir = root for h in hierarchy: hierarchy_dir = f"{hierarchy_dir}/{h}" - hierarchy_dir = f"{hierarchy_dir}/{asset}" + hierarchy_dir = f"{hierarchy_dir}/{folder_name}" _filter = unreal.ARFilter( class_names=["World"], @@ -226,14 +229,17 @@ class AnimationFBXLoader(plugin.Loader): data = { "schema": "ayon:container-2.0", "id": AYON_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"] + "representation": context["representation"]["id"], + "parent": context["representation"]["versionId"], + "folder_path": folder_path, + "product_type": product_type, + # TODO these shold be probably removed + "asset": folder_path, + "family": product_type } unreal_pipeline.imprint(f"{asset_dir}/{container_name}", data) @@ -247,9 +253,9 @@ class AnimationFBXLoader(plugin.Loader): unreal.EditorLevelLibrary.load_level(master_level) def update(self, container, context): - repre_doc = context["representation"] + repre_entity = context["representation"] folder_name = container["asset_name"] - source_path = get_representation_path(repre_doc) + source_path = get_representation_path(repre_entity) folder_entity = get_current_project_folder(fields=["attrib.fps"]) destination_path = container["namespace"] @@ -306,8 +312,8 @@ class AnimationFBXLoader(plugin.Loader): unreal_pipeline.imprint( container_path, { - "representation": str(repre_doc["_id"]), - "parent": str(repre_doc["parent"]) + "representation": repre_entity["id"], + "parent": repre_entity["versionId"], }) asset_content = EditorAssetLibrary.list_assets( diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_camera.py b/client/ayon_core/hosts/unreal/plugins/load/load_camera.py index 26ec80c804..ed159d31bd 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_camera.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_camera.py @@ -14,6 +14,7 @@ from unreal import ( from ayon_core.pipeline import ( AYON_CONTAINER_ID, get_current_project_name, + get_representation_path, ) from ayon_core.hosts.unreal.api import plugin from ayon_core.hosts.unreal.api.pipeline import ( @@ -246,18 +247,21 @@ class CameraLoader(plugin.Loader): create_container( container=container_name, path=asset_dir) + product_type = context["product"]["productType"] data = { "schema": "ayon:container-2.0", "id": AYON_CONTAINER_ID, - "asset": folder_name, "folder_path": folder_path, "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"] + "representation": context["representation"]["id"], + "parent": context["representation"]["versionId"], + "product_type": product_type, + # TODO these should be probably removed + "asset": folder_name, + "family": product_type, } imprint(f"{asset_dir}/{container_name}", data) @@ -393,28 +397,33 @@ class CameraLoader(plugin.Loader): sub_scene.set_sequence(new_sequence) - repre_doc = context["representation"] + repre_entity = context["representation"] + repre_path = get_representation_path(repre_entity) self._import_camera( EditorLevelLibrary.get_editor_world(), new_sequence, new_sequence.get_bindings(), settings, - str(repre_doc["data"]["path"]) + repre_path ) # Set range of all sections # Changing the range of the section is not enough. We need to change # the frame of all the keys in the section. project_name = get_current_project_name() - asset = container.get('asset') - data = get_asset_by_name(project_name, asset)["data"] + folder_path = container.get("folder_path") + if folder_path is None: + folder_path = container.get("asset") + folder_entity = ayon_api.get_folder_by_path(project_name, folder_path) + folder_attributes = folder_entity["attrib"] + clip_in = folder_attributes["clipIn"] + clip_out = folder_attributes["clipOut"] + frame_start = folder_attributes["frameStart"] for possessable in new_sequence.get_possessables(): for tracks in possessable.get_tracks(): for section in tracks.get_sections(): - section.set_range( - data.get('clipIn'), - data.get('clipOut') + 1) + section.set_range(clip_in, clip_out + 1) for channel in section.get_all_channels(): for key in channel.get_keys(): old_time = key.get_time().get_editor_property( @@ -422,13 +431,13 @@ class CameraLoader(plugin.Loader): old_time_value = old_time.get_editor_property( 'value') new_time = old_time_value + ( - data.get('clipIn') - data.get('frameStart') + clip_in - frame_start ) key.set_time(unreal.FrameNumber(value=new_time)) data = { - "representation": str(repre_doc["_id"]), - "parent": str(repre_doc["parent"]) + "representation": repre_entity["id"], + "parent": repre_entity["versionId"], } imprint(f"{asset_dir}/{container.get('container_name')}", data) diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_geometrycache_abc.py b/client/ayon_core/hosts/unreal/plugins/load/load_geometrycache_abc.py index c2f183480c..d0c936ed06 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_geometrycache_abc.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_geometrycache_abc.py @@ -84,22 +84,32 @@ class PointCacheAlembicLoader(plugin.Loader): create_container(container=container_name, path=asset_dir) def imprint( - self, asset, asset_dir, container_name, asset_name, representation, - frame_start, frame_end + self, + folder_path, + asset_dir, + container_name, + asset_name, + representation, + frame_start, + frame_end, + product_type, ): data = { "schema": "ayon:container-2.0", "id": AYON_CONTAINER_ID, - "asset": asset, "namespace": asset_dir, "container_name": container_name, "asset_name": asset_name, "loader": str(self.__class__.__name__), - "representation": representation["_id"], - "parent": representation["parent"], - "family": representation["context"]["family"], + "representation": representation["id"], + "parent": representation["versionId"], "frame_start": frame_start, - "frame_end": frame_end + "frame_end": frame_end, + "product_type": product_type, + "folder_path": folder_path, + # TODO these should be probably removed + "family": product_type, + "asset": folder_path, } imprint(f"{asset_dir}/{container_name}", data) @@ -119,24 +129,28 @@ class PointCacheAlembicLoader(plugin.Loader): list(str): list of container content """ # Create directory for asset and Ayon container - asset = context.get('asset').get('name') + folder_entity = context["folder"] + folder_path = folder_entity["path"] + folder_name = folder_entity["name"] + folder_attributes = folder_entity["attrib"] + suffix = "_CON" - asset_name = f"{asset}_{name}" if asset else f"{name}" - version = context.get('version') + asset_name = f"{folder_name}_{name}" if folder_name else f"{name}" + version = context["version"]["version"] # Check if version is hero version and use different name - if not version.get("name") and version.get('type') == "hero_version": + if version < 0: name_version = f"{name}_hero" else: - name_version = f"{name}_v{version.get('name'):03d}" + name_version = f"{name}_v{version:03d}" tools = unreal.AssetToolsHelpers().get_asset_tools() asset_dir, container_name = tools.create_unique_asset_name( - f"{self.root}/{asset}/{name_version}", suffix="") + f"{self.root}/{folder_name}/{name_version}", suffix="") container_name += suffix - frame_start = context.get('asset').get('data').get('frameStart') - frame_end = context.get('asset').get('data').get('frameEnd') + frame_start = folder_attributes.get("frameStart") + frame_end = folder_attributes.get("frameEnd") # If frame start and end are the same, we increase the end frame by # one, otherwise Unreal will not import it @@ -151,8 +165,15 @@ class PointCacheAlembicLoader(plugin.Loader): frame_start, frame_end) self.imprint( - asset, asset_dir, container_name, asset_name, - context["representation"], frame_start, frame_end) + folder_path, + asset_dir, + container_name, + asset_name, + context["representation"], + frame_start, + frame_end, + context["product"]["productType"] + ) asset_content = unreal.EditorAssetLibrary.list_assets( asset_dir, recursive=True, include_folder=True @@ -165,10 +186,12 @@ class PointCacheAlembicLoader(plugin.Loader): def update(self, container, context): # Create directory for folder and Ayon container + folder_path = context["folder"]["path"] folder_name = context["folder"]["name"] product_name = context["product"]["name"] + product_type = context["product"]["productType"] version = context["version"]["version"] - repre_doc = context["representation"] + repre_entity = context["representation"] suffix = "_CON" asset_name = product_name @@ -190,15 +213,22 @@ class PointCacheAlembicLoader(plugin.Loader): frame_end = int(container.get("frame_end")) if not unreal.EditorAssetLibrary.does_directory_exist(asset_dir): - path = get_representation_path(repre_doc) + path = get_representation_path(repre_entity) self.import_and_containerize( path, asset_dir, asset_name, container_name, frame_start, frame_end) self.imprint( - folder_name, asset_dir, container_name, asset_name, repre_doc, - frame_start, frame_end) + folder_path, + asset_dir, + container_name, + asset_name, + repre_entity, + frame_start, + frame_end, + product_type + ) asset_content = unreal.EditorAssetLibrary.list_assets( asset_dir, recursive=True, include_folder=False diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_layout.py b/client/ayon_core/hosts/unreal/plugins/load/load_layout.py index 47e99b9534..beb94ada7b 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_layout.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_layout.py @@ -17,7 +17,6 @@ from unreal import ( ) import ayon_api -from ayon_core.client import get_representations from ayon_core.pipeline import ( discover_loader_plugins, loaders_from_representation, @@ -291,7 +290,7 @@ class LayoutLoader(plugin.Loader): sec_params = section.get_editor_property('params') sec_params.set_editor_property('animation', animation) - def _get_repre_docs_by_version_id(self, data): + def _get_repre_entities_by_version_id(self, data): version_ids = { element.get("version") for element in data @@ -304,15 +303,15 @@ class LayoutLoader(plugin.Loader): return output project_name = get_current_project_name() - repre_docs = get_representations( + repre_entities = ayon_api.get_representations( project_name, - representation_names=["fbx", "abc"], + representation_names={"fbx", "abc"}, version_ids=version_ids, - fields=["_id", "parent", "name"] + fields={"id", "versionId", "name"} ) - for repre_doc in repre_docs: - version_id = str(repre_doc["parent"]) - output[version_id].append(repre_doc) + for repre_entity in repre_entities: + version_id = repre_entity["versionId"] + output[version_id].append(repre_entity) return output def _process(self, lib_path, asset_dir, sequence, repr_loaded=None): @@ -334,47 +333,50 @@ class LayoutLoader(plugin.Loader): loaded_assets = [] - repre_docs_by_version_id = self._get_repre_docs_by_version_id(data) + repre_entities_by_version_id = self._get_repre_entities_by_version_id( + data + ) for element in data: - representation = None + repre_id = None repr_format = None if element.get('representation'): - repre_docs = repre_docs_by_version_id[element.get("version")] - if not repre_docs: + version_id = element.get("version") + repre_entities = repre_entities_by_version_id[version_id] + if not repre_entities: self.log.error( - f"No valid representation found for version " - f"{element.get('version')}") + f"No valid representation found for version" + f" {version_id}") continue - repre_doc = repre_docs[0] - representation = str(repre_doc["_id"]) - repr_format = repre_doc["name"] + repre_entity = repre_entities[0] + repre_id = repre_entity["id"] + repr_format = repre_entity["name"] # This is to keep compatibility with old versions of the # json format. elif element.get('reference_fbx'): - representation = element.get('reference_fbx') + repre_id = element.get('reference_fbx') repr_format = 'fbx' elif element.get('reference_abc'): - representation = element.get('reference_abc') + repre_id = element.get('reference_abc') repr_format = 'abc' # If reference is None, this element is skipped, as it cannot be # imported in Unreal - if not representation: + if not repre_id: continue instance_name = element.get('instance_name') skeleton = None - if representation not in repr_loaded: - repr_loaded.append(representation) + if repre_id not in repr_loaded: + repr_loaded.append(repre_id) product_type = element.get("product_type") if product_type is None: product_type = element.get("family") loaders = loaders_from_representation( - all_loaders, representation) + all_loaders, repre_id) loader = None @@ -385,7 +387,7 @@ class LayoutLoader(plugin.Loader): if not loader: self.log.error( - f"No valid loader found for {representation}") + f"No valid loader found for {repre_id}") continue options = { @@ -394,7 +396,7 @@ class LayoutLoader(plugin.Loader): assets = load_container( loader, - representation, + repre_id, namespace=instance_name, options=options ) @@ -414,8 +416,8 @@ class LayoutLoader(plugin.Loader): item for item in data if ((item.get('version') and item.get('version') == element.get('version')) or - item.get('reference_fbx') == representation or - item.get('reference_abc') == representation)] + item.get('reference_fbx') == repre_id or + item.get('reference_abc') == repre_id)] for instance in instances: # transform = instance.get('transform') @@ -439,9 +441,9 @@ class LayoutLoader(plugin.Loader): bindings_dict[inst] = bindings if skeleton: - skeleton_dict[representation] = skeleton + skeleton_dict[repre_id] = skeleton else: - skeleton = skeleton_dict.get(representation) + skeleton = skeleton_dict.get(repre_id) animation_file = element.get('animation') @@ -655,8 +657,8 @@ class LayoutLoader(plugin.Loader): "container_name": container_name, "asset_name": asset_name, "loader": str(self.__class__.__name__), - "representation": context["representation"]["_id"], - "parent": context["representation"]["parent"], + "representation": context["representation"]["id"], + "parent": context["representation"]["versionId"], "family": context["representation"]["context"]["family"], "loaded_assets": loaded_assets } @@ -694,7 +696,7 @@ class LayoutLoader(plugin.Loader): asset_dir = container.get('namespace') folder_entity = context["folder"] - repre_doc = context["representation"] + repre_entity = context["representation"] hierarchy = folder_entity["path"].lstrip("/").split("/") first_parent_name = hierarchy[0] @@ -746,14 +748,14 @@ class LayoutLoader(plugin.Loader): EditorAssetLibrary.delete_directory(f"{asset_dir}/animations/") - source_path = get_representation_path(repre_doc) + source_path = get_representation_path(repre_entity) loaded_assets = self._process(source_path, asset_dir, sequence) data = { - "representation": str(repre_doc["_id"]), - "parent": str(repre_doc["parent"]), - "loaded_assets": loaded_assets + "representation": repre_entity["id"], + "parent": repre_entity["versionId"], + "loaded_assets": loaded_assets, } imprint( "{}/{}".format(asset_dir, container.get('container_name')), data) diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_layout_existing.py b/client/ayon_core/hosts/unreal/plugins/load/load_layout_existing.py index c896e7688b..144df10fe0 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_layout_existing.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_layout_existing.py @@ -5,7 +5,6 @@ import unreal from unreal import EditorLevelLibrary import ayon_api -from ayon_core.client import get_representations from ayon_core.pipeline import ( discover_loader_plugins, loaders_from_representation, @@ -65,7 +64,6 @@ class ExistingLayoutLoader(plugin.Loader): data = { "schema": "ayon:container-2.0", "id": AYON_CONTAINER_ID, - "asset": folder_path, "folder_path": folder_path, "namespace": asset_dir, "container_name": container_name, @@ -73,8 +71,10 @@ class ExistingLayoutLoader(plugin.Loader): # "loader": str(self.__class__.__name__), "representation": representation, "parent": version_id, - "family": product_type, "product_type": product_type, + # TODO these shold be probably removed + "asset": folder_path, + "family": product_type, } upipeline.imprint( @@ -201,19 +201,19 @@ class ExistingLayoutLoader(plugin.Loader): return assets - def _get_valid_repre_docs(self, project_name, version_ids): + def _get_valid_repre_entities(self, project_name, version_ids): valid_formats = ['fbx', 'abc'] - repre_docs = list(get_representations( + repre_entities = list(ayon_api.get_representations( project_name, representation_names=valid_formats, version_ids=version_ids )) - repre_doc_by_version_id = {} - for repre_doc in repre_docs: - version_id = str(repre_doc["parent"]) - repre_doc_by_version_id[version_id] = repre_doc - return repre_doc_by_version_id + repre_entities_by_version_id = {} + for repre_entity in repre_entities: + version_id = repre_entity["versionId"] + repre_entities_by_version_id[version_id] = repre_entity + return repre_entities_by_version_id def _process(self, lib_path, project_name): ar = unreal.AssetRegistryHelpers.get_asset_registry() @@ -232,44 +232,47 @@ class ExistingLayoutLoader(plugin.Loader): repre_ids.add(repre_id) elements.append(element) - repre_docs = get_representations( + repre_entities = ayon_api.get_representations( project_name, representation_ids=repre_ids ) - repre_docs_by_id = { - str(repre_doc["_id"]): repre_doc - for repre_doc in repre_docs + repre_entities_by_id = { + repre_entity["id"]: repre_entity + for repre_entity in repre_entities } layout_data = [] version_ids = set() for element in elements: repre_id = element.get("representation") - repre_doc = repre_docs_by_id.get(repre_id) - if not repre_doc: + repre_entity = repre_entities_by_id.get(repre_id) + if not repre_entity: raise AssertionError("Representation not found") - if not (repre_doc.get('data') or repre_doc['data'].get('path')): + if not ( + repre_entity.get("attrib") + or repre_entity["attrib"].get("path") + ): raise AssertionError("Representation does not have path") - if not repre_doc.get('context'): + if not repre_entity.get('context'): raise AssertionError("Representation does not have context") - layout_data.append((repre_doc, element)) - version_ids.add(repre_doc["parent"]) + layout_data.append((repre_entity, element)) + version_ids.add(repre_entity["versionId"]) repre_parents_by_id = ayon_api.get_representation_parents( - project_name, repre_docs_by_id.keys() + project_name, repre_entities_by_id.keys() ) # Prequery valid repre documents for all elements at once - valid_repre_doc_by_version_id = self._get_valid_repre_docs( + valid_repre_entities_by_version_id = self._get_valid_repre_entities( project_name, version_ids) containers = [] actors_matched = [] - for (repre_doc, lasset) in layout_data: + for (repre_entity, lasset) in layout_data: # For every actor in the scene, check if it has a representation in # those we got from the JSON. If so, create a container for it. # Otherwise, remove it from the scene. found = False - repre_id = repre_doc["_id"] + repre_id = repre_entity["id"] repre_parents = repre_parents_by_id[repre_id] folder_path = repre_parents.folder["path"] folder_name = repre_parents.folder["name"] @@ -291,7 +294,7 @@ class ExistingLayoutLoader(plugin.Loader): path = Path(filename) if (not path.name or - path.name not in repre_doc["data"]["path"]): + path.name not in repre_entity["attrib"]["path"]): continue actor.set_actor_label(lasset.get('instance_name')) @@ -303,8 +306,8 @@ class ExistingLayoutLoader(plugin.Loader): f"{folder_name}_{product_name}", mesh_path, folder_path, - repre_doc["_id"], - repre_doc["parent"], + repre_entity["id"], + repre_entity["versionId"], product_type ) containers.append(container) @@ -333,18 +336,18 @@ class ExistingLayoutLoader(plugin.Loader): loaded = False for container in all_containers: - repr = container.get('representation') + repre_id = container.get('representation') - if not repr == repre_doc["_id"]: + if not repre_id == repre_entity["id"]: continue asset_dir = container.get('namespace') - filter = unreal.ARFilter( + arfilter = unreal.ARFilter( class_names=["StaticMesh"], package_paths=[asset_dir], recursive_paths=False) - assets = ar.get_assets(filter) + assets = ar.get_assets(arfilter) for asset in assets: obj = asset.get_asset() @@ -357,8 +360,9 @@ class ExistingLayoutLoader(plugin.Loader): if loaded: continue + version_id = lasset.get('version') assets = self._load_asset( - valid_repre_doc_by_version_id.get(lasset.get('version')), + valid_repre_entities_by_version_id.get(version_id), lasset.get('representation'), lasset.get('instance_name'), lasset.get('family') @@ -414,17 +418,18 @@ class ExistingLayoutLoader(plugin.Loader): data = { "schema": "ayon:container-2.0", "id": AYON_CONTAINER_ID, - "asset": folder_path, "folder_path": folder_path, "namespace": curr_level_path, "container_name": container_name, "asset_name": asset_name, "loader": str(self.__class__.__name__), - "representation": context["representation"]["_id"], - "parent": context["representation"]["parent"], - "family": product_type, + "representation": context["representation"]["id"], + "parent": context["representation"]["versionId"], "product_type": product_type, - "loaded_assets": containers + "loaded_assets": containers, + # TODO these shold be probably removed + "asset": folder_path, + "family": product_type, } upipeline.imprint(f"{curr_level_path}/{container_name}", data) @@ -432,15 +437,15 @@ class ExistingLayoutLoader(plugin.Loader): asset_dir = container.get('namespace') project_name = context["project"]["name"] - repre_doc = context["representation"] + repre_entity = context["representation"] - source_path = get_representation_path(repre_doc) + source_path = get_representation_path(repre_entity) containers = self._process(source_path, project_name) data = { - "representation": str(repre_doc["_id"]), - "parent": str(repre_doc["parent"]), - "loaded_assets": containers + "representation": repre_entity["id"], + "loaded_assets": containers, + "parent": repre_entity["versionId"], } upipeline.imprint( "{}/{}".format(asset_dir, container.get('container_name')), data) diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_skeletalmesh_abc.py b/client/ayon_core/hosts/unreal/plugins/load/load_skeletalmesh_abc.py index 9879b0b967..4d9c0554d8 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_skeletalmesh_abc.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_skeletalmesh_abc.py @@ -73,19 +73,28 @@ class SkeletalMeshAlembicLoader(plugin.Loader): create_container(container=container_name, path=asset_dir) def imprint( - self, asset, asset_dir, container_name, asset_name, representation + self, + folder_path, + asset_dir, + container_name, + asset_name, + representation, + product_type ): data = { "schema": "ayon:container-2.0", "id": AYON_CONTAINER_ID, - "asset": asset, + "folder_path": folder_path, "namespace": asset_dir, "container_name": container_name, "asset_name": asset_name, "loader": str(self.__class__.__name__), - "representation": representation["_id"], - "parent": representation["parent"], - "family": representation["context"]["family"] + "representation": representation["id"], + "parent": representation["versionId"], + "product_type": product_type, + # TODO these should be probably removed + "asset": folder_path, + "family": product_type, } imprint(f"{asset_dir}/{container_name}", data) @@ -105,15 +114,16 @@ class SkeletalMeshAlembicLoader(plugin.Loader): list(str): list of container content """ # Create directory for asset and ayon container - asset = context.get('asset').get('name') + folder_path = context["folder"]["path"] + folder_name = context["folder"]["name"] suffix = "_CON" - asset_name = f"{asset}_{name}" if asset else f"{name}" - version = context.get('version') + asset_name = f"{folder_name}_{name}" if folder_name else f"{name}" + version = context["version"]["version"] # Check if version is hero version and use different name - if not version.get("name") and version.get('type') == "hero_version": + if version < 0: name_version = f"{name}_hero" else: - name_version = f"{name}_v{version.get('name'):03d}" + name_version = f"{name}_v{version:03d}" default_conversion = False if options.get("default_conversion"): @@ -121,7 +131,7 @@ class SkeletalMeshAlembicLoader(plugin.Loader): tools = unreal.AssetToolsHelpers().get_asset_tools() asset_dir, container_name = tools.create_unique_asset_name( - f"{self.root}/{asset}/{name_version}", suffix="") + f"{self.root}/{folder_name}/{name_version}", suffix="") container_name += suffix @@ -131,9 +141,15 @@ class SkeletalMeshAlembicLoader(plugin.Loader): self.import_and_containerize(path, asset_dir, asset_name, container_name, default_conversion) + product_type = context["product"]["productType"] self.imprint( - asset, asset_dir, container_name, asset_name, - context["representation"]) + folder_path, + asset_dir, + container_name, + asset_name, + context["representation"], + product_type + ) asset_content = unreal.EditorAssetLibrary.list_assets( asset_dir, recursive=True, include_folder=True @@ -145,10 +161,12 @@ class SkeletalMeshAlembicLoader(plugin.Loader): return asset_content def update(self, container, context): + folder_path = context["folder"]["path"] folder_name = context["folder"]["name"] product_name = context["product"]["name"] + product_type = context["product"]["productType"] version = context["version"]["version"] - repre_doc = context["representation"] + repre_entity = context["representation"] # Create directory for folder and Ayon container suffix = "_CON" @@ -167,13 +185,19 @@ class SkeletalMeshAlembicLoader(plugin.Loader): container_name += suffix if not unreal.EditorAssetLibrary.does_directory_exist(asset_dir): - path = get_representation_path(repre_doc) + path = get_representation_path(repre_entity) self.import_and_containerize(path, asset_dir, asset_name, container_name) self.imprint( - folder_name, asset_dir, container_name, asset_name, repre_doc) + folder_path, + asset_dir, + container_name, + asset_name, + repre_entity, + product_type, + ) asset_content = unreal.EditorAssetLibrary.list_assets( asset_dir, recursive=True, include_folder=False diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_skeletalmesh_fbx.py b/client/ayon_core/hosts/unreal/plugins/load/load_skeletalmesh_fbx.py index f643e027d2..990ad4b977 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_skeletalmesh_fbx.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_skeletalmesh_fbx.py @@ -78,19 +78,28 @@ class SkeletalMeshFBXLoader(plugin.Loader): create_container(container=container_name, path=asset_dir) def imprint( - self, asset, asset_dir, container_name, asset_name, representation + self, + folder_path, + asset_dir, + container_name, + asset_name, + representation, + product_type ): data = { "schema": "ayon:container-2.0", "id": AYON_CONTAINER_ID, - "asset": asset, + "folder_path": folder_path, "namespace": asset_dir, "container_name": container_name, "asset_name": asset_name, "loader": str(self.__class__.__name__), - "representation": representation["_id"], - "parent": representation["parent"], - "family": representation["context"]["family"] + "representation": representation["id"], + "parent": representation["versionId"], + "product_type": product_type, + # TODO these should be probably removed + "asset": folder_path, + "family": product_type, } imprint(f"{asset_dir}/{container_name}", data) @@ -110,19 +119,21 @@ class SkeletalMeshFBXLoader(plugin.Loader): list(str): list of container content """ # Create directory for asset and Ayon container - asset = context.get('asset').get('name') + folder_name = context["folder"]["name"] + product_type = context["product"]["productType"] suffix = "_CON" - asset_name = f"{asset}_{name}" if asset else f"{name}" - version = context.get('version') + asset_name = f"{folder_name}_{name}" if folder_name else f"{name}" + version_entity = context["version"] # Check if version is hero version and use different name - if not version.get("name") and version.get('type') == "hero_version": + version = version_entity["version"] + if version < 0: name_version = f"{name}_hero" else: - name_version = f"{name}_v{version.get('name'):03d}" + name_version = f"{name}_v{version:03d}" tools = unreal.AssetToolsHelpers().get_asset_tools() asset_dir, container_name = tools.create_unique_asset_name( - f"{self.root}/{asset}/{name_version}", suffix="" + f"{self.root}/{folder_name}/{name_version}", suffix="" ) container_name += suffix @@ -134,8 +145,13 @@ class SkeletalMeshFBXLoader(plugin.Loader): path, asset_dir, asset_name, container_name) self.imprint( - asset, asset_dir, container_name, asset_name, - context["representation"]) + folder_name, + asset_dir, + container_name, + asset_name, + context["representation"], + product_type + ) asset_content = unreal.EditorAssetLibrary.list_assets( asset_dir, recursive=True, include_folder=True @@ -147,10 +163,12 @@ class SkeletalMeshFBXLoader(plugin.Loader): return asset_content def update(self, container, context): + folder_path = context["folder"]["path"] folder_name = context["folder"]["name"] product_name = context["product"]["name"] + product_type = context["product"]["productType"] version = context["version"]["version"] - repre_doc = context["representation"] + repre_entity = context["representation"] # Create directory for asset and Ayon container suffix = "_CON" @@ -169,13 +187,19 @@ class SkeletalMeshFBXLoader(plugin.Loader): container_name += suffix if not unreal.EditorAssetLibrary.does_directory_exist(asset_dir): - path = get_representation_path(repre_doc) + path = get_representation_path(repre_entity) self.import_and_containerize( path, asset_dir, asset_name, container_name) self.imprint( - folder_name, asset_dir, container_name, asset_name, repre_doc) + folder_path, + asset_dir, + container_name, + asset_name, + repre_entity, + product_type + ) asset_content = unreal.EditorAssetLibrary.list_assets( asset_dir, recursive=True, include_folder=False diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_staticmesh_abc.py b/client/ayon_core/hosts/unreal/plugins/load/load_staticmesh_abc.py index 9056a471d8..5e4a28a031 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_staticmesh_abc.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_staticmesh_abc.py @@ -74,19 +74,28 @@ class StaticMeshAlembicLoader(plugin.Loader): create_container(container=container_name, path=asset_dir) def imprint( - self, asset, asset_dir, container_name, asset_name, representation + self, + folder_path, + asset_dir, + container_name, + asset_name, + representation, + product_type, ): data = { "schema": "ayon:container-2.0", "id": AYON_CONTAINER_ID, - "asset": asset, + "folder_path": folder_path, "namespace": asset_dir, "container_name": container_name, "asset_name": asset_name, "loader": str(self.__class__.__name__), - "representation": representation["_id"], - "parent": representation["parent"], - "family": representation["context"]["family"] + "representation": representation["id"], + "parent": representation["versionId"], + "product_type": product_type, + # TODO these should be probably removed + "asset": folder_path, + "family": product_type } imprint(f"{asset_dir}/{container_name}", data) @@ -106,15 +115,17 @@ class StaticMeshAlembicLoader(plugin.Loader): list(str): list of container content """ # Create directory for asset and Ayon container - asset = context.get('asset').get('name') + folder_path = context["folder"]["path"] + folder_name = context["folder"]["path"] + suffix = "_CON" - asset_name = f"{asset}_{name}" if asset else f"{name}" - version = context.get('version') + asset_name = f"{folder_name}_{name}" if folder_name else f"{name}" + version = context["version"]["version"] # Check if version is hero version and use different name - if not version.get("name") and version.get('type') == "hero_version": + if version < 0: name_version = f"{name}_hero" else: - name_version = f"{name}_v{version.get('name'):03d}" + name_version = f"{name}_v{version:03d}" default_conversion = False if options.get("default_conversion"): @@ -122,7 +133,7 @@ class StaticMeshAlembicLoader(plugin.Loader): tools = unreal.AssetToolsHelpers().get_asset_tools() asset_dir, container_name = tools.create_unique_asset_name( - f"{self.root}/{asset}/{name_version}", suffix="") + f"{self.root}/{folder_name}/{name_version}", suffix="") container_name += suffix @@ -132,9 +143,15 @@ class StaticMeshAlembicLoader(plugin.Loader): self.import_and_containerize(path, asset_dir, asset_name, container_name, default_conversion) + product_type = context["product"]["productType"] self.imprint( - asset, asset_dir, container_name, asset_name, - context["representation"]) + folder_path, + asset_dir, + container_name, + asset_name, + context["representation"], + product_type + ) asset_content = unreal.EditorAssetLibrary.list_assets( asset_dir, recursive=True, include_folder=False @@ -146,18 +163,24 @@ class StaticMeshAlembicLoader(plugin.Loader): return asset_content def update(self, container, context): + folder_path = context["folder"]["path"] folder_name = context["folder"]["name"] product_name = context["product"]["name"] - repre_doc = context["representation"] + product_type = context["product"]["productType"] + repre_entity = context["representation"] # Create directory for asset and Ayon container suffix = "_CON" asset_name = product_name if folder_name: asset_name = f"{folder_name}_{product_name}" - version = context.get('version') + version = context["version"]["version"] # Check if version is hero version and use different name - name_version = f"{product_name}_v{version:03d}" if version else f"{product_name}_hero" + if version < 0: + name_version = f"{product_name}_hero" + else: + name_version = f"{product_name}_v{version:03d}" + tools = unreal.AssetToolsHelpers().get_asset_tools() asset_dir, container_name = tools.create_unique_asset_name( f"{self.root}/{folder_name}/{name_version}", suffix="") @@ -165,13 +188,19 @@ class StaticMeshAlembicLoader(plugin.Loader): container_name += suffix if not unreal.EditorAssetLibrary.does_directory_exist(asset_dir): - path = get_representation_path(repre_doc) + path = get_representation_path(repre_entity) self.import_and_containerize(path, asset_dir, asset_name, container_name) self.imprint( - folder_name, asset_dir, container_name, asset_name, repre_doc) + folder_path, + asset_dir, + container_name, + asset_name, + repre_entity, + product_type + ) asset_content = unreal.EditorAssetLibrary.list_assets( asset_dir, recursive=True, include_folder=False diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_staticmesh_fbx.py b/client/ayon_core/hosts/unreal/plugins/load/load_staticmesh_fbx.py index a23290997e..1db2dcf676 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_staticmesh_fbx.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_staticmesh_fbx.py @@ -66,19 +66,28 @@ class StaticMeshFBXLoader(plugin.Loader): create_container(container=container_name, path=asset_dir) def imprint( - self, asset, asset_dir, container_name, asset_name, representation + self, + folder_path, + asset_dir, + container_name, + asset_name, + repre_entity, + product_type ): data = { "schema": "ayon:container-2.0", "id": AYON_CONTAINER_ID, - "asset": asset, "namespace": asset_dir, + "folder_path": folder_path, "container_name": container_name, "asset_name": asset_name, "loader": str(self.__class__.__name__), - "representation": representation["_id"], - "parent": representation["parent"], - "family": representation["context"]["family"] + "representation": repre_entity["id"], + "parent": repre_entity["versionId"], + "product_type": product_type, + # TODO these shold be probably removed + "asset": folder_path, + "family": product_type, } imprint(f"{asset_dir}/{container_name}", data) @@ -98,19 +107,20 @@ class StaticMeshFBXLoader(plugin.Loader): list(str): list of container content """ # Create directory for asset and Ayon container - asset = context.get('asset').get('name') + folder_path = context["folder"]["path"] + folder_name = context["folder"]["name"] suffix = "_CON" - asset_name = f"{asset}_{name}" if asset else f"{name}" - version = context.get('version') + asset_name = f"{folder_name}_{name}" if folder_name else f"{name}" + version = context["version"]["version"] # Check if version is hero version and use different name - if not version.get("name") and version.get('type') == "hero_version": + if version < 0: name_version = f"{name}_hero" else: - name_version = f"{name}_v{version.get('name'):03d}" + name_version = f"{name}_v{version:03d}" tools = unreal.AssetToolsHelpers().get_asset_tools() asset_dir, container_name = tools.create_unique_asset_name( - f"{self.root}/{asset}/{name_version}", suffix="" + f"{self.root}/{folder_name}/{name_version}", suffix="" ) container_name += suffix @@ -122,8 +132,13 @@ class StaticMeshFBXLoader(plugin.Loader): path, asset_dir, asset_name, container_name) self.imprint( - asset, asset_dir, container_name, asset_name, - context["representation"]) + folder_path, + asset_dir, + container_name, + asset_name, + context["representation"], + context["product"]["productType"] + ) asset_content = unreal.EditorAssetLibrary.list_assets( asset_dir, recursive=True, include_folder=True @@ -135,10 +150,12 @@ class StaticMeshFBXLoader(plugin.Loader): return asset_content def update(self, container, context): + folder_path = context["folder"]["path"] folder_name = context["folder"]["name"] product_name = context["product"]["name"] + product_type = context["product"]["productType"] version = context["version"]["version"] - repre_doc = context["representation"] + repre_entity = context["representation"] # Create directory for asset and Ayon container suffix = "_CON" @@ -157,13 +174,19 @@ class StaticMeshFBXLoader(plugin.Loader): container_name += suffix if not unreal.EditorAssetLibrary.does_directory_exist(asset_dir): - path = get_representation_path(repre_doc) + path = get_representation_path(repre_entity) self.import_and_containerize( path, asset_dir, asset_name, container_name) self.imprint( - folder_name, asset_dir, container_name, asset_name, repre_doc) + folder_path, + asset_dir, + container_name, + asset_name, + repre_entity, + product_type, + ) asset_content = unreal.EditorAssetLibrary.list_assets( asset_dir, recursive=True, include_folder=False diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_uasset.py b/client/ayon_core/hosts/unreal/plugins/load/load_uasset.py index d7a79616b7..e0b1a69aac 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_uasset.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_uasset.py @@ -42,12 +42,13 @@ class UAssetLoader(plugin.Loader): # Create directory for asset and Ayon container root = unreal_pipeline.AYON_ASSET_DIR - asset = context.get('asset').get('name') + folder_path = context["folder"]["path"] + folder_name = context["folder"]["name"] suffix = "_CON" - asset_name = f"{asset}_{name}" if asset else f"{name}" + asset_name = f"{folder_name}_{name}" if folder_name else f"{name}" tools = unreal.AssetToolsHelpers().get_asset_tools() asset_dir, container_name = tools.create_unique_asset_name( - f"{root}/{asset}/{name}", suffix="" + f"{root}/{folder_name}/{name}", suffix="" ) unique_number = 1 @@ -73,17 +74,21 @@ class UAssetLoader(plugin.Loader): unreal_pipeline.create_container( container=container_name, path=asset_dir) + product_type = context["product"]["productType"] data = { "schema": "ayon:container-2.0", "id": AYON_CONTAINER_ID, - "asset": asset, "namespace": asset_dir, + "folder_path": folder_path, "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"], + "representation": context["representation"]["id"], + "parent": context["representation"]["versionId"], + "product_type": product_type, + # TODO these should be probably removed + "asset": folder_path, + "family": product_type, } unreal_pipeline.imprint(f"{asset_dir}/{container_name}", data) @@ -102,7 +107,7 @@ class UAssetLoader(plugin.Loader): asset_dir = container["namespace"] product_name = context["product"]["name"] - repre_doc = context["representation"] + repre_entity = context["representation"] unique_number = container["container_name"].split("_")[-2] @@ -118,7 +123,7 @@ class UAssetLoader(plugin.Loader): if obj.get_class().get_name() != "AyonAssetContainer": unreal.EditorAssetLibrary.delete_asset(asset) - update_filepath = get_representation_path(repre_doc) + update_filepath = get_representation_path(repre_entity) shutil.copy( update_filepath, @@ -130,8 +135,8 @@ class UAssetLoader(plugin.Loader): unreal_pipeline.imprint( container_path, { - "representation": str(repre_doc["_id"]), - "parent": str(repre_doc["parent"]), + "representation": repre_entity["id"], + "parent": repre_entity["versionId"], } ) diff --git a/client/ayon_core/hosts/unreal/plugins/load/load_yeticache.py b/client/ayon_core/hosts/unreal/plugins/load/load_yeticache.py index c6e275c844..7a1767e52a 100644 --- a/client/ayon_core/hosts/unreal/plugins/load/load_yeticache.py +++ b/client/ayon_core/hosts/unreal/plugins/load/load_yeticache.py @@ -87,13 +87,14 @@ class YetiLoader(plugin.Loader): # Create directory for asset and Ayon container root = unreal_pipeline.AYON_ASSET_DIR - asset = context.get('asset').get('name') + folder_path = context["folder"]["path"] + folder_name = context["folder"]["name"] suffix = "_CON" - asset_name = f"{asset}_{name}" if asset else f"{name}" + asset_name = f"{folder_name}_{name}" if folder_name else f"{name}" tools = unreal.AssetToolsHelpers().get_asset_tools() asset_dir, container_name = tools.create_unique_asset_name( - f"{root}/{asset}/{name}", suffix="") + f"{root}/{folder_name}/{name}", suffix="") unique_number = 1 while unreal.EditorAssetLibrary.does_directory_exist( @@ -116,17 +117,21 @@ class YetiLoader(plugin.Loader): unreal_pipeline.create_container( container=container_name, path=asset_dir) + product_type = context["product"]["productType"] data = { "schema": "ayon:container-2.0", "id": AYON_CONTAINER_ID, - "asset": asset, "namespace": asset_dir, "container_name": container_name, + "folder_path": folder_path, "asset_name": asset_name, "loader": str(self.__class__.__name__), - "representation": context["representation"]["_id"], - "parent": context["representation"]["parent"], - "family": context["representation"]["context"]["family"] + "representation": context["representation"]["id"], + "parent": context["representation"]["versionId"], + "product_type": product_type, + # TODO these shold be probably removed + "asset": folder_path, + "family": product_type, } unreal_pipeline.imprint(f"{asset_dir}/{container_name}", data) @@ -140,9 +145,9 @@ class YetiLoader(plugin.Loader): return asset_content def update(self, container, context): - repre_doc = context["representation"] + repre_entity = context["representation"] name = container["asset_name"] - source_path = get_representation_path(repre_doc) + source_path = get_representation_path(repre_entity) destination_path = container["namespace"] task = self.get_task(source_path, destination_path, name, True) @@ -155,8 +160,8 @@ class YetiLoader(plugin.Loader): unreal_pipeline.imprint( container_path, { - "representation": str(repre_doc["_id"]), - "parent": str(repre_doc["parent"]) + "representation": repre_entity["id"], + "parent": repre_entity["versionId"], }) asset_content = unreal.EditorAssetLibrary.list_assets( diff --git a/client/ayon_core/hosts/unreal/plugins/publish/extract_layout.py b/client/ayon_core/hosts/unreal/plugins/publish/extract_layout.py index de8cf0be2a..5489057021 100644 --- a/client/ayon_core/hosts/unreal/plugins/publish/extract_layout.py +++ b/client/ayon_core/hosts/unreal/plugins/publish/extract_layout.py @@ -6,8 +6,8 @@ import math import unreal from unreal import EditorLevelLibrary as ell from unreal import EditorAssetLibrary as eal +import ayon_api -from ayon_core.client import get_representation_by_name from ayon_core.pipeline import publish @@ -60,10 +60,10 @@ class ExtractLayout(publish.Extractor): family = eal.get_metadata_tag(asset_container, "family") self.log.info("Parent: {}".format(parent_id)) - blend = get_representation_by_name( - project_name, "blend", parent_id, fields=["_id"] + blend = ayon_api.get_representation_by_name( + project_name, "blend", parent_id, fields={"id"} ) - blend_id = blend["_id"] + blend_id = blend["id"] json_element = {} json_element["reference"] = str(blend_id)