diff --git a/capture.py b/capture.py index 74437ff..74d2a08 100644 --- a/capture.py +++ b/capture.py @@ -7,6 +7,7 @@ import re import sys import contextlib +from collections import defaultdict from maya import cmds from maya import mel @@ -20,7 +21,7 @@ from PySide import QtGui QtWidgets = QtGui -version_info = (2, 5, 0) +version_info = (2, 6, 0) __version__ = "%s.%s.%s" % version_info __license__ = "MIT" @@ -45,6 +46,7 @@ def capture(camera=None, overwrite=False, frame_padding=4, raw_frame_numbers=False, + use_camera_sequencer=False, camera_options=None, display_options=None, viewport_options=None, @@ -84,6 +86,12 @@ def capture(camera=None, frame numbers from the scene or capture to a sequence starting at zero. Defaults to False. When set to True `viewer` can't be used and will be forced to False. + use_camera_sequencer (bool, optional): Whether or not to playblast + using the camera sequencer. Defaults to False. When set to True the + value of `camera` will be ignored and the cameras from the + sequencer will be used instead. Additionally, the `start_frame` and + `end_frame` values will be in sequence time instead of scene frame + numbers. camera_options (dict, optional): Supplied camera options, using `CameraOptions` display_options (dict, optional): Supplied display @@ -125,10 +133,21 @@ def capture(camera=None, ratio = cmds.getAttr("defaultResolution.deviceAspectRatio") height = round(width / ratio) - if start_frame is None: - start_frame = cmds.playbackOptions(minTime=True, query=True) - if end_frame is None: - end_frame = cmds.playbackOptions(maxTime=True, query=True) + # Set frame range if no custom frame range specified + if use_camera_sequencer: + # Get frames from the Camera Sequencer + sequencer = cmds.sequenceManager(query=True, writableSequencer=True) + + if start_frame is None: + start_frame = cmds.getAttr(sequencer + ".minFrame") + if end_frame is None: + end_frame = cmds.getAttr(sequencer + ".maxFrame") + else: + # Get frames from the timeline + if start_frame is None: + start_frame = cmds.playbackOptions(minTime=True, query=True) + if end_frame is None: + end_frame = cmds.playbackOptions(maxTime=True, query=True) # (#74) Bugfix: `maya.cmds.playblast` will raise an error when playblasting # with `rawFrameNumbers` set to True but no explicit `frames` provided. @@ -172,7 +191,7 @@ def capture(camera=None, with _disabled_inview_messages(),\ _maintain_camera(panel, camera),\ _applied_viewport_options(viewport_options, panel),\ - _applied_camera_options(camera_options, panel),\ + _applied_camera_options(camera_options, panel, use_camera_sequencer),\ _applied_display_options(display_options),\ _applied_viewport2_options(viewport2_options),\ _isolated_nodes(isolate, panel),\ @@ -193,6 +212,7 @@ def capture(camera=None, widthHeight=[width, height], rawFrameNumbers=raw_frame_numbers, framePadding=frame_padding, + sequenceTime=use_camera_sequencer, **playblast_kwargs) return output @@ -616,30 +636,41 @@ def _independent_panel(width, height, off_screen=False): @contextlib.contextmanager -def _applied_camera_options(options, panel): - """Context manager for applying `options` to `camera`""" - - camera = cmds.modelPanel(panel, query=True, camera=True) +def _applied_camera_options(options, panel, use_camera_sequencer=False): + """Context manager for applying `options` to the cameras used""" + + if use_camera_sequencer: + cameras = [ + cmds.shot(shot, query=True, currentCamera=True) + for shot in cmds.sequenceManager(listShots=True) + if not cmds.shot(shot, query=True, mute=True) + ] + else: + cameras = [cmds.modelPanel(panel, query=True, camera=True)] + options = dict(CameraOptions, **(options or {})) - old_options = dict() - for opt in options.copy(): - try: - old_options[opt] = cmds.getAttr(camera + "." + opt) - except: - sys.stderr.write("Could not get camera attribute " - "for capture: %s" % opt) - options.pop(opt) + old_options = defaultdict(dict) + for camera in cameras: + cam_options = options.copy() + for opt in cam_options: + try: + old_options[camera][opt] = cmds.getAttr(camera + "." + opt) + except: + sys.stderr.write("Could not get camera attribute " + "for capture: %s.%s" % (camera, opt)) + cam_options.pop(opt) - for opt, value in options.items(): - cmds.setAttr(camera + "." + opt, value) + for opt, value in cam_options.items(): + cmds.setAttr(camera + "." + opt, value) try: yield finally: - if old_options: - for opt, value in old_options.items(): - cmds.setAttr(camera + "." + opt, value) + for camera, orig_options in old_options.items(): + if orig_options: + for opt, value in orig_options.items(): + cmds.setAttr(camera + "." + opt, value) @contextlib.contextmanager