一半君的总结纸

听话只听一半君

如何在鼠标中键拖动maya时间滑条的过程中触发事件?

目的是在鼠标中键拖动时间滑条的时候触发事件,执行一些操作(基于拖动到的帧数)

首先当然是看了下最简单的scriptJob有没有,虽然有timeChanged event,但是他是当你真的改变了时间(使用中键拖动并放手之后才触发,lz想要的是还没放手之前就触发)

  • 方法一,脑残法
    由于现在整个界面都是qt的了,所以可以找到timecontrol对应的qobject,然后给他加个eventfilter,看按键是不是中键,以及拖到哪里了,当然此方法属于乱搞,如果实在没有api能做到的时候才会出此下策,肯定性能最差,不推荐,记录在此以备参考

    正常情况下(未胡乱修改maya ui的前提下)只有一个时间滑条,可以如下判定

    mc.lsUI(type='timeControl')
    # Result: [u'timeControl1'] #
    

    因此,可以

    import sip
    from PyQt4 import QtGui, QtCore
    import maya.OpenMayaUI as apiUI
    
    
    def toQtObject(mayaName):
        """
        Convert a Maya ui path to a Qt object
        @param mayaName: Maya UI Path to convert (Ex: "scriptEditorPanel1Window|TearOffPane|scriptEditorPanel1|testButton" )
        @return: PyQt representation of that object
        """
        ptr = apiUI.MQtUtil.findControl(mayaName)
        if ptr is None:
            ptr = apiUI.MQtUtil.findLayout(mayaName)
        if ptr is None:
            ptr = apiUI.MQtUtil.findMenuItem(mayaName)
        if ptr is not None:
            return sip.wrapinstance(long(ptr), QtCore.QObject)
    
    timectrl = 'timeControl1'
    timectrl_obj = toQtObject(timectrl)
    
    timectrl_obj.rect()
    
    
    class MyEventFilter(QtCore.QObject):
    
        def __init__(self, *args):
            super(MyEventFilter, self).__init__(*args)
            self._frame = None
    
        def eventFilter(self, obj, event):
            if obj == timectrl_obj:
                if(event.type() == QtCore.QEvent.MouseMove):
                    if event.buttons() == QtCore.Qt.MidButton:
                        start, end = mc.playbackOptions(
                            q=1, min=1), mc.playbackOptions(q=1, max=1)
                        _, _, w, _ = timectrl_obj.rect().getCoords()
                        range = end-start+1
                        frame = int(event.pos().x()*1.0/w * range + start)
                        if self._frame == frame:
                            pass
                        else:
                            print 'yeah dragging, current frame: %s' % frame
                            self._frame = frame
    
            # Call Base Class Method to Continue Normal Event Processing
            return super(MyEventFilter, self).eventFilter(obj, event)
    
    
    filter = MyEventFilter()
    
    timectrl_obj.installEventFilter(filter)
    
    # timectrl_obj.removeEventFilter(filter)
    

    上面是看拖的时候,鼠标的坐标(以timeControl的坐上角为原点),计算出当前的x占整个滑条长度的比例,从而得到当前frame,其中self._frame是为了避免多次触发事件,因为鼠标可能在同一个frame上触发多次事件,想也知道这很脑残,不过这显示了一种乱搞的可能

  • 方法2,正规法,使用OpenMaya.MDGMessage.addTimeChangeCallback

    当然使用api才是正解,其中用qApp.mouseButtons()判断是不是鼠标中键

    import maya.OpenMaya as om
    import maya.cmds as mc
    from PyQt4 import QtCore, QtGui
    
    callbacks = []
    
    def do_something(*args):
        if QtGui.qApp.mouseButtons()==QtCore.Qt.MidButton:
            print "yeah dragging:",mc.currentTime(q=1)
    
    def main():
        global callbacks
        idx = om.MDGMessage.addTimeChangeCallback(do_something)
        callbacks.append(idx)
    
    def remove_callbacks():
        for call in callbacks:
            om.MMessage.removeCallback(call)
    
    main()
    
    # remove_callbacks()
    
  • 此外,还有个可以考虑的是OpenMaya.MEventMessage.addEventCallback,但是他好像只有鼠标左键拖动时候才会触发

参考:
Guide to PyQt/PySide in Maya (Pt. 1) –
Nathan Horne – Technical Artist

Advertisements

2 responses to “如何在鼠标中键拖动maya时间滑条的过程中触发事件?

  1. wen 十月 24, 2016 @ 4:12 下午

    只要有对应数据流改变,maya内部时间事件就会相应
    更简单的办法,建一个locator, 把其某一属性和时间相联,时间条改变就会获被驱动(实时响应,不需要松鼠标)
    具体步骤
    1 建一个locator
    2 给这个locator 写一个时间相关的表达式 expressions
    locator1.scaleY = time*1;
    print (`currentTime -q` + “\n”);

    3拖动时间条就会被驱动,至少win平台下如此
    然后通过 属性改变事件 驱动你要驱动的东西

  2. 一半君 十月 24, 2016 @ 4:29 下午

    好办法 我明天试试. 可是我最终目的是把当前frame发送到用socket连到maya里的socket server上的外部播放器,如果像这样不是很好写(我要触发的event是运行一些python代码),所以最后还是用了MDGMessage

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

%d 博主赞过: