转自:http://blog.csdn.net/dotnet90/article/details/6153361
#ifndef _XPARSER_H_
#define _XPARSER_H_
#include <windows.h>
#include "dxfile.h"
#include "XFile.h"
#include "D3dx9xof.h"
// A macro to quickly release and NULL a COM interface
#define XPReleaseCOM(x) { if(x) { x->Release(); x= NULL; } }
class cXParser
{
protected:
// Functions called when parsing begins and end
virtual BOOL BeginParse(void **Data) { return TRUE; }
virtual BOOL EndParse(void **Data) { return TRUE; }
// Function called for every template found
virtual BOOL ParseObject( /
ID3DXFileData *pDataObj, /
ID3DXFileData *pParentDataObj, /
DWORD Depth, /
void **Data, BOOL Reference)
{
return ParseChildObjects(pDataObj, Depth, /
Data, Reference);
}
// Function called to enumerate child templates
BOOL ParseChildObjects(ID3DXFileData *pDataObj, /
DWORD Depth, void **Data, /
BOOL ForceReference = FALSE);
public:
// Function to start parsing an .X file
BOOL Parse(char *Filename, void **Data = NULL);
// Functions to help retrieve template information
const GUID *GetObjectGUID(ID3DXFileData *pDataObj);
char *GetObjectName(ID3DXFileData *pDataObj);
void *GetObjectData(ID3DXFileData *pDataObj, /
DWORD *Size);
};
#endif
#include "XParser.h"
BOOL cXParser::Parse(char *Filename, void **Data)
{
ID3DXFile *pDXFile = NULL;
ID3DXFileEnumObject *pDXEnum = NULL;
ID3DXFileData *pDXData = NULL;
// Error checking
if(Filename == NULL)
return FALSE;
// Create the file object
if(FAILED(D3DXFileCreate(&pDXFile)))
return FALSE;
// Register the common templates
if(FAILED(pDXFile->RegisterTemplates( /
(LPVOID)D3DRM_XTEMPLATES, /
D3DRM_XTEMPLATE_BYTES))) {
pDXFile->Release();
return FALSE;
}
// Create an enumeration object
if(FAILED(pDXFile->CreateEnumObject((LPVOID)Filename, /
DXFILELOAD_FROMFILE, /
&pDXEnum))) {
pDXFile->Release();
return FALSE;
}
// Call the begin parse function, continuing if allowed
if(BeginParse(Data) == TRUE) {
Loop through all top-level objects, breaking on errors
//BOOL ParseResult;
//while(SUCCEEDED(pDXEnum->GetNextDataObject(&pDXData))) {
// ParseResult = ParseObject(pDXData, NULL, 0, Data, FALSE);
// XPReleaseCOM(pDXData);
// if(ParseResult == FALSE)
// break;
//}
SIZE_T num_child;
pDXEnum->GetChildren(&num_child);
BOOL ParseResult;
for(SIZE_T i = 0; i < num_child; i++)
{
if(FAILED(pDXEnum->GetChild(i, &pDXData)))
return NULL;
ParseResult = ParseObject(pDXData, NULL,0,Data,FALSE);
XPReleaseCOM(pDXData);
if(ParseResult == FALSE)
break;
}
}
// Call end parse function
EndParse(Data);
// Release used COM objects
XPReleaseCOM(pDXEnum);
XPReleaseCOM(pDXFile);
return TRUE;
}
BOOL cXParser::ParseChildObjects( /
ID3DXFileData *pDataObj, /
DWORD Depth, void **Data, /
BOOL ForceReference)
{
ID3DXFileData *pSubObj = NULL;
SIZE_T num_child;
BOOL ParseResult = TRUE;
pDataObj->GetChildren(&num_child);
for(SIZE_T j = 0; j < num_child; j++)
{
pDataObj->GetChild(j, &pSubObj);
if(pSubObj->IsReference()){
ForceReference = true;
}
ParseResult = ParseObject(pSubObj,pDataObj,Depth+1, Data,ForceReference);
XPReleaseCOM(pSubObj);
// Return on parsing failure
if(ParseResult == FALSE)
return FALSE;
}
//ID3DXFileData *pSubObj = NULL;
//ID3DXFileData *pSubData = NULL;
//IDirectXFileDataReference *pDataRef = NULL;
//BOOL ParseResult = TRUE;
Scan for embedded templates
//while(SUCCEEDED(pDataObj->GetNextObject(&pSubObj))) {
// // Process embedded references
// if(SUCCEEDED(pSubObj->QueryInterface( /
// IID_IDirectXFileDataReference, /
// (void**)&pDataRef))) {
// // Resolve the data object
// if(SUCCEEDED(pDataRef->Resolve(&pSubData))) {
// // Parse the object, remembering the return code
// ParseResult = ParseObject(pSubData, pDataObj, /
// Depth+1, Data, TRUE);
// XPReleaseCOM(pSubData);
// }
// XPReleaseCOM(pDataRef);
// // Return on parsing failure
// if(ParseResult == FALSE)
// return FALSE;
// } else
// // Process non-referenced embedded templates
// if(SUCCEEDED(pSubObj->QueryInterface( /
// IID_IDirectXFileData, /
// (void**)&pSubData))) {
// // Parse the object, remembering the return code
// ParseResult = ParseObject(pSubData, pDataObj, /
// Depth+1, Data, /
// ForceReference);
// XPReleaseCOM(pSubData);
// }
// // Release the data object
// XPReleaseCOM(pSubObj);
// // Return on parsing failure
// if(ParseResult == FALSE)
// return FALSE;
//}
return TRUE;
}
const GUID *cXParser::GetObjectGUID( /
ID3DXFileData *pDataObj)
{
GUID* Type = new GUID;
// Error checking
if(pDataObj == NULL)
return NULL;
// Get the template type
if(FAILED(pDataObj->GetType(Type)))
return NULL;
return Type;
}
char *cXParser::GetObjectName(ID3DXFileData *pDataObj)
{
char *Name = NULL;
DWORD Size = 0;
// Error checking
if(pDataObj == NULL)
return NULL;
// Get the template name (if any)
if(FAILED(pDataObj->GetName(NULL, &Size)))
return NULL;
// Allocate a name buffer and retrieve name
if(Size) {
if((Name = new char[Size]) != NULL)
pDataObj->GetName(Name, &Size);
}
return Name;
}
void *cXParser::GetObjectData( /
ID3DXFileData *pDataObj, /
DWORD *Size)
{
void *TemplateData;
SIZE_T TemplateSize=0;;
// Error checking
if(pDataObj == NULL)
return NULL;
// Get a data pointer to template
pDataObj->Lock(&TemplateSize,(LPCVOID*)(VOID **)&TemplateData);
if (NULL==TemplateData)
{
return NULL;
}
// Save size if needed
if(Size != NULL)
*Size = TemplateSize;
pDataObj->Unlock();
return TemplateData;
}