Merge pull request #3 from aardschok/fusion_integration

Fusion integration
This commit is contained in:
Roy Nieterau 2018-02-21 18:02:55 +01:00 committed by GitHub
commit ad9ce2fb0d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 765 additions and 34 deletions

View file

@ -36,15 +36,6 @@ class CollectInstances(pyblish.api.ContextPlugin):
from avalon.fusion.lib import get_frame_path
# Change family when submitting to Deadline
targets = pyblish.api.registered_targets()
if "deadline" in targets:
# Submit to Deadline
family = "fusion.deadline"
else:
# Render local
family = "fusion.local"
comp = context.data["currentComp"]
# Get all savers in the comp
@ -85,8 +76,8 @@ class CollectInstances(pyblish.api.ContextPlugin):
"outputDir": os.path.dirname(path),
"ext": ext, # todo: should be redundant
"label": label,
"families": [family],
"family": family,
"families": ["colorbleed.saver"],
"family": "colorbleed.saver",
"active": active,
"publish": active # backwards compatibility
})

View file

@ -0,0 +1,44 @@
import pyblish.api
class CollectFusionRenderMode(pyblish.api.InstancePlugin):
"""Collect current comp's render Mode
Options:
renderlocal
deadline
Note that this value is set for each comp separately. When you save the
comp this information will be stored in that file. If for some reason the
available tool does not visualize which render mode is set for the
current comp, please run the following line in the console (Py2)
comp.GetData("colorbleed.rendermode")
This will return the name of the current render mode as seen above under
Options.
"""
order = pyblish.api.CollectorOrder + 0.4
label = "Collect Render Mode"
hosts = ["fusion"]
families = ["colorbleed.saver"]
def process(self, instance):
"""Collect all image sequence tools"""
options = ["renderlocal", "deadline"]
comp = instance.context.data.get("currentComp")
if not comp:
raise RuntimeError("No comp previously collected, unable to "
"retrieve Fusion version.")
rendermode = comp.GetData("colorbleed.rendermode") or "renderlocal"
assert rendermode in options, "Must be supported render mode"
self.log.info("Render mode: {0}".format(rendermode))
# Append family
family = "colorbleed.saver.{0}".format(rendermode)
instance.data["families"].append(family)

View file

