회원 로그인
|
[펌] 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개(1/24페이지)
번호 | 제목 | 글쓴이 | 조회 | 날짜 |
---|---|---|---|---|
마야 뷰포트 네비게이션 팁 | 푸딩뱃살 | 41834 | 2020.04.06 17:22 | |
Maya 버전 별 Python 버전 | 푸딩뱃살 | 63239 | 2014.01.08 17:59 | |
464 | [Dev] Autodesk Maya Devkit 다운로드 | 푸딩뱃살 | 672 | 2023.01.28 14:28 |
463 | [Base] (해결 중) modules 환경설정 중 | 푸딩뱃살 | 599 | 2022.11.09 11:47 |
462 | [Script] pymel 딕셔너리형 사용 시 KeyError | 푸딩뱃살 | 801 | 2022.11.07 12:08 |
461 | [오류] Building Numpy for Maya Python 2.7.x | 푸딩뱃살 | 570 | 2022.10.23 14:38 |
460 | [Base] 뷰포트에서 조절자가 안 보일때 | 푸딩뱃살 | 731 | 2022.10.13 15:47 |
459 | [Rigging] mirror joints 사용 시 유의 사항 | 푸딩뱃살 | 734 | 2022.10.04 10:46 |
458 | [Script] 2022에서 enum34 모듈 설치 금지 | 푸딩뱃살 | 584 | 2022.08.17 18:08 |
457 | [Script] pymel 예제 | 푸딩뱃살 | 605 | 2022.07.05 19:20 |
456 | [Script] 인코드 / 디코드 - 2.7 한글 사용 | 푸딩뱃살 | 868 | 2022.03.08 17:52 |
455 | [Dev] ui 없이 mayapy로 자동화 | 푸딩뱃살 | 673 | 2022.02.17 13:56 |
454 | [Dev] mayapy로 ui파일 py로 | 푸딩뱃살 | 512 | 2022.02.15 18:20 |
453 | [오류] Error : MayaBonusTools | 푸딩뱃살 | 879 | 2022.01.21 17:52 |
452 | [오류] Error: ModuleNotFoundError | 푸딩뱃살 | 742 | 2022.01.21 16:24 |
451 | [Dev] mayapy | 푸딩뱃살 | 619 | 2022.01.19 20:08 |
450 | [Base] function selCom at 0x7f29c5c04aa0 | 푸딩뱃살 | 585 | 2022.01.19 17:24 |
449 | [Base] wireframe on shaded 단축키 만들기 | 푸딩뱃살 | 869 | 2022.01.04 10:55 |
448 | [오류] OpenCL Error | 푸딩뱃살 | 505 | 2021.12.28 01:40 |
447 | [Script] Easily Translate MEL Commands to Python | 푸딩뱃살 | 792 | 2021.12.02 11:22 |
446 | [Base] output window 띄우지 않기 | 푸딩뱃살 | 771 | 2021.11.24 21:44 |
445 | [Rigging] shapeEditorManager 삭제 안됨 | 푸딩뱃살 | 846 | 2021.11.12 23:30 |