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 <V3d_Viewer.hxx>
31 #include <WNT_HIDSpaceMouse.hxx>
33 // =======================================================================
34 // function : AIS_ViewController
36 // =======================================================================
37 AIS_ViewController::AIS_ViewController()
38 : myLastEventsTime (0.0),
39 myToAskNextFrame (false),
40 myMinCamDistance (1.0),
41 myRotationMode (AIS_RotationMode_BndBoxActive),
42 myNavigationMode (AIS_NavigationMode_Orbit),
45 myToShowPanAnchorPoint (true),
46 myToShowRotateCenter (true),
47 myToLockOrbitZUp (false),
48 myToInvertPitch (false),
49 myToAllowTouchZRotation(false),
50 myToAllowRotation (true),
51 myToAllowPanning (true),
52 myToAllowZooming (true),
53 myToAllowZFocus (true),
54 myToAllowHighlight (true),
55 myToAllowDragging (true),
56 myToStickToRayOnZoom (true),
57 myToStickToRayOnRotation (true),
59 myWalkSpeedAbsolute (1.5f),
60 myWalkSpeedRelative (0.1f),
64 myViewAnimation (new AIS_AnimationCamera ("AIS_ViewController_ViewAnimation", Handle(V3d_View)())),
65 myPrevMoveTo (-1, -1),
66 myHasHlrOnBeforeRotation (false),
68 myXRPrsDevices (0, 0),
69 myXRLaserTeleColor (Quantity_NOC_GREEN),
70 myXRLaserPickColor (Quantity_NOC_BLUE),
71 myXRLastTeleportHand(Aspect_XRTrackedDeviceRole_Other),
72 myXRLastPickingHand (Aspect_XRTrackedDeviceRole_Other),
73 myXRLastPickDepthLeft (Precision::Infinite()),
74 myXRLastPickDepthRight(Precision::Infinite()),
75 myXRTurnAngle (M_PI_4),
76 myToDisplayXRAuxDevices (false),
77 myToDisplayXRHands (true),
79 myMouseClickThreshold (3.0),
80 myMouseDoubleClickInt (0.4),
81 myScrollZoomRatio (15.0f),
82 myMouseActiveGesture (AIS_MouseGesture_NONE),
83 myMouseActiveIdleRotation (false),
84 myMouseClickCounter (0),
85 myMousePressed (Aspect_VKeyMouse_NONE),
86 myMouseModifiers (Aspect_VKeyFlags_NONE),
87 myMouseSingleButton (-1),
88 myMouseStopDragOnUnclick (false),
90 myTouchToleranceScale (1.0f),
91 myTouchRotationThresholdPx (6.0f),
92 myTouchZRotationThreshold (float(2.0 * M_PI / 180.0)),
93 myTouchPanThresholdPx (4.0f),
94 myTouchZoomThresholdPx (6.0f),
95 myTouchZoomRatio (0.13f),
98 myUpdateStartPointPan (true),
99 myUpdateStartPointRot (true),
100 myUpdateStartPointZRot (true),
102 my3dMouseNoRotate (false, false, false),
103 my3dMouseToReverse (true, false, false),
104 my3dMouseAccelTrans (2.0f),
105 my3dMouseAccelRotate (4.0f),
106 my3dMouseIsQuadric (true),
108 myPanPnt3d (Precision::Infinite(), 0.0, 0.0)
110 memset(my3dMouseButtonState, 0, sizeof(my3dMouseButtonState));
111 myEventTimer.Start();
112 myViewAnimation->SetOwnDuration (0.5);
114 myAnchorPointPrs1 = new AIS_Point (new Geom_CartesianPoint (0.0, 0.0, 0.0));
115 myAnchorPointPrs1->SetZLayer (Graphic3d_ZLayerId_Top);
116 myAnchorPointPrs1->SetMutable (true);
118 myAnchorPointPrs2 = new AIS_Point (new Geom_CartesianPoint (0.0, 0.0, 0.0));
119 myAnchorPointPrs2->SetZLayer (Graphic3d_ZLayerId_Topmost);
120 myAnchorPointPrs2->SetMutable (true);
122 myRubberBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE4, 0.5, 1.0);
123 myRubberBand->SetZLayer (Graphic3d_ZLayerId_TopOSD);
124 myRubberBand->SetTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_UPPER));
125 myRubberBand->SetDisplayMode (0);
126 myRubberBand->SetMutable (true);
128 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton, AIS_MouseGesture_RotateOrbit);
129 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_Zoom);
130 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_SHIFT, AIS_MouseGesture_Pan);
131 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_ALT, AIS_MouseGesture_SelectRectangle);
132 myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_ALT | Aspect_VKeyFlags_SHIFT, AIS_MouseGesture_SelectRectangle);
134 myMouseSelectionSchemes.Bind (Aspect_VKeyMouse_LeftButton, AIS_SelectionScheme_Replace);
135 myMouseSelectionSchemes.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_ALT, AIS_SelectionScheme_Replace);
136 myMouseSelectionSchemes.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_SHIFT, AIS_SelectionScheme_XOR);
137 myMouseSelectionSchemes.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_ALT | Aspect_VKeyFlags_SHIFT, AIS_SelectionScheme_XOR);
139 myMouseGestureMap.Bind (Aspect_VKeyMouse_RightButton, AIS_MouseGesture_Zoom);
140 myMouseGestureMap.Bind (Aspect_VKeyMouse_RightButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_RotateOrbit);
142 myMouseGestureMap.Bind (Aspect_VKeyMouse_MiddleButton, AIS_MouseGesture_Pan);
143 myMouseGestureMap.Bind (Aspect_VKeyMouse_MiddleButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_Pan);
145 myXRTeleportHaptic.Duration = 3600.0f;
146 myXRTeleportHaptic.Frequency = 0.1f;
147 myXRTeleportHaptic.Amplitude = 0.2f;
149 myXRPickingHaptic.Duration = 0.1f;
150 myXRPickingHaptic.Frequency = 4.0f;
151 myXRPickingHaptic.Amplitude = 0.1f;
153 myXRSelectHaptic.Duration = 0.2f;
154 myXRSelectHaptic.Frequency = 4.0f;
155 myXRSelectHaptic.Amplitude = 0.5f;
158 // =======================================================================
159 // function : ~AIS_ViewController
161 // =======================================================================
162 AIS_ViewController::~AIS_ViewController()
167 // =======================================================================
168 // function : ResetViewInput
170 // =======================================================================
171 void AIS_ViewController::ResetViewInput()
174 myMousePressed = Aspect_VKeyMouse_NONE;
175 myMouseModifiers = Aspect_VKeyFlags_NONE;
176 myMouseSingleButton = -1;
177 myUI.Dragging.ToAbort = true;
178 myMouseActiveGesture = AIS_MouseGesture_NONE;
179 myMouseClickTimer.Stop();
180 myMouseClickCounter = 0;
183 // =======================================================================
184 // function : FlushViewEvents
186 // =======================================================================
187 void AIS_ViewController::FlushViewEvents (const Handle(AIS_InteractiveContext)& theCtx,
188 const Handle(V3d_View)& theView,
189 Standard_Boolean theToHandle)
191 flushBuffers (theCtx, theView);
192 flushGestures(theCtx, theView);
195 HandleViewEvents (theCtx, theView);
199 // =======================================================================
200 // function : flushBuffers
202 // =======================================================================
203 void AIS_ViewController::flushBuffers (const Handle(AIS_InteractiveContext)& ,
204 const Handle(V3d_View)& )
206 myToAskNextFrame = false;
208 myGL.IsNewGesture = myUI.IsNewGesture;
209 myUI.IsNewGesture = false;
211 myGL.ZoomActions.Clear();
212 myGL.ZoomActions.Append (myUI.ZoomActions);
213 myUI.ZoomActions.Clear();
215 myGL.Orientation.ToFitAll = myUI.Orientation.ToFitAll;
216 myUI.Orientation.ToFitAll = false;
217 if (myUI.Orientation.ToSetViewOrient)
219 myUI.Orientation.ToSetViewOrient = false;
220 myGL.Orientation.ToSetViewOrient = true;
221 myGL.Orientation.ViewOrient = myUI.Orientation.ViewOrient;
224 if (myUI.MoveTo.ToHilight)
226 myUI.MoveTo.ToHilight = false;
227 myGL.MoveTo.ToHilight = true;
228 myGL.MoveTo.Point = myUI.MoveTo.Point;
232 myGL.Selection.Tool = myUI.Selection.Tool;
233 myGL.Selection.Scheme = myUI.Selection.Scheme;
234 myGL.Selection.Points = myUI.Selection.Points;
235 //myGL.Selection.Scheme = AIS_SelectionScheme_UNKNOWN; // no need
236 if (myUI.Selection.Tool == AIS_ViewSelectionTool_Picking)
238 myUI.Selection.Points.Clear();
242 if (myUI.Selection.ToApplyTool)
244 myGL.Selection.ToApplyTool = true;
245 myUI.Selection.ToApplyTool = false;
246 myUI.Selection.Points.Clear();
249 if (myUI.Panning.ToStart)
251 myUI.Panning.ToStart = false;
252 myGL.Panning.ToStart = true;
253 myGL.Panning.PointStart = myUI.Panning.PointStart;
256 if (myUI.Panning.ToPan)
258 myUI.Panning.ToPan = false;
259 myGL.Panning.ToPan = true;
260 myGL.Panning.Delta = myUI.Panning.Delta;
263 if (myUI.Dragging.ToAbort)
265 myUI.Dragging.ToAbort = false;
266 myGL.Dragging.ToAbort = true;
268 else if (myUI.Dragging.ToStop)
270 myUI.Dragging.ToStop = false;
271 myGL.Dragging.ToStop = true;
273 else if (myUI.Dragging.ToStart)
275 myUI.Dragging.ToStart = false;
276 myGL.Dragging.ToStart = true;
277 myGL.Dragging.PointStart = myUI.Dragging.PointStart;
279 myGL.Dragging.PointTo = myUI.Dragging.PointTo;
281 if (myUI.OrbitRotation.ToStart)
283 myUI.OrbitRotation.ToStart = false;
284 myGL.OrbitRotation.ToStart = true;
285 myGL.OrbitRotation.PointStart = myUI.OrbitRotation.PointStart;
288 if (myUI.OrbitRotation.ToRotate)
290 myUI.OrbitRotation.ToRotate = false;
291 myGL.OrbitRotation.ToRotate = true;
292 myGL.OrbitRotation.PointTo = myUI.OrbitRotation.PointTo;
295 if (myUI.ViewRotation.ToStart)
297 myUI.ViewRotation.ToStart = false;
298 myGL.ViewRotation.ToStart = true;
299 myGL.ViewRotation.PointStart = myUI.ViewRotation.PointStart;
302 if (myUI.ViewRotation.ToRotate)
304 myUI.ViewRotation.ToRotate = false;
305 myGL.ViewRotation.ToRotate = true;
306 myGL.ViewRotation.PointTo = myUI.ViewRotation.PointTo;
309 if (myUI.ZRotate.ToRotate)
311 myGL.ZRotate = myUI.ZRotate;
312 myUI.ZRotate.ToRotate = false;
316 // =======================================================================
317 // function : flushGestures
319 // =======================================================================
320 void AIS_ViewController::flushGestures (const Handle(AIS_InteractiveContext)& ,
321 const Handle(V3d_View)& theView)
323 const Standard_Real aTolScale = myTouchToleranceScale;
324 const Standard_Integer aTouchNb = myTouchPoints.Extent();
325 if (myNbTouchesLast != aTouchNb)
327 myNbTouchesLast = aTouchNb;
328 myGL.IsNewGesture = true;
330 if (aTouchNb == 1) // touch
332 Aspect_Touch& aTouch = myTouchPoints.ChangeFromIndex (1);
333 if (myUpdateStartPointRot)
335 // skip rotation if have active dragged object
336 if (myNavigationMode == AIS_NavigationMode_Orbit)
338 myGL.OrbitRotation.ToStart = true;
339 myGL.OrbitRotation.PointStart = myStartRotCoord;
343 myGL.ViewRotation.ToStart = true;
344 myGL.ViewRotation.PointStart = myStartRotCoord;
347 myUpdateStartPointRot = false;
348 theView->Invalidate();
352 const Standard_Real aRotTouchTol = !aTouch.IsPreciseDevice
353 ? aTolScale * myTouchRotationThresholdPx
355 if (Abs (aTouch.Delta().x()) + Abs(aTouch.Delta().y()) > aRotTouchTol)
357 const Standard_Real aRotAccel = myNavigationMode == AIS_NavigationMode_FirstPersonWalk ? myMouseAccel : myOrbitAccel;
358 if (myNavigationMode == AIS_NavigationMode_Orbit)
360 const Graphic3d_Vec2d aRotDelta = aTouch.To - myGL.OrbitRotation.PointStart;
361 myGL.OrbitRotation.ToRotate = true;
362 myGL.OrbitRotation.PointTo = myGL.OrbitRotation.PointStart + aRotDelta * aRotAccel;
363 myGL.Dragging.PointTo.SetValues ((int )aTouch.To.x(), (int )aTouch.To.y());
367 const Graphic3d_Vec2d aRotDelta = aTouch.To - myGL.ViewRotation.PointStart;
368 myGL.ViewRotation.ToRotate = true;
369 myGL.ViewRotation.PointTo = myGL.ViewRotation.PointStart + aRotDelta * aRotAccel;
370 myGL.Dragging.PointTo.SetValues ((int )aTouch.To.x(), (int )aTouch.To.y());
373 aTouch.From = aTouch.To;
376 else if (aTouchNb == 2) // pinch
378 Aspect_Touch& aFirstTouch = myTouchPoints.ChangeFromIndex (1);
379 Aspect_Touch& aLastTouch = myTouchPoints.ChangeFromIndex (2);
380 const Graphic3d_Vec2d aFrom[2] = { aFirstTouch.From, aLastTouch.From };
381 const Graphic3d_Vec2d aTo[2] = { aFirstTouch.To, aLastTouch.To };
383 Graphic3d_Vec2d aPinchCenterStart ((aFrom[0].x() + aFrom[1].x()) / 2.0,
384 (aFrom[0].y() + aFrom[1].y()) / 2.0);
386 Standard_Real aPinchCenterXEnd = (aTo[0].x() + aTo[1].x()) / 2.0;
387 Standard_Real aPinchCenterYEnd = (aTo[0].y() + aTo[1].y()) / 2.0;
389 Standard_Real aPinchCenterXDev = aPinchCenterXEnd - aPinchCenterStart.x();
390 Standard_Real aPinchCenterYDev = aPinchCenterYEnd - aPinchCenterStart.y();
392 Standard_Real aStartSize = (aFrom[0] - aFrom[1]).Modulus();
393 Standard_Real anEndSize = ( aTo[0] - aTo[1]).Modulus();
395 Standard_Real aDeltaSize = anEndSize - aStartSize;
397 bool anIsClearDev = false;
399 if (myToAllowTouchZRotation)
401 Standard_Real A1 = aFrom[0].y() - aFrom[1].y();
402 Standard_Real B1 = aFrom[1].x() - aFrom[0].x();
404 Standard_Real A2 = aTo[0].y() - aTo[1].y();
405 Standard_Real B2 = aTo[1].x() - aTo[0].x();
407 Standard_Real aRotAngle = 0.0;
409 Standard_Real aDenomenator = A1*A2 + B1*B2;
410 if (aDenomenator <= Precision::Confusion())
416 Standard_Real aNumerator = A1*B2 - A2*B1;
417 aRotAngle = ATan (aNumerator / aDenomenator);
420 if (Abs(aRotAngle) > Standard_Real(myTouchZRotationThreshold))
422 myGL.ZRotate.ToRotate = true;
423 myGL.ZRotate.Angle = aRotAngle;
428 if (Abs(aDeltaSize) > aTolScale * myTouchZoomThresholdPx)
431 aDeltaSize *= Standard_Real(myTouchZoomRatio);
432 Aspect_ScrollDelta aParams (Graphic3d_Vec2i (aPinchCenterStart), aDeltaSize);
433 myGL.ZoomActions.Append (aParams);
437 const Standard_Real aPanTouchTol = !aFirstTouch.IsPreciseDevice
438 ? aTolScale * myTouchPanThresholdPx
440 if (Abs(aPinchCenterXDev) + Abs(aPinchCenterYDev) > aPanTouchTol)
443 if (myUpdateStartPointPan)
445 myGL.Panning.ToStart = true;
446 myGL.Panning.PointStart = Graphic3d_Vec2i (myStartPanCoord);
447 myUpdateStartPointPan = false;
448 theView->Invalidate();
451 myGL.Panning.ToPan = true;
452 myGL.Panning.Delta.x() = int( aPinchCenterXDev);
453 myGL.Panning.Delta.y() = int(-aPinchCenterYDev);
459 aFirstTouch.From = aFirstTouch.To;
460 aLastTouch .From = aLastTouch.To;
465 // =======================================================================
466 // function : UpdateViewOrientation
468 // =======================================================================
469 void AIS_ViewController::UpdateViewOrientation (V3d_TypeOfOrientation theOrientation,
472 myUI.Orientation.ToFitAll = theToFitAll;
473 myUI.Orientation.ToSetViewOrient = true;
474 myUI.Orientation.ViewOrient = theOrientation;
477 // =======================================================================
478 // function : SelectInViewer
480 // =======================================================================
481 void AIS_ViewController::SelectInViewer (const Graphic3d_Vec2i& thePnt,
482 const AIS_SelectionScheme theScheme)
484 if (myUI.Selection.Tool != AIS_ViewSelectionTool_Picking)
486 myUI.Selection.Tool = AIS_ViewSelectionTool_Picking;
487 myUI.Selection.Points.Clear();
490 myUI.Selection.Scheme = theScheme;
491 myUI.Selection.Points.Append (thePnt);
494 // =======================================================================
495 // function : SelectInViewer
497 // =======================================================================
498 void AIS_ViewController::SelectInViewer (const NCollection_Sequence<Graphic3d_Vec2i>& thePnts,
499 const AIS_SelectionScheme theScheme)
501 myUI.Selection.Scheme = theScheme;
502 myUI.Selection.Points = thePnts;
503 myUI.Selection.ToApplyTool = true;
504 if (thePnts.Length() == 1)
506 myUI.Selection.Tool = AIS_ViewSelectionTool_Picking;
508 else if (thePnts.Length() == 2)
510 myUI.Selection.Tool = AIS_ViewSelectionTool_RubberBand;
514 myUI.Selection.Tool = AIS_ViewSelectionTool_Polygon;
518 // =======================================================================
519 // function : UpdateRubberBand
521 // =======================================================================
522 void AIS_ViewController::UpdateRubberBand (const Graphic3d_Vec2i& thePntFrom,
523 const Graphic3d_Vec2i& thePntTo)
525 myUI.Selection.Tool = AIS_ViewSelectionTool_RubberBand;
526 myUI.Selection.Points.Clear();
527 myUI.Selection.Points.Append (thePntFrom);
528 myUI.Selection.Points.Append (thePntTo);
531 // =======================================================================
532 // function : UpdatePolySelection
534 // =======================================================================
535 void AIS_ViewController::UpdatePolySelection (const Graphic3d_Vec2i& thePnt,
538 if (myUI.Selection.Tool != AIS_ViewSelectionTool_Polygon)
540 myUI.Selection.Tool = AIS_ViewSelectionTool_Polygon;
541 myUI.Selection.Points.Clear();
544 if (myUI.Selection.Points.IsEmpty())
546 myUI.Selection.Points.Append (thePnt);
549 && myUI.Selection.Points.Last() != thePnt)
551 myUI.Selection.Points.Append (thePnt);
555 myUI.Selection.Points.ChangeLast() = thePnt;
559 // =======================================================================
560 // function : UpdateZoom
562 // =======================================================================
563 bool AIS_ViewController::UpdateZoom (const Aspect_ScrollDelta& theDelta)
565 if (!myUI.ZoomActions.IsEmpty())
567 if (myUI.ZoomActions.ChangeLast().Point == theDelta.Point)
569 myUI.ZoomActions.ChangeLast().Delta += theDelta.Delta;
574 myUI.ZoomActions.Append (theDelta);
578 // =======================================================================
579 // function : UpdateZRotation
581 // =======================================================================
582 bool AIS_ViewController::UpdateZRotation (double theAngle)
584 if (!ToAllowTouchZRotation())
589 myUI.ZRotate.Angle = myUI.ZRotate.ToRotate
590 ? myUI.ZRotate.Angle + theAngle
592 if (myUI.ZRotate.ToRotate)
596 myUI.ZRotate.ToRotate = true;
600 // =======================================================================
601 // function : UpdateMouseScroll
603 // =======================================================================
604 bool AIS_ViewController::UpdateMouseScroll (const Aspect_ScrollDelta& theDelta)
606 Aspect_ScrollDelta aDelta = theDelta;
607 aDelta.Delta *= myScrollZoomRatio;
608 return UpdateZoom (aDelta);
611 // =======================================================================
612 // function : UpdateMouseClick
614 // =======================================================================
615 bool AIS_ViewController::UpdateMouseClick (const Graphic3d_Vec2i& thePoint,
616 Aspect_VKeyMouse theButton,
617 Aspect_VKeyFlags theModifiers,
618 bool theIsDoubleClick)
620 (void )theIsDoubleClick;
621 AIS_SelectionScheme aScheme = AIS_SelectionScheme_UNKNOWN;
622 if (myMouseSelectionSchemes.Find (theButton | theModifiers, aScheme))
624 SelectInViewer (thePoint, aScheme);
630 // =======================================================================
631 // function : UpdateMouseButtons
633 // =======================================================================
634 bool AIS_ViewController::UpdateMouseButtons (const Graphic3d_Vec2i& thePoint,
635 Aspect_VKeyMouse theButtons,
636 Aspect_VKeyFlags theModifiers,
639 bool toUpdateView = false;
640 const double aTolClick = (theIsEmulated ? myTouchToleranceScale : 1.0) * myMouseClickThreshold;
641 if (theButtons == Aspect_VKeyMouse_NONE
642 && myMouseSingleButton > 0)
644 const Graphic3d_Vec2i aDelta = thePoint - myMousePressPoint;
645 if (double(aDelta.cwiseAbs().maxComp()) < aTolClick)
647 ++myMouseClickCounter;
648 const bool isDoubleClick = myMouseClickCounter == 2
649 && myMouseClickTimer.IsStarted()
650 && myMouseClickTimer.ElapsedTime() <= myMouseDoubleClickInt;
652 myMouseClickTimer.Stop();
653 myMouseClickTimer.Reset();
654 myMouseClickTimer.Start();
657 myMouseClickCounter = 0;
659 toUpdateView = UpdateMouseClick (thePoint, (Aspect_VKeyMouse )myMouseSingleButton, theModifiers, isDoubleClick) || toUpdateView;
663 myMouseClickTimer.Stop();
664 myMouseClickCounter = 0;
665 myMouseStopDragOnUnclick = false;
666 myUI.Dragging.ToStop = true;
669 myMouseSingleButton = -1;
671 else if (theButtons == Aspect_VKeyMouse_NONE)
673 myMouseSingleButton = -1;
674 if (myMouseStopDragOnUnclick)
676 myMouseStopDragOnUnclick = false;
677 myUI.Dragging.ToStop = true;
681 else if (myMouseSingleButton == -1)
683 if ((theButtons & Aspect_VKeyMouse_LeftButton) == Aspect_VKeyMouse_LeftButton)
685 myMouseSingleButton = Aspect_VKeyMouse_LeftButton;
687 else if ((theButtons & Aspect_VKeyMouse_RightButton) == Aspect_VKeyMouse_RightButton)
689 myMouseSingleButton = Aspect_VKeyMouse_RightButton;
691 else if ((theButtons & Aspect_VKeyMouse_MiddleButton) == Aspect_VKeyMouse_MiddleButton)
693 myMouseSingleButton = Aspect_VKeyMouse_MiddleButton;
697 myMouseSingleButton = 0;
699 if (myMouseSingleButton != 0)
701 if (myMouseClickCounter == 1)
703 const Graphic3d_Vec2i aDelta = thePoint - myMousePressPoint;
704 if (double(aDelta.cwiseAbs().maxComp()) >= aTolClick)
706 myMouseClickTimer.Stop();
707 myMouseClickCounter = 0;
710 myMousePressPoint = thePoint;
715 myMouseSingleButton = 0;
717 myUI.Dragging.ToAbort = true;
721 const AIS_MouseGesture aPrevGesture = myMouseActiveGesture;
722 const Aspect_VKeyMouse aPrevButtons = myMousePressed;
723 const Aspect_VKeyFlags aPrevModifiers = myMouseModifiers;
724 myMouseModifiers = theModifiers;
725 myMousePressed = theButtons;
727 || myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
729 myMouseActiveIdleRotation = false;
730 myMouseActiveGesture = AIS_MouseGesture_NONE;
733 myMousePressPoint = thePoint;
734 myMouseProgressPoint = myMousePressPoint;
737 if (myMouseGestureMap.Find (theButtons | theModifiers, myMouseActiveGesture))
739 switch (myMouseActiveGesture)
741 case AIS_MouseGesture_RotateView:
742 case AIS_MouseGesture_RotateOrbit:
744 if (myToAllowRotation)
746 myUpdateStartPointRot = true;
750 myMouseActiveGesture = AIS_MouseGesture_NONE;
754 case AIS_MouseGesture_Pan:
756 if (myToAllowPanning)
758 myUpdateStartPointPan = true;
762 myMouseActiveGesture = AIS_MouseGesture_NONE;
766 case AIS_MouseGesture_Zoom:
767 case AIS_MouseGesture_ZoomWindow:
769 if (!myToAllowZooming)
771 myMouseActiveGesture = AIS_MouseGesture_NONE;
775 case AIS_MouseGesture_SelectRectangle:
779 case AIS_MouseGesture_SelectLasso:
781 UpdatePolySelection (thePoint, true);
784 case AIS_MouseGesture_NONE:
791 if (theButtons == Aspect_VKeyMouse_LeftButton
792 && theModifiers == Aspect_VKeyFlags_NONE
793 && myToAllowDragging)
795 myUI.Dragging.ToStart = true;
796 myUI.Dragging.PointStart = thePoint;
800 if (aPrevGesture != myMouseActiveGesture)
802 if (aPrevGesture == AIS_MouseGesture_SelectRectangle
803 || aPrevGesture == AIS_MouseGesture_SelectLasso
804 || aPrevGesture == AIS_MouseGesture_ZoomWindow)
806 myUI.Selection.ToApplyTool = true;
807 myUI.Selection.Scheme = AIS_SelectionScheme_Replace;
808 myMouseSelectionSchemes.Find (aPrevButtons | aPrevModifiers, myUI.Selection.Scheme);
811 myUI.IsNewGesture = true;
818 // =======================================================================
819 // function : UpdateMousePosition
821 // =======================================================================
822 bool AIS_ViewController::UpdateMousePosition (const Graphic3d_Vec2i& thePoint,
823 Aspect_VKeyMouse theButtons,
824 Aspect_VKeyFlags theModifiers,
827 myMousePositionLast = thePoint;
828 if (myMouseSingleButton > 0)
830 const double aTolClick = (theIsEmulated ? myTouchToleranceScale : 1.0) * myMouseClickThreshold;
831 const Graphic3d_Vec2i aPressDelta = thePoint - myMousePressPoint;
832 if (double(aPressDelta.cwiseAbs().maxComp()) >= aTolClick)
834 myMouseClickTimer.Stop();
835 myMouseClickCounter = 0;
836 myMouseSingleButton = -1;
837 myMouseStopDragOnUnclick = true;
841 bool toUpdateView = false;
842 Graphic3d_Vec2i aDelta = thePoint - myMouseProgressPoint;
844 && myNavigationMode == AIS_NavigationMode_FirstPersonWalk)
846 if (!myMouseActiveIdleRotation
847 || myMouseActiveGesture != AIS_MouseGesture_RotateView)
849 myMouseActiveIdleRotation = true;
850 myMouseActiveGesture = AIS_MouseGesture_RotateView;
851 myMousePressPoint = thePoint;
852 myMouseProgressPoint = thePoint;
853 myUpdateStartPointRot = false;
854 myUI.ViewRotation.ToStart = true;
855 myUI.ViewRotation.PointStart.SetValues (thePoint.x(), thePoint.y());
856 myUI.ViewRotation.ToRotate = false;
857 aDelta.SetValues (0, 0);
862 if (myMouseActiveIdleRotation
863 && myMouseActiveGesture == AIS_MouseGesture_RotateView)
865 myMouseActiveGesture = AIS_MouseGesture_NONE;
867 myMouseActiveIdleRotation = false;
870 if (myMouseModifiers != theModifiers
871 && UpdateMouseButtons (thePoint, theButtons, theModifiers, theIsEmulated))
876 switch (myMouseActiveGesture)
878 case AIS_MouseGesture_SelectRectangle:
879 case AIS_MouseGesture_ZoomWindow:
881 UpdateRubberBand (myMousePressPoint, thePoint);
882 if (myMouseActiveGesture == AIS_MouseGesture_ZoomWindow)
884 myUI.Selection.Tool = AIS_ViewSelectionTool_ZoomWindow;
889 case AIS_MouseGesture_SelectLasso:
891 UpdatePolySelection (thePoint, true);
895 case AIS_MouseGesture_RotateOrbit:
896 case AIS_MouseGesture_RotateView:
898 if (!myToAllowRotation)
902 if (myUpdateStartPointRot)
904 if (myMouseActiveGesture == AIS_MouseGesture_RotateOrbit)
906 myUI.OrbitRotation.ToStart = true;
907 myUI.OrbitRotation.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
911 myUI.ViewRotation.ToStart = true;
912 myUI.ViewRotation.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
914 myUpdateStartPointRot = false;
917 const double aRotTol = theIsEmulated
918 ? double(myTouchToleranceScale) * myTouchRotationThresholdPx
920 if (double (Abs (aDelta.x()) + Abs (aDelta.y())) > aRotTol)
922 const double aRotAccel = myNavigationMode == AIS_NavigationMode_FirstPersonWalk ? myMouseAccel : myOrbitAccel;
923 const Graphic3d_Vec2i aRotDelta = thePoint - myMousePressPoint;
924 if (myMouseActiveGesture == AIS_MouseGesture_RotateOrbit)
926 myUI.OrbitRotation.ToRotate = true;
927 myUI.OrbitRotation.PointTo = Graphic3d_Vec2d (myMousePressPoint.x(), myMousePressPoint.y())
928 + Graphic3d_Vec2d (aRotDelta.x(), aRotDelta.y()) * aRotAccel;
932 myUI.ViewRotation.ToRotate = true;
933 myUI.ViewRotation.PointTo = Graphic3d_Vec2d (myMousePressPoint.x(), myMousePressPoint.y())
934 + Graphic3d_Vec2d (aRotDelta.x(), aRotDelta.y()) * aRotAccel;
936 myUI.Dragging.PointTo = thePoint;
938 myMouseProgressPoint = thePoint;
943 case AIS_MouseGesture_Zoom:
945 if (!myToAllowZooming)
949 const double aZoomTol = theIsEmulated
950 ? double(myTouchToleranceScale) * myTouchZoomThresholdPx
952 if (double (Abs (aDelta.x())) > aZoomTol)
954 if (UpdateZoom (Aspect_ScrollDelta (aDelta.x())))
958 myMouseProgressPoint = thePoint;
962 case AIS_MouseGesture_Pan:
964 if (!myToAllowPanning)
968 const double aPanTol = theIsEmulated
969 ? double(myTouchToleranceScale) * myTouchPanThresholdPx
971 if (double (Abs (aDelta.x()) + Abs (aDelta.y())) > aPanTol)
973 if (myUpdateStartPointPan)
975 myUI.Panning.ToStart = true;
976 myUI.Panning.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y());
977 myUpdateStartPointPan = false;
980 aDelta.y() = -aDelta.y();
981 myMouseProgressPoint = thePoint;
982 if (myUI.Panning.ToPan)
984 myUI.Panning.Delta += aDelta;
988 myUI.Panning.ToPan = true;
989 myUI.Panning.Delta = aDelta;
1001 if (theButtons == Aspect_VKeyMouse_NONE
1002 && myNavigationMode != AIS_NavigationMode_FirstPersonWalk
1004 && !HasTouchPoints()
1005 && myToAllowHighlight)
1007 myUI.MoveTo.ToHilight = true;
1008 myUI.MoveTo.Point = thePoint;
1009 toUpdateView = true;
1011 return toUpdateView;
1014 // =======================================================================
1015 // function : AddTouchPoint
1017 // =======================================================================
1018 void AIS_ViewController::AddTouchPoint (Standard_Size theId,
1019 const Graphic3d_Vec2d& thePnt,
1020 Standard_Boolean theClearBefore)
1022 myUI.MoveTo.ToHilight = false;
1025 RemoveTouchPoint ((Standard_Size )-1);
1028 myTouchPoints.Add (theId, Aspect_Touch (thePnt, false));
1029 if (myTouchPoints.Extent() == 1)
1031 myUpdateStartPointRot = true;
1032 myStartRotCoord = thePnt;
1033 if (myToAllowDragging)
1035 myUI.Dragging.ToStart = true;
1036 myUI.Dragging.PointStart.SetValues ((int )thePnt.x(), (int )thePnt.y());
1039 else if (myTouchPoints.Extent() == 2)
1041 myUI.Dragging.ToAbort = true;
1043 myUpdateStartPointPan = true;
1044 myStartPanCoord = thePnt;
1046 myUI.IsNewGesture = true;
1049 // =======================================================================
1050 // function : RemoveTouchPoint
1052 // =======================================================================
1053 bool AIS_ViewController::RemoveTouchPoint (Standard_Size theId,
1054 Standard_Boolean theClearSelectPnts)
1056 if (theId == (Standard_Size )-1)
1058 myTouchPoints.Clear (false);
1062 const Standard_Integer anOldExtent = myTouchPoints.Extent();
1063 myTouchPoints.RemoveKey (theId);
1064 if (myTouchPoints.Extent() == anOldExtent)
1070 if (myTouchPoints.Extent() == 1)
1072 // avoid incorrect transition from pinch to one finger
1073 Aspect_Touch& aFirstTouch = myTouchPoints.ChangeFromIndex (1);
1074 aFirstTouch.To = aFirstTouch.From;
1076 myStartRotCoord = aFirstTouch.To;
1077 myUpdateStartPointRot = true;
1079 else if (myTouchPoints.Extent() == 2)
1081 myStartPanCoord = myTouchPoints.FindFromIndex (1).To;
1082 myUpdateStartPointPan = true;
1084 else if (myTouchPoints.IsEmpty())
1086 if (theClearSelectPnts)
1088 myUI.Selection.ToApplyTool = true;
1091 myUI.Dragging.ToStop = true;
1093 myUI.IsNewGesture = true;
1097 // =======================================================================
1098 // function : UpdateTouchPoint
1100 // =======================================================================
1101 void AIS_ViewController::UpdateTouchPoint (Standard_Size theId,
1102 const Graphic3d_Vec2d& thePnt)
1104 if (Aspect_Touch* aTouch = myTouchPoints.ChangeSeek (theId))
1106 aTouch->To = thePnt;
1110 AddTouchPoint (theId, thePnt);
1114 // =======================================================================
1115 // function : Update3dMouse
1117 // =======================================================================
1118 bool AIS_ViewController::Update3dMouse (const WNT_HIDSpaceMouse& theEvent)
1120 bool toUpdate = false;
1121 toUpdate = update3dMouseTranslation (theEvent) || toUpdate;
1122 toUpdate = update3dMouseRotation (theEvent) || toUpdate;
1123 toUpdate = update3dMouseKeys (theEvent) || toUpdate;
1127 // =======================================================================
1128 // function : update3dMouseTranslation
1130 // =======================================================================
1131 bool AIS_ViewController::update3dMouseTranslation (const WNT_HIDSpaceMouse& theEvent)
1133 if (!theEvent.IsTranslation())
1139 const double aTimeStamp = EventTime();
1140 const Graphic3d_Vec3d aTrans = theEvent.Translation (isIdle, my3dMouseIsQuadric) * my3dMouseAccelTrans;
1141 myKeys.KeyFromAxis (Aspect_VKey_NavSlideLeft, Aspect_VKey_NavSlideRight, aTimeStamp, aTrans.x());
1142 myKeys.KeyFromAxis (Aspect_VKey_NavForward, Aspect_VKey_NavBackward, aTimeStamp, aTrans.y());
1143 myKeys.KeyFromAxis (Aspect_VKey_NavSlideUp, Aspect_VKey_NavSlideDown, aTimeStamp, aTrans.z());
1147 // =======================================================================
1148 // function : update3dMouseRotation
1150 // =======================================================================
1151 bool AIS_ViewController::update3dMouseRotation (const WNT_HIDSpaceMouse& theEvent)
1153 if (!theEvent.IsRotation()
1154 || !myToAllowRotation)
1159 bool isIdle = true, toUpdate = false;
1160 const double aTimeStamp = EventTime();
1161 const Graphic3d_Vec3d aRot3 = theEvent.Rotation (isIdle, my3dMouseIsQuadric) * my3dMouseAccelRotate;
1162 if (!my3dMouseNoRotate.x())
1164 KeyFromAxis (Aspect_VKey_NavLookUp, Aspect_VKey_NavLookDown, aTimeStamp, !my3dMouseToReverse.x() ? aRot3.x() : -aRot3.x());
1167 if (!my3dMouseNoRotate.y())
1169 KeyFromAxis (Aspect_VKey_NavRollCW, Aspect_VKey_NavRollCCW, aTimeStamp, !my3dMouseToReverse.y() ? aRot3.y() : -aRot3.y());
1172 if (!my3dMouseNoRotate.z())
1174 KeyFromAxis (Aspect_VKey_NavLookLeft, Aspect_VKey_NavLookRight, aTimeStamp, !my3dMouseToReverse.z() ? aRot3.z() : -aRot3.z());
1180 // =======================================================================
1181 // function : update3dMouseKeys
1183 // =======================================================================
1184 bool AIS_ViewController::update3dMouseKeys (const WNT_HIDSpaceMouse& theEvent)
1186 bool toUpdate = false;
1187 const double aTimeStamp = EventTime();
1188 if (theEvent.IsKeyState())
1190 const uint32_t aKeyState = theEvent.KeyState();
1191 for (unsigned short aKeyBit = 0; aKeyBit < 32; ++aKeyBit)
1193 const bool isPressed = (aKeyState & (1 << aKeyBit)) != 0;
1194 const bool isReleased = my3dMouseButtonState[aKeyBit] && !isPressed;
1195 //const bool isRepeated = my3dMouseButtonState[aKeyBit] && isPressed;
1196 my3dMouseButtonState[aKeyBit] = isPressed;
1197 if (!isReleased && !isPressed)
1202 const Aspect_VKey aVKey = theEvent.HidToSpaceKey (aKeyBit);
1203 if (aVKey != Aspect_VKey_UNKNOWN)
1208 KeyDown (aVKey, aTimeStamp);
1212 KeyUp (aVKey, aTimeStamp);
1220 // =======================================================================
1221 // function : SetNavigationMode
1223 // =======================================================================
1224 void AIS_ViewController::SetNavigationMode (AIS_NavigationMode theMode)
1226 myNavigationMode = theMode;
1229 myUI.OrbitRotation.ToStart = false;
1230 myUI.OrbitRotation.ToRotate = false;
1231 myUI.ViewRotation.ToStart = false;
1232 myUI.ViewRotation.ToRotate = false;
1235 // =======================================================================
1236 // function : KeyDown
1238 // =======================================================================
1239 void AIS_ViewController::KeyDown (Aspect_VKey theKey,
1243 myKeys.KeyDown (theKey, theTime, thePressure);
1246 // =======================================================================
1249 // =======================================================================
1250 void AIS_ViewController::KeyUp (Aspect_VKey theKey,
1253 myKeys.KeyUp (theKey, theTime);
1256 // =======================================================================
1257 // function : KeyFromAxis
1259 // =======================================================================
1260 void AIS_ViewController::KeyFromAxis (Aspect_VKey theNegative,
1261 Aspect_VKey thePositive,
1265 myKeys.KeyFromAxis (theNegative, thePositive, theTime, thePressure);
1268 // =======================================================================
1269 // function : FetchNavigationKeys
1271 // =======================================================================
1272 AIS_WalkDelta AIS_ViewController::FetchNavigationKeys (Standard_Real theCrouchRatio,
1273 Standard_Real theRunRatio)
1275 AIS_WalkDelta aWalk;
1278 double aPrevEventTime = 0.0, aNewEventTime = 0.0;
1279 updateEventsTime (aPrevEventTime, aNewEventTime);
1281 double aDuration = 0.0, aPressure = 1.0;
1282 if (Abs (myThrustSpeed) > gp::Resolution())
1286 aWalk[AIS_WalkTranslation_Forward].Value = myThrustSpeed * (aNewEventTime - aPrevEventTime);
1289 myToAskNextFrame = true;
1293 myHasThrust = false;
1296 aWalk.SetRunning (theRunRatio > 1.0
1297 && myKeys.IsKeyDown (Aspect_VKey_Shift));
1298 if (myKeys.HoldDuration (Aspect_VKey_NavJump, aNewEventTime, aDuration))
1300 myKeys.KeyUp (Aspect_VKey_NavJump, aNewEventTime);
1301 aWalk.SetJumping (true);
1303 if (!aWalk.IsJumping()
1304 && theCrouchRatio < 1.0
1305 && myKeys.HoldDuration (Aspect_VKey_NavCrouch, aNewEventTime, aDuration))
1307 aWalk.SetRunning (false);
1308 aWalk.SetCrouching (true);
1311 const double aMaxDuration = aNewEventTime - aPrevEventTime;
1312 const double aRunRatio = aWalk.IsRunning()
1314 : aWalk.IsCrouching()
1317 if (myKeys.HoldDuration (Aspect_VKey_NavForward, aNewEventTime, aDuration, aPressure))
1319 double aProgress = Abs (Min (aMaxDuration, aDuration));
1320 aProgress *= aRunRatio;
1321 aWalk[AIS_WalkTranslation_Forward].Value += aProgress;
1322 aWalk[AIS_WalkTranslation_Forward].Pressure = aPressure;
1323 aWalk[AIS_WalkTranslation_Forward].Duration = aDuration;
1325 if (myKeys.HoldDuration (Aspect_VKey_NavBackward, aNewEventTime, aDuration, aPressure))
1327 double aProgress = Abs (Min (aMaxDuration, aDuration));
1328 aProgress *= aRunRatio;
1329 aWalk[AIS_WalkTranslation_Forward].Value += -aProgress;
1330 aWalk[AIS_WalkTranslation_Forward].Pressure = aPressure;
1331 aWalk[AIS_WalkTranslation_Forward].Duration = aDuration;
1333 if (myKeys.HoldDuration (Aspect_VKey_NavSlideLeft, aNewEventTime, aDuration, aPressure))
1335 double aProgress = Abs (Min (aMaxDuration, aDuration));
1336 aProgress *= aRunRatio;
1337 aWalk[AIS_WalkTranslation_Side].Value = -aProgress;
1338 aWalk[AIS_WalkTranslation_Side].Pressure = aPressure;
1339 aWalk[AIS_WalkTranslation_Side].Duration = aDuration;
1341 if (myKeys.HoldDuration (Aspect_VKey_NavSlideRight, aNewEventTime, aDuration, aPressure))
1343 double aProgress = Abs (Min (aMaxDuration, aDuration));
1344 aProgress *= aRunRatio;
1345 aWalk[AIS_WalkTranslation_Side].Value = aProgress;
1346 aWalk[AIS_WalkTranslation_Side].Pressure = aPressure;
1347 aWalk[AIS_WalkTranslation_Side].Duration = aDuration;
1349 if (myKeys.HoldDuration (Aspect_VKey_NavLookLeft, aNewEventTime, aDuration, aPressure))
1351 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1352 aWalk[AIS_WalkRotation_Yaw].Value = aProgress;
1353 aWalk[AIS_WalkRotation_Yaw].Pressure = aPressure;
1354 aWalk[AIS_WalkRotation_Yaw].Duration = aDuration;
1356 if (myKeys.HoldDuration (Aspect_VKey_NavLookRight, aNewEventTime, aDuration, aPressure))
1358 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1359 aWalk[AIS_WalkRotation_Yaw].Value = -aProgress;
1360 aWalk[AIS_WalkRotation_Yaw].Pressure = aPressure;
1361 aWalk[AIS_WalkRotation_Yaw].Duration = aDuration;
1363 if (myKeys.HoldDuration (Aspect_VKey_NavLookUp, aNewEventTime, aDuration, aPressure))
1365 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1366 aWalk[AIS_WalkRotation_Pitch].Value = !myToInvertPitch ? -aProgress : aProgress;
1367 aWalk[AIS_WalkRotation_Pitch].Pressure = aPressure;
1368 aWalk[AIS_WalkRotation_Pitch].Duration = aDuration;
1370 if (myKeys.HoldDuration (Aspect_VKey_NavLookDown, aNewEventTime, aDuration, aPressure))
1372 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1373 aWalk[AIS_WalkRotation_Pitch].Value = !myToInvertPitch ? aProgress : -aProgress;
1374 aWalk[AIS_WalkRotation_Pitch].Pressure = aPressure;
1375 aWalk[AIS_WalkRotation_Pitch].Duration = aDuration;
1377 if (myKeys.HoldDuration (Aspect_VKey_NavRollCCW, aNewEventTime, aDuration, aPressure))
1379 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1380 aWalk[AIS_WalkRotation_Roll].Value = -aProgress;
1381 aWalk[AIS_WalkRotation_Roll].Pressure = aPressure;
1382 aWalk[AIS_WalkRotation_Roll].Duration = aDuration;
1384 if (myKeys.HoldDuration (Aspect_VKey_NavRollCW, aNewEventTime, aDuration, aPressure))
1386 double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure;
1387 aWalk[AIS_WalkRotation_Roll].Value = aProgress;
1388 aWalk[AIS_WalkRotation_Roll].Pressure = aPressure;
1389 aWalk[AIS_WalkRotation_Roll].Duration = aDuration;
1391 if (myKeys.HoldDuration (Aspect_VKey_NavSlideUp, aNewEventTime, aDuration, aPressure))
1393 double aProgress = Abs (Min (aMaxDuration, aDuration));
1394 aWalk[AIS_WalkTranslation_Up].Value = aProgress;
1395 aWalk[AIS_WalkTranslation_Up].Pressure = aPressure;
1396 aWalk[AIS_WalkTranslation_Up].Duration = aDuration;
1398 if (myKeys.HoldDuration (Aspect_VKey_NavSlideDown, aNewEventTime, aDuration, aPressure))
1400 double aProgress = Abs (Min (aMaxDuration, aDuration));
1401 aWalk[AIS_WalkTranslation_Up].Value = -aProgress;
1402 aWalk[AIS_WalkTranslation_Up].Pressure = aPressure;
1403 aWalk[AIS_WalkTranslation_Up].Duration = aDuration;
1408 // =======================================================================
1409 // function : AbortViewAnimation
1411 // =======================================================================
1412 void AIS_ViewController::AbortViewAnimation()
1414 if (!myViewAnimation.IsNull()
1415 && !myViewAnimation->IsStopped())
1417 myViewAnimation->Stop();
1418 myViewAnimation->SetView (Handle(V3d_View)());
1422 // =======================================================================
1423 // function : handlePanning
1425 // =======================================================================
1426 void AIS_ViewController::handlePanning (const Handle(V3d_View)& theView)
1428 if (!myGL.Panning.ToPan
1429 || !myToAllowPanning)
1434 AbortViewAnimation();
1436 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1437 if (aCam->IsOrthographic()
1438 || !hasPanningAnchorPoint())
1440 theView->Pan (myGL.Panning.Delta.x(), myGL.Panning.Delta.y());
1441 theView->Invalidate();
1442 theView->View()->SynchronizeXRPosedToBaseCamera();
1446 Graphic3d_Vec2i aWinSize;
1447 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1449 const gp_Dir& aDir = aCam->Direction();
1450 const gp_Ax3 aCameraCS (aCam->Center(), aDir.Reversed(), aDir ^ aCam->Up());
1451 const gp_XYZ anEyeToPnt = myPanPnt3d.XYZ() - aCam->Eye().XYZ();
1452 const gp_Pnt aViewDims = aCam->ViewDimensions (anEyeToPnt.Dot (aCam->Direction().XYZ())); // view dimensions at 3D point
1453 const Graphic3d_Vec2d aDxy (-aViewDims.X() * myGL.Panning.Delta.x() / double(aWinSize.x()),
1454 -aViewDims.X() * myGL.Panning.Delta.y() / double(aWinSize.x()));
1456 //theView->Translate (aCam, aDxy.x(), aDxy.y());
1458 const gp_Vec aCameraPan = gp_Vec (aCameraCS.XDirection()) * aDxy.x()
1459 + gp_Vec (aCameraCS.YDirection()) * aDxy.y();
1460 aPanTrsf.SetTranslation (aCameraPan);
1461 aCam->Transform (aPanTrsf);
1462 theView->Invalidate();
1463 theView->View()->SynchronizeXRPosedToBaseCamera();
1466 // =======================================================================
1467 // function : handleZRotate
1469 // =======================================================================
1470 void AIS_ViewController::handleZRotate (const Handle(V3d_View)& theView)
1472 if (!myGL.ZRotate.ToRotate
1473 || !myToAllowRotation)
1478 AbortViewAnimation();
1480 Graphic3d_Vec2i aViewPort;
1481 theView->Window()->Size (aViewPort.x(), aViewPort.y());
1482 Graphic3d_Vec2d aRotPnt (0.99 * aViewPort.x(),
1483 0.5 * aViewPort.y());
1484 theView->StartRotation (int(aRotPnt.x()), int(aRotPnt.y()), 0.4);
1485 aRotPnt.y() += myGL.ZRotate.Angle * aViewPort.y();
1486 theView->Rotation (int(aRotPnt.x()), int(aRotPnt.y()));
1487 theView->Invalidate();
1488 theView->View()->SynchronizeXRPosedToBaseCamera();
1491 // =======================================================================
1492 // function : handleZoom
1494 // =======================================================================
1495 void AIS_ViewController::handleZoom (const Handle(V3d_View)& theView,
1496 const Aspect_ScrollDelta& theParams,
1497 const gp_Pnt* thePnt)
1499 if (!myToAllowZooming)
1504 AbortViewAnimation();
1506 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1509 const double aViewDist = Max (myMinCamDistance, (thePnt->XYZ() - aCam->Eye().XYZ()).Modulus());
1510 aCam->SetCenter (aCam->Eye().XYZ() + aCam->Direction().XYZ() * aViewDist);
1513 if (!theParams.HasPoint())
1515 Standard_Real aCoeff = Abs(theParams.Delta) / 100.0 + 1.0;
1516 aCoeff = theParams.Delta > 0.0 ? aCoeff : 1.0 / aCoeff;
1517 theView->SetZoom (aCoeff, true);
1518 theView->Invalidate();
1519 theView->View()->SynchronizeXRPosedToBaseCamera();
1523 // integer delta is too rough for small smooth increments
1524 //theView->StartZoomAtPoint (theParams.Point.x(), theParams.Point.y());
1525 //theView->ZoomAtPoint (0, 0, (int )theParams.Delta, (int )theParams.Delta);
1527 double aDZoom = Abs (theParams.Delta) / 100.0 + 1.0;
1528 aDZoom = (theParams.Delta > 0.0) ? aDZoom : 1.0 / aDZoom;
1534 const Graphic3d_Vec2d aViewDims (aCam->ViewDimensions().X(), aCam->ViewDimensions().Y());
1536 // ensure that zoom will not be too small or too big
1537 double aCoef = aDZoom;
1538 if (aViewDims.x() < aCoef * Precision::Confusion())
1540 aCoef = aViewDims.x() / Precision::Confusion();
1542 else if (aViewDims.x() > aCoef * 1e12)
1544 aCoef = aViewDims.x() / 1e12;
1546 if (aViewDims.y() < aCoef * Precision::Confusion())
1548 aCoef = aViewDims.y() / Precision::Confusion();
1550 else if (aViewDims.y() > aCoef * 1e12)
1552 aCoef = aViewDims.y() / 1e12;
1555 Graphic3d_Vec2d aZoomAtPointXYv (0.0, 0.0);
1556 theView->Convert (theParams.Point.x(), theParams.Point.y(),
1557 aZoomAtPointXYv.x(), aZoomAtPointXYv.y());
1558 Graphic3d_Vec2d aDxy = aZoomAtPointXYv / aCoef;
1559 aCam->SetScale (aCam->Scale() / aCoef);
1561 const gp_Dir& aDir = aCam->Direction();
1562 const gp_Ax3 aCameraCS (aCam->Center(), aDir.Reversed(), aDir ^ aCam->Up());
1564 // pan back to the point
1565 aDxy = aZoomAtPointXYv - aDxy;
1568 // zoom at 3D point with perspective projection
1569 const gp_XYZ anEyeToPnt = thePnt->XYZ() - aCam->Eye().XYZ();
1570 aDxy.SetValues (anEyeToPnt.Dot (aCameraCS.XDirection().XYZ()),
1571 anEyeToPnt.Dot (aCameraCS.YDirection().XYZ()));
1573 // view dimensions at 3D point
1574 const gp_Pnt aViewDims1 = aCam->ViewDimensions (anEyeToPnt.Dot (aCam->Direction().XYZ()));
1576 Graphic3d_Vec2i aWinSize;
1577 theView->Window()->Size (aWinSize.x(), aWinSize.y());
1578 const Graphic3d_Vec2d aPanFromCenterPx (double(theParams.Point.x()) - 0.5 * double(aWinSize.x()),
1579 double(aWinSize.y() - theParams.Point.y() - 1) - 0.5 * double(aWinSize.y()));
1580 aDxy.x() += -aViewDims1.X() * aPanFromCenterPx.x() / double(aWinSize.x());
1581 aDxy.y() += -aViewDims1.Y() * aPanFromCenterPx.y() / double(aWinSize.y());
1584 //theView->Translate (aCam, aDxy.x(), aDxy.y());
1586 const gp_Vec aCameraPan = gp_Vec (aCameraCS.XDirection()) * aDxy.x()
1587 + gp_Vec (aCameraCS.YDirection()) * aDxy.y();
1588 aPanTrsf.SetTranslation (aCameraPan);
1589 aCam->Transform (aPanTrsf);
1590 theView->Invalidate();
1591 theView->View()->SynchronizeXRPosedToBaseCamera();
1594 // =======================================================================
1595 // function : handleZFocusScroll
1597 // =======================================================================
1598 void AIS_ViewController::handleZFocusScroll (const Handle(V3d_View)& theView,
1599 const Aspect_ScrollDelta& theParams)
1601 if (!myToAllowZFocus
1602 || !theView->Camera()->IsStereo())
1607 Standard_Real aFocus = theView->Camera()->ZFocus() + (theParams.Delta > 0.0 ? 0.05 : -0.05);
1611 theView->Camera()->SetZFocus (theView->Camera()->ZFocusType(), aFocus);
1612 theView->Invalidate();
1616 // =======================================================================
1617 // function : handleOrbitRotation
1619 // =======================================================================
1620 void AIS_ViewController::handleOrbitRotation (const Handle(V3d_View)& theView,
1621 const gp_Pnt& thePnt,
1624 if (!myToAllowRotation)
1629 const Handle(Graphic3d_Camera)& aCam = theView->View()->IsActiveXR()
1630 ? theView->View()->BaseXRCamera()
1631 : theView->Camera();
1632 if (myGL.OrbitRotation.ToStart)
1634 // default alternatives
1635 //if (myRotationMode == AIS_RotationMode_BndBoxActive) theView->StartRotation (myGL.RotateAtPoint.x(), myGL.RotateAtPoint.y());
1636 //theView->Rotate (0.0, 0.0, 0.0, thePnt.X(), thePnt.Y(), thePnt.Z(), true);
1638 myRotatePnt3d = thePnt;
1639 myCamStartOpUp = aCam->Up();
1640 myCamStartOpDir = aCam->Direction();
1641 myCamStartOpEye = aCam->Eye();
1642 myCamStartOpCenter = aCam->Center();
1645 aTrsf.SetTransformation (gp_Ax3 (myRotatePnt3d, aCam->OrthogonalizedUp(), aCam->Direction()),
1646 gp_Ax3 (myRotatePnt3d, gp::DZ(), gp::DX()));
1647 const gp_Quaternion aRot = aTrsf.GetRotation();
1648 aRot.GetEulerAngles (gp_YawPitchRoll, myRotateStartYawPitchRoll[0], myRotateStartYawPitchRoll[1], myRotateStartYawPitchRoll[2]);
1651 myCamStartOpToEye = gp_Vec (myRotatePnt3d, aCam->Eye()).Transformed (aTrsf);
1652 myCamStartOpToCenter = gp_Vec (myRotatePnt3d, aCam->Center()).Transformed (aTrsf);
1654 theView->Invalidate();
1657 if (!myGL.OrbitRotation.ToRotate)
1662 AbortViewAnimation();
1665 // amend camera to exclude roll angle (put camera Up vector to plane containing global Z and view direction)
1666 Graphic3d_Vec2i aWinXY;
1667 theView->Window()->Size (aWinXY.x(), aWinXY.y());
1668 double aYawAngleDelta = ((myGL.OrbitRotation.PointStart.x() - myGL.OrbitRotation.PointTo.x()) / double (aWinXY.x())) * (M_PI * 0.5);
1669 double aPitchAngleDelta = -((myGL.OrbitRotation.PointStart.y() - myGL.OrbitRotation.PointTo.y()) / double (aWinXY.y())) * (M_PI * 0.5);
1670 double aPitchAngleNew = 0.0, aRoll = 0.0;
1671 const double aYawAngleNew = myRotateStartYawPitchRoll[0] + aYawAngleDelta;
1672 if (!theView->View()->IsActiveXR())
1674 aPitchAngleNew = Max (Min (myRotateStartYawPitchRoll[1] + aPitchAngleDelta, M_PI * 0.5 - M_PI / 180.0), -M_PI * 0.5 + M_PI / 180.0);
1679 aRot.SetEulerAngles (gp_YawPitchRoll, aYawAngleNew, aPitchAngleNew, aRoll);
1681 aTrsfRot.SetRotation (aRot);
1683 const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot);
1684 aCam->SetUp (aNewUp);
1685 aCam->SetEyeAndCenter (myRotatePnt3d.XYZ() + myCamStartOpToEye .Transformed (aTrsfRot).XYZ(),
1686 myRotatePnt3d.XYZ() + myCamStartOpToCenter.Transformed (aTrsfRot).XYZ());
1688 aCam->OrthogonalizeUp();
1692 // default alternatives
1693 //if (myRotationMode == AIS_RotationMode_BndBoxActive) theView->Rotation (myGL.RotateToPoint.x(), myGL.RotateToPoint.y());
1694 //theView->Rotate (aDX, aDY, aDZ, myRotatePnt3d.X(), myRotatePnt3d.Y(), myRotatePnt3d.Z(), false);
1696 // restore previous camera state
1697 aCam->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter);
1698 aCam->SetUp (myCamStartOpUp);
1699 aCam->SetDirectionFromEye (myCamStartOpDir);
1701 Graphic3d_Vec2d aWinXY;
1702 theView->Size (aWinXY.x(), aWinXY.y());
1703 const Standard_Real rx = (Standard_Real )theView->Convert (aWinXY.x());
1704 const Standard_Real ry = (Standard_Real )theView->Convert (aWinXY.y());
1706 const double THE_2PI = M_PI * 2.0;
1707 double aDX = (myGL.OrbitRotation.PointTo.x() - myGL.OrbitRotation.PointStart.x()) * M_PI / rx;
1708 double aDY = (myGL.OrbitRotation.PointStart.y() - myGL.OrbitRotation.PointTo.y()) * M_PI / ry;
1710 if (aDX > 0.0) { while (aDX > THE_2PI) { aDX -= THE_2PI; } }
1711 else if(aDX < 0.0) { while (aDX < -THE_2PI) { aDX += THE_2PI; } }
1712 if (aDY > 0.0) { while (aDY > THE_2PI) { aDY -= THE_2PI; } }
1713 else if(aDY < 0.0) { while (aDY < -THE_2PI) { aDY += THE_2PI; } }
1715 // rotate camera around 3 initial axes
1716 gp_Dir aCamDir (aCam->Direction().Reversed());
1717 gp_Dir aCamUp (aCam->Up());
1718 gp_Dir aCamSide(aCamUp.Crossed (aCamDir));
1720 gp_Trsf aRot[2], aTrsf;
1721 aRot[0].SetRotation (gp_Ax1 (myRotatePnt3d, aCamUp), -aDX);
1722 aRot[1].SetRotation (gp_Ax1 (myRotatePnt3d, aCamSide), aDY);
1723 aTrsf.Multiply (aRot[0]);
1724 aTrsf.Multiply (aRot[1]);
1726 aCam->Transform (aTrsf);
1729 theView->Invalidate();
1730 theView->View()->SynchronizeXRBaseToPosedCamera();
1733 // =======================================================================
1734 // function : handleViewRotation
1736 // =======================================================================
1737 void AIS_ViewController::handleViewRotation (const Handle(V3d_View)& theView,
1739 double thePitchExtra,
1741 bool theToRestartOnIncrement)
1743 if (!myToAllowRotation)
1748 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1749 const bool toRotateAnyway = Abs (theYawExtra) > gp::Resolution()
1750 || Abs (thePitchExtra) > gp::Resolution()
1751 || Abs (theRoll - myRotateStartYawPitchRoll[2]) > gp::Resolution();
1753 && theToRestartOnIncrement)
1755 myGL.ViewRotation.ToStart = true;
1756 myGL.ViewRotation.PointTo = myGL.ViewRotation.PointStart;
1758 if (myGL.ViewRotation.ToStart)
1761 aTrsf.SetTransformation (gp_Ax3 (gp::Origin(), aCam->OrthogonalizedUp(), aCam->Direction()),
1762 gp_Ax3 (gp::Origin(), gp::DZ(), gp::DX()));
1763 const gp_Quaternion aRot = aTrsf.GetRotation();
1764 double aRollDummy = 0.0;
1765 aRot.GetEulerAngles (gp_YawPitchRoll, myRotateStartYawPitchRoll[0], myRotateStartYawPitchRoll[1], aRollDummy);
1769 myRotateStartYawPitchRoll[0] += theYawExtra;
1770 myRotateStartYawPitchRoll[1] += thePitchExtra;
1771 myRotateStartYawPitchRoll[2] = theRoll;
1772 myGL.ViewRotation.ToRotate = true;
1775 if (!myGL.ViewRotation.ToRotate)
1780 AbortViewAnimation();
1782 Graphic3d_Vec2i aWinXY;
1783 theView->Window()->Size (aWinXY.x(), aWinXY.y());
1784 double aYawAngleDelta = ((myGL.ViewRotation.PointStart.x() - myGL.ViewRotation.PointTo.x()) / double (aWinXY.x())) * (M_PI * 0.5);
1785 double aPitchAngleDelta = -((myGL.ViewRotation.PointStart.y() - myGL.ViewRotation.PointTo.y()) / double (aWinXY.y())) * (M_PI * 0.5);
1786 const double aPitchAngleNew = Max (Min (myRotateStartYawPitchRoll[1] + aPitchAngleDelta, M_PI * 0.5 - M_PI / 180.0), -M_PI * 0.5 + M_PI / 180.0);
1787 const double aYawAngleNew = myRotateStartYawPitchRoll[0] + aYawAngleDelta;
1789 aRot.SetEulerAngles (gp_YawPitchRoll, aYawAngleNew, aPitchAngleNew, theRoll);
1791 aTrsfRot.SetRotation (aRot);
1793 const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot);
1794 const gp_Dir aNewDir = gp::DX().Transformed (aTrsfRot);
1795 aCam->SetUp (aNewUp);
1796 aCam->SetDirectionFromEye (aNewDir);
1797 aCam->OrthogonalizeUp();
1798 theView->Invalidate();
1801 // =======================================================================
1802 // function : PickPoint
1804 // =======================================================================
1805 bool AIS_ViewController::PickPoint (gp_Pnt& thePnt,
1806 const Handle(AIS_InteractiveContext)& theCtx,
1807 const Handle(V3d_View)& theView,
1808 const Graphic3d_Vec2i& theCursor,
1809 bool theToStickToPickRay)
1811 ResetPreviousMoveTo();
1813 const Handle(StdSelect_ViewerSelector3d)& aSelector = theCtx->MainSelector();
1814 aSelector->Pick (theCursor.x(), theCursor.y(), theView);
1815 if (aSelector->NbPicked() < 1)
1820 const SelectMgr_SortCriterion& aPicked = aSelector->PickedData (1);
1821 if (theToStickToPickRay
1822 && !Precision::IsInfinite (aPicked.Depth))
1824 thePnt = aSelector->GetManager().DetectedPoint (aPicked.Depth);
1828 thePnt = aSelector->PickedPoint (1);
1830 return !Precision::IsInfinite (thePnt.X())
1831 && !Precision::IsInfinite (thePnt.Y())
1832 && !Precision::IsInfinite (thePnt.Z());
1835 // =======================================================================
1836 // function : GravityPoint
1838 // =======================================================================
1839 gp_Pnt AIS_ViewController::GravityPoint (const Handle(AIS_InteractiveContext)& theCtx,
1840 const Handle(V3d_View)& theView)
1842 switch (myRotationMode)
1844 case AIS_RotationMode_PickLast:
1845 case AIS_RotationMode_PickCenter:
1847 Graphic3d_Vec2i aCursor ((int )myGL.OrbitRotation.PointStart.x(), (int )myGL.OrbitRotation.PointStart.y());
1848 if (myRotationMode == AIS_RotationMode_PickCenter)
1850 Graphic3d_Vec2i aViewPort;
1851 theView->Window()->Size (aViewPort.x(), aViewPort.y());
1852 aCursor = aViewPort / 2;
1856 if (PickPoint (aPnt, theCtx, theView, aCursor, myToStickToRayOnRotation))
1862 case AIS_RotationMode_CameraAt:
1864 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1865 return aCam->Center();
1867 case AIS_RotationMode_BndBoxScene:
1869 Bnd_Box aBndBox = theView->View()->MinMaxValues (false);
1870 if (!aBndBox.IsVoid())
1872 return (aBndBox.CornerMin().XYZ() + aBndBox.CornerMax().XYZ()) * 0.5;
1876 case AIS_RotationMode_BndBoxActive:
1880 return theCtx ->GravityPoint (theView);
1883 // =======================================================================
1884 // function : FitAllAuto
1886 // =======================================================================
1887 void AIS_ViewController::FitAllAuto (const Handle(AIS_InteractiveContext)& theCtx,
1888 const Handle(V3d_View)& theView)
1890 const Bnd_Box aBoxSel = theCtx->BoundingBoxOfSelection();
1891 const double aFitMargin = 0.01;
1892 if (aBoxSel.IsVoid())
1894 theView->FitAll (aFitMargin, false);
1898 // fit all algorithm is not 100% stable - so compute some precision to compare equal camera values
1899 const double aFitTol = (aBoxSel.CornerMax().XYZ() - aBoxSel.CornerMin().XYZ()).Modulus() * 0.000001;
1900 const Bnd_Box aBoxAll = theView->View()->MinMaxValues();
1902 const Handle(Graphic3d_Camera)& aCam = theView->Camera();
1903 Handle(Graphic3d_Camera) aCameraSel = new Graphic3d_Camera (aCam);
1904 Handle(Graphic3d_Camera) aCameraAll = new Graphic3d_Camera (aCam);
1905 theView->FitMinMax (aCameraSel, aBoxSel, aFitMargin);
1906 theView->FitMinMax (aCameraAll, aBoxAll, aFitMargin);
1907 if (aCameraSel->Center().IsEqual (aCam->Center(), aFitTol)
1908 && Abs (aCameraSel->Scale() - aCam->Scale()) < aFitTol
1909 && Abs (aCameraSel->Distance() - aCam->Distance()) < aFitTol)
1911 // fit all entire view on second FitALL request
1912 aCam->Copy (aCameraAll);
1916 aCam->Copy (aCameraSel);
1920 // =======================================================================
1921 // function : handleViewOrientationKeys
1923 // =======================================================================
1924 void AIS_ViewController::handleViewOrientationKeys (const Handle(AIS_InteractiveContext)& theCtx,
1925 const Handle(V3d_View)& theView)
1927 if (myNavigationMode == AIS_NavigationMode_FirstPersonWalk)
1932 Handle(Graphic3d_Camera) aCameraBack;
1933 struct ViewKeyAction
1936 V3d_TypeOfOrientation Orientation;
1938 static const ViewKeyAction THE_VIEW_KEYS[] =
1940 { Aspect_VKey_ViewTop, V3d_TypeOfOrientation_Zup_Top },
1941 { Aspect_VKey_ViewBottom, V3d_TypeOfOrientation_Zup_Bottom },
1942 { Aspect_VKey_ViewLeft, V3d_TypeOfOrientation_Zup_Left },
1943 { Aspect_VKey_ViewRight, V3d_TypeOfOrientation_Zup_Right },
1944 { Aspect_VKey_ViewFront, V3d_TypeOfOrientation_Zup_Front },
1945 { Aspect_VKey_ViewBack, V3d_TypeOfOrientation_Zup_Back },
1946 { Aspect_VKey_ViewAxoLeftProj, V3d_TypeOfOrientation_Zup_AxoLeft },
1947 { Aspect_VKey_ViewAxoRightProj, V3d_TypeOfOrientation_Zup_AxoRight },
1948 { Aspect_VKey_ViewRoll90CW, (V3d_TypeOfOrientation )-1},
1949 { Aspect_VKey_ViewRoll90CCW, (V3d_TypeOfOrientation )-1},
1950 { Aspect_VKey_ViewFitAll, (V3d_TypeOfOrientation )-1}
1953 Standard_Mutex::Sentry aLock (myKeys.Mutex());
1954 const size_t aNbKeys = sizeof(THE_VIEW_KEYS) / sizeof(*THE_VIEW_KEYS);
1955 const double anEventTime = EventTime();
1956 for (size_t aKeyIter = 0; aKeyIter < aNbKeys; ++aKeyIter)
1958 const ViewKeyAction& aKeyAction = THE_VIEW_KEYS[aKeyIter];
1959 if (!myKeys.IsKeyDown (aKeyAction.Key))
1964 myKeys.KeyUp (aKeyAction.Key, anEventTime);
1965 if (aCameraBack.IsNull())
1967 aCameraBack = theView->Camera();
1968 theView->SetCamera (new Graphic3d_Camera (aCameraBack));
1970 if (aKeyAction.Orientation != (V3d_TypeOfOrientation )-1)
1972 theView->SetProj (aKeyAction.Orientation);
1973 FitAllAuto (theCtx, theView);
1975 else if (aKeyAction.Key == Aspect_VKey_ViewRoll90CW)
1977 const double aTwist = theView->Twist() + M_PI / 2.0;
1978 theView->SetTwist (aTwist);
1980 else if (aKeyAction.Key == Aspect_VKey_ViewRoll90CCW)
1982 const double aTwist = theView->Twist() - M_PI / 2.0;
1983 theView->SetTwist (aTwist);
1985 else if (aKeyAction.Key == Aspect_VKey_ViewFitAll)
1987 FitAllAuto (theCtx, theView);
1992 if (aCameraBack.IsNull())
1997 Handle(Graphic3d_Camera) aCameraNew = theView->Camera();
1998 theView->SetCamera (aCameraBack);
1999 const Graphic3d_Mat4d anOrientMat1 = aCameraBack->OrientationMatrix();
2000 const Graphic3d_Mat4d anOrientMat2 = aCameraNew ->OrientationMatrix();
2001 if (anOrientMat1 != anOrientMat2)
2003 const Handle(AIS_AnimationCamera)& aCamAnim = myViewAnimation;
2004 aCamAnim->SetView (theView);
2005 aCamAnim->SetStartPts (0.0);
2006 aCamAnim->SetCameraStart (new Graphic3d_Camera (aCameraBack));
2007 aCamAnim->SetCameraEnd (new Graphic3d_Camera (aCameraNew));
2008 aCamAnim->StartTimer (0.0, 1.0, true, false);
2012 // =======================================================================
2013 // function : handleNavigationKeys
2015 // =======================================================================
2016 AIS_WalkDelta AIS_ViewController::handleNavigationKeys (const Handle(AIS_InteractiveContext)& ,
2017 const Handle(V3d_View)& theView)
2020 double aCrouchRatio = 1.0, aRunRatio = 1.0;
2021 if (myNavigationMode == AIS_NavigationMode_FirstPersonFlight)
2026 const double aRotSpeed = 0.5;
2027 const double aWalkSpeedCoef = WalkSpeedRelative();
2028 AIS_WalkDelta aWalk = FetchNavigationKeys (aCrouchRatio, aRunRatio);
2029 if (aWalk.IsJumping())
2033 theView->Invalidate();
2035 if (aWalk.IsEmpty())
2039 else if (myGL.OrbitRotation.ToRotate
2040 || myGL.OrbitRotation.ToStart)
2046 const Bnd_Box aBndBox = theView->View()->MinMaxValues();
2047 if (!aBndBox.IsVoid())
2049 aMin = aBndBox.CornerMin().XYZ();
2050 aMax = aBndBox.CornerMax().XYZ();
2052 double aBndDiam = Max (Max (aMax.X() - aMin.X(), aMax.Y() - aMin.Y()), aMax.Z() - aMin.Z());
2053 if (aBndDiam <= gp::Resolution())
2058 const double aWalkSpeed = myNavigationMode != AIS_NavigationMode_Orbit
2059 && myNavigationMode != AIS_NavigationMode_FirstPersonFlight
2060 ? theView->View()->UnitFactor() * WalkSpeedAbsolute()
2061 : aWalkSpeedCoef * aBndDiam;
2062 const Handle(Graphic3d_Camera)& aCam = theView->View()->IsActiveXR()
2063 ? theView->View()->BaseXRCamera()
2064 : theView->Camera();
2066 // move forward in plane XY and up along Z
2067 const gp_Dir anUp = ToLockOrbitZUp() ? gp::DZ() : aCam->OrthogonalizedUp();
2069 && myToAllowPanning)
2071 const gp_Vec aSide = -aCam->SideRight();
2072 gp_XYZ aFwd = aCam->Direction().XYZ();
2073 aFwd -= anUp.XYZ() * (anUp.XYZ() * aFwd);
2076 if (!aWalk[AIS_WalkTranslation_Forward].IsEmpty())
2078 if (!aCam->IsOrthographic())
2080 aMoveVec += aFwd * aWalk[AIS_WalkTranslation_Forward].Value * aWalk[AIS_WalkTranslation_Forward].Pressure * aWalkSpeed;
2083 if (!aWalk[AIS_WalkTranslation_Side].IsEmpty())
2085 aMoveVec += aSide.XYZ() * aWalk[AIS_WalkTranslation_Side].Value * aWalk[AIS_WalkTranslation_Side].Pressure * aWalkSpeed;
2087 if (!aWalk[AIS_WalkTranslation_Up].IsEmpty())
2089 aMoveVec += anUp.XYZ() * aWalk[AIS_WalkTranslation_Up].Value * aWalk[AIS_WalkTranslation_Up].Pressure * aWalkSpeed;
2092 if (aCam->IsOrthographic())
2094 if (!aWalk[AIS_WalkTranslation_Forward].IsEmpty())
2096 const double aZoomDelta = aWalk[AIS_WalkTranslation_Forward].Value * aWalk[AIS_WalkTranslation_Forward].Pressure * aWalkSpeedCoef;
2097 handleZoom (theView, Aspect_ScrollDelta (aZoomDelta * 100.0), NULL);
2101 gp_Trsf aTrsfTranslate;
2102 aTrsfTranslate.SetTranslation (aMoveVec);
2103 aCam->Transform (aTrsfTranslate);
2107 if (myNavigationMode == AIS_NavigationMode_Orbit
2108 && myToAllowRotation)
2110 if (!aWalk[AIS_WalkRotation_Yaw].IsEmpty())
2113 aTrsfRot.SetRotation (gp_Ax1 (aCam->Eye(), anUp), aWalk[AIS_WalkRotation_Yaw].Value * aRotSpeed);
2114 aCam->Transform (aTrsfRot);
2116 if (!aWalk[AIS_WalkRotation_Pitch].IsEmpty())
2118 const gp_Vec aSide = -aCam->SideRight();
2120 aTrsfRot.SetRotation (gp_Ax1 (aCam->Eye(), aSide), -aWalk[AIS_WalkRotation_Pitch].Value * aRotSpeed);
2121 aCam->Transform (aTrsfRot);
2123 if (!aWalk[AIS_WalkRotation_Roll].IsEmpty()
2124 && !ToLockOrbitZUp())
2127 aTrsfRot.SetRotation (gp_Ax1 (aCam->Center(), aCam->Direction()), aWalk[AIS_WalkRotation_Roll].Value * aRotSpeed);
2128 aCam->Transform (aTrsfRot);
2134 theView->Invalidate();
2135 theView->View()->SynchronizeXRBaseToPosedCamera();
2139 // =======================================================================
2140 // function : handleCameraActions
2142 // =======================================================================
2143 void AIS_ViewController::handleCameraActions (const Handle(AIS_InteractiveContext)& theCtx,
2144 const Handle(V3d_View)& theView,
2145 const AIS_WalkDelta& theWalk)
2147 // apply view actions
2148 if (myGL.Orientation.ToSetViewOrient)
2150 theView->SetProj (myGL.Orientation.ViewOrient);
2151 myGL.Orientation.ToFitAll = true;
2155 if (myGL.Orientation.ToFitAll)
2157 const double aFitMargin = 0.01;
2158 theView->FitAll (aFitMargin, false);
2159 theView->Invalidate();
2160 myGL.Orientation.ToFitAll = false;
2163 if (myGL.IsNewGesture)
2165 if (myAnchorPointPrs1->HasInteractiveContext())
2167 theCtx->Remove (myAnchorPointPrs1, false);
2168 if (!theView->Viewer()->ZLayerSettings (myAnchorPointPrs1->ZLayer()).IsImmediate())
2170 theView->Invalidate();
2174 theView->InvalidateImmediate();
2177 if (myAnchorPointPrs2->HasInteractiveContext())
2179 theCtx->Remove (myAnchorPointPrs2, false);
2180 if (!theView->Viewer()->ZLayerSettings (myAnchorPointPrs2->ZLayer()).IsImmediate())
2182 theView->Invalidate();
2186 theView->InvalidateImmediate();
2190 if (myHasHlrOnBeforeRotation)
2192 myHasHlrOnBeforeRotation = false;
2193 theView->SetComputedMode (true);
2194 theView->Invalidate();
2198 if (myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
2200 if (myGL.Panning.ToStart
2201 && myToAllowPanning)
2203 gp_Pnt aPanPnt (Precision::Infinite(), 0.0, 0.0);
2204 if (!theView->Camera()->IsOrthographic())
2206 bool toStickToRay = false;
2207 if (myGL.Panning.PointStart.x() >= 0
2208 && myGL.Panning.PointStart.y() >= 0)
2210 PickPoint (aPanPnt, theCtx, theView, myGL.Panning.PointStart, toStickToRay);
2212 if (Precision::IsInfinite (aPanPnt.X()))
2214 Graphic3d_Vec2i aWinSize;
2215 theView->Window()->Size (aWinSize.x(), aWinSize.y());
2216 PickPoint (aPanPnt, theCtx, theView, aWinSize / 2, toStickToRay);
2218 if (!Precision::IsInfinite (aPanPnt.X())
2219 && myToShowPanAnchorPoint)
2222 aPntTrsf.SetTranslation (gp_Vec (aPanPnt.XYZ()));
2223 theCtx->SetLocation (myAnchorPointPrs2, aPntTrsf);
2226 setPanningAnchorPoint (aPanPnt);
2229 if (myToShowPanAnchorPoint
2230 && hasPanningAnchorPoint()
2231 && myGL.Panning.ToPan
2232 && !myGL.IsNewGesture
2233 && !myAnchorPointPrs2->HasInteractiveContext())
2235 theCtx->Display (myAnchorPointPrs2, 0, -1, false, AIS_DS_Displayed);
2238 handlePanning (theView);
2239 handleZRotate (theView);
2242 if ((myNavigationMode == AIS_NavigationMode_Orbit
2243 || myGL.OrbitRotation.ToStart
2244 || myGL.OrbitRotation.ToRotate)
2245 && myToAllowRotation)
2247 if (myGL.OrbitRotation.ToStart
2248 && !myHasHlrOnBeforeRotation)
2250 myHasHlrOnBeforeRotation = theView->ComputedMode();
2251 if (myHasHlrOnBeforeRotation)
2253 theView->SetComputedMode (false);
2258 if (myGL.OrbitRotation.ToStart)
2260 aGravPnt = GravityPoint (theCtx, theView);
2261 if (myToShowRotateCenter)
2264 aPntTrsf.SetTranslation (gp_Vec (aGravPnt.XYZ()));
2265 theCtx->SetLocation (myAnchorPointPrs1, aPntTrsf);
2266 theCtx->SetLocation (myAnchorPointPrs2, aPntTrsf);
2270 if (myToShowRotateCenter
2271 && myGL.OrbitRotation.ToRotate
2272 && !myGL.IsNewGesture
2273 && !myAnchorPointPrs1->HasInteractiveContext())
2275 theCtx->Display (myAnchorPointPrs1, 0, -1, false, AIS_DS_Displayed);
2276 theCtx->Display (myAnchorPointPrs2, 0, -1, false, AIS_DS_Displayed);
2278 handleOrbitRotation (theView, aGravPnt,
2279 myToLockOrbitZUp || myNavigationMode != AIS_NavigationMode_Orbit);
2282 if ((myNavigationMode != AIS_NavigationMode_Orbit
2283 || myGL.ViewRotation.ToStart
2284 || myGL.ViewRotation.ToRotate)
2285 && myToAllowRotation)
2287 if (myGL.ViewRotation.ToStart
2288 && !myHasHlrOnBeforeRotation)
2290 myHasHlrOnBeforeRotation = theView->ComputedMode();
2291 if (myHasHlrOnBeforeRotation)
2293 theView->SetComputedMode (false);
2298 if (!theWalk[AIS_WalkRotation_Roll].IsEmpty()
2299 && !myToLockOrbitZUp)
2301 aRoll = (M_PI / 12.0) * theWalk[AIS_WalkRotation_Roll].Pressure;
2302 aRoll *= Min (1000.0 * theWalk[AIS_WalkRotation_Roll].Duration, 100.0) / 100.0;
2303 if (theWalk[AIS_WalkRotation_Roll].Value < 0.0)
2309 handleViewRotation (theView, theWalk[AIS_WalkRotation_Yaw].Value, theWalk[AIS_WalkRotation_Pitch].Value, aRoll,
2310 myNavigationMode == AIS_NavigationMode_FirstPersonFlight);
2313 if (!myGL.ZoomActions.IsEmpty())
2315 for (NCollection_Sequence<Aspect_ScrollDelta>::Iterator aZoomIter (myGL.ZoomActions); aZoomIter.More(); aZoomIter.Next())
2317 Aspect_ScrollDelta aZoomParams = aZoomIter.Value();
2319 && (aZoomParams.Flags & Aspect_VKeyFlags_CTRL) != 0
2320 && theView->Camera()->IsStereo())
2322 handleZFocusScroll (theView, aZoomParams);
2326 if (!myToAllowZooming)
2331 if (!theView->Camera()->IsOrthographic())
2334 if (aZoomParams.HasPoint()
2335 && PickPoint (aPnt, theCtx, theView, aZoomParams.Point, myToStickToRayOnZoom))
2337 handleZoom (theView, aZoomParams, &aPnt);
2341 Graphic3d_Vec2i aWinSize;
2342 theView->Window()->Size (aWinSize.x(), aWinSize.y());
2343 if (PickPoint (aPnt, theCtx, theView, aWinSize / 2, myToStickToRayOnZoom))
2345 aZoomParams.ResetPoint(); // do not pretend to zoom at 'nothing'
2346 handleZoom (theView, aZoomParams, &aPnt);
2350 handleZoom (theView, aZoomParams, NULL);
2352 myGL.ZoomActions.Clear();
2356 // =======================================================================
2357 // function : handleXRInput
2359 // =======================================================================
2360 void AIS_ViewController::handleXRInput (const Handle(AIS_InteractiveContext)& theCtx,
2361 const Handle(V3d_View)& theView,
2362 const AIS_WalkDelta& )
2364 theView->View()->ProcessXRInput();
2365 if (!theView->View()->IsActiveXR())
2369 if (myXRCameraTmp.IsNull())
2371 myXRCameraTmp = new Graphic3d_Camera();
2373 handleXRTurnPad (theCtx, theView);
2374 handleXRTeleport(theCtx, theView);
2375 handleXRPicking (theCtx, theView);
2378 // =======================================================================
2379 // function : handleXRTurnPad
2381 // =======================================================================
2382 void AIS_ViewController::handleXRTurnPad (const Handle(AIS_InteractiveContext)& ,
2383 const Handle(V3d_View)& theView)
2385 if (myXRTurnAngle <= 0.0
2386 || !theView->View()->IsActiveXR())
2391 // turn left/right at 45 degrees on left/right trackpad clicks
2392 for (int aHand = 0; aHand < 2; ++aHand)
2394 const Aspect_XRTrackedDeviceRole aRole = aHand == 0 ? Aspect_XRTrackedDeviceRole_RightHand : Aspect_XRTrackedDeviceRole_LeftHand;
2395 const Handle(Aspect_XRAction)& aPadClickAct = theView->View()->XRSession()->GenericAction (aRole, Aspect_XRGenericAction_InputTrackPadClick);
2396 const Handle(Aspect_XRAction)& aPadPosAct = theView->View()->XRSession()->GenericAction (aRole, Aspect_XRGenericAction_InputTrackPadPosition);
2397 if (aPadClickAct.IsNull()
2398 || aPadPosAct.IsNull())
2403 const Aspect_XRDigitalActionData aPadClick = theView->View()->XRSession()->GetDigitalActionData (aPadClickAct);
2404 const Aspect_XRAnalogActionData aPadPos = theView->View()->XRSession()->GetAnalogActionData (aPadPosAct);
2405 if (aPadClick.IsActive
2406 && aPadClick.IsPressed
2407 && aPadClick.IsChanged
2409 && Abs (aPadPos.VecXYZ.y()) < 0.5f
2410 && Abs (aPadPos.VecXYZ.x()) > 0.7f)
2413 aTrsfTurn.SetRotation (gp_Ax1 (gp::Origin(), theView->View()->BaseXRCamera()->Up()), aPadPos.VecXYZ.x() < 0.0f ? myXRTurnAngle : -myXRTurnAngle);
2414 theView->View()->TurnViewXRCamera (aTrsfTurn);
2420 // =======================================================================
2421 // function : handleXRTeleport
2423 // =======================================================================
2424 void AIS_ViewController::handleXRTeleport (const Handle(AIS_InteractiveContext)& theCtx,
2425 const Handle(V3d_View)& theView)
2427 if (!theView->View()->IsActiveXR())
2432 // teleport on forward trackpad unclicks
2433 const Aspect_XRTrackedDeviceRole aTeleOld = myXRLastTeleportHand;
2434 myXRLastTeleportHand = Aspect_XRTrackedDeviceRole_Other;
2435 for (int aHand = 0; aHand < 2; ++aHand)
2437 const Aspect_XRTrackedDeviceRole aRole = aHand == 0 ? Aspect_XRTrackedDeviceRole_RightHand : Aspect_XRTrackedDeviceRole_LeftHand;
2438 const Standard_Integer aDeviceId = theView->View()->XRSession()->NamedTrackedDevice (aRole);
2439 if (aDeviceId == -1)
2444 const Handle(Aspect_XRAction)& aPadClickAct = theView->View()->XRSession()->GenericAction (aRole, Aspect_XRGenericAction_InputTrackPadClick);
2445 const Handle(Aspect_XRAction)& aPadPosAct = theView->View()->XRSession()->GenericAction (aRole, Aspect_XRGenericAction_InputTrackPadPosition);
2446 if (aPadClickAct.IsNull()
2447 || aPadPosAct.IsNull())
2452 const Aspect_XRDigitalActionData aPadClick = theView->View()->XRSession()->GetDigitalActionData (aPadClickAct);
2453 const Aspect_XRAnalogActionData aPadPos = theView->View()->XRSession()->GetAnalogActionData (aPadPosAct);
2454 const bool isPressed = aPadClick.IsPressed;
2455 const bool isClicked = !aPadClick.IsPressed
2456 && aPadClick.IsChanged;
2457 if (aPadClick.IsActive
2458 && (isPressed || isClicked)
2460 && aPadPos.VecXYZ.y() > 0.6f
2461 && Abs (aPadPos.VecXYZ.x()) < 0.5f)
2463 const Aspect_TrackedDevicePose& aPose = theView->View()->XRSession()->TrackedPoses()[aDeviceId];
2464 if (!aPose.IsValidPose)
2469 myXRLastTeleportHand = aRole;
2470 Standard_Real& aPickDepth = aRole == Aspect_XRTrackedDeviceRole_LeftHand ? myXRLastPickDepthLeft : myXRLastPickDepthRight;
2471 aPickDepth = Precision::Infinite();
2472 Graphic3d_Vec3 aPickNorm;
2473 const gp_Trsf aHandBase = theView->View()->PoseXRToWorld (aPose.Orientation);
2474 const Standard_Real aHeadHeight = theView->View()->XRSession()->HeadPose().TranslationPart().Y();
2476 const Standard_Integer aPickedId = handleXRMoveTo (theCtx, theView, aPose.Orientation, false);
2479 const SelectMgr_SortCriterion& aPickedData = theCtx->MainSelector()->PickedData (aPickedId);
2480 aPickNorm = aPickedData.Normal;
2481 if (aPickNorm.SquareModulus() > ShortRealEpsilon())
2483 aPickDepth = aPickedData.Point.Distance (aHandBase.TranslationPart());
2489 myXRLastTeleportHand = Aspect_XRTrackedDeviceRole_Other;
2490 if (!Precision::IsInfinite (aPickDepth))
2492 const gp_Dir aTeleDir = -gp::DZ().Transformed (aHandBase);
2493 const gp_Dir anUpDir = theView->View()->BaseXRCamera()->Up();
2495 bool isHorizontal = false;
2496 gp_Dir aPickNormDir (aPickNorm.x(), aPickNorm.y(), aPickNorm.z());
2497 if (anUpDir.IsEqual ( aPickNormDir, M_PI_4)
2498 || anUpDir.IsEqual (-aPickNormDir, M_PI_4))
2500 isHorizontal = true;
2503 gp_Pnt aNewEye = aHandBase.TranslationPart();
2506 aNewEye = aHandBase.TranslationPart()
2507 + aTeleDir.XYZ() * aPickDepth
2508 + anUpDir.XYZ() * aHeadHeight;
2512 if (aPickNormDir.Dot (aTeleDir) < 0.0)
2514 aPickNormDir.Reverse();
2516 aNewEye = aHandBase.TranslationPart()
2517 + aTeleDir.XYZ() * aPickDepth
2518 - aPickNormDir.XYZ() * aHeadHeight / 4;
2521 theView->View()->PosedXRCamera()->MoveEyeTo (aNewEye);
2522 theView->View()->ComputeXRBaseCameraFromPosed (theView->View()->PosedXRCamera(), theView->View()->XRSession()->HeadPose());
2529 if (myXRLastTeleportHand != aTeleOld)
2531 if (aTeleOld != Aspect_XRTrackedDeviceRole_Other)
2533 if (const Handle(Aspect_XRAction)& aHaptic = theView->View()->XRSession()->GenericAction (aTeleOld, Aspect_XRGenericAction_OutputHaptic))
2535 theView->View()->XRSession()->AbortHapticVibrationAction (aHaptic);
2538 if (myXRLastTeleportHand != Aspect_XRTrackedDeviceRole_Other)
2540 if (const Handle(Aspect_XRAction)& aHaptic = theView->View()->XRSession()->GenericAction (myXRLastTeleportHand, Aspect_XRGenericAction_OutputHaptic))
2542 theView->View()->XRSession()->TriggerHapticVibrationAction (aHaptic, myXRTeleportHaptic);
2548 // =======================================================================
2549 // function : handleXRPicking
2551 // =======================================================================
2552 void AIS_ViewController::handleXRPicking (const Handle(AIS_InteractiveContext)& theCtx,
2553 const Handle(V3d_View)& theView)
2555 if (!theView->View()->IsActiveXR())
2560 // handle selection on trigger clicks
2561 Aspect_XRTrackedDeviceRole aPickDevOld = myXRLastPickingHand;
2562 myXRLastPickingHand = Aspect_XRTrackedDeviceRole_Other;
2563 for (int aHand = 0; aHand < 2; ++aHand)
2565 const Aspect_XRTrackedDeviceRole aRole = aHand == 0 ? Aspect_XRTrackedDeviceRole_RightHand : Aspect_XRTrackedDeviceRole_LeftHand;
2566 const Handle(Aspect_XRAction)& aTrigClickAct = theView->View()->XRSession()->GenericAction (aRole, Aspect_XRGenericAction_InputTriggerClick);
2567 const Handle(Aspect_XRAction)& aTrigPullAct = theView->View()->XRSession()->GenericAction (aRole, Aspect_XRGenericAction_InputTriggerPull);
2568 if (aTrigClickAct.IsNull()
2569 || aTrigPullAct.IsNull())
2574 const Aspect_XRDigitalActionData aTrigClick = theView->View()->XRSession()->GetDigitalActionData (aTrigClickAct);
2575 const Aspect_XRAnalogActionData aTrigPos = theView->View()->XRSession()->GetAnalogActionData (aTrigPullAct);
2576 if (aTrigPos.IsActive
2577 && Abs (aTrigPos.VecXYZ.x()) > 0.1f)
2579 myXRLastPickingHand = aRole;
2580 handleXRHighlight (theCtx, theView);
2581 if (aTrigClick.IsActive
2582 && aTrigClick.IsPressed
2583 && aTrigClick.IsChanged)
2585 theCtx->SelectDetected();
2586 OnSelectionChanged (theCtx, theView);
2587 if (const Handle(Aspect_XRAction)& aHaptic = theView->View()->XRSession()->GenericAction (myXRLastPickingHand, Aspect_XRGenericAction_OutputHaptic))
2589 theView->View()->XRSession()->TriggerHapticVibrationAction (aHaptic, myXRSelectHaptic);
2595 if (myXRLastPickingHand != aPickDevOld)
2597 theCtx->ClearDetected();
2601 // =======================================================================
2602 // function : OnSelectionChanged
2604 // =======================================================================
2605 void AIS_ViewController::OnSelectionChanged (const Handle(AIS_InteractiveContext)& ,
2606 const Handle(V3d_View)& )
2611 // =======================================================================
2612 // function : OnObjectDragged
2614 // =======================================================================
2615 void AIS_ViewController::OnObjectDragged (const Handle(AIS_InteractiveContext)& theCtx,
2616 const Handle(V3d_View)& theView,
2617 AIS_DragAction theAction)
2621 case AIS_DragAction_Start:
2623 myDragObject.Nullify();
2624 myDragOwner.Nullify();
2625 if (!theCtx->HasDetected())
2630 const Handle(SelectMgr_EntityOwner)& aDetectedOwner = theCtx->DetectedOwner();
2631 Handle(AIS_InteractiveObject) aDetectedPrs = Handle(AIS_InteractiveObject)::DownCast (aDetectedOwner->Selectable());
2633 if (aDetectedPrs->ProcessDragging (theCtx, theView, aDetectedOwner, myGL.Dragging.PointStart,
2634 myGL.Dragging.PointTo, theAction))
2636 myDragObject = aDetectedPrs;
2637 myDragOwner = aDetectedOwner;
2641 case AIS_DragAction_Update:
2643 if (myDragObject.IsNull())
2648 if (Handle(SelectMgr_EntityOwner) aGlobOwner = myDragObject->GlobalSelOwner())
2650 theCtx->SetSelectedState (aGlobOwner, true);
2653 myDragObject->ProcessDragging (theCtx, theView, myDragOwner, myGL.Dragging.PointStart,
2654 myGL.Dragging.PointTo, theAction);
2655 theView->Invalidate();
2658 case AIS_DragAction_Abort:
2660 if (myDragObject.IsNull())
2665 myGL.Dragging.PointTo = myGL.Dragging.PointStart;
2666 OnObjectDragged (theCtx, theView, AIS_DragAction_Update);
2668 myDragObject->ProcessDragging (theCtx, theView, myDragOwner, myGL.Dragging.PointStart,
2669 myGL.Dragging.PointTo, theAction);
2670 Standard_FALLTHROUGH
2672 case AIS_DragAction_Stop:
2674 if (myDragObject.IsNull())
2679 if (Handle(SelectMgr_EntityOwner) aGlobOwner = myDragObject->GlobalSelOwner())
2681 theCtx->SetSelectedState (aGlobOwner, false);
2684 myDragObject->ProcessDragging (theCtx, theView, myDragOwner, myGL.Dragging.PointStart,
2685 myGL.Dragging.PointTo, theAction);
2686 theView->Invalidate();
2687 myDragObject.Nullify();
2688 myDragOwner.Nullify();
2694 // =======================================================================
2695 // function : contextLazyMoveTo
2697 // =======================================================================
2698 void AIS_ViewController::contextLazyMoveTo (const Handle(AIS_InteractiveContext)& theCtx,
2699 const Handle(V3d_View)& theView,
2700 const Graphic3d_Vec2i& thePnt)
2702 if (myPrevMoveTo == thePnt
2703 || myHasHlrOnBeforeRotation) // ignore highlighting in-between rotation of HLR view
2708 myPrevMoveTo = thePnt;
2710 Handle(SelectMgr_EntityOwner) aLastPicked = theCtx->DetectedOwner();
2712 // Picking relies on the camera frustum (including Z-range) - so make temporary AutoZFit()
2713 // and then restore previous frustum to avoid immediate layer rendering issues if View has not been invalidated.
2714 const Standard_Real aZNear = theView->Camera()->ZNear(), aZFar = theView->Camera()->ZFar();
2715 theView->AutoZFit();
2716 theCtx->MoveTo (thePnt.x(), thePnt.y(), theView, false);
2717 theView->Camera()->SetZRange (aZNear, aZFar);
2719 Handle(SelectMgr_EntityOwner) aNewPicked = theCtx->DetectedOwner();
2721 if (theView->Viewer()->IsGridActive()
2722 && theView->Viewer()->GridEcho())
2724 if (aNewPicked.IsNull())
2726 Graphic3d_Vec3d aPnt3d;
2727 theView->ConvertToGrid (thePnt.x(), thePnt.y(), aPnt3d[0], aPnt3d[1], aPnt3d[2]);
2728 theView->Viewer()->ShowGridEcho (theView, Graphic3d_Vertex (aPnt3d[0], aPnt3d[1], aPnt3d[2]));
2729 theView->InvalidateImmediate();
2733 theView->Viewer()->HideGridEcho (theView);
2734 theView->InvalidateImmediate();
2738 if (aLastPicked != aNewPicked
2739 || (!aNewPicked.IsNull() && aNewPicked->IsForcedHilight()))
2741 // dynamic highlight affects all Views
2742 for (V3d_ListOfViewIterator aViewIter (theView->Viewer()->ActiveViewIterator()); aViewIter.More(); aViewIter.Next())
2744 const Handle(V3d_View)& aView = aViewIter.Value();
2745 aView->InvalidateImmediate();
2750 // =======================================================================
2751 // function : handleSelectionPick
2753 // =======================================================================
2754 void AIS_ViewController::handleSelectionPick (const Handle(AIS_InteractiveContext)& theCtx,
2755 const Handle(V3d_View)& theView)
2757 if (myGL.Selection.Tool == AIS_ViewSelectionTool_Picking
2758 && !myGL.Selection.Points.IsEmpty())
2760 for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aPntIter (myGL.Selection.Points); aPntIter.More(); aPntIter.Next())
2762 const bool hadPrevMoveTo = HasPreviousMoveTo();
2763 contextLazyMoveTo (theCtx, theView, aPntIter.Value());
2766 ResetPreviousMoveTo();
2769 theCtx->SelectDetected (myGL.Selection.Scheme);
2771 // selection affects all Views
2772 theView->Viewer()->Invalidate();
2774 OnSelectionChanged (theCtx, theView);
2777 myGL.Selection.Points.Clear();
2781 // =======================================================================
2782 // function : handleSelectionPoly
2784 // =======================================================================
2785 void AIS_ViewController::handleSelectionPoly (const Handle(AIS_InteractiveContext)& theCtx,
2786 const Handle(V3d_View)& theView)
2788 // rubber-band & window polygon selection
2789 if (myGL.Selection.Tool == AIS_ViewSelectionTool_RubberBand
2790 || myGL.Selection.Tool == AIS_ViewSelectionTool_Polygon
2791 || myGL.Selection.Tool == AIS_ViewSelectionTool_ZoomWindow)
2793 if (!myGL.Selection.Points.IsEmpty())
2795 myRubberBand->ClearPoints();
2796 myRubberBand->SetToUpdate();
2798 const bool anIsRubber = myGL.Selection.Tool == AIS_ViewSelectionTool_RubberBand
2799 || myGL.Selection.Tool == AIS_ViewSelectionTool_ZoomWindow;
2802 myRubberBand->SetRectangle (myGL.Selection.Points.First().x(), -myGL.Selection.Points.First().y(),
2803 myGL.Selection.Points.Last().x(), -myGL.Selection.Points.Last().y());
2807 Graphic3d_Vec2i aPrev (IntegerLast(), IntegerLast());
2808 for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aSelIter (myGL.Selection.Points); aSelIter.More(); aSelIter.Next())
2810 Graphic3d_Vec2i aPntNew = Graphic3d_Vec2i (aSelIter.Value().x(), -aSelIter.Value().y());
2811 if (aPntNew != aPrev)
2814 myRubberBand->AddPoint (Graphic3d_Vec2i (aSelIter.Value().x(), -aSelIter.Value().y()));
2819 myRubberBand->SetPolygonClosed (anIsRubber);
2822 theCtx->Display (myRubberBand, 0, -1, false, AIS_DS_Displayed);
2824 catch (const Standard_Failure& theEx)
2826 Message::SendWarning (TCollection_AsciiString ("Internal error while displaying rubber-band: ")
2827 + theEx.DynamicType()->Name() + ", " + theEx.GetMessageString());
2828 myRubberBand->ClearPoints();
2830 if (!theView->Viewer()->ZLayerSettings (myRubberBand->ZLayer()).IsImmediate())
2832 theView->Invalidate();
2836 theView->InvalidateImmediate();
2839 else if (!myRubberBand.IsNull()
2840 && myRubberBand->HasInteractiveContext())
2842 theCtx->Remove (myRubberBand, false);
2843 myRubberBand->ClearPoints();
2847 if (myGL.Selection.ToApplyTool)
2849 myGL.Selection.ToApplyTool = false;
2850 if (theCtx->IsDisplayed (myRubberBand))
2852 theCtx->Remove (myRubberBand, false);
2854 const NCollection_Sequence<Graphic3d_Vec2i>& aPoints = myRubberBand->Points();
2855 if (aPoints.Size() == 4
2856 && aPoints.Value (1).x() == aPoints.Value (2).x()
2857 && aPoints.Value (3).x() == aPoints.Value (4).x()
2858 && aPoints.Value (1).y() == aPoints.Value (4).y()
2859 && aPoints.Value (2).y() == aPoints.Value (3).y())
2861 const Graphic3d_Vec2i aPnt1 (aPoints.Value (1).x(), -aPoints.Value (1).y());
2862 const Graphic3d_Vec2i aPnt2 (aPoints.Value (3).x(), -aPoints.Value (3).y());
2863 if (myGL.Selection.Tool == AIS_ViewSelectionTool_ZoomWindow)
2865 theView->WindowFitAll (aPnt1.x(), aPnt1.y(), aPnt2.x(), aPnt2.y());
2866 theView->Invalidate();
2870 theCtx->MainSelector()->AllowOverlapDetection (aPnt1.y() != Min (aPnt1.y(), aPnt2.y()));
2871 theCtx->SelectRectangle (Graphic3d_Vec2i (Min (aPnt1.x(), aPnt2.x()), Min (aPnt1.y(), aPnt2.y())),
2872 Graphic3d_Vec2i (Max (aPnt1.x(), aPnt2.x()), Max (aPnt1.y(), aPnt2.y())),
2874 myGL.Selection.Scheme);
2875 theCtx->MainSelector()->AllowOverlapDetection (false);
2878 else if (aPoints.Length() >= 3)
2880 TColgp_Array1OfPnt2d aPolyline (1, aPoints.Length());
2881 TColgp_Array1OfPnt2d::Iterator aPolyIter (aPolyline);
2882 for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aSelIter (aPoints);
2883 aSelIter.More(); aSelIter.Next(), aPolyIter.Next())
2885 const Graphic3d_Vec2i& aNewPnt = aSelIter.Value();
2886 aPolyIter.ChangeValue() = gp_Pnt2d (aNewPnt.x(), -aNewPnt.y());
2889 theCtx->SelectPolygon (aPolyline, theView, myGL.Selection.Scheme);
2890 theCtx->MainSelector()->AllowOverlapDetection (false);
2894 myRubberBand->ClearPoints();
2895 if (myGL.Selection.Tool != AIS_ViewSelectionTool_ZoomWindow)
2897 // selection affects all Views
2898 theView->Viewer()->Invalidate();
2899 OnSelectionChanged (theCtx, theView);
2905 // =======================================================================
2906 // function : handleDynamicHighlight
2908 // =======================================================================
2909 void AIS_ViewController::handleDynamicHighlight (const Handle(AIS_InteractiveContext)& theCtx,
2910 const Handle(V3d_View)& theView)
2912 if ((myGL.MoveTo.ToHilight || myGL.Dragging.ToStart)
2913 && myNavigationMode != AIS_NavigationMode_FirstPersonWalk)
2915 const Graphic3d_Vec2i& aMoveToPnt = myGL.MoveTo.ToHilight ? myGL.MoveTo.Point : myGL.Dragging.PointStart;
2916 if (myGL.Dragging.ToStart && (!myGL.MoveTo.ToHilight || !myToAllowHighlight)
2917 && !HasPreviousMoveTo())
2919 contextLazyMoveTo (theCtx, theView, aMoveToPnt);
2920 ResetPreviousMoveTo();
2921 OnObjectDragged (theCtx, theView, AIS_DragAction_Start);
2922 theCtx->ClearDetected();
2924 else if (myToAllowHighlight)
2926 if (myPrevMoveTo != aMoveToPnt
2927 || (!theView->View()->IsActiveXR()
2928 && (myGL.OrbitRotation.ToRotate
2929 || myGL.ViewRotation.ToRotate
2930 || theView->IsInvalidated())))
2932 ResetPreviousMoveTo();
2933 contextLazyMoveTo (theCtx, theView, aMoveToPnt);
2935 if (myGL.Dragging.ToStart)
2937 OnObjectDragged (theCtx, theView, AIS_DragAction_Start);
2941 myGL.MoveTo.ToHilight = false;
2944 if (!myDragObject.IsNull())
2946 if (myGL.Dragging.ToAbort)
2948 OnObjectDragged (theCtx, theView, AIS_DragAction_Abort);
2949 myGL.OrbitRotation.ToRotate = false;
2950 myGL.ViewRotation .ToRotate = false;
2952 else if (myGL.Dragging.ToStop)
2954 OnObjectDragged (theCtx, theView, AIS_DragAction_Stop);
2955 myGL.OrbitRotation.ToRotate = false;
2956 myGL.ViewRotation .ToRotate = false;
2958 else if (myGL.OrbitRotation.ToRotate
2959 || myGL.ViewRotation.ToRotate)
2961 OnObjectDragged (theCtx, theView, AIS_DragAction_Update);
2962 myGL.OrbitRotation.ToRotate = false;
2963 myGL.ViewRotation .ToRotate = false;
2968 // =======================================================================
2969 // function : handleMoveTo
2971 // =======================================================================
2972 void AIS_ViewController::handleMoveTo (const Handle(AIS_InteractiveContext)& theCtx,
2973 const Handle(V3d_View)& theView)
2975 handleSelectionPick (theCtx, theView);
2976 handleDynamicHighlight(theCtx, theView);
2977 handleSelectionPoly (theCtx, theView);
2980 // =======================================================================
2981 // function : handleViewRedraw
2983 // =======================================================================
2984 void AIS_ViewController::handleViewRedraw (const Handle(AIS_InteractiveContext)& ,
2985 const Handle(V3d_View)& theView)
2987 // manage animation state
2988 if (!myViewAnimation.IsNull()
2989 && !myViewAnimation->IsStopped())
2991 myViewAnimation->UpdateTimer();
2992 ResetPreviousMoveTo();
2996 if (theView->View()->IsActiveXR())
2998 // VR requires continuous rendering
2999 myToAskNextFrame = true;
3002 for (V3d_ListOfViewIterator aViewIter (theView->Viewer()->ActiveViewIterator()); aViewIter.More(); aViewIter.Next())
3004 const Handle(V3d_View)& aView = aViewIter.Value();
3005 if (aView->IsInvalidated()
3006 || (myToAskNextFrame && aView == theView))
3008 if (aView->ComputedMode())
3017 else if (aView->IsInvalidatedImmediate())
3019 aView->RedrawImmediate();
3023 if (myToAskNextFrame)
3026 theView->Window()->InvalidateContent (Handle(Aspect_DisplayConnection)());
3030 // =======================================================================
3031 // function : handleXRMoveTo
3033 // =======================================================================
3034 Standard_Integer AIS_ViewController::handleXRMoveTo (const Handle(AIS_InteractiveContext)& theCtx,
3035 const Handle(V3d_View)& theView,
3036 const gp_Trsf& thePose,
3037 const Standard_Boolean theToHighlight)
3039 //ResetPreviousMoveTo();
3040 Standard_Integer aPickResult = 0;
3042 Handle(Graphic3d_Camera) aCamBack = theView->Camera();
3043 myXRCameraTmp->Copy (aCamBack);
3044 theView->View()->ComputeXRPosedCameraFromBase (*myXRCameraTmp, thePose);
3045 theView->SetCamera (myXRCameraTmp);
3046 Graphic3d_Vec2i aPickPixel;
3047 theView->Window()->Size (aPickPixel.x(), aPickPixel.y());
3049 const Standard_Integer aSelTolerBack = theCtx->MainSelector()->CustomPixelTolerance();
3050 theCtx->MainSelector()->SetPixelTolerance (1);
3051 theView->AutoZFit();
3054 theCtx->MoveTo (aPickPixel.x(), aPickPixel.y(), theView, false);
3055 if (!theCtx->DetectedOwner().IsNull())
3057 // ignore 2D objects
3058 for (aPickResult = 1; !theCtx->DetectedOwner()->Selectable()->TransformPersistence().IsNull(); ++aPickResult)
3060 if (theCtx->HilightNextDetected (theView, false) <= 1)
3062 theCtx->ClearDetected();
3071 theCtx->MainSelector()->Pick (aPickPixel.x(), aPickPixel.y(), theView);
3072 for (Standard_Integer aPickIter = 1; aPickIter <= theCtx->MainSelector()->NbPicked(); ++aPickIter)
3074 const SelectMgr_SortCriterion& aPickedData = theCtx->MainSelector()->PickedData (aPickIter);
3075 if (!aPickedData.Entity->OwnerId()->Selectable()->TransformPersistence().IsNull())
3081 aPickResult = aPickIter;
3085 theCtx->MainSelector()->SetPixelTolerance (aSelTolerBack);
3086 theView->SetCamera (aCamBack);
3090 // =======================================================================
3091 // function : handleXRHighlight
3093 // =======================================================================
3094 void AIS_ViewController::handleXRHighlight (const Handle(AIS_InteractiveContext)& theCtx,
3095 const Handle(V3d_View)& theView)
3097 if (myXRLastPickingHand != Aspect_XRTrackedDeviceRole_LeftHand
3098 && myXRLastPickingHand != Aspect_XRTrackedDeviceRole_RightHand)
3103 const Standard_Integer aDeviceId = theView->View()->XRSession()->NamedTrackedDevice (myXRLastPickingHand);
3104 if (aDeviceId == -1)
3109 const Aspect_TrackedDevicePose& aPose = theView->View()->XRSession()->TrackedPoses()[aDeviceId];
3110 if (!aPose.IsValidPose)
3115 Handle(SelectMgr_EntityOwner) aDetOld = theCtx->DetectedOwner();
3116 handleXRMoveTo (theCtx, theView, aPose.Orientation, true);
3117 if (!theCtx->DetectedOwner().IsNull()
3118 && theCtx->DetectedOwner() != aDetOld)
3120 if (const Handle(Aspect_XRAction)& aHaptic = theView->View()->XRSession()->GenericAction (myXRLastPickingHand, Aspect_XRGenericAction_OutputHaptic))
3122 theView->View()->XRSession()->TriggerHapticVibrationAction (aHaptic, myXRPickingHaptic);
3126 Standard_Real& aPickDepth = myXRLastPickingHand == Aspect_XRTrackedDeviceRole_LeftHand ? myXRLastPickDepthLeft : myXRLastPickDepthRight;
3127 aPickDepth = Precision::Infinite();
3128 if (theCtx->MainSelector()->NbPicked() > 0)
3130 const gp_Trsf aHandBase = theView->View()->PoseXRToWorld (aPose.Orientation);
3131 const SelectMgr_SortCriterion& aPicked = theCtx->MainSelector()->PickedData (1);
3132 aPickDepth = aPicked.Point.Distance (aHandBase.TranslationPart());
3136 // =======================================================================
3137 // function : handleXRPresentations
3139 // =======================================================================
3140 void AIS_ViewController::handleXRPresentations (const Handle(AIS_InteractiveContext)& theCtx,
3141 const Handle(V3d_View)& theView)
3143 if (!theView->View()->IsActiveXR()
3144 || (!myToDisplayXRAuxDevices
3145 && !myToDisplayXRHands))
3147 for (NCollection_Array1<Handle(AIS_XRTrackedDevice)>::Iterator aPrsIter (myXRPrsDevices); aPrsIter.More(); aPrsIter.Next())
3149 if (!aPrsIter.Value().IsNull()
3150 && aPrsIter.Value()->HasInteractiveContext())
3152 theCtx->Remove (aPrsIter.Value(), false);
3154 aPrsIter.ChangeValue().Nullify();
3159 if (myXRPrsDevices.Length() != theView->View()->XRSession()->TrackedPoses().Length())
3161 for (NCollection_Array1<Handle(AIS_XRTrackedDevice)>::Iterator aPrsIter (myXRPrsDevices); aPrsIter.More(); aPrsIter.Next())
3163 if (!aPrsIter.Value().IsNull())
3165 theCtx->Remove (aPrsIter.Value(), false);
3168 myXRPrsDevices.Resize (theView->View()->XRSession()->TrackedPoses().Lower(), theView->View()->XRSession()->TrackedPoses().Upper(), false);
3171 const Standard_Integer aHeadDevice = theView->View()->XRSession()->NamedTrackedDevice (Aspect_XRTrackedDeviceRole_Head);
3172 const Standard_Integer aLeftDevice = theView->View()->XRSession()->NamedTrackedDevice (Aspect_XRTrackedDeviceRole_LeftHand);
3173 const Standard_Integer aRightDevice = theView->View()->XRSession()->NamedTrackedDevice (Aspect_XRTrackedDeviceRole_RightHand);
3174 for (Standard_Integer aDeviceIter = theView->View()->XRSession()->TrackedPoses().Lower(); aDeviceIter <= theView->View()->XRSession()->TrackedPoses().Upper(); ++aDeviceIter)
3176 const Aspect_TrackedDevicePose& aPose = theView->View()->XRSession()->TrackedPoses()[aDeviceIter];
3177 Handle(AIS_XRTrackedDevice)& aPosePrs = myXRPrsDevices[aDeviceIter];
3178 if (!aPose.IsValidPose)
3183 const bool isHand = aDeviceIter == aLeftDevice
3184 || aDeviceIter == aRightDevice;
3185 if ((!myToDisplayXRHands && isHand)
3186 || (!myToDisplayXRAuxDevices && !isHand))
3188 if (!aPosePrs.IsNull()
3189 && aPosePrs->HasInteractiveContext())
3191 theCtx->Remove (aPosePrs, false);
3196 Aspect_XRTrackedDeviceRole aRole = Aspect_XRTrackedDeviceRole_Other;
3197 if (aDeviceIter == aLeftDevice)
3199 aRole = Aspect_XRTrackedDeviceRole_LeftHand;
3201 else if (aDeviceIter == aRightDevice)
3203 aRole = Aspect_XRTrackedDeviceRole_RightHand;
3206 if (!aPosePrs.IsNull()
3207 && aPosePrs->UnitFactor() != (float )theView->View()->UnitFactor())
3209 theCtx->Remove (aPosePrs, false);
3213 if (aPosePrs.IsNull())
3215 Handle(Image_Texture) aTexture;
3216 Handle(Graphic3d_ArrayOfTriangles) aTris;
3217 if (aDeviceIter != aHeadDevice)
3219 aTris = theView->View()->XRSession()->LoadRenderModel (aDeviceIter, aTexture);
3221 if (!aTris.IsNull())
3223 aPosePrs = new AIS_XRTrackedDevice (aTris, aTexture);
3227 aPosePrs = new AIS_XRTrackedDevice();
3229 aPosePrs->SetUnitFactor ((float )theView->View()->UnitFactor());
3230 aPosePrs->SetMutable (true);
3231 aPosePrs->SetInfiniteState (true);
3233 aPosePrs->SetRole (aRole);
3235 if (!aPosePrs->HasInteractiveContext())
3237 theCtx->Display (aPosePrs, 0, -1, false);
3240 gp_Trsf aPoseLocal = aPose.Orientation;
3241 if (aDeviceIter == aHeadDevice)
3243 // show headset position on floor level
3244 aPoseLocal.SetTranslationPart (gp_Vec (aPoseLocal.TranslationPart().X(), 0.0, aPoseLocal.TranslationPart().Z()));
3246 const gp_Trsf aPoseWorld = theView->View()->PoseXRToWorld (aPoseLocal);
3247 theCtx->SetLocation (aPosePrs, aPoseWorld);
3249 Standard_Real aLaserLen = 0.0;
3251 && aPosePrs->Role() == myXRLastPickingHand)
3253 aLaserLen = myXRLastPickingHand == Aspect_XRTrackedDeviceRole_LeftHand ? myXRLastPickDepthLeft : myXRLastPickDepthRight;
3254 if (Precision::IsInfinite (aLaserLen))
3256 const Bnd_Box aViewBox = theView->View()->MinMaxValues (true);
3257 if (!aViewBox.IsVoid())
3259 aLaserLen = Sqrt (aViewBox.SquareExtent());
3266 aPosePrs->SetLaserColor (myXRLaserPickColor);
3269 && aPosePrs->Role() == myXRLastTeleportHand)
3271 aLaserLen = myXRLastTeleportHand == Aspect_XRTrackedDeviceRole_LeftHand ? myXRLastPickDepthLeft : myXRLastPickDepthRight;
3272 if (Precision::IsInfinite (aLaserLen))
3274 const Bnd_Box aViewBox = theView->View()->MinMaxValues (true);
3275 if (!aViewBox.IsVoid())
3277 aLaserLen = Sqrt (aViewBox.SquareExtent());
3284 aPosePrs->SetLaserColor (myXRLaserTeleColor);
3286 aPosePrs->SetLaserLength ((float )aLaserLen);
3290 // =======================================================================
3291 // function : HandleViewEvents
3293 // =======================================================================
3294 void AIS_ViewController::HandleViewEvents (const Handle(AIS_InteractiveContext)& theCtx,
3295 const Handle(V3d_View)& theView)
3297 const bool wasImmediateUpdate = theView->SetImmediateUpdate (false);
3299 handleViewOrientationKeys (theCtx, theView);
3300 const AIS_WalkDelta aWalk = handleNavigationKeys (theCtx, theView);
3301 handleXRInput (theCtx, theView, aWalk);
3302 if (theView->View()->IsActiveXR())
3304 theView->View()->SetupXRPosedCamera();
3306 handleMoveTo (theCtx, theView);
3307 handleCameraActions (theCtx, theView, aWalk);
3308 theView->View()->SynchronizeXRPosedToBaseCamera(); // handleCameraActions() may modify posed camera position - copy this modifications also to the base camera
3309 handleXRPresentations (theCtx, theView);
3311 handleViewRedraw (theCtx, theView);
3312 theView->View()->UnsetXRPosedCamera();
3314 theView->SetImmediateUpdate (wasImmediateUpdate);
3316 // make sure to not process the same events twice
3318 myToAskNextFrame = false;