blender is using product name and type

This commit is contained in:
Jakub Trllo 2024-02-23 11:16:04 +01:00
parent d19a9cc24c
commit 36129a12bd
38 changed files with 275 additions and 240 deletions

View file

@ -30,13 +30,13 @@ VALID_EXTENSIONS = [".blend", ".json", ".abc", ".fbx"]
def prepare_scene_name( def prepare_scene_name(
asset: str, subset: str, namespace: Optional[str] = None folder_name: str, product_name: str, namespace: Optional[str] = None
) -> str: ) -> str:
"""Return a consistent name for an asset.""" """Return a consistent name for an asset."""
name = f"{asset}" name = f"{folder_name}"
if namespace: if namespace:
name = f"{name}_{namespace}" name = f"{name}_{namespace}"
name = f"{name}_{subset}" name = f"{name}_{product_name}"
# Blender name for a collection or object cannot be longer than 63 # Blender name for a collection or object cannot be longer than 63
# characters. If the name is longer, it will raise an error. # characters. If the name is longer, it will raise an error.
@ -47,7 +47,7 @@ def prepare_scene_name(
def get_unique_number( def get_unique_number(
asset: str, subset: str folder_name: str, product_name: str
) -> str: ) -> str:
"""Return a unique number based on the asset name.""" """Return a unique number based on the asset name."""
avalon_container = bpy.data.collections.get(AVALON_CONTAINERS) avalon_container = bpy.data.collections.get(AVALON_CONTAINERS)
@ -64,10 +64,10 @@ def get_unique_number(
if c.get(AVALON_PROPERTY)} if c.get(AVALON_PROPERTY)}
container_names = obj_group_names.union(coll_group_names) container_names = obj_group_names.union(coll_group_names)
count = 1 count = 1
name = f"{asset}_{count:0>2}_{subset}" name = f"{folder_name}_{count:0>2}_{product_name}"
while name in container_names: while name in container_names:
count += 1 count += 1
name = f"{asset}_{count:0>2}_{subset}" name = f"{folder_name}_{count:0>2}_{product_name}"
return f"{count:0>2}" return f"{count:0>2}"
@ -161,24 +161,24 @@ class BaseCreator(Creator):
create_as_asset_group = False create_as_asset_group = False
@staticmethod @staticmethod
def cache_subsets(shared_data): def cache_instance_data(shared_data):
"""Cache instances for Creators shared data. """Cache instances for Creators shared data.
Create `blender_cached_subsets` key when needed in shared data and Create `blender_cached_instances` key when needed in shared data and
fill it with all collected instances from the scene under its fill it with all collected instances from the scene under its
respective creator identifiers. respective creator identifiers.
If legacy instances are detected in the scene, create If legacy instances are detected in the scene, create
`blender_cached_legacy_subsets` key and fill it with `blender_cached_legacy_instances` key and fill it with
all legacy subsets from this family as a value. # key or value? all legacy products from this family as a value. # key or value?
Args: Args:
shared_data(Dict[str, Any]): Shared data. shared_data(Dict[str, Any]): Shared data.
Return: Return:
Dict[str, Any]: Shared data with cached subsets. Dict[str, Any]: Shared data with cached products.
""" """
if not shared_data.get('blender_cached_subsets'): if not shared_data.get('blender_cached_instances'):
cache = {} cache = {}
cache_legacy = {} cache_legacy = {}
@ -210,19 +210,19 @@ class BaseCreator(Creator):
# Legacy creator instance # Legacy creator instance
cache_legacy.setdefault(family, []).append(obj_or_col) cache_legacy.setdefault(family, []).append(obj_or_col)
shared_data["blender_cached_subsets"] = cache shared_data["blender_cached_instances"] = cache
shared_data["blender_cached_legacy_subsets"] = cache_legacy shared_data["blender_cached_legacy_instances"] = cache_legacy
return shared_data return shared_data
def create( def create(
self, subset_name: str, instance_data: dict, pre_create_data: dict self, product_name: str, instance_data: dict, pre_create_data: dict
): ):
"""Override abstract method from Creator. """Override abstract method from Creator.
Create new instance and store it. Create new instance and store it.
Args: Args:
subset_name(str): Subset name of created instance. product_name(str): Subset name of created instance.
instance_data(dict): Instance base data. instance_data(dict): Instance base data.
pre_create_data(dict): Data based on pre creation attributes. pre_create_data(dict): Data based on pre creation attributes.
Those may affect how creator works. Those may affect how creator works.
@ -236,7 +236,7 @@ class BaseCreator(Creator):
# Create asset group # Create asset group
asset_name = instance_data["folderPath"].split("/")[-1] asset_name = instance_data["folderPath"].split("/")[-1]
name = prepare_scene_name(asset_name, subset_name) name = prepare_scene_name(asset_name, product_name)
if self.create_as_asset_group: if self.create_as_asset_group:
# Create instance as empty # Create instance as empty
instance_node = bpy.data.objects.new(name=name, object_data=None) instance_node = bpy.data.objects.new(name=name, object_data=None)
@ -247,10 +247,10 @@ class BaseCreator(Creator):
instance_node = bpy.data.collections.new(name=name) instance_node = bpy.data.collections.new(name=name)
instances.children.link(instance_node) instances.children.link(instance_node)
self.set_instance_data(subset_name, instance_data) self.set_instance_data(product_name, instance_data)
instance = CreatedInstance( instance = CreatedInstance(
self.family, subset_name, instance_data, self self.product_type, product_name, instance_data, self
) )
instance.transient_data["instance_node"] = instance_node instance.transient_data["instance_node"] = instance_node
self._add_instance_to_context(instance) self._add_instance_to_context(instance)
@ -263,18 +263,18 @@ class BaseCreator(Creator):
"""Override abstract method from BaseCreator. """Override abstract method from BaseCreator.
Collect existing instances related to this creator plugin.""" Collect existing instances related to this creator plugin."""
# Cache subsets in shared data # Cache instances in shared data
self.cache_subsets(self.collection_shared_data) self.cache_instance_data(self.collection_shared_data)
# Get cached subsets # Get cached instances
cached_subsets = self.collection_shared_data.get( cached_instances = self.collection_shared_data.get(
"blender_cached_subsets" "blender_cached_instances"
) )
if not cached_subsets: if not cached_instances:
return return
# Process only instances that were created by this creator # Process only instances that were created by this creator
for instance_node in cached_subsets.get(self.identifier, []): for instance_node in cached_instances.get(self.identifier, []):
property = instance_node.get(AVALON_PROPERTY) property = instance_node.get(AVALON_PROPERTY)
# Create instance object from existing data # Create instance object from existing data
instance = CreatedInstance.from_existing( instance = CreatedInstance.from_existing(
@ -306,16 +306,17 @@ class BaseCreator(Creator):
) )
return return
# Rename the instance node in the scene if subset or asset changed. # Rename the instance node in the scene if product
# or folder changed.
# Do not rename the instance if the family is workfile, as the # Do not rename the instance if the family is workfile, as the
# workfile instance is included in the AVALON_CONTAINER collection. # workfile instance is included in the AVALON_CONTAINER collection.
if ( if (
"subset" in changes.changed_keys "productName" in changes.changed_keys
or "folderPath" in changes.changed_keys or "folderPath" in changes.changed_keys
) and created_instance.family != "workfile": ) and created_instance.product_type != "workfile":
asset_name = data["folderPath"].split("/")[-1] asset_name = data["folderPath"].split("/")[-1]
name = prepare_scene_name( name = prepare_scene_name(
asset=asset_name, subset=data["subset"] asset_name, data["productName"]
) )
node.name = name node.name = name
@ -341,13 +342,13 @@ class BaseCreator(Creator):
def set_instance_data( def set_instance_data(
self, self,
subset_name: str, product_name: str,
instance_data: dict instance_data: dict
): ):
"""Fill instance data with required items. """Fill instance data with required items.
Args: Args:
subset_name(str): Subset name of created instance. product_name(str): Subset name of created instance.
instance_data(dict): Instance base data. instance_data(dict): Instance base data.
instance_node(bpy.types.ID): Instance node in blender scene. instance_node(bpy.types.ID): Instance node in blender scene.
""" """
@ -358,7 +359,7 @@ class BaseCreator(Creator):
{ {
"id": AVALON_INSTANCE_ID, "id": AVALON_INSTANCE_ID,
"creator_identifier": self.identifier, "creator_identifier": self.identifier,
"subset": subset_name, "productName": product_name,
} }
) )
@ -466,14 +467,14 @@ class AssetLoader(LoaderPlugin):
filepath = self.filepath_from_context(context) filepath = self.filepath_from_context(context)
assert Path(filepath).exists(), f"{filepath} doesn't exist." assert Path(filepath).exists(), f"{filepath} doesn't exist."
asset = context["asset"]["name"] folder_name = context["asset"]["name"]
subset = context["subset"]["name"] product_name = context["subset"]["name"]
unique_number = get_unique_number( unique_number = get_unique_number(
asset, subset folder_name, product_name
) )
namespace = namespace or f"{asset}_{unique_number}" namespace = namespace or f"{folder_name}_{unique_number}"
name = name or prepare_scene_name( name = name or prepare_scene_name(
asset, subset, unique_number folder_name, product_name, unique_number
) )
nodes = self.process_asset( nodes = self.process_asset(
@ -499,10 +500,10 @@ class AssetLoader(LoaderPlugin):
# loader=self.__class__.__name__, # loader=self.__class__.__name__,
# ) # )
# asset = context["asset"]["name"] # folder_name = context["asset"]["name"]
# subset = context["subset"]["name"] # product_name = context["subset"]["name"]
# instance_name = prepare_scene_name( # instance_name = prepare_scene_name(
# asset, subset, unique_number # folder_name, product_name, unique_number
# ) + '_CON' # ) + '_CON'
# return self._get_instance_collection(instance_name, nodes) # return self._get_instance_collection(instance_name, nodes)

View file

@ -1,24 +1,24 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""Converter for legacy Houdini subsets.""" """Converter for legacy Houdini products."""
from ayon_core.pipeline.create.creator_plugins import SubsetConvertorPlugin from ayon_core.pipeline.create.creator_plugins import SubsetConvertorPlugin
from ayon_core.hosts.blender.api.lib import imprint from ayon_core.hosts.blender.api.lib import imprint
class BlenderLegacyConvertor(SubsetConvertorPlugin): class BlenderLegacyConvertor(SubsetConvertorPlugin):
"""Find and convert any legacy subsets in the scene. """Find and convert any legacy products in the scene.
This Converter will find all legacy subsets in the scene and will This Converter will find all legacy products in the scene and will
transform them to the current system. Since the old subsets doesn't transform them to the current system. Since the old products doesn't
retain any information about their original creators, the only mapping retain any information about their original creators, the only mapping
we can do is based on their families. we can do is based on their product types.
Its limitation is that you can have multiple creators creating subset Its limitation is that you can have multiple creators creating product
of the same family and there is no way to handle it. This code should of the same product type and there is no way to handle it. This code
nevertheless cover all creators that came with OpenPype. should nevertheless cover all creators that came with OpenPype.
""" """
identifier = "io.openpype.creators.blender.legacy" identifier = "io.openpype.creators.blender.legacy"
family_to_id = { product_type_to_id = {
"action": "io.openpype.creators.blender.action", "action": "io.openpype.creators.blender.action",
"camera": "io.openpype.creators.blender.camera", "camera": "io.openpype.creators.blender.camera",
"animation": "io.openpype.creators.blender.animation", "animation": "io.openpype.creators.blender.animation",
@ -33,42 +33,42 @@ class BlenderLegacyConvertor(SubsetConvertorPlugin):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(BlenderLegacyConvertor, self).__init__(*args, **kwargs) super(BlenderLegacyConvertor, self).__init__(*args, **kwargs)
self.legacy_subsets = {} self.legacy_instances = {}
def find_instances(self): def find_instances(self):
"""Find legacy subsets in the scene. """Find legacy products in the scene.
Legacy subsets are the ones that doesn't have `creator_identifier` Legacy products are the ones that doesn't have `creator_identifier`
parameter on them. parameter on them.
This is using cached entries done in This is using cached entries done in
:py:meth:`~BaseCreator.cache_subsets()` :py:meth:`~BaseCreator.cache_instance_data()`
""" """
self.legacy_subsets = self.collection_shared_data.get( self.legacy_instances = self.collection_shared_data.get(
"blender_cached_legacy_subsets") "blender_cached_legacy_instances")
if not self.legacy_subsets: if not self.legacy_instances:
return return
self.add_convertor_item( self.add_convertor_item(
"Found {} incompatible subset{}".format( "Found {} incompatible product{}".format(
len(self.legacy_subsets), len(self.legacy_instances),
"s" if len(self.legacy_subsets) > 1 else "" "s" if len(self.legacy_instances) > 1 else ""
) )
) )
def convert(self): def convert(self):
"""Convert all legacy subsets to current. """Convert all legacy products to current.
It is enough to add `creator_identifier` and `instance_node`. It is enough to add `creator_identifier` and `instance_node`.
""" """
if not self.legacy_subsets: if not self.legacy_instances:
return return
for family, instance_nodes in self.legacy_subsets.items(): for product_type, instance_nodes in self.legacy_instances.items():
if family in self.family_to_id: if product_type in self.product_type_to_id:
for instance_node in instance_nodes: for instance_node in instance_nodes:
creator_identifier = self.family_to_id[family] creator_identifier = self.product_type_to_id[product_type]
self.log.info( self.log.info(
"Converting {} to {}".format(instance_node.name, "Converting {} to {}".format(instance_node.name,
creator_identifier) creator_identifier)

View file

@ -10,20 +10,20 @@ class CreateAction(plugin.BaseCreator):
identifier = "io.openpype.creators.blender.action" identifier = "io.openpype.creators.blender.action"
label = "Action" label = "Action"
family = "action" product_type = "action"
icon = "male" icon = "male"
def create( def create(
self, subset_name: str, instance_data: dict, pre_create_data: dict self, product_name: str, instance_data: dict, pre_create_data: dict
): ):
# Run parent create method # Run parent create method
collection = super().create( collection = super().create(
subset_name, instance_data, pre_create_data product_name, instance_data, pre_create_data
) )
# Get instance name # Get instance name
name = plugin.prepare_scene_name( name = plugin.prepare_scene_name(
instance_data["folderPath"], subset_name instance_data["folderPath"], product_name
) )
if pre_create_data.get("use_selection"): if pre_create_data.get("use_selection"):

View file

@ -8,15 +8,15 @@ class CreateAnimation(plugin.BaseCreator):
identifier = "io.openpype.creators.blender.animation" identifier = "io.openpype.creators.blender.animation"
label = "Animation" label = "Animation"
family = "animation" product_type = "animation"
icon = "male" icon = "male"
def create( def create(
self, subset_name: str, instance_data: dict, pre_create_data: dict self, product_name: str, instance_data: dict, pre_create_data: dict
): ):
# Run parent create method # Run parent create method
collection = super().create( collection = super().create(
subset_name, instance_data, pre_create_data product_name, instance_data, pre_create_data
) )
if pre_create_data.get("use_selection"): if pre_create_data.get("use_selection"):

View file

@ -10,16 +10,16 @@ class CreateBlendScene(plugin.BaseCreator):
identifier = "io.openpype.creators.blender.blendscene" identifier = "io.openpype.creators.blender.blendscene"
label = "Blender Scene" label = "Blender Scene"
family = "blendScene" product_type = "blendScene"
icon = "cubes" icon = "cubes"
maintain_selection = False maintain_selection = False
def create( def create(
self, subset_name: str, instance_data: dict, pre_create_data: dict self, product_name: str, instance_data: dict, pre_create_data: dict
): ):
instance_node = super().create(subset_name, instance_node = super().create(product_name,
instance_data, instance_data,
pre_create_data) pre_create_data)

View file

@ -11,16 +11,16 @@ class CreateCamera(plugin.BaseCreator):
identifier = "io.openpype.creators.blender.camera" identifier = "io.openpype.creators.blender.camera"
label = "Camera" label = "Camera"
family = "camera" product_type = "camera"
icon = "video-camera" icon = "video-camera"
create_as_asset_group = True create_as_asset_group = True
def create( def create(
self, subset_name: str, instance_data: dict, pre_create_data: dict self, product_name: str, instance_data: dict, pre_create_data: dict
): ):
asset_group = super().create(subset_name, asset_group = super().create(product_name,
instance_data, instance_data,
pre_create_data) pre_create_data)
@ -30,8 +30,8 @@ class CreateCamera(plugin.BaseCreator):
obj.parent = asset_group obj.parent = asset_group
else: else:
plugin.deselect_all() plugin.deselect_all()
camera = bpy.data.cameras.new(subset_name) camera = bpy.data.cameras.new(product_name)
camera_obj = bpy.data.objects.new(subset_name, camera) camera_obj = bpy.data.objects.new(product_name, camera)
instances = bpy.data.collections.get(AVALON_INSTANCES) instances = bpy.data.collections.get(AVALON_INSTANCES)
instances.objects.link(camera_obj) instances.objects.link(camera_obj)

View file

@ -10,16 +10,16 @@ class CreateLayout(plugin.BaseCreator):
identifier = "io.openpype.creators.blender.layout" identifier = "io.openpype.creators.blender.layout"
label = "Layout" label = "Layout"
family = "layout" product_type = "layout"
icon = "cubes" icon = "cubes"
create_as_asset_group = True create_as_asset_group = True
def create( def create(
self, subset_name: str, instance_data: dict, pre_create_data: dict self, product_name: str, instance_data: dict, pre_create_data: dict
): ):
asset_group = super().create(subset_name, asset_group = super().create(product_name,
instance_data, instance_data,
pre_create_data) pre_create_data)

View file

@ -10,15 +10,15 @@ class CreateModel(plugin.BaseCreator):
identifier = "io.openpype.creators.blender.model" identifier = "io.openpype.creators.blender.model"
label = "Model" label = "Model"
family = "model" product_type = "model"
icon = "cube" icon = "cube"
create_as_asset_group = True create_as_asset_group = True
def create( def create(
self, subset_name: str, instance_data: dict, pre_create_data: dict self, product_name: str, instance_data: dict, pre_create_data: dict
): ):
asset_group = super().create(subset_name, asset_group = super().create(product_name,
instance_data, instance_data,
pre_create_data) pre_create_data)

View file

@ -8,15 +8,15 @@ class CreatePointcache(plugin.BaseCreator):
identifier = "io.openpype.creators.blender.pointcache" identifier = "io.openpype.creators.blender.pointcache"
label = "Point Cache" label = "Point Cache"
family = "pointcache" product_type = "pointcache"
icon = "gears" icon = "gears"
def create( def create(
self, subset_name: str, instance_data: dict, pre_create_data: dict self, product_name: str, instance_data: dict, pre_create_data: dict
): ):
# Run parent create method # Run parent create method
collection = super().create( collection = super().create(
subset_name, instance_data, pre_create_data product_name, instance_data, pre_create_data
) )
if pre_create_data.get("use_selection"): if pre_create_data.get("use_selection"):

View file

@ -12,16 +12,16 @@ class CreateRenderlayer(plugin.BaseCreator):
identifier = "io.openpype.creators.blender.render" identifier = "io.openpype.creators.blender.render"
label = "Render" label = "Render"
family = "render" product_type = "render"
icon = "eye" icon = "eye"
def create( def create(
self, subset_name: str, instance_data: dict, pre_create_data: dict self, product_name: str, instance_data: dict, pre_create_data: dict
): ):
try: try:
# Run parent create method # Run parent create method
collection = super().create( collection = super().create(
subset_name, instance_data, pre_create_data product_name, instance_data, pre_create_data
) )
prepare_rendering(collection) prepare_rendering(collection)

View file

@ -8,15 +8,15 @@ class CreateReview(plugin.BaseCreator):
identifier = "io.openpype.creators.blender.review" identifier = "io.openpype.creators.blender.review"
label = "Review" label = "Review"
family = "review" product_type = "review"
icon = "video-camera" icon = "video-camera"
def create( def create(
self, subset_name: str, instance_data: dict, pre_create_data: dict self, product_name: str, instance_data: dict, pre_create_data: dict
): ):
# Run parent create method # Run parent create method
collection = super().create( collection = super().create(
subset_name, instance_data, pre_create_data product_name, instance_data, pre_create_data
) )
if pre_create_data.get("use_selection"): if pre_create_data.get("use_selection"):

View file

@ -10,15 +10,15 @@ class CreateRig(plugin.BaseCreator):
identifier = "io.openpype.creators.blender.rig" identifier = "io.openpype.creators.blender.rig"
label = "Rig" label = "Rig"
family = "rig" product_type = "rig"
icon = "wheelchair" icon = "wheelchair"
create_as_asset_group = True create_as_asset_group = True
def create( def create(
self, subset_name: str, instance_data: dict, pre_create_data: dict self, product_name: str, instance_data: dict, pre_create_data: dict
): ):
asset_group = super().create(subset_name, asset_group = super().create(product_name,
instance_data, instance_data,
pre_create_data) pre_create_data)

View file

@ -19,7 +19,7 @@ class CreateWorkfile(BaseCreator, AutoCreator):
""" """
identifier = "io.openpype.creators.blender.workfile" identifier = "io.openpype.creators.blender.workfile"
label = "Workfile" label = "Workfile"
family = "workfile" product_type = "workfile"
icon = "fa5.file" icon = "fa5.file"
def create(self): def create(self):
@ -43,7 +43,7 @@ class CreateWorkfile(BaseCreator, AutoCreator):
if not workfile_instance: if not workfile_instance:
asset_doc = get_asset_by_name(project_name, asset_name) asset_doc = get_asset_by_name(project_name, asset_name)
subset_name = self.get_subset_name( product_name = self.get_product_name(
task_name, task_name, asset_doc, project_name, host_name task_name, task_name, asset_doc, project_name, host_name
) )
data = { data = {
@ -63,7 +63,7 @@ class CreateWorkfile(BaseCreator, AutoCreator):
) )
self.log.info("Auto-creating workfile instance...") self.log.info("Auto-creating workfile instance...")
workfile_instance = CreatedInstance( workfile_instance = CreatedInstance(
self.family, subset_name, data, self self.product_type, product_name, data, self
) )
self._add_instance_to_context(workfile_instance) self._add_instance_to_context(workfile_instance)
@ -73,13 +73,13 @@ class CreateWorkfile(BaseCreator, AutoCreator):
): ):
# Update instance context if it's different # Update instance context if it's different
asset_doc = get_asset_by_name(project_name, asset_name) asset_doc = get_asset_by_name(project_name, asset_name)
subset_name = self.get_subset_name( product_name = self.get_product_name(
task_name, task_name, asset_doc, project_name, host_name task_name, task_name, asset_doc, project_name, host_name
) )
workfile_instance["folderPath"] = asset_name workfile_instance["folderPath"] = asset_name
workfile_instance["task"] = task_name workfile_instance["task"] = task_name
workfile_instance["subset"] = subset_name workfile_instance["productName"] = product_name
instance_node = bpy.data.collections.get(AVALON_CONTAINERS) instance_node = bpy.data.collections.get(AVALON_CONTAINERS)
if not instance_node: if not instance_node:

View file

@ -4,10 +4,10 @@ from ayon_core.hosts.blender.api import plugin
def append_workfile(context, fname, do_import): def append_workfile(context, fname, do_import):
asset = context['asset']['name'] folder_name = context['asset']['name']
subset = context['subset']['name'] product_name = context['subset']['name']
group_name = plugin.prepare_scene_name(asset, subset) group_name = plugin.prepare_scene_name(folder_name, product_name)
# We need to preserve the original names of the scenes, otherwise, # We need to preserve the original names of the scenes, otherwise,
# if there are duplicate names in the current workfile, the imported # if there are duplicate names in the current workfile, the imported

View file

@ -134,13 +134,15 @@ class CacheModelLoader(plugin.AssetLoader):
""" """
libpath = self.filepath_from_context(context) libpath = self.filepath_from_context(context)
asset = context["asset"]["name"] folder_name = context["asset"]["name"]
subset = context["subset"]["name"] product_name = context["subset"]["name"]
asset_name = plugin.prepare_scene_name(asset, subset) asset_name = plugin.prepare_scene_name(folder_name, product_name)
unique_number = plugin.get_unique_number(asset, subset) unique_number = plugin.get_unique_number(folder_name, product_name)
group_name = plugin.prepare_scene_name(asset, subset, unique_number) group_name = plugin.prepare_scene_name(
namespace = namespace or f"{asset}_{unique_number}" folder_name, product_name, unique_number
)
namespace = namespace or f"{folder_name}_{unique_number}"
containers = bpy.data.collections.get(AVALON_CONTAINERS) containers = bpy.data.collections.get(AVALON_CONTAINERS)
if not containers: if not containers:
@ -159,6 +161,7 @@ class CacheModelLoader(plugin.AssetLoader):
self._link_objects(objects, asset_group, containers, asset_group) self._link_objects(objects, asset_group, containers, asset_group)
product_type = context["subset"]["data"]["family"]
asset_group[AVALON_PROPERTY] = { asset_group[AVALON_PROPERTY] = {
"schema": "openpype:container-2.0", "schema": "openpype:container-2.0",
"id": AVALON_CONTAINER_ID, "id": AVALON_CONTAINER_ID,
@ -169,7 +172,7 @@ class CacheModelLoader(plugin.AssetLoader):
"libpath": libpath, "libpath": libpath,
"asset_name": asset_name, "asset_name": asset_name,
"parent": str(context["representation"]["parent"]), "parent": str(context["representation"]["parent"]),
"family": context["representation"]["context"]["family"], "productType": product_type,
"objectName": group_name "objectName": group_name
} }

View file

@ -44,11 +44,11 @@ class BlendActionLoader(plugin.AssetLoader):
""" """
libpath = self.filepath_from_context(context) libpath = self.filepath_from_context(context)
asset = context["asset"]["name"] folder_name = context["asset"]["name"]
subset = context["subset"]["name"] product_name = context["subset"]["name"]
lib_container = plugin.prepare_scene_name(asset, subset) lib_container = plugin.prepare_scene_name(folder_name, product_name)
container_name = plugin.prepare_scene_name( container_name = plugin.prepare_scene_name(
asset, subset, namespace folder_name, product_name, namespace
) )
container = bpy.data.collections.new(lib_container) container = bpy.data.collections.new(lib_container)

View file

@ -39,13 +39,15 @@ class AudioLoader(plugin.AssetLoader):
options: Additional settings dictionary options: Additional settings dictionary
""" """
libpath = self.filepath_from_context(context) libpath = self.filepath_from_context(context)
asset = context["asset"]["name"] folder_name = context["asset"]["name"]
subset = context["subset"]["name"] product_name = context["subset"]["name"]
asset_name = plugin.prepare_scene_name(asset, subset) asset_name = plugin.prepare_scene_name(folder_name, product_name)
unique_number = plugin.get_unique_number(asset, subset) unique_number = plugin.get_unique_number(folder_name, product_name)
group_name = plugin.prepare_scene_name(asset, subset, unique_number) group_name = plugin.prepare_scene_name(
namespace = namespace or f"{asset}_{unique_number}" folder_name, product_name, unique_number
)
namespace = namespace or f"{folder_name}_{unique_number}"
avalon_container = bpy.data.collections.get(AVALON_CONTAINERS) avalon_container = bpy.data.collections.get(AVALON_CONTAINERS)
if not avalon_container: if not avalon_container:
@ -85,7 +87,7 @@ class AudioLoader(plugin.AssetLoader):
"libpath": libpath, "libpath": libpath,
"asset_name": asset_name, "asset_name": asset_name,
"parent": str(context["representation"]["parent"]), "parent": str(context["representation"]["parent"]),
"family": context["representation"]["context"]["family"], "productType": context["subset"]["data"]["family"],
"objectName": group_name, "objectName": group_name,
"audio": audio "audio": audio
} }

View file

@ -127,20 +127,22 @@ class BlendLoader(plugin.AssetLoader):
options: Additional settings dictionary options: Additional settings dictionary
""" """
libpath = self.filepath_from_context(context) libpath = self.filepath_from_context(context)
asset = context["asset"]["name"] folder_name = context["asset"]["name"]
subset = context["subset"]["name"] product_name = context["subset"]["name"]
try: try:
family = context["representation"]["context"]["family"] product_type = context["subset"]["data"]["family"]
except ValueError: except ValueError:
family = "model" product_type = "model"
representation = str(context["representation"]["_id"]) representation = str(context["representation"]["_id"])
asset_name = plugin.prepare_scene_name(asset, subset) asset_name = plugin.prepare_scene_name(folder_name, product_name)
unique_number = plugin.get_unique_number(asset, subset) unique_number = plugin.get_unique_number(folder_name, product_name)
group_name = plugin.prepare_scene_name(asset, subset, unique_number) group_name = plugin.prepare_scene_name(
namespace = namespace or f"{asset}_{unique_number}" folder_name, product_name, unique_number
)
namespace = namespace or f"{folder_name}_{unique_number}"
avalon_container = bpy.data.collections.get(AVALON_CONTAINERS) avalon_container = bpy.data.collections.get(AVALON_CONTAINERS)
if not avalon_container: if not avalon_container:
@ -149,8 +151,8 @@ class BlendLoader(plugin.AssetLoader):
container, members = self._process_data(libpath, group_name) container, members = self._process_data(libpath, group_name)
if family == "layout": if product_type == "layout":
self._post_process_layout(container, asset, representation) self._post_process_layout(container, folder_name, representation)
avalon_container.objects.link(container) avalon_container.objects.link(container)
@ -164,7 +166,7 @@ class BlendLoader(plugin.AssetLoader):
"libpath": libpath, "libpath": libpath,
"asset_name": asset_name, "asset_name": asset_name,
"parent": str(context["representation"]["parent"]), "parent": str(context["representation"]["parent"]),
"family": context["representation"]["context"]["family"], "productType": context["subset"]["data"]["family"],
"objectName": group_name, "objectName": group_name,
"members": members, "members": members,
} }

View file

@ -34,7 +34,7 @@ class BlendSceneLoader(plugin.AssetLoader):
return None return None
def _process_data(self, libpath, group_name, family): def _process_data(self, libpath, group_name, product_type):
# Append all the data from the .blend file # Append all the data from the .blend file
with bpy.data.libraries.load( with bpy.data.libraries.load(
libpath, link=False, relative=False libpath, link=False, relative=False
@ -82,25 +82,29 @@ class BlendSceneLoader(plugin.AssetLoader):
options: Additional settings dictionary options: Additional settings dictionary
""" """
libpath = self.filepath_from_context(context) libpath = self.filepath_from_context(context)
asset = context["asset"]["name"] folder_name = context["asset"]["name"]
subset = context["subset"]["name"] product_name = context["subset"]["name"]
try: try:
family = context["representation"]["context"]["family"] product_type = context["subset"]["data"]["family"]
except ValueError: except ValueError:
family = "model" product_type = "model"
asset_name = plugin.prepare_scene_name(asset, subset) asset_name = plugin.prepare_scene_name(folder_name, product_name)
unique_number = plugin.get_unique_number(asset, subset) unique_number = plugin.get_unique_number(folder_name, product_name)
group_name = plugin.prepare_scene_name(asset, subset, unique_number) group_name = plugin.prepare_scene_name(
namespace = namespace or f"{asset}_{unique_number}" folder_name, product_name, unique_number
)
namespace = namespace or f"{folder_name}_{unique_number}"
avalon_container = bpy.data.collections.get(AVALON_CONTAINERS) avalon_container = bpy.data.collections.get(AVALON_CONTAINERS)
if not avalon_container: if not avalon_container:
avalon_container = bpy.data.collections.new(name=AVALON_CONTAINERS) avalon_container = bpy.data.collections.new(name=AVALON_CONTAINERS)
bpy.context.scene.collection.children.link(avalon_container) bpy.context.scene.collection.children.link(avalon_container)
container, members = self._process_data(libpath, group_name, family) container, members = self._process_data(
libpath, group_name, product_type
)
avalon_container.children.link(container) avalon_container.children.link(container)
@ -114,7 +118,7 @@ class BlendSceneLoader(plugin.AssetLoader):
"libpath": libpath, "libpath": libpath,
"asset_name": asset_name, "asset_name": asset_name,
"parent": str(context["representation"]["parent"]), "parent": str(context["representation"]["parent"]),
"family": context["representation"]["context"]["family"], "productType": context["subset"]["data"]["family"],
"objectName": group_name, "objectName": group_name,
"members": members, "members": members,
} }
@ -167,8 +171,12 @@ class BlendSceneLoader(plugin.AssetLoader):
self.exec_remove(container) self.exec_remove(container)
family = container["family"] product_type = container.get("productType")
asset_group, members = self._process_data(libpath, group_name, family) if product_type is None:
product_type = container["family"]
asset_group, members = self._process_data(
libpath, group_name, product_type
)
for member in members: for member in members:
if member.name in collection_parents: if member.name in collection_parents:

View file

@ -84,13 +84,15 @@ class AbcCameraLoader(plugin.AssetLoader):
libpath = self.filepath_from_context(context) libpath = self.filepath_from_context(context)
asset = context["asset"]["name"] folder_name = context["asset"]["name"]
subset = context["subset"]["name"] product_name = context["subset"]["name"]
asset_name = plugin.prepare_scene_name(asset, subset) asset_name = plugin.prepare_scene_name(folder_name, product_name)
unique_number = plugin.get_unique_number(asset, subset) unique_number = plugin.get_unique_number(folder_name, product_name)
group_name = plugin.prepare_scene_name(asset, subset, unique_number) group_name = plugin.prepare_scene_name(
namespace = namespace or f"{asset}_{unique_number}" folder_name, product_name, unique_number
)
namespace = namespace or f"{folder_name}_{unique_number}"
avalon_container = bpy.data.collections.get(AVALON_CONTAINERS) avalon_container = bpy.data.collections.get(AVALON_CONTAINERS)
if not avalon_container: if not avalon_container:
@ -121,7 +123,7 @@ class AbcCameraLoader(plugin.AssetLoader):
"libpath": libpath, "libpath": libpath,
"asset_name": asset_name, "asset_name": asset_name,
"parent": str(context["representation"]["parent"]), "parent": str(context["representation"]["parent"]),
"family": context["representation"]["context"]["family"], "productType": context["subset"]["data"]["family"],
"objectName": group_name, "objectName": group_name,
} }

View file

@ -87,13 +87,15 @@ class FbxCameraLoader(plugin.AssetLoader):
options: Additional settings dictionary options: Additional settings dictionary
""" """
libpath = self.filepath_from_context(context) libpath = self.filepath_from_context(context)
asset = context["asset"]["name"] folder_name = context["asset"]["name"]
subset = context["subset"]["name"] product_name = context["subset"]["name"]
asset_name = plugin.prepare_scene_name(asset, subset) asset_name = plugin.prepare_scene_name(folder_name, product_name)
unique_number = plugin.get_unique_number(asset, subset) unique_number = plugin.get_unique_number(folder_name, product_name)
group_name = plugin.prepare_scene_name(asset, subset, unique_number) group_name = plugin.prepare_scene_name(
namespace = namespace or f"{asset}_{unique_number}" folder_name, product_name, unique_number
)
namespace = namespace or f"{folder_name}_{unique_number}"
avalon_container = bpy.data.collections.get(AVALON_CONTAINERS) avalon_container = bpy.data.collections.get(AVALON_CONTAINERS)
if not avalon_container: if not avalon_container:
@ -124,7 +126,7 @@ class FbxCameraLoader(plugin.AssetLoader):
"libpath": libpath, "libpath": libpath,
"asset_name": asset_name, "asset_name": asset_name,
"parent": str(context["representation"]["parent"]), "parent": str(context["representation"]["parent"]),
"family": context["representation"]["context"]["family"], "productType": context["subset"]["data"]["family"],
"objectName": group_name "objectName": group_name
} }

View file

@ -131,13 +131,15 @@ class FbxModelLoader(plugin.AssetLoader):
options: Additional settings dictionary options: Additional settings dictionary
""" """
libpath = self.filepath_from_context(context) libpath = self.filepath_from_context(context)
asset = context["asset"]["name"] folder_name = context["asset"]["name"]
subset = context["subset"]["name"] product_name = context["subset"]["name"]
asset_name = plugin.prepare_scene_name(asset, subset) asset_name = plugin.prepare_scene_name(folder_name, product_name)
unique_number = plugin.get_unique_number(asset, subset) unique_number = plugin.get_unique_number(folder_name, product_name)
group_name = plugin.prepare_scene_name(asset, subset, unique_number) group_name = plugin.prepare_scene_name(
namespace = namespace or f"{asset}_{unique_number}" folder_name, product_name, unique_number
)
namespace = namespace or f"{folder_name}_{unique_number}"
avalon_container = bpy.data.collections.get(AVALON_CONTAINERS) avalon_container = bpy.data.collections.get(AVALON_CONTAINERS)
if not avalon_container: if not avalon_container:
@ -168,7 +170,7 @@ class FbxModelLoader(plugin.AssetLoader):
"libpath": libpath, "libpath": libpath,
"asset_name": asset_name, "asset_name": asset_name,
"parent": str(context["representation"]["parent"]), "parent": str(context["representation"]["parent"]),
"family": context["representation"]["context"]["family"], "productType": context["subset"]["data"]["family"],
"objectName": group_name "objectName": group_name
} }

View file

@ -50,11 +50,11 @@ class JsonLayoutLoader(plugin.AssetLoader):
if anim_collection: if anim_collection:
bpy.data.collections.remove(anim_collection) bpy.data.collections.remove(anim_collection)
def _get_loader(self, loaders, family): def _get_loader(self, loaders, product_type):
name = "" name = ""
if family == 'rig': if product_type == 'rig':
name = "BlendRigLoader" name = "BlendRigLoader"
elif family == 'model': elif product_type == 'model':
name = "BlendModelLoader" name = "BlendModelLoader"
if name == "": if name == "":
@ -76,10 +76,12 @@ class JsonLayoutLoader(plugin.AssetLoader):
for element in data: for element in data:
reference = element.get('reference') reference = element.get('reference')
family = element.get('family') product_type = element.get("product_type")
if product_type is None:
product_type = element.get("family")
loaders = loaders_from_representation(all_loaders, reference) loaders = loaders_from_representation(all_loaders, reference)
loader = self._get_loader(loaders, family) loader = self._get_loader(loaders, product_type)
if not loader: if not loader:
continue continue
@ -95,7 +97,7 @@ class JsonLayoutLoader(plugin.AssetLoader):
'parent': asset_group, 'parent': asset_group,
'transform': element.get('transform'), 'transform': element.get('transform'),
'action': action, 'action': action,
'create_animation': True if family == 'rig' else False, 'create_animation': True if product_type == 'rig' else False,
'animation_asset': asset 'animation_asset': asset
} }
@ -127,7 +129,7 @@ class JsonLayoutLoader(plugin.AssetLoader):
# legacy_create( # legacy_create(
# creator_plugin, # creator_plugin,
# name="camera", # name="camera",
# # name=f"{unique_number}_{subset}_animation", # # name=f"{unique_number}_{product[name]}_animation",
# asset=asset, # asset=asset,
# options={"useSelection": False} # options={"useSelection": False}
# # data={"dependencies": str(context["representation"]["_id"])} # # data={"dependencies": str(context["representation"]["_id"])}
@ -146,13 +148,15 @@ class JsonLayoutLoader(plugin.AssetLoader):
options: Additional settings dictionary options: Additional settings dictionary
""" """
libpath = self.filepath_from_context(context) libpath = self.filepath_from_context(context)
asset = context["asset"]["name"] folder_name = context["asset"]["name"]
subset = context["subset"]["name"] product_name = context["subset"]["name"]
asset_name = plugin.prepare_scene_name(asset, subset) asset_name = plugin.prepare_scene_name(folder_name, product_name)
unique_number = plugin.get_unique_number(asset, subset) unique_number = plugin.get_unique_number(folder_name, product_name)
group_name = plugin.prepare_scene_name(asset, subset, unique_number) group_name = plugin.prepare_scene_name(
namespace = namespace or f"{asset}_{unique_number}" folder_name, product_name, unique_number
)
namespace = namespace or f"{folder_name}_{unique_number}"
avalon_container = bpy.data.collections.get(AVALON_CONTAINERS) avalon_container = bpy.data.collections.get(AVALON_CONTAINERS)
if not avalon_container: if not avalon_container:
@ -177,7 +181,7 @@ class JsonLayoutLoader(plugin.AssetLoader):
"libpath": libpath, "libpath": libpath,
"asset_name": asset_name, "asset_name": asset_name,
"parent": str(context["representation"]["parent"]), "parent": str(context["representation"]["parent"]),
"family": context["representation"]["context"]["family"], "productType": context["subset"]["data"]["family"],
"objectName": group_name "objectName": group_name
} }
@ -239,7 +243,10 @@ class JsonLayoutLoader(plugin.AssetLoader):
for obj in asset_group.children: for obj in asset_group.children:
obj_meta = obj.get(AVALON_PROPERTY) obj_meta = obj.get(AVALON_PROPERTY)
if obj_meta.get('family') == 'rig': product_type = obj_meta.get("productType")
if product_type is None:
product_type = obj_meta.get("family")
if product_type == "rig":
rig = None rig = None
for child in obj.children: for child in obj.children:
if child.type == 'ARMATURE': if child.type == 'ARMATURE':

View file

@ -93,18 +93,18 @@ class BlendLookLoader(plugin.AssetLoader):
""" """
libpath = self.filepath_from_context(context) libpath = self.filepath_from_context(context)
asset = context["asset"]["name"] folder_name = context["asset"]["name"]
subset = context["subset"]["name"] product_name = context["subset"]["name"]
lib_container = plugin.prepare_scene_name( lib_container = plugin.prepare_scene_name(
asset, subset folder_name, product_name
) )
unique_number = plugin.get_unique_number( unique_number = plugin.get_unique_number(
asset, subset folder_name, product_name
) )
namespace = namespace or f"{asset}_{unique_number}" namespace = namespace or f"{folder_name}_{unique_number}"
container_name = plugin.prepare_scene_name( container_name = plugin.prepare_scene_name(
asset, subset, unique_number folder_name, product_name, unique_number
) )
container = bpy.data.collections.new(lib_container) container = bpy.data.collections.new(lib_container)
@ -131,7 +131,7 @@ class BlendLookLoader(plugin.AssetLoader):
metadata["materials"] = materials metadata["materials"] = materials
metadata["parent"] = str(context["representation"]["parent"]) metadata["parent"] = str(context["representation"]["parent"])
metadata["family"] = context["representation"]["context"]["family"] metadata["product_type"] = context["subset"]["data"]["family"]
nodes = list(container.objects) nodes = list(container.objects)
nodes.append(container) nodes.append(container)

View file

@ -25,7 +25,7 @@ class CollectBlenderInstanceData(pyblish.api.InstancePlugin):
members.extend(instance_node.children) members.extend(instance_node.children)
# Special case for animation instances, include armatures # Special case for animation instances, include armatures
if instance.data["family"] == "animation": if instance.data["productType"] == "animation":
for obj in instance_node.objects: for obj in instance_node.objects:
if obj.type == 'EMPTY' and obj.get(AVALON_PROPERTY): if obj.type == 'EMPTY' and obj.get(AVALON_PROPERTY):
members.extend( members.extend(

View file

@ -19,9 +19,9 @@ class ExtractABC(publish.Extractor, publish.OptionalPyblishPluginMixin):
# Define extract output file path # Define extract output file path
stagingdir = self.staging_dir(instance) stagingdir = self.staging_dir(instance)
asset_name = instance.data["assetEntity"]["name"] folder_name = instance.data["assetEntity"]["name"]
subset = instance.data["subset"] product_name = instance.data["productName"]
instance_name = f"{asset_name}_{subset}" instance_name = f"{folder_name}_{product_name}"
filename = f"{instance_name}.abc" filename = f"{instance_name}.abc"
filepath = os.path.join(stagingdir, filename) filepath = os.path.join(stagingdir, filename)

View file

@ -23,9 +23,9 @@ class ExtractAnimationABC(
# Define extract output file path # Define extract output file path
stagingdir = self.staging_dir(instance) stagingdir = self.staging_dir(instance)
asset_name = instance.data["assetEntity"]["name"] folder_name = instance.data["assetEntity"]["name"]
subset = instance.data["subset"] product_name = instance.data["prouctName"]
instance_name = f"{asset_name}_{subset}" instance_name = f"{folder_name}_{product_name}"
filename = f"{instance_name}.abc" filename = f"{instance_name}.abc"
filepath = os.path.join(stagingdir, filename) filepath = os.path.join(stagingdir, filename)

View file

@ -20,9 +20,9 @@ class ExtractBlend(publish.Extractor, publish.OptionalPyblishPluginMixin):
# Define extract output file path # Define extract output file path
stagingdir = self.staging_dir(instance) stagingdir = self.staging_dir(instance)
asset_name = instance.data["assetEntity"]["name"] folder_name = instance.data["assetEntity"]["name"]
subset = instance.data["subset"] product_name = instance.data["prouctName"]
instance_name = f"{asset_name}_{subset}" instance_name = f"{folder_name}_{product_name}"
filename = f"{instance_name}.blend" filename = f"{instance_name}.blend"
filepath = os.path.join(stagingdir, filename) filepath = os.path.join(stagingdir, filename)

View file

@ -23,9 +23,9 @@ class ExtractBlendAnimation(
# Define extract output file path # Define extract output file path
stagingdir = self.staging_dir(instance) stagingdir = self.staging_dir(instance)
asset_name = instance.data["assetEntity"]["name"] folder_name = instance.data["assetEntity"]["name"]
subset = instance.data["subset"] product_name = instance.data["prouctName"]
instance_name = f"{asset_name}_{subset}" instance_name = f"{folder_name}_{product_name}"
filename = f"{instance_name}.blend" filename = f"{instance_name}.blend"
filepath = os.path.join(stagingdir, filename) filepath = os.path.join(stagingdir, filename)

View file

@ -21,9 +21,9 @@ class ExtractCameraABC(publish.Extractor, publish.OptionalPyblishPluginMixin):
# Define extract output file path # Define extract output file path
stagingdir = self.staging_dir(instance) stagingdir = self.staging_dir(instance)
asset_name = instance.data["assetEntity"]["name"] folder_name = instance.data["assetEntity"]["name"]
subset = instance.data["subset"] product_name = instance.data["productName"]
instance_name = f"{asset_name}_{subset}" instance_name = f"{folder_name}_{product_name}"
filename = f"{instance_name}.abc" filename = f"{instance_name}.abc"
filepath = os.path.join(stagingdir, filename) filepath = os.path.join(stagingdir, filename)

View file

@ -20,9 +20,9 @@ class ExtractCamera(publish.Extractor, publish.OptionalPyblishPluginMixin):
# Define extract output file path # Define extract output file path
stagingdir = self.staging_dir(instance) stagingdir = self.staging_dir(instance)
asset_name = instance.data["assetEntity"]["name"] folder_name = instance.data["assetEntity"]["name"]
subset = instance.data["subset"] product_name = instance.data["prouctName"]
instance_name = f"{asset_name}_{subset}" instance_name = f"{folder_name}_{product_name}"
filename = f"{instance_name}.fbx" filename = f"{instance_name}.fbx"
filepath = os.path.join(stagingdir, filename) filepath = os.path.join(stagingdir, filename)

View file

@ -21,9 +21,9 @@ class ExtractFBX(publish.Extractor, publish.OptionalPyblishPluginMixin):
# Define extract output file path # Define extract output file path
stagingdir = self.staging_dir(instance) stagingdir = self.staging_dir(instance)
asset_name = instance.data["assetEntity"]["name"] folder_name = instance.data["assetEntity"]["name"]
subset = instance.data["subset"] product_name = instance.data["prouctName"]
instance_name = f"{asset_name}_{subset}" instance_name = f"{folder_name}_{product_name}"
filename = f"{instance_name}.fbx" filename = f"{instance_name}.fbx"
filepath = os.path.join(stagingdir, filename) filepath = os.path.join(stagingdir, filename)

View file

@ -145,9 +145,9 @@ class ExtractAnimationFBX(
root.select_set(True) root.select_set(True)
armature.select_set(True) armature.select_set(True)
asset_name = instance.data["assetEntity"]["name"] folder_name = instance.data["assetEntity"]["name"]
subset = instance.data["subset"] product_name = instance.data["prouctName"]
instance_name = f"{asset_name}_{subset}" instance_name = f"{folder_name}_{product_name}"
fbx_filename = f"{instance_name}_{armature.name}.fbx" fbx_filename = f"{instance_name}_{armature.name}.fbx"
filepath = os.path.join(stagingdir, fbx_filename) filepath = os.path.join(stagingdir, fbx_filename)

View file

@ -133,7 +133,7 @@ class ExtractLayout(publish.Extractor, publish.OptionalPyblishPluginMixin):
fbx_count = 0 fbx_count = 0
project_name = instance.context.data["projectEntity"]["name"] project_name = instance.context.data["projectName"]
for asset in asset_group.children: for asset in asset_group.children:
metadata = asset.get(AVALON_PROPERTY) metadata = asset.get(AVALON_PROPERTY)
if not metadata: if not metadata:
@ -147,7 +147,9 @@ class ExtractLayout(publish.Extractor, publish.OptionalPyblishPluginMixin):
continue continue
version_id = metadata["parent"] version_id = metadata["parent"]
family = metadata["family"] product_type = metadata.get("product_type")
if product_type is None:
product_type = metadata["family"]
self.log.debug("Parent: {}".format(version_id)) self.log.debug("Parent: {}".format(version_id))
# Get blend reference # Get blend reference
@ -179,7 +181,8 @@ class ExtractLayout(publish.Extractor, publish.OptionalPyblishPluginMixin):
json_element["reference_fbx"] = str(fbx_id) json_element["reference_fbx"] = str(fbx_id)
if abc_id: if abc_id:
json_element["reference_abc"] = str(abc_id) json_element["reference_abc"] = str(abc_id)
json_element["family"] = family json_element["family"] = product_type
json_element["product_type"] = product_type
json_element["instance_name"] = asset.name json_element["instance_name"] = asset.name
json_element["asset_name"] = metadata["asset_name"] json_element["asset_name"] = metadata["asset_name"]
json_element["file_path"] = metadata["libpath"] json_element["file_path"] = metadata["libpath"]
@ -215,7 +218,7 @@ class ExtractLayout(publish.Extractor, publish.OptionalPyblishPluginMixin):
] ]
# Extract the animation as well # Extract the animation as well
if family == "rig": if product_type == "rig":
f, n = self._export_animation( f, n = self._export_animation(
asset, instance, stagingdir, fbx_count) asset, instance, stagingdir, fbx_count)
if f: if f:
@ -225,9 +228,9 @@ class ExtractLayout(publish.Extractor, publish.OptionalPyblishPluginMixin):
json_data.append(json_element) json_data.append(json_element)
asset_name = instance.data["assetEntity"]["name"] folder_name = instance.data["assetEntity"]["name"]
subset = instance.data["subset"] product_name = instance.data["productName"]
instance_name = f"{asset_name}_{subset}" instance_name = f"{folder_name}_{product_name}"
json_filename = f"{instance_name}.json" json_filename = f"{instance_name}.json"
json_path = os.path.join(stagingdir, json_filename) json_path = os.path.join(stagingdir, json_filename)

View file

@ -55,9 +55,9 @@ class ExtractPlayblast(publish.Extractor, publish.OptionalPyblishPluginMixin):
# get output path # get output path
stagingdir = self.staging_dir(instance) stagingdir = self.staging_dir(instance)
asset_name = instance.data["assetEntity"]["name"] folder_name = instance.data["assetEntity"]["name"]
subset = instance.data["subset"] product_name = instance.data["prouctName"]
filename = f"{asset_name}_{subset}" filename = f"{folder_name}_{product_name}"
path = os.path.join(stagingdir, filename) path = os.path.join(stagingdir, filename)

View file

@ -32,9 +32,9 @@ class ExtractThumbnail(publish.Extractor):
return return
stagingdir = self.staging_dir(instance) stagingdir = self.staging_dir(instance)
asset_name = instance.data["assetEntity"]["name"] folder_name = instance.data["assetEntity"]["name"]
subset = instance.data["subset"] product_name = instance.data["prouctName"]
filename = f"{asset_name}_{subset}" filename = f"{folder_name}_{product_name}"
path = os.path.join(stagingdir, filename) path = os.path.join(stagingdir, filename)
@ -42,11 +42,11 @@ class ExtractThumbnail(publish.Extractor):
camera = instance.data.get("review_camera", "AUTO") camera = instance.data.get("review_camera", "AUTO")
start = instance.data.get("frameStart", bpy.context.scene.frame_start) start = instance.data.get("frameStart", bpy.context.scene.frame_start)
family = instance.data.get("family") product_type = instance.data["productType"]
isolate = instance.data("isolate", None) isolate = instance.data("isolate", None)
presets = json.loads(self.presets) presets = json.loads(self.presets)
preset = presets.get(family, {}) preset = presets.get(product_type, {})
preset.update({ preset.update({
"camera": camera, "camera": camera,

View file

@ -28,25 +28,27 @@ class IntegrateAnimation(
# Update the json file for the setdress to add the published # Update the json file for the setdress to add the published
# representations of the animations # representations of the animations
for json_dict in data: for json_dict in data:
json_product_name = json_dict["productName"]
i = None i = None
for elem in instance.context: for elem in instance.context:
if elem.data.get('subset') == json_dict['subset']: if elem.data["productName"] == json_product_name:
i = elem i = elem
break break
if not i: if not i:
continue continue
rep = None rep = None
pub_repr = i.data.get('published_representations') pub_repr = i.data["published_representations"]
for elem in pub_repr: for elem in pub_repr:
if pub_repr.get(elem).get('representation').get('name') == "fbx": if pub_repr[elem]["representation"]["name"] == "fbx":
rep = pub_repr.get(elem) rep = pub_repr[elem]
break break
if not rep: if not rep:
continue continue
obj_id = rep.get('representation').get('_id') obj_id = rep["representation"]["_id"]
if obj_id: if obj_id:
json_dict['_id'] = str(obj_id) json_dict["_id"] = str(obj_id)
json_dict["representation_id"] = str(obj_id)
with open(json_path, "w") as file: with open(json_path, "w") as file:
json.dump(data, fp=file, indent=2) json.dump(data, fp=file, indent=2)

View file

@ -26,6 +26,7 @@ class ValidateFileSaved(pyblish.api.ContextPlugin,
hosts = ["blender"] hosts = ["blender"]
label = "Validate File Saved" label = "Validate File Saved"
optional = False optional = False
# TODO rename to 'exclude_product_types'
exclude_families = [] exclude_families = []
actions = [SaveWorkfileAction] actions = [SaveWorkfileAction]
@ -41,8 +42,8 @@ class ValidateFileSaved(pyblish.api.ContextPlugin,
# Do not validate workfile has unsaved changes if only instances # Do not validate workfile has unsaved changes if only instances
# present of families that should be excluded # present of families that should be excluded
families = { product_types = {
instance.data["family"] for instance in context instance.data["productType"] for instance in context
# Consider only enabled instances # Consider only enabled instances
if instance.data.get("publish", True) if instance.data.get("publish", True)
and instance.data.get("active", True) and instance.data.get("active", True)
@ -52,7 +53,7 @@ class ValidateFileSaved(pyblish.api.ContextPlugin,
return any(family in exclude_family return any(family in exclude_family
for exclude_family in self.exclude_families) for exclude_family in self.exclude_families)
if all(is_excluded(family) for family in families): if all(is_excluded(product_type) for product_type in product_types):
self.log.debug("Only excluded families found, skipping workfile " self.log.debug("Only excluded families found, skipping workfile "
"unsaved changes validation..") "unsaved changes validation..")
return return