/**********************************************************************

	Title :			Level Editor Module
	Filename :		levedit.c
	Author :		Thomas Szirtes
	Revision :		1.0

	Notes :			THIS WILL NOT BE PROVIDED TO DEVELOPERS

	Copyright :		(C) SEGA Europe 1998

  **********************************************************************/

/*

	Commands
	CURSOR KEYS	-	Move cursor up/down left/right through map
	X (B)		-	Place Building at cursor
	Z (A)		-	Exit edit mode
	A (X)		-	Cycle left through buildings
	S (Y)		-	Cycle right through buildings
	D (Z)		-	Delete at cursor

*/


/*
 *			Includes
 */

#include	"ftypes.h"
#ifdef	USING_SET4
#include	<shinobi.h>
#else
#include	<ninjawin.h>
#endif

#include	"future.h"
#include	"tools.h"
#include	"display.h"
#include	"map.h"
#include	"camera.h"

/*
 *			Definitions
 */
#define MODE_PLACE		0
#define	MODE_DELETE		1
#define	MODE_SAVE		2


/*
 *			External References	
 */
extern CAMERA	mycam;
extern MAP		map;					/* the MAP */


/*
 *			Module Variables
 */

static	NJS_PERIPHERAL	*per1;	
static	int		curi = 11;
static	int		curj = 11;
static	int		scrx = 0;
static	int		scry = 0;

static	int		blink	=	0;
static	int		cursor	=	0;


/* LEVEDIT cursor */
static	NJS_TEXNAME	levedit_texname[] = {
									{"cursor2", 0, 0 },						
									{"cursor1", 0, 0 },						
									{"cursor3", 0, 0 },
									{"block2", 0, 0 },
									{"block1",0, 0 },
									{"block3",0, 0 }
								};


static	NJS_TEXLIST		levedit_texlist = { levedit_texname, 6 };	
static	NJS_SPRITE		sprite;
static	NJS_TEXANIM		cursor_texanim[] = {	
									{ 8,8,4,4,0,0,255,255,0,0 },
									{ 8,8,4,4,0,0,255,255,1,0 },
									{ 8,8,4,4,0,0,255,255,2,0 },
									{ 8,8,4,4,0,0,255,255,3,0 },
									{ 8,8,4,4,0,0,255,255,4,0 },
									{ 8,8,4,4,0,0,255,255,5,0 }
									};


static	int	currentslot;


static	Uint32		oldon			=	0;
static	int			mode			=	0;
static	int			select_build	=	0;
static	int			can_place		=	0;			/* flag can we place here? */
static	int			occupied		=	0;
static	Uint8		current_orient	=	0;


/*----------------------------------------- FUNCTIONS ---------------------------------------// */

/*--------------------------------------------------------------------------
 
  void LEVELEDIT_Init()
 
  Parameters:
 
  Returns:
 
  Notes:
 
  --------------------------------------------------------------------------*/

void LEVELEDIT_Init()
{
	njLoadTexture(&levedit_texlist);
}


/*--------------------------------------------------------------------------
 
  void DisplayEditGrid(int mode)
 
  Parameters:
		mode		-		place (0) mode or delete (1) mode 
  Returns:
 
  Notes:
 
  --------------------------------------------------------------------------*/

