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 CQHState::ReadFromVersion_1_2( IArchive &ar )
{
	StdString s;
	ar.Read( s, _T("name") );
	m_NewName = s;
	ar.Read( s, _T("entryEvent") );
	m_EntryEvent = s;
	ar.Read( s, _T("updateEvent") );
	m_UpdateEvent = s;
	ar.Read( s, _T("exitEvent") );
	m_ExitEvent = s;
}
void CQHState::ReadFromVersion_1_1( IArchive &ar )
{
	static const LPCTSTR *editorValueNames = GetEditorValueNames();
	StdString s;
	int iTemp;
	ar.Read( s, _T("name") );
	m_NewName = s;

	for( int i = 0; i < 4; ++i )
	{
		ar.Read( iTemp, editorValueNames[i] );
	}

	ar.Read( iTemp, _T("numSubStates") );
	ar.Read( iTemp, _T("numEvents") );
	ar.Read( s, _T("entryEvent") );
	m_EntryEvent = s;
	ar.Read( s, _T("updateEvent") );
	m_UpdateEvent = s;
	ar.Read( s, _T("exitEvent") );
	m_ExitEvent = s;

	for( int i = 4; i < 8; ++i )
	{
		ar.Read( iTemp, editorValueNames[i] );
	}
}
void CQHState::Serialize( IArchive &ar )
{
	if( ar.IsReading() )
	{
		float fVersion;
		ar.Read( fVersion, _T("version") );

		if( 1.2f == fVersion )
		{
			ReadFromVersion_1_2( ar );
		}
		else if( 1.1f == fVersion )
		{
			ReadFromVersion_1_1( ar );
		}
		else if( 1.0f == fVersion )
		{
			ReadFromVersion_1_0( ar );
		}
		else
		{
			LPCTSTR fmt = _T("%s(%d): Unsupported version (%f) of state machine state");
			m_ToolBox->Log( LOGERROR, fmt, __FILE__, __LINE__, fVersion );
			return;
		}
	}
	else
	{
		ar.Write( m_fCurrentVersion, _T("version") );
		ar.Write( m_Name.GetString(), _T("name") );
		ar.Write( m_EntryEvent.GetString(), _T("entryEvent") );
		ar.Write( m_UpdateEvent.GetString(), _T("updateEvent") );
		ar.Write( m_ExitEvent.GetString(), _T("exitEvent") );
	}
}
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
}
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;
}
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 COptionTreeWrapper::SerializeEditItemDouble(IArchive &ar, COptionTreeItem *item, bool read)
{
	double dVal;
	COptionTreeItemEdit *otiEdit;

	otiEdit = dynamic_cast<COptionTreeItemEdit*>(item);
	
	if(otiEdit == NULL)
	{
		//error
		StdString error = _T("Could not cast item to COptionTreeItemEdit: ");
		error += item->GetLabelText();
		::MessageBox(NULL, error, _T("Invalid Command"), MB_OK);
		return;
	}

	otiEdit->CreateEditItem(OT_EDIT_NUMERICAL, NULL);

	if(read)
	{
		ar.Read(dVal);
		otiEdit->SetEditDouble(dVal);
	}
	else
	{
		otiEdit->GetEditDouble(dVal);
		ar.Write(dVal);
	}
}
void COptionTreeWrapper::SerializeStaticItemString(IArchive &ar, COptionTreeItem *item, bool read)
{
	StdString szString;
	COptionTreeItemStatic *otiStatic = dynamic_cast<COptionTreeItemStatic*>(item);

	CString szItem;
	if(otiStatic == NULL)
	{
		//error
		StdString error = _T("Could not cast item to COptionTreeItemStatic: ");
		error += item->GetLabelText();
		::MessageBox(NULL, error, _T("Invalid Command"), MB_OK);
		return;
	}
	if(read)
	{
		ar.Read(szString);
		otiStatic->SetStaticText(szString.c_str());
	}
	else
	{
		szItem = otiStatic->GetStaticText();
		ar.Write(szItem);
	}
}
void COptionTreeWrapper::SerializeRadioItem(IArchive &ar, COptionTreeItem *item, bool read)
{
	StdString szVal;
	COptionTreeItemRadio *otiRadio;
	OT_RADIO_NODE *node;
	int index;

	otiRadio = dynamic_cast<COptionTreeItemRadio*>(item);
	if (item == NULL)
	{
		//error
		StdString error = _T("Could not cast item to COptionTreeItemRadio: ");
		error += item->GetLabelText();
		::MessageBox(NULL, error, _T("Invalid Command"), MB_OK);
		return;
	}
	if (read)
	{
		ar.Read(szVal);
		node = otiRadio->Node_FindNode(szVal.c_str());
		if (node != NULL)
		{	
			otiRadio->Node_UnCheckAll();
			node->m_bChecked = true;
		}	
	}
	else
	{
		index = otiRadio->Node_GetChecked();
		node = otiRadio->Node_FindNode(index);
		ar.Write(node->m_strText);
	}
}
void COptionTreeWrapper::SerializeCheckBoxItem(IArchive &ar, COptionTreeItem *item, bool read)
{
	bool bVal;
	COptionTreeItemCheckBox *otiCheckBox;

	otiCheckBox = dynamic_cast<COptionTreeItemCheckBox*>(item);
	if(otiCheckBox == NULL)
	{
		//error
		StdString error = _T("Could not cast item to COptionTreeItemCheckBox: ");
		error += item->GetLabelText();
		::MessageBox(NULL, error, _T("Invalid Command"), MB_OK);
		return;
	}
	if(read)
	{
		ar.Read(bVal);
		otiCheckBox->SetCheck(bVal);
	}
	else
	{
		bVal = (otiCheckBox->GetCheck() != 0);
		ar.Write(bVal);
	}
}
void COptionTreeWrapper::SerializeStaticItemBool(IArchive &ar, COptionTreeItem *item, bool read)
{
	bool bVal;
	COptionTreeItemStatic *otiStatic;
	CString text;

	otiStatic = dynamic_cast<COptionTreeItemStatic*>(item);
	if(otiStatic == NULL)
	{
		//error
		StdString error = _T("Could not cast item to COptionTreeItemStatic: ");
		error += item->GetLabelText();
		::MessageBox(NULL, error, _T("Invalid Command"), MB_OK);
		return;
	}
	if(read)
	{
		ar.Read(bVal);
		otiStatic->SetStaticText( bVal ? _T("true") : _T("false")  );
	}
	else
	{
		text = otiStatic->GetStaticText();
		if (_tcscmp( text, _T("true") ) == 0)
			ar.Write(true);
		else
			ar.Write(false);
	}
}
void COptionTreeWrapper::SerializeSpinnerItemDouble(IArchive &ar, COptionTreeItem *item, bool read)
{
	double dVal;
	COptionTreeItemSpinner *otiSpinner;

	otiSpinner = dynamic_cast<COptionTreeItemSpinner*>(item);
	if (otiSpinner == NULL)
	{
		//error
		StdString error = _T("Could not cast item to COptionTreeItemSpinner: ");
		error += item->GetLabelText();
		::MessageBox(NULL, error, _T("Invalid Command"), MB_OK);
		return;
	}
	if (read)
	{
		ar.Read(dVal);
		otiSpinner->SetEditDouble(dVal);
	}
	else
	{
		otiSpinner->GetEditDouble(dVal);
		ar.Write(dVal);
	}
}
void COptionTreeWrapper::SerializeStaticItemDouble(IArchive &ar, COptionTreeItem *item, bool read)
{
	double dVal;
	COptionTreeItemStatic *otiStatic;
	TCHAR buff[50];
	CString text;

	otiStatic = dynamic_cast<COptionTreeItemStatic*>(item);
	if(otiStatic == NULL)
	{
		//error
		StdString error = _T("Could not cast item to COptionTreeItemStatic: ");
		error += item->GetLabelText();
		::MessageBox(NULL, error, _T("Invalid Command"), MB_OK);
		return;
	}
	if(read)
	{
		ar.Read(dVal);
		_stprintf(buff, "%g", dVal);
		otiStatic->SetStaticText(buff);
	}
	else
	{
		text = otiStatic->GetStaticText();
		dVal = _tstof(text);

		ar.Write(dVal);
	}
}
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 COptionTreeWrapper::SerializeStaticItemInt(IArchive &ar, COptionTreeItem *item, bool read)
{
	int iVal;
	COptionTreeItemStatic *otiStatic;
	TCHAR buffer[50];
	CString text;

	otiStatic = dynamic_cast<COptionTreeItemStatic*>(item);
	if(otiStatic == NULL)
	{
		//error
		StdString error = _T("Could not cast item to COptionTreeItemStatic: ");
		error += item->GetLabelText();
		::MessageBox(NULL, error, _T("Invalid Command"), MB_OK);
		return;
	}
	if(read)
	{
		ar.Read(iVal);
		_itot(iVal, buffer, 10);
		otiStatic->SetStaticText(buffer);
	}
	else
	{
		text = otiStatic->GetStaticText();
		iVal = _tstoi(text);
		ar.Write(iVal);
	}
}
void COptionTreeWrapper::SerializeEditItemString(IArchive &ar, COptionTreeItem *item, bool read)
{	
	StdString szString;
	COptionTreeItemEdit *otiEdit;
	
	CString szItem;
	otiEdit = dynamic_cast<COptionTreeItemEdit*>(item);
	if(otiEdit == NULL)
	{
		//error
		StdString error = _T("Could not cast item to COptionTreeItemEdit: ");
		error += item->GetLabelText();
		::MessageBox(NULL, error, _T("Invalid Command"), MB_OK);
		return;
	}

	otiEdit->CreateEditItem(0, NULL);

	if (read)
	{
		ar.Read(szString);
		otiEdit->SetEditText(szString.c_str());
	}
	else
	{
		otiEdit->GetWindowText(szItem);
		ar.Write(szItem);
	}
}
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 CHeightmapObject::Serialize(IArchive &ar)
{
	if (ar.IsReading())
	{
		int iSize = 0;
		ar.Read( iSize );
		iSize = EE_ENDIANSWAP32( iSize );

		m_iWidth = iSize;
		m_iHeight = iSize;

		SAFE_DELETE_ARRAY( m_pHeightmapData );

		int iSamples = iSize * iSize;
		if( iSamples > 0 )
		{
			float f;
			m_pHeightmapData = new float[iSamples];
			for( int i = 0; i < iSamples; ++i )
			{
				ar.Read( f );
				m_pHeightmapData[i] = EE_ENDIANSWAP32F( f );
			}
		}
	}
	else
	{
		int iSize = m_iWidth;
		ar.Write( iSize );
		int iSamples = iSize * iSize;
		if( m_pHeightmapData != NULL )
		{
			for( int i = 0; i < iSamples; ++i )
			{
				ar.Write( m_pHeightmapData[i] );
			}
		}
		else
		{
			for( int i = 0; i < iSamples; ++i )
			{
				ar.Write( 0.0f );
			}
		}
	}
}
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;
}
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 CDetailObject::Serialize( IArchive &ar )
{
	StdString temp;
	if(ar.IsReading())
	{
		ar.Read(temp, "LayerLink");
		m_LayerLink = temp.c_str();
		ar.Read(temp, "ModelName");
		m_ModelName = temp.c_str();
		ar.Read(m_XCoverage, "XCoverage");
		ar.Read(m_YCoverage, "YCoverage");
		ar.Read(m_XRandomness, "XRandomness");
		ar.Read(m_YRandomness, "YRandomness");
		ar.Read(m_MinScale, "MinScale");
		ar.Read(m_MinScale, "MaxScale");
		ar.Read(m_MinYaw, "MinYaw");
		ar.Read(m_MaxYaw, "MaxYaw");
	}
	else
	{
		ar.Write(m_LayerLink.GetString(), "LayerLink");
		ar.Write(m_ModelName.GetString(), "ModelName");
		ar.Write(m_XCoverage, "XCoverage");
		ar.Write(m_YCoverage, "YCoverage");
		ar.Write(m_XRandomness, "XRandomness");
		ar.Write(m_YRandomness, "YRandomness");
		ar.Write(m_MinScale, "MinScale");
		ar.Write(m_MinScale, "MaxScale");
		ar.Write(m_MinYaw, "MinYaw");
		ar.Write(m_MaxYaw, "MaxYaw");
	}
}
void CLuaScript::Serialize(IArchive &ar)
{
	if(ar.IsReading())
	{
		ar.Read(m_ScriptName);
		ar.Read(m_bAutoStart);
	}
	else
	{
		ar.Write(m_ScriptName);
		ar.Write(m_bAutoStart);
	}

}
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();
	}
}
void CQHStateMachineActionHandler::Serialize( IArchive &ar )
{
	if( ar.IsReading() )
	{
		float fVersion;
		StdString tempStr;
		ar.Read( fVersion, _T("version") );
		if( fVersion > m_fCurrentVersion )
		{
			LPCTSTR fmt = _T("%s(%d): Unsupported version (%f) of state machine action handler");
			m_ToolBox->Log( LOGERROR, fmt, __FILE__, __LINE__, fVersion );
			return;
		}
		ar.Read( tempStr, _T("name") );
		m_szName.Init( tempStr );
		ar.Read( tempStr, _T("actionName") );
		m_szActionName.Init( tempStr );

		IComponent *amanagerComponent = m_ToolBox->GetComponent( GetManagerName() );
		CQHStateMachineManager *amanager = static_cast<CQHStateMachineManager*>( amanagerComponent );
		CQHStateMachineEvent *aparentEvent = amanager->GetEvent( GetParentName() );
		if( aparentEvent != NULL )
		{
			aparentEvent->AddActionHandler( this );
		}
		else
		{
			m_ToolBox->Log( LOGERROR, _T("Could not find parent event %s for action handler %s."), GetParentName()->GetString(), GetName()->GetString() );
		}
	}
	else
	{
		ar.Write( m_fCurrentVersion, _T("version") );
		ar.Write( m_szName.GetString(), _T("name") );
		ar.Write( m_szActionName.GetString(), _T("actionName") );
	}
}
void COptionTreeWrapper::SerializeFileItem(IArchive &ar, COptionTreeItem *item, bool read)
{
	StdString fileName;
	COptionTreeItemFile *otiFile;
	CString szItem;

	otiFile = dynamic_cast<COptionTreeItemFile*>(item);
	if(otiFile == NULL)
	{
		//error
		StdString error = _T("Could not cast item to COptionTreeItemFile: ");
		error += item->GetLabelText();
		::MessageBox(NULL, error, _T("Invalid Command"), MB_OK);
		return;
	}

	if (read)
	{
		ar.Read(fileName);
		CString fName = (const TCHAR*)fileName;
		GetRelativePath(fName, szItem);
		if ( _tcscmp(szItem, _T("")) != 0 )
		{
			otiFile->SetFileString(szItem);
		}
	}
	else
	{
		// Try to convert to a relative path
		if( !GetRelativePath(otiFile->GetFileString(), szItem) )
		{
			// if an invalid path reset the string
			otiFile->ResetFileString();
			// run it through the relative pathizer again
			GetRelativePath(otiFile->GetFileString(), szItem);					
		}
//		CGDSApp *app = DYNAMIC_DOWNCAST(CGDSApp, AfxGetApp());
//		CString resourcePath = app->GetResourcePath();
		StdString rootDir, resDir;
		EngineGetToolBox()->GetDirectories(&rootDir, &resDir);
		resDir += "\\";
		resDir += szItem;
		otiFile->SetFileString( szItem );
		// do not want to save absolute path! my bad
//		ar.Write(resDir);
		ar.Write(szItem);
	}
}
void COptionTreeWrapper::SerializeComboItem(IArchive &ar, COptionTreeItem *item, bool read)
{
	StdString defaultSelect;
	COptionTreeItemComboBox *otiCombo;
	CString szItem;
	int index;

	otiCombo = dynamic_cast<COptionTreeItemComboBox*>(item);
	if(otiCombo == NULL)
	{
		//error
		StdString error = _T("Could not cast item to COptionTreeItemCombo: ");
		error += item->GetLabelText();
		::MessageBox(NULL, error, _T("Invalid Command"), MB_OK);
		return;
	}
	if(read)
	{
		ar.Read(defaultSelect);
		if( _tcscmp( defaultSelect, _T("")) != 0 )
		{
			index = otiCombo->FindStringExact(0, defaultSelect.c_str());
			otiCombo->SetCurSel((index >= 0) ? index : 0);
		}

	}
	else
	{
		int sel = otiCombo->GetCurSel();
		if(sel == CB_ERR)
		{
			//display some message?
		}
		otiCombo->GetLBText(sel, szItem);
		ar.Write(szItem);
	}
}
void COptionTreeWrapper::SerializeColorItem(IArchive &ar, COptionTreeItem *item, bool read)
{
	int iVal;
	COptionTreeItemColor *otiColor;

	otiColor = dynamic_cast<COptionTreeItemColor*>(item);

	if (otiColor == NULL)
	{
		//error
		StdString error = _T("Could not cast item to COptionTreeItemColor: ");
		error += item->GetLabelText();
		::MessageBox(NULL, error, _T("Invalid Command"), MB_OK);
		return;
	}

	if (read)
	{
		ar.Read(iVal);
        if (iVal >= 0)
		{
			// our format: rgb... old format: (a)bgr
            DWORD mask = 0xff0000;
			unsigned int r, g, b;
			DWORD outColor = 0;
			r = (iVal & mask) >> 16;
			outColor += r;
			mask = 0x00ff00;
			g = (iVal & mask) >> 8;
			outColor += g << 8;
			mask = 0x0000ff;
			b = (iVal & mask);
			outColor += b << 16;
			otiColor->SetColor(outColor);
		}
	}
/////////////////////////////////////////////////////////////
// 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;
}