void CPrecacheObject::Serialize( IArchive &ar )
{
	if( ar.IsReading() )
	{
		// Version
		ar.Read( m_iVersion );
	
		// Number of Entries
		unsigned int tmpCount;
		ar.Read( tmpCount );
	
		// Read Entries and insert into the list
		for( unsigned int i = 0; i < tmpCount; i++ )
		{
			CHashString hszResourceName;
			StdString szResourceName;
			ar.Read( szResourceName );
			hszResourceName.Init( szResourceName );
			m_ResourceSet.insert( hszResourceName.GetUniqueID());
		}
	}
	
	else
	{
		// Version
		ar.Write( m_iVersion, _T("Version") );
		
		// Number of Entries
		ar.Write( (int)m_ResourceSet.size(), _T("NumEntries") );

		// Write out all the Entries from the list
		RESOURCESET::iterator itr = m_ResourceSet.begin();
		StdString szPrecacheEntry( _T("PrecacheEntry") );
		while( itr != m_ResourceSet.end() )
		{
			ar.StartClass( szPrecacheEntry );
			ar.Write( m_ToolBox->GetHashString( *itr ), _T("Name") );
			ar.EndClass();
			itr++;
		}
	}
}
void CSchemaItem::Serialize( IArchive &ar )
{
	if( ar.IsReading() )
	{
		StdString name; // Dummy variable to read the name. It should already be stored as CObjectTemplate
		StdString type;
		StdString attributeClass;

		ar.Read( m_fVersion, _T("Version") );
		ar.Read( name, _T("Name") );
		ar.Read( type, _T("Type") );
		ar.Read( attributeClass, _T("Class") );
		m_hszLabel.Init( name );
		m_hszType.Init( type );
		m_hszClass.Init( attributeClass );
		DBRead( &m_DefaultValue, &ar, _T("Default") ); // IMPORTANT: DBRead is dependent on m_hszType. Make sure m_hszType has been initialized before calling DBRead.

		// NOTE: We are assuming the order in which schema items are instantiated will be
		//       the order in which to read data items.
		if( m_Schema != NULL )
		{
			m_Schema->RegisterSchemaItem( this );
		}
	}
	else
	{
		ar.StartClass(_T("CSchemaItem"));

		ar.Write( m_fVersion, _T("Version") );
		ar.Write( m_hszLabel.GetString(), _T("Name") );
		ar.Write( m_hszType.GetString(), _T("Type") );
		ar.Write( m_hszClass.GetString(), _T("Class") );
		DBWrite( &m_DefaultValue, &ar, _T("Default") );

		ar.EndClass();
	}
}
//---------------------------------------------------------------------
// Function:	Serialize
// Description:	serializes the values
//				(deserializaton if ar.IsReading() returns ture)
//              The order of the values if bound
// Parameters:	ar - IArchive object which shows if we are reading or writing
//---------------------------------------------------------------------
void CProjectSettings::Serialize(IArchive &ar)
{
	unsigned int i;
	if (ar.IsReading())
	{
		// Restore everthing to default
		Init();

		// set the variables according to the data in the file
		ar.Read(m_szProjectName);
		ar.Read(m_szVersion);
		ar.Read(m_szDirectory);
		ar.Read(m_szStartScriptName);
		ar.Read(m_szLastWorldFile);
		ar.Read(m_iNumDlls);

		// clear the previous Dll list
		m_ProjectDLLs.clear();

		for (i=0; i<m_iNumDlls; i++)
		{
			StdString dllName;
			ar.Read(dllName);
			m_ProjectDLLs.push_back( dllName );
		}

		//reading the other tags are done in the loadSaver project
		//it attempts to call the serialize function of the objects
		//with the names of the xml tags.
	}
	else
	{
		ar.Write(m_szProjectName, "ProjectName");
		ar.Write(m_szVersion, "Version");
		ar.Write(m_szDirectory, "Directory");
		ar.Write(m_szStartScriptName, "StartupScript");
		ar.Write(m_szLastWorldFile, "LastWorldFile");
		ar.Write(m_iNumDlls, "NumDLLS");
		for (i=0; i<m_iNumDlls; i++)
		{
			ar.StartClass("ProjectDLL");
			ar.Write(m_ProjectDLLs[i], "name");
			ar.EndClass();
		}
	}

	// both save and load means that no change has happend "since last save"
	IsChangedSinceLastSave = FALSE;

	// make the project ready to save/close
	// save happens only if IsChangedSince... is also true, so incorrect
	// data can't be saved, because the dialog box checks consistency.
	SetSettingsStateConsistency( TRUE );

	//TODO: the following are necessary only on project load?
	// than they can be moved to the load part of the if branches above...

	// change EE resource directory manually
	EngineGetToolBox()->SetDirectories(NULL , &m_szDirectory);

	// Loading a new project usually changes the resource directory as well.
	// As the m_szDirectory setter would send out the change message but it is
	// not called if on project load, we need to send it manually
	// Although the new dir is the content of the message, the most plugins will
	// use only the message to recognize they need to refresh their value and they
	// we get the new value from EE toolbox instead of the content of this message.
	SETWORKINGDIRECTORIESPARAMS swdp;
	swdp.ResourceDirectory = NULL;
	swdp.BaseDirectory = &m_szDirectory;
	static DWORD msgHash_SetDirectories = CHashString(_T("SetResourceDirectory")).GetUniqueID();
	EngineGetToolBox()->SendMessage(msgHash_SetDirectories, sizeof(SETWORKINGDIRECTORIESPARAMS), &swdp );

	// we need to set the current working dir of the OS. 
	// this is a win32 plugin, so we can call it directly:
	SetCurrentDirectory( m_szDirectory.c_str() );
}
void CLuaScriptVarList::Serialize(IArchive &ar )
{
	if(ar.IsReading())
	{
		// Read the Schema File Name
		StdString tmpFileName;
		ar.Read( tmpFileName, _T("Schema") );
		m_SchemaFileName = tmpFileName;

		// Read the VarCount for Parsing Purposes
		unsigned int VarCount = 0;
		ar.Read( VarCount, _T("VarCount") );

		for( unsigned int i = 0; i < VarCount; i++ )
		{
			CLuaScriptVar tmpVar;
			StdString tmpStringName;
			StdString tmpStringValue;
			bool tmpBoolIsDefault;
			ar.Read( tmpStringName, _T("Name")  );
			ar.Read( tmpStringValue, _T("Value") );
			ar.Read( tmpBoolIsDefault, _T("Default") );
			tmpVar.SetName( tmpStringName );
			tmpVar.SetValue( tmpStringValue );
			tmpVar.SetIsDefault( tmpBoolIsDefault );

			bool bFound = false;

			for( unsigned int j = 0; j < m_Variables.size(); j++ )
			{
				if( tmpVar.GetName() == m_Variables[j].GetName() )
				{
					bFound = true;
					if( tmpVar.GetValueAsString() != m_Variables[j].GetValueAsString() )
					{
						m_Variables[j].SetValue( tmpVar.GetValueAsString() );
						m_Variables[j].SetIsDefault( false );
					}
					break;
				}
			}

			if( bFound == false )
			{
				m_Variables.push_back( tmpVar );
			}
		}
	}

	else
	{
		ar.Write( m_SchemaFileName.GetString(), _T("Schema") );

		// Read the VarCount for Parsing Purposes
		ar.Write( (unsigned int)m_Variables.size(), _T("VarCount") );

		for( unsigned int i = 0; i < m_Variables.size(); i++ )
		{
			ar.StartClass(_T("CLuaScriptVar") );
			ar.Write( m_Variables[i].GetName(), _T("Name") );
			ar.Write( m_Variables[i].GetValueAsString(), _T("Value") );
			ar.Write( m_Variables[i].GetIsDefault(), _T("Default") );
			ar.EndClass();
		}
	}

}
void CTimeOfDayObject::Serialize( IArchive &ar )
{
	if(ar.IsReading())
	{
		// clear lists otherwise we will keep adding to them!!
		m_vSunLightFrames.clear();
		m_vFogFrames.clear();

		ar.Read( m_fTimeStart, _T("TimeStart") );
		ar.Read( m_fTimeRate, _T("TimeRate") );
	
		int iNumSunLightFrames = 0;
		ar.Read( iNumSunLightFrames, _T("NumSunLightFrames") );
		int iNumFogFrames = 0;
		ar.Read( iNumFogFrames, _T("NumFogFrames") );

		for( int i = 0; i < iNumSunLightFrames; i++ )
		{
			SUNLIGHTKEYFRAME tmpSunLightFrame;
			ar.Read( tmpSunLightFrame.m_wszName, _T("Name") );
			ar.Read( tmpSunLightFrame.m_AmbientColor, _T("AmbientColor") );
			ar.Read( tmpSunLightFrame.m_FullbrightColor, _T("FulLBrightColor") );
			ar.Read( tmpSunLightFrame.m_fDawnWeight, _T("DawnWeight") );
			ar.Read( tmpSunLightFrame.m_fNightWeight, _T("NightWeight") );
			m_vSunLightFrames.push_back( tmpSunLightFrame );
		}

		for( int i = 0; i < iNumFogFrames; i++ )
		{
			FOGKEYFRAME tmpFogFrame;
			ar.Read( tmpFogFrame.m_wszName, _T("Name") );
			ar.Read( tmpFogFrame.m_FogColor, _T("FogColor") );
			ar.Read( tmpFogFrame.m_fFogStart, _T("FogStart") );
			ar.Read( tmpFogFrame.m_fFogEnd, _T("FogEnd") );
			m_vFogFrames.push_back( tmpFogFrame );
		}
	}

	else
	{
		ar.Write( m_fTimeStart, _T("TimeStart") );
		ar.Write( m_fTimeRate, _T("TimeRate") );
	
		ar.Write( (int)m_vSunLightFrames.size(), _T("NumSunLightFrames") );
		ar.Write( (int)m_vFogFrames.size(), _T("NumFogFrames") );

		for( unsigned int i = 0; i < m_vSunLightFrames.size(); i++ )
		{
			ar.StartClass( _T("SunLightFrame") );
			ar.Write( m_vSunLightFrames[i].m_wszName, _T("Name") );
			ar.Write( m_vSunLightFrames[i].m_AmbientColor, _T("AmbientColor") );
			ar.Write( m_vSunLightFrames[i].m_FullbrightColor, _T("FulLBrightColor") );
			ar.Write( m_vSunLightFrames[i].m_fDawnWeight, _T("DawnWeight") );
			ar.Write( m_vSunLightFrames[i].m_fNightWeight, _T("NightWeight") );
			ar.EndClass();
		}

		for( unsigned int i = 0; i < m_vFogFrames.size(); i++ )
		{
			ar.StartClass( _T("FogFrame") );
			ar.Write( m_vFogFrames[i].m_wszName, _T("Name") );
			ar.Write( m_vFogFrames[i].m_FogColor, _T("FogColor") );
			ar.Write( m_vFogFrames[i].m_fFogStart, _T("FogStart") );
			ar.Write( m_vFogFrames[i].m_fFogEnd, _T("FogEnd") );
			ar.EndClass();
		}
	}
}
void CLanguage::Serialize( IArchive &ar )
{
	float saveVersion = 1.0f;
	if (ar.IsReading())
	{
		float readVersion;
		StdString szLanguageName;
		
		ar.Read(readVersion, _T("Version"));
		ar.Read(szLanguageName, _T("LanguageName"));
		ar.Read(m_iNumEntries, _T("NumEntries"));
		
		m_hszLanguageName = szLanguageName;

		CREATEOBJECTPARAMS cop;
		INITOBJECTPARAMS iop;
		SERIALIZEOBJECTPARAMS sop;
		static DWORD msgCreateObject = CHashString(_T("CreateObject")).GetUniqueID();
		static DWORD msgSerializeObject = CHashString(_T("SerializeObject")).GetUniqueID();
		static DWORD msgInitObject = CHashString(_T("InitObject")).GetUniqueID();

		StdString szEntryObjName;
		CHashString hszEntryObjBase, hszEntryObjName;
		static CHashString hszEntryType(_T("CLanguageEntry"));

		for (UINT i=0; i<m_iNumEntries; i++)
		{
			szEntryObjName = m_hszLanguageName.GetString();
			szEntryObjName += _T("_Entry");
			hszEntryObjBase = szEntryObjName;

			GENERATEUNIQUEOBJECTNAMEPARAMS generateNameParams;
			generateNameParams.name = &hszEntryObjBase;
			generateNameParams.newname = &hszEntryObjName;
			static DWORD msgHash_GenerateUniqueObjectName = CHashString(_T("GenerateUniqueObjectName")).GetUniqueID();
			m_ToolBox->SendMessage(msgHash_GenerateUniqueObjectName, sizeof(generateNameParams), &generateNameParams );

			cop.name = &hszEntryObjName;
			cop.parentName = GetName();
			cop.typeName = &hszEntryType;

			if (m_ToolBox->SendMessage(msgCreateObject, sizeof(CREATEOBJECTPARAMS), &cop) == MSG_HANDLED)
			{
				sop.name = &hszEntryObjName;
				sop.archive = &ar;
				m_ToolBox->SendMessage(msgSerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sop);

				iop.name = &hszEntryObjName;
				m_ToolBox->SendMessage(msgInitObject, sizeof(INITOBJECTPARAMS), &iop);

				IObject *entryObj = SINGLETONINSTANCE(CLanguageManager)->GetObjectByName(&hszEntryObjName, &hszEntryType);
				if (entryObj)
				{
					ILanguageEntry *langEntry = dynamic_cast<ILanguageEntry*>(entryObj);
					if (langEntry)
					{
						IHashString *hsKey = langEntry->GetKey();
						if (hsKey)
						{
							ENTRYKEYMAP::iterator mapIter = m_mEntryMapByKey.find(hsKey->GetUniqueID());
							if (mapIter == m_mEntryMapByKey.end())
							{
								m_mEntryMapByKey[hsKey->GetUniqueID()] = langEntry;
							}
							else
							{
								m_ToolBox->Log(LOGERROR, _T("%s %d: duplicate key found for %s, deleting language entry!\n"), 
									__FILE__, __LINE__, hsKey->GetString());

								DELETEOBJECTPARAMS dop;
								dop.name = &hszEntryObjName;
								
								static DWORD msgDeleteObject = CHashString(_T("DeleteObject")).GetUniqueID();
								m_ToolBox->SendMessage(msgDeleteObject, sizeof(DELETEOBJECTPARAMS), &dop);
							}
						}
						else
						{
							m_ToolBox->Log(LOGERROR, _T("%s %d: could not get key string from entry!\n"), 
								__FILE__, __LINE__);
						}
					}
					else
					{
						m_ToolBox->Log(LOGERROR, _T("%s %d: could not cast to language entry!\n"), 
								__FILE__, __LINE__);
					}
				}
				else
				{
					m_ToolBox->Log(LOGERROR, _T("%s %d: could not get object pointer from manager!\n"), 
								__FILE__, __LINE__);
				}
			}
			else
			{
				m_ToolBox->Log(LOGERROR, _T("%s %d: could not create entry object %s!\n"), 
					__FILE__, __LINE__, hszEntryObjName.GetString());
			}
		}
	}
	else
	{
		ar.Write(saveVersion, _T("Version"));
		ar.Write(m_hszLanguageName.GetString(), _T("LanguageName"));
		ar.Write(m_iNumEntries, _T("NumEntries"));

		ENTRYKEYMAP::iterator mapIter = m_mEntryMapByKey.begin();
		for (; mapIter != m_mEntryMapByKey.end(); mapIter++)
		{
			ILanguageEntry *entry = mapIter->second;
			if (entry)
			{
				ar.StartClass(_T("CLanguageEntry"));
				entry->Serialize(ar);
				ar.EndClass();
			}
		}
	}
}