Shotgun Tasks are not displayed

While connecting to Shotgun from a Job Submission dialog box Deadline is supposed to catch and display all the Tasks assigned to the User.
Unfortunately even while the connection between Deadline Job Submission and Shotgun is successful there are no Tasks displayed.
In an “Advanced” mode set using Deadline/Shotgun Submission Options Deadline does display the name of the Project and the name of the Entity.
But it displays every Project and every Entity. We want to be able to show only those Entities to which the User is assigned through the Tasks.

  1. First Deadline would query what Tasks the User is assigned to.
  2. Then Deadline would query what Entities those Tasks are linked to.
  3. Lastly Deadline would return the names of those Entities which are linked to the User’s Tasks displaying them in a
    Submission Dialog box.

But at very least I would like to see the Tasks assigned to the User and not the list of all the Entities under the selected Project in Job Submission dialog box. Please advise.
It is possible that Deadline is confused because we added a number of our own Tasks. As I am know Shotgun internally assigns Task_ID integer to each Task. It is possible
Deadline doesn’t know the IDs created for the new Tasks…

The answer to this question is:

Job Submission Dialog box (in Maya) uses ShotgunUtils.py Python script which resides in:

…\Thinkbox\DeadlineRepository\events\Shotgun\ directory.

This script is the set of Python functions each performing a specific task while communication with Shotgun.
While the functions defined in a script are not commented it is not that hard to figure out what they do.
The function that pulls the Tasks data assigned to the User is called “GetTasks”.

The key Shotgun command used in this function is sg.find

Here is a full syntax:

tasks = sg.find(“Task”, filters=[[‘sg_status_list’, ‘is’, ‘rdy’],[“task_assignees”, “is”, userEntry]], fields=[‘content’,‘project’,‘entity’,draftField], order=[{‘field_name’:‘project’,‘direction’:‘asc’},{‘field_name’:‘entity’,‘direction’:‘asc’},{‘field_name’:‘content’,‘direction’:‘asc’}])

