#include "MAXProxyHeaders.hpp"
#include <GameOS\ToolOS.hpp>

//
//############################################################################
//##############################    MAXScene    ###############################
//############################################################################
//

INode *CreateNode(Interface *ip,SClass_ID superID,Class_ID classid);

MAXScene::ClassData*
	MAXScene::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MAXScene::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			MAXSceneClassID,
			"MAXScene",
			SceneProxy::DefaultData
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MAXScene::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MAXScene::Destroy()
{
	Check_Object(this);
	Verify(referenceCount == 1);
	Verify(activeChildProxies.IsEmpty());
	STOP(("Not implemented"));
	DetachReference();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MAXScene::MAXScene(Interface *i,const char *str):
	SceneProxy(DefaultData)
{
	Check_Pointer(this);
	//
	// keep the interface pointer on hand
	//
	iPointer = i;
	//
	// get the time of the first frame and keep it
	// to evaluate the world state for everything
	//
	Interval total_time = iPointer->GetAnimRange();
	time = total_time.Start();
	proxiedScene = i->GetRootNode();
	//
	// load the helper arrays
	//
	int node_count = 0;
	GetMaterials(proxiedScene,node_count);
	nodeCount = node_count;
	meshProxies.SetLength(nodeCount);
	GetBitmaps();
	Check_Object(this);
	notifiedOfError = false;
	Check_Pointer(str);
	strHintFile = str;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MAXScene::~MAXScene()
{
	Check_Object(this);
	
	if (stateLibrary)
	{
		Check_Object(stateLibrary);
		Verify(stateLibrary->GetReferenceCount() == 1);
		stateLibrary->DetachReference();
		Unregister_Object(stateLibrary);
		stateLibrary = NULL;
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MAXScene::TestInstance() const
{
	if (proxiedScene)
	{
		Check_Pointer(proxiedScene);
		Verify(IsDerivedFrom(DefaultData));
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Proxies::StateLibrary*
	MAXScene::GetStateLibrary()
{
	Check_Object(this);
	if (!stateLibrary)
	{
		stateLibrary = MAXStateLibrary::MakeProxy(this);
		Register_Object(stateLibrary);
	}
	Check_Object(stateLibrary);
	return stateLibrary;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	MAXScene::GetName(MString *name)
{
	Check_Object(this);
	Check_Pointer(name);
	Check_Pointer(proxiedScene);
	//
	//----------------------------------------------
	// Get the scene name and check the length
	//----------------------------------------------
	//
	TCHAR *string = proxiedScene->GetName();
	int len = strlen(string);
	if (len != 0)
	{
		*name = string;
		return true;
	}
	return false;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MAXScene::SetName(const char* name)
{
	Check_Object(this);
	Check_Pointer(name);
	Check_Pointer(proxiedScene);
	TCHAR *string = (TCHAR *)name;
	proxiedScene->SetName(string);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	MAXScene::GetOBB(OBB *obb)
{
	Check_Object(this);
	Check_Pointer(obb);
	return false;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MAXScene::SetOBB(const OBB &obb)
{
	Check_Object(this);
	Check_Object(&obb);
	STOP(("Not implemented"));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MAXScene::SetBoundingSphere(const Sphere &sphere)
{
	Check_Object(this);
	Check_Object(&sphere);
	STOP(("Not implemented"));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
unsigned
	MAXScene::GetChildCount()
{
	Check_Object(this);
	Check_Pointer(proxiedScene);
	return proxiedScene->NumberOfChildren();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Proxies::GroupProxy*
	MAXScene::AppendNewGroupProxy()
{
	Check_Object(this);
	Check_Object(this);

	int time = 0;
	int index = 0;
	INode *child = CreateNode(iPointer,HELPER_CLASS_ID,Class_ID(DUMMY_CLASS_ID,0));
	MAXGroup *proxy =	MAXGroup::MakeProxy(this, NULL, child, time, index, true);
	Check_Object(proxy);
	return proxy;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Proxies::GroupProxy*
	MAXScene::InsertNewGroupProxy(Proxies::ChildProxy *before)
{
	Check_Object(this);
	Check_Object(before);
	Verify(!before->GetParentGroupProxy());
	STOP(("Not implemented"));
	return NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
INode *CreateNode(Interface *ip,SClass_ID superID,Class_ID classid)
{
	Check_Pointer(ip);
	//Object *obj = (Object*)ip->CreateInstance(GEOMOBJECT_CLASS_ID, Class_ID(TRIOBJ_CLASS_ID,0));
	Object *obj = (Object*)ip->CreateInstance(superID,classid);
	Check_Pointer(obj);

	// Get a hold of the parameter block
	//IParamArray *iParams = obj->GetParamBlock();
	//Check_Pointer(iParams);

	// Set the parameters
	// Set to a default material
	//iParams->SetValue(CV_MATERIAL,TimeValue(0),MechWarrior4::SteelMaterial);


	INode *new_node = ip->CreateObjectNode(obj);



/*	{
		CString nodename = inode->GetName();
		int index = nodename.Find("_",0);
		if (index >=0)
			nodename.Delete(0,index+1);
		CString name = "cv_";
		name += nodename;
		new_node->SetName(name.GetBuffer(50));
	}
*/
/*riObject *meshData;
	Verify(os.obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0)));
	meshData = (TriObject *) os.obj->ConvertToType(0,Class_ID(TRIOBJ_CLASS_ID, 
	0));*/
/*	meshData->mesh.buildBoundingBox();

	Box3 box;
	box = meshData->mesh.getBoundingBox();
	Point3 pt = box.Width();
	iParams->SetValue(CV_SIZE,TimeValue(0),pt);


	// figure out the correct offset

	Point3 offset;
	offset.x = box.pmin.x - (pt.x*-0.5f);
	offset.y = box.pmin.y - (pt.y*-0.5f);
	offset.z = box.pmin.z - (pt.z*-0.5f);


	Point3 offset_trans = inode->GetObjOffsetPos();
	Quat   offset_rot   = inode->GetObjOffsetRot();

	//SPEW(("jerryeds", "obj-'%s'", inode->GetName()));
	//SPEW(("jerryeds", "qpvt - %f %f %f %f", offset_rot.x, offset_rot.y, 
	offset_rot.z, offset_rot.w));
	//SPEW(("jerryeds", "pvt  - %f %f %f", offset_trans.x, offset_trans.y, 
	offset_trans.z));
	//SPEW(("jerryeds", "pmin - %f %f %f", box.pmin.x, box.pmin.y, box.pmin.z));
	//SPEW(("jerryeds", "pmax - %f %f %f", box.pmax.x, box.pmax.y, box.pmax.z));
	//SPEW(("jerryeds", "pt   - %f %f %f", pt.x, pt.y, pt.z));
	//SPEW(("jerryeds", "ofst - %f %f %f", offset.x, offset.y, offset.z));

	offset.x += offset_trans.x;
	offset.y += offset_trans.y;
	offset.z += offset_trans.z;


	Matrix3 node_tm;
	node_tm.IdentityMatrix();
	offset_rot.MakeMatrix(node_tm);
	node_tm.SetTrans(offset);


	//find nearest joint_ parent node..
	INode *closest_parent = FindParentJoint(inode);
	Check_Pointer(closest_parent);


	new_node->SetNodeTM(0,node_tm);

	closest_parent->AttachChild(new_node,0);
	//SPEW(("jerryeds", "par-'%s'", closest_parent->GetName()));
	*/
	return new_node;
}



Proxies::PolygonMeshProxy*
	MAXScene::AppendNewPolygonMeshProxy()
{
	Check_Object(this);
	INode *pNode = CreateNode(iPointer,GEOMOBJECT_CLASS_ID, Class_ID(TRIOBJ_CLASS_ID,0));
	rootList.AddNode(pNode);
	Proxies::StateLibrary *library = GetStateLibrary();
	MAXProxies::MAXStateLibrary *maxlibrary = Cast_Object(MAXProxies::MAXStateLibrary *,library);
	pNode->SetMtl(maxlibrary->GetMultiMtl());

	proxiedScene->AttachChild(pNode,0);
	TimeValue time = 0;
	int index = 0;
	MAXPolygonMesh *proxy = MAXPolygonMesh::MakeProxy(this, NULL, pNode, time, index, false);
	Register_Object(proxy);

	return proxy;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Proxies::PolygonMeshProxy*
	MAXScene::InsertNewPolygonMeshProxy(Proxies::ChildProxy *before)
{
	Check_Object(this);
	Check_Object(before);
	Verify(!before->GetParentGroupProxy());
	STOP(("Not implemented"));
	return NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Proxies::ChildProxy*
	MAXScene::AppendMatchingChildProxy(Proxies::ChildProxy *child)
{
	Check_Object(this);
	Check_Object(child);
	STOP(("Not implemented"));
	return NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Proxies::ChildProxy*
	MAXScene::InsertMatchingChildProxy(
		Proxies::ChildProxy *child,
		Proxies::ChildProxy *before
	)
{
	Check_Object(this);
	Check_Object(child);
	Check_Object(before);
	Verify(!before->GetParentGroupProxy());
	STOP(("Not implemented"));
	return NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Proxies::ChildProxy*
	MAXScene::UseFirstChildProxy()
{
	Check_Object(this);

	int index = IndexFirstValidElement(iPointer->GetRootNode());

#if 0
	INode *root = FindRoot(iPointer->GetRootNode());
	if (root)
	{
		return
			InterpretRecord(NULL,root,0,true);
	}
#else
	if (index > -1)
	{
		return
			InterpretRecord(NULL,iPointer->GetRootNode()->GetChildNode(index),index,true);
	}
#endif

	return NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Proxies::ChildProxy*
	MAXScene::UseLastChildProxy()
{
	Check_Object(this);

	int index = IndexLastValidElement(iPointer->GetRootNode());
	if (index > -1)
	{
		return
			InterpretRecord(NULL,iPointer->GetRootNode()->GetChildNode(index),index,true);
	}
	return NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MAXScene::GetAmbientColor(RGBColor *color)
{
	Check_Object(this);
	Check_Pointer(color);
	Interval valid;

	Point3 c = iPointer->GetAmbient(time, valid);
	color->red   = c.x;
	color->green = c.y;
	color->blue  = c.z;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MAXScene::SetAmbientColor(const RGBColor &color)
{
	Check_Object(this);
	Check_Object(&color);
	Point3 c;
	c.x = color.red;
	c.y = color.green;
	c.z = color.blue;
	iPointer->SetAmbient(time, c);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MAXScene::Close()
{
	Check_Object(this);
	STOP(("Not implemented"));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Proxies::ChildProxy*
	MAXScene::InterpretRecord(
		MAXGroup *parent,
		INode *child,
		int index,
		bool auto_hierarchy
	)
{
	Check_Object(this);
	Check_Pointer(child);

	TCHAR *name = child->GetName();
	
	if (parent)
	{
		TCHAR *parent_name = parent->GetProxiedGroup()->GetName();
	}


	//
	//-------------------
	// Get the child type
	//-------------------
	//
	ObjectState os = child->EvalWorldState(time);
	Proxies::ChildProxy *proxy = NULL;

	if (os.obj)
	{
		//
		//----------------------------------
		// If the child is a light, make one
		//----------------------------------
		//
		if ((os.obj->SuperClassID() == LIGHT_CLASS_ID) || (os.obj->SuperClassID() == TARGET_CLASS_ID))
		{
			Verify(!parent);
//			DEBUG_STREAM << "  Found light class and made a light proxy" << endl;
			MAXLight *light = MAXLight::MakeProxy(this, parent, child,index);
			Register_Object(light);
			return light;
//			return NULL;
		}
		else if (os.obj->SuperClassID() == GEOMOBJECT_CLASS_ID)
		{
			//
			//------------------------------------------------------------------------
			// If the child is a mesh, we will need to auto-create a group between the
			// current parent and the mesh's children if it has any
			//------------------------------------------------------------------------
			//
			if (os.obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0)))
			{
				if (child->NumberOfChildren()>0 && auto_hierarchy)
				{
					proxy =	MAXGroup::MakeProxy(this, parent, child, time, index, true);
					Register_Object(proxy);
					return proxy;
				}
				bool has_children = false;
				if (child->NumberOfChildren()>0)
				{
					has_children = true;
				}
				proxy =	MAXPolygonMesh::MakeProxy(this, parent, child, time, index, has_children);
				Register_Object(proxy);
				LinearMatrix4D mat;
				proxy->GetLocalToParent(&mat);
				return proxy;
			}
			else
			{
				if (os.obj->CanConvertToType(Class_ID(TARGET_CLASS_ID, 0)))	
				{
				proxy =	MAXGroup::MakeProxy(this, parent, child, time, index, true);
					Register_Object(proxy);
					return proxy;
				}
			}
		}
		else if (os.obj->SuperClassID() == CAMERA_CLASS_ID)
		{
//			proxy =	MAXGroup::MakeProxy(this, parent, child, time);
//			Register_Object(proxy);
//			return proxy;
		}
		else if (os.obj->SuperClassID() == SHAPE_CLASS_ID)
		{
			proxy =	MAXGroup::MakeProxy(this, parent, child, time, index, false);
			Register_Object(proxy);
			return proxy;
		}
		else if (os.obj->SuperClassID() == HELPER_CLASS_ID)
		{
			//
			//--------------------------------------------------------
			// If this is a standard null, just make a hierarchy proxy
			//--------------------------------------------------------
			//
#if 0
			if (os.obj->IsSubClassOf(Class_ID(DUMMY_CLASS_ID, 0)))
			{
			}
#endif
			proxy =	MAXGroup::MakeProxy(this, parent, child, time, index, false);
			Register_Object(proxy);
			return proxy;
		}
	}
	return NULL;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void 
	MAXScene::GetMaterials(INode* node, int& nodeCount)
{
	nodeCount++;

	// Add the nodes material to out material list
	// Null entries are ignored when added...
	Mtl *m = node->GetMtl();
	if (m)
	{
		mtlList.AddMtl(m);
	}

	// For each child of this node, we recurse into ourselves 
	// and increment the counter until no more children are found.
	for (int c = 0; c < node->NumberOfChildren(); c++) 
	{
		GetMaterials(node->GetChildNode(c), nodeCount);

		if (m)
		{
			int number_sub_materials = m->NumSubMtls();
			for (int w=0;w<number_sub_materials;w++)
			{
				Mtl* sub = m->GetSubMtl(w);
				mtlList.AddMtl(sub);
			}
		}

		INode *temp = node->GetChildNode(c);
		TCHAR *string = temp->GetName();

	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void 
	MAXScene::GetRootElements()
{
	int elements = proxiedScene->NumberOfChildren();
	for (int i=0;i<elements;i++)
	{
		if (ValidElement(proxiedScene->GetChildNode(i)))
		{
			rootList.AddNode(proxiedScene->GetChildNode(i));
		}
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MAXScene::IndexFirstValidElement(INode *node)
{
	unsigned count = node->NumberOfChildren();
	Proxies::ChildProxy *child = NULL;

	int index = 0;
	while ((index < count)	&& (ValidElement(node) == false))
	{
		if (ValidElement(node->GetChildNode(index)))
		{
			return index;
		}
		index++;
	}
	return -1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MAXScene::IndexLastValidElement(INode *node)
{
	unsigned count = node->NumberOfChildren();
	Proxies::ChildProxy *child = NULL;

	int index = count-1;
	while ((index >= 0) && (ValidElement(node) == false))
	{
		if (ValidElement(node->GetChildNode(index)))
		{
			return index;
		}
		index--;
	}
	return -1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	MAXScene::ValidElement(INode *node)
{
	if (node == NULL) return false;

	ObjectState os = node->EvalWorldState(time);
	
	if (os.obj)
	{
		//
		// If the child is a light, make one
		//
		if (os.obj->SuperClassID() == LIGHT_CLASS_ID)
		{
			return true;
		}
		else if (os.obj->SuperClassID() == GEOMOBJECT_CLASS_ID)
		{
			//
			// If the child is a mesh, we will need to auto-create a group between the
			// current parent and the mesh's children if it has any
			//
			if (os.obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0)))
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		else if (os.obj->SuperClassID() == CAMERA_CLASS_ID)
		{
			return false;
		}
		else if (os.obj->SuperClassID() == SHAPE_CLASS_ID)
		{
			return true;
		}
		else if (os.obj->SuperClassID() == HELPER_CLASS_ID)
		{
			return true;
		}
	}
	return false;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void 
	MAXScene::GetBitmaps()
{
	int number_materials = mtlList.Count();

	Texmap *tmap = NULL;
	BitmapTex *texture = NULL;

	for (int i=0;i<number_materials;i++)
	{
		Mtl* m = mtlList.GetMtl(i);
		if (!m)
		{
			return;
		}
		if (m->ClassID() == Class_ID(DMTL_CLASS_ID,0))
		{
			for (int c=0;c<NTEXMAPS;c++)
			{	
				//
				// changed to do multitexturing
				//
				//tmap = m->GetSubTexmap(ID_DI);
				if (c==ID_OP) continue; // skip over the opacity map cause we use it
				tmap = m->GetSubTexmap(c);
				if (!tmap)
				{
					continue;
				}
				if (tmap->ClassID() == Class_ID(BMTEX_CLASS_ID,0))
				{
					texture = (BitmapTex*)tmap;
					bmpList.AddBitmap(texture);
					//TCHAR *temp1 = texture->GetMapName();
				}
			}
		} 
		else if (m->ClassID() == Class_ID(MULTI_CLASS_ID,0))
		{
			int number_sub_materials = m->NumSubMtls();
			for (int w=0;w<number_sub_materials;w++)
			{
				Mtl* sub = m->GetSubMtl(w);
				tmap = sub->GetSubTexmap(ID_DI);
				if (tmap)
				{
					if (tmap->ClassID() == Class_ID(BMTEX_CLASS_ID,0))
					{
						texture = (BitmapTex*)tmap;
						bmpList.AddBitmap(texture);
						//TCHAR *temp2 = texture->GetMapName();
						//DEBUG_STREAM << temp2 << " submap " << w << endl;
					}
				}	
			}
		}
	}

#if 0
	
	BitmapTex *temp = NULL;
	for (int z=0;z<bmpList.Count();z++)
	{
		temp = bmpList.GetBitmap(z);
		TCHAR *temp_string = temp->GetMapName();

	}
#endif
}

//
//############################################################################
//##############################    MtlKeeper    #############################
//############################################################################
//

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	 MtlKeeper::AddMtl(Mtl* mtl)
{
	if (!mtl) {
		return FALSE;
	}

	int numMtls = mtlTab.Count();
	for (int i=0; i<numMtls; i++) {
		if (mtlTab[i] == mtl) {
			return FALSE;
		}
	}
	mtlTab.Append(1, &mtl, 25);

	return TRUE;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int 
	MtlKeeper::GetMtlID(Mtl* mtl)
{
	int numMtls = mtlTab.Count();
	for (int i=0; i<numMtls; i++) {
		if (mtlTab[i] == mtl) {
			return i;
		}
	}
	return -1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int 
	MtlKeeper::Count()
{
	return mtlTab.Count();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Mtl* 
	MtlKeeper::GetMtl(int id)
{
	return mtlTab[id];
}

//
//############################################################################
//##############################    BitmapKeeper #############################
//############################################################################
//

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	 BitmapKeeper::AddBitmap(BitmapTex* bitmap)
{
	if (!bitmap) {
		return FALSE;
	}

	int numBitmap = bitmapTab.GetLength();
	for (int i=0; i<numBitmap; i++) 
	{
		BitmapTex *comp_bitmap = bitmapTab[i];
		if (comp_bitmap == bitmap) 
		{
			return FALSE;
		}
	}

	bitmapTab.SetLength(numBitmap + 1);

	bitmapTab[numBitmap] = bitmap;

	return TRUE;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int 
	BitmapKeeper::GetBitmapID(BitmapTex* bitmap)
{
	int numBitmap = bitmapTab.GetLength();
	for (int i=0; i<numBitmap; i++) {
		if (bitmapTab[i] == bitmap) {
			return i;
		}
	}
	return -1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int 
	BitmapKeeper::Count()
{
	return bitmapTab.GetLength();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BitmapTex* 
	BitmapKeeper::GetBitmap(int id)
{
	if (bitmapTab.GetLength())
		return bitmapTab[id];
	return NULL;
}

//
//############################################################################
//##############################    NodeKeeper ###############################
//############################################################################
//

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	 NodeKeeper::AddNode(INode* node)
{
	if (!node) {
		return FALSE;
	}

	int numNodes = nodeTab.Count();
	for (int i=0; i<numNodes; i++) {
		if (nodeTab[i] == node) {
			return FALSE;
		}
	}
	nodeTab.Append(1, &node, 25);
	return TRUE;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int 
	NodeKeeper::GetNodeID(INode* node)
{
	int numNodes = nodeTab.Count();
	for (int i=0; i<numNodes; i++) {
		if (nodeTab[i] == node) {
			return i;
		}
	}
	return -1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int 
	NodeKeeper::Count()
{
	return nodeTab.Count();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
INode* 
	NodeKeeper::GetNode(int id)
{
	return nodeTab[id];
}



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void 
	MAXScene::GetMeshProxies(INode* node, int& mesh_count)
{
	for (int c = 0; c < node->NumberOfChildren(); c++) {
		GetMeshProxies(node->GetChildNode(c),mesh_count);
		Proxies::ChildProxy* child = CheckNodeForMesh(node->GetChildNode(c));
		if (child != NULL)
		{
			meshProxies[mesh_count] = child;
			mesh_count++;
		}
	}
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Proxies::ChildProxy* 
	MAXScene::CheckNodeForMesh(INode *child)
{
	Check_Object(this);

	TCHAR *name = child->GetName();

	//
	//-------------------
	// Get the child type
	//-------------------
	//
	ObjectState os = child->EvalWorldState(time);
	Proxies::ChildProxy *proxy = NULL;

	if (os.obj)
	{
		if (os.obj->SuperClassID() == GEOMOBJECT_CLASS_ID)
		{
			//
			//------------------------------------------------------------------------
			// If the child is a mesh, we will need to auto-create a group between the
			// current parent and the mesh's children if it has any
			//------------------------------------------------------------------------
			//
			if (os.obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0)))
			{
				proxy =	MAXPolygonMesh::MakeProxy(this, NULL, child, time, 0, 0);
				Register_Object(proxy);
				return proxy;
			}
		}
	}
	return NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
INode *MAXScene::FindRoot(INode *node)
{
	for (int c = 0; c < node->NumberOfChildren(); c++) 
	{
		INode *result = FindRoot(node->GetChildNode(c));
		if (result) return result;
		INode *child = node->GetChildNode(c);
		TCHAR *name = child->GetName();
		if (strcmp(name,"ROOT") == 0)
		{
			return child;
		}
	}
	return NULL;
}

Page *MAXScene::FindHint(Stuff::MString name)
{
	Stuff::MString filename = strHintFile;
	Page *page = m_HintFile.FindPage(name);
	Page *newpage=NULL;
	if (NULL == page)
	{
		bool bDone = false;
		newpage = m_HintFile.AddPage(name);
		while (!bDone)
		{
			if (filename !="")
			{
				if (!gos_DoesFileExist(filename))
				{

					// Get the game dir from the plugins.ini
					Stuff::MString gameDir;

					TSTR ini_file = iPointer->GetDir(APP_PLUGCFG_DIR);
					ini_file += "\\Plugins.ini";
					
					Stuff::NotationFile data_file(ini_file);

					const char* read_dir = NULL;
					Page *ppage = data_file.FindPage("BRBData");
					if (ppage)
						ppage->GetEntry("GameDir", &read_dir);
					if (read_dir)
						gameDir = read_dir;

					filename = gameDir+"\\"+filename;

				}
				NotationFile notefile(filename);
				page = notefile.FindPage(name);
				if (page)
				{
					Page::NoteIterator *notes = page->MakeNoteIterator();

					Note *note;
					while (note = notes->ReadAndNext())
					{
						const char *entry;
						note->GetEntry(&entry);
						newpage->AppendEntry(note->GetName(),entry);
						page = newpage;
					}
					delete notes;
					bDone = true;
					filename="";
				}
				else
				{
					page = notefile.FindPage("");
					if (page)
					{
						const char *entry;
						if (page->GetEntry("Parent",&entry))
						{
							filename = entry;
						}
						else
						{
							filename="";
							bDone=true;
							page = NULL;
						}
					}
					else
					{
						filename="";
						bDone=true;
						page = NULL;
					}
				}
			}
			else
			{
				bDone = true;
			}
		}
	}
	else
	{
		newpage = page;
	}

	return newpage;
}
