// ImageGrinderView.cpp : implementation of the CImageGrinderView class
//

#include "stdafx.h"
#include "ImageGrinder.h"

#include "ImageGrinderDoc.h"
#include "ImageGrinderView.h"
#include "GridOptions.h"
#include "ColorProps.h"
#include "POutOpts.h"
#include <Compost\TexturePool.hpp>
#include <Process.h>
#include "ExpAllOpts.h"


extern CImageGrinderApp theApp;

/////////////////////////////////////////////////////////////////////////////
// CImageGrinderView

IMPLEMENT_DYNCREATE(CImageGrinderView, CView)

BEGIN_MESSAGE_MAP(CImageGrinderView, CView)
//{{AFX_MSG_MAP(CImageGrinderView)
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEWHEEL()
ON_WM_SIZE()
ON_WM_RBUTTONDOWN()
ON_WM_RBUTTONUP()
ON_COMMAND(ID_EDIT_ADDFEATURE, OnEditAddfeature)
ON_COMMAND(ID_EDIT_DELETEFEATURE, OnEditDeletefeature)
ON_COMMAND(ID_VIEW_DEPTHVIEW, OnViewDepthview)
ON_UPDATE_COMMAND_UI(ID_VIEW_DEPTHVIEW, OnUpdateViewDepthview)
ON_COMMAND(ID_TEST_TEST1, OnTestTest1)
ON_COMMAND(ID_TEST_XSNAP_1, OnTestXsnap1)
ON_COMMAND(ID_TEST_XSNAP_2, OnTestXsnap2)
ON_COMMAND(ID_TEST_XSNAP_8, OnTestXsnap8)
ON_COMMAND(ID_TEST_XSNAP_16, OnTestXsnap16)
ON_COMMAND(ID_TEST_XSNAP_4, OnTestXsnap4)
ON_UPDATE_COMMAND_UI(ID_TEST_XSNAP_1, OnUpdateTestXsnap1)
ON_UPDATE_COMMAND_UI(ID_TEST_XSNAP_16, OnUpdateTestXsnap16)
ON_UPDATE_COMMAND_UI(ID_TEST_XSNAP_2, OnUpdateTestXsnap2)
ON_UPDATE_COMMAND_UI(ID_TEST_XSNAP_4, OnUpdateTestXsnap4)
ON_UPDATE_COMMAND_UI(ID_TEST_XSNAP_8, OnUpdateTestXsnap8)
ON_COMMAND(ID_VIEW_GRIDOPTIONS, OnViewGridoptions)
ON_WM_LBUTTONDBLCLK()
ON_COMMAND(ID_EDIT_MAKEUNIQUE, OnEditMakeunique)
ON_COMMAND(ID_VIEW_GRID, OnViewGrid)
ON_UPDATE_COMMAND_UI(ID_VIEW_GRID, OnUpdateViewGrid)
ON_COMMAND(ID_VIEW_HELPERS, OnViewHelpers)
ON_UPDATE_COMMAND_UI(ID_VIEW_HELPERS, OnUpdateViewHelpers)
ON_COMMAND(ID_VIEW_WIREMODE, OnViewWiremode)
ON_UPDATE_COMMAND_UI(ID_VIEW_WIREMODE, OnUpdateViewWiremode)
ON_COMMAND(ID_VIEW_COLORPROPERTIES, OnViewColorproperties)
ON_COMMAND(ID_EDIT_LOCKSELECTION, OnEditLockselection)
ON_COMMAND(ID_EDIT_UNLOCKALL, OnEditUnlockall)
ON_WM_CHAR()
ON_WM_KEYDOWN()
ON_COMMAND(ID_EDIT_UNGROUPSELECTION, OnEditUngroupselection)
ON_COMMAND(ID_EDIT_GROUPSELECTION, OnEditGroupselection)
ON_COMMAND(ID_VIEW_ZOOMIN, OnViewZoomin)
ON_COMMAND(ID_VIEW_ZOOMOUT, OnViewZoomout)
ON_COMMAND(ID_EDIT_GLOBALTEXTURES, OnEditGlobaltextures)
ON_COMMAND(ID_EDIT_LOCALTEXTURES, OnEditLocaltextures)
ON_COMMAND(ID_FILE_EXPORT_PARTIALOUTPUT, OnFileExportPartialoutput)
ON_COMMAND(ID_FILE_EXPORT_MAPTEXTUREINDEX, OnFileExportMaptextureindex)
ON_COMMAND(ID_FILE_EXPORT_ALL, OnFileExportAll)
	ON_COMMAND(ID_VIEW_MANUALUPDATE, OnViewManualupdate)
	ON_UPDATE_COMMAND_UI(ID_VIEW_MANUALUPDATE, OnUpdateViewManualupdate)
	ON_COMMAND(ID_VIEW_UPDATE, OnViewUpdate)
	ON_COMMAND(ID_TEST_RENDERLOWRES, OnTestRenderlowres)
	ON_UPDATE_COMMAND_UI(ID_TEST_RENDERLOWRES, OnUpdateTestRenderlowres)
	ON_COMMAND(ID_OPTIONS_FORCESINGLEPROC, OnOptionsForcesingleproc)
	ON_UPDATE_COMMAND_UI(ID_OPTIONS_FORCESINGLEPROC, OnUpdateOptionsForcesingleproc)
	ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
	ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo)
	ON_COMMAND(ID_EDIT_REDO, OnEditRedo)
	ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, OnUpdateEditRedo)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CImageGrinderView construction/destruction

CImageGrinderView::CImageGrinderView()
{
	ProcRunning=0;
	ProcInfo=NULL;
	ProcInfo=new CComposeInfo[16];
	DetectProcs();
	Init();
}

CImageGrinderView::Init()
{
	
	OldPointSel=OldPointView=ViewOrg=CPoint(0,0);
	ViewScale=1;
	WireMode=true;
	Helpers=true;
	DragFlag=false;
	CanCopy=false;
	Grid=true;
	HanFlag=HF_NONE;
	HanFet=NULL;
	ViewMode=0;
	PixelSpace=256;
	RenderLowRes=false;
	FirstMove=false;

}

void CImageGrinderView::ForceSingleProc()
{
	sysinfo.dwNumberOfProcessors=1;	
}

void CImageGrinderView::DetectProcs()
{
	GetSystemInfo(&sysinfo);
	if(sysinfo.dwNumberOfProcessors>=16)  sysinfo.dwNumberOfProcessors=16;
}

int	CImageGrinderView::ProcCount()
{
	SYSTEM_INFO sinf;
	GetSystemInfo(&sinf);
	return sinf.dwNumberOfProcessors;
}


CImageGrinderView::~CImageGrinderView()
{
	//	BackBuf.DeleteObject();
	//delete ProcInfo;
}

BOOL CImageGrinderView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs
	
	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CImageGrinderView drawing

void CImageGrinderView::OnDraw(CDC* pDC)
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	ClearWindow();
	UpdateWindow();
}

/////////////////////////////////////////////////////////////////////////////
// CImageGrinderView diagnostics

#ifdef _DEBUG
void CImageGrinderView::AssertValid() const
{
	CView::AssertValid();
}

void CImageGrinderView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CImageGrinderDoc* CImageGrinderView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CImageGrinderDoc)));
	return (CImageGrinderDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CImageGrinderView message handlers

BOOL CImageGrinderView::OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point) 
{
	
	return CView::OnDrop(pDataObject, dropEffect, point);
}

DROPEFFECT CImageGrinderView::OnDragOver(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point) 
{
	
	return CView::OnDragOver(pDataObject, dwKeyState, point);
}

