Created
April 21, 2022 06:00
-
-
Save yamahigashi/887540b99c1b0ac9a950dffc969932f5 to your computer and use it in GitHub Desktop.
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
# -*- coding: utf-8 -*- | |
############################################################################### | |
import sys | |
import textwrap | |
import maya.cmds as cmds | |
import maya.mel as mel | |
import maya.api.OpenMayaUI as omui | |
# import gml_maya.decorator as deco | |
from logging import ( # noqa:F401 pylint: disable=unused-import, wrong-import-order | |
StreamHandler, | |
getLogger, | |
WARN, | |
DEBUG, | |
INFO | |
) | |
if sys.version_info >= (3, 0): # pylint: disable=using-constant-test # pylint: disable=using-constant-test, wrong-import-order | |
# For type annotation | |
from typing import ( # NOQA: F401 pylint: disable=unused-import | |
Optional, | |
Dict, | |
List, | |
Tuple, | |
Pattern, | |
Callable, | |
Any, | |
Text, | |
Generator, | |
Union | |
) | |
handler = StreamHandler() | |
handler.setLevel(DEBUG) | |
logger = getLogger(__name__) | |
logger.setLevel(INFO) | |
logger.addHandler(handler) | |
logger.propagate = False | |
############################################################################## | |
def open_objectview(display_objects=None, target=None, camera=None, namespace=None): | |
# type: (Optional[List[Text]], Optional[Text], Optional[Text], Optional[Text]) -> None | |
"""Open a window that shows only the objects. | |
""" | |
if not display_objects: | |
display_objects = cmds.ls(sl=True) | |
if not display_objects: | |
mes = "nothing to display, cancel opening objectview window" | |
logger.warning(mes) | |
cmds.inViewMessage( | |
assistMessage=mes, | |
position='topCenter', | |
fade=True | |
) | |
return | |
delete_invisible_objectview() | |
if not target: | |
target = display_objects[0] | |
if not camera: | |
camera = get_or_create_target_camera("CustomObjectViewer", target, namespace) | |
try: | |
# spawn GUI elements, window, panel and layout | |
window_id = get_unique_window_id("CustomObjectViewer") | |
cmds.window() | |
window = cmds.window( | |
window_id, | |
title='Custom ObjectViewer', | |
sizeable=True, | |
topLeftCorner=(200, 200), | |
widthHeight=(400, 470), | |
) | |
layout = cmds.formLayout() | |
model_panel = cmds.modelPanel( | |
label='CustomObjectViewer_ModelPanel', | |
camera=camera | |
) | |
cmds.setParent('..') | |
control_panel = "" | |
cmds.window( | |
window_id, | |
edit=True, | |
closeCommand=( | |
textwrap.dedent( | |
""" | |
cmds.deleteUI("{}", panel=True) | |
cmds.deleteUI("{}", panel=True) | |
""".format(model_panel, control_panel) | |
) | |
) | |
) | |
except RuntimeError: | |
raise | |
_fill_objectview_with_layout(namespace, model_panel, control_panel, layout, camera) | |
_tweak_modelpanel_setting(model_panel, display_objects) | |
cmds.showWindow(window) | |
def reset_camera(camera, panel_name): | |
cmds.xform(camera, r=False, ws=False, t=(0, 0, 0)) | |
cmds.xform(camera, r=False, ws=False, ro=(0, 0, 0)) | |
shape = get_camera_shape(camera) | |
cmds.setAttr("{}.orthographicWidth".format(shape), 55) | |
cmds.setAttr("{}.horizontalPan".format(shape), 0) | |
cmds.setAttr("{}.verticalPan".format(shape), 0) | |
cmds.setAttr("{}.zoom".format(shape), 1) | |
# cmds.setAttr("{}.panZoomEnabled".format(shape), False) | |
cmds.setAttr("{}.centerOfInterest".format(shape), 66) | |
cmds.modelPanel( | |
panel_name, | |
edit=True, | |
camera=camera | |
) | |
def turn_camera_perspective_on(camera): | |
shape = get_camera_shape(camera) | |
cmds.setAttr("{}.orthographic".format(shape), False) | |
def turn_camera_orthographic_on(camera): | |
shape = get_camera_shape(camera) | |
cmds.setAttr("{}.orthographic".format(shape), True) | |
def toggle_camera_orthographic(camera): | |
shape = get_camera_shape(camera) | |
current = cmds.getAttr("{}.orthographic".format(shape)) | |
cmds.setAttr("{}.orthographic".format(shape), not current) | |
def set_camera_focal_length(camera, focal_length): | |
# type: (Text, float) -> None | |
turn_camera_perspective_on(camera) | |
shape = get_camera_shape(camera) | |
cmds.setAttr("{}.focalLength".format(shape), focal_length) | |
def get_camera_shape(camera_xform): | |
# type: (Text) -> Text | |
shapes = cmds.listRelatives(camera_xform, shapes=True) or [] | |
shape = shapes[0] | |
return shape | |
def _fill_objectview_with_layout(namespace, model_panel, control_panel, layout, camera): | |
# type: (Text, Text, Text, Text, Text) -> None | |
cmds.setParent('..') | |
col2 = cmds.columnLayout() | |
cmds.rowLayout(numberOfColumns=7) | |
cmds.button( | |
label="Reset camera", | |
command=textwrap.dedent( | |
""" | |
reset_camera("{}", "{}") | |
""".format(camera, model_panel) | |
) | |
) | |
cmds.button( | |
label="Toggle display elements", | |
command=textwrap.dedent( | |
""" | |
import maya.api.OpenMayaUI as omui | |
mask = omui.M3dView.kDisplayTextures + omui.M3dView.kDisplayMeshes | |
toggle_displayelements(mask) | |
""".format(cam=camera) | |
) | |
) | |
cmds.button( | |
label="18mm", | |
command=textwrap.dedent( | |
""" | |
set_camera_focal_length("{}", {}) | |
""".format(camera, 18.0) | |
) | |
) | |
cmds.button( | |
label="35mm", | |
command=textwrap.dedent( | |
""" | |
set_camera_focal_length("{}", {}) | |
""".format(camera, 35.0) | |
) | |
) | |
cmds.button( | |
label="50mm", | |
command=textwrap.dedent( | |
""" | |
set_camera_focal_length("{}", {}) | |
""".format(camera, 50.0) | |
) | |
) | |
cmds.button( | |
label="Perspective / Orthographic", | |
command=textwrap.dedent( | |
""" | |
toggle_camera_orthographic("{}") | |
""".format(camera) | |
) | |
) | |
cmds.setParent('..') | |
cmds.formLayout( | |
layout, | |
edit=True, | |
attachForm=[ | |
(model_panel, 'left', 5), | |
(model_panel, 'top', 0), | |
(model_panel, 'bottom', 80), | |
(model_panel, 'right', 5), | |
# (control_panel, 'left', 205), | |
# (control_panel, 'top', 0), | |
# (control_panel, 'right', 5), | |
# (control_panel, 'bottom', 80), | |
(col2, 'left', 5), | |
# (col2, 'top', 400), | |
(col2, 'right', 5), | |
(col2, 'bottom', 20) | |
] # pyright: ignore | |
) | |
# @deco.keep_selection | |
def _tweak_modelpanel_setting(model_panel, display_objects=None): | |
# type: (Text, Optional[List[Text]]) -> None | |
cmds.modelEditor( | |
model_panel, | |
edit=True, | |
grid=False, | |
displayAppearance='smoothShaded', | |
activeOnly=False, | |
displayTextures=True | |
) | |
if not display_objects: | |
return | |
cmds.refresh() | |
cmds.select(display_objects) | |
mel.eval("""isolateSelect -state 1 "{}";""".format(model_panel)) | |
mel.eval("""isolateSelect -addSelectedObjects "{}";""".format(model_panel)) | |
# mel.eval("""enableIsolateSelect "{}" true;""".format(model_panel)) | |
def get_or_create_target_camera(camera_name, target, namespace, offset=None): | |
# type: (Text, Optional[Text], Text, Optional[Tuple[float, float, float]]) -> Text | |
if namespace: | |
query = "Camera_{}_{}".format(camera_name, namespace) | |
else: | |
query = "Camera_{}".format(camera_name) | |
if target: | |
query = "{}_{}".format(query, camera_name) | |
candidate = cmds.ls("{}*".format(query), type="transform") | |
if candidate: | |
return candidate[0] | |
return create_camera(camera_name, target, namespace) | |
def create_camera(name, lookat_object, namespace=None, offset=(0, 4, 50)): | |
# type: (Text, Optional[Text], Optional[Text], Tuple[int, int, int]) -> Text | |
"""Returns camera name.""" | |
if namespace: | |
lookat_object = "{}:{}".format(namespace, lookat_object) | |
name = "{}_{}".format(name, namespace) | |
camera_name = "Camera_{}".format(name) | |
cam = cmds.camera(n=camera_name) | |
loc = cmds.spaceLocator(n="loc_{}".format(name)) | |
cmds.parent(cam[0], loc) | |
if cmds.ls(lookat_object): | |
cmds.parent(loc, lookat_object) | |
cmds.xform(loc, worldSpace=False, relative=False, ro=(0, 0, 0)) | |
cmds.xform(loc, worldSpace=False, relative=False, t=offset) | |
try: | |
cmds.parent(loc, world=True) | |
except RuntimeError: | |
pass | |
cmds.setAttr("{}.centerOfInterest".format(cam[1]), 66) | |
''' | |
cmds.expression( | |
s=""" | |
{cam}.rotateX = 0; | |
{cam}.rotateY = 0; | |
{cam}.rotateZ = 0; | |
""".format(cam=cam[0]), | |
alwaysEvaluate=False | |
) | |
''' | |
if cmds.ls(lookat_object): | |
cmds.parentConstraint(lookat_object, loc, maintainOffset=True) | |
return cam[0] | |
def delete_invisible_objectview(): | |
all_model_panels = cmds.getPanel(type="modelPanel") | |
opened_panels = [] | |
for panel in all_model_panels: | |
label = cmds.panel(panel, q=True, label=True) | |
# if not isinstance(label, (str, unicode)): | |
# raise Exception("could not get panel {}".format(panel)) | |
if "CustomObjectViewer" in label: | |
opened_panels.append(panel) | |
invis_panel_list = cmds.getPanel(invisiblePanels=True) | |
for panel in opened_panels: | |
if panel in invis_panel_list: | |
cmds.deleteUI(panel, panel=True) | |
# -------------------------------------------------------------------------------------- | |
# copy from util.__init__.py | |
# -------------------------------------------------------------------------------------- | |
def get_unique_window_id(candidate): | |
# type: (Text) -> Text | |
"""Returns unique id for window it may contain sequencial number.""" | |
if cmds.about(batch=True): | |
raise Exception("access to the widgets does not supported in batch mode") | |
def _is_window_exists(query): | |
return cmds.window(query, q=True, exists=True) | |
num = 0 | |
query = candidate | |
while _is_window_exists(query): | |
query = "{}{}".format(candidate, num) | |
num += 1 | |
return query | |
SLIM_MASK = omui.M3dView.kDisplayTextures + omui.M3dView.kDisplayMeshes + omui.M3dView.kDisplayGrid | |
ALL_MASK = omui.M3dView.kDisplayEverything | |
def _hoge(mask): | |
av = omui.M3dView.active3dView() | |
av.setObjectDisplay(mask) | |
av.refresh() | |
def toggle_displayelements(mask=SLIM_MASK): | |
av = omui.M3dView.active3dView() | |
current = av.objectDisplay() | |
if mask == current: | |
_hoge(ALL_MASK) | |
else: | |
_hoge(mask) | |
# @deco.keep_selection | |
def open(): | |
sel = cmds.ls(sl=True) | |
open_objectview(display_objects=sel) | |
if __name__ == "__main__": | |
open() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment