# script Bevel pour Blender 2.30/2.31,	richie Decembre 2003

import Blender
from Blender import *
from Blender.BGL import *
from Blender.Draw import *

cursor=Create(0.0)
lstep=Create(10)

mob0=Create(1)
mob1=Create(0)

def vectunit(f1):
	ts=[]
	zero=0
	cnt=range(len(f1))+[0]
	for i in range(len(f1)):
		x=f1[cnt[i+1]][0]-f1[cnt[i]][0]
		y=f1[cnt[i+1]][1]-f1[cnt[i]][1]
		z=f1[cnt[i+1]][2]-f1[cnt[i]][2]
		norm=(x**2+y**2+z**2)**0.5
		if norm!=0:
			ts.append([x/norm,y/norm,z/norm])
			zero=1
	if zero==1:	return ts

def vers_centre2(f,k1,tts,j):
	cnt=range(len(f))+[0]
	for i in range(len(f)):
		f[cnt[i+1]][0]=vtt2[j][cnt[i+1]][0]+(-tts[cnt[i]][0]+tts[cnt[i+1]][0])*k1
		f[cnt[i+1]][1]=vtt2[j][cnt[i+1]][1]+(-tts[cnt[i]][1]+tts[cnt[i+1]][1])*k1
		f[cnt[i+1]][2]=vtt2[j][cnt[i+1]][2]+(-tts[cnt[i]][2]+tts[cnt[i+1]][2])*k1

def remplir_angle(m,fft):
	if len(fft)%2==0:	p=len(fft)/2-1
	else:	p=len(fft)/2
	while p!=0:
		f1=Blender.NMesh.Face()
		[f1.append(fft[i][1]) for i  in range(len(fft)) if fft[0][1]==fft[i][2]]
		map(f1.append,[fft[0][1],fft[0][2]])
		[f1.append(fft[j][2]) for j in range(len(fft)) if fft[0][2]==fft[j][1] and fft[j][2]!=f1[-3]]
		m.faces.append(f1)
		fft[0][1],fft[0][2]=f1[-4],f1[-1]
		p-=1

def trier_tri(mm,ft):
	while 1:
		if len(ft):
			a=[x[0] for x in ft]
			b=a.count(a[0])
			c=[x[1] for x in ft]
			nb=c.count(ft[0][0])
			if nb==0:	mm.verts.remove(ft[0][0])
			remplir_angle(mm,ft[0:b])
			del ft[0:b]
		else:
			break

def remplir_edge(a,b,mee1):
	f1= Blender.NMesh.Face()
	[[f1.v.append(xx[cnt]) for cnt in [2,3]] for xx in [a,b]]
	mee1.faces.append(f1)
	f1.smooth=sm

	ftri=[]
	for i in range(2):
		f1=[]
		[f1.append(a[cnt]) for cnt in [1,2]]
		f1.append(b[3])
		ftri.append(f1)
		a,b=b,a
	return ftri

def tri_bordure(me,tt,ftri):
	f1=Blender.NMesh.Face()
	[f1.v.append(tt[0][cnt]) for cnt in range(4)]
	me.faces.append(f1)
	map(ftri.append,[[tt[0][1],tt[0][2],tt[0][1]],[tt[0][0],tt[0][0],tt[0][3]]])

def tri_edge_bordure(mee,tt):
	j=1
	fftri=[]
	while len(tt)>1:
		if tt[0][0]==tt[j][1] and tt[0][1]==tt[j][0]:
			tab=remplir_edge(tt[0],tt[j],mee)
			map(fftri.append,[tab[0],tab[1]])
			map(tt.remove,[tt[j],tt[0]])
			j=1

		elif j==len(tt)-1:
			tri_bordure(mee,tt,fftri)
			tt.remove(tt[0])
			j=1
		else:
			j+=1

	if len(tt)==1:
		tri_bordure(mee,tt,fftri)

	fftri.sort()
	trier_tri(mee,fftri)
	return

def creation_selection_facette():
	global sm,vtt,vtt2,tts
	tt,vtt2,lf1,vtt=[],[],[],[]
	sm=0

	if mob0.val==1:
		Ft=m.faces
	if mob1.val==1:
		Ft=m.getSelectedFaces()
	finit=len(Ft)



	for f in Ft:
		cnt=range(len(f.v))+[0]
		vt=[]
		aa=[]
		for i in range(len(f.v)):
			v1=NMesh.Vert(f[cnt[i]][0],f[cnt[i]][1],f[cnt[i]][2])
			[fct.append(v1) for fct in [m.verts,vt]]
			aa.append([f[cnt[i]][0],f[cnt[i]][1],f[cnt[i]][2]])
		vtt2.append(aa)
		vtt.append(vt)
		[tt.append([f[cnt[i]],f[cnt[i+1]],vt[cnt[i+1]],vt[cnt[i]]]) for i in range(len(f.v))]

	for i in range(len(vtt)):
		f1=NMesh.Face()
		map(f1.v.append,vtt[i])
		m.faces.append(f1)

	map(m.faces.remove,Ft[0:finit])
	tts=[vectunit(f) for f in vtt]
	tri_edge_bordure(m,tt)

	NMesh.PutRaw(m,m.name)


def lancer():
	try:
		if vtt is not None:
			i=0
			k=cursor.val/200.0
			for f in vtt:
				vers_centre2(f,k,tts[i],i)
				i+=1
			NMesh.PutRaw(m,m.name)
	except:
		pass


def draw():
	global lstep,cursor,mob0,mob1
	glClearColor ( 0.6, 0.6, 0.6, 1.0)
	glClear (GL_COLOR_BUFFER_BIT)
	glRasterPos2f(20, 155)
	Text("If you want to keep your original mesh,")
	glRasterPos2f(20, 140)
	Text("make a copy with SHIFT+D before using the script")
	Button("Bevel",           10, 20,80,200,40)

	mob0=Toggle("object",         7, 20, 200,  100, 20, mob0.val)
	mob1=Toggle("Selected faces", 8, 140, 200,  100, 20, mob1.val)

	cursor=Slider("thickness  ",        5,20,43,200,18,cursor.val,-lstep.val,lstep.val,0)
	lstep=Number('limit  ',             5,20,20, 80, 18,lstep.val,0.0,1000.0,'thickness button extremum')

def event(ev,val):
	if ( ev == ESCKEY and not val) or (ev == QKEY):	Exit()

def bevent(ev):
	global vtt,m,tts

	if (ev==7):
		mob1.val=0
		Register(draw, event, bevent)
	if (ev==8):
		mob0.val=0
		Register(draw, event, bevent)

	if ( ev == 10 ) :
		ob=Object.GetSelected()
		cursor.val=0
		lstep.val=10
		if ob:
			m=ob[0].getData()
			creation_selection_facette()
			ob[0].makeDisplayList()
	if ( ev == 5 ):
		ob=Object.GetSelected()
		if ob:
			lancer()
			Register(draw, event, bevent)
			ob[0].makeDisplayList()
Register(draw, event, bevent)
Blender.Redraw()