aeb80806f6cb56f91005a7fa9413ccc951471024
[blender-staging.git] / source / gameengine / Ketsji / KX_KetsjiEngine.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  * The engine ties all game modules together. 
29  */
30
31 #ifdef WIN32
32 #pragma warning (disable : 4786)
33 #endif //WIN32
34
35 #include <iostream>
36
37 #include "KX_KetsjiEngine.h"
38
39 #include "ListValue.h"
40 #include "IntValue.h"
41 #include "VectorValue.h"
42 #include "BoolValue.h"
43 #include "FloatValue.h"
44
45 #define KX_NUM_ITERATIONS 4
46 #include "RAS_BucketManager.h"
47 #include "RAS_Rect.h"
48 #include "RAS_IRasterizer.h"
49 #include "RAS_IRenderTools.h"
50 #include "RAS_ICanvas.h"
51 #include "STR_String.h"
52 #include "MT_Vector3.h"
53 #include "MT_Transform.h"
54 #include "SCA_IInputDevice.h"
55 #include "KX_Scene.h"
56 #include "MT_CmMatrix4x4.h"
57 #include "KX_Camera.h"
58 #include "KX_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         // run the 2dfilters and motion blur once for all the scenes
902         PostRenderFrame();
903
904         EndFrame();
905 }
906
907
908
909 void KX_KetsjiEngine::RequestExit(int exitrequestmode)
910 {
911         m_exitcode = exitrequestmode;
912 }
913
914
915
916 void KX_KetsjiEngine::SetNameNextGame(const STR_String& nextgame)
917 {
918         m_exitstring = nextgame;
919 }
920
921
922
923 int KX_KetsjiEngine::GetExitCode()
924 {
925         // if a gameactuator has set an exitcode or if there are no scenes left
926         if (!m_exitcode)
927         {
928                 if (m_scenes.begin()==m_scenes.end())
929                         m_exitcode = KX_EXIT_REQUEST_NO_SCENES_LEFT;
930         }
931
932         return m_exitcode;
933 }
934
935
936
937 const STR_String& KX_KetsjiEngine::GetExitString()
938 {
939         return m_exitstring;
940 }
941
942
943
944 void KX_KetsjiEngine::DoSound(KX_Scene* scene)
945 {
946         m_logger->StartLog(tc_sound, m_kxsystem->GetTimeInSeconds(), true);
947
948         KX_Camera* cam = scene->GetActiveCamera();
949         if (!cam)
950                 return;
951         MT_Point3 listenerposition = cam->NodeGetWorldPosition();
952         MT_Vector3 listenervelocity = cam->GetLinearVelocity();
953         MT_Matrix3x3 listenerorientation = cam->NodeGetWorldOrientation();
954
955         SND_Scene* soundscene = scene->GetSoundScene();
956         soundscene->SetListenerTransform(
957                 listenerposition,
958                 listenervelocity,
959                 listenerorientation);
960
961         soundscene->Proceed();
962 }
963
964
965
966 void KX_KetsjiEngine::SetBackGround(KX_WorldInfo* wi)
967 {
968         if (wi->hasWorld())
969         {
970                 if (m_drawingmode == RAS_IRasterizer::KX_TEXTURED)
971                 {       
972                         m_rasterizer->SetBackColor(
973                                 wi->getBackColorRed(),
974                                 wi->getBackColorGreen(),
975                                 wi->getBackColorBlue(),
976                                 0.0
977                         );
978                 }
979         }
980 }
981
982
983
984 void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi)
985 {
986         if (wi->hasWorld())
987         {
988                 // ...
989                 m_rasterizer->SetAmbientColor(
990                         wi->getAmbientColorRed(),
991                         wi->getAmbientColorGreen(),
992                         wi->getAmbientColorBlue()
993                 );
994
995                 if (m_drawingmode == RAS_IRasterizer::KX_TEXTURED)
996                 {       
997                         if (wi->hasMist())
998                         {
999                                 m_rasterizer->SetFog(
1000                                         wi->getMistStart(),
1001                                         wi->getMistDistance(),
1002                                         wi->getMistColorRed(),
1003                                         wi->getMistColorGreen(),
1004                                         wi->getMistColorBlue()
1005                                 );
1006                         }
1007                         else
1008                         {
1009                                 m_rasterizer->DisableFog();
1010                         }
1011                 }
1012         }
1013 }
1014
1015
1016
1017 void KX_KetsjiEngine::SetDrawType(int drawingmode)
1018 {
1019         m_drawingmode = drawingmode;
1020 }
1021
1022
1023         
1024 void KX_KetsjiEngine::EnableCameraOverride(const STR_String& forscene)
1025 {
1026         m_overrideCam = true;
1027         m_overrideSceneName = forscene;
1028 }
1029
1030
1031
1032 void KX_KetsjiEngine::SetCameraZoom(float camzoom)
1033 {
1034         m_cameraZoom = camzoom;
1035 }
1036
1037
1038
1039 void KX_KetsjiEngine::SetCameraOverrideUseOrtho(bool useOrtho)
1040 {
1041         m_overrideCamUseOrtho = useOrtho;
1042 }
1043
1044
1045
1046 void KX_KetsjiEngine::SetCameraOverrideProjectionMatrix(const MT_CmMatrix4x4& mat)
1047 {
1048         m_overrideCamProjMat = mat;
1049 }
1050
1051
1052 void KX_KetsjiEngine::SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat)
1053 {
1054         m_overrideCamViewMat = mat;
1055 }
1056
1057 void KX_KetsjiEngine::SetCameraOverrideClipping(float near, float far)
1058 {
1059         m_overrideCamNear = near;
1060         m_overrideCamFar = far;
1061 }
1062
1063 void KX_KetsjiEngine::GetSceneViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect& area, RAS_Rect& viewport)
1064 {
1065         // In this function we make sure the rasterizer settings are upto
1066         // date. We compute the viewport so that logic
1067         // using this information is upto date.
1068
1069         // Note we postpone computation of the projection matrix
1070         // so that we are using the latest camera position.
1071         if (cam->GetViewport()) {
1072                 RAS_Rect userviewport;
1073
1074                 userviewport.SetLeft(cam->GetViewportLeft()); 
1075                 userviewport.SetBottom(cam->GetViewportBottom());
1076                 userviewport.SetRight(cam->GetViewportRight());
1077                 userviewport.SetTop(cam->GetViewportTop());
1078
1079                 // Don't do bars on user specified viewport
1080                 RAS_FrameSettings settings = scene->GetFramingType();
1081                 if(settings.FrameType() == RAS_FrameSettings::e_frame_bars)
1082                         settings.SetFrameType(RAS_FrameSettings::e_frame_extend);
1083
1084                 RAS_FramingManager::ComputeViewport(
1085                         scene->GetFramingType(),
1086                         userviewport,
1087                         viewport
1088                 );
1089
1090                 area = userviewport;
1091         }
1092         else if ( m_overrideCam || (scene->GetName() != m_overrideSceneName) ||  m_overrideCamUseOrtho ) {
1093                 RAS_FramingManager::ComputeViewport(
1094                         scene->GetFramingType(),
1095                         m_canvas->GetDisplayArea(),
1096                         viewport
1097                 );
1098
1099                 area = m_canvas->GetDisplayArea();
1100         } else {
1101                 viewport.SetLeft(0); 
1102                 viewport.SetBottom(0);
1103                 viewport.SetRight(int(m_canvas->GetWidth()));
1104                 viewport.SetTop(int(m_canvas->GetHeight()));
1105
1106                 area = m_canvas->GetDisplayArea();
1107         }
1108 }
1109
1110 void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
1111 {
1112         CListValue *objectlist = scene->GetObjectList();
1113         int i, drawmode;
1114
1115         m_rendertools->SetAuxilaryClientInfo(scene);
1116
1117         for(i=0; i<objectlist->GetCount(); i++) {
1118                 KX_GameObject *gameobj = (KX_GameObject*)objectlist->GetValue(i);
1119
1120                 if(!gameobj->IsLight())
1121                         continue;
1122
1123                 KX_LightObject *light = (KX_LightObject*)gameobj;
1124
1125                 light->Update();
1126
1127                 if(m_drawingmode == RAS_IRasterizer::KX_TEXTURED && light->HasShadowBuffer()) {
1128                         /* make temporary camera */
1129                         RAS_CameraData camdata = RAS_CameraData();
1130                         KX_Camera *cam = new KX_Camera(scene, scene->m_callbacks, camdata, false);
1131                         cam->SetName("__shadow__cam__");
1132
1133                         MT_Transform camtrans;
1134
1135                         /* switch drawmode for speed */
1136                         drawmode = m_rasterizer->GetDrawingMode();
1137                         m_rasterizer->SetDrawingMode(RAS_IRasterizer::KX_SHADOW);
1138
1139                         /* binds framebuffer object, sets up camera .. */
1140                         light->BindShadowBuffer(m_rasterizer, cam, camtrans);
1141
1142                         /* update scene */
1143                         scene->UpdateMeshTransformations();
1144                         scene->CalculateVisibleMeshes(m_rasterizer, cam, light->GetShadowLayer());
1145
1146                         /* render */
1147                         m_rasterizer->ClearDepthBuffer();
1148                         scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
1149
1150                         /* unbind framebuffer object, restore drawmode, free camera */
1151                         light->UnbindShadowBuffer(m_rasterizer);
1152                         m_rasterizer->SetDrawingMode(drawmode);
1153                         cam->Release();
1154                 }
1155         }
1156 }
1157         
1158 // update graphics
1159 void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
1160 {
1161         bool override_camera;
1162         RAS_Rect viewport, area;
1163         float left, right, bottom, top, nearfrust, farfrust, focallength;
1164         const float ortho = 100.0;
1165 //      KX_Camera* cam = scene->GetActiveCamera();
1166         
1167         if (!cam)
1168                 return;
1169
1170         GetSceneViewport(scene, cam, area, viewport);
1171
1172         // store the computed viewport in the scene
1173         scene->SetSceneViewport(viewport);      
1174
1175         // set the viewport for this frame and scene
1176         m_canvas->SetViewPort(viewport.GetLeft(), viewport.GetBottom(),
1177                 viewport.GetRight(), viewport.GetTop());        
1178         
1179         // see KX_BlenderMaterial::Activate
1180         //m_rasterizer->SetAmbient();
1181         m_rasterizer->DisplayFog();
1182
1183         override_camera = m_overrideCam && (scene->GetName() == m_overrideSceneName);
1184         override_camera = override_camera && (cam->GetName() == "__default__cam__");
1185
1186         if (override_camera && m_overrideCamUseOrtho) {
1187                 MT_CmMatrix4x4 projmat = m_overrideCamProjMat;
1188                 m_rasterizer->SetProjectionMatrix(projmat);
1189         } else if (cam->hasValidProjectionMatrix() && !cam->GetViewport() )
1190         {
1191                 m_rasterizer->SetProjectionMatrix(cam->GetProjectionMatrix());
1192         } else
1193         {
1194                 RAS_FrameFrustum frustum;
1195                 float lens = cam->GetLens();
1196                 bool orthographic = !cam->GetCameraData()->m_perspective;
1197                 nearfrust = cam->GetCameraNear();
1198                 farfrust = cam->GetCameraFar();
1199                 focallength = cam->GetFocalLength();
1200
1201                 if(override_camera) {
1202                         nearfrust = m_overrideCamNear;
1203                         farfrust = m_overrideCamFar;
1204                 }
1205
1206                 if (orthographic) {
1207                         lens *= ortho;
1208                         nearfrust = (nearfrust + 1.0)*ortho;
1209                         farfrust *= ortho;
1210                 }
1211                 
1212                 RAS_FramingManager::ComputeFrustum(
1213                         scene->GetFramingType(),
1214                         area,
1215                         viewport,
1216                         lens,
1217                         nearfrust,
1218                         farfrust,
1219                         frustum
1220                 );
1221
1222                 left = frustum.x1 * m_cameraZoom;
1223                 right = frustum.x2 * m_cameraZoom;
1224                 bottom = frustum.y1 * m_cameraZoom;
1225                 top = frustum.y2 * m_cameraZoom;
1226                 nearfrust = frustum.camnear;
1227                 farfrust = frustum.camfar;
1228
1229                 MT_Matrix4x4 projmat = m_rasterizer->GetFrustumMatrix(
1230                         left, right, bottom, top, nearfrust, farfrust, focallength);
1231
1232                 cam->SetProjectionMatrix(projmat);
1233                 
1234                 // Otherwise the projection matrix for each eye will be the same...
1235                 if (m_rasterizer->Stereo())
1236                         cam->InvalidateProjectionMatrix();
1237         }
1238
1239         MT_Transform camtrans(cam->GetWorldToCamera());
1240         if (!cam->GetCameraData()->m_perspective)
1241                 camtrans.getOrigin()[2] *= ortho;
1242         MT_Matrix4x4 viewmat(camtrans);
1243         
1244         m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldPosition(),
1245                 cam->GetCameraLocation(), cam->GetCameraOrientation());
1246         cam->SetModelviewMatrix(viewmat);
1247
1248         //redundant, already done in 
1249         //scene->UpdateMeshTransformations();
1250
1251         // The following actually reschedules all vertices to be
1252         // redrawn. There is a cache between the actual rescheduling
1253         // and this call though. Visibility is imparted when this call
1254         // runs through the individual objects.
1255
1256         m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
1257         SG_SetActiveStage(SG_STAGE_CULLING);
1258
1259         scene->CalculateVisibleMeshes(m_rasterizer,cam);
1260
1261         m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
1262         SG_SetActiveStage(SG_STAGE_RENDER);
1263
1264         scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
1265         
1266         if (scene->GetPhysicsEnvironment())
1267                 scene->GetPhysicsEnvironment()->debugDrawWorld();
1268         
1269         m_rasterizer->FlushDebugLines();
1270 }
1271
1272 void KX_KetsjiEngine::PostRenderFrame()
1273 {
1274         m_rendertools->Render2DFilters(m_canvas);
1275         m_rendertools->MotionBlur(m_rasterizer);
1276 }
1277
1278 void KX_KetsjiEngine::StopEngine()
1279 {
1280         if (m_bInitialized)
1281         {
1282
1283                 if (m_game2ipo)
1284                 {
1285 //                      printf("TestHandlesPhysicsObjectToAnimationIpo\n");
1286                         m_sceneconverter->TestHandlesPhysicsObjectToAnimationIpo();
1287                 }
1288
1289                 KX_SceneList::iterator sceneit;
1290                 for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
1291                 {
1292                         KX_Scene* scene = *sceneit;
1293                         m_sceneconverter->RemoveScene(scene);
1294                 }       
1295                 m_scenes.clear();
1296
1297                 // cleanup all the stuff                
1298                 m_rasterizer->Exit();
1299         }
1300 }
1301
1302 // Scene Management is able to switch between scenes
1303 // and have several scene's running in parallel
1304 void KX_KetsjiEngine::AddScene(KX_Scene* scene)
1305
1306         m_scenes.push_back(scene);
1307         PostProcessScene(scene);
1308         SceneListsChanged();
1309 }
1310
1311
1312
1313 void KX_KetsjiEngine::PostProcessScene(KX_Scene* scene)
1314 {
1315         bool override_camera = (m_overrideCam && (scene->GetName() == m_overrideSceneName));
1316
1317         SG_SetActiveStage(SG_STAGE_SCENE);
1318
1319         // if there is no activecamera, or the camera is being
1320         // overridden we need to construct a temporarily camera
1321         if (!scene->GetActiveCamera() || override_camera)
1322         {
1323                 KX_Camera* activecam = NULL;
1324
1325                 RAS_CameraData camdata = RAS_CameraData();
1326                 activecam = new KX_Camera(scene,KX_Scene::m_callbacks,camdata);
1327                 activecam->SetName("__default__cam__");
1328         
1329                         // set transformation
1330                 if (override_camera) {
1331                         const MT_CmMatrix4x4& cammatdata = m_overrideCamViewMat;
1332                         MT_Transform trans = MT_Transform(cammatdata.getPointer());
1333                         MT_Transform camtrans;
1334                         camtrans.invert(trans);
1335                         
1336                         activecam->NodeSetLocalPosition(camtrans.getOrigin());
1337                         activecam->NodeSetLocalOrientation(camtrans.getBasis());
1338                         activecam->NodeUpdateGS(0);
1339                 } else {
1340                         activecam->NodeSetLocalPosition(MT_Point3(0.0, 0.0, 0.0));
1341                         activecam->NodeSetLocalOrientation(MT_Vector3(0.0, 0.0, 0.0));
1342                         activecam->NodeUpdateGS(0);
1343                 }
1344
1345                 scene->AddCamera(activecam);
1346                 scene->SetActiveCamera(activecam);
1347                 scene->GetObjectList()->Add(activecam->AddRef());
1348                 scene->GetRootParentList()->Add(activecam->AddRef());
1349                 //done with activecam
1350                 activecam->Release();
1351         }
1352         
1353         scene->UpdateParents(0.0);
1354 }
1355
1356
1357
1358 void KX_KetsjiEngine::RenderDebugProperties()
1359 {
1360         STR_String debugtxt;
1361         int xcoord = 10;        // mmmm, these constants were taken from blender source
1362         int ycoord = 14;        // to 'mimic' behaviour
1363
1364         float tottime = m_logger->GetAverage();
1365         if (tottime < 1e-6f) {
1366                 tottime = 1e-6f;
1367         }
1368
1369         // Set viewport to entire canvas
1370         RAS_Rect viewport;
1371         m_canvas->SetViewPort(0, 0, int(m_canvas->GetWidth()), int(m_canvas->GetHeight()));
1372         
1373         /* Framerate display */
1374         if (m_show_framerate) {
1375                 debugtxt.Format("swap : %.3f (%.3f frames per second)", tottime, 1.0/tottime);
1376                 m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, 
1377                                                                         debugtxt.Ptr(),
1378                                                                         xcoord,
1379                                                                         ycoord, 
1380                                                                         m_canvas->GetWidth() /* RdV, TODO ?? */, 
1381                                                                         m_canvas->GetHeight() /* RdV, TODO ?? */);
1382                 ycoord += 14;
1383         }
1384
1385         /* Profile and framerate display */
1386         if (m_show_profile)
1387         {               
1388                 for (int j = tc_first; j < tc_numCategories; j++)
1389                 {
1390                         debugtxt.Format(m_profileLabels[j]);
1391                         m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, 
1392                                                                                 debugtxt.Ptr(),
1393                                                                                 xcoord,ycoord,
1394                                                                                 m_canvas->GetWidth(), 
1395                                                                                 m_canvas->GetHeight());
1396                         double time = m_logger->GetAverage((KX_TimeCategory)j);
1397                         debugtxt.Format("%2.2f %%", time/tottime * 100.f);
1398                         m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, 
1399                                                                                 debugtxt.Ptr(),
1400                                                                                 xcoord + 60 ,ycoord,
1401                                                                                 m_canvas->GetWidth(), 
1402                                                                                 m_canvas->GetHeight());
1403                         ycoord += 14;
1404                 }
1405         }
1406
1407         /* Property display*/
1408         if (m_show_debug_properties && m_propertiesPresent)
1409         {
1410                 KX_SceneList::iterator sceneit;
1411                 for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
1412                 {
1413                         KX_Scene* scene = *sceneit;
1414                         /* the 'normal' debug props */
1415                         vector<SCA_DebugProp*>& debugproplist = scene->GetDebugProperties();
1416                         
1417                         for (vector<SCA_DebugProp*>::iterator it = debugproplist.begin();
1418                                  !(it==debugproplist.end());it++)
1419                         {
1420                                 CValue* propobj = (*it)->m_obj;
1421                                 STR_String objname = propobj->GetName();
1422                                 STR_String propname = (*it)->m_name;
1423                                 if (propname == "__state__")
1424                                 {
1425                                         // reserve name for object state
1426                                         KX_GameObject* gameobj = static_cast<KX_GameObject*>(propobj);
1427                                         unsigned int state = gameobj->GetState();
1428                                         debugtxt = objname + "." + propname + " = ";
1429                                         bool first = true;
1430                                         for (int statenum=1;state;state >>= 1, statenum++)
1431                                         {
1432                                                 if (state & 1)
1433                                                 {
1434                                                         if (!first)
1435                                                         {
1436                                                                 debugtxt += ",";
1437                                                         }
1438                                                         debugtxt += STR_String(statenum);
1439                                                         first = false;
1440                                                 }
1441                                         }
1442                                         m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, 
1443                                                                                                         debugtxt.Ptr(),
1444                                                                                                         xcoord,
1445                                                                                                         ycoord,
1446                                                                                                         m_canvas->GetWidth(),
1447                                                                                                         m_canvas->GetHeight());
1448                                         ycoord += 14;
1449                                 }
1450                                 else
1451                                 {
1452                                         CValue* propval = propobj->GetProperty(propname);
1453                                         if (propval)
1454                                         {
1455                                                 STR_String text = propval->GetText();
1456                                                 debugtxt = objname + "." + propname + " = " + text;
1457                                                 m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, 
1458                                                                                                         debugtxt.Ptr(),
1459                                                                                                         xcoord,
1460                                                                                                         ycoord,
1461                                                                                                         m_canvas->GetWidth(),
1462                                                                                                         m_canvas->GetHeight());
1463                                                 ycoord += 14;
1464                                         }
1465                                 }
1466                         }
1467                 }
1468         }
1469 }
1470
1471
1472 KX_SceneList* KX_KetsjiEngine::CurrentScenes()
1473 {
1474         return &m_scenes;       
1475 }
1476
1477
1478
1479 KX_Scene* KX_KetsjiEngine::FindScene(const STR_String& scenename)
1480 {
1481         KX_SceneList::iterator sceneit = m_scenes.begin();
1482
1483         // bit risky :) better to split the second clause 
1484         while ( (sceneit != m_scenes.end()) 
1485                         && ((*sceneit)->GetName() != scenename))
1486         {
1487                 sceneit++;
1488         }
1489
1490         return ((sceneit == m_scenes.end()) ? NULL : *sceneit); 
1491 }
1492
1493
1494
1495 void KX_KetsjiEngine::ConvertAndAddScene(const STR_String& scenename,bool overlay)
1496 {
1497         // only add scene when it doesn't exist!
1498         if (FindScene(scenename))
1499         {
1500                 STR_String tmpname = scenename;
1501                 printf("warning: scene %s already exists, not added!\n",tmpname.Ptr());
1502         }
1503         else
1504         {
1505                 if (overlay)
1506                 {
1507                         m_addingOverlayScenes.insert(scenename);
1508                 }
1509                 else
1510                 {
1511                         m_addingBackgroundScenes.insert(scenename);
1512                 }
1513         }
1514 }
1515
1516
1517
1518
1519 void KX_KetsjiEngine::RemoveScene(const STR_String& scenename)
1520 {
1521         if (FindScene(scenename))
1522         {
1523                 m_removingScenes.insert(scenename);
1524         }
1525         else
1526         {
1527 //              STR_String tmpname = scenename;
1528                 std::cout << "warning: scene " << scenename << " does not exist, not removed!" << std::endl;
1529         }
1530 }
1531
1532
1533
1534 void KX_KetsjiEngine::RemoveScheduledScenes()
1535 {
1536         if (m_removingScenes.size())
1537         {
1538                 set<STR_String>::iterator scenenameit;
1539                 for (scenenameit=m_removingScenes.begin();scenenameit != m_removingScenes.end();scenenameit++)
1540                 {
1541                         STR_String scenename = *scenenameit;
1542
1543                         KX_SceneList::iterator sceneit;
1544                         for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
1545                         {
1546                                 KX_Scene* scene = *sceneit;
1547                                 if (scene->GetName()==scenename)
1548                                 {
1549                                         m_sceneconverter->RemoveScene(scene);
1550                                         m_scenes.erase(sceneit);
1551                                         break;
1552                                 }
1553                         }       
1554                 }
1555                 m_removingScenes.clear();
1556         }
1557 }
1558
1559
1560
1561 KX_Scene* KX_KetsjiEngine::CreateScene(const STR_String& scenename)
1562 {
1563         Scene *scene = m_sceneconverter->GetBlenderSceneForName(scenename);
1564         KX_Scene* tmpscene = new KX_Scene(m_keyboarddevice,
1565                                                                           m_mousedevice,
1566                                                                           m_networkdevice,
1567                                                                           m_audiodevice,
1568                                                                           scenename,
1569                                                                           scene);
1570
1571         m_sceneconverter->ConvertScene(scenename,
1572                                                           tmpscene,
1573                                                           m_pythondictionary,
1574                                                           m_keyboarddevice,
1575                                                           m_rendertools,
1576                                                           m_canvas);
1577
1578         return tmpscene;
1579 }
1580
1581
1582
1583 void KX_KetsjiEngine::AddScheduledScenes()
1584 {
1585         set<STR_String>::iterator scenenameit;
1586
1587         if (m_addingOverlayScenes.size())
1588         {
1589                 for (scenenameit = m_addingOverlayScenes.begin();
1590                         scenenameit != m_addingOverlayScenes.end();
1591                         scenenameit++)
1592                 {
1593                         STR_String scenename = *scenenameit;
1594                         KX_Scene* tmpscene = CreateScene(scenename);
1595                         m_scenes.push_back(tmpscene);
1596                         PostProcessScene(tmpscene);
1597                 }
1598                 m_addingOverlayScenes.clear();
1599         }
1600         
1601         if (m_addingBackgroundScenes.size())
1602         {
1603                 for (scenenameit = m_addingBackgroundScenes.begin();
1604                         scenenameit != m_addingBackgroundScenes.end();
1605                         scenenameit++)
1606                 {
1607                         STR_String scenename = *scenenameit;
1608                         KX_Scene* tmpscene = CreateScene(scenename);
1609                         m_scenes.insert(m_scenes.begin(),tmpscene);
1610                         PostProcessScene(tmpscene);
1611
1612                 }
1613                 m_addingBackgroundScenes.clear();
1614         }
1615 }
1616
1617
1618
1619 void KX_KetsjiEngine::ReplaceScene(const STR_String& oldscene,const STR_String& newscene)
1620 {
1621         m_replace_scenes.insert(std::make_pair(oldscene,newscene));
1622 }
1623
1624 // replace scene is not the same as removing and adding because the
1625 // scene must be in exact the same place (to maintain drawingorder)
1626 // (nzc) - should that not be done with a scene-display list? It seems
1627 // stupid to rely on the mem allocation order...
1628 void KX_KetsjiEngine::ReplaceScheduledScenes()
1629 {
1630         if (m_replace_scenes.size())
1631         {
1632                 set<pair<STR_String,STR_String> >::iterator scenenameit;
1633                 
1634                 for (scenenameit = m_replace_scenes.begin();
1635                         scenenameit != m_replace_scenes.end();
1636                         scenenameit++)
1637                 {
1638                         STR_String oldscenename = (*scenenameit).first;
1639                         STR_String newscenename = (*scenenameit).second;
1640                         int i=0;
1641                         /* Scenes are not supposed to be included twice... I think */
1642                         KX_SceneList::iterator sceneit;
1643                         for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
1644                         {
1645                                 KX_Scene* scene = *sceneit;
1646                                 if (scene->GetName() == oldscenename)
1647                                 {
1648                                         m_sceneconverter->RemoveScene(scene);
1649                                         KX_Scene* tmpscene = CreateScene(newscenename);
1650                                         m_scenes[i]=tmpscene;
1651                                         PostProcessScene(tmpscene);
1652                                 }
1653                                 i++;
1654                         }
1655                 }
1656                 m_replace_scenes.clear();
1657         }       
1658 }
1659
1660
1661
1662 void KX_KetsjiEngine::SuspendScene(const STR_String& scenename)
1663 {
1664         KX_Scene*  scene = FindScene(scenename);
1665         if (scene) scene->Suspend();
1666 }
1667
1668
1669
1670 void KX_KetsjiEngine::ResumeScene(const STR_String& scenename)
1671 {
1672         KX_Scene*  scene = FindScene(scenename);
1673         if (scene) scene->Resume();
1674 }
1675
1676
1677
1678 void KX_KetsjiEngine::SetUseFixedTime(bool bUseFixedTime)
1679 {
1680         m_bFixedTime = bUseFixedTime;
1681 }
1682
1683
1684 void    KX_KetsjiEngine::SetGame2IpoMode(bool game2ipo,int startFrame)
1685 {
1686         m_game2ipo = game2ipo;
1687         if (game2ipo)
1688         {
1689                 //when recording physics keyframes, always run at a fixed framerate
1690                 m_bFixedTime = true;
1691         }
1692         m_currentFrame = startFrame;
1693 }
1694
1695 bool KX_KetsjiEngine::GetUseFixedTime(void) const
1696 {
1697         return m_bFixedTime;
1698 }
1699
1700 double KX_KetsjiEngine::GetSuspendedDelta()
1701 {
1702         return m_suspendeddelta;
1703 }
1704
1705 double KX_KetsjiEngine::GetTicRate()
1706 {
1707         return m_ticrate;
1708 }
1709
1710 void KX_KetsjiEngine::SetTicRate(double ticrate)
1711 {
1712         m_ticrate = ticrate;
1713 }
1714
1715 double KX_KetsjiEngine::GetAnimFrameRate()
1716 {
1717         return m_anim_framerate;
1718 }
1719
1720 double KX_KetsjiEngine::GetClockTime(void) const
1721 {
1722         return m_clockTime;
1723 }
1724
1725 void KX_KetsjiEngine::SetAnimFrameRate(double framerate)
1726 {
1727         m_anim_framerate = framerate;
1728 }
1729
1730 double KX_KetsjiEngine::GetAverageFrameRate()
1731 {
1732         return m_average_framerate;
1733 }
1734
1735 void KX_KetsjiEngine::SetTimingDisplay(bool frameRate, bool profile, bool properties)
1736 {
1737         m_show_framerate = frameRate;
1738         m_show_profile = profile;
1739         m_show_debug_properties = properties;
1740 }
1741
1742
1743
1744 void KX_KetsjiEngine::GetTimingDisplay(bool& frameRate, bool& profile, bool& properties) const
1745 {
1746         frameRate = m_show_framerate;
1747         profile = m_show_profile;
1748         properties = m_show_debug_properties;
1749 }
1750
1751
1752
1753 void KX_KetsjiEngine::ProcessScheduledScenes(void)
1754 {
1755         // Check whether there will be changes to the list of scenes
1756         if (m_addingOverlayScenes.size() ||
1757                 m_addingBackgroundScenes.size() ||
1758                 m_replace_scenes.size() ||
1759                 m_removingScenes.size()) {
1760
1761                 // Change the scene list
1762                 ReplaceScheduledScenes();
1763                 RemoveScheduledScenes();
1764                 AddScheduledScenes();
1765
1766                 // Notify
1767                 SceneListsChanged();
1768         }
1769 }
1770
1771
1772
1773 void KX_KetsjiEngine::SceneListsChanged(void)
1774 {
1775         m_propertiesPresent = false;
1776         KX_SceneList::iterator sceneit = m_scenes.begin();
1777         while ((sceneit != m_scenes.end()) && (!m_propertiesPresent))
1778         {
1779                 KX_Scene* scene = *sceneit;
1780                 vector<SCA_DebugProp*>& debugproplist = scene->GetDebugProperties();    
1781                 m_propertiesPresent = !debugproplist.empty();
1782                 sceneit++;
1783         }
1784 }
1785
1786
1787 void KX_KetsjiEngine::SetHideCursor(bool hideCursor)
1788 {
1789         m_hideCursor = hideCursor;
1790 }
1791
1792
1793 bool KX_KetsjiEngine::GetHideCursor(void) const
1794 {
1795         return m_hideCursor;
1796 }
1797
1798
1799 void KX_KetsjiEngine::SetUseOverrideFrameColor(bool overrideFrameColor)
1800 {
1801         m_overrideFrameColor = overrideFrameColor;
1802 }
1803
1804
1805 bool KX_KetsjiEngine::GetUseOverrideFrameColor(void) const
1806 {
1807         return m_overrideFrameColor;
1808 }
1809
1810
1811 void KX_KetsjiEngine::SetOverrideFrameColor(float r, float g, float b)
1812 {
1813         m_overrideFrameColorR = r;
1814         m_overrideFrameColorG = g;
1815         m_overrideFrameColorB = b;
1816 }
1817
1818
1819 void KX_KetsjiEngine::GetOverrideFrameColor(float& r, float& g, float& b) const
1820 {
1821         r = m_overrideFrameColorR;
1822         g = m_overrideFrameColorG;
1823         b = m_overrideFrameColorB;
1824 }
1825
1826