DROPEFFECT CImageGrinderView::OnDragEnter(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point) 
{
	
	return CView::OnDragEnter(pDataObject, dwKeyState, point);
}

BOOL CImageGrinderView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) 
{
	
	return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
}



void CImageGrinderView::UpdateWindow()
{
	CenterBitmap();
	
	CDC  *pDC,memDC;
	pDC=GetDC();
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	CRect crct;
	GetClientRect(&crct);
	
	
	//    memDC.CreateCompatibleDC(pDC);
	//    memDC.SelectObject(&BackBuf);
	CPoint BltLoc,AdjV;
	int sx,sy;
	sy=pDoc->FGrid->GetRows()*pDoc->FGrid->GetGridSize();
	sx=pDoc->FGrid->GetColumns()*pDoc->FGrid->GetGridSize();
	AdjV=ViewOrg;
	AdjV.x/=ViewScale;
	AdjV.y/=ViewScale;
	BltLoc=crct.CenterPoint()-AdjV;
	pDC->SetStretchBltMode(COLORONCOLOR);
	//	pDC->StretchBlt(BltLoc.x,BltLoc.y,sx/ViewScale,sy/ViewScale,&memDC,0,0,sx,sy,SRCCOPY);
	CRect dst,src;
	dst.right=dst.left=BltLoc.x;
	dst.bottom=dst.top=BltLoc.y;
	dst.right+=sx/ViewScale;
	dst.bottom+=sy/ViewScale;
	
	src.right=src.left=0;
	src.bottom=src.top=0;
	src.right+=sx;
	src.bottom+=sy;
	
	
	if(dst.left<0)
	{
		src.left+=-dst.left*ViewScale;
		dst.left=0;
	}
	
	if(dst.top<0)
	{
		src.top+=-dst.top*ViewScale;
		dst.top=0;
	}
	
	if(dst.right>crct.Width())
	{
		src.right-=(dst.right-crct.Width())*ViewScale;
		dst.right=crct.Width();
	}
	
	
	if(dst.bottom>crct.Height())
	{
		src.bottom-=(dst.bottom-crct.Height())*ViewScale;
		dst.bottom=crct.Height();
	}
	
	BYTE *bpt=CompleteImage.Lock();
	bpt+=src.top*CompleteImage.GetWidth()*(CompleteImage.GetBpp()>>3);
	src.bottom-=src.top;
	src.top=0;
	
	BITMAPINFO       binf;
	ZeroMemory(&binf,sizeof(binf));
	binf.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
	binf.bmiHeader.biWidth=CompleteImage.GetWidth(); 
	binf.bmiHeader.biHeight=-src.Height();
	binf.bmiHeader.biPlanes=1;
	binf.bmiHeader.biBitCount=CompleteImage.GetBpp();
	binf.bmiHeader.biCompression=BI_RGB;
	int res;
	
	res=StretchDIBits(*pDC,
		dst.left,dst.top,dst.Width(),dst.Height(),
		src.left,0,src.Width(),src.Height(),
		bpt,&binf,DIB_RGB_COLORS,SRCCOPY);
	
	binf.bmiHeader.biHeight+=src.top;
	
	CRect drct;
	
	/*
	SetDIBitsToDevice(*pDC,
	dst.left,dst.top,dst.Width(),dst.Height(),
	src.left,0,0,dst.Height(),
	bpt,&binf,DIB_RGB_COLORS);
	*/
	Verify(res!=GDI_ERROR);
	
//	PreviewWin->UpdateWindow();	
	//	memDC.DeleteDC();
	
	if(Helpers)
	{
		pDC->SelectObject(GetStockObject(NULL_BRUSH));
		
		
		if(Grid)	
		{
			pDC->SelectObject(&GridPen);
			
			CPoint tpnt=pDoc->NewPlacePoint;
			DataToScreen(&tpnt);
			pDC->Ellipse(tpnt.x-5,tpnt.y-5,tpnt.x+5,tpnt.y+5);
			
			int x,y;
			CPoint tmppnt;
			for(y=0;y<pDoc->FGrid->GetRows()*pDoc->FGrid->GetGridSize() ;y+=PixelSpace)
			{
				tmppnt.x=0;
				tmppnt.y=y;
				DataToScreen(&tmppnt);
				pDC->MoveTo(tmppnt);	
				tmppnt.x=pDoc->FGrid->GetColumns()*pDoc->FGrid->GetGridSize();
				tmppnt.y=y;
				DataToScreen(&tmppnt);
				pDC->LineTo(tmppnt);	
			}
			
			for(x=0;x<pDoc->FGrid->GetColumns()*pDoc->FGrid->GetGridSize() ;x+=PixelSpace)
			{
				tmppnt.x=x;
				tmppnt.y=0;
				DataToScreen(&tmppnt);
				pDC->MoveTo(tmppnt);	
				tmppnt.x=x;
				tmppnt.y=pDoc->FGrid->GetRows()*pDoc->FGrid->GetGridSize();
				DataToScreen(&tmppnt);
				pDC->LineTo(tmppnt);	
			}
		}// end of if Grid	
		
		
		const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
		int count;
		int CurFet;
		
		FList=pDoc->FGrid->GetUniqueFeatureInstances(count);
		for(CurFet=0;CurFet<count;CurFet++)
		{
			pDC->SelectObject(GetStockObject(NULL_BRUSH));
			if(WireMode)
			{
				if(((Compost::Tool_Feature *)(*FList)[CurFet]->feature)->StatFlags&FF_HIGHLIGHTED)
					pDC->SelectObject(&WireHLPen);
				else
					pDC->SelectObject(&WirePen);
				
				drct.top=(*FList)[CurFet]->feature_z_pos;
				drct.left=(*FList)[CurFet]->feature_x_pos;
				drct.bottom=drct.top+(*FList)[CurFet]->feature->GetFeatureHeight()+1;
				drct.right=drct.left+(*FList)[CurFet]->feature->GetFeatureWidth()+1;
				DataToScreen(&drct);
				pDC->Rectangle(&drct);
				
				
			}// end of wireframe mode	
			
			
			if((*FList)[CurFet]->StatFlags&FIF_SELECTED)
			{
				pDC->SelectObject(&PenSelected);
				pDC->SelectObject(GetStockObject(NULL_BRUSH));
				CPoint tl,tr,bl,br,ct;
				bl.x=tl.x=(*FList)[CurFet]->feature_x_pos;
				tr.y=tl.y=(*FList)[CurFet]->feature_z_pos;
				tr.x=br.x=(*FList)[CurFet]->feature_x_pos+(*FList)[CurFet]->feature->GetFeatureWidth()+1;
				bl.y=br.y=(*FList)[CurFet]->feature_z_pos+(*FList)[CurFet]->feature->GetFeatureHeight()+1;
				ct.x=tl.x+(*FList)[CurFet]->feature->GetFeatureWidth()/2;
				ct.y=tl.y+(*FList)[CurFet]->feature->GetFeatureHeight()/2;
				// Draw Selected Box
				CRect rct;
				rct.SetRect(tl,br);
				DataToScreen(&rct);
				pDC->Rectangle(&rct);
				
				pDC->SelectObject(&SolidSel);
				rct.left=rct.top=-HANDLESIZE/2;
				rct.right=rct.bottom=HANDLESIZE/2;
				rct.OffsetRect(ct);
				DataToScreen(&rct);
				pDC->Rectangle(&rct);
				
				pDC->SelectObject(&GreenBrush);
				// Draw Streching handles
				//	rct.left=rct.top=-HANDLESIZE/2; rct.right=rct.bottom=HANDLESIZE/2;
				rct.left=rct.top=0; rct.right=rct.bottom=HANDLESIZE;
				rct.OffsetRect(tl);
				DataToScreen(&rct);
				pDC->Rectangle(&rct);
				
				rct.left=0;
				rct.top=-HANDLESIZE; 
				rct.right=HANDLESIZE;
				rct.bottom=0;
				
				rct.OffsetRect(bl);
				DataToScreen(&rct);
				pDC->Rectangle(&rct);
				
				rct.left=rct.top=-HANDLESIZE; rct.right=rct.bottom=0;
				rct.OffsetRect(br);
				DataToScreen(&rct);
				pDC->Rectangle(&rct);
				
				rct.left=-HANDLESIZE;
				rct.top=0; 
				rct.right=0;
				rct.bottom=HANDLESIZE;
				rct.OffsetRect(tr);
				DataToScreen(&rct);
				pDC->Rectangle(&rct);
				
				rct.left=-HANDLESIZE/2;
				rct.top=0; 
				rct.right=HANDLESIZE/2;
				rct.bottom=HANDLESIZE;
				rct.OffsetRect(tl.x+(tr.x-tl.x)/2,tl.y);
				DataToScreen(&rct);
				pDC->Rectangle(&rct);
				
				rct.left=-HANDLESIZE/2;
				rct.top=-HANDLESIZE; 
				rct.right=HANDLESIZE/2;
				rct.bottom=0;
				rct.OffsetRect(bl.x+(br.x-bl.x)/2,bl.y);
				DataToScreen(&rct);
				pDC->Rectangle(&rct);
				
				rct.left=0;
				rct.top=-HANDLESIZE/2; 
				rct.right=HANDLESIZE;
				rct.bottom=HANDLESIZE/2;
				rct.OffsetRect(tl.x,tl.y+(bl.y-tl.y)/2);
				DataToScreen(&rct);
				pDC->Rectangle(&rct);
				
				rct.left=-HANDLESIZE;
				rct.top=-HANDLESIZE/2; 
				rct.right=0;
				rct.bottom=HANDLESIZE/2;
				rct.OffsetRect(tr.x,tl.y+(br.y-tr.y)/2);
				DataToScreen(&rct);
				pDC->Rectangle(&rct);
				
			}	// end of idf selected
			
			
		}// end of feature loop
		
		
	}//End of if Helpers
	
	
	
	if(DragFlag)
	{
		pDC->SelectObject(&BoxPen);
		pDC->SelectObject(GetStockObject(NULL_BRUSH));
		pDC->Rectangle(&DragRect);
	}
	
	
	ReleaseDC(pDC);
}

