# Sample scripts in this file are not supported under any Autodesk standard support program or service.
# The sample scripts are provided without warranty of any kind.
# Autodesk disclaims all implied warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose.
# The entire risk arising out of the use or performance of the sample scripts and documentation remains with you.

from math import sqrt
import time
import socket
import urllib

ipAdresse = "192.168.0.102"

#----------------------------------------------------------------------
# GLOBALS

# These are the 2 objects showing tools and menus on your own hands
rightNode = findNode("MatrixRight") #controller1 is right
leftNode = findNode("MatrixLeft")   #controller0 is left

#here is the local ClipNode
clipNode1 = findNode("ClipPlane1")
clipNode2 = findNode("ClipPlane2")
comparisionPlane = findNode("Comparision_Plane")
comparisionCar = findNode("Comparision_Car")

# More global nodes for crazy cool menu by Simon
flashlight=findNode("Light_ON")
menuRotate=findNode("MenuRotate")
menuScale =findNode("MenuScale")

tool = 0
toolCounter = 0
rulerRotation = 0
clay = 0
interleaved = 1
scaleMode=0
soundState=0
cfdState=0

postItRoot = findNode("PostIt_Root")    # postit container
markerRoot = findNode("Marker_Root")    # drwaing container
posDraw = Pnt3f()
doDraw = false

#----------------------------------------------------
# Collaboration
# Define sync interval timer object (seconds)
timerSync = vrTimer(0.2)
timerSync.setActive(false)

# Stop sync timer with W key
keyW = vrKey(Key_W)
keyW.connect("sendSync(false)")

# Start sync timer with S key
keyS = vrKey(Key_S)
keyS.connect("sendSync(true)")

#Reset scene with R
keyR = vrKey(Key_R)
keyR.connect("resetScene()")

def sendSync(state):
    timerSync.setActive(state)
    colNode = findNode("Collaboration")
    colNode.setActive(state)

# Dummy transforms
nodevrsync_0 = findNode("vrsync_0")
nodevrsync_1 = findNode("vrsync_1")
nodevrsync_head = findNode("vrsync_head")


# Function to execute a command on the remote machine
def sendVredCmd(cmd):
    cmd = urllib.quote(cmd)
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((ipAdresse, 8888))
    s.send("GET /pythonasync?value=" + cmd + " HTTP/1.1\r\n\r\n")
    s.close()

# Sync timer event fires - send transforms of the 3 objects
timerSync.connect("sendTransforms()")

# Read the 3 local transforms and send to other machine, 3 lists with 16 values each
def sendTransforms():
    global nodevrsync_0
    global nodevrsync_1
    global nodevrsync_head

    nodevrsync_0.setTransformMatrix( controller0.getWorldMatrix(), false)
    nodevrsync_1.setTransformMatrix( controller1.getWorldMatrix(), false)
    nodevrsync_head.setTransformMatrix( getCamNode(-1).getWorldTransform(), false)

    # print nodevrsync_head.getWorldTransform()

    sendVredCmd("updateOther(" + str(nodevrsync_head.getWorldTransform()) + "," + str(nodevrsync_0.getWorldTransform()) + "," + str(nodevrsync_1.getWorldTransform()) + ")")

# These are the 3 objects showing what your partner does
nodeBrotherHead = findNode("Other_Head_Transform")
nodeBrotherLeft = findNode("Other_Left_Transform")
nodeBrotherRight = findNode("Other_Right_Transform")

# Function called over the web API transmitting the 3 matrixes
def updateOther(h,l,r):
    # print h
    nodeBrotherHead.setTransformMatrix(h, false)
    nodeBrotherLeft.setTransformMatrix(l, false)
    nodeBrotherRight.setTransformMatrix(r, false)

#----------------------------------------------------------------------
# KEYBOARD SHORTCUTS

keyR = vrKey(Key_R) # Reset the scene
keyR.connect("resetScene()")

keyD = vrKey(Key_D) # Set display to Vive
keyD.connect("setDisplayMode(VR_DISPLAY_OPEN_VR); resetScene()")

