diff --git a/colorbleed/plugins/fusion/publish/collect_instances.py b/colorbleed/plugins/fusion/publish/collect_instances.py index 98425f6672..322197fc87 100644 --- a/colorbleed/plugins/fusion/publish/collect_instances.py +++ b/colorbleed/plugins/fusion/publish/collect_instances.py @@ -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 }) diff --git a/colorbleed/plugins/fusion/publish/collect_render_target.py b/colorbleed/plugins/fusion/publish/collect_render_target.py new file mode 100644 index 0000000000..a9193eaee5 --- /dev/null +++ b/colorbleed/plugins/fusion/publish/collect_render_target.py @@ -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) diff --git a/colorbleed/plugins/fusion/publish/extract_image_sequence.py b/colorbleed/plugins/fusion/publish/extract_image_sequence.py index 272daa4371..bdb2d8fbf2 100644 --- a/colorbleed/plugins/fusion/publish/extract_image_sequence.py +++ b/colorbleed/plugins/fusion/publish/extract_image_sequence.py @@ -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") diff --git a/colorbleed/plugins/fusion/publish/increment_current_file_deadline.py b/colorbleed/plugins/fusion/publish/increment_current_file_deadline.py index 91589699c5..9d766c426c 100644 --- a/colorbleed/plugins/fusion/publish/increment_current_file_deadline.py +++ b/colorbleed/plugins/fusion/publish/increment_current_file_deadline.py @@ -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): diff --git a/colorbleed/plugins/fusion/publish/publish_image_sequences.py b/colorbleed/plugins/fusion/publish/publish_image_sequences.py index 23495517f3..cd0835b3ce 100644 --- a/colorbleed/plugins/fusion/publish/publish_image_sequences.py +++ b/colorbleed/plugins/fusion/publish/publish_image_sequences.py @@ -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): diff --git a/colorbleed/plugins/fusion/publish/save_scene.py b/colorbleed/plugins/fusion/publish/save_scene.py index cc302d684e..e88b8ba769 100644 --- a/colorbleed/plugins/fusion/publish/save_scene.py +++ b/colorbleed/plugins/fusion/publish/save_scene.py @@ -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"] diff --git a/colorbleed/plugins/fusion/publish/submit_deadline.py b/colorbleed/plugins/fusion/publish/submit_deadline.py index b1f3fdb4ad..5afb484e50 100644 --- a/colorbleed/plugins/fusion/publish/submit_deadline.py +++ b/colorbleed/plugins/fusion/publish/submit_deadline.py @@ -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) diff --git a/colorbleed/plugins/fusion/publish/validate_background_depth.py b/colorbleed/plugins/fusion/publish/validate_background_depth.py index 6173fd836a..abf5dd248e 100644 --- a/colorbleed/plugins/fusion/publish/validate_background_depth.py +++ b/colorbleed/plugins/fusion/publish/validate_background_depth.py @@ -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 diff --git a/colorbleed/plugins/fusion/publish/validate_comp_saved.py b/colorbleed/plugins/fusion/publish/validate_comp_saved.py index 741171ba10..18621ceb4f 100644 --- a/colorbleed/plugins/fusion/publish/validate_comp_saved.py +++ b/colorbleed/plugins/fusion/publish/validate_comp_saved.py @@ -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): diff --git a/colorbleed/plugins/fusion/publish/validate_create_folder_checked.py b/colorbleed/plugins/fusion/publish/validate_create_folder_checked.py index 3aa2552651..7a10b1e538 100644 --- a/colorbleed/plugins/fusion/publish/validate_create_folder_checked.py +++ b/colorbleed/plugins/fusion/publish/validate_create_folder_checked.py @@ -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 diff --git a/colorbleed/plugins/fusion/publish/validate_filename_has_extension.py b/colorbleed/plugins/fusion/publish/validate_filename_has_extension.py index 6e6c1423d2..b7fe1f4c31 100644 --- a/colorbleed/plugins/fusion/publish/validate_filename_has_extension.py +++ b/colorbleed/plugins/fusion/publish/validate_filename_has_extension.py @@ -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): diff --git a/colorbleed/plugins/fusion/publish/validate_saver_passthrough.py b/colorbleed/plugins/fusion/publish/validate_saver_passthrough.py index c2f910f642..4380f4e380 100644 --- a/colorbleed/plugins/fusion/publish/validate_saver_passthrough.py +++ b/colorbleed/plugins/fusion/publish/validate_saver_passthrough.py @@ -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 diff --git a/colorbleed/plugins/fusion/publish/validate_unique_subsets.py b/colorbleed/plugins/fusion/publish/validate_unique_subsets.py index a60304efcf..527b4acc69 100644 --- a/colorbleed/plugins/fusion/publish/validate_unique_subsets.py +++ b/colorbleed/plugins/fusion/publish/validate_unique_subsets.py @@ -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 diff --git a/colorbleed/plugins/publish/submit_publish_job.py b/colorbleed/plugins/publish/submit_publish_job.py index dda7600f58..c13f7e3dce 100644 --- a/colorbleed/plugins/publish/submit_publish_job.py +++ b/colorbleed/plugins/publish/submit_publish_job.py @@ -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): diff --git a/setup/fusion/scripts/Comp/colorbleed/32bit/backgrounds_selected_to32bit.py b/setup/fusion/scripts/Comp/colorbleed/32bit/backgrounds_selected_to32bit.py new file mode 100644 index 0000000000..16fc2a61af --- /dev/null +++ b/setup/fusion/scripts/Comp/colorbleed/32bit/backgrounds_selected_to32bit.py @@ -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() + + \ No newline at end of file diff --git a/setup/fusion/scripts/Comp/colorbleed/32bit/backgrounds_to32bit.py b/setup/fusion/scripts/Comp/colorbleed/32bit/backgrounds_to32bit.py new file mode 100644 index 0000000000..60d558a8cb --- /dev/null +++ b/setup/fusion/scripts/Comp/colorbleed/32bit/backgrounds_to32bit.py @@ -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() + + \ No newline at end of file diff --git a/setup/fusion/scripts/Comp/colorbleed/32bit/loaders_selected_to32bit.py b/setup/fusion/scripts/Comp/colorbleed/32bit/loaders_selected_to32bit.py new file mode 100644 index 0000000000..74c5ca00f7 --- /dev/null +++ b/setup/fusion/scripts/Comp/colorbleed/32bit/loaders_selected_to32bit.py @@ -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() + + \ No newline at end of file diff --git a/setup/fusion/scripts/Comp/colorbleed/32bit/loaders_to32bit.py b/setup/fusion/scripts/Comp/colorbleed/32bit/loaders_to32bit.py new file mode 100644 index 0000000000..edfeffaa75 --- /dev/null +++ b/setup/fusion/scripts/Comp/colorbleed/32bit/loaders_to32bit.py @@ -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() + + \ No newline at end of file diff --git a/setup/fusion/scripts/Comp/colorbleed/SE_LoaderTweaker.lua b/setup/fusion/scripts/Comp/colorbleed/SE_LoaderTweaker.lua new file mode 100644 index 0000000000..0d54536d7d --- /dev/null +++ b/setup/fusion/scripts/Comp/colorbleed/SE_LoaderTweaker.lua @@ -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() diff --git a/setup/fusion/scripts/Comp/colorbleed/duplicate_with_input_connections.py b/setup/fusion/scripts/Comp/colorbleed/duplicate_with_input_connections.py new file mode 100644 index 0000000000..1e53e213c1 --- /dev/null +++ b/setup/fusion/scripts/Comp/colorbleed/duplicate_with_input_connections.py @@ -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() + + \ No newline at end of file diff --git a/setup/fusion/scripts/Comp/colorbleed/predivide_postmultiply_BC_and_CC.py b/setup/fusion/scripts/Comp/colorbleed/predivide_postmultiply_BC_and_CC.py new file mode 100644 index 0000000000..9834625109 --- /dev/null +++ b/setup/fusion/scripts/Comp/colorbleed/predivide_postmultiply_BC_and_CC.py @@ -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) \ No newline at end of file diff --git a/setup/fusion/scripts/Comp/colorbleed/search_replace_paths.py b/setup/fusion/scripts/Comp/colorbleed/search_replace_paths.py new file mode 100644 index 0000000000..7fdfb6e388 --- /dev/null +++ b/setup/fusion/scripts/Comp/colorbleed/search_replace_paths.py @@ -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() + + \ No newline at end of file diff --git a/setup/fusion/scripts/Comp/colorbleed/set_relative_paths.py b/setup/fusion/scripts/Comp/colorbleed/set_relative_paths.py new file mode 100644 index 0000000000..d3a011162b --- /dev/null +++ b/setup/fusion/scripts/Comp/colorbleed/set_relative_paths.py @@ -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() + + \ No newline at end of file diff --git a/setup/fusion/scripts/Comp/colorbleed/set_rendermode.py b/setup/fusion/scripts/Comp/colorbleed/set_rendermode.py new file mode 100644 index 0000000000..1ab523ce3e --- /dev/null +++ b/setup/fusion/scripts/Comp/colorbleed/set_rendermode.py @@ -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_()) diff --git a/setup/fusion/scripts/Comp/colorbleed/update_selected_loader_ranges.py b/setup/fusion/scripts/Comp/colorbleed/update_selected_loader_ranges.py new file mode 100644 index 0000000000..7d0a4b25a8 --- /dev/null +++ b/setup/fusion/scripts/Comp/colorbleed/update_selected_loader_ranges.py @@ -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