Merged 15170:15635 from trunk (no conflicts or even merges)
[blender.git] / source / gameengine / GamePlayer / ghost / GPG_Application.cpp
index 48859392b54d36108916bfe00c3150da58357809..b5ebffb93784e3652ddcfee0920dd460e04d1899 100644 (file)
@@ -1,15 +1,12 @@
 /**
  * $Id$
  *
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License.  See http://www.blender.org/BL/ for information
- * about this.
+ * of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -27,7 +24,7 @@
  *
  * Contributor(s): none yet.
  *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * ***** END GPL LICENSE BLOCK *****
  * GHOST Blender Player application implementation file.
  */
 
        #include <windows.h>
 #endif
 
-#ifdef __APPLE__
-#include <OpenGL/gl.h>
-#include <OpenGL/glu.h>
-#else
-#include <GL/gl.h>
-#include <GL/glu.h>
-#endif
+#include "GL/glew.h"
 
 #include "GPG_Application.h"
 
 #include <iostream>
-#include <assert.h>
+#include <MT_assert.h>
+#include <stdlib.h>
 
 /**********************************
  * Begin Blender include block
@@ -62,6 +54,8 @@ extern "C"
 #endif  // __cplusplus
 #include "BLI_blenlib.h"
 #include "BLO_readfile.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
 #ifdef __cplusplus
 }
 #endif // __cplusplus
@@ -79,9 +73,11 @@ extern "C"
 #include "RAS_MeshObject.h"
 #include "RAS_OpenGLRasterizer.h"
 #include "RAS_VAOpenGLRasterizer.h"
+#include "RAS_ListRasterizer.h"
 #include "RAS_GLExtensionManager.h"
 #include "KX_PythonInit.h"
 #include "KX_PyConstraintBinding.h"
+#include "BL_Material.h" // MAXTEX
 
 #include "KX_BlenderSceneConverter.h"
 #include "NG_LoopBackNetworkDeviceInterface.h"
@@ -107,11 +103,28 @@ static void frameTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time);
 static GHOST_ISystem* fSystem = 0;
 static const int kTimerFreq = 10;
 
-GPG_Application::GPG_Application(GHOST_ISystem* system, struct Main *maggie, STR_String startSceneName)
-       : m_maggie(maggie), m_startSceneName(startSceneName), m_exitRequested(0),
-         m_system(system), m_mainWindow(0), m_frameTimer(0), m_cursor(GHOST_kStandardCursorFirstCursor),
-         m_mouse(0), m_keyboard(0), m_rasterizer(0), m_canvas(0), m_rendertools(0), m_kxsystem(0), m_networkdevice(0), m_audiodevice(0), m_sceneconverter(0),
-         m_engineInitialized(0), m_engineRunning(0), m_ketsjiengine(0)
+GPG_Application::GPG_Application(GHOST_ISystem* system, struct Main* maggie, STR_String startSceneName)
+       : m_startSceneName(startSceneName), 
+         m_maggie(maggie),
+         m_exitRequested(0),
+         m_system(system), 
+         m_mainWindow(0), 
+         m_frameTimer(0), 
+         m_cursor(GHOST_kStandardCursorFirstCursor),
+         m_engineInitialized(0), 
+         m_engineRunning(0), 
+         m_ketsjiengine(0),
+         m_kxsystem(0), 
+         m_keyboard(0), 
+         m_mouse(0), 
+         m_canvas(0), 
+         m_rendertools(0), 
+         m_rasterizer(0), 
+         m_sceneconverter(0),
+         m_networkdevice(0), 
+         m_audiodevice(0),
+         m_blendermat(0),
+         m_blenderglslmat(0)
 {
        fSystem = system;
 }
@@ -126,12 +139,13 @@ GPG_Application::~GPG_Application(void)
 
 
 
-bool GPG_Application::SetGameEngineData(struct Main *maggie, STR_String startSceneName)
+bool GPG_Application::SetGameEngineData(struct Mainmaggie, STR_String startSceneName)
 {
        bool result = false;
 
        if (maggie != NULL && startSceneName != "")
        {
+               G.scene = (Scene*)maggie->scene.first;
                m_maggie = maggie;
                m_startSceneName = startSceneName;
                result = true;
@@ -141,6 +155,138 @@ bool GPG_Application::SetGameEngineData(struct Main *maggie, STR_String startSce
 }
 
 
+#ifdef WIN32
+#define SCR_SAVE_MOUSE_MOVE_THRESHOLD 15
+
+static HWND found_ghost_window_hwnd;
+static GHOST_IWindow* ghost_window_to_find;
+static WNDPROC ghost_wnd_proc;
+static POINT scr_save_mouse_pos;
+
+static LRESULT CALLBACK screenSaverWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+       BOOL close = FALSE;
+       switch (uMsg)
+       {
+               case WM_MOUSEMOVE:
+               { 
+                       POINT pt; 
+                       GetCursorPos(&pt);
+                       LONG dx = scr_save_mouse_pos.x - pt.x;
+                       LONG dy = scr_save_mouse_pos.y - pt.y;
+                       if (abs(dx) > SCR_SAVE_MOUSE_MOVE_THRESHOLD
+                           || abs(dy) > SCR_SAVE_MOUSE_MOVE_THRESHOLD)
+                       {
+                               close = TRUE;
+                       }
+                       scr_save_mouse_pos = pt;
+                       break;
+               }
+               case WM_LBUTTONDOWN: 
+               case WM_MBUTTONDOWN: 
+               case WM_RBUTTONDOWN: 
+               case WM_KEYDOWN:
+                       close = TRUE;
+       }
+       if (close)
+               PostMessage(hwnd,WM_CLOSE,0,0);
+       return CallWindowProc(ghost_wnd_proc, hwnd, uMsg, wParam, lParam);
+}
+
+BOOL CALLBACK findGhostWindowHWNDProc(HWND hwnd, LPARAM lParam)
+{
+       GHOST_IWindow *p = (GHOST_IWindow*) GetWindowLong(hwnd, GWL_USERDATA);
+       BOOL ret = TRUE;
+       if (p == ghost_window_to_find)
+       {
+               found_ghost_window_hwnd = hwnd;
+               ret = FALSE;
+       }
+       return ret;
+}
+
+static HWND findGhostWindowHWND(GHOST_IWindow* window)
+{
+       found_ghost_window_hwnd = NULL;
+       ghost_window_to_find = window;
+       EnumWindows(findGhostWindowHWNDProc, NULL);
+       return found_ghost_window_hwnd;
+}
+
+bool GPG_Application::startScreenSaverPreview(
+       HWND parentWindow,
+       const bool stereoVisual,
+       const int stereoMode)
+{
+       bool success = false;
+
+       RECT rc;
+       if (GetWindowRect(parentWindow, &rc))
+       {
+               int windowWidth = rc.right - rc.left;
+               int windowHeight = rc.bottom - rc.top;
+               STR_String title = "";
+                                                       
+               m_mainWindow = fSystem->createWindow(title, 0, 0, windowWidth, windowHeight, GHOST_kWindowStateMinimized,
+                       GHOST_kDrawingContextTypeOpenGL, stereoVisual);
+               if (!m_mainWindow) {
+                       printf("error: could not create main window\n");
+                       exit(-1);
+               }
+
+               HWND ghost_hwnd = findGhostWindowHWND(m_mainWindow);
+               if (!ghost_hwnd) {
+                       printf("error: could find main window\n");
+                       exit(-1);
+               }
+
+               SetParent(ghost_hwnd, parentWindow);
+               LONG style = GetWindowLong(ghost_hwnd, GWL_STYLE);
+               LONG exstyle = GetWindowLong(ghost_hwnd, GWL_EXSTYLE);
+
+               RECT adjrc = { 0, 0, windowWidth, windowHeight };
+               AdjustWindowRectEx(&adjrc, style, FALSE, exstyle);
+
+               style = (style & (~(WS_POPUP|WS_OVERLAPPEDWINDOW|WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_TILEDWINDOW ))) | WS_CHILD;
+               SetWindowLong(ghost_hwnd, GWL_STYLE, style);
+               SetWindowPos(ghost_hwnd, NULL, adjrc.left, adjrc.top, 0, 0, SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE);
+
+               /* Check the size of the client rectangle of the window and resize the window
+                * so that the client rectangle has the size requested.
+                */
+               m_mainWindow->setClientSize(windowWidth, windowHeight);
+
+               success = initEngine(m_mainWindow, stereoMode);
+               if (success) {
+                       success = startEngine();
+               }
+
+       }
+       return success;
+}
+
+bool GPG_Application::startScreenSaverFullScreen(
+               int width,
+               int height,
+               int bpp,int frequency,
+               const bool stereoVisual,
+               const int stereoMode)
+{
+       bool ret = startFullScreen(width, height, bpp, frequency, stereoVisual, stereoMode);
+       if (ret)
+       {
+               HWND ghost_hwnd = findGhostWindowHWND(m_mainWindow);
+               if (ghost_hwnd != NULL)
+               {
+                       GetCursorPos(&scr_save_mouse_pos);
+                       ghost_wnd_proc = (WNDPROC) GetWindowLong(ghost_hwnd, GWL_WNDPROC);
+                       SetWindowLong(ghost_hwnd,GWL_WNDPROC, (LONG) screenSaverWindowProc);
+               }
+       }
+       return ret;
+}
+
+#endif
 
 bool GPG_Application::startWindow(STR_String& title,
        int windowLeft,
@@ -202,6 +348,7 @@ bool GPG_Application::startFullScreen(
 
 
 
+
 bool GPG_Application::StartGameEngine(int stereoMode)
 {
        bool success = initEngine(m_mainWindow, stereoMode);
@@ -280,10 +427,12 @@ bool GPG_Application::processEvent(GHOST_IEvent* event)
                                        m_exitRequested = m_ketsjiengine->GetExitCode();
                                        
                                        // kick the engine
-                                       m_ketsjiengine->NextFrame();
-                                       
-                                       // render the frame
-                                       m_ketsjiengine->Render();
+                                       bool renderFrame = m_ketsjiengine->NextFrame();
+                                       if (renderFrame)
+                                       {
+                                               // render the frame
+                                               m_ketsjiengine->Render();
+                                       }
                                }
                                m_exitString = m_ketsjiengine->GetExitString();
                        }
@@ -328,7 +477,8 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
 {
        if (!m_engineInitialized)
        {
-               bgl::InitExtensions(1);
+               glewInit();
+               bgl::InitExtensions(true);
 
                // get and set the preferences
                SYS_SystemHandle syshandle = SYS_GetSystem();
@@ -337,10 +487,22 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
                
                // SYS_WriteCommandLineInt(syshandle, "fixedtime", 0);
                // SYS_WriteCommandLineInt(syshandle, "vertexarrays",1);                
-               //bool properties       = (SYS_GetCommandLineInt(syshandle, "show_properties", 0) != 0);
-               //bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0);
+               bool properties = (SYS_GetCommandLineInt(syshandle, "show_properties", 0) != 0);
+               bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0);
+               bool fixedFr = (G.fileflags & G_FILE_ENABLE_ALL_FRAMES);
+
+               bool showPhysics = (G.fileflags & G_FILE_SHOW_PHYSICS);
+               SYS_WriteCommandLineInt(syshandle, "show_physics", showPhysics);
+
+               bool fixed_framerate= (SYS_GetCommandLineInt(syshandle, "fixed_framerate", fixedFr) != 0);
                bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
-               bool useVertexArrays = SYS_GetCommandLineInt(syshandle,"vertexarrays",1) != 0;
+               bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", G.fileflags & G_FILE_DIAPLAY_LISTS) != 0);
+
+               if(GLEW_ARB_multitexture && GLEW_VERSION_1_1) {
+                       int gameflag =(G.fileflags & G_FILE_GAME_MAT);
+                       m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", gameflag) != 0);
+               }
+       
                // create the canvas, rasterizer and rendertools
                m_canvas = new GPG_Canvas(window);
                if (!m_canvas)
@@ -350,12 +512,19 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
                m_rendertools = new GPC_RenderTools();
                if (!m_rendertools)
                        goto initFailed;
-                                       
-               if (useVertexArrays && bgl::QueryVersion(1, 1))
+               
+               if(useLists) {
+                       if(GLEW_VERSION_1_1)
+                               m_rasterizer = new RAS_ListRasterizer(m_canvas, true);
+                       else
+                               m_rasterizer = new RAS_ListRasterizer(m_canvas);
+               }
+               else if (GLEW_VERSION_1_1)
                        m_rasterizer = new RAS_VAOpenGLRasterizer(m_canvas);
                else
                        m_rasterizer = new RAS_OpenGLRasterizer(m_canvas);
-               m_rasterizer->SetStereoMode(stereoMode);
+
+               m_rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) stereoMode);
                if (!m_rasterizer)
                        goto initFailed;
                                                
