Creare Videogiochi - Game Developer
Tutorial 14 - Win32 Window - Versione stampabile

+- Creare Videogiochi - Game Developer (https://www.making-videogames.net/giochi)
+-- Forum: Altri Programmi per la Creazione di Videogames (https://www.making-videogames.net/giochi/Forum-Altri-Programmi-per-la-Creazione-di-Videogames)
+--- Forum: Irrlicht Engine (https://www.making-videogames.net/giochi/Forum-Irrlicht-Engine)
+--- Discussione: Tutorial 14 - Win32 Window (/thread-Tutorial-14-Win32-Window)



Tutorial 14 - Win32 Window - Chip - 19-08-2015

Tutorial 14: Win32 Window

[Immagine: 014shot.jpg]

Questo esempio gira solo su MS Windiws e dimostra come Irrlicht può produrre rendering dentro una finestra win32 originale. E' possibile anche farlo su finestre create con le librerie MFC e con le finestre Windows.Forms della libreria .NET.
All'inizio creiamo una finestra di Windows usando le API. Non spiegherò in dettaglio come funziona questo codice. Per maggiori approfondimenti si rimanda al sito MSDN o a testi specifici sulla programmazione di Windows.
Codice PHP:
#include <irrlicht.h>
#ifndef _IRR_WINDOWS_
#error Windows only example
#else
#include <windows.h> // this example only runs with windows
#include <iostream>
#include "driverChoice.h"

using namespace irr;

#pragma comment(lib, "irrlicht.lib")

HWND hOKButton;
HWND hWnd;

static 
LRESULT CALLBACK CustomWndProc(HWND hWndUINT message,
        
WPARAM wParamLPARAM lParam)
{
    switch (
message)
    {
    case 
WM_COMMAND:
        {
            
HWND hwndCtl = (HWND)lParam;
            
int code HIWORD(wParam);

            if (
hwndCtl == hOKButton)
            {
                
DestroyWindow(hWnd);
                
PostQuitMessage(0);
                return 
0;
            }
        }
        break;
    case 
WM_DESTROY:
        
PostQuitMessage(0);
        return 
0;

    }

    return 
DefWindowProc(hWndmessagewParamlParam);

Ora chiediamo quale driver usare e creiamo una istanza della finestra Windows definita prima.
Codice PHP:
int main()
{
    
// ask user for driver
    
video::E_DRIVER_TYPE driverType=driverChoiceConsole();
    if (
driverType==video::EDT_COUNT)
        return 
1;

    
printf("Select the render window (some dead window may exist too):\n"\
        
" (a) Window with button (via CreationParam)\n"\
        
" (b) Window with button (via beginScene)\n"\
        
" (c) Own Irrlicht window (default behavior)\n"\
        
" (otherKey) exit\n\n");

    
char key;
    
std::cin >> key;
    if (
key != 'a' && key != 'b' && key != 'c')
        return 
1;

    
HINSTANCE hInstance 0;
    
// create dialog

    
const charWin32ClassName "CIrrlichtWindowsTestDialog";

    
WNDCLASSEX wcex;
    
wcex.cbSize         sizeof(WNDCLASSEX);
    
wcex.style          CS_HREDRAW CS_VREDRAW;
    
wcex.lpfnWndProc    = (WNDPROC)CustomWndProc;
    
wcex.cbClsExtra     0;
    
wcex.cbWndExtra     DLGWINDOWEXTRA;
    
wcex.hInstance      hInstance;
    
wcex.hIcon          NULL;
    
wcex.hCursor        LoadCursor(NULLIDC_ARROW);
    
wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW);
    
wcex.lpszMenuName   0;
    
wcex.lpszClassName  Win32ClassName;
    
wcex.hIconSm        0;

    
RegisterClassEx(&wcex);

    
DWORD style WS_SYSMENU WS_BORDER WS_CAPTION |
        
WS_CLIPCHILDREN WS_CLIPSIBLINGS WS_MAXIMIZEBOX WS_MINIMIZEBOX WS_SIZEBOX;

    
int windowWidth 440;
    
int windowHeight 380;

    
hWnd CreateWindowWin32ClassName"Irrlicht Win32 window example",
        
style100100windowWidthwindowHeight,
        
NULLNULLhInstanceNULL);

    
RECT clientRect;
    
GetClientRect(hWnd, &clientRect);
    
windowWidth clientRect.right;
    
windowHeight clientRect.bottom;

    
// create ok button

    
hOKButton CreateWindow("BUTTON""OK - Close"WS_CHILD WS_VISIBLE BS_TEXT,
        
windowWidth 160windowHeight 4015030hWndNULLhInstanceNULL);

    
// create some text

    
CreateWindow("STATIC""This is Irrlicht running inside a standard Win32 window.\n"\
        
"Also mixing with MFC and .NET Windows.Forms is possible.",
        
WS_CHILD WS_VISIBLE202040040hWndNULLhInstanceNULL);

    
// create window to put irrlicht in

    
HWND hIrrlichtWindow CreateWindow("BUTTON""",
            
WS_CHILD WS_VISIBLE BS_OWNERDRAW,
            
5080320220hWndNULLhInstanceNULL);
    
video::SExposedVideoData videodata((key=='b')?hIrrlichtWindow:0); 
Adesso che abbiamo la finestra aperta possiamo crearci dentro il nostro device Irrlicht. Per farlo usiamo la funzione di Irrlicht createEx(). Ci servono l'handle (HWND) a quella finestra, impostarla come parametro di windowsID e poi lanciare l'engine come al solito. Questo è tutto.
Codice PHP:
// create irrlicht device in the button window

    
irr::SIrrlichtCreationParameters param;
    
param.DriverType driverType;
    if (
key=='a')
        
param.WindowId reinterpret_cast<void*>(hIrrlichtWindow);

    
irr::IrrlichtDevicedevice irr::createDeviceEx(param);
    if (!
device)
        return 
1;

    
// setup a simple 3d scene

    
irr::scene::ISceneManagersmgr device->getSceneManager();
    
video::IVideoDriverdriver device->getVideoDriver();

    if (
driverType==video::EDT_OPENGL)
    {
        
HDC HDc=GetDC(hIrrlichtWindow);
        
PIXELFORMATDESCRIPTOR pfd={0};
        
pfd.nSize=sizeof(PIXELFORMATDESCRIPTOR);
        
int pf GetPixelFormat(HDc);
        
DescribePixelFormat(HDcpfsizeof(PIXELFORMATDESCRIPTOR), &pfd);
        
pfd.dwFlags |= PFD_DOUBLEBUFFER PFD_SUPPORT_OPENGL PFD_DRAW_TO_WINDOW;
        
pfd.cDepthBits=16;
        
pf ChoosePixelFormat(HDc, &pfd);
        
SetPixelFormat(HDcpf, &pfd);
        
videodata.OpenGLWin32.HDc HDc;
        
videodata.OpenGLWin32.HRc=wglCreateContext(HDc);
        
wglShareLists((HGLRC)driver->getExposedVideoData().OpenGLWin32.HRc, (HGLRC)videodata.OpenGLWin32.HRc);
    }
    
scene::ICameraSceneNodecam smgr->addCameraSceneNode();
    
cam->setTarget(core::vector3df(0,0,0));

    
scene::ISceneNodeAnimatoranim =
        
smgr->createFlyCircleAnimator(core::vector3df(0,15,0), 30.0f);
    
cam->addAnimator(anim);
    
anim->drop();

    
scene::ISceneNodecube smgr->addCubeSceneNode(20);

    
cube->setMaterialTexture(0driver->getTexture("../../media/wall.bmp"));
    
cube->setMaterialTexture(1driver->getTexture("../../media/water.jpg"));
    
cube->setMaterialFlagvideo::EMF_LIGHTINGfalse );
    
cube->setMaterialTypevideo::EMT_REFLECTION_2_LAYER );

    
smgr->addSkyBoxSceneNode(
    
driver->getTexture("../../media/irrlicht2_up.jpg"),
    
driver->getTexture("../../media/irrlicht2_dn.jpg"),
    
driver->getTexture("../../media/irrlicht2_lf.jpg"),
    
driver->getTexture("../../media/irrlicht2_rt.jpg"),
    
driver->getTexture("../../media/irrlicht2_ft.jpg"),
    
driver->getTexture("../../media/irrlicht2_bk.jpg"));

    
// show and execute dialog

    
ShowWindow(hWnd SW_SHOW);
    
UpdateWindow(hWnd);

    
// do message queue 
L'ultima cosa che manca è il loop del disegno tramite IrrlichtDevice::run(). Lo facciamo come di solito abbiamo fatto. Ma potremmo anche fare in un altro modo: semplicemente utilizzare un nostro loop di messaggi windows tramite GetMessage, DispatchMessage. Poiché richiamare Device->run() causa l'invio dei messaggi internamente a Irrlicht, non vi serve più richiamarlo. Considerate però che se vorrete farvi da soli il vostro loop per la messaggistica Windows, Irrlicht non potrà più gestire nemmeno gli input utente che dovrete quindi gestire da soli usando la messaggistica di Window, oppure con le DirectInput, o una qualsiasi altra soluzione alternativa.
Codice PHP:
while (device->run())
    {
        
driver->beginScene(truetrue0videodata);
        
smgr->drawAll();
        
driver->endScene();
    } 
In alternativa un proprio sistema di messaggistica interno senza l'uso della Device->run() potrebbe assomigliare a qualcosa del genere:
Codice PHP:
MSG msg;
while (
true

   if (
PeekMessage(&msgNULL00PM_REMOVE)) 
   {
       
TranslateMessage(&msg);
      
DispatchMessage(&msg);
      if (
msg.message == WM_QUIT) break; 
   }
advance virtual time device->getTimer()->tick();
draw engine picture driver->beginScene(truetrue0, (key=='c')? hIrrlichtWindow:0);

smgr->drawAll();
driver->endScene(); }
device->closeDevice();
device->drop();

return 
0;
}
#endif // if windows 
Ed è tutto, ora Irrlicht gira dentro la vostra finestra Windows.

Versione pdf scaricabile da QUI