mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-25 05:14:40 +01:00
client#115 - added Texture batch for Standalone Publisher
Added collector Added validator Added family
This commit is contained in:
parent
076d1d8a28
commit
313e433d72
3 changed files with 293 additions and 8 deletions
|
|
@ -0,0 +1,220 @@
|
|||
import os
|
||||
import copy
|
||||
import re
|
||||
import opentimelineio as otio
|
||||
import pyblish.api
|
||||
from openpype import lib as plib
|
||||
import json
|
||||
|
||||
class CollectTextures(pyblish.api.ContextPlugin):
|
||||
"""Collect workfile (and its resource_files) and textures."""
|
||||
|
||||
order = pyblish.api.CollectorOrder
|
||||
label = "Collect Textures"
|
||||
hosts = ["standalonepublisher"]
|
||||
families = ["texture_batch"]
|
||||
actions = []
|
||||
|
||||
main_workfile_extensions = ['mra']
|
||||
other_workfile_extensions = ['spp', 'psd']
|
||||
texture_extensions = ["exr", "dpx", "jpg", "jpeg", "png", "tiff", "tga",
|
||||
"gif", "svg"]
|
||||
|
||||
color_space = ["lin_srgb", "raw", "acesg"]
|
||||
|
||||
version_regex = re.compile(r"^(.+)_v([0-9]+)")
|
||||
udim_regex = re.compile(r"_1[0-9]{3}\.")
|
||||
|
||||
def process(self, context):
|
||||
self.context = context
|
||||
import json
|
||||
def convertor(value):
|
||||
return str(value)
|
||||
|
||||
workfile_subset = "texturesMainWorkfile"
|
||||
resource_files = {}
|
||||
workfile_files = {}
|
||||
representations = {}
|
||||
version_data = {}
|
||||
asset_builds = set()
|
||||
asset = None
|
||||
for instance in context:
|
||||
if not asset:
|
||||
asset = instance.data["asset"] # selected from SP
|
||||
|
||||
self.log.info("instance.data:: {}".format(
|
||||
json.dumps(instance.data, indent=4, default=convertor)))
|
||||
processed_instance = False
|
||||
for repre in instance.data["representations"]:
|
||||
ext = repre["ext"].replace('.', '')
|
||||
asset_build = version = None
|
||||
if ext in self.main_workfile_extensions or \
|
||||
ext in self.other_workfile_extensions:
|
||||
self.log.info('workfile')
|
||||
asset_build, version = \
|
||||
self._parse_asset_build(repre["files"],
|
||||
self.version_regex)
|
||||
asset_builds.add((asset_build, version,
|
||||
workfile_subset, 'workfile'))
|
||||
processed_instance = True
|
||||
|
||||
if not representations.get(workfile_subset):
|
||||
representations[workfile_subset] = []
|
||||
|
||||
# asset_build must be here to tie workfile and texture
|
||||
if not workfile_files.get(asset_build):
|
||||
workfile_files[asset_build] = []
|
||||
|
||||
if ext in self.main_workfile_extensions:
|
||||
representations[workfile_subset].append(repre)
|
||||
workfile_files[asset_build].append(repre["files"])
|
||||
|
||||
if ext in self.other_workfile_extensions:
|
||||
self.log.info("other")
|
||||
# add only if not added already from main
|
||||
if not representations.get(workfile_subset):
|
||||
representations[workfile_subset].append(repre)
|
||||
|
||||
if not workfile_files.get(asset_build):
|
||||
workfile_files[asset_build].append(repre["files"])
|
||||
|
||||
if not resource_files.get(workfile_subset):
|
||||
resource_files[workfile_subset] = []
|
||||
item = {
|
||||
"files": [os.path.join(repre["stagingDir"],
|
||||
repre["files"])],
|
||||
"source": "standalone publisher"
|
||||
}
|
||||
resource_files[workfile_subset].append(item)
|
||||
|
||||
if ext in self.texture_extensions:
|
||||
c_space = self._get_color_space(repre["files"][0],
|
||||
self.color_space)
|
||||
subset = "texturesMain_{}".format(c_space)
|
||||
|
||||
asset_build, version = \
|
||||
self._parse_asset_build(repre["files"][0],
|
||||
self.version_regex)
|
||||
|
||||
if not representations.get(subset):
|
||||
representations[subset] = []
|
||||
representations[subset].append(repre)
|
||||
|
||||
udim = self._parse_udim(repre["files"][0], self.udim_regex)
|
||||
|
||||
if not version_data.get(subset):
|
||||
version_data[subset] = []
|
||||
ver_data = {
|
||||
"color_space": c_space,
|
||||
"UDIM": udim,
|
||||
}
|
||||
version_data[subset].append(ver_data)
|
||||
|
||||
asset_builds.add(
|
||||
(asset_build, version, subset, "textures"))
|
||||
processed_instance = True
|
||||
|
||||
if processed_instance:
|
||||
self.context.remove(instance)
|
||||
|
||||
self.log.info("asset_builds:: {}".format(asset_builds))
|
||||
self._create_new_instances(context,
|
||||
asset,
|
||||
asset_builds,
|
||||
resource_files,
|
||||
representations,
|
||||
version_data,
|
||||
workfile_files)
|
||||
|
||||
def _create_new_instances(self, context, asset, asset_builds,
|
||||
resource_files, representations,
|
||||
version_data, workfile_files):
|
||||
"""Prepare new instances from collected data.
|
||||
|
||||
Args:
|
||||
context (ContextPlugin)
|
||||
asset (string): selected asset from SP
|
||||
asset_builds (set) of tuples
|
||||
(asset_build, version, subset, family)
|
||||
resource_files (list) of resource dicts
|
||||
representations (dict) of representation files, key is
|
||||
asset_build
|
||||
"""
|
||||
for asset_build, version, subset, family in asset_builds:
|
||||
|
||||
self.log.info("resources:: {}".format(resource_files))
|
||||
self.log.info("-"*25)
|
||||
self.log.info("representations:: {}".format(representations))
|
||||
self.log.info("-"*25)
|
||||
self.log.info("workfile_files:: {}".format(workfile_files))
|
||||
|
||||
new_instance = context.create_instance(subset)
|
||||
new_instance.data.update(
|
||||
{
|
||||
"subset": subset,
|
||||
"asset": asset,
|
||||
"label": subset,
|
||||
"name": subset,
|
||||
"family": family,
|
||||
"version": int(version),
|
||||
"representations": representations.get(subset),
|
||||
"families": [family]
|
||||
}
|
||||
)
|
||||
if resource_files.get(subset):
|
||||
new_instance.data.update({
|
||||
"resources": resource_files.get(subset)
|
||||
})
|
||||
|
||||
repre = representations.get(subset)[0]
|
||||
new_instance.context.data["currentFile"] = os.path.join(
|
||||
repre["stagingDir"], repre["files"][0])
|
||||
|
||||
ver_data = version_data.get(subset)
|
||||
if ver_data:
|
||||
ver_data = ver_data[0]
|
||||
if workfile_files.get(asset_build):
|
||||
ver_data['workfile'] = workfile_files.get(asset_build)[0]
|
||||
|
||||
new_instance.data.update(
|
||||
{"versionData": ver_data}
|
||||
)
|
||||
|
||||
self.log.info("new instance:: {}".format(json.dumps(new_instance.data, indent=4)))
|
||||
|
||||
def _parse_asset_build(self, name, version_regex):
|
||||
regex_result = version_regex.findall(name)
|
||||
asset_name = None # ??
|
||||
version_number = 1
|
||||
if regex_result:
|
||||
asset_name, version_number = regex_result[0]
|
||||
|
||||
return asset_name, version_number
|
||||
|
||||
def _parse_udim(self, name, udim_regex):
|
||||
regex_result = udim_regex.findall(name)
|
||||
udim = None
|
||||
if not regex_result:
|
||||
self.log.warning("Didn't find UDIM in {}".format(name))
|
||||
else:
|
||||
udim = re.sub("[^0-9]", '', regex_result[0])
|
||||
|
||||
return udim
|
||||
|
||||
def _get_color_space(self, name, color_spaces):
|
||||
"""Looks for color_space from a list in a file name."""
|
||||
color_space = None
|
||||
found = [cs for cs in color_spaces if
|
||||
re.search("_{}_".format(cs), name)]
|
||||
|
||||
if not found:
|
||||
self.log.warning("No color space found in {}".format(name))
|
||||
else:
|
||||
if len(found) > 1:
|
||||
msg = "Multiple color spaces found in {}->{}".format(name,
|
||||
found)
|
||||
self.log.warning(msg)
|
||||
|
||||
color_space = found[0]
|
||||
|
||||
return color_space
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
import pyblish.api
|
||||
import openpype.api
|
||||
|
||||
|
||||
class ValidateTextureBatch(pyblish.api.ContextPlugin):
|
||||
"""Validates that collected instnaces for Texture batch are OK.
|
||||
|
||||
Validates:
|
||||
some textures are present
|
||||
workfile has resource files (optional)
|
||||
texture version matches to workfile version
|
||||
"""
|
||||
|
||||
label = "Validate Texture Batch"
|
||||
hosts = ["standalonepublisher"]
|
||||
order = openpype.api.ValidateContentsOrder
|
||||
families = ["workfile", "textures"]
|
||||
|
||||
def process(self, context):
|
||||
|
||||
workfiles = []
|
||||
workfiles_in_textures = []
|
||||
for instance in context:
|
||||
if instance.data["family"] == "workfile":
|
||||
workfiles.append(instance.data["representations"][0]["files"])
|
||||
|
||||
if not instance.data.get("resources"):
|
||||
msg = "No resources for workfile {}".\
|
||||
format(instance.data["name"])
|
||||
self.log.warning(msg)
|
||||
|
||||
if instance.data["family"] == "textures":
|
||||
wfile = instance.data["versionData"]["workfile"]
|
||||
workfiles_in_textures.append(wfile)
|
||||
|
||||
version_str = "v{:03d}".format(instance.data["version"])
|
||||
assert version_str in wfile, \
|
||||
"Not matching version, texture {} - workfile {}".format(
|
||||
instance.data["version"], wfile
|
||||
)
|
||||
|
||||
msg = "Not matching set of workfiles and textures." + \
|
||||
"{} not equal to {}".format(set(workfiles),
|
||||
set(workfiles_in_textures)) +\
|
||||
"\nCheck that both workfile and textures are present"
|
||||
keys = set(workfiles) == set(workfiles_in_textures)
|
||||
assert keys, msg
|
||||
|
|
@ -105,16 +105,33 @@
|
|||
"label": "Render",
|
||||
"family": "render",
|
||||
"icon": "image",
|
||||
"defaults": ["Animation", "Lighting", "Lookdev", "Compositing"],
|
||||
"defaults": [
|
||||
"Animation",
|
||||
"Lighting",
|
||||
"Lookdev",
|
||||
"Compositing"
|
||||
],
|
||||
"help": "Rendered images or video files"
|
||||
},
|
||||
"create_mov_batch": {
|
||||
"name": "mov_batch",
|
||||
"label": "Batch Mov",
|
||||
"family": "render_mov_batch",
|
||||
"icon": "image",
|
||||
"defaults": ["Main"],
|
||||
"help": "Process multiple Mov files and publish them for layout and comp."
|
||||
"name": "mov_batch",
|
||||
"label": "Batch Mov",
|
||||
"family": "render_mov_batch",
|
||||
"icon": "image",
|
||||
"defaults": [
|
||||
"Main"
|
||||
],
|
||||
"help": "Process multiple Mov files and publish them for layout and comp."
|
||||
},
|
||||
"create_texture_batch": {
|
||||
"name": "texture_batch",
|
||||
"label": "Texture Batch",
|
||||
"family": "texture_batch",
|
||||
"icon": "image",
|
||||
"defaults": [
|
||||
"Main"
|
||||
],
|
||||
"help": "Texture files with UDIM together with worfile"
|
||||
},
|
||||
"__dynamic_keys_labels__": {
|
||||
"create_workfile": "Workfile",
|
||||
|
|
@ -127,7 +144,8 @@
|
|||
"create_image": "Image",
|
||||
"create_matchmove": "Matchmove",
|
||||
"create_render": "Render",
|
||||
"create_mov_batch": "Batch Mov"
|
||||
"create_mov_batch": "Batch Mov",
|
||||
"create_texture_batch": "Batch Texture"
|
||||
}
|
||||
},
|
||||
"publish": {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue