#!BPY

""" Registration info for Blender menus:
Name: 'Kloputils 3'
Blender: 234
Group: 'Wizards'
Tip: 'Set of object aligning, modifying tools'
"""

__author__ = "Carlos López (klopez)"
__url__ = ("elysiun", "Author's web page, http://klopes.tk",
"Script's homepage, http://www.iespana.es/klopes/enchufes-guiri.htm",
"Thread on elYsiun with links to English and Spanish webpage and pdf docs,\
http://www.elysiun.com/forum/viewtopic.php?t=25736")
__version__ = "3.1"

__bpydoc__ = """\
This Wizard script contains customizable tools to align and modify mesh
objects.

Edited freely from a post by the author to elYsiun (last link button above):

These tools are initially oriented as a help for the general design of objects
in 2D and 3D (architecture, industrial...), and this is the paradigm the
program will be developed around.

The utilities in the program are separated in 4 areas, accessible through the
top menu in the GUI:

- Alignment:<br>
  + fitting an object between two others;<br>
  + setting to an object the absolute size of another one;<br>
  + aligning selected objects, according to several criteria: location,
rotation, scale (scale can be changed either additive or multiplicatively);<br>
  + location separation can be referenced either by centers, baricenters,
origins or limits.

- Object creation:<br>
  + circunference passing through 3 points;<br>
  + arc passing through 3 points;<br>
  + arc based on angles and radius (interactive).

- Mesh modification (affects vertices, faces and edges):<br>
  + edges subdivision in any number of parts;<br>
  + projection onto an arbitrary plane, in an arbitrary direction;<br>
  + transformation of position, rotation, scale values (new matrix) of an
object, though it looks unaffected.

- 3D objects modifications (affects transform matrices):<br>
  + translating / rotating / scaling randomly the selected objects;<br>
  + moving selected objects closer or away from the active one, setting them at
a fixed distance or translating by a fixed or proportional value.

Notes:<br>
    All numeric / vectorial values used during the program can be copied and
pasted with the help of a buffer, which can contain: a position vector, an
Euler list or a scaling vector and can store: numbers entered by user, values
acquired from objects (matrices averages, distances, differences of position or
rotation angles between two objects).  Buffer contents can also be pasted to
the console window as text.

Usage:

Open the script from the "Scripts->Wizards" menu of the Scripts window, then
one choose from the available languages.  The script has a GUI where specific
tools can be selected and configured before being applied.

Notes:<br>
    Kloputils has many useful tools.  To get a better idea of what it can do,
besides reading the tooltips for each button, users can check its online
documentation.
"""

# $Id: kloputils.py,v 1.4 2006/07/11 17:59:23 campbellbarton Exp $
#
##################################################
#                                                #
#        KLOPUTILES v3.1 para Blender v2.33      #
#                   multilingue                  #
#                                                #
##################################################
#		Pulsa Alt+P para ejecutar el script
#	Improved:	use of Mathutils
#	Feature:	actualize objects on ApplyLRS
#	Improved:	Project onto planes
#	Feature:	mover/rotar/escalar objetos al azar
#	Feature:	acercar objs al activo (fijo, abs, rel)
#	Improved:	Fit/Embrace
#	TODO: subdividir solo aristas seleccionadas (NO FUNCIONA)
#	TODO: Elipses
#
##################################################
#
# --------------------------------------------------------------------------
# Kloputils by Carlos López (klopez)
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2004: Carlos López, http://klopes.tk
#
# 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.Mathutils import *
from Blender.NMesh import *
from Blender.BGL import *
from Blender.Draw import *
from Blender.sys import *
from Blender.Noise import random

from math import *

#path=dirname(progname)
#path=[dirname(progname),'.blender','bpydata']
path=Blender.Get("datadir")
if not path:
	errmsg = "\nNo bpydata/ dir found! It should be in Blender's home dir."
	raise IOError, errmsg

sc=Blender.Scene.GetCurrent()
MId=Matrix([1,0],[0,1])
MId.resize4x4()

coo=['X','Y','Z']
l=PupMenu('Choose language%t|Espanol%x1|English%x2|Catala%x3')
Lang=['Espanol','English','Catala'][l-1]



#Buffer:
BfL=[0.,0.,0.]
BfR=[0.,0.,0.]
BfS=[1.,1.,1.]

pagina=Create(1)
creake=Create(1)
editake=Create(2)
moveke=Create(1)

numReal=Create(0.)
movekomo=Create(1)
menuLRS=Create(1)

ndiv=Create(3)
akeplano=Create(2)
akeplanoXYZ=Create(3)
enkedir=Create(3)

nLocX=Create(1.0)
nLocY=Create(2.0)
nLocZ=Create(3.0)
nRotX=Create(0.0)
nRotY=Create(0.0)
nRotZ=Create(0.0)
nSizX=Create(1.0)
nSizY=Create(1.0)
nSizZ=Create(1.0)
other=Create(1)

ang1=Create(0.0)
ang2=Create(30.0)
angulo=Create(30.0)
radio=Create(1.0)
pts=Create(10)
ctro=Create(0)
meTx=Create('Arc')

arcorden=Create(0)

CreaNew=Create(1)
Cuantos=Create(2)
toBuffer=Create(0)

menueqiX=Create(1)
sepX=Create(0.5)
aliX=Create(1)
menueqiY=Create(1)
sepY=Create(0.0)
aliY=Create(0)
menueqiZ=Create(2)
sepZ=Create(1.0)
aliZ=Create(0)

girX=Create(0)
incX=Create(0.0)
girY=Create(0)
incY=Create(0.0)
girZ=Create(1)
incZ=Create(5.0)

scaX=Create(1)
iScaX=Create(.5)
scaY=Create(1)
iScaY=Create(.5)
scaZ=Create(1)
iScaZ=Create(.5)

encX=Create(1)
encY=Create(0)
encZ=Create(0)
en2X=Create(1)
en2Y=Create(0)
en2Z=Create(0)


def CreaObjDeMalla(mm,o,nombre):
	oo=Blender.Object.New('Mesh')
	oo.link(mm)
	oo.setName(nombre)
	oo.LocX,oo.LocY,oo.LocZ=o.LocX,o.LocY,o.LocZ
	oo.RotX,oo.RotY,oo.RotZ=o.RotX,o.RotY,o.RotZ
	oo.SizeX,oo.SizeY,oo.SizeZ=o.SizeX,o.SizeY,o.SizeZ
	sc.link(oo)
	return oo

def rectang(x,y,l,h,r,g,b):
	glColor3f(r,g,b)
	glBegin(GL_POLYGON)
	glVertex2i(x, y)
	glVertex2i(l, y)
	glVertex2i(l, h)
	glVertex2i(x, h)
	glEnd()

def SituaL(objeto,coord,X):
	if coord==0:
		objeto.LocX=X
	elif coord==1:
		objeto.LocY=X
	elif coord==2:
		objeto.LocZ=X
def SituaR(objeto,coord,X):
	if coord==0:
		objeto.RotX=X
	elif coord==1:
		objeto.RotY=X
	elif coord==2:
		objeto.RotZ=X
def SituaS(objeto,coord,X):
	if coord==0:
		objeto.SizeX=X
	elif coord==1:
		objeto.SizeY=X
	elif coord==2:
		objeto.SizeZ=X

def mallaScan(o):
	return o.getType()=='Mesh'

def Sistema(MM,D):
	MM.invert()
	return MatMultVec(MM,D)

def GloVrt((x,y,z),M):	# Devuelve (vector) coords globs de v
	v=Vector([x,y,z,1])
	v*=M #v=VecMultMat(v,M)
	v.resize3D()
	return v

def Extremo(lista,M=MId):	# Devuelve extremos y pto medio de lista de vectores
	o1=GloVrt(lista[0],M)
	o2=GloVrt(lista[0],M)
	for v in lista:
		va=Vector(list(v))
		va.resize4D()
		va*=M #va=VecMultMat(va,M)
		for c in xrange(3):
			o1[c]=min(va[c],o1[c])
			o2[c]=max(va[c],o2[c])
	return [o1,(o1+o2)*0.5,o2]

def Media(lista):	#Media
	ctr=Vector([0,0,0])
	for c in range(3):
		for l in lista: ctr[c]=ctr[c]+l[c]
		ctr[c]=ctr[c]/len(lista)
	return ctr






def draw():
	global pagina, toBuffer
	glClearColor(0.4,0.2,0.2,0.0)
	glClear(GL_COLOR_BUFFER_BIT)

	pagina=Menu(menu0,98,20,370,170,28,pagina.val,"Select page")
	toBuffer=Menu(menu4,80,200,370,20,15,toBuffer.val,"Copy values to the internal buffer")
	glColor3f(0.6,0.6,0.2)
	glRasterPos2i(198,388)
	Text("Copy",'small')

	if (pagina.val==1): draw1()
	elif (pagina.val==2): draw2()
	elif (pagina.val==3): draw3()
	elif (pagina.val==4): draw4()

	Button(menuExit,99,20,5,200,18)

def draw4():
	global moveke,o
	global aliX,aliY,aliZ,numReal,movekomo,menuLRS,menuPaste
	

	rectang(15,38,225,264,0.2,0.,0.)

	moveke=Menu(menu5,98,10,248,200,20,moveke.val,"Modify the matrices of selected objects")
	if moveke.val==2:
		aliX=Toggle("X",0, 50,160,45,30,aliX.val,"Activate modification in X")
		aliY=Toggle("Y",0, 95,160,45,30,aliY.val,"Activate modification in Y")
		aliZ=Toggle("Z",0,140,160,45,30,aliZ.val,"Activate modification in Z")
		menuLRS=Menu("Loc%x1|Rot%x2|Size%x3",98,20,110,50,20,menuLRS.val)
	if moveke.val==1:
		movekomo=Menu(menu5a,98,20,225,200,20,movekomo.val,"Transformation type")
		m,M,tip= -100,100,"Quantity"
	else:
		if menuLRS.val==1:
			m,M,tip= -1000, 1000, "Distance"
		elif menuLRS.val==2:
			m,M,tip= 0, 360, "Angle"
		elif menuLRS.val==3:
			m,M,tip= 0, 100, "Scale"
	if moveke.val==1 and movekomo.val==3:	tip=tip+"Multiplier "
	if moveke.val==2:	tip=tip+" (max)"

	numReal=Number("",0,20,140,178,18,numReal.val,m,M,tip)
	glColor3f(0.6,0.6,0.2)
	glRasterPos2i(200,156)
	Text("Paste",'small')
	menuPaste=Menu("Paste...%t|LocX%x1|LocY%x2|LocZ%x3|\Loc\%x4|RotX%x5|RotY%x6|RotZ%x7|SizeX%x8|SizeY%x9|SizeZ%x10"
,88,202,140,20,12,0,"Paste what?")
	ok=Button("OK",50,80,110,80,20)


