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