void CImageGrinderView::OnInitialUpdate() 
{
	
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	CreatePens();
	
	CDC *pDC;
	pDC=GetDC();
	/*
	BOOL bres;
	
	  bres=BackBuf.CreateCompatibleBitmap(pDC,
	  pDoc->FGrid->GetColumns()*pDoc->FGrid->GetGridSize(),pDoc->FGrid->GetRows()*pDoc->FGrid->GetGridSize());
	  Verify(bres);
	*/
	CompleteImage.CreateBlank(pDoc->FGrid->GetColumns()*pDoc->FGrid->GetGridSize(),pDoc->FGrid->GetRows()*pDoc->FGrid->GetGridSize(),ITYPE_RGB,24);
	
	/*
	bres=BackBuf.CreateBitmap(pDoc->FGrid->GetColumns()*pDoc->FGrid->GetGridSize(),pDoc->FGrid->GetRows()*pDoc->FGrid->GetGridSize(),3,32,NULL);
	Verify(bres);
	*/
	ViewOrg.x=pDoc->FGrid->GetColumns()*pDoc->FGrid->GetGridSize()/2;
	ViewOrg.y=pDoc->FGrid->GetRows()*pDoc->FGrid->GetGridSize()/2;
	ReleaseDC(pDC);
	
	/*
	int  nobmp=(pDoc->FGrid->GetColumns()>>8)*(pDoc->FGrid->GetRows()>>8);
	ImageBuf=new CBitmap[nobmp];
	for(int i=0;i<nobmp;i++)
	{
	ImageBuf[i].CreateCompatibleBitmap(pDC,256,256);
	}
	*/
	
	ComposeBackBuffer();	
	UpdatePPoint();
	
	CView::OnInitialUpdate();
}


BOOL CImageGrinderView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) 
{
	if(zDelta>0) 
	{
	/*
	ViewScale*=2;
	if(ViewScale>2) ViewScale=2;
	ClearWindow();
		*/
	}
	
	if(zDelta<0) 
	{
		//		ViewScale/=2;
	}
	
	if(ViewScale<=1) ViewScale=1;
	
	//	UpdateWindow();
	
	return CView::OnMouseWheel(nFlags, zDelta, pt);
}

void CImageGrinderView::CenterBitmap()
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	CRect crct;
	GetClientRect(&crct);
	CPoint BltLoc,AdjV;
	AdjV=ViewOrg;
	AdjV.x/=ViewScale;
	AdjV.y/=ViewScale;
	BltLoc=crct.CenterPoint()-AdjV;
	int sx,sy;
	sy=pDoc->FGrid->GetRows()*pDoc->FGrid->GetGridSize();
	sx=pDoc->FGrid->GetColumns()*pDoc->FGrid->GetGridSize();
	
	if(crct.Width()>pDoc->FGrid->GetColumns()*pDoc->FGrid->GetGridSize()/ViewScale)
		ViewOrg.x=pDoc->FGrid->GetColumns()*pDoc->FGrid->GetGridSize()/2;
	else
	{
		if(BltLoc.x>0) ViewOrg.x+=BltLoc.x*ViewScale;
		if((BltLoc.x+(sx/ViewScale))<crct.Width()) ViewOrg.x-=crct.Width()-(BltLoc.x+(sx/ViewScale));
	}
	
	if(crct.Height()>pDoc->FGrid->GetRows()*pDoc->FGrid->GetGridSize()/ViewScale)
		ViewOrg.y=pDoc->FGrid->GetRows()*pDoc->FGrid->GetGridSize()/2;
	else
	{
		if(BltLoc.y>0) ViewOrg.y+=BltLoc.y*ViewScale;
		if((BltLoc.y+(sy/ViewScale))<crct.Height()) 
			ViewOrg.y-=crct.Height()-(BltLoc.y+(sy/ViewScale));
	}
}

void CImageGrinderView::OnSize(UINT nType, int cx, int cy) 
{
	CView::OnSize(nType, cx, cy);
	
}

void CImageGrinderView::ClearWindow()
{
	CDC *pDC;
	pDC=GetDC();
	
	CRect crct;
	GetClientRect(&crct);
	pDC->BitBlt(0,0,crct.Width(),crct.Height(),NULL,0,0,BLACKNESS);
	
	ReleaseDC(pDC);
}

void CImageGrinderView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) 
{
	
	ComposeBackBuffer();	
	UpdateWindow();
	
}

void CImageGrinderView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	OrgPoint=point;
	SetCapture();
	FirstMove=false;

   	CPoint tpnt;
	tpnt=point;
	ScreenToData(&tpnt);
	OldPointSel=point;
	
	bool inrgn=pDoc->InSelectedRegion(tpnt);

	short AltKey=GetAsyncKeyState(VK_MENU);
	
	if(AltKey)
	{
	pDoc->AddFeature(tpnt.x,tpnt.y);
	}

	
	if(!inrgn || nFlags&MK_CONTROL)
	{
		DragFlag=true;
	}
	else
	{
		if(inrgn)
		{
			if(pDoc->IsOnSelectHandle(tpnt))
			{
				UpdateWindow();
			}
			else
				HanFlag=pDoc->IsOnScaleHandle(tpnt,HanFet=pDoc->GetTopSelected(tpnt));
			CanCopy=true;
			
		}
	}
	
	//	UpdateWindow();
	
	CView::OnLButtonDown(nFlags, point);
}

