📄 soguigameviewer.cpp
字号:
/*****************************************************************************\ * * SoGuiGameViewer.cpp * * So???RenderArea derived GUI window with advanced mouse handling * (delta mouse mode). * * When delta mode is activated, SoLocationEvent does not contain absolute * mouse coordinates, but deltas from previous SoLocationEvent. * Such deltas can be used for easy realization of mouse-look and so on. * * * Authors: PCJohn (peciva AT fit.vutbr.cz) * Contributors: * * ---------------------------------------------------------------------------- * * THIS SOFTWARE IS NOT COPYRIGHTED * * This source code is offered for use in the public domain. * You may use, modify or distribute it freely. * * This source code is distributed in the hope that it will be useful but * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY * DISCLAIMED. This includes but is not limited to warranties of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * If you find the source code useful, authors will kindly welcome * if you give them credit and keep their names with their source code, * but do not feel forced to do so. *\*****************************************************************************/#include <Inventor/SbVec2s.h>#include <Inventor/SbBox2s.h>#include <Inventor/nodes/SoCamera.h>#include <Inventor/nodeKits/SoBaseKit.h>#include <Inventor/actions/SoSearchAction.h>#include <Inventor/events/SoLocation2Event.h>#include <Inventor/errors/SoDebugError.h>#include "SoGuiGameViewer.h"#if defined(__WIN32__) || defined(_WIN32)#include <Inventor/Win/devices/SoWinMouse.h>#define SoGuiMouse SoWinMouse#define SOGUI_OBJECT_SOURCE SOWIN_OBJECT_SOURCE#else#define SOGUI_OBJECT_SOURCE SOQT_OBJECT_SOURCE#endifclass SoGuiGameViewerP {public: SoGuiGameViewer *parent; SoGuiGameViewer::MouseMode mouseMode; SoCamera *camera; SbVec2f mouseSensitivity; SbBool mouseDeltaMode; SbBool mouseDeltaModeActive; SbVec2s mouseSavedPos; SbVec2s mouseCenter; SbBox2s windowRect; SoGuiGameViewer::ClipMode clipMode; void setMouseDeltaMode(SbBool on); void activateMouseDeltaMode(); void deactivateMouseDeltaMode(); void updateDeltaMouseActivation();#if defined(__WIN32__) || defined(_WIN32) HWND topLevelWnd; SbBool wndActive; WNDPROC prevWndProc; static HHOOK hookHandle; static HHOOK shellHookHandle; static LRESULT CALLBACK wndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK messageHook(int nCode, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK shellHook(int nCode, WPARAM wParam, LPARAM lParam); static SbList<SoGuiGameViewerP*> listOfGameViewers; static SbDict handle2viewerp; static SoGuiGameViewer* getViewerByHandle(HWND h, SbBool searchParentWidgets); SbBool isInForeground() const; static UINT focusMessageId; SoLocation2Event *locationEvent; SbBool shiftDown; SbBool ctrlDown; SbBool altDown; void clipMouse(const SbBox2s &box); void unclipMouse();#endif /* __WIN32__ || _WIN32 */ SoGuiGameViewerP(SoGuiGameViewer *parent); ~SoGuiGameViewerP();};#if defined(__WIN32__) || defined(_WIN32)HHOOK SoGuiGameViewerP::hookHandle;HHOOK SoGuiGameViewerP::shellHookHandle;SbList<SoGuiGameViewerP*> SoGuiGameViewerP::listOfGameViewers;SbDict SoGuiGameViewerP::handle2viewerp;UINT SoGuiGameViewerP::focusMessageId = -1;static SbVec2s getMousePos();static void setMousePos(const SbVec2s &pos);static void updateMouseCenter(SbVec2s &mouseCenter, const SbBox2s &windowRect);static void updateWindowRect(HWND h, SbBox2s &rect);#endif /* __WIN32__ || _WIN32 */#ifdef THIS#undef THIS#endif#define THIS pimplSOGUI_OBJECT_SOURCE(SoGuiGameViewer);void SoGuiGameViewer::setMouseMode(MouseMode mode){ THIS->mouseMode = mode; THIS->setMouseDeltaMode(mode==DELTA_TO_SCENE_GRAPH || mode==CAMERA || mode==CAMERA_AND_SCENE_GRAPH);}SoGuiGameViewer::MouseMode SoGuiGameViewer::getMouseMode() const{ return THIS->mouseMode;}void SoGuiGameViewer::setMouseSensitivity(const SbVec2f &sensitivity){ THIS->mouseSensitivity = sensitivity;}SbVec2f SoGuiGameViewer::getMouseSensitivity() const{ return THIS->mouseSensitivity;}void SoGuiGameViewer::setCamera(SoCamera *camera){ if (THIS->camera) THIS->camera->unref(); THIS->camera = camera; if (THIS->camera) THIS->camera->ref();}SoCamera* SoGuiGameViewer::getCamera() const{ return THIS->camera;}void SoGuiGameViewer::setSceneGraph(SoNode *node){ if (node == inherited::getSceneGraph()) return; inherited::setSceneGraph(node); if (node == NULL) // If no scene graph then reset camera setCamera(NULL); else { // Search for camera in the scene graph SbBool oldSearchChildren = SoBaseKit::isSearchingChildren(); SoBaseKit::setSearchingChildren(TRUE); SoSearchAction search; search.setType(SoCamera::getClassTypeId()); search.apply(node); SoBaseKit::setSearchingChildren(oldSearchChildren); SoPath *path = search.getPath(); if (path) setCamera((SoCamera*)((SoFullPath*)path)->getTail()); else { setCamera(NULL); SoDebugError::post("SoGuiGameViewer::setSceneGraph", "The scene graph does not contain any cameras.\n" "Consequences: (1) Nothing will be seen.\n" "(2) No camera movements will be made."); } }}SoGuiGameViewer::SoGuiGameViewer(WIDGET parent, const char *name, SbBool embed, MouseMode mouseMode) : inherited(parent, name, embed, TRUE, TRUE){ pimpl = new SoGuiGameViewerP(this); THIS->clipMode = CLIP_RELEASE_ONLY; THIS->mouseMode = mouseMode; THIS->camera = NULL; THIS->mouseSensitivity = SbVec2f(0.03f,0.03f); THIS->mouseDeltaMode = mouseMode==DELTA_TO_SCENE_GRAPH || mouseMode==CAMERA || mouseMode==CAMERA_AND_SCENE_GRAPH; THIS->mouseDeltaModeActive = FALSE;#if defined(__WIN32__) || defined(_WIN32) THIS->wndActive = FALSE; THIS->shiftDown = FALSE; THIS->ctrlDown = FALSE; THIS->altDown = FALSE;#endif /* __WIN32__ || _WIN32 */}SoGuiGameViewer::~SoGuiGameViewer(){ THIS->setMouseDeltaMode(FALSE); setCamera(NULL); delete pimpl;}void SoGuiGameViewerP::setMouseDeltaMode(SbBool on){ if (mouseDeltaMode == on) return; mouseDeltaMode = on; updateDeltaMouseActivation();}#if defined(__WIN32__) || defined(_WIN32)LRESULT CALLBACK SoGuiGameViewerP::wndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ // get pointer to our object SoGuiGameViewerP *pimpl; if (!handle2viewerp.find((unsigned long)hwnd, (*(void**)&pimpl))) assert(FALSE && "Pointer to SoGuiGameViewerP not found."); switch (uMsg) { case WM_MOUSEMOVE: {#ifdef DEBUG_FOCUS printf("mouseMove, focus is %s, my value %i\n", GetForegroundWindow() == THIS->parent->getParentWidget() ? "TRUE" : "FALSE", THIS->wndActive);#endif if (THIS->mouseMode == SoGuiGameViewer::SCENE_GRAPH) return CallWindowProc(THIS->prevWndProc, hwnd, uMsg, wParam, lParam); if (!THIS->mouseDeltaModeActive) return 0; // stop further processing // handle mouse SbVec2s pos = getMousePos(); SbVec2s delta = pos - THIS->mouseCenter; if (delta != SbVec2s(0,0)) { setMousePos(THIS->mouseCenter); assert(THIS->mouseMode != SoGuiGameViewer::DISABLED && THIS->mouseMode != SoGuiGameViewer::SCENE_GRAPH && "Wrong mouse mode."); if (THIS->mouseMode==SoGuiGameViewer::CAMERA || THIS->mouseMode==SoGuiGameViewer::CAMERA_AND_SCENE_GRAPH) { if (THIS->camera) { SbRotation orientation = THIS->camera->orientation.getValue(); SbRotation rotChange(SbRotation(SbVec3f(0.f,-1.f,0.f), delta[0]*THIS->mouseSensitivity[0]) * SbRotation(SbVec3f(-1.f,0.f,0.f), delta[1]*THIS->mouseSensitivity[1])); THIS->camera->orientation.setValue(rotChange * orientation); } } if (THIS->mouseMode==SoGuiGameViewer::DELTA_TO_SCENE_GRAPH || THIS->mouseMode == SoGuiGameViewer::CAMERA_AND_SCENE_GRAPH) { THIS->locationEvent->setPosition(delta); THIS->locationEvent->setShiftDown(THIS->shiftDown); THIS->locationEvent->setCtrlDown(THIS->ctrlDown); THIS->locationEvent->setAltDown(THIS->altDown); THIS->locationEvent->setTime(SbTime::getTimeOfDay()); THIS->parent->sendSoEvent(THIS->locationEvent); } } return 0; // stop further processing } case WM_SIZE: { // update mouse updateWindowRect(THIS->parent->getNormalWidget(), THIS->windowRect); updateMouseCenter(THIS->mouseCenter, THIS->windowRect); setMousePos(THIS->mouseCenter); break; } case WM_SETCURSOR: { // hide cursor if (THIS->mouseDeltaModeActive) { SetCursor(NULL); return TRUE; } break; } case WM_SETFOCUS: { THIS->wndActive = THIS->isInForeground();#ifdef DEBUG_FOCUS printf("setfocus, wndActive is %s\n", THIS->wndActive ? "TRUE" : "FALSE");#endif THIS->updateDeltaMouseActivation(); break; } case WM_KILLFOCUS: { THIS->wndActive = FALSE;#ifdef DEBUG_FOCUS printf("killfocus\n");#endif THIS->updateDeltaMouseActivation(); break; } case WM_KEYDOWN: case WM_SYSKEYDOWN: switch (wParam) { case VK_SHIFT: THIS->shiftDown = TRUE; break; case VK_CONTROL: THIS->ctrlDown = TRUE; break; case VK_MENU: THIS->altDown = TRUE; break; } break; case WM_KEYUP: case WM_SYSKEYUP: switch (wParam) { case VK_SHIFT: THIS->shiftDown = FALSE; break; case VK_CONTROL: THIS->ctrlDown = FALSE; break; case VK_MENU: THIS->altDown = FALSE; break; } break; default: if (uMsg == focusMessageId) { SetFocus(THIS->parent->getNormalWidget()); return 0; } } return CallWindowProc(THIS->prevWndProc, hwnd, uMsg, wParam, lParam);}SoGuiGameViewer* SoGuiGameViewerP::getViewerByHandle(HWND h, SbBool searchParentWidgets){ if (!searchParentWidgets) { SoGuiGameViewerP *pimpl; if (handle2viewerp.find((unsigned long)h, (*(void**)&pimpl))) return pimpl->parent; else return NULL; } else { const int c = listOfGameViewers.getLength(); int i; for (i=0; i<c; i++) { SoGuiGameViewer *gv = listOfGameViewers[i]->parent; HWND w = gv->getNormalWidget(); do { if (w == h) return gv; w = GetParent(w); } while (w != NULL); } return NULL; }}SbBool SoGuiGameViewerP::isInForeground() const{ HWND fg = GetForegroundWindow(); return (fg == parent->getParentWidget() || fg == parent->getNormalWidget());}LRESULT CALLBACK SoGuiGameViewerP::messageHook(int nCode, WPARAM wParam, LPARAM lParam){ CWPSTRUCT *msg = (CWPSTRUCT*)lParam; // Windows documentation says: process messages only when nCode >= 0 if (nCode >= 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -