#include "SpriteModel.h"

double fkut_SpriteModel::distPut = 1.0;

fkut_SpriteModel::fkut_SpriteModel(int argW, int argH) : fk_Model()
, winW(argW), winH(argH), fontReady(false)
{
	setParent(&pixelBase);

	texShape.setTextureMode(FK_TEX_MODULATE);
	texShape.setTexRendMode(FK_TEX_REND_SMOOTH);
	setShape(&texShape);

	absMate.setAmbDiff(0.0, 0.0, 0.0);
	absMate.setEmission(1.0, 1.0, 1.0);
	absMate.setAlpha(1.0);
	setMaterial(absMate);

	return;
}

fkut_SpriteModel::~fkut_SpriteModel(void)
{
}

bool fkut_SpriteModel::entryFirst(fk_Scene *argScn, fk_Model *argCam)
{
	if(texShape.getImage()->getWidth() == 0) {
		argScn->removeModel(this);
		argScn->removeOverlayModel(this);
		return false;
	}

	if(argCam != NULL) argScn->entryCamera(argCam);

	MakePixelBase(argScn);
	argScn->entryOverlayModel(this);

	return true;
}

void fkut_SpriteModel::MakePixelBase(fk_Scene *argScn)
{
	fk_Perspective	*pers = NULL;
	fk_Ortho		*orth = NULL;
	fk_Frustum		*frus = NULL;
	double	dW = (double)winW;
	double	dH = (double)winH;

	if((fk_Model*)argScn->getCamera() == NULL) return;
	pixelBase.setParent((fk_Model*)argScn->getCamera());

	if(argScn->getProjection()->getMode() == FK_PERSPECTIVE_MODE) {
		pers = (fk_Perspective *)argScn->getProjection();
		double halfFovy = pers->getFovy()*0.5;
		double nearPut = pers->getNear()+distPut;

		pixelBase.glMoveTo(0.0, 0.0, -nearPut);
		pixelBase.setScale((nearPut*tan(halfFovy)*2.0/dH), (nearPut*tan(halfFovy)*2.0/dH), 1.0);

	} else if(argScn->getProjection()->getMode() == FK_ORTHO_MODE){
		orth = (fk_Ortho *)argScn->getProjection();

		pixelBase.glMoveTo(0.0, 0.0, -(orth->getNear()+distPut));
		pixelBase.setScale((orth->getRight() - orth->getLeft())/dW,
						   (orth->getTop() - orth->getBottom())/dH, 1.0);

	} else if(argScn->getProjection()->getMode() == FK_FRUSTUM_MODE) {
		frus = (fk_Frustum *)argScn->getProjection();

		double nearPut = frus->getNear();
		double regL = frus->getLeft();
		double regR = frus->getRight();
		double regB = frus->getBottom();
		double regT = frus->getTop();
		regL /= nearPut;	regR /= nearPut;
		regB /= nearPut;	regT /= nearPut;
		nearPut += distPut;
		regL *= nearPut;	regR *= nearPut;
		regB *= nearPut;	regT *= nearPut;

		pixelBase.glMoveTo((regR + regL)/2.0, (regT + regB)/2.0, -nearPut);
		pixelBase.setScale((regR - regL)/dW, (regT - regB)/dH, 1.0);
	}
	pixelBase.glAngle(0.0, 0.0, 0.0);

	return;
}

void fkut_SpriteModel::setSpriteSize(double width, double height)
{
	if(width < 0.0) width = (double)getImage()->getWidth();
	if(height < 0.0) height = (double)getImage()->getHeight();
	texShape.setTextureSize(width, height);
	return;
}

fk_TexCoord	fkut_SpriteModel::getSpriteSize(void)
{
	return texShape.getTextureSize();
}

bool fkut_SpriteModel::readBMP(const string argFileName)
{
	if(!texShape.readBMP(argFileName)) return false;
	setSpriteSize();
	return true;
}

bool fkut_SpriteModel::readPNG(const string argFileName)
{
	if(!texShape.readPNG(argFileName)) return false;
	setSpriteSize();
	return true;
}

bool fkut_SpriteModel::readJPG(const string argFileName)
{
	if(!texShape.readJPG(argFileName)) return false;
	setSpriteSize();
	return true;
}

void fkut_SpriteModel::setImage(fk_Image &argImage)
{
	texShape.setImage(&argImage);
	setSpriteSize();
	return;
}

fk_Image * fkut_SpriteModel::getImage(void)
{
	return texShape.getImage();
}

bool fkut_SpriteModel::initFont(const string argFontFile)
{
	if(!text.initFont(argFontFile)) {
		fontReady = false;
		return false;
	}

	text.setDPI(96);
	text.setPTSize(18);
	text.setForeColor(1.0, 1.0, 1.0, 1.0);
	text.setBackColor(0.0, 0.0, 0.0, 0.5);
	text.setAlign(FK_ALIGN_CENTER);

	setImage(text);

	fontReady = true;
	return true;
}

void fkut_SpriteModel::drawText(const string argStr, bool argFlag, fk_StringCode argCode)
{
	if(!fontReady) return;

	if(argFlag) textStr.clear();
	textStr.convert(argStr, argCode);
	text.loadUniStr(&textStr);
	setImage(text);

	return;
}

void fkut_SpriteModel::drawText(const string argStr, fk_StringCode argCode)
{
	drawText(argStr, false, argCode);
}

void fkut_SpriteModel::setSpriteSmoothMode(bool flag)
{
	if(flag) texShape.setTexRendMode(FK_TEX_REND_SMOOTH);
	else texShape.setTexRendMode(FK_TEX_REND_NORMAL);
}

bool fkut_SpriteModel::getSpriteSmoothMode(void)
{
	if(texShape.getTexRendMode() == FK_TEX_REND_SMOOTH) return true;
	return false;
}

void fkut_SpriteModel::setSpriteArea(double left, double top, double width, double height)
{
	double imgWidth  = (double)getImage()->getWidth();
	double imgHeight = (double)getImage()->getHeight();
	if(imgWidth < 8.0 || imgHeight < 8.0 || fabs(width) < 8.0 || fabs(height) < 8.0) return;

	fk_TexCoord	lb, rt;

	lb.set(left/imgWidth, 1.0-(top+height)/imgHeight);
	rt.set((left+width)/imgWidth, 1.0-top/imgHeight);
	texShape.setTextureCoord(lb, rt);
	setSpriteSize(fabs(width), fabs(height));

	return;
}

void fkut_SpriteModel::setPositionLT(double x, double y)
{
	fk_TexCoord	size = getSpriteSize();
	glMoveTo(x + size.x/2.0, y - size.y/2.0, 0.0);
}
