회원 로그인
|
[펌] Maya 2017 PySide2 Docking Qt QMainWindow
Maya 2017 PySide2 Docking Qt QMainWindow
:PySide2를 이용한 마야 메인 윈도우에 도킹 스크립트
:PySide2를 이용한 마야 메인 윈도우에 도킹 스크립트
Qt.py를 이용한 윈도우 클래스
윈도우(QMainWindow) 형
출처
https://gist.github.com/liorbenhorin/217bfb7e54c6f75b9b1b2b3d73a1a43a
Tab(QDockWidget) 형
출처
https://gist.github.com/liorbenhorin/69da10ec6f22c6d7b92deefdb4a4f475
윈도우(QMainWindow) 형
#MayaDockingClass.py """ This is what you need to do in order to get a qt window to dock next to maya channel box, In all maya versions, including 2017 with PySide2 """ __author__ = "liorbenhorin@gmail.com" import sys import os import logging import xml.etree.ElementTree as xml from cStringIO import StringIO # Qt is a project by Marcus Ottosson ---> https://github.com/mottosso/Qt.py from Qt import QtGui, QtWidgets, QtCore, QtCompat try: import pysideuic from shiboken import wrapInstance logging.Logger.manager.loggerDict["pysideuic.uiparser"].setLevel(logging.CRITICAL) logging.Logger.manager.loggerDict["pysideuic.properties"].setLevel(logging.CRITICAL) except ImportError: import pyside2uic as pysideuic from shiboken2 import wrapInstance logging.Logger.manager.loggerDict["pyside2uic.uiparser"].setLevel(logging.CRITICAL) logging.Logger.manager.loggerDict["pyside2uic.properties"].setLevel(logging.CRITICAL) import maya.OpenMayaUI as omui from maya.app.general.mayaMixin import MayaQWidgetDockableMixin import maya.cmds as cmds def loadUiType(uiFile): """ :author: Jason Parks Pyside lacks the "loadUiType" command, so we have to convert the ui file to py code in-memory first and then execute it in a special frame to retrieve the form_class. """ parsed = xml.parse(uiFile) widget_class = parsed.find('widget').get('class') form_class = parsed.find('class').text with open(uiFile, 'r') as f: o = StringIO() frame = {} pysideuic.compileUi(f, o, indent=0) pyc = compile(o.getvalue(), '<string>', 'exec') exec pyc in frame # Fetch the base_class and form class based on their type in the xml from designer form_class = frame['Ui_%s' % form_class] base_class = getattr(QtWidgets, widget_class) return form_class, base_class def maya_main_window(): main_window_ptr = omui.MQtUtil.mainWindow() return wrapInstance(long(main_window_ptr), QtWidgets.QWidget) def maya_api_version(): return int(cmds.about(api=True)) class MyDockingWindow(MayaQWidgetDockableMixin, QtWidgets.QMainWindow): MAYA2014 = 201400 MAYA2015 = 201500 MAYA2016 = 201600 MAYA2016_5 = 201650 MAYA2017 = 201700 def __init__(self, parent=None): self.deleteInstances() # remove any instance of this window before starting super(MyDockingWindow, self).__init__(parent) self.setWindowFlags(QtCore.Qt.Tool) """ compile the .ui file on loadUiType(), a function that uses pysideuic / pyside2uic to compile .ui files """ uiFile = os.path.join(os.path.dirname(__file__), 'MyDockingWindow_ui.ui') form_class, base_class = loadUiType(uiFile) self.ui = form_class() self.ui.setupUi(self) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) def dockCloseEventTriggered(self): self.deleteInstances() # Delete any instances of this class def deleteInstances(self): def delete2016(): # Go through main window's children to find any previous instances for obj in maya_main_window().children(): if str(type(obj)) == "<class 'maya.app.general.mayaMixin.MayaQDockWidget'>": # ""<class 'maya.app.general.mayaMixin.MayaQDockWidget'>": if obj.widget().__class__.__name__ == "MyDockingWindow": # Compare object names obj.setParent(None) obj.deleteLater() def delete2017(): ''' Look like on 2017 this needs to be a little diffrents, like in this function, However, i might be missing something since ive done this very late at night :) ''' for obj in maya_main_window().children(): if str(type(obj)) == "<class '{}.MyDockingWindow'>".format(os.path.splitext(os.path.basename(__file__)[0])): # ""<class 'moduleName.mayaMixin.MyDockingWindow'>": if obj.__class__.__name__ == "MyDockingWindow": # Compare object names obj.setParent(None) obj.deleteLater() if maya_api_version() < MyDockingWindow.MAYA2017: delete2016() else: delete2017() def deleteControl(self, control): if cmds.workspaceControl(control, q=True, exists=True): cmds.workspaceControl(control, e=True, close=True) cmds.deleteUI(control, control=True) # Show window with docking ability def run(self): ''' 2017 docking is a little different... ''' def run2017(): self.setObjectName("MyMainDockingWindow") # The deleteInstances() dose not remove the workspace control, and we need to remove it manually workspaceControlName = self.objectName() + 'WorkspaceControl' self.deleteControl(workspaceControlName) # this class is inheriting MayaQWidgetDockableMixin.show(), which will eventually call maya.cmds.workspaceControl. # I'm calling it again, since the MayaQWidgetDockableMixin dose not have the option to use the "tabToControl" flag, # which was the only way i found i can dock my window next to the channel controls, attributes editor and modelling toolkit. self.show(dockable=True, area='right', floating=False) cmds.workspaceControl(workspaceControlName, e=True, ttc=["AttributeEditor", -1], wp="preferred", mw=420) self.raise_() # size can be adjusted, of course self.setDockableParameters(width=420) def run2016(): self.setObjectName("MyMainDockingWindow") # on maya < 2017, the MayaQWidgetDockableMixin.show() magiclly docks the window next # to the channel controls, attributes editor and modelling toolkit. self.show(dockable=True, area='right', floating=False) self.raise_() # size can be adjusted, of course self.setDockableParameters(width=420) self.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) self.setMinimumWidth(420) self.setMaximumWidth(600) if maya_api_version() < MyDockingWindow.MAYA2017: run2016() else: run2017() def show(): ''' this is the funciton that start things up ''' global MyDockingWindow MyDockingWindow = MyDockingWindow(parent=maya_main_window()) MyDockingWindow.run() return MyDockingWindow
출처
https://gist.github.com/liorbenhorin/217bfb7e54c6f75b9b1b2b3d73a1a43a
Tab(QDockWidget) 형
''' Template class for docking a Qt widget to maya 2017+. Author: Lior ben horin 12-1-2017 ''' import weakref import maya.cmds as cmds import maya.OpenMayaUI as omui from shiboken2 import wrapInstance from Qt import QtGui, QtWidgets, QtCore # https://github.com/mottosso/Qt.py by Marcus Ottosson def dock_window(dialog_class): try: cmds.deleteUI(dialog_class.CONTROL_NAME) logger.info('removed workspace {}'.format(dialog_class.CONTROL_NAME)) except: pass # building the workspace control with maya.cmds main_control = cmds.workspaceControl(dialog_class.CONTROL_NAME, ttc=["AttributeEditor", -1],iw=300, mw=True, wp='preferred', label = dialog_class.DOCK_LABEL_NAME) # now lets get a C++ pointer to it using OpenMaya control_widget = omui.MQtUtil.findControl(dialog_class.CONTROL_NAME) # conver the C++ pointer to Qt object we can use control_wrap = wrapInstance(long(control_widget), QtWidgets.QWidget) # control_wrap is the widget of the docking window and now we can start working with it: control_wrap.setAttribute(QtCore.Qt.WA_DeleteOnClose) win = dialog_class(control_wrap) # after maya is ready we should restore the window since it may not be visible cmds.evalDeferred(lambda *args: cmds.workspaceControl(main_control, e=True, rs=True)) # will return the class of the dock content. return win.run() class MyDockingUI(QtWidgets.QWidget): instances = list() CONTROL_NAME = 'my_workspcae_control' DOCK_LABEL_NAME = 'my workspcae control' def __init__(self, parent=None): super(MyDockingUI, self).__init__(parent) # let's keep track of our docks so we only have one at a time. MyDockingUI.delete_instances() self.__class__.instances.append(weakref.proxy(self)) self.window_name = self.CONTROL_NAME self.ui = parent self.main_layout = parent.layout() self.main_layout.setContentsMargins(2, 2, 2, 2) # here we can start coding our UI self.my_label = QtWidgets.QLabel('hello world!') self.main_layout.addWidget(self.my_label) @staticmethod def delete_instances(): for ins in MyDockingUI.instances: logger.info('Delete {}'.format(ins)) try: ins.setParent(None) ins.deleteLater() except: # ignore the fact that the actual parent has already been deleted by Maya... pass MyDockingUI.instances.remove(ins) del ins def run(self): return self # this is where we call the window my_dock = dock_window(MyDockingUI)
출처
https://gist.github.com/liorbenhorin/69da10ec6f22c6d7b92deefdb4a4f475
- MayaDockingClass.py (6.6KB) (0)
댓글 0개
| 엮인글 0개
466개(9/24페이지)
번호 | 제목 | 글쓴이 | 조회 | 날짜 |
---|---|---|---|---|
마야 뷰포트 네비게이션 팁 | 푸딩뱃살 | 42293 | 2020.04.06 17:22 | |
Maya 버전 별 Python 버전 | 푸딩뱃살 | 63639 | 2014.01.08 17:59 | |
304 | [Script] Expression Editor에서 원하는 구간 프레임 홀드 | cgextra | 2117 | 2017.08.24 12:10 |
303 | [오류] Expression Editor Open Error | cgextra | 2366 | 2017.08.24 12:06 |
302 | [Modeling] Maya에서 Collision과 함께 익스포트 (for UE4) | 푸딩뱃살 | 4202 | 2017.08.24 11:58 |
301 | [Base] Grid(Unit) 설정 for UE4 | 푸딩뱃살 | 3814 | 2017.08.24 10:19 |
300 | [Script] 쉐이더 검색 | 푸딩뱃살 | 3483 | 2017.08.23 11:03 |
299 | [Script] scriptNode | 푸딩뱃살 | 3822 | 2017.08.22 18:08 |
298 | [Rendering] Maya 2017 Render Setup & Legacy Render Layer | cgextra | 3434 | 2017.08.08 12:12 |
297 | [Script] Maya 2017 Switching to PySide2 | 푸딩뱃살 | 4108 | 2017.07.13 17:26 |
296 | [Plugin] convertInstanceUE4 설치 | 푸딩뱃살 | 3596 | 2017.07.12 14:14 |
295 | [Base] LOD (Level of Detail) | 푸딩뱃살 | 3227 | 2017.07.06 11:53 |
294 | [Dev] PySide2 | 푸딩뱃살 | 3315 | 2017.07.05 17:55 |
>> | [Script] [펌] Maya 2017 PySide2 Docking Qt QMainWindow | 푸딩뱃살 | 4413 | 2017.07.05 14:54 |
292 | [Script] Maya 버전 구하기 | 푸딩뱃살 | 3161 | 2017.07.05 12:56 |
291 | [Dev] Maya 2017 Qt5 Designer 실행 시 오류 | 푸딩뱃살 | 3878 | 2017.07.02 20:59 |
290 | [Rigging] 스켈레톤(본) 기반 페이셜 리깅 구조 | 푸딩뱃살 | 2863 | 2017.06.29 12:55 |
289 | [Animation] Controller Nodes | 푸딩뱃살 | 3164 | 2017.06.09 11:12 |
288 | [Dev] sip / PyQt5 빌드 for Maya 2017 | 푸딩뱃살 | 5254 | 2017.05.31 12:46 |
287 | [Dev] Maya Python API 2.0 : 나의 첫 플러그인 Hello World! | 푸딩뱃살 | 4030 | 2017.05.19 18:48 |
286 | [Dev] Maya 2017은 Python 버젼 2.7.11 (64bit) | 푸딩뱃살 | 3459 | 2017.05.18 16:29 |
285 | [Dev] Maya devkit 설정 | 푸딩뱃살 | 3338 | 2017.05.18 14:23 |