bool MeshXMLExporter::Export(OutputMap& output) 
	{

		try {

			// write XML to a strstream
			std::stringstream of;

			while (!m_submeshNames.empty())
				m_submeshNames.pop();

			if (m_pGame) {
				m_pGame->ReleaseIGame();
				m_pGame = 0;
			}

			m_ei->theScene->EnumTree(this);

			m_pGame = GetIGameInterface();
			IGameConversionManager* cm = GetConversionManager();
			cm->SetCoordSystem(IGameConversionManager::IGAME_OGL);
			m_pGame->InitialiseIGame(m_nodeTab, false);
			m_pGame->SetStaticFrame(0);
			int nodeCount = m_pGame->GetTopLevelNodeCount();

			if (nodeCount == 0) {
				MessageBox(GetActiveWindow(), "No nodes available to export, aborting...", "Nothing To Export", MB_ICONINFORMATION);
				m_pGame->ReleaseIGame();
				return false;
			}

			// if we are writing everything to one file, use the name provided when the user first started the export;
			// otherwise, create filenames on the basis of the node (submesh) names
			std::string fileName;
			IGameNode* node = m_pGame->GetTopLevelNode(0);
			if (!m_config.getExportMultipleFiles())
				fileName = m_config.getExportFilename();
			else {
				fileName = m_config.getExportPath() + "\\";
				fileName += node->GetName();
				fileName += ".mesh.xml";
			}

			// write start of XML data
			streamFileHeader(of);

			int nodeIdx = 0;
			std::map<std::string, std::string> materialScripts;

			while (nodeIdx < nodeCount) {

				std::string mtlName;
				IGameNode* node = m_pGame->GetTopLevelNode(nodeIdx);
				IGameObject* obj = node->GetIGameObject();

				// InitializeData() is important -- it performs all of the WSM/time eval for us; no data without it
				obj->InitializeData();
				
				IGameMaterial* mtl = node->GetNodeMaterial();
				if (mtl == NULL)
					mtlName = m_config.getDefaultMaterialName();
				else
					mtlName = mtl->GetMaterialName();

				// clean out any spaces the user left in their material name
				std::string::size_type pos;
				while ((pos = mtlName.find_first_of(' ')) != std::string::npos)
					mtlName.replace(pos, 1, _T("_"));

				if (materialScripts.find(mtlName) == materialScripts.end()) {

					// export new material script
					MaterialExporter mexp(m_config, m_materialMap);
					std::string script;

					mexp.buildMaterial(mtl, mtlName, script);
					materialScripts[mtlName] = script;
				}

				//if (streamSubmesh(of, node, mtlName))
				if (streamSubmesh(of, obj, mtlName))
					m_submeshNames.push(std::string(node->GetName()));

				node->ReleaseIGameObject();
				nodeIdx++;

				if (m_config.getExportMultipleFiles() || nodeIdx == nodeCount) {

					// write end of this file's XML
					streamFileFooter(of);

					// insert new filename --> stream pair into output map
					output[fileName] = std::string(of.str());
					of.str("");

					if (nodeIdx != nodeCount) {
						fileName = m_config.getExportPath() + "\\";
						node = m_pGame->GetTopLevelNode(nodeIdx);
						fileName += node->GetName();
						fileName += ".mesh.xml";

						// start over again with new data
						streamFileHeader(of);
					}
				}
			}

			m_pGame->ReleaseIGame();

			// export materials if we are writing those
			if (m_config.getExportMaterial()) {

				std::ofstream materialFile;
				materialFile.open((m_config.getExportPath() + "\\" + m_config.getMaterialFilename()).c_str(), std::ios::out);

				if (materialFile.is_open()) {
					for (std::map<std::string, std::string>::iterator it = materialScripts.begin();
						it != materialScripts.end(); ++it)
					{
						materialFile << it->second;
					}

					materialFile.close();
				}
			}

			return true;
		}
		catch (...) {
			MessageBox(GetActiveWindow(), "An unexpected error has occurred while trying to export, aborting", "Error", MB_ICONEXCLAMATION);

			if (m_pGame)
				m_pGame->ReleaseIGame();

			return false;
		}
	}
void Unreal3DExport::GetTris()
{
    
    // Export triangle data
    FJSMeshTri nulltri = FJSMeshTri();
    for( int n=0; n<Nodes.Count(); ++n )
    {
        CheckCancel();
        
        IGameNode* node = Nodes[n];
        IGameMesh* mesh = static_cast<IGameMesh*>(node->GetIGameObject());
        if( mesh->InitializeData() )
        {
            int vertcount = mesh->GetNumberOfVerts();
            int tricount = mesh->GetNumberOfFaces();
            if( vertcount > 0 && tricount > 0 )
            {
                // Progress
                ProgressMsg.printf(GetString(IDS_INFO_MESH),n+1,Nodes.Count(),TSTR(node->GetName()));
                pInt->ProgressUpdate(Progress+(static_cast<float>(n)/Nodes.Count()*U3D_PROGRESS_MESH), FALSE, ProgressMsg.data());

                // Alloc triangles space
                Tris.Resize(Tris.Count()+tricount);

                // Append triangles
                for( int i=0; i!=tricount; ++i )
                {
                    FaceEx* f = mesh->GetFace(i);
                    if( f )
                    {
                        FJSMeshTri tri(nulltri);

                        // TODO: add material id listing
                        RegisterMaterial( node, mesh, f, &tri );

                        tri.iVertex[0] = VertsPerFrame + f->vert[0];
                        tri.iVertex[1] = VertsPerFrame + f->vert[1];
                        tri.iVertex[2] = VertsPerFrame + f->vert[2];

                        Point2 p;
                        if( mesh->GetTexVertex(f->texCoord[0],p) ){
                            tri.Tex[0] = FMeshUV(p);
                        }
                        if( mesh->GetTexVertex(f->texCoord[1],p) ){
                            tri.Tex[1] = FMeshUV(p);
                        }
                        if( mesh->GetTexVertex(f->texCoord[2],p) ){
                            tri.Tex[2] = FMeshUV(p);
                        }
                        
                        Tris.Append(1,&tri);                       
                    }
                }

                VertsPerFrame += vertcount;
            }
            else
            {
                // remove invalid node
                Nodes.Delete(n--,1);
            }
        }
        node->ReleaseIGameObject();
    }
    Progress += U3D_PROGRESS_MESH;
}