#!BPY
################
#author: Daniel Jungmann (dsj at gmx dot net)
#version: 2.5
################
"""
Name: 'Eternal-Lands files (.e3d)'
Blender: 243
Group: 'Export'
Tip: 'Export to Eternal-Lands 3d object files.'
"""
import Blender
from Blender import NMesh, Object, Mesh
from Blender import Draw, BGL
from Blender.BGL import *
from Blender.Draw import *
from Blender.Window import *
from Blender.Image import *
from Blender.Mathutils import Vector
import sys, struct, string
from types import *
from math import *
import os
from os import path
import md5
import gzip

has_normal = 0
has_tangent = 0
do_compress = 0
has_extra_uv = 0
first_uv = 0
second_uv = 0
alpha_uv = 0
EVENT_NOEVENT = 1
EVENT_EXPORT = 2
EVENT_CANCEL = 3
EVENT_HAS_NORMAL = 4
EVENT_HAS_TANGENT = 5
EVENT_DO_COMPRESS = 6
EVENT_EXTRA_UV = 7
EVENT_FIRST_UV = 8
EVENT_SECOND_UV = 9
EVENT_ALPHA_UV = 9
EVENT_TRANSPARENT_BASE = 11
material_count = 0
material_dict = {}
material_options = []
material_names = []
default_uv_layer = "UVTex"
extra_uv_layer = ""
alpha_uv_layer = ""
extra_uv_list = []
layer_list = []
uv_menu = Create(1)
extra_uv_menu = Create(1)
default_filename = ""
clear_options = 1

#hashing of a vector + normal vector + texture coordinates
def complex_hash(v, n, t, uv, euv):
	global has_normal, has_tangent, has_extra_uv
	if (has_normal):
		if (has_extra_uv):
			return struct.pack("5i", v, uv[0]*32768, uv[1]*32768, \
				euv[0]*32768, euv[1]*32768)
		else:
			return struct.pack("3i", v, uv[0]*32768, \
				uv[1]*32768)
	elif (has_tangent):
		if (has_extra_uv):
			return struct.pack("11i", v, t[0]*32768, t[1]*32768, \
				t[2]*32768, n[0]*32768, n[1]*32768, \
				n[2]*32768, uv[0]*32768, uv[1]*32768, \
				euv[0]*32768, euv[1]*32768)
		else:
			return struct.pack("9i", v, t[0]*32768, t[1]*32768, \
				t[2]*32768, n[0]*32768, n[1]*32768, \
				n[2]*32768, uv[0]*32768, uv[1]*32768)
	else:
		if (has_extra_uv):
			return struct.pack("8i", v, n[0]*32768, n[1]*32768, \
				n[2]*32768, uv[0]*32768, uv[1]*32768, \
				euv[0]*32768, euv[1]*32768)
		else:
			return struct.pack("6i", v, n[0]*32768, n[1]*32768, \
				n[2]*32768, uv[0]*32768, uv[1]*32768)

class el3d_vertex:
	vertexes = []
	normals = []
	textures = []
	tangents = []
	extra_uvs = []
	binary_format_vertex = "3f"
	binary_format_normal = "3f"
	binary_format_tangent = "3f"
	binary_format_texture = "2f"
	binary_format_extra_uv = "2f"
	def __init__(self):
        	self.vertexes = [0]*3
        	self.normals = [0]*3
		self.textures = [0]*2
        	self.tangents = [0]*3
		self.extra_uvs = [0]*2
	def save(self, file):
		global has_normal, has_tangent, has_extra_uv
		data = struct.pack(self.binary_format_texture, \
			self.textures[0], self.textures[1])
        	file.write(data)
		if (has_extra_uv):
			data = struct.pack(self.binary_format_extra_uv, \
				self.extra_textures[0], self.extra_textures[1])
	        	file.write(data)
		if (has_normal):
			data = struct.pack(self.binary_format_normal, \
				self.normals[0], self.normals[1], \
				self.normals[2])
	        	file.write(data)
		if (has_tangent):
			data = struct.pack(self.binary_format_tangent, \
				self.tangents[0], self.tangents[1], \
				self.tangents[2])
	        	file.write(data)
		data = struct.pack(self.binary_format_vertex, \
			self.vertexes[0], self.vertexes[1], self.vertexes[2])
        	file.write(data)
	def size(self):
		global has_normal, has_tangent, has_extra_uv
		ret = struct.calcsize(self.binary_format_vertex)
		ret += struct.calcsize(self.binary_format_texture)
		if (has_normal):
			ret += struct.calcsize(self.binary_format_normal)
		if (has_tangent):
			ret += struct.calcsize(self.binary_format_tangent)
		if (has_extra_uv):		
			ret += struct.calcsize(self.binary_format_extra_uv)
		return ret

class el3d_index:
	index_val = 0
	binary_format = "1i"
	def save(self, file):
		data = struct.pack(self.binary_format, self.index_val)
		file.write(data)
	def size(self):
		return struct.calcsize(self.binary_format)

class el3d_material:
	options = 0
	start = 0
	count = 0
	min_x = 0
	min_y = 0
	min_z = 0
	max_x = 0
	max_y = 0
	max_z = 0
	min_index = 0
	max_index = 0
	material_name = ""
	extra_material_name = ""
	alpha_material_name = ""
	binary_format_material = "1i128s6f4i"
	binary_format_extra_material = "128s"
	binary_format_alpha_material = "128s"
	def save(self, file):
		global has_normal, has_tangent, has_extra_uv
		data = struct.pack(self.binary_format_material, self.options, \
			self.material_name, self.min_x, self.min_y, \
			self.min_z, self.max_x, self.max_y, self.max_z, \
			self.min_index, self.max_index, self.start, \
			self.count)
		file.write(data)
		if (has_extra_uv):
			data = struct.pack(self.binary_format_extra_material, self.extra_material_name)
			file.write(data)
			data = struct.pack(self.binary_format_alpha_material, self.alpha_material_name)
			file.write(data)
	def size(self):
		global has_normal, has_tangent, has_extra_uv
		ret = struct.calcsize(self.binary_format_material)
		if (has_extra_uv):
			ret += struct.calcsize(self.binary_format_extra_material)
			ret += struct.calcsize(self.binary_format_alpha_material)
		return ret 

class el3d_header:
	magic = "e3dx"
	version = [1, 0, 0, 0]
	header_offset = 28
	index_no = 0
	index_size = 4
	index_offset = 0
	vertex_no = 0
	vertex_size = 0
	vertex_offset = 0
	material_no = 0
	material_size = 0
	material_offset = 0
	vertex_options = 0
	char_reserved_1 = 0
	char_reserved_2 = 0
	char_reserved_3 = 0
	md5_obj = md5.new()
	binary_format = "4c4b16c10i4b"
	def save(self, file):
		digest = self.md5_obj.digest()
		data = struct.pack(self.binary_format, self.magic[0], \
			self.magic[1], self.magic[2], self.magic[3], \
			self.version[0], self.version[1], self.version[2], \
			self.version[3], digest[0], digest[1], digest[2], \
			digest[3], digest[4], digest[5], digest[6], \
			digest[7], digest[8], digest[9], digest[10], \
			digest[11], digest[12], digest[13], digest[14], \
			digest[15], self.header_offset, self.vertex_no, \
			self.vertex_size, self.vertex_offset, self.index_no, \
			self.index_size, self.index_offset, self.material_no, \
			self.material_size, self.material_offset, \
			self.vertex_options, self.char_reserved_1, \
			self.char_reserved_2, self.char_reserved_3)
		file.write(data)
	def size(self):
		return struct.calcsize(self.binary_format)
	def build_md5(self, file):
		self.md5_obj = md5.new()
		file.seek(self.header_offset)
		data = file.read()
		self.md5_obj.update(data)

def quad2tri(mesh):
	global default_uv_layer, extra_uv_layer, extra_uv_list
	face_list = []
	j = 0
	for i in range(0, len(mesh.faces)):
		face = mesh.faces[i]
		if (len(face.v) == 3):
			face_list.append(face)
			j += 1
			if (has_extra_uv):
				mesh.activeUVLayer = extra_uv_layer;
				face = mesh.faces[i]
				extra_uv_list.append(face.uv)
				mesh.activeUVLayer = default_uv_layer;
			else:
				extra_uv_list.append(face.uv)
		else:
			d1 = (mesh.verts[face.v[0].index].co.x - mesh.verts[face.v[2].index].co.x) ** 2 
			d1 += (mesh.verts[face.v[0].index].co.y - mesh.verts[face.v[2].index].co.y) ** 2 
			d1 += (mesh.verts[face.v[0].index].co.z - mesh.verts[face.v[2].index].co.z) ** 2 
			d2 = (mesh.verts[face.v[1].index].co.x - mesh.verts[face.v[3].index].co.x) ** 2 
			d2 += (mesh.verts[face.v[1].index].co.y - mesh.verts[face.v[3].index].co.y) ** 2 
			d2 += (mesh.verts[face.v[1].index].co.z - mesh.verts[face.v[3].index].co.z) ** 2 
			if (d1 < d2):
				face_list.append(NMesh.Face([face.v[0], face.v[1], face.v[2]]))
				face_list[j].uv = [face.uv[0], face.uv[1], face.uv[2]]
				face_list[j].smooth = face.smooth
				j += 1
				face_list.append(NMesh.Face([face.v[0],face.v[2],face.v[3]]))
				face_list[j].uv = [face.uv[0], face.uv[2], face.uv[3]]
				face_list[j].smooth = face.smooth
				j += 1
				if (has_extra_uv):
					mesh.activeUVLayer = extra_uv_layer;
					face = mesh.faces[i]
					extra_uv_list.append([face.uv[0], face.uv[1], face.uv[2]])
					extra_uv_list.append([face.uv[0], face.uv[2], face.uv[3]])
					mesh.activeUVLayer = default_uv_layer;
				else:
					extra_uv_list.append([face.uv[0], face.uv[1], face.uv[2]])
					extra_uv_list.append([face.uv[0], face.uv[2], face.uv[3]])
			else:
				face_list.append(NMesh.Face([face.v[0],face.v[1],face.v[3]]))
				face_list[j].uv = [face.uv[0], face.uv[1], face.uv[3]]
				face_list[j].smooth = face.smooth
				j += 1
				face_list.append(NMesh.Face([face.v[1],face.v[2],face.v[3]]))
				face_list[j].uv = [face.uv[1], face.uv[2], face.uv[3]]
				face_list[j].smooth = face.smooth
				j += 1
				if (has_extra_uv):
					mesh.activeUVLayer = extra_uv_layer;
					face = mesh.faces[i]
					extra_uv_list.append([face.uv[0], face.uv[1], face.uv[3]])
					extra_uv_list.append([face.uv[1], face.uv[2], face.uv[3]])
					mesh.activeUVLayer = default_uv_layer;
				else:
					extra_uv_list.append([face.uv[0], face.uv[1], face.uv[3]])
					extra_uv_list.append([face.uv[1], face.uv[2], face.uv[3]])
	return face_list

