// draw.m

#include "bsp5.h"
#import <appkit/appkit.h>

qboolean		draw_windowup;

id			window_i, view_i;

/*
===============
Draw_OpenWindow

Opens a window of a reasonable size and stores scaling values
based on the mins / maxs collected so far
===============
*/
void Draw_OpenWindow (void)
{
	NXPoint		minpt, maxpt;
	NXSize		size;
	double		big, scale;
	NXScreen	const *screens;
	int			screencount;
	NXRect		content;

	if (!NXApp)
		NXApp = [Application new];
		
	[NXApp getScreens:&screens count:&screencount];
	
	minpt.x = brushset->mins[0] + brushset->mins[1]/2 - 512;
	minpt.y = brushset->mins[2] + brushset->mins[1]/2 - 512;
	maxpt.x = brushset->maxs[0] + brushset->maxs[1]/2 + 512;
	maxpt.y = brushset->maxs[2] + brushset->maxs[1]/2 + 512;
	
	size.width = maxpt.x - minpt.x;
	size.height = maxpt.y - minpt.y;
	
	content.origin.x = 0;
	content.origin.y = 0;

	big = MAX(size.width,size.height);
	if (screencount > 1)
		scale = 1280/big;
	else
		scale = 512/big;

	content.size.width = size.width * scale;
	content.size.height = size.height * scale;
		
	window_i =
	[[Window alloc]
		initContent:	&content
		style:			NX_TITLEDSTYLE
		backing:		NX_RETAINED
		buttonMask:		0
		defer:			NO
		screen:			&screens[screencount-1]
	];
	view_i = [window_i contentView];
	
	[view_i
		setDrawSize:	size.width
		:				size.height];
	[view_i 
		setDrawOrigin:	minpt.x 
		: 				minpt.y];
	
	[window_i display];
	[window_i orderFront: nil];
	
	[view_i lockFocus];
	PSsetgray (NX_BLACK);	
	PSsetlinewidth (0.1);
	NXPing ();
}

/*
===============
Draw_Open2D

Opens a window of a reasonable size and stores scaling values
based on the mins / maxs collected so far
===============
*/
void Draw_Open2D (void)
{
	NXPoint		minpt, maxpt;
	NXSize		size;
	double		big, scale;
	NXScreen	const *screens;
	int			screencount;
	NXRect		content;

	if (!NXApp)
		NXApp = [Application new];
		
	[NXApp getScreens:&screens count:&screencount];
	
	minpt.x = brushset->mins[0] + brushset->mins[1]/2 - 512;
	minpt.y = brushset->mins[2] + brushset->mins[1]/2 - 512;
	maxpt.x = brushset->maxs[0] + brushset->maxs[1]/2 + 512;
	maxpt.y = brushset->maxs[2] + brushset->maxs[1]/2 + 512;
	
	size.width = maxpt.x - minpt.x;
	size.height = maxpt.y - minpt.y;
	
	content.origin.x = 0;
	content.origin.y = 0;

	big = MAX(size.width,size.height);
	if (screencount > 1)
		scale = 1280/big;
	else
		scale = 512/big;

	content.size.width = size.width * scale;
	content.size.height = size.height * scale;
		
	window_i =
	[[Window alloc]
		initContent:	&content
		style:			NX_TITLEDSTYLE
		backing:		NX_RETAINED
		buttonMask:		0
		defer:			NO
		screen:			&screens[screencount-1]
	];
	view_i = [window_i contentView];
	
	[view_i
		setDrawSize:	size.width
		:				size.height];
	[view_i 
		setDrawOrigin:	minpt.x 
		: 				minpt.y];
	
	[window_i display];
	[window_i orderFront: nil];
	
	[view_i lockFocus];
	PSsetgray (NX_BLACK);	
	PSsetlinewidth (0.1);
	NXPing ();
}

/*
================
Draw_CheckWindow
================
*/
void Draw_CheckWindow (void)
{
	if (draw_windowup)
		return;
		
	draw_windowup = true;
	
	Draw_OpenWindow ();
}

void PSmoveto3 (vec3_t pt)
{
	PSmoveto (pt[0]+pt[1]/2, pt[2]+pt[1]/2);
}

void PSlineto3 (vec3_t pt)
{
	PSlineto (pt[0]+pt[1]/2, pt[2]+pt[1]/2);
}

/*
============
Draw_DrawFace
============
*/
void Draw_DrawFace (face_t *f)
{
	int		i;
	double	*pt;
	
	if (!drawflag)
		return;
	Draw_CheckWindow ();		// bring up window if nor allready up
	
	pt = f->pts[f->numpoints-1];
	PSmoveto (pt[0]+pt[1]/2, pt[2]+pt[1]/2);
	pt = f->pts[0];
	for (i=0 ; i<f->numpoints ; i++, pt+= 3)
		PSlineto (pt[0]+pt[1]/2, pt[2]+pt[1]/2);
	
	PSstroke ();
	NXPing ();
}


