global  gridNear,  gridFar, HelperCam, zpdMin, zpdMax, zpd_registerTime, selectcamname, ZDepthPasser, appRef , zpdfilename,zpdLensVar, zpdFNumVar
fn zpdSetLensAndFNum = 
(
	if classof ZDepthPasser.zdp_PicCam.object == VRayPhysicalCamera then 
			(
				zpdFNumVar =  ZDepthPasser.zdp_PicCam.object.f_number
				zpdLensVar = ZDepthPasser.zdp_PicCam.object.focal_length	
			)
			else
			(
			--	zpdFNumVar =  (cameraFOV.FOVtoMM ZDepthPasser.zdp_PicCam.object.fov)/(getRendApertureWidth())
				zpdFNumVar  = 8
				zpdLensVar = cameraFOV.FOVtoMM ZDepthPasser.zdp_PicCam.object.fov
			)
)
fn calcNearDof = 
(
		zi =  ZDepthPasser.zdp_BlurDisk.value/1000
		zpd_R = 0.02540005080010160020320040640081*HelperCam.targetDistance
		zpd_f = zpdLensVar/1000
		zpd_K = zpdFNumVar
		--Calc Near
		step1 =  zpd_R * (zpd_f*zpd_f)
		step2 = zpd_R - zpd_f
		step2 = zpd_K*step2*zi
		step2 = (zpd_f*zpd_f) + step2
		zNearDof = step1/step2
		zNearDof = zNearDof/0.02540005080010160020320040640081
		gridNear.parent = undefined
		HelperCam.targetDistance = zNearDof
		gridNear.pos = HelperCam.target.pos
		HelperCam.targetDistance = ZDepthPasser.zdp_PicCam.object.targetDistance
		HelperCam.target.pos = ZDepthPasser.zdp_PicCam.object.target.pos
		gridNear.parent = ZDepthPasser.zdp_PicCam.object.target
)
fn calcFarDof = 
(
		zi =  ZDepthPasser.zdp_BlurDisk.value/1000
		zpd_R = 0.02540005080010160020320040640081*HelperCam.targetDistance
		zpd_f = zpdLensVar/1000
		zpd_K = zpdFNumVar
		--Calc Far
		step1 =  zpd_R * (zpd_f*zpd_f)	
		step2 = zpd_R - zpd_f
		step2 = zpd_K*step2*zi
		--print step2
		step2 = (zpd_f*zpd_f) - step2
		zfarDof = step1/step2
		zfarDof = zfarDof/0.02540005080010160020320040640081
		gridFar.parent = undefined
		oldTarget = HelperCam.targetDistance
		HelperCam.targetDistance = zFarDof
		gridFar.pos = HelperCam.target.pos
		HelperCam.targetDistance = ZDepthPasser.zdp_PicCam.object.targetDistance
		HelperCam.target.pos = ZDepthPasser.zdp_PicCam.object.target.pos
		gridFar.parent = ZDepthPasser.zdp_PicCam.object.target
)

fn zpdSetNode = 
(
	HelperCam = getNodeByName "zdp_Helper_Cam"
	HelperCam.target = getNodeByName "zdp_Helper_Cam_target"
	gridNear = getNodeByName "zdpNearPlane"
	gridFar = getNodeByName "zdpFarPlane"
	ZDepthPasser.zdp_PicCam.object = getNodeByName selectcamname
)

fn zdp_caldof = 
(
		zpdSetNode()
		HelperCam.pos = ZDepthPasser.zdp_PicCam.object.pos
		gridNear.dir = ZDepthPasser.zdp_PicCam.object.dir
		gridFar.dir = ZDepthPasser.zdp_PicCam.object.dir
		HelperCam.target.pos = ZDepthPasser.zdp_PicCam.object.target.pos
		calcNearDof()
		calcFarDof()	
)

fn setnumber4name num = 
(
	num = num as integer
	if num < 10 then 
		"000"+num as string
	else if num >= 10 AND num < 100 then
		"00"+num as string
	else if num >= 100 AND num < 1000 then
		"0"+num as string
	else if num >= 1000 then
		num as string
)
function zpdSaveFilePrisets = 
(
	saveMaxFile (GetDir #renderpresets+"\zpd_temp.max")
)
fn zpdSetMaterials = 
(
	for obj in objects do
	(
		if (superclassof obj) == GeometryClass then
		(
			if classof obj != Targetobject then
			(
				obj.material = standardMaterial diffuseMap:()
			)
		)else
		(	
			if (superclassof obj) == light then
			(
				obj.enabled = false
				hide obj
			)
		)
	)	
)

fn zpd_setrenderelements = 
(
	renderSceneDialog.close()
	if rendoutputfilename == "" then
		rendoutputfilename = GetDir #renderoutput
	rendoutputfilename = (getFilenamePath rendoutputfilename)+"dof.jpg"
	rendsavefile = true
	renderSceneDialog.open()
	ren = maxOps.GetCurRenderElementMgr() 
	ren.removeallrenderelements()
	zpdMin = Z_Depth elementname:"DOF_Near"
	zpdMax = Z_Depth elementname:"DOF_Far"	
	ren.addrenderelement zpdMin
	ren.addrenderelement zpdMax
	el = ren.getrenderelement 0
	el = ren.getrenderelement 1
	
	zpdMin.Zmin = distance HelperCam gridNear
	zpdMin.ZMax =  HelperCam.targetDistance
	zpdMin.filterOn = true
	zpdMin.zUpdate = false
	
	zpdMax.Zmin =HelperCam.targetDistance
	zpdMax.ZMax = distance  HelperCam gridFar
	zpdMax.filterOn = true
	zpdMax.zUpdate = false
	
)
fn zpdLoadFilePrisets=
(
	loadMaxFile (GetDir #renderpresets+"\zpd_temp.max")
)
fn zdpAddRender = 
(
	if ZDepthPasser.zdp_PicCam.object != undefined then 
	(
		if not isDeleted ZDepthPasser.zdp_PicCam.object then
		(
			zpdSetLensAndFNum()
			zdp_caldof()	
		)
	)
)
fn zpdRegEvents = 
(
	when parameters ZDepthPasser.zdp_PicCam.object changes id:#zpd_dir do
	(
		zpdSetLensAndFNum()
		zdpAddRender()
		deleteKeys gridNear.controller 
		deleteKeys gridFar.controller
		deleteKeys HelperCam 
	)				
	when names ZDepthPasser.zdp_PicCam.object changes id:#zpd_namepic do
		ZDepthPasser.zdp_PicCam.text = ZDepthPasser.zdp_PicCam.object.name	
	when select gridNear changes  id:#zpd_selectNear do
		gridNear.isSelected = false
	when select gridFar changes id:#zpd_selectFar  do
		gridFar.isSelected = false
	when  ZDepthPasser.zdp_PicCam.object deleted id:#zpd_deleted do
	(
		ZDepthPasser.zdp_PicCam.text = "Pic camera"
		delete gridFar
		delete HelperCam
		delete gridNear
		ZDepthPasser.zdp_PicCam.object = undefined
		deleteAllChangeHandlers id:#zpd_dirtarget
		deleteAllChangeHandlers id:#zpd_dir
		deleteAllChangeHandlers id:#zpd_namepic
		deleteAllChangeHandlers id:#zpd_selectNear
		deleteAllChangeHandlers id:#zpd_selectFar
		deleteAllChangeHandlers id:#zpd_deleted
		deleteAllChangeHandlers id:#zdpRenderChange			
	)
)
fn createPSPass numname = 
(
	--appRef.Visible = false

	filenear =(getFilenamePath rendoutputfilename)+(getFilenameFile rendoutputfilename)+"_DOF_Near"+(getFilenameType rendoutputfilename)
	NearDoc = appRef.open(filenear)
	filefar = (getFilenamePath rendoutputfilename)+(getFilenameFile rendoutputfilename)+"_DOF_Far"+(getFilenameType rendoutputfilename)
	FarDoc = appRef.open(filefar)
	appRef.ActiveDocument.flatten()
	appRef.ActiveDocument.Selection.SelectAll()
	appRef.ActiveDocument.Selection.Copy()
	appRef.ActiveDocument.Close(2)
	appRef.ActiveDocument.Paste()
	appRef.ActiveDocument.ActiveLayer.BlendMode = 9
	appRef.ActiveDocument.ActiveLayer.Invert
	appRef.ActiveDocument.ActiveLayer.Merge
	appRef.ActiveDocument.ActiveLayer.ApplyBlur
	appRef.ActiveDocument.ActiveLayer.ApplyBlur
	appRef.ActiveDocument.ActiveLayer.ApplyBlur
	jpgSaveOptions = createOLEObject "Photoshop.JPEGSaveOptions" 
	jpgSaveOptions.EmbedColorProfile = True 
	jpgSaveOptions.FormatOptions = 1
	jpgSaveOptions.Matte = 1 
	jpgSaveOptions.Quality = 10 
	outFileName = ((getFilenamePath rendoutputfilename)+(getFilenameFile rendoutputfilename)+numname+".jpg")
	appRef.ActiveDocument.SaveAs outFileName  jpgSaveOptions  True 
	appRef.ActiveDocument.Close(2)
	objFSO = createOLEObject "Scripting.FileSystemObject" 
	objFSO.DeleteFile(filenear)
	objFSO.DeleteFile(filefar)
	objFSO.DeleteFile((getFilenamePath rendoutputfilename)+"\\dof.jpg")

)
fn zpdStartRender =
(
	zpdSaveFilePrisets()
	
	zpdSetMaterials()
	renderers.current = DefaultScanlineRenderer()	
	selectFrame = sliderTime.frame
	if rendTimeType < 4 then
	(		
		 zdpAddRender()
		appRef = createOLEObject "Photoshop.Application"
		if rendTimeType==1 then
		(
			zpd_setrenderelements()
			render camera:HelperCam frame:selectFrame outputfile:rendoutputfilename
			createPSPass((setnumber4name sliderTime.frame) as string)
			zpdLoadFilePrisets()
			zpdSetNode()
			zpdRegEvents()			
			ren = maxOps.GetCurRenderElementMgr() 
			ren.removeallrenderelements()
		)else if rendTimeType==2  then 
		(
			startsslidertime = sliderTime
			for i in animationRange.start.frame to animationRange.end.frame do
			(
				sliderTime =  i 
				zpd_setrenderelements()
				render camera:HelperCam frame:sliderTime outputfile:rendoutputfilename
				createPSPass((setnumber4name sliderTime.frame) as string)
			)
			ren = maxOps.GetCurRenderElementMgr() 
			ren.removeallrenderelements()
			zpdLoadFilePrisets()
			zpdSetNode()
			zpdRegEvents()			
			sliderTime = startsslidertime
		)else if  rendTimeType==3 then 
		(
			startsslidertime = sliderTime
			for i in rendStart.frame to rendEnd.frame do
			(
				sliderTime =  i 
				zpd_setrenderelements()
				render camera:HelperCam frame:sliderTime outputfile:rendoutputfilename
				createPSPass((setnumber4name sliderTime.frame) as string)
			)
			ren = maxOps.GetCurRenderElementMgr() 
			ren.removeallrenderelements()
			zpdLoadFilePrisets()
			zpdSetNode()
			zpdRegEvents()
			sliderTime = startsslidertime
		)
		--appRef.quit
	)else(
		zpdLoadFilePrisets()
		messagebox "Don't support time output." title:"DOF Passer"
		renderSceneDialog.open()	
		zpdSetNode()	
		zpdRegEvents()
	)
	
)




utility ZDepthPasser "DOF Passer v0.4"
(
	group "Camera"
	(
		pickButton zdp_PicCam "Pic camera" width:120 height:39
	)
	group "Setting DOF"
	(
		spinner zdp_BlurDisk "Blur disk(mm)" range:[0,0.09,0] scale:0.001
	)
	button zdp_Render "Render DOF Pass"  width:102 height:45
	on zdp_PicCam picked obj do
	(
		if classof obj == Targetcamera or  classof obj == VRayPhysicalCamera then
		(
			if (getNodeByName "zdpNearPlane") != undefined then
			(
				delete (getNodeByName "zdpNearPlane")
				delete (getNodeByName "zdpFarPlane")
				delete (getNodeByName "zdp_Helper_Cam")
				deleteAllChangeHandlers id:#zpd_dirtarget
				deleteAllChangeHandlers id:#zpd_dir
				deleteAllChangeHandlers id:#zpd_namepic
				deleteAllChangeHandlers id:#zpd_selectNear
				deleteAllChangeHandlers id:#zpd_selectFar
				deleteAllChangeHandlers id:#zpd_deleted	
				deleteAllChangeHandlers id:#zdpRenderChange					
				unRegisterTimeCallback zdp_caldof		
			)
			zdp_PicCam.text = obj.name
			obj.target.dir = obj.dir
			selectcamname = obj.name
			--Set Near
			gridNear = grid length:15.7922 width:13.0935 grid:10
			gridNear.width = 30
			gridNear.length = 30
			gridNear.name = "zdpNearPlane"
			gridNear.dir = obj.dir
			gridNear.parent = zdp_PicCam.object.target
			gridNear.wirecolor = (color 175 194 208)
			--Set Far
			gridFar = grid length:15.7922 width:13.0935 grid:10
			gridFar.width = 60
			gridFar.length = 60
			gridFar.name = "zdpFarPlane"
			gridFar.dir = obj.dir
			gridFar.parent = zdp_PicCam.object.target
			gridFar.wirecolor = (color 175 194 208)
			--HelperCam
			HelperCam = Targetcamera pos:zdp_PicCam.object.pos target:(Targetobject pos:zdp_PicCam.object.target.pos)
			HelperCam.name = "zdp_Helper_Cam"
			HelperCam.target.name = "zdp_Helper_Cam_target"
			
			--HelperCam.parent = zdp_PicCam.object
			--HelperCam.target.parent = zdp_PicCam.object.target
			hide HelperCam
			--SetValues
			zpdSetLensAndFNum()
			
			zdp_BlurDisk.value =  0.025
			--Set events
			
			zpdRegEvents()	
			zdpAddRender()			
		)else
		(
			messagebox "Select Target camera or VRay Physical camera."
		)		
	)
	on renderApertureChanged value do 
	(
		
	)
	on  zdp_BlurDisk changed value do
	(
		if classof ZDepthPasser.zdp_PicCam.object == VRayPhysicalCamera then 
		(
			zdpAddRender()
		)else(
			zdpAddRender()
		)
	)
	on  zdp_Render pressed  do
	(
		if zdp_PicCam.object != undefined Then
		(			
				zpdStartRender()
		)
	)
	on ZDepthPasser open do
		(
			zdp_PicCam.object = undefined
		) 

)
fn zpdPreRender = 
(
--	zdpAddRender()
--	print (zpdMin.Zmin as string +" " + zpdMin.ZMax as string)
)
fn zdpReset = 
(
	ZDepthPasser.zdp_PicCam.object = undefined
	ZDepthPasser.zdp_PicCam.text = "Pic object"
)
callbacks.removeScripts id:#zdpRenderChange	
callbacks.addScript #renderParamsChanged "zdpAddRender()" id:#zdpRenderChange	
callbacks.removeScripts id:#izdpReset
callbacks.addScript #systemPostNew "zdpReset()" id:#izdpReset		
callbacks.removeScripts id:#zdpAddRenders
callbacks.addScript #preRenderFrame "zpdPreRender()" id:#zdpAddRenders			
if zpd_registerTime == undefined then
(
	registerTimeCallback zdpAddRender
	zpd_registerTime = true
)