keyE = vrKey(Key_E) # Set display back to standard
keyE.connect("setDisplayMode(VR_DISPLAY_STANDARD)")


#----------------------------------------------------------------------
# TOOLS

timer = vrTimer(0.1)     # drawing timer
timer.setActive(false)

def drawLine(): #drawing a simple line
    global markerRoot
    global posDraw
    global doDraw
    posnewDraw = Pnt3f()

    print ("drawline called: ", doDraw)

    c1Matrix = controller1.getWorldMatrix()
    print("Pos from matrix: ", c1Matrix[3], c1Matrix[7], c1Matrix[11])
    posnewDraw = Pnt3f( c1Matrix[3], c1Matrix[7], c1Matrix[11])

    if(doDraw):
        newLine = createLine(posDraw.x(), posDraw.y(), posDraw.z(), posnewDraw.x(), posnewDraw.y(), posnewDraw.z(), 1, 0, 0)
        markerRoot.addChild(newLine)  # add line under the draw transform
        print("line drawn: ", posDraw.x(), posDraw.y(), posDraw.z(), posnewDraw.x(), posnewDraw.y(), posnewDraw.z())

    posDraw = posnewDraw        # current end point becomes new line starting point
    doDraw = true

def deleteLines():
    global markerRoot
    while markerRoot.getNChildren():
        markerRoot.subChild(markerRoot.getChild(0))

def deletePostits():
    global postItRoot
    while postItRoot.getNChildren():
        postItRoot.subChild(postItRoot.getChild(0))


#----------------------------------------------------------------------
# VIVE CONTROLLER CALLBACKS

#----------------------------------------------------------------------
# Touchsensor Trigger
def triggerSensor( node):
    if node.hasAttachment("TouchSensorAttachment"):
        touchAttachment = node.getAttachment("TouchSensorAttachment")
        acc = vrFieldAccess(touchAttachment)
        if acc.isValid():
            variantSetName = acc.getMString("variantSets")
            for vset in variantSetName:
                selectVariantSet(vset)
                controller1.triggerHapticPulse(0,1000)
        return
    parentNode = node.getParent()
    if parentNode.isValid():
        triggerSensor( parentNode)

#----------------------------------------------------------------------
# HTC VIVE Buttons

def trigger0Pressed():
    controller0.setPickingAxis(0)

def trigger0Released():
    controller0.showPickingAxis(false)
    selectVariantSet("Menu_On")

def grip0Pressed():
    selectNode(getSelectedNode(), false)

def grip0Released():
    print("grip0Released")
    oldPosMenuRotate =getTransformNodeRotation(menuRotate)
    setTransformNodeRotation(menuRotate, 0, 0, oldPosMenuRotate.z()-90)

def touchpad0Pressed():
    print("touchpad0Pressed")

def touchpad0Released():
    print("touchpad0Released")

def touchpad0PositionChanged(position):
    print("touchpad0PositionChanged")

def controller0Moved():
    leftNode.setTransformMatrix( controller0.getWorldMatrix(), false)
    oldPosMenuRotate =getTransformNodeRotation(menuRotate)
    oldPosMenuScale=getTransformNodeScale(menuScale)
    touchPos = controller0.getTouchpadPosition()
    moveScaleSideways = -2.0 * touchPos.x() *touchPos.x() *touchPos.x()
    moveScaleForward = -0.05 * touchPos.y() * touchPos.y() * touchPos.y() *touchPos.y()*touchPos.y()
    setTransformNodeRotation(menuRotate, 0, 0, moveScaleSideways+oldPosMenuRotate.z())
    size = moveScaleForward + oldPosMenuScale.x()
    if size < 1.25 and size >0.75:
        setTransformNodeScale(menuScale, size, size, size)

def trigger1Pressed():
    controller1.setPickingAxis(0)
    controller1.showPickingAxis(true)
    selectNodeVariant("Switch_Flashlight", "OFF")

def trigger1Released():
    pickedNode = controller1.pickNode()
    controller1.showPickingAxis(false)
    triggerSensor(pickedNode)
    selectNodeVariant("Switch_Flashlight", "ON")

def grip1Pressed():
    setOpenVRTrackingOrigin( Pnt3f(0.0, 0.0, 0.0))

def grip1Released():
    print("grip1Released")
    global toolCounter
    if toolCounter==0:
        selectVariantSet("tool_1")
        print toolCounter
        toolCounter +=1
    elif toolCounter==1:
        selectVariantSet("tool_2")
        print toolCounter
        toolCounter +=1
    elif toolCounter==2:
        selectVariantSet("tool_3")
        print toolCounter
        toolCounter +=1
    elif toolCounter==3:
        selectVariantSet("tool_4")
        print toolCounter
        toolCounter +=1
    elif toolCounter== 4:
        selectVariantSet("tool_5")
        print toolCounter
        toolCounter +=1
    elif toolCounter== 5:
        selectVariantSet("tool_6")
        print toolCounter
        toolCounter +=1
    elif toolCounter== 6:
        selectVariantSet("tool_0")
        print toolCounter
        toolCounter = 0

cannotMoveText = findNode("CannotMove")

def touchpad1Pressed():
    print("touchpad1Pressed")
    selectVariantSet("Haptic_Pulse_Rechts")
    global soundState
    if tool ==0:
        controller1.setPickingAxis(0)
        controller1.showPickingAxis(true)
        global pickedNode
        global cMatrixInitial
        global worldTrans
        global worldPivot
        global moveSel
        global cannotMoveText
        global moveState
        global child
        global moveMatRoot
        global moveMat
        pickedNode = controller1.pickNode()
        name = getNodeName(pickedNode)
        if name != "MOVE":
            selectNode(pickedNode)
            selectParent()
            selection = getSelectedNode()
            nameSel = getNodeName(selection)
            for x in range (0,150):
                if nameSel != "MOVE":
                    selectParent()
                    selection = getSelectedNode()
                    nameSel = getNodeName(selection)
                    moveState = 0
                elif nameSel == "Root":
                    moveState = 0
                    break
                else:
                    selectNode(selection)
                    moveState = 1
                    break
        else:
            selectNode(pickedNode)
            moveState = 1
        touchPos1 = controller1.getTouchpadPosition()
        if touchPos1.y() < -0.2:
            setTransformNodeTranslation(moveSel, 0.0, 0.0, 0.0, 0)
            print ("undo")
        #if touchPos1.x() >0.8:
        #    oldPosMenuRotate =getTransformNodeRotation(moveSel)
        #    setTransformNodeRotation(moveSel, 0, 0, oldPosMenuRotate.z()-90)
        #    print ("rechts")
        #if touchPos1.x() <-0.8:
        #    oldPosMenuRotate =getTransformNodeRotation(moveSel)
        #    setTransformNodeRotation(moveSel, 0, 0, oldPosMenuRotate.z()-90)
        #    print ("links")
        controller1.showPickingAxis(true)
        cMatrixInitial = controller1.getWorldMatrix()
        moveSel = getSelectedNode()
        worldTrans = getTransformNodeTranslation(moveSel, true)
        worldPivot = getBoundingBoxCenter(moveSel,true)
        enableClippingPlane(false)
        clipNode1.fields().setBool("on",false)
        clipNode2.fields().setBool("on",false)
        comparisionCar.setActive(false)
    if tool ==1:
        selectVariantSet("Create_Postit")
        touchPos2 = controller1.getTouchpadPosition()
        if touchPos2.y() > 0:
            selectVariantSet("Create_Postit_Good")
        else:
            selectVariantSet("Create_Postit_Bad")
    if tool ==2:
        global flashlight
        flashlight.setActive(true)
        touchPos4 = controller1.getTouchpadPosition()
        if touchPos4.y() > -0.33:
            selectVariantSet("Flashlight_Normal")
        else:
            if touchPos4.x() < 0:
                selectVariantSet("Flashlight_Laser_Red")
            if touchPos4.x() > 0:
                selectVariantSet("Flashlight_Laser_Green")
    if tool ==3:
        timer.setActive(true)
        touchPos3 = controller1.getTouchpadPosition()
        if touchPos3.y() > -0.5:
            timer.setActive(true)
        else:
            deleteLines()
    if tool ==4:
        setClippingContourVisualization(false, Vec3f(1.0,1.0,0.0), 1)
        enableClippingPlane(true)
    if tool ==5:
        clipNode1.fields().setBool("on",true)
        clipNode2.fields().setBool("on",true)
        comparisionCar.setActive(true)
    if tool ==6:
        selectVariantSet("RotateRuler")

def touchpad1Released():
    print("touchpad1Released")
    if tool == 0:
        deselectAll()
        global cannotMoveText
        cannotMoveText.setActive(false)
        controller1.showPickingAxis(false)
    if tool == 2:
        global flashlight
        flashlight.setActive(false)
    if tool ==3:
        global doDraw
        timer.setActive(false)
        doDraw = false
    if tool == 4:
        setClippingContourVisualization(true, Vec3f(1.0,1.0,0.0), 1)
    if tool == 5:
        print ("released")
        global comparisionPlane
        comparisionPlane.setActive(false)


def touchpad1PositionChanged(position):
    print("touchpad1PositionChanged")

def getNormalizedDirection(matrix):
    inVec = Vec2f( -matrix[2], matrix[6])
    rescale = 1.0 / sqrt( inVec.x()*inVec.x() + inVec.y() * inVec.y())
    return Vec2f( inVec.x() * rescale, inVec.y() * rescale)

def controller1Moved():
    rightNode.setTransformMatrix( controller1.getWorldMatrix(), false)
    if tool ==0:
        if controller1.isTouchpadPressed():
            touchPos1 = controller1.getTouchpadPosition()
            #print touchPos1.y()
            if touchPos1.y() > -0.2 :
                if moveState == 1:
                    cannotMoveText.setActive(false)
                    global worldTrans
                    global worldPivot
                    global moveSel
                    global posInitialX
                    import math
                    cMatrix = controller1.getWorldMatrix()
                    posX = cMatrix[3]
                    posY = cMatrix[7]
                    posZ = cMatrix[11]
                    posInitialX = cMatrixInitial[3]
                    posInitialY = cMatrixInitial[7]
                    posInitialZ = cMatrixInitial[11]
                    offsetX = posX-posInitialX
                    offsetY = posY-posInitialY
                    offsetZ = posZ-posInitialZ
                    newPosX = offsetX+worldTrans.x()
                    newPosY = offsetY+worldTrans.y()
                    newPosZ = offsetZ+worldTrans.z()
                    setTransformNodeRotatePivot(moveSel,worldPivot.x(),worldPivot.y(),worldPivot.z(),1)
                    if abs(newPosX) <5 or abs(newPosY) <5 or abs(newPosZ) <5:
                        setTransformNodeTranslation(moveSel, 0.0, 0.0, 0.0, 0)
                    else:
                        setTransformNodeTranslation(moveSel, newPosX, newPosY, newPosZ, 1)
                else:
                    cannotMoveText.setActive(true)
            else:
                global moveSel
                setTransformNodeTranslation(moveSel, 0.0, 0.0, 0.0, 0)
                print ("undo")
    if tool ==3:
        if controller1.isTouchpadPressed():
            timer.connect("drawLine()")
    if tool == 4:
        if controller1.isTouchpadPressed():
            touchPos1 = controller1.getTouchpadPosition()
            if touchPos1.y() > -0.2:
                cMatrix = controller1.getWorldMatrix()
                clipPos = Pnt3f( cMatrix[3], cMatrix[7], cMatrix[11])
                clipNor = Vec3f( cMatrix[2], cMatrix[6], cMatrix[10])
                setClippingPlane(clipPos, clipNor, false)
            else:
                enableClippingPlane(false)
    if tool == 5:
        if controller1.isTouchpadPressed():
            touchPos1 = controller1.getTouchpadPosition()
            global clipNode1
            global clipNode2
            global comparisionPlane
            comparisionPlane.setActive(true)
            import math
            if touchPos1.y() > -0.2:
                clipNode1.fields().setBool("on",true)
                clipNode2.fields().setBool("on",true)
                cMatrix = controller1.getWorldMatrix()
                setTransformNodeTranslation(clipNode1, cMatrix[3], cMatrix[7], cMatrix[11], false)
                setTransformNodeTranslation(clipNode2, cMatrix[3], cMatrix[7], cMatrix[11], false)
                setTransformNodeTranslation(comparisionPlane, cMatrix[3], cMatrix[7], cMatrix[11], false)
                wertX = math.degrees(cMatrix[2])
                wertY = math.degrees(cMatrix[6])
                wertZ = math.degrees(cMatrix[10])
                if touchPos1.x() < -0.33:
                    setTransformNodeRotation(clipNode1,90, 0, 90)
                    setTransformNodeRotation(clipNode2,90, 0, -90)
                    setTransformNodeRotation(comparisionPlane,90, 0 , 90)
                    print ("X")
                if touchPos1.x()>-0.33 and touchPos1.x()<0.33:
                    setTransformNodeRotation(clipNode1,-90, 0, 0)
                    setTransformNodeRotation(clipNode2,90, 0, 0)
                    setTransformNodeRotation(comparisionPlane,-90, 0 , 0)
                    print ("Y")
                if touchPos1.x() > 0.33:
                    setTransformNodeRotation(clipNode1,180, 0, 0)
                    setTransformNodeRotation(clipNode2,0, 0, 0)
                    setTransformNodeRotation(comparisionPlane,180, 0 , 0)
                    print ("Z")
            else:
                clipNode1.fields().setBool("on",false)
                clipNode2.fields().setBool("on",false)
                comparisionCar.setActive(false)