@ -1,7 +1,9 @@
import pyblish.api
import avalon.fusion as fusion
class ExtractImageSequence(pyblish.api.Extractor):
class ExtractImageSequence(pyblish.api.InstancePlugin):
"""Extract result of saver by starting a comp render
This will run the local render of Fusion.
@ -11,9 +13,18 @@ class ExtractImageSequence(pyblish.api.Extractor):
order = pyblish.api.ExtractorOrder
label = "Render Local"
hosts = ["fusion"]
targets = ["renderlocal"]
families = ["colorbleed.saver.renderlocal"]
def process(self, context):
def process(self, instance):
# This should be a ContextPlugin, but this is a workaround
# for a bug in pyblish to run once for a family: issue #250
context = instance.context
key = "__hasRun{}".format(self.__class__.__name__)
if context.data.get(key, False):
return
else:
context.data[key] = True
current_comp = context.data["currentComp"]
start_frame = current_comp.GetAttrs("COMPN_RenderStart")
@ -23,6 +34,8 @@ class ExtractImageSequence(pyblish.api.Extractor):
self.log.info("Start frame: {}".format(start_frame))
self.log.info("End frame: {}".format(end_frame))
result = current_comp.Render()
with fusion.comp_lock_and_undo_chunk(current_comp):
result = current_comp.Render()
if not result:
raise RuntimeError("Comp render failed")

View file

@ -11,7 +11,7 @@ class FusionIncrementCurrentFile(pyblish.api.ContextPlugin):
label = "Increment current file"
order = pyblish.api.IntegratorOrder + 9.0
hosts = ["fusion"]
families = ["colorbleed.saver"]
families = ["colorbleed.saver.deadline"]
optional = True
def process(self, context):

View file

@ -24,14 +24,13 @@ def _get_script():
return module_path
class PublishImageSequence(pyblish.api.Extractor):
class PublishImageSequence(pyblish.api.Integrator):
"""Publish the generated local image sequences."""
order = pyblish.api.ExtractorOrder + 0.1
order = pyblish.api.IntegratorOrder
label = "Publish Rendered Image Sequence(s)"
hosts = ["fusion"]
targets = ["renderlocal"]
families = ["fusion.local"]
families = ["colorbleed.saver.renderlocal"]
def process(self, instance):

View file

@ -5,7 +5,7 @@ class FusionSaveComp(pyblish.api.ContextPlugin):
"""Save current comp"""
label = "Save current file"
order = pyblish.api.IntegratorOrder - 0.49
order = pyblish.api.ExtractorOrder - 0.49
hosts = ["fusion"]
families = ["colorbleed.saver"]

View file

@ -8,7 +8,7 @@ from avalon.vendor import requests
import pyblish.api
class FusionSubmitDeadline(pyblish.api.ContextPlugin):
class FusionSubmitDeadline(pyblish.api.InstancePlugin):
"""Submit current Comp to Deadline
Renders are submitted to a Deadline Web Service as
@ -19,10 +19,17 @@ class FusionSubmitDeadline(pyblish.api.ContextPlugin):
label = "Submit to Deadline"
order = pyblish.api.IntegratorOrder
hosts = ["fusion"]
families = ["fusion.deadline"]
targets = ["deadline"]
families = ["colorbleed.saver.deadline"]
def process(self, context):
def process(self, instance):
context = instance.context
key = "__hasRun{}".format(self.__class__.__name__)
if context.data.get(key, False):
return
else:
context.data[key] = True
from avalon.fusion.lib import get_frame_path
@ -33,16 +40,19 @@ class FusionSubmitDeadline(pyblish.api.ContextPlugin):
# Collect all saver instances in context that are to be rendered
saver_instances = []
for instance in context[:]:
if instance.data.get("families")[0] != "fusion.deadline":
if not self.families[0] in instance.data.get("families"):
# Allow only saver family instances
continue
if not instance.data.get("publish", True):
# Skip inactive instances
continue
self.log.debug(instance.data["name"])
saver_instances.append(instance)
if not saver_instances:
raise RuntimeError("No instances found for Deadline submittion")
fusion_version = int(context.data["fusionVersion"])
filepath = context.data["currentFile"]
filename = os.path.basename(filepath)

View file

@ -10,7 +10,7 @@ class ValidateBackgroundDepth(pyblish.api.InstancePlugin):
label = "Validate Background Depth 32 bit"
actions = [action.RepairAction]
hosts = ["fusion"]
families = ["fusion.deadline", "fusion.local"]
families = ["colorbleed.saver"]
optional = True
@classmethod

View file

@ -8,7 +8,7 @@ class ValidateFusionCompSaved(pyblish.api.ContextPlugin):
order = pyblish.api.ValidatorOrder
label = "Validate Comp Saved"
families = ["fusion.deadline", "fusion.local"]
families = ["colorbleed.saver"]
hosts = ["fusion"]
def process(self, context):

View file

@ -13,7 +13,7 @@ class ValidateCreateFolderChecked(pyblish.api.InstancePlugin):
order = pyblish.api.ValidatorOrder
actions = [action.RepairAction]
label = "Validate Create Folder Checked"
families = ["fusion.deadline", "fusion.local"]
families = ["colorbleed.saver"]
hosts = ["fusion"]
@classmethod

View file

@ -14,7 +14,7 @@ class ValidateFilenameHasExtension(pyblish.api.InstancePlugin):
order = pyblish.api.ValidatorOrder
label = "Validate Filename Has Extension"
families = ["fusion.deadline", "fusion.local"]
families = ["colorbleed.saver"]
hosts = ["fusion"]
def process(self, instance):

View file

@ -6,7 +6,7 @@ class ValidateSaverPassthrough(pyblish.api.InstancePlugin):
order = pyblish.api.ValidatorOrder
label = "Validate Saver Active"
families = ["fusion.deadline", "fusion.local"]
families = ["colorbleed.saver"]
hosts = ["fusion"]
@classmethod

View file

@ -6,7 +6,7 @@ class ValidateUniqueSubsets(pyblish.api.InstancePlugin):
order = pyblish.api.ValidatorOrder
label = "Validate Unique Subsets"
families = ["fusion.deadline", "fusion.local"]
families = ["colorbleed.saver"]
hosts = ["fusion"]
@classmethod

View file

@ -55,7 +55,7 @@ class SubmitDependentImageSequenceJobDeadline(pyblish.api.InstancePlugin):
label = "Submit image sequence jobs to Deadline"
order = pyblish.api.IntegratorOrder + 0.1
hosts = ["fusion", "maya"]
families = ["fusion.deadline", "colorbleed.renderlayer"]
families = ["colorbleed.saver.deadline", "colorbleed.renderlayer"]
def process(self, instance):

View file

@ -0,0 +1,28 @@
class FusionLockComp(object):
def __init__(self, undoQueueName="Script CMD"):
# Lock flow
comp.Lock()
# Start undo event
comp.StartUndo(undoQueueName)
def __enter__(self):
return None
def __exit__(self, type, value, traceback):
comp.EndUndo(True)
comp.Unlock()
def f1():
with FusionLockComp('Selected Backgrounds to 32bit'):
toolsDict = comp.GetToolList(True)
if toolsDict:
for i, tool in toolsDict.items():
if tool.ID == "Background":
tool.Depth = 5
f1()

View file

@ -0,0 +1,28 @@
class FusionLockComp(object):
def __init__(self, undoQueueName="Script CMD"):
# Lock flow
comp.Lock()
# Start undo event
comp.StartUndo(undoQueueName)
def __enter__(self):
return None
def __exit__(self, type, value, traceback):
comp.EndUndo(True)
comp.Unlock()
def f1():
with FusionLockComp('Backgrounds to 32bit'):
toolsDict = comp.GetToolList(False)
if toolsDict:
for i, tool in toolsDict.items():
if tool.ID == "Background":
tool.Depth = 5
f1()

View file

@ -0,0 +1,28 @@
class FusionLockComp(object):
def __init__(self, undoQueueName="Script CMD"):
# Lock flow
comp.Lock()
# Start undo event
comp.StartUndo(undoQueueName)
def __enter__(self):
return None
def __exit__(self, type, value, traceback):
comp.EndUndo(True)
comp.Unlock()
def f1():
with FusionLockComp('Selected Loaders to 32bit'):
toolsDict = comp.GetToolList(True)
if toolsDict:
for i, tool in toolsDict.items():
if tool.ID == "Loader":
tool.Depth = 5
f1()

View file

@ -0,0 +1,28 @@
class FusionLockComp(object):
def __init__(self, undoQueueName="Script CMD"):
# Lock flow
comp.Lock()
# Start undo event
comp.StartUndo(undoQueueName)
def __enter__(self):
return None
def __exit__(self, type, value, traceback):
comp.EndUndo(True)
comp.Unlock()
def f1():
with FusionLockComp('Loaders to 32bit'):
toolsDict = comp.GetToolList(False)
if toolsDict:
for i, tool in toolsDict.items():
if tool.ID == "Loader":
tool.Depth = 5
f1()

View file

