Created
September 1, 2019 10:17
-
-
Save davidlatwe/9c43ce89b39de86e19bd0d58690301a0 to your computer and use it in GitHub Desktop.
Maya scene modification aware via Pyblish
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Implement scene modification awareness | |
By tracking Maya's undo queue, if there are any undo command that is not | |
a simple select after collecting completed, consider this scene has been | |
modified and require to reset Pyblish. | |
""" | |
import collections | |
import maya.OpenMaya as om | |
import pyblish.api | |
class AvalonSceneReady(pyblish.api.ContextPlugin): | |
"""Define current scene in ready state | |
Collecte current undo count for later validation. | |
""" | |
order = pyblish.api.CollectorOrder + 0.49999 | |
label = "Scene Ready" | |
hosts = ["maya"] | |
def process(self, context): | |
from maya import cmds | |
# Ensure undo queue is active | |
cmds.undoInfo(state=True) | |
with OutputDeque() as undo_list: | |
cmds.undoInfo(query=True, printQueue=True) | |
context.data["_undoCount"] = len(undo_list) | |
class AvalonCheckSceneReady(pyblish.api.ContextPlugin): | |
"""Validate current scene still fit the definition of *ready* | |
By checking new undo commands in undo queue after collecting, and consider | |
scene is not ready if there are any non-select command. | |
""" | |
order = pyblish.api.ValidatorOrder - 0.49998 | |
label = "Is Scene Ready" | |
hosts = ["maya"] | |
def process(self, context): | |
from maya import cmds | |
if not cmds.undoInfo(query=True, state=True): | |
raise Exception("Undo queue is not open, please reset.") | |
undo_count = context.data["_undoCount"] | |
# self.log.debug(undo_count) | |
with OutputDeque(format=lambda l: l.split(": ", 1)[-1].strip(), | |
skip=undo_count, | |
) as undo_list: | |
cmds.undoInfo(query=True, printQueue=True) | |
while undo_list: | |
history = undo_list.pop() | |
# self.log.debug(history) | |
if history.startswith("select"): | |
continue | |
raise Exception("Scene has been modified, no longer in *ready* " | |
"state. Please reset.") | |
class OutputDeque(collections.deque): | |
"""Record Maya command output during the context | |
A context manager, subclass of `collections.deque`. | |
Maya command output will be added into this deque during the context. | |
Args: | |
ignore_empty (bool, optional): Whether to ignore empty formatted | |
output line. Default True. | |
format (callable, optional): Function for formatting output. | |
skip (int, optional): Skip first numbers of outputs. | |
max (int, optional): Max length of the deque. | |
""" | |
def __init__(self, | |
ignore_empty=True, | |
format=None, | |
skip=0, | |
max=None): | |
self.ignore_empty = ignore_empty | |
self.format = format or (lambda line: line) | |
self.skip = skip | |
self.__callback_id = None | |
self.__count = 0 | |
super(OutputDeque, self).__init__(maxlen=max) | |
def __enter__(self): | |
add_callback = om.MCommandMessage.addCommandOutputCallback | |
def catch_output(msg, *args): | |
self.__count += 1 | |
if self.__count <= self.skip: | |
return | |
formatted = self.format(msg) | |
if formatted or not self.ignore_empty: | |
self.append(formatted) | |
self.__callback_id = add_callback(catch_output) | |
return self | |
def __exit__(self, *args): | |
om.MCommandMessage.removeCallback(self.__callback_id) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment