Untitled

mail@pastecode.io avatar
unknown
plain_text
2 years ago
5.8 kB
2
Indexable
Never
'''
ScissorTool v1.0 by Jorrit Schulte

Add this to menu.py:
import  ScissorTool
'''

try:
    from PySide.QtGui import *
    from PySide.QtCore import *
except ImportError:
    from PySide2.QtWidgets import *
    from PySide2.QtCore import *
    from PySide2.QtGui import *
import nuke, threading, platform, time
from pyautogui import click

shortcut = 'z'

#switch that keeps the ui from reopening
canOpen = True

class Point:
    def __init__(self,x,y):
        self.x = x
        self.y = y

def ccw(A,B,C):
    return (C.y-A.y)*(B.x-A.x) > (B.y-A.y)*(C.x-A.x)

def intersect(A,B,C,D):
    return ccw(A,C,D) != ccw(B,C,D) and ccw(A,B,C) != ccw(A,B,D)

def DAGMousePos():
    click()
    for node in nuke.selectedNodes():
        node.setSelected(False)

    offset = nuke.toNode('preferences')['dot_node_scale'].value()*6
    dot = nuke.createNode("Dot", inpanel=False)
    coord = Point(dot.xpos()+offset, dot.ypos()+offset)
    nuke.delete(dot)
    return coord

class Panel(QWidget):
    finished = Signal()
    def __init__(self):
        super(Panel, self).__init__()
        #find active screen
        screen = QApplication.desktop().screenNumber(QApplication.desktop().cursor().pos())
        screenSize = QDesktopWidget().screenGeometry(screen)
        self.screenPos = QDesktopWidget().screenGeometry(screen).topLeft()

        #set window size
        self.resize(screenSize.width(),screenSize.height())
        self.move(self.screenPos.x(), self.screenPos.y())

        #make window transparent
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
        self.setAttribute(Qt.WA_NoSystemBackground)
        self.setAttribute(Qt.WA_TranslucentBackground)
        if platform.system() not in ['Darwin','Windows'] and nuke.NUKE_VERSION_MAJOR < 11:
            self.setAttribute(Qt.WA_PaintOnScreen)

        #initialise cursor position
        self.start = QCursor().pos() - self.screenPos
        self.mouse_position = self.start

        #set timer for cursor polling
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.pollCursor)
        self.timer.start()

        #install focus deactivation
        self.installEventFilter(self)

        #find initial DAG position, then open UI
        self.finished.connect(self.show)
        thread = threading.Thread(target=self.run)
        thread.daemon = True
        thread.start()

    def run(self):
        global parent
	#sleep a tiny amount to let the group context kick in
        time.sleep(0.001)
        with parent:
            self.a = DAGMousePos()
            self.finished.emit()

    #keeps the ui from reopening
    def keyPressEvent(self,event):
        if event.isAutoRepeat():
            return
    def keyReleaseEvent(self,event):
        if event.isAutoRepeat():
            return
        if event.text() == shortcut:
            self.closeWidget()
            return

    #focus deactivation
    def eventFilter(self, object, event):
        if event.type() in [QEvent.WindowDeactivate, QEvent.FocusOut] and not canOpen:
            self.closeWidget()
            return True
        return False

    #polling of the cursor
    def pollCursor(self):
        self.mouse_position = QCursor().pos() - self.screenPos
        self.update()

    #create the line
    def paintEvent(self, QPaintEvent):
        super(Panel, self).paintEvent(QPaintEvent)

        painter = QPainter(self)
        pen = QPen(QColor(200,0,0))
        pen.setWidth(2)
        pen.setStyle(Qt.DotLine)
        painter.setPen(pen)
        painter.setRenderHint(QPainter.Antialiasing)

        line = QLine(self.start, self.mouse_position)
        painter.drawLine(line)

    def cut(self):
        global parent
        with parent:
            undo = nuke.Undo()
            undo.begin("Scissor Tool")

            #define starting point and get end point scissor line
            a = self.a
            b = DAGMousePos()

            #find all connections
            for nodeA in nuke.allNodes():
                connections = nodeA.dependencies(nuke.INPUTS)

                if len(connections) > 0:
                    c = Point(nodeA.xpos()+(nodeA.screenWidth()/2),nodeA.ypos()+(nodeA.screenHeight()/2))

                    for nodeB in connections:
                        d = Point(nodeB.xpos()+(nodeB.screenWidth()/2),nodeB.ypos()+(nodeB.screenHeight()/2))
                        #check for intersection with scissor line
                        if intersect(a,b,c,d):
                            for i in range(nodeA.inputs()):
                                #disconnect if current input is connected to other node
                                if nodeA.input(i) is nodeB:
                                    nodeA.setInput(i, None)
            undo.end()

    def closeWidget(self):
        global canOpen
        canOpen = True
        #stop the polling timer
        self.timer.stop()
        #close widget
        self.close()
        #run intersect code
        thread = threading.Thread(target=self.cut)
        thread.daemon = True
        thread.start()
        return

def run():
    global canOpen
    if canOpen:
        #create dot to find group context
        contextDot = nuke.createNode("Dot", inpanel=False)
        fnn = contextDot.fullName().split('.')
        groupName = 'root.'
        for i in range(len(fnn)-1):
            groupName += fnn[i] + '.'
        #get parent
        global parent
        if groupName != 'root.':
            parent = nuke.toNode(groupName[:-1])
        else:
            parent = nuke.root()

        #initialize panel
        run.panel = Panel()
        #turns off canOpen so the ui doesnt reopen
        canOpen = False
        #delete dot again
        nuke.delete(contextDot)

menubar = nuke.menu('Nuke')
menubar.addCommand('@;Scissor tool', run , shortcut)