From 229d28a590d1b6d95639ecbf33fbcf84cd720f50 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 30 Oct 2020 10:50:55 +0100 Subject: [PATCH 01/12] add camera name to representation in extract playblast --- pype/plugins/maya/publish/extract_playblast.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pype/plugins/maya/publish/extract_playblast.py b/pype/plugins/maya/publish/extract_playblast.py index 8f8b7fcb36..fc80e74be0 100644 --- a/pype/plugins/maya/publish/extract_playblast.py +++ b/pype/plugins/maya/publish/extract_playblast.py @@ -110,6 +110,9 @@ class ExtractPlayblast(pype.api.Extractor): if not instance.data.get("keepImages"): tags.append("delete") + # Add camera node name to representation data + camera_node_name = pm.ls(camera)[0].nodeName() + representation = { 'name': 'png', 'ext': 'png', @@ -119,7 +122,8 @@ class ExtractPlayblast(pype.api.Extractor): "frameEnd": end, 'fps': fps, 'preview': True, - 'tags': tags + 'tags': tags, + 'camera_name': camera_node_name } instance.data["representations"].append(representation) From aa806b8e73d612ee3dc74efef83bd64724a30804 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 30 Oct 2020 10:51:19 +0100 Subject: [PATCH 02/12] add camera name to burnin data so it's usable in burnin templates --- pype/plugins/global/publish/extract_burnin.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pype/plugins/global/publish/extract_burnin.py b/pype/plugins/global/publish/extract_burnin.py index bf29e12eab..c856bf602f 100644 --- a/pype/plugins/global/publish/extract_burnin.py +++ b/pype/plugins/global/publish/extract_burnin.py @@ -157,6 +157,11 @@ class ExtractBurnin(pype.api.Extractor): filled_anatomy = anatomy.format_all(burnin_data) burnin_data["anatomy"] = filled_anatomy.get_solved() + # Add source camera name to burnin data + camera_name = repre.get("camera_name") + if camera_name: + burnin_data["camera_name"] = camera_name + first_output = True files_to_delete = [] From 05f6d92f8dd59d415f30c84585520fe7660648b6 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 30 Oct 2020 11:34:42 +0100 Subject: [PATCH 03/12] added options to imagel oader --- pype/plugins/tvpaint/load/load_image.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/pype/plugins/tvpaint/load/load_image.py b/pype/plugins/tvpaint/load/load_image.py index ec126adbee..1292608185 100644 --- a/pype/plugins/tvpaint/load/load_image.py +++ b/pype/plugins/tvpaint/load/load_image.py @@ -1,4 +1,5 @@ from avalon import api +from avalon.vendor import qargparse from avalon.tvpaint import CommunicatorWrapper @@ -20,6 +21,27 @@ class ImportImage(api.Loader): "tv_layerrename layer_id layer_name" ) + options = [ + qargparse.Boolean( + "stretch", + label="Stretch to project size", + default=True, + help="Stretch loaded image/s to project resolution?" + ), + qargparse.Boolean( + "timestretch", + label=" Stretch to timeline length", + default=True, + help="Clip loaded image/s to timeline length?" + ), + qargparse.Boolean( + "preload", + label="Preload loaded image/s", + default=True, + help="Preload image/s?" + ) + ] + def load(self, context, name, namespace, options): # Prepare layer name asset_name = context["asset"]["name"] From eae443264e5e65933f10be9cd86673707d58a598 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 30 Oct 2020 11:35:04 +0100 Subject: [PATCH 04/12] added defaults as options does not return value if they're not changed --- pype/plugins/tvpaint/load/load_image.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pype/plugins/tvpaint/load/load_image.py b/pype/plugins/tvpaint/load/load_image.py index 1292608185..4c4ebae7da 100644 --- a/pype/plugins/tvpaint/load/load_image.py +++ b/pype/plugins/tvpaint/load/load_image.py @@ -21,6 +21,12 @@ class ImportImage(api.Loader): "tv_layerrename layer_id layer_name" ) + defaults = { + "stretch": True, + "timestretch": True, + "preload": True + } + options = [ qargparse.Boolean( "stretch", From 111df4b9563e82b49b60e964da5460c42e358c60 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 30 Oct 2020 11:35:43 +0100 Subject: [PATCH 05/12] george script modify based on options --- pype/plugins/tvpaint/load/load_image.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/pype/plugins/tvpaint/load/load_image.py b/pype/plugins/tvpaint/load/load_image.py index 4c4ebae7da..e0a1267040 100644 --- a/pype/plugins/tvpaint/load/load_image.py +++ b/pype/plugins/tvpaint/load/load_image.py @@ -17,7 +17,7 @@ class ImportImage(api.Loader): import_script = ( "filepath = \"{}\"\n" "layer_name = \"{}\"\n" - "tv_loadsequence filepath \"preload\" PARSE layer_id\n" + "tv_loadsequence filepath {}PARSE layer_id\n" "tv_layerrename layer_id layer_name" ) @@ -49,6 +49,22 @@ class ImportImage(api.Loader): ] def load(self, context, name, namespace, options): + stretch = options.get("stretch", self.defaults["stretch"]) + timestretch = options.get("timestretch", self.defaults["timestretch"]) + preload = options.get("preload", self.defaults["preload"]) + + load_options = [] + if stretch: + load_options.append("\"STRETCH\"") + if timestretch: + load_options.append("\"TIMESTRETCH\"") + if preload: + load_options.append("\"PRELOAD\"") + + load_options_str = "" + for load_option in load_options: + load_options_str += (load_option + " ") + # Prepare layer name asset_name = context["asset"]["name"] version_name = context["version"]["name"] @@ -61,6 +77,7 @@ class ImportImage(api.Loader): # - filename mus not contain backwards slashes george_script = self.import_script.format( self.fname.replace("\\", "/"), - layer_name + layer_name, + load_options_str ) return CommunicatorWrapper.execute_george_through_file(george_script) From dbf75e1dfffd307e94dd66b055b8721b4bbafc01 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 30 Oct 2020 19:46:53 +0000 Subject: [PATCH 06/12] Ask user to select non-default camera from scene or create a new. --- pype/plugins/maya/load/load_image_plane.py | 97 ++++++++++++++++------ 1 file changed, 71 insertions(+), 26 deletions(-) diff --git a/pype/plugins/maya/load/load_image_plane.py b/pype/plugins/maya/load/load_image_plane.py index e17382f7ed..bbd80424d8 100644 --- a/pype/plugins/maya/load/load_image_plane.py +++ b/pype/plugins/maya/load/load_image_plane.py @@ -4,14 +4,70 @@ import maya.cmds as cmds from avalon import api, io from avalon.maya.pipeline import containerise from avalon.maya import lib -from Qt import QtWidgets +from Qt import QtWidgets, QtCore + + +class CameraWindow(QtWidgets.QDialog): + + def __init__(self, cameras): + super(CameraWindow, self).__init__() + self.setWindowFlags(self.windowFlags() | QtCore.Qt.FramelessWindowHint) + + self.camera = None + + self.widgets = { + "label": QtWidgets.QLabel("Select camera for image plane."), + "list": QtWidgets.QListWidget(), + "warning": QtWidgets.QLabel("No cameras selected!"), + "buttons": QtWidgets.QWidget(), + "okButton": QtWidgets.QPushButton("Ok"), + "cancelButton": QtWidgets.QPushButton("Cancel") + } + + # Build warning. + self.widgets["warning"].setVisible(False) + self.widgets["warning"].setStyleSheet("color: red") + + # Build list. + for camera in cameras: + self.widgets["list"].addItem(camera) + + # Build buttons. + layout = QtWidgets.QHBoxLayout(self.widgets["buttons"]) + layout.addWidget(self.widgets["okButton"]) + layout.addWidget(self.widgets["cancelButton"]) + + # Build layout. + layout = QtWidgets.QVBoxLayout(self) + layout.addWidget(self.widgets["label"]) + layout.addWidget(self.widgets["list"]) + layout.addWidget(self.widgets["buttons"]) + layout.addWidget(self.widgets["warning"]) + + self.widgets["okButton"].pressed.connect(self.on_ok_pressed) + self.widgets["cancelButton"].pressed.connect(self.on_cancel_pressed) + self.widgets["list"].itemPressed.connect(self.on_list_itemPressed) + + def on_list_itemPressed(self, item): + self.camera = item.text() + + def on_ok_pressed(self): + if self.camera is None: + self.widgets["warning"].setVisible(True) + return + + self.close() + + def on_cancel_pressed(self): + self.camera = None + self.close() class ImagePlaneLoader(api.Loader): """Specific loader of plate for image planes on selected camera.""" families = ["plate", "render"] - label = "Create imagePlane on selected camera." + label = "Load imagePlane." representations = ["mov", "exr", "preview", "png"] icon = "image" color = "orange" @@ -26,21 +82,22 @@ class ImagePlaneLoader(api.Loader): suffix="_", ) - # Getting camera from selection. - selection = pc.ls(selection=True) - + # Get camera from user selection. camera = None + default_cameras = [ + "frontShape", "perspShape", "sideShape", "topShape" + ] + cameras = [ + x for x in pc.ls(type="camera") if x.name() not in default_cameras + ] - if len(selection) > 1: - QtWidgets.QMessageBox.critical( - None, - "Error!", - "Multiple nodes selected. Please select only one.", - QtWidgets.QMessageBox.Ok - ) - return + if cameras: + camera_names = {x.getParent().name(): x for x in cameras} + window = CameraWindow(camera_names.keys()) + window.exec_() + camera = camera_names[window.camera] - if len(selection) < 1: + if camera is None: result = QtWidgets.QMessageBox.critical( None, "Error!", @@ -52,18 +109,6 @@ class ImagePlaneLoader(api.Loader): camera = pc.createNode("camera") else: return - else: - relatives = pc.listRelatives(selection[0], shapes=True) - if pc.ls(relatives, type="camera"): - camera = selection[0] - else: - QtWidgets.QMessageBox.critical( - None, - "Error!", - "Selected node is not a camera.", - QtWidgets.QMessageBox.Ok - ) - return try: camera.displayResolution.set(1) From 67c93962bd338566f16033c611cf081ddd0d070e Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 30 Oct 2020 19:48:38 +0000 Subject: [PATCH 07/12] Order workfile build as presets. --- pype/lib.py | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/pype/lib.py b/pype/lib.py index afcfa98307..4017686c6d 100644 --- a/pype/lib.py +++ b/pype/lib.py @@ -864,10 +864,10 @@ class BuildWorkfile: current_task_name = io.Session["AVALON_TASK"] # Load workfile presets for task - build_presets = self.get_build_presets(current_task_name) + self.build_presets = self.get_build_presets(current_task_name) # Skip if there are any presets for task - if not build_presets: + if not self.build_presets: log.warning( "Current task `{}` does not have any loading preset.".format( current_task_name @@ -876,9 +876,9 @@ class BuildWorkfile: return # Get presets for loading current asset - current_context_profiles = build_presets.get("current_context") + current_context_profiles = self.build_presets.get("current_context") # Get presets for loading linked assets - link_context_profiles = build_presets.get("linked_assets") + link_context_profiles = self.build_presets.get("linked_assets") # Skip if both are missing if not current_context_profiles and not link_context_profiles: log.warning("Current task `{}` has empty loading preset.".format( @@ -1231,7 +1231,36 @@ class BuildWorkfile: :rtype: list """ loaded_containers = [] - for subset_id, repres in repres_by_subset_id.items(): + + # Get subset id order from build presets. + build_presets = self.build_presets.get("current_context", []) + build_presets += self.build_presets.get("linked_assets", []) + subset_ids_ordered = [] + for preset in build_presets: + for preset_family in preset["families"]: + for id, subset in subsets_by_id.items(): + if preset_family not in subset["data"].get("families", []): + continue + + subset_ids_ordered.append(id) + + # Order representations from subsets. + print("repres_by_subset_id", repres_by_subset_id) + representations_ordered = [] + representations = [] + for id in subset_ids_ordered: + for subset_id, repres in repres_by_subset_id.items(): + if repres in representations: + continue + + if id == subset_id: + representations_ordered.append((subset_id, repres)) + representations.append(repres) + + print("representations", representations) + + # Load ordered reprensentations. + for subset_id, repres in representations_ordered: subset_name = subsets_by_id[subset_id]["name"] profile = profiles_per_subset_id[subset_id] From 74d214ad3f8ba7baed8ea8fe27f604b4c067d04d Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Sat, 31 Oct 2020 09:21:35 +0000 Subject: [PATCH 08/12] Reduce dialogs to one. --- pype/plugins/maya/load/load_image_plane.py | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/pype/plugins/maya/load/load_image_plane.py b/pype/plugins/maya/load/load_image_plane.py index bbd80424d8..fd92984114 100644 --- a/pype/plugins/maya/load/load_image_plane.py +++ b/pype/plugins/maya/load/load_image_plane.py @@ -90,24 +90,16 @@ class ImagePlaneLoader(api.Loader): cameras = [ x for x in pc.ls(type="camera") if x.name() not in default_cameras ] + camera_names = {x.getParent().name(): x for x in cameras} + camera_names["Create new camera."] = "create_camera" + window = CameraWindow(camera_names.keys()) + window.exec_() + camera = camera_names[window.camera] - if cameras: - camera_names = {x.getParent().name(): x for x in cameras} - window = CameraWindow(camera_names.keys()) - window.exec_() - camera = camera_names[window.camera] + if camera is "create_camera": + camera = pc.createNode("camera") if camera is None: - result = QtWidgets.QMessageBox.critical( - None, - "Error!", - "No camera selected. Do you want to create a camera?", - QtWidgets.QMessageBox.Ok, - QtWidgets.QMessageBox.Cancel - ) - if result == QtWidgets.QMessageBox.Ok: - camera = pc.createNode("camera") - else: return try: From 899f12087e49bff8b569d629902a072d3e81d82a Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Sat, 31 Oct 2020 09:22:29 +0000 Subject: [PATCH 09/12] Inform user about how many exr files are available to load. --- pype/plugins/maya/load/load_image_plane.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pype/plugins/maya/load/load_image_plane.py b/pype/plugins/maya/load/load_image_plane.py index fd92984114..c4718ba336 100644 --- a/pype/plugins/maya/load/load_image_plane.py +++ b/pype/plugins/maya/load/load_image_plane.py @@ -137,10 +137,16 @@ class ImagePlaneLoader(api.Loader): # Ensure OpenEXRLoader plugin is loaded. pc.loadPlugin("OpenEXRLoader.mll", quiet=True) + message = ( + "Hold image sequence on first frame?" + "\n{} files available.".format( + len(context["representation"]["files"]) + ) + ) reply = QtWidgets.QMessageBox.information( None, "Frame Hold.", - "Hold image sequence on first frame?", + message, QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Cancel ) From 19e86714a25a95eb8274b3731558b199d11995b7 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Sat, 31 Oct 2020 09:23:51 +0000 Subject: [PATCH 10/12] Hound fix --- pype/plugins/maya/load/load_image_plane.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/maya/load/load_image_plane.py b/pype/plugins/maya/load/load_image_plane.py index c4718ba336..1bb29e90c4 100644 --- a/pype/plugins/maya/load/load_image_plane.py +++ b/pype/plugins/maya/load/load_image_plane.py @@ -96,7 +96,7 @@ class ImagePlaneLoader(api.Loader): window.exec_() camera = camera_names[window.camera] - if camera is "create_camera": + if camera == "create_camera": camera = pc.createNode("camera") if camera is None: From 2d3f3acac5bef5192a1c704769180e213dbb9525 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 3 Nov 2020 12:07:19 +0100 Subject: [PATCH 11/12] removed space from label --- pype/plugins/tvpaint/load/load_image.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/tvpaint/load/load_image.py b/pype/plugins/tvpaint/load/load_image.py index e0a1267040..0d5a0b4aa1 100644 --- a/pype/plugins/tvpaint/load/load_image.py +++ b/pype/plugins/tvpaint/load/load_image.py @@ -36,7 +36,7 @@ class ImportImage(api.Loader): ), qargparse.Boolean( "timestretch", - label=" Stretch to timeline length", + label="Stretch to timeline length", default=True, help="Clip loaded image/s to timeline length?" ), From ea15579c060944ee5288019d5d5c3cb97fc01328 Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Thu, 5 Nov 2020 17:04:51 +0100 Subject: [PATCH 12/12] get transform of camera for burnin --- pype/plugins/maya/publish/extract_playblast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/maya/publish/extract_playblast.py b/pype/plugins/maya/publish/extract_playblast.py index fc80e74be0..647d1f4503 100644 --- a/pype/plugins/maya/publish/extract_playblast.py +++ b/pype/plugins/maya/publish/extract_playblast.py @@ -111,7 +111,7 @@ class ExtractPlayblast(pype.api.Extractor): tags.append("delete") # Add camera node name to representation data - camera_node_name = pm.ls(camera)[0].nodeName() + camera_node_name = pm.ls(camera)[0].getTransform().getName() representation = { 'name': 'png',