0031621: Draw Harness - handle navigation keys
[occt.git] / src / ViewerTest / ViewerTest_EventManager.cxx
CommitLineData
b311480e 1// Created on: 1998-08-27
2// Created by: Robert COUBLANC
3// Copyright (c) 1998-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 8// This library is free software; you can redistribute it and/or modify it under
9// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 10// by the Free Software Foundation, with special exception defined in the file
11// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12// distribution for complete text of the license and disclaimer of any warranty.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
780ee4e2 17#include <ViewerTest_EventManager.hxx>
42cf5bc1 18
2108d9a2 19#include <AIS_AnimationCamera.hxx>
7fd59977 20#include <AIS_InteractiveContext.hxx>
49582f9d 21#include <AIS_Shape.hxx>
679ecdee 22#include <Aspect_Grid.hxx>
49582f9d 23#include <Draw.hxx>
08b7a39f 24#include <ViewerTest_ContinuousRedrawer.hxx>
49582f9d 25#include <ViewerTest_V3dView.hxx>
26
27Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
7fd59977 28
25e59720 29IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_EventManager,Standard_Transient)
92efcf78 30
7fd59977 31//=======================================================================
2108d9a2 32//function : GlobalViewAnimation
33//purpose :
34//=======================================================================
35const Handle(AIS_AnimationCamera)& ViewerTest_EventManager::GlobalViewAnimation()
36{
37 static Handle(AIS_AnimationCamera) THE_CAMERA_ANIM = new AIS_AnimationCamera ("ViewerTest_EventManager_ViewAnimation", Handle(V3d_View)());
38 return THE_CAMERA_ANIM;
39}
40
41//=======================================================================
7fd59977 42//function : ViewerTest_EventManager
679ecdee 43//purpose :
7fd59977 44//=======================================================================
679ecdee 45ViewerTest_EventManager::ViewerTest_EventManager (const Handle(V3d_View)& theView,
46 const Handle(AIS_InteractiveContext)& theCtx)
47: myCtx (theCtx),
48 myView (theView),
08b7a39f 49 myToPickPnt (Standard_False),
50 myIsTmpContRedraw (Standard_False)
2108d9a2 51{
52 myViewAnimation = GlobalViewAnimation();
d22962e4 53
54 addActionHotKeys (Aspect_VKey_NavForward, Aspect_VKey_W, Aspect_VKey_W | Aspect_VKeyFlags_SHIFT);
55 addActionHotKeys (Aspect_VKey_NavBackward , Aspect_VKey_S, Aspect_VKey_S | Aspect_VKeyFlags_SHIFT);
56 addActionHotKeys (Aspect_VKey_NavSlideLeft, Aspect_VKey_A, Aspect_VKey_A | Aspect_VKeyFlags_SHIFT);
57 addActionHotKeys (Aspect_VKey_NavSlideRight, Aspect_VKey_D, Aspect_VKey_D | Aspect_VKeyFlags_SHIFT);
58 addActionHotKeys (Aspect_VKey_NavRollCCW, Aspect_VKey_Q, Aspect_VKey_Q | Aspect_VKeyFlags_SHIFT);
59 addActionHotKeys (Aspect_VKey_NavRollCW, Aspect_VKey_E, Aspect_VKey_E | Aspect_VKeyFlags_SHIFT);
60
61 addActionHotKeys (Aspect_VKey_NavSpeedIncrease, Aspect_VKey_Plus, Aspect_VKey_Plus | Aspect_VKeyFlags_SHIFT,
62 Aspect_VKey_Equal,
63 Aspect_VKey_NumpadAdd, Aspect_VKey_NumpadAdd | Aspect_VKeyFlags_SHIFT);
64 addActionHotKeys (Aspect_VKey_NavSpeedDecrease, Aspect_VKey_Minus, Aspect_VKey_Minus | Aspect_VKeyFlags_SHIFT,
65 Aspect_VKey_NumpadSubtract, Aspect_VKey_NumpadSubtract | Aspect_VKeyFlags_SHIFT);
66
67 addActionHotKeys (Aspect_VKey_NavLookUp, Aspect_VKey_Up);
68 addActionHotKeys (Aspect_VKey_NavLookDown, Aspect_VKey_Down);
69 addActionHotKeys (Aspect_VKey_NavLookLeft, Aspect_VKey_Left);
70 addActionHotKeys (Aspect_VKey_NavLookRight, Aspect_VKey_Right);
71 addActionHotKeys (Aspect_VKey_NavSlideLeft, Aspect_VKey_Left | Aspect_VKeyFlags_SHIFT);
72 addActionHotKeys (Aspect_VKey_NavSlideRight, Aspect_VKey_Right | Aspect_VKeyFlags_SHIFT);
73 addActionHotKeys (Aspect_VKey_NavSlideUp, Aspect_VKey_Up | Aspect_VKeyFlags_SHIFT);
74 addActionHotKeys (Aspect_VKey_NavSlideDown, Aspect_VKey_Down | Aspect_VKeyFlags_SHIFT);
2108d9a2 75}
76
77//=======================================================================
78//function : ~ViewerTest_EventManager
79//purpose :
80//=======================================================================
81ViewerTest_EventManager::~ViewerTest_EventManager()
82{
83 if (!myViewAnimation.IsNull()
84 && myViewAnimation->View() == myView)
85 {
86 myViewAnimation->Stop();
87 myViewAnimation->SetView (Handle(V3d_View)());
88 }
89}
7fd59977 90
91//=======================================================================
49582f9d 92//function : UpdateMouseButtons
679ecdee 93//purpose :
7fd59977 94//=======================================================================
49582f9d 95bool ViewerTest_EventManager::UpdateMouseButtons (const Graphic3d_Vec2i& thePoint,
96 Aspect_VKeyMouse theButtons,
97 Aspect_VKeyFlags theModifiers,
98 bool theIsEmulated)
7fd59977 99{
49582f9d 100 SetAllowRotation (!ViewerTest_V3dView::IsCurrentViewIn2DMode());
101
102 if (theButtons == Aspect_VKeyMouse_LeftButton)
679ecdee 103 {
49582f9d 104 if (myToPickPnt && (theModifiers & Aspect_VKeyFlags_CTRL) != 0)
679ecdee 105 {
49582f9d 106 Graphic3d_Vec3d anXYZ;
107 myView->Convert (thePoint.x(), thePoint.y(), anXYZ.x(), anXYZ.y(), anXYZ.z());
108 Draw::Set (myPickPntArgVec[0].ToCString(), anXYZ.x());
109 Draw::Set (myPickPntArgVec[1].ToCString(), anXYZ.y());
110 Draw::Set (myPickPntArgVec[2].ToCString(), anXYZ.z());
111 myToPickPnt = false;
679ecdee 112 }
113 }
114
49582f9d 115 return AIS_ViewController::UpdateMouseButtons (thePoint, theButtons, theModifiers, theIsEmulated);
7fd59977 116}
117
49582f9d 118//==============================================================================
119//function : ProcessExpose
679ecdee 120//purpose :
49582f9d 121//==============================================================================
122void ViewerTest_EventManager::ProcessExpose()
7fd59977 123{
49582f9d 124 if (!myView.IsNull())
780ee4e2 125 {
49582f9d 126 myView->Invalidate();
127 FlushViewEvents (myCtx, myView, true);
679ecdee 128 }
7fd59977 129}
130
49582f9d 131//==============================================================================
08b7a39f 132//function : handleViewRedraw
133//purpose :
134//==============================================================================
135void ViewerTest_EventManager::handleViewRedraw (const Handle(AIS_InteractiveContext)& theCtx,
136 const Handle(V3d_View)& theView)
137{
138 AIS_ViewController::handleViewRedraw (theCtx, theView);
139
140 // On non-Windows platforms Aspect_Window::InvalidateContent() from rendering thread does not work as expected
141 // as in Tcl event loop the new message might go to sleep with new event remaining in queue.
142 // As a workaround - use dedicated background thread to ping Tcl event loop.
143 if (myToAskNextFrame)
144 {
145 ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
146 if (!myIsTmpContRedraw
147 && (!aRedrawer.IsStarted() || aRedrawer.IsPaused()))
148 {
149 myIsTmpContRedraw = true;
150 #ifndef _WIN32
151 aRedrawer.Start (theView->Window(), 60.0);
152 #endif
153 }
154 }
155 else if (myIsTmpContRedraw)
156 {
157 myIsTmpContRedraw = false;
158 #ifndef _WIN32
159 ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
160 aRedrawer.Pause();
161 #endif
162 }
163}
164
165//==============================================================================
49582f9d 166//function : ProcessConfigure
679ecdee 167//purpose :
49582f9d 168//==============================================================================
169void ViewerTest_EventManager::ProcessConfigure()
679ecdee 170{
49582f9d 171 if (!myView.IsNull())
679ecdee 172 {
49582f9d 173 myView->MustBeResized();
174 FlushViewEvents (myCtx, myView, true);
679ecdee 175 }
7fd59977 176}
177
d22962e4 178// =======================================================================
179// function : navigationKeyModifierSwitch
180// purpose :
181// =======================================================================
182bool ViewerTest_EventManager::navigationKeyModifierSwitch (unsigned int theModifOld,
183 unsigned int theModifNew,
184 double theTimeStamp)
185{
186 bool hasActions = false;
187 for (unsigned int aKeyIter = 0; aKeyIter < Aspect_VKey_ModifiersLower; ++aKeyIter)
188 {
189 if (!myKeys.IsKeyDown (aKeyIter))
190 {
191 continue;
192 }
193
194 Aspect_VKey anActionOld = Aspect_VKey_UNKNOWN, anActionNew = Aspect_VKey_UNKNOWN;
195 myNavKeyMap.Find (aKeyIter | theModifOld, anActionOld);
196 myNavKeyMap.Find (aKeyIter | theModifNew, anActionNew);
197 if (anActionOld == anActionNew)
198 {
199 continue;
200 }
201
202 if (anActionOld != Aspect_VKey_UNKNOWN)
203 {
204 myKeys.KeyUp (anActionOld, theTimeStamp);
205 }
206 if (anActionNew != Aspect_VKey_UNKNOWN)
207 {
208 hasActions = true;
209 myKeys.KeyDown (anActionNew, theTimeStamp);
210 }
211 }
212 return hasActions;
213}
214
215//=======================================================================
216//function : KeyDown
217//purpose :
218//=======================================================================
219void ViewerTest_EventManager::KeyDown (Aspect_VKey theKey,
220 double theTime,
221 double thePressure)
222{
223 const unsigned int aModifOld = myKeys.Modifiers();
224 AIS_ViewController::KeyDown (theKey, theTime, thePressure);
225
226 const unsigned int aModifNew = myKeys.Modifiers();
227 if (aModifNew != aModifOld
228 && navigationKeyModifierSwitch (aModifOld, aModifNew, theTime))
229 {
230 // modifier key just pressed
231 }
232
233 Aspect_VKey anAction = Aspect_VKey_UNKNOWN;
234 if (myNavKeyMap.Find (theKey | myKeys.Modifiers(), anAction)
235 && anAction != Aspect_VKey_UNKNOWN)
236 {
237 AIS_ViewController::KeyDown (anAction, theTime, thePressure);
238 }
239}
240
7fd59977 241//=======================================================================
49582f9d 242//function : KeyUp
679ecdee 243//purpose :
7fd59977 244//=======================================================================
49582f9d 245void ViewerTest_EventManager::KeyUp (Aspect_VKey theKey,
246 double theTime)
7fd59977 247{
d22962e4 248 const unsigned int aModifOld = myKeys.Modifiers();
49582f9d 249 AIS_ViewController::KeyUp (theKey, theTime);
d22962e4 250
251 Aspect_VKey anAction = Aspect_VKey_UNKNOWN;
252 if (myNavKeyMap.Find (theKey | myKeys.Modifiers(), anAction)
253 && anAction != Aspect_VKey_UNKNOWN)
254 {
255 AIS_ViewController::KeyUp (anAction, theTime);
256 ProcessKeyPress (anAction);
257 }
258
259 const unsigned int aModifNew = myKeys.Modifiers();
260 if (aModifNew != aModifOld
261 && navigationKeyModifierSwitch (aModifOld, aModifNew, theTime))
262 {
263 // modifier key released
264 }
265
266 ProcessKeyPress (theKey | aModifNew);
7fd59977 267}
268
49582f9d 269//==============================================================================
270//function : ProcessKeyPress
679ecdee 271//purpose :
49582f9d 272//==============================================================================
273void ViewerTest_EventManager::ProcessKeyPress (Aspect_VKey theKey)
7fd59977 274{
49582f9d 275 if (myCtx.IsNull()
276 || myView.IsNull())
679ecdee 277 {
278 return;
279 }
679ecdee 280
49582f9d 281 switch (theKey)
679ecdee 282 {
d22962e4 283 case Aspect_VKey_Backspace: // AXO
49582f9d 284 {
285 if (!ViewerTest_V3dView::IsCurrentViewIn2DMode())
286 {
287 myView->SetProj(V3d_XposYnegZpos);
288 }
289 break;
290 }
49582f9d 291 case Aspect_VKey_F:
292 {
293 if (myCtx->NbSelected() > 0)
294 {
295 myCtx->FitSelected (myView);
296 }
297 else
298 {
299 myView->FitAll();
300 }
301 break;
302 }
303 case Aspect_VKey_H: // HLR
304 {
305 std::cout << "HLR\n";
306 myView->SetComputedMode (!myView->ComputedMode());
307 myView->Redraw();
308 break;
309 }
310 case Aspect_VKey_P: // Type of HLR
311 {
312 myCtx->DefaultDrawer()->SetTypeOfHLR (myCtx->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo
313 ? Prs3d_TOH_PolyAlgo
314 : Prs3d_TOH_Algo);
315 if (myCtx->NbSelected() == 0)
316 {
317 AIS_ListOfInteractive aListOfShapes;
318 myCtx->DisplayedObjects (aListOfShapes);
319 for (AIS_ListIteratorOfListOfInteractive anIter (aListOfShapes); anIter.More(); anIter.Next())
320 {
321 if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (anIter.Value()))
322 {
323 aShape->SetTypeOfHLR (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo
324 ? Prs3d_TOH_Algo
325 : Prs3d_TOH_PolyAlgo);
326 myCtx->Redisplay (aShape, Standard_False);
327 }
328 }
329 }
330 else
331 {
332 for (myCtx->InitSelected(); myCtx->MoreSelected(); myCtx->NextSelected())
333 {
334 if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (myCtx->SelectedInteractive()))
335 {
336 aShape->SetTypeOfHLR (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo
337 ? Prs3d_TOH_Algo
338 : Prs3d_TOH_PolyAlgo);
339 myCtx->Redisplay (aShape, Standard_False);
340 }
341 }
342 }
343 myCtx->UpdateCurrentViewer();
344 break;
345 }
d22962e4 346 case Aspect_VKey_S | Aspect_VKeyFlags_CTRL:
347 case Aspect_VKey_W | Aspect_VKeyFlags_CTRL:
49582f9d 348 {
349 Standard_Integer aDispMode = AIS_Shaded;
d22962e4 350 if (theKey == (Aspect_VKey_S | Aspect_VKeyFlags_CTRL))
49582f9d 351 {
352 aDispMode = AIS_Shaded;
353 std::cout << "setup Shaded display mode\n";
354 }
355 else
356 {
357 aDispMode = AIS_WireFrame;
358 std::cout << "setup WireFrame display mode\n";
359 }
4754e164 360
49582f9d 361 if (myCtx->NbSelected() == 0)
362 {
363 myCtx->SetDisplayMode (aDispMode, true);
364 }
365 else
366 {
367 for (myCtx->InitSelected(); myCtx->MoreSelected(); myCtx->NextSelected())
368 {
369 myCtx->SetDisplayMode (myCtx->SelectedInteractive(), aDispMode, false);
370 }
371 myCtx->UpdateCurrentViewer();
372 }
373 break;
374 }
375 case Aspect_VKey_U: // Unset display mode
376 {
377 std::cout << "reset display mode to defaults\n";
378 if (myCtx->NbSelected() == 0)
379 {
380 myCtx->SetDisplayMode (AIS_WireFrame, true);
381 }
382 else
383 {
384 for (myCtx->InitSelected(); myCtx->MoreSelected(); myCtx->NextSelected())
385 {
386 myCtx->UnsetDisplayMode (myCtx->SelectedInteractive(), false);
387 }
388 myCtx->UpdateCurrentViewer();
389 }
390 break;
391 }
392 case Aspect_VKey_T:
393 {
394 if (!ViewerTest_V3dView::IsCurrentViewIn2DMode())
395 {
396 myView->SetProj (V3d_TypeOfOrientation_Zup_Top);
397 }
398 break;
399 }
400 case Aspect_VKey_B:
401 {
402 if (!ViewerTest_V3dView::IsCurrentViewIn2DMode())
403 {
404 myView->SetProj (V3d_TypeOfOrientation_Zup_Bottom);
405 }
406 break;
407 }
408 case Aspect_VKey_L:
409 {
410 if (!ViewerTest_V3dView::IsCurrentViewIn2DMode())
411 {
412 myView->SetProj (V3d_TypeOfOrientation_Zup_Left);
413 }
414 break;
415 }
416 case Aspect_VKey_R:
417 {
418 if (!ViewerTest_V3dView::IsCurrentViewIn2DMode())
419 {
420 myView->SetProj (V3d_TypeOfOrientation_Zup_Right);
421 }
422 break;
423 }
424 case Aspect_VKey_Comma:
425 {
426 myCtx->HilightNextDetected (myView);
427 break;
428 }
429 case Aspect_VKey_Period:
430 {
431 myCtx->HilightPreviousDetected (myView);
432 break;
433 }
434 case Aspect_VKey_Slash:
435 case Aspect_VKey_NumpadDivide:
436 {
437 Handle(Graphic3d_Camera) aCamera = myView->Camera();
438 if (aCamera->IsStereo())
439 {
440 aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
441 myView->Redraw();
442 }
443 break;
444 }
445 case Aspect_VKey_NumpadMultiply:
446 {
447 Handle(Graphic3d_Camera) aCamera = myView->Camera();
448 if (aCamera->IsStereo())
449 {
450 aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
451 myView->Redraw();
452 }
453 break;
454 }
455 case Aspect_VKey_Delete:
456 {
457 if (!myCtx.IsNull()
458 && myCtx->NbSelected() > 0)
459 {
460 Draw_Interprete ("verase");
461 }
462 break;
463 }
464 case Aspect_VKey_Escape:
465 {
466 if (!myCtx.IsNull()
467 && ViewerTest_EventManager::ToCloseViewOnEscape())
468 {
469 Draw_Interprete (ViewerTest_EventManager::ToExitOnCloseView() ? "exit" : "vclose");
470 }
d22962e4 471 break;
472 }
473 case Aspect_VKey_NavSpeedDecrease:
474 case Aspect_VKey_NavSpeedIncrease:
475 {
476 // handle slide speed
477 float aNewSpeed = theKey == Aspect_VKey_NavSpeedDecrease
478 ? myWalkSpeedRelative * 0.5f
479 : myWalkSpeedRelative * 2.0f;
480 if (aNewSpeed >= 0.00001f
481 && aNewSpeed <= 10.0f)
482 {
483 if (Abs (aNewSpeed - 0.1f) < 0.001f)
484 {
485 aNewSpeed = 0.1f;
486 }
487 myWalkSpeedRelative = aNewSpeed;
488 }
489 break;
49582f9d 490 }
491 }
4754e164 492
49582f9d 493 if (theKey >= Aspect_VKey_0
494 && theKey <= Aspect_VKey_7)
679ecdee 495 {
49582f9d 496 const Standard_Integer aSelMode = theKey - Aspect_VKey_0;
497 bool toEnable = true;
498 if (!myCtx.IsNull())
499 {
500 AIS_ListOfInteractive aPrsList;
501 myCtx->DisplayedObjects (aPrsList);
502 for (AIS_ListOfInteractive::Iterator aPrsIter (aPrsList); aPrsIter.More() && toEnable; aPrsIter.Next())
503 {
504 TColStd_ListOfInteger aModes;
505 myCtx->ActivatedModes (aPrsIter.Value(), aModes);
506 for (TColStd_ListOfInteger::Iterator aModeIter (aModes); aModeIter.More() && toEnable; aModeIter.Next())
507 {
508 if (aModeIter.Value() == aSelMode)
509 {
510 toEnable = false;
511 }
512 }
513 }
514 }
515 TCollection_AsciiString aCmd = TCollection_AsciiString ("vselmode ") + aSelMode + (toEnable ? " 1" : " 0");
516 Draw_Interprete (aCmd.ToCString());
679ecdee 517 }
c398b00e 518}