.scr patch (from Raymond Penners)
authorKester Maddock <Christopher.Maddock.1@uni.massey.ac.nz>
Wed, 1 Dec 2004 08:35:38 +0000 (08:35 +0000)
committerKester Maddock <Christopher.Maddock.1@uni.massey.ac.nz>
Wed, 1 Dec 2004 08:35:38 +0000 (08:35 +0000)
- The patch only alters files in: blender/source/gameengine/GamePlayer/ghost

- Any blenderplayer.exe (with the patch applied) can be renamed into
something.scr, and it will behave as a Windows screen saver.
(Right-click the .scr file, and select "Install". Then, it will appear
in the screen saver properties dialog part of the display settings,
including small preview et al).

- The screen saving functionality does not affect the executable when
it is NOT named .scr

- The screen saver automatically exits when the mouse/keyboard is
moved/pressed. There is no more need to wrap blenderplayer.exe into a
bat file and use python quit controllers, or whatever else is
suggested at http://download.blender.org/documentation/oldsite/oldsite.blender3d.org/181_Blender%20news%20haloParty.html

- It has been currently been tested to work Windows XP

source/gameengine/GamePlayer/ghost/GPG_Application.cpp
source/gameengine/GamePlayer/ghost/GPG_Application.h
source/gameengine/GamePlayer/ghost/GPG_ghost.cpp

index 0e45b2a90f389db100644e8ebeeafe3c7f6c2894..a956ede0d57c2b51b3b4e898f622f0fbe8b932d8 100644 (file)
@@ -156,6 +156,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,
index 4fcd66e64e0e0f995ae84a096abf0193b72da5a0..183ca4318a9d5c82fba6ca1a9a982465fcdcc172 100644 (file)
 #include "GHOST_IEventConsumer.h"
 #include "STR_String.h"
 
+#ifdef WIN32
+#include <wtypes.h>
+#endif
+
 class KX_KetsjiEngine;
 class KX_ISceneConverter;
 class NG_LoopBackNetworkDeviceInterface;
@@ -60,6 +64,11 @@ public:
                        bool startWindow(STR_String& title, int windowLeft, int windowTop, int windowWidth, int windowHeight,
                        const bool stereoVisual, const int stereoMode);
                        bool startFullScreen(int width, int height, int bpp, int frequency, const bool stereoVisual, const int stereoMode);
+#ifdef WIN32
+                       bool startScreenSaverFullScreen(int width, int height, int bpp, int frequency, const bool stereoVisual, const int stereoMode);
+                       bool startScreenSaverPreview(HWND parentWindow, const bool stereoVisual, const int stereoMode);
+#endif
+
        virtual bool processEvent(GHOST_IEvent* event);
                        int getExitRequested(void);
                        const STR_String& getExitString(void);
index a4b03628a46afb4f03850a9c9703541f2248a5d8..d7a9ad2b41dcb6754988ddebb20d0c417a660d0a 100644 (file)
@@ -85,8 +85,8 @@ extern "C"
 #include "BKE_utildefines.h"
 
 #ifdef WIN32
-#ifdef NDEBUG
 #include <windows.h>
+#ifdef NDEBUG
 #include <wincon.h>
 #endif // NDEBUG
 #endif // WIN32
@@ -96,6 +96,62 @@ const int kMinWindowHeight = 100;
 
 char bprogname[FILE_MAXDIR+FILE_MAXFILE];
 
