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