Merge branch 'fusion_integration' of https://github.com/BigRoy/colorbleed-config into fusion_integration

This commit is contained in:
Roy Nieterau 2018-02-12 15:41:11 +01:00
commit 2d3a25117f
8 changed files with 163 additions and 117 deletions

View file

@ -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

View file

@ -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

View file

@ -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))

View file

@ -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.")

View file

@ -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)

View file

@ -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

View file

@ -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)

View file

@ -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)