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