def save_el3d(filename):
	global has_normal, has_tangent, do_compress, has_extra_uv
	global material_dict, material_count, material_options, material_names
	global default_uv_layer, extra_uv_layer, alpha_uv_layer, extra_uv_list
	if (filename.find(".e3d", -4) <= 0):
		if (do_compress):
			if (filename.find(".e3d.gz", -7) <= 0):
				filename += ".e3d.gz"
		else:
			filename += ".e3d"
	elif (do_compress):
		filename += ".gz"
	print "Starting e3d export to file: ", filename
	index_list = []
	index_no = 0
	vert_list = []
	vert_dict = {}
	vert_no = 0
	material_list = []
	#get the currently selected data structures
	for mesh_object in Blender.Object.GetSelected():
		if (mesh_object.getType() == "Mesh"):
			#get access to the mesh data
			mesh = mesh_object.getData(False, True)
			break
	#convert quads to tris
	face_list = quad2tri(mesh)
	header = el3d_header()
	header.vertex_options = (1 - has_normal) + has_tangent * 2 + has_extra_uv * 4
	if (has_tangent):
		tangent_list = [Vector(0, 0, 0)] * len(mesh.verts)
		vert = [Vector(0, 0, 0)] * 3
		for face in face_list:
			for i in range(0, 3):
				tmp = mesh.verts[face.v[i].index].co
				vert[i] = Vector(tmp[0], tmp[1], tmp[2])
			tangent = vert[2] - vert[0]
			if (face.uv[2][1] != face.uv[1][1]):
				m = (face.uv[2][1] - face.uv[0][1]) / (face.uv[2][1] - face.uv[1][1])
				tangent += vert[1] - vert[2] * m
			tangent.normalize()
			for i in range(0, 3):
				tangent_list[face.v[i].index] += tangent
	for i in range(0, material_count):
		material_list.append(el3d_material())
		material_list[i].material_name = Blender.sys.basename(material_names[i][0])
		material_list[i].options = material_options[i]
		material_list[i].start = index_no
		material_list[i].min_index = 0xFFFFFFFF
		material_list[i].max_index = 0
		if (has_extra_uv):
			material_list[i].extra_material_name = Blender.sys.basename(material_names[i][1])
			material_list[i].alpha_material_name = Blender.sys.basename(material_names[i][2])
		min_x = 10e30
 		min_y = 10e30
		min_z = 10e30
		max_x = -10e30
 		max_y = -10e30
		max_z = -10e30
		for idx in range(0, len(face_list)):
			face = face_list[idx]
			if (len(layer_list) > 1):
				cur_layer = mesh.activeUVLayer
				mesh.activeUVLayer = default_uv_layer
				material_name_1 = face.image.getFilename()
				mesh.activeUVLayer = extra_uv_layer
				material_name_2 = face.image.getFilename()
				mesh.activeUVLayer = alpha_uv_layer
				material_name_3 = face.image.getFilename()
				mesh.activeUVLayer = cur_layer
				material_dict_name = material_name_1 + material_name_2 + material_name_3
			else:
				material_dict_name = face.image.getFilename()
			if (material_dict[material_dict_name] != i):
				continue
			for j in range(0, 3):
				uv = extra_uv_list[idx][j]
				if (face.smooth == 1):
					normal = mesh.verts[face.v[j].index].no
				else:
					normal = face.no
				normal = mesh.verts[face.v[j].index].no
				normal = Vector(normal[0], normal[1], normal[2])
				if (has_tangent):
					tangent = tangent_list[face.v[j].index]
					tangent = tangent - normal * Blender.Mathutils.DotVecs(tangent, normal)
					tangent.normalize()
				else:
					tangent = Vector(0, 0, 0)
				hash_value = complex_hash(face.v[j].index, normal, tangent, face.uv[j], uv)
				if not vert_dict.has_key(hash_value):
					vert_dict[hash_value] = vert_no
					vert_list.append(el3d_vertex())
					vert_list[vert_no].vertexes = mesh.verts[face.v[j].index].co
					vert_list[vert_no].normals = normal
					vert_list[vert_no].textures = face.uv[j]
					vert_list[vert_no].extra_textures = uv
					vert_list[vert_no].tangents = tangent
					vert_no += 1
	        		index_list.append(el3d_index())
				index = vert_dict[hash_value]
				index_list[index_no].index_val = index
				material_list[i].min_index = min(material_list[i].min_index, index)
				material_list[i].max_index = max(material_list[i].max_index, index)
				#find the min and max values
				x = index_list[index_no].index_val
				if (vert_list[x].vertexes[0] < min_x):
					min_x = vert_list[x].vertexes[0]
				if (vert_list[x].vertexes[1] < min_y):
					min_y = vert_list[x].vertexes[1]
				if (vert_list[x].vertexes[2] < min_z):
					min_z = vert_list[x].vertexes[2]
				if (vert_list[x].vertexes[0] > max_x):
					max_x = vert_list[x].vertexes[0]
				if (vert_list[x].vertexes[1] > max_y):
					max_y = vert_list[x].vertexes[1]
				if (vert_list[x].vertexes[2] > max_z):
					max_z = vert_list[x].vertexes[2]
				index_no += 1
		material_list[i].count = index_no - material_list[i].start
		material_list[i].min_x = min_x
		material_list[i].min_y = min_y
		material_list[i].min_z = min_z
		material_list[i].max_x = max_x
		material_list[i].max_y = max_y
		material_list[i].max_z = max_z
	header.index_no = index_no
	header.vertex_no = vert_no
	header.material_no = material_count
	tmp = el3d_vertex()
	header.vertex_size = tmp.size()
	tmp = el3d_material()
	header.material_size = tmp.size()
	tmp = el3d_index()
	header.index_size = tmp.size()
	header.vertex_offset = header.size()
	header.index_offset = header.vertex_offset + header.vertex_no * header.vertex_size
	header.material_offset = header.index_offset + header.index_no * header.index_size
	file = open(filename, "w+b")
	header.save(file)
	for v in vert_list:
		v.save(file)
	for i in index_list:
		i.save(file)
	for m in material_list:
		m.save(file)
	header.build_md5(file)
	file.close()
	if (do_compress):
		file = gzip.open(filename, "wb", 9)
	else:
		file = open(filename, "wb")
	header.save(file)
	for v in vert_list:
		v.save(file)
	for i in index_list:
		i.save(file)
	for m in material_list:
		m.save(file)
	file.close()
	print "Done e3d export to file: ", filename