sg.find returns back a data from Shotgun based on the arguments the command was supplied with (the arguments supplied within the enclosed square brackets [ ] (as a list).

The first argument supplied with sg.find command is “Task”. It is quite clear that this argument tells Shotgun to look for the Tasks only.
Then there is another argument which is so-called filters. The filter is the list of arguments by itself. It can have as many arguments as you wish. The more arguments in the filter list the more narrow the search - the less data is returned from Shotgun. Now. Let’s take a look what our friends at Deadline specified there.
There are two Filters arguments there (or if you wish: there are two search criteria).
The first filter argument is:

[‘sg_status_list’, ‘is’, ‘rdy’]

That argument tells Shotgun to return only those tasks which have a status set to “Ready to Start” (or “rdy” for short).
If the Task was set to any other than to “Ready to Start” the Deadline Submission Job dialog box won’t be able to display the task simply because sg.find (“Tasks”) command returns nothing from Shotgun.

The second argument filters out only those Tasks that were assigned to the User.
The syntax used there is:

[“task_assignees”, “is”, userEntry]

where:
task_assignees is the internal to Shotgun Task’s field (you can always get the correct field syntax by going to Admin -Fields page in Shotgun).
userEntry is the variable that was assigned the output from another Shotgun command (which returned the Shotgun data values for the user) with a syntax:

userEntry = sg.find_one(“HumanUser”,filters=[[“login”,“is”,userName]],fields=[‘login’,‘name’])

where userName is another variable which as I understand just read the value typed in to the User field found in Submit Job Dialog box.

It would be nice if there would be an option to set Deadline to use System User Login name for that. This way we wouldn’t have to type the User name every time. And it would assure another level of security and
organization during the production (so the users are not given a chance to use other than their own system names):
Since I am working in Maya mostly here is what I use:
userName = mel.eval (‘getenv USER;’)

Please correct me if I am mistaken anything.

You are mostly correct in your assessment. We’re filtering the tasks based on their statuses – you wouldn’t want all your completed tasks to show up in the list, after all. In order for a task to be displayed, it must either be set to “Ready to Start”, as you pointed out, or “In Progress” (we grab those too). If you have a custom status you need to add to the filter, it should be a simple change to make, since you’ve figured out how it works already :slight_smile:

As for tying the user name to the system login, it would also be relatively easy to do. You’ll need to make changes (make a backup first!) to the ShotgunUI.py script located in your repository under events/Shotgun. I’ve listed the necessary changes below:

First, change this line:

import sys, time, re, webbrowser

to this line:

import os, sys, time, re, webbrowser

Next, change this line:

loginBox = scriptDialog.AddControl( "LoginBox", "TextControl", "", 175, -1 )

to these lines:

loginBox = scriptDialog.AddControl( "LoginBox", "LabelControl", "", 175, -1 ) scriptDialog.SetValue( "LoginBox", os.environ['USERNAME'] )

Finally, change these lines:

if versionSelectMode: settings = ("LoginBox", "TaskBox", "ProjectBox", "EntityBox") else: settings = ("LoginBox", "TaskBox", "ProjectBox", "EntityBox", "TemplateBox", "DescriptionBox")
to:

if versionSelectMode: settings = ("TaskBox", "ProjectBox", "EntityBox") else: settings = ("TaskBox", "ProjectBox", "EntityBox", "TemplateBox", "DescriptionBox")

That should auto-populate the login name and try to log in as that user when the Shotgun UI is brought up through any of the Deadline submitters. Note that this will probably only work on Windows the way I have it working, but it should be a simple matter of switching which environment variable you look at based on the OS.

Cheers,

  • Jon

Thanks for the help Jon!
It works like a charm! Thanks!
The modified code for ShotgunUI.py (with the Auto-Populate User Name) is posted below:

[code]#Python.NET

########################################################################
import os, sys, time, re, webbrowser
########################################################################

from System import *
from System.Collections.Specialized import *
from System.Drawing import *
from System.IO import *
from System.Text import *
from System.Threading import *
from System.Windows.Forms import *

from Deadline.Scripting import *

########################################################################

Globals

########################################################################
scriptDialog = None
settings = None
shotgunPath = None
logBox = None
appName = “” #the app name calling the script (so we can stash sticky settings separately per application)
sgURL = “” #the base URL for the studio’s SG db
sgConfig = {} #the shotgun configuration settings (taken from shotgun.dlinit)

currentUser = None #connected user
sgProjectDict = {} #dictionary of Shotgun Projects
sgTaskDict = {} #dictionary of Shotgun Tasks
sgEntityDict = {} #dictionary of Shotgun Entities
versionTemplates = [] #list of version templates
sgVersionDict = None #dictionary of Shotgun Versions

shotgunImported = False #keeps track of whether or not we added Shotgun to the PATH
updatingUI = False #variable used to bypass event handlers when values change programmatically

statusMessage = “” #current status
errorMessage = “”
logMessages = [""]

stickySettings = {} #a dictionary of sticky settings
advancedMode = False #tracks whether or not we’re using advanced Mode
versionSelectMode = False # tracks if the control is used to select an existing version

workerThread = None #Thread to do actual work in the background
progressThread = None #Thread for updating progress bar, in order to look “busy”

########################################################################

Main Function Called By Deadline

########################################################################
def main( *args ):
global advancedMode
global versionSelectMode
global logBox
global scriptDialog
global settings
global shotgunPath
global versionTemplates
global appName
global newEntityButton
global sgURL
global sgConfig

#Get the app name from the args (if it's there)
if len( args ) > 0:
	appName = args[0]
if len( args ) > 1 and args[1].lower() == "selectversion":
	versionSelectMode = True

scriptDialog = DeadlineScriptEngine.GetScriptDialog()

AddShotgunToPath()
try:
	#Try to import shotgun stuff; fail nicely if it doesn't work
	import ShotgunUtils
except:
	scriptDialog.ShowMessageBox( "An error occurred when trying to import the Shotgun API.\n\nPlease ensure that the Shotgun API has been added to your Shotgun event folder.", "Error" )
	return

#Get the shotgun plugin config values	
sgConfig = ShotgunUtils.GetIniFileData( shotgunPath )
#advancedMode = Boolean.Parse( shotgunConfig.get( "EnableAdvancedWorkflow", "False" ) )
advancedMode = StringUtils.ParseBooleanWithDefault( sgConfig.get( "EnableAdvancedWorkflow", "False" ), False )
versionTemplates = sgConfig.get( "VersionNameTemplates", "" ).split( ';' )
sgURL = sgConfig.get( "ShotgunURL", "" )

#append a / if there isn't one
if not IsNoneOrWhiteSpace( sgURL ) and not sgURL.endswith( "/" ):
	sgURL += "/"

shotgunAPIVersion = ShotgunUtils.GetShotgunAPIVersion()

#clean out empty templates
for template in versionTemplates:
	if IsNoneOrWhiteSpace( template ):
		versionTemplates.remove( template )

dialogWidth = 450
labelWidth = 90
dialogHeight = 382
padding = 6

shotgunPath = Path.Combine( GetRootDirectory(), "events/Shotgun" )

scriptDialog.SetSize( dialogWidth + 14, dialogHeight )
title = "Shotgun Settings"
if not IsNoneOrWhiteSpace( shotgunAPIVersion ):
	title += " (API v%s)" % shotgunAPIVersion

scriptDialog.SetTitle( title )
scriptDialog.SetIcon( Path.Combine( shotgunPath, "Shotgun.ico" ) )

scriptDialog.AddControl( "Separator1", "SeparatorControl", "Shotgun Fields", dialogWidth, -1 )

scriptDialog.AddRow()
scriptDialog.AddControl( "LoginLabel", "LabelControl", "Login Name", labelWidth, -1)

########################################################################
loginBox = scriptDialog.AddControl( "LoginBox", "TextControl", "", 175, -1 )
scriptDialog.SetValue( "LoginBox", os.environ['USERNAME'] )
########################################################################


loginBox.ValueModified += LoginNameChanged
loginButton = scriptDialog.AddControl( "LoginButton", "ButtonControl", "Connect", labelWidth, -1 )
loginButton.ValueModified += LoginButtonPressed
scriptDialog.EndRow()

scriptDialog.AddRow()
scriptDialog.AddControl( "UserLabel", "LabelControl", "Connected User", labelWidth, -1 )
scriptDialog.AddControl( "UserBox", "LabelControl", "", dialogWidth - (labelWidth + padding), -1 )
scriptDialog.EndRow()
scriptDialog.AddRow()
scriptDialog.AddControl( "TaskLabel", "LabelControl", "Task", labelWidth, -1 )
taskBox = scriptDialog.AddComboControl( "TaskBox", "ComboControl", "", (), dialogWidth - (labelWidth + padding) - 25, -1 )
taskBox.ValueModified += ShotgunTaskChanged

newTaskButton = scriptDialog.AddControl( "NewTaskButton", "ButtonControl", "+", 20, -1 )
newTaskButton.ValueModified += NewEntityButton_Pressed

#context menu
menu = ContextMenu()
item = MenuItem( "New Task..." )
item.Click += NewTaskMenuItem_Click
menu.MenuItems.Add( item )

newTaskButton.ContextMenu = menu

scriptDialog.EndRow()
scriptDialog.AddRow()
scriptDialog.AddControl( "ProjectLabel", "LabelControl", "Project", labelWidth, -1 )

#only use a drop down if we're using advanced workflow
if advancedMode:
	projectBox = scriptDialog.AddComboControl( "ProjectBox", "ComboControl", "", (), dialogWidth - (labelWidth + padding), -1 )
	projectBox.ValueModified += ShotgunProjectChanged
else:
	scriptDialog.AddControl( "ProjectBox", "LabelControl", "", dialogWidth - (labelWidth + padding), -1 )
	
scriptDialog.EndRow()
scriptDialog.AddRow()
scriptDialog.AddControl( "EntityLabel", "LabelControl", "Entity", labelWidth, -1 )

#only use a drop down if we're using advanced workflow
if advancedMode:
	entityBox = scriptDialog.AddComboControl( "EntityBox", "ComboControl", "", (), dialogWidth - (labelWidth + padding) - 25, -1 )
	entityBox.ValueModified += ShotgunEntityChanged
	
	newEntityButton = scriptDialog.AddControl( "NewEntityButton", "ButtonControl", "+", 20, -1 )
	newEntityButton.ValueModified += NewEntityButton_Pressed
	
	#context menu
	menu = ContextMenu()
	item = MenuItem( "New Asset..." )
	item.Click += NewAssetMenuItem_Click
	menu.MenuItems.Add( item )
	
	item = MenuItem( "New Element..." )
	item.Click += NewElementMenuItem_Click
	menu.MenuItems.Add( item )
	
	item = MenuItem( "New Shot..." )
	item.Click += NewShotMenuItem_Click
	menu.MenuItems.Add( item )
	
	newEntityButton.ContextMenu = menu
else:
	scriptDialog.AddControl( "EntityBox", "LabelControl", "", dialogWidth - (labelWidth + padding), -1 )
	
scriptDialog.EndRow()

if versionSelectMode:
	scriptDialog.AddRow()
	scriptDialog.AddControl( "VersionLabel", "LabelControl", "Version", labelWidth, -1 )
	versionControl = scriptDialog.AddComboControl( "VersionCombo", "ComboControl", "Version", (), dialogWidth - (labelWidth + padding), -1 )
	versionControl.ValueModified += ShotgunVersionChanged
	scriptDialog.EndRow()
	
	scriptDialog.AddRow()
	scriptDialog.AddControl( "DescriptionLabel", "LabelControl", "Description", labelWidth, -1 )
	scriptDialog.AddControl( "DescriptionBox", "ReadOnlyTextControl", "", dialogWidth - (labelWidth + padding), -1 )
	scriptDialog.EndRow()
else:
	scriptDialog.AddRow()
	scriptDialog.AddControl( "TemplateLabel", "LabelControl", "Version Template", labelWidth, -1 )
	
	#if we have templates, use an editable combo box
	if len( versionTemplates ) > 0:
		templateBox = scriptDialog.AddComboControl( "TemplateBox", "EditableComboControl", "", tuple( versionTemplates ), dialogWidth - (labelWidth + padding), -1 )
		templateBox.ValueModified += VersionTemplateChanged
	else:	
		templateBox = scriptDialog.AddControl( "TemplateBox", "TextControl", "", dialogWidth - (labelWidth + padding), -1 )
		templateBox.ValueModified += VersionTemplateChanged
	
	scriptDialog.EndRow()
	scriptDialog.AddRow()
	scriptDialog.AddControl( "PreviewLabel", "LabelControl", "Version Preview", labelWidth, -1 )
	scriptDialog.AddControl( "PreviewBox", "LabelControl", "", dialogWidth - (labelWidth + padding), -1 )
	scriptDialog.EndRow()
	scriptDialog.AddRow()
	scriptDialog.AddControl( "DescriptionLabel", "LabelControl", "Description", labelWidth, -1 )
	scriptDialog.AddControl( "DescriptionBox", "TextControl", "", dialogWidth - (labelWidth + padding), -1 )
	scriptDialog.EndRow()

scriptDialog.AddRow()
scriptDialog.AddControl( "LogLabel", "LabelControl", "Shotgun Log:", labelWidth, -1 )
scriptDialog.EndRow()

scriptDialog.AddRow()
logBox = scriptDialog.AddComboControl( "LogBox", "ListControl", "", (""), dialogWidth, 70 )
logBox.ScrollBars = ScrollBars.Vertical;
logBox.SelectionMode = SelectionMode.MultiExtended
scriptDialog.EndRow()

scriptDialog.AddRow()
scriptDialog.AddRangeControl( "ProgressBar", "ProgressBarControl", 0, 0, 100, 0, 0, labelWidth, 20)
scriptDialog.AddControl( "DummyLabel", "LabelControl", "", dialogWidth - labelWidth - 200 - (3 * padding), -1)
okButton = scriptDialog.AddControl( "OKButton", "ButtonControl", "OK", 100, -1 )
okButton.ValueModified += OKButtonPressed
cancelButton = scriptDialog.AddControl( "CancelButton", "ButtonControl", "Cancel", 100, -1 )
cancelButton.ValueModified += CancelButtonPressed
scriptDialog.EndRow()

scriptDialog.AddRow()
scriptDialog.AddControl( "StatusLabel", "LabelControl", "", dialogWidth, -1 )
scriptDialog.EndRow()

scriptDialog.Shown += DialogShown

settings = ()
if versionSelectMode:
	settings = ("TaskBox", "ProjectBox", "EntityBox")
else:
	settings = ("TaskBox", "ProjectBox", "EntityBox", "TemplateBox", "DescriptionBox")
	
GetStickySettings( GetSettingsFilename() ) #loads in sticky settings for later use (our combo box items are dynamic, those won't get loaded right away)
scriptDialog.LoadSettings( GetSettingsFilename(), settings ) #loads what sticky settings can be loaded right now

scriptDialog.ShowDialog( True )

#Dialog was shown, start up a background thread to connect to shotgun
def DialogShown(*args):
global scriptDialog

errors, warnings = CheckShotgunSetup()

if len( errors ) > 0:
	message = "Deadline's Shotgun integration does not seem to be configured properly.\n\nThe following errors must be rectified in the Shotgun Event Plugin configuration before proceeding:\n"
	for error in errors:
		message += ("    ERROR: %s\n" % error)
	
	scriptDialog.ShowMessageBox( message, "Shotgun Configuration Error" )
	CancelButtonPressed( None )
else:
	if len( warnings ) > 0:
		message = ""
		for warning in warnings:
			message += (warning + "\n\n")
			
		scriptDialog.ShowMessageBox( message.rstrip( '\n' ), "Shotgun Configurations Warning" )
	
	#this will bring the form to the foreground
	scriptDialog.TopMost = True
	scriptDialog.TopMost = False
	
	stickyUser = scriptDialog.GetValue( "LoginBox" )
	
	#if we loaded a sticky value for the user, try connecting right away
	if not IsNoneOrWhiteSpace( stickyUser ):
		WriteToLogBox( "Defaulting to user: '%s'" % stickyUser )
		LoginButtonPressed( None )
	else:
		UpdateEnabledStatus()

#Makes the progress bar fill up at a steady rate, while displaying a status message
def LookBusy():
global scriptDialog
global statusMessage
global workerThread
global errorMessage
global logMessages

UpdateEnabledStatus()

progress = 0

#Keep looping until the worker thread finishes
while workerThread.IsAlive and IsNoneOrWhiteSpace( errorMessage ):
	progress = ( progress + 2 ) % 101
	scriptDialog.SetValue( "ProgressBar", progress )
	
	dots = ""
	for i in range( 0, progress / 25 ):
		dots = dots + "."
	
	scriptDialog.SetValue( "StatusLabel", "%s%s" % (statusMessage, dots) )
	Thread.Sleep( 50 )

if IsNoneOrWhiteSpace( errorMessage ):
	#no error, rejoice!
	scriptDialog.SetValue( "ProgressBar", 100 )
	scriptDialog.SetValue( "StatusLabel", "Shotgun request complete" )
else:
	#there was an error, display it
	scriptDialog.SetValue( "ProgressBar", 0 )
	scriptDialog.SetValue( "StatusLabel", "error :(" )
	scriptDialog.ShowMessageBox( errorMessage, "Error" )
	errorMessage = ""

UpdateEnabledStatus()

#clear the status label after a few secs
Thread.Sleep( 2500 )
try:
	scriptDialog.SetValue( "StatusLabel", "" )
except:
	pass

#Updates the enabled status of all controls on the form to match their status (values)
def UpdateEnabledStatus():
global scriptDialog
global workerThread
global currentUser
global advancedMode
global versionSelectMode

#Check if we're working on something in the background thread
finishedWorking = (workerThread == None or not workerThread.IsAlive)

#Check which fields are empty -- this will help us determine which controls should be enabled
connected = (currentUser != None)
taskEmpty = IsNoneOrWhiteSpace( scriptDialog.GetValue( "TaskBox" ) )
projectEmpty =  IsNoneOrWhiteSpace( scriptDialog.GetValue( "ProjectBox" ) )
entityEmpty = IsNoneOrWhiteSpace( scriptDialog.GetValue( "EntityBox" ) )

#login related stuff
loginName = scriptDialog.GetValue( "LoginBox" )
loginEmpty = IsNoneOrWhiteSpace( loginName )
loginChanged = False

if connected:
	loginChanged = (currentUser['login'] != loginName)

scriptDialog.SetEnabled( "LoginLabel", finishedWorking )
scriptDialog.SetEnabled( "LoginBox", finishedWorking )
scriptDialog.SetEnabled( "LoginButton", finishedWorking and not loginEmpty )

if connected and not loginChanged:
	scriptDialog.SetValue( "LoginButton", "Refresh" )
else:
	scriptDialog.SetValue( "LoginButton", "Connect" )

scriptDialog.SetEnabled( "UserLabel", connected and finishedWorking )
scriptDialog.SetEnabled( "UserBox", connected and finishedWorking )

scriptDialog.SetEnabled( "TaskLabel", connected and finishedWorking and ( not advancedMode or (not taskEmpty or projectEmpty) ) )
scriptDialog.SetEnabled( "TaskBox", connected and finishedWorking and ( not advancedMode or (not taskEmpty or projectEmpty) ) )
scriptDialog.SetEnabled( "NewTaskButton", connected and finishedWorking and ( not advancedMode or (not taskEmpty or projectEmpty) ) )

scriptDialog.SetEnabled( "ProjectLabel", connected and finishedWorking and (not advancedMode or taskEmpty) )
scriptDialog.SetEnabled( "ProjectBox", connected and finishedWorking and (not advancedMode or taskEmpty) )

scriptDialog.SetEnabled( "EntityLabel", connected and finishedWorking and ( not advancedMode or (taskEmpty and not projectEmpty) ) )
scriptDialog.SetEnabled( "EntityBox", connected and finishedWorking and ( not advancedMode or (taskEmpty and not projectEmpty) ) )

if advancedMode:
	scriptDialog.SetEnabled( "NewEntityButton", connected and finishedWorking and taskEmpty and not projectEmpty )

if versionSelectMode:
	scriptDialog.SetEnabled( "VersionLabel", connected and finishedWorking and not entityEmpty )
	scriptDialog.SetEnabled( "VersionCombo", connected and finishedWorking and not entityEmpty )
else:
	scriptDialog.SetEnabled( "TemplateLabel", connected and finishedWorking )
	scriptDialog.SetEnabled( "TemplateBox", connected and finishedWorking )
	scriptDialog.SetEnabled( "PreviewLabel", connected and finishedWorking )
	scriptDialog.SetEnabled( "PreviewBox", connected and finishedWorking )

scriptDialog.SetEnabled( "DescriptionLabel", connected and finishedWorking )
scriptDialog.SetEnabled( "DescriptionBox", connected and finishedWorking )
scriptDialog.SetEnabled( "OKButton", connected and finishedWorking )
scriptDialog.SetEnabled( "CancelButton", True )

#Adds a line to the log box (in a thread-safe manner)
def WriteToLogBox( strAppending, suppressNewLine=False ):
global scriptDialog
global logBox
global logMessages
global mainThread

try:
	lines = strAppending.splitlines()
	
	for line in lines:
		logMessages[ len( logMessages ) - 1 ] += line
		
		if not suppressNewLine or lines.index(line) < len(lines) - 1:
			logMessages.append( "" )
		
		scriptDialog.SetItems( "LogBox", tuple( logMessages ) )
		logBox.EnsureVisible( len( logMessages ) - 1 )
		#hack to get the scrolled log box to draw properly on OSX
		scriptDialog.SetValue( "LogBox", line )
				
except:
	#the log box might just not be initialized, just supress the exception
	pass

#Checks the provided Shotgun settings dictionary (taken from Shotgun.dlinit) to make sure required values have been set up
def CheckShotgunSetup():
global sgConfig
global sgURL

warnings = []
errors = []

if IsNoneOrWhiteSpace( sgURL ):
	errors.append( "The Shotgun URL has not been set." )

if sgConfig.get( "ShotgunScriptName", "" ).strip() == "":
	errors.append( "The Shotgun Script Name has not been set." )
	
if sgConfig.get( "ShotgunScriptKey", "" ).strip() == "":
	errors.append( "The Shotgun Script Key has not been set." )

sgEnabled = sgConfig.get( "Enabled", "" ).strip()
if sgEnabled[:4].upper() != "TRUE":
	warnings.append( "The Shotgun Event Plugin is currently disabled.\n\nThe Shotgun Event Plugin must be enabled in order for Shotgun integration to work properly." )

return errors, warnings

#Ensures Shotgun stuff is in the PATH so we can import the Shotgun modules
def AddShotgunToPath():
global shotgunPath
global shotgunImported

if shotgunPath == None:
	shotgunPath = Path.Combine( GetRootDirectory(), "events/Shotgun" )
	
if not shotgunImported:
	sys.path.append( shotgunPath )
	shotgunImported = True
	
return shotgunPath

#Does the initial connection to shotgun
def ConnectToShotgun( userName ):
global errorMessage
global scriptDialog
global shotgunPath
global statusMessage
global stickySettings
global updatingUI
global currentUser
global advancedMode

try:
	statusMessage = "connecting"
	
	newUser = None
	try:
		AddShotgunToPath()
		import ShotgunUtils
		
		WriteToLogBox( "Connecting to Shotgun as '%s'... " % userName, True )
		newUser = ShotgunUtils.GetUser( userName, shotgunPath )

		if newUser != None:
			WriteToLogBox( "done!" )
		else:
			WriteToLogBox( "failed." )
	except:
		errorMessage = "An error occurred while attempting to connect to Shotgun; see log for details."
		raise
	
	if newUser != None:
		#Initialize defaults to None
		defaultTask = None
		defaultProject = None
		defaultEntity = None
		defaultVersion = None
		
		#Load sticky settings if it's our first time through
		if currentUser == None:
			defaultTask = stickySettings.get( "TaskBox", None )
			
			if advancedMode:
				defaultProject = stickySettings.get( "ProjectBox", None )
				defaultEntity = stickySettings.get( "EntityBox", None )
				defaultVersion = stickySettings.get( "VersionBox", None )
		elif currentUser == newUser:
			#refreshing, default to current settings
			defaultTask = scriptDialog.GetValue( "TaskBox" )
			defaultProject = scriptDialog.GetValue( "ProjectBox" )
			defaultEntity = scriptDialog.GetValue( "EntityBox" )
			if versionSelectMode:
				defaultVersion = scriptDialog.GetValue( "VersionBox" )
		
		#update current user
		currentUser = newUser
		scriptDialog.SetValue( "UserBox", currentUser['name'] )
		
		defaultedTask = GetTasksForUser( currentUser['login'], defaultTask )
		
		#don't need to fill these out if we're not doing advanced workflow, or if we already have a task (and therefore a project/entity)
		if advancedMode:
			defaultedProject = GetProjectsForUser( currentUser['login'], defaultProject )
			
			#only need to load entities if no task was defaulted
			if IsNoneOrWhiteSpace( defaultedTask ):
				defaultedEntity = GetEntitiesForProject( defaultedProject, defaultEntity )
				
				if versionSelectMode:
					GetVersionsForEntity( defaultedEntity, defaultVersion )
					
			elif versionSelectMode:
				GetVersionsForTask( defaultedTask, defaultVersion )
		
		#update the version template preview
		VersionTemplateChanged( None )
	else:
		errorMessage = "Failed to connect to Shotgun with the given login name. Please double-check your login and try again."
	
except:
	#Make sure we set this to notify other threads that this failed
	if IsNoneOrWhiteSpace( errorMessage ):
		errorMessage = "An error occurred while connecting to Shotgun; see log for details."
			
	WriteToLogBox( "UNEXPECTED ERROR:" )
	WriteToLogBox( str( sys.exc_info()[0] ) )
	WriteToLogBox( str( sys.exc_info()[1] ) )
	WriteToLogBox( "---END ERROR INFO---" )

#Get SG Tasks for a given user
#Returns the defaulted task, if applicable
def GetTasksForUser( user, defaultTask=None ):
global errorMessage
global shotgunPath
global updatingUI
global sgTaskDict
global scriptDialog
global statusMessage

try:
	tasks = []
	taskNames = []
	sgTaskDict = {}
	
	#fall back to current value as a default
	if defaultTask == None:
		defaultTask = scriptDialog.GetValue( "TaskBox" )
	
	statusMessage = "fetching tasks"
	
	if user != None:
		AddShotgunToPath()
		import ShotgunUtils
		
		WriteToLogBox( "Getting Task list for user '%s'... " % user, True )
		tasks = ShotgunUtils.GetTasks( user, None, shotgunPath )
		WriteToLogBox( "done!" )
		
		taskNames.append( " " )
			
	for task in tasks:
		if task['project'] != None and task['entity'] != None:
			taskName = task['project']['name'] + " > " + task['entity']['name'] + " > " + task['content']
			sgTaskDict[ taskName ] = task
			taskNames.append( taskName )
	
	taskNames.sort()
	
	scriptDialog.SetItems( "TaskBox", tuple( taskNames ) )
	
	#default to the given task, if available
	if not IsNoneOrWhiteSpace( defaultTask ) and defaultTask in taskNames:
		pass
	elif len( taskNames ) > 0:
		defaultTask = taskNames[0]
	else:
		defaultTask = None
	
	#Set the default task
	if defaultTask != None:
		if defaultTask.strip() != "":
			WriteToLogBox( "Defaulting to task: '%s'" % defaultTask )
			
		updatingUI = True
		scriptDialog.SetValue( "TaskBox", defaultTask )
		updatingUI = False
	
	return defaultTask
	
except:
	#Make sure we set this to notify other threads that this failed
	if IsNoneOrWhiteSpace( errorMessage ):
		errorMessage = "An error occurred while attempting to collect Task Names from Shotgun; see log for details."
		
	WriteToLogBox( "UNEXPECTED ERROR:" )
	WriteToLogBox( str( sys.exc_info()[0] ) )
	WriteToLogBox( str( sys.exc_info()[1] ) )
	WriteToLogBox( "---END ERROR INFO---" )

return None

#Gets SG Projects for a given user
#Returns the defaulted project, if applicable
def GetProjectsForUser( user, defaultProject=None ):
global errorMessage
global shotgunPath
global sgProjectDict
global updatingUI
global scriptDialog
global statusMessage
global advancedMode

try:
	projects = []
	projectNames = []
	sgProjectDict = {}
	
	#fall back on currently selected value as default
	if defaultProject == None:
		defaultProject = scriptDialog.GetValue( "ProjectBox" )
	
	statusMessage = "fetching projects"
	
	if user != None:
		AddShotgunToPath()
		import ShotgunUtils
		
		WriteToLogBox( "Getting Project list for user '%s'... " % user, True )
		projects = ShotgunUtils.GetProjects( shotgunPath )
		WriteToLogBox( "done!" )
		
		projectNames.append( " " )
		
	for project in projects:
		projectName = project['name']
		sgProjectDict[ projectName ] = project
		projectNames.append( projectName )
	
	projectNames.sort()
	
	if advancedMode:
		scriptDialog.SetItems( "ProjectBox", tuple( projectNames ) )
	
	#default to the previously selected project, if available
	if not IsNoneOrWhiteSpace( defaultProject ) and defaultProject in projectNames:
		pass
	elif len( projectNames ) > 0:
		defaultProject = projectNames[0]
	else:
		defaultProject = None
	
	#set the default project
	if defaultProject != None:
		updatingUI = True
		
		if defaultProject.strip() != "":
			WriteToLogBox( "Defaulting to project: '%s'" % defaultProject )
			
		scriptDialog.SetValue( "ProjectBox", defaultProject )
		updatingUI = False
		return defaultProject
	
except:
	#Make sure we set this to notify other threads that this failed
	if IsNoneOrWhiteSpace( errorMessage ):
		errorMessage = "An error occurred while attempting to collect Project Names from Shotgun; see log for details."
	
	WriteToLogBox( "UNEXPECTED ERROR:" )
	WriteToLogBox( str( sys.exc_info()[0] ) )
	WriteToLogBox( str( sys.exc_info()[1] ) )
	WriteToLogBox( "---END ERROR INFO---" )

return None

#Gets SG Entities (Shots/Assets) for a given project
#Returns the defaulted entity, if applicable
def GetEntitiesForProject( projectName, defaultEntity=None ):
global errorMessage
global shotgunPath
global scriptDialog
global updatingUI
global sgProjectDict
global sgEntityDict
global statusMessage

try:
	shotgunEntityDict = {}
	entityNames = [" "]
	
	#fall back on currently selected value as a default
	if defaultEntity == None:
		defaultEntity = scriptDialog.GetValue( "EntityBox" )
	
	statusMessage =  "fetching entities"
	
	if not IsNoneOrWhiteSpace( projectName ):
		shots = []
		assets = []
		shotNames = []
		assetNames = []
		elementNames = []
		
		project = sgProjectDict[ projectName ]
		
		AddShotgunToPath()
		import ShotgunUtils
		
		WriteToLogBox( "Getting Entity lists for project '%s'... " % projectName, True )
		shots, assets, elements = ShotgunUtils.GetShotsAssetsAndElements( project['id'], shotgunPath )
		WriteToLogBox( "done!" )
		
		for shot in shots:
			shotName = shot['code']
			
			if shot.get( "sg_sequence", None ):
				shotName = "%s > %s" % (shot['sg_sequence']['name'], shotName) 
				
			sgEntityDict[ shotName ] = shot
			shotNames.append( shotName )
			
		for asset in assets:
			assetName = asset['code']
			sgEntityDict[ assetName ] = asset
			assetNames.append( assetName )
			
		for element in elements:
			elementName = element['code']
			sgEntityDict[ elementName ] = element
			elementNames.append( elementName )
	
		shotNames.sort()
		entityNames.extend( shotNames )
		
		assetNames.sort()
		entityNames.extend( assetNames )
		
		elementNames.sort()
		entityNames.extend( elementNames )
			
	if advancedMode:
		scriptDialog.SetItems( "EntityBox", tuple( entityNames ) )
	
	#default to given entity if available
	if not IsNoneOrWhiteSpace( defaultEntity ) and defaultEntity in entityNames:
		pass
	elif len( entityNames ) > 0:
		defaultEntity = entityNames[0]
	else:
		defaultEntity = None
	
	#set the default entity
	if defaultEntity != None:
		updatingUI = True
		
		if defaultEntity.strip() != "":
			WriteToLogBox( "Defaulting to entity: '%s'" % defaultEntity )
			
		scriptDialog.SetValue( "EntityBox", defaultEntity )
		updatingUI = False
		return defaultEntity
except:
	#Make sure we set this to notify other threads that this failed
	if IsNoneOrWhiteSpace( errorMessage ):
		errorMessage = "An error occurred while attempting to collect Entity Names from Shotgun; see log for details."
	
	WriteToLogBox( "UNEXPECTED ERROR:" )
	WriteToLogBox( str( sys.exc_info()[0] ) )
	WriteToLogBox( str( sys.exc_info()[1] ) )
	WriteToLogBox( "---END ERROR INFO---" )
	
return None

def GetVersionsForEntity( entityName, defaultVersion=None ):
global errorMessage
global shotgunPath
global scriptDialog
global updatingUI
global sgProjectDict
global sgEntityDict
global statusMessage
global sgVersionDict

try:
	statusMessage =  "fetching versions"
	
	versionCodes = []
	sgVersionDict = dict()
	
	#fall back on currently selected value as a default
	if defaultVersion == None:
		defaultVersion = scriptDialog.GetValue( "VersionCombo" )
	
	if not IsNoneOrWhiteSpace( entityName ):
		AddShotgunToPath()
		import ShotgunUtils
		
		WriteToLogBox( "Getting Version list for entity '%s'... " % entityName, True )
		versions = ShotgunUtils.GetVersions( sgEntityDict[entityName]['type'], sgEntityDict[entityName]['id'], shotgunPath )
		WriteToLogBox( "done!" )
		
		for version in versions :
			versionCode = version['code']
			
			#need a unique display name for each version, so append [#] if it's already in the dict
			versionDisplayName = versionCode
			index = 0
			while versionDisplayName in sgVersionDict:
				index += 1
				versionDisplayName = "%s [%d]" % (versionCode, index)
			
			versionCodes.append( versionDisplayName )
			sgVersionDict[versionDisplayName] = version
	
	if len(versionCodes) > 0 :
		scriptDialog.SetItems( 'VersionCombo', Array[str](versionCodes) )
		scriptDialog.SetValue( 'VersionCombo', versionCodes[0])
	else :	
		scriptDialog.SetItems( 'VersionCombo', Array[str](['']) )
		scriptDialog.SetValue( 'VersionCombo', '')
		scriptDialog.SetItems( 'VersionCombo', Array[str]([]) )
	
	#default to given version if available
	if not IsNoneOrWhiteSpace( defaultVersion ) and defaultVersion in versionCodes:
		pass
	elif len( versionCodes ) > 0:
		defaultVersion = versionCodes[0]
	else:
		defaultVersion = None
	
	#set the default version
	if defaultVersion != None:
		updatingUI = True
		
		if defaultVersion.strip() != "":
			WriteToLogBox( "Defaulting to version: '%s'" % defaultVersion )
			
		scriptDialog.SetValue( "VersionCombo", defaultVersion )
		updatingUI = False
		return defaultVersion
except:
	#Make sure we set this to notify other threads that this failed
	if IsNoneOrWhiteSpace( errorMessage ):
		errorMessage = "An error occurred while attempting to collect Version Names from Shotgun; see log for details."
	
	WriteToLogBox( "UNEXPECTED ERROR:" )
	WriteToLogBox( str( sys.exc_info()[0] ) )
	WriteToLogBox( str( sys.exc_info()[1] ) )
	WriteToLogBox( "---END ERROR INFO---" )
	
return None

def GetVersionsForTask( taskName, defaultVersion=None ):
global errorMessage
global shotgunPath
global scriptDialog
global updatingUI
global sgTaskDict
global statusMessage
global sgVersionDict

try:
	statusMessage =  "fetching versions"
	
	versionCodes = []
	sgVersionDict = dict()
	
	#fall back on currently selected value as a default
	if defaultVersion == None:
		defaultVersion = scriptDialog.GetValue( "VersionCombo" )
	
	if not IsNoneOrWhiteSpace( taskName ):
		AddShotgunToPath()
		import ShotgunUtils
		
		WriteToLogBox( "Getting Version list for task '%s'... " % taskName, True )
		versions = ShotgunUtils.GetVersions( sgTaskDict[taskName]['entity']['type'], sgTaskDict[taskName]['entity']['id'], shotgunPath )
		WriteToLogBox( "done!" )
		
		for version in versions :
			versionCode = version['code']
			
			#need a unique display name for each version, so append [#] if it's already in the dict
			versionDisplayName = versionCode
			index = 0
			while versionDisplayName in sgVersionDict:
				index += 1
				versionDisplayName = "%s [%d]" % (versionCode, index)
			
			versionCodes.append( versionDisplayName )
			sgVersionDict[versionDisplayName] = version
			
		versionCodes.sort()
	
	if len(versionCodes) > 0 :
		scriptDialog.SetItems( 'VersionCombo', Array[str](versionCodes) )
		scriptDialog.SetValue( 'VersionCombo', versionCodes[0])
	else :	
		scriptDialog.SetItems( 'VersionCombo', Array[str](['']) )
		scriptDialog.SetValue( 'VersionCombo', '')
		scriptDialog.SetItems( 'VersionCombo', Array[str]([]) )
	
	#default to given version if available
	if not IsNoneOrWhiteSpace( defaultVersion ) and defaultVersion in versionCodes:
		pass
	elif len( versionCodes ) > 0:
		defaultVersion = versionCodes[0]
	else:
		defaultVersion = None
	
	#set the default version
	if defaultVersion != None:
		updatingUI = True
		
		if defaultVersion.strip() != "":
			WriteToLogBox( "Defaulting to version: '%s'" % defaultVersion )
			
		scriptDialog.SetValue( "VersionCombo", defaultVersion )
		updatingUI = False
		return defaultVersion
except:
	#Make sure we set this to notify other threads that this failed
	if IsNoneOrWhiteSpace( errorMessage ):
		errorMessage = "An error occurred while attempting to collect Version Names from Shotgun; see log for details."
	
	WriteToLogBox( "UNEXPECTED ERROR:" )
	WriteToLogBox( str( sys.exc_info()[0] ) )
	WriteToLogBox( str( sys.exc_info()[1] ) )
	WriteToLogBox( "---END ERROR INFO---" )
	
return None

def ShotgunTaskChanged( *args ):
global scriptDialog
global sgTaskDict
global sgProjectDict
global updatingUI
global advancedMode
global versionSelectMode
global workerThread
global progressThread

taskName = ""

if len( scriptDialog.GetItems( "TaskBox" ) ) > 0:
	taskName = scriptDialog.GetValue( "TaskBox" )
	
	#If we're updating in code, DON'T start new threads
	if versionSelectMode and not updatingUI:
		#Start up the worker & progress threads
		statusMessage = "connecting" # initial status message for progress bar
		workerThread = Thread( ParameterizedThreadStart( GetVersionsForTask ) )
		workerThread.IsBackground = True
		progressThread = Thread( ThreadStart( LookBusy ) )
		progressThread.IsBackground = True
		
		workerThread.Start( taskName )
		progressThread.Start()

	projectNames = [ ]
	entityNames = [ ]
	if not IsNoneOrWhiteSpace( taskName ):
		task = sgTaskDict[ taskName ]
		if task['project'] != None and task['entity'] != None:
			projectNames.append( task['project']['name'] )
			entityNames.append( task['entity']['name'] )
	else:
		projectNames.append( " " )
		entityNames.append( " " )
		
		if advancedMode:
			for key in sgProjectDict.keys():
				projectNames.append( key )
		
		projectNames.sort()
	
	updatingUI = True
	
	if advancedMode:
		scriptDialog.SetItems( "ProjectBox", tuple( projectNames ) )
	
	if len( projectNames ) > 0:
		scriptDialog.SetValue( "ProjectBox", projectNames[ 0 ] )
	
	if advancedMode:
		scriptDialog.SetItems( "EntityBox", tuple( entityNames ) )
	
	if len( entityNames ) > 0:
		scriptDialog.SetValue( "EntityBox", entityNames[ 0 ] )
		
	updatingUI = False
	
VersionTemplateChanged( None )
UpdateEnabledStatus()

def ShotgunProjectChanged( *args ):
global scriptDialog
global updatingUI
global workerThread
global progressThread

#Make sure we don't chain events when we're updating values in code
if updatingUI:
	return

if len( scriptDialog.GetItems( "ProjectBox" ) ) > 0:
	projectName = scriptDialog.GetValue( "ProjectBox" )
	
	#Start up the worker & progress threads
	statusMessage = "connecting" # initial status message for progress bar
	workerThread = Thread( ParameterizedThreadStart( GetEntitiesForProject ) )
	workerThread.IsBackground = True
	progressThread = Thread( ThreadStart( LookBusy ) )
	progressThread.IsBackground = True
	
	workerThread.Start( projectName )
	progressThread.Start()

VersionTemplateChanged( None )

def ShotgunVersionChanged( *args ):
global scriptDialog
global updatingUI
global sgVersionDict

if updatingUI:
	return

description = ""
if len( scriptDialog.GetItems( "VersionCombo" ) ) > 0:
	versionName = scriptDialog.GetValue( "VersionCombo" )
	if not IsNoneOrWhiteSpace( versionName ) and sgVersionDict.has_key( versionName ):
		version = sgVersionDict[versionName]
		if version.has_key( 'description' ):
			description = version['description']
		
scriptDialog.SetValue( "DescriptionBox", description )

UpdateEnabledStatus()

#Returns the template string with placeholder values swapped out (optionally replacing {jobid} with a dummy value)
def ApplyTemplate( templateString, dummyJobID=True ):
global sgTaskDict
global sgEntityDict
global currentUser
global advancedMode

#might not be logged in for whatever reason
if currentUser != None:
	#could change this to actual user name if users prefer (instead of login)
	userName = currentUser['login']
	templateString = re.sub( '(?i)\$\{user\}', userName, templateString )

#might not be a task selected
displayTaskName = scriptDialog.GetValue("TaskBox")
if not IsNoneOrWhiteSpace( displayTaskName ):
	task = sgTaskDict[ displayTaskName ]
	templateString = re.sub( '(?i)\$\{task\}', task['content'], templateString )
	templateString = re.sub( '(?i)\$\{project\}', task['project']['name'], templateString )
	templateString = re.sub( '(?i)\$\{shot\}', task['entity']['name'], templateString )
elif advancedMode:
	#no task selected, check project/entity
	projectName = scriptDialog.GetValue("ProjectBox")
	if not IsNoneOrWhiteSpace( projectName ):
		templateString = re.sub( '(?i)\$\{project\}', projectName, templateString )
	
		#might have to change this later if we want {shot} to ONLY pull shots (not whatever's selected in the entity box)
		displayEntityName = scriptDialog.GetValue("EntityBox")
		if not IsNoneOrWhiteSpace( displayEntityName ):
			entityName = sgEntityDict[ displayEntityName ]['code']
			templateString = re.sub( '(?i)\$\{shot\}', entityName, templateString )

if dummyJobID:
	templateString = re.sub( '(?i)\$\{jobid\}', '999_000_999_099a9aa9', templateString )

return templateString

def ShotgunEntityChanged( *args ):
global scriptDialog
global versionSelectMode
global workerThread
global progressThread
global updatingUI

#Make sure we don't chain events when we're updating values in code
if updatingUI:
	return

taskName = scriptDialog.GetValue( "TaskBox" )
if versionSelectMode and IsNoneOrWhiteSpace( taskName ):
	entityName = ""
	if len( scriptDialog.GetItems( "EntityBox" ) ) > 0:
		entityName = scriptDialog.GetValue( "EntityBox" )

	#Start up the worker & progress threads
	statusMessage = "connecting" # initial status message for progress bar
	workerThread = Thread( ParameterizedThreadStart( GetVersionsForEntity ) )
	workerThread.IsBackground = True
	progressThread = Thread( ThreadStart( LookBusy ) )
	progressThread.IsBackground = True
	
	workerThread.Start( entityName )
	progressThread.Start()

VersionTemplateChanged( None )

def VersionTemplateChanged( *args ):
global scriptDialog
global versionSelectMode

if not versionSelectMode:
	templateString = scriptDialog.GetValue( "TemplateBox" )
	scriptDialog.SetValue( "PreviewBox", ApplyTemplate( templateString ) )

def LoginNameChanged( *args ):
UpdateEnabledStatus()
return

def LoginButtonPressed( *args ):
global statusMessage
global workerThread
global progressThread
global scriptDialog

statusMessage = "connecting" # initial status message for progress bar
#ConnectToShotgun( scriptDialog.GetValue( "LoginBox" ) )

workerThread = Thread( ParameterizedThreadStart( ConnectToShotgun ) )
workerThread.IsBackground = True
progressThread = Thread( ThreadStart( LookBusy ) )
progressThread.IsBackground = True

workerThread.Start( scriptDialog.GetValue( "LoginBox" ) )
progressThread.Start()
return

def NewEntityButton_Pressed(*args):
if len( args ) > 0:
button = args[0]
button.ContextMenu.Show( button, Point(0, 0) )

def NewSGItemBrowser( itemName, additionalArgs="" ):
global sgURL
global scriptDialog

if not IsNoneOrWhiteSpace( sgURL ):
	newEntityURL = sgURL + "new/" + itemName + "?show_nav=no"
	projectName = scriptDialog.GetValue( "ProjectBox" )
	
	if not IsNoneOrWhiteSpace( projectName ):
		newEntityURL += '&project=' + projectName
	
	newEntityURL += additionalArgs
	
	webbrowser.open( newEntityURL, 1, True )

def NewAssetMenuItem_Click(*args):
NewSGItemBrowser( “Asset” )

def NewElementMenuItem_Click(*args):
NewSGItemBrowser( “Element” )

def NewShotMenuItem_Click(*args):
NewSGItemBrowser( “Shot” )

def NewTaskMenuItem_Click(*args):
#TODO: Figure out how to default users. Probably using the default={…} argument (not like project)…
#if currentUser != None:
# NewSGItemBrowser( “Task”, “&task_assignees=” + currentUser.get( “name”, “” ) )
#else:
NewSGItemBrowser( “Task” )

#reads in the sticky settings file and stores the key-value pairs in a dictionary
def GetStickySettings( fileName ):
global stickySettings

try:
	WriteToLogBox( "Retrieving sticky settings... ", True )
	settingsFile = open( fileName, "r" )
	settingLines = settingsFile.readlines()
	
	stickySettings = {}
	for currLine in settingLines:
		line = currLine.replace( "\n", "" ).replace( "\r", "" )
		equalIndex = line.find( "=" )
		if equalIndex >= 0:
			if equalIndex < (len(line) - 1):
				stickySettings[line[:equalIndex]] = line[equalIndex+1:]
			else:
				stickySettings[line[:equalIndex]] = ""
	
	WriteToLogBox( "done!" )
except:
	WriteToLogBox( "No sticky settings found." )
	
try:
	#Always try to close the file
	settingsFile.close()
except:
	pass

def GetSettingsFilename():
global appName

return Path.Combine( GetDeadlineSettingsPath(), appName + "ShotgunSettings.ini" )

def CancelButtonPressed( *args ):
global scriptDialog
global workerThread
global progressThread

#Make sure to abort non-ui threads first, so that they don't keep running
if workerThread != None and workerThread.IsAlive:
	workerThread.Abort()

if progressThread != None and progressThread.IsAlive:
	progressThread.Abort()
	
scriptDialog.CloseDialog()

def IsNoneOrWhiteSpace( someString ):
return someString == None or someString.strip() == “”

def OKButtonPressed( *args ):
global scriptDialog
global settings
global sgConfig
global sgEntityDict
global sgProjectDict
global sgTaskDict
global sgVersionDict
global advancedMode
global versionSelectMode
global currentUser

try:
	WriteToLogBox( "Validating selected values..." )
	userName = ""
	taskName = scriptDialog.GetValue( "TaskBox" )
	projectName = scriptDialog.GetValue( "ProjectBox" )
	entityName = scriptDialog.GetValue( "EntityBox" )
	description = ApplyTemplate( scriptDialog.GetValue( "DescriptionBox" ), False )
	
	if versionSelectMode:
		versionName = scriptDialog.GetValue( "VersionCombo" )
	else:
		versionName = ApplyTemplate( scriptDialog.GetValue( "TemplateBox" ), False )
	
	
	draftTemplate = ""
	if not IsNoneOrWhiteSpace( taskName ):
		draftTemplate = sgTaskDict[taskName].get( "draftTemplate", "" )
	
	validationPassed = True
	
	#Need to have a valid user logged in
	if currentUser == None:
		WriteToLogBox( "Validation failed on User Name" )
		validationPassed = False
	else:
		userName = currentUser.get( "login", None )
		
		if IsNoneOrWhiteSpace( userName ):
			WriteToLogBox( "Validation failed on User Name" )
			validationPassed = False
		
	#Need to either have Project & Entity, or Task specified
	if IsNoneOrWhiteSpace( taskName ) and (IsNoneOrWhiteSpace( projectName ) or IsNoneOrWhiteSpace( entityName ) or not advancedMode):
		WriteToLogBox( "Validation failed on Task or Project/Entity" )
		validationPassed = False
		
	#Need to specify a version name
	if IsNoneOrWhiteSpace( versionName ):
		WriteToLogBox( "Validation failed on Version Name" )
		validationPassed = False
	
	if not validationPassed:
		validationMessage = ""
		if versionSelectMode:
			validationMessage = "You must complete this form in order to select an existing Shotgun Version for this job.\n\nPlease fill in any missing info before proceeding."
		else:
			validationMessage = "You must complete this form in order to create a new Shotgun Version for this job.\n\nPlease fill in any missing info before proceeding."
		
		scriptDialog.ShowMessageBox( validationMessage, "Shotgun Form Incomplete" )
		return
		
	WriteToLogBox( "Validating passed!" )
	WriteToLogBox( "Building output... ", True )
	
	ClientUtils.LogText( "VersionName=%s" % versionName )
	ClientUtils.LogText( "Description=%s" % description )
	ClientUtils.LogText( "UserName=%s" % userName )
	
	if not IsNoneOrWhiteSpace( taskName ):
		task = sgTaskDict[ taskName ]
		
		ClientUtils.LogText( "TaskName=%s" % task['content'] )
		ClientUtils.LogText( "ProjectName=%s" % task['project']['name'] )
		ClientUtils.LogText( "EntityName=%s" % task['entity']['name'] )
		
		ClientUtils.LogText( "TaskId=%s" % task['id'] )
		ClientUtils.LogText( "ProjectId=%s" % task['project']['id'] )
		ClientUtils.LogText( "EntityId=%s" % task['entity']['id'] )
		ClientUtils.LogText( "EntityType=%s" % task['entity']['type'] )
	else:
		project = sgProjectDict[ projectName ]
		entity = sgEntityDict[ entityName ]
		
		ClientUtils.LogText( "TaskName=None" )
		ClientUtils.LogText( "ProjectName=%s" % projectName )
		ClientUtils.LogText( "EntityName=%s" % entityName )
		
		ClientUtils.LogText( "TaskId=-1" )
		ClientUtils.LogText( "ProjectId=%s" % project['id'] )
		ClientUtils.LogText( "EntityId=%s" % entity['id'] )
		ClientUtils.LogText( "EntityType=%s" % entity['type'] )
	
	if versionSelectMode:
		version = sgVersionDict[ versionName ]
		pathField = sgConfig.get('VersionEntityPathToFramesField', "")
		firstFrameField = sgConfig.get('VersionEntityFirstFrameField', "")
		lastFrameField = sgConfig.get('VersionEntityLastFrameField', "")
		
		ClientUtils.LogText( "VersionId=%s" % version['id'] )
		ClientUtils.LogText( "PathToFrames=%s" % version.get(pathField, "") )
		ClientUtils.LogText( "FirstFrame=%s" % version.get(firstFrameField, "") )
		ClientUtils.LogText( "LastFrame=%s" % version.get(lastFrameField, "") )
	
	ClientUtils.LogText( "DraftTemplate=%s" % draftTemplate )

	WriteToLogBox( "done!" )
	
	#switch the contents of the login box to be the current user, so it gets stickied properly
	scriptDialog.SetValue( "LoginBox", currentUser['login'] )
	
	WriteToLogBox( "Saving sticky settings... ", True )
	scriptDialog.SaveSettings( GetSettingsFilename(), settings )
	WriteToLogBox( "done!" )
	
	scriptDialog.CloseDialog()
except:
	#if an error occurred while trying to close the dialog, this UI stuff might fail -- don't want it to generate another exception
	try:
		WriteToLogBox( "UNEXPECTED ERROR:" )
		WriteToLogBox( str( sys.exc_info()[0] ) )
		WriteToLogBox( str( sys.exc_info()[1] ) )
		WriteToLogBox( "---END ERROR INFO---" )
		
		scriptDialog.ShowMessageBox( "An error occurred while preparing output; see log for details.", "ERROR!" )
	except:
		pass
[/code]

No problem, glad to be of help!

Cheers,

  • Jon