# -*- indent-tabs-mode: t -*-
# $Id: bcgui.py 426 2006-10-03 15:04:31Z cubicool $

import Blender
import os
import blendercal
import bcconf

CALLBACK = lambda *a, **k: None
UI       = [None] * 11
IMAGE    = None
(
	EV_AUTHOR,
	EV_PREPEND,
	EV_EXPORTGL,
	EV_LOD,
	EV_EXTRADATA,
	EV_XMLINDENT,
	EV_FLOATPRE,
	EV_ANIMFPS,
	EV_VIEW,
	EV_CANCEL,
	EV_WRITE
) = range(11)

# We do some forced type coersion here JUST IN CASE the user messes it up. :)
# I usually don't do stuff like this (since the python "way" is to let exceptions
# propagate), but we really don't want to have weird behavior here.
EXPORTS = [
	str(bcconf.AUTHOR),
	str(bcconf.PREPEND),
	int(bcconf.EXPORTGL),
	int(bcconf.LOD),
	int(bcconf.EXTRADATA),
	int(bcconf.XMLINDENT),
	int(bcconf.FLOATPRE),
	int(bcconf.ANIMFPS)
]

# Easy way to create and manage a progress bar. bar_steps is the number of times the 
# bar itself will be updated during the progress. This is to avoid a horrendous amount of
# bar updates, which would create a fantastic amount of overhead on machines without
# hardware rendering. Start by calling Progress.setup, and then call Progress.increment
# for each time any progress is made.
class Progress(object):
	def __init__(self, bar_steps):
		object.__init__(self)

		self.bar_steps = bar_steps

	def setup(self, total_steps, pstring):
		self.total_steps = total_steps
		self.pstring = pstring
		self.stepsize = float(self.total_steps)/float(self.bar_steps)
		self.progress = 0
		self.multiplier = 0
		self.steplimit = 0
		self.update()

	def increment(self, amount = 1):
		self.progress += amount

		if self.progress >= self.steplimit:
			self.multiplier += 1
			self.steplimit = self.stepsize * self.multiplier
			self.update()

	# TODO: Palle, whoa. :) I'll have to break this up a bit.
	def update(self):
		Blender.Window.DrawProgressBar(
			float(self.progress)/float(self.total_steps),
			self.pstring + ": " + str(int((float(self.progress)/float(self.total_steps))*100)) + "%"
		)

def InterfaceDraw():
	Blender.BGL.glClear(Blender.BGL.GL_COLOR_BUFFER_BIT)
	Blender.BGL.glEnable(Blender.BGL.GL_BLEND)
	Blender.BGL.glBlendFunc(
		Blender.BGL.GL_SRC_ALPHA,
		Blender.BGL.GL_ONE_MINUS_SRC_ALPHA
	)

	UI[0] = Blender.Draw.String(
		"Author's Name: ",
		EV_AUTHOR,
		5, 25, 400, 20,
		EXPORTS[0],
		255,
		"The author's name; goes into $MODEL.cfg."
	)
	
	UI[1] = Blender.Draw.String(
		"Prepend Name: ",
		EV_PREPEND,
		5, 45, 400, 20,
		EXPORTS[1],
		255,
		"Prepend all model files with this string."
	)
	
	UI[2] = Blender.Draw.Toggle(
		"Export OpenGL",
		EV_EXPORTGL,
		5, 65, 140, 20,
		EXPORTS[2],
		"Change the up direction to Y; useful for some engines."
	)
	
	UI[3] = Blender.Draw.Toggle(
		"Calculate LODS",
		EV_LOD,
		5, 85, 140, 20,
		EXPORTS[3],
		"Calculate Cal3D Level Of Detail steps."
	)
	
	UI[4] = Blender.Draw.Toggle(
		"Extra Data",
		EV_EXTRADATA,
		5, 105, 140, 20,
		EXPORTS[4],
		"Add date, time, etc. into $MODEL.cfg."
	)
	
	UI[5] = Blender.Draw.Number(
		"XML Indent:      ",
		EV_XMLINDENT,
		5, 125, 200, 20,
		EXPORTS[5],
		0,
		10,
		"Use this level of indentation in the XML files."
	)
	
	UI[6] = Blender.Draw.Number(
		"Float Precision: ",
		EV_FLOATPRE,
		5, 145, 200, 20,
		EXPORTS[6],
		3,
		20,
		"Use this level of float/double precision (significant digits)."
	)
	
	UI[7] = Blender.Draw.Number(
		"Animation FPS:   ",
		EV_ANIMFPS,
		5, 165, 200, 20,
		EXPORTS[7],
		1,
		100,
		"Frames Per Second"
	)
	
	UI[8] = Blender.Draw.PushButton(
		"View Stats",
		EV_VIEW,
		5, 5, 200, 20,
		"View the objects and groups the exporter will be aware of."
	)
	
	UI[9] = Blender.Draw.PushButton(
		"Quit",
		EV_CANCEL,
		205, 5, 100, 20,
		"Oh nos!"
	)
	
	UI[10] = Blender.Draw.PushButton(
		"WRITE",
		EV_WRITE,
		305, 5, 100, 20,
		"Weee!"
	)

	global IMAGE
	if not IMAGE:
		# Don't load the logo if used in non-GUI mode
		IMAGE = Blender.Image.Load(os.path.join(Blender.Get("scriptsdir"), "blendercal", "logo.png"))
	Blender.Draw.Image(IMAGE, 145, 65)

	Blender.BGL.glDisable(Blender.BGL.GL_BLEND)

def InterfaceEvent(event, value):
	if event == Blender.Draw.ESCKEY:
		Blender.Draw.Exit()

def InterfaceButton(event):
	def __setVal(e):
		EXPORTS[e] = UI[e].val
	
	def __setBool(e):
		EXPORTS[e] = not EXPORTS[e]

	def __doView(e):
		pass
	
	def __doCancel(e):
		Blender.Draw.Exit()
	
	def __doWrite(e):
		blendercal.ParseArgs(["""
			--blendercal=
			AUTHOR    = %s;
			PREPEND   = %s;
			XMLINDENT = %s;
			FLOATPRE  = %s;
			ANIMFPS   = %g;
			EXPORTGL  = %s;
			LOD       = %s;
			EXTRADATA = %s;
		""" % (
			EXPORTS[EV_AUTHOR],
			EXPORTS[EV_PREPEND],
			EXPORTS[EV_XMLINDENT],
			EXPORTS[EV_FLOATPRE],
			EXPORTS[EV_ANIMFPS],
			EXPORTS[EV_EXPORTGL],
			EXPORTS[EV_LOD],
			EXPORTS[EV_EXTRADATA]
		)])
	
		Blender.Window.FileSelector(CALLBACK, "Export Cal3D", "model.cfg")

		Blender.Draw.Exit()

	{
		EV_AUTHOR:     __setVal,
		EV_PREPEND:    __setVal,
		EV_XMLINDENT:  __setVal,
		EV_FLOATPRE:   __setVal,
		EV_ANIMFPS:    __setVal,
		EV_EXPORTGL:   __setBool,
		EV_LOD:        __setBool,
		EV_EXTRADATA:  __setBool,
		EV_VIEW:       __doView,
		EV_CANCEL:     __doCancel,
		EV_WRITE:      __doWrite
	}[event](event)
