Merge pull request #4751 from ynput/enhancement/OP-2261_maya-update-camera-resets-viewport

This commit is contained in:
Milan Kolar 2023-03-30 17:38:48 +02:00 committed by GitHub
commit 89c4d505d0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,4 +1,6 @@
import os
import difflib
import contextlib
from maya import cmds
from openpype.settings import get_project_settings
@ -8,7 +10,82 @@ from openpype.pipeline.create import (
get_legacy_creator_by_name,
)
import openpype.hosts.maya.api.plugin
from openpype.hosts.maya.api.lib import maintained_selection
from openpype.hosts.maya.api.lib import (
maintained_selection,
get_container_members
)
@contextlib.contextmanager
def preserve_modelpanel_cameras(container, log=None):
"""Preserve camera members of container in the modelPanels.
This is used to ensure a camera remains in the modelPanels after updating
to a new version.
"""
# Get the modelPanels that used the old camera
members = get_container_members(container)
old_cameras = set(cmds.ls(members, type="camera", long=True))
if not old_cameras:
# No need to manage anything
yield
return
panel_cameras = {}
for panel in cmds.getPanel(type="modelPanel"):
cam = cmds.ls(cmds.modelPanel(panel, query=True, camera=True),
long=True)
# Often but not always maya returns the transform from the
# modelPanel as opposed to the camera shape, so we convert it
# to explicitly be the camera shape
if cmds.nodeType(cam) != "camera":
cam = cmds.listRelatives(cam,
children=True,
fullPath=True,
type="camera")[0]
if cam in old_cameras:
panel_cameras[panel] = cam
if not panel_cameras:
# No need to manage anything
yield
return
try:
yield
finally:
new_members = get_container_members(container)
new_cameras = set(cmds.ls(new_members, type="camera", long=True))
if not new_cameras:
return
for panel, cam_name in panel_cameras.items():
new_camera = None
if cam_name in new_cameras:
new_camera = cam_name
elif len(new_cameras) == 1:
new_camera = next(iter(new_cameras))
else:
# Multiple cameras in the updated container but not an exact
# match detected by name. Find the closest match
matches = difflib.get_close_matches(word=cam_name,
possibilities=new_cameras,
n=1)
if matches:
new_camera = matches[0] # best match
if log:
log.info("Camera in '{}' restored with "
"closest match camera: {} (before: {})"
.format(panel, new_camera, cam_name))
if not new_camera:
# Unable to find the camera to re-apply in the modelpanel
continue
cmds.modelPanel(panel, edit=True, camera=new_camera)
class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader):
@ -68,6 +145,9 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader):
new_nodes = (list(set(nodes) - set(shapes)))
# if there are cameras, try to lock their transforms
self._lock_camera_transforms(new_nodes)
current_namespace = pm.namespaceInfo(currentNamespace=True)
if current_namespace != ":":
@ -136,6 +216,15 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader):
def switch(self, container, representation):
self.update(container, representation)
def update(self, container, representation):
with preserve_modelpanel_cameras(container, log=self.log):
super(ReferenceLoader, self).update(container, representation)
# We also want to lock camera transforms on any new cameras in the
# reference or for a camera which might have changed names.
members = get_container_members(container)
self._lock_camera_transforms(members)
def _post_process_rig(self, name, namespace, context, options):
output = next((node for node in self if
@ -168,3 +257,18 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader):
options={"useSelection": True},
data={"dependencies": dependency}
)
def _lock_camera_transforms(self, nodes):
cameras = cmds.ls(nodes, type="camera")
if not cameras:
return
# Check the Maya version, lockTransform has been introduced since
# Maya 2016.5 Ext 2
version = int(cmds.about(version=True))
if version >= 2016:
for camera in cameras:
cmds.camera(camera, edit=True, lockTransform=True)
else:
self.log.warning("This version of Maya does not support locking of"
" transforms of cameras.")