@ -0,0 +1,107 @@
------------------------------------------------------------
-- Change various options in Loadertools, Revision: 2.1
--
--
-- place in Fusion:\Scripts\Comp
--
-- written by Isaac Guenard (izyk@eyeonline.com) / Sean Konrad
-- created : January 24rd, 2005
-- modified by Eric Westphal (Eric@SirEdric.de), February 2007
------------------------------------------------------------
MissingFramesOpt = {"Do Not Change", "Fail", "Hold Previous", "Output Black", "Wait"}
DepthOpt={"Do Not Change", "Format", "Default", "int8", "int16", "float16", "float32"}
GeneralOpt={"Do Not Change", "Off", "On"}
HoldOpt={"Do Not Change", "Set to..."}
PixelOpt={"Do Not Change", "From File", "Default", "Custom (set below)"}
ret = comp.AskUser("SirEdric's Tweak-All-Loaders", {
{"AlphaSolid", "Dropdown", Options = GeneralOpt},
{"PostMultiply", "Dropdown", Options = GeneralOpt},
{"InvertAlpha", "Dropdown", Options = GeneralOpt},
{"MissingFrames", "Dropdown", Options = MissingFramesOpt},
{"Depth", "Dropdown", Options = DepthOpt},
{"PixelAspect", "Dropdown", Options = PixelOpt},
{"CustomPixelAspect", "Position", Default={1,1} },
{"HoldFirstOpt", Name="Hold First Frame", "Dropdown", Options = HoldOpt},
{"HoldFirst", Name = "Hold first Frame for", "Screw", Default = 0, Min = 0, Max=500, Integer = true},
{"HoldLastOpt", Name="Hold Last Frame", "Dropdown", Options = HoldOpt},
{"HoldLast", Name = "Hold first Frame for", "Screw", Default = 0, Min = 0, Max=500, Integer = true},
{"Selected", Name = "Affect Selected Tools Only", "Checkbox", Default = 0}
})
if ret then
composition:StartUndo("SE_LoaderTweaker")
MyPixX=ret.CustomPixelAspect[1]
MyPixY=ret.CustomPixelAspect[2]
print(MyPixX.."bb".. MyPixY)
print()
print("SE_LoaderTweaker is about to change...")
print("...AlphaSolid to ["..GeneralOpt[ret.AlphaSolid+1].."]")
print("...PostMultiply to ["..GeneralOpt[ret.PostMultiply+1].."]")
print("...InvertAlpha to ["..GeneralOpt[ret.InvertAlpha+1].."]")
print("...Missing Frames to [".. MissingFramesOpt[ret.MissingFrames + 1].."]")
print("...Depth to ["..DepthOpt[ret.Depth+1].."]")
print("...PixelAspect to ["..PixelOpt[ret.PixelAspect+1].."]")
print("...CustomPixelAspect(if selected): X="..MyPixX.." Y="..MyPixY)
print("...Hold First Frame to ["..HoldOpt[ret.HoldFirstOpt+1]..": " .. ret.HoldFirst.."]")
print("...Hold Last Frame to ["..HoldOpt[ret.HoldLastOpt+1]..": " .. ret.HoldLast.."]")
if ret.Selected then
print("...... *** on selected tools only! ***")
end
print("---------------------------------------------------")
print()
-- ((ret.Selected ==1)) will return true if the
-- selected checkbox is enabled.....
for i, v in composition:GetToolList((ret.Selected == 1)) do
id = v:GetAttrs().TOOLS_RegID
MyName = v:GetAttrs().TOOLS_Name
if id == "Loader" then
print("Changing "..MyName.." Options:")
if ret.AlphaSolid > 0 then -- check for 'DoNothing'
print("MakeAlphaSolid set to: "..(ret.AlphaSolid-1))
v.MakeAlphaSolid = (ret.AlphaSolid-1)
end
if ret.PostMultiply > 0 then -- check for 'DoNothing'
print("PostMultiplyByAlpha set to: "..(ret.PostMultiply-1))
v.PostMultiplyByAlpha = (ret.PostMultiply-1)
end
if ret.InvertAlpha > 0 then -- check for 'DoNothing'
print("InvertAlpha set to: "..(ret.InvertAlpha-1))
v.InvertAlpha = (ret.InvertAlpha-1)
end
if ret.MissingFrames >0 then -- check for 'DoNothing'
print("MissingFrames set to: "..(ret.MissingFrames-1))
v.MissingFrames = (ret.MissingFrames-1)
end
if ret.Depth >0 then -- check for 'DoNothing'
print("Depth set to: "..(ret.Depth-1))
v.Depth = (ret.Depth-1)
end
if ret.PixelAspect >0 then -- check for 'DoNothing'
print("PixelAspect set to: "..(ret.PixelAspect-1))
v.PixelAspect = (ret.PixelAspect-1)
if ret.PixelAspect == 3 then
v.CustomPixelAspect={MyPixX, MyPixY}
end
end
if ret.HoldFirstOpt >0 then -- check for 'DoNothing'
print("HoldFirstFrame set to: "..(ret.HoldFirst))
v.HoldFirstFrame = (ret.HoldFirst)
end
if ret.HoldLastOpt >0 then -- check for 'DoNothing'
print("HoldLastFrame set to: "..(ret.HoldLast))
v.HoldLastFrame = (ret.HoldLast)
end
print(v:GetAttrs().TOOLS_Name)
end
end
composition:EndUndo(true)
end
print()

View file

@ -0,0 +1,52 @@
class FusionLockComp(object):
def __init__(self, undoQueueName="Script CMD"):
# Lock flow
comp.Lock()
# Start undo event
comp.StartUndo(undoQueueName)
def __enter__(self):
return None
def __exit__(self, type, value, traceback):
comp.EndUndo(True)
comp.Unlock()
def pairs(n):
it = iter(n)
return zip(it, it)
def duplicateWithInputConnections():
with FusionLockComp("Duplicate With Input Connections"):
originalTools = comp.GetToolList(True)
if not originalTools:
return # nothing selected
comp.Copy()
comp.SetActiveTool()
comp.Paste()
duplicateTools = comp.GetToolList(True)
for i, tool in originalTools.iteritems():
dupToolInputs = duplicateTools[i].GetInputList()
for j, input in tool.GetInputList().iteritems():
if input.GetAttrs()['INPB_Connected']:
if j in dupToolInputs:
if dupToolInputs[j].GetAttrs()['INPB_Connected']:
print (" Both connected. ")
else:
dupToolInputs[j].ConnectTo(input.GetConnectedOutput())
if dupToolInputs[j].GetAttrs()['INPB_Connected']:
print (" Connection Successful ")
duplicateWithInputConnections()

View file

@ -0,0 +1,25 @@
class FusionLockComp(object):
def __init__(self, undoQueueName="Script CMD"):
# Lock flow
comp.Lock()
# Start undo event
comp.StartUndo(undoQueueName)
def __enter__(self):
return None
def __exit__(self, type, value, traceback):
comp.EndUndo(True)
comp.Unlock()
idList = set(["BrightnessContrast", "ColorCorrector"])
attrName = "PreDividePostMultiply"
with FusionLockComp("BC & CC set PreMultiplyPostDivide to 1"):
toolsDict = comp.GetToolList(False)
if toolsDict:
for i, tool in toolsDict.items():
if tool.ID in idList:
for input in tool.GetInputList().values():
setattr(tool, attrName, 1.0)

View file

@ -0,0 +1,107 @@
import os
import re
class FusionLockComp(object):
def __init__(self, undoQueueName="Script CMD"):
# Lock flow
comp.Lock()
# Start undo event
comp.StartUndo(undoQueueName)
def __enter__(self):
return None
def __exit__(self, type, value, traceback):
comp.EndUndo(True)
comp.Unlock()
def replaceStr(inputString, srchFor, srchTo, caseSensitive=True):
if caseSensitive:
return inputString.replace(srchFor, srchTo)
else:
regex = re.compile(re.escape(srchFor), re.IGNORECASE)
return regex.sub(srchTo, inputString)
def searchReplaceLoaderSavers():
userResponse = comp.AskUser("Repath All Loaders",
{1:{1:"Loaders", 2:"Checkbox", "Name":"Loaders", "NumAcross":3, "Default":1},
2:{1:"Savers", 2:"Checkbox", "Name":"Savers", "NumAcross":3, "Default":1},
3:{1:"Proxy", 2:"Checkbox", "Name":"Proxy", "NumAcross":3, "Default":1},
4:{1:"Source", 2:"Text", "Name":"Enter pattern to search for"},
5:{1:"Replacement", 2:"Text", "Name":"Enter the replacement path"},
6:{1:"Valid", 2:"Checkbox", "Name":"Check If New Path is Valid", "Default":1},
7:{1:"CaseSensitive", 2:"Checkbox", "Name":"Case Sensitive", "Default":1},
8:{1:"SelectedOnly", 2:"Checkbox", "Name":"Selected Only", "Default":0},
9:{1:"PreserveGlobalIn", 2:"Checkbox", "Name":"Preserve Global In Point", "Default":1}
}
)
if userResponse:
srchFor = userResponse['Source']
if not srchFor:
raise RuntimeError("No source string specified.")
srchTo = userResponse['Replacement']
if not srchTo:
raise RuntimeError("No replacement string specified.")
doLoaders = userResponse['Loaders']
doSavers = userResponse['Savers']
doProxy = userResponse['Proxy']
doValidate = userResponse['Valid']
doCaseSensitive = userResponse['CaseSensitive']
doSelectedOnly = bool(userResponse['SelectedOnly'])
doPreserveGlobalIn = bool(userResponse['PreserveGlobalIn'])
with FusionLockComp('Path Remap - "{0}" to "{1}"'.format(srchFor, srchTo)):
toolsDict = comp.GetToolList(doSelectedOnly)
for i, tool in toolsDict.items():
toolId = tool.ID
if toolId == "Loader" or toolId == "Saver":
tool_a = tool.GetAttrs()
if (doLoaders or doProxy) and toolId == "Loader":
clipTable = tool_a['TOOLST_Clip_Name']
altclipTable = tool_a['TOOLST_AltClip_Name']
startTime = tool_a['TOOLNT_Clip_Start']
if doPreserveGlobalIn:
oldGlobalIn = tool.GlobalIn[comp.CurrentTime]
if doLoaders:
for n, name in clipTable.items():
#for i in table.getn(clipTable):
if name:
newPath = replaceStr(name, srchFor, srchTo, doCaseSensitive)
print (name, newPath)
if not doValidate or os.path.exists(comp.MapPath(newPath)):
tool.Clip[startTime[n]] = newPath
else:
print( "FAILED : New clip does not exist; skipping sequence.\n {0} .. {1}".format(name, newPath))
if doProxy:
for n, name in altclipTable.items():
if name:
newPath = replaceStr(name, srchFor, srchTo, doCaseSensitive)
if not doValidate or os.path.exists(comp.MapPath(newPath)):
tool.ProxyFilename[startTime[n]] = newPath
else:
print( "FAILED : New proxy clip does not exist; skipping sequence.\n {0} .. {1}".format(name, newPath))
if doPreserveGlobalIn:
tool.GlobalIn[comp.CurrentTime] = oldGlobalIn
if doSavers and toolId == "Saver":
for i, name in tool_a['TOOLST_Clip_Name'].items():
newPath = replaceStr(name, srchFor, srchTo, doCaseSensitive)
if not doValidate or os.path.exists(os.path.dirname(comp.MapPath(newPath))):
tool.Clip[comp. ] = newPath
else:
print( "FAILED : Output directory does not exist; skipping saver.\n {0} .. {1}".format(name, newPath))
searchReplaceLoaderSavers()

View file

