synched with trunk at revision 36569
[blender.git] / source / gameengine / Ketsji / KX_KetsjiEngine.cpp
index 20600be..eef543e 100644 (file)
@@ -15,7 +15,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
  * The engine ties all game modules together. 
  */
 
-#ifdef WIN32
+/** \file gameengine/Ketsji/KX_KetsjiEngine.cpp
+ *  \ingroup ketsji
+ */
+
+
+#if defined(WIN32) && !defined(FREE_WINDOWS)
 #pragma warning (disable : 4786)
 #endif //WIN32
 
 #include <iostream>
+#include <stdio.h>
 
 #include "KX_KetsjiEngine.h"
 
 #include "KX_Scene.h"
 #include "MT_CmMatrix4x4.h"
 #include "KX_Camera.h"
+#include "KX_FontObject.h"
 #include "KX_Dome.h"
 #include "KX_Light.h"
 #include "KX_PythonInit.h"
 #include "KX_PyConstraintBinding.h"
 #include "PHY_IPhysicsEnvironment.h"
 
-#ifdef USE_SUMO_SOLID
-#include "SumoPhysicsEnvironment.h"
-#endif
-
-#include "SND_Scene.h"
-#include "SND_IAudioDevice.h"
+#include "AUD_C-API.h"
 
 #include "NG_NetworkScene.h"
 #include "NG_NetworkDeviceInterface.h"
 #include "KX_TimeCategoryLogger.h"
 
 #include "RAS_FramingManager.h"
-#include "stdio.h"
 #include "DNA_world_types.h"
 #include "DNA_scene_types.h"
 
+#include "KX_NavMeshObject.h"
+
 // If define: little test for Nzc: guarded drawing. If the canvas is
 // not valid, skip rendering this frame.
 //#define NZC_GUARDED_OUTPUT
@@ -117,8 +120,9 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
        m_rendertools(NULL),
        m_sceneconverter(NULL),
        m_networkdevice(NULL),
-       m_audiodevice(NULL),
+#ifdef WITH_PYTHON
        m_pythondictionary(NULL),
+#endif
        m_keyboarddevice(NULL),
        m_mousedevice(NULL),
 
@@ -158,7 +162,7 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
        m_showBackground(false),
        m_show_debug_properties(false),
 
-       m_game2ipo(false),
+       m_animation_record(false),
 
        // Default behavior is to hide the cursor every frame.
        m_hideCursor(false),
@@ -215,15 +219,6 @@ void KX_KetsjiEngine::SetNetworkDevice(NG_NetworkDeviceInterface* networkdevice)
 }
 
 
-
-void KX_KetsjiEngine::SetAudioDevice(SND_IAudioDevice* audiodevice)
-{
-       MT_assert(audiodevice);
-       m_audiodevice = audiodevice;
-}
-
-
-
 void KX_KetsjiEngine::SetCanvas(RAS_ICanvas* canvas)
 {
        MT_assert(canvas);
@@ -246,17 +241,17 @@ void KX_KetsjiEngine::SetRasterizer(RAS_IRasterizer* rasterizer)
        m_rasterizer = rasterizer;
 }
 
-
+#ifdef WITH_PYTHON
 /*
- * At the moment the GameLogic module is imported into 'pythondictionary' after this function is called.
+ * At the moment the bge.logic module is imported into 'pythondictionary' after this function is called.
  * if this function ever changes to assign a copy, make sure the game logic module is imported into this dictionary before hand.
  */
-void KX_KetsjiEngine::SetPythonDictionary(PyObject* pythondictionary)
+void KX_KetsjiEngine::SetPyNamespace(PyObject* pythondictionary)
 {
        MT_assert(pythondictionary);
        m_pythondictionary = pythondictionary;
 }
-
+#endif
 
 
 void KX_KetsjiEngine::SetSceneConverter(KX_ISceneConverter* sceneconverter)
@@ -298,6 +293,7 @@ void KX_KetsjiEngine::RenderDome()
                return;
 
        KX_SceneList::iterator sceneit;
+       KX_Scene* scene;
 
        int n_renders=m_dome->GetNumberRenders();// usually 4 or 6
        for (int i=0;i<n_renders;i++){
@@ -305,7 +301,7 @@ void KX_KetsjiEngine::RenderDome()
                for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++)
                // for each scene, call the proceed functions
                {
-                       KX_Scene* scene = *sceneit;
+                       scene = *sceneit;
                        KX_Camera* cam = scene->GetActiveCamera();
 
                        m_rendertools->BeginFrame(m_rasterizer);
@@ -347,6 +343,11 @@ void KX_KetsjiEngine::RenderDome()
                                
                                it++;
                        }
+                       // Part of PostRenderScene()
+                       m_rendertools->MotionBlur(m_rasterizer);
+                       scene->Render2DFilters(m_canvas);
+                       // no RunDrawingCallBacks
+                       // no FlushDebugLines
                }
                m_dome->BindImages(i);
        }       
@@ -375,11 +376,11 @@ void KX_KetsjiEngine::RenderDome()
                        1.0
                        );
        }
-
        m_dome->Draw();
-
-       // run the 2dfilters and motion blur once for all the scenes
-       PostRenderFrame();
+       // Draw Callback for the last scene
+#ifdef WITH_PYTHON
+       scene->RunDrawingCallbacks(scene->GetPostDrawCB());
+#endif 
        EndFrame();
 }
 
@@ -397,12 +398,12 @@ void KX_KetsjiEngine::StartEngine(bool clearIpo)
        m_firstframe = true;
        m_bInitialized = true;
        // there is always one scene enabled at startup
-       World* world = m_scenes[0]->GetBlenderScene()->world;
-       if (world)
+       Scene* scene = m_scenes[0]->GetBlenderScene();
+       if (scene)
        {
-               m_ticrate = world->ticrate;
-               m_maxLogicFrame = world->maxlogicstep;
-               m_maxPhysicsFrame = world->maxphystep;
+               m_ticrate = scene->gm.ticrate ? scene->gm.ticrate : DEFAULT_LOGIC_TIC_RATE;
+               m_maxLogicFrame = scene->gm.maxlogicstep ? scene->gm.maxlogicstep : 5;
+               m_maxPhysicsFrame = scene->gm.maxphystep ? scene->gm.maxlogicstep : 5;
        }
        else
        {
@@ -411,7 +412,7 @@ void KX_KetsjiEngine::StartEngine(bool clearIpo)
                m_maxPhysicsFrame = 5;
        }
        
-       if (m_game2ipo)
+       if (m_animation_record)
        {
                m_sceneconverter->ResetPhysicsObjectsAnimationIpo(clearIpo);
                m_sceneconverter->WritePhysicsObjectToAnimationIpo(m_currentFrame);
@@ -619,7 +620,9 @@ else
                                m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
                                SG_SetActiveStage(SG_STAGE_PHYSICS1);
                                // set Python hooks for each scene
+#ifdef WITH_PYTHON
                                PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
+#endif
                                KX_SetActiveScene(scene);
        
                                scene->GetPhysicsEnvironment()->endFrame();
@@ -668,7 +671,7 @@ else
                                scene->UpdateParents(m_frameTime);
                        
                        
-                               if (m_game2ipo)
+                               if (m_animation_record)
                                {                                       
                                        m_sceneconverter->WritePhysicsObjectToAnimationIpo(++m_currentFrame);
                                }
@@ -694,10 +697,7 @@ else
                
                if (m_networkdevice)
                        m_networkdevice->NextFrame();
-       
-               if (m_audiodevice)
-                       m_audiodevice->NextFrame();
-       
+
                // scene management
                ProcessScheduledScenes();
                
@@ -724,7 +724,9 @@ else
                                m_suspendeddelta = scene->getSuspendedDelta();
                                
                                // set Python hooks for each scene
+#ifdef WITH_PYTHON
                                PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
+#endif
                                KX_SetActiveScene(scene);
                                
                                m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
@@ -871,6 +873,7 @@ void KX_KetsjiEngine::Render()
                        
                        it++;
                }
+               PostRenderScene(scene);
        }
 
        // only one place that checks for stereo
@@ -920,6 +923,7 @@ void KX_KetsjiEngine::Render()
                                
                                it++;
                        }
+                       PostRenderScene(scene);
                }
        } // if(m_rasterizer->Stereo())
 
@@ -950,6 +954,14 @@ int KX_KetsjiEngine::GetExitCode()
                if (m_scenes.begin()==m_scenes.end())
                        m_exitcode = KX_EXIT_REQUEST_NO_SCENES_LEFT;
        }
+       
+       // check if the window has been closed.
+       if(!m_exitcode)
+       {
+               //if(!m_canvas->Check()) {
+               //      m_exitcode = KX_EXIT_REQUEST_OUTSIDE;
+               //}
+       }
 
        return m_exitcode;
 }
@@ -970,17 +982,17 @@ void KX_KetsjiEngine::DoSound(KX_Scene* scene)
        KX_Camera* cam = scene->GetActiveCamera();
        if (!cam)
                return;
-       MT_Point3 listenerposition = cam->NodeGetWorldPosition();
-       MT_Vector3 listenervelocity = cam->GetLinearVelocity();
-       MT_Matrix3x3 listenerorientation = cam->NodeGetWorldOrientation();
 
-       SND_Scene* soundscene = scene->GetSoundScene();
-       soundscene->SetListenerTransform(
-               listenerposition,
-               listenervelocity,
-               listenerorientation);
+       float f[4];
+
+       cam->NodeGetWorldPosition().getValue(f);
+       AUD_setListenerLocation(f);
 
