#!BPY

""" Registration info for Blender menus:
Name: 'Camera_Manager'
Blender: 248
Group: 'Animation'
Tooltip: 'An easy camera control panel'
"""

__author__ = "Claudio J Dobniewski (CJD)"
__url__ = ("http://wiki.blender.org/index.php/Extensions:Py/Scripts/Manual/Animation/Camera_Manager_GPL")
__version__ = "1.2 2007/2/9"

__bpydoc__ = """\
This script make an easy way to select, rename , set len of cameras, select active camera.

only execute in scrpt window, animation, camera_manager, use the GUI.
press EXIT to... exit
"""

# $Id: cameramanager.py,v 1.2 2007/02/09 14:00:00 CJD Exp $
#
# --------------------------------------------------------------------------
# camera manager by Claudio Dobniewski (CJD) claudiojd@yahoo.com.ar
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------


import Blender
from Blender import BGL,Draw,Object,Window,sys
from Blender.Draw import *
from Blender.sys import sleep

## ultimas modificaciones: botones de auto set start y end frame, y registreo en texto

# los que empiezon por cam_ son botones o =[] tambien
lente = []
cams = []
cam_LEN = []
cam_TOGR = []
cam_TOGS = []
cam_DATA = []
cam_NAME = []
cam_pin = []
togR = []
togS = []
pins = []
pin = 0
exh = 0
display = 12
AUTO_STA_END = []
staend = 0
fsta = []
fend = []
addstaend = []
autopath = 0 # activa autopath, cambia el nombre del archivo de render por nombre_blend+nombre_camara

dic_reg = {}

class registro:
	TEXTO = ""
	TXobj = ""
	cam_dic = {}
	header = '''# NO MODIFICAR # by CJD
# DATOS REMANENTES DE CAMERA_MAN #
# nombre_cam # start # end # on #\n'''
	datos_remanentes = "CAM_manager_DATA"
	
	def getTextObj(self,texto):
		'''busca el registro objeto texto, si existe lo devuelve,si no existe lo genera.'''
		try:
			TXobj = Blender.Text.Get(texto)
		except:
			TXobj = Blender.Text.New(texto)
			TXobj.write(self.header)
		self.TXobj = TXobj
		self.TEXT = []
		self.TEXTO = self.TXobj.asLines()
		return
	
	def addTextInObj(self,texto):
		'''agrega un texto al TXobj'''
		#suma = ""
		self.TEXTO.append(texto)
		self.TXobj.clear()
		#print self.TEXTO
		for a in self.TEXTO:
			self.TXobj.write(a+"\n")
		#print "texto en addTextInObj",self.TEXTO,texto
		self.tex2dicc()
		self.getTextObj(self.datos_remanentes)
		
		return
	
	def actualiza_TEXTO(self,camara):
		'''genera un TEXTO actualizado y lo salva en CAM_manager_DATA'''
		self.TXobj.clear()
		self.TXobj.write(self.header)
		print "en actualiza_TEXTO,",self.cam_dic
		for a in self.cam_dic.iteritems():
			print a
			self.TXobj.write(a[0]+"|"+"|".join(a[1])+"\n")
		self.getTextObj(self.datos_remanentes)
	
	def tex2dicc(self):
		'''crea un diccionario por nombre de camara'''
		print "inicia dicc"
		dic_reg = {}
		print self.TEXTO
		for b in self.TEXTO:
			print "b;",b
			blit = str.split(b,"|")
			print "en tex2dic",blit
			if len(blit) <= 1:
				print "blit=",blit,"no califica"
				continue
			else:
				print "blit=",blit,"califica"
				dic_reg[blit[0]] = blit[1:]
		self.cam_dic = dic_reg
		print self.TEXTO
		print "terminado tex2dicc"
	
	

def unselect():
	t= Blender.Scene.GetCurrent().getChildren()
	for a in t:
		a.sel = False
	

def camaras():
	'''lista de camaras en la escena activa'''
	j = []
	t= Blender.Scene.GetCurrent().getChildren()
	#print "escena ",Blender.Scene.GetCurrent()
	for r in t:
		if r.getType() == "Camera":
			#print r.name,"es una camara",r.getData().getLens()
			j.append(r.name)
				
	j.sort()
	j = map(Blender.Object.Get,j)
	
	while len(j) < 15:
		j.append(None)
	
	#print j
	return j

