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