mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-25 21:32:15 +01:00
Merge branch 'fusion_integration' of https://github.com/BigRoy/colorbleed-config into fusion_integration
This commit is contained in:
commit
2d3a25117f
8 changed files with 163 additions and 117 deletions
|
|
@ -1,7 +1,5 @@
|
|||
# absolute_import is needed to counter the `module has no cmds error` in Maya
|
||||
from __future__ import absolute_import
|
||||
|
||||
from maya import cmds
|
||||
import pyblish.api
|
||||
|
||||
|
||||
|
|
@ -104,6 +102,11 @@ class SelectInvalidAction(pyblish.api.Action):
|
|||
|
||||
def process(self, context, plugin):
|
||||
|
||||
try:
|
||||
from maya import cmds
|
||||
except ImportError:
|
||||
raise ImportError("Current host is not Maya")
|
||||
|
||||
errored_instances = get_errored_instances_from_context(context)
|
||||
|
||||
# Apply pyblish.logic to get the instances for the plug-in
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import os
|
||||
|
||||
import avalon.api
|
||||
from avalon import fusion
|
||||
|
||||
|
|
@ -6,15 +8,39 @@ class CreateTiffSaver(avalon.api.Creator):
|
|||
|
||||
name = "tiffDefault"
|
||||
label = "Create Tiff Saver"
|
||||
family = "colorbleed.imagesequence"
|
||||
hosts = ["fusion"]
|
||||
family = "colorbleed.saver"
|
||||
|
||||
def process(self):
|
||||
|
||||
file_format = "TiffFormat"
|
||||
|
||||
comp = fusion.get_current_comp()
|
||||
|
||||
# todo: improve method of getting current environment
|
||||
# todo: pref avalon.Session over os.environ
|
||||
|
||||
workdir = os.path.normpath(os.environ["AVALON_WORKDIR"])
|
||||
|
||||
filename = "{}..tiff".format(self.name)
|
||||
filepath = os.path.join(workdir, "render", "preview", filename)
|
||||
|
||||
with fusion.comp_lock_and_undo_chunk(comp):
|
||||
args = (-32768, -32768) # Magical position numbers
|
||||
saver = comp.AddTool("Saver", *args)
|
||||
saver.SetAttrs({
|
||||
"TOOLS_Name": self.data.get("name", self.name),
|
||||
'TOOLST_Clip_FormatID': {1.0: 'TiffFormat'},
|
||||
})
|
||||
saver.SetAttrs({"TOOLS_Name": self.name})
|
||||
|
||||
# Setting input attributes is different from basic attributes
|
||||
# Not confused with "MainInputAttributes" which
|
||||
saver["Clip"] = filepath
|
||||
saver["OutputFormat"] = file_format
|
||||
|
||||
# # # Set standard TIFF settings
|
||||
if saver[file_format] is None:
|
||||
raise RuntimeError("File format is not set to TiffFormat, "
|
||||
"this is a bug")
|
||||
|
||||
# Set file format attributes
|
||||
saver[file_format]["Depth"] = 1 # int8 | int16 | float32 | other
|
||||
saver[file_format]["SaveAlpha"] = 0
|
||||
|
||||
|
|
|
|||
|
|
@ -1,52 +0,0 @@
|
|||
import os
|
||||
|
||||
import pyblish.api
|
||||
|
||||
|
||||
class ValidateFileNames(pyblish.api.Validator):
|
||||
"""Ensure all file names follow the same structure
|
||||
|
||||
Filename should have identifiable parts:
|
||||
- name ( example: Avengers_shot010_preview )
|
||||
- frame ( example: #### )
|
||||
- extension ( example: tiff )
|
||||
|
||||
The result when rendering frame 1250 would be as follows:
|
||||
Avengers_shot010_preview.1250.tiff
|
||||
|
||||
When certain parts need to be rendered out separately for some reason it
|
||||
is advisable to something all the lines of:
|
||||
Avengers_shot010_character_beauty.1250.tiff
|
||||
"""
|
||||
|
||||
order = pyblish.api.ValidatorOrder
|
||||
label = "Validate File Names (Saver)"
|
||||
families = ["colorbleed.imagesequence"]
|
||||
hosts = ["fusion"]
|
||||
|
||||
@classmethod
|
||||
def get_invalid(cls, instance):
|
||||
|
||||
invalid = []
|
||||
|
||||
path = instance.data["path"]
|
||||
basename = os.path.basename(path)
|
||||
|
||||
parts = basename.split(".")
|
||||
if len(parts) != 3:
|
||||
invalid.append(instance)
|
||||
cls.log.error("%s has %i parts, should be 3"
|
||||
% (instance, len(parts)))
|
||||
else:
|
||||
is_numbers = all(i.isdigit() for i in parts[1])
|
||||
if len(parts[1]) != 4 or not is_numbers:
|
||||
cls.log.error("Number padding is not four digits")
|
||||
invalid.append(instance)
|
||||
|
||||
return invalid
|
||||
|
||||
def process(self, instance):
|
||||
invalid = self.get_invalid(instance)
|
||||
if invalid:
|
||||
raise RuntimeError("Found %i instances with a wrong file name "
|
||||
"structure" % len(invalid))
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
import pyblish.api
|
||||
|
||||
|
||||
class ValidateFrameRange(pyblish.api.InstancePlugin):
|
||||
"""Validate the frame range of the current Saver"""
|
||||
|
||||
order = pyblish.api.ValidatorOrder
|
||||
label = "Validate Frame Range"
|
||||
families = ["colorbleed.imagesequence"]
|
||||
hosts = ["fusion"]
|
||||
|
||||
@classmethod
|
||||
def get_invalid(cls, instance):
|
||||
return []
|
||||
|
||||
def process(self, instance):
|
||||
invalid = self.get_invalid(instance)
|
||||
if invalid:
|
||||
raise RuntimeError("Animation content is invalid. See log.")
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
import os
|
||||
import re
|
||||
|
||||
import pyblish.api
|
||||
|
||||
|
|
@ -35,6 +34,8 @@ class CollectInstances(pyblish.api.ContextPlugin):
|
|||
def process(self, context):
|
||||
"""Collect all image sequence tools"""
|
||||
|
||||
from avalon.fusion.lib import get_frame_path
|
||||
|
||||
comp = context.data["currentComp"]
|
||||
|
||||
# Get all savers in the comp
|
||||
|
|
@ -56,7 +57,6 @@ class CollectInstances(pyblish.api.ContextPlugin):
|
|||
"has no path set: {}".format(tool.Name))
|
||||
continue
|
||||
|
||||
from avalon.fusion.lib import get_frame_path
|
||||
filename = os.path.basename(path)
|
||||
head, padding, tail = get_frame_path(filename)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,27 @@
|
|||
import os
|
||||
import glob
|
||||
import re
|
||||
|
||||
import pyblish.api
|
||||
|
||||
_frame_regex = re.compile("[0-9]")
|
||||
from avalon.vendor import clique
|
||||
|
||||
|
||||
def get_collection_for_instance(subset, collections):
|
||||
"""Get the collection which matches the subset name
|
||||
|
||||
Args:
|
||||
subset (str): name of the subset
|
||||
collections (clique.Collection):
|
||||
|
||||
Returns:
|
||||
list
|
||||
"""
|
||||
for collection in collections:
|
||||
name = collection.head
|
||||
if name[-1] == ".":
|
||||
name = name[:-1]
|
||||
|
||||
if name == subset:
|
||||
return collection
|
||||
|
||||
|
||||
class ExtractImageSequence(pyblish.api.Extractor):
|
||||
|
|
@ -14,7 +31,7 @@ class ExtractImageSequence(pyblish.api.Extractor):
|
|||
"""
|
||||
|
||||
order = pyblish.api.ExtractorOrder
|
||||
label = "Extract Image Sequence"
|
||||
label = "Extract Image Sequence (Local)"
|
||||
families = ["colorbleed.imagesequence"]
|
||||
hosts = ["fusion"]
|
||||
|
||||
|
|
@ -37,44 +54,34 @@ class ExtractImageSequence(pyblish.api.Extractor):
|
|||
|
||||
# Get all output paths after render was successful
|
||||
# Note the .ID check, this is to ensure we only have savers
|
||||
# Use instance[0] to get the tool
|
||||
instances = [i for i in context[:] if i[0].ID == "Saver"]
|
||||
for instance in instances:
|
||||
# Ensure each instance has its files for the integrator
|
||||
output_path = instance.data["path"]
|
||||
query = self._create_qeury(output_path)
|
||||
files = glob.glob(query)
|
||||
|
||||
# Ensure each instance has its files for the integrator
|
||||
output_path = os.path.dirname(instance.data["path"])
|
||||
files = os.listdir(output_path)
|
||||
pattern = clique.PATTERNS["frames"]
|
||||
collections, remainder = clique.assemble(files,
|
||||
patterns=[pattern],
|
||||
minimum_items=1)
|
||||
|
||||
assert not remainder, ("There shouldn't have been a remainder "
|
||||
"for '%s': %s" %
|
||||
(instance.data["subset"],
|
||||
remainder))
|
||||
|
||||
# Filter collections to ensure specific files are part of
|
||||
# the instance, store instance's collection
|
||||
if "files" not in instance.data:
|
||||
instance.data["files"] = list()
|
||||
|
||||
print("{} files : {}".format(instance.data["subset"],
|
||||
len(files)))
|
||||
instance.data["files"].append(files)
|
||||
subset = instance.data["subset"]
|
||||
collection = get_collection_for_instance(subset, collections)
|
||||
assert collection, "No collection found, this is a bug"
|
||||
|
||||
# Add found collection to the instance
|
||||
instance.data["files"].append(list(collection))
|
||||
|
||||
# Ensure the integrator has stagingDir
|
||||
instance.data["stagingDir"] = os.path.dirname(output_path)
|
||||
|
||||
def _create_qeury(self, instance):
|
||||
"""Create a queriable string for glob
|
||||
|
||||
Args:
|
||||
instance: instance of current context (comp)
|
||||
|
||||
Returns:
|
||||
str
|
||||
"""
|
||||
|
||||
clipname = instance.data["path"]
|
||||
clip_dir = os.path.dirname(clipname)
|
||||
basename = os.path.basename(clipname)
|
||||
_, ext = os.path.splitext(basename)
|
||||
|
||||
match = re.match("([0-9]{4})", basename)
|
||||
if not match:
|
||||
query_name = "{}.*.{}".format(instance.data["subset"], ext[1:])
|
||||
else:
|
||||
query_name = basename.replace(match.group(0), ".*.")
|
||||
|
||||
query = os.path.join(clip_dir, query_name)
|
||||
|
||||
return query
|
||||
instance.data["stagingDir"] = output_path
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
import pyblish.api
|
||||
|
||||
from colorbleed import action
|
||||
|
||||
|
||||
class ValidateBackgroundDepth(pyblish.api.InstancePlugin):
|
||||
"""Validate if all Background tool are set to float32 bit"""
|
||||
|
||||
order = pyblish.api.ValidatorOrder
|
||||
label = "Validate Background Depth 32 bit"
|
||||
actions = [action.RepairAction]
|
||||
hosts = ["fusion"]
|
||||
families = ["*"]
|
||||
optional = True
|
||||
|
||||
@classmethod
|
||||
def get_invalid(cls, instance):
|
||||
|
||||
context = instance.context
|
||||
comp = context.data.get("currentComp")
|
||||
assert comp, "Must have Comp object"
|
||||
|
||||
backgrounds = comp.GetToolList(False, "Background").values()
|
||||
if not backgrounds:
|
||||
return []
|
||||
|
||||
return [i for i in backgrounds if i.GetInput("Depth") != 4.0]
|
||||
|
||||
def process(self, instance):
|
||||
invalid = self.get_invalid(instance)
|
||||
if invalid:
|
||||
raise RuntimeError("Found %i nodes which are not set to float32"
|
||||
% len(invalid))
|
||||
|
||||
@classmethod
|
||||
def repair(cls, instance):
|
||||
comp = instance.context.data.get("currentComp")
|
||||
invalid = cls.get_invalid(instance)
|
||||
for i in invalid:
|
||||
i.SetInput("Depth", 4.0, comp.TIME_UNDEFINED)
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
import pyblish.api
|
||||
|
||||
from colorbleed import action
|
||||
|
||||
|
||||
class ValidateCreateFolderChecked(pyblish.api.InstancePlugin):
|
||||
"""Valid if all savers have the input attribute CreateDir checked on
|
||||
|
||||
This attribute ensures that the folders to which the saver will write
|
||||
will be created.
|
||||
"""
|
||||
|
||||
order = pyblish.api.ValidatorOrder
|
||||
actions = [action.RepairAction]
|
||||
label = "Validate Create Folder Checked"
|
||||
family = "colorbleed.saver"
|
||||
hosts = ["fusion"]
|
||||
|
||||
@classmethod
|
||||
def get_invalid(cls, instance):
|
||||
active = instance.data.get("active", instance.data.get("publish"))
|
||||
if not active:
|
||||
return []
|
||||
|
||||
tool = instance[0]
|
||||
create_dir = tool.GetInput("CreateDir")
|
||||
if create_dir == 0.0:
|
||||
cls.log.error("%s has Create Folder turned off" % instance[0].Name)
|
||||
return [tool]
|
||||
|
||||
def process(self, instance):
|
||||
invalid = self.get_invalid(instance)
|
||||
if invalid:
|
||||
raise RuntimeError("Found Saver with Create Folder During "
|
||||
"Render checked off")
|
||||
|
||||
@classmethod
|
||||
def repair(cls, instance):
|
||||
invalid = cls.get_invalid(instance)
|
||||
for tool in invalid:
|
||||
tool.SetInput("CreateDir", 1.0)
|
||||
Loading…
Add table
Add a link
Reference in a new issue