def pin_cam(cam,opc=0):
	'''filtro de camaras pin   (camara,opc) donde
	opc = 0 devuelve 1 si esta en la lista de pin, cero si no esta
	opc = 1 agrega la camara a la lista de pin (verifica que no este repetida)
	opc = 2 verifica si esta en la lista de pin y la elimina
	'''
	global pins
	# verificar si esta en la lista PINS
	if opc == 0:
		ret = 0
		for i in pins:
			#print "verifica",i.getName#,cam.getName
			if cam.getName() == i.getName():
				#print i.getName(),"ya esta en PIN"
				ret = 1
				return ret
		return ret
	# agregar a la lista PINS
	if opc == 1:
		for i in pins:
			#print "agrega",cam.getName,i.getName
			if cam.getName() == i.getName():
				#print i.getName(),"ya esta en PIN"
				return
		pins.append(cam)
		#print cam.getName(),"agregada en PIN"
		return
	# borrar de la lista PINS
	if opc == 2:
		for i in pins:
			#print "elimina",cam.getName,i.getName
			if cam.getName() == i.getName():
				#print i.getName(),"estaba en PIN",
				pins.pop(pins.index(i) )
				#print " ... y fue eliminado de la lista"
				return
		#print "el elemento no esta en la lista PIN"
		return

def sel_cam(cam):
	'''camara activa en la escena'''
	t= Blender.Scene.GetCurrent().getCurrentCamera()
	#print "escena ",Blender.Scene.GetCurrent()
	#print cam,t
	if (cam != None) and (t != None) and (cam.name == t.name):
		sel = 1
	else:
		sel = 0
	return sel

def LEN_KEY():
	'''graba una key de Lens en la camara activa, la que tira el render'''
	activa = Blender.Scene.GetCurrent().getCurrentCamera()
	if activa != None:
		ipo_activa = activa.getData().getIpo()
		if ipo_activa == None:
			print "no hay IPO de camara asociado. se creara uno"
			ipo_activa = Blender.Ipo.New("Camera","Cam_manager")
			lente = ipo_activa.addCurve("Lens")
			activa.getData().setIpo(ipo_activa)
		else:
			ipo_activa == activa.getIpo()
		all = ipo_activa.getCurves()
		verify = 0
		for i in all:
			if i.getName() == "Lens":
				#print "encontrado canal Lens"
				verify = 1
				lente = ipo_activa.getCurve("Lens")
		if verify == 0:
			lente = ipo_activa.addCurve("Lens")
		ipo_activa

	# falta identificar feacientemente si tiene curva de Lens, si no la tiene agregarla, y agregar la key.
		#print "all",all[0].getName()
		#print "las curvas en la IPO son",all
	lente = activa.getData().getIpo().getCurve("Lens")
	lente.append( (Blender.Get("curframe"),activa.getData().getLens() ) ) #
	lente.setInterpolation("Linear")
	#if ipo_activa:
	#	print activa.getName(),"ACTIVA => datablock de ipo",ipo_activa,lente

#camaras()

def event(evt,val):
	''' eventos de teclado'''
	global exh,pin,display,press
	#print "evento",evt,val
	#num = Blender.Draw.Button("evt"+str(evt)+"  val"+str(val),1000,30,350,150,40)
	#	if (evt == Blender.Draw.QKEY) or (evt == Blender.Draw.ESCKEY) :
	#		Blender.Draw.Exit()
		
	if (evt == Blender.Draw.RKEY):# actualiza ventana de script
		Blender.Draw.Redraw()
		
	if (evt == Blender.Draw.UPARROWKEY): #sube el indice de inicio de lista de camara a mostrar en la botonera
		exh += 1
		numcam = len(camaras() )
		if (numcam - display) < exh:
			exh = numcam - display
		Blender.Draw.Redraw()
		
	if (evt == Blender.Draw.DOWNARROWKEY): #baja el indice de inicio de lista de camara a mostrar en la botonera
		exh += (-1)
		if exh < 0:
			exh = 0
		Blender.Draw.Redraw()
		
	if (evt == Blender.Draw.PKEY) and (val == 1): #filtro de camaras con PIN activo
		print "P key ",evt,val
		pin = 1 - pin
		Blender.Draw.Draw()
			
	if (evt == Blender.Draw.SPACEKEY): #inserta key en la lente de la camara activa
		LEN_KEY()
	
