Untitled

mail@pastecode.io avatar
unknown
plain_text
2 years ago
8.9 kB
1
Indexable
import nuke

import math



def ConcatTransform_getMatrix(node, frame=nuke.frame()):

    if node.Class() == 'Transform':

        t = node['translate'].valueAt(frame)

        r = node['rotate'].valueAt(frame)

        sc = node['scale'].valueAt(frame)

        if type(sc) is float:

            sc = [sc,sc]

        sx = node['skewX'].valueAt(frame)

        sy = node['skewY'].valueAt(frame)

        p = node['center'].valueAt(frame)



        #pivot

        pivot = nuke.math.Matrix4()

        pivot.makeIdentity()

        pivot.translate(-p[0],-p[1],0)

        pivot.transpose()

        inv = pivot.inverse()



        #transform

        matrix = nuke.math.Matrix4()

        matrix.makeIdentity()

        matrix.translate(t[0],t[1],0)

        matrix.rotateZ((math.pi/180)*r)

        if node['skew_order'].value() == 'XY':

            matrix.skewXY(sx,sy)

        else:

            matrix.skewXY(0,sy)

            matrix.skewXY(sx,0)

        matrix.scale(sc[0],sc[1],1)

        matrix.transpose()



        matrix = pivot*matrix*inv



        if node['invert_matrix'].value():

            matrix = matrix.inverse()



        return matrix



    elif node.Class() == 'CornerPin2D':

        to1x, to1y = node['to1'].valueAt(frame)

        to2x, to2y = node['to2'].valueAt(frame)

        to3x, to3y = node['to3'].valueAt(frame)

        to4x, to4y = node['to4'].valueAt(frame)

        from1x, from1y = node['from1'].valueAt(frame)

        from2x, from2y = node['from2'].valueAt(frame)

        from3x, from3y = node['from3'].valueAt(frame)

        from4x, from4y = node['from4'].valueAt(frame)

        To = nuke.math.Matrix4()

        From = nuke.math.Matrix4()



        To.mapUnitSquareToQuad(to1x,to1y,to2x,to2y,to3x,to3y,to4x,to4y)

        From.mapUnitSquareToQuad(from1x,from1y,from2x,from2y,from3x,from3y,from4x,from4y)

        matrix = To*From.inverse()

        matrix.transpose()



        extraMatrix = nuke.math.Matrix4()

        for index, value in enumerate(node['transform_matrix'].getValueAt(frame)):

            extraMatrix[index] = value

        matrix = matrix*extraMatrix



        if node['invert'].value():

            matrix = matrix.inverse()



        return matrix



def ConcatTransform_concatMatrix(node, frame=nuke.frame()):

    #collect transforms

    look = True

    un = node.input(1)

    tn = []



    while look:

        if un is None:

            look = False

        elif un.Class() in ['Dot', 'NoOp']:

            un = un.input(0)

        elif un.Class() == 'Switch':

            un = un.input(int(un['which'].valueAt(frame)))

        elif un.Class() in ['Transform', 'CornerPin2D']:

            if not un['disable'].valueAt(frame):

                tn.append(un)

            un = un.input(0)

        else:

            look = False

    tn = list(reversed(tn))



    #return identity matrix if no nodes found

    if len(tn) == 0:

        matrix = nuke.math.Matrix4()

        matrix.makeIdentity()

        return matrix



    #get concatinated matrix

    matrix = ConcatTransform_getMatrix(tn[0], frame)

    for i in tn[1:]:

        matrix = matrix * ConcatTransform_getMatrix(i, frame)



    #compensate for ref frame

    if node['use'].value():

        rframe = int(node['ref'].value())

        refMatrix = ConcatTransform_getMatrix(tn[0], rframe)

        for i in tn[1:]:

            refMatrix = refMatrix * ConcatTransform_getMatrix(i, rframe)

        refMatrix = refMatrix.inverse()

        matrix = matrix * refMatrix



    #invert if wanted

    if node['invert'].value():

        matrix = matrix.inverse()



    return matrix



def ConcatTransform_detectCP(node):

    look = True

    un = node.input(1)

    cornerpin = False

    while look:

        if un is None:

            look = False

        elif un.Class() in ['Dot', 'NoOp', 'Transform']:

            un = un.input(0)

        elif un.Class() == 'Switch':

            un = un.input(int(un['which'].valueAt(frame)))

        elif un.Class() == 'CornerPin2D':

            if un['disable'].value():

                un = un.input(0)

            else:

                cornerpin = True

                look = False

        else:

            look = False



    return cornerpin



def run():

    node = nuke.thisNode()

    width = node.width()

    height = node.height()



    #determine whether to create a Transform or CornerPin

    op = node['outputNode'].value()

    if op == 'CornerPin':

        cornerpin = True

    elif op == 'Transform':

        if ConcatTransform_detectCP(node) and not nuke.ask('A CornerPin is detected upstream, a transform might not be able to faithfully recreate the resulting matrix. continue?'):

            return

        cornerpin = False

    elif op == 'Detect':

        cornerpin = ConcatTransform_detectCP(node)



    #set range

    if node['noAnim'].value():

        frames = [nuke.frame()]

    else: #multiple frames

        start = int(nuke.root()['first_frame'].value())

        end = int(nuke.root()['last_frame'].value())



        retu = nuke.getFramesAndViews('bake range', str(start) + '-' + str(end))

        try:

            r = [int(i) for i in retu[0].split('-')]

            frames = range(r[0],r[1])

        except:

            return



    #find group name if node is in group

    fnn = node.fullName().split('.')

    groupName = 'root.'

    for i in range(len(fnn)-1):

        groupName += fnn[i] + '.'

    #get parent

    if groupName != 'root.':

        parent = nuke.toNode(groupName[:-1])

    else:

        parent = nuke.root()



    with parent:

        if cornerpin:

            #create CornerPin

            cp = nuke.nodes.CornerPin2D()

            cp['xpos'].setValue(node['xpos'].value()+100)

            cp['ypos'].setValue(node['ypos'].value()+50)

            cp['from2'].setValue([width,0])

            cp['from3'].setValue([width,height])

            cp['from4'].setValue([0,height])

            cp.showControlPanel()

            if not node['noAnim'].value():

                cp['to1'].setAnimated()

                cp['to2'].setAnimated()

                cp['to3'].setAnimated()

                cp['to4'].setAnimated()



            #convert matrix to cornerpin values

            for frame in frames:

                matrix = ConcatTransform_concatMatrix(node, frame)

                matrix.transpose()



                v1 = nuke.math.Vector4(0, 0, 0, 1)

                v1 = matrix.transform(v1)

                v1 /= v1.w

                v2 = nuke.math.Vector4(width, 0, 0, 1)

                v2 = matrix.transform(v2)

                v2 /= v2.w

                v3 = nuke.math.Vector4(width, height, 0, 1)

                v3 = matrix.transform(v3)

                v3 /= v3.w

                v4 = nuke.math.Vector4(0, height, 0, 1)

                v4 = matrix.transform(v4)

                v4 /= v4.w

                for i in range(2):

                    cp['to1'].setValueAt(v1[i], frame, i)

                    cp['to2'].setValueAt(v2[i], frame, i)

                    cp['to3'].setValueAt(v3[i], frame, i)

                    cp['to4'].setValueAt(v4[i], frame, i)

        else:

            #create Transform node

            t = nuke.nodes.Transform()

            t['xpos'].setValue(node['xpos'].value()+100)

            t['ypos'].setValue(node['ypos'].value()+50)

            t['center'].setValue([width/2,height/2])

            t.showControlPanel()

            if not node['noAnim'].value():

                t['translate'].setAnimated()

                t['rotate'].setAnimated()

                t['scale'].setAnimated()

                t['skewX'].setAnimated()



            #convert matrix to transform values

            for frame in frames:

                matrix = ConcatTransform_concatMatrix(node, frame)

                matrix.transpose()



                vector = nuke.math.Vector3(width/2, height/2, 0)

                vector_trans = matrix.transform(vector)

                delta = (matrix[0] * matrix[5]) - (matrix[4] * matrix[1])

                r = pow(matrix[0], 2) + pow(matrix[1], 2)



                translate_x = vector_trans[0] - width/2

                translate_y = vector_trans[1] - height/2

                rotation = math.degrees(math.atan2(matrix[1], matrix[0]))

                scale_x = math.sqrt(r)

                scale_y = delta / scale_x

                skew_x = (matrix[0] * matrix[4] + matrix[1] * matrix[5]) / delta



                t['translate'].setValueAt(translate_x, frame, 0)

                t['translate'].setValueAt(translate_y, frame, 1)

                t['rotate'].setValueAt(rotation, frame)

                t['scale'].setValueAt(scale_x, frame, 0)

                t['scale'].setValueAt(scale_y, frame, 1)

                t['skewX'].setValueAt(skew_x, frame)