void CModelViewRender::LoadModel()
{
    ASSERT(GetDocument() != NULL);
    CString strPath = GetDocument()->GetPathName();
    LPCTSTR szPath = strPath;
    TCHAR extStr[_MAX_EXT];
    TCHAR fileName[_MAX_FNAME];
    _tsplitpath(szPath, NULL, NULL, fileName, extStr);

    if (strPath.IsEmpty())
    {
        m_ToolBox->Log(LOGWARNING, _T("%s(%i):LoadModel shouldn't have been called with NULL path\n"), __FILE__, __LINE__);
        return;
    }

    StdString szFilename = fileName;
    szFilename += extStr;
    m_hszModelName = szFilename;

    CFileVersionSetter setter( _T("2.5") );

    if (0 == _tcsicmp(extStr, _T(".cfg")))
    {
        IArchive *pArchive = CreateMemoryArchive();
        if (pArchive != NULL)
        {
            pArchive->Write(szPath, _T("Filepath"));
            pArchive->SetIsWriting(false);
            static CHashString hszCal3DRenderObject(_T("Cal3DRenderObject"));
            CreateEEObject(&m_hszEntityName, &hszCal3DRenderObject, m_hszModelName, pArchive);
            FillAnimationList();
            pArchive->Close();
        }
    }
    else if (0 == _tcsicmp(extStr, _T(".hrc")))
    {
        IArchive *pArchive = CreateMemoryArchive();
        if (pArchive != NULL)
        {
            pArchive->Write(szPath);
            pArchive->SetIsWriting(false);
            static CHashString hszCal3DRenderObject(_T("CHierarchicalModel"));
            CreateEEObject(&m_hszEntityName, &hszCal3DRenderObject, m_hszModelName, pArchive);
            pArchive->Close();
        }
    }
    else
    {
        m_ToolBox->Log(LOGWARNING, _T("%s(%i):LoadModel was passed %s extension, which is not recognized\n"), __FILE__, __LINE__, extStr);
    }
}
int GameComponent::DeductCredits( int credits )
{
#ifdef _SHELL
	// deduct hardware credits
	return ::DeductCredits( credits );
#else
	// deduct software credits
	IArchive *archive = CreateMemoryArchive();
	if (archive)
	{
		archive->SetIsWriting(true);
		CHashString hsAttribName(_T("Credits"));
		GetGlobalAttribute(&hsAttribName, archive);

		archive->SetIsWriting(false);
		int currCredits = 0;
		archive->Read(currCredits, _T("Credits"));
		
		currCredits -= credits;
        SetGlobalAttribute(&hsAttribName, currCredits);

		archive->Close();
	}

	return 0;
#endif
}
bool CGUIStaticText::LoadTextFile(const TCHAR *szFilename)
{
	if (_tcscmp(szFilename, "") != 0)
	{
		CREATEARCHIVE ca;
		ca.mode = 0x00000001;
		static CHashString type = _T("File");
		ca.streamType = &type;
		ca.streamData = (void*) szFilename;
		static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID();
		DWORD retval = EngineGetToolBox()->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &ca);
		if ((retval == MSG_NOT_HANDLED) || (retval == MSG_ERROR) || (retval == MSG_WARNING))
		{
			return false;
		}
		
		IArchive *ar = ca.archive;
		StdString szTemp;
		unsigned int numBytes = ar->Read(szTemp);
		ar->Close();
		if (numBytes > 0)
		{
			m_szText = szTemp;
			return true;
		}
		else 
		{
			return false;
		}
	}
	else
	{
		return false;
	}
}
void CModelViewRender::CreateScene()
{
    Vec3 v3Zero(0.0f, 0.0f, 0.0f);
    EulerAngle eZero;
    Vec3 v3Scale(1.0f,1.0f,1.0f);
    StdString szEntityType(_T("EditorObject"));

    IArchive *pArchive = CreateMemoryArchive();
    pArchive->Write(_T("EditorObject"), _T("EntityType"));
    pArchive->Write(v3Zero, _T("Position"));
    pArchive->Write(eZero, _T("Rotation"));
    pArchive->Write(v3Scale, _T("Scale"));
    pArchive->SetIsWriting(false);

    // Create Instance of CEntity
    static CHashString hszEntity(_T("CEntity"));
    CreateEEObject(&m_hszSceneName, &hszEntity, m_hszEntityName, pArchive);

    pArchive->Close();

    m_v3Position.Set(0, 0, 0);
    m_v3CameraPos.Set(0.0f, 0.0f, 200.0f);
    m_v3Rotation.Set(0.0f, 0.0f, 0.0f);

    LoadModel();
}
int GameComponent::GetCreditCount()
{
#ifdef _SHELL
	// get hardware credits
	return ::GetCreditCount();	
#else
	// get software credits
	IArchive *archive = CreateMemoryArchive();
	if (archive)
	{
		archive->SetIsWriting(true);
		CHashString hsAttribName(_T("Credits"));
		GetGlobalAttribute(&hsAttribName, archive);

		archive->SetIsWriting(false);
		int credits = 0;
		archive->Read(credits, _T("Credits"));
		archive->Close();
		return credits;
	}

	return 0;

#endif
}
void CGUIStaticText::UpdateLanguageEntryText()
{
	CHashString hszLangKey(m_szLangEntryKey);
	CHashString hszLangTextOut(_T(""));

	static DWORD dwZeroString = CHashString(_T("")).GetUniqueID();
	if (hszLangKey.GetUniqueID() != dwZeroString)
	{
		IArchive *ar = CreateAndFillArchive();
		
		GETLANGUAGETEXTPARAMS gltp;
		gltp.arParams = ar;
		gltp.hszKeyString = &hszLangKey;
		gltp.hszTranslatedText = &hszLangTextOut;
		static DWORD msgGetLanguageText = CHashString(_T("GetLanguageText")).GetUniqueID();

		m_ToolBox->SendMessage(msgGetLanguageText, sizeof(GETLANGUAGETEXTPARAMS), &gltp);

		if (m_pStaticText)
		{
			m_pStaticText->SetText(m_szFont, "", hszLangTextOut.GetString(), hszLangTextOut.GetString(), hszLangTextOut.GetString(), 
				hszLangTextOut.GetString(), m_iFontsize);
		}

		if (ar)
		{
			ar->Close();
		}
	}
}
void CWorldEventToolPal::UpdateWorldEventTrigger( void )
{
	static DWORD msgHash_FindObject = CHashString(_T("FindObject")).GetUniqueID();
	static DWORD msgHash_GetComponentType = CHashString(_T("GetComponentType")).GetUniqueID();
	static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID();
	static DWORD msgHash_SerializeObject = CHashString(_T("SerializeObject")).GetUniqueID();

	static CHashString Hash_Type = CHashString(_T("CWorldEventTrigger"));

	CString buf;
	m_Name.GetLBText(m_Name.GetCurSel(), buf);
	CHashString hszName((TCHAR*)buf.GetBuffer());
	FINDOBJECTPARAMS param;
	param.hszName = &hszName;
	DWORD result = m_ToolBox->SendMessage(msgHash_FindObject, sizeof(FINDOBJECTPARAMS), &param);

	// object exists 
	if( param.bFound == true )
	{
		GETCOMPONENTTYPEPARAMS gctp;
		gctp.name = &hszName;
		m_ToolBox->SendMessage(msgHash_GetComponentType, sizeof(gctp), &gctp);

		// it is a world event, get values from it
		if ( (gctp.componenttype != NULL) && (gctp.componenttype->GetUniqueID() == Hash_Type.GetUniqueID()) )
		{
			CREATEARCHIVE ca;
			CHashString streamType(_T("Memory"));
			ca.streamData = NULL;
			ca.mode = STREAM_MODE_WRITE | STREAM_MODE_READ;
			ca.streamType = &streamType;
	 	
			m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &ca, NULL, NULL);
			IArchive *MemArchive = (ca.archive);

			MemArchive->SetIsWriting(true);
			MemArchive->SeekTo(0);

			SERIALIZEOBJECTPARAMS sop;
			sop.name = &hszName;
			sop.archive = MemArchive;
			m_ToolBox->SendMessage(msgHash_SerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sop, NULL, NULL);

			MemArchive->SetIsWriting(false);
			MemArchive->SeekTo(0);

			StdString tmp;
			MemArchive->Read( tmp );
			m_EntityName.SetWindowText( tmp.c_str() );
			MemArchive->Read( tmp );
			m_EntityType.SetWindowText( tmp.c_str() );
			MemArchive->Read( tmp );
			m_EventName.SetWindowText( tmp.c_str() );
			
			MemArchive->Close();
		}
	}
}
void GameComponent::SetGlobalAttribute( IHashString *attributeName, bool value )
{
	if( attributeName != NULL )
	{
		IArchive *archive = CreateMemoryArchive();
		archive->SetIsWriting( true );
		archive->Write( (bool)value );
		archive->SetIsWriting( false );

		SetGlobalAttribute( attributeName, archive );

		archive->Close();
	}
}
bool CNodeSystemTest::TestCreateNode()
{
	bool result = true;
	bool subResult = false;

	CHashString hszNodeName(_T("Node1"));
	CHashString hszNodeType(_T("CNode"));

	m_dialogEditControl->ReplaceSel(_T("  Testing Creation of Node 1 - \n"));
	CreateObject( &hszNodeName, NULL, &hszNodeType );

	InitializeObject( &hszNodeName );

	m_dialogEditControl->ReplaceSel(_T("    Created node found in engine: "));

	subResult = FindObject( &hszNodeName );
	SUBREPORT( subResult );
	result = result && subResult;

	m_dialogEditControl->ReplaceSel(_T("    Verify default values: "));
	IArchive *archive = CreateMemoryArchive();
	SerializeObject( &hszNodeName, archive, true );

	float fVersion;
	float fX;
	float fY;
	float fZ;
	archive->SetIsWriting( false );
	archive->Read( fVersion );
	archive->Read( fX );
	archive->Read( fY );
	archive->Read( fZ );
	archive->Close();

	subResult = fVersion == 1.0f;
	subResult = subResult && fX == 0.0f;
	subResult = subResult && fY == 0.0f;
	subResult = subResult && fZ == 0.0f;
	SUBREPORT( subResult );

	result = result && subResult;

	DeleteObject( &hszNodeName );

	m_dialogEditControl->ReplaceSel(_T("  TestCreateNode overall: "));
	return result;
}
IBaseTextureObject * CTextureManager::LoadCubeDDSTexture( IHashString* name )
{
	//Open the data stream
	DWORD result;

	IArchive *FileArchive;
	CHashString streamType(_T("File"));
	CREATEARCHIVE ca;

	ca.mode = STREAM_MODE_READ | STREAM_MODE_BINARY;
	ca.streamData = (void*)name->GetString();
	ca.streamType = &streamType;
	static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID();
	result = m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &ca);
	
	IBaseTextureObject *pTexture = NULL;
	if( result == MSG_HANDLED )
	{
		FileArchive = dynamic_cast<IArchive *>(ca.archive);
		//Check DDS
		UINT fourcc;
		FileArchive->Read( fourcc );
		if( EE_ENDIANSWAP32(fourcc) != MAKEFOURCC( 'D', 'D', 'S', ' ' ) )
		{
			return NULL;
		}
		DDSHeader header;
		char * pheader = (char*)&header;
		//DDS, start loading header
		for( int i = 0; i < sizeof( header ); i++ )
		{
			FileArchive->Read( (*pheader) );
			pheader++;
		}
		//close the file, no longer needed
		FileArchive->Close();
		if( IsDDSCubeMap( header ) )
		{
			static CHashString DX9CubeTexObj(_T("CDX9CubeTextureObject")); 
			pTexture = CreateTextureObject( name, &DX9CubeTexObj);
			pTexture->LoadFromFile( name->GetString() );
		}
	}
	return pTexture;
}
bool CNodeSystemTest::TestCreateNodeConnection()
{
	bool result = true;
	bool subResult = false;

	CHashString hszNodeConnectionName(_T("NodeConnection1"));
	CHashString hszNodeConnectionType(_T("CNodeConnection"));

	m_dialogEditControl->ReplaceSel(_T("  Testing Creation of Node Connection 1 - \n"));
	CreateObject( &hszNodeConnectionName, NULL, &hszNodeConnectionType );

	InitializeObject( &hszNodeConnectionName );

	m_dialogEditControl->ReplaceSel(_T("    Created node found in engine: "));

	subResult = FindObject( &hszNodeConnectionName );
	SUBREPORT( subResult );
	result = result && subResult;

	m_dialogEditControl->ReplaceSel(_T("    Verify default values: "));
	IArchive *archive = CreateMemoryArchive();
	SerializeObject( &hszNodeConnectionName, archive, true );

	float fVersion;
	StdString szNode1;
	StdString szNode2;
	archive->SetIsWriting( false );
	archive->Read( fVersion );
	archive->Read( szNode1 );
	archive->Read( szNode2 );
	archive->Close();

	subResult = fVersion == 1.0f;
	subResult = subResult && szNode1 == "";
	subResult = subResult && szNode2 == "";
	SUBREPORT( subResult );

	result = result && subResult;

	DeleteObject( &hszNodeConnectionName );
	m_dialogEditControl->ReplaceSel(_T("  TestCreateNodeConnection overall: "));
	return result;
}
/////////////////////////////////////////////////////////////
// SAVE PARTICLE EMITTER
/////////////////////////////////////////////////////////////
DWORD CParticleLoader::OnSaveParticleFile(DWORD size, void *params)
{
	VERIFY_MESSAGE_SIZE(size, sizeof(TCHAR *));
	TCHAR *pFilepath = (TCHAR *)params;

	StdString szFilename = ExtractFileName(pFilepath);
	CHashString hszFilename(szFilename);

	StdString szFilepath(pFilepath);
	CHashString hszFilepath(pFilepath);

	DWORD result;
	
	// Check to see that Emitter Exists
	static DWORD msgHash_FindObject = CHashString(_T("FindObject")).GetUniqueID();
	FINDOBJECTPARAMS param;
	param.hszName = &hszFilepath;
	result = m_ToolBox->SendMessage(msgHash_FindObject, sizeof(FINDOBJECTPARAMS), &param);
	if (param.bFound == false)
	{
		//Object does not exist to save out.
		return MSG_ERROR;
	}

	// Create XMLArchive using IXML
	IXMLArchive *XMLar;
	CHashString streamType(_T("File"));

	CREATEARCHIVE ca;
	ca.mode = STREAM_MODE_WRITE;
	ca.streamData = pFilepath;
	ca.streamType = &streamType;
	static DWORD msgHash_CreateXMLArchive = CHashString(_T("CreateXMLArchive")).GetUniqueID();
	result = EngineGetToolBox()->SendMessage(msgHash_CreateXMLArchive, sizeof(CREATEARCHIVE), &ca);
	if( result == MSG_ERROR )
	{
		return MSG_ERROR;
	}

	XMLar = dynamic_cast<IXMLArchive *>(ca.archive);
	if( !XMLar )
	{
		return MSG_ERROR;
	}

	// Create MemArchive using IAR
	IArchive *MemArchive;
	CHashString memType(_T("Memory"));

	CREATEARCHIVE caOut;
	caOut.mode = STREAM_MODE_READ | STREAM_MODE_WRITE;
	caOut.streamData = NULL;
	caOut.streamSize = 0;
	caOut.streamType = &memType;
	static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID();
	if (m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &caOut) != MSG_HANDLED)
	{
		XMLar->Close();
		return MSG_ERROR;
	}
	MemArchive = caOut.archive;

	// Change the Memarchive to write
	MemArchive->SetIsWriting(true);

	// Serialize out Emitter Data
	SERIALIZEOBJECTPARAMS sop;
	sop.archive = MemArchive;
	sop.name = &hszFilepath;
	static DWORD msgHash_SerializeObject = CHashString(_T("SerializeObject")).GetUniqueID();
	m_ToolBox->SendMessage(msgHash_SerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sop, NULL, NULL);

	// EMITTER PARSE VALUES
	StdString	szName(_T("ParticleEmitter"));
	StdString	szBrush(_T("Brush"));
	StdString	szKeyframe(_T("Keyframe"));

