www.pudn.com > uoth_src.zip > Region.cpp


//----------------------------------------------------------------------------- 
//  
// @doc 
// 
// @module	Region.cpp - region information class | 
// 
// This module contains the region information class. 
// 
// Copyright (c) 2002 - Descartes Systems Sciences, Inc. 
// 
// All rights reserved. 
// 
// Redistribution and use in source and binary forms, with or without  
// modification, are permitted provided that the following conditions are  
// met: 
//  
// 1. Redistributions of source code must retain the above copyright notice,  
//    this list of conditions and the following disclaimer.  
// 2. Neither the name of Descartes Systems Sciences, Inc nor the names of  
//    its contributors may be used to endorse or promote products derived  
//    from this software without specific prior written permission. 
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT  
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR  
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED  
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR  
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING  
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS  
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
// 
// @end 
// 
// $History: Cnf.cpp $ 
//       
//----------------------------------------------------------------------------- 
 
#include "stdafx.h" 
#include "Level.h" 
#include "DataParser.h" 
#include "Filter.h" 
 
// 
// Debug NEW 
// 
 
#if defined (_DEBUG) 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
// 
// Class globals 
// 
 
CAtlArray  CRegion::gm_vRegions; 
 
// 
// Externals 
// 
 
extern TCHAR g_szAppName []; 
 
// 
// String constants 
// 
 
extern LPCTSTR g_pszWorldOverlayName; 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc  constructor. 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
CRegion::CRegion () 
{ 
	Init (true); 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc  destructor. 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
CRegion::~CRegion () 
{ 
	if (m_paucPixels) 
		free (m_paucPixels); 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Initialize the object 
// 
// @parm bool | fConstruct | If true, we are being called from the 
//		the constructor 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CRegion::Init (bool fConstruct) 
{ 
	m_nIndex = 0; 
	m_x = 0; 
	m_y = 0; 
	m_fInRect = false; 
	m_strName .Empty (); 
	m_strComment .Empty (); 
	m_rect = CRect (0, 0, 0, 0); 
	if (!fConstruct) 
	{ 
		if (m_paucPixels) 
			free (m_paucPixels); 
	} 
    m_paucPixels = NULL; 
	m_nWidthBytes = 0; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Begin the processing of a region 
// 
// @parm CDataParser * | pParser | Current parser 
// 
// @parm const XML_Char ** | papszAttrs | Attributes 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CRegion::OnStart (CDataParser *pParser, const XML_Char **papszAttrs) 
{ 
 
	// 
	// The only allowed attribute is Index and 
	// it is required 
	// 
 
	if (papszAttrs [0] == NULL || 
		strcmp (papszAttrs [0], "Index") != 0 || 
		papszAttrs [2] != NULL) 
	{ 
		pParser ->SetError (IDS_ERR_XML_ONLY_INDEX); 
		return; 
	} 
 
	// 
	// Get the index number 
	//  
 
	int nIndex = atol (papszAttrs [1]); 
 
	// 
	// Validate the region range 
	// 
 
	if (nIndex <= 0 || nIndex > Max_Region) 
	{ 
		pParser ->SetError (IDS_ERR_XML_INDEX_RANGE); 
		return; 
	} 
 
	// 
	// Initialize the region 
	// 
 
	Init (false); 
	m_nIndex = nIndex; 
 
	// 
	// Move to the new state 
	// 
 
	pParser ->SetState (CDataParser::InRegion); 
	return; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Begin the processing of an XML element 
// 
// @parm CDataParser * | pParser | Current parser 
// 
// @parm const XML_Char * | pszName | Name of the element 
// 
// @parm const XML_Char ** | papszAttrs | Attributes 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CRegion::OnStartElement (CDataParser *pParser,  
	const XML_Char *pszName, const XML_Char **papszAttrs) 
{ 
	// 
	// Get the element 
	// 
 
	_Element nElement = GetElement (pszName); 
	if (nElement == Unknown) 
	{ 
		pParser ->SetError (IDS_ERR_XML_UNEXPECTED_ELEMENT); 
		return; 
	} 
 
	// 
	// No attributes are allowed 
	// 
 
	if (papszAttrs [0] != NULL) 
	{ 
		pParser ->SetError (IDS_ERR_XML_NO_ATTRS); 
		return; 
	} 
	return; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc End an XML element 
// 
// @parm CDataParser * | pParser | Current parser 
// 
// @parm const XML_Char * | pszName | Name of the element 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CRegion::OnEndElement (CDataParser *pParser, const XML_Char *pszName) 
{ 
 
	// 
	// Get the element 
	// 
 
	_Element nElement = GetElement (pszName); 
	if (nElement == Unknown) 
	{ 
		pParser ->SetError (IDS_ERR_XML_UNEXPECTED_ELEMENT); 
		return; 
	} 
 
	// 
	// Switch based on the element 
	// 
 
	switch (nElement) 
	{ 
		 
		// 
		// If we are ending the level 
		// 
 
		case Region: 
			pParser ->SetState (CDataParser::InData); 
			gm_vRegions .SetAtGrow (m_nIndex, *this); 
			break; 
 
		// 
		// If this is the name 
		// 
 
		case Name: 
			m_strName = pParser ->GetText (false); 
			break; 
 
		// 
		// If this is the mask offset 
		// 
 
		case MaskOffset: 
			pParser ->GetCoord (&m_x, &m_y); 
			break; 
 
		// 
		// If this is the mask hit test 
		// 
 
		case MaskHitTest: 
			m_fInRect = atol (pParser ->GetText (false)) != 0; 
			break; 
 
		// 
		// If this is the comment 
		// 
 
		case Comment: 
			m_strComment = pParser ->GetText (true); 
			break; 
	} 
	return; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Get the element number 
// 
// @parm const XML_Char * | pszName | Element name 
// 
// @rdesc Element id. 
// 
//----------------------------------------------------------------------------- 
 
CRegion::_Element CRegion::GetElement (const XML_Char *pszName) 
{ 
	if (stricmp (pszName, "Region") == 0) 
		return Region; 
	else if (stricmp (pszName, "Name") == 0) 
		return Name; 
	else if (stricmp (pszName, "MaskOffset") == 0) 
		return MaskOffset; 
	else if (stricmp (pszName, "MaskHitTest") == 0) 
		return MaskHitTest; 
	else if (stricmp (pszName, "Comment") == 0) 
		return Comment; 
	else 
		return Unknown; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Get the next valid region 
// 
// @parm int | nTreasure | Current position 
// 
// @parm bool | fForward | If true, move forward 
// 
// @parm CFilter * | pFilter | Filter to use for test 
// 
// @rdesc New region number or zero if there are no more 
// 
//----------------------------------------------------------------------------- 
 
int CRegion::GetNext (int nRegion, bool fForward, CFilter *pFilter) 
{ 
 
	// 
	// Get the additive 
	// 
 
	int nAdd = fForward ? 1 : -1; 
 
	// 
	// Look for the region 
	// 
 
	while (true) 
	{ 
		nRegion += nAdd; 
		if (nRegion <= 0 || nRegion >= gm_vRegions .GetCount ()) 
			return 0; 
		if (!gm_vRegions [nRegion] .IsValid ()) 
			continue; 
		if (pFilter) 
		{ 
			if (pFilter ->IsMineFilterEnabled () && 
				!pFilter ->DoesRegionHaveMap (nRegion)) 
				continue; 
		} 
		return nRegion; 
	} 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Get the region information 
// 
// @parm bool | fTerse | If true, only provide limited data 
// 
// @rdesc String containing the text 
// 
//----------------------------------------------------------------------------- 
 
CString CRegion::GetInformation (bool fTerse) 
{ 
	CString str; 
 
	// 
	// Set the basics 
	// 
 
	str .Format (IDS_INF_REGION, m_nIndex, (LPCTSTR) m_strName); 
 
	// 
	// Append the comment 
	// 
 
	if (!fTerse) 
	{ 
		if (!m_strComment .IsEmpty ()) 
		{ 
			str += CString (_T ( "\r\n")) + m_strComment + _T ( "\r\n"); 
		} 
	} 
	return str; 
} 
 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Load the region masks 
// 
// @parm unzFile | fpZip | Zip file containing data 
// 
// @rdesc Overall status 
// 
//----------------------------------------------------------------------------- 
 
bool CRegion::LoadMasks (unzFile fpZip) 
{ 
 
	// 
	// Load the region masks 
	// 
 
	for (int ir = 0; ir < CRegion::gm_vRegions .GetCount (); ++ir) 
	{ 
		CRegion *pRegion = &CRegion::gm_vRegions [ir]; 
		if (!pRegion ->IsValid ()) 
			continue; 
 
		// 
		// Load the bitmap 
		// 
 
		TCHAR szName [64]; 
		_sntprintf (szName, _countof (szName),  
			g_pszWorldOverlayName, pRegion ->m_nIndex); 
		HBITMAP hbm = LoadBitmapFromZip (fpZip, szName); 
		if (hbm == NULL) 
		{ 
			CString str; 
			str .Format (IDS_ERR_LOAD_FROM_ZIP, szName); 
			::MessageBox (NULL, str, g_szAppName, MB_OK); 
			return false; 
		} 
		if (!IsBitmapMonochrome (hbm)) 
		{ 
			CString str; 
			str .Format (IDS_ERR_MONOCHROME, szName); 
			::MessageBox (NULL, str, g_szAppName, MB_OK); 
			return false; 
		} 
 
		// 
		// Convert the bitmap 
		// 
 
		BITMAP bmo; 
		::GetObject (hbm, sizeof (bmo), &bmo); 
		CSize szBitmap (bmo .bmWidth, bmo .bmHeight); 
		_ASSERTE (bmo .bmBitsPixel == 1); 
		int nSize = bmo .bmHeight * bmo .bmWidthBytes; 
		unsigned char *pauchSrc = (unsigned char *) malloc (nSize); 
		::GetBitmapBits (hbm, nSize, pauchSrc); 
		::DeleteObject (hbm); 
 
		// 
		// Save the size 
		// 
 
		pRegion ->m_rect = CRect (CPoint (pRegion ->m_x, pRegion ->m_y), szBitmap); 
		pRegion ->m_paucPixels = pauchSrc; 
		pRegion ->m_nWidthBytes  = bmo .bmWidthBytes; 
	} 
 
	// 
	// Success 
	// 
 
	return true; 
}