@ -0,0 +1,96 @@
import os
import re
class FusionLockComp(object):
def __init__(self, undoQueueName="Script CMD"):
# Lock flow
comp.Lock()
# Start undo event
comp.StartUndo(undoQueueName)
def __enter__(self):
return None
def __exit__(self, type, value, traceback):
comp.EndUndo(True)
comp.Unlock()
def makeRelativePath(root, path):
try:
return "Comp:\{0}".format(os.path.relpath(os.path.abspath(fusion.MapPath(path)), root))
except ValueError:
print("Warning -- Can't define relative path for: {0}".format(path))
return path
def pathToCurrentComp():
return comp.GetAttrs()["COMPS_FileName"]
def cbRelativePaths():
userResponse = comp.AskUser("Make paths relative",
{
1:{1:"Loaders", 2:"Checkbox", "Name":"Loaders", "NumAcross":3, "Default":1},
2:{1:"Savers", 2:"Checkbox", "Name":"Savers", "NumAcross":3, "Default":1},
3:{1:"Proxy", 2:"Checkbox", "Name":"Proxy", "NumAcross":3, "Default":1},
4:{1:"SelectedOnly", 2:"Checkbox", "Name":"Selected Only", "Default":0}
}
)
if userResponse:
root = pathToCurrentComp()
if not root:
raise RuntimeError("Fusion file has not been saved. Can't make paths relative")
if root:
root = os.path.dirname(root)
# set root
os.chdir(root)
doLoaders = userResponse['Loaders']
doSavers = userResponse['Savers']
doProxy = userResponse['Proxy']
doSelectedOnly = bool(userResponse['SelectedOnly'])
with FusionLockComp('Make paths relative'):
toolsDict = comp.GetToolList(doSelectedOnly)
for i, tool in toolsDict.items():
toolId = tool.ID
if toolId == "Loader" or toolId == "Saver":
tool_a = tool.GetAttrs()
if (doLoaders or doProxy) and toolId == "Loader":
clipTable = tool_a['TOOLST_Clip_Name']
altclipTable = tool_a['TOOLST_AltClip_Name']
startTime = tool_a['TOOLNT_Clip_Start']
# Preserve global in
oldGlobalIn = tool.GlobalIn[comp.CurrentTime]
if doLoaders:
for n, name in clipTable.items():
if name:
newPath = makeRelativePath(root, name)
tool.Clip[startTime[n]] = newPath
if doProxy:
for n, name in altclipTable.items():
if name:
newPath = makeRelativePath(root, name)
tool.ProxyFilename[startTime[n]] = newPath
# Set global in (to what we preserved)
tool.GlobalIn[comp.CurrentTime] = oldGlobalIn
if doSavers and toolId == "Saver":
for i, name in tool_a['TOOLST_Clip_Name'].items():
if name:
newPath = makeRelativePath(root, name)
tool.Clip[comp.TIME_UNDEFINED] = newPath
cbRelativePaths()

View file

