Reserved some Bullet 2.x constraint data.
[blender.git] / source / gameengine / GamePlayer / ghost / GPG_Application.cpp
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  * GHOST Blender Player application implementation file.
32  */
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 #ifdef WIN32
39         #pragma warning (disable:4786) // suppress stl-MSVC debug info warning
40         #include <windows.h>
41 #endif
42
43 #ifdef __APPLE__
44 #define GL_GLEXT_LEGACY 1
45 #include <OpenGL/gl.h>
46 #include <OpenGL/glu.h>
47 #else
48 #include <GL/gl.h>
49 #include <GL/glu.h>
50 #endif
51
52 #include "GPG_Application.h"
53
54 #include <iostream>
55 #include <MT_assert.h>
56
57 /**********************************
58  * Begin Blender include block
59  **********************************/
60 #ifdef __cplusplus
61 extern "C"
62 {
63 #endif  // __cplusplus
64 #include "BLI_blenlib.h"
65 #include "BLO_readfile.h"
66 #include "BKE_global.h"
67 #include "BKE_main.h"
68 #ifdef __cplusplus
69 }
70 #endif // __cplusplus
71 /**********************************
72  * End Blender include block
73  **********************************/
74
75
76 #include "SYS_System.h"
77 #include "KX_KetsjiEngine.h"
78
79 // include files needed by "KX_BlenderSceneConverter.h"
80 #include "GEN_Map.h"
81 #include "SCA_IActuator.h"
82 #include "RAS_MeshObject.h"
83 #include "RAS_OpenGLRasterizer.h"
84 #include "RAS_VAOpenGLRasterizer.h"
85 #include "RAS_ListRasterizer.h"
86 #include "RAS_GLExtensionManager.h"
87 #include "KX_PythonInit.h"
88 #include "KX_PyConstraintBinding.h"
89 #include "BL_Material.h" // MAXTEX
90
91 #include "KX_BlenderSceneConverter.h"
92 #include "NG_LoopBackNetworkDeviceInterface.h"
93 #include "SND_DeviceManager.h"
94
95 #include "GPC_MouseDevice.h"
96 #include "GPC_RenderTools.h"
97 #include "GPG_Canvas.h" 
98 #include "GPG_KeyboardDevice.h"
99 #include "GPG_System.h"
100
101 #include "STR_String.h"
102
103 #include "GHOST_ISystem.h"
104 #include "GHOST_IEvent.h"
105 #include "GHOST_IEventConsumer.h"
106 #include "GHOST_IWindow.h"
107 #include "GHOST_Rect.h"
108
109
110 static void frameTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time);
111
112 static GHOST_ISystem* fSystem = 0;
113 static const int kTimerFreq = 10;
114
115 GPG_Application::GPG_Application(GHOST_ISystem* system, struct Main* maggie, STR_String startSceneName)
116         : m_startSceneName(startSceneName), 
117           m_maggie(maggie),
118           m_exitRequested(0),
119           m_system(system), 
120           m_mainWindow(0), 
121           m_frameTimer(0), 
122           m_cursor(GHOST_kStandardCursorFirstCursor),
123           m_engineInitialized(0), 
124           m_engineRunning(0), 
125           m_ketsjiengine(0),
126           m_kxsystem(0), 
127           m_keyboard(0), 
128           m_mouse(0), 
129           m_canvas(0), 
130           m_rendertools(0), 
131           m_rasterizer(0), 
132           m_sceneconverter(0),
133           m_networkdevice(0), 
134           m_audiodevice(0),
135           m_blendermat(0)
136 {
137         fSystem = system;
138 }
139
140
141
142 GPG_Application::~GPG_Application(void)
143 {
144         exitEngine();
145         fSystem->disposeWindow(m_mainWindow);
146 }
147
148
149
150 bool GPG_Application::SetGameEngineData(struct Main* maggie, STR_String startSceneName)
151 {
152         bool result = false;
153
154         if (maggie != NULL && startSceneName != "")
155         {
156                 G.scene = (Scene*)maggie->scene.first;
157                 m_maggie = maggie;
158                 m_startSceneName = startSceneName;
159                 result = true;
160         }
161
162         return result;
163 }
164
165
166 #ifdef WIN32
167 #define SCR_SAVE_MOUSE_MOVE_THRESHOLD 15
168
169 static HWND found_ghost_window_hwnd;
170 static GHOST_IWindow* ghost_window_to_find;
171 static WNDPROC ghost_wnd_proc;
172 static POINT scr_save_mouse_pos;
173
174 static LRESULT CALLBACK screenSaverWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
175 {
176         BOOL close = FALSE;
177         switch (uMsg)
178         {
179                 case WM_MOUSEMOVE:
180                 { 
181                         POINT pt; 
182                         GetCursorPos(&pt);
183                         LONG dx = scr_save_mouse_pos.x - pt.x;
184                         LONG dy = scr_save_mouse_pos.y - pt.y;
185                         if (abs(dx) > SCR_SAVE_MOUSE_MOVE_THRESHOLD
186                             || abs(dy) > SCR_SAVE_MOUSE_MOVE_THRESHOLD)
187                         {
188                                 close = TRUE;
189                         }
190                         scr_save_mouse_pos = pt;
191                         break;
192                 }
193                 case WM_LBUTTONDOWN: 
194                 case WM_MBUTTONDOWN: 
195                 case WM_RBUTTONDOWN: 
196                 case WM_KEYDOWN:
197                         close = TRUE;
198         }
199         if (close)
200                 PostMessage(hwnd,WM_CLOSE,0,0);
201         return CallWindowProc(ghost_wnd_proc, hwnd, uMsg, wParam, lParam);
202 }
203
204 BOOL CALLBACK findGhostWindowHWNDProc(HWND hwnd, LPARAM lParam)
205 {
206         GHOST_IWindow *p = (GHOST_IWindow*) GetWindowLong(hwnd, GWL_USERDATA);
207         BOOL ret = TRUE;
208         if (p == ghost_window_to_find)
209         {
210                 found_ghost_window_hwnd = hwnd;
211                 ret = FALSE;
212         }
213         return ret;
214 }
215
216 static HWND findGhostWindowHWND(GHOST_IWindow* window)
217 {
218         found_ghost_window_hwnd = NULL;
219         ghost_window_to_find = window;
220         EnumWindows(findGhostWindowHWNDProc, NULL);
221         return found_ghost_window_hwnd;
222 }
223
224 bool GPG_Application::startScreenSaverPreview(
225         HWND parentWindow,
226         const bool stereoVisual,
227         const int stereoMode)
228 {
229         bool success = false;
230
231         RECT rc;
232         if (GetWindowRect(parentWindow, &rc))
233         {
234                 int windowWidth = rc.right - rc.left;
235                 int windowHeight = rc.bottom - rc.top;
236                 STR_String title = "";
237                                                         
238                 m_mainWindow = fSystem->createWindow(title, 0, 0, windowWidth, windowHeight, GHOST_kWindowStateMinimized,
239                         GHOST_kDrawingContextTypeOpenGL, stereoVisual);
240                 if (!m_mainWindow) {
241                         printf("error: could not create main window\n");
242                         exit(-1);
243                 }
244
245                 HWND ghost_hwnd = findGhostWindowHWND(m_mainWindow);
246                 if (!ghost_hwnd) {
247                         printf("error: could find main window\n");
248                         exit(-1);
249                 }
250
251                 SetParent(ghost_hwnd, parentWindow);
252                 LONG style = GetWindowLong(ghost_hwnd, GWL_STYLE);
253                 LONG exstyle = GetWindowLong(ghost_hwnd, GWL_EXSTYLE);
254
255                 RECT adjrc = { 0, 0, windowWidth, windowHeight };
256                 AdjustWindowRectEx(&adjrc, style, FALSE, exstyle);
257
258                 style = (style & (~(WS_POPUP|WS_OVERLAPPEDWINDOW|WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_TILEDWINDOW ))) | WS_CHILD;
259                 SetWindowLong(ghost_hwnd, GWL_STYLE, style);
260                 SetWindowPos(ghost_hwnd, NULL, adjrc.left, adjrc.top, 0, 0, SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE);
261
262                 /* Check the size of the client rectangle of the window and resize the window
263                  * so that the client rectangle has the size requested.
264                  */
265                 m_mainWindow->setClientSize(windowWidth, windowHeight);
266
267                 success = initEngine(m_mainWindow, stereoMode);
268                 if (success) {
269                         success = startEngine();
270                 }
271
272         }
273         return success;
274 }
275
276 bool GPG_Application::startScreenSaverFullScreen(
277                 int width,
278                 int height,
279                 int bpp,int frequency,
280                 const bool stereoVisual,
281                 const int stereoMode)
282 {
283         bool ret = startFullScreen(width, height, bpp, frequency, stereoVisual, stereoMode);
284         if (ret)
285         {
286                 HWND ghost_hwnd = findGhostWindowHWND(m_mainWindow);
287                 if (ghost_hwnd != NULL)
288                 {
289                         GetCursorPos(&scr_save_mouse_pos);
290                         ghost_wnd_proc = (WNDPROC) GetWindowLong(ghost_hwnd, GWL_WNDPROC);
291                         SetWindowLong(ghost_hwnd,GWL_WNDPROC, (LONG) screenSaverWindowProc);
292                 }
293         }
294         return ret;
295 }
296
297 #endif
298
299 bool GPG_Application::startWindow(STR_String& title,
300         int windowLeft,
301         int windowTop,
302         int windowWidth,
303         int windowHeight,
304         const bool stereoVisual,
305         const int stereoMode)
306 {
307         bool success;
308         // Create the main window
309         //STR_String title ("Blender Player - GHOST");
310         m_mainWindow = fSystem->createWindow(title, windowLeft, windowTop, windowWidth, windowHeight, GHOST_kWindowStateNormal,
311                 GHOST_kDrawingContextTypeOpenGL, stereoVisual);
312         if (!m_mainWindow) {
313                 printf("error: could not create main window\n");
314                 exit(-1);
315         }
316
317         /* Check the size of the client rectangle of the window and resize the window
318          * so that the client rectangle has the size requested.
319          */
320         m_mainWindow->setClientSize(windowWidth, windowHeight);
321         m_mainWindow->setCursorVisibility(false);
322
323         success = initEngine(m_mainWindow, stereoMode);
324         if (success) {
325                 success = startEngine();
326         }
327         return success;
328 }
329
330
331
332 bool GPG_Application::startFullScreen(
333                 int width,
334                 int height,
335                 int bpp,int frequency,
336                 const bool stereoVisual,
337                 const int stereoMode)
338 {
339         bool success;
340         // Create the main window
341         GHOST_DisplaySetting setting;
342         setting.xPixels = width;
343         setting.yPixels = height;
344         setting.bpp = bpp;
345         setting.frequency = frequency;
346
347         fSystem->beginFullScreen(setting, &m_mainWindow, stereoVisual);
348         m_mainWindow->setCursorVisibility(false);
349
350         success = initEngine(m_mainWindow, stereoMode);
351         if (success) {
352                 success = startEngine();
353         }
354         return success;
355 }
356
357
358
359
360 bool GPG_Application::StartGameEngine(int stereoMode)
361 {
362         bool success = initEngine(m_mainWindow, stereoMode);
363         
364         if (success)
365                 success = startEngine();
366
367         return success;
368 }
369
370
371
372 void GPG_Application::StopGameEngine()
373 {
374         exitEngine();
375 }
376
377
378
379 bool GPG_Application::processEvent(GHOST_IEvent* event)
380 {
381         bool handled = true;
382
383         switch (event->getType())
384         {
385                 case GHOST_kEventUnknown:
386                         break;
387
388                 case GHOST_kEventButtonDown:
389                         handled = handleButton(event, true);
390                         break;
391
392                 case GHOST_kEventButtonUp:
393                         handled = handleButton(event, false);
394                         break;
395                         
396                 case GHOST_kEventWheel:
397                         handled = handleWheel(event);
398                         break;
399
400                 case GHOST_kEventCursorMove:
401                         handled = handleCursorMove(event);
402                         break;
403
404                 case GHOST_kEventKeyDown:
405                         handleKey(event, true);
406                         break;
407
408                 case GHOST_kEventKeyUp:
409                         handleKey(event, false);
410                         break;
411
412
413                 case GHOST_kEventWindowClose:
414                         m_exitRequested = KX_EXIT_REQUEST_OUTSIDE;
415                         break;
416
417                 case GHOST_kEventWindowActivate:
418                         handled = false;
419                         break;
420                 case GHOST_kEventWindowDeactivate:
421                         handled = false;
422                         break;
423
424                 case GHOST_kEventWindowUpdate:
425                         {
426                                 GHOST_IWindow* window = event->getWindow();
427                                 if (!m_system->validWindow(window)) break;
428                                 // Update the state of the game engine
429                                 if (m_kxsystem && !m_exitRequested)
430                                 {
431                                         // Proceed to next frame
432                                         window->activateDrawingContext();
433
434                                         // first check if we want to exit
435                                         m_exitRequested = m_ketsjiengine->GetExitCode();
436                                         
437                                         // kick the engine
438                                         m_ketsjiengine->NextFrame();
439                                         
440                                         // render the frame
441                                         m_ketsjiengine->Render();
442                                 }
443                                 m_exitString = m_ketsjiengine->GetExitString();
444                         }
445                         break;
446                 
447                 case GHOST_kEventWindowSize:
448                         {
449                         GHOST_IWindow* window = event->getWindow();
450                         if (!m_system->validWindow(window)) break;
451                         if (m_canvas) {
452                                 GHOST_Rect bnds;
453                                 window->getClientBounds(bnds);
454                                 m_canvas->Resize(bnds.getWidth(), bnds.getHeight());
455                         }
456                         }
457                         break;
458                 
459                 default:
460                         handled = false;
461                         break;
462         }
463         return handled;
464 }
465
466
467
468 int GPG_Application::getExitRequested(void)
469 {
470         return m_exitRequested;
471 }
472
473
474
475 const STR_String& GPG_Application::getExitString(void)
476 {
477         return m_exitString;
478 }
479
480
481
482 bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
483 {
484         if (!m_engineInitialized)
485         {
486                 bgl::InitExtensions(1);
487
488                 // get and set the preferences
489                 SYS_SystemHandle syshandle = SYS_GetSystem();
490                 if (!syshandle)
491                         return false;
492                 
493                 // SYS_WriteCommandLineInt(syshandle, "fixedtime", 0);
494                 // SYS_WriteCommandLineInt(syshandle, "vertexarrays",1);                
495                 bool properties = (SYS_GetCommandLineInt(syshandle, "show_properties", 0) != 0);
496                 bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0);
497                 bool fixedFr = (G.fileflags & G_FILE_ENABLE_ALL_FRAMES);
498
499                 bool fixed_framerate= (SYS_GetCommandLineInt(syshandle, "fixed_framerate", fixedFr) != 0);
500                 bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
501                 bool useVertexArrays = SYS_GetCommandLineInt(syshandle,"vertexarrays",1) != 0;
502                 bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", G.fileflags & G_FILE_DIAPLAY_LISTS) != 0);
503 #ifdef GL_ARB_multitexture
504                 int gameflag =(G.fileflags & G_FILE_GAME_MAT);
505                 // ----------------------------------
506                 if(bgl::RAS_EXT_support._ARB_multitexture && bgl::QueryVersion(1, 1)) {
507                         m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", gameflag) != 0);
508                         int unitmax=0;
509                         glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, (GLint*)&unitmax);
510                         bgl::max_texture_units = MAXTEX>unitmax?unitmax:MAXTEX;
511                         //std::cout << "using(" << bgl::max_texture_units << ") of(" << unitmax << ") texture units." << std::endl;
512                 } else {
513                         bgl::max_texture_units = 0;
514                 }
515 #else
516                 m_blendermat=0;
517 #endif//GL_ARB_multitexture
518                 // ----------------------------------
519         
520                 // create the canvas, rasterizer and rendertools
521                 m_canvas = new GPG_Canvas(window);
522                 if (!m_canvas)
523                         return false;
524                                 
525                 m_canvas->Init();                               
526                 m_rendertools = new GPC_RenderTools();
527                 if (!m_rendertools)
528                         goto initFailed;
529                 
530                 if(useLists)
531                         m_rasterizer = new RAS_ListRasterizer(m_canvas);
532                 else if (useVertexArrays && bgl::QueryVersion(1, 1))
533                         m_rasterizer = new RAS_VAOpenGLRasterizer(m_canvas);
534                 else
535                         m_rasterizer = new RAS_OpenGLRasterizer(m_canvas);
536                 m_rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) stereoMode);
537                 if (!m_rasterizer)
538                         goto initFailed;
539                                                 
540                 // create the inputdevices
541                 m_keyboard = new GPG_KeyboardDevice();
542                 if (!m_keyboard)
543                         goto initFailed;
544                         
545                 m_mouse = new GPC_MouseDevice();
546                 if (!m_mouse)
547                         goto initFailed;
548                         
549                 // create a networkdevice
550                 m_networkdevice = new NG_LoopBackNetworkDeviceInterface();
551                 if (!m_networkdevice)
552                         goto initFailed;
553                         
554                 // get an audiodevice
555                 SND_DeviceManager::Subscribe();
556                 m_audiodevice = SND_DeviceManager::Instance();
557                 if (!m_audiodevice)
558                         goto initFailed;
559                 m_audiodevice->UseCD();
560                 
561                 // create a ketsjisystem (only needed for timing and stuff)
562                 m_kxsystem = new GPG_System (m_system);
563                 if (!m_kxsystem)
564                         goto initFailed;
565                 
566                 // create the ketsjiengine
567                 m_ketsjiengine = new KX_KetsjiEngine(m_kxsystem);
568                 
569                 // set the devices
570                 m_ketsjiengine->SetKeyboardDevice(m_keyboard);
571                 m_ketsjiengine->SetMouseDevice(m_mouse);
572                 m_ketsjiengine->SetNetworkDevice(m_networkdevice);
573                 m_ketsjiengine->SetCanvas(m_canvas);
574                 m_ketsjiengine->SetRenderTools(m_rendertools);
575                 m_ketsjiengine->SetRasterizer(m_rasterizer);
576                 m_ketsjiengine->SetNetworkDevice(m_networkdevice);
577                 m_ketsjiengine->SetAudioDevice(m_audiodevice);
578                 m_ketsjiengine->SetTimingDisplay(frameRate, false, false);
579
580                 m_ketsjiengine->SetUseFixedTime(fixed_framerate);
581                 m_ketsjiengine->SetTimingDisplay(frameRate, profile, properties);
582
583                 m_engineInitialized = true;
584         }
585
586         return m_engineInitialized;
587 initFailed:
588         delete m_kxsystem;
589         delete m_audiodevice;
590         delete m_networkdevice;
591         delete m_mouse;
592         delete m_keyboard;
593         delete m_rasterizer;
594         delete m_rendertools;
595         delete m_canvas;
596         m_canvas = NULL;
597         m_rendertools = NULL;
598         m_rasterizer = NULL;
599         m_keyboard = NULL;
600         m_mouse = NULL;
601         m_networkdevice = NULL;
602         m_audiodevice = NULL;
603         m_kxsystem = NULL;
604         return false;
605 }
606
607
608
609 bool GPG_Application::startEngine(void)
610 {
611         if (m_engineRunning) {
612                 return false;
613         }
614         
615         // Temporary hack to disable banner display for NaN approved content.
616         /*
617         m_canvas->SetBannerDisplayEnabled(true);        
618         Camera* cam;
619         cam = (Camera*)G.scene->camera->data;
620         if (cam) {
621         if (((cam->flag) & 48)==48) {
622         m_canvas->SetBannerDisplayEnabled(false);
623         }
624         }
625         else {
626         showError(CString("Camera data invalid."));
627         return false;
628         }
629         */
630         
631         // create a scene converter, create and convert the stratingscene
632         m_sceneconverter = new KX_BlenderSceneConverter(m_maggie,0, m_ketsjiengine);
633         if (m_sceneconverter)
634         {
635                 STR_String startscenename = m_startSceneName.Ptr();
636                 m_ketsjiengine->SetSceneConverter(m_sceneconverter);
637                 
638                 //      if (always_use_expand_framing)
639                 //              sceneconverter->SetAlwaysUseExpandFraming(true);
640                 if(m_blendermat)
641                         m_sceneconverter->SetMaterials(true);
642
643                 KX_Scene* startscene = new KX_Scene(m_keyboard,
644                         m_mouse,
645                         m_networkdevice,
646                         m_audiodevice,
647                         startscenename);
648                 
649                 
650                 // some python things
651                 PyObject* dictionaryobject = initGamePlayerPythonScripting("Ketsji", psl_Lowest);
652                 m_ketsjiengine->SetPythonDictionary(dictionaryobject);
653                 initRasterizer(m_rasterizer, m_canvas);
654                 PyObject *gameLogic = initGameLogic(startscene);
655                 initGameKeys();
656                 initPythonConstraintBinding();
657
658
659
660
661
662                 m_sceneconverter->ConvertScene(
663                         startscenename,
664                         startscene,
665                         dictionaryobject,
666                         m_keyboard,
667                         m_rendertools,
668                         m_canvas);
669                 m_ketsjiengine->AddScene(startscene);
670                 
671                 // Create a timer that is used to kick the engine
672                 if (!m_frameTimer) {
673                         m_frameTimer = m_system->installTimer(0, kTimerFreq, frameTimerProc, m_mainWindow);
674                 }
675                 m_rasterizer->Init();
676                 m_ketsjiengine->StartEngine(true);
677                 m_engineRunning = true;
678                 
679         }
680         
681         if (!m_engineRunning)
682         {
683                 stopEngine();
684         }
685         
686         return m_engineRunning;
687 }
688
689
690 void GPG_Application::stopEngine()
691 {
692         // when exiting the mainloop
693         exitGamePythonScripting();
694         m_ketsjiengine->StopEngine();
695         m_networkdevice->Disconnect();
696
697         if (m_sceneconverter) {
698                 delete m_sceneconverter;
699                 m_sceneconverter = 0;
700         }
701         if (m_system && m_frameTimer) {
702                 m_system->removeTimer(m_frameTimer);
703                 m_frameTimer = 0;
704         }
705         m_engineRunning = false;
706 }
707
708
709 void GPG_Application::exitEngine()
710 {
711         if (m_ketsjiengine)
712         {
713                 stopEngine();
714                 delete m_ketsjiengine;
715                 m_ketsjiengine = 0;
716         }
717         if (m_kxsystem)
718         {
719                 delete m_kxsystem;
720                 m_kxsystem = 0;
721         }
722         if (m_audiodevice)
723         {
724                 SND_DeviceManager::Unsubscribe();
725                 m_audiodevice = 0;
726         }
727         if (m_networkdevice)
728         {
729                 delete m_networkdevice;
730                 m_networkdevice = 0;
731         }
732         if (m_mouse)
733         {
734                 delete m_mouse;
735                 m_mouse = 0;
736         }
737         if (m_keyboard)
738         {
739                 delete m_keyboard;
740                 m_keyboard = 0;
741         }
742         if (m_rasterizer)
743         {
744                 delete m_rasterizer;
745                 m_rasterizer = 0;
746         }
747         if (m_rendertools)
748         {
749                 delete m_rendertools;
750                 m_rendertools = 0;
751         }
752         if (m_canvas)
753         {
754                 delete m_canvas;
755                 m_canvas = 0;
756         }
757
758         m_exitRequested = 0;
759         m_engineInitialized = false;
760 }
761
762 bool GPG_Application::handleWheel(GHOST_IEvent* event)
763 {
764         bool handled = false;
765         MT_assert(event);
766         if (m_mouse) 
767         {
768                 GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
769                 GHOST_TEventWheelData* wheelData = static_cast<GHOST_TEventWheelData*>(eventData);
770                 GPC_MouseDevice::TButtonId button;
771                 if (wheelData->z > 0)
772                         button = GPC_MouseDevice::buttonWheelUp;
773                 else
774                         button = GPC_MouseDevice::buttonWheelDown;
775                 m_mouse->ConvertButtonEvent(button, true);
776                 handled = true;
777         }
778         return handled;
779 }
780
781 bool GPG_Application::handleButton(GHOST_IEvent* event, bool isDown)
782 {
783         bool handled = false;
784         MT_assert(event);
785         if (m_mouse) 
786         {
787                 GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
788                 GHOST_TEventButtonData* buttonData = static_cast<GHOST_TEventButtonData*>(eventData);
789                 GPC_MouseDevice::TButtonId button;
790                 switch (buttonData->button)
791                 {
792                 case GHOST_kButtonMaskMiddle:
793                         button = GPC_MouseDevice::buttonMiddle;
794                         break;
795                 case GHOST_kButtonMaskRight:
796                         button = GPC_MouseDevice::buttonRight;
797                         break;
798                 case GHOST_kButtonMaskLeft:
799                 default:
800                         button = GPC_MouseDevice::buttonLeft;
801                         break;
802                 }
803                 m_mouse->ConvertButtonEvent(button, isDown);
804                 handled = true;
805         }
806         return handled;
807 }
808
809
810 bool GPG_Application::handleCursorMove(GHOST_IEvent* event)
811 {
812         bool handled = false;
813         MT_assert(event);
814         if (m_mouse && m_mainWindow)
815         {
816                 GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
817                 GHOST_TEventCursorData* cursorData = static_cast<GHOST_TEventCursorData*>(eventData);
818                 GHOST_TInt32 x, y;
819                 m_mainWindow->screenToClient(cursorData->x, cursorData->y, x, y);
820                 m_mouse->ConvertMoveEvent(x, y);
821                 handled = true;
822         }
823         return handled;
824 }
825
826
827 bool GPG_Application::handleKey(GHOST_IEvent* event, bool isDown)
828 {
829         bool handled = false;
830         MT_assert(event);
831         if (m_keyboard)
832         {
833                 GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
834                 GHOST_TEventKeyData* keyData = static_cast<GHOST_TEventKeyData*>(eventData);
835                 if (fSystem->getFullScreen()) {
836                         if (keyData->key == GHOST_kKeyEsc) {
837                                 m_exitRequested = KX_EXIT_REQUEST_OUTSIDE;
838                         }
839                 }
840                 m_keyboard->ConvertEvent(keyData->key, isDown);
841                 handled = true;
842         }
843         return handled;
844 }
845
846
847
848 static void frameTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time)
849 {
850         GHOST_IWindow* window = (GHOST_IWindow*)task->getUserData();
851         if (fSystem->validWindow(window)) {
852                 window->invalidate();
853         }
854 }