AIS_ViewController::handleNavigationKeys() - added an interface for processing navigation keys.
ViewerTest_EventManager now maps WASD+Arrows navigation keys.
Axonometric view hotkey A has been replaced by Backspace.
Shaded/Wireframe are now mapped with hotkeys W+Ctrl/S+Ctrl.
Hotkey D (reset view to undefined default state) has been removed.
Previously, sub-classes of *Message_Printer* have to provide a triplet of *Message_Printer::Send()* methods accepting different string representations: TCollection_AsciiString, TCollection_ExtendedString and Standard_CString.
*Message_Printer* interface has been changed, so that sub-classes now have to implement only single method *Message_Printer::send()* accepting TCollection_AsciiString argument and having no Endl flag, which has been removed.
Old three Message_Printer::Send() methods remain defined virtual with unused last argument and redirecting to new send() method by default.
+
+@subsection upgrade_750_draw_hotkeys Draw Harness hotkeys
+
+Draw Harness hotkeys **W** (Wireframe) and **S** (Shaded) have been re-mapped to **Ctrl+W** and **Ctrl+S**.
+Hotkey **A** has been remapped to **Backspace**.
+Hotkeys WASD and Arrays are now mapped for walk-through navigation in 3D Viewer.
return theCtx ->GravityPoint (theView);
}
+// =======================================================================
+// function : handleNavigationKeys
+// purpose :
+// =======================================================================
+AIS_WalkDelta AIS_ViewController::handleNavigationKeys (const Handle(AIS_InteractiveContext)& ,
+ const Handle(V3d_View)& theView)
+{
+ // navigation keys
+ double aCrouchRatio = 1.0, aRunRatio = 1.0;
+ if (myNavigationMode == AIS_NavigationMode_FirstPersonFlight)
+ {
+ aRunRatio = 3.0;
+ }
+
+ const double aRotSpeed = 0.5;
+ const double aWalkSpeedCoef = WalkSpeedRelative();
+ AIS_WalkDelta aWalk = FetchNavigationKeys (aCrouchRatio, aRunRatio);
+ if (aWalk.IsJumping())
+ {
+ // ask more frames
+ setAskNextFrame();
+ theView->Invalidate();
+ }
+ if (aWalk.IsEmpty())
+ {
+ return aWalk;
+ }
+ else if (myGL.OrbitRotation.ToRotate
+ || myGL.OrbitRotation.ToStart)
+ {
+ return aWalk;
+ }
+
+ gp_XYZ aMin, aMax;
+ const Bnd_Box aBndBox = theView->View()->MinMaxValues();
+ if (!aBndBox.IsVoid())
+ {
+ aMin = aBndBox.CornerMin().XYZ();
+ aMax = aBndBox.CornerMax().XYZ();
+ }
+ double aBndDiam = Max (Max (aMax.X() - aMin.X(), aMax.Y() - aMin.Y()), aMax.Z() - aMin.Z());
+ if (aBndDiam <= gp::Resolution())
+ {
+ aBndDiam = 0.001;
+ }
+
+ const double aWalkSpeed = myNavigationMode != AIS_NavigationMode_Orbit
+ && myNavigationMode != AIS_NavigationMode_FirstPersonFlight
+ ? theView->View()->UnitFactor() * WalkSpeedAbsolute()
+ : aWalkSpeedCoef * aBndDiam;
+ const Handle(Graphic3d_Camera)& aCam = theView->View()->IsActiveXR()
+ ? theView->View()->BaseXRCamera()
+ : theView->Camera();
+
+ // move forward in plane XY and up along Z
+ const gp_Dir anUp = ToLockOrbitZUp() ? gp::DZ() : aCam->OrthogonalizedUp();
+ if (aWalk.ToMove()
+ && myToAllowPanning)
+ {
+ const gp_Vec aSide = -aCam->SideRight();
+ gp_XYZ aFwd = aCam->Direction().XYZ();
+ aFwd -= anUp.XYZ() * (anUp.XYZ() * aFwd);
+
+ gp_XYZ aMoveVec;
+ if (!aWalk[AIS_WalkTranslation_Forward].IsEmpty())
+ {
+ if (!aCam->IsOrthographic())
+ {
+ aMoveVec += aFwd * aWalk[AIS_WalkTranslation_Forward].Value * aWalk[AIS_WalkTranslation_Forward].Pressure * aWalkSpeed;
+ }
+ }
+ if (!aWalk[AIS_WalkTranslation_Side].IsEmpty())
+ {
+ aMoveVec += aSide.XYZ() * aWalk[AIS_WalkTranslation_Side].Value * aWalk[AIS_WalkTranslation_Side].Pressure * aWalkSpeed;
+ }
+ if (!aWalk[AIS_WalkTranslation_Up].IsEmpty())
+ {
+ aMoveVec += anUp.XYZ() * aWalk[AIS_WalkTranslation_Up].Value * aWalk[AIS_WalkTranslation_Up].Pressure * aWalkSpeed;
+ }
+ {
+ if (aCam->IsOrthographic())
+ {
+ if (!aWalk[AIS_WalkTranslation_Forward].IsEmpty())
+ {
+ const double aZoomDelta = aWalk[AIS_WalkTranslation_Forward].Value * aWalk[AIS_WalkTranslation_Forward].Pressure * aWalkSpeedCoef;
+ handleZoom (theView, Aspect_ScrollDelta (aZoomDelta * 100.0), NULL);
+ }
+ }
+
+ gp_Trsf aTrsfTranslate;
+ aTrsfTranslate.SetTranslation (aMoveVec);
+ aCam->Transform (aTrsfTranslate);
+ }
+ }
+
+ if (myNavigationMode == AIS_NavigationMode_Orbit
+ && myToAllowRotation)
+ {
+ if (!aWalk[AIS_WalkRotation_Yaw].IsEmpty())
+ {
+ gp_Trsf aTrsfRot;
+ aTrsfRot.SetRotation (gp_Ax1 (aCam->Eye(), anUp), aWalk[AIS_WalkRotation_Yaw].Value * aRotSpeed);
+ aCam->Transform (aTrsfRot);
+ }
+ if (!aWalk[AIS_WalkRotation_Pitch].IsEmpty())
+ {
+ const gp_Vec aSide = -aCam->SideRight();
+ gp_Trsf aTrsfRot;
+ aTrsfRot.SetRotation (gp_Ax1 (aCam->Eye(), aSide), -aWalk[AIS_WalkRotation_Pitch].Value * aRotSpeed);
+ aCam->Transform (aTrsfRot);
+ }
+ if (!aWalk[AIS_WalkRotation_Roll].IsEmpty()
+ && !ToLockOrbitZUp())
+ {
+ gp_Trsf aTrsfRot;
+ aTrsfRot.SetRotation (gp_Ax1 (aCam->Center(), aCam->Direction()), aWalk[AIS_WalkRotation_Roll].Value * aRotSpeed);
+ aCam->Transform (aTrsfRot);
+ }
+ }
+
+ // ask more frames
+ setAskNextFrame();
+ theView->Invalidate();
+ theView->View()->SynchronizeXRBaseToPosedCamera();
+ return aWalk;
+}
+
// =======================================================================
// function : handleCameraActions
// purpose :
{
const bool wasImmediateUpdate = theView->SetImmediateUpdate (false);
- const AIS_WalkDelta aWalk = FetchNavigationKeys (1.0, 1.0);
+ const AIS_WalkDelta aWalk = handleNavigationKeys (theCtx, theView);
handleXRInput (theCtx, theView, aWalk);
if (theView->View()->IsActiveXR())
{
public:
+ //! Perform navigation.
+ //! 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.
//! This method is expected to be called from rendering thread.
Standard_EXPORT virtual void handleCameraActions (const Handle(AIS_InteractiveContext)& theCtx,
myIsTmpContRedraw (Standard_False)
{
myViewAnimation = GlobalViewAnimation();
+
+ addActionHotKeys (Aspect_VKey_NavForward, Aspect_VKey_W, Aspect_VKey_W | Aspect_VKeyFlags_SHIFT);
+ addActionHotKeys (Aspect_VKey_NavBackward , Aspect_VKey_S, Aspect_VKey_S | Aspect_VKeyFlags_SHIFT);
+ addActionHotKeys (Aspect_VKey_NavSlideLeft, Aspect_VKey_A, Aspect_VKey_A | Aspect_VKeyFlags_SHIFT);
+ addActionHotKeys (Aspect_VKey_NavSlideRight, Aspect_VKey_D, Aspect_VKey_D | Aspect_VKeyFlags_SHIFT);
+ addActionHotKeys (Aspect_VKey_NavRollCCW, Aspect_VKey_Q, Aspect_VKey_Q | Aspect_VKeyFlags_SHIFT);
+ addActionHotKeys (Aspect_VKey_NavRollCW, Aspect_VKey_E, Aspect_VKey_E | Aspect_VKeyFlags_SHIFT);
+
+ addActionHotKeys (Aspect_VKey_NavSpeedIncrease, Aspect_VKey_Plus, Aspect_VKey_Plus | Aspect_VKeyFlags_SHIFT,
+ Aspect_VKey_Equal,
+ Aspect_VKey_NumpadAdd, Aspect_VKey_NumpadAdd | Aspect_VKeyFlags_SHIFT);
+ addActionHotKeys (Aspect_VKey_NavSpeedDecrease, Aspect_VKey_Minus, Aspect_VKey_Minus | Aspect_VKeyFlags_SHIFT,
+ Aspect_VKey_NumpadSubtract, Aspect_VKey_NumpadSubtract | Aspect_VKeyFlags_SHIFT);
+
+ addActionHotKeys (Aspect_VKey_NavLookUp, Aspect_VKey_Up);
+ addActionHotKeys (Aspect_VKey_NavLookDown, Aspect_VKey_Down);
+ addActionHotKeys (Aspect_VKey_NavLookLeft, Aspect_VKey_Left);
+ addActionHotKeys (Aspect_VKey_NavLookRight, Aspect_VKey_Right);
+ addActionHotKeys (Aspect_VKey_NavSlideLeft, Aspect_VKey_Left | Aspect_VKeyFlags_SHIFT);
+ addActionHotKeys (Aspect_VKey_NavSlideRight, Aspect_VKey_Right | Aspect_VKeyFlags_SHIFT);
+ addActionHotKeys (Aspect_VKey_NavSlideUp, Aspect_VKey_Up | Aspect_VKeyFlags_SHIFT);
+ addActionHotKeys (Aspect_VKey_NavSlideDown, Aspect_VKey_Down | Aspect_VKeyFlags_SHIFT);
}
//=======================================================================
}
}
+// =======================================================================
+// function : navigationKeyModifierSwitch
+// purpose :
+// =======================================================================
+bool ViewerTest_EventManager::navigationKeyModifierSwitch (unsigned int theModifOld,
+ unsigned int theModifNew,
+ double theTimeStamp)
+{
+ bool hasActions = false;
+ for (unsigned int aKeyIter = 0; aKeyIter < Aspect_VKey_ModifiersLower; ++aKeyIter)
+ {
+ if (!myKeys.IsKeyDown (aKeyIter))
+ {
+ continue;
+ }
+
+ Aspect_VKey anActionOld = Aspect_VKey_UNKNOWN, anActionNew = Aspect_VKey_UNKNOWN;
+ myNavKeyMap.Find (aKeyIter | theModifOld, anActionOld);
+ myNavKeyMap.Find (aKeyIter | theModifNew, anActionNew);
+ if (anActionOld == anActionNew)
+ {
+ continue;
+ }
+
+ if (anActionOld != Aspect_VKey_UNKNOWN)
+ {
+ myKeys.KeyUp (anActionOld, theTimeStamp);
+ }
+ if (anActionNew != Aspect_VKey_UNKNOWN)
+ {
+ hasActions = true;
+ myKeys.KeyDown (anActionNew, theTimeStamp);
+ }
+ }
+ return hasActions;
+}
+
+//=======================================================================
+//function : KeyDown
+//purpose :
+//=======================================================================
+void ViewerTest_EventManager::KeyDown (Aspect_VKey theKey,
+ double theTime,
+ double thePressure)
+{
+ const unsigned int aModifOld = myKeys.Modifiers();
+ AIS_ViewController::KeyDown (theKey, theTime, thePressure);
+
+ const unsigned int aModifNew = myKeys.Modifiers();
+ if (aModifNew != aModifOld
+ && navigationKeyModifierSwitch (aModifOld, aModifNew, theTime))
+ {
+ // modifier key just pressed
+ }
+
+ Aspect_VKey anAction = Aspect_VKey_UNKNOWN;
+ if (myNavKeyMap.Find (theKey | myKeys.Modifiers(), anAction)
+ && anAction != Aspect_VKey_UNKNOWN)
+ {
+ AIS_ViewController::KeyDown (anAction, theTime, thePressure);
+ }
+}
+
//=======================================================================
//function : KeyUp
//purpose :
void ViewerTest_EventManager::KeyUp (Aspect_VKey theKey,
double theTime)
{
+ const unsigned int aModifOld = myKeys.Modifiers();
AIS_ViewController::KeyUp (theKey, theTime);
- ProcessKeyPress (theKey);
+
+ Aspect_VKey anAction = Aspect_VKey_UNKNOWN;
+ if (myNavKeyMap.Find (theKey | myKeys.Modifiers(), anAction)
+ && anAction != Aspect_VKey_UNKNOWN)
+ {
+ AIS_ViewController::KeyUp (anAction, theTime);
+ ProcessKeyPress (anAction);
+ }
+
+ const unsigned int aModifNew = myKeys.Modifiers();
+ if (aModifNew != aModifOld
+ && navigationKeyModifierSwitch (aModifOld, aModifNew, theTime))
+ {
+ // modifier key released
+ }
+
+ ProcessKeyPress (theKey | aModifNew);
}
//==============================================================================
switch (theKey)
{
- case Aspect_VKey_A: // AXO
+ case Aspect_VKey_Backspace: // AXO
{
if (!ViewerTest_V3dView::IsCurrentViewIn2DMode())
{
}
break;
}
- case Aspect_VKey_D: // Reset
- {
- if (!ViewerTest_V3dView::IsCurrentViewIn2DMode())
- {
- myView->Reset();
- }
- break;
- }
case Aspect_VKey_F:
{
if (myCtx->NbSelected() > 0)
myCtx->UpdateCurrentViewer();
break;
}
- case Aspect_VKey_S:
- case Aspect_VKey_W:
+ case Aspect_VKey_S | Aspect_VKeyFlags_CTRL:
+ case Aspect_VKey_W | Aspect_VKeyFlags_CTRL:
{
Standard_Integer aDispMode = AIS_Shaded;
- if (theKey == Aspect_VKey_S)
+ if (theKey == (Aspect_VKey_S | Aspect_VKeyFlags_CTRL))
{
aDispMode = AIS_Shaded;
std::cout << "setup Shaded display mode\n";
{
Draw_Interprete (ViewerTest_EventManager::ToExitOnCloseView() ? "exit" : "vclose");
}
+ break;
+ }
+ case Aspect_VKey_NavSpeedDecrease:
+ case Aspect_VKey_NavSpeedIncrease:
+ {
+ // handle slide speed
+ float aNewSpeed = theKey == Aspect_VKey_NavSpeedDecrease
+ ? myWalkSpeedRelative * 0.5f
+ : myWalkSpeedRelative * 2.0f;
+ if (aNewSpeed >= 0.00001f
+ && aNewSpeed <= 10.0f)
+ {
+ if (Abs (aNewSpeed - 0.1f) < 0.001f)
+ {
+ aNewSpeed = 0.1f;
+ }
+ myWalkSpeedRelative = aNewSpeed;
+ }
+ break;
}
}
Aspect_VKeyFlags theModifiers,
bool theIsEmulated) Standard_OVERRIDE;
+ //! Release key.
+ Standard_EXPORT virtual void KeyDown (Aspect_VKey theKey,
+ double theTime,
+ double thePressure = 1.0) Standard_OVERRIDE;
+
//! Release key.
Standard_EXPORT virtual void KeyUp (Aspect_VKey theKey,
double theTime) Standard_OVERRIDE;
//! Handle KeyPress event.
Standard_EXPORT void ProcessKeyPress (Aspect_VKey theKey);
+protected:
+
+ //! Register hot-keys for specified Action.
+ void addActionHotKeys (Aspect_VKey theAction,
+ unsigned int theHotKey1 = 0,
+ unsigned int theHotKey2 = 0,
+ unsigned int theHotKey3 = 0,
+ unsigned int theHotKey4 = 0,
+ unsigned int theHotKey5 = 0)
+ {
+ if (theHotKey1 != 0) { myNavKeyMap.Bind (theHotKey1, theAction); }
+ if (theHotKey2 != 0) { myNavKeyMap.Bind (theHotKey2, theAction); }
+ if (theHotKey3 != 0) { myNavKeyMap.Bind (theHotKey3, theAction); }
+ if (theHotKey4 != 0) { myNavKeyMap.Bind (theHotKey4, theAction); }
+ if (theHotKey5 != 0) { myNavKeyMap.Bind (theHotKey5, theAction); }
+ }
+
+ //! Handle modifier key changes.
+ Standard_EXPORT bool navigationKeyModifierSwitch (unsigned int theModifOld,
+ unsigned int theModifNew,
+ double theTimeStamp);
+
private:
Handle(AIS_InteractiveContext) myCtx;
Handle(V3d_View) myView;
+ NCollection_DataMap<unsigned int, Aspect_VKey> myNavKeyMap; //!< map of Hot-Key (key+modifiers) to Action
TCollection_AsciiString myPickPntArgVec[3];
Standard_Boolean myToPickPnt;
di << "B : BottomView\n";
di << "R : RightView\n";
di << "L : LeftView\n";
- di << "A : AxonometricView\n";
- di << "D : ResetView\n";
+ di << "Backspace : AxonometricView\n";
di << "=========================\n";
- di << "S : Shading\n";
- di << "W : Wireframe\n";
+ di << "W, S : Fly forward/backward\n";
+ di << "A, D : Slide left/right\n";
+ di << "Q, E : Bank left/right\n";
+ di << "-, + : Change flying speed\n";
+ di << "Arrows : look left/right/up/down\n";
+ di << "Arrows+Shift : slide left/right/up/down\n";
+
+ di << "=========================\n";
+ di << "S + Ctrl : Shading\n";
+ di << "W + Ctrl : Wireframe\n";
di << "H : HiddenLineRemoval\n";
di << "U : Unset display mode\n";
di << "Delete : Remove selection from viewer\n";