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
}
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
}
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 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);
    }
}
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();
	}
}
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();
}
DWORD CSchemaItem::GetType( DATABASEATTRIBUTEPARAMS *databaseAttributeParams )
{
	DWORD retVal = MSG_NOT_HANDLED;
	if( databaseAttributeParams != NULL )
	{
		
		if( databaseAttributeParams->m_AttributeTypeArchive != NULL )
		{
			IArchive *ar = databaseAttributeParams->m_AttributeTypeArchive;
			ar->SetIsWriting( true );
			ar->SeekTo( 0 );
			ar->Write( m_hszType.GetString() );
		}
		else
		{
			m_ToolBox->Log( LOGWARNING, _T("No archive specified for GetAttributeType.\n") );
		}

		retVal = MSG_HANDLED_STOP;
	}
	else
	{
		m_ToolBox->Log( LOGWARNING, _T("Attribute parameters not defined.\n") );
	}

	return retVal;
}
DWORD CGUIStaticText::OnUpdateLanguageEntryParams(DWORD size, void *param)
{
	VERIFY_MESSAGE_SIZE(size, sizeof(IArchive*));
	IArchive* ar = (IArchive*) param;

	if (ar)
	{
		if (m_LanguageTextParams != NULL)
		{
			delete [] m_LanguageTextParams;
			m_LanguageTextParams = NULL;
		}
		// do deep copy of archive params
		UINT archiveSize = ar->SeekTo(0, SEEK_END);

		if (archiveSize > 0)
		{		
			ar->SeekTo(0, SEEK_SET);
			ar->SetIsWriting(false);

			m_LanguageTextParams = new BYTE[archiveSize];
			ar->Read(m_LanguageTextParams, archiveSize);

			m_iLangTextParamSize = archiveSize;
		}
	}

	UpdateLanguageEntryText();

	return MSG_HANDLED_STOP;
}
IArchive* CGUIStaticText::CreateAndFillArchive()
{
	if (m_LanguageTextParams)
	{
		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 *ar = ca.archive;
		if (ar)
		{
			ar->SetIsWriting(true);
			ar->SeekTo(0);
			ar->Write(m_LanguageTextParams, m_iLangTextParamSize);
		}
		return ar;
	}
	else
	{
		return NULL;
	}
}
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;
}
void CModelViewRender::PlaySequence(const ANIMATIONSEQUENCE &sequence)
{
    // make a copy of the requested sequence
    m_PlayingAnimationSequence.clear();
    std::copy(sequence.begin(), sequence.end(), std::back_inserter(m_PlayingAnimationSequence));
    m_itCurrentAnimationID = m_PlayingAnimationSequence.begin();

    // create all the callbacks at once for the sequence
    set<int> uniqueCallbackSet;
    for (ANIMATIONSEQUENCE::iterator itrAnim = m_PlayingAnimationSequence.begin(); itrAnim != m_PlayingAnimationSequence.end(); itrAnim++)
    {
        // skip duplicate animations (only need to make one callback per animation)
        if (uniqueCallbackSet.find( *itrAnim ) != uniqueCallbackSet.end())
            continue;

        IArchive* pArchive = CreateMemoryArchive();
        pArchive->Write(m_hszEntityName.GetString(), _T("EntityName"));
        pArchive->Write(*itrAnim);
        pArchive->SetIsWriting(false);
        m_AnimationCallbackArchives.push_back( pArchive );

        static CHashString hszCal3DRenderObject = _T("Cal3DRenderObject");
        static CHashString hszCModelViewComponent(_T("CModelViewComponent"));
        static CHashString hszPlayAnimationSequenceStep(_T("PlayAnimationSequenceStep"));

        REGISTERCAL3DANIMATIONCALLBACK ac;
        ac.AnimationId = *itrAnim;
        ac.bTriggerOnComplete = true;
        ac.bTriggerOnStop = false;
        ac.StateObjectName = &hszCModelViewComponent;
        ac.EventName = &hszPlayAnimationSequenceStep;
        ac.EventParamsArchive = pArchive;

        static DWORD msgHash_RegisterAnimationCallback = CHashString(_T("RegisterAnimationCallback")).GetUniqueID();
        DWORD res = m_ToolBox->SendMessage(msgHash_RegisterAnimationCallback, sizeof(ac), &ac, &m_hszEntityName, &hszCal3DRenderObject);
        if (MSG_HANDLED != res)
        {
            m_ToolBox->Log(LOGERROR, _T("%s(%i): Cannot register animation callback. \n"), __FILE__, __LINE__);
        }
        uniqueCallbackSet.insert( *itrAnim );
    }

    if (HasAnimation())
    {
        SINGLETONINSTANCE(CModelViewComponent)->PlayAnimation(this);
    }
}
DWORD CArchiveFactory::OnCreateXMLArchiveStream(DWORD size, void *param)
{
	IArchive *newArchive;
	CREATEARCHIVE *ca;
	CREATESTREAM cs;
	StdString csMessage;
	DWORD retVal;
	VERIFY_MESSAGE_SIZE(size, sizeof(CREATEARCHIVE));
	ca = (CREATEARCHIVE *)param;

	cs.streamData = ca->streamData;
	cs.streamSize = ca->streamSize;
	cs.mode = ca->mode;
	csMessage = _T("CreateStream_");
	csMessage += ca->streamType->GetString();
	// try and create the stream
	DWORD msgHash_csMessage = CHashString(csMessage).GetUniqueID();
	retVal = m_ToolBox->SendMessage(msgHash_csMessage, sizeof(CREATESTREAM), &cs);
	if (retVal != MSG_HANDLED)
	{
		return retVal;
	}

	try
	{
		newArchive = new CXMLArchive();
	}
	catch(...)
	{
		delete cs.openStream;
		return MSG_ERROR;
	}

	// check if we are creating a read and write stream
	if( (cs.mode & (STREAM_MODE_READ | STREAM_MODE_WRITE)) == (STREAM_MODE_READ | STREAM_MODE_WRITE))
	{
		newArchive->SetIsWriting( true );
	}

	// initalize it with the stream
	newArchive->Init(cs.openStream);

	ca->archive = newArchive;

	return MSG_HANDLED_STOP;
}
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;
}
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;
}
///	\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;
}
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;
}
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();
}
/////////////////////////////////////////////////////////////
//	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;
}
/////////////////////////////////////////////////////////////
// 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;
}
/////////////////////////////////////////////////////////////
//	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::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;
}