def butev(evt):
	''' eventos de GUI'''
	global cams,pin,exh,display,staend,fsta,fend,autopath
	if evt != 0:
		if evt == 5001: #sube el indice de inicio de lista de camara a mostrar en la botonera
			exh += 1
			numcam = len(camaras() )
			if (numcam - display) < exh:
				exh = numcam - display
		if evt == 5002: #baja el indice de inicio de lista de camara a mostrar en la botonera
			exh += (-1)
			if exh < 0:
				exh = 0
		if evt == 5003: #NO se puede salir con ESC o boton "EXIT"
			Blender.Draw.Exit()
		if evt == 5004: #redibujar la ventana del script para actualizar
			Blender.Draw.Redraw()
		if evt == 5005: #filtro de camaras con PIN activo
			pin = 1 - pin
		if evt == 5006: #inserta key de Lens en la camara ACTIVA
			LEN_KEY()
		if evt == 5007: #filtro de camaras con PIN activo
			staend = 1 - staend
		if evt == 5008: #auto renderpath
			autopath = 1 - autopath
		
		if 99 < evt < 99+display+2:
			for i in range(display): # eventos de slider/lente
				if evt == 100+i:
					#print cams[i],lente[i]
					cams[i].getData().setLens(cam_LEN[i].val)
					Blender.Window.RedrawAll()
		if 199 < evt < 199+display+2: # eventos de toggle/camara activa para render
			#print Blender.Window.GetScreenInfo()
			#print "len cams[]",Blender.Scene.GetCurrent().getCurrentCamera(),"---",cams
			if Blender.Scene.GetCurrent().getCurrentCamera() == None:
				Blender.Scene.GetCurrent().setCurrentCamera(cams[0])
			unselect()
			for i in range(display):
				if (cams[i] != None) and (evt == 200+i):
					#print i,cams[i],evt,togR[i]
					togR[i] = 1
					cams[i].sel = True
					print staend,"staend"
					if staend == 1:
						try:
							context = Blender.Scene.GetCurrent().getRenderingContext()
							#print fsta[i].val
							context.sFrame = fsta[i].val
							context.eFrame = fend[i].val
						except:
							print "error en",cams[i].name,"al setear frames"
					Blender.Scene.GetCurrent().setCurrentCamera(cams[i])
					Blender.Window.CameraView(0)
				elif cams[i] != None:
					#cams[i].sel = False
					togR[i] = 0
					
		if 299 < evt < 299+display+2: # eventos de Datablock de camara
			#print evt
			for i in range(display):
				if (cams[i] != None) and (evt == 300+i):
					cams[i].getData().setName(cam_DATA[i].val)
		if 399 < evt < 399+display+2: # eventos de objeto activo
			#print evt
			for i in range(display):
				unselect()
				if (cams[i] != None) and (evt == 400+i):
					#print i,cams[i],evt,togS[i]
					togS[i] = 1
					cams[i].sel = True
					print "seleccionada camara como objeto activo",cams[i]
				elif cams[i] != None:
					togS[i] = 0
					#cams[i].sel = False
			Blender.Window.RedrawAll()		
		
		if 499 < evt < 499+display+2: # eventos de nombre de camara
			#print evt
			for i in range(display):
				if (cams[i] != None) and (evt == 500+i):
					cams[i].setName(cam_NAME[i].val)
		if 599 < evt < 599+display+2: # eventos de PIN de camara
			#print evt
			for i in range(display):
				if (cams[i] != None) and (evt == 600+i):
					print "evento",evt
					if pin_cam(cams[i],0) == 1:
						pin_cam(cams[i],2) # si esta en la lista, lo borra
					else:
						pin_cam(cams[i],1) #si no esta en la lista, lo agrega
		if 699 < evt < 699+display+2: #eventos de start frame
			for i in range(display):
				FRAMES = prop_cam(cams[i])
				if (cams[i] != None) and (evt == 700+i) and FRAMES[0] != None:
					#print cams[i].name,cams[i].getProperty("fsta").data
					reg.cam_dic[cams[i].name][0] = str(fsta[i].val)
					print "actualizado",cams[i].name,reg.cam_dic[cams[i].name]
					reg.actualiza_TEXTO(cams[i].name)
		if 799 < evt < 799+display+2: #eventos de end frame
			for i in range(display):
				FRAMES = prop_cam(cams[i])
				if (cams[i] != None) and (evt == 800+i) and FRAMES[0] != None:
					#print cams[i].name,cams[i].getProperty("fend").data
					reg.cam_dic[cams[i].name][1] = str(fend[i].val)
					print "actualizado",cams[i].name,reg.cam_dic[cams[i].name]
					reg.actualiza_TEXTO(cams[i].name)
		if 899 < evt < 999+display+2: #eventos de agregar start/end frame button
			for i in range(display):
				FRAMES = prop_cam(cams[i])
				if FRAMES[0] == None and (cams[i] != None) and (evt == 900+i):
					start = Blender.Get("staframe")
					end = Blender.Get("endframe")
					#print "addstaend para",cams[i].name
					new_reg = cams[i].name+"|"+str(Blender.Get("staframe"))+"|"+str(Blender.Get("endframe"))+"|1"
					#print new_reg
					reg.cam_dic[cams[i].name]=[str(Blender.Get("staframe")),str(Blender.Get("endframe")),"1"]
					reg.addTextInObj(new_reg)
		Blender.Draw.Redraw()

