#!BPY

import Blender
from Blender import NMesh, Scene, Object, Draw, Image, Material, Texture, sys
from Blender.BGL import *
from Blender.Draw import *
from Blender.Window import *
from Blender.Image import *
from Blender.Material import *
from Blender.Texture import *
from Blender.sys import *


import sys, struct, string
from types import *

import os
from os import path

# HACK -- it seems that some Blender versions don't define sys.argv,
# which may crash Python if a warning occurs.
if not hasattr(sys, "argv"): sys.argv = ["???"]

# Import globals
g_obj_filename=Create("model")

#Globals
g_scale=Create(1.0)


# Events
EVENT_NOEVENT=1
EVENT_LOAD_OBJ=2
EVENT_CHOOSE_FILENAME=3
EVENT_EXIT=100

######################################################
# Callbacks for Window functions
######################################################
def filename_callback(input_filename):
	global g_obj_filename
	g_obj_filename.val=input_filename

######################################################
# GUI Loader
######################################################
def draw_gui():
	global g_scale
	global g_obj_filename
	global g_scale_slider
	global EVENT_NOEVENT,EVENT_LOAD_OBJ,EVENT_CHOOSE_FILENAME,EVENT_EXIT

	########## Titles
	glClear(GL_COLOR_BUFFER_BIT)
	glRasterPos2d(8, 103)
	Text("OBJ loader")

	######### Parameters GUI Buttons
	g_obj_filename = String("ICO file to load: ", EVENT_NOEVENT, 10, 55, 210, 18, g_obj_filename.val, 255, "ICO file to load")
	########## obj File Search Button
	Button("Search",EVENT_CHOOSE_FILENAME,220,55,80,18)

	########## Scale slider-default is 1
	g_scale= Slider("Scale Factor: ", EVENT_NOEVENT, 10, 75, 210, 18,
		1.0, 0.001, 10.0, 1, "Scale factor for obj Model");

	######### Draw and Exit Buttons
	Button("Load",EVENT_LOAD_OBJ , 10, 10, 80, 18)
	Button("Exit",EVENT_EXIT , 170, 10, 80, 18)

def event(evt, val):
	if (evt == QKEY and not val):
		Exit()

def bevent(evt):
	global g_obj_filename
	global EVENT_NOEVENT,EVENT_LOAD_OBJ,EVENT_EXIT

	######### Manages GUI events
	if (evt==EVENT_EXIT):
		Exit()
	elif (evt==EVENT_CHOOSE_FILENAME):
		FileSelector(filename_callback, "OBJ File Selection")
	
	#load the object
	elif (evt==EVENT_LOAD_OBJ):
		if (g_obj_filename.val == "model"):
			Exit()
		else:
			load_obj(g_obj_filename.val)
			Blender.Redraw()
			Exit()

Register(draw_gui, event, bevent)

def tw(n):
	if n>1.002:
		print "TW>"+str(n)	
		while n>1.002:
			n=n-1
	else:
		if n<(-0.002):
			print "TW<"+str(n)
			while n<(-0.002):
				n=n+1
	return n

def load_obj (obj_filename):
	#load_maps(obj_filename)
	#load_materials((splitext(obj_filename))[0]+".mtl", dirname(obj_filename))
	file=open(obj_filename,"r")

	print "LOAD "+obj_filename

	just_found_group=0
	mesh = NMesh.New()
	mesh_material_index=-1

	current_material=""

	uv_list=[]
	uv_coord=[]

	no_list=[]
	no_coord=[]

	v_count=0
	vt_count=0
	vn_count=0

	vert_offset=0

	
	h=file.read(20)
	header=struct.unpack("IIIII",h)
	if header[0]!=0x010000:
		print "Invalid header"
		return
	if header[3]!=0x3f800000:
		print "Invalid header"
		return
	
	numshapes=header[1]
	vertices=header[4]
	textype=header[2]
	if numshapes!=1:
		print "Animations are not supported"
		return
	
	
	if int(vertices/3)!=(vertices/3):
		print "Not a multiple of 3 vertices"
		return
	
	if textype!=7:
		print "Unsupported texture type"
		return
	numtrigs=vertices/3

	for counter in range(numtrigs):
		face = NMesh.Face()
		for i in range(3):
			vc=file.read(8)
			(x,y,z,l)=struct.unpack("hhhH",vc)
			v=NMesh.Vert(float((float(x))/4096)*g_scale.val, float((float(z))/4096)*g_scale.val, float((-float(y))/4096)*g_scale.val)
			nc=file.read(8)
			(nx,ny,nz,nl)=struct.unpack("hhhH",vc)
			#paso de las normales, de momento
			#v.no[0]=float(float(x)/4096)
			#v.no[1]=float((-float(z))/4096)
			#v.no[2]=float((-float(y))/4096)
			tc=file.read(4)
			(tu,tv)=struct.unpack("hh",tc)
			#v.uvco[0]=float(float(tu)/4096)
			#v.uvco[1]=float(float(tv)/4096)
			
			mesh.verts.append(v)
			face.v.append(v)
			face.uv.append((tw(float(float(tu)/4096)),tw(1-float(float(tv)/4096))))
			rgba=file.read(4)
			(r,g,b,a)=struct.unpack("BBBB",rgba)
			#print "vertex "+str(x)+" "+str(y)+" "+str(z)+" "+str(l)
			face.col.append(NMesh.Col(r,g,b,a))
			#print "->col: "+str(r)+" "+str(g)+" "+str(b)+" "+str(a)
			#print "->UV: "+str(tu)+" "+str(tv)
			
		mesh.faces.append(face)

	ah=file.read(20)

	aheader=struct.unpack("IIIII",ah)
	
	if aheader[0]!=1:
		print "Invalid animation header"
		return

	nframes=aheader[4]
	for i in range(nframes):
		fd=file.read(16)
		fdata=struct.unpack("IIII",fd)
		nfk=fdata[1]-1
		for i in range(nfk):
			fk=file.read(8)

	texture=file.read(128*128*2)
	mat=Material.New("M"+os.path.split(obj_filename)[1])

	rfile=open(splitext(obj_filename)[0]+".rgb","w")

	for i in range(128*128):
		a=texture[i*2]
		b=texture[i*2+1]
		n=struct.unpack("H",a+b)
		r=8*(n[0] & 0x1f)
		g=8*((n[0]>>5) & 0x1f)
		b=8*((n[0]>>10) & 0x1f)
		#print r,g,b
		d=struct.pack("BBB",r,g,b)
		rfile.write(d)
	rfile.close()
	os.system("convert -depth 8 -size 128x128 rgb:"+splitext(obj_filename)[0]+".rgb "+splitext(obj_filename)[0]+".png")
	tex = Texture.New("T"+os.path.split(obj_filename)[1])
	image = Image.Load(splitext(obj_filename)[0]+".png")
	tex.setType("Image")
	tex.setImage(image)
	mat.clearTexture(0)
	mat.setTexture(0, tex,TexCo.UV)

	mesh.materials.append(mat)

	for f in mesh.faces:
		f.image=image
	

	#########Puts the last mesh into blender and close file
	mesh_obj = NMesh.PutRaw(mesh,os.path.split(obj_filename)[1],1)
	file.close()

	#put the object at the cursor position
	cursor_pos=Blender.Window.GetCursorPos()
	mesh_obj.setLocation(float(cursor_pos[0]),float(cursor_pos[1]),float(cursor_pos[2]))
