some minor webplugin changes, new loading .blend, upgraded version to 2.42, enabled...
[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 bool GPG_Application::StartGameEngine(int stereoMode)
360 {
361         bool success = initEngine(m_mainWindow, stereoMode);
362         
363         if (success)
364                 success = startEngine();
365
366         return success;
367 }
368
369
370
371 void GPG_Application::StopGameEngine()
372 {
373         exitEngine();
374 }
375
376
377
378 bool GPG_Application::processEvent(GHOST_IEvent* event)
379 {
380         bool handled = true;
381
382         switch (event->getType())
383         {
384                 case GHOST_kEventUnknown:
385                         break;
386
387                 case GHOST_kEventButtonDown:
388                         handled = handleButton(event, true);
389                         break;
390
391                 case GHOST_kEventButtonUp:
392                         handled = handleButton(event, false);
393                         break;
394                         
395                 case GHOST_kEventWheel:
396                         handled = handleWheel(event);
397                         break;
398
399                 case GHOST_kEventCursorMove:
400                         handled = handleCursorMove(event);
401                         break;
402
403                 case GHOST_kEventKeyDown:
404                         handleKey(event, true);
405                         break;
406
407                 case GHOST_kEventKeyUp:
408                         handleKey(event, false);
409                         break;
410
411
412                 case GHOST_kEventWindowClose:
413                         m_exitRequested = KX_EXIT_REQUEST_OUTSIDE;
414                         break;
415
416                 case GHOST_kEventWindowActivate:
417                         handled = false;
418                         break;
419                 case GHOST_kEventWindowDeactivate:
420                         handled = false;
421                         break;
422
423                 case GHOST_kEventWindowUpdate:
424                         {
425                                 GHOST_IWindow* window = event->getWindow();
426                                 if (!m_system->validWindow(window)) break;
427                                 // Update the state of the game engine
428                                 if (m_kxsystem && !m_exitRequested)
429                                 {
430                                         // Proceed to next frame
431                                         window->activateDrawingContext();
432
433                                         // first check if we want to exit
434                                         m_exitRequested = m_ketsjiengine->GetExitCode();
435                                         
436                                         // kick the engine
437                                         m_ketsjiengine->NextFrame();
438                                         
439                                         // render the frame
440                                         m_ketsjiengine->Render();
441                                 }
442                                 m_exitString = m_ketsjiengine->GetExitString();
443                         }
444                         break;
445                 
446                 case GHOST_kEventWindowSize:
447                         {
448                         GHOST_IWindow* window = event->getWindow();
449                         if (!m_system->validWindow(window)) break;
450                         if (m_canvas) {
451                                 GHOST_Rect bnds;
452                                 window->getClientBounds(bnds);
453                                 m_canvas->Resize(bnds.getWidth(), bnds.getHeight());
454                         }
455                         }
456                         break;
457                 
458                 default:
459                         handled = false;
460                         break;
461         }
462         return handled;
463 }
464
465
466
467 int GPG_Application::getExitRequested(void)
468 {
469         return m_exitRequested;
470 }
471
472
473
474 const STR_String& GPG_Application::getExitString(void)
475 {
476         return m_exitString;
477 }
478
479
480
481 bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
482 {
483         if (!m_engineInitialized)
484         {
485                 bgl::InitExtensions(1);
486
487                 // get and set the preferences
488                 SYS_SystemHandle syshandle = SYS_GetSystem();
489                 if (!syshandle)
490                         return false;
491                 
492                 // SYS_WriteCommandLineInt(syshandle, "fixedtime", 0);
493                 // SYS_WriteCommandLineInt(syshandle, "vertexarrays",1);                
494                 bool properties = (SYS_GetCommandLineInt(syshandle, "show_properties", 0) != 0);
495                 bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0);
496                 bool fixed_framerate= (SYS_GetCommandLineInt(syshandle, "fixed_framerate", 0) != 0);
497                 bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
498                 bool useVertexArrays = SYS_GetCommandLineInt(syshandle,"vertexarrays",1) != 0;
499                 bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", G.fileflags & G_FILE_DIAPLAY_LISTS) != 0);
500 #ifdef GL_ARB_multitexture
501                 int gameflag =(G.fileflags & G_FILE_GAME_MAT);
502                 // ----------------------------------
503                 if(bgl::RAS_EXT_support._ARB_multitexture && bgl::QueryVersion(1, 1)) {
504                         m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", gameflag) != 0);
505                         int unitmax=0;
506                         glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, (GLint*)&unitmax);
507                         bgl::max_texture_units = MAXTEX>unitmax?unitmax:MAXTEX;
508                         //std::cout << "using(" << bgl::max_texture_units << ") of(" << unitmax << ") texture units." << std::endl;
509                 } else {
510                         bgl::max_texture_units = 0;
511                 }
512 #else
513                 m_blendermat=0;
514 #endif//GL_ARB_multitexture
515                 // ----------------------------------
516         
517                 // create the canvas, rasterizer and rendertools
518                 m_canvas = new GPG_Canvas(window);
519                 if (!m_canvas)
520                         return false;
521                                 
522                 m_canvas->Init();                               
523                 m_rendertools = new GPC_RenderTools();
524                 if (!m_rendertools)
525                         goto initFailed;
526                 
527                 if(useLists)
528                         m_rasterizer = new RAS_ListRasterizer(m_canvas);
529                 else if (useVertexArrays && bgl::QueryVersion(1, 1))
530                         m_rasterizer = new RAS_VAOpenGLRasterizer(m_canvas);
531                 else
532                         m_rasterizer = new RAS_OpenGLRasterizer(m_canvas);
533                 m_rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) stereoMode);
534                 if (!m_rasterizer)
535                         goto initFailed;
536                                                 
537                 // create the inputdevices
538                 m_keyboard = new GPG_KeyboardDevice();
539                 if (!m_keyboard)
540                         goto initFailed;
541                         
542                 m_mouse = new GPC_MouseDevice();
543                 if (!m_mouse)
544                         goto initFailed;
545                         
546                 // create a networkdevice
547                 m_networkdevice = new NG_LoopBackNetworkDeviceInterface();
548                 if (!m_networkdevice)
549                         goto initFailed;
550                         
551                 // get an audiodevice
552                 SND_DeviceManager::Subscribe();
553                 m_audiodevice = SND_DeviceManager::Instance();
554                 if (!m_audiodevice)
555                         goto initFailed;
556                 m_audiodevice->UseCD();
557                 
558                 // create a ketsjisystem (only needed for timing and stuff)
559                 m_kxsystem = new GPG_System (m_system);
560                 if (!m_kxsystem)
561                         goto initFailed;
562                 
563                 // create the ketsjiengine
564                 m_ketsjiengine = new KX_KetsjiEngine(m_kxsystem);
565                 
566                 // set the devices
567                 m_ketsjiengine->SetKeyboardDevice(m_keyboard);
568                 m_ketsjiengine->SetMouseDevice(m_mouse);
569                 m_ketsjiengine->SetNetworkDevice(m_networkdevice);
570                 m_ketsjiengine->SetCanvas(m_canvas);
571                 m_ketsjiengine->SetRenderTools(m_rendertools);
572                 m_ketsjiengine->SetRasterizer(m_rasterizer);
573                 m_ketsjiengine->SetNetworkDevice(m_networkdevice);
574                 m_ketsjiengine->SetAudioDevice(m_audiodevice);
575                 m_ketsjiengine->SetTimingDisplay(frameRate, false, false);
576
577                 m_ketsjiengine->SetUseFixedTime(fixed_framerate);
578                 m_ketsjiengine->SetTimingDisplay(frameRate, profile, properties);
579
580                 m_engineInitialized = true;
581         }
582
583         return m_engineInitialized;
584 initFailed:
585         delete m_kxsystem;
586         delete m_audiodevice;
587         delete m_networkdevice;
588         delete m_mouse;
589         delete m_keyboard;
590         delete m_rasterizer;
591         delete m_rendertools;
592         delete m_canvas;
593         m_canvas = NULL;
594         m_rendertools = NULL;
595         m_rasterizer = NULL;
596         m_keyboard = NULL;
597         m_mouse = NULL;
598         m_networkdevice = NULL;
599         m_audiodevice = NULL;
600         m_kxsystem = NULL;
601         return false;
602 }
603
604
605
606 bool GPG_Application::startEngine(void)
607 {
608         if (m_engineRunning) {
609                 return false;
610         }
611         
612         // Temporary hack to disable banner display for NaN approved content.
613         /*
614         m_canvas->SetBannerDisplayEnabled(true);        
615         Camera* cam;
616         cam = (Camera*)G.scene->camera->data;
617         if (cam) {
618         if (((cam->flag) & 48)==48) {
619         m_canvas->SetBannerDisplayEnabled(false);
620         }
621         }
622         else {
623         showError(CString("Camera data invalid."));
624         return false;
625         }
626         */
627         
628         // create a scene converter, create and convert the stratingscene
629         m_sceneconverter = new KX_BlenderSceneConverter(m_maggie,0, m_ketsjiengine);
630         if (m_sceneconverter)
631         {
632                 STR_String startscenename = m_startSceneName.Ptr();
633                 m_ketsjiengine->SetSceneConverter(m_sceneconverter);
634                 
635                 //      if (always_use_expand_framing)
636                 //              sceneconverter->SetAlwaysUseExpandFraming(true);
637                 if(m_blendermat)
638                         m_sceneconverter->SetMaterials(true);
639
640                 KX_Scene* startscene = new KX_Scene(m_keyboard,
641                         m_mouse,
642                         m_networkdevice,
643                         m_audiodevice,
644                         startscenename);
645                 
646                 
647                 // some python things
648                 PyObject* dictionaryobject = initGamePythonScripting("Ketsji", psl_Lowest);
649                 m_ketsjiengine->SetPythonDictionary(dictionaryobject);
650                 initRasterizer(m_rasterizer, m_canvas);
651                 PyObject *gameLogic = initGameLogic(startscene);
652                 initGameKeys();
653                 initPythonConstraintBinding();
654
655
656
657
658
659                 m_sceneconverter->ConvertScene(
660                         startscenename,
661                         startscene,
662                         dictionaryobject,
663                         m_keyboard,
664                         m_rendertools,
665                         m_canvas);
666                 m_ketsjiengine->AddScene(startscene);
667                 
668                 // Create a timer that is used to kick the engine
669                 if (!m_frameTimer) {
670                         m_frameTimer = m_system->installTimer(0, kTimerFreq, frameTimerProc, m_mainWindow);
671                 }
672                 m_rasterizer->Init();
673                 m_ketsjiengine->StartEngine();
674                 m_engineRunning = true;
675                 
676         }
677         
678         if (!m_engineRunning)
679         {
680                 stopEngine();
681         }
682         
683         return m_engineRunning;
684 }
685
686
687 void GPG_Application::stopEngine()
688 {
689         // when exiting the mainloop
690         exitGamePythonScripting();
691         m_ketsjiengine->StopEngine();
692         m_networkdevice->Disconnect();
693
694         if (m_sceneconverter) {
695                 delete m_sceneconverter;
696                 m_sceneconverter = 0;
697         }
698         if (m_system && m_frameTimer) {
699                 m_system->removeTimer(m_frameTimer);
700                 m_frameTimer = 0;
701         }
702         m_engineRunning = false;
703 }
704
705
706 void GPG_Application::exitEngine()
707 {
708         if (m_ketsjiengine)
709         {
710                 stopEngine();
711                 delete m_ketsjiengine;
712                 m_ketsjiengine = 0;
713         }
714         if (m_kxsystem)
715         {
716                 delete m_kxsystem;
717                 m_kxsystem = 0;
718         }
719         if (m_audiodevice)
720         {
721                 SND_DeviceManager::Unsubscribe();
722                 m_audiodevice = 0;
723         }
724         if (m_networkdevice)
725         {
726                 delete m_networkdevice;
727                 m_networkdevice = 0;
728         }
729         if (m_mouse)
730         {
731                 delete m_mouse;
732                 m_mouse = 0;
733         }
734         if (m_keyboard)
735         {
736                 delete m_keyboard;
737                 m_keyboard = 0;
738         }
739         if (m_rasterizer)
740         {
741                 delete m_rasterizer;
742                 m_rasterizer = 0;
743         }
744         if (m_rendertools)
745         {
746                 delete m_rendertools;
747                 m_rendertools = 0;
748         }
749         if (m_canvas)
750         {
751                 delete m_canvas;
752                 m_canvas = 0;
753         }
754
755         m_exitRequested = 0;
756         m_engineInitialized = false;
757 }
758
759 bool GPG_Application::handleWheel(GHOST_IEvent* event)
760 {
761         bool handled = false;
762         MT_assert(event);
763         if (m_mouse) 
764         {
765                 GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
766                 GHOST_TEventWheelData* wheelData = static_cast<GHOST_TEventWheelData*>(eventData);
767                 GPC_MouseDevice::TButtonId button;
768                 if (wheelData->z > 0)
769                         button = GPC_MouseDevice::buttonWheelUp;
770                 else
771                         button = GPC_MouseDevice::buttonWheelDown;
772                 m_mouse->ConvertButtonEvent(button, true);
773                 handled = true;
774         }
775         return handled;
776 }
777
778 bool GPG_Application::handleButton(GHOST_IEvent* event, bool isDown)
779 {
780         bool handled = false;
781         MT_assert(event);
782         if (m_mouse) 
783         {
784                 GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
785                 GHOST_TEventButtonData* buttonData = static_cast<GHOST_TEventButtonData*>(eventData);
786                 GPC_MouseDevice::TButtonId button;
787                 switch (buttonData->button)
788                 {
789                 case GHOST_kButtonMaskMiddle:
790                         button = GPC_MouseDevice::buttonMiddle;
791                         break;
792                 case GHOST_kButtonMaskRight:
793                         button = GPC_MouseDevice::buttonRight;
794                         break;
795                 case GHOST_kButtonMaskLeft:
796                 default:
797                         button = GPC_MouseDevice::buttonLeft;
798                         break;
799                 }
800                 m_mouse->ConvertButtonEvent(button, isDown);
801                 handled = true;
802         }
803         return handled;
804 }
805
806
807 bool GPG_Application::handleCursorMove(GHOST_IEvent* event)
808 {
809         bool handled = false;
810         MT_assert(event);
811         if (m_mouse && m_mainWindow)
812         {
813                 GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
814                 GHOST_TEventCursorData* cursorData = static_cast<GHOST_TEventCursorData*>(eventData);
815                 GHOST_TInt32 x, y;
816                 m_mainWindow->screenToClient(cursorData->x, cursorData->y, x, y);
817                 m_mouse->ConvertMoveEvent(x, y);
818                 handled = true;
819         }
820         return handled;
821 }
822
823
824 bool GPG_Application::handleKey(GHOST_IEvent* event, bool isDown)
825 {
826         bool handled = false;
827         MT_assert(event);
828         if (m_keyboard)
829         {
830                 GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
831                 GHOST_TEventKeyData* keyData = static_cast<GHOST_TEventKeyData*>(eventData);
832                 if (fSystem->getFullScreen()) {
833                         if (keyData->key == GHOST_kKeyEsc) {
834                                 m_exitRequested = KX_EXIT_REQUEST_OUTSIDE;
835                         }
836                 }
837                 m_keyboard->ConvertEvent(keyData->key, isDown);
838                 handled = true;
839         }
840         return handled;
841 }
842
843
844
845 static void frameTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time)
846 {
847         GHOST_IWindow* window = (GHOST_IWindow*)task->getUserData();
848         if (fSystem->validWindow(window)) {
849                 window->invalidate();
850         }
851 }