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