def prop_cam(camara):
	'''revisa en las properties del objeto si tiene las de start y end frame.
	si las tiene las devuelve, sino devuelve [None,None]'''
	
	fsta = None
	fend = None
	try:
		#print reg.cam_dic
		#print reg.cam_dic[camara.name]
		all = reg.cam_dic[camara.name]
		fsta = int(all[0])
		fend = int(all[1])
		setframe = int(all[2])
		#print "valor de fsta y fend",fsta,fend
		return [fsta,fend]
	except:
		return [None,None]
	
	
def GUI():
	''' botonera'''
	global lente,cam_LEN,cam_TOG,cam_TOGS,cam_pin,togR,togS,pins,pin,cams,display,fsta,fend,addstaend
	
	y = 30 # margen inferior de la GUI
	z = 26 # salto entre botones
	u = 0
	upper =  z*(display+1) # calculo auxiliar para la altura de los botones superiores
	aux_but_alt = 20 # altura de los botones auxiliares
	camera_but_alt = 20 #altura de lo botones de camaras
	camaras_l = camaras()
	if pin == 0:
		cams = camaras_l[exh:display+exh]
	if pin == 1:
		cams = []
		for xx in camaras_l:
			if (xx == None) or (pin_cam(xx,0) == 1):
				cams.append(xx)
		cams = cams[exh:display+exh]
		while len(cams) < 15:
			cams.append(None)
	for n in range(display):
		if cams[n] != None:
			lente[n] = float(cams[n].getData().getLens())
		else:
			lente[n] = 0
	#
	BGL.glRasterPos2d(25,5)
	version = Blender.Draw.Text("camera_manager v1.2 -> 9/02/07")
	# botones de control
	up = Blender.Draw.Button("UP",5001,150,y,80,aux_but_alt,"UP arrow key")
	down = Blender.Draw.Button("DOWN",5002,240,y,80,aux_but_alt,"DOWN aroow key")
	exit = Blender.Draw.Button("EXIT",5003,50,y,80,aux_but_alt,"WARNING: press to EXIT")
	redraw = Blender.Draw.Button("REDRAW",5004,90,y+upper,80,aux_but_alt,"R key to REDRAW buttons")
	pinned = Blender.Draw.Toggle("PINNED",5005,280,y+upper,60,aux_but_alt,pin,"P key to PIN filter")
	len_key = Blender.Draw.Button("LEN key",5006,20,y+upper,60,aux_but_alt,"SPACE BAR Inserta un key de LENTE en la camara ACTIVA")
	auto_sta_end = Blender.Draw.Toggle("AUTO start/end",5007,360,y,120,aux_but_alt,staend,"WIP-Activa auto seteo de start/end al seleccionar la camara")
	autopath_button = Blender.Draw.Toggle("AUTO path OGL",5008,175,y+upper,100,aux_but_alt,autopath,"activa auto path para render")
	# autopath section
	if autopath == 1:
		path = Blender.Scene.GetCurrent().getRenderingContext().renderPath
		#blend = ".".join(str.split(Blender.Get("filename"),".")[:1]) # pidieron no poner nombre del blend
		try:
			actcam = Blender.Scene.GetCurrent().getCurrentCamera().name
		except :
			actcam = "viewport"
		if path[-1:] == "/":
			new_path = path+actcam
			#print "new_path si solo tiene ruta terminada en /",new_path
		else:
			#print "path",path
			#print "path sin nombre",str.split(path,"/")[:-1]
			new_path = "/".join(str.split(path,"/")[:-1])+"/"+actcam
			#print "new_path",new_path
		Blender.Scene.GetCurrent().getRenderingContext().renderPath = new_path+".avi"
		#print
		#Blender.Set(
	#	# botones de camaras
	for i in range(len(cams)):
		alt = y+(z*(i+1))
		# botones de nombre y lente
		if cams[i] == None:
			cam_LEN[i] = Blender.Draw.Create(1)
			cam_DATA[i] = Blender.Draw.Create("")
			cam_TOGR[i] = Blender.Draw.Create(1)
			cam_TOGS[i] = Blender.Draw.Create(1)
			cam_NAME[i] = Blender.Draw.Create("")
			cam_pin[i] = Blender.Draw.Create("")
			fsta[i] = Blender.Draw.Create(0)
			fend[i] = Blender.Draw.Create(0)
			addstaend[i] = Blender.Draw.Create(0)
		else:
			cam_LEN[i] = Blender.Draw.Slider(" " ,100+i,175,alt,100,camera_but_alt,lente[i],1,250,1,"Lente") # lente
			cam_TOGR[i] = Blender.Draw.Toggle("R",200+i,280,alt,30,camera_but_alt,togR[i],"presionado = camara activa" ) #camara que renderiza
			# cam_DATA se va a usar para salguna otra cosa
			# cam_DATA[i] = Blender.Draw.String("",300+i,390,alt,150,camera_but_alt,str(cams[i].getData().getName()),19,"DATABLOCK asociado a la camara")
			togR[i] = sel_cam(cams[i]) #variable de camara seleccionasda, booleana
			cam_TOGS[i] = Blender.Draw.Create(1) # desactivado por funcionalidad obsoleta cam_TOGS[i] = Blender.Draw.Toggle(str(cams[i].isSelected()),400+i,350,alt,30,camera_but_alt,togS[i],"0 = no select|1 = select|press = active object" ) #objeto activo
			cam_NAME[i] = Blender.Draw.String("",500+i,10,alt,160,camera_but_alt,str(cams[i].getName() ),20,"Nombre del objeto")
			cam_pin[i] = Blender.Draw.Toggle("P",600+i,315,alt,30,camera_but_alt,pin_cam(cams[i],0),"pinned object" ) #objeto PINNED
			FRAMES = prop_cam(cams[i])
			if FRAMES[0] != None and staend == 1:
				fsta[i] = Blender.Draw.Number("",700+i,360,alt,60,camera_but_alt,FRAMES[0],1,299999,"Start Frame")
				fend[i] = Blender.Draw.Number("",800+i,430,alt,60,camera_but_alt,FRAMES[1],2,300000,"End Frame")
			elif FRAMES[0] == None and staend == 1:
				#print cams[i].name,addstaend
				addstaend[i] = Blender.Draw.PushButton("add auto S/E",900+i,360,alt,100,camera_but_alt,"add start-end data")
	#

def init_GUI():
	'''inicializa botones vacios que van a controlar las camaras'''
	global lente,cams,toogle,cam_DATA,cam_LEN,cam_TOGR,cam_TOGS,cam_pin,fsta,fend,addstaend
	cams = camaras()
	for i in range(len(cams)):
		cam_LEN.append(Blender.Draw.Create(1) ) # botones slider para bombre y lente
		cam_TOGR.append(Blender.Draw.Create(1) ) # botones toggle para camara de render
		cam_DATA.append(Blender.Draw.Create("") ) # botones de datablock de camaras
		cam_TOGS.append(Blender.Draw.Create(1) ) # botones toggle para camara activa
		cam_NAME.append(Blender.Draw.Create("") ) # botones de nombre de camara
		cam_pin.append(Blender.Draw.Create("") ) # botones de fijar camara
		lente.append(0.0)
		togR.append(0)
		togS.append(0)
		fsta.append(0) # frame de inicio
		fend.append(0) # frame final
		addstaend.append(Blender.Draw.Create(0) ) #si no tiene seteado sta y end, para ponerle
		
	Blender.Window.RedrawAll()

press = 0

unselect()
print "============="
print "unselect all objects"

reg = registro()
datos = reg.datos_remanentes
reg.getTextObj(datos)
reg.tex2dicc()


init_GUI()

Blender.Draw.Register(GUI,event,butev)
