There was a problem with the last merge :S
[blender.git] / source / gameengine / Ketsji / KX_KetsjiEngine.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  * The engine ties all game modules together. 
29  */
30
31 #ifdef WIN32
32 #pragma warning (disable : 4786)
33 #endif //WIN32
34
35 #include <iostream>
36
37 #include "KX_KetsjiEngine.h"
38
39 #include "ListValue.h"
40 #include "IntValue.h"
41 #include "VectorValue.h"
42 #include "BoolValue.h"
43 #include "FloatValue.h"
44
45 #define KX_NUM_ITERATIONS 4
46 #include "RAS_BucketManager.h"
47 #include "RAS_Rect.h"
48 #include "RAS_IRasterizer.h"
49 #include "RAS_IRenderTools.h"
50 #include "RAS_ICanvas.h"
51 #include "STR_String.h"
52 #include "MT_Vector3.h"
53 #include "MT_Transform.h"
54 #include "SCA_IInputDevice.h"
55 #include "KX_Scene.h"
56 #include "MT_CmMatrix4x4.h"
57 #include "KX_Camera.h"
58 #include "KX_Light.h"
59 #include "KX_PythonInit.h"
60 #include "KX_PyConstraintBinding.h"
61 #include "PHY_IPhysicsEnvironment.h"
62 #include "SumoPhysicsEnvironment.h"
63
64 #include "SND_Scene.h"
65 #include "SND_IAudioDevice.h"
66
67 #include "NG_NetworkScene.h"
68 #include "NG_NetworkDeviceInterface.h"
69
70 #include "KX_WorldInfo.h"
71 #include "KX_ISceneConverter.h"
72 #include "KX_TimeCategoryLogger.h"
73
74 #include "RAS_FramingManager.h"
75 #include "stdio.h"
76
77 // If define: little test for Nzc: guarded drawing. If the canvas is
78 // not valid, skip rendering this frame.
79 //#define NZC_GUARDED_OUTPUT
80 #define DEFAULT_LOGIC_TIC_RATE 60.0
81 #define DEFAULT_PHYSICS_TIC_RATE 60.0
82
83 const char KX_KetsjiEngine::m_profileLabels[tc_numCategories][15] = {
84         "Physics:",             // tc_physics
85         "Logic",                // tc_logic
86         "Network:",             // tc_network
87         "Scenegraph:",  // tc_scenegraph
88         "Sound:",               // tc_sound
89         "Rasterizer:",  // tc_rasterizer
90         "Services:",    // tc_services
91         "Overhead:",    // tc_overhead
92         "Outside:"              // tc_outside
93 };
94
95 double KX_KetsjiEngine::m_ticrate = DEFAULT_LOGIC_TIC_RATE;
96 double KX_KetsjiEngine::m_anim_framerate = 25.0;
97 double KX_KetsjiEngine::m_suspendedtime = 0.0;
98 double KX_KetsjiEngine::m_suspendeddelta = 0.0;
99
100
101 /**
102  *      Constructor of the Ketsji Engine
103  */
104 KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
105      :  m_canvas(NULL),
106         m_rasterizer(NULL),
107         m_kxsystem(system),
108         m_rendertools(NULL),
109         m_sceneconverter(NULL),
110         m_networkdevice(NULL),
111         m_audiodevice(NULL),
112         m_pythondictionary(NULL),
113         m_keyboarddevice(NULL),
114         m_mousedevice(NULL),
115
116         m_propertiesPresent(false),
117
118         m_bInitialized(false),
119         m_activecam(0),
120         m_bFixedTime(false),
121         m_game2ipo(false),
122         
123         m_firstframe(true),
124         
125         m_frameTime(0.f),
126         m_clockTime(0.f),
127         m_previousClockTime(0.f),
128
129
130         m_exitcode(KX_EXIT_REQUEST_NO_REQUEST),
131         m_exitstring(""),
132         
133         m_drawingmode(5),
134         m_cameraZoom(1.0),
135         
136         m_overrideCam(false),
137         m_overrideCamUseOrtho(false),
138
139         m_stereo(false),
140         m_curreye(0),
141
142         m_logger(NULL),
143         
144         // Set up timing info display variables
145         m_show_framerate(false),
146         m_show_profile(false),
147         m_showProperties(false),
148         m_showBackground(false),
149         m_show_debug_properties(false),
150
151         // Default behavior is to hide the cursor every frame.
152         m_hideCursor(false),
153
154         m_overrideFrameColor(false),
155         m_overrideFrameColorR(0.0),
156         m_overrideFrameColorG(0.0),
157         m_overrideFrameColorB(0.0)
158 {
159         // Initialize the time logger
160         m_logger = new KX_TimeCategoryLogger (25);
161
162         for (int i = tc_first; i < tc_numCategories; i++)
163                 m_logger->AddCategory((KX_TimeCategory)i);
164                 
165 }
166
167
168
169 /**
170  *      Destructor of the Ketsji Engine, release all memory
171  */
172 KX_KetsjiEngine::~KX_KetsjiEngine()
173 {
174         delete m_logger;
175 }
176
177
178
179 void KX_KetsjiEngine::SetKeyboardDevice(SCA_IInputDevice* keyboarddevice)
180 {
181         MT_assert(keyboarddevice);
182         m_keyboarddevice = keyboarddevice;
183 }
184
185
186
187 void KX_KetsjiEngine::SetMouseDevice(SCA_IInputDevice* mousedevice)
188 {
189         MT_assert(mousedevice);
190         m_mousedevice = mousedevice;
191 }
192
193
194
195 void KX_KetsjiEngine::SetNetworkDevice(NG_NetworkDeviceInterface* networkdevice)
196 {
197         MT_assert(networkdevice);
198         m_networkdevice = networkdevice;
199 }
200
201
202
203 void KX_KetsjiEngine::SetAudioDevice(SND_IAudioDevice* audiodevice)
204 {
205         MT_assert(audiodevice);
206         m_audiodevice = audiodevice;
207 }
208
209
210
211 void KX_KetsjiEngine::SetCanvas(RAS_ICanvas* canvas)
212 {
213         MT_assert(canvas);
214         m_canvas = canvas;
215 }
216
217
218
219 void KX_KetsjiEngine::SetRenderTools(RAS_IRenderTools* rendertools)
220 {
221         MT_assert(rendertools);
222         m_rendertools = rendertools;
223 }
224
225
226
227 void KX_KetsjiEngine::SetRasterizer(RAS_IRasterizer* rasterizer)
228 {
229         MT_assert(rasterizer);
230         m_rasterizer = rasterizer;
231 }
232
233
234 /*
235  * At the moment the GameLogic module is imported into 'pythondictionary' after this function is called.
236  * if this function ever changes to assign a copy, make sure the game logic module is imported into this dictionary before hand.
237  */
238 void KX_KetsjiEngine::SetPythonDictionary(PyObject* pythondictionary)
239 {
240         MT_assert(pythondictionary);
241         m_pythondictionary = pythondictionary;
242 }
243
244
245
246 void KX_KetsjiEngine::SetSceneConverter(KX_ISceneConverter* sceneconverter)
247 {
248         MT_assert(sceneconverter);
249         m_sceneconverter = sceneconverter;
250 }
251
252
253
254 /**
255  * Ketsji Init(), Initializes datastructures and converts data from
256  * Blender into Ketsji native (realtime) format also sets up the
257  * graphics context
258  */
259 void KX_KetsjiEngine::StartEngine(bool clearIpo)
260 {
261         m_clockTime = m_kxsystem->GetTimeInSeconds();
262         m_frameTime = m_kxsystem->GetTimeInSeconds();
263         m_previousClockTime = m_kxsystem->GetTimeInSeconds();
264
265         m_firstframe = true;
266         m_bInitialized = true;
267         m_ticrate = DEFAULT_LOGIC_TIC_RATE;
268         
269         if (m_game2ipo)
270         {
271                 m_sceneconverter->ResetPhysicsObjectsAnimationIpo(clearIpo);
272                 m_sceneconverter->WritePhysicsObjectToAnimationIpo(m_currentFrame);
273         }
274
275 }
276
277 bool KX_KetsjiEngine::BeginFrame()
278 {
279         bool result = false;
280
281         RAS_Rect vp;
282         KX_Scene* firstscene = *m_scenes.begin();
283         const RAS_FrameSettings &framesettings = firstscene->GetFramingType();
284
285         // set the area used for rendering
286         m_rasterizer->SetRenderArea();
287
288         RAS_FramingManager::ComputeViewport(framesettings, m_canvas->GetDisplayArea(), vp);
289
290         if (m_canvas->BeginDraw())
291         {
292                 result = true;
293
294                 m_canvas->SetViewPort(vp.GetLeft(), vp.GetBottom(), vp.GetRight(), vp.GetTop());
295                 SetBackGround( firstscene->GetWorldInfo() );
296                 m_rasterizer->BeginFrame( m_drawingmode , m_kxsystem->GetTimeInSeconds());
297                 m_rendertools->BeginFrame( m_rasterizer);
298         }
299         
300         return result;
301 }               
302
303
304 void KX_KetsjiEngine::EndFrame()
305 {
306         // Show profiling info
307         m_logger->StartLog(tc_overhead, m_kxsystem->GetTimeInSeconds(), true);
308         if (m_show_framerate || m_show_profile || (m_show_debug_properties && m_propertiesPresent))
309         {
310                 RenderDebugProperties();
311         }
312         // Go to next profiling measurement, time spend after this call is shown in the next frame.
313         m_logger->NextMeasurement(m_kxsystem->GetTimeInSeconds());
314
315         m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
316         m_rasterizer->EndFrame();
317         // swap backbuffer (drawing into this buffer) <-> front/visible buffer
318         m_rasterizer->SwapBuffers();
319         m_rendertools->EndFrame(m_rasterizer);
320
321         
322         m_canvas->EndDraw();
323         
324
325 }
326
327 //#include "PIL_time.h"
328 //#include "LinearMath/btQuickprof.h"
329
330
331 bool KX_KetsjiEngine::NextFrame()
332 {
333
334 //      static hidden::Clock sClock;
335
336 m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(),true);
337
338 //float dt = sClock.getTimeMicroseconds() * 0.000001f;
339 //sClock.reset();
340
341 if (m_bFixedTime)
342         m_clockTime += 1./m_ticrate;
343 else
344 {
345
346 //      m_clockTime += dt;
347         m_clockTime = m_kxsystem->GetTimeInSeconds();
348 }
349         
350         double deltatime = m_clockTime - m_frameTime;
351         if (deltatime<0.f)
352         {
353                 printf("problem with clock\n");
354                 deltatime = 0.f;
355                 m_clockTime = 0.f;
356                 m_frameTime = 0.f;
357         }
358
359
360         // Compute the number of logic frames to do each update (fixed tic bricks)
361         int frames =int(deltatime*m_ticrate);
362 //      if (frames>1)
363 //              printf("****************************************");
364 //      printf("dt = %f, deltatime = %f, frames = %d\n",dt, deltatime,frames);
365         
366 //      if (!frames)
367 //              PIL_sleep_ms(1);
368         
369         KX_SceneList::iterator sceneit;
370         int frameOut = 5;
371         
372         if (frames>frameOut)
373         {
374         
375         //      printf("framedOut: %d\n",frames);
376                 m_frameTime+=(frames-frameOut)*(1.0/m_ticrate);
377                 frames = frameOut;
378         }
379         
380
381         bool doRender = frames>0;
382
383         while (frames)
384         {
385         
386
387                 m_frameTime += 1.0/m_ticrate;
388                 
389                 for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
390                 // for each scene, call the proceed functions
391                 {
392                         KX_Scene* scene = *sceneit;
393         
394                         /* Suspension holds the physics and logic processing for an
395                         * entire scene. Objects can be suspended individually, and
396                         * the settings for that preceed the logic and physics
397                         * update. */
398                         m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
399
400                         m_sceneconverter->resetNoneDynamicObjectToIpo();//this is for none dynamic objects with ipo
401
402                         scene->UpdateObjectActivity();
403         
404                         if (!scene->IsSuspended())
405                         {
406                                 // if the scene was suspended recalcutlate the delta tu "curtime"
407                                 m_suspendedtime = scene->getSuspendedTime();
408                                 if (scene->getSuspendedTime()!=0.0)
409                                         scene->setSuspendedDelta(scene->getSuspendedDelta()+m_clockTime-scene->getSuspendedTime());
410                                 m_suspendeddelta = scene->getSuspendedDelta();
411
412                                 
413                                 m_logger->StartLog(tc_network, m_kxsystem->GetTimeInSeconds(), true);
414                                 scene->GetNetworkScene()->proceed(m_frameTime);
415         
416                                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
417                                 scene->UpdateParents(m_frameTime);
418                                 
419                                 m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
420                                 // set Python hooks for each scene
421                                 PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
422                                 PHY_SetActiveScene(scene);
423         
424                                 scene->GetPhysicsEnvironment()->endFrame();
425                                 
426                                 // Update scenegraph after physics step. This maps physics calculations
427                                 // into node positions.         
428                                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
429                                 scene->UpdateParents(m_frameTime);
430                                 
431                                 // Process sensors, and controllers
432                                 m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
433                                 scene->LogicBeginFrame(m_frameTime);
434         
435                                 // Scenegraph needs to be updated again, because Logic Controllers 
436                                 // can affect the local matrices.
437                                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
438                                 scene->UpdateParents(m_frameTime);
439         
440                                 // Process actuators
441         
442                                 // Do some cleanup work for this logic frame
443                                 m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
444                                 scene->LogicUpdateFrame(m_frameTime, true);
445                                 
446                                 scene->LogicEndFrame();
447         
448                                 // Actuators can affect the scenegraph
449                                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
450                                 scene->UpdateParents(m_frameTime);
451                                 
452                                 m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
453                                 scene->GetPhysicsEnvironment()->beginFrame();
454                 
455                                 // Perform physics calculations on the scene. This can involve 
456                                 // many iterations of the physics solver.
457                                 scene->GetPhysicsEnvironment()->proceedDeltaTime(m_frameTime,1.0/m_ticrate);//m_deltatimerealDeltaTime);
458
459                                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
460                                 scene->UpdateParents(m_frameTime);
461                         
462                         
463                                 if (m_game2ipo)
464                                 {                                       
465                                         m_sceneconverter->WritePhysicsObjectToAnimationIpo(++m_currentFrame);
466                                 }
467
468                                 scene->setSuspendedTime(0.0);
469                         } // suspended
470                         else
471                                 if(scene->getSuspendedTime()==0.0)
472                                         scene->setSuspendedTime(m_clockTime);
473         
474                         DoSound(scene);
475                         
476                         m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true);
477                 }
478
479                 // update system devices
480                 m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
481                 if (m_keyboarddevice)
482                         m_keyboarddevice->NextFrame();
483         
484                 if (m_mousedevice)
485                         m_mousedevice->NextFrame();
486                 
487                 if (m_networkdevice)
488                         m_networkdevice->NextFrame();
489         
490                 if (m_audiodevice)
491                         m_audiodevice->NextFrame();
492         
493                 // scene management
494                 ProcessScheduledScenes();
495                 
496                 frames--;
497         }
498
499         bool bUseAsyncLogicBricks= false;//true;
500
501         if (bUseAsyncLogicBricks)
502         {       
503                 // Logic update sub frame: this will let some logic bricks run at the
504                 // full frame rate.
505                 for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
506                 // for each scene, call the proceed functions
507                 {
508                         KX_Scene* scene = *sceneit;
509
510                         if (!scene->IsSuspended())
511                         {
512                                 // if the scene was suspended recalcutlate the delta tu "curtime"
513                                 m_suspendedtime = scene->getSuspendedTime();
514                                 if (scene->getSuspendedTime()!=0.0)
515                                         scene->setSuspendedDelta(scene->getSuspendedDelta()+m_clockTime-scene->getSuspendedTime());
516                                 m_suspendeddelta = scene->getSuspendedDelta();
517                                 
518                                 // set Python hooks for each scene
519                                 PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
520                                 PHY_SetActiveScene(scene);
521                                 
522                                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
523                                 scene->UpdateParents(m_clockTime);
524
525                                 // Perform physics calculations on the scene. This can involve 
526                                 // many iterations of the physics solver.
527                                 m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
528                                 scene->GetPhysicsEnvironment()->proceedDeltaTime(m_clockTime,0.f);
529                                 // Update scenegraph after physics step. This maps physics calculations
530                                 // into node positions.         
531                                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
532                                 scene->UpdateParents(m_clockTime);
533                                 
534                                 // Do some cleanup work for this logic frame
535                                 m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
536                                 scene->LogicUpdateFrame(m_clockTime, false);
537
538                                 // Actuators can affect the scenegraph
539                                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
540                                 scene->UpdateParents(m_clockTime);
541                                  
542                                 scene->setSuspendedTime(0.0);
543                         } // suspended
544                         else
545                                 if(scene->getSuspendedTime()==0.0)
546                                         scene->setSuspendedTime(m_clockTime);
547
548                         DoSound(scene);
549
550                         m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true);
551                 }
552         }
553
554
555         m_previousClockTime = m_clockTime;
556         
557         // Start logging time spend outside main loop
558         m_logger->StartLog(tc_outside, m_kxsystem->GetTimeInSeconds(), true);
559         
560         return doRender;
561 }
562
563
564
565 void KX_KetsjiEngine::Render()
566 {
567         KX_Scene* firstscene = *m_scenes.begin();
568         const RAS_FrameSettings &framesettings = firstscene->GetFramingType();
569
570         m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
571
572         // hiding mouse cursor each frame
573         // (came back when going out of focus and then back in again)
574         if (m_hideCursor)
575                 m_canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
576
577         // clear the entire game screen with the border color
578         // only once per frame
579         m_canvas->BeginDraw();
580         if (m_drawingmode == RAS_IRasterizer::KX_TEXTURED) {
581                 m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight());
582                 if (m_overrideFrameColor)
583                 {
584                         // Do not use the framing bar color set in the Blender scenes
585                         m_canvas->ClearColor(
586                                 m_overrideFrameColorR,
587                                 m_overrideFrameColorG,
588                                 m_overrideFrameColorB,
589                                 1.0
590                                 );
591                 }
592                 else
593                 {
594                         // Use the framing bar color set in the Blender scenes
595                         m_canvas->ClearColor(
596                                 framesettings.BarRed(),
597                                 framesettings.BarGreen(),
598                                 framesettings.BarBlue(),
599                                 1.0
600                                 );
601                 }
602                 // clear the -whole- viewport
603                 m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER);
604         }
605
606         m_rasterizer->SetEye(RAS_IRasterizer::RAS_STEREO_LEFTEYE);
607
608         // BeginFrame() sets the actual drawing area. You can use a part of the window
609         if (!BeginFrame())
610                 return;
611
612         KX_SceneList::iterator sceneit;
613         for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++)
614         // for each scene, call the proceed functions
615         {
616                 KX_Scene* scene = *sceneit;
617                 KX_Camera* cam = scene->GetActiveCamera();
618                 // pass the scene's worldsettings to the rasterizer
619                 SetWorldSettings(scene->GetWorldInfo());
620
621                 // shadow buffers
622                 RenderShadowBuffers(scene);
623
624                 // Avoid drawing the scene with the active camera twice when it's viewport is enabled
625                 if(cam && !cam->GetViewport())
626                 {
627                         if (scene->IsClearingZBuffer())
628                                 m_rasterizer->ClearDepthBuffer();
629         
630                         m_rendertools->SetAuxilaryClientInfo(scene);
631         
632                         //Initialize scene viewport.
633                         SetupRenderFrame(scene, cam);
634         
635                         // do the rendering
636                         RenderFrame(scene, cam);
637                 }
638                 
639                 list<class KX_Camera*>* cameras = scene->GetCameras();
640                 
641                 // Draw the scene once for each camera with an enabled viewport
642                 list<KX_Camera*>::iterator it = cameras->begin();
643                 while(it != cameras->end())
644                 {
645                         if((*it)->GetViewport())
646                         {
647                                 if (scene->IsClearingZBuffer())
648                                         m_rasterizer->ClearDepthBuffer();
649                 
650                                 m_rendertools->SetAuxilaryClientInfo(scene);
651                 
652                                 //Initialize scene viewport.
653                                 SetupRenderFrame(scene, (*it));
654                 
655                                 // do the rendering
656                                 RenderFrame(scene, (*it));
657                         }
658                         
659                         it++;
660                 }
661         }
662
663         // only one place that checks for stereo
664         if(m_rasterizer->Stereo())
665         {
666                 m_rasterizer->SetEye(RAS_IRasterizer::RAS_STEREO_RIGHTEYE);
667
668                 if (!BeginFrame())
669                         return;
670
671                 KX_SceneList::iterator sceneit;
672                 for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++)
673                 // for each scene, call the proceed functions
674                 {
675                         KX_Scene* scene = *sceneit;
676                         KX_Camera* cam = scene->GetActiveCamera();
677
678                         // pass the scene's worldsettings to the rasterizer
679                         SetWorldSettings(scene->GetWorldInfo());
680                 
681                         if (scene->IsClearingZBuffer())
682                                 m_rasterizer->ClearDepthBuffer();
683
684                         //pass the scene, for picking and raycasting (shadows)
685                         m_rendertools->SetAuxilaryClientInfo(scene);
686
687                         //Initialize scene viewport.
688                         //SetupRenderFrame(scene);
689                         SetupRenderFrame(scene, cam);
690
691                         // do the rendering
692                         //RenderFrame(scene);
693                         RenderFrame(scene, cam);
694                 }
695         } // if(m_rasterizer->Stereo())
696
697         EndFrame();
698 }
699
700
701
702 void KX_KetsjiEngine::RequestExit(int exitrequestmode)
703 {
704         m_exitcode = exitrequestmode;
705 }
706
707
708
709 void KX_KetsjiEngine::SetNameNextGame(const STR_String& nextgame)
710 {
711         m_exitstring = nextgame;
712 }
713
714
715
716 int KX_KetsjiEngine::GetExitCode()
717 {
718         // if a gameactuator has set an exitcode or if there are no scenes left
719         if (!m_exitcode)
720         {
721                 if (m_scenes.begin()==m_scenes.end())
722                         m_exitcode = KX_EXIT_REQUEST_NO_SCENES_LEFT;
723         }
724
725         return m_exitcode;
726 }
727
728
729
730 const STR_String& KX_KetsjiEngine::GetExitString()
731 {
732         return m_exitstring;
733 }
734
735
736
737 void KX_KetsjiEngine::DoSound(KX_Scene* scene)
738 {
739         m_logger->StartLog(tc_sound, m_kxsystem->GetTimeInSeconds(), true);
740
741         KX_Camera* cam = scene->GetActiveCamera();
742         if (!cam)
743                 return;
744         MT_Point3 listenerposition = cam->NodeGetWorldPosition();
745         MT_Vector3 listenervelocity = cam->GetLinearVelocity();
746         MT_Matrix3x3 listenerorientation = cam->NodeGetWorldOrientation();
747
748         SND_Scene* soundscene = scene->GetSoundScene();
749         soundscene->SetListenerTransform(
750                 listenerposition,
751                 listenervelocity,
752                 listenerorientation);
753
754         soundscene->Proceed();
755 }
756
757
758
759 void KX_KetsjiEngine::SetBackGround(KX_WorldInfo* wi)
760 {
761         if (wi->hasWorld())
762         {
763                 if (m_drawingmode == RAS_IRasterizer::KX_TEXTURED)
764                 {       
765                         m_rasterizer->SetBackColor(
766                                 wi->getBackColorRed(),
767                                 wi->getBackColorGreen(),
768                                 wi->getBackColorBlue(),
769                                 0.0
770                         );
771                 }
772         }
773 }
774
775
776
777 void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi)
778 {
779         if (wi->hasWorld())
780         {
781                 // ...
782                 m_rasterizer->SetAmbientColor(
783                         wi->getAmbientColorRed(),
784                         wi->getAmbientColorGreen(),
785                         wi->getAmbientColorBlue()
786                 );
787
788                 if (m_drawingmode == RAS_IRasterizer::KX_TEXTURED)
789                 {       
790                         if (wi->hasMist())
791                         {
792                                 m_rasterizer->SetFog(
793                                         wi->getMistStart(),
794                                         wi->getMistDistance(),
795                                         wi->getMistColorRed(),
796                                         wi->getMistColorGreen(),
797                                         wi->getMistColorBlue()
798                                 );
799                         }
800                         else
801                         {
802                                 m_rasterizer->DisableFog();
803                         }
804                 }
805         }
806 }
807
808
809
810 void KX_KetsjiEngine::SetDrawType(int drawingmode)
811 {
812         m_drawingmode = drawingmode;
813 }
814
815
816         
817 void KX_KetsjiEngine::EnableCameraOverride(const STR_String& forscene)
818 {
819         m_overrideCam = true;
820         m_overrideSceneName = forscene;
821 }
822
823
824
825 void KX_KetsjiEngine::SetCameraZoom(float camzoom)
826 {
827         m_cameraZoom = camzoom;
828 }
829
830
831
832 void KX_KetsjiEngine::SetCameraOverrideUseOrtho(bool useOrtho)
833 {
834         m_overrideCamUseOrtho = useOrtho;
835 }
836
837
838
839 void KX_KetsjiEngine::SetCameraOverrideProjectionMatrix(const MT_CmMatrix4x4& mat)
840 {
841         m_overrideCamProjMat = mat;
842 }
843
844
845 void KX_KetsjiEngine::SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat)
846 {
847         m_overrideCamViewMat = mat;
848 }
849
850         
851 void KX_KetsjiEngine::SetupRenderFrame(KX_Scene *scene, KX_Camera* cam)
852 {
853         // In this function we make sure the rasterizer settings are upto
854         // date. We compute the viewport so that logic
855         // using this information is upto date.
856
857         // Note we postpone computation of the projection matrix
858         // so that we are using the latest camera position.
859
860         RAS_Rect viewport;
861
862         if (!cam)
863                 return;
864
865         if (cam->GetViewport()) {
866                 viewport.SetLeft(cam->GetViewportLeft()); 
867                 viewport.SetBottom(cam->GetViewportBottom());
868                 viewport.SetRight(cam->GetViewportRight());
869                 viewport.SetTop(cam->GetViewportTop());
870         }
871         else if ( m_overrideCam || (scene->GetName() != m_overrideSceneName) ||  m_overrideCamUseOrtho ) {
872                 RAS_FramingManager::ComputeViewport(
873                         scene->GetFramingType(),
874                         m_canvas->GetDisplayArea(),
875                         viewport
876                 );
877         } else {
878                 viewport.SetLeft(0); 
879                 viewport.SetBottom(0);
880                 viewport.SetRight(int(m_canvas->GetWidth()));
881                 viewport.SetTop(int(m_canvas->GetHeight()));
882         }
883         // store the computed viewport in the scene
884
885         scene->SetSceneViewport(viewport);      
886
887         // set the viewport for this frame and scene
888         m_canvas->SetViewPort(
889                 viewport.GetLeft(),
890                 viewport.GetBottom(),
891                 viewport.GetRight(),
892                 viewport.GetTop()
893         );      
894
895 }
896
897 void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
898 {
899         CListValue *lightlist = scene->GetLightList();
900         int i, drawmode;
901
902         for(i=0; i<lightlist->GetCount(); i++) {
903                 KX_LightObject *light = (KX_LightObject*)lightlist->GetValue(i);
904
905                 light->Update();
906
907                 if(m_drawingmode == RAS_IRasterizer::KX_TEXTURED && light->HasShadowBuffer()) {
908                         /* make temporary camera */
909                         RAS_CameraData camdata = RAS_CameraData();
910                         KX_Camera *cam = new KX_Camera(scene, scene->m_callbacks, camdata, false);
911                         cam->SetName("__shadow__cam__");
912
913                         MT_Transform camtrans;
914
915                         /* switch drawmode for speed */
916                         drawmode = m_rasterizer->GetDrawingMode();
917                         m_rasterizer->SetDrawingMode(RAS_IRasterizer::KX_SHADOW);
918
919                         /* binds framebuffer object, sets up camera .. */
920                         light->BindShadowBuffer(m_rasterizer, cam, camtrans);
921
922                         /* update scene */
923                         scene->UpdateMeshTransformations();
924                         scene->CalculateVisibleMeshes(m_rasterizer, cam, light->GetShadowLayer());
925
926                         /* render */
927                         m_rasterizer->ClearDepthBuffer();
928                         scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
929
930                         /* unbind framebuffer object, restore drawmode, free camera */
931                         light->UnbindShadowBuffer(m_rasterizer);
932                         m_rasterizer->SetDrawingMode(drawmode);
933                         cam->Release();
934                 }
935         }
936 }
937         
938 // update graphics
939 void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
940 {
941         float left, right, bottom, top, nearfrust, farfrust, focallength;
942         const float ortho = 100.0;
943 //      KX_Camera* cam = scene->GetActiveCamera();
944         
945         if (!cam)
946                 return;
947         
948         // see KX_BlenderMaterial::Activate
949         //m_rasterizer->SetAmbient();
950         m_rasterizer->DisplayFog();
951
952         if (m_overrideCam && (scene->GetName() == m_overrideSceneName) && m_overrideCamUseOrtho) {
953                 MT_CmMatrix4x4 projmat = m_overrideCamProjMat;
954                 m_rasterizer->SetProjectionMatrix(projmat);
955         } else if (cam->hasValidProjectionMatrix() && !cam->GetViewport() )
956         {
957                 m_rasterizer->SetProjectionMatrix(cam->GetProjectionMatrix());
958         } else
959         {
960                 RAS_FrameFrustum frustum;
961                 float lens = cam->GetLens();
962                 nearfrust = cam->GetCameraNear();
963                 farfrust = cam->GetCameraFar();
964                 focallength = cam->GetFocalLength();
965
966                 if (!cam->GetCameraData()->m_perspective)
967                 {
968                         lens *= ortho;
969                         nearfrust = (nearfrust + 1.0)*ortho;
970                         farfrust *= ortho;
971                 }
972                 
973                 RAS_FramingManager::ComputeFrustum(
974                         scene->GetFramingType(),
975                         m_canvas->GetDisplayArea(),
976                         scene->GetSceneViewport(),
977                         lens,
978                         nearfrust,
979                         farfrust,
980                         frustum
981                 );
982
983                 left = frustum.x1 * m_cameraZoom;
984                 right = frustum.x2 * m_cameraZoom;
985                 bottom = frustum.y1 * m_cameraZoom;
986                 top = frustum.y2 * m_cameraZoom;
987                 nearfrust = frustum.camnear;
988                 farfrust = frustum.camfar;
989
990                 MT_Matrix4x4 projmat = m_rasterizer->GetFrustumMatrix(
991                         left, right, bottom, top, nearfrust, farfrust, focallength);
992         
993                 cam->SetProjectionMatrix(projmat);
994                 
995                 // Otherwise the projection matrix for each eye will be the same...
996                 if (m_rasterizer->Stereo())
997                         cam->InvalidateProjectionMatrix();
998         }
999
1000         MT_Transform camtrans(cam->GetWorldToCamera());
1001         if (!cam->GetCameraData()->m_perspective)
1002                 camtrans.getOrigin()[2] *= ortho;
1003         MT_Matrix4x4 viewmat(camtrans);
1004         
1005         m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldPosition(),
1006                 cam->GetCameraLocation(), cam->GetCameraOrientation());
1007         cam->SetModelviewMatrix(viewmat);
1008
1009         scene->UpdateMeshTransformations();
1010
1011         // The following actually reschedules all vertices to be
1012         // redrawn. There is a cache between the actual rescheduling
1013         // and this call though. Visibility is imparted when this call
1014         // runs through the individual objects.
1015         scene->CalculateVisibleMeshes(m_rasterizer,cam);
1016
1017         scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
1018         
1019         PostRenderFrame();
1020 }
1021
1022 void KX_KetsjiEngine::PostRenderFrame()
1023 {
1024         m_rendertools->PushMatrix();
1025         m_rendertools->Render2DFilters(m_canvas);
1026         m_rendertools->MotionBlur(m_rasterizer);
1027         m_rendertools->PopMatrix();
1028 }
1029
1030 void KX_KetsjiEngine::StopEngine()
1031 {
1032         if (m_bInitialized)
1033         {
1034
1035                 if (m_game2ipo)
1036                 {
1037 //                      printf("TestHandlesPhysicsObjectToAnimationIpo\n");
1038                         m_sceneconverter->TestHandlesPhysicsObjectToAnimationIpo();
1039                 }
1040
1041                 KX_SceneList::iterator sceneit;
1042                 for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
1043                 {
1044                         KX_Scene* scene = *sceneit;
1045                         m_sceneconverter->RemoveScene(scene);
1046                 }       
1047                 m_scenes.clear();
1048
1049                 // cleanup all the stuff                
1050                 m_rasterizer->Exit();
1051         }
1052 }
1053
1054 // Scene Management is able to switch between scenes
1055 // and have several scene's running in parallel
1056 void KX_KetsjiEngine::AddScene(KX_Scene* scene)
1057
1058         m_scenes.push_back(scene);
1059         PostProcessScene(scene);
1060         SceneListsChanged();
1061 }
1062
1063
1064
1065 void KX_KetsjiEngine::PostProcessScene(KX_Scene* scene)
1066 {
1067         bool override_camera = (m_overrideCam && (scene->GetName() == m_overrideSceneName));
1068         
1069                 // if there is no activecamera, or the camera is being
1070                 // overridden we need to construct a temporarily camera
1071         if (!scene->GetActiveCamera() || override_camera)
1072         {
1073                 KX_Camera* activecam = NULL;
1074
1075                 RAS_CameraData camdata = RAS_CameraData();
1076                 activecam = new KX_Camera(scene,KX_Scene::m_callbacks,camdata, false);
1077                 activecam->SetName("__default__cam__");
1078         
1079                         // set transformation
1080                 if (override_camera) {
1081                         const MT_CmMatrix4x4& cammatdata = m_overrideCamViewMat;
1082                         MT_Transform trans = MT_Transform(cammatdata.getPointer());
1083                         MT_Transform camtrans;
1084                         camtrans.invert(trans);
1085                         
1086                         activecam->NodeSetLocalPosition(camtrans.getOrigin());
1087                         activecam->NodeSetLocalOrientation(camtrans.getBasis());
1088                         activecam->NodeUpdateGS(0,true);
1089                 } else {
1090                         activecam->NodeSetLocalPosition(MT_Point3(0.0, 0.0, 0.0));
1091                         activecam->NodeSetLocalOrientation(MT_Vector3(0.0, 0.0, 0.0));
1092                         activecam->NodeUpdateGS(0,true);
1093                 }
1094
1095                 scene->AddCamera(activecam);
1096                 scene->SetActiveCamera(activecam);
1097                 scene->GetObjectList()->Add(activecam->AddRef());
1098                 scene->GetRootParentList()->Add(activecam->AddRef());
1099                 //done with activecam
1100                 activecam->Release();
1101         }
1102         
1103         scene->UpdateParents(0.0);
1104 }
1105
1106
1107
1108 void KX_KetsjiEngine::RenderDebugProperties()
1109 {
1110         STR_String debugtxt;
1111         int xcoord = 10;        // mmmm, these constants were taken from blender source
1112         int ycoord = 14;        // to 'mimic' behaviour
1113
1114         float tottime = m_logger->GetAverage();
1115         if (tottime < 1e-6f) {
1116                 tottime = 1e-6f;
1117         }
1118
1119         // Set viewport to entire canvas
1120         RAS_Rect viewport;
1121         m_canvas->SetViewPort(0, 0, int(m_canvas->GetWidth()), int(m_canvas->GetHeight()));
1122         
1123         /* Framerate display */
1124         if (m_show_framerate) {
1125                 debugtxt.Format("swap : %.3f (%.3f frames per second)", tottime, 1.0/tottime);
1126                 m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, 
1127                                                                         debugtxt.Ptr(),
1128                                                                         xcoord,
1129                                                                         ycoord, 
1130                                                                         m_canvas->GetWidth() /* RdV, TODO ?? */, 
1131                                                                         m_canvas->GetHeight() /* RdV, TODO ?? */);
1132                 ycoord += 14;
1133         }
1134
1135         /* Profile and framerate display */
1136         if (m_show_profile)
1137         {               
1138                 for (int j = tc_first; j < tc_numCategories; j++)
1139                 {
1140                         debugtxt.Format(m_profileLabels[j]);
1141                         m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, 
1142                                                                                 debugtxt.Ptr(),
1143                                                                                 xcoord,ycoord,
1144                                                                                 m_canvas->GetWidth(), 
1145                                                                                 m_canvas->GetHeight());
1146                         double time = m_logger->GetAverage((KX_TimeCategory)j);
1147                         debugtxt.Format("%2.2f %%", time/tottime * 100.f);
1148                         m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, 
1149                                                                                 debugtxt.Ptr(),
1150                                                                                 xcoord + 60 ,ycoord,
1151                                                                                 m_canvas->GetWidth(), 
1152                                                                                 m_canvas->GetHeight());
1153                         ycoord += 14;
1154                 }
1155         }
1156
1157         /* Property display*/
1158         if (m_show_debug_properties && m_propertiesPresent)
1159         {
1160                 KX_SceneList::iterator sceneit;
1161                 for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
1162                 {
1163                         KX_Scene* scene = *sceneit;
1164                         /* the 'normal' debug props */
1165                         vector<SCA_DebugProp*>& debugproplist = scene->GetDebugProperties();
1166                         
1167                         for (vector<SCA_DebugProp*>::iterator it = debugproplist.begin();
1168                                  !(it==debugproplist.end());it++)
1169                         {
1170                                 CValue* propobj = (*it)->m_obj;
1171                                 STR_String objname = propobj->GetName();
1172                                 STR_String propname = (*it)->m_name;
1173                                 CValue* propval = propobj->GetProperty(propname);
1174                                 if (propval)
1175                                 {
1176                                         STR_String text = propval->GetText();
1177                                         debugtxt = objname + "." + propname + " = " + text;
1178                                         m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, 
1179                                                                                                 debugtxt.Ptr(),
1180                                                                                                 xcoord,
1181                                                                                                 ycoord,
1182                                                                                                 m_canvas->GetWidth(),
1183                                                                                                 m_canvas->GetHeight());
1184                                         ycoord += 14;
1185                                 }
1186                         }
1187                 }
1188         }
1189 }
1190
1191
1192 KX_SceneList* KX_KetsjiEngine::CurrentScenes()
1193 {
1194         return &m_scenes;       
1195 }
1196
1197
1198
1199 KX_Scene* KX_KetsjiEngine::FindScene(const STR_String& scenename)
1200 {
1201         KX_SceneList::iterator sceneit = m_scenes.begin();
1202
1203         // bit risky :) better to split the second clause 
1204         while ( (sceneit != m_scenes.end()) 
1205                         && ((*sceneit)->GetName() != scenename))
1206         {
1207                 sceneit++;
1208         }
1209
1210         return ((sceneit == m_scenes.end()) ? NULL : *sceneit); 
1211 }
1212
1213
1214
1215 void KX_KetsjiEngine::ConvertAndAddScene(const STR_String& scenename,bool overlay)
1216 {
1217         // only add scene when it doesn't exist!
1218         if (FindScene(scenename))
1219         {
1220                 STR_String tmpname = scenename;
1221                 printf("warning: scene %s already exists, not added!\n",tmpname.Ptr());
1222         }
1223         else
1224         {
1225                 if (overlay)
1226                 {
1227                         m_addingOverlayScenes.insert(scenename);
1228                 }
1229                 else
1230                 {
1231                         m_addingBackgroundScenes.insert(scenename);
1232                 }
1233         }
1234 }
1235
1236
1237
1238
1239 void KX_KetsjiEngine::RemoveScene(const STR_String& scenename)
1240 {
1241         if (FindScene(scenename))
1242         {
1243                 m_removingScenes.insert(scenename);
1244         }
1245         else
1246         {
1247 //              STR_String tmpname = scenename;
1248                 std::cout << "warning: scene " << scenename << " does not exist, not removed!" << std::endl;
1249         }
1250 }
1251
1252
1253
1254 void KX_KetsjiEngine::RemoveScheduledScenes()
1255 {
1256         if (m_removingScenes.size())
1257         {
1258                 set<STR_String>::iterator scenenameit;
1259                 for (scenenameit=m_removingScenes.begin();scenenameit != m_removingScenes.end();scenenameit++)
1260                 {
1261                         STR_String scenename = *scenenameit;
1262
1263                         KX_SceneList::iterator sceneit;
1264                         for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
1265                         {
1266                                 KX_Scene* scene = *sceneit;
1267                                 if (scene->GetName()==scenename)
1268                                 {
1269                                         m_sceneconverter->RemoveScene(scene);
1270                                         m_scenes.erase(sceneit);
1271                                         break;
1272                                 }
1273                         }       
1274                 }
1275                 m_removingScenes.clear();
1276         }
1277 }
1278
1279
1280
1281 KX_Scene* KX_KetsjiEngine::CreateScene(const STR_String& scenename)
1282 {
1283
1284         KX_Scene* tmpscene = new KX_Scene(m_keyboarddevice,
1285                                                                           m_mousedevice,
1286                                                                           m_networkdevice,
1287                                                                           m_audiodevice,
1288                                                                           scenename);
1289
1290         m_sceneconverter->ConvertScene(scenename,
1291                                                           tmpscene,
1292                                                           m_pythondictionary,
1293                                                           m_keyboarddevice,
1294                                                           m_rendertools,
1295                                                           m_canvas);
1296
1297         return tmpscene;
1298 }
1299
1300
1301
1302 void KX_KetsjiEngine::AddScheduledScenes()
1303 {
1304         set<STR_String>::iterator scenenameit;
1305
1306         if (m_addingOverlayScenes.size())
1307         {
1308                 for (scenenameit = m_addingOverlayScenes.begin();
1309                         scenenameit != m_addingOverlayScenes.end();
1310                         scenenameit++)
1311                 {
1312                         STR_String scenename = *scenenameit;
1313                         KX_Scene* tmpscene = CreateScene(scenename);
1314                         m_scenes.push_back(tmpscene);
1315                         PostProcessScene(tmpscene);
1316                 }
1317                 m_addingOverlayScenes.clear();
1318         }
1319         
1320         if (m_addingBackgroundScenes.size())
1321         {
1322                 for (scenenameit = m_addingBackgroundScenes.begin();
1323                         scenenameit != m_addingBackgroundScenes.end();
1324                         scenenameit++)
1325                 {
1326                         STR_String scenename = *scenenameit;
1327                         KX_Scene* tmpscene = CreateScene(scenename);
1328                         m_scenes.insert(m_scenes.begin(),tmpscene);
1329                         PostProcessScene(tmpscene);
1330
1331                 }
1332                 m_addingBackgroundScenes.clear();
1333         }
1334 }
1335
1336
1337
1338 void KX_KetsjiEngine::ReplaceScene(const STR_String& oldscene,const STR_String& newscene)
1339 {
1340         m_replace_scenes.insert(std::make_pair(oldscene,newscene));
1341 }
1342
1343 // replace scene is not the same as removing and adding because the
1344 // scene must be in exact the same place (to maintain drawingorder)
1345 // (nzc) - should that not be done with a scene-display list? It seems
1346 // stupid to rely on the mem allocation order...
1347 void KX_KetsjiEngine::ReplaceScheduledScenes()
1348 {
1349         if (m_replace_scenes.size())
1350         {
1351                 set<pair<STR_String,STR_String> >::iterator scenenameit;
1352                 
1353                 for (scenenameit = m_replace_scenes.begin();
1354                         scenenameit != m_replace_scenes.end();
1355                         scenenameit++)
1356                 {
1357                         STR_String oldscenename = (*scenenameit).first;
1358                         STR_String newscenename = (*scenenameit).second;
1359                         int i=0;
1360                         /* Scenes are not supposed to be included twice... I think */
1361                         KX_SceneList::iterator sceneit;
1362                         for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
1363                         {
1364                                 KX_Scene* scene = *sceneit;
1365                                 if (scene->GetName() == oldscenename)
1366                                 {
1367                                         m_sceneconverter->RemoveScene(scene);
1368                                         KX_Scene* tmpscene = CreateScene(newscenename);
1369                                         m_scenes[i]=tmpscene;
1370                                         PostProcessScene(tmpscene);
1371                                 }
1372                                 i++;
1373                         }
1374                 }
1375                 m_replace_scenes.clear();
1376         }       
1377 }
1378
1379
1380
1381 void KX_KetsjiEngine::SuspendScene(const STR_String& scenename)
1382 {
1383         KX_Scene*  scene = FindScene(scenename);
1384         if (scene) scene->Suspend();
1385 }
1386
1387
1388
1389 void KX_KetsjiEngine::ResumeScene(const STR_String& scenename)
1390 {
1391         KX_Scene*  scene = FindScene(scenename);
1392         if (scene) scene->Resume();
1393 }
1394
1395
1396
1397 void KX_KetsjiEngine::SetUseFixedTime(bool bUseFixedTime)
1398 {
1399         m_bFixedTime = bUseFixedTime;
1400 }
1401
1402
1403 void    KX_KetsjiEngine::SetGame2IpoMode(bool game2ipo,int startFrame)
1404 {
1405         m_game2ipo = game2ipo;
1406         if (game2ipo)
1407         {
1408                 //when recording physics keyframes, always run at a fixed framerate
1409                 m_bFixedTime = true;
1410         }
1411         m_currentFrame = startFrame;
1412 }
1413
1414 bool KX_KetsjiEngine::GetUseFixedTime(void) const
1415 {
1416         return m_bFixedTime;
1417 }
1418
1419 double KX_KetsjiEngine::GetSuspendedDelta()
1420 {
1421         return m_suspendeddelta;
1422 }
1423
1424 double KX_KetsjiEngine::GetTicRate()
1425 {
1426         return m_ticrate;
1427 }
1428
1429 void KX_KetsjiEngine::SetTicRate(double ticrate)
1430 {
1431         m_ticrate = ticrate;
1432 }
1433
1434 double KX_KetsjiEngine::GetAnimFrameRate()
1435 {
1436         return m_anim_framerate;
1437 }
1438
1439 void KX_KetsjiEngine::SetAnimFrameRate(double framerate)
1440 {
1441         m_anim_framerate = framerate;
1442 }
1443
1444 void KX_KetsjiEngine::SetTimingDisplay(bool frameRate, bool profile, bool properties)
1445 {
1446         m_show_framerate = frameRate;
1447         m_show_profile = profile;
1448         m_show_debug_properties = properties;
1449 }
1450
1451
1452
1453 void KX_KetsjiEngine::GetTimingDisplay(bool& frameRate, bool& profile, bool& properties) const
1454 {
1455         frameRate = m_show_framerate;
1456         profile = m_show_profile;
1457         properties = m_show_debug_properties;
1458 }
1459
1460
1461
1462 void KX_KetsjiEngine::ProcessScheduledScenes(void)
1463 {
1464         // Check whether there will be changes to the list of scenes
1465         if (m_addingOverlayScenes.size() ||
1466                 m_addingBackgroundScenes.size() ||
1467                 m_replace_scenes.size() ||
1468                 m_removingScenes.size()) {
1469
1470                 // Change the scene list
1471                 ReplaceScheduledScenes();
1472                 RemoveScheduledScenes();
1473                 AddScheduledScenes();
1474
1475                 // Notify
1476                 SceneListsChanged();
1477         }
1478 }
1479
1480
1481
1482 void KX_KetsjiEngine::SceneListsChanged(void)
1483 {
1484         m_propertiesPresent = false;
1485         KX_SceneList::iterator sceneit = m_scenes.begin();
1486         while ((sceneit != m_scenes.end()) && (!m_propertiesPresent))
1487         {
1488                 KX_Scene* scene = *sceneit;
1489                 vector<SCA_DebugProp*>& debugproplist = scene->GetDebugProperties();    
1490                 m_propertiesPresent = !debugproplist.empty();
1491                 sceneit++;
1492         }
1493 }
1494
1495
1496 void KX_KetsjiEngine::SetHideCursor(bool hideCursor)
1497 {
1498         m_hideCursor = hideCursor;
1499 }
1500
1501
1502 bool KX_KetsjiEngine::GetHideCursor(void) const
1503 {
1504         return m_hideCursor;
1505 }
1506
1507
1508 void KX_KetsjiEngine::SetUseOverrideFrameColor(bool overrideFrameColor)
1509 {
1510         m_overrideFrameColor = overrideFrameColor;
1511 }
1512
1513
1514 bool KX_KetsjiEngine::GetUseOverrideFrameColor(void) const
1515 {
1516         return m_overrideFrameColor;
1517 }
1518
1519
1520 void KX_KetsjiEngine::SetOverrideFrameColor(float r, float g, float b)
1521 {
1522         m_overrideFrameColorR = r;
1523         m_overrideFrameColorG = g;
1524         m_overrideFrameColorB = b;
1525 }
1526
1527
1528 void KX_KetsjiEngine::GetOverrideFrameColor(float& r, float& g, float& b) const
1529 {
1530         r = m_overrideFrameColorR;
1531         g = m_overrideFrameColorG;
1532         b = m_overrideFrameColorB;
1533 }
1534
1535
1536