ホーム < ゲームつくろー! < DirectX技術編 < Xファイルにカスタムテンプレートデータを保存してみよう:サンプルプログラム
その33 Xファイルにカスタムテンプレートデータを保存してみよう:サンプルプログラム
DirectX技術編その33「Xファイルにカスタムテンプレートデータを保存してみよう」で説明した内容を踏まえたサンプルプログラムです。実行すると、PersonID.xというテンプレートを定義したファイルからテンプレート定義を読み込み、それを登録した後に、SaveID.xというファイルに対して名前とID番号をXファイル形式で登録します。このプログラムには描画情報はありません。
以下のプログラムは指定のカスタムテンプレート(PersonID.x)をパスの通った場所に置き、空のプロジェクトにコピペすることで完全に動きます。PersonIDテンプレートは世界に一つしかない番号が振られておりますので、こちらからファイルをダウンロードしてください。上からデバッグしていくと、何をしているか良くわかるように1つのソースで完結させています。今回のポイントになりそうなところは太文字で示されています。
(もしうまく動かないようでしたら掲示板にてご連絡下さい)
(2011. 12. 4改正)
・ MemoryStockerクラスにunsigned long型の対処が無かったので追加。
・ main.cpp内でMemoryStocker.hがインクルードされていなかったのを改正。
MemoryStockerクラス(MemoryStocker.h) // MemoryStocker.h (2007. 8. 10)
// メモリストッククラス
#pragma once
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
namespace IKD{
/////////////////////////////////////////////////////
// MemoryStocker : オブジェクトメモリ操作クラス
// 色々な情報を格納できる連続的なメモリバッファを作成し
// 登録関数や演算子によりデータを登録する。
//////
class MemoryStocker
{
protected:
unsigned char *m_pBuf; // メモリバッファへのポインタ
size_t m_Pos; // 現在のポインタ位置
size_t m_Size; // 現在のサイズ
size_t m_FullSize; // 現在の確保メモリ
size_t m_Remain; // 残りのメモリ量
size_t m_Unit; // メモリの拡張単位
size_t *m_pHash; // データアクセスハッシュ
size_t *m_pSzAry; // 登録データサイズ配列
size_t m_RegNum; // 登録数
int m_iPrec; // 浮動小数点精度
public:
MemoryStocker(){
m_pBuf = (unsigned char*)malloc(0); m_Pos = 0; m_Unit=10; m_Size=0; m_Remain = 0; m_FullSize=0;
m_pHash = (size_t*)malloc(0); m_pSzAry = (size_t*)malloc(0); m_RegNum=0;
m_iPrec = 8;
}
~MemoryStocker(){
free(m_pBuf);
free(m_pHash);
free(m_pSzAry);
}
/////////////////////////////////
// 引数付きマニピュレータ
// オブジェクトハードコピー
template<class T> MemoryStocker& Obj( T* Obj ){AddData( (void*)T, sizeof(T) ); return *this;}
/////////////////////
// オペレータ
////
MemoryStocker& operator <<(const int &val){AddData( (void*)&val, sizeof(const int) ); return *this;}
MemoryStocker& operator <<(int &val){AddData( (void*)&val, sizeof(int) ); return *this;}
MemoryStocker& operator <<(const unsigned int &val){AddData( (void*)&val, sizeof(const unsigned int) ); return *this;}
MemoryStocker& operator <<(unsigned int &val){AddData( (void*)&val, sizeof(int) ); return *this;}
MemoryStocker& operator <<(const unsigned long &val){AddData( (void*)&val, sizeof(const unsigned long) ); return *this;}
MemoryStocker& operator <<(unsigned long &val){AddData( (void*)&val, sizeof(unsigned long) ); return *this;}
MemoryStocker& operator <<(const float &val){AddData( (void*)&val, sizeof(const float) ); return *this;}
MemoryStocker& operator <<(float &val){AddData( (void*)&val, sizeof(float) ); return *this;}
MemoryStocker& operator <<(const double &val){AddData( (void*)&val, sizeof(const double) ); return *this;}
MemoryStocker& operator <<(double &val){AddData( (void*)&val, sizeof(double) ); return *this;}
MemoryStocker& operator <<(const unsigned char &val){AddData( (void*)&val, sizeof(const unsigned char) ); return *this;}
MemoryStocker& operator <<(unsigned char &val){AddData( (void*)&val, sizeof(unsigned char) ); return *this;}
MemoryStocker& operator <<(const unsigned short &val){AddData( (void*)&val, sizeof(const unsigned short) ); return *this;}
MemoryStocker& operator <<(unsigned short &val){AddData( (void*)&val, sizeof(unsigned short) ); return *this;}
MemoryStocker& operator <<(const char &val){AddData( (void*)&val, sizeof(const char) ); return *this;}
MemoryStocker& operator <<(char &val){AddData( (void*)&val, sizeof(char) ); return *this;}
MemoryStocker& operator <<(const void* &val){AddData( (void*)&val, sizeof(const void*) ); return *this;} // 汎用ポインタ
MemoryStocker& operator <<(void* &val){AddData( (void*)&val, sizeof(void*) ); return *this;}
MemoryStocker& operator <<(const void* val){AddData( (void*)val, sizeof(const void*) ); return *this;} // 汎用ポインタ
MemoryStocker& operator <<(void* val){AddData( (void*)val, sizeof(void*) ); return *this;}
MemoryStocker& operator <<(MemoryStocker &val){AddData( (void*)(val.GetRootPtr()), val.Size() ); return *this;}
// 文字列は特別
MemoryStocker& operator <<(const char* val){AddData( (void*)val, strlen(val)+1 ); return *this;}
MemoryStocker& operator <<(char* &val){AddData( (void*)val, strlen(val)+1 ); return *this;}
public:
//////////////////////////////////////////
// 指定のサイズ分データをメモリに格納
///////
MemoryStocker& AddData( void* dataptr, size_t size ){
// 残量メモリをチェックし、足りなければ拡張
size_t tmpRemain = m_Remain;
int cnt = 0;
while( tmpRemain < size ){
tmpRemain += m_Unit;
cnt++;
}
// カウント数分だけメモリを拡張
unsigned char *p = (unsigned char*)realloc( m_pBuf, m_FullSize+cnt*m_Unit );
if(!p) // 確保失敗
return *this;
// ハッシュを拡張
size_t *pH = (size_t*)realloc( m_pHash, (m_RegNum+1)*sizeof(size_t));
if(!pH) // 確保失敗
return *this;
// 登録サイズ配列を拡張
size_t *pSz = (size_t*)realloc( m_pSzAry, (m_RegNum+1)*sizeof(size_t));
if(!pSz) // 確保失敗
return *this;
// 増加部分を初期化
memset( p+m_FullSize, 0, cnt*m_Unit);
// 情報を格納
memcpy( p+m_Pos, dataptr, size );
pH[m_RegNum] = m_Pos; // ハッシュ位置登録
pSz[m_RegNum] = size; // サイズ登録
// メモリ情報を更新
m_Pos+=size; // 現在位置を更新
m_FullSize += cnt*m_Unit;
m_Size += size;
m_Remain = m_FullSize - m_Size;
m_RegNum++;
m_pBuf = p; // ポインタを更新
m_pHash = pH;
m_pSzAry = pSz;
return *this;
}
///////////////////////////
// ルートポインタを取得
/////
void *GetRootPtr(){ return (void*)m_pBuf; }
///////////////////////
// 保存サイズを取得
/////
size_t Size(){ return m_Size; }
/////////////////////
// 情報を取得
/////
size_t GetData( size_t elem, void** pout ){
if( elem >= m_RegNum ){ // 指定の要素が無い
if(pout)
*pout=NULL;
return 0;
}
if(pout)
memcpy(*pout, m_pBuf+m_pHash[elem], m_pSzAry[elem]);
// サイズを返す
return m_pSzAry[elem];
}
////////////////////////
// コピー関連
/////////
// コピーコンストラクタ
MemoryStocker( const MemoryStocker& src ) {
// 自分の情報を削除
free( m_pBuf );
m_pBuf = (unsigned char*)malloc(0); m_Pos = 0; m_Unit=10; m_Size=0; m_Remain = 0; m_FullSize=0;
m_pHash = (size_t*)malloc(0); m_pSzAry = (size_t*)malloc(0); m_RegNum=0;
m_iPrec = 8;
AddData( src.m_pBuf, src.m_Size );
}
// 代入演算子
MemoryStocker& operator = ( MemoryStocker& src ) {
free( m_pBuf );
m_pBuf = (unsigned char*)malloc(0); m_Pos = 0; m_Unit=10; m_Size=0; m_Remain = 0; m_FullSize=0;
m_pHash = (size_t*)malloc(0); m_pSzAry = (size_t*)malloc(0); m_RegNum=0;
m_iPrec = 8;
AddData( src.m_pBuf, src.m_Size );
return *this;
}
};
} // end namespace IKD
XFileカスタムテンプレートセーブテスト(main.cpp) /// XFileカスタムテンプレートセーブテスト #pragma comment(lib, "dxguid.lib") #pragma comment(lib, "d3d9.lib") #pragma comment(lib, "d3dx9.lib") #pragma comment(lib, "d3dxof.lib") #include <windows.h> #include <tchar.h> #include <d3d9.h> #include <d3dx9.h> #include <dxfile.h> // Xファイル関連を使用するのに必要 #include <fstream> #include "memorystocker.h" using namespace std; using namespace IKD; // PersonIDテンプレートGUID const GUID PersonID_GUID ={ 0xB2B63407,0x6AA9,0x4618, 0x95, 0x63, 0x63, 0x1E, 0xDC, 0x20, 0x4C, 0xDE}; // テキストファイルをメモリにコピーする関数 char* GetFileText( char* filename ){ ifstream ifs; ifs.open( filename ); if( !ifs.is_open() ) return NULL; DWORD FileSize=0; while(!ifs.eof()){ ifs.ignore(); FileSize++;} // サイズ取得 ifs.clear(); ifs.seekg(0, ios_base::beg); // ファイルポインタを初期位置へ char* tmp = new char[FileSize]; ZeroMemory( tmp, FileSize ); ifs.read( tmp, FileSize-1); return tmp; } int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { // カスタムテンプレートファイルからテンプレート定義を抽出 char* g_pTEMPLATE_PERSONID = GetFileText( "PersonID.x" ); if( !g_pTEMPLATE_PERSONID ){ return 0; } // セーブするテンプレート文字列を取得 IDirectXFile *pDXFile; DirectXFileCreate( &pDXFile ); if(FAILED(pDXFile->RegisterTemplates( g_pTEMPLATE_PERSONID, strlen( g_pTEMPLATE_PERSONID ) ))){ return 0; } // セーブオブジェクトを作成する IDirectXFileSaveObject *pDXSave; if(FAILED(pDXFile->CreateSaveObject("SaveID.x", DXFILEFORMAT_TEXT, &pDXSave ))){ pDXFile->Release(); return 0; } // 保存するデータを生成 MemoryStocker MS; char *Name = "IKD"; // 名前 DWORD val = 1234; // ID番号 MS << &Name << val; // 文字列はダブルポインタを与えます void* ptr = MS.GetRootPtr(); // データオブジェクトを作成する IDirectXFileData *pDXData; if(FAILED(pDXSave->CreateDataObject( PersonID_GUID, "Me", NULL, MS.Size(), ptr, &pDXData))){ pDXSave->Release(); pDXFile->Release(); return 0; } // データをセーブする if(FAILED(pDXSave->SaveData( pDXData ))){ pDXData->Release(); pDXSave->Release(); pDXFile->Release(); return 0; } // Xファイル関連のインターフェイスを解放 pDXData->Release(); pDXSave->Release(); pDXFile->Release(); return 0; }