#############################################################
# Animating Blender FOV: ScriptLink Script
# (c) 2007 K. G. Nyman
# Not registered for direct running - scriptlink only
# For more info see
# http://home.metrocast.net/~chipartist/BlensesSite/AnimBLenses
# Bug reports and comments: chipartist@metrocast.net
#############################################################
# History
# V: 0.0.1 - 10-30-2007 - Version one public release
#############################################################

import Blender
from Blender import *
import math

#############################################################
# Globals
VERSION         ='0.0.1'

# Get scene data
curScn = Scene.GetCurrent()
curCam = curScn.objects.camera # current Camera
curCamData = curCam.getData() # the Camera data object
curDofDist = curCamData.dofDist # current DoFDist value

DATA_ANIM = {}
# load required data from BLenses data set
DATA_CACHED = Blender.Registry.GetKey('BLensAnimData', True)
if	DATA_CACHED:
	DATA_ANIM['IMG_AP_W'] = DATA_CACHED['IMG_AP_W']
	DATA_ANIM['WSU_MM'] = DATA_CACHED['WSU_MM']
	DATA_ANIM['WSU_CM'] = DATA_CACHED['WSU_CM']
	DATA_ANIM['WSU_M'] = DATA_CACHED['WSU_M']
	
# find the zoom control object
ScnObjs = curScn.objects
for obj in ScnObjs:
	if	obj.name.startswith('Zoom_'+curCam.name):
		Zoomer = obj

# "Zoomer" scale value stores the focal length (FL) for animation
# purposes. Script uses X part of tuple for calculation
ZoomerFL = Zoomer.SizeX
Zoomer.drawSize = (10 / Zoomer.SizeX) #keeps draw size manageable
Zoomer.setLocation(curCam.getLocation())

####################################################
# the core focal length to FOV calculation

	# set World Scale Unit multiplier
if	(DATA_ANIM['WSU_M'] == 1):
	WorldScale = 1000
elif (DATA_ANIM['WSU_CM'] == 1):
	WorldScale = 10
elif (DATA_ANIM['WSU_MM'] == 1):
	WorldScale = 1
	
# calculate camera-to-subject distance
# using location of POI constraint
# find POI
for	CamConst in curCam.constraints: #CamConstraints:
	if	(CamConst.type == Constraint.Type.TRACKTO):
		if CamConst.name.startswith('POI_'+curCam.name):
			CamPOITarg = CamConst.__getitem__(Constraint.Settings.TARGET)
		else:
			PupText = "Requires a Point of Interest%t"
			Draw.PupMenu(PupText)
			Draw.Exit()
	
curCamLoc = curCam.getLocation('worldspace')
curCamPOILoc = CamPOITarg.getLocation('worldspace')
#break down tuples (done mainly for clarity of scripting)
curCamLocX = curCamLoc[0]
curCamLocY = curCamLoc[1]
curCamLocZ = curCamLoc[2]
curCamPOILocX = curCamPOILoc[0]
curCamPOILocY = curCamPOILoc[1]
curCamPOILocZ = curCamPOILoc[2]
# find absolute differences
X1 = abs(curCamLocX - curCamPOILocX)
Y1 = abs(curCamLocY - curCamPOILocY)
Z1 = abs(curCamLocZ - curCamPOILocZ)
# Pythagorean math finds absolute distance between Camera & POI
Hyp1 = math.sqrt(math.pow(X1, 2) + math.pow(Z1, 2))
Hyp2 = math.sqrt(math.pow(Hyp1, 2) + math.pow(Y1, 2))

curCamData.dofDist = Hyp2

# make sure clip is > DoFDist
if	(curCamData.clipEnd < curCamData.dofDist):
	curCamData.clipEnd = curCamData.dofDist + 50

s = curCamData.dofDist * WorldScale
A = DATA_ANIM['IMG_AP_W']
f = ZoomerFL

FOV = 2 * math.atan((A*(s-f))/(2 * s * f)) * 180/math.pi
	
#set the Blender camera angle (field of view)
curCamData.angle = FOV