void CImageGrinderView::OnLButtonUp(UINT nFlags, CPoint point) 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	
	
   	CPoint tpnt;
	tpnt=point;
	ScreenToData(&tpnt);
	OldPointSel=point;
	
	{
		if(point==OrgPoint)
		{	
			bool inrgn=pDoc->InSelectedRegion(tpnt);
			
			if(inrgn)
			{
				
				
			}
			
			
			if(nFlags&MK_SHIFT)
			{
				pDoc->AddSelection(tpnt);
			}
			else
			{
				if(nFlags&MK_CONTROL)
				{
					pDoc->SubSelection(tpnt);
				}
				else
				{
					if(!inrgn)
						pDoc->NewSelection(tpnt);
				}
			}
		}	
		else
		{
			if(DragFlag)
			{
				CRect prct;
				prct=DragRect;
				ScreenToData(&prct);
				
				if(nFlags&MK_SHIFT)
				{
					pDoc->AddSelection(prct);
				}
				else
				{
					if(nFlags&MK_CONTROL)
					{
						pDoc->SubSelection(prct);
					}
					else
					{
						pDoc->NewSelection(prct);
					}
				}
				
			}
		}
	}
	HanFlag=HF_NONE;
	HanFet=NULL;
	DragIn=0;
	
	DragFlag=false;
	ReleaseCapture();
	
	CView::OnLButtonUp(nFlags, point);
	pDoc->UpdateAllViews(NULL);
}
void CImageGrinderView::OnRButtonDown(UINT nFlags, CPoint point) 
{
	
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	DragIn=-1;
   	CPoint tpnt;
	tpnt=point;
	ScreenToData(&tpnt);
	
	pDoc->SelectionByList(tpnt);
	
	UpdateWindow();	
	
	CView::OnRButtonDown(nFlags, point);
}

void CImageGrinderView::OnRButtonUp(UINT nFlags, CPoint point) 
{
	
	CView::OnRButtonUp(nFlags, point);
}

void CImageGrinderView::OnMouseMove(UINT nFlags, CPoint point) 
{
	if(DragIn==0) DragIn=1;
	
	
	if(nFlags&MK_LBUTTON)
	{
		CImageGrinderDoc* pDoc = GetDocument();
		ASSERT_VALID(pDoc);
		
		CPoint tpnt;
		tpnt=point;
		ScreenToData(&tpnt);
		
		if(DragFlag)
		{
			DragRect.top=point.y<OrgPoint.y?point.y:OrgPoint.y;
			DragRect.bottom=point.y>OrgPoint.y?point.y:OrgPoint.y;
			DragRect.left=point.x<OrgPoint.x?point.x:OrgPoint.x;
			DragRect.right=point.x>OrgPoint.x?point.x:OrgPoint.x;
		}
		else
		{
			if(HanFlag==HF_NONE)
			{
				if(CanCopy==false  && !(nFlags&MK_SHIFT))
					CanCopy=true;
				
				if(CanCopy==true  && nFlags&MK_SHIFT)
				{
					pDoc->CloneSelection();
					CanCopy=false;
				}
				if(!FirstMove) pDoc->SavePosForUndo();
				FirstMove=true;
				pDoc->OffsetSelection((point.x-OldPointSel.x)*ViewScale,
					(point.y-OldPointSel.y)*ViewScale);
			}	
			else
			{	//Scaleing
				if(HanFlag&HF_BOTTOM)
				{
					if(tpnt.y>HanFet->feature_z_pos)
					{
						if( (tpnt.y-HanFet->feature_z_pos)<=(HanFet->feature->GetFeatureHeight()>>1)&& (HanFet->feature->GetFeatureHeight()>>1)>=8)
						{
							pDoc->SetDrawFlags(HanFet->feature);
							HanFet->feature->SetFeatureHeight(HanFet->feature->GetFeatureHeight()>>1);
							HanFet->feature->ReCalculateScale();
							pDoc->FGrid->RedoFeaturePosition();
							pDoc->SetDrawFlags(HanFet->feature);
						}
						
						if( (tpnt.y-HanFet->feature_z_pos)> HanFet->feature->GetFeatureHeight())
						{
							pDoc->SetDrawFlags(HanFet->feature);
							HanFet->feature->SetFeatureHeight(HanFet->feature->GetFeatureHeight()<<1);
							HanFet->feature->ReCalculateScale();
							pDoc->FGrid->RedoFeaturePosition();
							pDoc->SetDrawFlags(HanFet->feature);
						}
					}
				}
				
				if(HanFlag&HF_RIGHT)
				{
					if(tpnt.x>HanFet->feature_x_pos)
					{
						if( (tpnt.x-HanFet->feature_x_pos)<=(HanFet->feature->GetFeatureWidth()>>1)&& (HanFet->feature->GetFeatureWidth()>>1)>=8)
						{
							pDoc->SetDrawFlags(HanFet->feature);
							HanFet->feature->SetFeatureWidth(HanFet->feature->GetFeatureWidth()>>1);
							HanFet->feature->ReCalculateScale();
							pDoc->FGrid->RedoFeaturePosition();
							pDoc->SetDrawFlags(HanFet->feature);
						}
						
						if( (tpnt.x-HanFet->feature_x_pos)> HanFet->feature->GetFeatureWidth())
						{
							pDoc->SetDrawFlags(HanFet->feature);
							HanFet->feature->SetFeatureWidth(HanFet->feature->GetFeatureWidth()<<1);
							HanFet->feature->ReCalculateScale();
							pDoc->FGrid->RedoFeaturePosition();
							pDoc->SetDrawFlags(HanFet->feature);
						}
					}
				}
				
				if(HanFlag&HF_TOP)
				{
					if( (tpnt.y-HanFet->feature_z_pos)>=(HanFet->feature->GetFeatureHeight()>>1) && (HanFet->feature->GetFeatureHeight()>>1)>=8)
					{
						pDoc->SetDrawFlags(HanFet->feature);
						HanFet->feature->SetFeatureHeight(HanFet->feature->GetFeatureHeight()>>1);
						HanFet->feature_z_pos+=HanFet->feature->GetFeatureHeight();
						HanFet->feature->ReCalculateScale();
						pDoc->FGrid->RedoFeaturePosition();
						pDoc->SetDrawFlags(HanFet->feature);
					}
					
					if( tpnt.y<HanFet->feature_z_pos)
					{
						pDoc->SetDrawFlags(HanFet->feature);
						HanFet->feature_z_pos-=HanFet->feature->GetFeatureHeight();
						HanFet->feature->SetFeatureHeight(HanFet->feature->GetFeatureHeight()<<1);
						HanFet->feature->ReCalculateScale();
						pDoc->FGrid->RedoFeaturePosition();
						pDoc->SetDrawFlags(HanFet->feature);
					}
				}
				
				if(HanFlag&HF_LEFT)
				{
					if( (tpnt.x-HanFet->feature_x_pos)>=(HanFet->feature->GetFeatureWidth()>>1) && (HanFet->feature->GetFeatureWidth()>>1)>=8)
					{
						pDoc->SetDrawFlags(HanFet->feature);
						HanFet->feature->SetFeatureWidth(HanFet->feature->GetFeatureWidth()>>1);
						HanFet->feature_x_pos+=HanFet->feature->GetFeatureWidth();
						HanFet->feature->ReCalculateScale();
						pDoc->FGrid->RedoFeaturePosition();
						pDoc->SetDrawFlags(HanFet->feature);
					}
					
					if( tpnt.x<HanFet->feature_x_pos)
					{
						pDoc->SetDrawFlags(HanFet->feature);
						HanFet->feature_x_pos-=HanFet->feature->GetFeatureWidth();
						HanFet->feature->SetFeatureWidth(HanFet->feature->GetFeatureWidth()<<1);
						HanFet->feature->ReCalculateScale();
						pDoc->FGrid->RedoFeaturePosition();
						pDoc->SetDrawFlags(HanFet->feature);
					}
				}
				
			}
			
			OldPointSel=point;
			ComposeBackBuffer();
		}
		UpdateWindow();
	}
	
	if(nFlags&MK_MBUTTON)
	{
		ViewOrg.x-=(point.x-OldPointView.x)*ViewScale;
		ViewOrg.y-=(point.y-OldPointView.y)*ViewScale;
		OldPointView=point;
		
		UpdatePPoint();
		
		UpdateWindow();
	}
	
	CView::OnMouseMove(nFlags, point);
}



LRESULT CImageGrinderView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	switch(message)
	{
	case WM_MBUTTONDOWN:
		{
			CPoint point;
			point.x = LOWORD(lParam);  // horizontal position of cursor 
			point.y = HIWORD(lParam);  // vertical position of cursor 
			OldPointView=point;
			SetCapture();
		}
		break;
		
	case WM_MBUTTONUP:
		{
			ReleaseCapture();
		}
		break;
	}
	return CView::WindowProc(message, wParam, lParam);
}

void CImageGrinderView::DataToScreen(CPoint *pt)
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	CRect crct;
	GetClientRect(&crct);
	
	*pt-=ViewOrg;
	pt->x/=ViewScale;
	pt->y/=ViewScale;
	*pt+=crct.CenterPoint();
}

void CImageGrinderView::DataToScreen(CRect *pt)
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	CRect crct;
	GetClientRect(&crct);
	CPoint AdjV;
	
	pt->left-=ViewOrg.x;
	pt->right-=ViewOrg.x;
	pt->top-=ViewOrg.y;
	pt->bottom-=ViewOrg.y;
	
	pt->left/=ViewScale;
	pt->right/=ViewScale;
	pt->top/=ViewScale;
	pt->bottom/=ViewScale;
	*pt+=crct.CenterPoint();
	
}

void CImageGrinderView::ScreenToData(CPoint *pt)
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	CRect crct;
	GetClientRect(&crct);
	
	
	*pt-=crct.CenterPoint();
	pt->x*=ViewScale;
	pt->y*=ViewScale;
	*pt+=ViewOrg;
}

void CImageGrinderView::ScreenToData(CRect *pt)
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	CRect crct;
	GetClientRect(&crct);
	CPoint AdjV;
	
	*pt-=crct.CenterPoint();
	pt->left*=ViewScale;
	pt->right*=ViewScale;
	pt->top*=ViewScale;
	pt->bottom*=ViewScale;
	
	pt->left+=ViewOrg.x;
	pt->right+=ViewOrg.x;
	pt->top+=ViewOrg.y;
	pt->bottom+=ViewOrg.y;
	
	
}

void CImageGrinderView::OnEditAddfeature() 
{
	
}

void CImageGrinderView::OnEditDeletefeature() 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	pDoc->DeleteSelected();
	ComposeBackBuffer();
	UpdateWindow();
}


void CImageGrinderView::OnViewDepthview() 
{
	if(ViewMode) ViewMode=0; else ViewMode=1;
	
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	pDoc->SetDrawFlags();
	ComposeBackBuffer();
	UpdateWindow();	
}

void CImageGrinderView::OnUpdateViewDepthview(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(ViewMode!=0);
}




void CImageGrinderView::OnTestTest1() 
{
/*
CImageGrinderDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);

  if(pDoc->FPool==NULL || pDoc->FGrid==NULL) return;
  
	CDC *pDC,memDC;
	pDC=GetDC();
	
	  memDC.CreateCompatibleDC(pDC);
	  memDC.SelectObject(&BackBuf);
	  
		BITMAPINFOHEADER bhd;
		BITMAPINFO       binf;
		bhd.biSize=sizeof(BITMAPINFOHEADER);
		bhd.biWidth=pDoc->FGrid->GetGridSize(); bhd.biHeight=-pDoc->FGrid->GetGridSize();
		bhd.biPlanes=1;
		bhd.biBitCount=24;
		bhd.biCompression=BI_RGB;
		bhd.biSizeImage=0;
		bhd.biClrImportant=0;
		binf.bmiHeader=bhd;
		
		  BYTE *imgdat=(BYTE *)BmpBuf.Lock();
		  
			int row,col;
			for(int j=0;j<100;j++)
			{
			for(row=0;row<pDoc->FGrid->GetRows();row++)
			{
			for(col=0;col<pDoc->FGrid->GetColumns();col++)
			{
			pDoc->FGrid->ComposeGrid(row, col, imgdat, 0, ViewMode);
			}
			}
			}
			
			  for(row=0;row<pDoc->FGrid->GetRows();row++)
			  {
			  for(col=0;col<pDoc->FGrid->GetColumns();col++)
			  {
			  if(!pDoc->FGrid->ComposeGrid(row, col, imgdat, 0, ViewMode))
			  {
			  for(int i=0;i<pDoc->FGrid->GetGridSize()*pDoc->FGrid->GetGridSize()*3;i++)
			  {
			  imgdat[i]=i%pDoc->FGrid->GetGridSize();
			  }
			  
				SetDIBitsToDevice(memDC,col*pDoc->FGrid->GetGridSize(),row*pDoc->FGrid->GetGridSize(),pDoc->FGrid->GetGridSize(),
				pDoc->FGrid->GetGridSize(),0,0,0,pDoc->FGrid->GetGridSize(),imgdat,
				&binf,DIB_RGB_COLORS);  
				
				  pDoc->UpdateList[pDoc->FGrid->GetColumns()*row+col] =false;
				  }
				  }
				  }
				  
					BmpBuf.UnLock();
					memDC.DeleteDC();
					ReleaseDC(pDC);
	*/
}

void CImageGrinderView::OnTestXsnap1() 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	pDoc->SnapMask = 1;	
}

void CImageGrinderView::OnTestXsnap2() 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	pDoc->SnapMask=2;
}

void CImageGrinderView::OnTestXsnap4() 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	pDoc->SnapMask=4;	
}

void CImageGrinderView::OnTestXsnap8() 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	pDoc->SnapMask=8;	
}

void CImageGrinderView::OnTestXsnap16() 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	pDoc->SnapMask=16;	
}

void CImageGrinderView::OnUpdateTestXsnap1(CCmdUI* pCmdUI) 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	pCmdUI->SetCheck(pDoc->SnapMask==1?1:0);
}

void CImageGrinderView::OnUpdateTestXsnap2(CCmdUI* pCmdUI) 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	pCmdUI->SetCheck(pDoc->SnapMask==2?1:0);
}

void CImageGrinderView::OnUpdateTestXsnap4(CCmdUI* pCmdUI) 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	pCmdUI->SetCheck(pDoc->SnapMask==4?1:0);
}

void CImageGrinderView::OnUpdateTestXsnap8(CCmdUI* pCmdUI) 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	pCmdUI->SetCheck(pDoc->SnapMask==8?1:0);
}

void CImageGrinderView::OnUpdateTestXsnap16(CCmdUI* pCmdUI) 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	pCmdUI->SetCheck(pDoc->SnapMask==16?1:0);
}

void CImageGrinderView::OnViewGridoptions() 
{
	CGridOptions dlg;
	dlg.m_PSpace=PixelSpace;
	
	if(dlg.DoModal()==IDOK)
	{
		PixelSpace=dlg.m_PSpace;
		UpdateWindow();
	}
	
	
	
	
}

void CImageGrinderView::UpdatePPoint()
{
	CRect crct;
	CPoint pnt;
	GetClientRect(&crct);
	pnt=crct.CenterPoint();
	ScreenToData(&pnt);
	
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	pDoc->NewPlacePoint=pnt;
	
}



void _cdecl ComposeThread(void *dat)
{
	CComposeInfo *info=(CComposeInfo *)dat;
	info->CurView->ComposeList(*info);
}

void CImageGrinderView::ComposeBackBuffer()
{
	//CompleteImage.FillColor();	
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
 
	
	if(pDoc->ManualUpdate) return;

	if(pDoc->FPool==NULL || pDoc->FGrid==NULL) return;
	
	int gridcount=0;
	int row,col;
	for(row=0;row<pDoc->FGrid->GetRows();row++)
		for(col=0;col<pDoc->FGrid->GetColumns();col++)
			if( pDoc->UpdateList[pDoc->FGrid->GetColumns()*row+col]==true)
			{
				gridcount++;
			}
			
			if(gridcount<1) 
				return;
/*			
			if(PreviewWin->IsWindowVisible()) 
			{
				pDoc->BuildHF();
				PreviewWin->UpdateHF();
			}			
*/			
			if(sysinfo.dwNumberOfProcessors==1 || gridcount==1)	
			{
				Image BmpBuf;
				int GridSize=pDoc->FGrid->GetGridSize();
				if(RenderLowRes) GridSize>>=1;

				BmpBuf.CreateBlank(GridSize,GridSize,ITYPE_RGB,32);
				BYTE *imgdat=(BYTE *)BmpBuf.Lock();
				
				
				for(row=0;row<pDoc->FGrid->GetRows();row++)
					for(col=0;col<pDoc->FGrid->GetColumns();col++)
						if( pDoc->UpdateList[pDoc->FGrid->GetColumns()*row+col]==true)
						{
							//Each Compose Grid Should Be in it's own thread
							
							if(!pDoc->FGrid->ComposeGrid(row,col,imgdat, RenderLowRes?1:0, ViewMode))
								for(int i=0;i<GridSize*GridSize*3;i++) imgdat[i]=i%GridSize;
								
								CompleteImage.Blt(BmpBuf,CRect(col*pDoc->FGrid->GetGridSize(),row*pDoc->FGrid->GetGridSize(),(col+1)*pDoc->FGrid->GetGridSize(),(row+1)*pDoc->FGrid->GetGridSize()),CRect(0,0,BmpBuf.GetWidth(),BmpBuf.GetHeight()));
								
								pDoc->UpdateList[pDoc->FGrid->GetColumns()*row+col]=false;
						}
			}
			else
			{
				
				int i;
				for(i=0;i<sysinfo.dwNumberOfProcessors;i++)
				{	
					ProcInfo[i].Init((gridcount/2)+1);
					ProcInfo[i].CurView=this;
					ProcInfo[i].CurDoc=pDoc;
				}
				
				int pnum=0;
				
				for(row=0;row<pDoc->FGrid->GetRows();row++)
					for(col=0;col<pDoc->FGrid->GetColumns();col++)
						if( pDoc->UpdateList[pDoc->FGrid->GetColumns()*row+col]==true)
						{
							ProcInfo[pnum].AddSeg(GridSeg(row,col));
							pnum++;
							pnum=pnum%sysinfo.dwNumberOfProcessors;
						}
						
						ProcRunning=sysinfo.dwNumberOfProcessors;
						for( i=0;i<sysinfo.dwNumberOfProcessors;i++)
						{
							
							if(i==sysinfo.dwNumberOfProcessors-1) 
								ComposeList(ProcInfo[i]);
							else
								_beginthread(ComposeThread,0,(void* )&(ProcInfo[i]));
						}
			}
			
			
			while(ProcRunning>0) 
			{	
				ProcRunning=ProcRunning;
				Sleep(50);	
			}
}



void CImageGrinderView::ComposeList(CComposeInfo &List)
{
	int i;
	Image BmpBuf;
	CImageGrinderDoc* pDoc = List.CurDoc;
	
	BmpBuf.CreateBlank(pDoc->FGrid->GetGridSize(),pDoc->FGrid->GetGridSize(),ITYPE_RGB,32);
	BYTE *imgdat=(BYTE *)BmpBuf.Lock();
	int row,col;
	
	for(i=0;i<List.NumSeg;i++)
	{
		row=List.Segs[i].row;
		col=List.Segs[i].col;
		
		if(!pDoc->FGrid->ComposeGrid(row,col,imgdat, 0, ViewMode))
			for(int i=0;i<pDoc->FGrid->GetGridSize()*pDoc->FGrid->GetGridSize()*3;i++) imgdat[i]=i%pDoc->FGrid->GetGridSize();
			
			CompleteImage.Blt(BmpBuf,CRect(col*pDoc->FGrid->GetGridSize(),row*pDoc->FGrid->GetGridSize(),(col+1)*pDoc->FGrid->GetGridSize(),(row+1)*pDoc->FGrid->GetGridSize()),CRect(0,0,BmpBuf.GetWidth(),BmpBuf.GetHeight()));
			
			pDoc->UpdateList[pDoc->FGrid->GetColumns()*row+col]=false;
	}
	
	ProcLock.Lock();
	ProcRunning--;
	ProcLock.Unlock();
	
}

void CImageGrinderView::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	Compost::FeatureInstance *fetint;
	DWORD Han;
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
   	CPoint tpnt;
	tpnt=point;
	ScreenToData(&tpnt);
	
	if((Han=pDoc->IsOnScaleHandle(tpnt,fetint=pDoc->GetTopSelected(tpnt)))!=HF_NONE && fetint)
	{
		pDoc->SetModifiedFlag(TRUE);
		int fmd=fetint->feature->GetFlipMode();
		if(Han&(HF_TOP|HF_BOTTOM))
		{
			if(fmd&Compost::Feature::Mask0_Vertical_Flip)
				fetint->feature->ClearFlipMode(Compost::Feature::Mask0_Vertical_Flip);
			else
				fetint->feature->SetFlipMode(Compost::Feature::Mask0_Vertical_Flip);
			
			if(fmd&Compost::Feature::Mask1_Vertical_Flip)
				fetint->feature->ClearFlipMode(Compost::Feature::Mask1_Vertical_Flip);
			else
				fetint->feature->SetFlipMode(Compost::Feature::Mask1_Vertical_Flip);
		}
		
		if(Han&(HF_LEFT|HF_RIGHT))
		{
			if(fmd&Compost::Feature::Mask0_Horizontal_Flip)
				fetint->feature->ClearFlipMode(Compost::Feature::Mask0_Horizontal_Flip);
			else
				fetint->feature->SetFlipMode(Compost::Feature::Mask0_Horizontal_Flip);
			
			if(fmd&Compost::Feature::Mask1_Horizontal_Flip)
				fetint->feature->ClearFlipMode(Compost::Feature::Mask1_Horizontal_Flip);
			else
				fetint->feature->SetFlipMode(Compost::Feature::Mask1_Horizontal_Flip);
		}
		pDoc->SetDrawFlags(fetint->feature);
		ComposeBackBuffer();
		UpdateWindow();
	}
	CView::OnLButtonDblClk(nFlags, point);
}

