/*	Viewer.c
	Does viewing object stuff for Glover PSX
	By Chris Wilson, started on 2/12/98
*/

#include "glover.h"
//#include "bff_load.h"


// move to new module
#define MAX_ACTORS 32
#define MAX_MODELS 16

typedef struct tagPSXACTOR
{
	NEWMODEL *pModel;
	VECTOR   pos,rot,scale;
	AnimType anim;
}PSXACTOR;

PSXACTOR pActorList[MAX_ACTORS];

typedef struct tagIMODEL{
	NEWMODEL *pModel;
	objectSegDataType *pSeg;
}IMODEL;

IMODEL pModelList[MAX_MODELS];



enum{
	VIEW_ROTATESCALE,
	VIEW_ANIMATION,
	VIEW_LIGHTING,
	VIEW_NUMVIEWS
};

VIEWDATA viewData[NUM_VIEW]={VD};

GsRVIEW2 mycamera;

static int viewModel=0;
static int viewModelOld=-1;
static TextureBankType *pTBank[2];
static NEWMODEL *pObj=NULL;
static objectSegDataType *pAnim=NULL;
static int cRange=0, nRanges;
static int frmFixed;
static long scale=2048;
VECTOR rot={0,0,0};
static int viewMode=VIEW_ROTATESCALE;
static char *psViewMode[]={"ROTATE/SCALE","ANIMATION","LIGHTING"};

void viewerCLS(void)
{
	POLY_G4 *si = (POLY_G4 *) GsOUT_PACKET_P; 
	register	GsOTA 	*otptr=(GsOTA*)(PolyList->org+MAXPOLYDEPTH);

  	if (TOOMANYPOLYS(sizeof(POLY_G4),"CLEAR SCREEN"))return;

	SETRGBC(si->r0, 127, 0, 0, GPU_COM_G4);
	SETRGBC(si->r1, 0, 0, 127, GPU_COM_G4);
	SETRGBC(si->r2, 0, 127, 0,GPU_COM_G4);
	SETRGBC(si->r3, 0, 0, 0,GPU_COM_G4);
	
	si->x0=si->x2=0-320;
	si->x1=si->x3=640-320;
	si->y0=si->y1=0-120-PALMODE*8;
	si->y2=si->y3=240+(PALMODE*8)-120;
 	PUTPACKETINTABLE(si,otptr,POLYG4_LEN);
	GsOUT_PACKET_P+=sizeof(POLY_G4);

}


void viewerInitialise(void)
{
	viewModel=0;

	mycamera.vpx=0;
	mycamera.vpy=0;
	mycamera.vpz=-1024;

	mycamera.vrx=0;
	mycamera.vry=0;
	mycamera.vrz=0;

	cameraSetView(&mycamera);

	lightInitFlat();

	textReset();
	messctrl.font=fontList[1];//textureLoadSPT("GRAPHICS\\NEWFONT.SPT");

	spriteReset();
	sprctrl.stretch=1;

	pTBank[0]=NULL;//textureLoadBank("WORLDS\\GENERIC\\GENERIC.SPT");
	pTBank[1]=NULL;
	modelctrl.lighting=LIGHTING_PARALLEL;
}

char sBankName[64];
char sFileName[64];
char sSegName[64];

void viewerFrame(void)
{
	int lev,subLev;
	int startFixed, endFixed;
	int j;
	GsF_LIGHT light;

	//for(j=0;j<3;j++)
	j=0;
	{
 		light.vx = 2000;
	 	light.vy = 2000;
 		light.vz = 0;
	 	SETRGBC(light.r,128,128,128,0);
		GsSetFlatLight(j,&light);
	}

 	GsSetAmbient(64*16,64*16,64*16);
	GsSetLightMode(2);	   //fogging?

	textSetPos(32,240);
	SETRGBC(sprctrl.r,128,64,64,0);
	textPrintf("MODE: %s\n", psViewMode[viewMode]);

	textSetPos(32,8);
	SETRGBC(sprctrl.r,128,128,128,0);
	sprctrl.scalex=4096;//2048;
	sprctrl.scaley=4096;//2048;

	SETRGBC(clscol.r,254/*don't CLS*/,0,0,GPU_COM_F4);

	// Test SELECT so we can change mode
	if(debounce[0]&PAD_SELECT)
	{
		viewMode++;
		if(viewMode==VIEW_NUMVIEWS) viewMode=0;
	}

	// always allow this
	if((debounce[0]&PAD_SQUARE)&&(viewModel>0))
		viewModel--;
	else
		if((debounce[0]&PAD_CIRCLE)&&(viewModel<(NUM_VIEW-1)))
			viewModel++;

	if(viewMode==VIEW_ANIMATION)
	{
		if(debounce[0]&PAD_LEFT)
		{
			if(cRange>0)
			{
				cRange--;
				frmFixed=pAnim[cRange].segStart*4096;
			}
		}
		else
		{
			if(debounce[0]&PAD_RIGHT)
			{
				cRange++;
				if(cRange==nRanges)
					cRange--;

				frmFixed=pAnim[cRange].segStart*4096;
			}
		}
	}

	if(viewMode==VIEW_ROTATESCALE)
	{
		if(pad[0]&PAD_LEFT)
			rot.vy-=64;
		else
			if(pad[0]&PAD_RIGHT)
				rot.vy+=64;

		if(pad[0]&PAD_UP)
			rot.vx-=64;
		else
			if(pad[0]&PAD_DOWN)
				rot.vx+=64;

		rot.vy&=0xfff; // keep <4096
		rot.vx&=0xfff; // keep <4096
		
		if((pad[0]&PAD_R1)&&(scale>0))
			scale-=32;
		else
			if((pad[0]&PAD_R2)&&(scale<16384))
				scale+=32;
	}

	if(viewMode==VIEW_LIGHTING)
	{
		if(debounce[0]&PAD_TRIANGLE)
			modelctrl.lighting^=LIGHTING_PARALLEL;
	}

	lev=viewData[viewModel].level;
	subLev=viewData[viewModel].subLevel;

	if(lev==GENERIC)
	{
		sprintf(sBankName, "WORLDS\\HUB\\HUB8\\HUB8.spt");
	}
	else
	{
		sprintf(sBankName, "WORLDS\\%s\\%s\\%s%s.spt",
				WorldDirectoryNames[lev], sSubLevelDirNames[subLev],
				sAbbrevNames[lev], sSubLevelNames[subLev]);
	}

	if(viewModelOld!=viewModel)
	{
		memoryShowStats();

		if(sBankName)
		{
			if(pTBank[1])
			{
				textureUnloadBank(pTBank[1]);
			}
			pTBank[1]=textureLoadBank(sBankName);
			textureDownloadBank(pTBank[1]);
			textureDestroyBank(pTBank[1]);
		}
		
		if(pObj)
			objectFree(pObj, NULL);
		if(pAnim)
		{
			FREE(pAnim);
			pAnim=NULL;
		}
		
		sprintf(sFileName, "WORLDS\\%s\\NME\\%s.psa",
				WorldDirectoryNames[lev], viewData[viewModel].sFileName);

//		pObj=LoadPSA(sFileName);

// sadly, this won't actually work. What's needed is a BFF of level models

		pObj = BFF_IsModelLoaded(viewData[viewModel].sFileName,&pAnim);
		if(pAnim)
		{
			nRanges=pAnim->numSegs;
			cRange=0;
			frmFixed=pAnim->segStart*4096;
		}

		objectSetupSegmentSort(pObj);
	}

	textPrintf("Model: %d %s '%s'\n", viewModel, viewData[viewModel].sModelName, viewData[viewModel].sFileName);
	textPrintf("Scale: %s\n", printFixed(scale));
	textPrintf("Lighting: %s\n", (modelctrl.lighting&LIGHTING_PARALLEL)?"ON":"OFF");

	if(pAnim)
	{
/*
		textPrintf("Range: '%s' (%d/%d) FPS %d\n", pAnim[cRange].segName, cRange, nRanges,
													pAnim[cRange].segFPS);
*/
		textPrintf("Range: '---' (%d/%d) FPS %d\n", cRange, nRanges,
													pAnim[cRange].segFPS);
	}
	else
		textPrintf("No animation loaded\n");

	pObj->position.vx=0;
	pObj->position.vy=0;
	pObj->position.vz=0;

	pObj->globalscale.vx=scale;
	pObj->globalscale.vy=scale;
	pObj->globalscale.vz=scale;

	pObj->world.rotate.vx=rot.vx;
	pObj->world.rotate.vy=rot.vy;
	pObj->world.rotate.vz=rot.vz;
	
	objectSegmentSort(pObj);

	if(pAnim)
	{
		startFixed=pAnim[cRange].segStart*4096;
		endFixed=pAnim[cRange].segEnd*4096;

		frmFixed+=4096;
		if(frmFixed>=endFixed)
			frmFixed=startFixed+(endFixed-frmFixed);

		objectSetAnimation(pObj, frmFixed/4096);
	}
	else
		objectSetAnimation(pObj, 0);

	objectDraw(pObj);

	viewerCLS();

	viewModelOld=viewModel;
}