def draw3():
	global editake,ndiv,akeplano,akeplanoXYZ,enkedir,ok
	global other
	global getlocrotsiz,ok,nLocX,nLocY,nLocZ
	global nRotX,nRotY,nRotZ,nSizX,nSizY,nSizZ
	global Cloc,Ploc,Crot,Prot,Csiz,Psiz

	rectang(15,38,225,264,0.3,0.7,0.5)

	editake=Menu(menu3,98,10,248,143,20,editake.val,"Mesh editing menu")
	if(editake.val==1):
		ndiv=Number(menu3a,98,20,200,150,18,ndiv.val,2,1000)
		ok=Button("OK",20,172,200,32,18)
	elif(editake.val==2):
		akeplano=Menu(menu3b,98,20,200,140,20,akeplano.val)
		if akeplano.val in [1,2]:
			akeplanoXYZ=Menu(menu3c,98,162,200,55,20,akeplanoXYZ.val) 
		enkedir=Menu(menu3d,98,20,100,140,20,enkedir.val)
		ok=Button("OK",40,162,100,55,20)
	elif(editake.val==3):
		Button("P",87,192,222,30,18,"Paste buffer matrix")
		nLocX=Number("LocX:",98,20,200,170,19,nLocX.val,-1000.,1000.)
		nLocY=Number("LocY:",98,20,180,170,19,nLocY.val,-1000.,1000.)
		nLocZ=Number("LocZ:",98,20,160,170,19,nLocZ.val,-1000.,1000.)
		nRotX=Number("RotX:",98,20,140,170,19,nRotX.val,-1000.,1000.)
		nRotY=Number("RotY:",98,20,120,170,19,nRotY.val,-1000.,1000.)
		nRotZ=Number("RotZ:",98,20,100,170,19,nRotZ.val,-1000.,1000.)
		nSizX=Number("SizeX:",98,20, 80,170,19,nSizX.val,-1000.,1000.)
		nSizY=Number("SizeY:",98,20, 60,170,19,nSizY.val,-1000.,1000.)
		nSizZ=Number("SizeZ:",98,20, 40,170,19,nSizZ.val,-1000.,1000.)
		other=Toggle("Refresh others",98,20,222,170,18,other.val)
		oklocrotsiz=Button("OK",30,192,40,30,179)

def draw2():
	global creake,ang1,ang2,angulo,radio,pts,ctro,meTx,arcorden

	rectang(15,65,224,257,0.7,0.5,0.65)

	creake=Menu(menu2,98,10,248,143,20,creake.val,"Object type")
	if(creake.val==1):
		pts=Number(menu2a[0],98,20,115,80,18,pts.val,2,1000)
		ctro=Toggle(menu2a[1],98,102,115,50,18,ctro.val,"Close the arc with a vertex on its center")
		arcorden=Menu(menu2a[2]+"%t|1-2-3%x1|2-3-1%x2|3-1-2%x3",17,155,115,65,18,arcorden.val,"Vertices order (arc is created when this is chosen)")
		meTx=String("Object: ",98,20,70,200,22,meTx.val,30,"New object's name")
	if(creake.val==2):
		ang1=Slider(menu2a[4],10,20,220,200,18,ang1.val,-360,360,0,"Initial angle in degrees")
		ang2=Slider(menu2a[5],11,20,200,200,18,ang2.val,ang1.val,ang1.val+360,0,"Final angle in degress")
		angulo=Slider(menu2a[6],12,20,170,200,18,angulo.val,-360,360,0,"Arc's angle in degress")
		radio=Slider(menu2a[7],13,20,140,200,18,radio.val,0,1,0)
		pts=Number(menu2a[8],14,20,115,80,18,pts.val,2,1000)
		ctro=Toggle(menu2a[9],15,102,115,50,18,ctro.val,"Close the arc with a vertex on its center")
		meTx=String(menu2a[10],16,20,70,200,22,meTx.val,30,"Name of the mesh to substitute")
	if(creake.val==3):
		pts=Number("Pts:",98,20,115,80,18,pts.val,2,1000)
		ok=Button("OK",18,102,115,120,36)
		meTx=String("Object: ",98,20,70,200,22,meTx.val,30,"New object's name")
		
def draw1():
	global menueqiX,sepX,aliX,menueqiY,sepY,aliY,menueqiZ,sepZ,aliZ
	global girX,incX,girY,incY,girZ,incZ
	global encX,encY,encZ,en2X,en2Y,en2Z
	global scaX,scaY,scaZ,iScaX,iScaY,iScaZ
	global CreaNew,Cuantos,toBuffer

######################### ALINEACIONES #####################
	rectang(5,167,254,292,0.7,0.5,0.65)
	Button("C",81,194,270,25,18,"Copy")
	Button("P",82,220,270,25,18,"Paste buffer Loc")

	aliX=Toggle("X",0,10,270,30,18,aliX.val,"Activate X alignment")
	menueqiX=Menu(menu1b,98,41,270,148,18,menueqiX.val,"Separation extremes")  
	sepX=Number(menu1a[4],0,10,250,179,18,sepX.val,-1000,1000,"X separation distance")

	aliY=Toggle("Y",0,10,230,30,18,aliY.val,"Activate Y alignment")
	menueqiY=Menu(menu1b,98,41,230,148,18,menueqiY.val,"Separation extremes")  
	sepY=Number(menu1a[4],0,10,210,179,18,sepY.val,-1000,1000,"Y separation distance")

	aliZ=Toggle("Z",0,10,190,30,18,aliZ.val,"Activate Z alignment")
	menueqiZ=Menu(menu1b,98,41,190,148,18,menueqiZ.val,"Separation extremes")  
	sepZ=Number(menu1a[4],0,10,170,179,18,sepZ.val,-1000,1000,"Y separation distance")

########################## GIROS ##############################
	rectang(5,97,254,162,0.67,0.54,0.1)
	Button("C",83,194,140,25,18,"Copy")
	Button("P",84,220,140,25,18,"Paste buffer Rot")

	girX=Toggle("X",0,10,140,30,18,girX.val,"Increment RotX values")
	incX=Number("X: ",0,42,140,147,18,incX.val,-180,180,"X increment in degress")
	girY=Toggle("Y",0,10,120,30,18,girY.val,"Increment RotY values")
	incY=Number("Y: ",0,42,120,147,18,incY.val,-180,180,"Y increment in degrees")
	girZ=Toggle("Z",0,10,100,30,18,girZ.val,"Increment RotZ values")
	incZ=Number("Z: ",0,42,100,147,18,incZ.val,-180,180,"Z increment in degrees")

######################### ESCALADOS ##########################
	rectang(5,27,254,92,0.27,0.54,0.4)
	Button("C",85,194,70,25,18,"Copy")
	Button("P",86,220,70,25,18,"Paste buffer Sca")

	scaX=Toggle("X",0,10,70,30,18,scaX.val)
	iScaX=Number(menu1a[7],0,42,70,147,18,iScaX.val,-180,180,"X scale increment")
	scaY=Toggle("Y",0,10,50,30,18,scaY.val)
	iScaY=Number(menu1a[7],0,42,50,147,18,iScaY.val,-180,180,"Y scale increment")
	scaZ=Toggle("Z",0,10,30,30,18,scaZ.val)
	iScaZ=Number(menu1a[7],0,42,30,147,18,iScaZ.val,-180,180,"Z scale increment")
########################## ENCAJES ##########################
	rectang(5,317,254,363,0.1,0.5,0.6)

	encX=Toggle(menu1a[0]+"X",0,10,340,43,18,encX.val,"Move object in X")
	encY=Toggle(menu1a[0]+"Y",0,55,340,43,18,encY.val,"Move object in Y")
	encZ=Toggle(menu1a[0]+"Z",0,100,340,43,18,encZ.val,"Move object in Z")

	en2X=Toggle(menu1a[1]+"X",0,10,320,43,18,en2X.val,"Adjust X size")
	en2Y=Toggle(menu1a[1]+"Y",0,55,320,43,18,en2Y.val,"Adjust Y size")
	en2Z=Toggle(menu1a[1]+"Z",0,100,320,43,18,en2Z.val,"Adjust Z size")
######################################################
	CreaNew=Toggle(menu1a[8],98,10,295,129,18,CreaNew.val,"Create new objects or just modify selected?")
	if CreaNew.val:
		Cuantos=Number('',98,139,295,30,18,Cuantos.val,1,999,"Number of copies")
	Button(menu1a[5],1,190,170,60,98,"Align")		#Alinea
	Button(menu1a[6],2,190,100,60,38,"Rotate")		#Gira
	Button(menu1a[9],3,190,30,29,38,"Scale +")		#Escala+
	Button(menu1a[10],7,220,30,30,38,"Scale *")		#Escala*
	Button(menu1a[2],6,147,320,45,38,"Fit active in one or two others using max limits (creates new object)")		#Encaja
	Button(menu1a[3],5,195,320,55,38,"Fit active in one or two others using min limits (creates new object)")		#Abarca

def HaceArco(pts,ang1,angul,ctro,R):
	me=New()
	for c in range(pts):
		alfa=(ang1+angul*c/(pts-1))*pi/180
		if (c): v1=v
		v=Vert()
		v.co[0]=R*cos(alfa)
		v.co[1]=R*sin(alfa)
		v.co[2]=0
		me.verts.append(v)
		if (c):
			f=Face()
			f.v=[v1]
			f.v.append(v)
			me.faces.append(f)
		if (c==0): v0=v
	if(ctro):
		v1=v
		v=Vert()
		me.verts.append(v)
		f=Face()
		f.v=[v1,v]
		me.faces.append(f)
		f=Face()
		f.v=[v,v0]
		me.faces.append(f)
	return me

def Exec_align(os,c,ali,eqi,sep):
	coor=os[0].loc[c]
	ademas=0
	flag=0
	for o in os:
		m=o.data     #Maya del objeto
		ctr=[0,0,0]
		if(eqi[c]==2):
			for d in range(3): ctr[d]=Extremo(m.verts,o.matrix)[1][d]
		elif(eqi[c]==3 or eqi[c]==6):
			ctr=Extremo(m.verts,o.matrix)[0]
		elif(eqi[c]==4):
			ctr=Extremo(m.verts,o.matrix)[2]
		elif(eqi[c]==5):
			ctr=Media(m.verts)
			ctr=GloVrt(ctr,o.matrix)

		if (eqi[c]>1): ademas=ctr[c]-o.loc[c]
		if (flag):	coor=coor-ademas
		else:	flag=1
		SituaL(o,c,coor)
		if(eqi[c]==6): ademas=Extremo(m.verts,o.matrix)[2][c]-o.loc[c]
		coor=coor+sep[c]+ademas

def event(evt,val):
	if (evt==ESCKEY and not val):
		print "Bye..."
		Exit()

#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@22#

def bevent(evt):
	global me
	global BfL,BfR,BfS
	#print "Event:",evt
	
	os=Blender.Object.GetSelected()
	oa= Blender.Scene.GetCurrent().getActiveObject()
	if not oa:
		return

	##########MENU BUFFER
	if evt==80:
		copi=toBuffer.val
		if copi==1:
			if len(os)==2:
				for c in range(3): BfL[c]=os[1].loc[c]-os[0].loc[c]
				print "Copied to Loc buffer:",BfL
			else:
				PupMenu('ERROR%t|Selecciona 2 objetos|Just select 2 objects!')
		if copi==2:
			if len(os)==2:
				BfL=3*[sqrt((os[1].loc[0]-os[0].loc[0])**2+
(os[1].loc[1]-oa.loc[1])**2+
(os[1].loc[2]-oa.loc[2])**2)]
				print "Copied to Loc buffer:",BfL
			else:
				PupMenu('ERROR%t|Selecciona 2 objetos|Just select 2 objects!')
		if copi==3:
			if len(os)==2:
				for c in range(3): BfR[c]=os[1].rot[c]-oa.rot[c]
				print "Copied to Rot buffer:",BfR
			else:
				PupMenu('ERROR%t|Selecciona 2 objetos|Just select 2 objects!')
		if copi==4 and len(os):
			lista=[]
			for o in os: lista.append(o.loc)
			BfL=Media(lista)
			print "Copied to Loc buffer:",BfL
			lista=[]
			for o in os: lista.append(o.rot)
			BfR=Media(lista)
			for c in range(3): BfR[c]*=180/pi
			print "Copied to Rot buffer:",BfR
			lista=[]
			for o in os: lista.append(o.size)
			BfS=Media(lista)
			print "Copiado to Size buffer:",BfS
		if copi==5:
			print"\n_Buffer contents_\n"
			for c in range(3): print "Loc",coo[c]," :",BfL[c]
			for c in range(3): print "Rot",coo[c]," :",BfR[c]
			for c in range(3): print "Size",coo[c],":",BfS[c]
			print "______________________"

	##########COPY
	if evt==81:
		X	=[sepX.val,sepY.val,sepZ.val]
		ali	=[aliX.val,aliY.val,aliZ.val]
		for c in range(3):
			if ali[c]:
				BfL[c]=X[c]
				print"Copying to Loc buffer",coo[c],"value", BfL[c]

	if evt==83:
		X	=[incX.val,incY.val,incZ.val]
		ali	=[girX.val,girY.val,girZ.val]
		for c in range(3):
			if ali[c]:
				BfR[c]=X[c]
				print"Copying to Rot buffer",coo[c],"value", BfR[c]

	if evt==85:
		X	=[iScaX.val,iScaY.val,iScaZ.val]
		ali	=[scaX.val,scaY.val,scaZ.val]
		for c in range(3):
			if ali[c]:
				BfS[c]=X[c]
				print"Copying to Size buffer",coo[c],"value", BfS[c]

	##########PASTE
	if evt==82:
		X	=[sepX.val,sepY.val,sepZ.val]
		ali	=[aliX.val,aliY.val,aliZ.val]
		for c in range(3):
			if ali[c]:
				X[c]=BfL[c]
				print"Retrieving from buffer Loc",coo[c],"value", BfL[c]
		sepX.val,sepY.val,sepZ.val=X

	if evt==84:
		X	=[incX.val,incY.val,incZ.val]
		ali	=[girX.val,girY.val,girZ.val]
		for c in range(3):
			if ali[c]:
				X[c]=BfR[c]
				print"Retrieving from buffer Rot",coo[c],"value", BfR[c]
		incX.val,incY.val,incZ.val=X

	if evt==86:
		X	=[iScaX.val,iScaY.val,iScaZ.val]
		ali	=[scaX.val,scaY.val,scaZ.val]
		for c in range(3):
			if ali[c]:
				X[c]=BfS[c]
				print"Retrieving from buffer Size",coo[c],"value", BfS[c]
		iScaX.val,iScaY.val,iScaZ.val=X

	if evt==87:
		print"Retrieving <ApplyLocRotSize> matrix"
		nLocX.val,nLocY.val,nLocZ.val=BfL
		nRotX.val,nRotY.val,nRotZ.val=BfR
		nSizX.val,nSizY.val,nSizZ.val=BfS

	if evt==88:
		print"Retrieving float number to button"
		x=[BfL[0],BfL[1],BfL[2],
sqrt(BfL[0]**2+BfL[1]**2+BfL[2]**2),
BfR[0],BfR[1],BfR[2],
BfS[0],BfS[1],BfS[2]]
		numReal.val = x[menuPaste.val-1]

	if evt==50:
		if moveke.val==1:				#		MOVER HACIA EL O.ACTIVO
			oaV=Vector(list(oa.loc))
			for o in os[1:]:
				oV=Vector(list(o.loc))
				v=oV-oaV									#Calculo del vector final
				d=sqrt(DotVecs(v,v))
				v1=v*numReal.val
				if movekomo.val==1:
					if d:	v1 = oaV+v1*(1/d)
					else:	v1 = oaV
				elif movekomo.val==2:
					if d:	v1 = oV+v1*(1/d)
					else:	v1 = oV
				elif movekomo.val==3:
					v1 = oaV+v1
				o.setLocation(v1)

		if moveke.val==2:					#	MOVER AL AZAR
			n=numReal.val
			if menuLRS.val==2:
				n=n*pi/180
			for o in os:
				v1=Vector([
aliX.val * (2*n*random() - n),
aliY.val * (2*n*random() - n),
aliZ.val * (2*n*random() - n)])

				if menuLRS.val==1:							#Uso del vector final
					oV=Vector(list(o.loc))
					o.setLocation(oV+v1)
				elif menuLRS.val==2:
					v=Vector(list(o.getEuler()))+v1
					o.setEuler(v)
				else:
					oV=Vector(list(o.size))
					o.setSize(oV+v1)

	if evt==40:				#					PROYECTA EN PLANOS
		n=Vector([0.,0.,0.])

		numObjs=-len(os)+1
		if akeplano.val==1:	#plano global
			n[akeplanoXYZ.val-1]=1.
			numObjs=-len(os)
		elif akeplano.val==2: n=oa.matrix[akeplanoXYZ.val-1] #plano local
		n= Vector(n) # copy
		n.resize3D()

		d=Vector([0.,0.,0.])
		if enkedir.val<4: d[enkedir.val-1]=1.	#direccion global
		elif enkedir.val==4: d=n				#direc. ortog. al plano

		n1 = Vector([-n[2],n[0],n[1]])
		N1 = CrossVecs (n,n1)
		N2 = CrossVecs (n,N1)	
		n.normalize(), N1.normalize(), N2.normalize()
		#print"productos escalares (deben ser 0):",DotVecs(N1,n),DotVecs(N2,n),DotVecs(N2,N1)
		p=oa.loc
		N=Matrix(
	[N1[0],N1[1],N1[2],0],
	[N2[0],N2[1],N2[2],0],
	[ n[0], n[1], n[2],0],
	[ p[0], p[1], p[2],1])
		NI=CopyMat(N)
		NI.invert()

		dN= d*NI.rotationPart() #VecMultMat(d,NI.rotationPart())
		if dN[2]==0:
			PupMenu('Error%t|Operacion no permitida: la direccion esta en el plano%x1|Illegal operation: plane contains direction%x2')
			return
		print"Absolute direction:",d,"\nPlane normal:",n,"\nRelative direction:",dN
		for o in filter(mallaScan,os[numObjs:]):
			me=Blender.NMesh.GetRawFromObject(o.name)
			M=o.matrix
			for v in me.verts:
				v0=Vector([v[0],v[1],v[2]])
				v0=GloVrt(v0,M)
				v0.resize4D()
				v0*= NI #=VecMultMat(v0,NI)
				v[0] = v0[0] - v0[2]/dN[2] * dN[0]
				v[1] = v0[1] - v0[2]/dN[2] * dN[1]
				v[2] = 0
			oo=Blender.Object.New('Mesh')
			oo.setName(o.name+'Proy')
			oo.link(me)
			sc.link(oo)
			oo.setMatrix(N)

	if(evt>9 and evt<17):	#	HACE ARCO INTERACTIV.
		GetRaw(meTx.val)
		if(evt==11): angulo.val=ang2.val-ang1.val
		if(evt==12 or evt==10): ang2.val=(ang1.val+angulo.val)
		m=HaceArco(pts.val,ang1.val,angulo.val,ctro.val,radio.val)
		PutRaw(m,meTx.val)

	if evt in [17,18]: 	# HACE ARCO CON 3 PTS.
		o=oa
		m=o.getData()
		M=o.matrix
		if arcorden.val==1 or evt==18:
			p1,p2,p3=m.verts[0],m.verts[1],m.verts[2]
		elif arcorden.val==2:
			p1,p2,p3=m.verts[1],m.verts[2],m.verts[0]
		elif arcorden.val==3:
			p1,p2,p3=m.verts[2],m.verts[0],m.verts[1]

		p1=GloVrt(p1,M)
		p2=GloVrt(p2,M)
		p3=GloVrt(p3,M)

		print "Points:\n ",p1,p2,p3
		
		p21=p2-p1
		p31=p3-p1

		M1=CrossVecs(p21,p31)

		D=DotVecs(M1,p1)
		D2=DotVecs(p21,p1+p2)/2
		D3=DotVecs(p31,p1+p3)/2

		SS=Matrix(
		[M1[0],M1[1],M1[2]],
		[p21[0],p21[1],p21[2]],
		[p31[0],p31[1],p31[2]],
		)
		O=Sistema(SS,Vector([D,D2,D3]))
		
		v2=p2-O
		b3=p3-O
		vN=CrossVecs(v2,b3)
		v3=CrossVecs(v2,vN)

			#Terna ortogonal: v2,vN,v3
		R=sqrt(DotVecs(v2,v2))
		RN=sqrt(DotVecs(vN,vN))
		R3=sqrt(DotVecs(v3,v3))

		if evt==18: angul=2*pi
		else: angul=AngleBetweenVecs(v2,b3)

		print "Center:",O
		print "Radius :",R,"RN:",RN,"R3:",R3
		print "Angle:",angul
		M2=Matrix([v2[0]/R,v2[1]/R,v2[2]/R],[-v3[0]/R3,-v3[1]/R3,-v3[2]/R3],[vN[0]/RN,vN[1]/RN,vN[2]/RN])

		arco=HaceArco(pts.val,0,angul,ctro.val,1)
		oo=CreaObjDeMalla(arco,o,meTx.val+'.In')
		EU=M2.toEuler()
		EU=EU[0]*pi/180,EU[1]*pi/180,EU[2]*pi/180
		oo.RotX,oo.RotY,oo.RotZ=EU[0],EU[1],EU[2]
		oo.setLocation(O)
		oo.setSize(R,R,R)

		if evt==17:
			angul=angul-360
			arco=HaceArco(pts.val,0,angul,ctro.val,1)
			oo=CreaObjDeMalla(arco,o,meTx.val+'.Ex')
			oo.RotX,oo.RotY,oo.RotZ=EU[0],EU[1],EU[2]
			oo.setLocation(O)
			oo.setSize(R,R,R)

	if(evt==20): # SUBDIVIDE
		for o in filter(mallaScan,os):
			m=o.data
			mm=New()
			mm.name=m.name+'.Subdiv'
			for v in m.verts: mm.verts.append(v)
			N=ndiv.val
			NV=len(m.verts)-1
			for k1 in range(NV+1):
				v1=m.verts[k1]
				for k2 in range(NV-k1):
					v2=m.verts[NV-k2]
					for f in m.faces:
						if (v1 in f.v) and (v2 in f.v):	#	SI...
							dif=abs(f.v.index(v2)-f.v.index(v1))
							if dif==1 or dif==len(f.v)-1: #...entonces f contiene la arista v1-v2
								v=v1
								for K in range(N):
									cara=Face()
									cara.v.append(v)
									if K<N-1:
										v=Vert()
										for c in range(3): v.co[c]=(v1.co[c]*(N-K-1)+v2.co[c]*(K+1))/N
										mm.verts.append(v)
									elif K==N-1: v=v2
									cara.v.append(v)
									mm.faces.append(cara)
							break #para que no se repitan aristas comunes a varias caras
			CreaObjDeMalla(mm,o,o.name+'.Subdiv')

	if evt==30:						# APLICA LOC.ROT.SIZE
		for o in filter(mallaScan,os):
			M=o.matrix

			eu=Euler([nRotX.val,nRotY.val,nRotZ.val])
			Mr=eu.toMatrix()
			Mr.resize4x4()
			Mt=TranslationMatrix(Vector([nLocX.val,nLocY.val,nLocZ.val]))

			o.setMatrix(Mr*Mt)
			o.setSize(nSizX.val,nSizY.val,nSizZ.val)
			MI=o.getInverseMatrix()
			P=M*MI
			maya=o.getData()
			for v in maya.verts:
				w=list(Vector([v[0],v[1],v[2],1]) * P)
				for c in xrange(3):	v[c]=w[c]/o.size[c]

			maya.update()
			if other.val:
				P.invert()
				for oo in Scene.GetCurrent().getChildren():
					try: same= oo.getData(mesh=1).name==maya.name and o!=oo
					except: same = False
					
					if same:
						N=oo.getMatrix()
						oo.setMatrix(P*N)
						oo.setSize(oo.SizeX*nSizX.val,oo.SizeY*nSizY.val,oo.SizeZ*nSizZ.val)

	if(evt==5 or evt==6) and len(os) and oa.getType()=='Mesh':   #  ENCAJA-ABARCA
		enc=[encX.val,encY.val,encZ.val]
		en2=[en2X.val,en2Y.val,en2Z.val]
		me=oa.data
		meVs= me.verts
		me.transform(oa.matrix)
		for c in xrange(3):
			if en2[c] or enc[c]:
				if (len(os)>1):
					n1=Extremo(os[1].data.verts,os[1].matrix)[0][c]
					m1=Extremo(os[1].data.verts,os[1].matrix)[2][c]
				if (len(os)>2):
					n2=Extremo(os[2].data.verts,os[2].matrix)[0][c]
					m2=Extremo(os[2].data.verts,os[2].matrix)[2][c]
				n0=Extremo(meVs)[0] [c]
				m0=Extremo(meVs)[2] [c]
				ancho=m0-n0
				pm=(m0+n0)/2
				if (len(os)==1): n1,m1=n0,m0
				if (len(os)<3): n2,m2=n1,m1
				if (n2<n1):
					t,s=n2,m2
					n2,n1,m2,m1=n1,t,m1,s
				print coo[c],n0,m0,n1,m1,n2,m2
			for v in meVs:
				A , factor = 0. , 1.
				pm2= None
				if enc[c]:
					if evt==5:	pm2=(n2+m1)*0.5
					else:		pm2=(m2+n1)*0.5
					v[c]+= pm2-pm
				if en2[c] and ancho:
					if pm2==None:
						if evt==5:	pm2=(n2+m1)*0.5
						else:		pm2=(m2+n1)*0.5
						v[c]+= pm2-pm
					
					if evt==5:	factor=(n2-m1)/ancho
					else:		factor=(m2-n1)/ancho
					v[c]=pm2+(v[c]-pm2)*factor
		PutRaw(me)

	elif (evt==1 and len(os)):
		ali=[aliX.val,aliY.val,aliZ.val]
		eqi=[menueqiX.val,menueqiY.val,menueqiZ.val]
		sep=[sepX.val,sepY.val,sepZ.val]
		if CreaNew.val:
			for o in filter(mallaScan,os):
				newos=[o]
				for i in range(Cuantos.val):
					newo=CreaObjDeMalla(o.getData(),o,o.name)
					newos.append(newo)
					for c in range(3):
						if (ali[c]):
							Exec_align(newos,c,ali,eqi,sep)
		else:
			for c in range(3):
				if (ali[c]):
					Exec_align(filter(mallaScan,os),c,ali,eqi,sep)
	elif (evt==2 and len(os)):
		gir=[girX.val,girY.val,girZ.val]
		inc=[incX.val,incY.val,incZ.val]
		if CreaNew.val:
			for o in filter(mallaScan,os):
				newos=[o]
				for i in range(Cuantos.val):
					newo=CreaObjDeMalla(o.getData(),o,o.name)
					newos.append(newo)
					for c in range(3):
						valor=o.rot[c]
						for oo in newos:
							if (gir[c]):
								SituaR(oo,c,valor)
								valor=valor+inc[c]*pi/180
		else:
			for c in range(3):
				if (gir[c]):
					valor=oa.rot[c]
					for o in os:
						SituaR(o,c,valor)
						valor=valor+inc[c]*pi/180
				
	elif evt in [3,7] and len(os):
		sca=[scaX.val,scaY.val,scaZ.val]
		inc=[iScaX.val,iScaY.val,iScaZ.val]
		if CreaNew.val:
			for o in filter(mallaScan,os):
				newos=[o]
				for i in range(Cuantos.val):
					newo=CreaObjDeMalla(o.getData(),o,o.name)
					newos.append(newo)
					for c in range(3):
						valor=o.size[c]
						for oo in newos:
							if (sca[c]):
								SituaS(oo,c,valor)
								if evt==3: valor=valor+inc[c]
								if evt==7: valor=valor*inc[c]
		else:
			for c in range(3):
				if (sca[c]):
					valor=oa.size[c]
					for o in os:
						SituaS(o,c,valor)
						if evt==3: valor=valor+inc[c]
						if evt==7: valor=valor*inc[c]

	elif (evt==99): Exit()
	Blender.Redraw()