+#ifdef WIN32
+typedef enum 
+{
+  SCREEN_SAVER_MODE_NONE = 0,
+  SCREEN_SAVER_MODE_PREVIEW,
+  SCREEN_SAVER_MODE_SAVER,
+  SCREEN_SAVER_MODE_CONFIGURATION,
+  SCREEN_SAVER_MODE_PASSWORD,
+} ScreenSaverMode;
+
+static ScreenSaverMode scr_saver_mode = SCREEN_SAVER_MODE_NONE;
+static HWND scr_saver_hwnd = NULL;
+
+static BOOL scr_saver_init(int argc, char **argv) 
+{
+       scr_saver_mode = SCREEN_SAVER_MODE_NONE;
+       scr_saver_hwnd = NULL;
+       BOOL ret = FALSE;
+
+       int len = ::strlen(argv[0]);
+       if (len > 4 && !::stricmp(".scr", argv[0] + len - 4))
+       {
+               scr_saver_mode = SCREEN_SAVER_MODE_CONFIGURATION;
+               ret = TRUE;
+               if (argc >= 2)
+               {
+                       if (argc >= 3)
+                       {
+                               scr_saver_hwnd = (HWND) ::atoi(argv[2]);
+                       }
+                       if (!::stricmp("/c", argv[1]))
+                       {
+                               scr_saver_mode = SCREEN_SAVER_MODE_CONFIGURATION;
+                               if (scr_saver_hwnd == NULL)
+                                       scr_saver_hwnd = ::GetForegroundWindow();
+                       }
+                       else if (!::stricmp("/s", argv[1]))
+                       {
+                               scr_saver_mode = SCREEN_SAVER_MODE_SAVER;
+                       }
+                       else if (!::stricmp("/a", argv[1]))
+                       {
+                               scr_saver_mode = SCREEN_SAVER_MODE_PASSWORD;
+                       }
+                       else if (!::stricmp("/p", argv[1])
+                                || !::stricmp("/l", argv[1]))
+                       {
+                               scr_saver_mode = SCREEN_SAVER_MODE_PREVIEW;
+                       }
+               }
+       }
+       return ret;
+}
+
+#endif /* WIN32 */
+
 void usage(char* program)
 {
        char * consoleoption;
@@ -280,7 +336,34 @@ int main(int argc, char** argv)
        printf("argv[0] = '%s'\n", argv[0]);
 #endif
 
-       for (i = 1; (i < argc) && !error;)
+
+#ifdef WIN32
+       if (scr_saver_init(argc, argv))
+       {
+               switch (scr_saver_mode)
+               {
+               case SCREEN_SAVER_MODE_CONFIGURATION:
+                       MessageBox(scr_saver_hwnd, "This screen saver has no options that you can set", "Screen Saver", MB_OK);
+                       break;
+               case SCREEN_SAVER_MODE_PASSWORD:
+                       /* This is W95 only, which we currently do not support.
+                          Fall-back to normal screen saver behaviour in that case... */
+               case SCREEN_SAVER_MODE_SAVER:
+                       fullScreen = true;
+                       fullScreenParFound = true;
+                       break;
+
+               case SCREEN_SAVER_MODE_PREVIEW:
+                       /* This will actually be handled somewhere below... */
+                       break;
+               }
+       }
+#endif
+       for (i = 1; (i < argc) && !error 
+#ifdef WIN32
+               && scr_saver_mode == SCREEN_SAVER_MODE_NONE
+#endif
+               ;)
 
        {
 #ifndef NDEBUG
@@ -447,6 +530,9 @@ int main(int argc, char** argv)
                usage(argv[0]);
        }
        else
+#ifdef WIN32
+               if (scr_saver_mode != SCREEN_SAVER_MODE_CONFIGURATION)
+#endif
        {
 #ifdef __APPLE__
                //SYS_WriteCommandLineInt(syshandle, "show_framerate", 1);
@@ -567,8 +653,18 @@ int main(int argc, char** argv)
                                                        
                                                        if (fullScreen)
                                                        {
-                                                               app.startFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency,
-                                                                       stereoWindow, stereomode);
+#ifdef WIN32
+                                                               if (scr_saver_mode == SCREEN_SAVER_MODE_SAVER)
+                                                               {
+                                                                       app.startScreenSaverFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency,
+                                                                               stereoWindow, stereomode);
+                                                               }
+                                                               else
+#endif
+                                                               {
+                                                                       app.startFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency,
+                                                                               stereoWindow, stereomode);
+                                                               }
                                                        }
                                                        else
                                                        {
@@ -604,8 +700,17 @@ int main(int argc, char** argv)
                                                                {
                                                                        title = "blenderplayer";
                                                                }
-                                                               app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight,
-                                                                       stereoWindow, stereomode);
+#ifdef WIN32
+                                                               if (scr_saver_mode == SCREEN_SAVER_MODE_PREVIEW)
+                                                               {
+                                                                       app.startScreenSaverPreview(scr_saver_hwnd, stereoWindow, stereomode);
+                                                               }
+                                                               else
+#endif
+                                                               {
+                                                                       app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight,
+                                                                               stereoWindow, stereomode);
+                                                               }
                                                        }
                                                }
                                                else