void DisplayEditGrid(int mode)
{
	int	i,j;
	Sint8	n,m;
	Uint16 index;
	Uint8	orient;

	sprite.tlist	=	&levedit_texlist;
	sprite.tanim	=	cursor_texanim;
	sprite.ang		=	0;
	sprite.sx		=	16.f;
	sprite.sy		=	16.f;
	sprite.p.y		=	0.f; 

	
	for(j=-14;j<14;j++)
	{
		for(i=-14;i<15;i++)
		{
			sprite.p.x		=	(float)((curi+i)*GRID_SIZE); 
			sprite.p.z		=	(float)((curj+j)*GRID_SIZE); 
			if (curi+i <= 128 && curi+i >= 0 && curj+j <= 128 && curj+j >= 0)
			{
				if(map.map[curi+i][curj+j].inst==0xffff)
					njDrawSprite3D	( &sprite, 3, NJD_SPRITE_SCALE );
				else
					njDrawSprite3D	( &sprite, 4, NJD_SPRITE_SCALE );
			}
		}
	}

	if (mode==0)
	{
		/* Draw currently buildings shadow */
		sprite.p.y		=	1.f; 
		i				=	curi;
		j				=	curj;
		if (buildings[select_build].shadow!=NULL)
		{
			index		=	0;
			occupied	=	0;
			while (GetBuildingShadow((Uint8)select_build, &n, &m, index++, current_orient)!=0)
			{
			/* check if overlapping */
				if(map.map[i+(int)n][j+(int)m].inst!=0xffff) occupied=1;
			}
			
			index	=	0;
			while (GetBuildingShadow((Uint8)select_build, &n, &m, index++, current_orient)!=0)
			{
				/* now display all grid squares belonging to root */
				sprite.p.x	=	(float)((i+(int)(n))*GRID_SIZE);
				sprite.p.z	=	(float)((j+(int)(m))*GRID_SIZE);
				njDrawSprite3D	( &sprite, 5-occupied, NJD_SPRITE_SCALE  );
			}
		}
	}
	else
	{
		if(map.map[curi][curj].inst!=0xffff)
		{
				orient	=	build_inst[map.map[curi][curj].inst].flag & INST_FLAG_ORIENT_MASK;
				switch (orient)
				{
				case INST_FLAG_ORIENT0 : orient	=	0; break;
				case INST_FLAG_ORIENT1 : orient	=	1; break;
				case INST_FLAG_ORIENT2 : orient	=	2; break;
				case INST_FLAG_ORIENT3 : orient	=	3; break;
				}
			/* Draw currently buildings shadow */
			sprite.p.y		=	1.f; 
			i				=	build_inst[map.map[curi][curj].inst].i;
			j				=	build_inst[map.map[curi][curj].inst].j;
			if (buildings[select_build].shadow!=NULL)
			{
				index		=	0;
				occupied	=	1;
				while (GetBuildingShadow(build_inst[map.map[curi][curj].inst].id, &n, &m, index++, orient)!=0)
				{
					/* now display all grid squares belonging to root */
					sprite.p.x	=	(float)((i+(int)(n))*GRID_SIZE);
					sprite.p.z	=	(float)((j+(int)(m))*GRID_SIZE);
					njDrawSprite3D	( &sprite, 5-occupied, NJD_SPRITE_SCALE  );
				}
			}
		}
		else
		{
			occupied=0;
		}
	}


	sprite.p.y		=	2.f; 
	sprite.p.x		=	(float)(curi*GRID_SIZE); 
	sprite.p.z		=	(float)(curj*GRID_SIZE); 
	njDrawSprite3D	( &sprite, cursor, NJD_SPRITE_SCALE | NJD_SPRITE_ALPHA );

}


/*--------------------------------------------------------------------------
 
  int	findfirstslot( void )
 
  Parameters:

  Returns:
 
  Notes:
	Finds the first free slot in the buildings instance database
 
  --------------------------------------------------------------------------*/

int	findfirstslot( void )
{
	int		n;
	for (n=0;n<instance_count;n++)
	{
		if (build_inst[n].id==-1) return n;
	}
	
	return instance_count++;		/* no buildings found */
}



/*--------------------------------------------------------------------------
 
  void placebuild(void)
 
  Parameters:

  Returns:
 
  Notes:
	place the current selected building at the current position

  --------------------------------------------------------------------------*/

void placebuild(void)
{
	Sint8	n,m;
	Uint16		index;
	int		i;

	currentslot		=	i	=	findfirstslot();

	/* create instance */
	build_inst[i].id	=	select_build;
	build_inst[i].i		=	curi;
	build_inst[i].j		=	curj;
	build_inst[i].particleinst		=	0xffff;

	switch(current_orient)
	{
	case 0 :	build_inst[i].flag	=	INST_FLAG_ORIENT0; break;
	case 1 :	build_inst[i].flag	=	INST_FLAG_ORIENT1; break;
	case 2 :	build_inst[i].flag	=	INST_FLAG_ORIENT2; break;
	case 3 :	build_inst[i].flag	=	INST_FLAG_ORIENT3; break;
	}

	/* place instance in map */
	if (buildings[select_build].shadow!=NULL)
	{
		index		=	0;
		while (GetBuildingShadow((Uint8)select_build, &n, &m, index++, current_orient)!=0)
		{
			map.map[curi+(int)n][curj+(int)m].inst	=	i;
			map.map[curi+(int)n][curj+(int)m].gnd	=	0;
		}
		
	}
/*	instance_count++; */
}


/*--------------------------------------------------------------------------
 
  void deletebuild(void)
 
  Parameters:

  Returns:
 
  Notes:
	delete the building at the current position

  --------------------------------------------------------------------------*/

void deletebuild(void)
{
	Sint8	n,m;
	Uint16	inst;
	Uint16		index;
	Uint8	orient;

	inst	=	map.map[curi][curj].inst;
	orient	=	build_inst[inst].flag & INST_FLAG_ORIENT_MASK;
	switch (orient)
	{
	case INST_FLAG_ORIENT0 : orient	=	0; break;
	case INST_FLAG_ORIENT1 : orient	=	1; break;
	case INST_FLAG_ORIENT2 : orient	=	2; break;
	case INST_FLAG_ORIENT3 : orient	=	3; break;
	}

	/* remove instance in map */
	if (buildings[build_inst[inst].id].shadow != NULL)
	{
		index		=	0;
		curi		=	build_inst[inst].i;
		curj		=	build_inst[inst].j;

		while (GetBuildingShadow(build_inst[inst].id, &n, &m, index++, orient)!=0)
		{
			map.map[curi+(int)n][curj+(int)m].inst	=	0xffff;
		}
		
	}

	
	/* delete instance */
	build_inst[inst].id	=	-1;
}


/*--------------------------------------------------------------------------
 
  int	LEVELEDIT_Main()
 
  Parameters:

  Returns:
 
  Notes:
	Main routine for level editor

  --------------------------------------------------------------------------*/