@ -0,0 +1,138 @@
import os
from avalon.vendor.Qt import QtCore, QtWidgets
from avalon.vendor import qtawesome
import avalon.fusion as avalon
_help = {"renderlocal": "Render the comp on your own machine and publish "
"it from that the destination folder",
"deadline": "Submit a Fusion render job to Deadline to use all other "
"computers and add a publish job"}
class SetRenderMode(QtWidgets.QWidget):
def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent)
self._comp = avalon.get_current_comp()
self._comp_name = self._get_comp_name()
self.setWindowTitle("Set Render Mode - {}".format(self._comp_name))
self.resize(300, 150)
self.setFixedSize(300, 150)
layout = QtWidgets.QVBoxLayout()
# region comp info
comp_info_layout = QtWidgets.QHBoxLayout()
update_btn = QtWidgets.QPushButton(qtawesome.icon("fa.refresh"), "")
update_btn.setFixedWidth(25)
update_btn.setFixedHeight(25)
comp_information = QtWidgets.QLineEdit()
comp_information.setEnabled(False)
comp_info_layout.addWidget(comp_information)
comp_info_layout.addWidget(update_btn)
# endregion comp info
# region modes
mode_options = QtWidgets.QComboBox()
mode_options.addItems(_help.keys())
mode_information = QtWidgets.QTextEdit()
mode_information.setEnabled(False)
# endregion modes
accept_layout = QtWidgets.QHBoxLayout()
accept_btn = QtWidgets.QPushButton("Accept")
validation_state = QtWidgets.QPushButton()
validation_state.setFixedHeight(15)
validation_state.setFixedWidth(15)
validation_state.setEnabled(False)
validation_state.setStyleSheet("background-color: green")
accept_layout.addWidget(accept_btn)
accept_layout.addWidget(validation_state)
layout.addLayout(comp_info_layout)
layout.addWidget(mode_options)
layout.addWidget(mode_information)
layout.addLayout(accept_layout)
self.setLayout(layout)
self.comp_information = comp_information
self.update_btn = update_btn
self.mode_options = mode_options
self.mode_information = mode_information
self.accept_btn = accept_btn
self.validation = validation_state
self.connections()
self.update()
def connections(self):
"""Build connections between code and buttons"""
self.update_btn.clicked.connect(self.update)
self.accept_btn.clicked.connect(self._set_comp_rendermode)
self.mode_options.currentIndexChanged.connect(
self._update_rendermode_info)
def update(self):
"""Update all information in the UI"""
self._comp = avalon.get_current_comp()
self._comp_name = self._get_comp_name()
self.setWindowTitle("Set Render Mode")
self.comp_information.setText(self._comp_name)
self._update_rendermode_info()
def _update_rendermode_info(self):
rendermode = self._get_comp_rendermode()
if rendermode is None:
rendermode = "renderlocal"
self.mode_information.setText(_help[rendermode])
def _get_comp_name(self):
return os.path.basename(self._comp.GetAttrs("COMPS_FileName"))
def _get_comp_rendermode(self):
return self._comp.GetData("colorbleed.rendermode")
def _set_comp_rendermode(self):
rendermode = self.mode_options.currentText()
self._comp.SetData("colorbleed.rendermode", rendermode)
# Validate the rendermode has been updated correctly
if not self._validation():
self.validation.setStyleSheet("background-color: red")
raise AssertionError("Rendermode in UI is not render mode in comp: "
"%s" % self._comp_name)
print("Updated render mode for %s to %s" % (self._comp_name, rendermode))
def _validation(self):
ui_mode = self.mode_options.currentText()
comp_mode = self._get_comp_rendermode()
return comp_mode == ui_mode
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = SetRenderMode()
w.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,37 @@
class FusionLockComp(object):
def __init__(self, undoQueueName="Script CMD"):
# Lock flow
comp.Lock()
# Start undo event
comp.StartUndo(undoQueueName)
def __enter__(self):
return None
def __exit__(self, type, value, traceback):
comp.EndUndo(True)
comp.Unlock()
with FusionLockComp("Reload clip time ranges"):
toolsDict = comp.GetToolList(True)
if toolsDict:
for i, tool in toolsDict.items():
if tool.ID != "Loader":
continue
tool_a = tool.GetAttrs()
clipTable = tool_a['TOOLST_Clip_Name']
altclipTable = tool_a['TOOLST_AltClip_Name']
startTime = tool_a['TOOLNT_Clip_Start']
oldGlobalIn = tool.GlobalIn[comp.CurrentTime]
for n, c in clipTable.items():
tool.Clip[startTime[n]] = tool.Clip[startTime[n]]
for n, c in altclipTable.items():
tool.ProxyFilename[startTime[n]] = tool.ProxyFilename[startTime[n]]
tool.GlobalIn[comp.CurrentTime] = oldGlobalIn