/*
============
Draw_ClearWindow
============
*/
void Draw_ClearWindow (void)
{
	NXRect	b;
	
	if (!drawflag)
		return;
	Draw_CheckWindow ();		// bring up window if nor allready up
	[view_i getBounds: &b];
	NXEraseRect (&b);
	NXPing ();
}

/*
============
Draw_Set*
============
*/
void Draw_SetRed (void)
{
	if (!NXApp)
		return;
	PSsetrgbcolor (1.0,0,0);	
}

void Draw_SetGrey (void)
{
	if (!NXApp)
		return;
	PSsetrgbcolor (0.7,0.7,0.7);
}

void Draw_SetBlack (void)
{
	if (!NXApp)
		return;
	PSsetrgbcolor (0,0,0);
}


void Draw_SetColor (int c)
{
	switch (c&7)
	{
	case 0:
		PSsetrgbcolor (0,0,0);
		break;
	case 1:
		PSsetrgbcolor (0,0,1);
		break;
	case 2:
		PSsetrgbcolor (0,1,0);
		break;
	case 3:
		PSsetrgbcolor (0,1,1);
		break;
	case 4:
		PSsetrgbcolor (1,0,0);
		break;
	case 5:
		PSsetrgbcolor (1,0,1);
		break;
	case 6:
		PSsetrgbcolor (1,1,0);
		break;
	case 7:
		PSsetrgbcolor (1,1,1);
		break;
	}
}


void DrawPoint (vec3_t v)
{
	if (!drawflag)
		return;
	Draw_CheckWindow ();		// bring up window if nor allready up

	PSarc (v[0]+v[1]/2, v[2]+v[1]/2, 2, 0, 360);
	PSfill ();
	NXPing ();
}


void DrawPortal (portal_t *p)
{
	int		i;
	winding_t	*w;
	
	if (!drawflag)
		return;
	Draw_CheckWindow ();		// bring up window if nor allready up
	w = p->winding;
	PSmoveto3 (w->points[w->numpoints-1]);
	for (i=0 ; i< w->numpoints ; i++)
		PSlineto3 (w->points[i]);

	PSstroke ();
	NXPing ();
}

void FillPortal (portal_t *p)
{
	int		i;
	winding_t	*w;
	
	if (!drawflag)
		return;
	Draw_CheckWindow ();		// bring up window if nor allready up
	w = p->winding;
	PSmoveto3 (w->points[w->numpoints-1]);
	for (i=0 ; i< w->numpoints ; i++)
		PSlineto3 (w->points[i]);

	PSfill ();	
	NXPing ();
}

void DrawLeaf (node_t *l, int color)
{
	portal_t	*p;
	
	if (!drawflag)
		return;
	Draw_CheckWindow ();		// bring up window if nor allready up

	Draw_SetColor (color);
	for (p=l->portals ; p ; )
	{
		FillPortal (p);
		if (p->nodes[0] == l)
			p = p->next[0];
		else
			p = p->next[1];
	}
	
	Draw_SetColor (0);
	for (p=l->portals ; p ; )
	{
		DrawPortal (p);
		if (p->nodes[0] == l)
			p = p->next[0];
		else
			p = p->next[1];
	}
}

void DrawBrush (brush_t *b)
{
	face_t	*f;
	
	for (f=b->faces ; f ; f=f->next)
		Draw_DrawFace (f);
}


void DrawWinding (winding_t *w)
{
	int		i;
	
	if (!drawflag)
		return;
	Draw_CheckWindow ();		// bring up window if nor allready up

	Draw_SetColor (2);
	PSmoveto3 (w->points[w->numpoints-1]);
	for (i=0 ; i<w->numpoints ; i++)
		PSlineto3 (w->points[i]);
	PSfill ();
	
	Draw_SetColor (0);
	PSmoveto3 (w->points[w->numpoints-1]);
	for (i=0 ; i<w->numpoints ; i++)
		PSlineto3 (w->points[i]);
	PSstroke ();

	Draw_SetColor (0);
	for (i=0 ; i<w->numpoints ; i++)
		DrawPoint (w->points[i]);
	NXPing ();
}

void DrawTri (vec3_t p1, vec3_t p2, vec3_t p3)
{
	if (!drawflag)
		return;
	Draw_CheckWindow ();		// bring up window if not allready up

	Draw_SetColor (3);
	PSmoveto3 (p1);
	PSlineto3 (p2);
	PSlineto3 (p3);
	PSlineto3 (p1);
	PSfill ();
	
	Draw_SetColor (0);
	PSmoveto3 (p1);
	PSlineto3 (p2);
	PSlineto3 (p3);
	PSlineto3 (p1);
	PSstroke ();

	NXPing ();
}


