Skip to content

Instantly share code, notes, and snippets.

@redglasses67
Created December 14, 2025 17:06
Show Gist options
  • Select an option

  • Save redglasses67/37dae23d6ed8ecd0d17e5da620d946b5 to your computer and use it in GitHub Desktop.

Select an option

Save redglasses67/37dae23d6ed8ecd0d17e5da620d946b5 to your computer and use it in GitHub Desktop.
選択したオブジェクト名を QLabel を使ってディスプレイ上に表示する
# -*- coding: utf-8 -*-
import maya.api.OpenMaya as om2
import maya.api.OpenMayaUI as om2u
import maya.OpenMayaUI as omui
import maya.cmds as mc
from functools import partial
mainDisplayMenuPath = "MayaWindow|mainDisplayMenu"
pluginMenuName = "DisplaySelectedNameWithQLabel"
pluginMenuPath = mainDisplayMenuPath + "|" + pluginMenuName
pluginLabel = "Display Selected Name With QLabel"
scriptName = "kkDisplaySelectedNameWithQLabel"
colorWindowName = f"{scriptName}_ColorWindow"
colorInputWidgetGrpName = f"{scriptName}_ColorInputWidgetGrp"
optionVarColorR = f"{scriptName}_ColorR"
optionVarColorG = f"{scriptName}_ColorG"
optionVarColorB = f"{scriptName}_ColorB"
optionVarColorA = f"{scriptName}_ColorA"
selectionChangeCallbackID = None
postRenderCallbackID = None
labelList = []
try:
from PySide2.QtCore import Qt
from PySide2.QtGui import QPalette, QColor
from PySide2.QtWidgets import QLabel, QWidget
from shiboken2 import wrapInstance
except ImportError:
from PySide6.QtCore import Qt
from PySide6.QtGui import QPalette, QColor
from PySide6.QtWidgets import QLabel, QWidget
from shiboken6 import wrapInstance
try:
long
except NameError:
long = int
#===============================================================
def changeColorUI(*args):
if mc.window(colorWindowName, exists=True):
mc.deleteUI(colorWindowName)
colorR = 1.0
colorG = 1.0
colorB = 1.0
colorA = 0.5
if mc.optionVar(exists = optionVarColorR) == True:
colorR = mc.optionVar(q = optionVarColorR)
if mc.optionVar(exists = optionVarColorG) == True:
colorG = mc.optionVar(q = optionVarColorG)
if mc.optionVar(exists = optionVarColorB) == True:
colorG = mc.optionVar(q = optionVarColorB)
if mc.optionVar(exists = optionVarColorA) == True:
colorA = mc.optionVar(q = optionVarColorA)
mc.window(colorWindowName, title=f"{pluginLabel} Text Color")
mc.columnLayout()
mc.colorInputWidgetGrp(colorInputWidgetGrpName,
label = "Text Color",
rgb = (colorR, colorG, colorB),
changeCommand = changeColorAttr,
alphaValue = colorA)
mc.showWindow()
def changeColorAttr(*args):
changeColRGB = mc.colorInputWidgetGrp(colorInputWidgetGrpName, q = True, rgbValue = True)
changeColA = mc.colorInputWidgetGrp(colorInputWidgetGrpName, q = True, alphaValue = True)
if mc.optionVar(exists = optionVarColorR) == True:
mc.optionVar(floatValue = [optionVarColorR, changeColRGB[0]])
if mc.optionVar(exists = optionVarColorG) == True:
mc.optionVar(floatValue = [optionVarColorG, changeColRGB[1]])
if mc.optionVar(exists = optionVarColorB) == True:
mc.optionVar(floatValue = [optionVarColorB, changeColRGB[2]])
if mc.optionVar(exists = optionVarColorA) == True:
mc.optionVar(floatValue = [optionVarColorA, changeColA[0]])
#===============================================================
def maya_useNewAPI():
pass
# initialize the script plug-in
def initializePlugin(obj):
try:
# ディスプレイメニューに追加 チェックボックスはデフォルトOFF
mc.menuItem(pluginMenuName,
label = pluginLabel,
checkBox = False,
parent = mainDisplayMenuPath)
mc.menuItem(optionBox = True,
command = changeColorUI,
parent = mainDisplayMenuPath)
global selectionChangeCallbackID
selectionChangeCallbackID = om2.MModelMessage.addCallback(
om2.MModelMessage.kActiveListModified,
selectionChange)
# optionVarに文字カラー用の変数を作成
mc.optionVar(floatValue = [optionVarColorR, 1.0])
mc.optionVar(floatValue = [optionVarColorG, 1.0])
mc.optionVar(floatValue = [optionVarColorB, 1.0])
mc.optionVar(floatValue = [optionVarColorA, 0.5])
except:
# sys.stderr.write("Failed to register node: %s" % kkDisplaySelectedNameNode.kPluginNodeTypeName)
raise
#===============================================================
# uninitialize the script plug-in
def uninitializePlugin(obj):
try:
# optionVarから文字カラー用の変数を削除
mc.optionVar(remove = optionVarColorR)
mc.optionVar(remove = optionVarColorG)
mc.optionVar(remove = optionVarColorB)
mc.optionVar(remove = optionVarColorA)
if mc.menuItem(pluginMenuPath, exists = True):
mc.deleteUI(pluginMenuPath, menuItem = True)
resetLabels()
global selectionChangeCallbackID
global postRenderCallbackID
if selectionChangeCallbackID is not None:
om2.MEventMessage.removeCallback(selectionChangeCallbackID)
if postRenderCallbackID is not None:
om2.MEventMessage.removeCallback(postRenderCallbackID)
selectionChangeCallbackID = None
postRenderCallbackID = None
print(f" Unload >> {pluginMenuName} Plugin ")
except:
# sys.stderr.write("Failed to deregister node: %s" % kkDisplaySelectedNameNode.kPluginNodeTypeName)
raise
#=======================================================================================================================
def selectionChange(*args):
if not mc.menuItem(pluginMenuPath, q = True, checkBox = True):
return
activePanelName = mc.getPanel(withFocus=True)
control = omui.MQtUtil.findControl(activePanelName)
widget = wrapInstance(int(control), QWidget) # type: QWidget
targetWidget = None
if targetWidget is None:
targetWidget = widget
global postRenderCallbackID
if postRenderCallbackID is not None:
om2.MEventMessage.removeCallback(postRenderCallbackID)
postRenderCallbackID = om2u.MUiMessage.add3dViewPostRenderMsgCallback(
activePanelName,
partial(updateLabelPosition, targetWidget))
def worldPosToScreenPos(worldPoint, activePanelName):
activeView = om2u.M3dView.getM3dViewFromModelPanel(activePanelName) # type: om2u.M3dView
mPoint = om2.MPoint(worldPoint) # type: om2.MPoint
# ワールド座標 → スクリーン座標に変換
_screenPosX, _screenPosY, _ = activeView.worldToView(mPoint)
viewPosX, viewPosY = activeView.getScreenPosition()
viewHeight = activeView.portHeight()
viewWidth = activeView.portWidth()
# Y座標を反転(PySideの座標系に合わせる)
_screenPosY = viewHeight - _screenPosY
screenPosX = _screenPosX + viewPosX
screenPosY = _screenPosY + viewPosY
# アクティブモデルパネルの範囲外にある場合は None をセット
if _screenPosX < 0 or viewWidth < _screenPosX:
screenPosX = None
if _screenPosY < 0 or viewHeight < _screenPosY:
screenPosY = None
return screenPosX, screenPosY
def resetLabels():
global labelList
for label in labelList:
label.deleteLater()
labelList = []
# 描画後に呼ばれるコールバック関数
def updateLabelPosition(widget, *args):
# まず既存のラベルを削除
resetLabels()
if not mc.menuItem(pluginMenuPath, q = True, checkBox = True):
return
# 選択しているリスト
selList = om2.MGlobal.getActiveSelectionList()
activePanelName = widget.accessibleName()
global labelList
colorR = mc.optionVar(q = optionVarColorR) * 255.0
colorG = mc.optionVar(q = optionVarColorG) * 255.0
colorB = mc.optionVar(q = optionVarColorB) * 255.0
colorA = mc.optionVar(q = optionVarColorA)
for i in range(selList.length()):
mDagPath = selList.getDagPath(i)
transform = om2.MFnTransform(mDagPath)
worldPos = transform.translation(om2.MSpace.kWorld)
screenPosX, screenPosY = worldPosToScreenPos(worldPos, activePanelName)
# screenPosX, screenPosY どちらも None じゃない場合のみ表示
if screenPosX is not None and screenPosY is not None:
label = QLabel(mDagPath.partialPathName(), parent=widget) # type: QLabel
label.setWindowFlags(Qt.Tool | Qt.FramelessWindowHint)
# テキストの RGB 値をセット
palette = label.palette()
palette.setColor(QPalette.WindowText, QColor(colorR, colorG, colorB))
label.setPalette(palette)
# テキストの A 値をセット
label.setWindowOpacity(colorA)
label.show()
label.move(screenPosX, screenPosY)
labelList.append(label)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment