# Copyright 2009 Autodesk, Inc.  All rights reserved.
# Use of this software is subject to the terms of the Autodesk license agreement 
# provided at the time of installation or download, or which otherwise accompanies
# this software in either electronic or hard copy form.
#
# Script description:
#  MotionBuilder 2009 and Pre-Visualization Demo 1
#
# Topic: FBPlayerControl, FBLayout, FBConfigFile
# 

from pyfbsdk import *
from pyfbsdk_additions import *
from sys import *
import os
import traceback

global lFp
lFp = FBFilePopup()

#There would need to be more error handling added if an unperfect shot track definition files were added.

def BrowseCallback(control, event):
    #OPENING AND FILE READING
    #Create the popup and set necessary initial values.

    lFp.Caption = "Select the shot track definition file:"
    lFp.Style = FBFilePopupStyle.kFBFilePopupOpen
    lFp.Filter = "*.txt" # BUG: If we do not set the filter, we will have an exception.
    if os.path.isdir(os.path.splitext(traceback.extract_stack()[-1][0])[0]):
        lFp.Path = os.path.normpath(os.path.splitext(traceback.extract_stack()[-1][0])[0])
    else:
        lFp.Path = os.path.normpath(os.path.dirname(traceback.extract_stack()[-1][0]))
    ## Set the default path to the script folder
    lRes = lFp.Execute() # Get the GUI to show.

    if lRes: # if a file was selected set the FBEdit button to the values
        eButt.Text = os.path.join(lFp.Path,lFp.FileName) #set up the edit box to contain the path

def SetupCallback(control, event):
    try:
        f=open(os.path.join(lFp.Path,lFp.FileName), 'r') #Open Shot Track Definition File
        shotInfoFile = f.readlines() #Read all the content of  Shot Track Definition File
        f.close()         #Close the file that you were reading

        shotCnt = len(shotInfoFile) #Find out how many lines were in the file
        counter = 1
        for shotInfo in shotInfoFile:
            #PARSING THE STRINGS
            shots = shotInfo.split() # Spitting the lines in the file
            (shotName,shotStart,shotEnd) = shots
            iShotStart = int(shotStart)
            iShotEnd = int(shotEnd)
            if shotInfoFile[0] == shotInfo:
               completeShotStart = iShotStart # Capture the final start frame of all the clips for setting the Transport Controls later

            if shotInfoFile[shotCnt - 1] == shotInfo:
                completeShotEnd = iShotEnd # Capture the final end frame of all the clips for setting the Transport Controls later

            #CAMERA AND INTERST, Create a camera, named the same as the label in the definition
            lCam = FBCamera (shotName)
            lCam.Visible = True
            lCam.Show = True
            lNull = FBModelNull (shotName + "_INT") #Create a Camera Interest, named the same as the label in the definition with _INT appended
            lCam.Interest = lNull #Link the null to be the camera interest.

            #STORY
            #In Story you need to create the clips
            lTrackContainer = FBStory().RootEditFolder.Tracks
            lastTrack=0
            lTrack=None
            for Track in lTrackContainer:
                if Track.Label =="Shot Track 1":
                    lTrack=Track
            clipStart = FBTime(0,0,0,iShotStart)
            if lTrack:
                lClip = FBStoryClip (lCam, lTrack, clipStart)
                lClip.Start = FBTime(0,0,0,iShotStart) #Set the correct start and end frame from the shot track definition file.
                lClip.Stop = FBTime(0,0,0,iShotEnd)
                if lastTrack<iShotEnd: lastTrack=iShotEnd

            #Setting up the backplates if the user chooses to
            if backPlate.State == 1:
                if counter < 10:
                    vidPath = os.path.join(lFp.Path, "shot0"+str(counter)+".avi")
                else:
                    vidPath = os.path.normpath(lFp.Path+"shot" + str(counter) +".avi")
                lVid = FBVideoClip(vidPath)
                if lVid.IsValid():
                    lCam.BackGroundMedia = lVid #linking the backplate to the camera
            counter = counter + 1
        FBPlayerControl().LoopEnd=FBTime(0,0,0,lastTrack,0)
        #TRANSPORT CONTROLS
        #You need to set up the Transport Controls so it goes from the start of the Shot Track to the End.
        #When you save your scene, this is not remembered, bug 313059 :(
        lPlayer = FBPlayerControl()
        lPlayer.LoopStart = FBTime(0,0,0,completeShotStart)
        lPlayer.ZoomWindowStart = FBTime(0,0,0,completeShotStart)
        lPlayer.LoopStop = FBTime(0,0,0,completeShotEnd)
        lPlayer.ZoomWindowStop = FBTime(0,0,0,completeShotEnd)

        #####################################
        #This is purely code for demoing

        lModel = FBFindModelByName('SHOT_001')
        lModel.Translation = FBVector3d(-10000, 145, 300)

        lModel = FBFindModelByName('SHOT_001_INT')
        lModel.Translation = FBVector3d(-10000, 0, 0)

        lModel = FBFindModelByName('SHOT_002')
        lModel.Translation = FBVector3d(-5000, 145, 300)

        lModel = FBFindModelByName('SHOT_002_INT')
        lModel.Translation = FBVector3d(-5000, 0, 0)

        lModel = FBFindModelByName('SHOT_003')
        lModel.Translation = FBVector3d(0, 145, 300)

        lModel = FBFindModelByName('SHOT_003_INT')
        lModel.Translation = FBVector3d(0, 0, 0)

        lModel = FBFindModelByName('SHOT_004')
        lModel.Translation = FBVector3d(5000, 145, 300)

        lModel = FBFindModelByName('SHOT_004_INT')
        lModel.Translation = FBVector3d(5000, 0, 0)

        lModel = FBFindModelByName('SHOT_005')
        lModel.Translation = FBVector3d(10000, 145, 300)

        lModel = FBFindModelByName('SHOT_005_INT')
        lModel.Translation = FBVector3d(10000, 0, 0)

        lCameras = FBSystem().Scene.Cameras

        for lCam in lCameras:
            if lCam.Name == "Producer Perspective":
                lCam.FarPlaneDistance = 40000
            break
        FBApplication().SwitchViewerCamera(FBCameraSwitcher().CurrentCamera)

    except IOError:
        FBMessageBox( "Cannot Continue", "Unable to read the shot track definition file you selected or you have not selected one.", "OK", None, None )
        exit

def PopulateLayout(mainLyt):
    #1.  Creating the instruction title
    l = FBLabel()
    l.Caption = "Select the shot track definition file to use:"
    l.Style = FBTextStyle.kFBTextStyleBold
    l.WordWrap = True

    x = FBAddRegionParam(5,FBAttachType.kFBAttachLeft,"") # Create a label that is left justify 
    y = FBAddRegionParam(5,FBAttachType.kFBAttachTop,"") # ... and at the top of the layout. 
    w = FBAddRegionParam(300,FBAttachType.kFBAttachNone,"") # its width is fixed at 300 pixels
    h = FBAddRegionParam(20,FBAttachType.kFBAttachNone,"") # and its height is fixed at 15 pixels

    mainLyt.AddRegion("lab","lab", x, y, w, h)
    mainLyt.SetControl("lab",l)

    #2.  Creating a temp button for a place holder
    e = FBEdit()
    e.ReadOnly = True
    e.Text = ""

    x2 = FBAddRegionParam(5,FBAttachType.kFBAttachLeft,"")
    y2 = FBAddRegionParam(5,FBAttachType.kFBAttachBottom,"lab")
    w2 = FBAddRegionParam(220,FBAttachType.kFBAttachNone,"")
    h2 = FBAddRegionParam(20,FBAttachType.kFBAttachNone,"")

    mainLyt.AddRegion("path","path", x2, y2, w2, h2)
    mainLyt.SetControl("path",e)

    #3.  Creating a the browse button
    b2 = FBButton()
    b2.Caption = "Browse..."
    b2.Justify = FBTextJustify.kFBTextJustifyCenter

    x3 = FBAddRegionParam(225,FBAttachType.kFBAttachLeft,"path")
    y3 = FBAddRegionParam(5,FBAttachType.kFBAttachBottom,"lab")
    w3 = FBAddRegionParam(57,FBAttachType.kFBAttachNone,"")
    h3 = FBAddRegionParam(20,FBAttachType.kFBAttachNone,"")

    mainLyt.AddRegion("but","but", x3, y3, w3, h3)
    mainLyt.SetControl("but",b2)

    global eButt #creating The FBEdit button as global so it can be set in the function BrowseCallback
    eButt = e
    b2.OnClick.Add(BrowseCallback)

    #4. Creating the 'create backplate' checkbox
    cb = FBButton()
    cb.Style = FBButtonStyle.kFBCheckbox
    cb.Caption = "Add backplates to each shot"

    x4 = FBAddRegionParam(60, FBAttachType.kFBAttachLeft, "")
    y4 = FBAddRegionParam(5, FBAttachType.kFBAttachBottom, "path")
    w4 = FBAddRegionParam(300,FBAttachType.kFBAttachNone,"")
    h4 = FBAddRegionParam(25,FBAttachType.kFBAttachNone,"")

    mainLyt.AddRegion("backp", "backp",x4,y4,w4,h4)
    mainLyt.SetControl("backp",cb)

    global backPlate #Create this global so the setupCallback can find the result of the checkbox
    backPlate = cb
##    cb.OnClick.Add(

    #5. Creating the button the automatically does everything
    b3 = FBButton()
    b3.Caption = "Setup Shots"
    b3.Justify = FBTextJustify.kFBTextJustifyCenter

    x5 = FBAddRegionParam(40,FBAttachType.kFBAttachLeft,"")
    y5 = FBAddRegionParam(5,FBAttachType.kFBAttachBottom,"backp")
    w5 = FBAddRegionParam(100,FBAttachType.kFBAttachNone,"")
    h5 = FBAddRegionParam(25,FBAttachType.kFBAttachNone,"")

    mainLyt.AddRegion("shots","shots", x5, y5, w5, h5)
    mainLyt.SetControl("shots",b3)
    b3.OnClick.Add(SetupCallback)

    x6 = FBAddRegionParam(20,FBAttachType.kFBAttachRight,"shots")
    y6 = FBAddRegionParam(5,FBAttachType.kFBAttachBottom,"backp")
    w6 = FBAddRegionParam(100,FBAttachType.kFBAttachNone,"")
    h6 = FBAddRegionParam(25,FBAttachType.kFBAttachNone,"")

def CreateTool():
    # Tool creation will serve as the hub for all other controls
    global t
    t = CreateUniqueTool("Shot Track Setup Tool")
    t.StartSizeX = 300
    t.StartSizeY = 143

    PopulateLayout(t)
    ShowTool(t)

CreateTool()