Big patches:
[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 #include <OpenGL/gl.h>
45 #include <OpenGL/glu.h>
46 #else
47 #include <GL/gl.h>
48 #include <GL/glu.h>
49 #endif
50
51 #include "GPG_Application.h"
52
53 #include <iostream>
54 #include <MT_assert.h>
55
56 /**********************************
57  * Begin Blender include block
58  **********************************/
59 #ifdef __cplusplus
60 extern "C"
61 {
62 #endif  // __cplusplus
63 #include "BLI_blenlib.h"
64 #include "BLO_readfile.h"
65 #ifdef __cplusplus
66 }
67 #endif // __cplusplus
68 /**********************************
69  * End Blender include block
70  **********************************/
71
72
73 #include "SYS_System.h"
74 #include "KX_KetsjiEngine.h"
75
76 // include files needed by "KX_BlenderSceneConverter.h"
77 #include "GEN_Map.h"
78 #include "SCA_IActuator.h"
79 #include "RAS_MeshObject.h"
80 #include "RAS_OpenGLRasterizer.h"
81 #include "RAS_VAOpenGLRasterizer.h"
82 #include "RAS_GLExtensionManager.h"
83 #include "KX_PythonInit.h"
84 #include "KX_PyConstraintBinding.h"
85
86 #include "KX_BlenderSceneConverter.h"
87 #include "NG_LoopBackNetworkDeviceInterface.h"
88 #include "SND_DeviceManager.h"
89
90 #include "GPC_MouseDevice.h"
91 #include "GPC_RenderTools.h"
92 #include "GPG_Canvas.h" 
93 #include "GPG_KeyboardDevice.h"
94 #include "GPG_System.h"
95
96 #include "STR_String.h"
97
98 #include "GHOST_ISystem.h"
99 #include "GHOST_IEvent.h"
100 #include "GHOST_IEventConsumer.h"
101 #include "GHOST_IWindow.h"
102 #include "GHOST_Rect.h"
103
104
105 static void frameTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time);
106
107 static GHOST_ISystem* fSystem = 0;
108 static const int kTimerFreq = 10;
109
110 GPG_Application::GPG_Application(GHOST_ISystem* system, struct Main *maggie, STR_String startSceneName)
111         : m_startSceneName(startSceneName), 
112           m_maggie(maggie), 
113           m_exitRequested(0),
114           m_system(system), 
115           m_mainWindow(0), 
116           m_frameTimer(0), 
117           m_cursor(GHOST_kStandardCursorFirstCursor),
118           m_engineInitialized(0), 
119           m_engineRunning(0), 
120           m_ketsjiengine(0),
121           m_kxsystem(0), 
122           m_keyboard(0), 
123           m_mouse(0), 
124           m_canvas(0), 
125           m_rendertools(0), 
126           m_rasterizer(0), 
127           m_sceneconverter(0),
128           m_networkdevice(0), 
129           m_audiodevice(0)
130 {
131         fSystem = system;
132 }
133
134
135
136 GPG_Application::~GPG_Application(void)
137 {
138         exitEngine();
139         fSystem->disposeWindow(m_mainWindow);
140 }
141
142
143
144 bool GPG_Application::SetGameEngineData(struct Main *maggie, STR_String startSceneName)
145 {
146         bool result = false;
147
148         if (maggie != NULL && startSceneName != "")
149         {
150                 m_maggie = maggie;
151                 m_startSceneName = startSceneName;
152                 result = true;
153         }
154
155         return result;
156 }
157
158
159 #ifdef WIN32
160 #define SCR_SAVE_MOUSE_MOVE_THRESHOLD 15
161
162 static HWND found_ghost_window_hwnd;
163 static GHOST_IWindow* ghost_window_to_find;
164 static WNDPROC ghost_wnd_proc;
165 static POINT scr_save_mouse_pos;
166
167 static LRESULT CALLBACK screenSaverWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
168 {
169         BOOL close = FALSE;
170         switch (uMsg)
171         {
172                 case WM_MOUSEMOVE:
173                 { 
174                         POINT pt; 
175                         GetCursorPos(&pt);
176                         LONG dx = scr_save_mouse_pos.x - pt.x;
177                         LONG dy = scr_save_mouse_pos.y - pt.y;
178                         if (abs(dx) > SCR_SAVE_MOUSE_MOVE_THRESHOLD
179                             || abs(dy) > SCR_SAVE_MOUSE_MOVE_THRESHOLD)
180                         {
181                                 close = TRUE;
182                         }
183                         scr_save_mouse_pos = pt;
184                         break;
185                 }
186                 case WM_LBUTTONDOWN: 
187                 case WM_MBUTTONDOWN: 
188                 case WM_RBUTTONDOWN: 
189                 case WM_KEYDOWN:
190                         close = TRUE;
191         }
192         if (close)
193                 PostMessage(hwnd,WM_CLOSE,0,0);
194         return CallWindowProc(ghost_wnd_proc, hwnd, uMsg, wParam, lParam);
195 }
196
197 BOOL CALLBACK findGhostWindowHWNDProc(HWND hwnd, LPARAM lParam)
198 {
199         GHOST_IWindow *p = (GHOST_IWindow*) GetWindowLong(hwnd, GWL_USERDATA);
200         BOOL ret = TRUE;
201         if (p == ghost_window_to_find)
202         {
203                 found_ghost_window_hwnd = hwnd;
204                 ret = FALSE;
205         }
206         return ret;
207 }
208
209 static HWND findGhostWindowHWND(GHOST_IWindow* window)
210 {
211         found_ghost_window_hwnd = NULL;
212         ghost_window_to_find = window;
213         EnumWindows(findGhostWindowHWNDProc, NULL);
214         return found_ghost_window_hwnd;
215 }
216
217 bool GPG_Application::startScreenSaverPreview(
218         HWND parentWindow,
219         const bool stereoVisual,
220         const int stereoMode)
221 {
222         bool success = false;
223
224         RECT rc;
225         if (GetWindowRect(parentWindow, &rc))
226         {
227                 int windowWidth = rc.right - rc.left;
228                 int windowHeight = rc.bottom - rc.top;
229                 STR_String title = "";
230                                                         
231                 m_mainWindow = fSystem->createWindow(title, 0, 0, windowWidth, windowHeight, GHOST_kWindowStateMinimized,
232                         GHOST_kDrawingContextTypeOpenGL, stereoVisual);
233                 if (!m_mainWindow) {
234                         printf("error: could not create main window\n");
235                         exit(-1);
236                 }
237
238                 HWND ghost_hwnd = findGhostWindowHWND(m_mainWindow);
239                 if (!ghost_hwnd) {
240                         printf("error: could find main window\n");
241                         exit(-1);
242                 }
243
244                 SetParent(ghost_hwnd, parentWindow);
245                 LONG style = GetWindowLong(ghost_hwnd, GWL_STYLE);
246                 LONG exstyle = GetWindowLong(ghost_hwnd, GWL_EXSTYLE);
247
248                 RECT adjrc = { 0, 0, windowWidth, windowHeight };
249                 AdjustWindowRectEx(&adjrc, style, FALSE, exstyle);
250
251                 style = (style & (~(WS_POPUP|WS_OVERLAPPEDWINDOW|WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_TILEDWINDOW ))) | WS_CHILD;
252                 SetWindowLong(ghost_hwnd, GWL_STYLE, style);
253                 SetWindowPos(ghost_hwnd, NULL, adjrc.left, adjrc.top, 0, 0, SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE);
254
255                 /* Check the size of the client rectangle of the window and resize the window
256                  * so that the client rectangle has the size requested.
257                  */
258                 m_mainWindow->setClientSize(windowWidth, windowHeight);
259
260                 success = initEngine(m_mainWindow, stereoMode);
261                 if (success) {
262                         success = startEngine();
263                 }
264
265         }
266         return success;
267 }
268
269 bool GPG_Application::startScreenSaverFullScreen(
270                 int width,
271                 int height,
272                 int bpp,int frequency,
273                 const bool stereoVisual,
274                 const int stereoMode)
275 {
276         bool ret = startFullScreen(width, height, bpp, frequency, stereoVisual, stereoMode);
277         if (ret)
278         {
279                 HWND ghost_hwnd = findGhostWindowHWND(m_mainWindow);
280                 if (ghost_hwnd != NULL)
281                 {
282                         GetCursorPos(&scr_save_mouse_pos);
283                         ghost_wnd_proc = (WNDPROC) GetWindowLong(ghost_hwnd, GWL_WNDPROC);
284                         SetWindowLong(ghost_hwnd,GWL_WNDPROC, (LONG) screenSaverWindowProc);
285                 }
286         }
287         return ret;
288 }
289
290 #endif
291
292 bool GPG_Application::startWindow(STR_String& title,
293         int windowLeft,
294         int windowTop,
295         int windowWidth,
296         int windowHeight,
297         const bool stereoVisual,
298         const int stereoMode)
299 {
300         bool success;
301         // Create the main window
302         //STR_String title ("Blender Player - GHOST");
303         m_mainWindow = fSystem->createWindow(title, windowLeft, windowTop, windowWidth, windowHeight, GHOST_kWindowStateNormal,
304                 GHOST_kDrawingContextTypeOpenGL, stereoVisual);
305         if (!m_mainWindow) {
306                 printf("error: could not create main window\n");
307                 exit(-1);
308         }
309
310         /* Check the size of the client rectangle of the window and resize the window
311          * so that the client rectangle has the size requested.
312          */
313         m_mainWindow->setClientSize(windowWidth, windowHeight);
314         m_mainWindow->setCursorVisibility(false);
315
316         success = initEngine(m_mainWindow, stereoMode);
317         if (success) {
318                 success = startEngine();
319         }
320         return success;
321 }
322
323
324
325 bool GPG_Application::startFullScreen(
326                 int width,
327                 int height,
328                 int bpp,int frequency,
329                 const bool stereoVisual,
330                 const int stereoMode)
331 {
332         bool success;
333         // Create the main window
334         GHOST_DisplaySetting setting;
335         setting.xPixels = width;
336         setting.yPixels = height;
337         setting.bpp = bpp;
338         setting.frequency = frequency;
339
340         fSystem->beginFullScreen(setting, &m_mainWindow, stereoVisual);
341         m_mainWindow->setCursorVisibility(false);
342
343         success = initEngine(m_mainWindow, stereoMode);
344         if (success) {
345                 success = startEngine();
346         }
347         return success;
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                                         m_ketsjiengine->NextFrame();
431                                         
432                                         // render the frame
433                                         m_ketsjiengine->Render();
434                                 }
435                                 m_exitString = m_ketsjiengine->GetExitString();
436                         }
437                         break;
438                 
439                 case GHOST_kEventWindowSize:
440                         {
441                         GHOST_IWindow* window = event->getWindow();
442                         if (!m_system->validWindow(window)) break;
443                         if (m_canvas) {
444                                 GHOST_Rect bnds;
445                                 window->getClientBounds(bnds);
446                                 m_canvas->Resize(bnds.getWidth(), bnds.getHeight());
447                         }
448                         }
449                         break;
450                 
451                 default:
452                         handled = false;
453                         break;
454         }
455         return handled;
456 }
457
458
459
460 int GPG_Application::getExitRequested(void)
461 {
462         return m_exitRequested;
463 }
464
465
466
467 const STR_String& GPG_Application::getExitString(void)
468 {
469         return m_exitString;
470 }
471
472
473
474 bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
475 {
476         if (!m_engineInitialized)
477         {
478                 bgl::InitExtensions(1);
479
480                 // get and set the preferences
481                 SYS_SystemHandle syshandle = SYS_GetSystem();
482                 if (!syshandle)
483                         return false;
484                 
485                 // SYS_WriteCommandLineInt(syshandle, "fixedtime", 0);
486                 // SYS_WriteCommandLineInt(syshandle, "vertexarrays",1);                
487                 bool properties = (SYS_GetCommandLineInt(syshandle, "show_properties", 0) != 0);
488                 bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0);
489                 bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
490                 bool useVertexArrays = SYS_GetCommandLineInt(syshandle,"vertexarrays",1) != 0;
491                 // create the canvas, rasterizer and rendertools
492                 m_canvas = new GPG_Canvas(window);
493                 if (!m_canvas)
494                         return false;
495                                 
496                 m_canvas->Init();                               
497                 m_rendertools = new GPC_RenderTools();
498                 if (!m_rendertools)
499                         goto initFailed;
500                                         
501                 if (useVertexArrays && bgl::QueryVersion(1, 1))
502                         m_rasterizer = new RAS_VAOpenGLRasterizer(m_canvas);
503                 else
504                         m_rasterizer = new RAS_OpenGLRasterizer(m_canvas);
505                 m_rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) stereoMode);
506                 if (!m_rasterizer)
507                         goto initFailed;
508                                                 
509                 // create the inputdevices
510                 m_keyboard = new GPG_KeyboardDevice();
511                 if (!m_keyboard)
512                         goto initFailed;
513                         
514                 m_mouse = new GPC_MouseDevice();
515                 if (!m_mouse)
516                         goto initFailed;
517                         
518                 // create a networkdevice
519                 m_networkdevice = new NG_LoopBackNetworkDeviceInterface();
520                 if (!m_networkdevice)
521                         goto initFailed;
522                         
523                 // get an audiodevice
524                 SND_DeviceManager::Subscribe();
525                 m_audiodevice = SND_DeviceManager::Instance();
526                 if (!m_audiodevice)
527                         goto initFailed;
528                 m_audiodevice->UseCD();
529                 
530                 // create a ketsjisystem (only needed for timing and stuff)
531                 m_kxsystem = new GPG_System (m_system);
532                 if (!m_kxsystem)
533                         goto initFailed;
534                 
535                 // create the ketsjiengine
536                 m_ketsjiengine = new KX_KetsjiEngine(m_kxsystem);
537                 
538                 // set the devices
539                 m_ketsjiengine->SetKeyboardDevice(m_keyboard);
540                 m_ketsjiengine->SetMouseDevice(m_mouse);
541                 m_ketsjiengine->SetNetworkDevice(m_networkdevice);
542                 m_ketsjiengine->SetCanvas(m_canvas);
543                 m_ketsjiengine->SetRenderTools(m_rendertools);
544                 m_ketsjiengine->SetRasterizer(m_rasterizer);
545                 m_ketsjiengine->SetNetworkDevice(m_networkdevice);
546                 m_ketsjiengine->SetAudioDevice(m_audiodevice);
547                 m_ketsjiengine->SetTimingDisplay(frameRate, false, false);
548
549                 m_ketsjiengine->SetUseFixedTime(false);
550                 m_ketsjiengine->SetTimingDisplay(frameRate, profile, properties);
551
552                 m_engineInitialized = true;
553         }
554
555         return m_engineInitialized;
556 initFailed:
557         delete m_kxsystem;
558         delete m_audiodevice;
559         delete m_networkdevice;
560         delete m_mouse;
561         delete m_keyboard;
562         delete m_rasterizer;
563         delete m_rendertools;
564         delete m_canvas;
565         m_canvas = NULL;
566         m_rendertools = NULL;
567         m_rasterizer = NULL;
568         m_keyboard = NULL;
569         m_mouse = NULL;
570         m_networkdevice = NULL;
571         m_audiodevice = NULL;
572         m_kxsystem = NULL;
573         return false;
574 }
575
576
577
578 bool GPG_Application::startEngine(void)
579 {
580         if (m_engineRunning) {
581                 return false;
582         }
583         
584         // Temporary hack to disable banner display for NaN approved content.
585         /*
586         m_canvas->SetBannerDisplayEnabled(true);        
587         Camera* cam;
588         cam = (Camera*)G.scene->camera->data;
589         if (cam) {
590         if (((cam->flag) & 48)==48) {
591         m_canvas->SetBannerDisplayEnabled(false);
592         }
593         }
594         else {
595         showError(CString("Camera data invalid."));
596         return false;
597         }
598         */
599         
600         // create a scene converter, create and convert the stratingscene
601         m_sceneconverter = new KX_BlenderSceneConverter(m_maggie, m_ketsjiengine);
602         if (m_sceneconverter)
603         {
604                 STR_String startscenename = m_startSceneName.Ptr();
605                 m_ketsjiengine->SetSceneConverter(m_sceneconverter);
606                 
607                 //      if (always_use_expand_framing)
608                 //              sceneconverter->SetAlwaysUseExpandFraming(true);
609                 
610
611                 KX_Scene* startscene = new KX_Scene(m_keyboard,
612                         m_mouse,
613                         m_networkdevice,
614                         m_audiodevice,
615                         startscenename);
616                 
617                 // some python things
618                 PyObject* m_dictionaryobject = initGamePlayerPythonScripting("Ketsji", psl_Lowest);
619                 m_ketsjiengine->SetPythonDictionary(m_dictionaryobject);
620                 initRasterizer(m_rasterizer, m_canvas);
621                 initGameLogic(startscene);
622                 initGameKeys();
623                 initPythonConstraintBinding();
624                 
625                 m_sceneconverter->ConvertScene(
626                         startscenename,
627                         startscene,
628                         m_dictionaryobject,
629                         m_keyboard,
630                         m_rendertools,
631                         m_canvas);
632                 m_ketsjiengine->AddScene(startscene);
633                 
634                 // Create a timer that is used to kick the engine
635                 if (!m_frameTimer) {
636                         m_frameTimer = m_system->installTimer(0, kTimerFreq, frameTimerProc, m_mainWindow);
637                 }
638                 m_rasterizer->Init();
639                 m_ketsjiengine->StartEngine();
640                 m_engineRunning = true;
641                 
642         }
643         
644         if (!m_engineRunning)
645         {
646                 stopEngine();
647         }
648         
649         return m_engineRunning;
650 }
651
652
653 void GPG_Application::stopEngine()
654 {
655         // when exiting the mainloop
656         exitGamePythonScripting();
657         m_ketsjiengine->StopEngine();
658         m_networkdevice->Disconnect();
659
660         if (m_sceneconverter) {
661                 delete m_sceneconverter;
662                 m_sceneconverter = 0;
663         }
664         if (m_system && m_frameTimer) {
665                 m_system->removeTimer(m_frameTimer);
666                 m_frameTimer = 0;
667         }
668         m_engineRunning = false;
669 }
670
671
672 void GPG_Application::exitEngine()
673 {
674         if (m_ketsjiengine)
675         {
676                 stopEngine();
677                 delete m_ketsjiengine;
678                 m_ketsjiengine = 0;
679         }
680         if (m_kxsystem)
681         {
682                 delete m_kxsystem;
683                 m_kxsystem = 0;
684         }
685         if (m_audiodevice)
686         {
687                 SND_DeviceManager::Unsubscribe();
688                 m_audiodevice = 0;
689         }
690         if (m_networkdevice)
691         {
692                 delete m_networkdevice;
693                 m_networkdevice = 0;
694         }
695         if (m_mouse)
696         {
697                 delete m_mouse;
698                 m_mouse = 0;
699         }
700         if (m_keyboard)
701         {
702                 delete m_keyboard;
703                 m_keyboard = 0;
704         }
705         if (m_rasterizer)
706         {
707                 delete m_rasterizer;
708                 m_rasterizer = 0;
709         }
710         if (m_rendertools)
711         {
712                 delete m_rendertools;
713                 m_rendertools = 0;
714         }
715         if (m_canvas)
716         {
717                 delete m_canvas;
718                 m_canvas = 0;
719         }
720
721         m_exitRequested = 0;
722         m_engineInitialized = false;
723 }
724
725 bool GPG_Application::handleWheel(GHOST_IEvent* event)
726 {
727         bool handled = false;
728         MT_assert(event);
729         if (m_mouse) 
730         {
731                 GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
732                 GHOST_TEventWheelData* wheelData = static_cast<GHOST_TEventWheelData*>(eventData);
733                 GPC_MouseDevice::TButtonId button;
734                 if (wheelData->z > 0)
735                         button = GPC_MouseDevice::buttonWheelUp;
736                 else
737                         button = GPC_MouseDevice::buttonWheelDown;
738                 m_mouse->ConvertButtonEvent(button, true);
739                 handled = true;
740         }
741         return handled;
742 }
743
744 bool GPG_Application::handleButton(GHOST_IEvent* event, bool isDown)
745 {
746         bool handled = false;
747         MT_assert(event);
748         if (m_mouse) 
749         {
750                 GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
751                 GHOST_TEventButtonData* buttonData = static_cast<GHOST_TEventButtonData*>(eventData);
752                 GPC_MouseDevice::TButtonId button;
753                 switch (buttonData->button)
754                 {
755                 case GHOST_kButtonMaskMiddle:
756                         button = GPC_MouseDevice::buttonMiddle;
757                         break;
758                 case GHOST_kButtonMaskRight:
759                         button = GPC_MouseDevice::buttonRight;
760                         break;
761                 case GHOST_kButtonMaskLeft:
762                 default:
763                         button = GPC_MouseDevice::buttonLeft;
764                         break;
765                 }
766                 m_mouse->ConvertButtonEvent(button, isDown);
767                 handled = true;
768         }
769         return handled;
770 }
771
772
773 bool GPG_Application::handleCursorMove(GHOST_IEvent* event)
774 {
775         bool handled = false;
776         MT_assert(event);
777         if (m_mouse && m_mainWindow)
778         {
779                 GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
780                 GHOST_TEventCursorData* cursorData = static_cast<GHOST_TEventCursorData*>(eventData);
781                 GHOST_TInt32 x, y;
782                 m_mainWindow->screenToClient(cursorData->x, cursorData->y, x, y);
783                 m_mouse->ConvertMoveEvent(x, y);
784                 handled = true;
785         }
786         return handled;
787 }
788
789
790 bool GPG_Application::handleKey(GHOST_IEvent* event, bool isDown)
791 {
792         bool handled = false;
793         MT_assert(event);
794         if (m_keyboard)
795         {
796                 GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
797                 GHOST_TEventKeyData* keyData = static_cast<GHOST_TEventKeyData*>(eventData);
798                 if (fSystem->getFullScreen()) {
799                         if (keyData->key == GHOST_kKeyEsc) {
800                                 m_exitRequested = KX_EXIT_REQUEST_OUTSIDE;
801                         }
802                 }
803                 m_keyboard->ConvertEvent(keyData->key, isDown);
804                 handled = true;
805         }
806         return handled;
807 }
808
809
810
811 static void frameTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time)
812 {
813         GHOST_IWindow* window = (GHOST_IWindow*)task->getUserData();
814         if (fSystem->validWindow(window)) {
815                 window->invalidate();
816         }
817 }