1 // Copyright (c) 2016-2019 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
14 #include "AIS_ViewController.hxx"
16 #include <AIS_AnimationCamera.hxx>
17 #include <AIS_InteractiveContext.hxx>
18 #include <AIS_Point.hxx>
19 #include <AIS_RubberBand.hxx>
20 #include <AIS_XRTrackedDevice.hxx>
21 #include <Aspect_XRSession.hxx>
22 #include <Aspect_Grid.hxx>
23 #include <Geom_CartesianPoint.hxx>
24 #include <Graphic3d_ArrayOfSegments.hxx>
25 #include <Graphic3d_Texture2Dmanual.hxx>
26 #include <Message.hxx>
27 #include <Message_Messenger.hxx>
28 #include <gp_Quaternion.hxx>
29 #include <V3d_View.hxx>
30 #include <WNT_HIDSpaceMouse.hxx>
32 // =======================================================================
33 // function : AIS_ViewController
35 // =======================================================================
36 AIS_ViewController::AIS_ViewController()
37 : myLastEventsTime (0.0),
38 myToAskNextFrame (false),
39 myMinCamDistance (1.0),
40 myRotationMode (AIS_RotationMode_BndBoxActive),
41 myNavigationMode (AIS_NavigationMode_Orbit),
44 myToShowPanAnchorPoint (true),
45 myToShowRotateCenter (true),
46 myToLockOrbitZUp (false),
47 myToInvertPitch (false),
48 myToAllowTouchZRotation(false),
49 myToAllowRotation (true),
50 myToAllowPanning (true),
51 myToAllowZooming (true),
52 myToAllowZFocus (true),
53 myToAllowHighlight (true),
54 myToAllowDragging (true),
55 myToStickToRayOnZoom (true),
56 myToStickToRayOnRotation (true),
58 myWalkSpeedAbsolute (1.5f),
59 myWalkSpeedRelative (0.1f),
63 myViewAnimation (new AIS_AnimationCamera ("AIS_ViewController_ViewAnimation", Handle(V3d_View)())),
64 myPrevMoveTo (-1, -1),
65 myHasHlrOnBeforeRotation (false),
67 myXRPrsDevices (0, 0),
68 myXRLaserTeleColor (Quantity_NOC_GREEN),
69 myXRLaserPickColor (Quantity_NOC_BLUE),
70 myXRLastTeleportHand(Aspect_XRTrackedDeviceRole_Other),
71 myXRLastPickingHand (Aspect_XRTrackedDeviceRole_Other),
72 myXRLastPickDepthLeft (Precision::Infinite()),
73 myXRLastPickDepthRight(Precision::Infinite()),
74 myXRTurnAngle (M_PI_4),
75 myToDisplayXRAuxDevices (false),
76 myToDisplayXRHands (true),
78 myMouseClickThreshold (3.0),
79 myMouseDoubleClickInt (0.4),
80 myScrollZoomRatio (15.0f),
81 myMouseActiveGesture (AIS_MouseGesture_NONE),
82 myMouseActiveIdleRotation (false),
83 myMouseClickCounter (0),
84 myMousePressed (Aspect_VKeyMouse_NONE),
85 myMouseModifiers (Aspect_VKeyFlags_NONE),
86 myMouseSingleButton (-1),
87 myMouseStopDragOnUnclick (false),
89 myTouchToleranceScale (1.0f),
90 myTouchRotationThresholdPx (6.0f),
91 myTouchZRotationThreshold (float(2.0 * M_PI / 180.0)),
92 myTouchPanThresholdPx (4.0f),
93 myTouchZoomThresholdPx (6.0f),
94 myTouchZoomRatio (0.13f),
97 myUpdateStartPointPan (true),
98 myUpdateStartPointRot (true),
99 myUpdateStartPointZRot (true),
101 my3dMouseNoRotate (false, false, false),
102 my3dMouseToReverse (true, false, false),
103 my3dMouseAccelTrans (2.0f),
104 my3dMouseAccelRotate (4.0f),
105 my3dMouseIsQuadric (true),
107 myPanPnt3d (Precision::Infinite(), 0.0, 0.0)
109 memset(my3dMouseButtonState, 0, sizeof(my3dMouseButtonState));
110 myEventTimer.Start();
111 myViewAnimation->SetOwnDuration (0.5);
113 myAnchorPointPrs1 = new AIS_Point (new Geom_CartesianPoint (0.0, 0.0, 0.0));
114 myAnchorPointPrs1->SetZLayer (Graphic3d_ZLayerId_Top);
115 myAnchorPointPrs1->SetMutable (true);
117 myAnchorPointPrs2 = new AIS_Point (new Geom_CartesianPoint (0.0, 0.0, 0.0));
118 myAnchorPointPrs2->SetZLayer (Graphic3d_ZLayerId_Topmost);
119 myAnchorPointPrs2->SetMutable (true);
121 myRubberBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE4, 0.5, 1.0);
122 myRubberBand->SetZLayer (Graphic3d_ZLayerId_TopOSD);
123 myRubberBand->SetTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_UPPER));
124 myRubberBand->SetDisplayMode (0);
125 myRubberBand->SetMutable (true);
127 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton, AIS_MouseGesture_RotateOrbit);
128 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_Zoom);
129 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_SHIFT, AIS_MouseGesture_Pan);
130 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_ALT, AIS_MouseGesture_SelectRectangle);
131 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_ALT | Aspect_VKeyFlags_SHIFT, AIS_MouseGesture_SelectRectangle);
133 myMouseSelectionSchemes.Bind (Aspect_VKeyMouse_LeftButton, AIS_SelectionScheme_Replace);
134 myMouseSelectionSchemes.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_ALT, AIS_SelectionScheme_Replace);
135 myMouseSelectionSchemes.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_SHIFT, AIS_SelectionScheme_XOR);
136 myMouseSelectionSchemes.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_ALT | Aspect_VKeyFlags_SHIFT, AIS_SelectionScheme_XOR);
138 myMouseGestureMap.Bind (Aspect_VKeyMouse_RightButton, AIS_MouseGesture_Zoom);
139 myMouseGestureMap.Bind (Aspect_VKeyMouse_RightButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_RotateOrbit);
141 myMouseGestureMap.Bind (Aspect_VKeyMouse_MiddleButton, AIS_MouseGesture_Pan);
142 myMouseGestureMap.Bind (Aspect_VKeyMouse_MiddleButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_Pan);
144 myXRTeleportHaptic.Duration = 3600.0f;
145 myXRTeleportHaptic.Frequency = 0.1f;
146 myXRTeleportHaptic.Amplitude = 0.2f;
148 myXRPickingHaptic.Duration = 0.1f;
149 myXRPickingHaptic.Frequency = 4.0f;
150 myXRPickingHaptic.Amplitude = 0.1f;
152 myXRSelectHaptic.Duration = 0.2f;
153 myXRSelectHaptic.Frequency = 4.0f;
154 myXRSelectHaptic.Amplitude = 0.5f;
157 // =======================================================================
158 // function : ~AIS_ViewController
160 // =======================================================================
161 AIS_ViewController::~AIS_ViewController()
166 // =======================================================================
167 // function : ResetViewInput
169 // =======================================================================
170 void AIS_ViewController::ResetViewInput()
173 myMousePressed = Aspect_VKeyMouse_NONE;
174 myMouseModifiers = Aspect_VKeyFlags_NONE;
175 myMouseSingleButton = -1;
176 myUI.Dragging.ToAbort = true;
177 myMouseActiveGesture = AIS_MouseGesture_NONE;
178 myMouseClickTimer.Stop();
179 myMouseClickCounter = 0;
182 // =======================================================================
183 // function : FlushViewEvents
185 // =======================================================================
186 void AIS_ViewController::FlushViewEvents (const Handle(AIS_InteractiveContext)& theCtx,
187 const Handle(V3d_View)& theView,
188 Standard_Boolean theToHandle)
190 flushBuffers (theCtx, theView);
191 flushGestures(theCtx, theView);
194 HandleViewEvents (theCtx, theView);
198 // =======================================================================
199 // function : flushBuffers
201 // =======================================================================
202 void AIS_ViewController::flushBuffers (const Handle(AIS_InteractiveContext)& ,
203 const Handle(V3d_View)& )
205 myToAskNextFrame = false;
207 myGL.IsNewGesture = myUI.IsNewGesture;
208 myUI.IsNewGesture = false;
210 myGL.ZoomActions.Clear();
211 myGL.ZoomActions.Append (myUI.ZoomActions);
212 myUI.ZoomActions.Clear();
214 myGL.Orientation.ToFitAll = myUI.Orientation.ToFitAll;
215 myUI.Orientation.ToFitAll = false;
216 if (myUI.Orientation.ToSetViewOrient)
218 myUI.Orientation.ToSetViewOrient = false;
219 myGL.Orientation.ToSetViewOrient = true;
220 myGL.Orientation.ViewOrient = myUI.Orientation.ViewOrient;
223 if (myUI.MoveTo.ToHilight)
225 myUI.MoveTo.ToHilight = false;
226 myGL.MoveTo.ToHilight = true;
227 myGL.MoveTo.Point = myUI.MoveTo.Point;
231 myGL.Selection.Tool = myUI.Selection.Tool;
232 myGL.Selection.Scheme = myUI.Selection.Scheme;
233 myGL.Selection.Points = myUI.Selection.Points;
234 //myGL.Selection.Scheme = AIS_SelectionScheme_UNKNOWN; // no need
235 if (myUI.Selection.Tool == AIS_ViewSelectionTool_Picking)
237 myUI.Selection.Points.Clear();
241 if (myUI.Selection.ToApplyTool)
243 myGL.Selection.ToApplyTool = true;
244 myUI.Selection.ToApplyTool = false;
245 myUI.Selection.Points.Clear();
248 if (myUI.Panning.ToStart)
250 myUI.Panning.ToStart = false;
251 myGL.Panning.ToStart = true;
252 myGL.Panning.PointStart = myUI.Panning.PointStart;
255 if (myUI.Panning.ToPan)
257 myUI.Panning.ToPan = false;
258 myGL.Panning.ToPan = true;
259 myGL.Panning.Delta = myUI.Panning.Delta;
262 if (myUI.Dragging.ToAbort)
264 myUI.Dragging.ToAbort = false;
265 myGL.Dragging.ToAbort = true;
267 else if (myUI.Dragging.ToStop)
269 myUI.Dragging.ToStop = false;
270 myGL.Dragging.ToStop = true;
272 else if (myUI.Dragging.ToStart)
274 myUI.Dragging.ToStart = false;
275 myGL.Dragging.ToStart = true;
276 myGL.Dragging.PointStart = myUI.Dragging.PointStart;
278 myGL.Dragging.PointTo = myUI.Dragging.PointTo;
280 if (myUI.OrbitRotation.ToStart)
282 myUI.OrbitRotation.ToStart = false;
283 myGL.OrbitRotation.ToStart = true;
284 myGL.OrbitRotation.PointStart = myUI.OrbitRotation.PointStart;
287 if (myUI.OrbitRotation.ToRotate)
289 myUI.OrbitRotation.ToRotate = false;
290 myGL.OrbitRotation.ToRotate = true;
291 myGL.OrbitRotation.PointTo = myUI.OrbitRotation.PointTo;
294 if (myUI.ViewRotation.ToStart)
296 myUI.ViewRotation.ToStart = false;
297 myGL.ViewRotation.ToStart = true;
298 myGL.ViewRotation.PointStart = myUI.ViewRotation.PointStart;
301 if (myUI.ViewRotation.ToRotate)
303 myUI.ViewRotation.ToRotate = false;
304 myGL.ViewRotation.ToRotate = true;
305 myGL.ViewRotation.PointTo = myUI.ViewRotation.PointTo;
308 if (myUI.ZRotate.ToRotate)
310 myGL.ZRotate = myUI.ZRotate;
311 myUI.ZRotate.ToRotate = false;
315 // =======================================================================
316 // function : flushGestures
318 // =======================================================================
319 void AIS_ViewController::flushGestures (const Handle(AIS_InteractiveContext)& ,
320 const Handle(V3d_View)& theView)
322 const Standard_Real aTolScale = myTouchToleranceScale;
323 const Standard_Integer aTouchNb = myTouchPoints.Extent();
324 if (myNbTouchesLast != aTouchNb)
326 myNbTouchesLast = aTouchNb;
327 myGL.IsNewGesture = true;
329 if (aTouchNb == 1) // touch
331 Aspect_Touch& aTouch = myTouchPoints.ChangeFromIndex (1);
332 if (myUpdateStartPointRot)
334 // skip rotation if have active dragged object
335 if (myNavigationMode == AIS_NavigationMode_Orbit)
337 myGL.OrbitRotation.ToStart = true;
338 myGL.OrbitRotation.PointStart = myStartRotCoord;
342 myGL.ViewRotation.ToStart = true;
343 myGL.ViewRotation.PointStart = myStartRotCoord;
346 myUpdateStartPointRot = false;
347 theView->Invalidate();
351 const Standard_Real aRotTouchTol = !aTouch.IsPreciseDevice
352 ? aTolScale * myTouchRotationThresholdPx
354 if (Abs (aTouch.Delta().x()) + Abs(aTouch.Delta().y()) > aRotTouchTol)
356 const Standard_Real aRotAccel = myNavigationMode == AIS_NavigationMode_FirstPersonWalk ? myMouseAccel : myOrbitAccel;
357 if (myNavigationMode == AIS_NavigationMode_Orbit)
359 const Graphic3d_Vec2d aRotDelta = aTouch.To - myGL.OrbitRotation.PointStart;
360 myGL.OrbitRotation.ToRotate = true;
361 myGL.OrbitRotation.PointTo = myGL.OrbitRotation.PointStart + aRotDelta * aRotAccel;
362 myGL.Dragging.PointTo.SetValues ((int )aTouch.To.x(), (int )aTouch.To.y());
366 const Graphic3d_Vec2d aRotDelta = aTouch.To - myGL.ViewRotation.PointStart;
367 myGL.ViewRotation.ToRotate = true;
368 myGL.ViewRotation.PointTo = myGL.ViewRotation.PointStart + aRotDelta * aRotAccel;
369 myGL.Dragging.PointTo.SetValues ((int )aTouch.To.x(), (int )aTouch.To.y());
372 aTouch.From = aTouch.To;
375 else if (aTouchNb == 2) // pinch
377 Aspect_Touch& aFirstTouch = myTouchPoints.ChangeFromIndex (1);
378 Aspect_Touch& aLastTouch = myTouchPoints.ChangeFromIndex (2);
379 const Graphic3d_Vec2d aFrom[2] = { aFirstTouch.From, aLastTouch.From };
380 const Graphic3d_Vec2d aTo[2] = { aFirstTouch.To, aLastTouch.To };
382 Graphic3d_Vec2d aPinchCenterStart ((aFrom[0].x() + aFrom[1].x()) / 2.0,
383 (aFrom[0].y() + aFrom[1].y()) / 2.0);
385 Standard_Real aPinchCenterXEnd = (aTo[0].x() + aTo[1].x()) / 2.0;
386 Standard_Real aPinchCenterYEnd = (aTo[0].y() + aTo[1].y()) / 2.0;
388 Standard_Real aPinchCenterXDev = aPinchCenterXEnd - aPinchCenterStart.x();
389 Standard_Real aPinchCenterYDev = aPinchCenterYEnd - aPinchCenterStart.y();
391 Standard_Real aStartSize = (aFrom[0] - aFrom[1]).Modulus();
392 Standard_Real anEndSize = ( aTo[0] - aTo[1]).Modulus();
394 Standard_Real aDeltaSize = anEndSize - aStartSize;
396 bool anIsClearDev = false;
398 if (myToAllowTouchZRotation)
400 Standard_Real A1 = aFrom[0].y() - aFrom[1].y();
401 Standard_Real B1 = aFrom[1].x() - aFrom[0].x();
403 Standard_Real A2 = aTo[0].y() - aTo[1].y();
404 Standard_Real B2 = aTo[1].x() - aTo[0].x();
406 Standard_Real aRotAngle = 0.0;
408 Standard_Real aDenomenator = A1*A2 + B1*B2;
409 if (aDenomenator <= Precision::Confusion())
415 Standard_Real aNumerator = A1*B2 - A2*B1;
416 aRotAngle = ATan (aNumerator / aDenomenator);
419 if (Abs(aRotAngle) > Standard_Real(myTouchZRotationThreshold))
421 myGL.ZRotate.ToRotate = true;
422 myGL.ZRotate.Angle = aRotAngle;
427 if (Abs(aDeltaSize) > aTolScale * myTouchZoomThresholdPx)
430 aDeltaSize *= Standard_Real(myTouchZoomRatio);
431 Aspect_ScrollDelta aParams (Graphic3d_Vec2i (aPinchCenterStart), aDeltaSize);
432 myGL.ZoomActions.Append (aParams);
436 const Standard_Real aPanTouchTol = !aFirstTouch.IsPreciseDevice
437 ? aTolScale * myTouchPanThresholdPx
439 if (Abs(aPinchCenterXDev) + Abs(aPinchCenterYDev) > aPanTouchTol)
442 if (myUpdateStartPointPan)
444 myGL.Panning.ToStart = true;
445 myGL.Panning.PointStart = Graphic3d_Vec2i (myStartPanCoord);
446 myUpdateStartPointPan = false;
447 theView->Invalidate();
450 myGL.Panning.ToPan = true;
451 myGL.Panning.Delta.x() = int( aPinchCenterXDev);
452 myGL.Panning.Delta.y() = int(-aPinchCenterYDev);
458 aFirstTouch.From = aFirstTouch.To;
459 aLastTouch .From = aLastTouch.To;
464 // =======================================================================
465 // function : UpdateViewOrientation
467 // =======================================================================
468 void AIS_ViewController::UpdateViewOrientation (V3d_TypeOfOrientation theOrientation,
471 myUI.Orientation.ToFitAll = theToFitAll;
472 myUI.Orientation.ToSetViewOrient = true;
473 myUI.Orientation.ViewOrient = theOrientation;
476 // =======================================================================
477 // function : SelectInViewer
479 // =======================================================================
480 void AIS_ViewController::SelectInViewer (const Graphic3d_Vec2i& thePnt,
481 const AIS_SelectionScheme theScheme)
483 if (myUI.Selection.Tool != AIS_ViewSelectionTool_Picking)
485 myUI.Selection.Tool = AIS_ViewSelectionTool_Picking;
486 myUI.Selection.Points.Clear();
489 myUI.Selection.Scheme = theScheme;
490 myUI.Selection.Points.Append (thePnt);
493 // =======================================================================
494 // function : SelectInViewer
496 // =======================================================================
497 void AIS_ViewController::SelectInViewer (const NCollection_Sequence<Graphic3d_Vec2i>& thePnts,
498 const AIS_SelectionScheme theScheme)
500 myUI.Selection.Scheme = theScheme;
501 myUI.Selection.Points = thePnts;
502 myUI.Selection.ToApplyTool = true;
503 if (thePnts.Length() == 1)
505 myUI.Selection.Tool = AIS_ViewSelectionTool_Picking;
507 else if (thePnts.Length() == 2)
509 myUI.Selection.Tool = AIS_ViewSelectionTool_RubberBand;
513 myUI.Selection.Tool = AIS_ViewSelectionTool_Polygon;
517 // =======================================================================
518 // function : UpdateRubberBand
520 // =======================================================================
521 void AIS_ViewController::UpdateRubberBand (const Graphic3d_Vec2i& thePntFrom,
522 const Graphic3d_Vec2i& thePntTo)
524 myUI.Selection.Tool = AIS_ViewSelectionTool_RubberBand;
525 myUI.Selection.Points.Clear();
526 myUI.Selection.Points.Append (thePntFrom);
527 myUI.Selection.Points.Append (thePntTo);
530 // =======================================================================
531 // function : UpdatePolySelection
533 // =======================================================================
534 void AIS_ViewController::UpdatePolySelection (const Graphic3d_Vec2i& thePnt,
537 if (myUI.Selection.Tool != AIS_ViewSelectionTool_Polygon)
539 myUI.Selection.Tool = AIS_ViewSelectionTool_Polygon;
540 myUI.Selection.Points.Clear();
543 if (myUI.Selection.Points.IsEmpty())
545 myUI.Selection.Points.Append (thePnt);
548 && myUI.Selection.Points.Last() != thePnt)
550 myUI.Selection.Points.Append (thePnt);
554 myUI.Selection.Points.ChangeLast() = thePnt;
558 // =======================================================================
559 // function : UpdateZoom
561 // =======================================================================
562 bool AIS_ViewController::UpdateZoom (const Aspect_ScrollDelta& theDelta)
564 if (!myUI.ZoomActions.IsEmpty())
566 if (myUI.ZoomActions.ChangeLast().Point == theDelta.Point)
568 myUI.ZoomActions.ChangeLast().Delta += theDelta.Delta;
573 myUI.ZoomActions.Append (theDelta);
577 // =======================================================================
578 // function : UpdateZRotation
580 // =======================================================================
581 bool AIS_ViewController::UpdateZRotation (double theAngle)
583 if (!ToAllowTouchZRotation())
588 myUI.ZRotate.Angle = myUI.ZRotate.ToRotate
589 ? myUI.ZRotate.Angle + theAngle
591 if (myUI.ZRotate.ToRotate)
595 myUI.ZRotate.ToRotate = true;
599 // =======================================================================
600 // function : UpdateMouseScroll
602 // =======================================================================
603 bool AIS_ViewController::UpdateMouseScroll (const Aspect_ScrollDelta& theDelta)
605 Aspect_ScrollDelta aDelta = theDelta;
606 aDelta.Delta *= myScrollZoomRatio;
607 return UpdateZoom (aDelta);
610 // =======================================================================
611 // function : UpdateMouseClick
613 // =======================================================================
614 bool AIS_ViewController::UpdateMouseClick (const Graphic3d_Vec2i& thePoint,
615 Aspect_VKeyMouse theButton,
616 Aspect_VKeyFlags theModifiers,
617 bool theIsDoubleClick)
619 (void )theIsDoubleClick;
620 AIS_SelectionScheme aScheme = AIS_SelectionScheme_UNKNOWN;
621 if (myMouseSelectionSchemes.Find (theButton | theModifiers, aScheme))
623 SelectInViewer (thePoint, aScheme);
629 // =======================================================================
630 // function : UpdateMouseButtons
632 // =======================================================================
633 bool AIS_ViewController::UpdateMouseButtons (const Graphic3d_Vec2i& thePoint,
634 Aspect_VKeyMouse theButtons,
635 Aspect_VKeyFlags theModifiers,
638 bool toUpdateView = false;
639 const double aTolClick = (theIsEmulated ? myTouchToleranceScale : 1.0) * myMouseClickThreshold;
640 if (theButtons == Aspect_VKeyMouse_NONE
641 && myMouseSingleButton > 0)
643 const Graphic3d_Vec2i aDelta = thePoint - myMousePressPoint;
644 if (double(aDelta.cwiseAbs().maxComp()) < aTolClick)
646 ++myMouseClickCounter;
647 const bool isDoubleClick = myMouseClickCounter == 2
648 && myMouseClickTimer.IsStarted()
649 && myMouseClickTimer.ElapsedTime() <= myMouseDoubleClickInt;
651 myMouseClickTimer.Stop();
652 myMouseClickTimer.Reset();
653 myMouseClickTimer.Start();
656 myMouseClickCounter = 0;
658 toUpdateView = UpdateMouseClick (thePoint, (Aspect_VKeyMouse )myMouseSingleButton, theModifiers, isDoubleClick) || toUpdateView;
662 myMouseClickTimer.Stop();
663 myMouseClickCounter = 0;
664 myMouseStopDragOnUnclick = false;
665 myUI.Dragging.ToStop = true;
668 myMouseSingleButton = -1;
670 else if (theButtons == Aspect_VKeyMouse_NONE)
672 myMouseSingleButton = -1;
673 if (myMouseStopDragOnUnclick)
675 myMouseStopDragOnUnclick = false;
676 myUI.Dragging.ToStop = true;
680 else if (myMouseSingleButton == -1)
682 if ((theButtons & Aspect_VKeyMouse_LeftButton) == Aspect_VKeyMouse_LeftButton)
684 myMouseSingleButton = Aspect_VKeyMouse_LeftButton;
686 else if ((theButtons & Aspect_VKeyMouse_RightButton) == Aspect_VKeyMouse_RightButton)
688 myMouseSingleButton = Aspect_VKeyMouse_RightButton;
690 else if ((theButtons & Aspect_VKeyMouse_MiddleButton) == Aspect_VKeyMouse_MiddleButton)
692 myMouseSingleButton = Aspect_VKeyMouse_MiddleButton;
696 myMouseSingleButton = 0;
698 if (myMouseSingleButton != 0)
700 if (myMouseClickCounter == 1)
702 const Graphic3d_Vec2i aDelta = thePoint - myMousePressPoint;
703 if (double(aDelta.cwiseAbs().maxComp()) >= aTolClick)
705 myMouseClickTimer.Stop();
706 myMouseClickCounter = 0;
709 myMousePressPoint = thePoint;
714 myMouseSingleButton = 0;
716 myUI.Dragging.ToAbort = true;
720 const AIS_MouseGesture aPrevGesture = myMouseActiveGesture;
721 const Aspect_VKeyMouse aPrevButtons = myMousePressed;
722 const Aspect_VKeyFlags aPrevModifiers = myMouseModifiers;
723 myMouseModifiers = theModifiers;
724 myMousePressed = theButtons;
726 || myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
728 myMouseActiveIdleRotation = false;
729 myMouseActiveGesture = AIS_MouseGesture_NONE;
732 myMousePressPoint = thePoint;
733 myMouseProgressPoint = myMousePressPoint;
736 if (myMouseGestureMap.Find (theButtons | theModifiers, myMouseActiveGesture))
738 switch (myMouseActiveGesture)
740 case AIS_MouseGesture_RotateView:
741 case AIS_MouseGesture_RotateOrbit:
743 if (myToAllowRotation)
745 myUpdateStartPointRot = true;
749 myMouseActiveGesture = AIS_MouseGesture_NONE;
753 case AIS_MouseGesture_Pan:
755 if (myToAllowPanning)
757 myUpdateStartPointPan = true;
761 myMouseActiveGesture = AIS_MouseGesture_NONE;
765 case AIS_MouseGesture_Zoom:
766 case AIS_MouseGesture_ZoomWindow:
768 if (!myToAllowZooming)
770 myMouseActiveGesture = AIS_MouseGesture_NONE;
774 case AIS_MouseGesture_SelectRectangle:
778 case AIS_MouseGesture_SelectLasso:
780 UpdatePolySelection (thePoint, true);
783 case AIS_MouseGesture_NONE:
790 if (theButtons == Aspect_VKeyMouse_LeftButton
791 && theModifiers == Aspect_VKeyFlags_NONE
792 && myToAllowDragging)
794 myUI.Dragging.ToStart = true;
795 myUI.Dragging.PointStart = thePoint;
799 if (aPrevGesture != myMouseActiveGesture)
801 if (aPrevGesture == AIS_MouseGesture_SelectRectangle
802 || aPrevGesture == AIS_MouseGesture_SelectLasso
803 || aPrevGesture == AIS_MouseGesture_ZoomWindow)
805 myUI.Selection.ToApplyTool = true;
806 myUI.Selection.Scheme = AIS_SelectionScheme_Replace;
807 myMouseSelectionSchemes.Find (aPrevButtons | aPrevModifiers, myUI.Selection.Scheme);
810 myUI.IsNewGesture = true;
817 // =======================================================================
818 // function : UpdateMousePosition
820 // =======================================================================
821 bool AIS_ViewController::UpdateMousePosition (const Graphic3d_Vec2i& thePoint,
822 Aspect_VKeyMouse theButtons,
823 Aspect_VKeyFlags theModifiers,
826 myMousePositionLast = thePoint;
827 if (myMouseSingleButton > 0)
829 const double aTolClick = (theIsEmulated ? myTouchToleranceScale : 1.0) * myMouseClickThreshold;
830 const Graphic3d_Vec2i aPressDelta = thePoint - myMousePressPoint;
831 if (double(aPressDelta.cwiseAbs().maxComp()) >= aTolClick)
833 myMouseClickTimer.Stop();
834 myMouseClickCounter = 0;
835 myMouseSingleButton = -1;
836 myMouseStopDragOnUnclick = true;
840 bool toUpdateView = false;
841 Graphic3d_Vec2i aDelta = thePoint - myMouseProgressPoint;
843 && myNavigationMode == AIS_NavigationMode_FirstPersonWalk)
845 if (!myMouseActiveIdleRotation
846 || myMouseActiveGesture != AIS_MouseGesture_RotateView)
848 myMouseActiveIdleRotation = true;
849 myMouseActiveGesture = AIS_MouseGesture_RotateView;
850 myMousePressPoint = thePoint;
851 myMouseProgressPoint = thePoint;
852 myUpdateStartPointRot = false;
853 myUI.ViewRotation.ToStart = true;
854 myUI.ViewRotation.PointStart.SetValues (thePoint.x(), thePoint.y());
855 myUI.ViewRotation.ToRotate = false;
856 aDelta.SetValues (0, 0);
861 if (myMouseActiveIdleRotation
862 && myMouseActiveGesture == AIS_MouseGesture_RotateView)
864 myMouseActiveGesture = AIS_MouseGesture_NONE;
866 myMouseActiveIdleRotation = false;
869 if (myMouseModifiers != theModifiers
870 && UpdateMouseButtons (thePoint, theButtons, theModifiers, theIsEmulated))
875 switch (myMouseActiveGesture)
877 case AIS_MouseGesture_SelectRectangle:
878 case AIS_MouseGesture_ZoomWindow:
880 UpdateRubberBand (myMousePressPoint, thePoint);
881 if (myMouseActiveGesture == AIS_MouseGesture_ZoomWindow)
883 myUI.Selection.Tool = AIS_ViewSelectionTool_ZoomWindow;
888 case AIS_MouseGesture_SelectLasso:
890 UpdatePolySelection (thePoint, true);
894 case AIS_MouseGesture_RotateOrbit:
895 case AIS_MouseGesture_RotateView:
897 if (!myToAllowRotation)
901 if (myUpdateStartPointRot)
903 if (myMouseActiveGesture == AIS_MouseGesture_RotateOrbit)
905 myUI.OrbitRotation.ToStart = true;
906 myUI.OrbitRotation.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
910 myUI.ViewRotation.ToStart = true;
911 myUI.ViewRotation.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
913 myUpdateStartPointRot = false;
916 const double aRotTol = theIsEmulated
917 ? double(myTouchToleranceScale) * myTouchRotationThresholdPx
919 if (double (Abs (aDelta.x()) + Abs (aDelta.y())) > aRotTol)
921 const double aRotAccel = myNavigationMode == AIS_NavigationMode_FirstPersonWalk ? myMouseAccel : myOrbitAccel;
922 const Graphic3d_Vec2i aRotDelta = thePoint - myMousePressPoint;
923 if (myMouseActiveGesture == AIS_MouseGesture_RotateOrbit)
925 myUI.OrbitRotation.ToRotate = true;
926 myUI.OrbitRotation.PointTo = Graphic3d_Vec2d (myMousePressPoint.x(), myMousePressPoint.y())
927 + Graphic3d_Vec2d (aRotDelta.x(), aRotDelta.y()) * aRotAccel;
931 myUI.ViewRotation.ToRotate = true;
932 myUI.ViewRotation.PointTo = Graphic3d_Vec2d (myMousePressPoint.x(), myMousePressPoint.y())
933 + Graphic3d_Vec2d (aRotDelta.x(), aRotDelta.y()) * aRotAccel;
935 myUI.Dragging.PointTo = thePoint;
937 myMouseProgressPoint = thePoint;
942 case AIS_MouseGesture_Zoom:
944 if (!myToAllowZooming)
948 const double aZoomTol = theIsEmulated
949 ? double(myTouchToleranceScale) * myTouchZoomThresholdPx
951 if (double (Abs (aDelta.x())) > aZoomTol)
953 if (UpdateZoom (Aspect_ScrollDelta (aDelta.x())))
957 myMouseProgressPoint = thePoint;
961 case AIS_MouseGesture_Pan:
963 if (!myToAllowPanning)
967 const double aPanTol = theIsEmulated
968 ? double(myTouchToleranceScale) * myTouchPanThresholdPx
970 if (double (Abs (aDelta.x()) + Abs (aDelta.y())) > aPanTol)
972 if (myUpdateStartPointPan)
974 myUI.Panning.ToStart = true;
975 myUI.Panning.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
976 myUpdateStartPointPan = false;
979 aDelta.y() = -aDelta.y();
980 myMouseProgressPoint = thePoint;
981 if (myUI.Panning.ToPan)
983 myUI.Panning.Delta += aDelta;
987 myUI.Panning.ToPan = true;
988 myUI.Panning.Delta = aDelta;
1000 if (theButtons == Aspect_VKeyMouse_NONE
1001 && myNavigationMode != AIS_NavigationMode_FirstPersonWalk
1003 && !HasTouchPoints()
1004 && myToAllowHighlight)
1006 myUI.MoveTo.ToHilight = true;
1007 myUI.MoveTo.Point = thePoint;
1008 toUpdateView = true;
1010 return toUpdateView;
1013 // =======================================================================
1014 // function : AddTouchPoint
1016 // =======================================================================
1017 void AIS_ViewController::AddTouchPoint (Standard_Size theId,
1018 const Graphic3d_Vec2d& thePnt,
1019 Standard_Boolean theClearBefore)
1021 myUI.MoveTo.ToHilight = false;
1024 RemoveTouchPoint ((Standard_Size )-1);
1027 myTouchPoints.Add (theId, Aspect_Touch (thePnt, false));
1028 if (myTouchPoints.Extent() == 1)
1030 myUpdateStartPointRot = true;
1031 myStartRotCoord = thePnt;
1032 if (myToAllowDragging)
1034 myUI.Dragging.ToStart = true;
1035 myUI.Dragging.PointStart.SetValues ((int )thePnt.x(), (int )thePnt.y());
1038 else if (myTouchPoints.Extent() == 2)
1040 myUI.Dragging.ToAbort = true;
1042 myUpdateStartPointPan = true;
1043 myStartPanCoord = thePnt;
1045 myUI.IsNewGesture = true;
1048 // =======================================================================
1049 // function : RemoveTouchPoint
1051 // =======================================================================
1052 bool AIS_ViewController::RemoveTouchPoint (Standard_Size theId,
1053 Standard_Boolean theClearSelectPnts)
1055 if (theId == (Standard_Size )-1)
1057 myTouchPoints.Clear (false);
1061 const Standard_Integer anOldExtent = myTouchPoints.Extent();
1062 myTouchPoints.RemoveKey (theId);
1063 if (myTouchPoints.Extent() == anOldExtent)
1069 if (myTouchPoints.Extent() == 1)
1071 // avoid incorrect transition from pinch to one finger
1072 Aspect_Touch& aFirstTouch = myTouchPoints.ChangeFromIndex (1);
1073 aFirstTouch.To = aFirstTouch.From;
1075 myStartRotCoord = aFirstTouch.To;
1076 myUpdateStartPointRot = true;
1078 else if (myTouchPoints.Extent() == 2)
1080 myStartPanCoord = myTouchPoints.FindFromIndex (1).To;
1081 myUpdateStartPointPan = true;
1083 else if (myTouchPoints.IsEmpty())
1085 if (theClearSelectPnts)
1087 myUI.Selection.ToApplyTool = true;
1090 myUI.Dragging.ToStop = true;
1092 myUI.IsNewGesture = true;
1096 // =======================================================================
1097 // function : UpdateTouchPoint
1099 // =======================================================================
1100 void AIS_ViewController::UpdateTouchPoint (Standard_Size theId,
1101 const Graphic3d_Vec2d& thePnt)
1103 if (Aspect_Touch* aTouch = myTouchPoints.ChangeSeek (theId))
1105 aTouch->To = thePnt;
1109 AddTouchPoint (theId, thePnt);
1113 // =======================================================================
1114 // function : Update3dMouse
1116 // =======================================================================
1117 bool AIS_ViewController::Update3dMouse (const WNT_HIDSpaceMouse& theEvent)
1119 bool toUpdate = false;
1120 toUpdate = update3dMouseTranslation (theEvent) || toUpdate;
1121 toUpdate = update3dMouseRotation (theEvent) || toUpdate;
1122 toUpdate = update3dMouseKeys (theEvent) || toUpdate;
1126 // =======================================================================
1127 // function : update3dMouseTranslation
1129 // =======================================================================
1130 bool AIS_ViewController::update3dMouseTranslation (const WNT_HIDSpaceMouse& theEvent)
1132 if (!theEvent.IsTranslation())
1138 const double aTimeStamp = EventTime();
1139 const Graphic3d_Vec3d aTrans = theEvent.Translation (isIdle, my3dMouseIsQuadric) * my3dMouseAccelTrans;
1140 myKeys.KeyFromAxis (Aspect_VKey_NavSlideLeft, Aspect_VKey_NavSlideRight, aTimeStamp, aTrans.x());
1141 myKeys.KeyFromAxis (Aspect_VKey_NavForward, Aspect_VKey_NavBackward, aTimeStamp, aTrans.y());
1142 myKeys.KeyFromAxis (Aspect_VKey_NavSlideUp, Aspect_VKey_NavSlideDown, aTimeStamp, aTrans.z());
1146 // =======================================================================
1147 // function : update3dMouseRotation
1149 // =======================================================================
1150 bool AIS_ViewController::update3dMouseRotation (const WNT_HIDSpaceMouse& theEvent)
1152 if (!theEvent.IsRotation()
1153 || !myToAllowRotation)
1158 bool isIdle = true, toUpdate = false;
1159 const double aTimeStamp = EventTime();
1160 const Graphic3d_Vec3d aRot3 = theEvent.Rotation (isIdle, my3dMouseIsQuadric) * my3dMouseAccelRotate;
1161 if (!my3dMouseNoRotate.x())
1163 KeyFromAxis (Aspect_VKey_NavLookUp, Aspect_VKey_NavLookDown, aTimeStamp, !my3dMouseToReverse.x() ? aRot3.x() : -aRot3.x());
1166 if (!my3dMouseNoRotate.y())
1168 KeyFromAxis (Aspect_VKey_NavRollCW, Aspect_VKey_NavRollCCW, aTimeStamp, !my3dMouseToReverse.y() ? aRot3.y() : -aRot3.y());
1171 if (!my3dMouseNoRotate.z())
1173 KeyFromAxis (Aspect_VKey_NavLookLeft, Aspect_VKey_NavLookRight, aTimeStamp, !my3dMouseToReverse.z() ? aRot3.z() : -aRot3.z());
1179 // =======================================================================
1180 // function : update3dMouseKeys
1182 // =======================================================================
1183 bool AIS_ViewController::update3dMouseKeys (const WNT_HIDSpaceMouse& theEvent)
1185 bool toUpdate = false;
1186 const double aTimeStamp = EventTime();
1187 if (theEvent.IsKeyState())
1189 const uint32_t aKeyState = theEvent.KeyState();
1190 for (unsigned short aKeyBit = 0; aKeyBit < 32; ++aKeyBit)
1192 const bool isPressed = (aKeyState & (1 << aKeyBit)) != 0;
1193 const bool isReleased = my3dMouseButtonState[aKeyBit] && !isPressed;
1194 //const bool isRepeated = my3dMouseButtonState[aKeyBit] && isPressed;
1195 my3dMouseButtonState[aKeyBit] = isPressed;
1196 if (!isReleased && !isPressed)
1201 const Aspect_VKey aVKey = theEvent.HidToSpaceKey (aKeyBit);
1202 if (aVKey != Aspect_VKey_UNKNOWN)
1207 KeyDown (aVKey, aTimeStamp);
1211 KeyUp (aVKey, aTimeStamp);
1219 // =======================================================================
1220 // function : SetNavigationMode
1222 // =======================================================================
1223 void AIS_ViewController::SetNavigationMode (AIS_NavigationMode theMode)
1225 myNavigationMode = theMode;
1228 myUI.OrbitRotation.ToStart = false;
1229 myUI.OrbitRotation.ToRotate = false;
1230 myUI.ViewRotation.ToStart = false;
1231 myUI.ViewRotation.ToRotate = false;
1234 // =======================================================================
1235 // function : KeyDown
1237 // =======================================================================
1238 void AIS_ViewController::KeyDown (Aspect_VKey theKey,
1242 myKeys.KeyDown (theKey, theTime, thePressure);
1245 // =======================================================================
1248 // =======================================================================
1249 void AIS_ViewController::KeyUp (Aspect_VKey theKey,
1252 myKeys.KeyUp (theKey, theTime);
1255 // =======================================================================
1256 // function : KeyFromAxis
1258 // =======================================================================
1259 void AIS_ViewController::KeyFromAxis (Aspect_VKey theNegative,
1260 Aspect_VKey thePositive,
1264 myKeys.KeyFromAxis (theNegative, thePositive, theTime, thePressure);
1267 // =======================================================================
1268 // function : FetchNavigationKeys
1270 // =======================================================================
1271 AIS_WalkDelta AIS_ViewController::FetchNavigationKeys (Standard_Real theCrouchRatio,
1272 Standard_Real theRunRatio)
1274 AIS_WalkDelta aWalk;
1277 double aPrevEventTime = 0.0, aNewEventTime = 0.0;
1278 updateEventsTime (aPrevEventTime, aNewEventTime);
1280 double aDuration = 0.0, aPressure = 1.0;
1281 if (Abs (myThrustSpeed) > gp::Resolution())
1285 aWalk[AIS_WalkTranslation_Forward].Value = myThrustSpeed * (aNewEventTime - aPrevEventTime);
1288 myToAskNextFrame = true;
1292 myHasThrust = false;
1295 aWalk.SetRunning (theRunRatio > 1.0
1296 && myKeys.IsKeyDown (Aspect_VKey_Shift));
1297 if (myKeys.HoldDuration (Aspect_VKey_NavJump, aNewEventTime, aDuration))
1299 myKeys.KeyUp (Aspect_VKey_NavJump, aNewEventTime);
1300 aWalk.SetJumping (true);
1302 if (!aWalk.IsJumping()
1303 && theCrouchRatio < 1.0
1304 && myKeys.HoldDuration (Aspect_VKey_NavCrouch, aNewEventTime, aDuration))
1306 aWalk.SetRunning (false);
1307 aWalk.SetCrouching (true);
1310 const double aMaxDuration = aNewEventTime - aPrevEventTime;
1311 const double aRunRatio = aWalk.IsRunning()
1313 : aWalk.IsCrouching()
1316 if (myKeys.HoldDuration (Aspect_VKey_NavForward, aNewEventTime, aDuration, aPressure))
1318 double aProgress = Abs (Min (aMaxDuration, aDuration));
1319 aProgress *= aRunRatio;
1320 aWalk[AIS_WalkTranslation_Forward].Value += aProgress;
1321 aWalk[AIS_WalkTranslation_Forward].Pressure = aPressure;
1322 aWalk[AIS_WalkTranslation_Forward].Duration = aDuration;
1324 if (myKeys.HoldDuration (Aspect_VKey_NavBackward, aNewEventTime, aDuration, aPressure))
1326 double aProgress = Abs (Min (aMaxDuration, aDuration));
1327 aProgress *= aRunRatio;
1328 aWalk[AIS_WalkTranslation_Forward].Value += -aProgress;
1329 aWalk[AIS_WalkTranslation_Forward].Pressure = aPressure;
1330 aWalk[AIS_WalkTranslation_Forward].Duration = aDuration;
1332 if (myKeys.HoldDuration (Aspect_VKey_NavSlideLeft, aNewEventTime, aDuration, aPressure))
1334 double aProgress = Abs (Min (aMaxDuration, aDuration));
1335 aProgress *= aRunRatio;
1336 aWalk[AIS_WalkTranslation_Side].Value = -aProgress;
1337 aWalk[AIS_WalkTranslation_Side].Pressure = aPressure;
1338 aWalk[AIS_WalkTranslation_Side].Duration = aDuration;
1340 if (myKeys.HoldDuration (Aspect_VKey_NavSlideRight, aNewEventTime, aDuration, aPressure))
1342 double aProgress = Abs (Min (aMaxDuration, aDuration));
1343 aProgress *= aRunRatio;
1344 aWalk[AIS_WalkTranslation_Side].Value = aProgress;
1345 aWalk[AIS_WalkTranslation_Side].Pressure = aPressure;
1346 aWalk[AIS_WalkTranslation_Side].Duration = aDuration;
1348 if (myKeys.HoldDuration (Aspect_VKey_NavLookLeft, aNewEventTime, aDuration, aPressure))
1350 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1351 aWalk[AIS_WalkRotation_Yaw].Value = aProgress;
1352 aWalk[AIS_WalkRotation_Yaw].Pressure = aPressure;
1353 aWalk[AIS_WalkRotation_Yaw].Duration = aDuration;
1355 if (myKeys.HoldDuration (Aspect_VKey_NavLookRight, aNewEventTime, aDuration, aPressure))
1357 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1358 aWalk[AIS_WalkRotation_Yaw].Value = -aProgress;
1359 aWalk[AIS_WalkRotation_Yaw].Pressure = aPressure;
1360 aWalk[AIS_WalkRotation_Yaw].Duration = aDuration;
1362 if (myKeys.HoldDuration (Aspect_VKey_NavLookUp, aNewEventTime, aDuration, aPressure))
1364 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1365 aWalk[AIS_WalkRotation_Pitch].Value = !myToInvertPitch ? -aProgress : aProgress;
1366 aWalk[AIS_WalkRotation_Pitch].Pressure = aPressure;
1367 aWalk[AIS_WalkRotation_Pitch].Duration = aDuration;
1369 if (myKeys.HoldDuration (Aspect_VKey_NavLookDown, aNewEventTime, aDuration, aPressure))
1371 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1372 aWalk[AIS_WalkRotation_Pitch].Value = !myToInvertPitch ? aProgress : -aProgress;
1373 aWalk[AIS_WalkRotation_Pitch].Pressure = aPressure;
1374 aWalk[AIS_WalkRotation_Pitch].Duration = aDuration;
1376 if (myKeys.HoldDuration (Aspect_VKey_NavRollCCW, aNewEventTime, aDuration, aPressure))
1378 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1379 aWalk[AIS_WalkRotation_Roll].Value = -aProgress;
1380 aWalk[AIS_WalkRotation_Roll].Pressure = aPressure;
1381 aWalk[AIS_WalkRotation_Roll].Duration = aDuration;
1383 if (myKeys.HoldDuration (Aspect_VKey_NavRollCW, aNewEventTime, aDuration, aPressure))
1385 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1386 aWalk[AIS_WalkRotation_Roll].Value = aProgress;
1387 aWalk[AIS_WalkRotation_Roll].Pressure = aPressure;
1388 aWalk[AIS_WalkRotation_Roll].Duration = aDuration;
1390 if (myKeys.HoldDuration (Aspect_VKey_NavSlideUp, aNewEventTime, aDuration, aPressure))
1392 double aProgress = Abs (Min (aMaxDuration, aDuration));
1393 aWalk[AIS_WalkTranslation_Up].Value = aProgress;
1394 aWalk[AIS_WalkTranslation_Up].Pressure = aPressure;
1395 aWalk[AIS_WalkTranslation_Up].Duration = aDuration;
1397 if (myKeys.HoldDuration (Aspect_VKey_NavSlideDown, aNewEventTime, aDuration, aPressure))
1399 double aProgress = Abs (Min (aMaxDuration, aDuration));
1400 aWalk[AIS_WalkTranslation_Up].Value = -aProgress;
1401 aWalk[AIS_WalkTranslation_Up].Pressure = aPressure;
1402 aWalk[AIS_WalkTranslation_Up].Duration = aDuration;
1407 // =======================================================================
1408 // function : AbortViewAnimation
1410 // =======================================================================
1411 void AIS_ViewController::AbortViewAnimation()
1413 if (!myViewAnimation.IsNull()
1414 && !myViewAnimation->IsStopped())
1416 myViewAnimation->Stop();
1417 myViewAnimation->SetView (Handle(V3d_View)());
1421 // =======================================================================
1422 // function : handlePanning
1424 // =======================================================================
1425 void AIS_ViewController::handlePanning (const Handle(V3d_View)& theView)
1427 if (!myGL.Panning.ToPan
1428 || !myToAllowPanning)
1433 AbortViewAnimation();
1435 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1436 if (aCam->IsOrthographic()
1437 || !hasPanningAnchorPoint())
1439 theView->Pan (myGL.Panning.Delta.x(), myGL.Panning.Delta.y());
1440 theView->Invalidate();
1441 theView->View()->SynchronizeXRPosedToBaseCamera();
1445 Graphic3d_Vec2i aWinSize;
1446 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1448 const gp_Dir& aDir = aCam->Direction();
1449 const gp_Ax3 aCameraCS (aCam->Center(), aDir.Reversed(), aDir ^ aCam->Up());
1450 const gp_XYZ anEyeToPnt = myPanPnt3d.XYZ() - aCam->Eye().XYZ();
1451 const gp_Pnt aViewDims = aCam->ViewDimensions (anEyeToPnt.Dot (aCam->Direction().XYZ())); // view dimensions at 3D point
1452 const Graphic3d_Vec2d aDxy (-aViewDims.X() * myGL.Panning.Delta.x() / double(aWinSize.x()),
1453 -aViewDims.X() * myGL.Panning.Delta.y() / double(aWinSize.x()));
1455 //theView->Translate (aCam, aDxy.x(), aDxy.y());
1457 const gp_Vec aCameraPan = gp_Vec (aCameraCS.XDirection()) * aDxy.x()
1458 + gp_Vec (aCameraCS.YDirection()) * aDxy.y();
1459 aPanTrsf.SetTranslation (aCameraPan);
1460 aCam->Transform (aPanTrsf);
1461 theView->Invalidate();
1462 theView->View()->SynchronizeXRPosedToBaseCamera();
1465 // =======================================================================
1466 // function : handleZRotate
1468 // =======================================================================
1469 void AIS_ViewController::handleZRotate (const Handle(V3d_View)& theView)
1471 if (!myGL.ZRotate.ToRotate
1472 || !myToAllowRotation)
1477 AbortViewAnimation();
1479 Graphic3d_Vec2i aViewPort;
1480 theView->Window()->Size (aViewPort.x(), aViewPort.y());
1481 Graphic3d_Vec2d aRotPnt (0.99 * aViewPort.x(),
1482 0.5 * aViewPort.y());
1483 theView->StartRotation (int(aRotPnt.x()), int(aRotPnt.y()), 0.4);
1484 aRotPnt.y() += myGL.ZRotate.Angle * aViewPort.y();
1485 theView->Rotation (int(aRotPnt.x()), int(aRotPnt.y()));
1486 theView->Invalidate();
1487 theView->View()->SynchronizeXRPosedToBaseCamera();
1490 // =======================================================================
1491 // function : handleZoom
1493 // =======================================================================
1494 void AIS_ViewController::handleZoom (const Handle(V3d_View)& theView,
1495 const Aspect_ScrollDelta& theParams,
1496 const gp_Pnt* thePnt)
1498 if (!myToAllowZooming)
1503 AbortViewAnimation();
1505 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1508 const double aViewDist = Max (myMinCamDistance, (thePnt->XYZ() - aCam->Eye().XYZ()).Modulus());
1509 aCam->SetCenter (aCam->Eye().XYZ() + aCam->Direction().XYZ() * aViewDist);
1512 if (!theParams.HasPoint())
1514 Standard_Real aCoeff = Abs(theParams.Delta) / 100.0 + 1.0;
1515 aCoeff = theParams.Delta > 0.0 ? aCoeff : 1.0 / aCoeff;
1516 theView->SetZoom (aCoeff, true);
1517 theView->Invalidate();
1518 theView->View()->SynchronizeXRPosedToBaseCamera();
1522 // integer delta is too rough for small smooth increments
1523 //theView->StartZoomAtPoint (theParams.Point.x(), theParams.Point.y());
1524 //theView->ZoomAtPoint (0, 0, (int )theParams.Delta, (int )theParams.Delta);
1526 double aDZoom = Abs (theParams.Delta) / 100.0 + 1.0;
1527 aDZoom = (theParams.Delta > 0.0) ? aDZoom : 1.0 / aDZoom;
1533 const Graphic3d_Vec2d aViewDims (aCam->ViewDimensions().X(), aCam->ViewDimensions().Y());
1535 // ensure that zoom will not be too small or too big
1536 double aCoef = aDZoom;
1537 if (aViewDims.x() < aCoef * Precision::Confusion())
1539 aCoef = aViewDims.x() / Precision::Confusion();
1541 else if (aViewDims.x() > aCoef * 1e12)
1543 aCoef = aViewDims.x() / 1e12;
1545 if (aViewDims.y() < aCoef * Precision::Confusion())
1547 aCoef = aViewDims.y() / Precision::Confusion();
1549 else if (aViewDims.y() > aCoef * 1e12)
1551 aCoef = aViewDims.y() / 1e12;
1554 Graphic3d_Vec2d aZoomAtPointXYv (0.0, 0.0);
1555 theView->Convert (theParams.Point.x(), theParams.Point.y(),
1556 aZoomAtPointXYv.x(), aZoomAtPointXYv.y());
1557 Graphic3d_Vec2d aDxy = aZoomAtPointXYv / aCoef;
1558 aCam->SetScale (aCam->Scale() / aCoef);
1560 const gp_Dir& aDir = aCam->Direction();
1561 const gp_Ax3 aCameraCS (aCam->Center(), aDir.Reversed(), aDir ^ aCam->Up());
1563 // pan back to the point
1564 aDxy = aZoomAtPointXYv - aDxy;
1567 // zoom at 3D point with perspective projection
1568 const gp_XYZ anEyeToPnt = thePnt->XYZ() - aCam->Eye().XYZ();
1569 aDxy.SetValues (anEyeToPnt.Dot (aCameraCS.XDirection().XYZ()),
1570 anEyeToPnt.Dot (aCameraCS.YDirection().XYZ()));
1572 // view dimensions at 3D point
1573 const gp_Pnt aViewDims1 = aCam->ViewDimensions (anEyeToPnt.Dot (aCam->Direction().XYZ()));
1575 Graphic3d_Vec2i aWinSize;
1576 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1577 const Graphic3d_Vec2d aPanFromCenterPx (double(theParams.Point.x()) - 0.5 * double(aWinSize.x()),
1578 double(aWinSize.y() - theParams.Point.y() - 1) - 0.5 * double(aWinSize.y()));
1579 aDxy.x() += -aViewDims1.X() * aPanFromCenterPx.x() / double(aWinSize.x());
1580 aDxy.y() += -aViewDims1.Y() * aPanFromCenterPx.y() / double(aWinSize.y());
1583 //theView->Translate (aCam, aDxy.x(), aDxy.y());
1585 const gp_Vec aCameraPan = gp_Vec (aCameraCS.XDirection()) * aDxy.x()
1586 + gp_Vec (aCameraCS.YDirection()) * aDxy.y();
1587 aPanTrsf.SetTranslation (aCameraPan);
1588 aCam->Transform (aPanTrsf);
1589 theView->Invalidate();
1590 theView->View()->SynchronizeXRPosedToBaseCamera();
1593 // =======================================================================
1594 // function : handleZFocusScroll
1596 // =======================================================================
1597 void AIS_ViewController::handleZFocusScroll (const Handle(V3d_View)& theView,
1598 const Aspect_ScrollDelta& theParams)
1600 if (!myToAllowZFocus
1601 || !theView->Camera()->IsStereo())
1606 Standard_Real aFocus = theView->Camera()->ZFocus() + (theParams.Delta > 0.0 ? 0.05 : -0.05);
1610 theView->Camera()->SetZFocus (theView->Camera()->ZFocusType(), aFocus);
1611 theView->Invalidate();
1615 // =======================================================================
1616 // function : handleOrbitRotation
1618 // =======================================================================
1619 void AIS_ViewController::handleOrbitRotation (const Handle(V3d_View)& theView,
1620 const gp_Pnt& thePnt,
1623 if (!myToAllowRotation)
1628 const Handle(Graphic3d_Camera)& aCam = theView->View()->IsActiveXR()
1629 ? theView->View()->BaseXRCamera()
1630 : theView->Camera();
1631 if (myGL.OrbitRotation.ToStart)
1633 // default alternatives
1634 //if (myRotationMode == AIS_RotationMode_BndBoxActive) theView->StartRotation (myGL.RotateAtPoint.x(), myGL.RotateAtPoint.y());
1635 //theView->Rotate (0.0, 0.0, 0.0, thePnt.X(), thePnt.Y(), thePnt.Z(), true);
1637 myRotatePnt3d = thePnt;
1638 myCamStartOpUp = aCam->Up();
1639 myCamStartOpDir = aCam->Direction();
1640 myCamStartOpEye = aCam->Eye();
1641 myCamStartOpCenter = aCam->Center();
1644 aTrsf.SetTransformation (gp_Ax3 (myRotatePnt3d, aCam->OrthogonalizedUp(), aCam->Direction()),
1645 gp_Ax3 (myRotatePnt3d, gp::DZ(), gp::DX()));
1646 const gp_Quaternion aRot = aTrsf.GetRotation();
1647 aRot.GetEulerAngles (gp_YawPitchRoll, myRotateStartYawPitchRoll[0], myRotateStartYawPitchRoll[1], myRotateStartYawPitchRoll[2]);
1650 myCamStartOpToEye = gp_Vec (myRotatePnt3d, aCam->Eye()).Transformed (aTrsf);
1651 myCamStartOpToCenter = gp_Vec (myRotatePnt3d, aCam->Center()).Transformed (aTrsf);
1653 theView->Invalidate();
1656 if (!myGL.OrbitRotation.ToRotate)
1661 AbortViewAnimation();
1664 // amend camera to exclude roll angle (put camera Up vector to plane containing global Z and view direction)
1665 Graphic3d_Vec2i aWinXY;
1666 theView->Window()->Size (aWinXY.x(), aWinXY.y());
1667 double aYawAngleDelta = ((myGL.OrbitRotation.PointStart.x() - myGL.OrbitRotation.PointTo.x()) / double (aWinXY.x())) * (M_PI * 0.5);
1668 double aPitchAngleDelta = -((myGL.OrbitRotation.PointStart.y() - myGL.OrbitRotation.PointTo.y()) / double (aWinXY.y())) * (M_PI * 0.5);
1669 double aPitchAngleNew = 0.0, aRoll = 0.0;
1670 const double aYawAngleNew = myRotateStartYawPitchRoll[0] + aYawAngleDelta;
1671 if (!theView->View()->IsActiveXR())
1673 aPitchAngleNew = Max (Min (myRotateStartYawPitchRoll[1] + aPitchAngleDelta, M_PI * 0.5 - M_PI / 180.0), -M_PI * 0.5 + M_PI / 180.0);
1678 aRot.SetEulerAngles (gp_YawPitchRoll, aYawAngleNew, aPitchAngleNew, aRoll);
1680 aTrsfRot.SetRotation (aRot);
1682 const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot);
1683 aCam->SetUp (aNewUp);
1684 aCam->SetEyeAndCenter (myRotatePnt3d.XYZ() + myCamStartOpToEye .Transformed (aTrsfRot).XYZ(),
1685 myRotatePnt3d.XYZ() + myCamStartOpToCenter.Transformed (aTrsfRot).XYZ());
1687 aCam->OrthogonalizeUp();
1691 // default alternatives
1692 //if (myRotationMode == AIS_RotationMode_BndBoxActive) theView->Rotation (myGL.RotateToPoint.x(), myGL.RotateToPoint.y());
1693 //theView->Rotate (aDX, aDY, aDZ, myRotatePnt3d.X(), myRotatePnt3d.Y(), myRotatePnt3d.Z(), false);
1695 // restore previous camera state
1696 aCam->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
1697 aCam->SetUp (myCamStartOpUp);
1698 aCam->SetDirectionFromEye (myCamStartOpDir);
1700 Graphic3d_Vec2d aWinXY;
1701 theView->Size (aWinXY.x(), aWinXY.y());
1702 const Standard_Real rx = (Standard_Real )theView->Convert (aWinXY.x());
1703 const Standard_Real ry = (Standard_Real )theView->Convert (aWinXY.y());
1705 const double THE_2PI = M_PI * 2.0;
1706 double aDX = (myGL.OrbitRotation.PointTo.x() - myGL.OrbitRotation.PointStart.x()) * M_PI / rx;
1707 double aDY = (myGL.OrbitRotation.PointStart.y() - myGL.OrbitRotation.PointTo.y()) * M_PI / ry;
1709 if (aDX > 0.0) { while (aDX > THE_2PI) { aDX -= THE_2PI; } }
1710 else if(aDX < 0.0) { while (aDX < -THE_2PI) { aDX += THE_2PI; } }
1711 if (aDY > 0.0) { while (aDY > THE_2PI) { aDY -= THE_2PI; } }
1712 else if(aDY < 0.0) { while (aDY < -THE_2PI) { aDY += THE_2PI; } }
1714 // rotate camera around 3 initial axes
1715 gp_Dir aCamDir (aCam->Direction().Reversed());
1716 gp_Dir aCamUp (aCam->Up());
1717 gp_Dir aCamSide(aCamUp.Crossed (aCamDir));
1719 gp_Trsf aRot[2], aTrsf;
1720 aRot[0].SetRotation (gp_Ax1 (myRotatePnt3d, aCamUp), -aDX);
1721 aRot[1].SetRotation (gp_Ax1 (myRotatePnt3d, aCamSide), aDY);
1722 aTrsf.Multiply (aRot[0]);
1723 aTrsf.Multiply (aRot[1]);
1725 aCam->Transform (aTrsf);
1728 theView->Invalidate();
1729 theView->View()->SynchronizeXRBaseToPosedCamera();
1732 // =======================================================================
1733 // function : handleViewRotation
1735 // =======================================================================
1736 void AIS_ViewController::handleViewRotation (const Handle(V3d_View)& theView,
1738 double thePitchExtra,
1740 bool theToRestartOnIncrement)
1742 if (!myToAllowRotation)
1747 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1748 const bool toRotateAnyway = Abs (theYawExtra) > gp::Resolution()
1749 || Abs (thePitchExtra) > gp::Resolution()
1750 || Abs (theRoll - myRotateStartYawPitchRoll[2]) > gp::Resolution();
1752 && theToRestartOnIncrement)
1754 myGL.ViewRotation.ToStart = true;
1755 myGL.ViewRotation.PointTo = myGL.ViewRotation.PointStart;
1757 if (myGL.ViewRotation.ToStart)
1760 aTrsf.SetTransformation (gp_Ax3 (gp::Origin(), aCam->OrthogonalizedUp(), aCam->Direction()),
1761 gp_Ax3 (gp::Origin(), gp::DZ(), gp::DX()));
1762 const gp_Quaternion aRot = aTrsf.GetRotation();
1763 double aRollDummy = 0.0;
1764 aRot.GetEulerAngles (gp_YawPitchRoll, myRotateStartYawPitchRoll[0], myRotateStartYawPitchRoll[1], aRollDummy);
1768 myRotateStartYawPitchRoll[0] += theYawExtra;
1769 myRotateStartYawPitchRoll[1] += thePitchExtra;
1770 myRotateStartYawPitchRoll[2] = theRoll;
1771 myGL.ViewRotation.ToRotate = true;
1774 if (!myGL.ViewRotation.ToRotate)
1779 AbortViewAnimation();
1781 Graphic3d_Vec2i aWinXY;
1782 theView->Window()->Size (aWinXY.x(), aWinXY.y());
1783 double aYawAngleDelta = ((myGL.ViewRotation.PointStart.x() - myGL.ViewRotation.PointTo.x()) / double (aWinXY.x())) * (M_PI * 0.5);
1784 double aPitchAngleDelta = -((myGL.ViewRotation.PointStart.y() - myGL.ViewRotation.PointTo.y()) / double (aWinXY.y())) * (M_PI * 0.5);
1785 const double aPitchAngleNew = Max (Min (myRotateStartYawPitchRoll[1] + aPitchAngleDelta, M_PI * 0.5 - M_PI / 180.0), -M_PI * 0.5 + M_PI / 180.0);
1786 const double aYawAngleNew = myRotateStartYawPitchRoll[0] + aYawAngleDelta;
1788 aRot.SetEulerAngles (gp_YawPitchRoll, aYawAngleNew, aPitchAngleNew, theRoll);
1790 aTrsfRot.SetRotation (aRot);
1792 const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot);
1793 const gp_Dir aNewDir = gp::DX().Transformed (aTrsfRot);
1794 aCam->SetUp (aNewUp);
1795 aCam->SetDirectionFromEye (aNewDir);
1796 aCam->OrthogonalizeUp();
1797 theView->Invalidate();
1800 // =======================================================================
1801 // function : PickPoint
1803 // =======================================================================
1804 bool AIS_ViewController::PickPoint (gp_Pnt& thePnt,
1805 const Handle(AIS_InteractiveContext)& theCtx,
1806 const Handle(V3d_View)& theView,
1807 const Graphic3d_Vec2i& theCursor,
1808 bool theToStickToPickRay)
1810 ResetPreviousMoveTo();
1812 const Handle(StdSelect_ViewerSelector3d)& aSelector = theCtx->MainSelector();
1813 aSelector->Pick (theCursor.x(), theCursor.y(), theView);
1814 if (aSelector->NbPicked() < 1)
1819 const SelectMgr_SortCriterion& aPicked = aSelector->PickedData (1);
1820 if (theToStickToPickRay
1821 && !Precision::IsInfinite (aPicked.Depth))
1823 thePnt = aSelector->GetManager().DetectedPoint (aPicked.Depth);
1827 thePnt = aSelector->PickedPoint (1);
1829 return !Precision::IsInfinite (thePnt.X())
1830 && !Precision::IsInfinite (thePnt.Y())
1831 && !Precision::IsInfinite (thePnt.Z());
1834 // =======================================================================
1835 // function : GravityPoint
1837 // =======================================================================
1838 gp_Pnt AIS_ViewController::GravityPoint (const Handle(AIS_InteractiveContext)& theCtx,
1839 const Handle(V3d_View)& theView)
1841 switch (myRotationMode)
1843 case AIS_RotationMode_PickLast:
1844 case AIS_RotationMode_PickCenter:
1846 Graphic3d_Vec2i aCursor ((int )myGL.OrbitRotation.PointStart.x(), (int )myGL.OrbitRotation.PointStart.y());
1847 if (myRotationMode == AIS_RotationMode_PickCenter)
1849 Graphic3d_Vec2i aViewPort;
1850 theView->Window()->Size (aViewPort.x(), aViewPort.y());
1851 aCursor = aViewPort / 2;
1855 if (PickPoint (aPnt, theCtx, theView, aCursor, myToStickToRayOnRotation))
1861 case AIS_RotationMode_CameraAt:
1863 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1864 return aCam->Center();
1866 case AIS_RotationMode_BndBoxScene:
1868 Bnd_Box aBndBox = theView->View()->MinMaxValues (false);
1869 if (!aBndBox.IsVoid())
1871 return (aBndBox.CornerMin().XYZ() + aBndBox.CornerMax().XYZ()) * 0.5;
1875 case AIS_RotationMode_BndBoxActive:
1879 return theCtx ->GravityPoint (theView);
1882 // =======================================================================
1883 // function : FitAllAuto
1885 // =======================================================================
1886 void AIS_ViewController::FitAllAuto (const Handle(AIS_InteractiveContext)& theCtx,
1887 const Handle(V3d_View)& theView)
1889 const Bnd_Box aBoxSel = theCtx->BoundingBoxOfSelection();
1890 const double aFitMargin = 0.01;
1891 if (aBoxSel.IsVoid())
1893 theView->FitAll (aFitMargin, false);
1897 // fit all algorithm is not 100% stable - so compute some precision to compare equal camera values
1898 const double aFitTol = (aBoxSel.CornerMax().XYZ() - aBoxSel.CornerMin().XYZ()).Modulus() * 0.000001;
1899 const Bnd_Box aBoxAll = theView->View()->MinMaxValues();
1901 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1902 Handle(Graphic3d_Camera) aCameraSel = new Graphic3d_Camera (aCam);
1903 Handle(Graphic3d_Camera) aCameraAll = new Graphic3d_Camera (aCam);
1904 theView->FitMinMax (aCameraSel, aBoxSel, aFitMargin);
1905 theView->FitMinMax (aCameraAll, aBoxAll, aFitMargin);
1906 if (aCameraSel->Center().IsEqual (aCam->Center(), aFitTol)
1907 && Abs (aCameraSel->Scale() - aCam->Scale()) < aFitTol
1908 && Abs (aCameraSel->Distance() - aCam->Distance()) < aFitTol)
1910 // fit all entire view on second FitALL request
1911 aCam->Copy (aCameraAll);
1915 aCam->Copy (aCameraSel);
1919 // =======================================================================
1920 // function : handleViewOrientationKeys
1922 // =======================================================================
1923 void AIS_ViewController::handleViewOrientationKeys (const Handle(AIS_InteractiveContext)& theCtx,
1924 const Handle(V3d_View)& theView)
1926 if (myNavigationMode == AIS_NavigationMode_FirstPersonWalk)
1931 Handle(Graphic3d_Camera) aCameraBack;
1932 struct ViewKeyAction
1935 V3d_TypeOfOrientation Orientation;
1937 static const ViewKeyAction THE_VIEW_KEYS[] =
1939 { Aspect_VKey_ViewTop, V3d_TypeOfOrientation_Zup_Top },
1940 { Aspect_VKey_ViewBottom, V3d_TypeOfOrientation_Zup_Bottom },
1941 { Aspect_VKey_ViewLeft, V3d_TypeOfOrientation_Zup_Left },
1942 { Aspect_VKey_ViewRight, V3d_TypeOfOrientation_Zup_Right },
1943 { Aspect_VKey_ViewFront, V3d_TypeOfOrientation_Zup_Front },
1944 { Aspect_VKey_ViewBack, V3d_TypeOfOrientation_Zup_Back },
1945 { Aspect_VKey_ViewAxoLeftProj, V3d_TypeOfOrientation_Zup_AxoLeft },
1946 { Aspect_VKey_ViewAxoRightProj, V3d_TypeOfOrientation_Zup_AxoRight },
1947 { Aspect_VKey_ViewRoll90CW, (V3d_TypeOfOrientation )-1},
1948 { Aspect_VKey_ViewRoll90CCW, (V3d_TypeOfOrientation )-1},
1949 { Aspect_VKey_ViewFitAll, (V3d_TypeOfOrientation )-1}
1952 Standard_Mutex::Sentry aLock (myKeys.Mutex());
1953 const size_t aNbKeys = sizeof(THE_VIEW_KEYS) / sizeof(*THE_VIEW_KEYS);
1954 const double anEventTime = EventTime();
1955 for (size_t aKeyIter = 0; aKeyIter < aNbKeys; ++aKeyIter)
1957 const ViewKeyAction& aKeyAction = THE_VIEW_KEYS[aKeyIter];
1958 if (!myKeys.IsKeyDown (aKeyAction.Key))
1963 myKeys.KeyUp (aKeyAction.Key, anEventTime);
1964 if (aCameraBack.IsNull())
1966 aCameraBack = theView->Camera();
1967 theView->SetCamera (new Graphic3d_Camera (aCameraBack));
1969 if (aKeyAction.Orientation != (V3d_TypeOfOrientation )-1)
1971 theView->SetProj (aKeyAction.Orientation);
1972 FitAllAuto (theCtx, theView);
1974 else if (aKeyAction.Key == Aspect_VKey_ViewRoll90CW)
1976 const double aTwist = theView->Twist() + M_PI / 2.0;
1977 theView->SetTwist (aTwist);
1979 else if (aKeyAction.Key == Aspect_VKey_ViewRoll90CCW)
1981 const double aTwist = theView->Twist() - M_PI / 2.0;
1982 theView->SetTwist (aTwist);
1984 else if (aKeyAction.Key == Aspect_VKey_ViewFitAll)
1986 FitAllAuto (theCtx, theView);
1991 if (aCameraBack.IsNull())
1996 Handle(Graphic3d_Camera) aCameraNew = theView->Camera();
1997 theView->SetCamera (aCameraBack);
1998 const Graphic3d_Mat4d anOrientMat1 = aCameraBack->OrientationMatrix();
1999 const Graphic3d_Mat4d anOrientMat2 = aCameraNew ->OrientationMatrix();
2000 if (anOrientMat1 != anOrientMat2)
2002 const Handle(AIS_AnimationCamera)& aCamAnim = myViewAnimation;
2003 aCamAnim->SetView (theView);
2004 aCamAnim->SetStartPts (0.0);
2005 aCamAnim->SetCameraStart (new Graphic3d_Camera (aCameraBack));
2006 aCamAnim->SetCameraEnd (new Graphic3d_Camera (aCameraNew));
2007 aCamAnim->StartTimer (0.0, 1.0, true, false);
2011 // =======================================================================
2012 // function : handleNavigationKeys
2014 // =======================================================================
2015 AIS_WalkDelta AIS_ViewController::handleNavigationKeys (const Handle(AIS_InteractiveContext)& ,
2016 const Handle(V3d_View)& theView)
2019 double aCrouchRatio = 1.0, aRunRatio = 1.0;
2020 if (myNavigationMode == AIS_NavigationMode_FirstPersonFlight)
2025 const double aRotSpeed = 0.5;
2026 const double aWalkSpeedCoef = WalkSpeedRelative();
2027 AIS_WalkDelta aWalk = FetchNavigationKeys (aCrouchRatio, aRunRatio);
2028 if (aWalk.IsJumping())
2032 theView->Invalidate();
2034 if (aWalk.IsEmpty())
2038 else if (myGL.OrbitRotation.ToRotate
2039 || myGL.OrbitRotation.ToStart)
2045 const Bnd_Box aBndBox = theView->View()->MinMaxValues();
2046 if (!aBndBox.IsVoid())
2048 aMin = aBndBox.CornerMin().XYZ();
2049 aMax = aBndBox.CornerMax().XYZ();
2051 double aBndDiam = Max (Max (aMax.X() - aMin.X(), aMax.Y() - aMin.Y()), aMax.Z() - aMin.Z());
2052 if (aBndDiam <= gp::Resolution())
2057 const double aWalkSpeed = myNavigationMode != AIS_NavigationMode_Orbit
2058 && myNavigationMode != AIS_NavigationMode_FirstPersonFlight
2059 ? theView->View()->UnitFactor() * WalkSpeedAbsolute()
2060 : aWalkSpeedCoef * aBndDiam;
2061 const Handle(Graphic3d_Camera)& aCam = theView->View()->IsActiveXR()
2062 ? theView->View()->BaseXRCamera()
2063 : theView->Camera();
2065 // move forward in plane XY and up along Z
2066 const gp_Dir anUp = ToLockOrbitZUp() ? gp::DZ() : aCam->OrthogonalizedUp();
2068 && myToAllowPanning)
2070 const gp_Vec aSide = -aCam->SideRight();
2071 gp_XYZ aFwd = aCam->Direction().XYZ();
2072 aFwd -= anUp.XYZ() * (anUp.XYZ() * aFwd);
2075 if (!aWalk[AIS_WalkTranslation_Forward].IsEmpty())
2077 if (!aCam->IsOrthographic())
2079 aMoveVec += aFwd * aWalk[AIS_WalkTranslation_Forward].Value * aWalk[AIS_WalkTranslation_Forward].Pressure * aWalkSpeed;
2082 if (!aWalk[AIS_WalkTranslation_Side].IsEmpty())
2084 aMoveVec += aSide.XYZ() * aWalk[AIS_WalkTranslation_Side].Value * aWalk[AIS_WalkTranslation_Side].Pressure * aWalkSpeed;
2086 if (!aWalk[AIS_WalkTranslation_Up].IsEmpty())
2088 aMoveVec += anUp.XYZ() * aWalk[AIS_WalkTranslation_Up].Value * aWalk[AIS_WalkTranslation_Up].Pressure * aWalkSpeed;
2091 if (aCam->IsOrthographic())
2093 if (!aWalk[AIS_WalkTranslation_Forward].IsEmpty())
2095 const double aZoomDelta = aWalk[AIS_WalkTranslation_Forward].Value * aWalk[AIS_WalkTranslation_Forward].Pressure * aWalkSpeedCoef;
2096 handleZoom (theView, Aspect_ScrollDelta (aZoomDelta * 100.0), NULL);
2100 gp_Trsf aTrsfTranslate;
2101 aTrsfTranslate.SetTranslation (aMoveVec);
2102 aCam->Transform (aTrsfTranslate);
2106 if (myNavigationMode == AIS_NavigationMode_Orbit
2107 && myToAllowRotation)
2109 if (!aWalk[AIS_WalkRotation_Yaw].IsEmpty())
2112 aTrsfRot.SetRotation (gp_Ax1 (aCam->Eye(), anUp), aWalk[AIS_WalkRotation_Yaw].Value * aRotSpeed);
2113 aCam->Transform (aTrsfRot);
2115 if (!aWalk[AIS_WalkRotation_Pitch].IsEmpty())
2117 const gp_Vec aSide = -aCam->SideRight();
2119 aTrsfRot.SetRotation (gp_Ax1 (aCam->Eye(), aSide), -aWalk[AIS_WalkRotation_Pitch].Value * aRotSpeed);
2120 aCam->Transform (aTrsfRot);
2122 if (!aWalk[AIS_WalkRotation_Roll].IsEmpty()
2123 && !ToLockOrbitZUp())
2126 aTrsfRot.SetRotation (gp_Ax1 (aCam->Center(), aCam->Direction()), aWalk[AIS_WalkRotation_Roll].Value * aRotSpeed);
2127 aCam->Transform (aTrsfRot);
2133 theView->Invalidate();
2134 theView->View()->SynchronizeXRBaseToPosedCamera();
2138 // =======================================================================
2139 // function : handleCameraActions
2141 // =======================================================================
2142 void AIS_ViewController::handleCameraActions (const Handle(AIS_InteractiveContext)& theCtx,
2143 const Handle(V3d_View)& theView,
2144 const AIS_WalkDelta& theWalk)
2146 // apply view actions
2147 if (myGL.Orientation.ToSetViewOrient)
2149 theView->SetProj (myGL.Orientation.ViewOrient);
2150 myGL.Orientation.ToFitAll = true;
2154 if (myGL.Orientation.ToFitAll)
2156 const double aFitMargin = 0.01;
2157 theView->FitAll (aFitMargin, false);
2158 theView->Invalidate();
2159 myGL.Orientation.ToFitAll = false;
2162 if (myGL.IsNewGesture)
2164 if (myAnchorPointPrs1->HasInteractiveContext())
2166 theCtx->Remove (myAnchorPointPrs1, false);
2167 if (!theView->Viewer()->ZLayerSettings (myAnchorPointPrs1->ZLayer()).IsImmediate())
2169 theView->Invalidate();
2173 theView->InvalidateImmediate();
2176 if (myAnchorPointPrs2->HasInteractiveContext())
2178 theCtx->Remove (myAnchorPointPrs2, false);
2179 if (!theView->Viewer()->ZLayerSettings (myAnchorPointPrs2->ZLayer()).IsImmediate())
2181 theView->Invalidate();
2185 theView->InvalidateImmediate();
2189 if (myHasHlrOnBeforeRotation)
2191 myHasHlrOnBeforeRotation = false;
2192 theView->SetComputedMode (true);
2193 theView->Invalidate();
2197 if (myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
2199 if (myGL.Panning.ToStart
2200 && myToAllowPanning)
2202 gp_Pnt aPanPnt (Precision::Infinite(), 0.0, 0.0);
2203 if (!theView->Camera()->IsOrthographic())
2205 bool toStickToRay = false;
2206 if (myGL.Panning.PointStart.x() >= 0
2207 && myGL.Panning.PointStart.y() >= 0)
2209 PickPoint (aPanPnt, theCtx, theView, myGL.Panning.PointStart, toStickToRay);
2211 if (Precision::IsInfinite (aPanPnt.X()))
2213 Graphic3d_Vec2i aWinSize;
2214 theView->Window()->Size (aWinSize.x(), aWinSize.y());
2215 PickPoint (aPanPnt, theCtx, theView, aWinSize / 2, toStickToRay);
2217 if (!Precision::IsInfinite (aPanPnt.X())
2218 && myToShowPanAnchorPoint)
2221 aPntTrsf.SetTranslation (gp_Vec (aPanPnt.XYZ()));
2222 theCtx->SetLocation (myAnchorPointPrs2, aPntTrsf);
2225 setPanningAnchorPoint (aPanPnt);
2228 if (myToShowPanAnchorPoint
2229 && hasPanningAnchorPoint()
2230 && myGL.Panning.ToPan
2231 && !myGL.IsNewGesture
2232 && !myAnchorPointPrs2->HasInteractiveContext())
2234 theCtx->Display (myAnchorPointPrs2, 0, -1, false, AIS_DS_Displayed);
2237 handlePanning (theView);
2238 handleZRotate (theView);
2241 if ((myNavigationMode == AIS_NavigationMode_Orbit
2242 || myGL.OrbitRotation.ToStart
2243 || myGL.OrbitRotation.ToRotate)
2244 && myToAllowRotation)
2246 if (myGL.OrbitRotation.ToStart
2247 && !myHasHlrOnBeforeRotation)
2249 myHasHlrOnBeforeRotation = theView->ComputedMode();
2250 if (myHasHlrOnBeforeRotation)
2252 theView->SetComputedMode (false);
2257 if (myGL.OrbitRotation.ToStart)
2259 aGravPnt = GravityPoint (theCtx, theView);
2260 if (myToShowRotateCenter)
2263 aPntTrsf.SetTranslation (gp_Vec (aGravPnt.XYZ()));
2264 theCtx->SetLocation (myAnchorPointPrs1, aPntTrsf);
2265 theCtx->SetLocation (myAnchorPointPrs2, aPntTrsf);
2269 if (myToShowRotateCenter
2270 && myGL.OrbitRotation.ToRotate
2271 && !myGL.IsNewGesture
2272 && !myAnchorPointPrs1->HasInteractiveContext())
2274 theCtx->Display (myAnchorPointPrs1, 0, -1, false, AIS_DS_Displayed);
2275 theCtx->Display (myAnchorPointPrs2, 0, -1, false, AIS_DS_Displayed);
2277 handleOrbitRotation (theView, aGravPnt,
2278 myToLockOrbitZUp || myNavigationMode != AIS_NavigationMode_Orbit);
2281 if ((myNavigationMode != AIS_NavigationMode_Orbit
2282 || myGL.ViewRotation.ToStart
2283 || myGL.ViewRotation.ToRotate)
2284 && myToAllowRotation)
2286 if (myGL.ViewRotation.ToStart
2287 && !myHasHlrOnBeforeRotation)
2289 myHasHlrOnBeforeRotation = theView->ComputedMode();
2290 if (myHasHlrOnBeforeRotation)
2292 theView->SetComputedMode (false);
2297 if (!theWalk[AIS_WalkRotation_Roll].IsEmpty()
2298 && !myToLockOrbitZUp)
2300 aRoll = (M_PI / 12.0) * theWalk[AIS_WalkRotation_Roll].Pressure;
2301 aRoll *= Min (1000.0 * theWalk[AIS_WalkRotation_Roll].Duration, 100.0) / 100.0;
2302 if (theWalk[AIS_WalkRotation_Roll].Value < 0.0)
2308 handleViewRotation (theView, theWalk[AIS_WalkRotation_Yaw].Value, theWalk[AIS_WalkRotation_Pitch].Value, aRoll,
2309 myNavigationMode == AIS_NavigationMode_FirstPersonFlight);
2312 if (!myGL.ZoomActions.IsEmpty())
2314 for (NCollection_Sequence<Aspect_ScrollDelta>::Iterator aZoomIter (myGL.ZoomActions); aZoomIter.More(); aZoomIter.Next())
2316 Aspect_ScrollDelta aZoomParams = aZoomIter.Value();
2318 && (aZoomParams.Flags & Aspect_VKeyFlags_CTRL) != 0
2319 && theView->Camera()->IsStereo())
2321 handleZFocusScroll (theView, aZoomParams);
2325 if (!myToAllowZooming)
2330 if (!theView->Camera()->IsOrthographic())
2333 if (aZoomParams.HasPoint()
2334 && PickPoint (aPnt, theCtx, theView, aZoomParams.Point, myToStickToRayOnZoom))
2336 handleZoom (theView, aZoomParams, &aPnt);
2340 Graphic3d_Vec2i aWinSize;
2341 theView->Window()->Size (aWinSize.x(), aWinSize.y());
2342 if (PickPoint (aPnt, theCtx, theView, aWinSize / 2, myToStickToRayOnZoom))
2344 aZoomParams.ResetPoint(); // do not pretend to zoom at 'nothing'
2345 handleZoom (theView, aZoomParams, &aPnt);
2349 handleZoom (theView, aZoomParams, NULL);
2351 myGL.ZoomActions.Clear();
2355 // =======================================================================
2356 // function : handleXRInput
2358 // =======================================================================
2359 void AIS_ViewController::handleXRInput (const Handle(AIS_InteractiveContext)& theCtx,
2360 const Handle(V3d_View)& theView,
2361 const AIS_WalkDelta& )
2363 theView->View()->ProcessXRInput();
2364 if (!theView->View()->IsActiveXR())
2368 if (myXRCameraTmp.IsNull())
2370 myXRCameraTmp = new Graphic3d_Camera();
2372 handleXRTurnPad (theCtx, theView);
2373 handleXRTeleport(theCtx, theView);
2374 handleXRPicking (theCtx, theView);
2377 // =======================================================================
2378 // function : handleXRTurnPad
2380 // =======================================================================
2381 void AIS_ViewController::handleXRTurnPad (const Handle(AIS_InteractiveContext)& ,
2382 const Handle(V3d_View)& theView)
2384 if (myXRTurnAngle <= 0.0
2385 || !theView->View()->IsActiveXR())
2390 // turn left/right at 45 degrees on left/right trackpad clicks
2391 for (int aHand = 0; aHand < 2; ++aHand)
2393 const Aspect_XRTrackedDeviceRole aRole = aHand == 0 ? Aspect_XRTrackedDeviceRole_RightHand : Aspect_XRTrackedDeviceRole_LeftHand;
2394 const Handle(Aspect_XRAction)& aPadClickAct = theView->View()->XRSession()->GenericAction (aRole, Aspect_XRGenericAction_InputTrackPadClick);
2395 const Handle(Aspect_XRAction)& aPadPosAct = theView->View()->XRSession()->GenericAction (aRole, Aspect_XRGenericAction_InputTrackPadPosition);
2396 if (aPadClickAct.IsNull()
2397 || aPadPosAct.IsNull())
2402 const Aspect_XRDigitalActionData aPadClick = theView->View()->XRSession()->GetDigitalActionData (aPadClickAct);
2403 const Aspect_XRAnalogActionData aPadPos = theView->View()->XRSession()->GetAnalogActionData (aPadPosAct);
2404 if (aPadClick.IsActive
2405 && aPadClick.IsPressed
2406 && aPadClick.IsChanged
2408 && Abs (aPadPos.VecXYZ.y()) < 0.5f
2409 && Abs (aPadPos.VecXYZ.x()) > 0.7f)
2412 aTrsfTurn.SetRotation (gp_Ax1 (gp::Origin(), theView->View()->BaseXRCamera()->Up()), aPadPos.VecXYZ.x() < 0.0f ? myXRTurnAngle : -myXRTurnAngle);
2413 theView->View()->TurnViewXRCamera (aTrsfTurn);
2419 // =======================================================================
2420 // function : handleXRTeleport
2422 // =======================================================================
2423 void AIS_ViewController::handleXRTeleport (const Handle(AIS_InteractiveContext)& theCtx,
2424 const Handle(V3d_View)& theView)
2426 if (!theView->View()->IsActiveXR())
2431 // teleport on forward trackpad unclicks
2432 const Aspect_XRTrackedDeviceRole aTeleOld = myXRLastTeleportHand;
2433 myXRLastTeleportHand = Aspect_XRTrackedDeviceRole_Other;
2434 for (int aHand = 0; aHand < 2; ++aHand)
2436 const Aspect_XRTrackedDeviceRole aRole = aHand == 0 ? Aspect_XRTrackedDeviceRole_RightHand : Aspect_XRTrackedDeviceRole_LeftHand;
2437 const Standard_Integer aDeviceId = theView->View()->XRSession()->NamedTrackedDevice (aRole);
2438 if (aDeviceId == -1)
2443 const Handle(Aspect_XRAction)& aPadClickAct = theView->View()->XRSession()->GenericAction (aRole, Aspect_XRGenericAction_InputTrackPadClick);
2444 const Handle(Aspect_XRAction)& aPadPosAct = theView->View()->XRSession()->GenericAction (aRole, Aspect_XRGenericAction_InputTrackPadPosition);
2445 if (aPadClickAct.IsNull()
2446 || aPadPosAct.IsNull())
2451 const Aspect_XRDigitalActionData aPadClick = theView->View()->XRSession()->GetDigitalActionData (aPadClickAct);
2452 const Aspect_XRAnalogActionData aPadPos = theView->View()->XRSession()->GetAnalogActionData (aPadPosAct);
2453 const bool isPressed = aPadClick.IsPressed;
2454 const bool isClicked = !aPadClick.IsPressed
2455 && aPadClick.IsChanged;
2456 if (aPadClick.IsActive
2457 && (isPressed || isClicked)
2459 && aPadPos.VecXYZ.y() > 0.6f
2460 && Abs (aPadPos.VecXYZ.x()) < 0.5f)
2462 const Aspect_TrackedDevicePose& aPose = theView->View()->XRSession()->TrackedPoses()[aDeviceId];
2463 if (!aPose.IsValidPose)
2468 myXRLastTeleportHand = aRole;
2469 Standard_Real& aPickDepth = aRole == Aspect_XRTrackedDeviceRole_LeftHand ? myXRLastPickDepthLeft : myXRLastPickDepthRight;
2470 aPickDepth = Precision::Infinite();
2471 Graphic3d_Vec3 aPickNorm;
2472 const gp_Trsf aHandBase = theView->View()->PoseXRToWorld (aPose.Orientation);
2473 const Standard_Real aHeadHeight = theView->View()->XRSession()->HeadPose().TranslationPart().Y();
2475 const Standard_Integer aPickedId = handleXRMoveTo (theCtx, theView, aPose.Orientation, false);
2478 const SelectMgr_SortCriterion& aPickedData = theCtx->MainSelector()->PickedData (aPickedId);
2479 aPickNorm = aPickedData.Normal;
2480 if (aPickNorm.SquareModulus() > ShortRealEpsilon())
2482 aPickDepth = aPickedData.Point.Distance (aHandBase.TranslationPart());
2488 myXRLastTeleportHand = Aspect_XRTrackedDeviceRole_Other;
2489 if (!Precision::IsInfinite (aPickDepth))
2491 const gp_Dir aTeleDir = -gp::DZ().Transformed (aHandBase);
2492 const gp_Dir anUpDir = theView->View()->BaseXRCamera()->Up();
2494 bool isHorizontal = false;
2495 gp_Dir aPickNormDir (aPickNorm.x(), aPickNorm.y(), aPickNorm.z());
2496 if (anUpDir.IsEqual ( aPickNormDir, M_PI_4)
2497 || anUpDir.IsEqual (-aPickNormDir, M_PI_4))
2499 isHorizontal = true;
2502 gp_Pnt aNewEye = aHandBase.TranslationPart();
2505 aNewEye = aHandBase.TranslationPart()
2506 + aTeleDir.XYZ() * aPickDepth
2507 + anUpDir.XYZ() * aHeadHeight;
2511 if (aPickNormDir.Dot (aTeleDir) < 0.0)
2513 aPickNormDir.Reverse();
2515 aNewEye = aHandBase.TranslationPart()
2516 + aTeleDir.XYZ() * aPickDepth
2517 - aPickNormDir.XYZ() * aHeadHeight / 4;
2520 theView->View()->PosedXRCamera()->MoveEyeTo (aNewEye);
2521 theView->View()->ComputeXRBaseCameraFromPosed (theView->View()->PosedXRCamera(), theView->View()->XRSession()->HeadPose());
2528 if (myXRLastTeleportHand != aTeleOld)
2530 if (aTeleOld != Aspect_XRTrackedDeviceRole_Other)
2532 if (const Handle(Aspect_XRAction)& aHaptic = theView->View()->XRSession()->GenericAction (aTeleOld, Aspect_XRGenericAction_OutputHaptic))
2534 theView->View()->XRSession()->AbortHapticVibrationAction (aHaptic);
2537 if (myXRLastTeleportHand != Aspect_XRTrackedDeviceRole_Other)
2539 if (const Handle(Aspect_XRAction)& aHaptic = theView->View()->XRSession()->GenericAction (myXRLastTeleportHand, Aspect_XRGenericAction_OutputHaptic))
2541 theView->View()->XRSession()->TriggerHapticVibrationAction (aHaptic, myXRTeleportHaptic);
2547 // =======================================================================
2548 // function : handleXRPicking
2550 // =======================================================================
2551 void AIS_ViewController::handleXRPicking (const Handle(AIS_InteractiveContext)& theCtx,
2552 const Handle(V3d_View)& theView)
2554 if (!theView->View()->IsActiveXR())
2559 // handle selection on trigger clicks
2560 Aspect_XRTrackedDeviceRole aPickDevOld = myXRLastPickingHand;
2561 myXRLastPickingHand = Aspect_XRTrackedDeviceRole_Other;
2562 for (int aHand = 0; aHand < 2; ++aHand)
2564 const Aspect_XRTrackedDeviceRole aRole = aHand == 0 ? Aspect_XRTrackedDeviceRole_RightHand : Aspect_XRTrackedDeviceRole_LeftHand;
2565 const Handle(Aspect_XRAction)& aTrigClickAct = theView->View()->XRSession()->GenericAction (aRole, Aspect_XRGenericAction_InputTriggerClick);
2566 const Handle(Aspect_XRAction)& aTrigPullAct = theView->View()->XRSession()->GenericAction (aRole, Aspect_XRGenericAction_InputTriggerPull);
2567 if (aTrigClickAct.IsNull()
2568 || aTrigPullAct.IsNull())
2573 const Aspect_XRDigitalActionData aTrigClick = theView->View()->XRSession()->GetDigitalActionData (aTrigClickAct);
2574 const Aspect_XRAnalogActionData aTrigPos = theView->View()->XRSession()->GetAnalogActionData (aTrigPullAct);
2575 if (aTrigPos.IsActive
2576 && Abs (aTrigPos.VecXYZ.x()) > 0.1f)
2578 myXRLastPickingHand = aRole;
2579 handleXRHighlight (theCtx, theView);
2580 if (aTrigClick.IsActive
2581 && aTrigClick.IsPressed
2582 && aTrigClick.IsChanged)
2584 theCtx->SelectDetected();
2585 OnSelectionChanged (theCtx, theView);
2586 if (const Handle(Aspect_XRAction)& aHaptic = theView->View()->XRSession()->GenericAction (myXRLastPickingHand, Aspect_XRGenericAction_OutputHaptic))
2588 theView->View()->XRSession()->TriggerHapticVibrationAction (aHaptic, myXRSelectHaptic);
2594 if (myXRLastPickingHand != aPickDevOld)
2596 theCtx->ClearDetected();
2600 // =======================================================================
2601 // function : OnSelectionChanged
2603 // =======================================================================
2604 void AIS_ViewController::OnSelectionChanged (const Handle(AIS_InteractiveContext)& ,
2605 const Handle(V3d_View)& )
2610 // =======================================================================
2611 // function : OnObjectDragged
2613 // =======================================================================
2614 void AIS_ViewController::OnObjectDragged (const Handle(AIS_InteractiveContext)& theCtx,
2615 const Handle(V3d_View)& theView,
2616 AIS_DragAction theAction)
2620 case AIS_DragAction_Start:
2622 myDragObject.Nullify();
2623 myDragOwner.Nullify();
2624 if (!theCtx->HasDetected())
2629 const Handle(SelectMgr_EntityOwner)& aDetectedOwner = theCtx->DetectedOwner();
2630 Handle(AIS_InteractiveObject) aDetectedPrs = Handle(AIS_InteractiveObject)::DownCast (aDetectedOwner->Selectable());
2632 if (aDetectedPrs->ProcessDragging (theCtx, theView, aDetectedOwner, myGL.Dragging.PointStart,
2633 myGL.Dragging.PointTo, theAction))
2635 myDragObject = aDetectedPrs;
2636 myDragOwner = aDetectedOwner;
2640 case AIS_DragAction_Update:
2642 if (myDragObject.IsNull())
2647 if (Handle(SelectMgr_EntityOwner) aGlobOwner = myDragObject->GlobalSelOwner())
2649 theCtx->SetSelectedState (aGlobOwner, true);
2652 myDragObject->ProcessDragging (theCtx, theView, myDragOwner, myGL.Dragging.PointStart,
2653 myGL.Dragging.PointTo, theAction);
2654 theView->Invalidate();
2657 case AIS_DragAction_Abort:
2659 if (myDragObject.IsNull())
2664 myGL.Dragging.PointTo = myGL.Dragging.PointStart;
2665 OnObjectDragged (theCtx, theView, AIS_DragAction_Update);
2667 myDragObject->ProcessDragging (theCtx, theView, myDragOwner, myGL.Dragging.PointStart,
2668 myGL.Dragging.PointTo, theAction);
2669 Standard_FALLTHROUGH
2671 case AIS_DragAction_Stop:
2673 if (myDragObject.IsNull())
2678 if (Handle(SelectMgr_EntityOwner) aGlobOwner = myDragObject->GlobalSelOwner())
2680 theCtx->SetSelectedState (aGlobOwner, false);
2683 myDragObject->ProcessDragging (theCtx, theView, myDragOwner, myGL.Dragging.PointStart,
2684 myGL.Dragging.PointTo, theAction);
2685 theView->Invalidate();
2686 myDragObject.Nullify();
2687 myDragOwner.Nullify();
2693 // =======================================================================
2694 // function : contextLazyMoveTo
2696 // =======================================================================
2697 void AIS_ViewController::contextLazyMoveTo (const Handle(AIS_InteractiveContext)& theCtx,
2698 const Handle(V3d_View)& theView,
2699 const Graphic3d_Vec2i& thePnt)
2701 if (myPrevMoveTo == thePnt
2702 || myHasHlrOnBeforeRotation) // ignore highlighting in-between rotation of HLR view
2707 myPrevMoveTo = thePnt;
2709 Handle(SelectMgr_EntityOwner) aLastPicked = theCtx->DetectedOwner();
2711 // Picking relies on the camera frustum (including Z-range) - so make temporary AutoZFit()
2712 // and then restore previous frustum to avoid immediate layer rendering issues if View has not been invalidated.
2713 const Standard_Real aZNear = theView->Camera()->ZNear(), aZFar = theView->Camera()->ZFar();
2714 theView->AutoZFit();
2715 theCtx->MoveTo (thePnt.x(), thePnt.y(), theView, false);
2716 theView->Camera()->SetZRange (aZNear, aZFar);
2718 Handle(SelectMgr_EntityOwner) aNewPicked = theCtx->DetectedOwner();
2720 if (theView->Viewer()->IsGridActive()
2721 && theView->Viewer()->GridEcho())
2723 if (aNewPicked.IsNull())
2725 Graphic3d_Vec3d aPnt3d;
2726 theView->ConvertToGrid (thePnt.x(), thePnt.y(), aPnt3d[0], aPnt3d[1], aPnt3d[2]);
2727 theView->Viewer()->ShowGridEcho (theView, Graphic3d_Vertex (aPnt3d[0], aPnt3d[1], aPnt3d[2]));
2728 theView->InvalidateImmediate();
2732 theView->Viewer()->HideGridEcho (theView);
2733 theView->InvalidateImmediate();
2737 if (aLastPicked != aNewPicked
2738 || (!aNewPicked.IsNull() && aNewPicked->IsForcedHilight()))
2740 // dynamic highlight affects all Views
2741 for (V3d_ListOfViewIterator aViewIter (theView->Viewer()->ActiveViewIterator()); aViewIter.More(); aViewIter.Next())
2743 const Handle(V3d_View)& aView = aViewIter.Value();
2744 aView->InvalidateImmediate();
2749 // =======================================================================
2750 // function : handleSelectionPick
2752 // =======================================================================
2753 void AIS_ViewController::handleSelectionPick (const Handle(AIS_InteractiveContext)& theCtx,
2754 const Handle(V3d_View)& theView)
2756 if (myGL.Selection.Tool == AIS_ViewSelectionTool_Picking
2757 && !myGL.Selection.Points.IsEmpty())
2759 for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aPntIter (myGL.Selection.Points); aPntIter.More(); aPntIter.Next())
2761 const bool hadPrevMoveTo = HasPreviousMoveTo();
2762 contextLazyMoveTo (theCtx, theView, aPntIter.Value());
2765 ResetPreviousMoveTo();
2768 theCtx->SelectDetected (myGL.Selection.Scheme);
2770 // selection affects all Views
2771 theView->Viewer()->Invalidate();
2773 OnSelectionChanged (theCtx, theView);
2776 myGL.Selection.Points.Clear();
2780 // =======================================================================
2781 // function : handleSelectionPoly
2783 // =======================================================================
2784 void AIS_ViewController::handleSelectionPoly (const Handle(AIS_InteractiveContext)& theCtx,
2785 const Handle(V3d_View)& theView)
2787 // rubber-band & window polygon selection
2788 if (myGL.Selection.Tool == AIS_ViewSelectionTool_RubberBand
2789 || myGL.Selection.Tool == AIS_ViewSelectionTool_Polygon
2790 || myGL.Selection.Tool == AIS_ViewSelectionTool_ZoomWindow)
2792 if (!myGL.Selection.Points.IsEmpty())
2794 myRubberBand->ClearPoints();
2795 myRubberBand->SetToUpdate();
2797 const bool anIsRubber = myGL.Selection.Tool == AIS_ViewSelectionTool_RubberBand
2798 || myGL.Selection.Tool == AIS_ViewSelectionTool_ZoomWindow;
2801 myRubberBand->SetRectangle (myGL.Selection.Points.First().x(), -myGL.Selection.Points.First().y(),
2802 myGL.Selection.Points.Last().x(), -myGL.Selection.Points.Last().y());
2806 Graphic3d_Vec2i aPrev (IntegerLast(), IntegerLast());
2807 for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aSelIter (myGL.Selection.Points); aSelIter.More(); aSelIter.Next())
2809 Graphic3d_Vec2i aPntNew = Graphic3d_Vec2i (aSelIter.Value().x(), -aSelIter.Value().y());
2810 if (aPntNew != aPrev)
2813 myRubberBand->AddPoint (Graphic3d_Vec2i (aSelIter.Value().x(), -aSelIter.Value().y()));
2818 myRubberBand->SetPolygonClosed (anIsRubber);
2821 theCtx->Display (myRubberBand, 0, -1, false, AIS_DS_Displayed);
2823 catch (const Standard_Failure& theEx)
2825 Message::SendWarning (TCollection_AsciiString ("Internal error while displaying rubber-band: ")
2826 + theEx.DynamicType()->Name() + ", " + theEx.GetMessageString());
2827 myRubberBand->ClearPoints();
2829 if (!theView->Viewer()->ZLayerSettings (myRubberBand->ZLayer()).IsImmediate())
2831 theView->Invalidate();
2835 theView->InvalidateImmediate();
2838 else if (!myRubberBand.IsNull()
2839 && myRubberBand->HasInteractiveContext())
2841 theCtx->Remove (myRubberBand, false);
2842 myRubberBand->ClearPoints();
2846 if (myGL.Selection.ToApplyTool)
2848 myGL.Selection.ToApplyTool = false;
2849 if (theCtx->IsDisplayed (myRubberBand))
2851 theCtx->Remove (myRubberBand, false);
2853 const NCollection_Sequence<Graphic3d_Vec2i>& aPoints = myRubberBand->Points();
2854 if (aPoints.Size() == 4
2855 && aPoints.Value (1).x() == aPoints.Value (2).x()
2856 && aPoints.Value (3).x() == aPoints.Value (4).x()
2857 && aPoints.Value (1).y() == aPoints.Value (4).y()
2858 && aPoints.Value (2).y() == aPoints.Value (3).y())
2860 const Graphic3d_Vec2i aPnt1 (aPoints.Value (1).x(), -aPoints.Value (1).y());
2861 const Graphic3d_Vec2i aPnt2 (aPoints.Value (3).x(), -aPoints.Value (3).y());
2862 if (myGL.Selection.Tool == AIS_ViewSelectionTool_ZoomWindow)
2864 theView->WindowFitAll (aPnt1.x(), aPnt1.y(), aPnt2.x(), aPnt2.y());
2865 theView->Invalidate();
2869 theCtx->MainSelector()->AllowOverlapDetection (aPnt1.y() != Min (aPnt1.y(), aPnt2.y()));
2870 theCtx->SelectRectangle (Graphic3d_Vec2i (Min (aPnt1.x(), aPnt2.x()), Min (aPnt1.y(), aPnt2.y())),
2871 Graphic3d_Vec2i (Max (aPnt1.x(), aPnt2.x()), Max (aPnt1.y(), aPnt2.y())),
2873 myGL.Selection.Scheme);
2874 theCtx->MainSelector()->AllowOverlapDetection (false);
2877 else if (aPoints.Length() >= 3)
2879 TColgp_Array1OfPnt2d aPolyline (1, aPoints.Length());
2880 TColgp_Array1OfPnt2d::Iterator aPolyIter (aPolyline);
2881 for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aSelIter (aPoints);
2882 aSelIter.More(); aSelIter.Next(), aPolyIter.Next())
2884 const Graphic3d_Vec2i& aNewPnt = aSelIter.Value();
2885 aPolyIter.ChangeValue() = gp_Pnt2d (aNewPnt.x(), -aNewPnt.y());
2888 theCtx->SelectPolygon (aPolyline, theView, myGL.Selection.Scheme);
2889 theCtx->MainSelector()->AllowOverlapDetection (false);
2893 myRubberBand->ClearPoints();
2894 if (myGL.Selection.Tool != AIS_ViewSelectionTool_ZoomWindow)
2896 // selection affects all Views
2897 theView->Viewer()->Invalidate();
2898 OnSelectionChanged (theCtx, theView);
2904 // =======================================================================
2905 // function : handleDynamicHighlight
2907 // =======================================================================
2908 void AIS_ViewController::handleDynamicHighlight (const Handle(AIS_InteractiveContext)& theCtx,
2909 const Handle(V3d_View)& theView)
2911 if ((myGL.MoveTo.ToHilight || myGL.Dragging.ToStart)
2912 && myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
2914 const Graphic3d_Vec2i& aMoveToPnt = myGL.MoveTo.ToHilight ? myGL.MoveTo.Point : myGL.Dragging.PointStart;
2915 if (myGL.Dragging.ToStart && (!myGL.MoveTo.ToHilight || !myToAllowHighlight)
2916 && !HasPreviousMoveTo())
2918 contextLazyMoveTo (theCtx, theView, aMoveToPnt);
2919 ResetPreviousMoveTo();
2920 OnObjectDragged (theCtx, theView, AIS_DragAction_Start);
2921 theCtx->ClearDetected();
2923 else if (myToAllowHighlight)
2925 if (myPrevMoveTo != aMoveToPnt
2926 || (!theView->View()->IsActiveXR()
2927 && (myGL.OrbitRotation.ToRotate
2928 || myGL.ViewRotation.ToRotate
2929 || theView->IsInvalidated())))
2931 ResetPreviousMoveTo();
2932 contextLazyMoveTo (theCtx, theView, aMoveToPnt);
2934 if (myGL.Dragging.ToStart)
2936 OnObjectDragged (theCtx, theView, AIS_DragAction_Start);
2940 myGL.MoveTo.ToHilight = false;
2943 if (!myDragObject.IsNull())
2945 if (myGL.Dragging.ToAbort)
2947 OnObjectDragged (theCtx, theView, AIS_DragAction_Abort);
2948 myGL.OrbitRotation.ToRotate = false;
2949 myGL.ViewRotation .ToRotate = false;
2951 else if (myGL.Dragging.ToStop)
2953 OnObjectDragged (theCtx, theView, AIS_DragAction_Stop);
2954 myGL.OrbitRotation.ToRotate = false;
2955 myGL.ViewRotation .ToRotate = false;
2957 else if (myGL.OrbitRotation.ToRotate
2958 || myGL.ViewRotation.ToRotate)
2960 OnObjectDragged (theCtx, theView, AIS_DragAction_Update);
2961 myGL.OrbitRotation.ToRotate = false;
2962 myGL.ViewRotation .ToRotate = false;
2967 // =======================================================================
2968 // function : handleMoveTo
2970 // =======================================================================
2971 void AIS_ViewController::handleMoveTo (const Handle(AIS_InteractiveContext)& theCtx,
2972 const Handle(V3d_View)& theView)
2974 handleSelectionPick (theCtx, theView);
2975 handleDynamicHighlight(theCtx, theView);
2976 handleSelectionPoly (theCtx, theView);
2979 // =======================================================================
2980 // function : handleViewRedraw
2982 // =======================================================================
2983 void AIS_ViewController::handleViewRedraw (const Handle(AIS_InteractiveContext)& ,
2984 const Handle(V3d_View)& theView)
2986 // manage animation state
2987 if (!myViewAnimation.IsNull()
2988 && !myViewAnimation->IsStopped())
2990 myViewAnimation->UpdateTimer();
2991 ResetPreviousMoveTo();
2995 if (theView->View()->IsActiveXR())
2997 // VR requires continuous rendering
2998 myToAskNextFrame = true;
3001 for (V3d_ListOfViewIterator aViewIter (theView->Viewer()->ActiveViewIterator()); aViewIter.More(); aViewIter.Next())
3003 const Handle(V3d_View)& aView = aViewIter.Value();
3004 if (aView->IsInvalidated()
3005 || (myToAskNextFrame && aView == theView))
3007 if (aView->ComputedMode())
3016 else if (aView->IsInvalidatedImmediate())
3018 aView->RedrawImmediate();
3022 if (myToAskNextFrame)
3025 theView->Window()->InvalidateContent (Handle(Aspect_DisplayConnection)());
3029 // =======================================================================
3030 // function : handleXRMoveTo
3032 // =======================================================================
3033 Standard_Integer AIS_ViewController::handleXRMoveTo (const Handle(AIS_InteractiveContext)& theCtx,
3034 const Handle(V3d_View)& theView,
3035 const gp_Trsf& thePose,
3036 const Standard_Boolean theToHighlight)
3038 //ResetPreviousMoveTo();
3039 Standard_Integer aPickResult = 0;
3041 Handle(Graphic3d_Camera) aCamBack = theView->Camera();
3042 myXRCameraTmp->Copy (aCamBack);
3043 theView->View()->ComputeXRPosedCameraFromBase (*myXRCameraTmp, thePose);
3044 theView->SetCamera (myXRCameraTmp);
3045 Graphic3d_Vec2i aPickPixel;
3046 theView->Window()->Size (aPickPixel.x(), aPickPixel.y());
3048 const Standard_Integer aSelTolerBack = theCtx->MainSelector()->CustomPixelTolerance();
3049 theCtx->MainSelector()->SetPixelTolerance (1);
3050 theView->AutoZFit();
3053 theCtx->MoveTo (aPickPixel.x(), aPickPixel.y(), theView, false);
3054 if (!theCtx->DetectedOwner().IsNull())
3056 // ignore 2D objects
3057 for (aPickResult = 1; !theCtx->DetectedOwner()->Selectable()->TransformPersistence().IsNull(); ++aPickResult)
3059 if (theCtx->HilightNextDetected (theView, false) <= 1)
3061 theCtx->ClearDetected();
3070 theCtx->MainSelector()->Pick (aPickPixel.x(), aPickPixel.y(), theView);
3071 for (Standard_Integer aPickIter = 1; aPickIter <= theCtx->MainSelector()->NbPicked(); ++aPickIter)
3073 const SelectMgr_SortCriterion& aPickedData = theCtx->MainSelector()->PickedData (aPickIter);
3074 if (!aPickedData.Entity->OwnerId()->Selectable()->TransformPersistence().IsNull())
3080 aPickResult = aPickIter;
3084 theCtx->MainSelector()->SetPixelTolerance (aSelTolerBack);
3085 theView->SetCamera (aCamBack);
3089 // =======================================================================
3090 // function : handleXRHighlight
3092 // =======================================================================
3093 void AIS_ViewController::handleXRHighlight (const Handle(AIS_InteractiveContext)& theCtx,
3094 const Handle(V3d_View)& theView)
3096 if (myXRLastPickingHand != Aspect_XRTrackedDeviceRole_LeftHand
3097 && myXRLastPickingHand != Aspect_XRTrackedDeviceRole_RightHand)
3102 const Standard_Integer aDeviceId = theView->View()->XRSession()->NamedTrackedDevice (myXRLastPickingHand);
3103 if (aDeviceId == -1)
3108 const Aspect_TrackedDevicePose& aPose = theView->View()->XRSession()->TrackedPoses()[aDeviceId];
3109 if (!aPose.IsValidPose)
3114 Handle(SelectMgr_EntityOwner) aDetOld = theCtx->DetectedOwner();
3115 handleXRMoveTo (theCtx, theView, aPose.Orientation, true);
3116 if (!theCtx->DetectedOwner().IsNull()
3117 && theCtx->DetectedOwner() != aDetOld)
3119 if (const Handle(Aspect_XRAction)& aHaptic = theView->View()->XRSession()->GenericAction (myXRLastPickingHand, Aspect_XRGenericAction_OutputHaptic))
3121 theView->View()->XRSession()->TriggerHapticVibrationAction (aHaptic, myXRPickingHaptic);
3125 Standard_Real& aPickDepth = myXRLastPickingHand == Aspect_XRTrackedDeviceRole_LeftHand ? myXRLastPickDepthLeft : myXRLastPickDepthRight;
3126 aPickDepth = Precision::Infinite();
3127 if (theCtx->MainSelector()->NbPicked() > 0)
3129 const gp_Trsf aHandBase = theView->View()->PoseXRToWorld (aPose.Orientation);
3130 const SelectMgr_SortCriterion& aPicked = theCtx->MainSelector()->PickedData (1);
3131 aPickDepth = aPicked.Point.Distance (aHandBase.TranslationPart());
3135 // =======================================================================
3136 // function : handleXRPresentations
3138 // =======================================================================
3139 void AIS_ViewController::handleXRPresentations (const Handle(AIS_InteractiveContext)& theCtx,
3140 const Handle(V3d_View)& theView)
3142 if (!theView->View()->IsActiveXR()
3143 || (!myToDisplayXRAuxDevices
3144 && !myToDisplayXRHands))
3146 for (NCollection_Array1<Handle(AIS_XRTrackedDevice)>::Iterator aPrsIter (myXRPrsDevices); aPrsIter.More(); aPrsIter.Next())
3148 if (!aPrsIter.Value().IsNull()
3149 && aPrsIter.Value()->HasInteractiveContext())
3151 theCtx->Remove (aPrsIter.Value(), false);
3153 aPrsIter.ChangeValue().Nullify();
3158 if (myXRPrsDevices.Length() != theView->View()->XRSession()->TrackedPoses().Length())
3160 for (NCollection_Array1<Handle(AIS_XRTrackedDevice)>::Iterator aPrsIter (myXRPrsDevices); aPrsIter.More(); aPrsIter.Next())
3162 if (!aPrsIter.Value().IsNull())
3164 theCtx->Remove (aPrsIter.Value(), false);
3167 myXRPrsDevices.Resize (theView->View()->XRSession()->TrackedPoses().Lower(), theView->View()->XRSession()->TrackedPoses().Upper(), false);
3170 const Standard_Integer aHeadDevice = theView->View()->XRSession()->NamedTrackedDevice (Aspect_XRTrackedDeviceRole_Head);
3171 const Standard_Integer aLeftDevice = theView->View()->XRSession()->NamedTrackedDevice (Aspect_XRTrackedDeviceRole_LeftHand);
3172 const Standard_Integer aRightDevice = theView->View()->XRSession()->NamedTrackedDevice (Aspect_XRTrackedDeviceRole_RightHand);
3173 for (Standard_Integer aDeviceIter = theView->View()->XRSession()->TrackedPoses().Lower(); aDeviceIter <= theView->View()->XRSession()->TrackedPoses().Upper(); ++aDeviceIter)
3175 const Aspect_TrackedDevicePose& aPose = theView->View()->XRSession()->TrackedPoses()[aDeviceIter];
3176 Handle(AIS_XRTrackedDevice)& aPosePrs = myXRPrsDevices[aDeviceIter];
3177 if (!aPose.IsValidPose)
3182 const bool isHand = aDeviceIter == aLeftDevice
3183 || aDeviceIter == aRightDevice;
3184 if ((!myToDisplayXRHands && isHand)
3185 || (!myToDisplayXRAuxDevices && !isHand))
3187 if (!aPosePrs.IsNull()
3188 && aPosePrs->HasInteractiveContext())
3190 theCtx->Remove (aPosePrs, false);
3195 Aspect_XRTrackedDeviceRole aRole = Aspect_XRTrackedDeviceRole_Other;
3196 if (aDeviceIter == aLeftDevice)
3198 aRole = Aspect_XRTrackedDeviceRole_LeftHand;
3200 else if (aDeviceIter == aRightDevice)
3202 aRole = Aspect_XRTrackedDeviceRole_RightHand;
3205 if (!aPosePrs.IsNull()
3206 && aPosePrs->UnitFactor() != (float )theView->View()->UnitFactor())
3208 theCtx->Remove (aPosePrs, false);
3212 if (aPosePrs.IsNull())
3214 Handle(Image_Texture) aTexture;
3215 Handle(Graphic3d_ArrayOfTriangles) aTris;
3216 if (aDeviceIter != aHeadDevice)
3218 aTris = theView->View()->XRSession()->LoadRenderModel (aDeviceIter, aTexture);
3220 if (!aTris.IsNull())
3222 aPosePrs = new AIS_XRTrackedDevice (aTris, aTexture);
3226 aPosePrs = new AIS_XRTrackedDevice();
3228 aPosePrs->SetUnitFactor ((float )theView->View()->UnitFactor());
3229 aPosePrs->SetMutable (true);
3230 aPosePrs->SetInfiniteState (true);
3232 aPosePrs->SetRole (aRole);
3234 if (!aPosePrs->HasInteractiveContext())
3236 theCtx->Display (aPosePrs, 0, -1, false);
3239 gp_Trsf aPoseLocal = aPose.Orientation;
3240 if (aDeviceIter == aHeadDevice)
3242 // show headset position on floor level
3243 aPoseLocal.SetTranslationPart (gp_Vec (aPoseLocal.TranslationPart().X(), 0.0, aPoseLocal.TranslationPart().Z()));
3245 const gp_Trsf aPoseWorld = theView->View()->PoseXRToWorld (aPoseLocal);
3246 theCtx->SetLocation (aPosePrs, aPoseWorld);
3248 Standard_Real aLaserLen = 0.0;
3250 && aPosePrs->Role() == myXRLastPickingHand)
3252 aLaserLen = myXRLastPickingHand == Aspect_XRTrackedDeviceRole_LeftHand ? myXRLastPickDepthLeft : myXRLastPickDepthRight;
3253 if (Precision::IsInfinite (aLaserLen))
3255 const Bnd_Box aViewBox = theView->View()->MinMaxValues (true);
3256 if (!aViewBox.IsVoid())
3258 aLaserLen = Sqrt (aViewBox.SquareExtent());
3265 aPosePrs->SetLaserColor (myXRLaserPickColor);
3268 && aPosePrs->Role() == myXRLastTeleportHand)
3270 aLaserLen = myXRLastTeleportHand == Aspect_XRTrackedDeviceRole_LeftHand ? myXRLastPickDepthLeft : myXRLastPickDepthRight;
3271 if (Precision::IsInfinite (aLaserLen))
3273 const Bnd_Box aViewBox = theView->View()->MinMaxValues (true);
3274 if (!aViewBox.IsVoid())
3276 aLaserLen = Sqrt (aViewBox.SquareExtent());
3283 aPosePrs->SetLaserColor (myXRLaserTeleColor);
3285 aPosePrs->SetLaserLength ((float )aLaserLen);
3289 // =======================================================================
3290 // function : HandleViewEvents
3292 // =======================================================================
3293 void AIS_ViewController::HandleViewEvents (const Handle(AIS_InteractiveContext)& theCtx,
3294 const Handle(V3d_View)& theView)
3296 const bool wasImmediateUpdate = theView->SetImmediateUpdate (false);
3298 handleViewOrientationKeys (theCtx, theView);
3299 const AIS_WalkDelta aWalk = handleNavigationKeys (theCtx, theView);
3300 handleXRInput (theCtx, theView, aWalk);
3301 if (theView->View()->IsActiveXR())
3303 theView->View()->SetupXRPosedCamera();
3305 handleMoveTo (theCtx, theView);
3306 handleCameraActions (theCtx, theView, aWalk);
3307 theView->View()->SynchronizeXRPosedToBaseCamera(); // handleCameraActions() may modify posed camera position - copy this modifications also to the base camera
3308 handleXRPresentations (theCtx, theView);
3310 handleViewRedraw (theCtx, theView);
3311 theView->View()->UnsetXRPosedCamera();
3313 theView->SetImmediateUpdate (wasImmediateUpdate);
3315 // make sure to not process the same events twice
3317 myToAskNextFrame = false;