mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-25 05:14:40 +01:00
fusion is using product name and type
This commit is contained in:
parent
cf0ac31aa6
commit
800249daab
7 changed files with 81 additions and 57 deletions
|
|
@ -33,14 +33,16 @@ class GenericCreateSaver(Creator):
|
|||
|
||||
# TODO: This should be renamed together with Nuke so it is aligned
|
||||
temp_rendering_path_template = (
|
||||
"{workdir}/renders/fusion/{subset}/{subset}.{frame}.{ext}")
|
||||
"{workdir}/renders/fusion/{product[name]}/"
|
||||
"{product[name]}.{frame}.{ext}"
|
||||
)
|
||||
|
||||
def create(self, subset_name, instance_data, pre_create_data):
|
||||
def create(self, product_name, instance_data, pre_create_data):
|
||||
self.pass_pre_attributes_to_instance(instance_data, pre_create_data)
|
||||
|
||||
instance = CreatedInstance(
|
||||
family=self.family,
|
||||
subset_name=subset_name,
|
||||
product_type=self.product_type,
|
||||
product_name=product_name,
|
||||
data=instance_data,
|
||||
creator=self,
|
||||
)
|
||||
|
|
@ -111,23 +113,23 @@ class GenericCreateSaver(Creator):
|
|||
tool.SetData(f"openpype.{key}", value)
|
||||
|
||||
def _update_tool_with_data(self, tool, data):
|
||||
"""Update tool node name and output path based on subset data"""
|
||||
if "subset" not in data:
|
||||
"""Update tool node name and output path based on product data"""
|
||||
if "productName" not in data:
|
||||
return
|
||||
|
||||
original_subset = tool.GetData("openpype.subset")
|
||||
original_product_name = tool.GetData("openpype.productName")
|
||||
original_format = tool.GetData(
|
||||
"openpype.creator_attributes.image_format"
|
||||
)
|
||||
|
||||
subset = data["subset"]
|
||||
product_name = data["productName"]
|
||||
if (
|
||||
original_subset != subset
|
||||
original_product_name != product_name
|
||||
or original_format != data["creator_attributes"]["image_format"]
|
||||
):
|
||||
self._configure_saver_tool(data, tool, subset)
|
||||
self._configure_saver_tool(data, tool, product_name)
|
||||
|
||||
def _configure_saver_tool(self, data, tool, subset):
|
||||
def _configure_saver_tool(self, data, tool, product_name):
|
||||
formatting_data = deepcopy(data)
|
||||
|
||||
# get frame padding from anatomy templates
|
||||
|
|
@ -137,25 +139,39 @@ class GenericCreateSaver(Creator):
|
|||
ext = data["creator_attributes"]["image_format"]
|
||||
|
||||
# Subset change detected
|
||||
product_type = formatting_data["productType"]
|
||||
f_product_name = formatting_data["productName"]
|
||||
|
||||
folder_path = formatting_data["folderPath"]
|
||||
folder_name = folder_path.rsplit("/", 1)[-1]
|
||||
|
||||
workdir = os.path.normpath(os.getenv("AYON_WORKDIR"))
|
||||
formatting_data.update({
|
||||
"workdir": workdir,
|
||||
"frame": "0" * frame_padding,
|
||||
"ext": ext,
|
||||
"product": {
|
||||
"name": formatting_data["subset"],
|
||||
"type": formatting_data["family"],
|
||||
"name": f_product_name,
|
||||
"type": product_type,
|
||||
},
|
||||
# TODO add more variants for 'folder' and 'task'
|
||||
"folder": {
|
||||
"name": folder_name,
|
||||
},
|
||||
"task": {
|
||||
"name": data["task"],
|
||||
},
|
||||
# Backwards compatibility
|
||||
"asset": folder_name,
|
||||
"subset": f_product_name,
|
||||
"family": product_type,
|
||||
})
|
||||
|
||||
# build file path to render
|
||||
# TODO make sure the keys are available in 'formatting_data'
|
||||
temp_rendering_path_template = (
|
||||
self.temp_rendering_path_template
|
||||
.replace("{product[name]}", "{subset}")
|
||||
.replace("{product[type]}", "{family}")
|
||||
.replace("{folder[name]}", "{asset}")
|
||||
.replace("{task[name]}", "{task}")
|
||||
.replace("{task}", "{task[name]}")
|
||||
)
|
||||
|
||||
filepath = temp_rendering_path_template.format(**formatting_data)
|
||||
|
|
@ -164,9 +180,9 @@ class GenericCreateSaver(Creator):
|
|||
tool["Clip"] = comp.ReverseMapPath(os.path.normpath(filepath))
|
||||
|
||||
# Rename tool
|
||||
if tool.Name != subset:
|
||||
print(f"Renaming {tool.Name} -> {subset}")
|
||||
tool.SetAttrs({"TOOLS_Name": subset})
|
||||
if tool.Name != product_name:
|
||||
print(f"Renaming {tool.Name} -> {product_name}")
|
||||
tool.SetAttrs({"TOOLS_Name": product_name})
|
||||
|
||||
def get_managed_tool_data(self, tool):
|
||||
"""Return data of the tool if it matches creator identifier"""
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class CreateImageSaver(GenericCreateSaver):
|
|||
identifier = "io.openpype.creators.fusion.imagesaver"
|
||||
label = "Image (saver)"
|
||||
name = "image"
|
||||
family = "image"
|
||||
product_type = "image"
|
||||
description = "Fusion Saver to generate image"
|
||||
|
||||
default_frame = 0
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class CreateSaver(GenericCreateSaver):
|
|||
identifier = "io.openpype.creators.fusion.saver"
|
||||
label = "Render (saver)"
|
||||
name = "render"
|
||||
family = "render"
|
||||
product_type = "render"
|
||||
description = "Fusion Saver to generate image sequence"
|
||||
|
||||
default_frame_range_option = "asset_db"
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ from ayon_core.pipeline import (
|
|||
|
||||
class FusionWorkfileCreator(AutoCreator):
|
||||
identifier = "workfile"
|
||||
family = "workfile"
|
||||
product_type = "workfile"
|
||||
label = "Workfile"
|
||||
icon = "fa5.file"
|
||||
|
||||
|
|
@ -27,9 +27,12 @@ class FusionWorkfileCreator(AutoCreator):
|
|||
if not data:
|
||||
return
|
||||
|
||||
product_name = data.get("productName")
|
||||
if product_name is None:
|
||||
product_name = data["subset"]
|
||||
instance = CreatedInstance(
|
||||
family=self.family,
|
||||
subset_name=data["subset"],
|
||||
product_type=self.product_type,
|
||||
product_name=product_name,
|
||||
data=data,
|
||||
creator=self
|
||||
)
|
||||
|
|
@ -59,7 +62,7 @@ class FusionWorkfileCreator(AutoCreator):
|
|||
|
||||
existing_instance = None
|
||||
for instance in self.create_context.instances:
|
||||
if instance.family == self.family:
|
||||
if instance.product_type == self.product_type:
|
||||
existing_instance = instance
|
||||
break
|
||||
|
||||
|
|
@ -75,7 +78,7 @@ class FusionWorkfileCreator(AutoCreator):
|
|||
|
||||
if existing_instance is None:
|
||||
asset_doc = get_asset_by_name(project_name, asset_name)
|
||||
subset_name = self.get_subset_name(
|
||||
product_name = self.get_product_name(
|
||||
self.default_variant, task_name, asset_doc,
|
||||
project_name, host_name
|
||||
)
|
||||
|
|
@ -90,7 +93,7 @@ class FusionWorkfileCreator(AutoCreator):
|
|||
))
|
||||
|
||||
new_instance = CreatedInstance(
|
||||
self.family, subset_name, data, self
|
||||
self.product_type, product_name, data, self
|
||||
)
|
||||
new_instance.transient_data["comp"] = comp
|
||||
self._add_instance_to_context(new_instance)
|
||||
|
|
@ -100,10 +103,10 @@ class FusionWorkfileCreator(AutoCreator):
|
|||
or existing_instance["task"] != task_name
|
||||
):
|
||||
asset_doc = get_asset_by_name(project_name, asset_name)
|
||||
subset_name = self.get_subset_name(
|
||||
product_name = self.get_product_name(
|
||||
self.default_variant, task_name, asset_doc,
|
||||
project_name, host_name
|
||||
)
|
||||
existing_instance["folderPath"] = asset_name
|
||||
existing_instance["task"] = task_name
|
||||
existing_instance["subset"] = subset_name
|
||||
existing_instance["productName"] = product_name
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class CollectInstanceData(pyblish.api.InstancePlugin):
|
|||
instance.data["frame_range_source"] = frame_range_source
|
||||
|
||||
# get asset frame ranges to all instances
|
||||
# render family instances `asset_db` render target
|
||||
# render product type instances `asset_db` render target
|
||||
start = context.data["frameStart"]
|
||||
end = context.data["frameEnd"]
|
||||
handle_start = context.data["handleStart"]
|
||||
|
|
@ -34,7 +34,7 @@ class CollectInstanceData(pyblish.api.InstancePlugin):
|
|||
start_with_handle = start - handle_start
|
||||
end_with_handle = end + handle_end
|
||||
|
||||
# conditions for render family instances
|
||||
# conditions for render product type instances
|
||||
if frame_range_source == "render_range":
|
||||
# set comp render frame ranges
|
||||
start = context.data["renderFrameStart"]
|
||||
|
|
@ -70,11 +70,11 @@ class CollectInstanceData(pyblish.api.InstancePlugin):
|
|||
end_with_handle = frame
|
||||
|
||||
# Include start and end render frame in label
|
||||
subset = instance.data["subset"]
|
||||
product_name = instance.data["productName"]
|
||||
label = (
|
||||
"{subset} ({start}-{end}) [{handle_start}-{handle_end}]"
|
||||
"{product_name} ({start}-{end}) [{handle_start}-{handle_end}]"
|
||||
).format(
|
||||
subset=subset,
|
||||
product_name=product_name,
|
||||
start=int(start),
|
||||
end=int(end),
|
||||
handle_start=int(handle_start),
|
||||
|
|
|
|||
|
|
@ -49,17 +49,17 @@ class CollectFusionRender(
|
|||
if not inst.data.get("active", True):
|
||||
continue
|
||||
|
||||
family = inst.data["family"]
|
||||
if family not in ["render", "image"]:
|
||||
product_type = inst.data["productType"]
|
||||
if product_type not in ["render", "image"]:
|
||||
continue
|
||||
|
||||
task_name = context.data["task"]
|
||||
tool = inst.data["transientData"]["tool"]
|
||||
|
||||
instance_families = inst.data.get("families", [])
|
||||
subset_name = inst.data["subset"]
|
||||
product_name = inst.data["productName"]
|
||||
instance = FusionRenderInstance(
|
||||
family=family,
|
||||
productType=product_type,
|
||||
tool=tool,
|
||||
workfileComp=comp,
|
||||
families=instance_families,
|
||||
|
|
@ -67,13 +67,13 @@ class CollectFusionRender(
|
|||
time="",
|
||||
source=current_file,
|
||||
label=inst.data["label"],
|
||||
subset=subset_name,
|
||||
productName=product_name,
|
||||
folderPath=inst.data["folderPath"],
|
||||
task=task_name,
|
||||
attachTo=False,
|
||||
setMembers='',
|
||||
publish=True,
|
||||
name=subset_name,
|
||||
name=product_name,
|
||||
resolutionWidth=comp_frame_format_prefs.get("Width"),
|
||||
resolutionHeight=comp_frame_format_prefs.get("Height"),
|
||||
pixelAspect=aspect_x / aspect_y,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from ayon_core.hosts.fusion.api.action import SelectInvalidAction
|
|||
|
||||
|
||||
class ValidateUniqueSubsets(pyblish.api.ContextPlugin):
|
||||
"""Ensure all instances have a unique subset name"""
|
||||
"""Ensure all instances have a unique product name"""
|
||||
|
||||
order = pyblish.api.ValidatorOrder
|
||||
label = "Validate Unique Subsets"
|
||||
|
|
@ -18,27 +18,31 @@ class ValidateUniqueSubsets(pyblish.api.ContextPlugin):
|
|||
@classmethod
|
||||
def get_invalid(cls, context):
|
||||
|
||||
# Collect instances per subset per asset
|
||||
instances_per_subset_asset = defaultdict(lambda: defaultdict(list))
|
||||
# Collect instances per product per folder
|
||||
instances_per_product_folder = defaultdict(lambda: defaultdict(list))
|
||||
for instance in context:
|
||||
asset = instance.data.get(
|
||||
"folderPath", context.data.get("folderPath")
|
||||
folder_path = instance.data["folderPath"]
|
||||
product_name = instance.data["productName"]
|
||||
instances_per_product_folder[folder_path][product_name].append(
|
||||
instance
|
||||
)
|
||||
subset = instance.data.get("subset", context.data.get("subset"))
|
||||
instances_per_subset_asset[asset][subset].append(instance)
|
||||
|
||||
# Find which asset + subset combination has more than one instance
|
||||
# Those are considered invalid because they'd integrate to the same
|
||||
# destination.
|
||||
invalid = []
|
||||
for asset, instances_per_subset in instances_per_subset_asset.items():
|
||||
for subset, instances in instances_per_subset.items():
|
||||
for folder_path, instances_per_product in (
|
||||
instances_per_product_folder.items()
|
||||
):
|
||||
for product_name, instances in instances_per_product.items():
|
||||
if len(instances) > 1:
|
||||
cls.log.warning(
|
||||
"{asset} > {subset} used by more than "
|
||||
"one instance: {instances}".format(
|
||||
asset=asset,
|
||||
subset=subset,
|
||||
(
|
||||
"{folder_path} > {product_name} used by more than "
|
||||
"one instance: {instances}"
|
||||
).format(
|
||||
folder_path=folder_path,
|
||||
product_name=product_name,
|
||||
instances=instances
|
||||
)
|
||||
)
|
||||
|
|
@ -52,6 +56,7 @@ class ValidateUniqueSubsets(pyblish.api.ContextPlugin):
|
|||
def process(self, context):
|
||||
invalid = self.get_invalid(context)
|
||||
if invalid:
|
||||
raise PublishValidationError("Multiple instances are set to "
|
||||
"the same asset > subset.",
|
||||
title=self.label)
|
||||
raise PublishValidationError(
|
||||
"Multiple instances are set to the same folder > product.",
|
||||
title=self.label
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue