Merge branch 'develop' into bugfix/OP-8125_3dsmax-removing-item-in-manager

This commit is contained in:
Libor Batek 2024-02-22 08:52:51 +01:00 committed by GitHub
commit d97814024b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
112 changed files with 473 additions and 397 deletions

View file

@ -9,6 +9,8 @@ from ayon_core.pipeline import (
register_loader_plugin_path,
register_creator_plugin_path,
AVALON_CONTAINER_ID,
AVALON_INSTANCE_ID,
AYON_INSTANCE_ID,
)
from ayon_core.hosts.aftereffects.api.workfile_template_builder import (
AEPlaceholderLoadPlugin,
@ -142,7 +144,9 @@ class AfterEffectsHost(HostBase, IWorkfileHost, ILoadHost, IPublishHost):
layers_meta = stub.get_metadata()
for instance in layers_meta:
if instance.get("id") == "pyblish.avalon.instance":
if instance.get("id") in {
AYON_INSTANCE_ID, AVALON_INSTANCE_ID
}:
instances.append(instance)
return instances

View file

@ -98,7 +98,7 @@ class CollectAERender(publish.AbstractCollectRender):
source=current_file,
label="{} - {}".format(subset_name, family),
subset=subset_name,
asset=inst.data["asset"],
folderPath=inst.data["folderPath"],
task=task_name,
attachTo=False,
setMembers='',
@ -175,7 +175,7 @@ class CollectAERender(publish.AbstractCollectRender):
version_str = "v{:03d}".format(render_instance.version)
if "#" not in file_name: # single frame (mov)W
path = os.path.join(base_dir, "{}_{}_{}.{}".format(
render_instance.asset,
render_instance.folderPath,
render_instance.subset,
version_str,
ext
@ -184,7 +184,7 @@ class CollectAERender(publish.AbstractCollectRender):
else:
for frame in range(start, end + 1):
path = os.path.join(base_dir, "{}_{}_{}.{}.{}".format(
render_instance.asset,
render_instance.folderPath,
render_instance.subset,
version_str,
str(frame).zfill(self.padding_width),

View file

@ -50,11 +50,11 @@ class CollectWorkfile(pyblish.api.ContextPlugin):
asset_entity = context.data["assetEntity"]
project_entity = context.data["projectEntity"]
asset_name = get_asset_name_identifier(asset_entity)
folder_path = get_asset_name_identifier(asset_entity)
instance_data = {
"active": True,
"asset": asset_name,
"folderPath": folder_path,
"task": task,
"frameStart": context.data['frameStart'],
"frameEnd": context.data['frameEnd'],

View file

@ -30,7 +30,7 @@ class ValidateInstanceAssetRepair(pyblish.api.Action):
for instance in instances:
data = stub.read(instance[0])
data["asset"] = get_current_asset_name()
data["folderPath"] = get_current_asset_name()
stub.imprint(instance[0].instance_id, data)
@ -53,7 +53,7 @@ class ValidateInstanceAsset(pyblish.api.InstancePlugin):
order = ValidateContentsOrder
def process(self, instance):
instance_asset = instance.data["asset"]
instance_asset = instance.data["folderPath"]
current_asset = get_current_asset_name()
msg = (
f"Instance asset {instance_asset} is not the same "

View file

@ -26,6 +26,7 @@ from ayon_core.pipeline import (
deregister_loader_plugin_path,
deregister_creator_plugin_path,
AVALON_CONTAINER_ID,
AYON_CONTAINER_ID,
)
from ayon_core.lib import (
Logger,
@ -563,8 +564,9 @@ def ls() -> Iterator:
called containers.
"""
for container in lib.lsattr("id", AVALON_CONTAINER_ID):
yield parse_container(container)
for id_type in {AYON_CONTAINER_ID, AVALON_CONTAINER_ID}:
for container in lib.lsattr("id", id_type):
yield parse_container(container)
def publish():

View file

@ -10,6 +10,8 @@ from ayon_core.pipeline import (
Creator,
CreatedInstance,
LoaderPlugin,
AVALON_INSTANCE_ID,
AYON_INSTANCE_ID,
)
from ayon_core.lib import BoolDef
@ -193,7 +195,9 @@ class BaseCreator(Creator):
if not avalon_prop:
continue
if avalon_prop.get('id') != 'pyblish.avalon.instance':
if avalon_prop.get('id') not in {
AYON_INSTANCE_ID, AVALON_INSTANCE_ID
}:
continue
creator_id = avalon_prop.get('creator_identifier')
@ -352,7 +356,7 @@ class BaseCreator(Creator):
instance_data.update(
{
"id": "pyblish.avalon.instance",
"id": AVALON_INSTANCE_ID,
"creator_identifier": self.identifier,
"subset": subset_name,
}

View file

@ -22,7 +22,9 @@ class CreateAction(plugin.BaseCreator):
)
# Get instance name
name = plugin.prepare_scene_name(instance_data["asset"], subset_name)
name = plugin.prepare_scene_name(
instance_data["folderPath"], subset_name
)
if pre_create_data.get("use_selection"):
for obj in lib.get_selection():

View file

@ -22,7 +22,7 @@ class CollectCelactionInstances(pyblish.api.ContextPlugin):
asset_name = get_asset_name_identifier(asset_entity)
shared_instance_data = {
"asset": asset_name,
"folderPath": asset_name,
"frameStart": asset_entity["data"]["frameStart"],
"frameEnd": asset_entity["data"]["frameEnd"],
"handleStart": asset_entity["data"]["handleStart"],

View file

@ -3,6 +3,7 @@ from types import NoneType
import pyblish
import ayon_core.hosts.flame.api as opfapi
from ayon_core.hosts.flame.otio import flame_export
from ayon_core.pipeline import AYON_INSTANCE_ID, AVALON_INSTANCE_ID
from ayon_core.pipeline.editorial import (
is_overlapping_otio_ranges,
get_media_range_with_retimes
@ -47,7 +48,9 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin):
if not marker_data:
continue
if marker_data.get("id") != "pyblish.avalon.instance":
if marker_data.get("id") not in {
AYON_INSTANCE_ID, AVALON_INSTANCE_ID
}:
continue
self.log.debug("__ segment.name: {}".format(

View file

@ -34,7 +34,7 @@ class CollecTimelineOTIO(pyblish.api.ContextPlugin):
project_settings=context.data["project_settings"]
)
asset_name = get_asset_name_identifier(asset_doc)
folder_path = get_asset_name_identifier(asset_doc)
# adding otio timeline to context
with opfapi.maintained_segment_selection(sequence) as selected_seg:
@ -42,7 +42,7 @@ class CollecTimelineOTIO(pyblish.api.ContextPlugin):
instance_data = {
"name": subset_name,
"asset": asset_name,
"folderPath": folder_path,
"subset": subset_name,
"family": "workfile",
"families": []

View file

@ -55,7 +55,7 @@ class ExtractProductResources(publish.Extractor):
# flame objects
segment = instance.data["item"]
asset_name = instance.data["asset"]
folder_path = instance.data["folderPath"]
segment_name = segment.name.get_value()
clip_path = instance.data["path"]
sequence_clip = instance.context.data["flameSequence"]
@ -249,7 +249,7 @@ class ExtractProductResources(publish.Extractor):
out_mark = in_mark + source_duration_handles
exporting_clip = self.import_clip(clip_path)
exporting_clip.name.set_value("{}_{}".format(
asset_name, segment_name))
folder_path, segment_name))
# add xml tags modifications
modify_xml_data.update({

View file

@ -168,10 +168,10 @@ class IntegrateBatchGroup(pyblish.api.InstancePlugin):
handle_start = instance.data["handleStart"]
handle_end = instance.data["handleEnd"]
frame_duration = (frame_end - frame_start) + 1
asset_name = instance.data["asset"]
folder_path = instance.data["folderPath"]
task_name = task_data["name"]
batchgroup_name = "{}_{}".format(asset_name, task_name)
batchgroup_name = "{}_{}".format(folder_path, task_name)
batch_data = {
"shematic_reels": [

View file

@ -12,7 +12,9 @@ from ayon_core.lib import (
)
from ayon_core.pipeline import (
Creator,
CreatedInstance
CreatedInstance,
AVALON_INSTANCE_ID,
AYON_INSTANCE_ID,
)
@ -172,13 +174,13 @@ class GenericCreateSaver(Creator):
if not isinstance(data, dict):
return
required = {
"id": "pyblish.avalon.instance",
"creator_identifier": self.identifier,
}
for key, value in required.items():
if key not in data or data[key] != value:
return
if (
data.get("creator_identifier") != self.identifier
or data.get("id") not in {
AYON_INSTANCE_ID, AVALON_INSTANCE_ID
}
):
return
# Get active state from the actual tool state
attrs = tool.GetAttrs()

View file

@ -68,7 +68,7 @@ class CollectFusionRender(
source=current_file,
label=inst.data["label"],
subset=subset_name,
asset=inst.data["asset"],
folderPath=inst.data["folderPath"],
task=task_name,
attachTo=False,
setMembers='',

View file

@ -72,7 +72,7 @@ class FusionRenderLocal(
self.log.info(
"Rendered '{nm}' for asset '{ast}' under the task '{tsk}'".format(
nm=instance.data["name"],
ast=instance.data["asset"],
ast=instance.data["folderPath"],
tsk=instance.data["task"],
)
)

View file

@ -21,7 +21,9 @@ class ValidateUniqueSubsets(pyblish.api.ContextPlugin):
# Collect instances per subset per asset
instances_per_subset_asset = defaultdict(lambda: defaultdict(list))
for instance in context:
asset = instance.data.get("asset", context.data.get("asset"))
asset = instance.data.get(
"folderPath", context.data.get("folderPath")
)
subset = instance.data.get("subset", context.data.get("subset"))
instances_per_subset_asset[asset][subset].append(instance)

View file

@ -212,6 +212,7 @@ class CreateComposite(harmony.Creator):
The creator plugin can be configured to use other node types. For example here is a write node creator:
```python
from uuid import uuid4
import ayon_core.hosts.harmony.api as harmony
@ -242,6 +243,7 @@ class CreateRender(harmony.Creator):
#### Collector Plugin
```python
import pyblish.api
from ayon_core.pipeline import AYON_INSTANCE_ID, AVALON_INSTANCE_ID
import ayon_core.hosts.harmony.api as harmony
@ -252,7 +254,7 @@ class CollectInstances(pyblish.api.ContextPlugin):
a composite node and marked with a unique identifier;
Identifier:
id (str): "pyblish.avalon.instance"
id (str): "ayon.create.instance"
"""
label = "Instances"
@ -272,7 +274,7 @@ class CollectInstances(pyblish.api.ContextPlugin):
continue
# Skip containers.
if "container" in data["id"]:
if data["id"] not in {AYON_INSTANCE_ID, AVALON_INSTANCE_ID}:
continue
instance = context.create_instance(node.split("/")[-1])
@ -287,6 +289,7 @@ class CollectInstances(pyblish.api.ContextPlugin):
#### Extractor Plugin
```python
import os
from uuid import uuid4
import pyblish.api
import ayon_core.hosts.harmony.api as harmony
@ -418,6 +421,7 @@ class ExtractImage(pyblish.api.InstancePlugin):
#### Loader Plugin
```python
import os
from uuid import uuid4
import ayon_core.hosts.harmony.api as harmony

View file

@ -98,7 +98,7 @@ class CollectFarmRender(publish.AbstractCollectRender):
self_name = self.__class__.__name__
asset_name = context.data["asset"]
folder_path = context.data["folderPath"]
for node in context.data["allNodes"]:
data = harmony.read(node)
@ -142,7 +142,7 @@ class CollectFarmRender(publish.AbstractCollectRender):
source=context.data["currentFile"],
label=node.split("/")[1],
subset=subset_name,
asset=asset_name,
folderPath=folder_path,
task=task_name,
attachTo=False,
setMembers=[node],

View file

@ -13,7 +13,7 @@ class CollectInstances(pyblish.api.ContextPlugin):
a composite node and marked with a unique identifier.
Identifier:
id (str): "pyblish.avalon.instance"
id (str): "ayon.create.instance"
"""
label = "Instances"

View file

@ -31,7 +31,7 @@ class CollectPalettes(pyblish.api.ContextPlugin):
if (not any([re.search(pattern, task_name)
for pattern in self.allowed_tasks])):
return
asset_name = context.data["asset"]
folder_path = context.data["folderPath"]
for name, id in palettes.items():
instance = context.create_instance(name)
@ -39,7 +39,7 @@ class CollectPalettes(pyblish.api.ContextPlugin):
"id": id,
"family": "harmony.palette",
'families': [],
"asset": asset_name,
"folderPath": folder_path,
"subset": "{}{}".format("palette", name)
})
self.log.info(

View file

@ -36,5 +36,5 @@ class CollectWorkfile(pyblish.api.ContextPlugin):
"family": family,
"families": [family],
"representations": [],
"asset": context.data["asset"]
"folderPath": context.data["folderPath"]
})

View file

@ -27,9 +27,10 @@ class ValidateInstanceRepair(pyblish.api.Action):
# Apply pyblish.logic to get the instances for the plug-in
instances = pyblish.api.instances_by_plugin(failed, plugin)
folder_path = get_current_asset_name()
for instance in instances:
data = harmony.read(instance.data["setMembers"][0])
data["asset"] = get_current_asset_name()
data["folderPath"] = folder_path
harmony.imprint(instance.data["setMembers"][0], data)
@ -42,7 +43,7 @@ class ValidateInstance(pyblish.api.InstancePlugin):
order = ValidateContentsOrder
def process(self, instance):
instance_asset = instance.data["asset"]
instance_asset = instance.data["folderPath"]
current_asset = get_current_asset_name()
msg = (
"Instance asset is not the same as current asset:"

View file

@ -22,7 +22,12 @@ except ImportError:
from ayon_core.client import get_project
from ayon_core.settings import get_project_settings
from ayon_core.pipeline import Anatomy, get_current_project_name
from ayon_core.pipeline import (
Anatomy,
get_current_project_name,
AYON_INSTANCE_ID,
AVALON_INSTANCE_ID,
)
from ayon_core.pipeline.load import filter_containers
from ayon_core.lib import Logger
from . import tags
@ -1217,7 +1222,9 @@ def sync_clip_name_to_data_asset(track_items_list):
# ignore if no data on the clip or not publish instance
if not data:
continue
if data.get("id") != "pyblish.avalon.instance":
if data.get("id") not in {
AYON_INSTANCE_ID, AVALON_INSTANCE_ID
}:
continue
# fix data if wrong name

View file

@ -15,6 +15,7 @@ from ayon_core.pipeline import (
deregister_creator_plugin_path,
deregister_loader_plugin_path,
AVALON_CONTAINER_ID,
AYON_CONTAINER_ID,
)
from ayon_core.tools.utils import host_tools
from . import lib, menu, events
@ -158,7 +159,9 @@ def parse_container(item, validate=True):
def data_to_container(item, data):
if (
not data
or data.get("id") != "pyblish.avalon.container"
or data.get("id") not in {
AYON_CONTAINER_ID, AVALON_CONTAINER_ID
}
):
return

View file

@ -118,9 +118,9 @@ class CollectClipEffects(pyblish.api.InstancePlugin):
data["subset"] = name
data["family"] = family
data["families"] = [family]
data["name"] = data["subset"] + "_" + data["asset"]
data["name"] = data["subset"] + "_" + data["folderPath"]
data["label"] = "{} - {}".format(
data['asset'], data["subset"]
data["folderPath"], data["subset"]
)
data["effects"] = effects

View file

@ -102,7 +102,7 @@ class CollectFrameTagInstances(pyblish.api.ContextPlugin):
# first collect all available subset tag frames
subset_data = {}
context_asset_doc = context.data["assetEntity"]
context_asset_name = get_asset_name_identifier(context_asset_doc)
context_folder_path = get_asset_name_identifier(context_asset_doc)
for tag_data in sequence_tags:
frame = int(tag_data["start"])
@ -120,7 +120,7 @@ class CollectFrameTagInstances(pyblish.api.ContextPlugin):
subset_data[subset] = {
"frames": [frame],
"format": tag_data["format"],
"asset": context_asset_name
"folderPath": context_folder_path
}
return subset_data
@ -133,7 +133,7 @@ class CollectFrameTagInstances(pyblish.api.ContextPlugin):
"label": "{} {}".format(name, subset_data["frames"]),
"family": "image",
"families": ["frame"],
"asset": subset_data["asset"],
"folderPath": subset_data["folderPath"],
"subset": name,
"format": subset_data["format"],
"frames": subset_data["frames"]

View file

@ -57,7 +57,7 @@ class ExtractClipEffects(publish.Extractor):
"sourceStart", "sourceStartH", "sourceEnd", "sourceEndH",
"frameStart", "frameEnd",
"clipIn", "clipOut", "clipInH", "clipOutH",
"asset", "version"
"folderPath", "version"
]
# pass data to version

View file

@ -1,5 +1,6 @@
import pyblish
from ayon_core.pipeline import AYON_INSTANCE_ID, AVALON_INSTANCE_ID
from ayon_core.pipeline.editorial import is_overlapping_otio_ranges
from ayon_core.hosts.hiero import api as phiero
@ -56,7 +57,9 @@ class PrecollectInstances(pyblish.api.ContextPlugin):
if not tag_data:
continue
if tag_data.get("id") != "pyblish.avalon.instance":
if tag_data.get("id") not in {
AYON_INSTANCE_ID, AVALON_INSTANCE_ID
}:
continue
# get clips subtracks and anotations
@ -98,7 +101,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin):
data.update({
"name": "{}_{}".format(asset, subset),
"label": label,
"asset": asset,
"folderPath": asset,
"asset_name": asset_name,
"item": track_item,
"families": families,
@ -189,7 +192,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin):
if not hierarchy_data:
return
asset = data["asset"]
asset = data["folderPath"]
asset_name = data["asset_name"]
# insert family into families
@ -241,7 +244,6 @@ class PrecollectInstances(pyblish.api.ContextPlugin):
if not master_layer:
return
asset = data.get("asset")
item = data.get("item")
clip_name = item.name()
@ -249,7 +251,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin):
if not self.test_any_audio(item):
return
asset = data["asset"]
asset = data["folderPath"]
asset_name = data["asset_name"]
# insert family into families

View file

@ -17,7 +17,7 @@ class PrecollectWorkfile(pyblish.api.ContextPlugin):
order = pyblish.api.CollectorOrder - 0.491
def process(self, context):
asset = context.data["asset"]
asset = context.data["folderPath"]
asset_name = asset.split("/")[-1]
active_timeline = hiero.ui.activeSequence()
@ -64,7 +64,7 @@ class PrecollectWorkfile(pyblish.api.ContextPlugin):
"label": "{} - {}Main".format(
asset, family),
"name": "{}_{}".format(asset_name, family),
"asset": context.data["asset"],
"folderPath": context.data["folderPath"],
# TODO use 'get_subset_name'
"subset": "{}{}Main".format(asset_name, family.capitalize()),
"item": project,

View file

@ -15,6 +15,7 @@ from ayon_core.pipeline import (
register_loader_plugin_path,
register_inventory_action_path,
AVALON_CONTAINER_ID,
AYON_CONTAINER_ID,
)
from ayon_core.pipeline.load import any_outdated_containers
from ayon_core.hosts.houdini import HOUDINI_HOST_DIR
@ -271,8 +272,11 @@ def parse_container(container):
def ls():
containers = []
for identifier in (AVALON_CONTAINER_ID,
"pyblish.mindbender.container"):
for identifier in (
AYON_CONTAINER_ID,
AVALON_CONTAINER_ID,
"pyblish.mindbender.container"
):
containers += lib.lsattr("id", identifier)
for container in sorted(containers,

View file

@ -11,7 +11,9 @@ from ayon_core.pipeline import (
CreatorError,
LegacyCreator,
Creator as NewCreator,
CreatedInstance
CreatedInstance,
AYON_INSTANCE_ID,
AVALON_INSTANCE_ID,
)
from ayon_core.lib import BoolDef
from .lib import imprint, read, lsattr, add_self_publish_button
@ -118,7 +120,10 @@ class HoudiniCreatorBase(object):
cache = dict()
cache_legacy = dict()
for node in lsattr("id", "pyblish.avalon.instance"):
nodes = []
for id_type in [AYON_INSTANCE_ID, AVALON_INSTANCE_ID]:
nodes.extend(lsattr("id", id_type))
for node in nodes:
creator_identifier_parm = node.parm("creator_identifier")
if creator_identifier_parm:

View file

@ -2,6 +2,7 @@ import hou
import pyblish.api
from ayon_core.pipeline import AYON_INSTANCE_ID, AVALON_INSTANCE_ID
from ayon_core.hosts.houdini.api import lib
@ -12,7 +13,7 @@ class CollectInstances(pyblish.api.ContextPlugin):
an specific node and marked with a unique identifier;
Identifier:
id (str): "pyblish.avalon.instance
id (str): "ayon.create.instance"
Specific node:
The specific node is important because it dictates in which way the
@ -44,7 +45,9 @@ class CollectInstances(pyblish.api.ContextPlugin):
if not node.parm("id"):
continue
if node.evalParm("id") != "pyblish.avalon.instance":
if node.evalParm("id") not in {
AYON_INSTANCE_ID, AVALON_INSTANCE_ID
}:
continue
# instance was created by new creator code, skip it as
@ -72,7 +75,7 @@ class CollectInstances(pyblish.api.ContextPlugin):
# Create nice name if the instance has a frame range.
label = data.get("name", node.name())
label += " (%s)" % data["asset"] # include asset in name
label += " (%s)" % data["folderPath"] # include folder in name
instance = context.create_instance(label)

View file

@ -12,7 +12,7 @@ class CollectInstancesUsdLayered(pyblish.api.ContextPlugin):
layers remain set to 'publish' by the user.
This works differently from most of our Avalon instances in the pipeline.
As opposed to storing `pyblish.avalon.instance` as id on the node we store
As opposed to storing `ayon.create.instance` as id on the node we store
`pyblish.avalon.usdlayered`.
Additionally this instance has no need for storing family, asset, subset

View file

@ -55,7 +55,7 @@ class CollectUsdBootstrap(pyblish.api.InstancePlugin):
self.log.debug("Add bootstrap for: %s" % bootstrap)
project_name = instance.context.data["projectName"]
asset_name = instance.data["asset"]
asset_name = instance.data["folderPath"]
asset_doc = get_asset_by_name(project_name, asset_name)
assert asset_doc, "Asset must exist: %s" % asset_name
@ -95,7 +95,7 @@ class CollectUsdBootstrap(pyblish.api.InstancePlugin):
new.data["optional"] = False
# Copy some data from the instance for which we bootstrap
for key in ["asset"]:
for key in ["folderPath"]:
new.data[key] = instance.data[key]
def _subset_exists(self, project_name, instance, subset_name, asset_doc):
@ -107,7 +107,7 @@ class CollectUsdBootstrap(pyblish.api.InstancePlugin):
for inst in context:
if (
inst.data["subset"] == subset_name
and inst.data["asset"] == asset_doc_name
and inst.data["folderPath"] == asset_doc_name
):
return True

View file

@ -55,7 +55,7 @@ class CollectUsdLayers(pyblish.api.InstancePlugin):
layer_inst.data["families"] = [family]
layer_inst.data["subset"] = "__stub__"
layer_inst.data["label"] = label
layer_inst.data["asset"] = instance.data["asset"]
layer_inst.data["folderPath"] = instance.data["folderPath"]
layer_inst.data["instance_node"] = instance.data["instance_node"]
# include same USD ROP
layer_inst.append(rop_node)

View file

@ -285,7 +285,7 @@ class ExtractUSDLayered(publish.Extractor):
# to detect whether we should make this into a new publish
# version. If not, skip it.
asset = get_asset_by_name(
project_name, dependency.data["asset"], fields=["_id"]
project_name, dependency.data["folderPath"], fields=["_id"]
)
subset = get_subset_by_name(
project_name,

View file

@ -18,7 +18,7 @@ class ValidateUSDShadeModelExists(pyblish.api.InstancePlugin):
def process(self, instance):
project_name = instance.context.data["projectName"]
asset_name = instance.data["asset"]
asset_name = instance.data["folderPath"]
subset = instance.data["subset"]
# Assume shading variation starts after a dot separator

View file

@ -12,6 +12,7 @@ from ayon_core.pipeline import (
register_creator_plugin_path,
register_loader_plugin_path,
AVALON_CONTAINER_ID,
AYON_CONTAINER_ID,
)
from ayon_core.hosts.max.api.menu import OpenPypeMenu
from ayon_core.hosts.max.api import lib
@ -151,7 +152,9 @@ def ls() -> list:
objs = rt.objects
containers = [
obj for obj in objs
if rt.getUserProp(obj, "id") == AVALON_CONTAINER_ID
if rt.getUserProp(obj, "id") in {
AYON_CONTAINER_ID, AVALON_CONTAINER_ID
}
]
for container in sorted(containers, key=attrgetter("name")):

View file

@ -6,7 +6,13 @@ import six
from pymxs import runtime as rt
from ayon_core.lib import BoolDef
from ayon_core.pipeline import CreatedInstance, Creator, CreatorError
from ayon_core.pipeline import (
CreatedInstance,
Creator,
CreatorError,
AYON_INSTANCE_ID,
AVALON_INSTANCE_ID,
)
from .lib import imprint, lsattr, read
@ -162,7 +168,11 @@ class MaxCreatorBase(object):
return shared_data
shared_data["max_cached_subsets"] = {}
cached_instances = lsattr("id", "pyblish.avalon.instance")
cached_instances = []
for id_type in [AYON_INSTANCE_ID, AVALON_INSTANCE_ID]:
cached_instances.extend(lsattr("id", id_type))
for i in cached_instances:
creator_id = rt.GetUserProp(i, "creator_identifier")
if creator_id not in shared_data["max_cached_subsets"]:

View file

@ -94,7 +94,7 @@ class CollectRender(pyblish.api.InstancePlugin):
renderer = str(renderer_class).split(":")[0]
# also need to get the render dir for conversion
data = {
"asset": instance.data["asset"],
"folderPath": instance.data["folderPath"],
"subset": str(instance.name),
"publish": True,
"maxversion": str(get_max_version()),

View file

@ -15,7 +15,7 @@ class GenerateUUIDsOnInvalidAction(pyblish.api.Action):
receive new UUIDs are actually invalid.
Requires:
- instance.data["asset"]
- instance.data["folderPath"]
"""
@ -78,7 +78,7 @@ class GenerateUUIDsOnInvalidAction(pyblish.api.Action):
# should be always available, but kept a way to query it by name.
asset_doc = instance.data.get("assetEntity")
if not asset_doc:
asset_name = instance.data["asset"]
asset_name = instance.data["folderPath"]
project_name = instance.context.data["projectName"]
self.log.info((
"Asset is not stored on instance."

View file

@ -24,7 +24,8 @@ from ayon_core.client import (
get_asset_by_name,
get_subsets,
get_last_versions,
get_representation_by_name
get_representation_by_name,
get_asset_name_identifier,
)
from ayon_core.settings import get_project_settings
from ayon_core.pipeline import (
@ -35,7 +36,11 @@ from ayon_core.pipeline import (
loaders_from_representation,
get_representation_path,
load_container,
registered_host
registered_host,
AVALON_CONTAINER_ID,
AVALON_INSTANCE_ID,
AYON_INSTANCE_ID,
AYON_CONTAINER_ID,
)
from ayon_core.lib import NumberDef
from ayon_core.pipeline.context_tools import get_current_project_asset
@ -2100,7 +2105,7 @@ def get_related_sets(node):
"""Return objectSets that are relationships for a look for `node`.
Filters out based on:
- id attribute is NOT `pyblish.avalon.container`
- id attribute is NOT `AVALON_CONTAINER_ID`
- shapes and deformer shapes (alembic creates meshShapeDeformed)
- set name ends with any from a predefined list
- set in not in viewport set (isolate selected for example)
@ -2120,7 +2125,12 @@ def get_related_sets(node):
defaults = {"defaultLightSet", "defaultObjectSet"}
# Ids to ignore
ignored = {"pyblish.avalon.instance", "pyblish.avalon.container"}
ignored = {
AVALON_INSTANCE_ID,
AVALON_CONTAINER_ID,
AYON_INSTANCE_ID,
AYON_CONTAINER_ID,
}
view_sets = get_isolate_view_sets()
@ -3143,21 +3153,27 @@ def fix_incompatible_containers():
def update_content_on_context_change():
"""
This will update scene content to match new asset on context change
This will update scene content to match new folder on context change
"""
scene_sets = cmds.listSets(allSets=True)
asset_doc = get_current_project_asset()
new_asset = asset_doc["name"]
new_folder_path = get_asset_name_identifier(asset_doc)
new_data = asset_doc["data"]
for s in scene_sets:
try:
if cmds.getAttr("{}.id".format(s)) == "pyblish.avalon.instance":
if cmds.getAttr("{}.id".format(s)) in {
AYON_INSTANCE_ID, AVALON_INSTANCE_ID
}:
attr = cmds.listAttr(s)
print(s)
if "asset" in attr:
print(" - setting asset to: [ {} ]".format(new_asset))
cmds.setAttr("{}.asset".format(s),
new_asset, type="string")
if "folderPath" in attr:
print(
" - setting folder to: [ {} ]".format(new_folder_path)
)
cmds.setAttr(
"{}.folderPath".format(s),
new_folder_path, type="string"
)
if "frameStart" in attr:
cmds.setAttr("{}.frameStart".format(s),
new_data["frameStart"])

View file

@ -33,6 +33,7 @@ from ayon_core.pipeline import (
deregister_loader_plugin_path,
deregister_inventory_action_path,
deregister_creator_plugin_path,
AYON_CONTAINER_ID,
AVALON_CONTAINER_ID,
)
from ayon_core.pipeline.load import any_outdated_containers
@ -376,9 +377,11 @@ def _ls():
yield iterator.thisNode()
iterator.next()
ids = {AVALON_CONTAINER_ID,
# Backwards compatibility
"pyblish.mindbender.container"}
ids = {
AYON_CONTAINER_ID,
# Backwards compatibility
AVALON_CONTAINER_ID
}
# Iterate over all 'set' nodes in the scene to detect whether
# they have the avalon container ".id" attribute.

View file

@ -10,6 +10,9 @@ from maya.app.renderSetup.model import renderSetup
from ayon_core.lib import BoolDef, Logger
from ayon_core.settings import get_project_settings
from ayon_core.pipeline import (
AYON_INSTANCE_ID,
AYON_CONTAINER_ID,
AVALON_INSTANCE_ID,
AVALON_CONTAINER_ID,
Anatomy,
@ -110,7 +113,9 @@ class MayaCreatorBase(object):
for node in cmds.ls(type="objectSet"):
if _get_attr(node, attr="id") != "pyblish.avalon.instance":
if _get_attr(node, attr="id") not in {
AYON_INSTANCE_ID, AVALON_INSTANCE_ID
}:
continue
creator_id = _get_attr(node, attr="creator_identifier")
@ -992,5 +997,7 @@ class ReferenceLoader(Loader):
id_attr = "{}.id".format(node)
if not cmds.attributeQuery("id", node=node, exists=True):
continue
if cmds.getAttr(id_attr) == AVALON_CONTAINER_ID:
if cmds.getAttr(id_attr) not in {
AYON_CONTAINER_ID, AVALON_CONTAINER_ID
}:
cmds.sets(node, forceElement=container)

View file

@ -2,7 +2,12 @@ import json
from maya import cmds
from ayon_core.pipeline import registered_host, get_current_asset_name
from ayon_core.pipeline import (
registered_host,
get_current_asset_name,
AYON_INSTANCE_ID,
AVALON_INSTANCE_ID,
)
from ayon_core.pipeline.workfile.workfile_template_builder import (
TemplateAlreadyImported,
AbstractTemplateBuilder,
@ -73,7 +78,9 @@ class MayaTemplateBuilder(AbstractTemplateBuilder):
for node in imported_sets:
if not cmds.attributeQuery("id", node=node, exists=True):
continue
if cmds.getAttr("{}.id".format(node)) != "pyblish.avalon.instance":
if cmds.getAttr("{}.id".format(node)) not in {
AYON_INSTANCE_ID, AVALON_INSTANCE_ID
}:
continue
if not cmds.attributeQuery("asset", node=node, exists=True):
continue

View file

@ -11,7 +11,7 @@ class CollectNewInstances(pyblish.api.InstancePlugin):
an objectSet and marked with a unique identifier;
Identifier:
id (str): "pyblish.avalon.instance"
id (str): "ayon.create.instance"
Limitations:
- Does not take into account nodes connected to those

View file

@ -307,7 +307,7 @@ class CollectMayaRender(pyblish.api.InstancePlugin):
_instance.data["version"] = context.data["version"]
# Define nice label
label = "{0} ({1})".format(layer_name, instance.data["asset"])
label = "{0} ({1})".format(layer_name, instance.data["folderPath"])
label += " [{0}-{1}]".format(
int(data["frameStartHandle"]), int(data["frameEndHandle"])
)

View file

@ -99,7 +99,7 @@ class CollectVrayScene(pyblish.api.InstancePlugin):
instance.data.update(data)
# Define nice label
label = "{0} ({1})".format(layer_name, instance.data["asset"])
label = "{0} ({1})".format(layer_name, instance.data["folderPath"])
label += " [{0}-{1}]".format(
int(data["frameStartHandle"]), int(data["frameEndHandle"])
)

View file

@ -5,7 +5,11 @@ import os
from maya import cmds
from ayon_core.hosts.maya.api.lib import maintained_selection
from ayon_core.pipeline import AVALON_CONTAINER_ID, publish
from ayon_core.pipeline import (
AYON_CONTAINER_ID,
AVALON_CONTAINER_ID,
publish,
)
from ayon_core.pipeline.publish import AYONPyblishPluginMixin
from ayon_core.lib import BoolDef
@ -136,7 +140,9 @@ class ExtractMayaSceneRaw(publish.Extractor, AYONPyblishPluginMixin):
continue
id_attr = "{}.id".format(obj_set)
if cmds.getAttr(id_attr) != AVALON_CONTAINER_ID:
if cmds.getAttr(id_attr) not in {
AYON_CONTAINER_ID, AVALON_CONTAINER_ID
}:
continue
set_content = set(cmds.sets(obj_set, query=True))

View file

@ -61,7 +61,7 @@ class ExtractUnrealSkeletalMeshFbx(publish.Extractor):
# we rely on hierarchy under one root.
original_parent = to_extract[0].split("|")[1]
parent_node = instance.data.get("asset")
parent_node = instance.data.get("folderPath")
# this needs to be done for AYON
# WARNING: since AYON supports duplicity of asset names,
# this needs to be refactored throughout the pipeline.

View file

@ -37,7 +37,7 @@ class ValidateInstanceInContext(pyblish.api.InstancePlugin,
if not self.is_active(instance.data):
return
asset = instance.data.get("asset")
asset = instance.data.get("folderPath")
context_asset = self.get_context_asset(instance)
if asset != context_asset:
raise PublishValidationError(
@ -74,4 +74,4 @@ class ValidateInstanceInContext(pyblish.api.InstancePlugin,
@staticmethod
def get_context_asset(instance):
return instance.context.data["asset"]
return instance.context.data["folderPath"]

View file

@ -51,7 +51,7 @@ class ValidateShaderName(pyblish.api.InstancePlugin,
descendants = cmds.ls(descendants, noIntermediate=True, long=True)
shapes = cmds.ls(descendants, type=["nurbsSurface", "mesh"], long=True)
asset_name = instance.data.get("asset")
asset_name = instance.data.get("folderPath")
# Check the number of connected shadingEngines per shape
regex_compile = re.compile(cls.regex)

View file

@ -45,6 +45,8 @@ from ayon_core.pipeline import (
get_current_host_name,
get_current_project_name,
get_current_asset_name,
AYON_INSTANCE_ID,
AVALON_INSTANCE_ID,
)
from ayon_core.pipeline.context_tools import (
get_custom_workfile_template_from_session
@ -2300,12 +2302,16 @@ Reopening Nuke should synchronize these paths and resolve any discrepancies.
# backward compatibility
# TODO: remove this once old avalon data api will be removed
avalon_knob_data
and avalon_knob_data.get("id") != "pyblish.avalon.instance"
and avalon_knob_data.get("id") not in {
AYON_INSTANCE_ID, AVALON_INSTANCE_ID
}
):
continue
elif (
node_data
and node_data.get("id") != "pyblish.avalon.instance"
and node_data.get("id") not in {
AYON_INSTANCE_ID, AVALON_INSTANCE_ID
}
):
continue

View file

@ -18,6 +18,8 @@ from ayon_core.pipeline import (
register_loader_plugin_path,
register_creator_plugin_path,
register_inventory_action_path,
AYON_INSTANCE_ID,
AVALON_INSTANCE_ID,
AVALON_CONTAINER_ID,
get_current_asset_name,
get_current_task_name,
@ -550,7 +552,9 @@ def list_instances(creator_id=None):
if not instance_data:
continue
if instance_data["id"] != "pyblish.avalon.instance":
if instance_data["id"] not in {
AYON_INSTANCE_ID, AVALON_INSTANCE_ID
}:
continue
if creator_id and instance_data["creator_identifier"] != creator_id:

View file

@ -19,7 +19,9 @@ from ayon_core.pipeline import (
CreatorError,
Creator as NewCreator,
CreatedInstance,
get_current_task_name
get_current_task_name,
AYON_INSTANCE_ID,
AVALON_INSTANCE_ID,
)
from ayon_core.pipeline.colorspace import (
get_display_view_colorspace_name,
@ -1265,7 +1267,9 @@ def convert_to_valid_instaces():
if not avalon_knob_data:
continue
if avalon_knob_data["id"] != "pyblish.avalon.instance":
if avalon_knob_data["id"] not in {
AYON_INSTANCE_ID, AVALON_INSTANCE_ID
}:
continue
transfer_data.update({

View file

@ -1,3 +1,4 @@
from ayon_core.pipeline import AYON_INSTANCE_ID, AVALON_INSTANCE_ID
from ayon_core.pipeline.create.creator_plugins import SubsetConvertorPlugin
from ayon_core.hosts.nuke.api.lib import (
INSTANCE_DATA_KNOB,
@ -34,7 +35,9 @@ class LegacyConverted(SubsetConvertorPlugin):
if not avalon_knob_data:
continue
if avalon_knob_data["id"] != "pyblish.avalon.instance":
if avalon_knob_data["id"] not in {
AYON_INSTANCE_ID, AVALON_INSTANCE_ID
}:
continue
# catch and break

View file

@ -23,10 +23,10 @@ class ValidateCorrectAssetContext(
current asset (shot). This validator checks if this is so. It is optional
so it can be disabled when needed.
Checking `asset` and `task` keys.
Checking `folderPath` and `task` keys.
"""
order = ValidateContentsOrder
label = "Validate asset context"
label = "Validate Folder context"
hosts = ["nuke"]
actions = [
RepairAction,
@ -85,7 +85,7 @@ class ValidateCorrectAssetContext(
"""Get invalid keys from instance data and context data."""
invalid_keys = []
testing_keys = ["asset", "task"]
testing_keys = ["folderPath", "task"]
for _key in testing_keys:
if _key not in instance.data:
invalid_keys.append(_key)

View file

@ -75,7 +75,7 @@ class CollectInstances(pyblish.api.ContextPlugin):
an LayerSet and marked with a unique identifier;
Identifier:
id (str): "pyblish.avalon.instance"
id (str): "ayon.create.instance"
"""
label = "Instances"

View file

@ -9,6 +9,8 @@ from ayon_core.pipeline import (
register_loader_plugin_path,
register_creator_plugin_path,
AVALON_CONTAINER_ID,
AYON_INSTANCE_ID,
AVALON_INSTANCE_ID,
)
from ayon_core.host import (
@ -121,7 +123,9 @@ class PhotoshopHost(HostBase, IWorkfileHost, ILoadHost, IPublishHost):
layers_meta = stub.get_layers_metadata()
if layers_meta:
for instance in layers_meta:
if instance.get("id") == "pyblish.avalon.instance":
if instance.get("id") in {
AYON_INSTANCE_ID, AVALON_INSTANCE_ID
}:
instances.append(instance)
return instances

View file

@ -119,14 +119,14 @@ class PhotoshopServerStub:
"active":true,
"subset":"imageBG",
"family":"image",
"id":"pyblish.avalon.instance",
"asset":"Town",
"id":"ayon.create.instance",
"folderPath":"Town",
"uuid": "8"
}] - for created instances
OR
[{
"schema": "openpype:container-2.0",
"id": "pyblish.avalon.instance",
"id": "ayon.create.instance",
"name": "imageMG",
"namespace": "Jungle_imageMG_001",
"loader": "ImageLoader",
@ -420,8 +420,8 @@ class PhotoshopServerStub:
(list)
example:
{"8":{"active":true,"subset":"imageBG",
"family":"image","id":"pyblish.avalon.instance",
"asset":"Town"}}
"family":"image","id":"ayon.create.instance",
"folderPath":"/Town"}}
8 is layer(group) id - used for deletion, update etc.
"""
res = self.websocketserver.call(self.client.call('Photoshop.read'))

View file

@ -28,7 +28,7 @@ class CollectAutoImage(pyblish.api.ContextPlugin):
task_name = context.data["task"]
host_name = context.data["hostName"]
asset_doc = context.data["assetEntity"]
asset_name = get_asset_name_identifier(asset_doc)
folder_path = get_asset_name_identifier(asset_doc)
auto_creator = proj_settings.get(
"photoshop", {}).get(
@ -86,7 +86,7 @@ class CollectAutoImage(pyblish.api.ContextPlugin):
instance = context.create_instance(subset_name)
instance.data["family"] = family
instance.data["asset"] = asset_name
instance.data["folderPath"] = folder_path
instance.data["subset"] = subset_name
instance.data["ids"] = publishable_ids
instance.data["publish"] = True

View file

@ -67,7 +67,7 @@ class CollectAutoReview(pyblish.api.ContextPlugin):
host_name = context.data["hostName"]
asset_doc = context.data["assetEntity"]
asset_name = get_asset_name_identifier(asset_doc)
folder_path = get_asset_name_identifier(asset_doc)
subset_name = get_subset_name(
family,
@ -87,7 +87,7 @@ class CollectAutoReview(pyblish.api.ContextPlugin):
"family": family,
"families": [],
"representations": [],
"asset": asset_name,
"folderPath": folder_path,
"publish": self.publish
})

View file

@ -71,7 +71,7 @@ class CollectAutoWorkfile(pyblish.api.ContextPlugin):
host_name = context.data["hostName"]
asset_doc = context.data["assetEntity"]
asset_name = get_asset_name_identifier(asset_doc)
folder_path = get_asset_name_identifier(asset_doc)
subset_name = get_subset_name(
family,
variant,
@ -91,7 +91,7 @@ class CollectAutoWorkfile(pyblish.api.ContextPlugin):
"family": family,
"families": [],
"representations": [],
"asset": asset_name
"folderPath": folder_path
})
# creating representation

View file

@ -2,7 +2,7 @@
Provides:
context -> Loaded batch file.
- asset
- folderPath
- task (task name)
- taskType
- project_name
@ -71,7 +71,7 @@ class CollectBatchData(pyblish.api.ContextPlugin):
os.environ["AYON_FOLDER_PATH"] = asset_name
os.environ["AYON_TASK_NAME"] = task_name
context.data["asset"] = asset_name
context.data["folderPath"] = asset_name
context.data["task"] = task_name
context.data["taskType"] = task_type
context.data["project_name"] = project_name

View file

@ -26,7 +26,7 @@ class CollectColorCodedInstances(pyblish.api.ContextPlugin):
only separate subsets per marked layer.
Identifier:
id (str): "pyblish.avalon.instance"
id (str): "ayon.create.instance"
"""
label = "Collect Color-coded Instances"
@ -56,7 +56,7 @@ class CollectColorCodedInstances(pyblish.api.ContextPlugin):
existing_subset_names = self._get_existing_subset_names(context)
# from CollectBatchData
asset_name = context.data["asset"]
asset_name = context.data["folderPath"]
task_name = context.data["task"]
variant = context.data["variant"]
project_name = context.data["projectEntity"]["name"]
@ -163,7 +163,7 @@ class CollectColorCodedInstances(pyblish.api.ContextPlugin):
instance = context.create_instance(layer.name)
instance.data["family"] = family
instance.data["publish"] = True
instance.data["asset"] = asset
instance.data["folderPath"] = asset
instance.data["task"] = task_name
instance.data["subset"] = subset
instance.data["layer"] = layer

View file

@ -31,7 +31,7 @@ class ValidateInstanceAssetRepair(pyblish.api.Action):
current_asset_name = get_current_asset_name()
for instance in instances:
data = stub.read(instance[0])
data["asset"] = current_asset_name
data["folderPath"] = current_asset_name
stub.imprint(instance[0], data)
@ -54,7 +54,7 @@ class ValidateInstanceAsset(OptionalPyblishPluginMixin,
order = ValidateContentsOrder
def process(self, instance):
instance_asset = instance.data["asset"]
instance_asset = instance.data["folderPath"]
current_asset = get_current_asset_name()
if instance_asset != current_asset:

View file

@ -519,7 +519,7 @@ def imprint(timeline_item, data=None):
Examples:
data = {
'asset': 'sq020sh0280',
'folderPath': 'sq020sh0280',
'family': 'render',
'subset': 'subsetMain'
}

View file

@ -2,6 +2,7 @@ from pprint import pformat
import pyblish
from ayon_core.pipeline import AYON_INSTANCE_ID, AVALON_INSTANCE_ID
from ayon_core.hosts.resolve.api.lib import (
get_current_timeline_items,
get_timeline_item_pype_tag,
@ -39,7 +40,9 @@ class PrecollectInstances(pyblish.api.ContextPlugin):
if not tag_data:
continue
if tag_data.get("id") != "pyblish.avalon.instance":
if tag_data.get("id") not in {
AYON_INSTANCE_ID, AVALON_INSTANCE_ID
}:
continue
media_pool_item = timeline_item.GetMediaPoolItem()
@ -66,7 +69,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin):
data.update({
"name": "{}_{}".format(asset, subset),
"label": "{} {}".format(asset, subset),
"asset": asset,
"folderPath": asset,
"item": timeline_item,
"publish": get_publish_attribute(timeline_item),
"fps": context.data["fps"],
@ -124,7 +127,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin):
if not hierarchy_data:
return
asset = data["asset"]
asset = data["folderPath"]
subset = "shotMain"
# insert family into families
@ -134,7 +137,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin):
"name": "{}_{}".format(asset, subset),
"label": "{} {}".format(asset, subset),
"subset": subset,
"asset": asset,
"folderPath": asset,
"family": family,
"families": [],
"publish": get_publish_attribute(timeline_item)

View file

@ -28,7 +28,7 @@ class PrecollectWorkfile(pyblish.api.ContextPlugin):
instance_data = {
"name": "{}_{}".format(asset_name, subset),
"label": "{} {}".format(current_asset_name, subset),
"asset": current_asset_name,
"folderPath": current_asset_name,
"subset": subset,
"item": project,
"family": "workfile",

View file

@ -27,8 +27,8 @@ class CollectTextureSet(pyblish.api.InstancePlugin):
config = self.get_export_config(instance)
asset_doc = get_asset_by_name(
project_name=instance.context.data["projectName"],
asset_name=instance.data["asset"]
instance.context.data["projectName"],
instance.data["folderPath"]
)
instance.data["exportConfig"] = config

View file

@ -53,7 +53,7 @@ class OnlineCreator(TrayPublishCreator):
# disable check for existing subset with the same name
"""
asset = get_asset_by_name(
self.project_name, instance_data["asset"], fields=["_id"])
self.project_name, instance_data["folderPath"], fields=["_id"])
if get_subset_by_name(
self.project_name, origin_basename, asset["_id"],

View file

@ -17,7 +17,7 @@ class CollectShotInstance(pyblish.api.InstancePlugin):
families = ["shot"]
SHARED_KEYS = [
"asset",
"folderPath",
"fps",
"handleStart",
"handleEnd",
@ -132,7 +132,7 @@ class CollectShotInstance(pyblish.api.InstancePlugin):
"sourceIn": _cr_attrs["sourceIn"],
"sourceOut": _cr_attrs["sourceOut"],
"workfileFrameStart": workfile_start_frame,
"asset": _cr_attrs["folderPath"],
"folderPath": _cr_attrs["folderPath"],
}
def _solve_hierarchy_context(self, instance):
@ -170,7 +170,7 @@ class CollectShotInstance(pyblish.api.InstancePlugin):
parents = instance.data.get('parents', [])
# Split by '/' for AYON where asset is a path
asset_name = instance.data["asset"].split("/")[-1]
asset_name = instance.data["folderPath"].split("/")[-1]
actual = {asset_name: in_info}
for parent in reversed(parents):

View file

@ -40,7 +40,7 @@ class ValidateExistingVersion(
formatting_data = {
"subset_name": subset_name,
"asset_name": instance.data["asset"],
"asset_name": instance.data["folderPath"],
"version": version
}
raise PublishXmlValidationError(

View file

@ -52,7 +52,7 @@ expected that there are also keys `["instances0", "instances1"]`.
Workfile data looks like:
```
[avalon]
instances0=[{{__dq__}id{__dq__}: {__dq__}pyblish.avalon.instance{__dq__...
instances0=[{{__dq__}id{__dq__}: {__dq__}ayon.create.instance{__dq__...
instances1=...more data...
instances=2
```

View file

@ -65,7 +65,7 @@ class CollectWorkfileData(pyblish.api.ContextPlugin):
# Collect and store current context to have reference
current_context = {
"project_name": context.data["projectName"],
"asset_name": context.data["asset"],
"asset_name": context.data["folderPath"],
"task_name": context.data["task"]
}
self.log.debug("Current context is: {}".format(current_context))
@ -105,7 +105,7 @@ class CollectWorkfileData(pyblish.api.ContextPlugin):
))
# Store context asset name
context.data["asset"] = asset_name
context.data["folderPath"] = asset_name
context.data["task"] = task_name
self.log.info(
"Context is set to Asset: \"{}\" and Task: \"{}\"".format(

View file

@ -20,7 +20,7 @@ class FixAssetNames(pyblish.api.Action):
on = "failed"
def process(self, context, plugin):
context_asset_name = context.data["asset"]
context_asset_name = context.data["folderPath"]
old_instance_items = list_instances()
new_instance_items = []
for instance_item in old_instance_items:
@ -51,9 +51,9 @@ class ValidateAssetName(
def process(self, context):
if not self.is_active(context.data):
return
context_asset_name = context.data["asset"]
context_asset_name = context.data["folderPath"]
for instance in context:
asset_name = instance.data.get("asset")
asset_name = instance.data.get("folderPath")
if asset_name and asset_name == context_asset_name:
continue

View file

@ -64,7 +64,7 @@ class CollectRenderInstances(pyblish.api.InstancePlugin):
new_data = new_instance.data
new_data["asset"] = seq_name
new_data["folderPath"] = seq_name
new_data["setMembers"] = seq_name
new_data["family"] = "render"
new_data["families"] = ["render", "review"]

View file

@ -112,7 +112,7 @@ class ProcessSubmittedCacheJobOnFarm(pyblish.api.InstancePlugin,
output_dir = self._get_publish_folder(
anatomy,
deepcopy(instance.data["anatomyData"]),
instance.data.get("asset"),
instance.data.get("folderPath"),
instance.data["subset"],
instance.context,
instance.data["family"],
@ -126,7 +126,7 @@ class ProcessSubmittedCacheJobOnFarm(pyblish.api.InstancePlugin,
environment = {
"AYON_PROJECT_NAME": instance.context.data["projectName"],
"AYON_FOLDER_PATH": instance.context.data["asset"],
"AYON_FOLDER_PATH": instance.context.data["folderPath"],
"AYON_TASK_NAME": instance.context.data["task"],
"AYON_USERNAME": instance.context.data["user"],
"AYON_LOG_NO_COLORS": "1",
@ -359,7 +359,7 @@ class ProcessSubmittedCacheJobOnFarm(pyblish.api.InstancePlugin,
# publish job file
publish_job = {
"asset": instance_skeleton_data["asset"],
"folderPath": instance_skeleton_data["folderPath"],
"frameStart": instance_skeleton_data["frameStart"],
"frameEnd": instance_skeleton_data["frameEnd"],
"fps": instance_skeleton_data["fps"],

View file

@ -189,7 +189,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin,
output_dir = self._get_publish_folder(
anatomy,
deepcopy(instance.data["anatomyData"]),
instance.data.get("asset"),
instance.data.get("folderPath"),
instances[0]["subset"],
instance.context,
instances[0]["family"],
@ -203,7 +203,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin,
environment = {
"AYON_PROJECT_NAME": instance.context.data["projectName"],
"AYON_FOLDER_PATH": instance.context.data["asset"],
"AYON_FOLDER_PATH": instance.context.data["folderPath"],
"AYON_TASK_NAME": instance.context.data["task"],
"AYON_USERNAME": instance.context.data["user"],
"AYON_LOG_NO_COLORS": "1",
@ -475,7 +475,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin,
# publish job file
publish_job = {
"asset": instance_skeleton_data["asset"],
"folderPath": instance_skeleton_data["folderPath"],
"frameStart": instance_skeleton_data["frameStart"],
"frameEnd": instance_skeleton_data["frameEnd"],
"fps": instance_skeleton_data["fps"],

View file

@ -1,6 +1,6 @@
from .royal_render_module import RoyalRenderModule
from .addon import RoyalRenderAddon
__all__ = (
"RoyalRenderModule",
"RoyalRenderAddon",
)

View file

@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
"""Module providing support for Royal Render."""
import os
from ayon_core.addon import AYONAddon, IPluginPaths
class RoyalRenderAddon(AYONAddon, IPluginPaths):
"""Class providing basic Royal Render implementation logic."""
name = "royalrender"
# _rr_api = None
# @property
# def rr_api(self):
# if not self._rr_api:
# # import royal render modules
# from .api import Api
# self._rr_api = Api(self.settings)
# return self._rr_api
def initialize(self, studio_settings):
# type: (dict) -> None
self.enabled = self.name in studio_settings
@staticmethod
def get_plugin_paths():
# type: () -> dict
"""Royal Render plugin paths.
Returns:
dict: Dictionary of plugin paths for RR.
"""
current_dir = os.path.dirname(os.path.abspath(__file__))
return {
"publish": [os.path.join(current_dir, "plugins", "publish")]
}

View file

@ -108,9 +108,7 @@ class BaseCreateRoyalRenderJob(pyblish.api.InstancePlugin,
context = instance.context
self._rr_root = self._resolve_rr_path(context, instance.data.get(
"rrPathName")) # noqa
self.log.debug(self._rr_root)
self._rr_root = instance.data.get("rrPathName")
if not self._rr_root:
raise KnownPublishError(
("Missing RoyalRender root. "
@ -210,35 +208,6 @@ class BaseCreateRoyalRenderJob(pyblish.api.InstancePlugin,
"""Host specific mapping for RRJob"""
raise NotImplementedError
@staticmethod
def _resolve_rr_path(context, rr_path_name):
# type: (pyblish.api.Context, str) -> str
rr_settings = (
context.data
["system_settings"]
["modules"]
["royalrender"]
)
try:
default_servers = rr_settings["rr_paths"]
project_servers = (
context.data
["project_settings"]
["royalrender"]
["rr_paths"]
)
rr_servers = {
k: default_servers[k]
for k in project_servers
if k in default_servers
}
except (AttributeError, KeyError):
# Handle situation were we had only one url for royal render.
return context.data["defaultRRPath"][platform.system().lower()]
return rr_servers[rr_path_name][platform.system().lower()]
def expected_files(self, instance, path, start_frame, end_frame):
"""Get expected files.
@ -350,7 +319,7 @@ class BaseCreateRoyalRenderJob(pyblish.api.InstancePlugin,
add_kwargs = {
"project": anatomy_data["project"]["name"],
"asset": instance.context.data["asset"],
"asset": instance.context.data["folderPath"],
"task": anatomy_data["task"]["name"],
"app": instance.context.data.get("appName"),
"envgroup": "farm"

View file

@ -18,30 +18,24 @@ class CollectRRPathFromInstance(pyblish.api.InstancePlugin):
def _collect_rr_path_name(instance):
# type: (pyblish.api.Instance) -> str
"""Get Royal Render pat name from render instance."""
rr_settings = (
instance.context.data
["system_settings"]
["modules"]
["royalrender"]
)
if not instance.data.get("rrPaths"):
# TODO there are no "rrPaths" on instance, if Publisher should expose
# this (eg. artist could select specific server) it must be added
# to publisher
instance_rr_paths = instance.data.get("rrPaths")
if instance_rr_paths is None:
return "default"
try:
default_servers = rr_settings["rr_paths"]
project_servers = (
instance.context.data
["project_settings"]
["royalrender"]
["rr_paths"]
)
rr_servers = {
k: default_servers[k]
for k in project_servers
if k in default_servers
}
except (AttributeError, KeyError):
# Handle situation were we had only one url for royal render.
return rr_settings["rr_paths"]["default"]
rr_settings = instance.context.data["project_settings"]["royalrender"]
rr_paths = rr_settings["rr_paths"]
selected_paths = rr_settings["selected_rr_paths"]
return list(rr_servers.keys())[int(instance.data.get("rrPaths"))]
rr_servers = {
path_key
for path_key in selected_paths
if path_key in rr_paths
}
for instance_rr_path in instance_rr_paths:
if instance_rr_path in rr_servers:
return instance_rr_path
return "default"

View file

@ -189,8 +189,8 @@ class CollectSequencesFromJob(pyblish.api.ContextPlugin):
"family": families[0], # backwards compatibility / pyblish
"families": list(families),
"subset": subset,
"asset": data.get(
"asset", context.data["asset"]
"folderPath": data.get(
"folderPath", context.data["folderPath"]
),
"stagingDir": root,
"frameStart": start,

View file

@ -132,7 +132,7 @@ class CreatePublishRoyalRenderJob(pyblish.api.InstancePlugin,
# publish job file
publish_job = {
"asset": instance_skeleton_data["asset"],
"folderPath": instance_skeleton_data["folderPath"],
"frameStart": instance_skeleton_data["frameStart"],
"frameEnd": instance_skeleton_data["frameEnd"],
"fps": instance_skeleton_data["fps"],
@ -180,7 +180,7 @@ class CreatePublishRoyalRenderJob(pyblish.api.InstancePlugin,
environment = RREnvList({
"AYON_PROJECT_NAME": anatomy_data["project"]["name"],
"AYON_FOLDER_PATH": instance.context.data["asset"],
"AYON_FOLDER_PATH": instance.context.data["folderPath"],
"AYON_TASK_NAME": anatomy_data["task"]["name"],
"AYON_USERNAME": anatomy_data["user"]
})
@ -216,7 +216,7 @@ class CreatePublishRoyalRenderJob(pyblish.api.InstancePlugin,
SeqEnd=1,
SeqStep=1,
SeqFileOffset=0,
Version=self._sanitize_version(os.environ.get("OPENPYPE_VERSION")),
Version=os.environ["AYON_BUNDLE_NAME"],
SceneName=abs_metadata_path,
# command line arguments
CustomAddCmdFlags=" ".join(args),
@ -243,26 +243,3 @@ class CreatePublishRoyalRenderJob(pyblish.api.InstancePlugin,
job.WaitForPreIDs += jobs_pre_ids
return job
def _sanitize_version(self, version):
"""Returns version in format MAJOR.MINORPATCH
3.15.7-nightly.2 >> 3.157
"""
VERSION_REGEX = re.compile(
r"(?P<major>0|[1-9]\d*)"
r"\.(?P<minor>0|[1-9]\d*)"
r"\.(?P<patch>0|[1-9]\d*)"
r"(?:-(?P<prerelease>[a-zA-Z\d\-.]*))?"
r"(?:\+(?P<buildmetadata>[a-zA-Z\d\-.]*))?"
)
valid_parts = VERSION_REGEX.findall(version)
if len(valid_parts) != 1:
# Return invalid version with filled 'origin' attribute
return version
# Unpack found version
major, minor, patch, pre, post = valid_parts[0]
return "{}.{}{}".format(major, minor, patch)

View file

@ -25,16 +25,6 @@ class SubmitJobsToRoyalRender(pyblish.api.ContextPlugin):
self._submission_parameters = []
def process(self, context):
rr_settings = (
context.data
["system_settings"]
["modules"]
["royalrender"]
)
if rr_settings["enabled"] is not True:
self.log.warning("RoyalRender modules is disabled.")
return
# iterate over all instances and try to find RRJobs
jobs = []
@ -51,7 +41,7 @@ class SubmitJobsToRoyalRender(pyblish.api.ContextPlugin):
instance_rr_path = instance.data["rrPathName"]
if jobs:
self._rr_root = self._resolve_rr_path(context, instance_rr_path)
self._rr_root = instance_rr_path
if not self._rr_root:
raise KnownPublishError(
("Missing RoyalRender root. "
@ -100,32 +90,3 @@ class SubmitJobsToRoyalRender(pyblish.api.ContextPlugin):
def get_submission_parameters(self):
return [SubmitterParameter("RequiredMemory", "0")]
@staticmethod
def _resolve_rr_path(context, rr_path_name):
# type: (pyblish.api.Context, str) -> str
rr_settings = (
context.data
["system_settings"]
["modules"]
["royalrender"]
)
try:
default_servers = rr_settings["rr_paths"]
project_servers = (
context.data
["project_settings"]
["royalrender"]
["rr_paths"]
)
rr_servers = {
k: default_servers[k]
for k in project_servers
if k in default_servers
}
except (AttributeError, KeyError):
# Handle situation were we had only one url for royal render.
return context.data["defaultRRPath"][platform.system().lower()]
return rr_servers[rr_path_name][platform.system().lower()]

View file

@ -1,45 +0,0 @@
# -*- coding: utf-8 -*-
"""Module providing support for Royal Render."""
import os
import ayon_core.modules
from ayon_core.modules import OpenPypeModule, IPluginPaths
class RoyalRenderModule(OpenPypeModule, IPluginPaths):
"""Class providing basic Royal Render implementation logic."""
name = "royalrender"
@property
def api(self):
if not self._api:
# import royal render modules
from . import api as rr_api
self._api = rr_api.Api(self.settings)
return self._api
def __init__(self, manager, settings):
# type: (ayon_core.addon.AddonsManager, dict) -> None
self.rr_paths = {}
self._api = None
self.settings = settings
super(RoyalRenderModule, self).__init__(manager, settings)
def initialize(self, module_settings):
# type: (dict) -> None
rr_settings = module_settings[self.name]
self.enabled = rr_settings["enabled"]
self.rr_paths = rr_settings.get("rr_paths")
@staticmethod
def get_plugin_paths():
# type: () -> dict
"""Royal Render plugin paths.
Returns:
dict: Dictionary of plugin paths for RR.
"""
current_dir = os.path.dirname(os.path.abspath(__file__))
return {
"publish": [os.path.join(current_dir, "plugins", "publish")]
}

View file

@ -24,7 +24,7 @@ class StartTimer(pyblish.api.ContextPlugin):
return
project_name = context.data["projectName"]
asset_name = context.data.get("asset")
asset_name = context.data.get("folderPath")
task_name = context.data.get("task")
if not project_name or not asset_name or not task_name:
self.log.info((

View file

@ -1,6 +1,8 @@
from .constants import (
AVALON_CONTAINER_ID,
AVALON_INSTANCE_ID,
AYON_CONTAINER_ID,
AYON_INSTANCE_ID,
HOST_WORKFILE_EXTENSIONS,
)
@ -101,7 +103,9 @@ uninstall = uninstall_host
__all__ = (
"AVALON_CONTAINER_ID",
"AVALON_INSTANCE_ID",
"AYON_CONTAINER_ID",
"AYON_INSTANCE_ID",
"HOST_WORKFILE_EXTENSIONS",
# --- Anatomy ---

View file

@ -1,5 +1,9 @@
# Metadata ID of loaded container into scene
AVALON_CONTAINER_ID = AYON_CONTAINER_ID = "pyblish.avalon.container"
AYON_CONTAINER_ID = "ayon.load.container"
AYON_INSTANCE_ID = "ayon.create.instance"
# Backwards compatibility
AVALON_CONTAINER_ID = "pyblish.avalon.container"
AVALON_INSTANCE_ID = "pyblish.avalon.instance"
# TODO get extensions from host implementations
HOST_WORKFILE_EXTENSIONS = {

View file

@ -14,7 +14,7 @@ Except creating and removing instances are all changes not automatically propaga
## CreatedInstance
Product of creation is "instance" which holds basic data defying it. Core data are `creator_identifier`, `family` and `subset`. Other data can be keys used to fill subset name or metadata modifying publishing process of the instance (more described later). All instances have `id` which holds constant `pyblish.avalon.instance` and `instance_id` which is identifier of the instance.
Product of creation is "instance" which holds basic data defying it. Core data are `creator_identifier`, `family` and `subset`. Other data can be keys used to fill subset name or metadata modifying publishing process of the instance (more described later). All instances have `id` which holds constant `ayon.create.instance` or `pyblish.avalon.instance` (for backwards compatibility) and `instance_id` which is identifier of the instance.
Family tells how should be instance processed and subset what name will published item have.
- There are cases when subset is not fully filled during creation and may change during publishing. That is in most of cases caused because instance is related to other instance or instance data do not represent final product.
@ -24,7 +24,7 @@ Family tells how should be instance processed and subset what name will publishe
{
# Immutable data after creation
## Identifier that this data represents instance for publishing (automatically assigned)
"id": "pyblish.avalon.instance",
"id": "ayon.create.instance",
## Identifier of this specific instance (automatically assigned)
"instance_id": <uuid4>,
## Instance family (used from Creator)
@ -48,7 +48,7 @@ Family tells how should be instance processed and subset what name will publishe
<Plugin name>: {...},
...
},
## Additional data related to instance (`asset`, `task`, etc.)
## Additional data related to instance (`folderPath`, `task`, etc.)
...
}
```

View file

@ -27,7 +27,11 @@ from ayon_core.lib.attribute_definitions import (
get_default_values,
)
from ayon_core.host import IPublishHost, IWorkfileHost
from ayon_core.pipeline import Anatomy
from ayon_core.pipeline import (
Anatomy,
AYON_INSTANCE_ID,
AVALON_INSTANCE_ID,
)
from ayon_core.pipeline.plugin_discover import DiscoverResult
from .creator_plugins import (
@ -937,7 +941,11 @@ class CreatedInstance:
# QUESTION Does it make sense to have data stored as ordered dict?
self._data = collections.OrderedDict()
# QUESTION Do we need this "id" information on instance?
self._data["id"] = "pyblish.avalon.instance"
item_id = data.get("id")
# TODO use only 'AYON_INSTANCE_ID' when all hosts support it
if item_id not in {AYON_INSTANCE_ID, AVALON_INSTANCE_ID}:
item_id = AVALON_INSTANCE_ID
self._data["id"] = item_id
self._data["family"] = family
self._data["subset"] = subset_name
self._data["active"] = data.get("active", True)

View file

@ -10,6 +10,7 @@ import logging
import collections
from ayon_core.client import get_asset_by_id
from ayon_core.pipeline.constants import AVALON_INSTANCE_ID
from .subset_name import get_subset_name
@ -27,15 +28,16 @@ class LegacyCreator(object):
log = logging.getLogger("LegacyCreator")
log.propagate = True
def __init__(self, name, asset, options=None, data=None):
def __init__(self, name, folder_path, options=None, data=None):
self.name = name # For backwards compatibility
self.options = options
# Default data
self.data = collections.OrderedDict()
self.data["id"] = "pyblish.avalon.instance"
# TODO use 'AYON_INSTANCE_ID' when all hosts support it
self.data["id"] = AVALON_INSTANCE_ID
self.data["family"] = self.family
self.data["asset"] = asset
self.data["folderPath"] = folder_path
self.data["subset"] = name
self.data["active"] = True

View file

@ -32,7 +32,7 @@ def get_last_versions_for_instances(
subset_names_by_asset_name = collections.defaultdict(set)
instances_by_hierarchy = {}
for instance in instances:
asset_name = instance.data.get("asset")
asset_name = instance.data.get("folderPath")
subset_name = instance.subset_name
if not asset_name or not subset_name:
if use_value_for_missing:

View file

@ -197,7 +197,7 @@ def create_skeleton_instance(
if data.get("extendFrames", False):
time_data.start, time_data.end = extend_frames(
data["asset"],
data["folderPath"],
data["subset"],
time_data.start,
time_data.end,
@ -228,7 +228,7 @@ def create_skeleton_instance(
"family": family,
"subset": data["subset"],
"families": families,
"asset": data["asset"],
"folderPath": data["folderPath"],
"frameStart": time_data.start,
"frameEnd": time_data.end,
"handleStart": time_data.handle_start,
@ -777,7 +777,7 @@ def create_skeleton_instance_cache(instance):
if data.get("extendFrames", False):
time_data.start, time_data.end = extend_frames(
data["asset"],
data["folderPath"],
data["subset"],
time_data.start,
time_data.end,
@ -805,7 +805,7 @@ def create_skeleton_instance_cache(instance):
"family": family,
"subset": data["subset"],
"families": families,
"asset": data["asset"],
"folderPath": data["folderPath"],
"frameStart": time_data.start,
"frameEnd": time_data.end,
"handleStart": time_data.handle_start,
@ -1011,7 +1011,7 @@ def copy_extend_frames(instance, representation):
version = get_last_version_by_subset_name(
project_name,
instance.data.get("subset"),
asset_name=instance.data.get("asset")
asset_name=instance.data.get("folderPath")
)
# get its files based on extension

View file

@ -30,7 +30,7 @@ class RenderInstance(object):
label = attr.ib() # label to show in GUI
subset = attr.ib() # subset name
task = attr.ib() # task name
asset = attr.ib() # asset name
folderPath = attr.ib() # folder path
attachTo = attr.ib() # subset name to attach render to
setMembers = attr.ib() # list of nodes/members producing render output
publish = attr.ib() # bool, True to publish instance

View file

@ -0,0 +1,59 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "ayon:container-3.0",
"description": "A loaded asset",
"type": "object",
"additionalProperties": true,
"required": [
"schema",
"id",
"objectName",
"name",
"namespace",
"loader",
"representation"
],
"properties": {
"schema": {
"description": "Schema identifier for payload",
"type": "string",
"enum": ["ayon:container-3.0"],
"example": "ayon:container-3.0"
},
"id": {
"description": "Identifier for finding object in host",
"type": "string",
"enum": ["ayon.load.container"],
"example": "ayon.load.container"
},
"objectName": {
"description": "Name of internal object, such as the objectSet in Maya.",
"type": "string",
"example": "Bruce_:rigDefault_CON"
},
"loader": {
"description": "Name of loader plug-in used to produce this container",
"type": "string",
"example": "ModelLoader"
},
"name": {
"description": "Internal object name of container in application",
"type": "string",
"example": "modelDefault_01"
},
"namespace": {
"description": "Internal namespace of container in application",
"type": "string",
"example": "Bruce_"
},
"representation": {
"description": "Unique id of representation in database",
"type": "string",
"example": "59523f355f8c1b5f6c5e8348"
}
}
}

View file

@ -3,7 +3,7 @@ Requires:
context -> anatomyData
context -> projectEntity
context -> assetEntity
instance -> asset
instance -> folderPath
instance -> subset
instance -> family
@ -68,7 +68,7 @@ class CollectAnatomyInstanceData(pyblish.api.ContextPlugin):
instances_with_missing_asset_doc = collections.defaultdict(list)
for instance in context:
instance_asset_doc = instance.data.get("assetEntity")
_asset_name = instance.data["asset"]
_asset_name = instance.data["folderPath"]
# There is possibility that assetEntity on instance is already set
# which can happen in standalone publisher
@ -296,7 +296,7 @@ class CollectAnatomyInstanceData(pyblish.api.ContextPlugin):
if hierarchy:
parent_name = hierarchy.split("/")[-1]
asset_name = instance.data["asset"].split("/")[-1]
asset_name = instance.data["folderPath"].split("/")[-1]
anatomy_data.update({
"asset": asset_name,
"hierarchy": hierarchy,
@ -337,7 +337,7 @@ class CollectAnatomyInstanceData(pyblish.api.ContextPlugin):
# Try to find task data based on hierarchy context and asset name
hierarchy_context = instance.context.data.get("hierarchyContext")
asset_name = instance.data.get("asset")
asset_name = instance.data.get("folderPath")
if not hierarchy_context or not asset_name:
return

View file

@ -66,7 +66,7 @@ class CollectAudio(pyblish.api.ContextPlugin):
# Add audio to instance if exists.
instances_by_asset_name = collections.defaultdict(list)
for instance in filtered_instances:
asset_name = instance.data["asset"]
asset_name = instance.data["folderPath"]
instances_by_asset_name[asset_name].append(instance)
asset_names = set(instances_by_asset_name.keys())

View file

@ -25,7 +25,7 @@ class CollectContextEntities(pyblish.api.ContextPlugin):
def process(self, context):
project_name = context.data["projectName"]
asset_name = context.data["asset"]
asset_name = context.data["folderPath"]
task_name = context.data["task"]
project_entity = get_project(project_name)

Some files were not shown because too many files have changed in this diff Show more