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