// ImageGrinderDoc.cpp : implementation of the CImageGrinderDoc class
//

#include "stdafx.h"
#include "ImageGrinder.h"
#include "NewGridDlg.h"
#include "ImageGrinderDoc.h"
#include "BackGroundProps.h"
#include "DepthDiag.h"
#include "ImageCache.h"

#include <Compost\TexturePool.hpp>
#include <Stuff\StuffHeaders.hpp>
#include <GameOS\ToolOS.hpp>

#define  MAXDOCS 256
CImageGrinderDoc *DocList[MAXDOCS];
int DocCount=0;

/////////////////////////////////////////////////////////////////////////////
// CImageGrinderDoc

IMPLEMENT_DYNCREATE(CImageGrinderDoc, CDocument)

BEGIN_MESSAGE_MAP(CImageGrinderDoc, CDocument)
//{{AFX_MSG_MAP(CImageGrinderDoc)
ON_COMMAND(ID_FILE_EXPORT_TGAFILES, OnFileExportTgafiles)
ON_COMMAND(ID_FILE_EXPORT_IMAGEDATA, OnFileExportImagedata)
ON_COMMAND(ID_FILE_EXPORT_SINGLETGA, OnFileExportSingletga)
ON_COMMAND(ID_FILE_MERGEFEATURES, OnFileMergefeatures)
ON_COMMAND(ID_FILE_EXPORT_USEDIMAGELIST, OnFileExportUsedimagelist)
ON_COMMAND(ID_FILE_EXPORT_MATERIALMAP, OnFileExportMaterialmap)
ON_COMMAND(ID_FILE_EXPORT_SINGLEMATERIALMAP, OnFileExportSinglematerialmap)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CImageGrinderDoc construction/destruction




CImageGrinderDoc::CImageGrinderDoc()
{
	CurSelFet=NULL;
	DocList[DocCount++]=this;
	
	Verify(DocCount<MAXDOCS);
	FPool = NULL;
	FGrid = NULL;
	UpdateList=NULL;
	ManualUpdate=false;
	//	SelectionCount=0;
	//	HLCount=0;
	//	LockCount=0;
	SnapMask = 4;
	
}

CImageGrinderDoc::~CImageGrinderDoc()
{
	int i,didx;
	for(didx=0;didx<DocCount && DocList[didx]!=this;didx++);
	Verify(didx<DocCount);
	for(i=didx;i<(DocCount-1);i++) DocList[i]=DocList[i+1];
	DocCount--;
	
	if(UpdateList)
	{
		delete UpdateList;
	}
	
	if(FGrid)
	{
		Unregister_Pointer(FGrid);
		delete FGrid;
	}
	
	if(FPool)
	{
		Unregister_Pointer(FPool);
		delete FPool;
	}
}

BOOL CImageGrinderDoc::OnNewDocument()
{
	CNewGridDlg ngd;
	if(ngd.DoModal()==IDOK)
	{
		
		if (!CDocument::OnNewDocument())
			return FALSE;
		
		FPool = new Compost::FeaturePool();
		Register_Pointer(FPool);
		
		if(ngd.m_hires==TRUE)
		{
			FGrid = new Compost::FeatureGrid(8*ngd.m_XZones, 8*ngd.m_YZones, FPool, true);
		}
		else
		{
			FGrid = new Compost::FeatureGrid(8*ngd.m_XZones, 8*ngd.m_YZones, FPool);
		}
		
		Register_Pointer(FGrid);
		
		UpdateList=new bool[FGrid->GetRows()*FGrid->GetColumns()];
		ClearSelection();
		
		CBackGroundProps dlg;
		
		Compost::Tool_Feature *TmpFet = new Compost::Tool_Feature;
		Register_Pointer(TmpFet);
		TmpFet->SetName((LPCSTR)"BackGround");
		TmpFet->SetFeatureHeight(FGrid->GetRows()*FGrid->GetGridSize());
		TmpFet->SetFeatureWidth(FGrid->GetColumns()*FGrid->GetGridSize());
		
		dlg.DoModal(TmpFet);
		if(dlg.m_stretch)
		{
			TmpFet->SetBlendMode(Compost::Feature::Blend_Mode::StretchPaste);
			TmpFet->SetFeatureMask0(TmpFet->GetFeatureTexture());
		}
		else
			TmpFet->SetBlendMode(Compost::Feature::Blend_Mode::Paste);
		
		FPool->Add(TmpFet);
		FGrid->Add(TmpFet, 0, 0);
		SetDrawFlags();
		
		
		return TRUE;
		
	}	
	
	return FALSE;
	
	// (SDI documents will reuse this document)
}



/////////////////////////////////////////////////////////////////////////////
// CImageGrinderDoc serialization

void CImageGrinderDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
	}
	else
	{
		// TODO: add loading code here
	}
}

/////////////////////////////////////////////////////////////////////////////
// CImageGrinderDoc diagnostics

#ifdef _DEBUG
void CImageGrinderDoc::AssertValid() const
{
	CDocument::AssertValid();
}

