Merging r57518 through r57545 from trunk into soc-20133-depsgraph_mt
[blender-staging.git] / source / gameengine / Ketsji / KX_KetsjiEngine.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  * The engine ties all game modules together. 
27  */
28
29 /** \file gameengine/Ketsji/KX_KetsjiEngine.cpp
30  *  \ingroup ketsji
31  */
32
33 #ifdef _MSC_VER
34 #  pragma warning (disable:4786)
35 #endif
36
37 #include <iostream>
38 #include <stdio.h>
39
40 #include "KX_KetsjiEngine.h"
41
42 #include "ListValue.h"
43 #include "IntValue.h"
44 #include "VectorValue.h"
45 #include "BoolValue.h"
46 #include "FloatValue.h"
47
48 #include "RAS_BucketManager.h"
49 #include "RAS_Rect.h"
50 #include "RAS_IRasterizer.h"
51 #include "RAS_IRenderTools.h"
52 #include "RAS_ICanvas.h"
53 #include "MT_Vector3.h"
54 #include "MT_Transform.h"
55 #include "SCA_IInputDevice.h"
56 #include "KX_Camera.h"
57 #include "KX_FontObject.h"
58 #include "KX_Dome.h"
59 #include "KX_Light.h"
60 #include "KX_PythonInit.h"
61 #include "KX_PyConstraintBinding.h"
62 #include "PHY_IPhysicsEnvironment.h"
63
64 #ifdef WITH_AUDASPACE
65 #  include "AUD_C-API.h"
66 #  include "AUD_I3DDevice.h"
67 #endif
68
69 #include "NG_NetworkScene.h"
70 #include "NG_NetworkDeviceInterface.h"
71
72 #include "KX_WorldInfo.h"
73 #include "KX_ISceneConverter.h"
74 #include "KX_TimeCategoryLogger.h"
75
76 #include "RAS_FramingManager.h"
77 #include "DNA_world_types.h"
78 #include "DNA_scene_types.h"
79
80 #include "KX_NavMeshObject.h"
81
82 // If define: little test for Nzc: guarded drawing. If the canvas is
83 // not valid, skip rendering this frame.
84 //#define NZC_GUARDED_OUTPUT
85 #define DEFAULT_LOGIC_TIC_RATE 60.0
86 //#define DEFAULT_PHYSICS_TIC_RATE 60.0
87
88 #ifdef FREE_WINDOWS /* XXX mingw64 (gcc 4.7.0) defines a macro for DrawText that translates to DrawTextA. Not good */
89 #ifdef DrawText
90 #undef DrawText
91 #endif
92 #endif
93
94 const char KX_KetsjiEngine::m_profileLabels[tc_numCategories][15] = {
95         "Physics:",             // tc_physics
96         "Logic:",               // tc_logic
97         "Animations:",  // tc_animations
98         "Network:",             // tc_network
99         "Scenegraph:",  // tc_scenegraph
100         "Rasterizer:",  // tc_rasterizer
101         "Services:",    // tc_services
102         "Overhead:",    // tc_overhead
103         "Outside:"              // tc_outside
104 };
105
106 double KX_KetsjiEngine::m_ticrate = DEFAULT_LOGIC_TIC_RATE;
107 int        KX_KetsjiEngine::m_maxLogicFrame = 5;
108 int        KX_KetsjiEngine::m_maxPhysicsFrame = 5;
109 double KX_KetsjiEngine::m_anim_framerate = 25.0;
110 double KX_KetsjiEngine::m_suspendedtime = 0.0;
111 double KX_KetsjiEngine::m_suspendeddelta = 0.0;
112 double KX_KetsjiEngine::m_average_framerate = 0.0;
113 bool   KX_KetsjiEngine::m_restrict_anim_fps = false;
114 short  KX_KetsjiEngine::m_exitkey = 130; //ESC Key
115
116
117 /**
118  *      Constructor of the Ketsji Engine
119  */
120 KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
121         :       m_canvas(NULL),
122         m_rasterizer(NULL),
123         m_kxsystem(system),
124         m_rendertools(NULL),
125         m_sceneconverter(NULL),
126         m_networkdevice(NULL),
127 #ifdef WITH_PYTHON
128         m_pythondictionary(NULL),
129 #endif
130         m_keyboarddevice(NULL),
131         m_mousedevice(NULL),
132
133         m_propertiesPresent(false),
134
135         m_bInitialized(false),
136         m_activecam(0),
137         m_bFixedTime(false),
138         
139         m_firstframe(true),
140         
141         m_frameTime(0.f),
142         m_clockTime(0.f),
143         m_previousClockTime(0.f),
144         m_previousAnimTime(0.f),
145
146
147         m_exitcode(KX_EXIT_REQUEST_NO_REQUEST),
148         m_exitstring(""),
149         
150         m_drawingmode(5),
151         m_cameraZoom(1.0),
152         
153         m_overrideCam(false),
154         m_overrideCamUseOrtho(false),
155         m_overrideCamNear(0.0),
156         m_overrideCamFar(0.0),
157
158         m_stereo(false),
159         m_curreye(0),
160
161         m_logger(NULL),
162         
163         // Set up timing info display variables
164         m_show_framerate(false),
165         m_show_profile(false),
166         m_showProperties(false),
167         m_showBackground(false),
168         m_show_debug_properties(false),
169
170         m_animation_record(false),
171
172         // Default behavior is to hide the cursor every frame.
173         m_hideCursor(false),
174
175         m_overrideFrameColor(false),
176         m_overrideFrameColorR(0.0),
177         m_overrideFrameColorG(0.0),
178         m_overrideFrameColorB(0.0),
179
180         m_usedome(false)
181 {
182         // Initialize the time logger
183         m_logger = new KX_TimeCategoryLogger (25);
184
185         for (int i = tc_first; i < tc_numCategories; i++)
186                 m_logger->AddCategory((KX_TimeCategory)i);
187
188 #ifdef WITH_PYTHON
189         m_pyprofiledict = PyDict_New();
190 #endif
191 }
192
193
194
195 /**
196  *      Destructor of the Ketsji Engine, release all memory
197  */
198 KX_KetsjiEngine::~KX_KetsjiEngine()
199 {
200         delete m_logger;
201         if (m_usedome)
202                 delete m_dome;
203
204 #ifdef WITH_PYTHON
205         Py_CLEAR(m_pyprofiledict);
206 #endif
207 }
208
209
210
211 void KX_KetsjiEngine::SetKeyboardDevice(SCA_IInputDevice* keyboarddevice)
212 {
213         MT_assert(keyboarddevice);
214         m_keyboarddevice = keyboarddevice;
215 }
216
217
218
219 void KX_KetsjiEngine::SetMouseDevice(SCA_IInputDevice* mousedevice)
220 {
221         MT_assert(mousedevice);
222         m_mousedevice = mousedevice;
223 }
224
225
226
227 void KX_KetsjiEngine::SetNetworkDevice(NG_NetworkDeviceInterface* networkdevice)
228 {
229         MT_assert(networkdevice);
230         m_networkdevice = networkdevice;
231 }
232
233
234 void KX_KetsjiEngine::SetCanvas(RAS_ICanvas* canvas)
235 {
236         MT_assert(canvas);
237         m_canvas = canvas;
238 }
239
240
241
242 void KX_KetsjiEngine::SetRenderTools(RAS_IRenderTools* rendertools)
243 {
244         MT_assert(rendertools);
245         m_rendertools = rendertools;
246 }
247
248
249
250 void KX_KetsjiEngine::SetRasterizer(RAS_IRasterizer* rasterizer)
251 {
252         MT_assert(rasterizer);
253         m_rasterizer = rasterizer;
254 }
255
256 #ifdef WITH_PYTHON
257 /*
258  * At the moment the bge.logic module is imported into 'pythondictionary' after this function is called.
259  * if this function ever changes to assign a copy, make sure the game logic module is imported into this dictionary before hand.
260  */
261 void KX_KetsjiEngine::SetPyNamespace(PyObject *pythondictionary)
262 {
263         MT_assert(pythondictionary);
264         m_pythondictionary = pythondictionary;
265 }
266
267 PyObject* KX_KetsjiEngine::GetPyProfileDict()
268 {
269         Py_INCREF(m_pyprofiledict);
270         return m_pyprofiledict;
271 }
272 #endif
273
274
275 void KX_KetsjiEngine::SetSceneConverter(KX_ISceneConverter* sceneconverter)
276 {
277         MT_assert(sceneconverter);
278         m_sceneconverter = sceneconverter;
279 }
280
281 void KX_KetsjiEngine::InitDome(short res, short mode, short angle, float resbuf, short tilt, struct Text* text)
282 {
283         m_dome = new KX_Dome(m_canvas, m_rasterizer, m_rendertools,this, res, mode, angle, resbuf, tilt, text);
284         m_usedome = true;
285 }
286
287 void KX_KetsjiEngine::RenderDome()
288 {
289         const GLint *viewport = m_canvas->GetViewPort();
290         
291         m_dome->SetViewPort(viewport);
292
293         KX_Scene* firstscene = *m_scenes.begin();
294         const RAS_FrameSettings &framesettings = firstscene->GetFramingType();
295
296         m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
297
298         // hiding mouse cursor each frame
299         // (came back when going out of focus and then back in again)
300         if (m_hideCursor)
301                 m_canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
302
303         // clear the entire game screen with the border color
304         // only once per frame
305
306         m_canvas->BeginDraw();
307
308         // BeginFrame() sets the actual drawing area. You can use a part of the window
309         if (!BeginFrame())
310                 return;
311
312         KX_SceneList::iterator sceneit;
313         KX_Scene* scene = NULL;
314
315         int n_renders=m_dome->GetNumberRenders();// usually 4 or 6
316         for (int i=0;i<n_renders;i++) {
317                 m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER);
318                 for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++)
319                 // for each scene, call the proceed functions
320                 {
321                         scene = *sceneit;
322                         KX_Camera* cam = scene->GetActiveCamera();
323
324                         m_rendertools->BeginFrame(m_rasterizer);
325                         // pass the scene's worldsettings to the rasterizer
326                         SetWorldSettings(scene->GetWorldInfo());
327
328                         // shadow buffers
329                         if (i == 0) {
330                                 RenderShadowBuffers(scene);
331                         }
332                         // Avoid drawing the scene with the active camera twice when it's viewport is enabled
333                         if (cam && !cam->GetViewport())
334                         {
335                                 if (scene->IsClearingZBuffer())
336                                         m_rasterizer->ClearDepthBuffer();
337                 
338                                 m_rendertools->SetAuxilaryClientInfo(scene);
339                 
340                                 // do the rendering
341                                 m_dome->RenderDomeFrame(scene,cam, i);
342                                 //render all the font objects for this scene
343                                 RenderFonts(scene);
344                         }
345                         
346                         list<class KX_Camera*>* cameras = scene->GetCameras();
347                         
348                         // Draw the scene once for each camera with an enabled viewport
349                         list<KX_Camera*>::iterator it = cameras->begin();
350                         while (it != cameras->end()) {
351                                 if ((*it)->GetViewport())
352                                 {
353                                         if (scene->IsClearingZBuffer())
354                                                 m_rasterizer->ClearDepthBuffer();
355                         
356                                         m_rendertools->SetAuxilaryClientInfo(scene);
357                         
358                                         // do the rendering
359                                         m_dome->RenderDomeFrame(scene, (*it),i);
360                                         //render all the font objects for this scene
361                                         RenderFonts(scene);
362                                 }
363                                 
364                                 it++;
365                         }
366                         // Part of PostRenderScene()
367                         m_rendertools->MotionBlur(m_rasterizer);
368                         scene->Render2DFilters(m_canvas);
369                         // no RunDrawingCallBacks
370                         // no FlushDebugLines
371                 }
372                 m_dome->BindImages(i);
373         }
374
375         m_canvas->EndFrame();//XXX do we really need that?
376
377         m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight());
378
379         if (m_overrideFrameColor) //XXX why do we want
380         {
381                 // Do not use the framing bar color set in the Blender scenes
382                 m_canvas->ClearColor(
383                         m_overrideFrameColorR,
384                         m_overrideFrameColorG,
385                         m_overrideFrameColorB,
386                         1.0
387                         );
388         }
389         else
390         {
391                 // Use the framing bar color set in the Blender scenes
392                 m_canvas->ClearColor(
393                         framesettings.BarRed(),
394                         framesettings.BarGreen(),
395                         framesettings.BarBlue(),
396                         1.0
397                         );
398         }
399         m_dome->Draw();
400         // Draw Callback for the last scene
401 #ifdef WITH_PYTHON
402         scene->RunDrawingCallbacks(scene->GetPostDrawCB());
403 #endif
404         EndFrame();
405 }
406
407 /**
408  * Ketsji Init(), Initializes data-structures and converts data from
409  * Blender into Ketsji native (realtime) format also sets up the
410  * graphics context
411  */
412 void KX_KetsjiEngine::StartEngine(bool clearIpo)
413 {
414         m_clockTime = m_kxsystem->GetTimeInSeconds();
415         m_frameTime = m_kxsystem->GetTimeInSeconds();
416         m_previousClockTime = m_kxsystem->GetTimeInSeconds();
417
418         m_firstframe = true;
419         m_bInitialized = true;
420         // there is always one scene enabled at startup
421         Scene* scene = m_scenes[0]->GetBlenderScene();
422         if (scene)
423         {
424                 m_ticrate = scene->gm.ticrate ? scene->gm.ticrate : DEFAULT_LOGIC_TIC_RATE;
425                 m_maxLogicFrame = scene->gm.maxlogicstep ? scene->gm.maxlogicstep : 5;
426                 m_maxPhysicsFrame = scene->gm.maxphystep ? scene->gm.maxlogicstep : 5;
427         }
428         else
429         {
430                 m_ticrate = DEFAULT_LOGIC_TIC_RATE;
431                 m_maxLogicFrame = 5;
432                 m_maxPhysicsFrame = 5;
433         }
434         
435         if (m_animation_record)
436         {
437                 m_sceneconverter->ResetPhysicsObjectsAnimationIpo(clearIpo);
438                 m_sceneconverter->WritePhysicsObjectToAnimationIpo(m_currentFrame);
439         }
440
441 }
442
443 void KX_KetsjiEngine::ClearFrame()
444 {
445         // clear unless we're drawing overlapping stereo
446         if (m_rasterizer->InterlacedStereo() &&
447                 m_rasterizer->GetEye() == RAS_IRasterizer::RAS_STEREO_RIGHTEYE)
448                 return;
449
450         // clear the viewports with the background color of the first scene
451         bool doclear = false;
452         KX_SceneList::iterator sceneit;
453         RAS_Rect clearvp, area, viewport;
454
455         for (sceneit = m_scenes.begin(); sceneit != m_scenes.end(); sceneit++)
456         {
457                 KX_Scene* scene = *sceneit;
458                 //const RAS_FrameSettings &framesettings = scene->GetFramingType();
459                 list<class KX_Camera*>* cameras = scene->GetCameras();
460
461                 list<KX_Camera*>::iterator it;
462                 for (it = cameras->begin(); it != cameras->end(); it++)
463                 {
464                         GetSceneViewport(scene, (*it), area, viewport);
465
466                         if (!doclear) {
467                                 clearvp = viewport;
468                                 doclear = true;
469                         }
470                         else {
471                                 if (viewport.GetLeft() < clearvp.GetLeft())
472                                         clearvp.SetLeft(viewport.GetLeft());
473                                 if (viewport.GetBottom() < clearvp.GetBottom())
474                                         clearvp.SetBottom(viewport.GetBottom());
475                                 if (viewport.GetRight() > clearvp.GetRight())
476                                         clearvp.SetRight(viewport.GetRight());
477                                 if (viewport.GetTop() > clearvp.GetTop())
478                                         clearvp.SetTop(viewport.GetTop());
479
480                         }
481                 }
482         }
483
484         if (doclear) {
485                 KX_Scene* firstscene = *m_scenes.begin();
486                 SetBackGround(firstscene->GetWorldInfo());
487
488                 m_canvas->SetViewPort(clearvp.GetLeft(), clearvp.GetBottom(),
489                         clearvp.GetRight(), clearvp.GetTop());
490                 m_rasterizer->ClearColorBuffer();
491         }
492 }
493
494 bool KX_KetsjiEngine::BeginFrame()
495 {
496         // set the area used for rendering (stereo can assign only a subset)
497         m_rasterizer->SetRenderArea();
498
499         if (m_canvas->BeginDraw())
500         {
501                 ClearFrame();
502
503                 m_rasterizer->BeginFrame(m_drawingmode , m_kxsystem->GetTimeInSeconds());
504                 m_rendertools->BeginFrame(m_rasterizer);
505
506                 return true;
507         }
508         
509         return false;
510 }
511
512
513 void KX_KetsjiEngine::EndFrame()
514 {
515         m_rendertools->MotionBlur(m_rasterizer);
516
517         // Show profiling info
518         m_logger->StartLog(tc_overhead, m_kxsystem->GetTimeInSeconds(), true);
519         if (m_show_framerate || m_show_profile || (m_show_debug_properties && m_propertiesPresent))
520         {
521                 RenderDebugProperties();
522         }
523
524         double tottime = m_logger->GetAverage(), time;
525         if (tottime < 1e-6)
526                 tottime = 1e-6;
527
528 #ifdef WITH_PYTHON
529         for (int i = tc_first; i < tc_numCategories; ++i) {
530                 time = m_logger->GetAverage((KX_TimeCategory)i);
531                 PyObject *val = PyTuple_New(2);
532                 PyTuple_SetItem(val, 0, PyFloat_FromDouble(time*1000.f));
533                 PyTuple_SetItem(val, 1, PyFloat_FromDouble(time/tottime * 100.f));
534
535                 PyDict_SetItemString(m_pyprofiledict, m_profileLabels[i], val);
536                 Py_DECREF(val);
537         }
538 #endif
539
540         m_average_framerate = 1.0/tottime;
541
542         // Go to next profiling measurement, time spend after this call is shown in the next frame.
543         m_logger->NextMeasurement(m_kxsystem->GetTimeInSeconds());
544
545         m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
546         m_rasterizer->EndFrame();
547         // swap backbuffer (drawing into this buffer) <-> front/visible buffer
548         m_rasterizer->SwapBuffers();
549         m_rendertools->EndFrame(m_rasterizer);
550
551         
552         m_canvas->EndDraw();
553 }
554
555 //#include "PIL_time.h"
556 //#include "LinearMath/btQuickprof.h"
557
558
559 bool KX_KetsjiEngine::NextFrame()
560 {
561         double timestep = 1.0/m_ticrate;
562         double framestep = timestep;
563         //      static hidden::Clock sClock;
564
565         m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(),true);
566
567         //float dt = sClock.getTimeMicroseconds() * 0.000001f;
568         //sClock.reset();
569
570         if (m_bFixedTime) {
571                 m_clockTime += timestep;
572         }
573         else {
574                 // m_clockTime += dt;
575                 m_clockTime = m_kxsystem->GetTimeInSeconds();
576         }
577         
578         double deltatime = m_clockTime - m_frameTime;
579         if (deltatime<0.f)
580         {
581                 // We got here too quickly, which means there is nothing todo, just return and don't render.
582                 // Not sure if this is the best fix, but it seems to stop the jumping framerate issue (#33088)
583                 return false;
584         }
585
586
587         // Compute the number of logic frames to do each update (fixed tic bricks)
588         int frames =int(deltatime*m_ticrate+1e-6);
589 //      if (frames>1)
590 //              printf("****************************************");
591 //      printf("dt = %f, deltatime = %f, frames = %d\n",dt, deltatime,frames);
592         
593 //      if (!frames)
594 //              PIL_sleep_ms(1);
595         
596         KX_SceneList::iterator sceneit;
597         
598         if (frames>m_maxPhysicsFrame)
599         {
600         
601         //      printf("framedOut: %d\n",frames);
602                 m_frameTime+=(frames-m_maxPhysicsFrame)*timestep;
603                 frames = m_maxPhysicsFrame;
604         }
605         
606
607         bool doRender = frames>0;
608
609         if (frames > m_maxLogicFrame)
610         {
611                 framestep = (frames*timestep)/m_maxLogicFrame;
612                 frames = m_maxLogicFrame;
613         }
614
615         while (frames)
616         {
617         
618
619                 m_frameTime += framestep;
620                 
621                 m_sceneconverter->MergeAsyncLoads();
622
623                 for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
624                 // for each scene, call the proceed functions
625                 {
626                         KX_Scene* scene = *sceneit;
627         
628                         /* Suspension holds the physics and logic processing for an
629                          * entire scene. Objects can be suspended individually, and
630                          * the settings for that precede the logic and physics
631                          * update. */
632                         m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
633
634                         m_sceneconverter->resetNoneDynamicObjectToIpo();//this is for none dynamic objects with ipo
635
636                         scene->UpdateObjectActivity();
637         
638                         if (!scene->IsSuspended())
639                         {
640                                 // if the scene was suspended recalcutlate the delta tu "curtime"
641                                 m_suspendedtime = scene->getSuspendedTime();
642                                 if (scene->getSuspendedTime()!=0.0)
643                                         scene->setSuspendedDelta(scene->getSuspendedDelta()+m_clockTime-scene->getSuspendedTime());
644                                 m_suspendeddelta = scene->getSuspendedDelta();
645
646                                 
647                                 m_logger->StartLog(tc_network, m_kxsystem->GetTimeInSeconds(), true);
648                                 SG_SetActiveStage(SG_STAGE_NETWORK);
649                                 scene->GetNetworkScene()->proceed(m_frameTime);
650         
651                                 //m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
652                                 //SG_SetActiveStage(SG_STAGE_NETWORK_UPDATE);
653                                 //scene->UpdateParents(m_frameTime);
654                                 
655                                 m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
656                                 SG_SetActiveStage(SG_STAGE_PHYSICS1);
657                                 // set Python hooks for each scene
658 #ifdef WITH_PYTHON
659                                 PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
660 #endif
661                                 KX_SetActiveScene(scene);
662         
663                                 scene->GetPhysicsEnvironment()->endFrame();
664                                 
665                                 // Update scenegraph after physics step. This maps physics calculations
666                                 // into node positions.
667                                 //m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
668                                 //SG_SetActiveStage(SG_STAGE_PHYSICS1_UPDATE);
669                                 //scene->UpdateParents(m_frameTime);
670                                 
671                                 // Process sensors, and controllers
672                                 m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
673                                 SG_SetActiveStage(SG_STAGE_CONTROLLER);
674                                 scene->LogicBeginFrame(m_frameTime);
675         
676                                 // Scenegraph needs to be updated again, because Logic Controllers 
677                                 // can affect the local matrices.
678                                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
679                                 SG_SetActiveStage(SG_STAGE_CONTROLLER_UPDATE);
680                                 scene->UpdateParents(m_frameTime);
681         
682                                 // Process actuators
683         
684                                 // Do some cleanup work for this logic frame
685                                 m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
686                                 SG_SetActiveStage(SG_STAGE_ACTUATOR);
687                                 scene->LogicUpdateFrame(m_frameTime, true);
688                                 
689                                 scene->LogicEndFrame();
690         
691                                 // Actuators can affect the scenegraph
692                                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
693                                 SG_SetActiveStage(SG_STAGE_ACTUATOR_UPDATE);
694                                 scene->UpdateParents(m_frameTime);
695
696                                 if (!GetRestrictAnimationFPS())
697                                 {
698                                         m_logger->StartLog(tc_animations, m_kxsystem->GetTimeInSeconds(), true);
699                                         SG_SetActiveStage(SG_STAGE_ANIMATION_UPDATE);
700                                         scene->UpdateAnimations(m_frameTime);
701                                 }
702
703                                 m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
704                                 SG_SetActiveStage(SG_STAGE_PHYSICS2);
705                                 scene->GetPhysicsEnvironment()->beginFrame();
706                 
707                                 // Perform physics calculations on the scene. This can involve 
708                                 // many iterations of the physics solver.
709                                 scene->GetPhysicsEnvironment()->proceedDeltaTime(m_frameTime,timestep,framestep);//m_deltatimerealDeltaTime);
710
711                                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
712                                 SG_SetActiveStage(SG_STAGE_PHYSICS2_UPDATE);
713                                 scene->UpdateParents(m_frameTime);
714                         
715                         
716                                 if (m_animation_record)
717                                 {
718                                         m_sceneconverter->WritePhysicsObjectToAnimationIpo(++m_currentFrame);
719                                 }
720
721                                 scene->setSuspendedTime(0.0);
722                         } // suspended
723                         else
724                                 if (scene->getSuspendedTime()==0.0)
725                                         scene->setSuspendedTime(m_clockTime);
726                         
727                         m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true);
728                 }
729
730                 // update system devices
731                 m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
732                 if (m_keyboarddevice)
733                         m_keyboarddevice->NextFrame();
734         
735                 if (m_mousedevice)
736                         m_mousedevice->NextFrame();
737                 
738                 if (m_networkdevice)
739                         m_networkdevice->NextFrame();
740
741                 // scene management
742                 ProcessScheduledScenes();
743                 
744                 frames--;
745         }
746
747         bool bUseAsyncLogicBricks= false;//true;
748
749         if (bUseAsyncLogicBricks)
750         {
751                 // Logic update sub frame: this will let some logic bricks run at the
752                 // full frame rate.
753                 for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
754                 // for each scene, call the proceed functions
755                 {
756                         KX_Scene* scene = *sceneit;
757
758                         if (!scene->IsSuspended())
759                         {
760                                 // if the scene was suspended recalcutlate the delta tu "curtime"
761                                 m_suspendedtime = scene->getSuspendedTime();
762                                 if (scene->getSuspendedTime()!=0.0)
763                                         scene->setSuspendedDelta(scene->getSuspendedDelta()+m_clockTime-scene->getSuspendedTime());
764                                 m_suspendeddelta = scene->getSuspendedDelta();
765                                 
766                                 // set Python hooks for each scene
767 #ifdef WITH_PYTHON
768                                 PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
769 #endif
770                                 KX_SetActiveScene(scene);
771                                 
772                                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
773                                 SG_SetActiveStage(SG_STAGE_PHYSICS1);
774                                 scene->UpdateParents(m_clockTime);
775
776                                 // Perform physics calculations on the scene. This can involve 
777                                 // many iterations of the physics solver.
778                                 m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
779                                 scene->GetPhysicsEnvironment()->proceedDeltaTime(m_clockTime,timestep,timestep);
780                                 // Update scenegraph after physics step. This maps physics calculations
781                                 // into node positions.
782                                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
783                                 SG_SetActiveStage(SG_STAGE_PHYSICS2);
784                                 scene->UpdateParents(m_clockTime);
785                                 
786                                 // Do some cleanup work for this logic frame
787                                 m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
788                                 scene->LogicUpdateFrame(m_clockTime, false);
789
790                                 // Actuators can affect the scenegraph
791                                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
792                                 SG_SetActiveStage(SG_STAGE_ACTUATOR);
793                                 scene->UpdateParents(m_clockTime);
794
795                                 scene->setSuspendedTime(0.0);
796                         } // suspended
797                         else
798                                 if (scene->getSuspendedTime()==0.0)
799                                         scene->setSuspendedTime(m_clockTime);
800
801                         m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true);
802                 }
803         }
804
805                 
806         // Handle the animations independently of the logic time step
807         if (GetRestrictAnimationFPS())
808         {
809                 double clocktime = m_kxsystem->GetTimeInSeconds();
810                 m_logger->StartLog(tc_animations, clocktime, true);
811                 SG_SetActiveStage(SG_STAGE_ANIMATION_UPDATE);
812
813                 double anim_timestep = 1.0/KX_GetActiveScene()->GetAnimationFPS();
814                 if (clocktime - m_previousAnimTime > anim_timestep)
815                 {
816                         // Sanity/debug print to make sure we're actually going at the fps we want (should be close to anim_timestep)
817                         // printf("Anim fps: %f\n", 1.0/(m_clockTime - m_previousAnimTime));
818                         m_previousAnimTime = clocktime;
819                         for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
820                         {
821                                 (*sceneit)->UpdateAnimations(clocktime);
822                         }
823                 }
824         }
825         
826         // Start logging time spend outside main loop
827         m_logger->StartLog(tc_outside, m_kxsystem->GetTimeInSeconds(), true);
828         
829         return doRender;
830 }
831
832
833
834 void KX_KetsjiEngine::Render()
835 {
836         if (m_usedome) {
837                 RenderDome();
838                 return;
839         }
840         KX_Scene* firstscene = *m_scenes.begin();
841         const RAS_FrameSettings &framesettings = firstscene->GetFramingType();
842
843         m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
844         SG_SetActiveStage(SG_STAGE_RENDER);
845
846         // hiding mouse cursor each frame
847         // (came back when going out of focus and then back in again)
848         if (m_hideCursor)
849                 m_canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
850
851         // clear the entire game screen with the border color
852         // only once per frame
853         m_canvas->BeginDraw();
854         if (m_drawingmode == RAS_IRasterizer::KX_TEXTURED) {
855                 m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight());
856                 if (m_overrideFrameColor)
857                 {
858                         // Do not use the framing bar color set in the Blender scenes
859                         m_canvas->ClearColor(
860                                 m_overrideFrameColorR,
861                                 m_overrideFrameColorG,
862                                 m_overrideFrameColorB,
863                                 1.0
864                                 );
865                 }
866                 else
867                 {
868                         // Use the framing bar color set in the Blender scenes
869                         m_canvas->ClearColor(
870                                 framesettings.BarRed(),
871                                 framesettings.BarGreen(),
872                                 framesettings.BarBlue(),
873                                 1.0
874                                 );
875                 }
876                 // clear the -whole- viewport
877                 m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER);
878         }
879
880         m_rasterizer->SetEye(RAS_IRasterizer::RAS_STEREO_LEFTEYE);
881
882         // BeginFrame() sets the actual drawing area. You can use a part of the window
883         if (!BeginFrame())
884                 return;
885
886         KX_SceneList::iterator sceneit;
887         for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++)
888         // for each scene, call the proceed functions
889         {
890                 KX_Scene* scene = *sceneit;
891                 KX_Camera* cam = scene->GetActiveCamera();
892                 // pass the scene's worldsettings to the rasterizer
893                 SetWorldSettings(scene->GetWorldInfo());
894
895                 // this is now done incrementatlly in KX_Scene::CalculateVisibleMeshes
896                 //scene->UpdateMeshTransformations();
897
898                 // shadow buffers
899                 RenderShadowBuffers(scene);
900
901                 // Avoid drawing the scene with the active camera twice when it's viewport is enabled
902                 if (cam && !cam->GetViewport())
903                 {
904                         if (scene->IsClearingZBuffer())
905                                 m_rasterizer->ClearDepthBuffer();
906         
907                         m_rendertools->SetAuxilaryClientInfo(scene);
908         
909                         // do the rendering
910                         RenderFrame(scene, cam);
911                 }
912                 
913                 list<class KX_Camera*>* cameras = scene->GetCameras();
914                 
915                 // Draw the scene once for each camera with an enabled viewport
916                 list<KX_Camera*>::iterator it = cameras->begin();
917                 while (it != cameras->end()) {
918                         if ((*it)->GetViewport())
919                         {
920                                 if (scene->IsClearingZBuffer())
921                                         m_rasterizer->ClearDepthBuffer();
922                 
923                                 m_rendertools->SetAuxilaryClientInfo(scene);
924                 
925                                 // do the rendering
926                                 RenderFrame(scene, (*it));
927                         }
928                         
929                         it++;
930                 }
931                 PostRenderScene(scene);
932         }
933
934         // only one place that checks for stereo
935         if (m_rasterizer->Stereo())
936         {
937                 m_rasterizer->SetEye(RAS_IRasterizer::RAS_STEREO_RIGHTEYE);
938
939                 if (!BeginFrame())
940                         return;
941
942
943                 for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++)
944                 // for each scene, call the proceed functions
945                 {
946                         KX_Scene* scene = *sceneit;
947                         KX_Camera* cam = scene->GetActiveCamera();
948
949                         // pass the scene's worldsettings to the rasterizer
950                         SetWorldSettings(scene->GetWorldInfo());
951                 
952                         if (scene->IsClearingZBuffer())
953                                 m_rasterizer->ClearDepthBuffer();
954
955                         //pass the scene, for picking and raycasting (shadows)
956                         m_rendertools->SetAuxilaryClientInfo(scene);
957
958                         // do the rendering
959                         //RenderFrame(scene);
960                         RenderFrame(scene, cam);
961
962                         list<class KX_Camera*>* cameras = scene->GetCameras();
963         
964                         // Draw the scene once for each camera with an enabled viewport
965                         list<KX_Camera*>::iterator it = cameras->begin();
966                         while (it != cameras->end()) {
967                                 if ((*it)->GetViewport())
968                                 {
969                                         if (scene->IsClearingZBuffer())
970                                                 m_rasterizer->ClearDepthBuffer();
971                         
972                                         m_rendertools->SetAuxilaryClientInfo(scene);
973                         
974                                         // do the rendering
975                                         RenderFrame(scene, (*it));
976                                 }
977                                 
978                                 it++;
979                         }
980                         PostRenderScene(scene);
981                 }
982         } // if (m_rasterizer->Stereo())
983
984         EndFrame();
985 }
986
987
988
989 void KX_KetsjiEngine::RequestExit(int exitrequestmode)
990 {
991         m_exitcode = exitrequestmode;
992 }
993
994
995
996 void KX_KetsjiEngine::SetNameNextGame(const STR_String& nextgame)
997 {
998         m_exitstring = nextgame;
999 }
1000
1001
1002
1003 int KX_KetsjiEngine::GetExitCode()
1004 {
1005         // if a gameactuator has set an exitcode or if there are no scenes left
1006         if (!m_exitcode)
1007         {
1008                 if (m_scenes.begin()==m_scenes.end())
1009                         m_exitcode = KX_EXIT_REQUEST_NO_SCENES_LEFT;
1010         }
1011         
1012         // check if the window has been closed.
1013         if (!m_exitcode)
1014         {
1015                 //if (!m_canvas->Check()) {
1016                 //      m_exitcode = KX_EXIT_REQUEST_OUTSIDE;
1017                 //}
1018         }
1019
1020         return m_exitcode;
1021 }
1022
1023
1024
1025 const STR_String& KX_KetsjiEngine::GetExitString()
1026 {
1027         return m_exitstring;
1028 }
1029
1030
1031 void KX_KetsjiEngine::SetBackGround(KX_WorldInfo* wi)
1032 {
1033         if (wi->hasWorld())
1034         {
1035                 if (m_drawingmode == RAS_IRasterizer::KX_TEXTURED)
1036                 {
1037                         m_rasterizer->SetBackColor(
1038                                 wi->getBackColorRed(),
1039                                 wi->getBackColorGreen(),
1040                                 wi->getBackColorBlue(),
1041                                 0.0
1042                         );
1043                 }
1044         }
1045 }
1046
1047
1048
1049 void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi)
1050 {
1051         if (wi->hasWorld())
1052         {
1053                 // ...
1054                 m_rasterizer->SetAmbientColor(
1055                         wi->getAmbientColorRed(),
1056                         wi->getAmbientColorGreen(),
1057                         wi->getAmbientColorBlue()
1058                 );
1059
1060                 if (m_drawingmode >= RAS_IRasterizer::KX_SOLID)
1061                 {
1062                         if (wi->hasMist())
1063                         {
1064                                 m_rasterizer->SetFog(
1065                                         wi->getMistStart(),
1066                                         wi->getMistDistance(),
1067                                         wi->getMistColorRed(),
1068                                         wi->getMistColorGreen(),
1069                                         wi->getMistColorBlue()
1070                                 );
1071                         }
1072                 }
1073         }
1074 }
1075
1076
1077
1078 void KX_KetsjiEngine::SetDrawType(int drawingmode)
1079 {
1080         m_drawingmode = drawingmode;
1081 }
1082
1083
1084         
1085 void KX_KetsjiEngine::EnableCameraOverride(const STR_String& forscene)
1086 {
1087         m_overrideCam = true;
1088         m_overrideSceneName = forscene;
1089 }
1090
1091 void KX_KetsjiEngine::SetCameraZoom(float camzoom)
1092 {
1093         m_cameraZoom = camzoom;
1094 }
1095
1096 void KX_KetsjiEngine::SetCameraOverrideUseOrtho(bool useOrtho)
1097 {
1098         m_overrideCamUseOrtho = useOrtho;
1099 }
1100
1101 void KX_KetsjiEngine::SetCameraOverrideProjectionMatrix(const MT_CmMatrix4x4& mat)
1102 {
1103         m_overrideCamProjMat = mat;
1104 }
1105
1106 void KX_KetsjiEngine::SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat)
1107 {
1108         m_overrideCamViewMat = mat;
1109 }
1110
1111 void KX_KetsjiEngine::SetCameraOverrideClipping(float nearfrust, float farfrust)
1112 {
1113         m_overrideCamNear = nearfrust;
1114         m_overrideCamFar = farfrust;
1115 }
1116
1117 void KX_KetsjiEngine::SetCameraOverrideLens(float lens)
1118 {
1119         m_overrideCamLens = lens;
1120 }
1121
1122 void KX_KetsjiEngine::GetSceneViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect& area, RAS_Rect& viewport)
1123 {
1124         // In this function we make sure the rasterizer settings are upto
1125         // date. We compute the viewport so that logic
1126         // using this information is upto date.
1127
1128         // Note we postpone computation of the projection matrix
1129         // so that we are using the latest camera position.
1130         if (cam->GetViewport()) {
1131                 RAS_Rect userviewport;
1132
1133                 userviewport.SetLeft(cam->GetViewportLeft()); 
1134                 userviewport.SetBottom(cam->GetViewportBottom());
1135                 userviewport.SetRight(cam->GetViewportRight());
1136                 userviewport.SetTop(cam->GetViewportTop());
1137
1138                 // Don't do bars on user specified viewport
1139                 RAS_FrameSettings settings = scene->GetFramingType();
1140                 if (settings.FrameType() == RAS_FrameSettings::e_frame_bars)
1141                         settings.SetFrameType(RAS_FrameSettings::e_frame_extend);
1142
1143                 RAS_FramingManager::ComputeViewport(
1144                         scene->GetFramingType(),
1145                         userviewport,
1146                         viewport
1147                 );
1148
1149                 area = userviewport;
1150         }
1151         else if ( !m_overrideCam || (scene->GetName() != m_overrideSceneName) ||  m_overrideCamUseOrtho ) {
1152                 RAS_FramingManager::ComputeViewport(
1153                         scene->GetFramingType(),
1154                         m_canvas->GetDisplayArea(),
1155                         viewport
1156                 );
1157
1158                 area = m_canvas->GetDisplayArea();
1159         } else {
1160                 viewport.SetLeft(0); 
1161                 viewport.SetBottom(0);
1162                 viewport.SetRight(int(m_canvas->GetWidth()));
1163                 viewport.SetTop(int(m_canvas->GetHeight()));
1164
1165                 area = m_canvas->GetDisplayArea();
1166         }
1167 }
1168
1169 void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
1170 {
1171         CListValue *lightlist = scene->GetLightList();
1172         int i, drawmode;
1173
1174         m_rendertools->SetAuxilaryClientInfo(scene);
1175
1176         for (i=0; i<lightlist->GetCount(); i++) {
1177                 KX_GameObject *gameobj = (KX_GameObject*)lightlist->GetValue(i);
1178
1179                 KX_LightObject *light = (KX_LightObject*)gameobj;
1180
1181                 light->Update();
1182
1183                 if (m_drawingmode == RAS_IRasterizer::KX_TEXTURED && light->HasShadowBuffer()) {
1184                         /* make temporary camera */
1185                         RAS_CameraData camdata = RAS_CameraData();
1186                         KX_Camera *cam = new KX_Camera(scene, scene->m_callbacks, camdata, true, true);
1187                         cam->SetName("__shadow__cam__");
1188
1189                         MT_Transform camtrans;
1190
1191                         /* switch drawmode for speed */
1192                         drawmode = m_rasterizer->GetDrawingMode();
1193                         m_rasterizer->SetDrawingMode(RAS_IRasterizer::KX_SHADOW);
1194
1195                         /* binds framebuffer object, sets up camera .. */
1196                         light->BindShadowBuffer(m_rasterizer, m_canvas, cam, camtrans);
1197
1198                         /* update scene */
1199                         scene->CalculateVisibleMeshes(m_rasterizer, cam, light->GetShadowLayer());
1200
1201                         /* render */
1202                         m_rasterizer->ClearDepthBuffer();
1203                         scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
1204
1205                         /* unbind framebuffer object, restore drawmode, free camera */
1206                         light->UnbindShadowBuffer(m_rasterizer);
1207                         m_rasterizer->SetDrawingMode(drawmode);
1208                         cam->Release();
1209                 }
1210         }
1211 }
1212         
1213 // update graphics
1214 void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
1215 {
1216         bool override_camera;
1217         RAS_Rect viewport, area;
1218         float nearfrust, farfrust, focallength;
1219 //      KX_Camera* cam = scene->GetActiveCamera();
1220         
1221         if (!cam)
1222                 return;
1223         GetSceneViewport(scene, cam, area, viewport);
1224
1225         // store the computed viewport in the scene
1226         scene->SetSceneViewport(viewport);
1227
1228         // set the viewport for this frame and scene
1229         m_canvas->SetViewPort(viewport.GetLeft(), viewport.GetBottom(),
1230                 viewport.GetRight(), viewport.GetTop());
1231         
1232         // see KX_BlenderMaterial::Activate
1233         //m_rasterizer->SetAmbient();
1234         m_rasterizer->DisplayFog();
1235
1236         override_camera = m_overrideCam && (scene->GetName() == m_overrideSceneName);
1237         override_camera = override_camera && (cam->GetName() == "__default__cam__");
1238
1239         if (override_camera && m_overrideCamUseOrtho) {
1240                 m_rasterizer->SetProjectionMatrix(m_overrideCamProjMat);
1241                 if (!cam->hasValidProjectionMatrix()) {
1242                         // needed to get frustrum planes for culling
1243                         MT_Matrix4x4 projmat;
1244                         projmat.setValue(m_overrideCamProjMat.getPointer());
1245                         cam->SetProjectionMatrix(projmat);
1246                 }
1247         } else if (cam->hasValidProjectionMatrix())
1248         {
1249                 m_rasterizer->SetProjectionMatrix(cam->GetProjectionMatrix());
1250         } else
1251         {
1252                 RAS_FrameFrustum frustum;
1253                 bool orthographic = !cam->GetCameraData()->m_perspective;
1254                 nearfrust = cam->GetCameraNear();
1255                 farfrust = cam->GetCameraFar();
1256                 focallength = cam->GetFocalLength();
1257                 MT_Matrix4x4 projmat;
1258
1259                 if (override_camera) {
1260                         nearfrust = m_overrideCamNear;
1261                         farfrust = m_overrideCamFar;
1262                 }
1263
1264                 if (orthographic) {
1265
1266                         RAS_FramingManager::ComputeOrtho(
1267                                 scene->GetFramingType(),
1268                                 area,
1269                                 viewport,
1270                                 cam->GetScale(),
1271                                 nearfrust,
1272                                 farfrust,
1273                                 cam->GetSensorFit(),
1274                                 frustum
1275                         );
1276                         if (!cam->GetViewport()) {
1277                                 frustum.x1 *= m_cameraZoom;
1278                                 frustum.x2 *= m_cameraZoom;
1279                                 frustum.y1 *= m_cameraZoom;
1280                                 frustum.y2 *= m_cameraZoom;
1281                         }
1282                         projmat = m_rasterizer->GetOrthoMatrix(
1283                                 frustum.x1, frustum.x2, frustum.y1, frustum.y2, frustum.camnear, frustum.camfar);
1284
1285                 } else {
1286                         RAS_FramingManager::ComputeFrustum(
1287                                 scene->GetFramingType(),
1288                                 area,
1289                                 viewport,
1290                                 cam->GetLens(),
1291                                 cam->GetSensorWidth(),
1292                                 cam->GetSensorHeight(),
1293                                 cam->GetSensorFit(),
1294                                 nearfrust,
1295                                 farfrust,
1296                                 frustum
1297                         );
1298
1299                         if (!cam->GetViewport()) {
1300                                 frustum.x1 *= m_cameraZoom;
1301                                 frustum.x2 *= m_cameraZoom;
1302                                 frustum.y1 *= m_cameraZoom;
1303                                 frustum.y2 *= m_cameraZoom;
1304                         }
1305                         projmat = m_rasterizer->GetFrustumMatrix(
1306                                 frustum.x1, frustum.x2, frustum.y1, frustum.y2, frustum.camnear, frustum.camfar, focallength);
1307                 }
1308                 cam->SetProjectionMatrix(projmat);
1309                 
1310                 // Otherwise the projection matrix for each eye will be the same...
1311                 if (!orthographic && m_rasterizer->Stereo())
1312                         cam->InvalidateProjectionMatrix();
1313         }
1314
1315         MT_Transform camtrans(cam->GetWorldToCamera());
1316         MT_Matrix4x4 viewmat(camtrans);
1317         
1318         m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldOrientation(), cam->NodeGetWorldPosition(), cam->GetCameraData()->m_perspective);
1319         cam->SetModelviewMatrix(viewmat);
1320
1321         // The following actually reschedules all vertices to be
1322         // redrawn. There is a cache between the actual rescheduling
1323         // and this call though. Visibility is imparted when this call
1324         // runs through the individual objects.
1325
1326         m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
1327         SG_SetActiveStage(SG_STAGE_CULLING);
1328
1329         scene->CalculateVisibleMeshes(m_rasterizer,cam);
1330
1331         m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
1332         SG_SetActiveStage(SG_STAGE_RENDER);
1333
1334 #ifdef WITH_PYTHON
1335         // Run any pre-drawing python callbacks
1336         scene->RunDrawingCallbacks(scene->GetPreDrawCB());
1337 #endif
1338
1339         scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
1340
1341         //render all the font objects for this scene
1342         RenderFonts(scene);
1343         
1344         if (scene->GetPhysicsEnvironment())
1345                 scene->GetPhysicsEnvironment()->debugDrawWorld();
1346 }
1347
1348 void KX_KetsjiEngine::RenderFonts(KX_Scene* scene)
1349 {
1350         list<class KX_FontObject*>* fonts = scene->GetFonts();
1351         
1352         list<KX_FontObject*>::iterator it = fonts->begin();
1353         while (it != fonts->end()) {
1354                 (*it)->DrawText();
1355                 ++it;
1356         }
1357 }
1358
1359 /*
1360  * To run once per scene
1361  */
1362 void KX_KetsjiEngine::PostRenderScene(KX_Scene* scene)
1363 {
1364         // We need to first make sure our viewport is correct (enabling multiple viewports can mess this up)
1365         m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight());
1366         
1367         m_rasterizer->FlushDebugShapes();
1368         scene->Render2DFilters(m_canvas);
1369 #ifdef WITH_PYTHON
1370         scene->RunDrawingCallbacks(scene->GetPostDrawCB());
1371 #endif
1372 }
1373
1374 void KX_KetsjiEngine::StopEngine()
1375 {
1376         if (m_bInitialized)
1377         {
1378
1379                 if (m_animation_record)
1380                 {
1381 //                      printf("TestHandlesPhysicsObjectToAnimationIpo\n");
1382                         m_sceneconverter->TestHandlesPhysicsObjectToAnimationIpo();
1383                 }
1384
1385                 KX_SceneList::iterator sceneit;
1386                 for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
1387                 {
1388                         KX_Scene* scene = *sceneit;
1389                         m_sceneconverter->RemoveScene(scene);
1390                 }
1391                 m_scenes.clear();
1392
1393                 // cleanup all the stuff
1394                 m_rasterizer->Exit();
1395         }
1396 }
1397
1398 // Scene Management is able to switch between scenes
1399 // and have several scene's running in parallel
1400 void KX_KetsjiEngine::AddScene(KX_Scene* scene)
1401
1402         m_scenes.push_back(scene);
1403         PostProcessScene(scene);
1404         SceneListsChanged();
1405 }
1406
1407
1408
1409 void KX_KetsjiEngine::PostProcessScene(KX_Scene* scene)
1410 {
1411         bool override_camera = (m_overrideCam && (scene->GetName() == m_overrideSceneName));
1412
1413         SG_SetActiveStage(SG_STAGE_SCENE);
1414
1415         // if there is no activecamera, or the camera is being
1416         // overridden we need to construct a temporarily camera
1417         if (!scene->GetActiveCamera() || override_camera)
1418         {
1419                 KX_Camera* activecam = NULL;
1420
1421                 RAS_CameraData camdata = RAS_CameraData();
1422                 if (override_camera)
1423                 {
1424                         camdata.m_lens = m_overrideCamLens;
1425                         camdata.m_clipstart = m_overrideCamNear;
1426                         camdata.m_clipend = m_overrideCamFar;
1427                         
1428                         camdata.m_perspective= !m_overrideCamUseOrtho;
1429                 }
1430                 activecam = new KX_Camera(scene,KX_Scene::m_callbacks,camdata);
1431                 activecam->SetName("__default__cam__");
1432         
1433                         // set transformation
1434                 if (override_camera) {
1435                         const MT_CmMatrix4x4& cammatdata = m_overrideCamViewMat;
1436                         MT_Transform trans = MT_Transform(cammatdata.getPointer());
1437                         MT_Transform camtrans;
1438                         camtrans.invert(trans);
1439                         
1440                         activecam->NodeSetLocalPosition(camtrans.getOrigin());
1441                         activecam->NodeSetLocalOrientation(camtrans.getBasis());
1442                         activecam->NodeUpdateGS(0);
1443                 } else {
1444                         activecam->NodeSetLocalPosition(MT_Point3(0.0, 0.0, 0.0));
1445                         activecam->NodeSetLocalOrientation(MT_Vector3(0.0, 0.0, 0.0));
1446                         activecam->NodeUpdateGS(0);
1447                 }
1448
1449                 scene->AddCamera(activecam);
1450                 scene->SetActiveCamera(activecam);
1451                 scene->GetObjectList()->Add(activecam->AddRef());
1452                 scene->GetRootParentList()->Add(activecam->AddRef());
1453                 //done with activecam
1454                 activecam->Release();
1455         }
1456         
1457         scene->UpdateParents(0.0);
1458 }
1459
1460
1461
1462 void KX_KetsjiEngine::RenderDebugProperties()
1463 {
1464         STR_String debugtxt;
1465         int title_xmargin = -7;
1466         int title_y_top_margin = 4;
1467         int title_y_bottom_margin = 2;
1468
1469         int const_xindent = 4;
1470         int const_ysize = 14;
1471
1472         int xcoord = 12;        // mmmm, these constants were taken from blender source
1473         int ycoord = 17;        // to 'mimic' behavior
1474         
1475         int profile_indent = 72;
1476
1477         float tottime = m_logger->GetAverage();
1478         if (tottime < 1e-6f) {
1479                 tottime = 1e-6f;
1480         }
1481
1482         // Set viewport to entire canvas
1483         RAS_Rect viewport;
1484         m_canvas->SetViewPort(0, 0, int(m_canvas->GetWidth()), int(m_canvas->GetHeight()));
1485         
1486         if (m_show_framerate || m_show_profile) {
1487                 /* Title for profiling("Profile") */
1488                 m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
1489                                             "Profile",
1490                                             xcoord + const_xindent + title_xmargin, // Adds the constant x indent (0 for now) to the title x margin
1491                                             ycoord,
1492                                             m_canvas->GetWidth() /* RdV, TODO ?? */,
1493                                             m_canvas->GetHeight() /* RdV, TODO ?? */);
1494
1495                 // Increase the indent by default increase
1496                 ycoord += const_ysize;
1497                 // Add the title indent afterwards
1498                 ycoord += title_y_bottom_margin;
1499         }
1500
1501         /* Framerate display */
1502         if (m_show_framerate) {
1503                 m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
1504                                             "Frametime :",
1505                                             xcoord + const_xindent,
1506                                             ycoord,
1507                                             m_canvas->GetWidth() /* RdV, TODO ?? */,
1508                                             m_canvas->GetHeight() /* RdV, TODO ?? */);
1509                 
1510                 debugtxt.Format("%5.1fms (%.1ffps)", tottime * 1000.f, 1.0/tottime);
1511                 m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
1512                                             debugtxt.ReadPtr(),
1513                                             xcoord + const_xindent + profile_indent,
1514                                             ycoord,
1515                                             m_canvas->GetWidth() /* RdV, TODO ?? */,
1516                                             m_canvas->GetHeight() /* RdV, TODO ?? */);
1517                 // Increase the indent by default increase
1518                 ycoord += const_ysize;
1519         }
1520
1521         /* Profile display */
1522         if (m_show_profile) {
1523                 for (int j = tc_first; j < tc_numCategories; j++) {
1524                         m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
1525                                                     m_profileLabels[j],
1526                                                     xcoord + const_xindent,
1527                                                     ycoord,
1528                                                     m_canvas->GetWidth(),
1529                                                     m_canvas->GetHeight());
1530
1531                         double time = m_logger->GetAverage((KX_TimeCategory)j);
1532
1533                         debugtxt.Format("%5.2fms | %d%%", time*1000.f, (int)(time/tottime * 100.f));
1534                         m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
1535                                                     debugtxt.ReadPtr(),
1536                                                     xcoord + const_xindent + profile_indent, ycoord,
1537                                                     m_canvas->GetWidth(),
1538                                                     m_canvas->GetHeight());
1539
1540                         m_rendertools->RenderBox2D(xcoord + (int)(2.2 * profile_indent), ycoord, m_canvas->GetWidth(), m_canvas->GetHeight(), time/tottime);
1541                         ycoord += const_ysize;
1542                 }
1543         }
1544         // Add the ymargin for titles below the other section of debug info
1545         ycoord += title_y_top_margin;
1546
1547         /* Property display*/
1548         if (m_show_debug_properties && m_propertiesPresent) {
1549
1550                 /* Title for debugging("Debug properties") */
1551                 m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
1552                                             "Debug Properties",
1553                                             xcoord + const_xindent + title_xmargin, // Adds the constant x indent (0 for now) to the title x margin
1554                                             ycoord,
1555                                             m_canvas->GetWidth() /* RdV, TODO ?? */,
1556                                             m_canvas->GetHeight() /* RdV, TODO ?? */);
1557
1558                 // Increase the indent by default increase
1559                 ycoord += const_ysize;
1560                 // Add the title indent afterwards
1561                 ycoord += title_y_bottom_margin;
1562
1563                 KX_SceneList::iterator sceneit;
1564                 for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++) {
1565                         KX_Scene* scene = *sceneit;
1566                         /* the 'normal' debug props */
1567                         vector<SCA_DebugProp*>& debugproplist = scene->GetDebugProperties();
1568                         
1569                         for (vector<SCA_DebugProp*>::iterator it = debugproplist.begin();
1570                              !(it==debugproplist.end());it++)
1571                         {
1572                                 CValue *propobj = (*it)->m_obj;
1573                                 STR_String objname = propobj->GetName();
1574                                 STR_String propname = (*it)->m_name;
1575                                 if (propname == "__state__") {
1576                                         // reserve name for object state
1577                                         KX_GameObject* gameobj = static_cast<KX_GameObject*>(propobj);
1578                                         unsigned int state = gameobj->GetState();
1579                                         debugtxt = objname + "." + propname + " = ";
1580                                         bool first = true;
1581                                         for (int statenum=1;state;state >>= 1, statenum++)
1582                                         {
1583                                                 if (state & 1)
1584                                                 {
1585                                                         if (!first)
1586                                                         {
1587                                                                 debugtxt += ",";
1588                                                         }
1589                                                         debugtxt += STR_String(statenum);
1590                                                         first = false;
1591                                                 }
1592                                         }
1593                                         m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
1594                                                                     debugtxt.ReadPtr(),
1595                                                                     xcoord + const_xindent,
1596                                                                     ycoord,
1597                                                                     m_canvas->GetWidth(),
1598                                                                     m_canvas->GetHeight());
1599                                         ycoord += const_ysize;
1600                                 }
1601                                 else {
1602                                         CValue *propval = propobj->GetProperty(propname);
1603                                         if (propval) {
1604                                                 STR_String text = propval->GetText();
1605                                                 debugtxt = objname + ": '" + propname + "' = " + text;
1606                                                 m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
1607                                                                             debugtxt.ReadPtr(),
1608                                                                             xcoord + const_xindent,
1609                                                                             ycoord,
1610                                                                             m_canvas->GetWidth(),
1611                                                                             m_canvas->GetHeight());
1612                                                 ycoord += const_ysize;
1613                                         }
1614                                 }
1615                         }
1616                 }
1617         }
1618 }
1619
1620
1621 KX_SceneList* KX_KetsjiEngine::CurrentScenes()
1622 {
1623         return &m_scenes;
1624 }
1625
1626
1627
1628 KX_Scene* KX_KetsjiEngine::FindScene(const STR_String& scenename)
1629 {
1630         KX_SceneList::iterator sceneit = m_scenes.begin();
1631
1632         // bit risky :) better to split the second clause 
1633         while ( (sceneit != m_scenes.end()) 
1634                         && ((*sceneit)->GetName() != scenename))
1635         {
1636                 sceneit++;
1637         }
1638
1639         return ((sceneit == m_scenes.end()) ? NULL : *sceneit);
1640 }
1641
1642
1643
1644 void KX_KetsjiEngine::ConvertAndAddScene(const STR_String& scenename,bool overlay)
1645 {
1646         // only add scene when it doesn't exist!
1647         if (FindScene(scenename)) {
1648                 printf("warning: scene %s already exists, not added!\n",scenename.ReadPtr());
1649         }
1650         else {
1651                 if (overlay) {
1652                         m_addingOverlayScenes.push_back(scenename);
1653                 }
1654                 else {
1655                         m_addingBackgroundScenes.push_back(scenename);
1656                 }
1657         }
1658 }
1659
1660
1661
1662
1663 void KX_KetsjiEngine::RemoveScene(const STR_String& scenename)
1664 {
1665         if (FindScene(scenename))
1666         {
1667                 m_removingScenes.push_back(scenename);
1668         }
1669         else
1670         {
1671 //              STR_String tmpname = scenename;
1672                 std::cout << "warning: scene " << scenename << " does not exist, not removed!" << std::endl;
1673         }
1674 }
1675
1676
1677
1678 void KX_KetsjiEngine::RemoveScheduledScenes()
1679 {
1680         if (m_removingScenes.size())
1681         {
1682                 vector<STR_String>::iterator scenenameit;
1683                 for (scenenameit=m_removingScenes.begin();scenenameit != m_removingScenes.end();scenenameit++)
1684                 {
1685                         STR_String scenename = *scenenameit;
1686
1687                         KX_SceneList::iterator sceneit;
1688                         for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
1689                         {
1690                                 KX_Scene* scene = *sceneit;
1691                                 if (scene->GetName()==scenename)
1692                                 {
1693                                         m_sceneconverter->RemoveScene(scene);
1694                                         m_scenes.erase(sceneit);
1695                                         break;
1696                                 }
1697                         }
1698                 }
1699                 m_removingScenes.clear();
1700         }
1701 }
1702
1703 KX_Scene* KX_KetsjiEngine::CreateScene(Scene *scene, bool libloading)
1704 {
1705         KX_Scene* tmpscene = new KX_Scene(m_keyboarddevice,
1706                                                                           m_mousedevice,
1707                                                                           m_networkdevice,
1708                                                                           scene->id.name+2,
1709                                                                           scene,
1710                                                                           m_canvas);
1711
1712         m_sceneconverter->ConvertScene(tmpscene,
1713                                                           m_rendertools,
1714                                                           m_canvas,
1715                                                           libloading);
1716
1717         return tmpscene;
1718 }
1719
1720 KX_Scene* KX_KetsjiEngine::CreateScene(const STR_String& scenename)
1721 {
1722         Scene *scene = m_sceneconverter->GetBlenderSceneForName(scenename);
1723         return CreateScene(scene);
1724 }
1725
1726 void KX_KetsjiEngine::AddScheduledScenes()
1727 {
1728         vector<STR_String>::iterator scenenameit;
1729
1730         if (m_addingOverlayScenes.size())
1731         {
1732                 for (scenenameit = m_addingOverlayScenes.begin();
1733                         scenenameit != m_addingOverlayScenes.end();
1734                         scenenameit++)
1735                 {
1736                         STR_String scenename = *scenenameit;
1737                         KX_Scene* tmpscene = CreateScene(scenename);
1738                         m_scenes.push_back(tmpscene);
1739                         PostProcessScene(tmpscene);
1740                 }
1741                 m_addingOverlayScenes.clear();
1742         }
1743         
1744         if (m_addingBackgroundScenes.size())
1745         {
1746                 for (scenenameit = m_addingBackgroundScenes.begin();
1747                         scenenameit != m_addingBackgroundScenes.end();
1748                         scenenameit++)
1749                 {
1750                         STR_String scenename = *scenenameit;
1751                         KX_Scene* tmpscene = CreateScene(scenename);
1752                         m_scenes.insert(m_scenes.begin(),tmpscene);
1753                         PostProcessScene(tmpscene);
1754
1755                 }
1756                 m_addingBackgroundScenes.clear();
1757         }
1758 }
1759
1760
1761
1762 void KX_KetsjiEngine::ReplaceScene(const STR_String& oldscene,const STR_String& newscene)
1763 {
1764         m_replace_scenes.push_back(std::make_pair(oldscene,newscene));
1765 }
1766
1767 // replace scene is not the same as removing and adding because the
1768 // scene must be in exact the same place (to maintain drawingorder)
1769 // (nzc) - should that not be done with a scene-display list? It seems
1770 // stupid to rely on the mem allocation order...
1771 void KX_KetsjiEngine::ReplaceScheduledScenes()
1772 {
1773         if (m_replace_scenes.size())
1774         {
1775                 vector<pair<STR_String,STR_String> >::iterator scenenameit;
1776                 
1777                 for (scenenameit = m_replace_scenes.begin();
1778                         scenenameit != m_replace_scenes.end();
1779                         scenenameit++)
1780                 {
1781                         STR_String oldscenename = (*scenenameit).first;
1782                         STR_String newscenename = (*scenenameit).second;
1783                         int i=0;
1784                         /* Scenes are not supposed to be included twice... I think */
1785                         KX_SceneList::iterator sceneit;
1786                         for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
1787                         {
1788                                 KX_Scene* scene = *sceneit;
1789                                 if (scene->GetName() == oldscenename)
1790                                 {
1791                                         m_sceneconverter->RemoveScene(scene);
1792                                         KX_Scene* tmpscene = CreateScene(newscenename);
1793                                         m_scenes[i]=tmpscene;
1794                                         PostProcessScene(tmpscene);
1795                                 }
1796                                 i++;
1797                         }
1798                 }
1799                 m_replace_scenes.clear();
1800         }
1801 }
1802
1803
1804
1805 void KX_KetsjiEngine::SuspendScene(const STR_String& scenename)
1806 {
1807         KX_Scene*  scene = FindScene(scenename);
1808         if (scene) scene->Suspend();
1809 }
1810
1811
1812
1813 void KX_KetsjiEngine::ResumeScene(const STR_String& scenename)
1814 {
1815         KX_Scene*  scene = FindScene(scenename);
1816         if (scene) scene->Resume();
1817 }
1818
1819
1820
1821 void KX_KetsjiEngine::SetUseFixedTime(bool bUseFixedTime)
1822 {
1823         m_bFixedTime = bUseFixedTime;
1824 }
1825
1826
1827 void    KX_KetsjiEngine::SetAnimRecordMode(bool animation_record, int startFrame)
1828 {
1829         m_animation_record = animation_record;
1830         if (animation_record)
1831         {
1832                 //when recording physics keyframes, run at a variable (capped) frame rate (fixed time == full speed)
1833                 m_bFixedTime = false;
1834         }
1835         m_currentFrame = startFrame;
1836 }
1837
1838 bool KX_KetsjiEngine::GetUseFixedTime(void) const
1839 {
1840         return m_bFixedTime;
1841 }
1842
1843 double KX_KetsjiEngine::GetSuspendedDelta()
1844 {
1845         return m_suspendeddelta;
1846 }
1847
1848 double KX_KetsjiEngine::GetTicRate()
1849 {
1850         return m_ticrate;
1851 }
1852
1853 void KX_KetsjiEngine::SetTicRate(double ticrate)
1854 {
1855         m_ticrate = ticrate;
1856 }
1857
1858 int KX_KetsjiEngine::GetMaxLogicFrame()
1859 {
1860         return m_maxLogicFrame;
1861 }
1862
1863 void KX_KetsjiEngine::SetMaxLogicFrame(int frame)
1864 {
1865         m_maxLogicFrame = frame;
1866 }
1867
1868 int KX_KetsjiEngine::GetMaxPhysicsFrame()
1869 {
1870         return m_maxPhysicsFrame;
1871 }
1872
1873 void KX_KetsjiEngine::SetMaxPhysicsFrame(int frame)
1874 {
1875         m_maxPhysicsFrame = frame;
1876 }
1877
1878 bool KX_KetsjiEngine::GetRestrictAnimationFPS()
1879 {
1880         return m_restrict_anim_fps;
1881 }
1882
1883 void KX_KetsjiEngine::SetRestrictAnimationFPS(bool bRestrictAnimFPS)
1884 {
1885         m_restrict_anim_fps = bRestrictAnimFPS;
1886 }
1887
1888 double KX_KetsjiEngine::GetAnimFrameRate()
1889 {
1890         return m_anim_framerate;
1891 }
1892
1893 double KX_KetsjiEngine::GetClockTime(void) const
1894 {
1895         return m_clockTime;
1896 }
1897
1898 double KX_KetsjiEngine::GetFrameTime(void) const
1899 {
1900         return m_frameTime;
1901 }
1902
1903 double KX_KetsjiEngine::GetRealTime(void) const
1904 {
1905         return m_kxsystem->GetTimeInSeconds();
1906 }
1907
1908 void KX_KetsjiEngine::SetAnimFrameRate(double framerate)
1909 {
1910         m_anim_framerate = framerate;
1911 }
1912
1913 double KX_KetsjiEngine::GetAverageFrameRate()
1914 {
1915         return m_average_framerate;
1916 }
1917
1918 void KX_KetsjiEngine::SetExitKey(short key)
1919 {
1920         m_exitkey = key;
1921 }
1922
1923 short KX_KetsjiEngine::GetExitKey()
1924 {
1925         return m_exitkey;
1926 }
1927
1928 void KX_KetsjiEngine::SetTimingDisplay(bool frameRate, bool profile, bool properties)
1929 {
1930         m_show_framerate = frameRate;
1931         m_show_profile = profile;
1932         m_show_debug_properties = properties;
1933 }
1934
1935
1936
1937 void KX_KetsjiEngine::GetTimingDisplay(bool& frameRate, bool& profile, bool& properties) const
1938 {
1939         frameRate = m_show_framerate;
1940         profile = m_show_profile;
1941         properties = m_show_debug_properties;
1942 }
1943
1944
1945
1946 void KX_KetsjiEngine::ProcessScheduledScenes(void)
1947 {
1948         // Check whether there will be changes to the list of scenes
1949         if (m_addingOverlayScenes.size() ||
1950                 m_addingBackgroundScenes.size() ||
1951                 m_replace_scenes.size() ||
1952                 m_removingScenes.size()) {
1953
1954                 // Change the scene list
1955                 ReplaceScheduledScenes();
1956                 RemoveScheduledScenes();
1957                 AddScheduledScenes();
1958
1959                 // Notify
1960                 SceneListsChanged();
1961         }
1962 }
1963
1964
1965
1966 void KX_KetsjiEngine::SceneListsChanged(void)
1967 {
1968         m_propertiesPresent = false;
1969         KX_SceneList::iterator sceneit = m_scenes.begin();
1970         while ((sceneit != m_scenes.end()) && (!m_propertiesPresent))
1971         {
1972                 KX_Scene* scene = *sceneit;
1973                 vector<SCA_DebugProp*>& debugproplist = scene->GetDebugProperties();
1974                 m_propertiesPresent = !debugproplist.empty();
1975                 sceneit++;
1976         }
1977 }
1978
1979
1980 void KX_KetsjiEngine::SetHideCursor(bool hideCursor)
1981 {
1982         m_hideCursor = hideCursor;
1983 }
1984
1985
1986 bool KX_KetsjiEngine::GetHideCursor(void) const
1987 {
1988         return m_hideCursor;
1989 }
1990
1991
1992 void KX_KetsjiEngine::SetUseOverrideFrameColor(bool overrideFrameColor)
1993 {
1994         m_overrideFrameColor = overrideFrameColor;
1995 }
1996
1997
1998 bool KX_KetsjiEngine::GetUseOverrideFrameColor(void) const
1999 {
2000         return m_overrideFrameColor;
2001 }
2002
2003
2004 void KX_KetsjiEngine::SetOverrideFrameColor(float r, float g, float b)
2005 {
2006         m_overrideFrameColorR = r;
2007         m_overrideFrameColorG = g;
2008         m_overrideFrameColorB = b;
2009 }
2010
2011
2012 void KX_KetsjiEngine::GetOverrideFrameColor(float& r, float& g, float& b) const
2013 {
2014         r = m_overrideFrameColorR;
2015         g = m_overrideFrameColorG;
2016         b = m_overrideFrameColorB;
2017 }
2018
2019
2020 void KX_KetsjiEngine::Resize()
2021 {
2022         KX_SceneList::iterator sceneit;
2023
2024         /* extended mode needs to recalculate camera frustrums when */
2025         KX_Scene* firstscene = *m_scenes.begin();
2026         const RAS_FrameSettings &framesettings = firstscene->GetFramingType();
2027
2028         if (framesettings.FrameType() == RAS_FrameSettings::e_frame_extend) {
2029                 for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++) {
2030                         KX_Camera* cam = ((KX_Scene *)*sceneit)->GetActiveCamera();
2031                         cam->InvalidateProjectionMatrix();
2032                 }
2033         }
2034 }
2035
2036
2037 void KX_KetsjiEngine::SetGlobalSettings(GlobalSettings* gs)
2038 {
2039         m_globalsettings.matmode = gs->matmode;
2040         m_globalsettings.glslflag = gs->glslflag;
2041 }
2042
2043 GlobalSettings* KX_KetsjiEngine::GetGlobalSettings(void)
2044 {
2045         return &m_globalsettings;
2046 }
2047