|  | 
 
| 本帖最后由 夜行的猫仔 于 2012-9-6 09:45 编辑 
 在Tut01_CreateWindwos 里已经介绍了MANGOGUI的程序框架,例题Tut01为了让结构看起来更简单,因此简化了很多的函数,这样做甚至牺牲了一部分框架的完整性。在本节例题中,将介绍较为完整的框架结构。以及如何控制创景管理器创建GUI界面。
 
 Tut02中已经讲过了,每一个界面控制文件都对应游戏界面中的一个Scene,一系列的Scene组成了一个游戏的GUI界面。因此管理好Scene就管理了游戏界面。在MANGOGUI中是通过CMANGOSceneManager 来控制游戏中的Scene的。
 
 
 本教程完整项目下载地址(工作目录是bin文件夹):
 http://kuai.xunlei.com/d/SUFKNHVDLQLU
 
 以下是完整调用代码
 需要解释的几个地方:复制代码//=============================================================================
// Desc: Direct3D应用程序框架
//=============================================================================
#include "../MangoInterface/interface/Mango.h"
#include "MessageId.h"
//-----------------------------------------------------------------------------
// 全局变量
//-----------------------------------------------------------------------------
CMANGOSceneManager                   g_SceneManager;
//-----------------------------------------------------------------------------
// Desc: 函数声明
// 以下罗列了MANGOGUI中使用到的回调函数。整个MANGOGUI都是在这些回调函数的驱动下工作的。
//------------------------------------------------------------------------------
bool    CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed, void* pUserContext );
bool    CALLBACK ModifyDeviceSettings( MANGODeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps, void* pUserContext );
HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext );
HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext );
void    CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext );
void    CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext );
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing, void* pUserContext );
void    CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext );
void    CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CMANGOControl* pControl, void* pUserContext );
void    CALLBACK OnLostDevice( void* pUserContext );
void    CALLBACK OnDestroyDevice( void* pUserContext );
void    InitApp();
//-----------------------------------------------------------------------------
// Desc: 入口函数
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
        //为Debug配置启用运行时内存检查功能