void CImageGrinderView::OnEditMakeunique() 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	pDoc->MakeSelectedUnique();
}

void CImageGrinderView::OnViewGrid() 
{
	Grid=!Grid;
	
	if(Grid) Helpers=true;	
	UpdateWindow();
}

void CImageGrinderView::OnUpdateViewGrid(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(Grid?1:0);	
}

void CImageGrinderView::OnViewHelpers() 
{
	Helpers=!Helpers;
	UpdateWindow();
	
}

void CImageGrinderView::OnUpdateViewHelpers(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(Helpers?1:0);	
	
}

void CImageGrinderView::OnViewWiremode() 
{
	WireMode=!WireMode;
	
	if(WireMode) Helpers=true;	
	UpdateWindow();
	
}

void CImageGrinderView::OnUpdateViewWiremode(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(WireMode?1:0);	
	
}

void CImageGrinderView::OnViewColorproperties() 
{
	CColorProps dlg;
	if(dlg.DoModal()==IDOK)
	{
		DeletePens();
		CreatePens();
		UpdateWindow();
	}
	
}

void CImageGrinderView::OnEditLockselection() 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	pDoc->LockSelection();	
	UpdateWindow();
}

void CImageGrinderView::OnEditUnlockall() 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	pDoc->UnLockAll();
	
}

void CImageGrinderView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	// TODO: Add your message handler code here and/or call default
	
	CView::OnChar(nChar, nRepCnt, nFlags);
}

void CImageGrinderView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	pDoc->SavePosForUndo();

	switch(nChar)
	{
	case VK_LEFT:
		pDoc->OffsetSelection(-pDoc->SnapMask,0);
		ComposeBackBuffer();
		UpdateWindow();
		break;
	case VK_RIGHT:
		pDoc->OffsetSelection(pDoc->SnapMask,0);
		ComposeBackBuffer();
		UpdateWindow();
		break;
	case VK_UP:
		pDoc->OffsetSelection(0,-pDoc->SnapMask);
		ComposeBackBuffer();
		UpdateWindow();
		break;
	case VK_DOWN:
		pDoc->OffsetSelection(0,pDoc->SnapMask);
		ComposeBackBuffer();
		UpdateWindow();
		break;
	}
	CView::OnKeyDown(nChar, nRepCnt, nFlags);
}

void CImageGrinderView::CreatePens()
{
	CString AppName;
	AppName.LoadString(AFX_IDS_APP_TITLE);
	
	
	LOGBRUSH lb;
	lb.lbColor=theApp.GetProfileInt(AppName,"SelectionColor",0x00ff00);
	lb.lbStyle=BS_SOLID;
	PenSelected.CreatePen(PS_DASH,1,&lb);
	
	
	lb.lbColor=theApp.GetProfileInt(AppName,"BoxColor",0xffffff);
	lb.lbStyle=BS_SOLID;
	BoxPen.CreatePen(PS_DOT,1,&lb);
	
	SolidSel.CreatePen(PS_SOLID,1,theApp.GetProfileInt(AppName,"SelectionColor",0x00ff00));
	GridPen.CreatePen(PS_SOLID,1,theApp.GetProfileInt(AppName,"GridColor",0xffff00));
	WirePen.CreatePen(PS_SOLID,1,theApp.GetProfileInt(AppName,"WireColor",0x7f6f7f));
	WireHLPen.CreatePen(PS_SOLID,1,theApp.GetProfileInt(AppName,"WireHLColor",0xff7fff));
	GreenBrush.CreateSolidBrush(theApp.GetProfileInt(AppName,"SelectionColor",0x00ff00));
	
}

void CImageGrinderView::DeletePens()
{
	PenSelected.DeleteObject();
	BoxPen.DeleteObject();
	SolidSel.DeleteObject();
	GridPen.DeleteObject();
	WirePen.DeleteObject();
	WireHLPen.DeleteObject();
	GreenBrush.DeleteObject();
}

void CImageGrinderView::OnEditUngroupselection() 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	pDoc->UnGroupSelection();
}

void CImageGrinderView::OnEditGroupselection() 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	pDoc->GroupSelection();
}

void CImageGrinderView::OnViewZoomin() 
{
	
	ViewScale/=2;
	if(ViewScale<=1) ViewScale=1;
	
	
	UpdateWindow();
	
}

void CImageGrinderView::OnViewZoomout() 
{
	ViewScale*=2;
	//		if(ViewScale>2) ViewScale=2;
	ClearWindow();
	UpdateWindow();
	
}


void CImageGrinderView::OnEditGlobaltextures() 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	pDoc->MakeSelectionWorldSpaceTexture();
	UpdateWindow();
	
}

void CImageGrinderView::OnEditLocaltextures() 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	pDoc->MakeSelectionLocalTexture();
	UpdateWindow();
	
	
}

void CImageGrinderView::OnFileExportPartialoutput() 
{
	CPOutOpts	dlg;
	
	if(dlg.DoModal()==IDOK)
	{
		CImageGrinderDoc* pDoc = GetDocument();
		ASSERT_VALID(pDoc);
		
		CFileDialog svedlg(FALSE,"fgd",pDoc->GetTitle(),NULL,"ImageGrinder files (*.fgd)|*.fgd||",NULL);
		
		if(svedlg.DoModal()==IDOK)
		{
			int xoffset,zoffset;
			
			xoffset=dlg.m_zcol*256*8;
			zoffset=dlg.m_zrow*256*8;
			
			
			pDoc->SaveAs((LPCSTR)svedlg.GetPathName(),xoffset,zoffset);
		}
		
	}
	
}

struct MStringPlug : Stuff::Plug {
	MStringPlug() : Plug(DefaultData) { name = NULL; };

	Stuff::MString *name;
};