int	LEVELEDIT_Main()
{
	NJS_ARGB	argb;

#ifndef USING_SET4
	njPrintC(NJM_LOCATION(2,1),"FUTURISTIC : T. SZIRTES / SEGA EUROPE  v.02/3/98");
	njPrintC(NJM_LOCATION(2,2),"************** LEVEL EDITING MODE **************");
	
	njPrintC(NJM_LOCATION(2,4),"CURSOR : ");
	njPrintD(NJM_LOCATION(11,4),curi,3);
	njPrintC(NJM_LOCATION(15,4),",");
	njPrintD(NJM_LOCATION(17,4),curj,3);
	njPrintC(NJM_LOCATION(2,6),"MODE:");
	njPrintD(NJM_LOCATION(2,8),currentslot,3);
#endif
	njSetConstantAttr	( 0xffffffff, NJD_FILTER_POINT | NJD_FLAG_USE_ALPHA ); 
#ifndef	USING_SET4
	per1 = njGetPeripheral(NJD_PORT_SYSKEYBOARD);
#endif
	/* screen coord chase grid coord */
	if (scrx<(curi*GRID_SIZE)) scrx+=16;
	if (scrx>(curi*GRID_SIZE)) scrx-=16;
	if (scry<(curj*GRID_SIZE)) scry+=16;
	if (scry>(curj*GRID_SIZE)) scry-=16;

	/* move and bound check */
	if (scrx==(curi*GRID_SIZE) && scry==(curj*GRID_SIZE)) 
	{
		if (per1->on & NJD_DGT_KL)	{if (curi<127) curi++;}
		if (per1->on & NJD_DGT_KR)	{if (curi>001) curi--;}
		if (per1->on & NJD_DGT_KU)	{if (curj<127) curj++;}
		if (per1->on & NJD_DGT_KD)	{if (curj>001) curj--;}
	}

	switch(mode)
	{
	case MODE_PLACE :	
#ifndef USING_SET4
			njPrintC(NJM_LOCATION(8,6),"PLACE"); 
		njPrintC(NJM_LOCATION(16,6),"SELECT BUILDING:");
		njPrintH(NJM_LOCATION(35,6),select_build,2);
		njPrintC(NJM_LOCATION(16,7),"SELECT ORIENT:");
		njPrintH(NJM_LOCATION(35,7),current_orient,2);
#endif
		if((per1->on & NJD_DGT_TX) && !(oldon & NJD_DGT_TX)) 
		{
			if (select_build>0)				select_build--;
		}
		if((per1->on & NJD_DGT_TY) && !(oldon & NJD_DGT_TY)) 
		{
			if (select_build<MAX_BUILDINGS)	select_build++;
		}
		if((per1->on & NJD_DGT_TB) && !(oldon & NJD_DGT_TB))
		{
			if (occupied!=1) placebuild();
		}
		if((per1->on & NJD_DGT_TC) && !(oldon & NJD_DGT_TC))
		{
			current_orient++;
			if (current_orient==4) current_orient=0;
		}
		break;

	case MODE_DELETE :	
		njPrintC(NJM_LOCATION(8,6),"DELETE");
		if((per1->on & NJD_DGT_TB) && !(oldon & NJD_DGT_TB))
		{
			if (occupied==1) deletebuild();
		}
		break;
	case MODE_SAVE :	njPrintC(NJM_LOCATION(8,6),"SAVE"); break;
	}

	/* cycle mode */
	if ((per1->on & NJD_DGT_TZ) && !(oldon & NJD_DGT_TZ))
	{
		mode++;
		if(mode>MODE_SAVE) mode=0;
	}

	/* set camera view */
	camera_MoveTo		(&mycam, (float)scrx, 1400.f, (float)scry-50.f);
	camera_LookAt		(&mycam, (float)scrx, 0.f, (float)scry );
	camera_Perspective	(100);				
	camera_View			(&mycam);
	njClearMatrix		();

	/* blink cursor */
	blink++;
	if(blink>32) 
	{
		blink=0;
		cursor	=	(cursor+1)&1;
	}
	
	/* display buildings */
/*	use a constant material	 */
	njControl3D			( NJD_CONTROL_3D_CONSTANT_ATTR |
						  NJD_CONTROL_3D_CONSTANT_MATERIAL |
						  NJD_CONTROL_3D_ENABLE_ALPHA );
	argb.a	=	0.6f;
	argb.r	=	argb.g	=	argb.b	=	1.0f;
	njSetConstantMaterial	( &argb );	
	DISPLAY_Map			( &map, 1 );
	njControl3D			( NJD_CONTROL_3D_CONSTANT_ATTR |
						  NJD_CONTROL_3D_ENABLE_ALPHA );

	/* display editor information */
	DisplayEditGrid(mode);

	/* check exit */
	if ((per1->on & NJD_DGT_TA) && !(oldon & NJD_DGT_TA))
	{
		njPrintC(NJM_LOCATION(10,10)," SAVING MAP ");
#ifndef	USING_SET4
		MAP_Save("d:\\future\\image\\empty.bin");
		BLDLIGHTS_AnalysisMap();
#endif
		njSetConstantAttr	( 0xffffffff, NJD_FILTER_BILINEAR ); 
		return NORMAL;
	} 
	else 
	{
		oldon	=	per1->on;
		return LEVEL_EDIT; 
	}

}
 