def fill_mat(mesh):
	global material_dict, material_count, material_options, material_names
	global default_uv_layer, extra_uv_layer, alpha_uv_layer, layer_list, uv_menu
	global clear_options
	material_count = 0
	material_dict = {}
	material_names = []
	if (clear_options):
		material_options = []
	for face in mesh.faces:
		try:
			if (len(layer_list) > 1):
				cur_layer = mesh.activeUVLayer
				mesh.activeUVLayer = default_uv_layer
				material_name_1 = face.image.getFilename()
				mesh.activeUVLayer = extra_uv_layer
				material_name_2 = face.image.getFilename()
				mesh.activeUVLayer = alpha_uv_layer
				material_name_3 = face.image.getFilename()
				mesh.activeUVLayer = cur_layer
				material_name = [material_name_1, material_name_2, material_name_3]
				material_dict_name = material_name_1 + material_name_2 + material_name_3
			else:
				material_name = [face.image.getFilename(), ""]
				material_dict_name = face.image.getFilename()
		except ValueError:
			return False
		if not material_dict.has_key(material_dict_name):
			material_dict[material_dict_name] = material_count
			if (clear_options):
				material_options.append(0)
			material_names.append(material_name)
			material_count += 1
	clear_options = 0
	return True

def draw():
	global has_normal, has_tangent, do_compress, has_extra_uv, first_uv, second_uv, alpha_uv
	global material_dict, material_count, material_options, material_names
	global default_uv_layer, extra_uv_layer, alpha_uv_layer, layer_list, uv_menu
	global extra_uv_menu, default_filename
	global EVENT_NOEVENT, EVENT_CANCEL, EVENT_EXPORT, EVENT_HAS_NORMAL
	global EVENT_SAVE_TANGENT, EVENT_DO_COMPRESS, EVENT_EXTRA_UV, EVENT_ALPHA_UV
	global EVENT_TRANSPARENT_BASE, EVENT_FIRST_UV
	glClear(GL_COLOR_BUFFER_BIT)
	size = list(Blender.Window.GetAreaSize())
	#get the currently selected data structures
	for mesh_object in Blender.Object.GetSelected():
		if (mesh_object.getType() == "Mesh"):
			#get access to the mesh data
			mesh = mesh_object.getData(False, True)
			default_filename = mesh_object.name + ".e3d"
			if (do_compress):
				default_filename += ".gz"
			break
	layer_list = mesh.getUVLayerNames()
	if (len(layer_list) > 0):
		default_uv_layer = layer_list[first_uv]
		extra_uv_layer = layer_list[second_uv]
		alpha_uv_layer = layer_list[alpha_uv]
	if (not fill_mat(mesh)):
		PupMenu("Error: Not all faces have images!")
		Exit()
		return
	menu_string = ""
	for i in range (0, len(layer_list)):
		menu_string += "| " + layer_list[i] + " %x" + str(i)
	if (len(layer_list) > 1):
		if size[0] < 450:
			size[0] = 450
	else:
		if size[0] < 230:
			size[0] = 230
	columns = (size[0] - 10) / 220;
	rows = (material_count + columns - 1) / columns;
	columns = min(columns, material_count)
	rows = max(rows, 1)

	if (size[1] < (270 + rows * 30)):
		size[1] = 270 + rows * 30
	# 10 px border
	rect = [10, 10, size[0] - 11, size[1] - 11]
	middle = (rect[0] + rect[2]) / 2
	string = "EL Exporter Options"
	glRasterPos2i(middle - (GetStringWidth(string, "large") / 2), \
		rect[3] - 9)
	Text(string, "large")
	glRasterPos2i(middle - (GetStringWidth(string, "large") / 2) + 1, \
		rect[3] - 9)
	Text(string, "large")
	rect[3] -= 16
	if (len(layer_list) > 1):
		pos = middle - 215
	else:
		pos = middle - 105
	rect[3] -= 30
	Toggle("GZip Compression", EVENT_DO_COMPRESS, pos, rect[3], 210, 25, \
		do_compress)
	if (len(layer_list) > 1):
		glRasterPos2i(pos + 220, rect[3] + 9)
		Text("First UV coordinates", "large")
		rect[3] -= 30
		Toggle("Save extra uv's", EVENT_EXTRA_UV, pos, rect[3], \
			210, 25, has_extra_uv)
		uv_menu = Menu("First UV coordinates %t" + menu_string, \
			EVENT_FIRST_UV, pos + 220, rect[3], 210, 25, first_uv)
	rect[3] -= 30
	Toggle("Save normals", EVENT_HAS_NORMAL, pos, rect[3], 210, 25, \
		has_normal)
	if (len(layer_list) > 1):
		glRasterPos2i(pos + 220, rect[3] + 9)
		Text("Second UV coordinates", "large")
	rect[3] -= 30
	Toggle("Save tangents", EVENT_HAS_TANGENT, pos, rect[3], 210, 25, \
		has_tangent)
	if (len(layer_list) > 1):
		extra_uv_menu = Menu("Second UV coordinates %t" + \
			menu_string, EVENT_SECOND_UV, pos + 220, rect[3], \
			210, 25, second_uv)
	if (len(layer_list) > 2):
		rect[3] -= 30
		glRasterPos2i(pos + 220, rect[3] + 9)
		Text("Alpha UV coordinates", "large")
		rect[3] -= 30
		alpha_uv_menu = Menu("Alpha UV coordinates %t" + \
			menu_string, EVENT_ALPHA_UV, pos + 220, rect[3], \
			210, 25, alpha_uv)
	rect[3] -= 10
	string = "Transparent Materials"
	glRasterPos2i(middle - (GetStringWidth(string, "large") / 2), \
		rect[3] - 9)
	Text(string, "large")
	glRasterPos2i(middle - (GetStringWidth(string, "large") / 2) + 1, \
		rect[3] - 9)
	Text(string, "large")
	rect[3] -= 16
	i = 0
	start_pos = middle - columns * 110 + 5
	if (columns > 0):
		for string in material_names:
			if ((i % columns) == 0):
				pos = start_pos
				rect[3] -= 30
			Toggle(Blender.sys.basename(string[0]), \
				EVENT_TRANSPARENT_BASE + i, pos, rect[3], \
				210, 25, material_options[i])
			pos += 220
			i += 1
	Button("Export", EVENT_EXPORT, middle + 005, rect[1], 100, 50)
	Button("Cancel", EVENT_CANCEL, middle - 105, rect[1], 100, 50)

