mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-25 21:32:15 +01:00
Merge remote-tracking branch 'origin/enhancement/OP-2903_Hero-versions-custom-templates' into feature/OP-2983_simple-texture-publishing
This commit is contained in:
commit
c181d2da7c
4 changed files with 171 additions and 110 deletions
|
|
@ -7,8 +7,12 @@ import shutil
|
|||
from bson.objectid import ObjectId
|
||||
from pymongo import InsertOne, ReplaceOne
|
||||
import pyblish.api
|
||||
|
||||
from avalon import api, io, schema
|
||||
from openpype.lib import create_hard_link
|
||||
from openpype.lib import (
|
||||
create_hard_link,
|
||||
filter_profiles
|
||||
)
|
||||
|
||||
|
||||
class IntegrateHeroVersion(pyblish.api.InstancePlugin):
|
||||
|
|
@ -17,7 +21,9 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
|
|||
order = pyblish.api.IntegratorOrder + 0.1
|
||||
|
||||
optional = True
|
||||
active = True
|
||||
|
||||
# Families are modified using settings
|
||||
families = [
|
||||
"model",
|
||||
"rig",
|
||||
|
|
@ -33,11 +39,13 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
|
|||
"project", "asset", "task", "subset", "representation",
|
||||
"family", "hierarchy", "task", "username"
|
||||
]
|
||||
# TODO add family filtering
|
||||
# QUESTION/TODO this process should happen on server if crashed due to
|
||||
# permissions error on files (files were used or user didn't have perms)
|
||||
# *but all other plugins must be sucessfully completed
|
||||
|
||||
template_name_profiles = []
|
||||
_default_template_name = "hero"
|
||||
|
||||
def process(self, instance):
|
||||
self.log.debug(
|
||||
"--- Integration of Hero version for subset `{}` begins.".format(
|
||||
|
|
@ -51,27 +59,35 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
|
|||
)
|
||||
return
|
||||
|
||||
project_name = api.Session["AVALON_PROJECT"]
|
||||
template_key = self._get_template_key(instance)
|
||||
|
||||
# TODO raise error if Hero not set?
|
||||
anatomy = instance.context.data["anatomy"]
|
||||
if "hero" not in anatomy.templates:
|
||||
self.log.warning("!!! Anatomy does not have set `hero` key!")
|
||||
return
|
||||
|
||||
if "path" not in anatomy.templates["hero"]:
|
||||
project_name = api.Session["AVALON_PROJECT"]
|
||||
if template_key not in anatomy.templates:
|
||||
self.log.warning((
|
||||
"!!! There is not set `path` template in `hero` anatomy"
|
||||
" for project \"{}\"."
|
||||
).format(project_name))
|
||||
"!!! Anatomy of project \"{}\" does not have set"
|
||||
" \"{}\" template key!"
|
||||
).format(project_name, template_key))
|
||||
return
|
||||
|
||||
hero_template = anatomy.templates["hero"]["path"]
|
||||
if "path" not in anatomy.templates[template_key]:
|
||||
self.log.warning((
|
||||
"!!! There is not set \"path\" template in \"{}\" anatomy"
|
||||
" for project \"{}\"."
|
||||
).format(template_key, project_name))
|
||||
return
|
||||
|
||||
hero_template = anatomy.templates[template_key]["path"]
|
||||
self.log.debug("`hero` template check was successful. `{}`".format(
|
||||
hero_template
|
||||
))
|
||||
|
||||
hero_publish_dir = self.get_publish_dir(instance)
|
||||
self.integrate_instance(instance, template_key, hero_template)
|
||||
|
||||
def integrate_instance(self, instance, template_key, hero_template):
|
||||
anatomy = instance.context.data["anatomy"]
|
||||
published_repres = instance.data["published_representations"]
|
||||
hero_publish_dir = self.get_publish_dir(instance, template_key)
|
||||
|
||||
src_version_entity = instance.data.get("versionEntity")
|
||||
filtered_repre_ids = []
|
||||
|
|
@ -271,12 +287,12 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
|
|||
continue
|
||||
|
||||
# Prepare anatomy data
|
||||
anatomy_data = repre_info["anatomy_data"]
|
||||
anatomy_data = copy.deepcopy(repre_info["anatomy_data"])
|
||||
anatomy_data.pop("version", None)
|
||||
|
||||
# Get filled path to repre context
|
||||
anatomy_filled = anatomy.format(anatomy_data)
|
||||
template_filled = anatomy_filled["hero"]["path"]
|
||||
template_filled = anatomy_filled[template_key]["path"]
|
||||
|
||||
repre_data = {
|
||||
"path": str(template_filled),
|
||||
|
|
@ -308,11 +324,11 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
|
|||
collections, remainders = clique.assemble(published_files)
|
||||
if remainders or not collections or len(collections) > 1:
|
||||
raise Exception((
|
||||
"Integrity error. Files of published representation "
|
||||
"is combination of frame collections and single files."
|
||||
"Collections: `{}` Single files: `{}`"
|
||||
).format(str(collections),
|
||||
str(remainders)))
|
||||
"Integrity error. Files of published"
|
||||
" representation is combination of frame"
|
||||
" collections and single files. Collections:"
|
||||
" `{}` Single files: `{}`"
|
||||
).format(str(collections), str(remainders)))
|
||||
|
||||
src_col = collections[0]
|
||||
|
||||
|
|
@ -320,13 +336,10 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
|
|||
frame_splitter = "_-_FRAME_SPLIT_-_"
|
||||
anatomy_data["frame"] = frame_splitter
|
||||
_anatomy_filled = anatomy.format(anatomy_data)
|
||||
_template_filled = _anatomy_filled["hero"]["path"]
|
||||
_template_filled = _anatomy_filled[template_key]["path"]
|
||||
head, tail = _template_filled.split(frame_splitter)
|
||||
padding = int(
|
||||
anatomy.templates["render"].get(
|
||||
"frame_padding",
|
||||
anatomy.templates["render"].get("padding")
|
||||
)
|
||||
anatomy.templates[template_key]["frame_padding"]
|
||||
)
|
||||
|
||||
dst_col = clique.Collection(
|
||||
|
|
@ -444,6 +457,8 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
|
|||
backup_hero_publish_dir is not None and
|
||||
os.path.exists(backup_hero_publish_dir)
|
||||
):
|
||||
if os.path.exists(hero_publish_dir):
|
||||
shutil.rmtree(hero_publish_dir)
|
||||
os.rename(backup_hero_publish_dir, hero_publish_dir)
|
||||
self.log.error((
|
||||
"!!! Creating of hero version failed."
|
||||
|
|
@ -466,13 +481,13 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
|
|||
files.append(_path)
|
||||
return files
|
||||
|
||||
def get_publish_dir(self, instance):
|
||||
def get_publish_dir(self, instance, template_key):
|
||||
anatomy = instance.context.data["anatomy"]
|
||||
template_data = copy.deepcopy(instance.data["anatomyData"])
|
||||
|
||||
if "folder" in anatomy.templates["hero"]:
|
||||
if "folder" in anatomy.templates[template_key]:
|
||||
anatomy_filled = anatomy.format(template_data)
|
||||
publish_folder = anatomy_filled["hero"]["folder"]
|
||||
publish_folder = anatomy_filled[template_key]["folder"]
|
||||
else:
|
||||
# This is for cases of Deprecated anatomy without `folder`
|
||||
# TODO remove when all clients have solved this issue
|
||||
|
|
@ -489,7 +504,7 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
|
|||
" key underneath `publish` (in global of for project `{}`)."
|
||||
).format(project_name))
|
||||
|
||||
file_path = anatomy_filled["hero"]["path"]
|
||||
file_path = anatomy_filled[template_key]["path"]
|
||||
# Directory
|
||||
publish_folder = os.path.dirname(file_path)
|
||||
|
||||
|
|
@ -499,6 +514,38 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
|
|||
|
||||
return publish_folder
|
||||
|
||||
def _get_template_key(self, instance):
|
||||
anatomy_data = instance.data["anatomyData"]
|
||||
task_data = anatomy_data.get("task") or {}
|
||||
task_name = task_data.get("name")
|
||||
task_type = task_data.get("type")
|
||||
host_name = instance.context.data["hostName"]
|
||||
# TODO raise error if Hero not set?
|
||||
family = self.main_family_from_instance(instance)
|
||||
key_values = {
|
||||
"families": family,
|
||||
"task_names": task_name,
|
||||
"task_types": task_type,
|
||||
"hosts": host_name
|
||||
}
|
||||
profile = filter_profiles(
|
||||
self.template_name_profiles,
|
||||
key_values,
|
||||
logger=self.log
|
||||
)
|
||||
if profile:
|
||||
template_name = profile["template_name"]
|
||||
else:
|
||||
template_name = self._default_template_name
|
||||
return template_name
|
||||
|
||||
def main_family_from_instance(self, instance):
|
||||
"""Returns main family of entered instance."""
|
||||
family = instance.data.get("family")
|
||||
if not family:
|
||||
family = instance.data["families"][0]
|
||||
return family
|
||||
|
||||
def copy_file(self, src_path, dst_path):
|
||||
# TODO check drives if are the same to check if cas hardlink
|
||||
dirname = os.path.dirname(dst_path)
|
||||
|
|
@ -564,22 +611,16 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
|
|||
src_file (string) - original file path
|
||||
dst_file (string) - hero file path
|
||||
"""
|
||||
_, rootless = anatomy.find_root_template_from_path(
|
||||
dst_file
|
||||
)
|
||||
_, rtls_src = anatomy.find_root_template_from_path(
|
||||
src_file
|
||||
)
|
||||
_, rootless = anatomy.find_root_template_from_path(dst_file)
|
||||
_, rtls_src = anatomy.find_root_template_from_path(src_file)
|
||||
return path.replace(rtls_src, rootless)
|
||||
|
||||
def _update_hash(self, hash, src_file_name, dst_file):
|
||||
"""
|
||||
Updates hash value with proper hero name
|
||||
"""
|
||||
src_file_name = self._get_name_without_ext(
|
||||
src_file_name)
|
||||
hero_file_name = self._get_name_without_ext(
|
||||
dst_file)
|
||||
src_file_name = self._get_name_without_ext(src_file_name)
|
||||
hero_file_name = self._get_name_without_ext(dst_file)
|
||||
return hash.replace(src_file_name, hero_file_name)
|
||||
|
||||
def _get_name_without_ext(self, value):
|
||||
|
|
|
|||
|
|
@ -33,20 +33,6 @@
|
|||
"enabled": false,
|
||||
"profiles": []
|
||||
},
|
||||
"IntegrateHeroVersion": {
|
||||
"enabled": true,
|
||||
"optional": true,
|
||||
"families": [
|
||||
"model",
|
||||
"rig",
|
||||
"look",
|
||||
"pointcache",
|
||||
"animation",
|
||||
"setdress",
|
||||
"layout",
|
||||
"mayaScene"
|
||||
]
|
||||
},
|
||||
"ExtractJpegEXR": {
|
||||
"enabled": true,
|
||||
"ffmpeg_args": {
|
||||
|
|
@ -215,6 +201,22 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"IntegrateHeroVersion": {
|
||||
"enabled": true,
|
||||
"optional": true,
|
||||
"active": true,
|
||||
"families": [
|
||||
"model",
|
||||
"rig",
|
||||
"look",
|
||||
"pointcache",
|
||||
"animation",
|
||||
"setdress",
|
||||
"layout",
|
||||
"mayaScene"
|
||||
],
|
||||
"template_name_profiles": []
|
||||
},
|
||||
"CleanUp": {
|
||||
"paterns": [],
|
||||
"remove_temp_renders": false
|
||||
|
|
|
|||
|
|
@ -122,32 +122,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"collapsible": true,
|
||||
"checkbox_key": "enabled",
|
||||
"key": "IntegrateHeroVersion",
|
||||
"label": "IntegrateHeroVersion",
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "enabled",
|
||||
"label": "Enabled"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "optional",
|
||||
"label": "Optional"
|
||||
},
|
||||
{
|
||||
"key": "families",
|
||||
"label": "Families",
|
||||
"type": "list",
|
||||
"object_type": "text"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"collapsible": true,
|
||||
|
|
@ -652,6 +626,80 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"collapsible": true,
|
||||
"checkbox_key": "enabled",
|
||||
"key": "IntegrateHeroVersion",
|
||||
"label": "IntegrateHeroVersion",
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "enabled",
|
||||
"label": "Enabled"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "optional",
|
||||
"label": "Optional"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "active",
|
||||
"label": "Active"
|
||||
},
|
||||
{
|
||||
"key": "families",
|
||||
"label": "Families",
|
||||
"type": "list",
|
||||
"object_type": "text"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"key": "template_name_profiles",
|
||||
"label": "Template name profiles",
|
||||
"use_label_wrap": true,
|
||||
"object_type": {
|
||||
"type": "dict",
|
||||
"children": [
|
||||
{
|
||||
"key": "families",
|
||||
"label": "Families",
|
||||
"type": "list",
|
||||
"object_type": "text"
|
||||
},
|
||||
{
|
||||
"type": "hosts-enum",
|
||||
"key": "hosts",
|
||||
"label": "Hosts",
|
||||
"multiselection": true
|
||||
},
|
||||
{
|
||||
"key": "task_types",
|
||||
"label": "Task types",
|
||||
"type": "task-types-enum"
|
||||
},
|
||||
{
|
||||
"key": "task_names",
|
||||
"label": "Task names",
|
||||
"type": "list",
|
||||
"object_type": "text"
|
||||
},
|
||||
{
|
||||
"type": "separator"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "template_name",
|
||||
"label": "Template name",
|
||||
"tooltip": "Name of template from Anatomy templates"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"collapsible": true,
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
[
|
||||
{
|
||||
"type": "list-strict",
|
||||
"key": "{name}",
|
||||
"label": "{label}",
|
||||
"object_types": [
|
||||
{
|
||||
"label": "Red",
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 1,
|
||||
"decimal": 3
|
||||
},
|
||||
{
|
||||
"label": "Green",
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 1,
|
||||
"decimal": 3
|
||||
},
|
||||
{
|
||||
"label": "Blue",
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 1,
|
||||
"decimal": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
Loading…
Add table
Add a link
Reference in a new issue