@@ -399,8 +568,8 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
                m_ketsjiengine->SetAudioDevice(m_audiodevice);
                m_ketsjiengine->SetTimingDisplay(frameRate, false, false);
 
-               m_ketsjiengine->SetUseFixedTime(false);
-               //m_ketsjiengine->SetTimingDisplay(frameRate, profile, properties);
+               m_ketsjiengine->SetUseFixedTime(fixed_framerate);
+               m_ketsjiengine->SetTimingDisplay(frameRate, profile, properties);
 
                m_engineInitialized = true;
        }
@@ -451,7 +620,7 @@ bool GPG_Application::startEngine(void)
        */
        
        // create a scene converter, create and convert the stratingscene
-       m_sceneconverter = new KX_BlenderSceneConverter(m_maggie, m_ketsjiengine);
+       m_sceneconverter = new KX_BlenderSceneConverter(m_maggie,0, m_ketsjiengine);
        if (m_sceneconverter)
        {
                STR_String startscenename = m_startSceneName.Ptr();
@@ -459,7 +628,10 @@ bool GPG_Application::startEngine(void)
                
                //      if (always_use_expand_framing)
                //              sceneconverter->SetAlwaysUseExpandFraming(true);
-               
+               if(m_blendermat)
+                       m_sceneconverter->SetMaterials(true);
+               if(m_blenderglslmat)
+                       m_sceneconverter->SetGLSLMaterials(true);
 
                KX_Scene* startscene = new KX_Scene(m_keyboard,
                        m_mouse,
@@ -467,18 +639,23 @@ bool GPG_Application::startEngine(void)
                        m_audiodevice,
                        startscenename);
                
+               
                // some python things
-               PyObject* m_dictionaryobject = initGamePlayerPythonScripting("Ketsji", psl_Lowest);
-               m_ketsjiengine->SetPythonDictionary(m_dictionaryobject);
+               PyObject* dictionaryobject = initGamePlayerPythonScripting("Ketsji", psl_Lowest);
+               m_ketsjiengine->SetPythonDictionary(dictionaryobject);
                initRasterizer(m_rasterizer, m_canvas);
-               initGameLogic(startscene);
+               PyDict_SetItemString(dictionaryobject, "GameLogic", initGameLogic(startscene)); // Same as importing the module
                initGameKeys();
                initPythonConstraintBinding();
-               
+
+
+
+
+
                m_sceneconverter->ConvertScene(
                        startscenename,
                        startscene,
-                       m_dictionaryobject,
+                       dictionaryobject,
                        m_keyboard,
                        m_rendertools,
                        m_canvas);
@@ -489,7 +666,7 @@ bool GPG_Application::startEngine(void)
                        m_frameTimer = m_system->installTimer(0, kTimerFreq, frameTimerProc, m_mainWindow);
                }
                m_rasterizer->Init();