#----------------------------------------------------------------------
# Create two controller and connect their signals to functions as needed
#

controller0 = vrOpenVRController("Controller0")
controller0.connectSignal("controllerMoved", controller0Moved)
controller0.connectSignal("triggerPressed", trigger0Pressed)
controller0.connectSignal("triggerReleased", trigger0Released)
controller0.connectSignal("gripPressed", grip0Pressed)
controller0.connectSignal("gripReleased", grip0Released)
controller0.connectSignal("touchpadPressed", touchpad0Pressed)
controller0.connectSignal("touchpadReleased", touchpad0Released)
#controller0.connectSignal("touchpadPositionChanged", touchpad0PositionChanged)

controller1 = vrOpenVRController("Controller1")
controller1.connectSignal("controllerMoved", controller1Moved)
controller1.connectSignal("triggerPressed", trigger1Pressed)
controller1.connectSignal("triggerReleased", trigger1Released)
controller1.connectSignal("gripPressed", grip1Pressed)
controller1.connectSignal("gripReleased", grip1Released)
controller1.connectSignal("touchpadPressed", touchpad1Pressed)
controller1.connectSignal("touchpadReleased", touchpad1Released)
#controller1.connectSignal("touchpadPositionChanged", touchpad1PositionChanged)


#----------------------------------------------------------------------
# In case the scene origin is not located at 0,0,0 you may set a reference origin instead

setOpenVRTrackingOrigin( Pnt3f(0.0, 0.0, 0.0))

#----------------------------------------------------------------------
# Sounds Testing

sound = findNode("Sound")

def pitch(v):
    sound.setFieldReal32("pitch", v)

keyH = vrKey(Key_H)
keyH.connect(pitch, 2.0)

keyL = vrKey(Key_J)
keyL.connect(pitch, 0.5)

keyK = vrKey(Key_K)
keyK.connect(pitch, 1.0)

#----------------------------------------------------------------------
# Initializaiton / Reset

def resetScene():
    print "reset"

    deleteLines()   # remove the lines
    deletePostits() #remove postits

    enableClippingPlane(false)
    selectVariantSet("Button_1")
    selectVariantSet("Button_10")   # Pacfic_Road
    selectVariantSet("Button_22")  # Genesis
    selectVariantSet("Button_20")  # Mini

    selectVariantSet("Viewpoint_1")

    print "reset end"

    clipNode1.fields().setBool("on",false)
    clipNode2.fields().setBool("on",false)
    comparisionCar.setActive(false)


resetScene()    # reset on startup

setFromAtUp(-1, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)

# Scripts by Simon Nagel, Jason Walter and Merten Stroetzel
