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