-               m_ketsjiengine->StartEngine();
+               m_ketsjiengine->StartEngine(true);
                m_engineRunning = true;
                
        }
@@ -578,7 +755,7 @@ void GPG_Application::exitEngine()
 bool GPG_Application::handleWheel(GHOST_IEvent* event)
 {
        bool handled = false;
-       assert(event);
+       MT_assert(event);
        if (m_mouse) 
        {
                GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
@@ -597,7 +774,7 @@ bool GPG_Application::handleWheel(GHOST_IEvent* event)
 bool GPG_Application::handleButton(GHOST_IEvent* event, bool isDown)
 {
        bool handled = false;
-       assert(event);
+       MT_assert(event);
        if (m_mouse) 
        {
                GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
@@ -626,7 +803,7 @@ bool GPG_Application::handleButton(GHOST_IEvent* event, bool isDown)
 bool GPG_Application::handleCursorMove(GHOST_IEvent* event)
 {
        bool handled = false;
-       assert(event);
+       MT_assert(event);
        if (m_mouse && m_mainWindow)
        {
                GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
@@ -643,16 +820,17 @@ bool GPG_Application::handleCursorMove(GHOST_IEvent* event)
 bool GPG_Application::handleKey(GHOST_IEvent* event, bool isDown)
 {
        bool handled = false;
-       assert(event);
+       MT_assert(event);
        if (m_keyboard)
        {
                GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
                GHOST_TEventKeyData* keyData = static_cast<GHOST_TEventKeyData*>(eventData);
-               if (fSystem->getFullScreen()) {
-                       if (keyData->key == GHOST_kKeyEsc) {
+               //no need for this test
+               //if (fSystem->getFullScreen()) {
+                       if (keyData->key == GHOST_kKeyEsc && !m_keyboard->m_hookesc) {
                                m_exitRequested = KX_EXIT_REQUEST_OUTSIDE;
                        }
-               }
+               //}
                m_keyboard->ConvertEvent(keyData->key, isDown);
                handled = true;
        }