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