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