#file=open(path+dirsep+'KUlang.txt','r')
#file=open(dirsep.join(path)+dirsep+'KUlang.txt','r')

file=open(join(path,'KUlang.txt'),'r')
fich=file.readlines()
print "\n\nKloputils",fich[0]
for i in range(len(fich)):
	if fich[i]==Lang+'\012': break
print "Language:",fich[i]
menuExit=fich[i+1]#Sale prog.
menu0=fich[i+2]#Pral.
J=int(fich[i+3])#Alinea:botones
menu1a=[]
for j in range(J): menu1a.append(fich[i+j+4])
i=i+J
menu1b=fich[i+4]#Alinea:menu separa
menu2=str(fich[i+5])#Crea:menu
J=int(fich[i+6])#Crea:botones
menu2a=[]
for j in range(J): menu2a.append(fich[i+j+7])
i=i+J
menu3=fich[i+7]#Modif:menu
menu3a=fich[i+8]#Modif:"partes
menu3b=fich[i+9]#Modif:menu plano
menu3c=fich[i+10]#Modf:"Actua...
menu3d=fich[i+11]#Modif:menu dire
menu3e=fich[i+12]#Modf:"Captura
menu4=fich[i+13]#Buffer
menu5=fich[i+14]#ModifObjs
menu5a=fich[i+15]

file.close

Register(draw,event,bevent)
