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