WNT_HIDSpaceMouse - added auxiliary class for processing 3d mouse Raw HID input.
AIS_ViewController::Update3dMouse() - added default processor for 3d mouse input event.
ViewerTest now redirects WM_INPUT to AIS_ViewController::Update3dMouse().
Aspect_VKey enumeration has been extended by 3D view buttons.
WNT_Window::RegisterRawInputDevices() has beend added as a small wrapper
over WinAPI RegisterRawInputDevices() for common HID input devices.
AIS_ViewCube now stores animation duration within AIS_AnimationCamera instead of dedicated duplicating class property.
set (OCCT_PACKAGE_NAME "${OCCT_PACKAGE}")
endif()
- # TKService contains platform-dependent packages: Xw and WNT
- if ((WIN32 AND "${OCCT_PACKAGE}" STREQUAL "Xw") OR (NOT WIN32 AND "${OCCT_PACKAGE}" STREQUAL "WNT"))
- # do nothing
- else()
-
- if (WIN32)
- list (APPEND PRECOMPILED_DEFS "-D__${OCCT_PACKAGE_NAME}_DLL")
- endif()
-
- set (SOURCE_FILES)
- set (HEADER_FILES)
+ if (WIN32)
+ list (APPEND PRECOMPILED_DEFS "-D__${OCCT_PACKAGE_NAME}_DLL")
+ endif()
- # Generate Flex and Bison files
- if (${BUILD_YACCLEX})
+ set (SOURCE_FILES)
+ set (HEADER_FILES)
- # flex files
- OCCT_ORIGIN_AND_PATCHED_FILES ("${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}" "*[.]lex" SOURCE_FILES_FLEX)
- list (LENGTH SOURCE_FILES_FLEX SOURCE_FILES_FLEX_LEN)
+ # Generate Flex and Bison files
+ if (${BUILD_YACCLEX})
+ # flex files
+ OCCT_ORIGIN_AND_PATCHED_FILES ("${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}" "*[.]lex" SOURCE_FILES_FLEX)
+ list (LENGTH SOURCE_FILES_FLEX SOURCE_FILES_FLEX_LEN)
- # bison files
- OCCT_ORIGIN_AND_PATCHED_FILES ("${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}" "*[.]yacc" SOURCE_FILES_BISON)
- list (LENGTH SOURCE_FILES_BISON SOURCE_FILES_BISON_LEN)
+ # bison files
+ OCCT_ORIGIN_AND_PATCHED_FILES ("${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}" "*[.]yacc" SOURCE_FILES_BISON)
+ list (LENGTH SOURCE_FILES_BISON SOURCE_FILES_BISON_LEN)
- if (${SOURCE_FILES_FLEX_LEN} EQUAL ${SOURCE_FILES_BISON_LEN} AND NOT ${SOURCE_FILES_FLEX_LEN} EQUAL 0)
+ if (${SOURCE_FILES_FLEX_LEN} EQUAL ${SOURCE_FILES_BISON_LEN} AND NOT ${SOURCE_FILES_FLEX_LEN} EQUAL 0)
- list (SORT SOURCE_FILES_FLEX)
- list (SORT SOURCE_FILES_BISON)
+ list (SORT SOURCE_FILES_FLEX)
+ list (SORT SOURCE_FILES_BISON)
- math (EXPR SOURCE_FILES_FLEX_LEN "${SOURCE_FILES_FLEX_LEN} - 1")
- foreach (FLEX_FILE_INDEX RANGE ${SOURCE_FILES_FLEX_LEN})
+ math (EXPR SOURCE_FILES_FLEX_LEN "${SOURCE_FILES_FLEX_LEN} - 1")
+ foreach (FLEX_FILE_INDEX RANGE ${SOURCE_FILES_FLEX_LEN})
- list (GET SOURCE_FILES_FLEX ${FLEX_FILE_INDEX} CURRENT_FLEX_FILE)
- get_filename_component (CURRENT_FLEX_FILE_NAME ${CURRENT_FLEX_FILE} NAME_WE)
+ list (GET SOURCE_FILES_FLEX ${FLEX_FILE_INDEX} CURRENT_FLEX_FILE)
+ get_filename_component (CURRENT_FLEX_FILE_NAME ${CURRENT_FLEX_FILE} NAME_WE)
- list (GET SOURCE_FILES_BISON ${FLEX_FILE_INDEX} CURRENT_BISON_FILE)
- get_filename_component (CURRENT_BISON_FILE_NAME ${CURRENT_BISON_FILE} NAME_WE)
+ list (GET SOURCE_FILES_BISON ${FLEX_FILE_INDEX} CURRENT_BISON_FILE)
+ get_filename_component (CURRENT_BISON_FILE_NAME ${CURRENT_BISON_FILE} NAME_WE)
- string (COMPARE EQUAL ${CURRENT_FLEX_FILE_NAME} ${CURRENT_BISON_FILE_NAME} ARE_FILES_EQUAL)
-
- if (EXISTS "${CURRENT_FLEX_FILE}" AND EXISTS "${CURRENT_BISON_FILE}" AND ${ARE_FILES_EQUAL})
- set (BISON_OUTPUT_FILE ${CURRENT_BISON_FILE_NAME}.tab.c)
- set (FLEX_OUTPUT_FILE lex.${CURRENT_FLEX_FILE_NAME}.c)
- BISON_TARGET (Parser_${CURRENT_BISON_FILE_NAME} ${CURRENT_BISON_FILE} ${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${BISON_OUTPUT_FILE} COMPILE_FLAGS "-p ${CURRENT_BISON_FILE_NAME}")
- FLEX_TARGET (Scanner_${CURRENT_FLEX_FILE_NAME} ${CURRENT_FLEX_FILE} ${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${FLEX_OUTPUT_FILE} COMPILE_FLAGS "-P${CURRENT_FLEX_FILE_NAME}")
- ADD_FLEX_BISON_DEPENDENCY (Scanner_${CURRENT_FLEX_FILE_NAME} Parser_${CURRENT_BISON_FILE_NAME})
+ string (COMPARE EQUAL ${CURRENT_FLEX_FILE_NAME} ${CURRENT_BISON_FILE_NAME} ARE_FILES_EQUAL)
+
+ if (EXISTS "${CURRENT_FLEX_FILE}" AND EXISTS "${CURRENT_BISON_FILE}" AND ${ARE_FILES_EQUAL})
+ set (BISON_OUTPUT_FILE ${CURRENT_BISON_FILE_NAME}.tab.c)
+ set (FLEX_OUTPUT_FILE lex.${CURRENT_FLEX_FILE_NAME}.c)
+ BISON_TARGET (Parser_${CURRENT_BISON_FILE_NAME} ${CURRENT_BISON_FILE} ${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${BISON_OUTPUT_FILE} COMPILE_FLAGS "-p ${CURRENT_BISON_FILE_NAME}")
+ FLEX_TARGET (Scanner_${CURRENT_FLEX_FILE_NAME} ${CURRENT_FLEX_FILE} ${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${FLEX_OUTPUT_FILE} COMPILE_FLAGS "-P${CURRENT_FLEX_FILE_NAME}")
+ ADD_FLEX_BISON_DEPENDENCY (Scanner_${CURRENT_FLEX_FILE_NAME} Parser_${CURRENT_BISON_FILE_NAME})
- list (APPEND SOURCE_FILES ${BISON_OUTPUT_FILE} ${FLEX_OUTPUT_FILE})
- endif()
- endforeach()
- endif()
+ list (APPEND SOURCE_FILES ${BISON_OUTPUT_FILE} ${FLEX_OUTPUT_FILE})
+ endif()
+ endforeach()
endif()
+ endif()
- # header files
- if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES")
- file (STRINGS "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES" HEADER_FILES_M REGEX ".+[.]h")
- file (STRINGS "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES" HEADER_FILES_LXX REGEX ".+[.]lxx")
- file (STRINGS "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES" HEADER_FILES_GXX REGEX ".+[.]gxx")
+ # header files
+ if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES")
+ file (STRINGS "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES" HEADER_FILES_M REGEX ".+[.]h")
+ file (STRINGS "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES" HEADER_FILES_LXX REGEX ".+[.]lxx")
+ file (STRINGS "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES" HEADER_FILES_GXX REGEX ".+[.]gxx")
- file (STRINGS "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES" SOURCE_FILES_C REGEX ".+[.]c")
- if(APPLE)
- file (STRINGS "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES" SOURCE_FILES_M REGEX ".+[.]mm")
- endif()
- else()
- file (STRINGS "${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES" HEADER_FILES_M REGEX ".+[.]h")
- file (STRINGS "${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES" HEADER_FILES_LXX REGEX ".+[.]lxx")
- file (STRINGS "${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES" HEADER_FILES_GXX REGEX ".+[.]gxx")
+ file (STRINGS "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES" SOURCE_FILES_C REGEX ".+[.]c")
+ if(APPLE)
+ file (STRINGS "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES" SOURCE_FILES_M REGEX ".+[.]mm")
+ endif()
+ else()
+ file (STRINGS "${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES" HEADER_FILES_M REGEX ".+[.]h")
+ file (STRINGS "${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES" HEADER_FILES_LXX REGEX ".+[.]lxx")
+ file (STRINGS "${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES" HEADER_FILES_GXX REGEX ".+[.]gxx")
- file (STRINGS "${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES" SOURCE_FILES_C REGEX ".+[.]c")
- if(APPLE)
- file (STRINGS "${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES" SOURCE_FILES_M REGEX ".+[.]mm")
- endif()
+ file (STRINGS "${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES" SOURCE_FILES_C REGEX ".+[.]c")
+ if(APPLE)
+ file (STRINGS "${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/FILES" SOURCE_FILES_M REGEX ".+[.]mm")
endif()
+ endif()
- list (APPEND HEADER_FILES ${HEADER_FILES_M} ${HEADER_FILES_LXX} ${SOURCE_FILES_GXX})
- list (APPEND SOURCE_FILES ${SOURCE_FILES_C})
- if(APPLE)
- list (APPEND SOURCE_FILES ${SOURCE_FILES_M})
+ list (APPEND HEADER_FILES ${HEADER_FILES_M} ${HEADER_FILES_LXX} ${SOURCE_FILES_GXX})
+ list (APPEND SOURCE_FILES ${SOURCE_FILES_C})
+ if(APPLE)
+ list (APPEND SOURCE_FILES ${SOURCE_FILES_M})
+ endif()
+
+ foreach(HEADER_FILE ${HEADER_FILES})
+ if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${HEADER_FILE}")
+ message (STATUS "Info: consider patched file: ${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${HEADER_FILE}")
+ list (APPEND USED_INCFILES "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${HEADER_FILE}")
+ SOURCE_GROUP ("Header Files\\${OCCT_PACKAGE_NAME}" FILES "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${HEADER_FILE}")
+ else()
+ list (APPEND USED_INCFILES "${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${HEADER_FILE}")
+ SOURCE_GROUP ("Header Files\\${OCCT_PACKAGE_NAME}" FILES "${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${HEADER_FILE}")
endif()
+ endforeach()
- foreach(HEADER_FILE ${HEADER_FILES})
- if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${HEADER_FILE}")
- message (STATUS "Info: consider patched file: ${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${HEADER_FILE}")
- list (APPEND USED_INCFILES "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${HEADER_FILE}")
- SOURCE_GROUP ("Header Files\\${OCCT_PACKAGE_NAME}" FILES "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${HEADER_FILE}")
- else()
- list (APPEND USED_INCFILES "${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${HEADER_FILE}")
- SOURCE_GROUP ("Header Files\\${OCCT_PACKAGE_NAME}" FILES "${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${HEADER_FILE}")
- endif()
- endforeach()
-
- foreach(SOURCE_FILE ${SOURCE_FILES})
- if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${SOURCE_FILE}")
- message (STATUS "Info: consider patched file: ${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${SOURCE_FILE}")
- list (APPEND USED_SRCFILES "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${SOURCE_FILE}")
- SOURCE_GROUP ("Source Files\\${OCCT_PACKAGE_NAME}" FILES "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${SOURCE_FILE}")
- else()
- list (APPEND USED_SRCFILES "${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${SOURCE_FILE}")
- SOURCE_GROUP ("Source Files\\${OCCT_PACKAGE_NAME}" FILES "${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${SOURCE_FILE}")
- endif()
- endforeach()
+ foreach(SOURCE_FILE ${SOURCE_FILES})
+ if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${SOURCE_FILE}")
+ message (STATUS "Info: consider patched file: ${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${SOURCE_FILE}")
+ list (APPEND USED_SRCFILES "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${SOURCE_FILE}")
+ SOURCE_GROUP ("Source Files\\${OCCT_PACKAGE_NAME}" FILES "${BUILD_PATCH}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${SOURCE_FILE}")
+ else()
+ list (APPEND USED_SRCFILES "${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${SOURCE_FILE}")
+ SOURCE_GROUP ("Source Files\\${OCCT_PACKAGE_NAME}" FILES "${CMAKE_SOURCE_DIR}/${RELATIVE_SOURCES_DIR}/${OCCT_PACKAGE}/${SOURCE_FILE}")
+ endif()
+ endforeach()
- if (USE_QT)
- FIND_AND_INSTALL_QT_RESOURCES (${OCCT_PACKAGE} RESOURCE_FILES)
- #message("Qt Resource files are: ${QT_RESOURCE_FILES} in ${OCCT_PACKAGE}")
- endif(USE_QT)
+ if (USE_QT)
+ FIND_AND_INSTALL_QT_RESOURCES (${OCCT_PACKAGE} RESOURCE_FILES)
+ #message("Qt Resource files are: ${QT_RESOURCE_FILES} in ${OCCT_PACKAGE}")
+ endif(USE_QT)
- #message("Resource files are: ${RESOURCE_FILES} in ${OCCT_PACKAGE}")
- foreach(RESOURCE_FILE ${RESOURCE_FILES})
- SOURCE_GROUP ("Resource Files\\${OCCT_PACKAGE_NAME}" FILES "${RESOURCE_FILE}")
- endforeach()
- endif()
+ #message("Resource files are: ${RESOURCE_FILES} in ${OCCT_PACKAGE}")
+ foreach(RESOURCE_FILE ${RESOURCE_FILES})
+ SOURCE_GROUP ("Resource Files\\${OCCT_PACKAGE_NAME}" FILES "${RESOURCE_FILE}")
+ endforeach()
endforeach()
string (REGEX REPLACE ";" " " PRECOMPILED_DEFS "${PRECOMPILED_DEFS}")
return $l
}
-proc osutils:justwnt { listloc } {
- set goaway [list Xw]
- return [osutils:juststation $goaway $listloc]
-}
-
# remove from listloc OpenCascade units indesirables on NT
proc osutils:juststation {goaway listloc} {
global path
}
}
-# remove from listloc OpenCascade units indesirables on Unix
-proc osutils:justunix { listloc } {
- if { "$::tcl_platform(os)" == "Darwin" } {
- set goaway [list Xw WNT]
- } else {
- set goaway [list WNT]
- }
- return [osutils:juststation $goaway $listloc]
-}
-
-
####### CODEBLOCK ###################################################################
# Function to generate Code Blocks workspace and project files
proc OS:MKCBP { theOutDir theModules theAllSolution thePlatform theCmpl } {
set listloc $theToolKit
}
- if { $thePlatform == "wnt" || $thePlatform == "uwp" } {
- set resultloc [osutils:justwnt $listloc]
- } else {
- set resultloc [osutils:justunix $listloc]
- }
if [array exists written] { unset written }
- foreach fxlo $resultloc {
+ foreach fxlo $listloc {
set xlo $fxlo
set aSrcFiles [osutils:tk:cxxfiles $xlo $thePlatform "src"]
foreach aSrcFile [lsort $aSrcFiles] {
upvar $theIncPaths anIncPaths
set listloc [osutils:tk:units $theToolKit "src"]
- set resultloc [osutils:justunix $listloc]
set aBuildFileSection ""
- set aPackages [lsort -nocase $resultloc]
+ set aPackages [lsort -nocase $listloc]
if { "$theTargetType" == "executable" } {
set aPackages [list "$theToolKit"]
}
#include <Message_Messenger.hxx>
#include <gp_Quaternion.hxx>
#include <V3d_View.hxx>
+#include <WNT_HIDSpaceMouse.hxx>
// =======================================================================
// function : AIS_ViewController
myUpdateStartPointRot (true),
myUpdateStartPointZRot (true),
//
+ my3dMouseNoRotate (false, false, false),
+ my3dMouseToReverse (true, false, false),
+ my3dMouseAccelTrans (2.0f),
+ my3dMouseAccelRotate (4.0f),
+ my3dMouseIsQuadric (true),
+ //
myPanPnt3d (Precision::Infinite(), 0.0, 0.0)
{
+ memset(my3dMouseButtonState, 0, sizeof(my3dMouseButtonState));
myEventTimer.Start();
+ myViewAnimation->SetOwnDuration (0.5);
myAnchorPointPrs1 = new AIS_Point (new Geom_CartesianPoint (0.0, 0.0, 0.0));
myAnchorPointPrs1->SetZLayer (Graphic3d_ZLayerId_Top);
}
}
+// =======================================================================
+// function : Update3dMouse
+// purpose :
+// =======================================================================
+bool AIS_ViewController::Update3dMouse (const WNT_HIDSpaceMouse& theEvent)
+{
+ bool toUpdate = false;
+ toUpdate = update3dMouseTranslation (theEvent) || toUpdate;
+ toUpdate = update3dMouseRotation (theEvent) || toUpdate;
+ toUpdate = update3dMouseKeys (theEvent) || toUpdate;
+ return toUpdate;
+}
+
+// =======================================================================
+// function : update3dMouseTranslation
+// purpose :
+// =======================================================================
+bool AIS_ViewController::update3dMouseTranslation (const WNT_HIDSpaceMouse& theEvent)
+{
+ if (!theEvent.IsTranslation())
+ {
+ return false;
+ }
+
+ bool isIdle = true;
+ const double aTimeStamp = EventTime();
+ const Graphic3d_Vec3d aTrans = theEvent.Translation (isIdle, my3dMouseIsQuadric) * my3dMouseAccelTrans;
+ myKeys.KeyFromAxis (Aspect_VKey_NavSlideLeft, Aspect_VKey_NavSlideRight, aTimeStamp, aTrans.x());
+ myKeys.KeyFromAxis (Aspect_VKey_NavForward, Aspect_VKey_NavBackward, aTimeStamp, aTrans.y());
+ myKeys.KeyFromAxis (Aspect_VKey_NavSlideUp, Aspect_VKey_NavSlideDown, aTimeStamp, aTrans.z());
+ return true;
+}
+
+// =======================================================================
+// function : update3dMouseRotation
+// purpose :
+// =======================================================================
+bool AIS_ViewController::update3dMouseRotation (const WNT_HIDSpaceMouse& theEvent)
+{
+ if (!theEvent.IsRotation()
+ || !myToAllowRotation)
+ {
+ return false;
+ }
+
+ bool isIdle = true, toUpdate = false;
+ const double aTimeStamp = EventTime();
+ const Graphic3d_Vec3d aRot3 = theEvent.Rotation (isIdle, my3dMouseIsQuadric) * my3dMouseAccelRotate;
+ if (!my3dMouseNoRotate.x())
+ {
+ KeyFromAxis (Aspect_VKey_NavLookUp, Aspect_VKey_NavLookDown, aTimeStamp, !my3dMouseToReverse.x() ? aRot3.x() : -aRot3.x());
+ toUpdate = true;
+ }
+ if (!my3dMouseNoRotate.y())
+ {
+ KeyFromAxis (Aspect_VKey_NavRollCW, Aspect_VKey_NavRollCCW, aTimeStamp, !my3dMouseToReverse.y() ? aRot3.y() : -aRot3.y());
+ toUpdate = true;
+ }
+ if (!my3dMouseNoRotate.z())
+ {
+ KeyFromAxis (Aspect_VKey_NavLookLeft, Aspect_VKey_NavLookRight, aTimeStamp, !my3dMouseToReverse.z() ? aRot3.z() : -aRot3.z());
+ toUpdate = true;
+ }
+ return toUpdate;
+}
+
+// =======================================================================
+// function : update3dMouseKeys
+// purpose :
+// =======================================================================
+bool AIS_ViewController::update3dMouseKeys (const WNT_HIDSpaceMouse& theEvent)
+{
+ bool toUpdate = false;
+ const double aTimeStamp = EventTime();
+ if (theEvent.IsKeyState())
+ {
+ const uint32_t aKeyState = theEvent.KeyState();
+ for (unsigned short aKeyBit = 0; aKeyBit < 32; ++aKeyBit)
+ {
+ const bool isPressed = (aKeyState & (1 << aKeyBit)) != 0;
+ const bool isReleased = my3dMouseButtonState[aKeyBit] && !isPressed;
+ //const bool isRepeated = my3dMouseButtonState[aKeyBit] && isPressed;
+ my3dMouseButtonState[aKeyBit] = isPressed;
+ if (!isReleased && !isPressed)
+ {
+ continue;
+ }
+
+ const Aspect_VKey aVKey = theEvent.HidToSpaceKey (aKeyBit);
+ if (aVKey != Aspect_VKey_UNKNOWN)
+ {
+ toUpdate = true;
+ if (isPressed)
+ {
+ KeyDown (aVKey, aTimeStamp);
+ }
+ else
+ {
+ KeyUp (aVKey, aTimeStamp);
+ }
+ }
+ }
+ }
+ return toUpdate;
+}
+
// =======================================================================
// function : SetNavigationMode
// purpose :
return theCtx ->GravityPoint (theView);
}
+// =======================================================================
+// function : FitAllAuto
+// purpose :
+// =======================================================================
+void AIS_ViewController::FitAllAuto (const Handle(AIS_InteractiveContext)& theCtx,
+ const Handle(V3d_View)& theView)
+{
+ const Bnd_Box aBoxSel = theCtx->BoundingBoxOfSelection();
+ const double aFitMargin = 0.01;
+ if (aBoxSel.IsVoid())
+ {
+ theView->FitAll (aFitMargin, false);
+ return;
+ }
+
+ // fit all algorithm is not 100% stable - so compute some precision to compare equal camera values
+ const double aFitTol = (aBoxSel.CornerMax().XYZ() - aBoxSel.CornerMin().XYZ()).Modulus() * 0.000001;
+ const Bnd_Box aBoxAll = theView->View()->MinMaxValues();
+
+ const Handle(Graphic3d_Camera)& aCam = theView->Camera();
+ Handle(Graphic3d_Camera) aCameraSel = new Graphic3d_Camera (aCam);
+ Handle(Graphic3d_Camera) aCameraAll = new Graphic3d_Camera (aCam);
+ theView->FitMinMax (aCameraSel, aBoxSel, aFitMargin);
+ theView->FitMinMax (aCameraAll, aBoxAll, aFitMargin);
+ if (aCameraSel->Center().IsEqual (aCam->Center(), aFitTol)
+ && Abs (aCameraSel->Scale() - aCam->Scale()) < aFitTol
+ && Abs (aCameraSel->Distance() - aCam->Distance()) < aFitTol)
+ {
+ // fit all entire view on second FitALL request
+ aCam->Copy (aCameraAll);
+ }
+ else
+ {
+ aCam->Copy (aCameraSel);
+ }
+}
+
+// =======================================================================
+// function : handleViewOrientationKeys
+// purpose :
+// =======================================================================
+void AIS_ViewController::handleViewOrientationKeys (const Handle(AIS_InteractiveContext)& theCtx,
+ const Handle(V3d_View)& theView)
+{
+ if (myNavigationMode == AIS_NavigationMode_FirstPersonWalk)
+ {
+ return;
+ }
+
+ Handle(Graphic3d_Camera) aCameraBack;
+ struct ViewKeyAction
+ {
+ Aspect_VKey Key;
+ V3d_TypeOfOrientation Orientation;
+ };
+ static const ViewKeyAction THE_VIEW_KEYS[] =
+ {
+ { Aspect_VKey_ViewTop, V3d_TypeOfOrientation_Zup_Top },
+ { Aspect_VKey_ViewBottom, V3d_TypeOfOrientation_Zup_Bottom },
+ { Aspect_VKey_ViewLeft, V3d_TypeOfOrientation_Zup_Left },
+ { Aspect_VKey_ViewRight, V3d_TypeOfOrientation_Zup_Right },
+ { Aspect_VKey_ViewFront, V3d_TypeOfOrientation_Zup_Front },
+ { Aspect_VKey_ViewBack, V3d_TypeOfOrientation_Zup_Back },
+ { Aspect_VKey_ViewAxoLeftProj, V3d_TypeOfOrientation_Zup_AxoLeft },
+ { Aspect_VKey_ViewAxoRightProj, V3d_TypeOfOrientation_Zup_AxoRight },
+ { Aspect_VKey_ViewRoll90CW, (V3d_TypeOfOrientation )-1},
+ { Aspect_VKey_ViewRoll90CCW, (V3d_TypeOfOrientation )-1},
+ { Aspect_VKey_ViewFitAll, (V3d_TypeOfOrientation )-1}
+ };
+ {
+ Standard_Mutex::Sentry aLock (myKeys.Mutex());
+ const size_t aNbKeys = sizeof(THE_VIEW_KEYS) / sizeof(*THE_VIEW_KEYS);
+ const double anEventTime = EventTime();
+ for (size_t aKeyIter = 0; aKeyIter < aNbKeys; ++aKeyIter)
+ {
+ const ViewKeyAction& aKeyAction = THE_VIEW_KEYS[aKeyIter];
+ if (!myKeys.IsKeyDown (aKeyAction.Key))
+ {
+ continue;
+ }
+
+ myKeys.KeyUp (aKeyAction.Key, anEventTime);
+ if (aCameraBack.IsNull())
+ {
+ aCameraBack = theView->Camera();
+ theView->SetCamera (new Graphic3d_Camera (aCameraBack));
+ }
+ if (aKeyAction.Orientation != (V3d_TypeOfOrientation )-1)
+ {
+ theView->SetProj (aKeyAction.Orientation);
+ FitAllAuto (theCtx, theView);
+ }
+ else if (aKeyAction.Key == Aspect_VKey_ViewRoll90CW)
+ {
+ const double aTwist = theView->Twist() + M_PI / 2.0;
+ theView->SetTwist (aTwist);
+ }
+ else if (aKeyAction.Key == Aspect_VKey_ViewRoll90CCW)
+ {
+ const double aTwist = theView->Twist() - M_PI / 2.0;
+ theView->SetTwist (aTwist);
+ }
+ else if (aKeyAction.Key == Aspect_VKey_ViewFitAll)
+ {
+ FitAllAuto (theCtx, theView);
+ }
+ }
+ }
+
+ if (aCameraBack.IsNull())
+ {
+ return;
+ }
+
+ Handle(Graphic3d_Camera) aCameraNew = theView->Camera();
+ theView->SetCamera (aCameraBack);
+ const Graphic3d_Mat4d anOrientMat1 = aCameraBack->OrientationMatrix();
+ const Graphic3d_Mat4d anOrientMat2 = aCameraNew ->OrientationMatrix();
+ if (anOrientMat1 != anOrientMat2)
+ {
+ const Handle(AIS_AnimationCamera)& aCamAnim = myViewAnimation;
+ aCamAnim->SetView (theView);
+ aCamAnim->SetStartPts (0.0);
+ aCamAnim->SetCameraStart (new Graphic3d_Camera (aCameraBack));
+ aCamAnim->SetCameraEnd (new Graphic3d_Camera (aCameraNew));
+ aCamAnim->StartTimer (0.0, 1.0, true, false);
+ }
+}
+
// =======================================================================
// function : handleNavigationKeys
// purpose :
{
const Handle(V3d_View)& aView = aViewIter.Value();
if (aView->IsInvalidated()
- || myToAskNextFrame)
+ || (myToAskNextFrame && aView == theView))
{
if (aView->ComputedMode())
{
{
const bool wasImmediateUpdate = theView->SetImmediateUpdate (false);
+ handleViewOrientationKeys (theCtx, theView);
const AIS_WalkDelta aWalk = handleNavigationKeys (theCtx, theView);
handleXRInput (theCtx, theView, aWalk);
if (theView->View()->IsActiveXR())
class AIS_XRTrackedDevice;
class Graphic3d_Camera;
class V3d_View;
+class WNT_HIDSpaceMouse;
//! Auxiliary structure for handling viewer events between GUI and Rendering threads.
//!
Standard_EXPORT virtual void UpdateTouchPoint (Standard_Size theId,
const Graphic3d_Vec2d& thePnt);
+public: //! @name 3d mouse input
+
+ //! Return acceleration ratio for translation event; 2.0 by default.
+ float Get3dMouseTranslationScale() const { return my3dMouseAccelTrans; }
+
+ //! Set acceleration ratio for translation event.
+ void Set3dMouseTranslationScale (float theScale) { my3dMouseAccelTrans = theScale; }
+
+ //! Return acceleration ratio for rotation event; 4.0 by default.
+ float Get3dMouseRotationScale() const { return my3dMouseAccelRotate; }
+
+ //! Set acceleration ratio for rotation event.
+ void Set3dMouseRotationScale (float theScale) { my3dMouseAccelRotate = theScale; }
+
+ //! Return quadric acceleration flag; TRUE by default.
+ bool To3dMousePreciseInput() const { return my3dMouseIsQuadric; }
+
+ //! Set quadric acceleration flag.
+ void Set3dMousePreciseInput (bool theIsQuadric) { my3dMouseIsQuadric = theIsQuadric; }
+
+ //! Return 3d mouse rotation axes (tilt/roll/spin) ignore flag; (FALSE, FALSE, FALSE) by default.
+ const NCollection_Vec3<bool>& Get3dMouseIsNoRotate() const { return my3dMouseNoRotate; }
+
+ //! Return 3d mouse rotation axes (tilt/roll/spin) ignore flag; (FALSE, FALSE, FALSE) by default.
+ NCollection_Vec3<bool>& Change3dMouseIsNoRotate() { return my3dMouseNoRotate; }
+
+ //! Return 3d mouse rotation axes (tilt/roll/spin) reverse flag; (TRUE, FALSE, FALSE) by default.
+ const NCollection_Vec3<bool>& Get3dMouseToReverse() const { return my3dMouseToReverse; }
+
+ //! Return 3d mouse rotation axes (tilt/roll/spin) reverse flag; (TRUE, FALSE, FALSE) by default.
+ NCollection_Vec3<bool>& Change3dMouseToReverse() { return my3dMouseToReverse; }
+
+ //! Process 3d mouse input event (redirects to translation, rotation and keys).
+ Standard_EXPORT virtual bool Update3dMouse (const WNT_HIDSpaceMouse& theEvent);
+
+ //! Process 3d mouse input translation event.
+ Standard_EXPORT virtual bool update3dMouseTranslation (const WNT_HIDSpaceMouse& theEvent);
+
+ //! Process 3d mouse input rotation event.
+ Standard_EXPORT virtual bool update3dMouseRotation (const WNT_HIDSpaceMouse& theEvent);
+
+ //! Process 3d mouse input keys event.
+ Standard_EXPORT virtual bool update3dMouseKeys (const WNT_HIDSpaceMouse& theEvent);
+
public:
//! Return event time (e.g. current time).
Standard_EXPORT virtual gp_Pnt GravityPoint (const Handle(AIS_InteractiveContext)& theCtx,
const Handle(V3d_View)& theView);
+ //! Modify view camera to fit all objects.
+ //! Default implementation fits either all visible and all selected objects (swapped on each call).
+ Standard_EXPORT virtual void FitAllAuto (const Handle(AIS_InteractiveContext)& theCtx,
+ const Handle(V3d_View)& theView);
+
public:
- //! Perform navigation.
+ //! Handle hot-keys defining new camera orientation (Aspect_VKey_ViewTop and similar keys).
+ //! Default implementation starts an animated transaction from the current to the target camera orientation, when specific action key was pressed.
+ //! This method is expected to be called from rendering thread.
+ Standard_EXPORT virtual void handleViewOrientationKeys (const Handle(AIS_InteractiveContext)& theCtx,
+ const Handle(V3d_View)& theView);
+
+ //! Perform navigation (Aspect_VKey_NavForward and similar keys).
//! This method is expected to be called from rendering thread.
Standard_EXPORT virtual AIS_WalkDelta handleNavigationKeys (const Handle(AIS_InteractiveContext)& theCtx,
const Handle(V3d_View)& theView);
- //! Perform camera actions.
+ //! Perform immediate camera actions (rotate/zoom/pan) on gesture progress.
//! This method is expected to be called from rendering thread.
Standard_EXPORT virtual void handleCameraActions (const Handle(AIS_InteractiveContext)& theCtx,
const Handle(V3d_View)& theView,
Standard_Boolean myUpdateStartPointRot; //!< flag indicating that new gravity point should be picked for starting rotation gesture
Standard_Boolean myUpdateStartPointZRot; //!< flag indicating that new gravity point should be picked for starting Z-rotation gesture
+protected: //! @name 3d mouse input variables
+
+ bool my3dMouseButtonState[32];//!< cached button state
+ NCollection_Vec3<bool> my3dMouseNoRotate; //!< ignore 3d mouse rotation axes
+ NCollection_Vec3<bool> my3dMouseToReverse; //!< reverse 3d mouse rotation axes
+ float my3dMouseAccelTrans; //!< acceleration ratio for translation event
+ float my3dMouseAccelRotate; //!< acceleration ratio for rotation event
+ bool my3dMouseIsQuadric; //!< quadric acceleration
+
protected: //! @name rotation/panning transient state variables
Handle(AIS_Point) myAnchorPointPrs1; //!< anchor point presentation (Graphic3d_ZLayerId_Top)
myViewAnimation (new AIS_AnimationCamera ("AIS_ViewCube", Handle(V3d_View)())),
myStartState(new Graphic3d_Camera()),
myEndState (new Graphic3d_Camera()),
- myDuration (0.5),
myToAutoStartAnim (true),
myIsFixedAnimation (true),
myToFitSelected (true),
myToResetCameraUp (false)
{
+ myViewAnimation->SetOwnDuration (0.5);
myInfiniteState = true;
myIsMutable = true;
myDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
}
}
+//=======================================================================
+//function : Duration
+//purpose :
+//=======================================================================
+Standard_Real AIS_ViewCube::Duration() const
+{
+ return myViewAnimation->OwnDuration();
+}
+
+//=======================================================================
+//function : SetDuration
+//purpose :
+//=======================================================================
+void AIS_ViewCube::SetDuration (Standard_Real theDurationSec)
+{
+ myViewAnimation->SetOwnDuration (theDurationSec);
+}
+
//=======================================================================
//function : HasAnimation
//purpose :
myViewAnimation->SetView (aView);
myViewAnimation->SetCameraStart (myStartState);
myViewAnimation->SetCameraEnd (myEndState);
- myViewAnimation->SetOwnDuration (myDuration);
myViewAnimation->StartTimer (0.0, 1.0, true, false);
}
Standard_Boolean AIS_ViewCube::updateAnimation()
{
const Standard_Real aPts = myViewAnimation->UpdateTimer();
- if (aPts >= myDuration)
+ if (aPts >= myViewAnimation->OwnDuration())
{
myViewAnimation->Stop();
onAnimationFinished();
public: //! @name animation methods
//! Return duration of animation in seconds; 0.5 sec by default
- Standard_Real Duration() const { return myDuration; }
+ Standard_EXPORT Standard_Real Duration() const;
//! Set duration of animation.
//! @param theValue [in] input value of duration in seconds
- void SetDuration (Standard_Real theValue) { myDuration = theValue; }
+ Standard_EXPORT void SetDuration (Standard_Real theValue);
//! Return TRUE if new camera Up direction should be always set to default value for a new camera Direction; FALSE by default.
//! When this flag is FALSE, the new camera Up will be set as current Up orthogonalized to the new camera Direction,
Handle(AIS_AnimationCamera) myViewAnimation; //!< Camera animation object
Handle(Graphic3d_Camera) myStartState; //!< Start state of view camera
Handle(Graphic3d_Camera) myEndState; //!< End state of view camera
- Standard_Real myDuration; //!< Duration of animation. By default it is half a second
Standard_Boolean myToAutoStartAnim; //!< start animation automatically on click
Standard_Boolean myIsFixedAnimation; //!< fixed-loop animation
Standard_Boolean myToFitSelected; //!< fit selected or fit entire scene
Aspect_VKey_BrowserFavorites,
Aspect_VKey_BrowserHome,
+ // 3d view keys
+ Aspect_VKey_ViewTop,
+ Aspect_VKey_ViewBottom,
+ Aspect_VKey_ViewLeft,
+ Aspect_VKey_ViewRight,
+ Aspect_VKey_ViewFront,
+ Aspect_VKey_ViewBack,
+ Aspect_VKey_ViewAxoLeftProj,
+ Aspect_VKey_ViewAxoRightProj,
+ Aspect_VKey_ViewFitAll,
+ Aspect_VKey_ViewRoll90CW,
+ Aspect_VKey_ViewRoll90CCW,
+ Aspect_VKey_ViewSwitchRotate,
+
// modifier keys, @sa Aspect_VKey_ModifiersLower and Aspect_VKey_ModifiersUpper below
Aspect_VKey_Shift,
Aspect_VKey_Control,
return myKeys[theKey].Status == KeyStatus_Pressed;
}
+ //! Return mutex for thread-safe updates.
+ //! All operations in class implicitly locks this mutex,
+ //! so this method could be used only for batch processing of keys.
+ Standard_Mutex& Mutex() { return myLock; }
+
public:
//! Reset the key state into unpressed state.
const Handle(AIS_AnimationCamera)& ViewerTest_EventManager::GlobalViewAnimation()
{
static Handle(AIS_AnimationCamera) THE_CAMERA_ANIM = new AIS_AnimationCamera ("ViewerTest_EventManager_ViewAnimation", Handle(V3d_View)());
+ THE_CAMERA_ANIM->SetOwnDuration (0.5);
return THE_CAMERA_ANIM;
}
#include <Message_ProgressSentry.hxx>
#include <NCollection_DataMap.hxx>
#include <NCollection_List.hxx>
+#include <NCollection_LocalArray.hxx>
#include <NCollection_Vector.hxx>
#include <OSD.hxx>
#include <OSD_Timer.hxx>
#if defined(_WIN32)
#include <WNT_WClass.hxx>
#include <WNT_Window.hxx>
+ #include <WNT_HIDSpaceMouse.hxx>
#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
#include <Cocoa_Window.hxx>
#else
aPxLeft, aPxTop,
aPxWidth, aPxHeight,
Quantity_NOC_BLACK);
+ VT_GetWindow()->RegisterRawInputDevices (WNT_Window::RawInputMask_SpaceMouse);
#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
aPxLeft, aPxTop,
ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), aView, true);
break;
}
+ case WM_INPUT:
+ {
+ UINT aSize = 0;
+ ::GetRawInputData ((HRAWINPUT )lParam, RID_INPUT, NULL, &aSize, sizeof(RAWINPUTHEADER));
+ NCollection_LocalArray<BYTE> aRawData (aSize);
+ if (aSize == 0 || ::GetRawInputData ((HRAWINPUT )lParam, RID_INPUT, aRawData, &aSize, sizeof(RAWINPUTHEADER)) != aSize)
+ {
+ break;
+ }
+
+ const RAWINPUT* aRawInput = (RAWINPUT* )(BYTE* )aRawData;
+ if (aRawInput->header.dwType != RIM_TYPEHID)
+ {
+ break;
+ }
+
+ RID_DEVICE_INFO aDevInfo;
+ aDevInfo.cbSize = sizeof(RID_DEVICE_INFO);
+ UINT aDevInfoSize = sizeof(RID_DEVICE_INFO);
+ if (::GetRawInputDeviceInfoW (aRawInput->header.hDevice, RIDI_DEVICEINFO, &aDevInfo, &aDevInfoSize) != sizeof(RID_DEVICE_INFO)
+ || (aDevInfo.hid.dwVendorId != WNT_HIDSpaceMouse::VENDOR_ID_LOGITECH
+ && aDevInfo.hid.dwVendorId != WNT_HIDSpaceMouse::VENDOR_ID_3DCONNEXION))
+ {
+ break;
+ }
+
+ WNT_HIDSpaceMouse aSpaceData (aDevInfo.hid.dwProductId, aRawInput->data.hid.bRawData, aRawInput->data.hid.dwSizeHid);
+ if (ViewerTest::CurrentEventManager()->Update3dMouse (aSpaceData)
+ && !VT_GetWindow().IsNull())
+ {
+ VT_GetWindow()->InvalidateContent();
+ }
+ break;
+ }
default:
{
return DefWindowProcW (theWinHandle, theMsg, wParam, lParam);
WNT_ClassDefinitionError.hxx
WNT_Dword.hxx
+WNT_HIDSpaceMouse.cxx
+WNT_HIDSpaceMouse.hxx
WNT_OrientationType.hxx
WNT_WClass.cxx
WNT_WClass.hxx
--- /dev/null
+// Copyright (c) 2019-2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <WNT_HIDSpaceMouse.hxx>
+
+namespace
+{
+ //! Enumeration of known Space Mouse models.
+ enum SpacePid
+ {
+ // VENDOR_ID_LOGITECH
+ SpacePid_SpaceMouse = 0xC603,
+ SpacePid_CADMan = 0xC605,
+ SpacePid_SpaceMouseClassic = 0xC606,
+ SpacePid_SpaceBall5000 = 0xC621,
+ SpacePid_SpaceTraveler = 0xC623,
+ SpacePid_SpacePilot = 0xC625,
+ SpacePid_SpaceNavigator = 0xC626, //!< has only 2 "menu" buttons (second one is treated as SpaceVKey_Fit)
+ SpacePid_SpaceExplorer = 0xC627, //!< 15 buttons
+ SpacePid_NavigatorForNotebooks = 0xC628, //!< has only 2 "menu" buttons (second one is treated as SpaceVKey_Fit)
+ SpacePid_SpacePilotPro = 0xC629, //!< 31 buttons
+ SpacePid_SpaceMousePro = 0xC62B, //!< has only 15 buttons, but codes range from 0 to 26
+ // VENDOR_ID_3DCONNEXION
+ SpacePid_SpaceMouseWireless1 = 0xC62E, //!< [plugged in] has only 2 buttons
+ SpacePid_SpaceMouseWireless2 = 0xC62F, //!< [wireless] has only 2 buttons
+ SpacePid_SpaceMouseProWireless1 = 0xC631, //!< [plugged in] has only 15 buttons
+ SpacePid_SpaceMouseProWireless2 = 0xC632, //!< [wireless] has only 15 buttons
+ SpacePid_SpaceMouseEnterprise = 0xC633, //!< 31 buttons
+ SpacePid_SpaceMouseCompact = 0xC635
+ };
+
+ //! Enumeration of known keys available on various Space Mouse models.
+ enum SpaceVKey
+ {
+ SpaceVKey_INVALID = 0,
+ SpaceVKey_Menu = 1, SpaceVKey_Fit,
+ SpaceVKey_Top, SpaceVKey_Left, SpaceVKey_Right, SpaceVKey_Front, SpaceVKey_Bottom, SpaceVKey_Back,
+ SpaceVKey_RollCW, SpaceVKey_RollCCW,
+ SpaceVKey_ISO1, SpaceVKey_ISO2,
+ SpaceVKey_1, SpaceVKey_2, SpaceVKey_3, SpaceVKey_4, SpaceVKey_5, SpaceVKey_6, SpaceVKey_7, SpaceVKey_8, SpaceVKey_9, SpaceVKey_10,
+ SpaceVKey_Esc, SpaceVKey_Alt, SpaceVKey_Shift, SpaceVKey_Ctrl,
+ SpaceVKey_Rotate, SpaceVKey_PanZoom, SpaceVKey_Dominant,
+ SpaceVKey_Plus, SpaceVKey_Minus,
+ };
+
+ //! The raw value range on tested device is [-350; 350].
+ enum { THE_RAW_RANGE_350 = 350 };
+
+ //! Convert key state bit into virtual key.
+ static SpaceVKey hidToSpaceKey (unsigned long theProductId,
+ unsigned short theKeyBit)
+ {
+ static const SpaceVKey THE_PILOT_KEYS[] =
+ {
+ SpaceVKey_1, SpaceVKey_2, SpaceVKey_3, SpaceVKey_4, SpaceVKey_5, SpaceVKey_6,
+ SpaceVKey_Top, SpaceVKey_Left, SpaceVKey_Right, SpaceVKey_Front,
+ SpaceVKey_Esc, SpaceVKey_Alt, SpaceVKey_Shift, SpaceVKey_Ctrl,
+ SpaceVKey_Fit, SpaceVKey_Menu,
+ SpaceVKey_Plus, SpaceVKey_Minus,
+ SpaceVKey_Dominant, SpaceVKey_Rotate
+ };
+ const int THE_NB_PILOT_KEYS = sizeof(THE_PILOT_KEYS) / sizeof(SpaceVKey);
+
+ static const SpaceVKey THE_EXPLORER_KEYS[] =
+ {
+ SpaceVKey_1, SpaceVKey_2,
+ SpaceVKey_Top, SpaceVKey_Left, SpaceVKey_Right, SpaceVKey_Front,
+ SpaceVKey_Esc, SpaceVKey_Alt, SpaceVKey_Shift, SpaceVKey_Ctrl,
+ SpaceVKey_Fit, SpaceVKey_Menu,
+ SpaceVKey_Plus, SpaceVKey_Minus,
+ SpaceVKey_Rotate
+ };
+ const int THE_NB_EXPLORER_KEYS = sizeof(THE_EXPLORER_KEYS) / sizeof(SpaceVKey);
+
+ // shared by latest 3Dconnexion hardware
+ static const SpaceVKey THE_SPACEMOUSEPRO_KEYS[] =
+ {
+ SpaceVKey_Menu, SpaceVKey_Fit,
+ SpaceVKey_Top, SpaceVKey_Left, SpaceVKey_Right, SpaceVKey_Front, SpaceVKey_Bottom, SpaceVKey_Back,
+ SpaceVKey_RollCW, SpaceVKey_RollCCW, SpaceVKey_ISO1, SpaceVKey_ISO2,
+ SpaceVKey_1, SpaceVKey_2, SpaceVKey_3, SpaceVKey_4,
+ SpaceVKey_5, SpaceVKey_6, SpaceVKey_7, SpaceVKey_8, SpaceVKey_9, SpaceVKey_10,
+ SpaceVKey_Esc, SpaceVKey_Alt, SpaceVKey_Shift, SpaceVKey_Ctrl,
+ SpaceVKey_Rotate,
+ SpaceVKey_PanZoom, SpaceVKey_Dominant, SpaceVKey_Plus, SpaceVKey_Minus
+ };
+ const int THE_NB_SPACEMOUSEPRO_KEYS = sizeof(THE_SPACEMOUSEPRO_KEYS) / sizeof(SpaceVKey);
+
+ switch (theProductId)
+ {
+ case SpacePid_SpacePilot:
+ return theKeyBit < THE_NB_PILOT_KEYS ? THE_PILOT_KEYS[theKeyBit] : SpaceVKey_INVALID;
+ case SpacePid_SpaceExplorer:
+ return theKeyBit < THE_NB_EXPLORER_KEYS ? THE_EXPLORER_KEYS[theKeyBit] : SpaceVKey_INVALID;
+ case SpacePid_SpaceNavigator:
+ case SpacePid_NavigatorForNotebooks:
+ case SpacePid_SpacePilotPro:
+ case SpacePid_SpaceMousePro:
+ case SpacePid_SpaceMouseWireless1:
+ case SpacePid_SpaceMouseWireless2:
+ case SpacePid_SpaceMouseProWireless1:
+ case SpacePid_SpaceMouseProWireless2:
+ case SpacePid_SpaceMouseEnterprise:
+ case SpacePid_SpaceMouseCompact:
+ return theKeyBit < THE_NB_SPACEMOUSEPRO_KEYS ? THE_SPACEMOUSEPRO_KEYS[theKeyBit] : SpaceVKey_INVALID;
+ }
+ return SpaceVKey_INVALID;
+ }
+
+}
+
+// =======================================================================
+// function : WNT_HIDSpaceMouse
+// purpose :
+// =======================================================================
+WNT_HIDSpaceMouse::WNT_HIDSpaceMouse (unsigned long theProductId,
+ const Standard_Byte* theData,
+ Standard_Size theSize)
+: myData (theData),
+ mySize (theSize),
+ myProductId (theProductId),
+ myValueRange (THE_RAW_RANGE_350)
+{
+ //
+}
+
+// =======================================================================
+// function : IsKnownProduct
+// purpose :
+// =======================================================================
+bool WNT_HIDSpaceMouse::IsKnownProduct (unsigned long theProductId)
+{
+ switch (theProductId)
+ {
+ case SpacePid_SpacePilot:
+ case SpacePid_SpaceExplorer:
+ case SpacePid_SpaceNavigator:
+ case SpacePid_NavigatorForNotebooks:
+ case SpacePid_SpacePilotPro:
+ case SpacePid_SpaceMousePro:
+ case SpacePid_SpaceMouseWireless1:
+ case SpacePid_SpaceMouseWireless2:
+ case SpacePid_SpaceMouseProWireless1:
+ case SpacePid_SpaceMouseProWireless2:
+ case SpacePid_SpaceMouseEnterprise:
+ case SpacePid_SpaceMouseCompact:
+ return true;
+ }
+ return false;
+}
+
+// =======================================================================
+// function : Translation
+// purpose :
+// =======================================================================
+Graphic3d_Vec3d WNT_HIDSpaceMouse::Translation (bool& theIsIdle,
+ bool theIsQuadric) const
+{
+ theIsIdle = true;
+ return myData[0] == SpaceRawInput_Translation
+ && (mySize == 7 || mySize == 13)
+ ? fromRawVec3 (theIsIdle, myData + 1, true, theIsQuadric)
+ : Graphic3d_Vec3d();
+}
+
+// =======================================================================
+// function : Rotation
+// purpose :
+// =======================================================================
+Graphic3d_Vec3d WNT_HIDSpaceMouse::Rotation (bool& theIsIdle,
+ bool theIsQuadric) const
+{
+ theIsIdle = true;
+ if (myData[0] == SpaceRawInput_Rotation && mySize == 7)
+ {
+ return fromRawVec3 (theIsIdle, myData + 1, false, theIsQuadric);
+ }
+ else if (myData[0] == SpaceRawInput_Translation && mySize == 13)
+ {
+ return fromRawVec3 (theIsIdle, myData + 7, false, theIsQuadric);
+ }
+ return Graphic3d_Vec3d();
+}
+
+// =======================================================================
+// function : fromRawVec3
+// purpose :
+// =======================================================================
+Graphic3d_Vec3d WNT_HIDSpaceMouse::fromRawVec3 (bool& theIsIdle,
+ const Standard_Byte* theData,
+ bool theIsTrans,
+ bool theIsQuadric) const
+{
+ theIsIdle = true;
+ const NCollection_Vec3<int16_t>& aRaw16 = *reinterpret_cast<const NCollection_Vec3<int16_t>*>(theData);
+ Graphic3d_Vec3d aVec (aRaw16.x(), aRaw16.y(), aRaw16.z());
+ if (theIsTrans)
+ {
+ static const int16_t THE_MIN_RAW_TRANS = 4;
+ static const int16_t THE_MIN_RAW_TRANS_Z = 8;
+ for (int aCompIter = 0; aCompIter < 3; ++aCompIter)
+ {
+ if (aRaw16[aCompIter] > -THE_MIN_RAW_TRANS && aRaw16[aCompIter] < THE_MIN_RAW_TRANS)
+ {
+ aVec[aCompIter] = 0.0;
+ }
+ else
+ {
+ theIsIdle = false;
+ }
+ }
+ if (aRaw16.z() > -THE_MIN_RAW_TRANS_Z && aRaw16.z() < THE_MIN_RAW_TRANS_Z)
+ {
+ aVec.z() = 0.0;
+ }
+ }
+ else
+ {
+ for (int aCompIter = 0; aCompIter < 3; ++aCompIter)
+ {
+ if (aRaw16[aCompIter] != 0)
+ {
+ theIsIdle = false;
+ break;
+ }
+ }
+ }
+
+ // determine raw value range
+ for (int aCompIter = 0; aCompIter < 3; ++aCompIter)
+ {
+ if (aRaw16[aCompIter] > myValueRange
+ || -aRaw16[aCompIter] > myValueRange)
+ {
+ myValueRange = 32767; // SHRT_MAX
+ break;
+ }
+ }
+
+ if (!theIsQuadric)
+ {
+ return aVec / double(myValueRange);
+ }
+
+ for (int aCompIter = 0; aCompIter < 3; ++aCompIter)
+ {
+ aVec[aCompIter] = aRaw16[aCompIter] > 0
+ ? aVec[aCompIter] * aVec[aCompIter]
+ : -aVec[aCompIter] * aVec[aCompIter];
+ }
+ return aVec / (double(myValueRange) * double(myValueRange));
+}
+
+// =======================================================================
+// function : HidToSpaceKey
+// purpose :
+// =======================================================================
+Aspect_VKey WNT_HIDSpaceMouse::HidToSpaceKey (unsigned short theKeyBit) const
+{
+ const SpaceVKey aKey = hidToSpaceKey (myProductId, theKeyBit);
+ switch (aKey)
+ {
+ case SpaceVKey_1:
+ case SpaceVKey_2:
+ case SpaceVKey_3:
+ case SpaceVKey_4:
+ case SpaceVKey_5:
+ case SpaceVKey_6:
+ case SpaceVKey_7:
+ case SpaceVKey_8:
+ case SpaceVKey_9:
+ case SpaceVKey_10:
+ return (int(aKey) - int(SpaceVKey_1)) + Aspect_VKey_1;
+ case SpaceVKey_Esc:
+ return Aspect_VKey_Escape;
+ case SpaceVKey_Shift:
+ return Aspect_VKey_Shift;
+ case SpaceVKey_Alt:
+ return Aspect_VKey_Alt;
+ case SpaceVKey_Ctrl:
+ return Aspect_VKey_Control;
+ case SpaceVKey_Top:
+ return Aspect_VKey_ViewTop;
+ case SpaceVKey_Bottom:
+ return Aspect_VKey_ViewBottom;
+ case SpaceVKey_Left:
+ return Aspect_VKey_ViewLeft;
+ case SpaceVKey_Right:
+ return Aspect_VKey_ViewRight;
+ case SpaceVKey_Front:
+ return Aspect_VKey_ViewFront;
+ case SpaceVKey_Back:
+ return Aspect_VKey_ViewBack;
+ case SpaceVKey_ISO1:
+ return Aspect_VKey_ViewAxoLeftProj;
+ case SpaceVKey_ISO2:
+ return Aspect_VKey_ViewAxoRightProj;
+ case SpaceVKey_Fit:
+ return Aspect_VKey_ViewFitAll;
+ case SpaceVKey_RollCW:
+ return Aspect_VKey_ViewRoll90CW;
+ case SpaceVKey_RollCCW:
+ return Aspect_VKey_ViewRoll90CCW;
+ case SpaceVKey_Rotate:
+ return Aspect_VKey_ViewSwitchRotate;
+ default:
+ break;
+ }
+ return Aspect_VKey_UNKNOWN;
+}
--- /dev/null
+// Copyright (c) 2019-2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _WNT_HIDSpaceMouse_Header
+#define _WNT_HIDSpaceMouse_Header
+
+#include <Aspect_VKey.hxx>
+#include <Graphic3d_Vec.hxx>
+
+//! Wrapper over Space Mouse data chunk within WM_INPUT event (known also as Raw Input in WinAPI).
+//! This class predefines specific list of supported devices, which does not depend on 3rdparty library provided by mouse vendor.
+//! Supported input chunks:
+//! - Rotation (3 directions);
+//! - Translation (3 directions);
+//! - Pressed buttons.
+//!
+//! To use the class, register Raw Input device:
+//! @code
+//! Handle(WNT_Window) theWindow;
+//! RAWINPUTDEVICE aRawInDevList[1];
+//! RAWINPUTDEVICE& aRawSpace = aRawInDevList[0];
+//! aRawSpace.usUsagePage = HID_USAGE_PAGE_GENERIC;
+//! aRawSpace.usUsage = HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER;
+//! aRawSpace.dwFlags = 0; // RIDEV_DEVNOTIFY
+//! aRawSpace.hwndTarget = (HWND )theWindow->NativeHandle();
+//! if (!::RegisterRawInputDevices (aRawInDevList, 1, sizeof(aRawInDevList[0]))) { Error; }
+//! @endcode
+//!
+//! Then handle WM_INPUT events within window message loop.
+//! @code
+//! AIS_ViewController theViewCtrl;
+//! case WM_INPUT:
+//! {
+//! UINT aSize = 0;
+//! ::GetRawInputData ((HRAWINPUT )theLParam, RID_INPUT, NULL, &aSize, sizeof(RAWINPUTHEADER));
+//! NCollection_LocalArray<BYTE> aRawData (aSize); // receive Raw Input for any device and process known devices
+//! if (aSize == 0 || ::GetRawInputData ((HRAWINPUT )theLParam, RID_INPUT, aRawData, &aSize, sizeof(RAWINPUTHEADER)) != aSize)
+//! {
+//! break;
+//! }
+//! const RAWINPUT* aRawInput = (RAWINPUT* )(BYTE* )aRawData;
+//! if (aRawInput->header.dwType != RIM_TYPEHID)
+//! {
+//! break;
+//! }
+//!
+//! RID_DEVICE_INFO aDevInfo; aDevInfo.cbSize = sizeof(RID_DEVICE_INFO);
+//! UINT aDevInfoSize = sizeof(RID_DEVICE_INFO);
+//! if (::GetRawInputDeviceInfoW (aRawInput->header.hDevice, RIDI_DEVICEINFO, &aDevInfo, &aDevInfoSize) != sizeof(RID_DEVICE_INFO)
+//! || (aDevInfo.hid.dwVendorId != WNT_HIDSpaceMouse::VENDOR_ID_LOGITECH
+//! && aDevInfo.hid.dwVendorId != WNT_HIDSpaceMouse::VENDOR_ID_3DCONNEXION))
+//! {
+//! break;
+//! }
+//!
+//! Aspect_VKeySet& aKeys = theViewCtrl.ChangeKeys();
+//! const double aTimeStamp = theViewCtrl.EventTime();
+//! WNT_HIDSpaceMouse aSpaceData (aDevInfo.hid.dwProductId, aRawInput->data.hid.bRawData, aRawInput->data.hid.dwSizeHid);
+//! if (aSpaceData.IsTranslation())
+//! {
+//! // process translation input
+//! bool isIdle = true, isQuadric = true;
+//! const Graphic3d_Vec3d aTrans = aSpaceData.Translation (isIdle, isQuadric);
+//! aKeys.KeyFromAxis (Aspect_VKey_NavSlideLeft, Aspect_VKey_NavSlideRight, aTimeStamp, aTrans.x());
+//! aKeys.KeyFromAxis (Aspect_VKey_NavForward, Aspect_VKey_NavBackward, aTimeStamp, aTrans.y());
+//! aKeys.KeyFromAxis (Aspect_VKey_NavSlideUp, Aspect_VKey_NavSlideDown, aTimeStamp, aTrans.z());
+//! }
+//! if (aSpaceData.IsRotation()) {} // process rotation input
+//! if (aSpaceData.IsKeyState()) {} // process keys input
+//! break;
+//! }
+//! @endcode
+class WNT_HIDSpaceMouse
+{
+public:
+ //! Vendor HID identifier.
+ enum { VENDOR_ID_LOGITECH = 0x46D, VENDOR_ID_3DCONNEXION = 0x256F };
+
+ //! Return if product id is known by this class.
+ Standard_EXPORT static bool IsKnownProduct (unsigned long theProductId);
+
+public:
+ //! Main constructor.
+ Standard_EXPORT WNT_HIDSpaceMouse (unsigned long theProductId,
+ const Standard_Byte* theData,
+ Standard_Size theSize);
+
+ //! Return the raw value range.
+ int16_t RawValueRange() const { return myValueRange; }
+
+ //! Set the raw value range.
+ void SetRawValueRange (int16_t theRange) { myValueRange = theRange > myValueRange ? theRange : myValueRange; }
+
+ //! Return TRUE if data chunk defines new translation values.
+ bool IsTranslation() const
+ {
+ return myData[0] == SpaceRawInput_Translation
+ && (mySize == 7 || mySize == 13);
+ }
+
+ //! Return new translation values.
+ //! @param theIsIdle [out] flag indicating idle state (no translation)
+ //! @param theIsQuadric [in] flag to apply non-linear scale factor
+ //! @return vector of 3 elements defining translation values within [-1..1] range, 0 meaning idle,
+ //! .x defining left/right slide, .y defining forward/backward and .z defining up/down slide.
+ Standard_EXPORT Graphic3d_Vec3d Translation (bool& theIsIdle,
+ bool theIsQuadric) const;
+
+ //! Return TRUE if data chunk defines new rotation values.
+ bool IsRotation() const
+ {
+ return (myData[0] == SpaceRawInput_Rotation && mySize == 7)
+ || (myData[0] == SpaceRawInput_Translation && mySize == 13);
+ }
+
+ //! Return new rotation values.
+ //! @param theIsIdle [out] flag indicating idle state (no rotation)
+ //! @param theIsQuadric [in] flag to apply non-linear scale factor
+ //! @return vector of 3 elements defining rotation values within [-1..1] range, 0 meaning idle,
+ //! .x defining tilt, .y defining roll and .z defining spin.
+ Standard_EXPORT Graphic3d_Vec3d Rotation (bool& theIsIdle,
+ bool theIsQuadric) const;
+
+ //! Return TRUE for key state data chunk.
+ bool IsKeyState() const { return myData[0] == SpaceRawInput_KeyState; }
+
+ //! Return new keystate.
+ uint32_t KeyState() const { return *reinterpret_cast<const uint32_t*>(myData + 1); }
+
+ //! Convert key state bit into virtual key.
+ Standard_EXPORT Aspect_VKey HidToSpaceKey (unsigned short theKeyBit) const;
+
+private:
+
+ //! Translate raw data chunk of 3 int16 values into normalized vec3.
+ //! The values are considered within the range [-350; 350], with 0 as neutral state.
+ Graphic3d_Vec3d fromRawVec3 (bool& theIsIdle,
+ const Standard_Byte* theData,
+ bool theIsTrans,
+ bool theIsQuadric) const;
+
+ //! Data chunk type.
+ enum
+ {
+ SpaceRawInput_Translation = 0x01, //!< translation data chunk
+ SpaceRawInput_Rotation = 0x02, //!< rotation data chunk
+ SpaceRawInput_KeyState = 0x03, //!< keystate data chunk
+ };
+
+private:
+ const Standard_Byte* myData; //!< RAW data chunk
+ Standard_Size mySize; //!< size of RAW data chunk
+ unsigned long myProductId; //!< product id
+ mutable int16_t myValueRange; //!< RAW value range
+};
+
+#endif // _WNT_HIDSpaceMouse_Header
#include <Aspect_Convert.hxx>
#include <Aspect_WindowDefinitionError.hxx>
#include <Aspect_WindowError.hxx>
+#include <Message.hxx>
#include <Standard_Type.hxx>
#include <TCollection_ExtendedString.hxx>
#include <WNT_WClass.hxx>
return aButtons;
}
+// =======================================================================
+// function : RegisterRawInputDevices
+// purpose :
+// =======================================================================
+int WNT_Window::RegisterRawInputDevices (unsigned int theRawDeviceMask)
+{
+ if (IsVirtual()
+ || myHWindow == NULL)
+ {
+ return 0;
+ }
+
+ // hidusage.h
+ enum HidUsagePage { THE_HID_USAGE_PAGE_GENERIC = 0x01 }; // HID_USAGE_PAGE_GENERIC
+ enum HidUsage
+ {
+ THE_HID_USAGE_GENERIC_MOUSE = 0x02, // HID_USAGE_GENERIC_MOUSE
+ THE_HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER = 0x08, // HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER
+ };
+
+ int aNbDevices = 0;
+ RAWINPUTDEVICE aRawInDevList[2];
+ if ((theRawDeviceMask & RawInputMask_Mouse) != 0)
+ {
+ // mouse
+ RAWINPUTDEVICE& aRawMouse = aRawInDevList[aNbDevices++];
+ aRawMouse.usUsagePage = THE_HID_USAGE_PAGE_GENERIC;
+ aRawMouse.usUsage = THE_HID_USAGE_GENERIC_MOUSE;
+ aRawMouse.dwFlags = RIDEV_INPUTSINK;
+ aRawMouse.hwndTarget = (HWND )myHWindow;
+ }
+ if ((theRawDeviceMask & RawInputMask_SpaceMouse) != 0)
+ {
+ // space mouse
+ RAWINPUTDEVICE& aRawSpace = aRawInDevList[aNbDevices++];
+ aRawSpace.usUsagePage = THE_HID_USAGE_PAGE_GENERIC;
+ aRawSpace.usUsage = THE_HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER;
+ aRawSpace.dwFlags = 0; // RIDEV_DEVNOTIFY
+ aRawSpace.hwndTarget = (HWND )myHWindow;
+ }
+
+ for (int aTryIter = aNbDevices; aTryIter > 0; --aTryIter)
+ {
+ if (::RegisterRawInputDevices (aRawInDevList, aTryIter, sizeof(aRawInDevList[0])))
+ {
+ return aTryIter;
+ }
+
+ Message::SendTrace (aRawInDevList[aTryIter - 1].usUsage == THE_HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER
+ ? "Warning: RegisterRawInputDevices() failed to register RAW multi-axis controller input"
+ : "Warning: RegisterRawInputDevices() failed to register RAW mouse input");
+ }
+ return 0;
+}
+
#endif // _WIN32
//! Method can be called from non-window thread, and system will also automatically aggregate multiple events into single one.
Standard_EXPORT virtual void InvalidateContent (const Handle(Aspect_DisplayConnection)& theDisp = NULL) Standard_OVERRIDE;
+ //! Raw input flags.
+ enum RawInputMask
+ {
+ RawInputMask_Mouse = 0x01, //!< HID_USAGE_GENERIC_MOUSE
+ RawInputMask_SpaceMouse = 0x02, //!< HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER
+ };
+
+ //! RegisterRawInputDevices() wrapper.
+ //! @param theRawDeviceMask [in] mask of RawInputMask flags
+ //! @return number of actually registered device types
+ Standard_EXPORT int RegisterRawInputDevices (unsigned int theRawDeviceMask);
+
DEFINE_STANDARD_RTTIEXT(WNT_Window,Aspect_Window)
protected: