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