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