void CImageGrinderView::OnFileExportMaptextureindex() 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	
	CString BaseName, GridName,FinalName,HintName;
	GridName=pDoc->GetTitle();
	BaseName=GridName.Left(GridName.ReverseFind('.'));
	FinalName=Compost::TexturePool::Instance->GetTexturePath();
	FinalName+="\\";
	FinalName+=BaseName+".index.tcf";

	HintName=Compost::TexturePool::Instance->GetTexturePath();
	HintName+="\\";
	HintName+=BaseName+".index.hint";

	Stuff::NotationFile hint_file(HintName);
	hint_file.DeleteAllPages();
	Stuff::Page *hpage=hint_file.SetPage("Resource\\Maps\\"+BaseName+".mw4");

	Stuff::NotationFile index_file;

	Stuff::HashOf<MStringPlug*, Stuff::MString>	testHash(4099, NULL, true);
	
	Compost::Feature *feature = NULL;
	Compost::Feature_Texture *fTexture = NULL;
	int last_texture_index = 0;
	
	for(int i=0;i<pDoc->FPool->GetNumberOfFeatures();i++)
	{
		feature = pDoc->FPool->GetFeatureNumber(i);
		Check_Pointer(feature);
		fTexture = feature->GetFeatureTexture();
		Check_Object(fTexture);
		CString text_number;

		int indexq = fTexture->GetName()->GetHashValue();

		MStringPlug *test_name;
		Stuff::MString *name;
		
		if ((test_name = testHash.Find(*fTexture->GetName())) == NULL)
		{
			MStringPlug *stringPlug = new MStringPlug;
			Register_Object(stringPlug);
			stringPlug->name = fTexture->GetName();
			testHash.AddValue(stringPlug, *fTexture->GetName());

			text_number.Format("%d", ++last_texture_index);
			
			Stuff::Page *page = index_file.AddPage((LPCSTR)text_number);
			Check_Object(page);
			
			name = fTexture->GetName();
			
			if(name)
			{
				page->SetEntry("Name", *name);
				hpage->AppendEntry("file", "Textures\\Composttexture\\"+*name+".bid");
			}
			else
			{
				page->SetEntry("Index", indexq);
			}
			
			page->SetEntry("Type", fTexture->GetTextureMode());
			page->SetEntry("Width", fTexture->width);
			page->SetEntry("Height", fTexture->height);

		}
		else if(*test_name->name != *fTexture->GetName())
		{
			PAUSE(("Unique texture name rule violated ! \"%s\" and \"%s\" produce same hash value !! Index File not saved.",
				(const char*)*test_name->name,
				(const char*)*fTexture->GetName()
			));
			return;
		}

		fTexture = feature->GetFeatureMask0();
		if(fTexture != NULL)
		{
			Check_Object(fTexture);
			
			if ((test_name = testHash.Find(*fTexture->GetName())) == NULL)
			{
				MStringPlug *stringPlug = new MStringPlug;
				Register_Object(stringPlug);
				stringPlug->name = fTexture->GetName();
				testHash.AddValue(stringPlug, *fTexture->GetName());

				text_number.Format("%d", ++last_texture_index);
				
				Stuff::Page *page = index_file.AddPage((LPCSTR)text_number);
				Check_Object(page);
				
				Stuff::MString *name;
				
				name = fTexture->GetName();
				
				if(name)
				{
					page->SetEntry("Name", *name);
					hpage->AppendEntry("file", "Textures\\Composttexture\\"+*name+".bid");
				}
				else
				{
					page->SetEntry("Index", indexq);
				}
				
				page->SetEntry("Type", fTexture->GetTextureMode());
				page->SetEntry("Width", fTexture->width);
				page->SetEntry("Height", fTexture->height);
			}
			else if(*test_name->name != *fTexture->GetName())
			{
				PAUSE(("Unique texture name rule violated ! \"%s\" and \"%s\" produce same hash value !! Index File not saved.",
					(const char*)*test_name->name,
					(const char*)*fTexture->GetName()
				));
				return;
			}
		}
		
		fTexture = feature->GetFeatureMask1();
		if(fTexture != NULL)
		{
			Check_Object(fTexture);
			
			if ((test_name = testHash.Find(*fTexture->GetName())) == NULL)
			{
				MStringPlug *stringPlug = new MStringPlug;
				Register_Object(stringPlug);
				stringPlug->name = fTexture->GetName();
				testHash.AddValue(stringPlug, *fTexture->GetName());

				text_number.Format("%d",last_texture_index);
				
				Stuff::Page *page = index_file.AddPage((LPCSTR)text_number);
				Check_Object(page);
				
				Stuff::MString *name;
				
				name = fTexture->GetName();
				
				if(name)
				{
					page->SetEntry("Name", *name);
					hpage->AppendEntry("file", "Textures\\Composttexture\\"+*name+".bid");
				}
				else
				{
					page->SetEntry("Index", indexq);
				}
				
				page->SetEntry("Type", fTexture->GetTextureMode());
				page->SetEntry("Width", fTexture->width);
				page->SetEntry("Height", fTexture->height);
			}
			else if(*test_name->name != *fTexture->GetName())
			{
				PAUSE(("Unique texture name rule violated ! \"%s\" and \"%s\" produce same hash value !! Index File not saved.",
					(const char*)*test_name->name,
					(const char*)*fTexture->GetName()
				));
				return;
			}
		}
	}
	index_file.SaveAs((LPCSTR)FinalName);
	hint_file.Save();
	
	testHash.DeletePlugs();	
}

void CImageGrinderView::OnFileExportAll() 
{
CExpAllOpts	dlg;
	dlg.m_idata=TRUE;
	dlg.m_mti=TRUE;
	dlg.m_singletga=FALSE;
	dlg.m_tgafiles=TRUE;
	dlg.m_usedimagelist=FALSE;
	dlg.m_Material=TRUE;
	dlg.m_Fgd=TRUE;
	dlg.m_IGData=TRUE;
	dlg.m_SingleMat=FALSE;

if(dlg.DoModal()==IDOK)
	{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	if(dlg.m_idata)			pDoc->OnFileExportImagedata();
	if(dlg.m_mti)			OnFileExportMaptextureindex();
	if(dlg.m_singletga) 	pDoc->OnFileExportSingletga();
	if(dlg.m_tgafiles)		pDoc->OnFileExportTgafiles();
	if(dlg.m_usedimagelist)	pDoc->OnFileExportUsedimagelist();
	if(dlg.m_Material)		pDoc->OnFileExportMaterialmap();
	if(dlg.m_SingleMat)		pDoc->OnFileExportSinglematerialmap();
	if(dlg.m_Fgd)			pDoc->SaveToGame();
	if(dlg.m_IGData)		pDoc->SaveIGDataToGame();
	}
}



void CImageGrinderView::OnViewManualupdate() 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	pDoc->ManualUpdate=!pDoc->ManualUpdate;
}

void CImageGrinderView::OnUpdateViewManualupdate(CCmdUI* pCmdUI) 
{
	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	pCmdUI->SetCheck(pDoc->ManualUpdate?1:0);
	
}

void CImageGrinderView::OnViewUpdate() 
{
		CImageGrinderDoc* pDoc = GetDocument();
		ASSERT_VALID(pDoc);
		bool oldval=pDoc->ManualUpdate;
		pDoc->ManualUpdate=false;
		ComposeBackBuffer();	
		UpdateWindow();
		pDoc->ManualUpdate=oldval;

}

void CImageGrinderView::OnTestRenderlowres() 
{
	RenderLowRes=!RenderLowRes;

	CImageGrinderDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	bool oldval=pDoc->ManualUpdate;
	pDoc->ManualUpdate=false;

	pDoc->SetDrawFlags();
	pDoc->UpdateAllViews(NULL);

	pDoc->ManualUpdate=oldval;

}

void CImageGrinderView::OnUpdateTestRenderlowres(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(RenderLowRes?1:0);	
}


void CImageGrinderView::OnOptionsForcesingleproc() 
{
	if(sysinfo.dwNumberOfProcessors==1) 
		DetectProcs(); 
	else 
		ForceSingleProc();	
}

void CImageGrinderView::OnUpdateOptionsForcesingleproc(CCmdUI* pCmdUI) 
{
	if(ProcCount()==1) 
	{
		pCmdUI->Enable(FALSE); 
	}
		else
	{
		pCmdUI->Enable(TRUE); 
		pCmdUI->SetCheck(sysinfo.dwNumberOfProcessors==1?1:0);
	}
	
}

void CImageGrinderView::OnEditUndo() 
{
	CImageGrinderDoc* pDoc = GetDocument();
	pDoc->UndoMan.Undo();	
	UpdateWindow();

}

void CImageGrinderView::OnUpdateEditUndo(CCmdUI* pCmdUI) 
{
	CImageGrinderDoc* pDoc = GetDocument();
	pCmdUI->Enable(pDoc->UndoMan.CanUndo()?TRUE:FALSE);	
	
}

void CImageGrinderView::OnEditRedo() 
{
	CImageGrinderDoc* pDoc = GetDocument();
	pDoc->UndoMan.Redo();	
	UpdateWindow();
}

void CImageGrinderView::OnUpdateEditRedo(CCmdUI* pCmdUI) 
{
	CImageGrinderDoc* pDoc = GetDocument();
	pCmdUI->Enable(pDoc->UndoMan.CanRedo()?TRUE:FALSE);	
	
}