//	StdString	szDummy;
	float time = 0.0f;
	float value = 0.0f;
	StdString szEmitterName;
	int numBrushes = 0;
	int numKeyframes = 0;
	StdString	szBrushFilepath;
	StdString	szPropertyName;
	
	// Change the Memarchive to read
	MemArchive->SetIsWriting(false);

//	MemArchive->Read( szDummy, _T("filename"));
	MemArchive->Read( szEmitterName, _T("name"));
	MemArchive->Read( numBrushes, _T("brushes"));
	MemArchive->Read( numKeyframes, _T("keyframes"));

	XMLar->StartClass(szName);
		XMLar->Write(szEmitterName, _T("name"));
		XMLar->Write(numBrushes, _T("brushes"));
		XMLar->Write(numKeyframes, _T("keyframes"));

		for (int i = 0; i < numBrushes; i++)
		{	
			MemArchive->Read( szBrushFilepath, _T("Brush") );

			XMLar->StartClass( szBrush );
				XMLar->Write( szBrushFilepath, _T("file") );
			XMLar->EndClass();
		}

		for ( int i = 0; i < numKeyframes; i++ )
		{
			MemArchive->Read( szPropertyName, _T("type") );
			MemArchive->Read( time, _T("time") );
			MemArchive->Read( value, _T("value") );

			XMLar->StartClass( szKeyframe );
				XMLar->Write( szPropertyName, _T("type") );
				XMLar->Write( time, _T("time") );
				XMLar->Write( value, _T("value") );
			XMLar->EndClass();
		}
	XMLar->EndClass();

	MemArchive->Close();
	XMLar->Close();

	return MSG_HANDLED_STOP;
}
void CModelViewRender::InitRenderScene()
{
    // set active scene to model view scene so objects created here will be placed in the correct scene
    SetActiveScene();

    //Create Cal3DRenderObject from loaded file
    CreateScene();

    // create a new Memory Archive
    IArchive *pArchive = CreateMemoryArchive();
    if (pArchive == NULL)
    {
        return;
    }

    StdString szEntityType(_T("EditorObject"));
    //Vec3 v3Zero(0.0f, 0.0f, 0.0f);
    Vec3 v3EntityLightPosition(0.0f, 200.0f, 200.0f);
    EulerAngle eaZero;
    Vec3 v3Scale(1.0f, 1.0f, 1.0f);
    pArchive->Write(szEntityType, _T("EntityType"));
    pArchive->Write(v3EntityLightPosition, _T("Position"));
    pArchive->Write(eaZero, _T("Rotation"));
    pArchive->Write(v3Scale, _T("Scale"));
    pArchive->SetIsWriting(false);

    CFileVersionSetter setter;
    // Create the CEntity LightObject Parent /////////////////////////////////////////////////////////
    static CHashString hszCEntity(_T("CEntity"));
    if (CreateEEObject(&m_hszSceneName, &hszCEntity, m_hszLightEntityName, pArchive))
    {
        pArchive->SetIsWriting(true);
        pArchive->SeekTo(0);
        int iVersionNumber = 1000;
        Vec3 v3LightPosition( 0.0, 0.0f, 0.0f );
        Vec3 v3LightDirection( 0.0f, 0.0f, 0.0f );
        float fAttenuation = 99999.0f;
        float fColor[] = { 0.75f, 0.75f, 0.75f, 1.0f };
        StdString szLightType(_T("OMNI_POINT_LIGHT"));
        bool bCastShadows = false;
        UINT numKeys = 0;
        pArchive->Write(iVersionNumber, _T("Version"));
        pArchive->Write(v3LightPosition, _T("Position"));
        pArchive->Write(v3LightDirection, _T("Direction"));
        pArchive->Write(fAttenuation, _T("Attenuation"));
        pArchive->Write(fColor[0], _T("ColorRed") );
        pArchive->Write(fColor[1], _T("ColorGreen") );
        pArchive->Write(fColor[2], _T("ColorBlue") );
        pArchive->Write(fColor[3], _T("ColorAlpha") );
        pArchive->Write(szLightType, _T("LightType") );
        pArchive->Write(bCastShadows, _T("CastShadows") );
        pArchive->Write(numKeys, _T("NumKeyframes") );
        pArchive->SetIsWriting(false);

        // Create the Light Object ////////////////////////////////////////////////////////////////
        static CHashString hszCLightObject(_T("CLightObject"));
        CreateEEObject(&m_hszLightEntityName, &hszCLightObject, m_hszLightObjectName, pArchive);
    }

    pArchive->Close();
}
DWORD CShaderEffectLoader::OnLoadFile(DWORD size, void *params)
{
	VERIFY_MESSAGE_SIZE(size, sizeof(TCHAR *));
	TCHAR *pFileName = (TCHAR *)params;

	if( _tcslen( pFileName ) == 0 )
	{
		m_ToolBox->Log( LOGWARNING, _T("Shader File is empty string") );
		return MSG_ERROR;
	}

	StdString szFileName(pFileName);
	szFileName.MakeSafeFileName();
	CHashString effectname( szFileName );

	// only load an effect file once
	static DWORD msgHash_FindObject = CHashString(_T("FindObject")).GetUniqueID();
	FINDOBJECTPARAMS param;
	param.hszName = &effectname;
	m_ToolBox->SendMessage(msgHash_FindObject, sizeof(FINDOBJECTPARAMS), &param );
	if ( param.bFound == true )
	{
		// effect already loaded
		return MSG_HANDLED_STOP;
	}

	IArchive *MemArchive;
	// hash the file name
	CHashString streamType(_T("File"));
	// create a new archive and load the file
	CREATEARCHIVE ca;
	DWORD retVal;
	ca.streamData = pFileName;
	ca.mode = STREAM_MODE_READ;
	ca.streamType = &streamType;
	// call the Archive factory to create an XML archive
	static DWORD msgHash_CreateXMLArchive = CHashString(_T("CreateXMLArchive")).GetUniqueID();
	if (retVal = m_ToolBox->SendMessage(msgHash_CreateXMLArchive, sizeof(CREATEARCHIVE), &ca) != MSG_HANDLED)
	{
		m_ToolBox->Log( LOGWARNING, _T("SHADEREFFECTLOADER: %s\n\tCould not create XML Archive\n"), pFileName );
		return MSG_ERROR;
	}

	MemArchive = dynamic_cast<IXMLArchive *>(ca.archive);

	///create the cal model
	CREATEOBJECTPARAMS cop;
	INITOBJECTPARAMS iop;
	SERIALIZEOBJECTPARAMS sop;
	
	CHashString hszParentName( _T("World") );
	CHashString hszTypeName(_T("CEffect"));	

	cop.parentName = &hszParentName;
	cop.typeName = &hszTypeName;
	cop.name = &effectname;
	static DWORD msgHash_CreateObject = CHashString(_T("CreateObject")).GetUniqueID();
	DWORD retval = m_ToolBox->SendMessage(msgHash_CreateObject, sizeof(CREATEOBJECTPARAMS), &cop, NULL, NULL);

	sop.name = &effectname;
	sop.archive = MemArchive;
	static DWORD msgHash_SerializeObject = CHashString(_T("SerializeObject")).GetUniqueID();
	m_ToolBox->SendMessage(msgHash_SerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sop, NULL, NULL);
	

	iop.name = &effectname;
	if( retval == MSG_HANDLED )
	{
		static DWORD msgHash_InitObject = CHashString(_T("InitObject")).GetUniqueID();
		retval = m_ToolBox->SendMessage(msgHash_InitObject, sizeof(INITOBJECTPARAMS), &iop, NULL, NULL);
	}

	MemArchive->Close();

	CREATEEFFECTINTERFACE addmsg;
	addmsg.m_Name = &effectname;
	static DWORD msgHash_AddEffect = CHashString(_T("AddEffect")).GetUniqueID();
	m_ToolBox->SendMessage(msgHash_AddEffect, sizeof( CREATEEFFECTINTERFACE ), &addmsg );
	return MSG_HANDLED_STOP;
}
// load a file if we recognize the type.
DWORD CXMLWorldLoader::OnLoadWorldFile(DWORD size, void *params)
{
	CHashString oldVersion = _T("");
	CREATEOBJECTPARAMS cop;
	INITOBJECTPARAMS iop;
	SERIALIZEOBJECTPARAMS sop;
	DWORD retVal;
	IXMLArchive *Archive = NULL;
	DWORD currNode = 0;
	LOADINGUPDATEPARAMS pbp;

	VERIFY_MESSAGE_SIZE(size, sizeof(TCHAR *));
	TCHAR *pFileName = (TCHAR *)params;

	// use both a hashstring and a pointer so that the first iteration of the loop
	// will pass SetParentName a NULL instead of an address of a hashstring
	// hashed to ""
	CHashString hszParentType(_T("CWorld"));
	CHashString hszParentName(_T("World"));
	CHashString hszName(_T(""));
	CHashString hszTypeName(_T(""));
	CHashString streamType(_T("File"));

	// delete previous world root
	DELETEOBJECTPARAMS dop;
	dop.name = &hszParentName;
	static DWORD msgHash_DeleteObject = CHashString(_T("DeleteObject")).GetUniqueID();
	EngineGetToolBox()->SendMessage(msgHash_DeleteObject, sizeof(dop), &dop );
	// delete is ok to fail if no world has been created yet

	// create new world root
	cop.name = &hszParentName;
	cop.parentName = NULL;
	cop.typeName = &hszParentType;
	static DWORD msgHash_CreateObject = CHashString(_T("CreateObject")).GetUniqueID();
	DWORD returnValue = EngineGetToolBox()->SendMessage(msgHash_CreateObject, sizeof(cop), &cop );
	if (returnValue != MSG_HANDLED)
	{
		EngineGetToolBox()->Log(LOGERROR, _T("Failed to create World Root Object\n"));
		return MSG_ERROR;
	}

	CREATEARCHIVE ca;
	ca.streamData = (void *)pFileName;
	ca.mode = STREAM_MODE_READ;
	ca.streamType = &streamType;
#ifdef USEXMLFILESTREAMS
	// call the Archive factory to create an XML archive
	static DWORD msgHash_CreateXMLArchiveStream = CHashString(_T("CreateXMLArchiveStream")).GetUniqueID();
	if (retVal = m_ToolBox->SendMessage(msgHash_CreateXMLArchiveStream, sizeof(CREATEARCHIVE), &ca) != MSG_HANDLED)
#else
	// call the Archive factory to create an XML archive
	static DWORD msgHash_CreateXMLArchive = CHashString(_T("CreateXMLArchive")).GetUniqueID();
	if (retVal = m_ToolBox->SendMessage(msgHash_CreateXMLArchive, sizeof(CREATEARCHIVE), &ca) != MSG_HANDLED)
#endif
	{
		return retVal;
	}

	Archive = dynamic_cast<IXMLArchive *>(ca.archive);
	DWORD numNodes = Archive->GetNumberOfNodes();

	// Deteriminte World Version
	int iWorldNumAttrib = Archive->GetNumAttributes();

	StdString szNodeName;
	Archive->GetNode(szNodeName);
	
	pbp.currentPosition = Archive->GetCurrentNodePosition();
	pbp.totalSize = numNodes;
	// update progress bar
	static DWORD msgHash_LoadingUpdate = CHashString(_T("LoadingUpdate")).GetUniqueID();
	m_ToolBox->SendMessage(msgHash_LoadingUpdate, sizeof(LOADINGUPDATEPARAMS), &pbp);


	// must start with <World>
	if (szNodeName != _T("CWorld"))
	{
		EngineGetToolBox()->SetErrorValue(WARN_INVALID_FILE);
		EngineGetToolBox()->Log(LOGWARNING, _T("Invalid world file %s\n"), pFileName);
		Archive->Close();
		return MSG_ERROR;
	}

	// Version 1.0
	if( iWorldNumAttrib == 1 )
	{
		// read the name of the world
		StdString szName;
		Archive->Read( szName, _T("Name") );
		m_WorldFileVersion = 1.0f;
		static DWORD msgHash_GetFileVersion = CHashString(_T("GetFileVersion")).GetUniqueID();
		DWORD retval = m_ToolBox->SendMessage(msgHash_GetFileVersion, sizeof(IHashString), &oldVersion);
		if (retval != MSG_HANDLED)
		{
			m_ToolBox->Log(LOGERROR, _T("Could not get world version!"));
			return MSG_ERROR;
		}
		CHashString hszNewVersion = _T("1.0");
		static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID();
		retval = m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &hszNewVersion);
		if (retval != MSG_HANDLED)
		{
			m_ToolBox->Log(LOGERROR, _T("Could not set world version!"));
			return MSG_ERROR;
		}
	}
	// Version 1.5
	else if( iWorldNumAttrib == 2 )
	{
		StdString szName;
		Archive->Read( szName, _T("Name") );
		float fileVersion = 0;
		Archive->Read( m_WorldFileVersion, _T("Version") );
		static DWORD msgHash_GetFileVersion = CHashString(_T("GetFileVersion")).GetUniqueID();
		DWORD retval = m_ToolBox->SendMessage(msgHash_GetFileVersion, sizeof(IHashString), &oldVersion);
		if (retval != MSG_HANDLED)
		{
			m_ToolBox->Log(LOGERROR, _T("Could not get world version!"));
			return MSG_ERROR;
		}
		TCHAR buf[50];
		_stprintf(buf, "%.1f", m_WorldFileVersion);
		CHashString hszNewVersion(buf);
		static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID();
		retval = m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &hszNewVersion);
		if (retval != MSG_HANDLED)
		{
			m_ToolBox->Log(LOGERROR, _T("Could not set world version!"));
			return MSG_ERROR;
		}
	}
	// Unknown Version
	else
	{
		EngineGetToolBox()->SetErrorValue(WARN_INVALID_FILE);
		EngineGetToolBox()->Log(LOGWARNING, _T("Invalid world file %s\n"), pFileName);
		Archive->Close();
		static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID();
		m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &oldVersion);
		return MSG_ERROR;
	}

	// failure checks
	bool componentFailed = false;
	int failedDepth = 0;

	float secondsPerFrame = 1 / m_fLoadingUpdateFPS;
	ITimer *timer = EngineGetToolBox()->GetTimer();
	float lastLoadTime = timer->GetRealTime();
	float elapsedTime = 0.0f;

	while (Archive->GetNode(szNodeName))
	{
		int currDepth = Archive->GetDepth();
		if (componentFailed == true)
		{
			// current node is child of failed
			if (currDepth > failedDepth)
			{
				continue;
			}
			// if sibling or uncle, reset comp failed flag
			else
			{
				componentFailed = false;
			}
		}

		hszTypeName.Init( szNodeName.c_str() );

		StdString parentName;
		StdString parentType;
		StdString childType;
		Archive->GotoParentNode( parentType );
		Archive->Read( parentName, _T("Name") );
		if ( parentName != _T("") )
		{
			hszParentName = parentName;
		}
		Archive->ReturnToChildNode( childType );
		if( hszTypeName.GetString() != childType )
		{
			assert( hszTypeName.GetString() == childType );
			static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID();
			m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &oldVersion);
			return MSG_ERROR;
		}
		//parentName = Archive->GetParentName();

		StdString szName;
		Archive->Read( szName, _T("Name") );
		hszName.Init( szName.c_str() );

		cop.parentName = &hszParentName;
		cop.typeName = &hszTypeName;
		cop.name = &hszName;
		static DWORD msgHash_CreateObject = CHashString(_T("CreateObject")).GetUniqueID();
		DWORD retval = m_ToolBox->SendMessage(msgHash_CreateObject, sizeof(CREATEOBJECTPARAMS), &cop, NULL, NULL);

		if (retval != MSG_HANDLED)
		{
			m_ToolBox->Log(LOGINFORMATION, _T("World loader: could not create component; skipping children!\n"));
			componentFailed = true;
			failedDepth = Archive->GetDepth();			
			continue;
		}

		// 1.0 -> 1.5 Readjusted scale and position on object by 1000/898
		if( m_WorldFileVersion == 1.0 )
		{
			float fConvert = 1000.0f/898.0f;
			if( hszTypeName.GetUniqueID() == CHashString(_T("CV3ORenderObject")).GetUniqueID() )
			{
				StdString szFileName;
				Vec3 vPosition(0,0,0);
				Vec3 vRotation(0,0,0);
				Vec3 vScaling(0,0,0);

				Archive->Read( szFileName, _T("FileName") );
				
				Archive->Read( vPosition, _T("Position") );
				vPosition.x = ( vPosition.x * fConvert );
				vPosition.y = ( vPosition.y * fConvert );
				vPosition.z = ( vPosition.z * fConvert );
				
				Archive->Read( vRotation, _T("Rotation") );

				Archive->Read( vScaling, _T("Scaling") );
				vScaling.x = ( vScaling.x * fConvert );
				vScaling.y = ( vScaling.y * fConvert );
				vScaling.z = ( vScaling.z * fConvert );

				IArchive *MemArchive;
				CHashString memType(_T("Memory"));

				CREATEARCHIVE caOut;
				caOut.mode = STREAM_MODE_WRITE;
				caOut.streamData = NULL;
				caOut.streamSize = 0;
				caOut.streamType = &memType;
				static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID();
				if (m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &caOut) != MSG_HANDLED)
				{
					static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID();
					m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &oldVersion);
					return true;
				}
				MemArchive = caOut.archive;

				MemArchive->Write( szFileName, _T("FileName") );
				MemArchive->Write( vPosition, _T("Position") );
				MemArchive->Write( vRotation, _T("Rotation") );
				MemArchive->Write( vScaling, _T("Scaling") );
		
				CREATESTREAM cs;
				cs.streamData = caOut.streamData;
				cs.streamSize = caOut.streamSize;
				cs.mode = STREAM_MODE_READ;
				static DWORD msgHash_CreateStream_Memory = CHashString(_T("CreateStream_Memory")).GetUniqueID();
				if (m_ToolBox->SendMessage(msgHash_CreateStream_Memory, sizeof(CREATESTREAM), &cs) != MSG_HANDLED)
				{
					static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID();
					m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &oldVersion);
					return true;
				}
				MemArchive->Init(cs.openStream);

				sop.name = &hszName;
				sop.archive = MemArchive;
				static DWORD msgHash_SerializeObject = CHashString(_T("SerializeObject")).GetUniqueID();
				m_ToolBox->SendMessage(msgHash_SerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sop, NULL, NULL);
				
				MemArchive->Close();
			}

			else if( hszTypeName.GetUniqueID() == CHashString(_T("CPhysicsObject")).GetUniqueID() )
			{
				//StdString szDynamics;
				StdString szType;
				StdString szShapeFileName;
				//float fMass;
				//Vec3 vPosition;
				//Vec3 vRotation;
				//Vec3 vScaling;

				//Archive->Read( vPosition, _T("pos") );
				//vPosition.SetX( vPosition.GetX() * fConvert );
				//vPosition.SetY( vPosition.GetY() * fConvert );
				//vPosition.SetZ( vPosition.GetZ() * fConvert );

				//Archive->Read( vRotation, _T("rot") );
				
				//Archive->Read( vScaling, _T("scale") );
				//vScaling.SetX( vScaling.GetX() * fConvert );
				//vScaling.SetY( vScaling.GetY() * fConvert );
				//vScaling.SetZ( vScaling.GetZ() * fConvert );

				//Archive->Read( fMass, _T("mass") );
				Archive->Read( szType, _T("Type") );
				Archive->Read( szShapeFileName, _T("filename") );

				IArchive *MemArchive;
				CHashString memType(_T("Memory"));
				//int size =	sizeof(char) * 256 * 2 + sizeof(float) + sizeof(Vec3) * 3 + 256;
				
				CREATEARCHIVE caOut;
				caOut.mode = STREAM_MODE_WRITE;
				caOut.streamData = NULL;
				caOut.streamSize = 0;
				caOut.streamType = &memType;
				static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID();
				if (m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &caOut) != MSG_HANDLED)
				{
					static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID();
					m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &oldVersion);
					return true;
				}
				MemArchive = caOut.archive;

				//MemArchive->Write( vPosition, _T("pos") );
				//MemArchive->Write( vRotation, _T("rot") );
				//MemArchive->Write( vScaling, _T("scale") );
				//MemArchive->Write( fMass, _T("mass") );
				//MemArchive->Write( szDynamics, _T("dynamics") );
				//MemArchive->Write( szShapeFileName, _T("shapeFile") );
				MemArchive->Write( szType, _T("Type") );
				MemArchive->Write( szShapeFileName, _T("filename") );

				CREATESTREAM cs;
				cs.streamData = caOut.streamData;
				cs.streamSize = caOut.streamSize;
				cs.mode = STREAM_MODE_READ;
				static DWORD msgHash_CreateStream_Memory = CHashString(_T("CreateStream_Memory")).GetUniqueID();
				if (m_ToolBox->SendMessage(msgHash_CreateStream_Memory, sizeof(CREATESTREAM), &cs) != MSG_HANDLED)
				{
					static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID();
					m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &oldVersion);
					return true;
				}
				MemArchive->Init(cs.openStream);

				sop.name = &hszName;
				sop.archive = MemArchive;
				static DWORD msgHash_SerializeObject = CHashString(_T("SerializeObject")).GetUniqueID();
				m_ToolBox->SendMessage(msgHash_SerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sop, NULL, NULL);

				MemArchive->Close();
			}
			else if( hszTypeName.GetUniqueID() == CHashString(_T("CTerrainConfig")).GetUniqueID() )
			{
				StdString szTerShaderLib;
				StdString szTerShaderEff;
				int iSectorRes;
				float fSectorSize;
				float fZScale;
				float fLODDistance;

				Archive->Read( szTerShaderLib, _T("TerrainShaderLibrary") );
				Archive->Read( szTerShaderEff, _T("TerrainShaderEffect") );
				Archive->Read( iSectorRes, _T("SectorResolution") );
				Archive->Read( fSectorSize, _T("SectorSize") );
				fSectorSize = fSectorSize * fConvert;
				Archive->Read( fZScale, _T("ZScale") );
				fZScale = fZScale * fConvert;
				Archive->Read( fLODDistance, _T("LODDistance") );
				
				IArchive *MemArchive;
				CHashString memType(_T("Memory"));
				
				CREATEARCHIVE caOut;
				caOut.mode = STREAM_MODE_WRITE;
				caOut.streamData = NULL;
				caOut.streamSize = 0;
				caOut.streamType = &memType;
				static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID();
				if (m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &caOut) != MSG_HANDLED)
				{
					static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID();
					m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &oldVersion);
					return true;
				}
				MemArchive = caOut.archive;

				MemArchive->Write( szTerShaderLib, _T("TerrainShaderLibrary") );
				MemArchive->Write( szTerShaderEff, _T("TerrainShaderEffect") );
				MemArchive->Write( iSectorRes, _T("SectorResolution") );
				MemArchive->Write( fSectorSize, _T("SectorSize") );
				MemArchive->Write( fZScale, _T("ZScale") );
				MemArchive->Write( fLODDistance, _T("LODDistance") );

				CREATESTREAM cs;
				cs.streamData = caOut.streamData;
				cs.streamSize = caOut.streamSize;
				cs.mode = STREAM_MODE_READ;
				static DWORD msgHash_CreateStream_Memory = CHashString(_T("CreateStream_Memory")).GetUniqueID();
				if (m_ToolBox->SendMessage(msgHash_CreateStream_Memory, sizeof(CREATESTREAM), &cs) != MSG_HANDLED)
				{
					static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID();
					m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &oldVersion);
					return true;
				}
				MemArchive->Init(cs.openStream);

				sop.name = &hszName;
				sop.archive = MemArchive;
				static DWORD msgHash_SerializeObject = CHashString(_T("SerializeObject")).GetUniqueID();
				m_ToolBox->SendMessage(msgHash_SerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sop, NULL, NULL);

				MemArchive->Close();
			}
			else
			{
				sop.name = &hszName;
				sop.archive = Archive;
				static DWORD msgHash_SerializeObject = CHashString(_T("SerializeObject")).GetUniqueID();
				m_ToolBox->SendMessage(msgHash_SerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sop, NULL, NULL);
			}
		}
		else
		{
			sop.name = &hszName;
			sop.archive = Archive;
			static DWORD msgHash_SerializeObject = CHashString(_T("SerializeObject")).GetUniqueID();
			m_ToolBox->SendMessage(msgHash_SerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sop, NULL, NULL);
		}

		iop.name = &hszName;
		static DWORD msgHash_InitObject = CHashString(_T("InitObject")).GetUniqueID();
		m_ToolBox->SendMessage(msgHash_InitObject, sizeof(INITOBJECTPARAMS), &iop, NULL, NULL);

		elapsedTime += timer->GetRealTime() - lastLoadTime;
		lastLoadTime = timer->GetRealTime();				
		if (elapsedTime > secondsPerFrame)
		{
			elapsedTime = 0.0f;
			pbp.currentPosition = Archive->GetCurrentNodePosition();
			pbp.totalSize = numNodes;
			m_ToolBox->SendMessage(msgHash_LoadingUpdate, sizeof(LOADINGUPDATEPARAMS), &pbp);
		}
	}

	pbp.currentPosition = 0;
	pbp.totalSize = 0;
	m_ToolBox->SendMessage(msgHash_LoadingUpdate, sizeof(LOADINGUPDATEPARAMS), &pbp);

	Archive->Close();

	static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID();
	m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &oldVersion);

	return MSG_HANDLED_STOP;
}
bool CWorldVisitor::Visit( IComponent * component, bool bVisitEnter )
{
	IObject *theObject;
	IHashString *name;
	IHashString *parentName;
	IHashString *type;

	StdString parentType;
	StdString childType;

	std::string str;

	theObject = dynamic_cast<IObject *>(component);
	// This shouldn't happen but it does for some odd reason....
	assert(theObject);
	if( theObject == NULL )
	{
		return false;
	}
	name = theObject->GetName();
	parentName = theObject->GetParentName();
	type = theObject->GetComponentType();

	//Check to see if it is a valid object (for object exclusion)
	if( !CheckObject( type->GetString() ) )
	{
		return true;
	}

	else
	{
		if ( name == NULL )
		{
			name = &CHashString(_T("NULL"));
		}	

		if( bVisitEnter == true )
		{
			//if( (m_pArchiver != NULL) && ( _tcscmp( type->GetString(), _T("CPhysicsObject") ) != 0 ) )
			if( (m_pArchiver != NULL) )
			{
				// Start the Node
				m_pArchiver->StartClass( type->GetString() );
				
				// Write out the Unique ID aka Name
				m_pArchiver->Write( name->GetString(), _T("Name") );
				theObject->Serialize( *m_pArchiver );
			}

			// Removal of CPhysShape and changes to CPhysicsObject
			if( _tcscmp( type->GetString(), _T("CPhysicsObject") ) == 0 )
			{
				
				CPhysObjectStruct tmpCPhysObject;
				StdString CPhyShapeFile;
				StdString CPhyShapeFileOld;
				// if it's parent is not a CTerrainSector Object
				if( _tcsstr( name->GetString(), _T("Terrain") ) == NULL )
				{
					static DWORD msgHash_GetModelFileName = CHashString(_T("GetModelFileName")).GetUniqueID();
					m_ToolBox->SendMessage(msgHash_GetModelFileName, sizeof(StdString*), &CPhyShapeFile, parentName, NULL );
					CPhyShapeFile += _T(".psl");
				}
				// CTerrainSector Object
				else
				{
					CPhyShapeFile = _T("maps\\terrain.psl");
				}

				IArchive *PhysObjectIn;
				IArchive *PhysObjectRead;
				CHashString memTypePhysObjectIn(_T("Memory"));
				
				int PhysObjectInMemSize = 1024 * 1024 * sizeof(char);
				char* PhysObjectInMemChunk = new char[PhysObjectInMemSize];
				memset( PhysObjectInMemChunk, 0, PhysObjectInMemSize );

				CREATEARCHIVE caPhysObjectIn;
				caPhysObjectIn.mode = STREAM_MODE_READ;
				caPhysObjectIn.streamData = PhysObjectInMemChunk;
				caPhysObjectIn.streamSize = PhysObjectInMemSize;
				caPhysObjectIn.streamType = &memTypePhysObjectIn;
				static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID();
				if (m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &caPhysObjectIn) != MSG_HANDLED)
				{
					return true;
				}
				PhysObjectIn = caPhysObjectIn.archive;

				CREATESTREAM csPhysObjectIn;
				csPhysObjectIn.streamData = caPhysObjectIn.streamData;
				csPhysObjectIn.streamSize = caPhysObjectIn.streamSize;
				csPhysObjectIn.mode = STREAM_MODE_WRITE;
				static DWORD msgHash_CreateStream_Memory = CHashString(_T("CreateStream_Memory")).GetUniqueID();
				if (m_ToolBox->SendMessage(msgHash_CreateStream_Memory, sizeof(CREATESTREAM), &csPhysObjectIn) != MSG_HANDLED)
				{
					return true;
				}
				PhysObjectIn->Init(csPhysObjectIn.openStream);		    

				SERIALIZEOBJECTPARAMS sop;
				sop.name = name;
				sop.archive = PhysObjectIn;
				static DWORD msgHash_SerializeObject = CHashString(_T("SerializeObject")).GetUniqueID();
				m_ToolBox->SendMessage(msgHash_SerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sop, NULL, NULL);
				PhysObjectIn->Close();
				
				CREATEARCHIVE caPhysObjectRead;
				caPhysObjectRead.mode = STREAM_MODE_WRITE;
				caPhysObjectRead.streamData = PhysObjectInMemChunk;
				caPhysObjectRead.streamSize = PhysObjectInMemSize;
				caPhysObjectRead.streamType = &memTypePhysObjectIn;
				if (m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &caPhysObjectRead) != MSG_HANDLED)
				{
					return true;
				}
				PhysObjectRead = caPhysObjectRead.archive;

				CREATESTREAM csPhysObjectRead;
				csPhysObjectRead.streamData = caPhysObjectRead.streamData;
				csPhysObjectRead.streamSize = caPhysObjectRead.streamSize;
				csPhysObjectRead.mode = STREAM_MODE_READ;
				if (m_ToolBox->SendMessage(msgHash_CreateStream_Memory, sizeof(CREATESTREAM), &csPhysObjectRead) != MSG_HANDLED)
				{
					return true;
				}
				PhysObjectRead->Init(csPhysObjectRead.openStream);
				PhysObjectRead->Read( tmpCPhysObject.vPosition, _T("pos") );
				PhysObjectRead->Read( tmpCPhysObject.vRotation, _T("rot") );
				PhysObjectRead->Read( tmpCPhysObject.vScale, _T("scale") );
				PhysObjectRead->Read( tmpCPhysObject.fMass, _T("mass") );
				PhysObjectRead->Read( tmpCPhysObject.szDynamic, _T("dynamics") );
				PhysObjectRead->Read( CPhyShapeFileOld, _T("shapeFile") );
				PhysObjectRead->Close();
                
				// Archive the Data Back In
				IArchive *MemArchivePhysObject;	
				CHashString memTypePhysObject(_T("Memory"));
				//int sizePhysObject = 1024 * 1024;
				//char* memchunkPhysObject = new char[sizePhysObject];

				CREATEARCHIVE caPhysObject;
				caPhysObject.mode = STREAM_MODE_WRITE;
				caPhysObject.streamData = PhysObjectInMemChunk;
				caPhysObject.streamSize = PhysObjectInMemSize;
				caPhysObject.streamType = &memTypePhysObject;
				if (m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &caPhysObject) != MSG_HANDLED)
				{
					return true;
				}
				MemArchivePhysObject = caPhysObject.archive;
				MemArchivePhysObject->Write( tmpCPhysObject.vPosition, _T("pos") );
				MemArchivePhysObject->Write( tmpCPhysObject.vRotation, _T("rot") );
				MemArchivePhysObject->Write( tmpCPhysObject.vScale, _T("scale") );
				MemArchivePhysObject->Write( tmpCPhysObject.fMass, _T("mass") );
				MemArchivePhysObject->Write( tmpCPhysObject.szDynamic, _T("dynamics") );
				MemArchivePhysObject->Write( CPhyShapeFile, _T("shapeFile") );
				
				CREATESTREAM csPhysObject;
				csPhysObject.streamData = caPhysObject.streamData;
				csPhysObject.streamSize = caPhysObject.streamSize;
				csPhysObject.mode = STREAM_MODE_READ;
				if (m_ToolBox->SendMessage(msgHash_CreateStream_Memory, sizeof(CREATESTREAM), &csPhysObject) != MSG_HANDLED)
				{
					return true;
				}
				MemArchivePhysObject->Init(csPhysObject.openStream);

				SERIALIZEOBJECTPARAMS sopPhysObject;
				sopPhysObject.name = name;
				sopPhysObject.archive = MemArchivePhysObject;
				m_ToolBox->SendMessage(msgHash_SerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sopPhysObject, NULL, NULL);

				MemArchivePhysObject->Close();
				//delete [] memchunkPhysObject;
				//memchunkPhysObject = NULL;
				delete [] PhysObjectInMemChunk;
				PhysObjectInMemChunk = NULL;
			}

			// Model Rename Changes
			if( (m_pReporter != NULL) && ( _tcscmp( type->GetString(), _T("CV3ORenderObject") ) == 0 ) )
			{
				IArchive *MemArchive;
				IArchive *MemArchive2;
				CHashString memType(_T("Memory"));
				memset( m_pMemChunk, '\0', m_iMemSize );

				CREATEARCHIVE ca;
				ca.mode = STREAM_MODE_READ;
				ca.streamData = m_pMemChunk;
				ca.streamSize = m_iMemSize;
				ca.streamType = &memType;
				static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID();
				if (m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &ca) != MSG_HANDLED)
				{
					return true;
				}
				MemArchive = ca.archive;

				CREATESTREAM cs;
				cs.streamData = ca.streamData;
				cs.streamSize = ca.streamSize;
				cs.mode = STREAM_MODE_WRITE;
				static DWORD msgHash_CreateStream_Memory = CHashString(_T("CreateStream_Memory")).GetUniqueID();
				if (m_ToolBox->SendMessage(msgHash_CreateStream_Memory, sizeof(CREATESTREAM), &cs) != MSG_HANDLED)
				{
					return true;
				}
				MemArchive->Init(cs.openStream);		    

				SERIALIZEOBJECTPARAMS sop;
				sop.name = name;
				sop.archive = MemArchive;
				static DWORD msgHash_SerializeObject = CHashString(_T("SerializeObject")).GetUniqueID();
				m_ToolBox->SendMessage(msgHash_SerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sop, NULL, NULL);
				MemArchive->Close();
				
				CREATEARCHIVE ca2;
				ca2.mode = STREAM_MODE_WRITE;
				ca2.streamData = m_pMemChunk;
				ca2.streamSize = m_iMemSize;
				ca2.streamType = &memType;
				if (m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &ca2) != MSG_HANDLED)
				{
					return true;
				}
				MemArchive2 = ca2.archive;

				CREATESTREAM cs2;
				cs2.streamData = ca2.streamData;
				cs2.streamSize = ca2.streamSize;
				cs2.mode = STREAM_MODE_READ;
				if (m_ToolBox->SendMessage(msgHash_CreateStream_Memory, sizeof(CREATESTREAM), &cs2) != MSG_HANDLED)
				{
					return true;
				}
				MemArchive2->Init(cs2.openStream);

				StdString wszModelFileName;
				Vec3 Position;
				Vec3 Rotation;
				Vec3 Scale;

				MemArchive2->Read( wszModelFileName );
				MemArchive2->Read( Position );
				MemArchive2->Read( Rotation );
				MemArchive2->Read( Scale );
				MemArchive2->Close();
				
				MODELMAP::iterator itr;
				bool bReArchive = false;
				while( 1 )
				{		
					itr = m_vModelReference.find( wszModelFileName );
					// If the Model Refernce already exists
					if( itr != m_vModelReference.end() )
					{
						// If its newfilename is different and it isn't an empty string
						// We Change the file name and set the archive flag
						if( (wszModelFileName != itr->second.m_wszNewFileName) &&
							(itr->second.m_wszNewFileName != StdString("")) )
						{
							wszModelFileName = itr->second.m_wszNewFileName;
							bReArchive = true;
						}
						
						// We've reached a file that has the same exact newfilename, no change neccisary
						else
						{
							break;
						}
					}
					
					
					// We change model name first (up above) and then make sure to add it as a reference and break out
					itr = m_vModelReference.find( wszModelFileName );
					if( itr == m_vModelReference.end() )
					{
						/*
						MODELINFO tmpModelInfo;
						tmpModelInfo.m_wszNewFileName = wszModelFileName;
						m_vModelReference[wszModelFileName] = tmpModelInfo;
						m_iNewEntries++;
						*/
						break;
					}
					
				}
				
				m_szLastV3OFileName = wszModelFileName;

				// Archive the object back out
				if( bReArchive == true )
				{
					IArchive *MemArchiveRE;	
					CHashString memTypeRE(_T("Memory"));
					int sizeRE = 1024 + sizeof(Vec3) * 3;
					char* memchunkRE = new char[sizeRE];

					CREATEARCHIVE caRE;
					caRE.mode = STREAM_MODE_WRITE;
					caRE.streamData = memchunkRE;
					caRE.streamSize = sizeRE;
					caRE.streamType = &memTypeRE;
					static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID();
					if (m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &caRE) != MSG_HANDLED)
					{
						return true;
					}
					MemArchiveRE = caRE.archive;
					MemArchiveRE->Write( wszModelFileName );
					MemArchiveRE->Write( Position );
					MemArchiveRE->Write( Rotation );
					MemArchiveRE->Write( Scale );

					CREATESTREAM csRE;
					csRE.streamData = caRE.streamData;
					csRE.streamSize = caRE.streamSize;
					csRE.mode = STREAM_MODE_READ;
					static DWORD msgHash_CreateStream_Memory = CHashString(_T("CreateStream_Memory")).GetUniqueID();
					if (m_ToolBox->SendMessage(msgHash_CreateStream_Memory, sizeof(CREATESTREAM), &csRE) != MSG_HANDLED)
					{
						return true;
					}
					MemArchiveRE->Init(csRE.openStream);

					SERIALIZEOBJECTPARAMS sopRE;
					sopRE.name = name;
					sopRE.archive = MemArchiveRE;
					static DWORD msgHash_SerializeObject = CHashString(_T("SerializeObject")).GetUniqueID();
					m_ToolBox->SendMessage(msgHash_SerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sopRE, NULL, NULL);

					MemArchiveRE->Close();
					delete [] memchunkRE;
					memchunkRE = NULL;
					m_iV3ONameEdits++;
				}
			}
		}

		// bVisitEnter == false
		else
		{
			if( m_pArchiver != NULL )
			{
				m_pArchiver->EndClass();
			}
		}
	}
	
	return true;
}
DWORD CDatabaseManager::OnLoadGlobalAttributes( DWORD size, void *params )
{
	if( m_GlobalAttributesDatabase == NULL )
	{
		VERIFY_MESSAGE_SIZE( size, sizeof(LOADGLOBALATTRIBUTESPARAMS) );
		LOADGLOBALATTRIBUTESPARAMS *loadGlobalAttributesParams = (LOADGLOBALATTRIBUTESPARAMS*)params;
		CHashString definedDatabaseType( _T("CDefinedDatabase") );
		CHashString databaseItemType( _T("CDatabaseItem") );

		// Creating a CDefinedDatabase for the global attributes.
		// It is simply a database with a single entry.
		CREATEOBJECTPARAMS cop;

		cop.name = loadGlobalAttributesParams->Name;
		cop.parentName = NULL;
		cop.typeName = &definedDatabaseType;
		static DWORD msgHash_CreateObject = CHashString(_T("CreateObject")).GetUniqueID();
		m_ToolBox->SendMessage(msgHash_CreateObject, sizeof(CREATEOBJECTPARAMS), &cop);

		// Set a pointer to the global attributes database
		IDTOOBJECTMAP *objectMap = GetObjectMap( &definedDatabaseType );
		if (objectMap)
		{
			IDTOOBJECTMAP::iterator objectsIterator = objectMap->find( loadGlobalAttributesParams->Name->GetUniqueID() );
			if( objectsIterator != objectMap->end() )
			{
				m_GlobalAttributesDatabase = (CDefinedDatabase*)objectsIterator->second;
			}
		}
		else
			return MSG_ERROR;
		// Creating memory archive
		CREATEARCHIVE ca;
		CHashString memType(_T("Memory"));

		ca.mode = STREAM_MODE_WRITE | STREAM_MODE_READ;
		ca.streamData = NULL;
		ca.streamSize = 0;
		ca.streamType = &memType;
		ca.archive = NULL;

		static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID();
		m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &ca);
		if (!ca.archive)
			return MSG_ERROR;
		// Writing serialization values to archive
		float fVersion = 1.0f;
		const TCHAR *name = loadGlobalAttributesParams->Name->GetString();
		const TCHAR *schemaFile = loadGlobalAttributesParams->SchemaFile->GetString();
		const TCHAR *schemaName = loadGlobalAttributesParams->SchemaName->GetString();
		int numItems = 1;
		IArchive *archive = ca.archive;
		archive->SetIsWriting( true );
		archive->Write( fVersion );
		archive->Write( name );
		archive->Write( schemaFile );
		archive->Write( schemaName );
		archive->Write( numItems );
		archive->SetIsWriting( false );

		// Serialize values to defined database object
		SERIALIZEOBJECTPARAMS sop;
		sop.name = loadGlobalAttributesParams->Name;
		sop.archive = archive;
		static DWORD msgHash_SerializeObject = CHashString(_T("SerializeObject")).GetUniqueID();
		m_ToolBox->SendMessage(msgHash_SerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sop );

		archive->Close();

		// Creating a CDatabaseItem single entry.
		StdString szDatabaseItemName = loadGlobalAttributesParams->Name->GetString();
		szDatabaseItemName += _T("_SingleEntry");
		CHashString hszDatabaseItemName( szDatabaseItemName );

		cop.name = &hszDatabaseItemName;
		cop.parentName = loadGlobalAttributesParams->Name;
		cop.typeName = &databaseItemType;
		m_ToolBox->SendMessage(msgHash_CreateObject, sizeof(CREATEOBJECTPARAMS), &cop);
	}
	else
	{
		EngineGetToolBox()->Log( LOGWARNING, _T("A global attributes set has already loaded.") );
	}

	return MSG_HANDLED_STOP;
}
///	\brief	implementation for buffer data interaction of object undo/redo actions
///	\param	pCommand - pointer to command this action belongs to
///	\param	hashName - hash of object name to interact
///	\param	offset - delta data offset in command buffer
///	\param	size - delta data size in command buffer
///	\param	mode - command buffer interaction mode
DWORD UndoRedoObjectDataImpl(CUndoCommandData *pCommand, DWORD hashName, size_t offset, size_t size, DeltaMode mode)
{
	DWORD res = MSG_HANDLED;
	// get data offset
	LPBYTE pData = pCommand->GetDeltaData() + offset;

	IToolBox *pToolBox = EngineGetToolBox();
	CHashString hszName = pToolBox->GetHashString(hashName);
	// check if we need to apply data changes or may init object directly
	if (size > 0)
	{
		IArchive *pArchive;
		if (DeltaNone == mode)
		{
			// create archive for serialization and fill it with buffered data
			pArchive = CreateMemoryArchive(pData, (DWORD)size);
		}
		else
		{
			// get current object state for applying delta data
			pArchive = GetEEObjectProperties(&hszName);
			Buffer currentData;
			// extract serialized data to buffer
			GetArchiveStreamData(pArchive, currentData);

			// adjust serialized data length if this is needed
			if (currentData.size() < size)
			{
				currentData.resize(size, 0);
			}

			// restore correct data for the stream
			if (DeltaAdd == mode)
			{
				for (Buffer::iterator it = currentData.begin(); size > 0; --size, ++pData, ++it)
				{
					(*it) = (*it) + (*pData);
				}
			}
			else
			{
				for (Buffer::iterator it = currentData.begin(); size > 0; --size, ++pData, ++it)
				{
					(*it) = (*it) - (*pData);
				}
			}

			// then write it
			pArchive->SetIsWriting(true);
			pArchive->SeekTo(0);
			pArchive->Write(&currentData.front(), currentData.size());
		}

		CFileVersionSetter lastVersion;
		// setup up serialization parameters
		SERIALIZEOBJECTPARAMS sop;
		sop.name = &hszName;
		sop.archive = pArchive;
		pArchive->SetIsWriting(false);
		pArchive->SeekTo(0);
		// serialize object from archive
		static DWORD msgHash_SerializeObject = CHashString(_T("SerializeObject")).GetUniqueID();
		res = pToolBox->SendMessage(msgHash_SerializeObject, sizeof(sop), &sop);
		if (res != MSG_HANDLED)
		{
			// log this error?
			return res;
		}

		int count = 0;
		pArchive->Read(count, _T("count"));
		ASSERT(count >= 0 && count <= 8);
		if (count > 0)
		{
			EDITINGPROPERTIESPARAMS epp;
			epp.name = &hszName;
			while (count--)
			{
				StdString name;
				StdString value;
				pArchive->Read(name, _T("name"));
				pArchive->Read(value, _T("value"));
				epp.params.insert(make_pair(name, value));
			}
			static const DWORD hashMsg_SetEditingProperties = CHashString(_T("SetEditingProperties")).GetUniqueID();
			pToolBox->SendMessage(hashMsg_SetEditingProperties, sizeof(epp), &epp);
		}

		pArchive->Close();
	}

	INITOBJECTPARAMS iop;
	// send message to EE to initialize the object
	iop.name = &hszName;
	static DWORD msgHash_InitObject = CHashString(_T("InitObject")).GetUniqueID();
	res = pToolBox->SendMessage(msgHash_InitObject, sizeof(INITOBJECTPARAMS), &iop);

	return res;
}
DWORD CQHStateMachineManager::OnLoadAndInitStateObject( DWORD size, void* aloadParams )
{
	StdString error;
	VERIFY_MESSAGE_SIZE(sizeof(LOADANDINITSTATEOBJECTPARAMS), size);
	DWORD areturn = MSG_NOT_HANDLED;

	LOADANDINITSTATEOBJECTPARAMS *SOParams = (LOADANDINITSTATEOBJECTPARAMS *)aloadParams;

	if( SOParams->StateMachineFileName == NULL ||
		SOParams->StateMachineName == NULL ||
		SOParams->StateObjectName == NULL )
	{
		areturn = MSG_ERROR;
		m_ToolBox->Log( LOGWARNING, _T("%s OnLoadAndInitStateObject(): null parameters from message\n"),
			__FILE__ );
		return areturn;
	}

	IHashString* Name = SOParams->StateObjectName;
	IHashString* parentName = SOParams->StateObjectParentName;

	CQHStateObject *pQHStateObject = NULL;
	pQHStateObject = dynamic_cast<CQHStateObject *>(m_ToolBox->CreateComponent(&m_stateObjectComponentType, 3, Name, parentName, SOParams->bIsInHierarchy));
	if( pQHStateObject == NULL )
	{
		areturn = MSG_ERROR;
		m_ToolBox->Log( LOGWARNING, _T("%s OnLoadAndInitStateObject(): cannot create object\n"), __FILE__);
		return areturn;
	}

	// add object to object factory
	OFACTORYADDPARAMS ofap;
	ofap.name = Name;
	ofap.component = pQHStateObject;
	static DWORD msgHash_AddObjectToFactory = CHashString(_T("AddObjectToFactory")).GetUniqueID();
	areturn = m_ToolBox->SendMessage(msgHash_AddObjectToFactory, sizeof(OFACTORYADDPARAMS), &ofap);
	if( areturn != MSG_HANDLED )
	{
		StdString error( __FILE__ " OnLoadAndInitStateObject(): cannot add object to factory\n" );
		m_ToolBox->Log( LOGWARNING, error );
		return areturn;
	}
	else
	{
		CREATEARCHIVE ca;
		CHashString memType(_T("Memory"));
		
		ca.mode = STREAM_MODE_WRITE | STREAM_MODE_READ;
		ca.streamData = NULL;
		ca.streamSize = 0;
		ca.streamType = &memType;

		static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID();
		areturn = m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &ca);
		if (areturn != MSG_HANDLED)
		{
			StdString error( __FILE__ " OnLoadAndInitStateObject(): cannot create archive\n" );
			m_ToolBox->Log( LOGWARNING, error );
			return areturn;
		}

		IArchive *ar = ca.archive;

		// We checked earlier if these were NULL        
		ar->Write( SOParams->StateMachineFileName->GetString() );
		ar->Write( SOParams->StateMachineName->GetString() );
		if( SOParams->StateMachineStartState != NULL )
		{
			ar->Write( SOParams->StateMachineStartState->GetString() );
		}
		else
		{
			ar->Write( _T("") );
		}
		ar->Write( SOParams->iUpdatePriority );
        
		SERIALIZEOBJECTPARAMS sop;
		sop.name = Name;
		sop.archive = ar;

		// serialize object
		static DWORD msgHash_SerializeObject = CHashString(_T("SerializeObject")).GetUniqueID();
		areturn = m_ToolBox->SendMessage(msgHash_SerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sop);
		ar->Close();

		if( areturn != MSG_HANDLED )
		{
			StdString error( __FILE__ " OnLoadAndInitStateObject(): cannot serialize object\n" );
			m_ToolBox->Log( LOGWARNING, error );
			return areturn;
		}
		else
		{
			// initialize object
			INITOBJECTPARAMS iop;
			iop.name = Name;
			static DWORD msgHash_InitObject = CHashString(_T("InitObject")).GetUniqueID();
			areturn = m_ToolBox->SendMessage(msgHash_InitObject, sizeof(INITOBJECTPARAMS), &iop);
			if( areturn != MSG_HANDLED )
			{
				StdString error( __FILE__ _T(" OnLoadAndInitStateObject(): cannot init object\n") );
				m_ToolBox->Log( LOGWARNING, error );
				return areturn;
			}
		}
	}

	return areturn;
}
/////////////////////////////////////////////////////////////
//	LOAD PARTICLE EMITTER
/////////////////////////////////////////////////////////////
DWORD CParticleLoader::OnLoadParticleFile(DWORD size, void *params)
{
	PERFORMANCE_PROFILER_AUTO(ParticleLoader_loadfile);

	VERIFY_MESSAGE_SIZE(size, sizeof(TCHAR *));
	TCHAR *pFilepath = (TCHAR *)params;

	StdString szFilename = ExtractFileName(pFilepath);
	CHashString hszFilename(szFilename);

	StdString szFilepath(pFilepath);
	CHashString hszFilepath(pFilepath);

	DWORD result;
	// Search for Object to see if it is already loaded
	// Check using the FindObject Message if the CParticleEmitter exists
	static DWORD msgHash_FindObject = CHashString(_T("FindObject")).GetUniqueID();
	FINDOBJECTPARAMS param;
	param.hszName = &hszFilepath;
	result = m_ToolBox->SendMessage(msgHash_FindObject, sizeof(FINDOBJECTPARAMS), &param);
	if (param.bFound == true)
	{
		//Object Exists
		return MSG_HANDLED_STOP;
	}

	// Create XMLArchive using IXML
	IXMLArchive *XMLar;
	CHashString streamType(_T("File"));

	CREATEARCHIVE ca;
	ca.mode = STREAM_MODE_READ;
	ca.streamData = pFilepath;
	ca.streamType = &streamType;
	static DWORD msgHash_CreateXMLArchive = CHashString(_T("CreateXMLArchive")).GetUniqueID();
	result = EngineGetToolBox()->SendMessage(msgHash_CreateXMLArchive, sizeof(CREATEARCHIVE), &ca);

	if( result != MSG_HANDLED )
	{
		m_ToolBox->Log(LOGWARNING, _T("Failed to load particle file: \"%s\"!\n"), szFilepath.c_str() );
		return MSG_ERROR;
	}
	XMLar = dynamic_cast<IXMLArchive *>(ca.archive);
	// break out if XMLar is NULL.
	if( !XMLar )
	{
		m_ToolBox->Log(LOGWARNING, _T("Failed to load particle file: \"%s\"!\n"), szFilepath.c_str() );
		XMLar->Close();
		return MSG_ERROR;
	}

	// Create MemArchive using IAR
	IArchive *MemArchive;
	CHashString memType(_T("Memory"));

	CREATEARCHIVE caOut;
	caOut.mode = STREAM_MODE_READ | STREAM_MODE_WRITE;
	caOut.streamData = NULL;
	caOut.streamSize = 0;
	caOut.streamType = &memType;
	static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID();
	if (m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &caOut) != MSG_HANDLED)
		return MSG_ERROR;
	MemArchive = caOut.archive;

	// EMITTER PARSE VALUES
	PARTICLEPROPERTIESKEY k;
	StdString szEmitterCheck;
	StdString szEmitterName;
	int numBrushes = 0;
	int numKeyframes = 0;
	StdString	szType;
	StdString	szBrushFilename;
	StdString	szPropertyName;

	// Archive -> GetNode (this should be "CParticleEmitter" )
	XMLar->GetNode(szEmitterCheck);

	// if this is particle line type, load it
	if ( szEmitterCheck == _T("CParticleLineType") )
	{
		static CHashString hszCParticleLineType(_T("CParticleLineType"));
		AddLoadedParticleType( &hszFilepath, &hszCParticleLineType, XMLar );
		m_ParticleObjectMap[ hszFilepath.GetUniqueID() ] = hszFilepath.GetUniqueID();
		XMLar->Close();
		MemArchive->Close();
		return MSG_HANDLED_STOP;
	}

	// if this is particle ribbon type, load it
	if ( szEmitterCheck == _T("CParticleRibbonType") )
	{
		static CHashString hszCParticleRibbonType(_T("CParticleRibbonType"));
		AddLoadedParticleType( &hszFilepath, &hszCParticleRibbonType, XMLar );
		m_ParticleObjectMap[ hszFilepath.GetUniqueID() ] = hszFilepath.GetUniqueID();
		XMLar->Close();
		MemArchive->Close();
		return MSG_HANDLED_STOP;
	}

	if ( szEmitterCheck != _T("ParticleEmitter") )
	{
		// Exit out if GetNode != CParticleEmitter
		XMLar->Close();
		MemArchive->Close();
		return MSG_ERROR;
	}
	MemArchive->SetIsWriting(true);
	// PARSE HEADER
	// READ
	XMLar->Read(szEmitterName, _T("name"));
	XMLar->Read(numBrushes, _T("brushes"));
	XMLar->Read(numKeyframes, _T("keyframes"));

	// WRITE
//	MemArchive->Write( szFilename, _T("filename") );
	MemArchive->Write( szEmitterName, _T("name"));

	MemArchive->Write( PARTICLE_SERIALIZE_NORMAL, _T("flag"));

	MemArchive->Write( numBrushes, _T("brushes"));
	MemArchive->Write( numKeyframes, _T("keyframes"));

	// PARSE BRUSHES
	for (int i = 0; i < numBrushes; i++)
	{
		XMLar->GetNode(szType);
		if (szType == _T("Brush"))
		{
			// READ
			XMLar->Read(szBrushFilename, _T("file"));
			// WRITE
			MemArchive->Write( szBrushFilename, _T("file"));
		}
		// Too many keyframes or invalid brush node
		else
		{
			XMLar->Close();
			MemArchive->Close();
			return MSG_ERROR;
		}
	}
	// PARSE KEYFRAMES
	for (int i = 0 ; i < numKeyframes ; i++)
	{
		XMLar->GetNode(szType);
		if (szType == _T("Keyframe"))
		{
			// READ
			XMLar->Read(szPropertyName, _T("type"));
			XMLar->Read(k.time, _T("time"));
			XMLar->Read(k.value, _T("value"));
			// WRITE
			MemArchive->Write( szPropertyName, _T("type"));
			MemArchive->Write( k.time, _T("time"));
			MemArchive->Write( k.value, _T("value"));
		}
		// Too many keyframes or invalid keyframe node
		else
		{
			XMLar->Close();
			MemArchive->Close();
			return MSG_ERROR;
		}
	}
	XMLar->Close();

	// Change the Memarchive to read;
	MemArchive->SetIsWriting(false);

	CHashString hszParticleManager = _T("CParticleManager");
	PARTICLELOADINFO pli;
	pli.filepath = &hszFilepath;
	pli.data = MemArchive;
	static DWORD msgHash_AddLoadedEmitter = CHashString(_T("AddLoadedEmitter")).GetUniqueID();
	result = m_ToolBox->SendMessage(msgHash_AddLoadedEmitter, sizeof( PARTICLELOADINFO), &pli);
	if (result != MSG_HANDLED)
	{
		m_ToolBox->Log(LOGERROR, _T("%s(%d): ParticleLoader failed to add emitter %s to manager map\n"), __FILE__, __LINE__, hszFilepath.GetString());
	}

	// Clean up temporary data.
	MemArchive->Close();

	return MSG_HANDLED_STOP;
}
bool CNodeSystemTest::TestCreateNodeSystem()
{
	bool result = true;
	bool subResult = false;

	CHashString hszNodeSystemName(_T("NodeSystem1"));
	CHashString hszNodeSystemType(_T("CNodeSystem"));

	m_dialogEditControl->ReplaceSel(_T("  Testing Creation of Node System 1 - \n"));
	CreateObject( &hszNodeSystemName, NULL, &hszNodeSystemType );

	InitializeObject( &hszNodeSystemName );

	m_dialogEditControl->ReplaceSel(_T("    Created node system found in engine: "));

	subResult = FindObject( &hszNodeSystemName );
	SUBREPORT( subResult );
	result = result && subResult;

	CHashString hszNodeName(_T("Node1"));
	CHashString hszNodeType(_T("CNode"));

	CreateObject( &hszNodeName, &hszNodeSystemName, &hszNodeType );

	InitializeObject( &hszNodeName );
	IArchive *archive = CreateMemoryArchive();
	archive->SetIsWriting( true );
	archive->Write( 1.0f, _T("Version") );
	archive->Write( 0.0f, _T("X") );
	archive->Write( 0.0f, _T("Y") );
	archive->Write( 0.0f, _T("Z") );
	archive->SetIsWriting( false );

	SerializeObject( &hszNodeName, archive, false );
	archive->Close();

	CHashString hszNodeConnectionName(_T("NodeConnection1"));
	CHashString hszNodeConnectionType(_T("CNodeConnection"));

	CreateObject( &hszNodeConnectionName, &hszNodeSystemName, &hszNodeConnectionType );

	InitializeObject( &hszNodeConnectionName );
	archive = CreateMemoryArchive();
	archive->SetIsWriting( true );
	archive->Write( 1.0f, _T("Version") );
	archive->Write( "", _T("Node1") );
	archive->Write( "", _T("Node2") );
	archive->SetIsWriting( false );

	SerializeObject( &hszNodeConnectionName, archive, false );
	archive->Close();

	archive = CreateMemoryArchive();
	archive->SetIsWriting( true );
	SerializeObject( &hszNodeSystemName, archive, true );
	float fVersion;
	int iNumNodes;
	int iNumConnections;

	archive->SetIsWriting( false );
	archive->Read( fVersion );
	archive->Read( iNumNodes );
	archive->Read( iNumConnections );
	archive->Close();

	m_dialogEditControl->ReplaceSel(_T("    Verify values: "));
	subResult = fVersion == 1.0f;
	subResult = subResult && iNumNodes == 1;
	subResult = subResult && iNumConnections == 1;
	SUBREPORT( subResult );
	result = result && subResult;

	DeleteObject( &hszNodeSystemName );

	m_dialogEditControl->ReplaceSel(_T("    Objects properly deleted: "));
	subResult = !FindObject( &hszNodeSystemName );
	subResult = subResult && !FindObject( &hszNodeName );
	subResult = subResult && !FindObject( &hszNodeConnectionName );
	SUBREPORT( subResult );
	result = result && subResult;

	m_dialogEditControl->ReplaceSel(_T("  TestCreateNodeSystem overall: "));
	return result;
}
DWORD CSoundManager::OnPlaySound(DWORD size, void *params)
{
	VERIFY_MESSAGE_SIZE(sizeof(PLAYSOUNDPARAMS), size);
	PLAYSOUNDPARAMS psp = *(PLAYSOUNDPARAMS *)params;

	if ( psp.fileName == NULL )
	{
		m_ToolBox->SetErrorValue(ERR_NULL_POINTER);
		m_ToolBox->Log( LOGWARNING, _T("CSoundManager error: malformed PLAYSOUNDPARAMS struct (fileName is NULL)\n"));
		return MSG_NOT_HANDLED;
	}

	CHashString hsObjName;
	GENERATEUNIQUEOBJECTNAMEPARAMS guonp;
	guonp.name = psp.fileName;
	guonp.newname = &hsObjName;
	static DWORD msgGenerateUniqueObjectName = CHashString(_T("GenerateUniqueObjectName")).GetUniqueID();
	if (m_ToolBox->SendMessage(msgGenerateUniqueObjectName, sizeof(GENERATEUNIQUEOBJECTNAMEPARAMS), &guonp) != MSG_HANDLED)
	{
		m_ToolBox->Log(LOGERROR, _T("CSoundManager could not generate a unique object name for sound %s\n"), psp.fileName->GetString());
		return MSG_ERROR;
	}

	IComponent *soundComp = m_ToolBox->CreateComponent(&m_hsSoundObjTypeName, 3, &hsObjName, psp.hsParentName, psp.bInHierarchy);
	if (soundComp == NULL)
	{
		m_ToolBox->Log(LOGWARNING, _T("Sound manager: unable to create Sound Object %s, in file %s at line %d\n"),
			hsObjName.GetString(), __FILE__, __LINE__);
		return MSG_NOT_HANDLED;
	}

	OFACTORYADDPARAMS ofap;
	ofap.name = &hsObjName;
	ofap.component = soundComp;
	static DWORD msgHash_AddObjectToFactory = CHashString(_T("AddObjectToFactory")).GetUniqueID();
	m_ToolBox->SendMessage(msgHash_AddObjectToFactory, sizeof(OFACTORYADDPARAMS), &ofap);

	ISoundObject *newSoundObject = dynamic_cast<ISoundObject*>(soundComp);
	if (newSoundObject == NULL)
	{
		m_ToolBox->Log(LOGWARNING, _T("COpenALSoundManager: could not cast component to a CSoundObject!\n"));
		assert(newSoundObject);
		return MSG_NOT_HANDLED;
	}

	CREATEARCHIVE ca;
	ca.mode = STREAM_MODE_WRITE | STREAM_MODE_READ;
	ca.streamData = NULL; // use internal buffer
	ca.streamSize = 0;
	CHashString memType(_T("Memory"));
	ca.streamType = &memType;
	static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID();
	if (m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &ca) != MSG_HANDLED)
	{
		return MSG_ERROR;
	}
	IArchive *MemArchive = ca.archive;

	MemArchive->SetIsWriting(true);

	// some pre-checks
	bool autoRemove = true;
	bool is3DSound = false;

	// always have to auto remove if the remote creator isn't going to keep track of the object
	if (psp.objectName != NULL)
	{
		autoRemove = psp.autoRemove;
	}

	if (psp.is3DSound)
	{
		if (psp.soundPosition != NULL)
		{
			is3DSound = true;
		}
		else
		{
			m_ToolBox->Log(LOGWARNING, _T("Sound manager: play sound position is null for sound %s; 3D sound will play in 2D space\n"), psp.fileName->GetString());
		}
	}

	// coordinates with sound obj serialization
	MemArchive->Write(1.1f, _T("Version"));
	MemArchive->Write(psp.fileName->GetString(), _T("FileName"));
	MemArchive->Write(psp.volume, _T("MaxVolume"));
	MemArchive->Write(autoRemove, _T("AutoRemove"));
	MemArchive->Write(is3DSound, _T("Is3DSound"));	
	MemArchive->Write(psp.looping, _T("IsLooping"));
	MemArchive->Write(true, _T("AutoStart"));
	MemArchive->Write(psp.pitch, _T("PitchMultiplier"));

	MemArchive->SetIsWriting(false);

	SERIALIZEOBJECTPARAMS sop;
	sop.name = &hsObjName;
	sop.archive = MemArchive;
	static DWORD msgHash_SerializeObject = CHashString(_T("SerializeObject")).GetUniqueID();
	m_ToolBox->SendMessage(msgHash_SerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sop, NULL, NULL);

	MemArchive->Close();	

	if (is3DSound == true)
	{
		newSoundObject->SetSoundPosition(*psp.soundPosition);
	}
	
	INITOBJECTPARAMS iop;
	iop.name = &hsObjName;
	static DWORD msgHash_InitObject = CHashString(_T("InitObject")).GetUniqueID();
	m_ToolBox->SendMessage(msgHash_InitObject, sizeof(INITOBJECTPARAMS), &iop, NULL, NULL);

	if (psp.objectName != NULL)
	{
		// copy string name into message hashstring
		*psp.objectName = hsObjName;
	}

	return MSG_HANDLED_STOP;
}
DWORD COpenALSoundUtility::OnLoadSoundDatabase(DWORD size, void* param)
{
	VERIFY_MESSAGE_SIZE(size, sizeof(IHashString));
	IHashString *dbFileName = (IHashString*) param;

	if ((dbFileName != NULL) && (_tcscmp(dbFileName->GetString(), _T("")) != 0))
	{
		TCHAR *fileName = _tcsdup(dbFileName->GetString());
		LOADFILEEXTPARAMS lfep;
		lfep.fileName = fileName;
		lfep.bInternalLoad = true;

		static DWORD msgLoadFileByExtension = CHashString(_T("LoadFileByExtension")).GetUniqueID();
		DWORD retval = m_ToolBox->SendMessage(msgLoadFileByExtension, sizeof(LOADFILEEXTPARAMS), &lfep);
		free( fileName );
		if (retval == MSG_HANDLED)
		{
			// clear prior sound list - not additive, exclusive!
			m_SoundMap.clear();
			
			CHashString hsSoundDBObject;
			DATABASEINFO dbi;
			dbi.m_FileName = dbFileName;
			static DWORD msgGetDatabase = CHashString(_T("GetDatabase")).GetUniqueID();
			retval = m_ToolBox->SendMessage(msgGetDatabase, sizeof(DATABASEINFO), &dbi);
			if (retval == MSG_HANDLED)
			{
				hsSoundDBObject.Init(dbi.m_DatabaseName->GetString());
				DATABASEATTRIBUTEPARAMS dap;
				CREATEARCHIVE ca;
				static CHashString memType(_T("Memory"));

				ca.mode = STREAM_MODE_WRITE | STREAM_MODE_READ;
				ca.streamData = NULL;
				ca.streamSize = 0;
				ca.streamType = &memType;
				static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID();
				m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &ca);

				IArchive *attribArchive = ca.archive;
				if (attribArchive == NULL)
				{
					m_ToolBox->Log(LOGERROR, _T("Sound manager: archive is null; could not get sound attributes!\n\tNo sounds loaded!\n"));
					return MSG_ERROR;
				}

				dap.m_AttributeArchive = attribArchive;

				static DWORD msgGetAttribute = CHashString(_T("GetAttribute")).GetUniqueID();
				static CHashString hsKeyString(_T("KeyString"));
				static CHashString hsFileName(_T("FileName"));
				static CHashString hsGlobalVolume(_T("GlobalVolume"));
				static CHashString hsCachedUncompressed(_T("CacheUncompressed"));

				static CHashString hsDBType(_T("CDefinedDatabase"));
				for (UINT i=0; i<(UINT)dbi.m_nItems; i++)
				{
					// get key string
					attribArchive->SeekTo(0, SEEK_SET);
					dap.m_Index = i;
					dap.m_AttributeName = &hsKeyString;
					retval = m_ToolBox->SendMessage(msgGetAttribute, sizeof(DATABASEATTRIBUTEPARAMS), &dap, &hsSoundDBObject, &hsDBType);
					if (retval != MSG_HANDLED)
					{
						m_ToolBox->Log(LOGERROR, _T("Sound manager: could not get key attribute for row %d; sounds not fully loaded!\n"), i);
						attribArchive->Close();
						return MSG_ERROR;
					}

					CHashString hsKey;
					StdString szKey;
					attribArchive->SetIsWriting(false);
					attribArchive->Read(szKey);
					hsKey = szKey;

					// get filename
					attribArchive->SeekTo(0, SEEK_SET);
					dap.m_AttributeName = &hsFileName;
					retval = m_ToolBox->SendMessage(msgGetAttribute, sizeof(DATABASEATTRIBUTEPARAMS), &dap, &hsSoundDBObject, &hsDBType);
					if (retval != MSG_HANDLED)
					{
						m_ToolBox->Log(LOGERROR, _T("Sound manager: could not get file attribute for row %d; sounds not fully loaded!\n"), i);
						attribArchive->Close();
						return MSG_ERROR;
					}

					CHashString hsFile;
					StdString szFile;
					attribArchive->SetIsWriting(false);
					attribArchive->Read(szFile);
					szFile.tolower();
					hsFile = szFile;

					// get volume
					attribArchive->SeekTo(0, SEEK_SET);
					dap.m_AttributeName = &hsGlobalVolume;
					retval = m_ToolBox->SendMessage(msgGetAttribute, sizeof(DATABASEATTRIBUTEPARAMS), &dap, &hsSoundDBObject, &hsDBType);
					if (retval != MSG_HANDLED)
					{
						m_ToolBox->Log(LOGERROR, _T("Sound manager: could not get volume attribute for row %d; sounds not fully loaded!\n"), i);
						attribArchive->Close();
						return MSG_ERROR;
					}

					float fVolume;
					attribArchive->SetIsWriting(false);
					attribArchive->Read(fVolume);

					// get cached attribute
					attribArchive->SeekTo(0, SEEK_SET);
					dap.m_AttributeName = &hsCachedUncompressed;
					retval = m_ToolBox->SendMessage(msgGetAttribute, sizeof(DATABASEATTRIBUTEPARAMS), &dap, &hsSoundDBObject, &hsDBType);
					if (retval != MSG_HANDLED)
					{
						m_ToolBox->Log(LOGERROR, _T("Sound manager: could not get volume attribute for row %d; sounds not fully loaded!\n"), i);
						attribArchive->Close();
						return MSG_ERROR;
					}

					bool bCachedUncompressed;
					attribArchive->SetIsWriting(false);
					attribArchive->Read(bCachedUncompressed);

					if (_tcscmp(szKey, _T("GlobalSoundVolume")) == 0)
					{
						static DWORD msgSetGlobalSoundVolume = CHashString(_T("SetGlobalSoundVolume")).GetUniqueID();
						m_ToolBox->SendMessage(msgSetGlobalSoundVolume, sizeof(float), &fVolume);						
					}
					else if(_tcscmp(szKey, _T("GlobalMusicVolume")) == 0)
					{
						static DWORD msgSetGlobalMusicVolume = CHashString(_T("SetGlobalMusicVolume")).GetUniqueID();
						m_ToolBox->SendMessage(msgSetGlobalMusicVolume, sizeof(float), &fVolume);
					}
					else
					{					
						// insert into map
						GLOBALSOUNDDATA gsd;
						gsd.dwFileName = hsFile.GetUniqueID();
						gsd.fVolume = fVolume;
						gsd.bCachedUncompressed = bCachedUncompressed;

						m_SoundMap[hsKey.GetUniqueID()] = gsd;
						m_FileToKeyMap[hsFile.GetUniqueID()] = hsKey.GetUniqueID();
					}
				}

				attribArchive->Close();
			}
			else
			{
				m_ToolBox->Log(LOGERROR, _T("Sound manager: could not get database info!\n\tNo sounds loaded!\n"));
				return MSG_ERROR;
			}
		}
		else
		{
			m_ToolBox->Log(LOGERROR, _T("Sound manager: sound database failed to load!\n\tNo sounds loaded!\n"));
			return MSG_ERROR;
		}
	}
	return MSG_HANDLED_STOP;
}
/////////////////////////////////////////////////////////////
//	LOAD PARTICLE BRUSH
/////////////////////////////////////////////////////////////
DWORD CParticleLoader::OnLoadParticleBrush(DWORD size, void *params)
{
	VERIFY_MESSAGE_SIZE(size, sizeof(TCHAR *));
	TCHAR *pFilepath = (TCHAR *)params;

	StdString szFilename = ExtractFileName(pFilepath);
	CHashString hszFilename(szFilename);

	StdString szFilepath(pFilepath);
	CHashString hszFilepath(pFilepath);
	
	DWORD result;

	// Search for Object to see if it is already loaded
	// Check using the FindObject Message if the CParticleEmitter exists
	static DWORD msgHash_FindObject = CHashString(_T("FindObject")).GetUniqueID();
	FINDOBJECTPARAMS param;
	param.hszName = &hszFilename;
	result = m_ToolBox->SendMessage(msgHash_FindObject, sizeof(FINDOBJECTPARAMS), &param);
	if (param.bFound == true)
	{
		//Object Exists
		return MSG_HANDLED_STOP;
	}

	// Create XMLArchive using IXML
	IXMLArchive *XMLar;
	CHashString streamType(_T("File"));

	CREATEARCHIVE ca;
	ca.mode = STREAM_MODE_READ;
	ca.streamData = pFilepath;
	ca.streamType = &streamType;
	static DWORD msgHash_CreateXMLArchive = CHashString(_T("CreateXMLArchive")).GetUniqueID();
	result = EngineGetToolBox()->SendMessage(msgHash_CreateXMLArchive, sizeof(CREATEARCHIVE), &ca);

	if( result != MSG_HANDLED )
	{
		m_ToolBox->Log(LOGWARNING, _T("Failed to load particle file: \"%s\"!\n"), szFilepath.c_str() );
		return MSG_ERROR;
	}
	XMLar = dynamic_cast<IXMLArchive *>(ca.archive);
	// break out if XMLar is NULL.
	if( !XMLar )
	{
		m_ToolBox->Log(LOGWARNING, _T("Failed to load particle file: \"%s\"!\n"), szFilepath.c_str() );
		XMLar->Close();
		return MSG_ERROR;
	}

	// Create MemArchive using IAR
	IArchive *MemArchive;
	CHashString memType(_T("Memory"));

	CREATEARCHIVE caOut;
	caOut.mode = STREAM_MODE_READ | STREAM_MODE_WRITE;
	caOut.streamData = NULL;
	caOut.streamSize = 0;
	caOut.streamType = &memType;
	static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID();
	if (m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &caOut) != MSG_HANDLED)
	{
		XMLar->Close();
		return MSG_ERROR;
	}
	MemArchive = caOut.archive;

	// BRUSH PARSE VALUES
	StdString szType;
	StdString szPropertyName;
	StdString szBrushCheck;
	StdString szBrushName;
	bool additive;
	int nKeyframes;
	float framerate;
	float texturerate;
	StdString szTexturePath;
	bool loop;
	float AttachToEmitter;
	StdString szShader;
	PARTICLEPROPERTIESKEY k;

	// Archive -> GetNode (this should be "ParticleBrush" )
	XMLar->GetNode(szBrushCheck);
	if ( szBrushCheck != _T("ParticleBrush") )
	{
		// Exit out if GetNode != ParticleBrush
		XMLar->Close();
		MemArchive->Close();
		return MSG_ERROR;
	}

	MemArchive->SetIsWriting(true);
	// PARSE HEADER
	// READ
	XMLar->Read( szBrushName, _T("name"));
	XMLar->Read( additive, _T("additive"));
	XMLar->Read( framerate, _T("framerate"));
	XMLar->Read( texturerate, _T("texturerate"));
	XMLar->Read( szTexturePath, _T("texture"));
	XMLar->Read( loop, _T("loop"));
	XMLar->Read( AttachToEmitter, _T("AttachToEmitter"));
	XMLar->Read( szShader, _T("shader"));

	XMLar->Read( nKeyframes, _T("keyframes"));

	// WRITE
//	MemArchive->Write( szFilename, _T("filename") );
//	MemArchive->Write( szFilepath, _T("filepath") );

	MemArchive->Write( szBrushName, _T("name"));
	MemArchive->Write( additive, _T("additive"));
	MemArchive->Write( framerate, _T("framerate"));
	MemArchive->Write( texturerate, _T("texturerate"));
	MemArchive->Write( szTexturePath, _T("texture"));
	MemArchive->Write( loop, _T("loop"));
	MemArchive->Write( AttachToEmitter, _T("AttachToEmitter"));
	MemArchive->Write( szShader, _T("shader"));

	MemArchive->Write( PARTICLE_SERIALIZE_NORMAL, _T("flag"));

	MemArchive->Write( nKeyframes, _T("keyframes"));

	// PARSE KEYFRAMES
	for (int i = 0 ; i < nKeyframes ; i++)
	{
		XMLar->GetNode(szType);
		if (szType == _T("Keyframe"))
		{
			// READ
			XMLar->Read(szPropertyName, _T("type"));
			XMLar->Read(k.time, _T("time"));
			XMLar->Read(k.value, _T("value"));
			// WRITE
			MemArchive->Write( szPropertyName, _T("type"));
			MemArchive->Write( k.time, _T("time"));
			MemArchive->Write( k.value, _T("value"));
		}
		// Too many keyframes or invalid keyframe node
		else
		{
			XMLar->Close();
			MemArchive->Close();
			return MSG_ERROR;
		}
	}
	XMLar->Close();

	// Change the Memarchive to read;
	MemArchive->SetIsWriting(false);

	CHashString hszParticleManager = _T("CParticleManager");
	PARTICLELOADINFO pli;
	pli.filepath = &hszFilepath;
	pli.data = MemArchive;
	static DWORD msgHash_AddLoadedBrush = CHashString(_T("AddLoadedBrush")).GetUniqueID();
	result = m_ToolBox->SendMessage(msgHash_AddLoadedBrush, sizeof( PARTICLELOADINFO), &pli);
	if (result != MSG_HANDLED)
	{
		m_ToolBox->Log(LOGERROR, _T("ParticleLoader failed to add emitter to manager map"));
	}

	// Object Serialized, close memarchive;
	MemArchive->Close();

	return MSG_HANDLED_STOP;
}
DWORD CDatabaseManager::OnGetTypedDatabase(DWORD size, void *params)
{
	TYPEDATABASEINFO *pDBTypeInfo = NULL;
	LOADFILEEXTPARAMS lfep;
	FILENAMETODATABASEMAP::iterator itrDBInfo;
	IDTOOBJECTMAP::iterator itrDBObject;
	DWORD result = 0;

	// Verify and Process incomming data.
	VERIFY_MESSAGE_SIZE(size, sizeof(TYPEDATABASEINFO));
	pDBTypeInfo = (TYPEDATABASEINFO *)params;

	IHashString *tempHash = pDBTypeInfo->phszFilepath;
	if (tempHash == NULL)
	{
		m_ToolBox->Log(LOGWARNING, _T("DB: Invalid database filename specifed, cannot be NULL\n"));
		return MSG_ERROR;
	}
	if (!pDBTypeInfo->pArchive)
	{
		m_ToolBox->Log(LOGWARNING, _T("DB: Invalid database archive specifed, cannot be NULL\n"));
		return MSG_ERROR;
	}
	// Check manager maps to see if database is already loaded.
	itrDBInfo = m_FilepathToDBInfo.find( tempHash->GetUniqueID() );
	itrDBObject = m_FilepathToObject.find( tempHash->GetUniqueID() );

	// Name is not found and database does not exist in manager map. Load DB.
	if( itrDBInfo == m_FilepathToDBInfo.end() && itrDBObject == m_FilepathToObject.end() )
	{
		lfep.fileName = (TCHAR *)tempHash->GetString();
		lfep.bInternalLoad = true;
		DWORD msgHash_LoadFileByExtension = CHashString(_T("LoadFileByExtension")).GetUniqueID();
		result = m_ToolBox->SendMessage(msgHash_LoadFileByExtension,
								   sizeof(LOADFILEEXTPARAMS), 
								   &lfep);
		if (result != MSG_HANDLED)
		{
			m_ToolBox->SetErrorValue(WARN_INVALID_FILE);
			m_ToolBox->Log(LOGWARNING, _T("Invalid database file %s\n"), lfep.fileName);
			return MSG_NOT_HANDLED;
		}

		// Because databases are added to the manager automatically and we cannot get
		// an iterator to the object just loaded by extension, we have to search for the
		// object again in manager map.
		itrDBInfo = m_FilepathToDBInfo.find( tempHash->GetUniqueID() );
		itrDBObject = m_FilepathToObject.find( tempHash->GetUniqueID() );
	}
	

	// There are two types of Databases, an old type that does not use schemas and a newer type that does.
	// New Type:
	CDefinedDatabase *pDefinedDB = NULL;
	CDatabaseSchema *pDBSchema = NULL;
	if ((itrDBInfo == m_FilepathToDBInfo.end()) &&  (itrDBObject != m_FilepathToObject.end()))
	{
		pDefinedDB = (CDefinedDatabase*)(itrDBObject->second);
		pDBSchema = (CDatabaseSchema*)(pDefinedDB->GetSchema());

		// Retrieve Schema Table.
		CREATEARCHIVE ca;
		CHashString memType(_T("Memory"));
		ca.mode = STREAM_MODE_WRITE | STREAM_MODE_READ;
		ca.streamData = NULL;
		ca.streamSize = 0;
		ca.streamType = &memType;
		static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID();
		m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &ca);
		IArchive * archive = ca.archive;
		pDBSchema->GetSchemaArchive( archive );
		
		IArchive * archiveOut = pDBTypeInfo->pArchive;

		StdString szTemp;
		bool bTemp;
		int nSchemaValues = 0;
		StdString szName;
		CHashString hszName;
		StdString szType;
		archive->Read(szTemp);
		archive->Read(nSchemaValues);
		int nDBItems = pDefinedDB->GetNumItems();

		// Write Total Number of Elements
		archiveOut->SetIsWriting(true);
		archiveOut->Write(nDBItems);
		archiveOut->Write(nSchemaValues);
		for (int i = 0; i < nDBItems; i++)
		{
			archive->SeekTo(0);	
			archive->Read(szTemp);
			archive->Read(nSchemaValues);
			for (int j = 0; j < nSchemaValues; j++)
			{
				archive->Read(szName);
				archive->Read(szType);
				archive->Read(bTemp);

				hszName.Init( szType.c_str() );
				archiveOut->Write(szName.c_str());
				archiveOut->Write(szType.c_str());
				DATABASEDATA * pValue = NULL;
				pValue = pDefinedDB->GetDatabaseItem(i)->GetDataByName( &hszName );
				pDBSchema->GetSchemaItem(&hszName)->DBWrite(pValue, archiveOut, _T(""));
			}
		}
		archiveOut->SetIsWriting(false);
		archive->Close();
		return MSG_HANDLED_STOP;
	}
	// Old Type DB or Missing DB:
	else
	{
		m_ToolBox->Log(LOGERROR, _T("DB: Attempt to call GetTypedDatabase on a non-existant DB or a CDatabase DB that does not support types.\n"));
		return MSG_ERROR;
	}
}
/////////////////////////////////////////////////////////////
// New Particle Brush
/////////////////////////////////////////////////////////////
DWORD CParticleLoader::OnNewParticleBrush(DWORD size, void *params)
{

	VERIFY_MESSAGE_SIZE(size, sizeof(TCHAR *));
	TCHAR *czFilepath = (TCHAR *)params;

	StdString szFilename = ExtractFileName(czFilepath);
	CHashString hszFilename(szFilename);

	StdString szFilepath(czFilepath);
	CHashString hszFilepath(czFilepath);

	CREATE_PARTICLE_STRING_TABLE(BrushPropertyStringTable);

	DWORD result;
	// Search for Object to see if it is already loaded
	// Check using the FindObject Message if the CParticleEmitter exists
	static DWORD msgHash_FindObject = CHashString(_T("FindObject")).GetUniqueID();
	FINDOBJECTPARAMS param;
	param.hszName = &hszFilename;
	result = m_ToolBox->SendMessage(msgHash_FindObject, sizeof(FINDOBJECTPARAMS), &param);
    if (param.bFound == true)
	{
		//Object Exists
		return MSG_HANDLED_STOP;
	}

	// Use Create Object Message to create the object (use the filename as the name)
	CHashString hszTypeName(_T("CParticleType"));
	CREATEOBJECTPARAMS cop;
	cop.name = &hszFilename;
	cop.parentName = NULL;
	cop.typeName = &hszTypeName;
	static DWORD msgHash_CreateObject = CHashString(_T("CreateObject")).GetUniqueID();
	result = m_ToolBox->SendMessage(msgHash_CreateObject, sizeof(CREATEOBJECTPARAMS), &cop);
	if (result == MSG_ERROR)
		return MSG_ERROR;

	// Create MemArchive using IAR
	IArchive *MemArchive;
	CHashString memType(_T("Memory"));

	CREATEARCHIVE caOut;
	caOut.mode = STREAM_MODE_READ | STREAM_MODE_WRITE;
	caOut.streamData = NULL;
	caOut.streamSize = 0;
	caOut.streamType = &memType;
	static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID();
	result = m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &caOut);
	if (result == MSG_ERROR)
		return MSG_ERROR;

	MemArchive = caOut.archive;

	// Change the Memarchive to write
	MemArchive->SetIsWriting(true);

	// Write Initial Emitter Properties:
	// WRITE INTERNAL DATA
	MemArchive->Write( szFilename, _T("filename") );
	MemArchive->Write( szFilepath, _T("filepath") );

	// WRITE FILE HEADER
	MemArchive->Write( _T("NewEmitter"), _T("name"));
	MemArchive->Write( false, _T("additive"));
	MemArchive->Write( 30.0f, _T("framerate"));
	MemArchive->Write( 30.0f, _T("texturerate"));
	MemArchive->Write( _T(""), _T("texture"));
	MemArchive->Write( false, _T("loop"));
	MemArchive->Write( 0.0f, _T("AttachToEmitter"));
	MemArchive->Write( _T(""), _T("shader"));

	MemArchive->Write( PARTICLE_VARIABLE_MAX, _T("keyframes"));

	// WRITE PROPERTIES
	for (int i = 0; i < PARTICLE_VARIABLE_MAX; i++)
	{
		MemArchive->Write(BrushPropertyStringTable[i], _T("type"));
		MemArchive->Write(0.0f, _T("time"));
		MemArchive->Write(0.0f, _T("value"));
	}

	// Change the Memarchive to read
	MemArchive->SetIsWriting(false);

	// Serialize out Emitter Data
	SERIALIZEOBJECTPARAMS sop;
	sop.archive = MemArchive;
	sop.name = &hszFilename;
	static DWORD msgHash_SerializeObject = CHashString(_T("SerializeObject")).GetUniqueID();
	result = m_ToolBox->SendMessage(msgHash_SerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sop, NULL, NULL);
	if (result == MSG_ERROR)
	{
		MemArchive->Close();
		return MSG_ERROR;
	}

	// Object Serialized, close memarchive;
	MemArchive->Close();

	// Use the Init Message with the MemArchive
	INITOBJECTPARAMS iop;
	iop.name = &hszFilename;
	static DWORD msgHash_InitObject = CHashString(_T("InitObject")).GetUniqueID();
	m_ToolBox->SendMessage(msgHash_InitObject, sizeof(INITOBJECTPARAMS), &iop, NULL, NULL);

	return MSG_HANDLED_STOP;
}
DWORD CDatabaseManager::OnCreateGlobalDBObject(DWORD size, void *params)
{
	DBCREATEPARAMS *db;
	CHashString memType(_T("Memory"));
	IArchive *MemArchive;
	StdString str;
	TCHAR strNum[50];
	int memsize;
	VERIFY_MESSAGE_SIZE(size, sizeof(DBCREATEPARAMS));

	db = (DBCREATEPARAMS*)params;

	// begin name
	str = _T("GlobalDatabase");

	// append number to each name
	_ltot(m_iGlobalCount, strNum, 10);
	str = str + strNum;
	
	// increment global count
	++m_iGlobalCount;

	// get name, parent and type
	CHashString name(str.c_str());
	static CHashString typeName(_T("CDatabase"));
	
	// create object
	CDatabase *pDatabase = dynamic_cast<CDatabase *>(
		m_ToolBox->CreateComponent(&typeName, 3, &name, NULL, false));

	// add object to object factory by hand since we need a pointer to the database object
	OFACTORYADDPARAMS aotf;
	aotf.component = pDatabase;
	aotf.name = &name;
	static DWORD msgHash_AddObjectToFactory = CHashString(_T("AddObjectToFactory")).GetUniqueID();
	m_ToolBox->SendMessage(msgHash_AddObjectToFactory, sizeof(aotf), &aotf );

	// get size of name
	memsize = _tcslen(db->fileName)+1;

	// create memory chunk
	char* memBuffer = new char[memsize];

	// create archive
	CREATEARCHIVE ca;
	ca.mode =  STREAM_MODE_READ | STREAM_MODE_WRITE;
	ca.streamData = memBuffer;
	ca.streamSize = memsize;
	ca.streamType = &memType;
	static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID();
	if (m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &ca) != MSG_HANDLED)
	{
		StdString error;
		error = _T(__FILE__ " OnCreateGlobalDBObject(): cannot create archive\n");
		EngineGetToolBox()->Log( LOGWARNING, error );
		if( memBuffer != NULL )
		{
			delete [] memBuffer;
		}
		memBuffer = NULL;
		return MSG_ERROR;
	}

	// write name to archive 
	MemArchive = ca.archive;
	MemArchive->Write(db->fileName);

	// serialize database object
	pDatabase->Serialize(*MemArchive);
	// init database object
	pDatabase->Init();

	// close the archive
	MemArchive->Close();
	// clean up
	if( memBuffer != NULL )
	{
		delete [] memBuffer;
	}
	memBuffer = NULL;
	
	*static_cast<IDatabase**>(db->dbObj) = pDatabase;

	return MSG_HANDLED_STOP;
}