def event(evt, val):
	if (evt == QKEY and not val): 
		Exit()
 
def bevent(evt):
	global has_normal, has_tangent, do_compress, has_extra_uv, first_uv
	global second_uv, alpha_uv, material_dict, material_count, material_options
	global material_names, default_uv_layer, extra_uv_layer, uv_menu
	global extra_uv_menu, alpha_uv_menu, default_filename
	global EVENT_NOEVENT, EVENT_CANCEL, EVENT_EXPORT, EVENT_HAS_NORMAL
	global EVENT_HAS_TANGENT, EVENT_DO_COMPRESS, EVENT_EXTRA_UV, EVENT_ALPHA_UV
	global EVENT_TRANSPARENT_BASE, EVENT_FIRST_UV, EVENT_SECOND_UV
	global clear_options
	if (evt == EVENT_EXPORT):
		if (has_tangent and (not has_normal)):
			PupMenu("Warning: Files without normals " + \
				"can't have tangents! Tangents disabled.")
			has_tangent = 0
		if (has_extra_uv and (first_uv == second_uv)):
			PupMenu("Warning: First and second texture " + \
				"coordinates are the same layer! " + \
				"Second texture coordinates disabled.")
		Blender.Window.FileSelector(save_el3d, "Export e3dx", default_filename)
		Redraw(1)
	elif (evt == EVENT_HAS_NORMAL):
		has_normal = 1 - has_normal
		if (has_tangent and (not has_normal)):
			PupMenu("Warning: Files without normals " + \
				"can't have tangents! Tangents disabled.")
			has_tangent = 0
		Redraw(1)
	elif (evt == EVENT_HAS_TANGENT):
		has_tangent = 1 - has_tangent
		if (has_tangent and (not has_normal)):
			PupMenu("Warning: Files without normals " + \
				"can't have tangents! Normals enabled.")
			has_normal = 1
		Redraw(1)
	elif (evt == EVENT_DO_COMPRESS):
		do_compress = 1 - do_compress
		Redraw(1)
	elif (evt == EVENT_EXTRA_UV):
		has_extra_uv = 1 - has_extra_uv
		Redraw(1)
	elif (evt == EVENT_FIRST_UV):
		if (first_uv != uv_menu.val):
			clear_options = 1
		first_uv = uv_menu.val
		Redraw(1)
	elif (evt == EVENT_SECOND_UV):
		second_uv = extra_uv_menu.val
		Redraw(1)
	elif (evt == EVENT_ALPHA_UV):
		alpha_uv = alpha_uv_menu.val
		Redraw(1)
	elif ((evt >= EVENT_TRANSPARENT_BASE) and (evt < \
		(EVENT_TRANSPARENT_BASE + material_count))):
		i = evt - EVENT_TRANSPARENT_BASE
		material_options[i] = 1 - material_options[i]
		Redraw(1)
	elif (evt == EVENT_CANCEL):
		Exit()

def register_exporter():
	for mesh_object in Blender.Object.GetSelected():
		if (mesh_object.getType() == "Mesh"):
			#get access to the mesh data
			Register(draw, event, bevent)
			return
	PupMenu("Fatal Error: You must select a mesh to output as e3d!")

register_exporter()
