0031621: Draw Harness - handle navigation keys
[occt.git] / src / ViewerTest / ViewerTest_EventManager.cxx
index 4dffd89..2f732e8 100644 (file)
@@ -21,6 +21,7 @@
 #include <AIS_Shape.hxx>
 #include <Aspect_Grid.hxx>
 #include <Draw.hxx>
+#include <ViewerTest_ContinuousRedrawer.hxx>
 #include <ViewerTest_V3dView.hxx>
 
 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
@@ -45,9 +46,32 @@ ViewerTest_EventManager::ViewerTest_EventManager (const Handle(V3d_View)&
                                                   const Handle(AIS_InteractiveContext)& theCtx)
 : myCtx  (theCtx),
   myView (theView),
-  myToPickPnt (Standard_False)
+  myToPickPnt (Standard_False),
+  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);
 }
 
 //=======================================================================
@@ -104,6 +128,40 @@ void ViewerTest_EventManager::ProcessExpose()
   }
 }
 
+//==============================================================================
+//function : handleViewRedraw
+//purpose  :
+//==============================================================================
+void ViewerTest_EventManager::handleViewRedraw (const Handle(AIS_InteractiveContext)& theCtx,
+                                                const Handle(V3d_View)& theView)
+{
+  AIS_ViewController::handleViewRedraw (theCtx, theView);
+
+  // On non-Windows platforms Aspect_Window::InvalidateContent() from rendering thread does not work as expected
+  // as in Tcl event loop the new message might go to sleep with new event remaining in queue.
+  // As a workaround - use dedicated background thread to ping Tcl event loop.
+  if (myToAskNextFrame)
+  {
+    ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
+    if (!myIsTmpContRedraw
+     && (!aRedrawer.IsStarted() || aRedrawer.IsPaused()))
+    {
+      myIsTmpContRedraw = true;
+    #ifndef _WIN32
+      aRedrawer.Start (theView->Window(), 60.0);
+    #endif
+    }
+  }
+  else if (myIsTmpContRedraw)
+  {
+    myIsTmpContRedraw = false;
+  #ifndef _WIN32
+    ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
+    aRedrawer.Pause();
+  #endif
+  }
+}
+
 //==============================================================================
 //function : ProcessConfigure
 //purpose  :
@@ -117,6 +175,69 @@ void ViewerTest_EventManager::ProcessConfigure()
   }
 }
 
+// =======================================================================
+// 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  :
@@ -124,8 +245,25 @@ void ViewerTest_EventManager::ProcessConfigure()
 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);
 }
 
 //==============================================================================
@@ -142,7 +280,7 @@ void ViewerTest_EventManager::ProcessKeyPress (Aspect_VKey theKey)
 
   switch (theKey)
   {
-    case Aspect_VKey_A: // AXO
+    case Aspect_VKey_Backspace: // AXO
     {
       if (!ViewerTest_V3dView::IsCurrentViewIn2DMode())
       {
@@ -150,14 +288,6 @@ void ViewerTest_EventManager::ProcessKeyPress (Aspect_VKey theKey)
       }
       break;
     }
-    case Aspect_VKey_D: // Reset
-    {
-      if (!ViewerTest_V3dView::IsCurrentViewIn2DMode())
-      {
-        myView->Reset();
-      }
-      break;
-    }
     case Aspect_VKey_F:
     {
       if (myCtx->NbSelected() > 0)
@@ -213,11 +343,11 @@ void ViewerTest_EventManager::ProcessKeyPress (Aspect_VKey theKey)
       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";
@@ -338,6 +468,25 @@ void ViewerTest_EventManager::ProcessKeyPress (Aspect_VKey theKey)
       {
         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;
     }
   }