void CImageGrinderDoc::Dump(CDumpContext& dc) const
{
	CDocument::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CImageGrinderDoc commands

void CImageGrinderDoc::AddFeature(Compost::Feature *fet, int x, int y)
{
	if(x<0)
	{
		x = 0;
	}
	if(y<0)
	{
		y = 0;
	}
	if(x + fet->GetFeatureWidth()>FGrid->GetColumns()*FGrid->GetGridSize())
	{
		x -= (x+fet->GetFeatureWidth()) - (FGrid->GetColumns()*FGrid->GetGridSize());
	}
	if(y+fet->GetFeatureHeight()>FGrid->GetRows()*FGrid->GetGridSize())
	{
		y-=(y+fet->GetFeatureHeight())-(FGrid->GetRows()*FGrid->GetGridSize());
	}
	if(x<0)
	{
		x = 0;
	}
	if(y<0)
	{
		y = 0;
	}
	
	ClearSelection();
	Compost::FeatureInstance *fetint;
	fetint=FGrid->Add(fet, x & ~(SnapMask-1), y & ~(SnapMask-1));	// & ~(SnapMask-1));
	
	fetint->StatFlags|=FIF_SELECTED;
	AddCommand *addcom=new AddCommand(fetint,this);
	UndoMan.AddCommand(addcom);
	SetDrawFlags(fetint);
	
	SetModifiedFlag();	
}

void CImageGrinderDoc::AddFeature(Compost::Feature *fet)
{
	AddFeature(fet,NewPlacePoint.x,NewPlacePoint.y);
	CPoint offset;
	
	offset.x=(int)((rand()*20)/RAND_MAX)-10;
	offset.y=(int)((rand()*20)/RAND_MAX)-10;
	
	NewPlacePoint+=offset;
}

void CImageGrinderDoc::OffsetSelection(int xp, int yp)
{
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	
	int CurFet;
	
	
	for(CurFet=0;CurFet<count;CurFet++)
		if((*FList)[CurFet]->StatFlags&FIF_SELECTED)
		{
			SetDrawFlags((*FList)[CurFet]);
			int x,y,tx,ty;
			x=(*FList)[CurFet]->feature_x_pos;
			y=(*FList)[CurFet]->feature_z_pos;
			x+=xp;
			y+=yp;
			tx=(*FList)[CurFet]->texture_x_pos;
			ty=(*FList)[CurFet]->texture_z_pos;
			tx-=xp;
			ty-=yp;
			
			Compost::Feature *fet=(*FList)[CurFet]->feature;
			
			if(x<0) x=0;
			if(y<0) y=0;
			if(x+fet->GetFeatureWidth()>FGrid->GetColumns()*FGrid->GetGridSize()) 
			{
				x-=(x+fet->GetFeatureWidth())-(FGrid->GetColumns()*FGrid->GetGridSize());
				tx+=(x+fet->GetFeatureWidth())-(FGrid->GetColumns()*FGrid->GetGridSize());	
			}
			
			if(y+fet->GetFeatureHeight()>FGrid->GetRows()*FGrid->GetGridSize()) 
			{
				y-=(y+fet->GetFeatureHeight())-(FGrid->GetRows()*FGrid->GetGridSize());
				ty+=(y+fet->GetFeatureHeight())-(FGrid->GetRows()*FGrid->GetGridSize());	
			}
			
			int nx,ny,dx,dy;
			nx=(x + (SnapMask>>1)) & ~(SnapMask-1);
			dx=nx-x;
			x=nx;
			tx-=dx;
			
			ny=(y + (SnapMask>>1)) & ~(SnapMask-1);
			dy=ny-y;
			y=ny;
			ty-=dy;
			
			
			(*FList)[CurFet]->feature_x_pos = x;
			(*FList)[CurFet]->feature_z_pos = y;
			
			if((*FList)[CurFet]->StatFlags&FIF_WSTEXTURE)
			{
				(*FList)[CurFet]->texture_x_pos = tx;
				(*FList)[CurFet]->texture_z_pos = ty;
			}
			
			SetDrawFlags((*FList)[CurFet]);
		}
		FGrid->LoadGridFromUnique();
		
		SetModifiedFlag();	
}




void CImageGrinderDoc::NewSelection(Compost::FeatureInstance *fet)
{
	if(IsLocked(fet)) return;
	ClearSelection();
	AddSelection(fet);
	UpdateAllViews(NULL);
}

void CImageGrinderDoc::AddSelection(Compost::FeatureInstance *fet)
{
	if(IsLocked(fet)) return;
	fet->StatFlags|=FIF_SELECTED;
	((Compost::Tool_Feature *)fet->feature)->StatFlags|=FF_HIGHLIGHTED;
	SelectGroupMembers(fet);
}

void CImageGrinderDoc::SubSelection(Compost::FeatureInstance *fet)
{
	fet->StatFlags&=~FIF_SELECTED;
	DeSelectGroupMembers(fet);
}

void CImageGrinderDoc::NewSelection(CRect &rct)
{
	ClearSelection();
	AddSelection(rct);
}

void CImageGrinderDoc::AddSelection(CRect &rct)
{
	int i;
	Stuff::DynamicArrayOf<Compost::FeatureInstance*>  list;
	
	FGrid->ShootRectangle(list,(unsigned short)rct.left,(unsigned short)rct.top,rct.Width(),rct.Height());
	
	
	for(i=0;i<list.GetLength();i++)
		AddSelection(list[i]);
}

void CImageGrinderDoc::SubSelection(CRect &rct)
{
	int i;
	Stuff::DynamicArrayOf<Compost::FeatureInstance*>  list;
	
	FGrid->ShootRectangle(list,(unsigned short)rct.left,(unsigned short)rct.top,rct.Width(),rct.Height());
	
	
	for(i=0;i<list.GetLength();i++)
		SubSelection(list[i]);
}

void CImageGrinderDoc::NewSelection(CPoint &pnt)
{
	ClearSelection();
	ClearHL();
	AddSelection(pnt);
}

void CImageGrinderDoc::AddSelection(CPoint &pnt)
{
	
	int i,depth;
	depth=FGrid->ShootRay((unsigned short)pnt.x,(unsigned short)pnt.y);
	if(depth<=1) return;
	
	for(i=depth-1;
	i>0 && (IsSelected(FGrid->GetCollectedNr(i)) ||
		!(FGrid->GetCollectedNr(i)->feature->GetFeatureWidth()<FGrid->GetColumns()*FGrid->GetGridSize() && 
		FGrid->GetCollectedNr(i)->feature->GetFeatureHeight()<FGrid->GetRows()*FGrid->GetGridSize()))
		;i--);
	
	if(i>0) 
	{
		AddSelection(FGrid->GetCollectedNr(i));
	}
}

void CImageGrinderDoc::SubSelection(CPoint &pnt)
{
	
	int selfet,depth;
	depth=FGrid->ShootRay((unsigned short)pnt.x,(unsigned short)pnt.y);
	if(depth<=1) return;
	
	for(selfet=1;selfet<depth && !IsSelected(FGrid->GetCollectedNr(selfet));selfet++);
	
	if(selfet<depth)
	{
		SubSelection(FGrid->GetCollectedNr(selfet));
	}
	
}


void CImageGrinderDoc::SelectionByList(CPoint &pnt)
{
	if(FGrid->ShootRay((unsigned short)pnt.x,(unsigned short)pnt.y)<=1) return;
	CDepthDiag dlg;
	
	dlg.DoModal(this,pnt);
	
}




void CImageGrinderDoc::SetDrawFlags(Compost::Feature *fet)
{
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	
	int CurFet;
	
	for(CurFet=0;CurFet<count;CurFet++)
		if((*FList)[CurFet]->feature==fet)
			SetDrawFlags((*FList)[CurFet]);
}

void CImageGrinderDoc::SetDrawFlags(Compost::FeatureInstance *fetI)
{
	
	int xl,yl,r,c,w,h;
	int x,y;
	x=fetI->feature_x_pos;
	y=fetI->feature_z_pos;
	Compost::Feature *fet=fetI->feature;	
	w=fet->GetFeatureWidth();
	h=fet->GetFeatureHeight();
	
	for(yl=y;yl<=y+h;yl+=FGrid->GetGridSize()<h?FGrid->GetGridSize():h)
		for(xl=x;xl<=x+w;xl+=FGrid->GetGridSize()<w?FGrid->GetGridSize():w)
		{
			r=yl>>FGrid->GetGridShift();	c=xl>>FGrid->GetGridShift();	
			if(c<FGrid->GetColumns() && r<FGrid->GetRows())
			{
				UpdateList[FGrid->GetColumns()*r+c]=true;
			}
		}
		
		
}

void CImageGrinderDoc::SetDrawFlags()
{
	int gsqu=FGrid->GetRows()*FGrid->GetColumns();
	for(int i=0;i<gsqu;i++) UpdateList[i]=true;
}

void CImageGrinderDoc::DeleteSelected()
{
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count, CurFet;
	UndoCommand *cmd=NULL;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	do
	{
		for(CurFet=0;CurFet<count && !((*FList)[CurFet]->StatFlags&FIF_SELECTED);CurFet++);
		
		if(CurFet<count)
		{
			if(FPool->GetFeaturePosition((*FList)[CurFet]->feature)==0) return;
			SetDrawFlags((*FList)[CurFet]);	
			DeleteCommand *dcom=new DeleteCommand((*FList)[CurFet],this);
			if(cmd==NULL) cmd=dcom; else cmd->Attach(dcom);
			FGrid->Remove((*FList)[CurFet]);
		}
		FList=FGrid->GetUniqueFeatureInstances(count);
	}
	while(CurFet<count);
	
	if(cmd) 
	{
		UndoMan.Clear();
		UndoMan.AddCommand(cmd);
	}
	FGrid->RedoFeaturePosition();
	SetModifiedFlag();
}

BOOL CImageGrinderDoc::OnOpenDocument(LPCTSTR lpszPathName) 
{
/*
if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
	*/	
	CloseCurrent();
	OpenText(lpszPathName);
	PostLoadInit();
	return TRUE;
}

BOOL CImageGrinderDoc::OnSaveDocument(LPCTSTR lpszPathName) 
{
	SaveAs(lpszPathName);
	SetModifiedFlag(FALSE);
	//	return CDocument::OnSaveDocument(lpszPathName);
	return TRUE;
}


bool CImageGrinderDoc::InSelectedRegion(CPoint &pnt)
{
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	
	int CurFet;
	
	for(CurFet=0;CurFet<count;CurFet++)
		if((*FList)[CurFet]->StatFlags&FIF_SELECTED)
		{
			CRect rct;
			rct.left=(*FList)[CurFet]->feature_x_pos;
			rct.top=(*FList)[CurFet]->feature_z_pos;
			rct.right=(*FList)[CurFet]->feature_x_pos+(*FList)[CurFet]->feature->GetFeatureWidth();
			rct.bottom=(*FList)[CurFet]->feature_z_pos+(*FList)[CurFet]->feature->GetFeatureHeight();
			
			if(rct.PtInRect(pnt)==TRUE) 
				return true;
		}
		return false;
}



void CImageGrinderDoc::OnFileExportTgafiles() 
{
	CString ImgName, BaseName, GridName;
	GridName=GetTitle();
	BaseName=GridName.Left(GridName.ReverseFind('.'));
	
	
	Verify((FGrid->GetRows()%8)==0);
	Verify((FGrid->GetColumns()%8)==0);
	int ZoneCountX = FGrid->GetColumns()/8;
	int ZoneCountY = FGrid->GetRows()/8;
	
	
	
	CString DirName = Compost::TexturePool::Instance->GetTexturePath();
	DirName=DirName.Left(DirName.ReverseFind('\\'));
	DirName+="\\Maps\\";
	DirName+=BaseName;
	
	if(!gos_DoesFileExist(DirName))
		gos_CreateDirectory(DirName);
	
	Image imgseg,totimg,savimg;
	
	imgseg.CreateBlank(FGrid->GetGridSize(),FGrid->GetGridSize(), ITYPE_RGB, 32);
	imgseg.MaskTo(RGBMask(0xff0000,0x00ff00,0x0000ff));
	
	totimg.CreateBlank(FGrid->GetColumns()*FGrid->GetGridSize(), FGrid->GetRows()*FGrid->GetGridSize(), ITYPE_RGB, 32);
	totimg.MaskTo(RGBMask(0xff0000,0x00ff00,0x0000ff));
	
	//		GridName=dlg.GetPathName();
	//		BaseName=GridName.Left(GridName.ReverseFind('.'));
	
	int zrow, zcol;
	
	for(zrow=0;zrow<ZoneCountY;zrow++)
	{
		for(zcol=0;zcol<ZoneCountX;zcol++)
		{
			CString subDirName;
			
			subDirName.Format("%s\\%c%c", DirName, 'A'+ZoneCountY-zrow-1, 'A'+ZoneCountX-zcol-1);
			
			if(!gos_DoesFileExist(subDirName))
			{
				gos_CreateDirectory(subDirName);
			}
			int row, col;
			
			for(row=0;row<8;row++)
			{
				for(col=0;col<8;col++)
				{
					
					BYTE *imgdat=imgseg.Lock();		
					
					if(!FGrid->ComposeGrid(row+zrow*8, col+zcol*8, imgdat))
					{
						for(int i=0;i<FGrid->GetGridSize()*FGrid->GetGridSize()*4;i++)
						{
							imgdat[i]=i%FGrid->GetGridSize();
						}
					}
					
					imgseg.UnLock();
					totimg.Blt(
						imgseg,
						(col+zcol*8)*FGrid->GetGridSize(),
						(row+zrow*8)*FGrid->GetGridSize(),
						CRect(0,0,FGrid->GetGridSize(),FGrid->GetGridSize())
						);
					
				}
			}
			
			{
				int iw = totimg.GetWidth()/(2*ZoneCountX);
				int ih = totimg.GetHeight()/(2*ZoneCountY);
				int i, j;
				
				for(j=0;j<2;j++)
				{
					for(i=0;i<2;i++)
					{
						imgseg.Blt(
							totimg, 
							CRect(
							0,
							0,
							imgseg.GetWidth(),
							imgseg.GetHeight()
							),
							CRect(
							zcol*8*FGrid->GetGridSize()+i*iw,
							zrow*8*FGrid->GetGridSize()+j*ih,
							zcol*8*FGrid->GetGridSize()+(i+1)*iw,
							zrow*8*FGrid->GetGridSize()+(j+1)*ih
							)
							);		
						
						ImgName.Format("%s\\%c%c\\%s_%c%c_1_%02X%02X.tga",
							DirName,
							'A'+ZoneCountY-zrow-1,
							'A'+ZoneCountX-zcol-1,
							BaseName,
							'A'+ZoneCountY-zrow-1,
							'A'+ZoneCountX-zcol-1,
							i,
							j
							);
						
						savimg=imgseg;
						savimg.MakeRGB24();
						savimg.SaveTga((char *)(LPCSTR)ImgName);
					}
				}
			}
			
			imgseg.Blt(
				totimg, 
				CRect(
				0,
				0,
				imgseg.GetWidth(),
				imgseg.GetHeight()
				),
				CRect(
				zcol*8*FGrid->GetGridSize(),
				zrow*8*FGrid->GetGridSize(),
				zcol*8*FGrid->GetGridSize() + (totimg.GetWidth()/ZoneCountX),
				zrow*8*FGrid->GetGridSize() + (totimg.GetHeight()/ZoneCountY)
				)
				);		
			
			ImgName.Format("%s\\%c%c\\%s_%c%c_0_0000.Tga",
				DirName,
				'A'+ZoneCountY-zrow-1,
				'A'+ZoneCountX-zcol-1,
				BaseName,
				'A'+ZoneCountY-zrow-1,
				'A'+ZoneCountX-zcol-1
				);
			
			savimg=imgseg;
			savimg.MakeRGB24();
			savimg.SaveTga((char *)(LPCSTR)ImgName);
			}
		}
		
}

void CImageGrinderDoc::OnFileExportImagedata() 
{
	Compost::Feature_Texture *FTexture;
	Stuff::TableIteratorOf<Compost::Feature_Texture*, int> imageTableIterator(Compost::TexturePool::Instance->GetImageTable());
	
	CString tgaFileName, bidFileName;
	while(NULL!=(FTexture = imageTableIterator.ReadAndNext()))
	{
		if(FTexture->GetName() && (FTexture->dataSize > 0))
		{
			tgaFileName = Compost::TexturePool::Instance->GetTexturePath();
			tgaFileName += "\\";
			tgaFileName += *(FTexture->GetName());
			tgaFileName += ".tga";
			
			bidFileName = Compost::TexturePool::Instance->GetTexturePath();
			bidFileName += "\\";
			bidFileName += *(FTexture->GetName());
			bidFileName += ".bid";
			
			HGOSFILE hfile;
			gos_OpenFile(&hfile, bidFileName, READWRITE);
			gos_WriteFile(hfile, FTexture->data, FTexture->dataSize);
			gos_CloseFile(hfile);
		}
	}
}


void CImageGrinderDoc::OnFileExportSingletga() 
{
	CString ImgName,BaseName,GridName;
	GridName=GetTitle();
	BaseName=GridName.Left(GridName.ReverseFind('.'));
	
	CFileDialog dlg(FALSE,"Tga",BaseName+".tga",NULL,"Targa Images (*.tga)|*.tga||",NULL);
	if(dlg.DoModal()==IDOK)
	{
		Image imgseg,totimg;
		
		
		imgseg.CreateBlank(FGrid->GetGridSize(),FGrid->GetGridSize(),ITYPE_RGB,32);
		imgseg.MaskTo(RGBMask(0xff0000,0x00ff00,0x0000ff));
		
		totimg.CreateBlank(FGrid->GetRows()*FGrid->GetGridSize(),FGrid->GetColumns()*FGrid->GetGridSize(),ITYPE_RGB,24);
		totimg.MaskTo(RGBMask(0xff0000,0x00ff00,0x0000ff));
		
		
		int row,col;
		for(row=0;row<FGrid->GetRows();row++)
			for(col=0;col<FGrid->GetColumns();col++)
			{
				BYTE *imgdat=imgseg.Lock();		
				
				if(!FGrid->ComposeGrid(row,col,imgdat))
					for(int i=0;i<FGrid->GetGridSize()*FGrid->GetGridSize()*3;i++) imgdat[i]=i%FGrid->GetGridSize();
					
					imgseg.UnLock();
					totimg.Blt(imgseg,col*FGrid->GetGridSize(),row*FGrid->GetGridSize(),CRect(0,0,FGrid->GetGridSize(),FGrid->GetGridSize()));
			}
			
			
			imgseg.Blt(totimg, CRect(0,0,imgseg.GetWidth(),imgseg.GetHeight()) ,
				CRect(0,0,totimg.GetWidth(),totimg.GetHeight()));		
			
			totimg.SaveTga((char *)(LPCSTR)dlg.GetPathName());
	}	
	
}

bool CImageGrinderDoc::IsSelected(Compost::FeatureInstance *fetint)
{
	return fetint->StatFlags&FIF_SELECTED?true:false;
	
}

bool CImageGrinderDoc::IsSelected(Compost::Tool_Feature *fet)
{
	if(fet==NULL) return false;
	
	
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	
	int CurFet;
	
	for(CurFet=0;CurFet<count;CurFet++)
		if((*FList)[CurFet]->StatFlags&FIF_SELECTED && (*FList)[CurFet]->feature==fet)
			return true;
		
		
		return false;
}

Compost::FeatureInstance *CImageGrinderDoc::GetTopFeature(CPoint &pnt)
{
	
	int selfet,depth;
	depth=FGrid->ShootRay((unsigned short)pnt.x,(unsigned short)pnt.y);
	if(depth<=1) return NULL;
	
	for(selfet=1;selfet<depth && !IsSelected(FGrid->GetCollectedNr(selfet)) && !IsLocked(FGrid->GetCollectedNr(selfet));selfet++);
	
	return FGrid->GetCollectedNr(depth-1);
}	

Compost::FeatureInstance *CImageGrinderDoc::GetTopSelected(CPoint &pnt)
{
	
	int selfet,depth;
	depth=FGrid->ShootRay((unsigned short)pnt.x,(unsigned short)pnt.y);
	if(depth<=1) return NULL;
	
	for(selfet=1;selfet<depth && !IsSelected(FGrid->GetCollectedNr(selfet)) && !IsLocked(FGrid->GetCollectedNr(selfet));selfet++);
	
	if(selfet<depth)
	{
		return FGrid->GetCollectedNr(selfet);
	}
	
	return NULL;
}

DWORD CImageGrinderDoc::IsOnScaleHandle(CPoint &pnt,Compost::FeatureInstance *fetint)
{
	if(!fetint) 
		return HF_NONE;
	if(pnt.x<fetint->feature_x_pos || pnt.y<fetint->feature_z_pos ||
		pnt.x>=(fetint->feature->GetFeatureWidth()+fetint->feature_x_pos) ||
		pnt.y>=(fetint->feature->GetFeatureHeight()+fetint->feature_z_pos) )
		return HF_NONE;
	
	DWORD flg=HF_NONE;
	
	if((pnt.x-fetint->feature_x_pos)<HANDLESIZE) 
		flg|=HF_LEFT;
	else
		if(((fetint->feature->GetFeatureWidth()+fetint->feature_x_pos)-pnt.x)<HANDLESIZE) 
			flg|=HF_RIGHT;
		
		if((pnt.y-fetint->feature_z_pos)<HANDLESIZE) 
			flg|=HF_TOP;
		else
			if(((fetint->feature->GetFeatureHeight()+fetint->feature_z_pos)-pnt.y)<HANDLESIZE) 
				flg|=HF_BOTTOM;
			
			return flg;
}

bool CImageGrinderDoc::IsOnSelectHandle(CPoint &pnt,Compost::FeatureInstance *fetint)
{
	if(!fetint) 
		return false;
	
	if(pnt.x<fetint->feature_x_pos || pnt.y<fetint->feature_z_pos ||
		pnt.x>=(fetint->feature->GetFeatureWidth()+fetint->feature_x_pos) ||
		pnt.y>=(fetint->feature->GetFeatureHeight()+fetint->feature_z_pos) )
		return false;
	
	DWORD flg=HF_NONE;
	CRect rct(-HANDLESIZE/2,-HANDLESIZE/2,HANDLESIZE/2,HANDLESIZE/2);
	CPoint ct(fetint->feature_x_pos+fetint->feature->GetFeatureWidth()/2,fetint->feature_z_pos+fetint->feature->GetFeatureHeight()/2);
	rct.OffsetRect(ct);
	return rct.PtInRect(pnt)?true:false;
}

bool CImageGrinderDoc::IsOnSelectHandle(CPoint &pnt)
{
	
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	
	int CurFet;
	
	for(CurFet=0;CurFet<count;CurFet++)
		if((*FList)[CurFet]->StatFlags&FIF_SELECTED && IsOnSelectHandle(pnt,(*FList)[CurFet]))
		{
			NewSelection((*FList)[CurFet]);
			return true;
		}
		
		return false;
		
}


void CImageGrinderDoc::MakeSelectedUnique()
{
	
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	
	int CurFet;
	
	for(CurFet=0;CurFet<count;CurFet++)
		if((*FList)[CurFet]->StatFlags&FIF_SELECTED)
			MakeUnique((*FList)[CurFet]);
		
}

CString CImageGrinderDoc::MakeNameUnique(CString &istr)
{
	
	
	if(!InList(istr)) 
	{
		return istr;
	}
	else
	{
		CString bstr;
		
		if(istr.FindOneOf("0123456789")==-1)
			bstr=istr;
		else
			bstr=istr.Left(istr.FindOneOf("0123456789"));
		
		int num=0;
		CString fstr;
		do
		{
			fstr.Format("%s%04i",bstr,num);
			num++;
		}
		while(InList(fstr));
		
		return fstr;
	}
}

bool CImageGrinderDoc::InList(CString &str)
{
	
	ASSERT(FPool!=NULL && FGrid!=NULL);
	
	Compost::Feature *Fet;
	
	int itmtot=FPool->GetNumberOfFeatures();
	for(int i=1;i<itmtot;i++)
	{
		Fet=FPool->GetFeatureNumber(i);
		CString tstr((char *)(*(Fet->GetName())));
		if(tstr.CompareNoCase(str)==0) return true;
	}
	
	return false;
}

void CImageGrinderDoc::MakeUnique(Compost::FeatureInstance *fetint)
{
	
	if(FGrid->CountFeature(fetint->feature)>1)
	{
		
		Compost::Tool_Feature *TmpFet=new Compost::Tool_Feature;
		Register_Pointer(TmpFet);
		*TmpFet=*((Compost::Tool_Feature *)fetint->feature);
		
		TmpFet->SetName((LPCSTR)MakeNameUnique(CString(*(fetint->feature->GetName()))));
		FPool->Add(TmpFet);
		
		FGrid->Add(TmpFet, fetint->feature_x_pos,fetint->feature_z_pos);
		FGrid->Remove(fetint);
		
		SetModifiedFlag(TRUE);
		UpdateAllViews(NULL);
	}
}

void CImageGrinderDoc::CloneSelection()
{
	
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	
	int CurFet;
	
	for(CurFet=0;CurFet<count;CurFet++)
		if((*FList)[CurFet]->StatFlags&FIF_SELECTED)
		{
			Clone((*FList)[CurFet]);
		}
		
}

Compost::FeatureInstance *CImageGrinderDoc::Clone(Compost::FeatureInstance *fetint)
{
	Compost::FeatureInstance *newfet;
	newfet=FGrid->Add(fetint->feature, fetint->feature_x_pos,fetint->feature_z_pos);
	SetModifiedFlag(TRUE);
	
	
	return newfet;
}

bool CImageGrinderDoc::IsHLFeature(Compost::FeatureInstance *fetint)
{
	return	((Compost::Tool_Feature *)fetint->feature)->StatFlags&FF_HIGHLIGHTED?true:false;
}

void CImageGrinderDoc::AddHLFeature(Compost::Tool_Feature *fet)
{
	fet->StatFlags|=FF_HIGHLIGHTED;
}

void CImageGrinderDoc::SubHLFeature(Compost::Tool_Feature *fet)
{
	fet->StatFlags&=~FF_HIGHLIGHTED;
}

void CImageGrinderDoc::LockFeature(Compost::FeatureInstance  *fet)
{
	fet->StatFlags|=FIF_LOCKED;
	fet->StatFlags&=~FIF_SELECTED;
	
}

void CImageGrinderDoc::LockSelection()
{
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	
	int CurFet;
	
	for(CurFet=0;CurFet<count;CurFet++)
		if((*FList)[CurFet]->StatFlags&FIF_SELECTED)
			LockFeature((*FList)[CurFet]);
		
		
		
}

void CImageGrinderDoc::UnLockFeature(Compost::FeatureInstance  *fet)
{
	fet->StatFlags&=~FIF_LOCKED;
	
}

bool CImageGrinderDoc::IsLocked(Compost::FeatureInstance  *fet)
{
	if(fet->StatFlags&FIF_LOCKED)
		return true;
	else 
		return false;
	
}

void CImageGrinderDoc::ClearHL()
{
	int count;
	int CurFet;
	
	
	count=FPool->GetNumberOfFeatures();
	
	for(CurFet=0;CurFet<count;CurFet++)
	{
		Compost::Tool_Feature *temfet=((Compost::Tool_Feature *)FPool->GetFeatureNumber(CurFet));
		temfet->StatFlags&=~FF_HIGHLIGHTED;
	}
}

void CImageGrinderDoc::UnLockAll()
{
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	int CurFet;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	
	
	
	for(CurFet=0;CurFet<count;CurFet++)
		UnLockFeature((*FList)[CurFet]);
	
}

void CImageGrinderDoc::ClearSelection()
{
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	int CurFet;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	
	
	
	for(CurFet=0;CurFet<count;CurFet++)
		SubSelection((*FList)[CurFet]);
	
}

void CImageGrinderDoc::MakeWorldSpaceTexture(Compost::FeatureInstance  *fet)
{
	fet->StatFlags|=FIF_WSTEXTURE;
}

void CImageGrinderDoc::MakeLocalTexture(Compost::FeatureInstance  *fet)
{
	fet->StatFlags&=~FIF_WSTEXTURE;
}

void CImageGrinderDoc::SetFlagOnSelection(UINT flg)
{
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	
	int CurFet;
	
	for(CurFet=0;CurFet<count;CurFet++)
		if((*FList)[CurFet]->StatFlags&FIF_SELECTED)
			(*FList)[CurFet]->StatFlags|=flg;
		
}

void CImageGrinderDoc::ClearFlagOnSelection(UINT flg)
{
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	
	int CurFet;
	
	for(CurFet=0;CurFet<count;CurFet++)
		if((*FList)[CurFet]->StatFlags&FIF_SELECTED)
			(*FList)[CurFet]->StatFlags&=~flg;
		
		
}

void CImageGrinderDoc::GroupSelection()
{
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	
	int CurFet;
	int NewTag=GetAvailableTag();
	
	for(CurFet=0;CurFet<count;CurFet++)
		if((*FList)[CurFet]->StatFlags&FIF_SELECTED)
			(*FList)[CurFet]->Tag=NewTag;
		
		
}

void CImageGrinderDoc::UnGroupSelection()
{
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	
	int CurFet;
	
	for(CurFet=0;CurFet<count;CurFet++)
		if((*FList)[CurFet]->StatFlags&FIF_SELECTED)
			(*FList)[CurFet]->Tag=0;
		
}

int CImageGrinderDoc::GetAvailableTag()
{
	int Tag;
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	
	int CurFet;
	
	Tag=0;
	do
	{
		Tag++;
		for(CurFet=0;CurFet<count && (*FList)[CurFet]->Tag!=Tag;CurFet++);
	}
	while(CurFet<count);
	
	if(Tag>=256) return 0;
	else
		return Tag;
}

void CImageGrinderDoc::SelectGroupMembers(Compost::FeatureInstance  *fet)
{
	if(fet->Tag==0) return;
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	
	int CurFet;
	
	for(CurFet=0;CurFet<count;CurFet++)
		if(fet->Tag==(*FList)[CurFet]->Tag)
		{
			(*FList)[CurFet]->StatFlags|=FIF_SELECTED;
			((Compost::Tool_Feature *)(*FList)[CurFet]->feature)->StatFlags|=FF_HIGHLIGHTED;
		}
		
}

void CImageGrinderDoc::DeSelectGroupMembers(Compost::FeatureInstance  *fet)
{
	if(fet->Tag==0) return;
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	
	int CurFet;
	
	for(CurFet=0;CurFet<count;CurFet++)
		if(fet->Tag==(*FList)[CurFet]->Tag)
			(*FList)[CurFet]->StatFlags&=~FIF_SELECTED;
		
}

void CImageGrinderDoc::OnFileMergefeatures() 
{
	CFileDialog dlg(TRUE,NULL,NULL,NULL,"Image Gringer files (*.fgd)|*.fgd||");	
	
	if(dlg.DoModal()==IDOK)
	{
		Compost::FeaturePool *TmpFPool;
		
		
		TmpFPool = new Compost::FeaturePool();
		Register_Pointer(TmpFPool);
		
		
		Check_Object(Stuff::FileStreamManager::Instance);
		Stuff::FileStream *fstr=new Stuff::FileStream;
		Register_Object(fstr);
		fstr->Open(dlg.GetPathName(),Stuff::FileStream::ReadOnly);
		TmpFPool->LoadIndex(fstr);
		//		fstr->Close();
		Unregister_Object(fstr);
		delete fstr;
		
		int i, fettot=TmpFPool->GetNumberOfFeatures();
		
		for(i=0;i<fettot;i++)
		{
			Compost::Tool_Feature *TmpFet=new Compost::Tool_Feature;
			Register_Pointer(TmpFet);
			
			*TmpFet=*((Compost::Tool_Feature *)TmpFPool->GetFeatureNumber(i));
			FPool->Add(TmpFet);
		}
		
		Unregister_Pointer(TmpFPool);
		delete TmpFPool;
		
		UpdateAllViews(NULL);
		SetModifiedFlag(TRUE);
	}
	
	
	
}

void CImageGrinderDoc::RemoveFeature(Compost::Tool_Feature *fet)
{
	
	
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	
	
	int CurFet;
	
	do
	{
		FList=FGrid->GetUniqueFeatureInstances(count);
		for(CurFet=0;CurFet<count && ((*FList)[CurFet]->feature!=fet);CurFet++);
		
		if(CurFet<count)
		{
			if(FPool->GetFeaturePosition((*FList)[CurFet]->feature)==0) return;
			SetDrawFlags((*FList)[CurFet]);	
			FGrid->Remove((*FList)[CurFet]);
		}
		
	}
	while(CurFet<count);
	
	FGrid->RedoFeaturePosition();
	
	
	
	
	FPool->Remove(fet);
	delete fet;
	
	SetModifiedFlag();
}



void CImageGrinderDoc::MakeSelectionWorldSpaceTexture()
{
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	
	int CurFet;
	
	for(CurFet=0;CurFet<count;CurFet++)
		if((*FList)[CurFet]->StatFlags&FIF_SELECTED && !((*FList)[CurFet]->StatFlags&FIF_WSTEXTURE))
		{
			MakeWorldSpaceTexture((*FList)[CurFet]);
			SetDrawFlags((*FList)[CurFet]);
		}
		
		SetModifiedFlag();
}

void CImageGrinderDoc::MakeSelectionLocalTexture()
{
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	
	int CurFet;
	
	for(CurFet=0;CurFet<count;CurFet++)
		if((*FList)[CurFet]->StatFlags&FIF_SELECTED && (*FList)[CurFet]->StatFlags&FIF_WSTEXTURE)
		{
			MakeLocalTexture((*FList)[CurFet]);
			SetDrawFlags((*FList)[CurFet]);
		}
		SetModifiedFlag();
}

int CStringCompare( const void *arg1, const void *arg2 )
{
	
	return ((CString *)arg1)->CompareNoCase(*((CString *)arg2));
}

void CImageGrinderDoc::OnFileExportUsedimagelist() 
{
	CString *name_list;
	int *used_count;
	int image_count;
	
	Compost::Feature_Texture *FTexture;
		Stuff::TableIteratorOf<Compost::Feature_Texture*, int> imageTableIterator(Compost::TexturePool::Instance->GetImageTable());

	image_count=imageTableIterator.GetSize();
	name_list=new CString[image_count];
	used_count=new int[image_count];
	
	imageTableIterator.First();
	{
	int cpos=0;
	while(NULL!=(FTexture=imageTableIterator.ReadAndNext()))
	{
		name_list[cpos]=(char *)(*(FTexture->GetName()));
		used_count[cpos]=0;
		cpos++;
	}
	
	Verify(cpos==image_count);
	}
	
	qsort(name_list,image_count,sizeof(CString),CStringCompare);
		
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	int CurFet;
	Stuff::MString *mstr;
	Compost::Tool_Feature *feature = NULL;
	Compost::Feature_Texture *fTexture = NULL;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	for(CurFet=0;CurFet<count;CurFet++)
	{
		feature=((Compost::Tool_Feature *)(*FList)[CurFet]->feature);
			Check_Pointer(feature);
		fTexture = feature->GetFeatureTexture();
		Check_Object(fTexture);
		
		int tpos;
		
		mstr = fTexture->GetName();
		for(tpos=0;tpos<image_count && name_list[tpos].CompareNoCase((char *)*mstr);tpos++);
		if(tpos>=image_count) PAUSE(("Texture Count Problem"));
		used_count[tpos]++;
		
		fTexture = feature->GetFeatureMask0();
		if(fTexture != NULL)
		{
			mstr = fTexture->GetName();
			for(tpos=0;tpos<image_count && name_list[tpos].CompareNoCase((char *)*mstr);tpos++);
			if(tpos>=image_count) PAUSE(("Texture Count Problem"));
			used_count[tpos]++;
		}
		
		fTexture = feature->GetFeatureMask1();
		if(fTexture != NULL)
		{
			mstr = fTexture->GetName();
			for(tpos=0;tpos<image_count && name_list[tpos].CompareNoCase((char *)*mstr);tpos++);
			if(tpos>=image_count) PAUSE(("Texture Count Problem"));
			used_count[tpos]++;
		}
		
		
	}
	
		
		CString BaseName, GridName;
		GridName=GetTitle();
		BaseName=GridName.Left(GridName.ReverseFind('.'));
		
		CFileDialog dlg(FALSE,"bat",BaseName+"BidCopy.bat",NULL,"batch files (*.bat)|*.bat||",NULL);
		if(dlg.DoModal()==IDOK)
		{
			FILE *fl;
			fl=fopen(dlg.GetPathName(),"w");
			Verify(fl);
			if(fl)
			{
				for(int i=0;i<image_count;i++)
					if(used_count[i]>0)
					{
						fprintf(fl,"copy %s.bid %%1 /y\n",name_list[i]);
						fprintf(fl,"copy %s.tga %%2 /y\n",name_list[i]);
					}
			fclose(fl);
			}
		}
	delete used_count;	
//	delete name_list;
}

void CImageGrinderDoc::SaveAs(LPCTSTR lpszPathName,int xoffset,int zoffset)
{
	SaveText(lpszPathName,xoffset,zoffset);
	
	CString ImgName, BaseName, GridName;
	GridName=lpszPathName;
	BaseName=GridName.Left(GridName.ReverseFind('.'));
	
}

void CImageGrinderDoc::ExportMaterialMap(CString &path)
{
	CString ImgName,DirName=path;
	
	
	Verify((FGrid->GetRows()%8)==0);
	Verify((FGrid->GetColumns()%8)==0);
	int ZoneCountX = FGrid->GetColumns()/8;
	int ZoneCountY = FGrid->GetRows()/8;
	
	
	Image imgseg,totimg,savimg;
	
	imgseg.CreateBlank(256,256,ITYPE_RGB,32);
	imgseg.MaskTo(RGBMask(0xff0000,0x00ff00,0x0000ff));
	
	totimg.CreateBlank(8*256,8*256,ITYPE_RGB,32);
	totimg.MaskTo(RGBMask(0xff0000,0x00ff00,0x0000ff));
	
	savimg.CreateBlank(256,256,ITYPE_INDEXED,8);
	savimg.MakeGrayscalePalette();
	

	int zrow, zcol;
	
	for(zrow=0;zrow<ZoneCountY;zrow++)
	{
		for(zcol=0;zcol<ZoneCountX;zcol++)
		{
			
			int row, col;
			
			for(row=0;row<8;row++)
			{
				for(col=0;col<8;col++)
				{
					
					BYTE *imgdat=imgseg.Lock();		
					
					if(!FGrid->ComposeGrid(row+zrow*8, col+zcol*8, imgdat, 0, 2))
					{
						for(int i=0;i<FGrid->GetGridSize()*FGrid->GetGridSize()*4;i++)
						{
							imgdat[i]=i%FGrid->GetGridSize();
						}
					}
					
					//						imgseg.SaveTga("C:\\temp\\SourceMat1.tga");
					imgseg.UnLock();
					totimg.Blt(
						imgseg,
						(col*256),
						(row*256),
						CRect(0,0,256,256)
						);
					
				}
			}
			
			imgseg.BltDominantColor(
				totimg, 
				CRect(
				0,
				0,
				imgseg.GetWidth(),
				imgseg.GetHeight()
				),
				CRect(
				0,
				0,
				totimg.GetWidth(),
				totimg.GetHeight()
				)
				);		
			
	
			
			
			DWORD *srcptr=(DWORD *)imgseg.Lock();
			BYTE *dstptr=savimg.Lock();
			int xps,yps;
			BYTE colidx;
			DWORD tcol;
			for(yps=0;yps<imgseg.GetHeight();yps++)
				for(xps=0;xps<imgseg.GetWidth();xps++)
				{
					tcol=srcptr[xps+yps*savimg.GetWidth()];
					
					for(colidx=0;colidx<Compost::MaterialEntriesCount;colidx++)
					{
						if(Compost::MaterialEntries[colidx].color==tcol)
						{
							break;
						}
					}
					Verify(colidx<Compost::MaterialEntriesCount);
					
					dstptr[xps+yps*savimg.GetWidth()]=colidx;
				}
				
				imgseg.UnLock();
				savimg.UnLock();

				ImgName.Format("%s\\%c%c.Material",
				DirName,
				'A'+ZoneCountY-zrow-1,
				'A'+ZoneCountX-zcol-1
				);

				savimg.SaveRaw((char *)(LPCSTR)ImgName);
		}


	}
	
	
	
}


void CImageGrinderDoc::ExportSingleMaterialMap(CString &path)
{
	CString ImgName,DirName=path;
	
	
	Verify((FGrid->GetRows()%8)==0);
	Verify((FGrid->GetColumns()%8)==0);
	int ZoneCountX = FGrid->GetColumns()/8;
	int ZoneCountY = FGrid->GetRows()/8;
	
	
	Image imgseg,totimg;
	
	imgseg.CreateBlank(256,256,ITYPE_RGB,32);
	imgseg.MaskTo(RGBMask(0xff0000,0x00ff00,0x0000ff));
	
	totimg.CreateBlank(1024*ZoneCountX,1024*ZoneCountY,ITYPE_RGB,32);
	totimg.MaskTo(RGBMask(0xff0000,0x00ff00,0x0000ff));
	
	int zrow, zcol;
	
	for(zrow=0;zrow<ZoneCountY;zrow++)
	{
		for(zcol=0;zcol<ZoneCountX;zcol++)
		{
			
			int row, col;
			
			for(row=0;row<8;row++)
			{
				for(col=0;col<8;col++)
				{
					
					BYTE *imgdat=imgseg.Lock();		
					
					if(!FGrid->ComposeGrid(row+zrow*8, col+zcol*8, imgdat, 0, 2))
					{
						for(int i=0;i<FGrid->GetGridSize()*FGrid->GetGridSize()*4;i++)
						{
							imgdat[i]=i%FGrid->GetGridSize();
						}
					}
					
					//						imgseg.SaveTga("C:\\temp\\SourceMat1.tga");
					imgseg.UnLock();
					totimg.BltDominantColor(
						imgseg,
						CRect(
						zcol*1024+col*128,
						zrow*1024+row*128,
						zcol*1024+col*128+128,
						zrow*1024+row*128+128
							),
						CRect(0,0,256,256)
						);
					
				}
			}
			
		}

	}
	
			
					totimg.SaveTga((char *)(LPCSTR)path);
	
	
}


CString CImageGrinderDoc::MapPath()
{
	CString path = Compost::TexturePool::Instance->GetTexturePath();
	path=path.Left(path.ReverseFind('\\'));
	path=path.Left(path.ReverseFind('\\'));
	path+="\\Maps\\";
	path+=GetTitle();
	path=path.Left(path.ReverseFind('.'));
	return path;
}

void CImageGrinderDoc::OnFileExportMaterialmap() 
{
	CString path = MapPath();
	
	if(!gos_DoesFileExist(path))
		gos_CreateDirectory(path);
	
	ExportMaterialMap(path);
	
}

void CImageGrinderDoc::SavePosForUndo()
{
	
	UndoCommand *com=NULL;
	
	
	const Stuff::DynamicArrayOf<Compost::FeatureInstance*> *FList;
	int count;
	
	FList=FGrid->GetUniqueFeatureInstances(count);
	
	int CurFet;
	
	
	for(CurFet=0;CurFet<count;CurFet++)
		if((*FList)[CurFet]->StatFlags&FIF_SELECTED)
		{
			MoveCommand *mcom=new MoveCommand((*FList)[CurFet],this);
			if(com==NULL) com=mcom; else com->Attach(mcom);
		}
		
		if(com!=NULL) 	UndoMan.AddCommand(com);
		
}

void CImageGrinderDoc::SaveToGame()
{
	CString bname=GetTitle();
	bname=bname.Left(bname.ReverseFind('.'));
	SaveFgd(MapPath()+"\\"+bname+".fgd");
}

void CImageGrinderDoc::SaveIGDataToGame()
{
	CString bname=GetTitle();
	bname=bname.Left(bname.ReverseFind('.'));
	SaveText(MapPath()+"\\"+bname+".IGData");
}


void CImageGrinderDoc::SaveFgd(LPCTSTR lpszPathName,int xoffset,int zoffset)
{
	
	Check_Object(Stuff::FileStreamManager::Instance);
	Stuff::FileStream *fstr=new Stuff::FileStream;
	Register_Object(fstr);
	fstr->Open(lpszPathName,Stuff::FileStream::WriteOnly);
	FPool->SaveIndex(fstr);
	FGrid->SaveGrid(fstr,xoffset,zoffset);	
	
	Unregister_Object(fstr);
	delete fstr;
	
}	

void CImageGrinderDoc::SaveText(LPCTSTR lpszPathName,int xoffset,int zoffset)
{
	
	Check_Object(Stuff::FileStreamManager::Instance);
	Stuff::NotationFile note_file(lpszPathName);
	note_file.DeleteAllPages();
	Stuff::Page *page=note_file.SetPage(NULL);
	Check_Object(page);
	page->SetEntry("!concatenate","no");

	FPool->SaveIndex(&note_file);
	FGrid->SaveGrid(&note_file,xoffset,zoffset);	
	note_file.Save();
}

void CImageGrinderDoc::CloseCurrent()
{
	if(FPool)
	{
		Unregister_Pointer(FPool);
		delete FPool;
	}
	
	if(FGrid)
	{
		Unregister_Pointer(FGrid);
		delete FGrid;
	}
	
	CurSelFet=NULL;
	
	if(UpdateList) delete UpdateList;
	
}

void CImageGrinderDoc::OpenFgd(LPCTSTR lpszPathName)
{
	
	FPool = new Compost::FeaturePool();
	Register_Pointer(FPool);
	
	Check_Object(Stuff::FileStreamManager::Instance);
	Stuff::FileStream *fstr=new Stuff::FileStream;
	Register_Object(fstr);
	fstr->Open(lpszPathName,Stuff::FileStream::ReadOnly);
	FPool->LoadIndex(fstr);
	FGrid = new Compost::FeatureGrid(fstr, FPool);
	Register_Pointer(FGrid);
	Unregister_Object(fstr);
	delete fstr;
	
	ClearSelection();
}

void CImageGrinderDoc::OpenText(LPCTSTR lpszPathName)
{
	
	
	FPool = new Compost::FeaturePool();
	Register_Pointer(FPool);
	
	
	Check_Object(Stuff::FileStreamManager::Instance);
	Stuff::NotationFile note_file(lpszPathName);
	FPool->LoadIndex(&note_file);
	FGrid = new Compost::FeatureGrid(&note_file, FPool);
	Register_Pointer(FGrid);
	ClearSelection();

}

void CImageGrinderDoc::PostLoadInit()
{
	if(Compost::TexturePool::Instance->IsChanged()==true)
	{
		Compost::TexturePool::Instance->SaveIndex(NULL);
	}
	
	
	UpdateList=new bool[FGrid->GetRows()*FGrid->GetColumns()];
	SetDrawFlags();
	
}

void CImageGrinderDoc::OnFileExportSinglematerialmap() 
{
	CString ImgName,BaseName,GridName;
	GridName=GetTitle();
	BaseName=GridName.Left(GridName.ReverseFind('.'));
	CString path = MapPath();
	
	if(!gos_DoesFileExist(path))
		gos_CreateDirectory(path);
	
	CFileDialog dlg(FALSE,"Tga",BaseName+"Material.tga",NULL,"Targa Images (*.tga)|*.tga||",NULL);
	if(dlg.DoModal()==IDOK)
	{
	ExportSingleMaterialMap(dlg.GetPathName());
	}
	
}
