Untitled

 avatar
unknown
python
a year ago
12 kB
4
Indexable

import hou, nodegraph, os, sys
from collections import defaultdict
from canvaseventtypes import *
from utility_ui import getSessionVariable, setSessionVariable
import utility_generic
import utility_hotkey_system
import traceback
from PySide2 import QtCore, QtWidgets, QtGui
import nodegraphutils as utils
import nodegraphbase as base
import nodegraphstates as states
import importlib

try:
    from utility_overlay_network_editor import setOverlayNetworkEditorVisible
except:
    pass



this = sys.modules[__name__]
currentdir = os.path.dirname(os.path.realpath(__file__))

def __reload_pythonlibs(showstatus=True):
    if showstatus:
        print ("Reloading hotkey system...")

    importlib.reload(this)
    importlib.reload(utility_hotkey_system)

fs_watcher = QtCore.QFileSystemWatcher()
fs_watcher.addPath(os.path.join(currentdir, "nodegraphhooks.py"))
fs_watcher.addPath(os.path.join(currentdir, "utility_hotkey_system.py"))


fs_watcher.fileChanged.connect(__reload_pythonlibs)



class CustomViewPanHandler(base.EventHandler):
    def __init__(self, start_uievent):
        base.EventHandler.__init__(self, start_uievent)
        self.startbounds = start_uievent.editor.visibleBounds()
        self.olddefaultcursor = start_uievent.editor.defaultCursor()
        self.start_uievent.editor.setDefaultCursor(utils.theCursorPan)

    def handleEvent(self, uievent, pending_actions):
        if uievent.eventtype == 'mousedrag':# and delay >= hou.session.MMBSelectNearestNodeTimeLimit * 0.3:
            dist = uievent.mousestartpos - uievent.mousepos
            dist = uievent.editor.sizeFromScreen(dist)
            bounds = hou.BoundingRect(self.startbounds)
            bounds.translate(dist)
            uievent.editor.setVisibleBounds(bounds)
            return self

        # Select Nearest Node using MMB
        elif uievent.eventtype == 'mouseup':
            self.start_uievent.editor.setDefaultCursor(self.olddefaultcursor)
            if hou.session.UseMMBToSelectNearestNode and self.start_uievent.mousestate.mmb:
                delay = uievent.time - hou.session.mouseDownEventTime
                if delay < hou.session.MMBSelectNearestNodeTimeLimit:
                    # Restore network editor visible bounds back because it's not a panning event
                    uievent.editor.setVisibleBounds(hou.session.networkEditorVisibleBounds)
                    utility_generic.selectNearestNode(uievent)
                    return None

            return None

        # Keep handling events until the mouse button is released.
        return self



class CustomBackgroundMouseHandler(base.EventHandler):
    def handleEvent(self, uievent, pending_actions):
        if uievent.eventtype == 'mousedrag':
            handler = None
            if self.start_uievent.mousestate.lmb:
                handler = states.BoxPickHandler(self.start_uievent, True)
            elif base.isPanEvent(self.start_uievent):
                if hou.session.UseMMBToSelectNearestNode:
                    handler = base.CustomViewPanHandler(self.start_uievent)
                else:
                    handler = base.ViewPanHandler(self.start_uievent)
            elif base.isScaleEvent(self.start_uievent):
                handler = base.ViewScaleHandler(self.start_uievent)
            if handler:
                return handler.handleEvent(uievent, pending_actions)

        elif uievent.eventtype == 'mouseup':
            # Select Nearest Node using MMB
            if hou.session.UseMMBToSelectNearestNode and self.start_uievent.mousestate.mmb:
                delay = uievent.time - hou.session.mouseDownEventTime
                if delay < hou.session.MMBSelectNearestNodeTimeLimit:
                    utility_generic.selectNearestNode(uievent)
                    return None

            if self.start_uievent.mousestate.lmb:
                with hou.undos.group('Clear selection', uievent.editor):
                    uievent.editor.clearAllSelected()

            elif self.start_uievent.mousestate.rmb:
                uievent.editor.openTabMenu(key = utils.getDefaultTabMenuKey(uievent.editor))

            return None

        # deselect TOP workitems
        elif uievent.eventtype == 'mousedown':
            if self.start_uievent.mousestate.lmb:
                pwd = uievent.editor.pwd()
                if isinstance(pwd, hou.OpNode):
                    pwd.deselectWorkItem()

        # Select Nearest Node using LMB
        elif uievent.eventtype == 'doubleclick':
            if hou.session.UseLMBToSelectNearestNode and self.start_uievent.mousestate.lmb:
                utility_generic.selectNearestNode(uievent)
                return None

        # Keep handling events until the mouse is dragged, or the mouse button
        # is released.
        return self



class BoxPickHandler(base.EventHandler):
    def __init__(self, start_uievent, set_cursor = False):
        base.EventHandler.__init__(self, start_uievent)
        # Remember the node-space position of where the box starts.
        self.start_pos = start_uievent.mousestartpos
        self.start_pos = start_uievent.editor.posFromScreen(self.start_pos)
        self.set_cursor = set_cursor
        if set_cursor:
            self.oldcursormap = start_uievent.editor.cursorMap()
            self.olddefaultcursor = start_uievent.editor.defaultCursor()
            start_uievent.editor.setCursorMap({})
            self.setSelectCursor(start_uievent)

    def getItemsInBox(self, items):
        items = list(item[0] for item in items)
        # If we have any non-wires in the box, ignore the wires.
        has_non_wire = any((not isinstance(item, hou.NodeConnection)
                            for item in items))
        if has_non_wire:
            items = list(item for item in items
                         if not isinstance(item, hou.NodeConnection))
            # Select box picked nodes in visual order.
            if utils.isNetworkHorizontal(items[0].parent()):
                items.sort(key = lambda item : -item.position().y())
            else:
                items.sort(key = lambda item : item.position().x())

        return items

    def setSelectCursor(self, uievent):
        if self.set_cursor:
            if isinstance(uievent, MouseEvent) or \
               isinstance(uievent, KeyboardEvent):
                if uievent.modifierstate.ctrl and uievent.modifierstate.shift:
                    cursor = utils.theCursorSelectToggle
                elif uievent.modifierstate.ctrl:
                    cursor = utils.theCursorSelectRemove
                elif uievent.modifierstate.shift:
                    cursor = utils.theCursorSelectAdd
                else:
                    cursor = utils.theCursorSelect
                uievent.editor.setDefaultCursor(cursor)

    def handleBoxPickComplete(self, items, uievent):
        view.modifySelection(uievent, None, items)

    def handleEvent(self, uievent, pending_actions):
        # Set the current selection cursor based on our modifier key states.
        self.setSelectCursor(uievent)

        # Check if the user wants to enter the scroll state.
        if isScrollStateEvent(uievent):
            return ScrollStateHandler(uievent, self)

        if uievent.eventtype == 'mousedrag':
            autoscroll.startAutoScroll(self, uievent, pending_actions)
            # Convert the node space position to a screen-space position for
            # the starting point of the box (which may be outside the visible
            # area of the view).
            pos1 = uievent.editor.posToScreen(self.start_pos)
            pos2 = uievent.editor.screenBounds().closestPoint(uievent.mousepos)
            rect = hou.BoundingRect(pos1, pos2)
            pickbox = hou.NetworkShapeBox(rect,
                            hou.ui.colorFromName('GraphPickFill'), 0.3,
                            True, True)
            pickboxborder = hou.NetworkShapeBox(rect,
                            hou.ui.colorFromName('GraphPickFill'), 0.8,
                            False, True)
            self.editor_updates.setOverlayShapes([pickbox, pickboxborder])
            items = uievent.editor.networkItemsInBox(pos1,pos2,for_select=True)
            items = self.getItemsInBox(items)
            uievent.editor.setPreSelectedItems(items)
            return self

        elif uievent.eventtype == 'mouseup':
            pos1 = uievent.editor.posToScreen(self.start_pos)
            pos2 = uievent.editor.screenBounds().closestPoint(uievent.mousepos)
            items = uievent.editor.networkItemsInBox(pos1,pos2,for_select=True)
            items = self.getItemsInBox(items)
            uievent.editor.setPreSelectedItems(())
            self.handleBoxPickComplete(items, uievent)
            if self.set_cursor:
                uievent.editor.setCursorMap(self.oldcursormap)
                uievent.editor.setDefaultCursor(self.olddefaultcursor)
            return None

        # Keep handling events until the mouse button is released.
        return self



def createEventHandler(uievent, pending_actions):
    if not isinstance(uievent.editor, hou.NetworkEditor):
        return None, False


    if uievent.eventtype == 'mousedown' and uievent.selected.item is None and not uievent.selected.name.startswith('overview'):
        hou.session.networkEditorVisibleBounds = uievent.editor.visibleBounds()
        hou.session.mouseDownEventTime = uievent.time
        return CustomBackgroundMouseHandler(uievent), True

    # if uievent.eventtype == 'mousemove':
    #     currentnode = uievent.editor.currentNode()
    #     a = uievent.located.item
    #     if a:
    #         noderect = uievent.editor.itemRect(a)
    #         #print (uievent.located.item)
    #         s1 = hou.NetworkShapeNodeShape(noderect, 'rect')

    #         uievent.editor.setShapes([s1])


    if getSessionVariable("useRMBToSelectDisplayNodes") and uievent.eventtype == 'mousedown' and uievent.mousestate.rmb:
        node = uievent.selected.item
        
        if node and not isinstance(node, hou.NodeConnection) and not isinstance(node, hou.NetworkDot) and not isinstance(node, hou.OpSubnetIndirectInput):
            category = node.type().category().name()
            if category in hou.nodeTypeCategories().keys() and category != "Vop":
                if uievent.modifierstate.ctrl:
                    if uievent.modifierstate.shift:
                        utility_generic.selectableTemplateNearestNodeInEditor(nearestNode=node)
                    if uievent.modifierstate.alt:
                        utility_generic.bypassNearestNodeInEditor(nearestNode=node)
                    else:
                        utility_generic.templateNearestNodeInEditor(nearestNode=node)
                elif uievent.modifierstate.shift:
                    utility_generic.displayNearestNodeInEditor(nearestNode=node)
                elif uievent.modifierstate.alt:
                    utility_generic.showNodeMenuNearestNodeInEditor()
                else:
                    utility_generic.selectDisplayNearestNodeInEditor(nearestNode=node)


                return None, True



    if isinstance(uievent, KeyboardEvent):
        key = utility_generic.getUnshiftedKey(uievent.key, uievent.modifierstate)
        
        if hou.session.useVolatileSpaceToToggleNetworkEditor:
            hou.session.spaceKeyIsDown = uievent.editor.isVolatileHotkeyDown('h.pane.wsheet.view_mode')
        #print("space is down:", uievent.editor.isVolatileHotkeyDown('h.pane.wsheet.view_mode'))

        if uievent.eventtype == 'keyhit':
            return utility_hotkey_system.invokeActionFromKey(uievent)

    return None, False
Editor is loading...
Leave a Comment