#if defined(DEBUG) | defined(_DEBUG)
        _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
        //设置回调函数
        MANGOSetDeviceCreated( OnCreateDevice );
        MANGOSetDeviceReset( OnResetDevice );
        MANGOSetDeviceLost( OnLostDevice );
        MANGOSetDeviceDestroyed( OnDestroyDevice );
        MANGOSetMsgProc( MsgProc );
        MANGOSetKeyboard( KeyboardProc );
        MANGOSetFrameRender( OnFrameRender );
        MANGOSetFrameMove( OnFrameMove );
        //应用程序相关的初始化
        InitApp();
        //初始化MANGO, 创建窗口, 创建Direct3D设备对象
        MANGOInit( true, true, true );
        MANGOSetCursorSettings( true, true );
        MANGOCreateWindow( L"MangoGUI System  v 0.1.53" );
        MANGOCreateDevice( D3DADAPTER_DEFAULT, true, 640, 480, IsDeviceAcceptable, ModifyDeviceSettings );
        //进入消息循环和场景渲染
        MANGOMainLoop();
        //在此进行应用程序相关的清除工作
        return MANGOGetExitCode();
}
//-----------------------------------------------------------------------------
// Desc: 应用程序相关初始化
//-----------------------------------------------------------------------------
void InitApp()
{
        //载入一个界面
        g_SceneManager.CreateScene("layout/scene.xml");        
}
//-----------------------------------------------------------------------------
// Desc: 设备能力检查
//-----------------------------------------------------------------------------
bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, 
                                                                 D3DFORMAT BackBufferFormat, bool bWindowed, 
                                                                 void* pUserContext )
{
        //检查后台缓冲区格式是否支持Alpha混合等操作(post pixel blending operations)
        IDirect3D9* pD3D = MANGOGetD3DObject(); 
        if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
                AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, 
                D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
                return false;
        return true;
}
//-----------------------------------------------------------------------------
// Desc: 修改Direct3D渲染设备设置
//-----------------------------------------------------------------------------
bool CALLBACK ModifyDeviceSettings( MANGODeviceSettings* pDeviceSettings, 
                                                                   const D3DCAPS9* pCaps, void* pUserContext )
{
        pDeviceSettings->pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
        //如果不支持硬件顶点处理则使用软件顶点处理
        if( (pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0)
        {
                pDeviceSettings->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
        }
        //如果使用参考设备,则弹出警告对话框
        static bool s_bFirstTime = true;
        if( s_bFirstTime )
        {
                s_bFirstTime = false;
                if( pDeviceSettings->DeviceType == D3DDEVTYPE_REF )
                        MANGODisplaySwitchingToREFWarning();
        }
        return true;
}
//-----------------------------------------------------------------------------
// Desc: 在此创建管理内存资源对象
//-----------------------------------------------------------------------------
HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, 
                                                                const D3DSURFACE_DESC* pBackBufferSurfaceDesc, 
                                                                void* pUserContext )
{
        HRESULT hr;
        V_RETURN( g_SceneManager.OnCreateDevice( pd3dDevice ) );
        return S_OK;
}
//-----------------------------------------------------------------------------
// Desc: 在此创建默认内存类型资源对象
//-----------------------------------------------------------------------------
HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, 
                                                           const D3DSURFACE_DESC* pBackBufferSurfaceDesc, 
                                                           void* pUserContext )
{
        HRESULT hr;
        V_RETURN( g_SceneManager.OnResetDevice() );
        g_SceneManager.GetSceneByName(L"Mango")->SetLocation( pBackBufferSurfaceDesc->Width - 170, 0 );
        //设置观察矩阵
        D3DXMATRIXA16 matView;
        D3DXVECTOR3 vEyePt( 0.0f, 0.0f,-5 );
        D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
        D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
        D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
        pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
        //设置投影矩阵
        D3DXMATRIXA16 matProj;
        float fAspectRatio = (float)pBackBufferSurfaceDesc->Width / pBackBufferSurfaceDesc->Height;
        D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, fAspectRatio, 1.0f, 100.0f );
        pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
        return S_OK;
}
//-----------------------------------------------------------------------------
// Desc: 更新场景
//-----------------------------------------------------------------------------
void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, 
                                                  float fElapsedTime, void* pUserContext )
{
}
//-----------------------------------------------------------------------------
// Desc: 渲染场景
//-----------------------------------------------------------------------------
void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, 
                                                        float fElapsedTime, void* pUserContext )
{
        HRESULT hr;
        //清除后台颜色缓冲区和深度缓冲区
        V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 
                D3DCOLOR_ARGB(0, 45, 50, 170), 1.0f, 0) );
        //渲染场景
        if( SUCCEEDED( pd3dDevice->BeginScene() ) )
        {
                //渲染文本和控件
                MANGO_BeginPerfEvent( MANGO_PERFEVENTCOLOR, L"HUD / Stats" ); 
                g_SceneManager.OnRender(fElapsedTime);
                MANGO_EndPerfEvent();
                V( pd3dDevice->EndScene() );
        }
}
//-----------------------------------------------------------------------------
// Desc: 消息处理
//-----------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, 
                                                 bool* pbNoFurtherProcessing, void* pUserContext )
{
        *pbNoFurtherProcessing = g_SceneManager.MsgProc( hWnd, uMsg, wParam, lParam );
        if( *pbNoFurtherProcessing )
                return 0;
        return 0;
}
//-----------------------------------------------------------------------------
// Desc: 键盘消息处理
//-----------------------------------------------------------------------------
void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext )
{
}
//-----------------------------------------------------------------------------
// Desc: 处理各种控件消息
//-----------------------------------------------------------------------------
void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CMANGOControl* pControl, 
                                                 void* pUserContext )
{
        switch( nControlID )
        {
        case Button1:
                MANGOToggleFullScreen(); 
                break;
        case Button2:
                MANGOToggleREF(); 
                break;
        case Button3:
                break;
        }
}
//-----------------------------------------------------------------------------
// Desc: 释放在OnResetDevice()中创建的资源
//-----------------------------------------------------------------------------
void CALLBACK OnLostDevice( void* pUserContext )
{
        g_SceneManager.OnLostDevice();
}
//------------------------------------------------------------------------------
// Desc: 释放在OnCreateDevice()中创建的资源
//------------------------------------------------------------------------------
void CALLBACK OnDestroyDevice( void* pUserContext )
{
        g_SceneManager.OnDestroyDevice();
}
"MessageId.h"是消息ID定义文件。在MangoGUI中每一个消息的识别是通过 所在Scene ID+控件ID来识别的。但是对于每一个Scene内部的控件用ID就足够了。MessageId.h中定义的就是控件ID。我们Tut02中已经展示了scene.xml中的数据:
 显示Toggle full screen的按钮的ID是101,在“MessageId.h”中也定义了复制代码<Button ID='101' name ="FullScreen" x='35' y='10' width ='135' height='45' >Toggle full screen</Button>
在后面的OnGUIEvent()函数中,处理了对应的宏定义为Button1的方法。也就是说,当按下了Toggle full screen按钮就会发送nControlID 是101的消息,当我们在OnGUIEvent()中收到这个消息,就执行MANGOToggleFullScreen()这个全屏化操作。复制代码//Window Massage map
#define Button1 101
#define Button2 102
#define Button3 103
 如果大家对D3D不是太熟悉,那么以上的框架就不要改动,以为这个框架完全不影响游戏GUI的操作。我们要完成游戏GUI的所有操作,都是在限定的几个函数内完成的。只需要将我们的逻辑类放在框架内运行即可。
 
 
 CMANGOSceneManager场景管理器最好在游戏中只创建一个,这个管理器已经集成了对界面控制文件的相关操作,因此需要在界面上显示例如按钮等控件,只需要在相应的界面控制XML文件中添加,控件产生的响应在OnGUIEvent()中对应处理即可。
 通过CreateScene方法载入UI数据。复制代码g_SceneManager.CreateScene("layout/scene.xml");
OnRender方法绘制UI数据。复制代码g_SceneManager.OnRender(fElapsedTime);
 | 
 |