-       soundscene->Proceed();
+       cam->GetLinearVelocity().getValue(f);
+       AUD_setListenerVelocity(f);
+
+       cam->NodeGetWorldOrientation().getRotation().getValue(f);
+       AUD_setListenerOrientation(f);
 }
 
 
@@ -1291,21 +1303,43 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
        m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
        SG_SetActiveStage(SG_STAGE_RENDER);
 
+#ifdef WITH_PYTHON
+       // Run any pre-drawing python callbacks
+       scene->RunDrawingCallbacks(scene->GetPreDrawCB());
+#endif
+
        scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
+
+       //render all the font objects for this scene
+       RenderFonts(scene);
        
        if (scene->GetPhysicsEnvironment())
                scene->GetPhysicsEnvironment()->debugDrawWorld();
-       
-       m_rasterizer->FlushDebugLines();
+}
 
-       //it's running once for every scene (i.e. overlay scenes have  it running twice). That's not the ideal.
-       PostRenderFrame();
+void KX_KetsjiEngine::RenderFonts(KX_Scene* scene)
+{
+       list<class KX_FontObject*>* fonts = scene->GetFonts();
+       
+       list<KX_FontObject*>::iterator it = fonts->begin();
+       while(it != fonts->end())
+       {
+               (*it)->DrawText();
+               ++it;
+       }
 }
 
-void KX_KetsjiEngine::PostRenderFrame()
+/*
+To run once per scene
+*/
+void KX_KetsjiEngine::PostRenderScene(KX_Scene* scene)
 {
-       m_rendertools->Render2DFilters(m_canvas);
        m_rendertools->MotionBlur(m_rasterizer);
+       scene->Render2DFilters(m_canvas);
+#ifdef WITH_PYTHON
+       scene->RunDrawingCallbacks(scene->GetPostDrawCB());     
+#endif
+       m_rasterizer->FlushDebugShapes();
 }
 
 void KX_KetsjiEngine::StopEngine()
@@ -1313,7 +1347,7 @@ void KX_KetsjiEngine::StopEngine()
        if (m_bInitialized)
        {
 
-               if (m_game2ipo)
+               if (m_animation_record)
                {
 //                     printf("TestHandlesPhysicsObjectToAnimationIpo\n");
                        m_sceneconverter->TestHandlesPhysicsObjectToAnimationIpo();
@@ -1591,28 +1625,27 @@ void KX_KetsjiEngine::RemoveScheduledScenes()
        }
 }
 
-
-
-KX_Scene* KX_KetsjiEngine::CreateScene(const STR_String& scenename)
+KX_Scene* KX_KetsjiEngine::CreateScene(Scene *scene)
 {
-       Scene *scene = m_sceneconverter->GetBlenderSceneForName(scenename);
        KX_Scene* tmpscene = new KX_Scene(m_keyboarddevice,
                                                                          m_mousedevice,
                                                                          m_networkdevice,
-                                                                         m_audiodevice,
-                                                                         scenename,
-                                                                         scene);
+                                                                         scene->id.name+2,
+                                                                         scene,
+                                                                         m_canvas);
 
        m_sceneconverter->ConvertScene(tmpscene,
-                                                         m_pythondictionary,
-                                                         m_keyboarddevice,
                                                          m_rendertools,
                                                          m_canvas);
 
        return tmpscene;
 }
 
-
+KX_Scene* KX_KetsjiEngine::CreateScene(const STR_String& scenename)
+{
+       Scene *scene = m_sceneconverter->GetBlenderSceneForName(scenename);
+       return CreateScene(scene);
+}
 
 void KX_KetsjiEngine::AddScheduledScenes()
 {
@@ -1715,10 +1748,10 @@ void KX_KetsjiEngine::SetUseFixedTime(bool bUseFixedTime)
 }
 
 
-void   KX_KetsjiEngine::SetGame2IpoMode(bool game2ipo,int startFrame)
+void   KX_KetsjiEngine::SetAnimRecordMode(bool animation_record, int startFrame)
 {
-       m_game2ipo = game2ipo;
-       if (game2ipo)
+       m_animation_record = animation_record;
+       if (animation_record)
        {
                //when recording physics keyframes, always run at a fixed framerate
                m_bFixedTime = true;
@@ -1776,6 +1809,11 @@ double KX_KetsjiEngine::GetClockTime(void) const
        return m_clockTime;
 }
 
+double KX_KetsjiEngine::GetFrameTime(void) const
+{
+       return m_frameTime;
+}
+
 double KX_KetsjiEngine::GetRealTime(void) const
 {
        return m_kxsystem->GetTimeInSeconds();